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.3 (Berkeley) 12/14/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 <luna68k/dev/device.h> 38 #include <luna68k/dev/sioreg.h> 39 #include <luna68k/dev/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 int bmcconsole = -1; 68 int bmcdefaultrate = B9600; /* speed of console line is fixed */ 69 int bmcmajor = 0; 70 71 #define bmcunit(x) minor(x) 72 73 extern struct tty *constty; 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 int unit = bmcunit(dev); 207 register struct tty *tp = &bmc_tty[unit]; 208 209 if ((unit == bmcconsole) && constty && 210 (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN)) 211 tp = constty; 212 213 return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 214 } 215 216 /* 217 * Stop output on a line. 218 */ 219 /*ARGSUSED*/ 220 bmcstop(tp, flag) 221 register struct tty *tp; 222 { 223 register int s; 224 225 s = spltty(); 226 if (tp->t_state & TS_BUSY) { 227 if ((tp->t_state&TS_TTSTOP)==0) 228 tp->t_state |= TS_FLUSH; 229 } 230 splx(s); 231 } 232 233 bmcioctl(dev, cmd, data, flag, p) 234 dev_t dev; 235 int cmd; 236 caddr_t data; 237 int flag; 238 struct proc *p; 239 { 240 register struct tty *tp; 241 register int unit = bmcunit(dev); 242 register int error; 243 244 tp = &bmc_tty[unit]; 245 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 246 if (error >= 0) 247 return (error); 248 error = ttioctl(tp, cmd, data, flag); 249 if (error >= 0) 250 return (error); 251 252 switch (cmd) { 253 default: 254 return (ENOTTY); 255 } 256 return (0); 257 } 258 259 /* 260 * 261 */ 262 #ifdef BMD 263 void 264 bmcstart(tp) 265 register struct tty *tp; 266 { 267 int unit = bmcunit(tp->t_dev); 268 register struct bmc_softc *sc = &bmc_softc[unit]; 269 register int cc, s; 270 int hiwat = 0; 271 272 s = spltty(); 273 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { 274 splx(s); 275 return; 276 } 277 tp->t_state |= TS_BUSY; 278 cc = tp->t_outq.c_cc; 279 if (cc <= tp->t_lowat) { 280 if (tp->t_state & TS_ASLEEP) { 281 tp->t_state &= ~TS_ASLEEP; 282 wakeup((caddr_t)&tp->t_outq); 283 } 284 selwakeup(&tp->t_wsel); 285 } 286 /* 287 * Limit the amount of output we do in one burst 288 * to prevent hogging the CPU. 289 */ 290 /* 291 if (cc > iteburst) { 292 hiwat++; 293 cc = iteburst; 294 } 295 */ 296 while (--cc >= 0) { 297 register int c; 298 299 c = getc(&tp->t_outq); 300 /* 301 * iteputchar() may take a long time and we don't want to 302 * block all interrupts for long periods of time. Since 303 * there is no need to stay at high priority while outputing 304 * the character (since we don't have to worry about 305 * interrupts), we don't. We just need to make sure that 306 * we don't reenter iteputchar, which is guarenteed by the 307 * earlier setting of TS_BUSY. 308 */ 309 splx(s); 310 bmdputc(c & sc->sc_mask); 311 spltty(); 312 } 313 /* 314 if (hiwat) { 315 tp->t_state |= TS_TIMEOUT; 316 timeout(ttrstrt, tp, 1); 317 } 318 */ 319 tp->t_state &= ~TS_BUSY; 320 splx(s); 321 } 322 #else 323 void 324 bmcstart(tp) 325 register struct tty *tp; 326 { 327 register struct siodevice *sio; 328 register int rr; 329 int s, unit, c; 330 331 unit = bmcunit(tp->t_dev); 332 sio = bmc_softc[unit].sc_pc->pc_addr; 333 s = spltty(); 334 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 335 goto out; 336 if (tp->t_outq.c_cc <= tp->t_lowat) { 337 if (tp->t_state&TS_ASLEEP) { 338 tp->t_state &= ~TS_ASLEEP; 339 wakeup((caddr_t)&tp->t_outq); 340 } 341 selwakeup(&tp->t_wsel); 342 } 343 if (tp->t_outq.c_cc == 0) 344 goto out; 345 rr = siogetreg(sio); 346 if (rr & RR_TXRDY) { 347 c = getc(&tp->t_outq); 348 tp->t_state |= TS_BUSY; 349 sio->sio_data = c; 350 } 351 out: 352 splx(s); 353 } 354 #endif 355 356 bmcparam(tp, t) 357 register struct tty *tp; 358 register struct termios *t; 359 { 360 int unit = bmcunit(tp->t_dev); 361 register struct bmc_softc *sc = &bmc_softc[unit]; 362 register int cflag = t->c_cflag; 363 364 /* and copy to tty */ 365 tp->t_ispeed = t->c_ispeed; 366 tp->t_ospeed = t->c_ospeed; 367 tp->t_cflag = cflag; 368 369 /* 370 * change line speed 371 */ 372 373 switch (cflag&CSIZE) { 374 case CS5: 375 sc->sc_mask = 0x1F ; break; 376 case CS6: 377 sc->sc_mask = 0x3F ; break; 378 case CS7: 379 sc->sc_mask = 0x7F ; break; 380 case CS8: 381 sc->sc_mask = 0xFF ; break; 382 } 383 384 /* 385 * parity 386 */ 387 388 /* 389 * stop bit 390 */ 391 392 return (0); 393 } 394 395 396 /* 397 * interrupt handling 398 */ 399 400 #ifdef BMD 401 bmcintr(unit) 402 register int unit; 403 { 404 register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr; 405 register struct tty *tp; 406 register u_char code; 407 register int c; 408 int s, rr; 409 410 tp = &bmc_tty[unit]; 411 rr = siogetreg(sio); 412 413 if (rr & RR_RXRDY) { 414 code = sio->sio_data; 415 c = kbd_decode(code); 416 if (c & KC_TYPE) /* skip special codes */ 417 return; 418 code = (c & KC_CHAR); 419 if ((tp->t_state & TS_ISOPEN) != 0) 420 (*linesw[tp->t_line].l_rint)(code, tp); 421 } 422 } 423 #else 424 bmcintr(unit) 425 register int unit; 426 { 427 register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr; 428 register u_char code; 429 register struct tty *tp; 430 int s, rr; 431 432 tp = &bmc_tty[unit]; 433 rr = siogetreg(sio); 434 435 if (rr & RR_RXRDY) { 436 code = sio->sio_data; 437 if ((tp->t_state & TS_ISOPEN) != 0) 438 (*linesw[tp->t_line].l_rint)(code, tp); 439 } 440 441 if (rr & RR_TXRDY) { 442 sio->sio_cmd = WR0_RSTPEND; 443 tp->t_state &= ~(TS_BUSY|TS_FLUSH); 444 if (tp->t_line) 445 (*linesw[tp->t_line].l_start)(tp); 446 else 447 bmcstart(tp); 448 } 449 450 } 451 #endif 452 453 /* 454 * Following are all routines needed for SIO to act as console 455 */ 456 #include "../luna68k/cons.h" 457 458 bmccnprobe(cp) 459 register struct consdev *cp; 460 { 461 #ifdef BMC_NOCONSOLE 462 cp->cn_pri = CN_DEAD; 463 return; 464 #else 465 /* check DIP-SW setup */ 466 /* check bitmap interface board */ 467 468 /* locate the major number */ 469 for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++) 470 if (cdevsw[bmcmajor].d_open == bmcopen) 471 break; 472 473 /* initialize required fields */ 474 cp->cn_dev = makedev(bmcmajor, 0); 475 cp->cn_tp = &bmc_tty[0]; 476 cp->cn_pri = CN_INTERNAL; 477 478 bmc_config_done = 1; 479 #endif 480 } 481 482 bmccninit(cp) 483 struct consdev *cp; 484 { 485 int unit = bmcunit(cp->cn_dev); 486 register struct bmc_softc *sc = &bmc_softc[0]; 487 488 sioinit((struct siodevice *) SIO_HARDADDR, bmcdefaultrate); 489 #ifdef BMD 490 bmdinit(); 491 #endif 492 493 /* port assign */ 494 sc->sc_pc = sio_port_assign(BMC_CNPORT, bmcmajor, 0, bmcintr); 495 496 bmcconsole = unit; 497 } 498 499 bmccngetc(dev) 500 dev_t dev; 501 { 502 struct bmc_softc *sc = &bmc_softc[bmcunit(dev)]; 503 struct sio_portc *pc = sc->sc_pc; 504 #ifdef BMD 505 register int c; 506 register u_char code; 507 508 do { 509 code = sio_imgetc(pc->pc_addr); 510 } while ((c = kbd_decode(code)) & KC_TYPE); 511 512 return(c); 513 #else 514 return(sio_imgetc(pc->pc_addr)); 515 #endif 516 } 517 518 bmccnputc(dev, c) 519 dev_t dev; 520 int c; 521 { 522 struct bmc_softc *sc = &bmc_softc[bmcunit(dev)]; 523 struct sio_portc *pc = sc->sc_pc; 524 525 #ifdef BMD 526 bmdputc(c); 527 #else 528 sio_imputc(pc->pc_addr, c); 529 #endif 530 } 531 #endif 532