]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/i386/km.c
xnu-517.12.7.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 *
e5568f75
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 *
e5568f75
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,
e5568f75
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);
1c79356b
A
62static void kmstart(struct tty *tp);
63
64extern void KeyboardOpen(void);
65
66int kminit()
67{
68 cons.t_dev = makedev(12, 0);
69 initialized = 1;
70}
71/*
72 * cdevsw interface to km driver.
73 */
74int
75kmopen(
76 dev_t dev,
77 int flag,
78 int devtype,
79 struct proc *pp)
80{
81 int rtn;
82 int unit;
83 struct tty *tp;
84 struct winsize *wp;
85 int ret;
86
87 unit = minor(dev);
88 if(unit >= 1)
89 return (ENXIO);
90
91 tp = (struct tty *)&cons;
92 tp->t_oproc = kmstart;
93 tp->t_param = NULL;
94 tp->t_dev = dev;
95
96 if ( !(tp->t_state & TS_ISOPEN) ) {
97 tp->t_iflag = TTYDEF_IFLAG;
98 tp->t_oflag = TTYDEF_OFLAG;
99 tp->t_cflag = (CREAD | CS8 | CLOCAL);
100 tp->t_lflag = TTYDEF_LFLAG;
101 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
102 termioschars(&tp->t_termios);
103 ttsetwater(tp);
104 } else if ((tp->t_state & TS_XCLUDE) && pp->p_ucred->cr_uid != 0)
105 return EBUSY;
106
107 tp->t_state |= TS_CARR_ON; /* lie and say carrier exists and is on. */
108 ret = ((*linesw[tp->t_line].l_open)(dev, tp));
109 {
110 PE_Video video;
111 wp = &tp->t_winsize;
112 /* Magic numbers. These are CHARWIDTH and CHARHEIGHT
113 * from pexpert/i386/video_console.c
114 */
115 wp->ws_xpixel = 8;
116 wp->ws_ypixel = 16;
117
118 if (flag & O_POPUP)
119 PE_initialize_console(0, kPETextScreen);
120
121 bzero(&video, sizeof(video));
122 PE_current_console(&video);
123 if( video.v_width != 0 && video.v_height != 0 ) {
124 wp->ws_col = video.v_width / wp->ws_xpixel;
125 wp->ws_row = video.v_height / wp->ws_ypixel;
126 } else {
127 wp->ws_col = 100;
128 wp->ws_row = 36;
129 }
130 }
131 return ret;
132}
133
134int
135kmclose(
136 dev_t dev,
137 int flag,
138 int mode,
139 struct proc *p)
140{
141
142 struct tty *tp;
143
144 tp = &cons;
145 (*linesw[tp->t_line].l_close)(tp,flag);
146 ttyclose(tp);
147 return (0);
148}
149
150int
151kmread(
152 dev_t dev,
153 struct uio *uio,
154 int ioflag)
155{
156 register struct tty *tp;
157
158 tp = &cons;
159 return ((*linesw[tp->t_line].l_read)(tp, uio, ioflag));
160}
161
162int
163kmwrite(
164 dev_t dev,
165 struct uio *uio,
166 int ioflag)
167{
168 register struct tty *tp;
169
170 tp = &cons;
171 return ((*linesw[tp->t_line].l_write)(tp, uio, ioflag));
172}
173
174int
175kmioctl(
176 dev_t dev,
177 int cmd,
178 caddr_t data,
179 int flag,
180 struct proc *p)
181{
182 int error;
183 struct tty *tp = &cons;
184 struct winsize *wp;
185
186 switch (cmd) {
187
188
189
190 case KMIOCSIZE:
191 wp = (struct winsize *)data;
192 *wp = tp->t_winsize;
193 return 0;
194
195 case TIOCSWINSZ:
196 /* Prevent changing of console size --
197 * this ensures that login doesn't revert to the
198 * termcap-defined size
199 */
200 return EINVAL;
201
202 /* Bodge in the CLOCAL flag as the km device is always local */
203 case TIOCSETA:
204 case TIOCSETAW:
205 case TIOCSETAF: {
206 register struct termios *t = (struct termios *)data;
207 t->c_cflag |= CLOCAL;
208 /* No Break */
209 }
210 default:
211 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
212 if (error >= 0) {
213 return error;
214 }
215 error = ttioctl (tp, cmd, data, flag, p);
216 if (error >= 0) {
217 return error;
218 }
219 else {
220 return ENOTTY;
221 }
222 }
223}
224
225int
226kmputc(
227 int c)
228{
229
230 if( disableConsoleOutput)
231 return( 0);
232
233 if(!initialized)
234 return( 0);
235
236 if(c == '\n')
237 cnputc('\r');
238
239 cnputc(c);
240
241 return 0;
242}
243
244int
245kmgetc(
246 dev_t dev)
247{
248 int c;
249
250 c= cngetc();
251
252 if (c == '\r') {
253 c = '\n';
254 }
255 cnputc(c);
256 return c;
257}
258
259int
260kmgetc_silent(
261 dev_t dev)
262{
263 int c;
264
265 c= cngetc();
266 if (c == '\r') {
267 c = '\n';
268 }
269 return c;
270}
271
272/*
273 * Callouts from linesw.
274 */
275
276#define KM_LOWAT_DELAY ((ns_time_t)1000)
277
278static void
279kmstart(
280 struct tty *tp)
281{
282 extern int hz;
283 if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
284 goto out;
285 if (tp->t_outq.c_cc == 0)
286 goto out;
287 tp->t_state |= TS_BUSY;
288 if (tp->t_outq.c_cc > tp->t_lowat) {
289 /*
290 * Start immediately.
291 */
292 kmoutput(tp);
293 }
294 else {
295 /*
296 * Wait a bit...
297 */
298#if 0
299 /* FIXME */
300 timeout(kmtimeout, tp, hz);
301#else
302 kmoutput(tp);
303#endif
304 }
305out:
306 ttwwakeup(tp);
307}
308
309static void
55e303ae 310kmtimeout(void *arg)
1c79356b
A
311{
312 boolean_t funnel_state;
55e303ae 313 struct tty *tp = (struct tty *) arg;
1c79356b
A
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