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