1 /* $NetBSD: kd.c,v 1.8 1994/12/17 20:14:23 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 /* This is called by kbd_serial() like a pseudo-device. */ 67 void 68 kd_attach(n) 69 int n; 70 { 71 kd_tty[0] = ttymalloc(); 72 73 /* Tell keyboard module where to send read data. */ 74 kbd_ascii(kd_tty[0]); 75 } 76 77 int 78 kdopen(dev, flag, mode, p) 79 dev_t dev; 80 int flag, mode; 81 struct proc *p; 82 { 83 int error, unit; 84 struct tty *tp; 85 86 unit = minor(dev); 87 if (unit) return ENXIO; 88 89 tp = kd_tty[unit]; 90 if (tp == NULL) 91 return ENXIO; 92 93 if ((error = kbd_iopen()) != 0) { 94 #ifdef DIAGNOSTIC 95 printf("kd: kbd_iopen, error=%d\n", error); 96 #endif 97 return (error); 98 } 99 100 tp->t_oproc = kdstart; 101 tp->t_param = kdparam; 102 tp->t_dev = dev; 103 if ((tp->t_state & TS_ISOPEN) == 0) { 104 tp->t_state |= TS_WOPEN; 105 ttychars(tp); 106 tp->t_iflag = TTYDEF_IFLAG; 107 tp->t_oflag = TTYDEF_OFLAG; 108 tp->t_cflag = TTYDEF_CFLAG; 109 tp->t_lflag = TTYDEF_LFLAG; 110 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 111 kdparam(tp, &tp->t_termios); 112 ttsetwater(tp); 113 } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) 114 return EBUSY; 115 tp->t_state |= TS_CARR_ON; 116 117 return ((*linesw[tp->t_line].l_open)(dev, tp)); 118 } 119 120 int 121 kdclose(dev, flag, mode, p) 122 dev_t dev; 123 int flag, mode; 124 struct proc *p; 125 { 126 int unit = minor(dev); 127 struct tty *tp = kd_tty[unit]; 128 129 (*linesw[tp->t_line].l_close)(tp, flag); 130 ttyclose(tp); 131 return (0); 132 } 133 134 int 135 kdread(dev, uio, flag) 136 dev_t dev; 137 struct uio *uio; 138 int flag; 139 { 140 int unit = minor(dev); 141 struct tty *tp = kd_tty[unit]; 142 143 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 144 } 145 146 int 147 kdwrite(dev, uio, flag) 148 dev_t dev; 149 struct uio *uio; 150 int flag; 151 { 152 int unit = minor(dev); 153 struct tty *tp = kd_tty[unit]; 154 155 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 156 } 157 158 int 159 kdioctl(dev, cmd, data, flag, p) 160 dev_t dev; 161 int cmd; 162 caddr_t data; 163 int flag; 164 struct proc *p; 165 { 166 int error; 167 int unit = minor(dev); 168 struct tty *tp = kd_tty[unit]; 169 170 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 171 if (error >= 0) 172 return error; 173 error = ttioctl(tp, cmd, data, flag, p); 174 if (error >= 0) 175 return error; 176 177 /* Handle any ioctl commands specific to kbd/display. */ 178 /* XXX - Send KB* ioctls to kbd module? */ 179 /* XXX - Send FB* ioctls to fb module? */ 180 181 return ENOTTY; 182 } 183 184 void 185 kdstart(tp) 186 struct tty *tp; 187 { 188 struct clist *cl; 189 int s, len; 190 u_char buf[BURST]; 191 192 s = spltty(); 193 if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) 194 goto out; 195 tp->t_state |= TS_BUSY; 196 cl = &tp->t_outq; 197 198 /* 199 * XXX - It might be nice to have our own fbputs() so 200 * we would not have to use the (slow) PROM printf. 201 */ 202 while ((len = q_to_b(cl, buf, BURST-1)) > 0) { 203 buf[len] = '\0'; 204 (void) splhigh(); 205 #if 0 206 /* XXX - Not yet. Not sure what args should be. */ 207 (romVectorPtr->fbWriteStr)(buf); 208 #else 209 mon_printf("%s", buf); 210 #endif 211 (void) spltty(); 212 } 213 214 tp->t_state &= ~TS_BUSY; 215 if (tp->t_state & TS_ASLEEP) { 216 tp->t_state &= ~TS_ASLEEP; 217 wakeup((caddr_t)cl); 218 } 219 selwakeup(&tp->t_wsel); 220 out: 221 splx(s); 222 } 223 224 static int 225 kdparam(tp, t) 226 struct tty *tp; 227 struct termios *t; 228 { 229 /* XXX - These are ignored... */ 230 tp->t_ispeed = t->c_ispeed; 231 tp->t_ospeed = t->c_ospeed; 232 tp->t_cflag = t->c_cflag; 233 return 0; 234 } 235 236 237 /* 238 * kd console support 239 */ 240 241 extern int zscnprobe_kbd(), zscngetc(), kbd_translate(); 242 243 kdcnprobe(cp) 244 struct consdev *cp; 245 { 246 int maj; 247 248 /* locate the major number */ 249 for (maj = 0; maj < nchrdev; maj++) 250 if (cdevsw[maj].d_open == (void*)kdopen) 251 break; 252 253 /* initialize required fields */ 254 cp->cn_dev = makedev(maj, 0); 255 cp->cn_pri = zscnprobe_kbd(); 256 } 257 258 kdcninit(cp) 259 struct consdev *cp; 260 { 261 262 /* This prepares zscngetc() */ 263 zs_set_conschan(1, 0); 264 265 /* This prepares kbd_translate() */ 266 kbd_init_tables(); 267 268 mon_printf("console on kd0 (keyboard/display)\n"); 269 } 270 271 kdcngetc(dev) 272 dev_t dev; 273 { 274 int c; 275 276 do { 277 c = zscngetc(0); 278 c = kbd_translate(c); 279 } while (c == -1); 280 281 return (c); 282 } 283 284 kdcnputc(dev, c) 285 dev_t dev; 286 int c; 287 { 288 int s; 289 290 s = splhigh(); 291 #if 0 292 /* XXX - Is this worth doing? */ 293 (romVectorPtr->fbWriteChar)(c); 294 #else 295 mon_putchar(c); 296 #endif 297 splx(s); 298 } 299