]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/i386/km.c
xnu-792.24.17.tar.gz
[apple/xnu.git] / bsd / dev / i386 / km.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
6601e61a 4 * @APPLE_LICENSE_HEADER_START@
1c79356b 5 *
6601e61a
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.
8f6c56a5 11 *
6601e61a
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
8f6c56a5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6601e61a
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.
8f6c56a5 19 *
6601e61a 20 * @APPLE_LICENSE_HEADER_END@
1c79356b
A
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
91447636
A
44extern int hz;
45
46extern void cnputcusr(char);
47extern int cngetc(void);
48
49void kminit(void);
50int kmopen(dev_t dev, int flag, int devtype, struct proc *pp);
51int kmclose(dev_t dev, int flag, int mode, struct proc *p);
52int kmread(dev_t dev, struct uio *uio, int ioflag);
53int kmwrite(dev_t dev, struct uio *uio, int ioflag);
54int kmioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
55int kmputc(int c);
56int kmgetc(dev_t dev);
57int kmgetc_silent(dev_t dev);
58void cons_cinput(char ch);
59
1c79356b
A
60/*
61 * 'Global' variables, shared only by this file and conf.c.
62 */
1c79356b
A
63struct 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 */
69int disableConsoleOutput;
70
71/*
72 * 'Global' variables, shared only by this file and kmDevice.m.
73 */
74int initialized = 0;
75
76static int kmoutput(struct tty *tp);
1c79356b
A
77static void kmstart(struct tty *tp);
78
79extern void KeyboardOpen(void);
80
91447636
A
81void
82kminit(void)
1c79356b 83{
91447636 84 cons.t_dev = makedev(12, 0);
1c79356b
A
85 initialized = 1;
86}
87/*
88 * cdevsw interface to km driver.
89 */
90int
91kmopen(
92 dev_t dev,
93 int flag,
91447636 94 __unused int devtype,
1c79356b
A
95 struct proc *pp)
96{
1c79356b
A
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);
91447636 119 } else if ((tp->t_state & TS_XCLUDE) && proc_suser(pp))
1c79356b
A
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);
6601e61a 138 if( video.v_width != 0 && video.v_height != 0 ) {
1c79356b
A
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
149int
150kmclose(
91447636 151 __unused dev_t dev,
1c79356b 152 int flag,
91447636
A
153 __unused int mode,
154 __unused struct proc *p)
1c79356b
A
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
165int
166kmread(
91447636 167 __unused dev_t dev,
1c79356b
A
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
177int
178kmwrite(
91447636 179 __unused dev_t dev,
1c79356b
A
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
189int
190kmioctl(
91447636 191 __unused dev_t dev,
1c79356b
A
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);
91447636 227 if (ENOTTY != error)
1c79356b 228 return error;
91447636 229 return ttioctl (tp, cmd, data, flag, p);
1c79356b
A
230 }
231}
232
233int
234kmputc(
235 int c)
236{
237
238 if( disableConsoleOutput)
239 return( 0);
240
241 if(!initialized)
242 return( 0);
243
244 if(c == '\n')
91447636 245 cnputcusr('\r');
1c79356b 246
91447636 247 cnputcusr(c);
1c79356b
A
248
249 return 0;
250}
251
252int
253kmgetc(
91447636 254 __unused dev_t dev)
1c79356b
A
255{
256 int c;
257
258 c= cngetc();
259
260 if (c == '\r') {
261 c = '\n';
262 }
91447636 263 cnputcusr(c);
1c79356b
A
264 return c;
265}
266
267int
268kmgetc_silent(
91447636 269 __unused dev_t dev)
1c79356b
A
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
286static void
287kmstart(
288 struct tty *tp)
289{
1c79356b
A
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;
91447636
A
295 kmoutput(tp);
296 return;
297
1c79356b 298out:
91447636
A
299 (*linesw[tp->t_line].l_start)(tp);
300 return;
1c79356b
A
301}
302
303static void
55e303ae 304kmtimeout(void *arg)
1c79356b
A
305{
306 boolean_t funnel_state;
55e303ae 307 struct tty *tp = (struct tty *) arg;
1c79356b
A
308
309 funnel_state = thread_funnel_set(kernel_flock, TRUE);
310 kmoutput(tp);
9bccf70c 311 (void) thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
312
313
314}
315static int
316kmoutput(
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;
1c79356b
A
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;
91447636 341 (*linesw[tp->t_line].l_start)(tp);
1c79356b
A
342
343 return 0;
344}
91447636
A
345
346void
1c79356b
A
347cons_cinput(char ch)
348{
349 struct tty *tp = &cons;
1c79356b
A
350
351 (*linesw[tp->t_line].l_rint) (ch, tp);
1c79356b
A
352}
353