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