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