1 /* 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1992 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * OMRON Corporation. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)kbd.c 7.6 (Berkeley) 02/04/93 12 */ 13 14 /* 15 * kbd.c -- keyboard device driver 16 * remade by A.Fujita, DEC-21-1992 17 */ 18 19 #define NKBD 2 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/ioctl.h> 24 #include <sys/proc.h> 25 #include <sys/tty.h> 26 #include <sys/conf.h> 27 #include <sys/file.h> 28 #include <sys/uio.h> 29 #include <sys/kernel.h> 30 #include <sys/syslog.h> 31 32 #include <luna68k/dev/device.h> 33 #include <luna68k/dev/sioreg.h> 34 #include <luna68k/dev/siovar.h> 35 #include <luna68k/dev/kbio.h> 36 37 extern struct sio_portc *sio_port_assign(); 38 extern struct sio_portc *sio_port_get(); 39 40 struct sio_softc kbd_softc[NKBD]; 41 struct sio_portc kbd_sport; 42 struct sio_portc *kbd_pc; 43 44 int kbdopen(); 45 void kbdstart(); 46 int kbdparam(); 47 int kbdintr(); 48 49 struct tty kbd_tty[NKBD]; 50 51 int kbddefaultrate = B9600; /* speed of console line is fixed */ 52 int kbdmajor = 14; 53 int kbd_state = 0; 54 55 #define kbdunit(x) minor(x) 56 57 /* 58 * entry routines 59 */ 60 61 /* ARGSUSED */ 62 #ifdef __STDC__ 63 kbdopen(dev_t dev, int flag, int mode, struct proc *p) 64 #else 65 kbdopen(dev, flag, mode, p) 66 dev_t dev; 67 int flag, mode; 68 struct proc *p; 69 #endif 70 { 71 register struct tty *tp; 72 register int unit, s; 73 register struct sio_portc *pc; 74 int error = 0; 75 76 unit = kbdunit(dev); 77 78 if (unit != 0) 79 return (ENXIO); 80 81 if (kbd_state == 0) { 82 s = splhigh(); 83 pc = sio_port_get(1); 84 kbd_sport = *pc; 85 kbd_pc = sio_port_assign(1, kbdmajor, unit, kbdintr); 86 splx(s); 87 } 88 kbd_softc[unit].sc_pc = kbd_pc; 89 kbd_state |= 1 << unit; 90 91 tp = &kbd_tty[unit]; 92 tp->t_oproc = kbdstart; 93 tp->t_param = kbdparam; 94 tp->t_dev = dev; 95 if ((tp->t_state & TS_ISOPEN) == 0) { 96 tp->t_state |= TS_WOPEN; 97 ttychars(tp); 98 if (tp->t_ispeed == 0) { 99 /* 100 tp->t_iflag = TTYDEF_IFLAG; 101 tp->t_oflag = TTYDEF_OFLAG; 102 tp->t_cflag = TTYDEF_CFLAG; 103 tp->t_lflag = TTYDEF_LFLAG; 104 */ 105 tp->t_iflag = 0; 106 tp->t_oflag = 0; 107 tp->t_cflag = (CREAD | CS8 | HUPCL); 108 tp->t_lflag = 0; 109 110 tp->t_ispeed = tp->t_ospeed = kbddefaultrate; 111 } 112 ttsetwater(tp); 113 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 114 return (EBUSY); 115 116 tp->t_state |= TS_CARR_ON; 117 118 if (error == 0) 119 error = (*linesw[tp->t_line].l_open)(dev, tp); 120 121 return (error); 122 } 123 124 /*ARGSUSED*/ 125 kbdclose(dev, flag, mode, p) 126 dev_t dev; 127 int flag, mode; 128 struct proc *p; 129 { 130 register struct siodevice *sio = kbd_pc->pc_addr; 131 register struct sio_portc *pc; 132 register struct tty *tp; 133 register int unit, s; 134 int code, rr; 135 136 unit = kbdunit(dev); 137 138 tp = &kbd_tty[unit]; 139 (*linesw[tp->t_line].l_close)(tp, flag); 140 ttyclose(tp); 141 142 kbd_state &= ~(1 << unit); 143 144 if (kbd_state == 0) { 145 s = splhigh(); 146 147 while((rr = siogetreg(sio)) & RR_RXRDY) { 148 code = sio->sio_data; 149 DELAY(100); 150 } 151 152 pc = &kbd_sport; 153 (void) sio_port_assign(1, pc->pc_major, pc->pc_unit, pc->pc_intr); 154 splx(s); 155 } 156 157 return (0); 158 } 159 160 kbdread(dev, uio, flag) 161 dev_t dev; 162 struct uio *uio; 163 { 164 register struct tty *tp = &kbd_tty[kbdunit(dev)]; 165 166 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 167 } 168 169 int 170 kbdparam(tp, t) 171 register struct tty *tp; 172 register struct termios *t; 173 { 174 int unit = kbdunit(tp->t_dev); 175 register struct sio_softc *sc = &kbd_softc[unit]; 176 register int cflag = t->c_cflag; 177 178 /* and copy to tty */ 179 tp->t_ispeed = t->c_ispeed; 180 tp->t_ospeed = t->c_ospeed; 181 tp->t_cflag = cflag; 182 183 /* 184 * change line speed 185 */ 186 187 /* 188 * parity 189 */ 190 191 /* 192 * stop bit 193 */ 194 195 return (0); 196 } 197 198 kbdioctl(dev, cmd, data, flag, p) 199 dev_t dev; 200 int cmd; 201 caddr_t data; 202 int flag; 203 struct proc *p; 204 { 205 register struct siodevice *sio = kbd_pc->pc_addr; 206 register struct tty *tp; 207 register int unit = kbdunit(dev); 208 register int error; 209 int code, rr, s; 210 211 tp = &kbd_tty[unit]; 212 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 213 if (error >= 0) 214 return (error); 215 error = ttioctl(tp, cmd, data, flag); 216 if (error >= 0) 217 return (error); 218 219 switch (cmd) { 220 221 case KIOCMOUSE: 222 if (*((int *) data)) { 223 sio->sio_data = 0x60; /* enable mouse tracking */ 224 } else { 225 s = splhigh(); 226 sio->sio_data = 0x20; /* disable mouse tracking */ 227 while((rr = siogetreg(sio)) & RR_RXRDY) { 228 code = sio->sio_data; 229 DELAY(100); 230 } 231 splx(s); 232 } 233 break; 234 235 default: 236 return (ENOTTY); 237 } 238 return (0); 239 } 240 241 /* 242 * 243 */ 244 void 245 kbdstart(tp) 246 register struct tty *tp; 247 { 248 register int unit; 249 register struct siodevice *sio = kbd_pc->pc_addr; 250 register int rr; 251 int s, c; 252 253 s = spltty(); 254 255 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 256 goto out; 257 258 if (tp->t_outq.c_cc <= tp->t_lowat) { 259 if (tp->t_state&TS_ASLEEP) { 260 tp->t_state &= ~TS_ASLEEP; 261 wakeup((caddr_t)&tp->t_outq); 262 } 263 selwakeup(&tp->t_wsel); 264 } 265 266 if (tp->t_outq.c_cc != 0) 267 c = getc(&tp->t_outq); 268 269 out: 270 splx(s); 271 } 272 273 /* 274 * interrupt handling 275 */ 276 277 kbdintr(unit) 278 register int unit; 279 { 280 register struct siodevice *sio = kbd_pc->pc_addr; 281 register struct tty *tp; 282 register u_char code; 283 int s, rr; 284 285 tp = &kbd_tty[0]; /* Keyboard */ 286 rr = siogetreg(sio); 287 288 if (rr & RR_RXRDY) { 289 code = sio->sio_data; 290 if ((tp->t_state & TS_ISOPEN) != 0) 291 (*linesw[tp->t_line].l_rint)(code, tp); 292 293 while ((rr = siogetreg(sio)) & RR_RXRDY) { 294 code = sio->sio_data; 295 if ((tp->t_state & TS_ISOPEN) != 0) 296 (*linesw[tp->t_line].l_rint)(code, tp); 297 } 298 } 299 300 if (rr & RR_TXRDY) { 301 sio->sio_cmd = WR0_RSTPEND; 302 } 303 } 304 305 kbdselect(dev, rw, p) 306 dev_t dev; 307 int rw; 308 struct proc *p; 309 { 310 register int unit = kbdunit(dev); 311 register struct tty *tp; 312 int nread; 313 int s = spltty(); 314 315 tp = &kbd_tty[unit]; 316 317 switch (rw) { 318 319 case FREAD: 320 nread = ttnread(tp); 321 if (nread > 0 || ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0)) 322 goto win; 323 324 selrecord(p, &tp->t_rsel); 325 break; 326 327 case FWRITE: 328 if (tp->t_outq.c_cc <= tp->t_lowat) 329 goto win; 330 selrecord(p, &tp->t_wsel); 331 break; 332 } 333 splx(s); 334 return (0); 335 win: 336 splx(s); 337 return (1); 338 } 339