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