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 * @(#)bmc.c 7.1 (Berkeley) 11/17/92 12 */ 13 14 #define BMC_NOCONSOLE 15 #define BMD 16 17 #ifdef BMD 18 #define BMC_CNPORT 1 19 #else 20 #define BMC_CNPORT 0 21 #endif 22 23 #include "bmc.h" 24 #if NBMC > 0 25 26 #include "sys/param.h" 27 #include "sys/systm.h" 28 #include "sys/ioctl.h" 29 #include "sys/proc.h" 30 #include "sys/tty.h" 31 #include "sys/conf.h" 32 #include "sys/file.h" 33 #include "sys/uio.h" 34 #include "sys/kernel.h" 35 #include "sys/syslog.h" 36 37 #include "device.h" 38 #include "sioreg.h" 39 #include "siovar.h" 40 41 #ifdef BMD 42 #include "kbdreg.h" 43 #endif 44 45 extern struct sio_portc *sio_port_assign(); 46 47 int bmcprobe(); 48 int bmcopen(); 49 void bmcstart(); 50 int bmcparam(); 51 int bmcintr(); 52 53 struct driver bmcdriver = { 54 bmcprobe, "bmc", 55 }; 56 57 struct bmc_softc { 58 struct sio_portc *sc_pc; 59 int sc_mask; 60 }; 61 62 struct bmc_softc bmc_softc[NBMC]; 63 64 struct tty bmc_tty[NBMC]; 65 66 int bmc_config_done = 0; 67 68 int bmcconsole; 69 int bmcdefaultrate = B9600; /* speed of console line is fixed */ 70 int bmcmajor = 0; 71 72 #define bmcunit(x) minor(x) 73 74 75 /* 76 * probe routine 77 */ 78 79 bmcprobe(hd) 80 register struct hp_device *hd; 81 { 82 } 83 84 bmcinit(port) 85 register int port; 86 { 87 register struct bmc_softc *sc = &bmc_softc[0]; 88 89 /* 90 * if BMC is already configured, should be skipped. 91 */ 92 if (bmc_config_done) 93 return(0); 94 95 /* 96 * Check out bitmap Interface board 97 */ 98 99 /* port checking (for keyboard) */ 100 if (port != 1) 101 return(0); 102 103 /* locate the major number */ 104 for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++) 105 if (cdevsw[bmcmajor].d_open == bmcopen) 106 break; 107 108 sc->sc_pc = sio_port_assign(port, bmcmajor, 0, bmcintr); 109 110 printf("bmc%d: port %d, address 0x%x\n", sc->sc_pc->pc_unit, port, sc->sc_pc->pc_addr); 111 112 #ifdef BMD 113 bmdinit(); 114 #endif 115 116 bmc_config_done = 1; 117 return(1); 118 } 119 120 121 /* 122 * entry routines 123 */ 124 125 /* ARGSUSED */ 126 #ifdef __STDC__ 127 bmcopen(dev_t dev, int flag, int mode, struct proc *p) 128 #else 129 bmcopen(dev, flag, mode, p) 130 dev_t dev; 131 int flag, mode; 132 struct proc *p; 133 #endif 134 { 135 register struct tty *tp; 136 register int unit; 137 int error = 0; 138 139 unit = bmcunit(dev); 140 if (unit >= NBMC) 141 return (ENXIO); 142 tp = &bmc_tty[unit]; 143 tp->t_oproc = bmcstart; 144 tp->t_param = bmcparam; 145 tp->t_dev = dev; 146 if ((tp->t_state & TS_ISOPEN) == 0) { 147 tp->t_state |= TS_WOPEN; 148 ttychars(tp); 149 if (tp->t_ispeed == 0) { 150 tp->t_iflag = TTYDEF_IFLAG; 151 tp->t_oflag = TTYDEF_OFLAG; 152 tp->t_cflag = TTYDEF_CFLAG; 153 /* tp->t_cflag = (CREAD | CS8 | HUPCL); */ 154 tp->t_lflag = TTYDEF_LFLAG; 155 tp->t_ispeed = tp->t_ospeed = bmcdefaultrate; 156 } 157 bmcparam(tp, &tp->t_termios); 158 ttsetwater(tp); 159 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 160 return (EBUSY); 161 tp->t_state |= TS_CARR_ON; 162 (void) spltty(); 163 while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 164 (tp->t_state & TS_CARR_ON) == 0) { 165 tp->t_state |= TS_WOPEN; 166 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 167 ttopen, 0)) 168 break; 169 } 170 (void) spl0(); 171 if (error == 0) 172 error = (*linesw[tp->t_line].l_open)(dev, tp); 173 174 return (error); 175 } 176 177 /*ARGSUSED*/ 178 bmcclose(dev, flag, mode, p) 179 dev_t dev; 180 int flag, mode; 181 struct proc *p; 182 { 183 register struct tty *tp; 184 register int unit; 185 186 unit = bmcunit(dev); 187 tp = &bmc_tty[unit]; 188 (*linesw[tp->t_line].l_close)(tp, flag); 189 ttyclose(tp); 190 return (0); 191 } 192 193 bmcread(dev, uio, flag) 194 dev_t dev; 195 struct uio *uio; 196 { 197 register struct tty *tp = &bmc_tty[bmcunit(dev)]; 198 199 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 200 } 201 202 bmcwrite(dev, uio, flag) 203 dev_t dev; 204 struct uio *uio; 205 { 206 register struct tty *tp = &bmc_tty[bmcunit(dev)]; 207 208 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 209 } 210 211 /* 212 * Stop output on a line. 213 */ 214 /*ARGSUSED*/ 215 bmcstop(tp, flag) 216 register struct tty *tp; 217 { 218 register int s; 219 220 s = spltty(); 221 if (tp->t_state & TS_BUSY) { 222 if ((tp->t_state&TS_TTSTOP)==0) 223 tp->t_state |= TS_FLUSH; 224 } 225 splx(s); 226 } 227 228 bmcioctl(dev, cmd, data, flag, p) 229 dev_t dev; 230 int cmd; 231 caddr_t data; 232 int flag; 233 struct proc *p; 234 { 235 register struct tty *tp; 236 register int unit = bmcunit(dev); 237 register int error; 238 239 tp = &bmc_tty[unit]; 240 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 241 if (error >= 0) 242 return (error); 243 error = ttioctl(tp, cmd, data, flag); 244 if (error >= 0) 245 return (error); 246 247 switch (cmd) { 248 default: 249 return (ENOTTY); 250 } 251 return (0); 252 } 253 254 /* 255 * 256 */ 257 #ifdef BMD 258 void 259 bmcstart(tp) 260 register struct tty *tp; 261 { 262 int unit = bmcunit(tp->t_dev); 263 register struct bmc_softc *sc = &bmc_softc[unit]; 264 register int cc, s; 265 int hiwat = 0; 266 267 s = spltty(); 268 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { 269 splx(s); 270 return; 271 } 272 tp->t_state |= TS_BUSY; 273 cc = tp->t_outq.c_cc; 274 if (cc <= tp->t_lowat) { 275 if (tp->t_state & TS_ASLEEP) { 276 tp->t_state &= ~TS_ASLEEP; 277 wakeup((caddr_t)&tp->t_outq); 278 } 279 selwakeup(&tp->t_wsel); 280 } 281 /* 282 * Limit the amount of output we do in one burst 283 * to prevent hogging the CPU. 284 */ 285 /* 286 if (cc > iteburst) { 287 hiwat++; 288 cc = iteburst; 289 } 290 */ 291 while (--cc >= 0) { 292 register int c; 293 294 c = getc(&tp->t_outq); 295 /* 296 * iteputchar() may take a long time and we don't want to 297 * block all interrupts for long periods of time. Since 298 * there is no need to stay at high priority while outputing 299 * the character (since we don't have to worry about 300 * interrupts), we don't. We just need to make sure that 301 * we don't reenter iteputchar, which is guarenteed by the 302 * earlier setting of TS_BUSY. 303 */ 304 splx(s); 305 bmdputc(c & sc->sc_mask); 306 spltty(); 307 } 308 /* 309 if (hiwat) { 310 tp->t_state |= TS_TIMEOUT; 311 timeout(ttrstrt, tp, 1); 312 } 313 */ 314 tp->t_state &= ~TS_BUSY; 315 splx(s); 316 } 317 #else 318 void 319 bmcstart(tp) 320 register struct tty *tp; 321 { 322 register struct siodevice *sio; 323 register int rr; 324 int s, unit, c; 325 326 unit = bmcunit(tp->t_dev); 327 sio = bmc_softc[unit].sc_pc->pc_addr; 328 s = spltty(); 329 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 330 goto out; 331 if (tp->t_outq.c_cc <= tp->t_lowat) { 332 if (tp->t_state&TS_ASLEEP) { 333 tp->t_state &= ~TS_ASLEEP; 334 wakeup((caddr_t)&tp->t_outq); 335 } 336 selwakeup(&tp->t_wsel); 337 } 338 if (tp->t_outq.c_cc == 0) 339 goto out; 340 rr = siogetreg(sio); 341 if (rr & RR_TXRDY) { 342 c = getc(&tp->t_outq); 343 tp->t_state |= TS_BUSY; 344 sio->sio_data = c; 345 } 346 out: 347 splx(s); 348 } 349 #endif 350 351 bmcparam(tp, t) 352 register struct tty *tp; 353 register struct termios *t; 354 { 355 int unit = bmcunit(tp->t_dev); 356 register struct bmc_softc *sc = &bmc_softc[unit]; 357 register int cflag = t->c_cflag; 358 359 /* and copy to tty */ 360 tp->t_ispeed = t->c_ispeed; 361 tp->t_ospeed = t->c_ospeed; 362 tp->t_cflag = cflag; 363 364 /* 365 * change line speed 366 */ 367 368 switch (cflag&CSIZE) { 369 case CS5: 370 sc->sc_mask = 0x1F ; break; 371 case CS6: 372 sc->sc_mask = 0x3F ; break; 373 case CS7: 374 sc->sc_mask = 0x7F ; break; 375 case CS8: 376 sc->sc_mask = 0xFF ; break; 377 } 378 379 /* 380 * parity 381 */ 382 383 /* 384 * stop bit 385 */ 386 387 return (0); 388 } 389 390 391 /* 392 * interrupt handling 393 */ 394 395 #ifdef BMD 396 bmcintr(unit) 397 register int unit; 398 { 399 register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr; 400 register struct tty *tp; 401 register u_char code; 402 register int c; 403 int s, rr; 404 405 tp = &bmc_tty[unit]; 406 rr = siogetreg(sio); 407 408 if (rr & RR_RXRDY) { 409 code = sio->sio_data; 410 c = kbd_decode(code); 411 if (c & KC_TYPE) /* skip special codes */ 412 return; 413 code = (c & KC_CHAR); 414 if ((tp->t_state & TS_ISOPEN) != 0) 415 (*linesw[tp->t_line].l_rint)(code, tp); 416 } 417 } 418 #else 419 bmcintr(unit) 420 register int unit; 421 { 422 register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr; 423 register u_char code; 424 register struct tty *tp; 425 int s, rr; 426 427 tp = &bmc_tty[unit]; 428 rr = siogetreg(sio); 429 430 if (rr & RR_RXRDY) { 431 code = sio->sio_data; 432 if ((tp->t_state & TS_ISOPEN) != 0) 433 (*linesw[tp->t_line].l_rint)(code, tp); 434 } 435 436 if (rr & RR_TXRDY) { 437 sio->sio_cmd = WR0_RSTPEND; 438 tp->t_state &= ~(TS_BUSY|TS_FLUSH); 439 if (tp->t_line) 440 (*linesw[tp->t_line].l_start)(tp); 441 else 442 bmcstart(tp); 443 } 444 445 } 446 #endif 447 448 /* 449 * Following are all routines needed for SIO to act as console 450 */ 451 #include "../luna68k/cons.h" 452 453 bmccnprobe(cp) 454 register struct consdev *cp; 455 { 456 #ifdef BMC_NOCONSOLE 457 cp->cn_pri = CN_DEAD; 458 return; 459 #else 460 /* check DIP-SW setup */ 461 /* check bitmap interface board */ 462 463 /* locate the major number */ 464 for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++) 465 if (cdevsw[bmcmajor].d_open == bmcopen) 466 break; 467 468 /* initialize required fields */ 469 cp->cn_dev = makedev(bmcmajor, 0); 470 cp->cn_tp = &bmc_tty[0]; 471 cp->cn_pri = CN_INTERNAL; 472 473 bmc_config_done = 1; 474 #endif 475 } 476 477 bmccninit(cp) 478 struct consdev *cp; 479 { 480 int unit = bmcunit(cp->cn_dev); 481 register struct bmc_softc *sc = &bmc_softc[0]; 482 483 sioinit((struct siodevice *) SIO_HARDADDR, bmcdefaultrate); 484 #ifdef BMD 485 bmdinit(); 486 #endif 487 488 /* port assign */ 489 sc->sc_pc = sio_port_assign(BMC_CNPORT, bmcmajor, 0, bmcintr); 490 491 bmcconsole = unit; 492 } 493 494 bmccngetc(dev) 495 dev_t dev; 496 { 497 struct bmc_softc *sc = &bmc_softc[bmcunit(dev)]; 498 struct sio_portc *pc = sc->sc_pc; 499 #ifdef BMD 500 register int c; 501 register u_char code; 502 503 do { 504 code = sio_imgetc(pc->pc_addr); 505 } while ((c = kbd_decode(code)) & KC_TYPE); 506 507 return(c); 508 #else 509 return(sio_imgetc(pc->pc_addr)); 510 #endif 511 } 512 513 bmccnputc(dev, c) 514 dev_t dev; 515 int c; 516 { 517 struct bmc_softc *sc = &bmc_softc[bmcunit(dev)]; 518 struct sio_portc *pc = sc->sc_pc; 519 520 #ifdef BMD 521 bmdputc(c); 522 #else 523 sio_imputc(pc->pc_addr, c); 524 #endif 525 } 526 #endif 527