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