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