1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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>
37#include <sys/errno.h>
38#include <sys/proc.h>
39#include <sys/msgbuf.h>
40#include <sys/time.h>
41#include <dev/kmreg_com.h>
42#include <pexpert/pexpert.h>
43
44
45
46
47struct tty *km_tty[1] = { &cons };
48
49
50
51
52
53int disableConsoleOutput;
54
55static int initialized = 0;
56
57
58extern d_open_t kmopen;
59extern d_close_t kmclose;
60extern d_read_t kmread;
61extern d_write_t kmwrite;
62extern d_ioctl_t kmioctl;
63extern d_getc_t kmgetc;
64extern d_putc_t kmputc;
65
66extern void kminit(void);
67
68
69extern void cnputcusr(char);
70extern int cngetc(void);
71extern void cons_cinput(char ch);
72
73static int kmoutput(struct tty *tp);
74static void kmtimeout(struct tty *tp);
75static void kmstart(struct tty *tp);
76
77extern void KeyboardOpen(void);
78
79void
80kminit(void)
81{
82 cons.t_dev = makedev(12, 0);
83 initialized = 1;
84}
85
86
87
88int
89kmopen(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;
117 ret = ((*linesw[tp->t_line].l_open)(dev, tp));
118 {
119 PE_Video video;
120 wp = &tp->t_winsize;
121
122
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
143int
144kmclose(__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
156int
157kmread(__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
165int
166kmwrite(__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
174int
175kmioctl( __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
193
194
195
196 return EINVAL;
197
198
199 case TIOCSETA:
200 case TIOCSETAW:
201 case TIOCSETAF: {
202 register struct termios *t = (struct termios *)data;
203 t->c_cflag |= CLOCAL;
204
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
214int
215kmputc(__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
232int
233kmgetc(__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
247int
248kmgetc_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
260
261
262
263
264
265#define KM_LOWAT_DELAY ((ns_time_t)1000)
266
267static void
268kmstart(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
278out:
279 (*linesw[tp->t_line].l_start)(tp);
280 return;
281}
282
283static void
284kmtimeout(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}
294static int
295kmoutput(struct tty *tp)
296{
297
298
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
322void cons_cinput(char ch)
323{
324 struct tty *tp = &cons;
325
326 (*linesw[tp->t_line].l_rint) (ch, tp);
327}
328
329