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