]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/i386/km.c
xnu-344.34.tar.gz
[apple/xnu.git] / bsd / dev / i386 / km.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
de355530
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
de355530
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
de355530
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
23 *
24 * km.m - kernel keyboard/monitor module, procedural interface.
25 *
26 * HISTORY
27 */
28
29#include <sys/param.h>
30#include <sys/tty.h>
31
32#include <dev/i386/cons.h>
33#include <sys/conf.h>
34#include <sys/systm.h>
35#include <sys/uio.h>
36#include <sys/fcntl.h> /* for kmopen */
37#include <sys/errno.h>
38#include <sys/proc.h> /* for kmopen */
39#include <sys/msgbuf.h>
40#include <sys/time.h>
41#include <dev/kmreg_com.h>
42#include <pexpert/pexpert.h>
43
44/*
45 * 'Global' variables, shared only by this file and conf.c.
46 */
47extern struct tty cons;
48struct tty *km_tty[1] = { &cons };
49
50/*
51 * this works early on, after initialize_screen() but before autoconf (and thus
52 * before we have a kmDevice).
53 */
54int disableConsoleOutput;
55
56/*
57 * 'Global' variables, shared only by this file and kmDevice.m.
58 */
59int initialized = 0;
60
61static int kmoutput(struct tty *tp);
62static void kmtimeout(struct tty *tp);
63static void kmstart(struct tty *tp);
64
65extern void KeyboardOpen(void);
66
67int kminit()
68{
69 cons.t_dev = makedev(12, 0);
70 initialized = 1;
71}
72/*
73 * cdevsw interface to km driver.
74 */
75int
76kmopen(
77 dev_t dev,
78 int flag,
79 int devtype,
80 struct proc *pp)
81{
82 int rtn;
83 int unit;
84 struct tty *tp;
85 struct winsize *wp;
86 int ret;
87
88 unit = minor(dev);
89 if(unit >= 1)
90 return (ENXIO);
91
92 tp = (struct tty *)&cons;
93 tp->t_oproc = kmstart;
94 tp->t_param = NULL;
95 tp->t_dev = dev;
96
97 if ( !(tp->t_state & TS_ISOPEN) ) {
98 tp->t_iflag = TTYDEF_IFLAG;
99 tp->t_oflag = TTYDEF_OFLAG;
100 tp->t_cflag = (CREAD | CS8 | CLOCAL);
101 tp->t_lflag = TTYDEF_LFLAG;
102 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
103 termioschars(&tp->t_termios);
104 ttsetwater(tp);
105 } else if ((tp->t_state & TS_XCLUDE) && pp->p_ucred->cr_uid != 0)
106 return EBUSY;
107
108 tp->t_state |= TS_CARR_ON; /* lie and say carrier exists and is on. */
109 ret = ((*linesw[tp->t_line].l_open)(dev, tp));
110 {
111 PE_Video video;
112 wp = &tp->t_winsize;
113 /* Magic numbers. These are CHARWIDTH and CHARHEIGHT
114 * from pexpert/i386/video_console.c
115 */
116 wp->ws_xpixel = 8;
117 wp->ws_ypixel = 16;
118
119 if (flag & O_POPUP)
120 PE_initialize_console(0, kPETextScreen);
121
122 bzero(&video, sizeof(video));
123 PE_current_console(&video);
124 if( video.v_width != 0 && video.v_height != 0 ) {
125 wp->ws_col = video.v_width / wp->ws_xpixel;
126 wp->ws_row = video.v_height / wp->ws_ypixel;
127 } else {
128 wp->ws_col = 100;
129 wp->ws_row = 36;
130 }
131 }
132 return ret;
133}
134
135int
136kmclose(
137 dev_t dev,
138 int flag,
139 int mode,
140 struct proc *p)
141{
142
143 struct tty *tp;
144
145 tp = &cons;
146 (*linesw[tp->t_line].l_close)(tp,flag);
147 ttyclose(tp);
148 return (0);
149}
150
151int
152kmread(
153 dev_t dev,
154 struct uio *uio,
155 int ioflag)
156{
157 register struct tty *tp;
158
159 tp = &cons;
160 return ((*linesw[tp->t_line].l_read)(tp, uio, ioflag));
161}
162
163int
164kmwrite(
165 dev_t dev,
166 struct uio *uio,
167 int ioflag)
168{
169 register struct tty *tp;
170
171 tp = &cons;
172 return ((*linesw[tp->t_line].l_write)(tp, uio, ioflag));
173}
174
175int
176kmioctl(
177 dev_t dev,
178 int cmd,
179 caddr_t data,
180 int flag,
181 struct proc *p)
182{
183 int error;
184 struct tty *tp = &cons;
185 struct winsize *wp;
186
187 switch (cmd) {
188
189
190
191 case KMIOCSIZE:
192 wp = (struct winsize *)data;
193 *wp = tp->t_winsize;
194 return 0;
195
196 case TIOCSWINSZ:
197 /* Prevent changing of console size --
198 * this ensures that login doesn't revert to the
199 * termcap-defined size
200 */
201 return EINVAL;
202
203 /* Bodge in the CLOCAL flag as the km device is always local */
204 case TIOCSETA:
205 case TIOCSETAW:
206 case TIOCSETAF: {
207 register struct termios *t = (struct termios *)data;
208 t->c_cflag |= CLOCAL;
209 /* No Break */
210 }
211 default:
212 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
213 if (error >= 0) {
214 return error;
215 }
216 error = ttioctl (tp, cmd, data, flag, p);
217 if (error >= 0) {
218 return error;
219 }
220 else {
221 return ENOTTY;
222 }
223 }
224}
225
226int
227kmputc(
228 int c)
229{
230
231 if( disableConsoleOutput)
232 return( 0);
233
234 if(!initialized)
235 return( 0);
236
237 if(c == '\n')
238 cnputc('\r');
239
240 cnputc(c);
241
242 return 0;
243}
244
245int
246kmgetc(
247 dev_t dev)
248{
249 int c;
250
251 c= cngetc();
252
253 if (c == '\r') {
254 c = '\n';
255 }
256 cnputc(c);
257 return c;
258}
259
260int
261kmgetc_silent(
262 dev_t dev)
263{
264 int c;
265
266 c= cngetc();
267 if (c == '\r') {
268 c = '\n';
269 }
270 return c;
271}
272
273/*
274 * Callouts from linesw.
275 */
276
277#define KM_LOWAT_DELAY ((ns_time_t)1000)
278
279static void
280kmstart(
281 struct tty *tp)
282{
283 extern int hz;
284 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
285 goto out;
286 if (tp->t_outq.c_cc == 0)
287 goto out;
288 tp->t_state |= TS_BUSY;
289 if (tp->t_outq.c_cc > tp->t_lowat) {
290 /*
291 * Start immediately.
292 */
293 kmoutput(tp);
294 }
295 else {
296 /*
297 * Wait a bit...
298 */
299#if 0
300 /* FIXME */
301 timeout(kmtimeout, tp, hz);
302#else
303 kmoutput(tp);
304#endif
305 }
306out:
307 ttwwakeup(tp);
308}
309
310static void
311kmtimeout( struct tty *tp)
312{
313 boolean_t funnel_state;
314
315 funnel_state = thread_funnel_set(kernel_flock, TRUE);
316 kmoutput(tp);
9bccf70c 317 (void) thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
318
319
320}
321static int
322kmoutput(
323 struct tty *tp)
324{
325 /*
326 * FIXME - to be grokked...copied from m68k km.c.
327 */
328 char buf[80];
329 char *cp;
330 int cc = -1;
331 extern int hz;
332
333
334 while (tp->t_outq.c_cc > 0) {
335 cc = ndqb(&tp->t_outq, 0);
336 if (cc == 0)
337 break;
338 cc = min(cc, sizeof buf);
339 (void) q_to_b(&tp->t_outq, buf, cc);
340 for (cp = buf; cp < &buf[cc]; cp++) {
341 kmputc(*cp & 0x7f);
342 }
343 }
344 if (tp->t_outq.c_cc > 0) {
345 timeout(kmtimeout, tp, hz);
346 }
347 tp->t_state &= ~TS_BUSY;
348 ttwwakeup(tp);
349
350 return 0;
351}
352cons_cinput(char ch)
353{
354 struct tty *tp = &cons;
355 boolean_t funnel_state;
356
357
358 (*linesw[tp->t_line].l_rint) (ch, tp);
359
360}
361