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