]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/i386/km.c
a75e4ea54cf7ee04ba48d075d0880e0d0645f684
[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 * 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.
11 *
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
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 #include <pexpert/i386/boot.h>
44
45 extern int hz;
46
47 extern void cnputcusr(char);
48 extern int cngetc(void);
49
50 void kminit(void);
51 int kmopen(dev_t dev, int flag, int devtype, struct proc *pp);
52 int kmclose(dev_t dev, int flag, int mode, struct proc *p);
53 int kmread(dev_t dev, struct uio *uio, int ioflag);
54 int kmwrite(dev_t dev, struct uio *uio, int ioflag);
55 int kmioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
56 int kmputc(int c);
57 int kmgetc(dev_t dev);
58 int kmgetc_silent(dev_t dev);
59 void cons_cinput(char ch);
60
61 /*
62 * 'Global' variables, shared only by this file and conf.c.
63 */
64 struct tty *km_tty[1] = { &cons };
65
66 /*
67 * this works early on, after initialize_screen() but before autoconf (and thus
68 * before we have a kmDevice).
69 */
70 int disableConsoleOutput;
71
72 /*
73 * 'Global' variables, shared only by this file and kmDevice.m.
74 */
75 int initialized = 0;
76
77 static int kmoutput(struct tty *tp);
78 static void kmstart(struct tty *tp);
79
80 extern void KeyboardOpen(void);
81
82 void
83 kminit(void)
84 {
85 cons.t_dev = makedev(12, 0);
86 initialized = 1;
87 }
88 /*
89 * cdevsw interface to km driver.
90 */
91 int
92 kmopen(
93 dev_t dev,
94 int flag,
95 __unused int devtype,
96 struct proc *pp)
97 {
98 int unit;
99 struct tty *tp;
100 struct winsize *wp;
101 int ret;
102
103 unit = minor(dev);
104 if(unit >= 1)
105 return (ENXIO);
106
107 tp = (struct tty *)&cons;
108 tp->t_oproc = kmstart;
109 tp->t_param = NULL;
110 tp->t_dev = dev;
111
112 if ( !(tp->t_state & TS_ISOPEN) ) {
113 tp->t_iflag = TTYDEF_IFLAG;
114 tp->t_oflag = TTYDEF_OFLAG;
115 tp->t_cflag = (CREAD | CS8 | CLOCAL);
116 tp->t_lflag = TTYDEF_LFLAG;
117 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
118 termioschars(&tp->t_termios);
119 ttsetwater(tp);
120 } else if ((tp->t_state & TS_XCLUDE) && proc_suser(pp))
121 return EBUSY;
122
123 tp->t_state |= TS_CARR_ON; /* lie and say carrier exists and is on. */
124 ret = ((*linesw[tp->t_line].l_open)(dev, tp));
125 {
126 PE_Video video;
127 wp = &tp->t_winsize;
128 /* Magic numbers. These are CHARWIDTH and CHARHEIGHT
129 * from pexpert/i386/video_console.c
130 */
131 wp->ws_xpixel = 8;
132 wp->ws_ypixel = 16;
133
134 if (flag & O_POPUP)
135 PE_initialize_console(0, kPETextScreen);
136
137 bzero(&video, sizeof(video));
138 PE_current_console(&video);
139 if( video.v_display == VGA_TEXT_MODE ) {
140 wp->ws_col = video.v_width;
141 wp->ws_row = video.v_height;
142 } else if( video.v_width != 0 && video.v_height != 0 ) {
143 wp->ws_col = video.v_width / wp->ws_xpixel;
144 wp->ws_row = video.v_height / wp->ws_ypixel;
145 } else {
146 wp->ws_col = 100;
147 wp->ws_row = 36;
148 }
149 }
150 return ret;
151 }
152
153 int
154 kmclose(
155 __unused dev_t dev,
156 int flag,
157 __unused int mode,
158 __unused struct proc *p)
159 {
160
161 struct tty *tp;
162
163 tp = &cons;
164 (*linesw[tp->t_line].l_close)(tp,flag);
165 ttyclose(tp);
166 return (0);
167 }
168
169 int
170 kmread(
171 __unused dev_t dev,
172 struct uio *uio,
173 int ioflag)
174 {
175 register struct tty *tp;
176
177 tp = &cons;
178 return ((*linesw[tp->t_line].l_read)(tp, uio, ioflag));
179 }
180
181 int
182 kmwrite(
183 __unused dev_t dev,
184 struct uio *uio,
185 int ioflag)
186 {
187 register struct tty *tp;
188
189 tp = &cons;
190 return ((*linesw[tp->t_line].l_write)(tp, uio, ioflag));
191 }
192
193 int
194 kmioctl(
195 __unused dev_t dev,
196 int cmd,
197 caddr_t data,
198 int flag,
199 struct proc *p)
200 {
201 int error;
202 struct tty *tp = &cons;
203 struct winsize *wp;
204
205 switch (cmd) {
206
207
208
209 case KMIOCSIZE:
210 wp = (struct winsize *)data;
211 *wp = tp->t_winsize;
212 return 0;
213
214 case TIOCSWINSZ:
215 /* Prevent changing of console size --
216 * this ensures that login doesn't revert to the
217 * termcap-defined size
218 */
219 return EINVAL;
220
221 /* Bodge in the CLOCAL flag as the km device is always local */
222 case TIOCSETA:
223 case TIOCSETAW:
224 case TIOCSETAF: {
225 register struct termios *t = (struct termios *)data;
226 t->c_cflag |= CLOCAL;
227 /* No Break */
228 }
229 default:
230 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
231 if (ENOTTY != error)
232 return error;
233 return ttioctl (tp, cmd, data, flag, p);
234 }
235 }
236
237 int
238 kmputc(
239 int c)
240 {
241
242 if( disableConsoleOutput)
243 return( 0);
244
245 if(!initialized)
246 return( 0);
247
248 if(c == '\n')
249 cnputcusr('\r');
250
251 cnputcusr(c);
252
253 return 0;
254 }
255
256 int
257 kmgetc(
258 __unused dev_t dev)
259 {
260 int c;
261
262 c= cngetc();
263
264 if (c == '\r') {
265 c = '\n';
266 }
267 cnputcusr(c);
268 return c;
269 }
270
271 int
272 kmgetc_silent(
273 __unused dev_t dev)
274 {
275 int c;
276
277 c= cngetc();
278 if (c == '\r') {
279 c = '\n';
280 }
281 return c;
282 }
283
284 /*
285 * Callouts from linesw.
286 */
287
288 #define KM_LOWAT_DELAY ((ns_time_t)1000)
289
290 static void
291 kmstart(
292 struct tty *tp)
293 {
294 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
295 goto out;
296 if (tp->t_outq.c_cc == 0)
297 goto out;
298 tp->t_state |= TS_BUSY;
299 kmoutput(tp);
300 return;
301
302 out:
303 (*linesw[tp->t_line].l_start)(tp);
304 return;
305 }
306
307 static void
308 kmtimeout(void *arg)
309 {
310 boolean_t funnel_state;
311 struct tty *tp = (struct tty *) arg;
312
313 funnel_state = thread_funnel_set(kernel_flock, TRUE);
314 kmoutput(tp);
315 (void) thread_funnel_set(kernel_flock, funnel_state);
316
317
318 }
319 static int
320 kmoutput(
321 struct tty *tp)
322 {
323 /*
324 * FIXME - to be grokked...copied from m68k km.c.
325 */
326 char buf[80];
327 char *cp;
328 int cc = -1;
329
330
331 while (tp->t_outq.c_cc > 0) {
332 cc = ndqb(&tp->t_outq, 0);
333 if (cc == 0)
334 break;
335 cc = min(cc, sizeof buf);
336 (void) q_to_b(&tp->t_outq, buf, cc);
337 for (cp = buf; cp < &buf[cc]; cp++) {
338 kmputc(*cp & 0x7f);
339 }
340 }
341 if (tp->t_outq.c_cc > 0) {
342 timeout(kmtimeout, tp, hz);
343 }
344 tp->t_state &= ~TS_BUSY;
345 (*linesw[tp->t_line].l_start)(tp);
346
347 return 0;
348 }
349
350 void
351 cons_cinput(char ch)
352 {
353 struct tty *tp = &cons;
354
355 (*linesw[tp->t_line].l_rint) (ch, tp);
356 }
357