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