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