]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/i386/km.c
xnu-1228.3.13.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 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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>
0c530ab8 49#include <pexpert/i386/boot.h>
1c79356b 50
91447636
A
51extern int hz;
52
53extern void cnputcusr(char);
54extern int cngetc(void);
55
56void kminit(void);
57int kmopen(dev_t dev, int flag, int devtype, struct proc *pp);
58int kmclose(dev_t dev, int flag, int mode, struct proc *p);
59int kmread(dev_t dev, struct uio *uio, int ioflag);
60int kmwrite(dev_t dev, struct uio *uio, int ioflag);
61int kmioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p);
62int kmputc(int c);
63int kmgetc(dev_t dev);
64int kmgetc_silent(dev_t dev);
65void cons_cinput(char ch);
66
1c79356b
A
67/*
68 * 'Global' variables, shared only by this file and conf.c.
69 */
1c79356b
A
70struct 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 */
76int disableConsoleOutput;
77
78/*
79 * 'Global' variables, shared only by this file and kmDevice.m.
80 */
81int initialized = 0;
82
83static int kmoutput(struct tty *tp);
1c79356b
A
84static void kmstart(struct tty *tp);
85
86extern void KeyboardOpen(void);
87
91447636
A
88void
89kminit(void)
1c79356b 90{
91447636 91 cons.t_dev = makedev(12, 0);
1c79356b
A
92 initialized = 1;
93}
94/*
95 * cdevsw interface to km driver.
96 */
97int
98kmopen(
99 dev_t dev,
100 int flag,
91447636 101 __unused int devtype,
1c79356b
A
102 struct proc *pp)
103{
1c79356b
A
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);
91447636 126 } else if ((tp->t_state & TS_XCLUDE) && proc_suser(pp))
1c79356b
A
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);
0c530ab8
A
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 ) {
1c79356b
A
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
159int
160kmclose(
91447636 161 __unused dev_t dev,
1c79356b 162 int flag,
91447636
A
163 __unused int mode,
164 __unused struct proc *p)
1c79356b
A
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
175int
176kmread(
91447636 177 __unused dev_t dev,
1c79356b
A
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
187int
188kmwrite(
91447636 189 __unused dev_t dev,
1c79356b
A
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
199int
200kmioctl(
91447636 201 __unused dev_t dev,
1c79356b
A
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);
91447636 237 if (ENOTTY != error)
1c79356b 238 return error;
91447636 239 return ttioctl (tp, cmd, data, flag, p);
1c79356b
A
240 }
241}
242
243int
244kmputc(
245 int c)
246{
247
248 if( disableConsoleOutput)
249 return( 0);
250
251 if(!initialized)
252 return( 0);
253
254 if(c == '\n')
91447636 255 cnputcusr('\r');
1c79356b 256
91447636 257 cnputcusr(c);
1c79356b
A
258
259 return 0;
260}
261
262int
263kmgetc(
91447636 264 __unused dev_t dev)
1c79356b
A
265{
266 int c;
267
268 c= cngetc();
269
270 if (c == '\r') {
271 c = '\n';
272 }
91447636 273 cnputcusr(c);
1c79356b
A
274 return c;
275}
276
277int
278kmgetc_silent(
91447636 279 __unused dev_t dev)
1c79356b
A
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
296static void
297kmstart(
298 struct tty *tp)
299{
1c79356b
A
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;
91447636
A
305 kmoutput(tp);
306 return;
307
1c79356b 308out:
91447636
A
309 (*linesw[tp->t_line].l_start)(tp);
310 return;
1c79356b
A
311}
312
313static void
55e303ae 314kmtimeout(void *arg)
1c79356b
A
315{
316 boolean_t funnel_state;
55e303ae 317 struct tty *tp = (struct tty *) arg;
1c79356b
A
318
319 funnel_state = thread_funnel_set(kernel_flock, TRUE);
320 kmoutput(tp);
9bccf70c 321 (void) thread_funnel_set(kernel_flock, funnel_state);
1c79356b
A
322
323
324}
325static int
326kmoutput(
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;
1c79356b
A
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;
91447636 351 (*linesw[tp->t_line].l_start)(tp);
1c79356b
A
352
353 return 0;
354}
91447636
A
355
356void
1c79356b
A
357cons_cinput(char ch)
358{
359 struct tty *tp = &cons;
1c79356b
A
360
361 (*linesw[tp->t_line].l_rint) (ch, tp);
1c79356b
A
362}
363