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