1 /* $NetBSD: kd.c,v 1.10 1995/03/24 19:48:44 gwr Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Gordon W. Ross 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * Keyboard/Display device. 32 * 33 * This driver exists simply to provide a tty device that 34 * the indirect console driver can point to. 35 * The kbd driver sends its input here. 36 * Output goes to the screen via PROM printf. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/proc.h> 41 #include <sys/systm.h> 42 #include <sys/ioctl.h> 43 #include <sys/tty.h> 44 #include <sys/file.h> 45 #include <sys/conf.h> 46 #include <sys/device.h> 47 48 #include <machine/autoconf.h> 49 #include <machine/mon.h> 50 51 #include <dev/cons.h> 52 53 #define BURST 64 54 55 struct tty *kd_tty[1]; 56 57 int kdopen(dev_t, int, int, struct proc *); 58 int kdclose(dev_t, int, int, struct proc *); 59 int kdread(dev_t, struct uio *, int); 60 int kdwrite(dev_t, struct uio *, int); 61 int kdioctl(dev_t, int, caddr_t, int, struct proc *); 62 63 static int kdparam(struct tty *, struct termios *); 64 static void kdstart(struct tty *); 65 66 int kd_is_console; 67 68 /* This is called by kbd_serial() like a pseudo-device. */ 69 void 70 kd_attach(n) 71 int n; 72 { 73 kd_tty[0] = ttymalloc(); 74 75 /* Tell keyboard module where to send read data. */ 76 kbd_ascii(kd_tty[0]); 77 } 78 79 int 80 kdopen(dev, flag, mode, p) 81 dev_t dev; 82 int flag, mode; 83 struct proc *p; 84 { 85 int error, unit; 86 struct tty *tp; 87 88 unit = minor(dev); 89 if (unit) return ENXIO; 90 91 tp = kd_tty[unit]; 92 if (tp == NULL) 93 return ENXIO; 94 95 if ((error = kbd_iopen()) != 0) { 96 #ifdef DIAGNOSTIC 97 printf("kd: kbd_iopen, error=%d\n", error); 98 #endif 99 return (error); 100 } 101 102 tp->t_oproc = kdstart; 103 tp->t_param = kdparam; 104 tp->t_dev = dev; 105 if ((tp->t_state & TS_ISOPEN) == 0) { 106 tp->t_state |= TS_WOPEN; 107 ttychars(tp); 108 tp->t_iflag = TTYDEF_IFLAG; 109 tp->t_oflag = TTYDEF_OFLAG; 110 tp->t_cflag = TTYDEF_CFLAG; 111 tp->t_lflag = TTYDEF_LFLAG; 112 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 113 kdparam(tp, &tp->t_termios); 114 ttsetwater(tp); 115 } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 116 return EBUSY; 117 tp->t_state |= TS_CARR_ON; 118 119 return ((*linesw[tp->t_line].l_open)(dev, tp)); 120 } 121 122 int 123 kdclose(dev, flag, mode, p) 124 dev_t dev; 125 int flag, mode; 126 struct proc *p; 127 { 128 int unit = minor(dev); 129 struct tty *tp = kd_tty[unit]; 130 131 (*linesw[tp->t_line].l_close)(tp, flag); 132 ttyclose(tp); 133 return (0); 134 } 135 136 int 137 kdread(dev, uio, flag) 138 dev_t dev; 139 struct uio *uio; 140 int flag; 141 { 142 int unit = minor(dev); 143 struct tty *tp = kd_tty[unit]; 144 145 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 146 } 147 148 int 149 kdwrite(dev, uio, flag) 150 dev_t dev; 151 struct uio *uio; 152 int flag; 153 { 154 int unit = minor(dev); 155 struct tty *tp = kd_tty[unit]; 156 157 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 158 } 159 160 int 161 kdioctl(dev, cmd, data, flag, p) 162 dev_t dev; 163 int cmd; 164 caddr_t data; 165 int flag; 166 struct proc *p; 167 { 168 int error; 169 int unit = minor(dev); 170 struct tty *tp = kd_tty[unit]; 171 172 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 173 if (error >= 0) 174 return error; 175 error = ttioctl(tp, cmd, data, flag, p); 176 if (error >= 0) 177 return error; 178 179 /* Handle any ioctl commands specific to kbd/display. */ 180 /* XXX - Send KB* ioctls to kbd module? */ 181 /* XXX - Send FB* ioctls to fb module? */ 182 183 return ENOTTY; 184 } 185 186 void 187 kdstart(tp) 188 struct tty *tp; 189 { 190 struct clist *cl; 191 int s, len; 192 u_char buf[BURST]; 193 194 s = spltty(); 195 if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) 196 goto out; 197 tp->t_state |= TS_BUSY; 198 cl = &tp->t_outq; 199 200 /* 201 * XXX - It might be nice to have our own fbputs() so 202 * we would not have to use the (slow) PROM printf. 203 */ 204 while ((len = q_to_b(cl, buf, BURST-1)) > 0) { 205 buf[len] = '\0'; 206 207 /* 208 * Note that this device might NOT be the console. 209 * Using the PROM to put text on the screen is easy, 210 * but it only works if this is the console (sigh). 211 * If this is not the console, you are typing blind! 212 */ 213 if (kd_is_console) { 214 (romVectorPtr->fbWriteStr)(buf, len); 215 } 216 } 217 218 tp->t_state &= ~TS_BUSY; 219 if (tp->t_state & TS_ASLEEP) { 220 tp->t_state &= ~TS_ASLEEP; 221 wakeup((caddr_t)cl); 222 } 223 selwakeup(&tp->t_wsel); 224 out: 225 splx(s); 226 } 227 228 static int 229 kdparam(tp, t) 230 struct tty *tp; 231 struct termios *t; 232 { 233 /* XXX - These are ignored... */ 234 tp->t_ispeed = t->c_ispeed; 235 tp->t_ospeed = t->c_ospeed; 236 tp->t_cflag = t->c_cflag; 237 return 0; 238 } 239 240 241 /* 242 * kd console support 243 */ 244 245 extern int zscnprobe_kbd(), zscngetc(), kbd_translate(); 246 247 kdcnprobe(cp) 248 struct consdev *cp; 249 { 250 int maj; 251 252 /* locate the major number */ 253 for (maj = 0; maj < nchrdev; maj++) 254 if (cdevsw[maj].d_open == (void*)kdopen) 255 break; 256 257 /* initialize required fields */ 258 cp->cn_dev = makedev(maj, 0); 259 cp->cn_pri = zscnprobe_kbd(); 260 } 261 262 kdcninit(cp) 263 struct consdev *cp; 264 { 265 266 /* This prepares zscngetc() */ 267 zs_set_conschan(1, 0); 268 269 /* This prepares kbd_translate() */ 270 kbd_init_tables(); 271 272 /* Indicate that it is OK to use the PROM fbwrite */ 273 kd_is_console = 1; 274 275 mon_printf("console on kd0 (keyboard/display)\n"); 276 } 277 278 kdcngetc(dev) 279 dev_t dev; 280 { 281 int c; 282 283 do { 284 c = zscngetc(0); 285 c = kbd_translate(c); 286 } while (c == -1); 287 288 return (c); 289 } 290 291 kdcnputc(dev, c) 292 dev_t dev; 293 int c; 294 { 295 int s; 296 297 s = splhigh(); 298 #if 0 299 /* XXX - Is this worth doing? */ 300 (romVectorPtr->fbWriteChar)(c); 301 #else 302 mon_putchar(c); 303 #endif 304 splx(s); 305 } 306 307 extern void fb_unblank(); 308 void kdcnpollc(dev, on) 309 dev_t dev; 310 int on; 311 { 312 if (on) 313 fb_unblank(); 314 } 315