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