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