156876Sakito /* 256876Sakito * Copyright (c) 1992 OMRON Corporation. 356876Sakito * Copyright (c) 1992 The Regents of the University of California. 456876Sakito * All rights reserved. 556876Sakito * 656876Sakito * This code is derived from software contributed to Berkeley by 756876Sakito * OMRON Corporation. 856876Sakito * 956876Sakito * %sccs.include.redist.c% 1056876Sakito * 11*57059Sakito * @(#)bmc.c 7.2 (Berkeley) 12/10/92 1256876Sakito */ 1356876Sakito 1456876Sakito #define BMC_NOCONSOLE 1556876Sakito #define BMD 1656876Sakito 1756876Sakito #ifdef BMD 1856876Sakito #define BMC_CNPORT 1 1956876Sakito #else 2056876Sakito #define BMC_CNPORT 0 2156876Sakito #endif 2256876Sakito 2356876Sakito #include "bmc.h" 2456876Sakito #if NBMC > 0 2556876Sakito 26*57059Sakito #include <sys/param.h> 27*57059Sakito #include <sys/systm.h> 28*57059Sakito #include <sys/ioctl.h> 29*57059Sakito #include <sys/proc.h> 30*57059Sakito #include <sys/tty.h> 31*57059Sakito #include <sys/conf.h> 32*57059Sakito #include <sys/file.h> 33*57059Sakito #include <sys/uio.h> 34*57059Sakito #include <sys/kernel.h> 35*57059Sakito #include <sys/syslog.h> 3656876Sakito 37*57059Sakito #include <luna68k/dev/device.h> 38*57059Sakito #include <luna68k/dev/sioreg.h> 39*57059Sakito #include <luna68k/dev/siovar.h> 4056876Sakito 4156876Sakito #ifdef BMD 4256876Sakito #include "kbdreg.h" 4356876Sakito #endif 4456876Sakito 4556876Sakito extern struct sio_portc *sio_port_assign(); 4656876Sakito 4756876Sakito int bmcprobe(); 4856876Sakito int bmcopen(); 4956876Sakito void bmcstart(); 5056876Sakito int bmcparam(); 5156876Sakito int bmcintr(); 5256876Sakito 5356876Sakito struct driver bmcdriver = { 5456876Sakito bmcprobe, "bmc", 5556876Sakito }; 5656876Sakito 5756876Sakito struct bmc_softc { 5856876Sakito struct sio_portc *sc_pc; 5956876Sakito int sc_mask; 6056876Sakito }; 6156876Sakito 6256876Sakito struct bmc_softc bmc_softc[NBMC]; 6356876Sakito 6456876Sakito struct tty bmc_tty[NBMC]; 6556876Sakito 6656876Sakito int bmc_config_done = 0; 6756876Sakito 6856876Sakito int bmcconsole; 6956876Sakito int bmcdefaultrate = B9600; /* speed of console line is fixed */ 7056876Sakito int bmcmajor = 0; 7156876Sakito 7256876Sakito #define bmcunit(x) minor(x) 7356876Sakito 7456876Sakito 7556876Sakito /* 7656876Sakito * probe routine 7756876Sakito */ 7856876Sakito 7956876Sakito bmcprobe(hd) 8056876Sakito register struct hp_device *hd; 8156876Sakito { 8256876Sakito } 8356876Sakito 8456876Sakito bmcinit(port) 8556876Sakito register int port; 8656876Sakito { 8756876Sakito register struct bmc_softc *sc = &bmc_softc[0]; 8856876Sakito 8956876Sakito /* 9056876Sakito * if BMC is already configured, should be skipped. 9156876Sakito */ 9256876Sakito if (bmc_config_done) 9356876Sakito return(0); 9456876Sakito 9556876Sakito /* 9656876Sakito * Check out bitmap Interface board 9756876Sakito */ 9856876Sakito 9956876Sakito /* port checking (for keyboard) */ 10056876Sakito if (port != 1) 10156876Sakito return(0); 10256876Sakito 10356876Sakito /* locate the major number */ 10456876Sakito for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++) 10556876Sakito if (cdevsw[bmcmajor].d_open == bmcopen) 10656876Sakito break; 10756876Sakito 10856876Sakito sc->sc_pc = sio_port_assign(port, bmcmajor, 0, bmcintr); 10956876Sakito 11056876Sakito printf("bmc%d: port %d, address 0x%x\n", sc->sc_pc->pc_unit, port, sc->sc_pc->pc_addr); 11156876Sakito 11256876Sakito #ifdef BMD 11356876Sakito bmdinit(); 11456876Sakito #endif 11556876Sakito 11656876Sakito bmc_config_done = 1; 11756876Sakito return(1); 11856876Sakito } 11956876Sakito 12056876Sakito 12156876Sakito /* 12256876Sakito * entry routines 12356876Sakito */ 12456876Sakito 12556876Sakito /* ARGSUSED */ 12656876Sakito #ifdef __STDC__ 12756876Sakito bmcopen(dev_t dev, int flag, int mode, struct proc *p) 12856876Sakito #else 12956876Sakito bmcopen(dev, flag, mode, p) 13056876Sakito dev_t dev; 13156876Sakito int flag, mode; 13256876Sakito struct proc *p; 13356876Sakito #endif 13456876Sakito { 13556876Sakito register struct tty *tp; 13656876Sakito register int unit; 13756876Sakito int error = 0; 13856876Sakito 13956876Sakito unit = bmcunit(dev); 14056876Sakito if (unit >= NBMC) 14156876Sakito return (ENXIO); 14256876Sakito tp = &bmc_tty[unit]; 14356876Sakito tp->t_oproc = bmcstart; 14456876Sakito tp->t_param = bmcparam; 14556876Sakito tp->t_dev = dev; 14656876Sakito if ((tp->t_state & TS_ISOPEN) == 0) { 14756876Sakito tp->t_state |= TS_WOPEN; 14856876Sakito ttychars(tp); 14956876Sakito if (tp->t_ispeed == 0) { 15056876Sakito tp->t_iflag = TTYDEF_IFLAG; 15156876Sakito tp->t_oflag = TTYDEF_OFLAG; 15256876Sakito tp->t_cflag = TTYDEF_CFLAG; 15356876Sakito /* tp->t_cflag = (CREAD | CS8 | HUPCL); */ 15456876Sakito tp->t_lflag = TTYDEF_LFLAG; 15556876Sakito tp->t_ispeed = tp->t_ospeed = bmcdefaultrate; 15656876Sakito } 15756876Sakito bmcparam(tp, &tp->t_termios); 15856876Sakito ttsetwater(tp); 15956876Sakito } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 16056876Sakito return (EBUSY); 16156876Sakito tp->t_state |= TS_CARR_ON; 16256876Sakito (void) spltty(); 16356876Sakito while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 16456876Sakito (tp->t_state & TS_CARR_ON) == 0) { 16556876Sakito tp->t_state |= TS_WOPEN; 16656876Sakito if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 16756876Sakito ttopen, 0)) 16856876Sakito break; 16956876Sakito } 17056876Sakito (void) spl0(); 17156876Sakito if (error == 0) 17256876Sakito error = (*linesw[tp->t_line].l_open)(dev, tp); 17356876Sakito 17456876Sakito return (error); 17556876Sakito } 17656876Sakito 17756876Sakito /*ARGSUSED*/ 17856876Sakito bmcclose(dev, flag, mode, p) 17956876Sakito dev_t dev; 18056876Sakito int flag, mode; 18156876Sakito struct proc *p; 18256876Sakito { 18356876Sakito register struct tty *tp; 18456876Sakito register int unit; 18556876Sakito 18656876Sakito unit = bmcunit(dev); 18756876Sakito tp = &bmc_tty[unit]; 18856876Sakito (*linesw[tp->t_line].l_close)(tp, flag); 18956876Sakito ttyclose(tp); 19056876Sakito return (0); 19156876Sakito } 19256876Sakito 19356876Sakito bmcread(dev, uio, flag) 19456876Sakito dev_t dev; 19556876Sakito struct uio *uio; 19656876Sakito { 19756876Sakito register struct tty *tp = &bmc_tty[bmcunit(dev)]; 19856876Sakito 19956876Sakito return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 20056876Sakito } 20156876Sakito 20256876Sakito bmcwrite(dev, uio, flag) 20356876Sakito dev_t dev; 20456876Sakito struct uio *uio; 20556876Sakito { 20656876Sakito register struct tty *tp = &bmc_tty[bmcunit(dev)]; 20756876Sakito 20856876Sakito return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 20956876Sakito } 21056876Sakito 21156876Sakito /* 21256876Sakito * Stop output on a line. 21356876Sakito */ 21456876Sakito /*ARGSUSED*/ 21556876Sakito bmcstop(tp, flag) 21656876Sakito register struct tty *tp; 21756876Sakito { 21856876Sakito register int s; 21956876Sakito 22056876Sakito s = spltty(); 22156876Sakito if (tp->t_state & TS_BUSY) { 22256876Sakito if ((tp->t_state&TS_TTSTOP)==0) 22356876Sakito tp->t_state |= TS_FLUSH; 22456876Sakito } 22556876Sakito splx(s); 22656876Sakito } 22756876Sakito 22856876Sakito bmcioctl(dev, cmd, data, flag, p) 22956876Sakito dev_t dev; 23056876Sakito int cmd; 23156876Sakito caddr_t data; 23256876Sakito int flag; 23356876Sakito struct proc *p; 23456876Sakito { 23556876Sakito register struct tty *tp; 23656876Sakito register int unit = bmcunit(dev); 23756876Sakito register int error; 23856876Sakito 23956876Sakito tp = &bmc_tty[unit]; 24056876Sakito error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 24156876Sakito if (error >= 0) 24256876Sakito return (error); 24356876Sakito error = ttioctl(tp, cmd, data, flag); 24456876Sakito if (error >= 0) 24556876Sakito return (error); 24656876Sakito 24756876Sakito switch (cmd) { 24856876Sakito default: 24956876Sakito return (ENOTTY); 25056876Sakito } 25156876Sakito return (0); 25256876Sakito } 25356876Sakito 25456876Sakito /* 25556876Sakito * 25656876Sakito */ 25756876Sakito #ifdef BMD 25856876Sakito void 25956876Sakito bmcstart(tp) 26056876Sakito register struct tty *tp; 26156876Sakito { 26256876Sakito int unit = bmcunit(tp->t_dev); 26356876Sakito register struct bmc_softc *sc = &bmc_softc[unit]; 26456876Sakito register int cc, s; 26556876Sakito int hiwat = 0; 26656876Sakito 26756876Sakito s = spltty(); 26856876Sakito if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) { 26956876Sakito splx(s); 27056876Sakito return; 27156876Sakito } 27256876Sakito tp->t_state |= TS_BUSY; 27356876Sakito cc = tp->t_outq.c_cc; 27456876Sakito if (cc <= tp->t_lowat) { 27556876Sakito if (tp->t_state & TS_ASLEEP) { 27656876Sakito tp->t_state &= ~TS_ASLEEP; 27756876Sakito wakeup((caddr_t)&tp->t_outq); 27856876Sakito } 27956876Sakito selwakeup(&tp->t_wsel); 28056876Sakito } 28156876Sakito /* 28256876Sakito * Limit the amount of output we do in one burst 28356876Sakito * to prevent hogging the CPU. 28456876Sakito */ 28556876Sakito /* 28656876Sakito if (cc > iteburst) { 28756876Sakito hiwat++; 28856876Sakito cc = iteburst; 28956876Sakito } 29056876Sakito */ 29156876Sakito while (--cc >= 0) { 29256876Sakito register int c; 29356876Sakito 29456876Sakito c = getc(&tp->t_outq); 29556876Sakito /* 29656876Sakito * iteputchar() may take a long time and we don't want to 29756876Sakito * block all interrupts for long periods of time. Since 29856876Sakito * there is no need to stay at high priority while outputing 29956876Sakito * the character (since we don't have to worry about 30056876Sakito * interrupts), we don't. We just need to make sure that 30156876Sakito * we don't reenter iteputchar, which is guarenteed by the 30256876Sakito * earlier setting of TS_BUSY. 30356876Sakito */ 30456876Sakito splx(s); 30556876Sakito bmdputc(c & sc->sc_mask); 30656876Sakito spltty(); 30756876Sakito } 30856876Sakito /* 30956876Sakito if (hiwat) { 31056876Sakito tp->t_state |= TS_TIMEOUT; 31156876Sakito timeout(ttrstrt, tp, 1); 31256876Sakito } 31356876Sakito */ 31456876Sakito tp->t_state &= ~TS_BUSY; 31556876Sakito splx(s); 31656876Sakito } 31756876Sakito #else 31856876Sakito void 31956876Sakito bmcstart(tp) 32056876Sakito register struct tty *tp; 32156876Sakito { 32256876Sakito register struct siodevice *sio; 32356876Sakito register int rr; 32456876Sakito int s, unit, c; 32556876Sakito 32656876Sakito unit = bmcunit(tp->t_dev); 32756876Sakito sio = bmc_softc[unit].sc_pc->pc_addr; 32856876Sakito s = spltty(); 32956876Sakito if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 33056876Sakito goto out; 33156876Sakito if (tp->t_outq.c_cc <= tp->t_lowat) { 33256876Sakito if (tp->t_state&TS_ASLEEP) { 33356876Sakito tp->t_state &= ~TS_ASLEEP; 33456876Sakito wakeup((caddr_t)&tp->t_outq); 33556876Sakito } 33656876Sakito selwakeup(&tp->t_wsel); 33756876Sakito } 33856876Sakito if (tp->t_outq.c_cc == 0) 33956876Sakito goto out; 34056876Sakito rr = siogetreg(sio); 34156876Sakito if (rr & RR_TXRDY) { 34256876Sakito c = getc(&tp->t_outq); 34356876Sakito tp->t_state |= TS_BUSY; 34456876Sakito sio->sio_data = c; 34556876Sakito } 34656876Sakito out: 34756876Sakito splx(s); 34856876Sakito } 34956876Sakito #endif 35056876Sakito 35156876Sakito bmcparam(tp, t) 35256876Sakito register struct tty *tp; 35356876Sakito register struct termios *t; 35456876Sakito { 35556876Sakito int unit = bmcunit(tp->t_dev); 35656876Sakito register struct bmc_softc *sc = &bmc_softc[unit]; 35756876Sakito register int cflag = t->c_cflag; 35856876Sakito 35956876Sakito /* and copy to tty */ 36056876Sakito tp->t_ispeed = t->c_ispeed; 36156876Sakito tp->t_ospeed = t->c_ospeed; 36256876Sakito tp->t_cflag = cflag; 36356876Sakito 36456876Sakito /* 36556876Sakito * change line speed 36656876Sakito */ 36756876Sakito 36856876Sakito switch (cflag&CSIZE) { 36956876Sakito case CS5: 37056876Sakito sc->sc_mask = 0x1F ; break; 37156876Sakito case CS6: 37256876Sakito sc->sc_mask = 0x3F ; break; 37356876Sakito case CS7: 37456876Sakito sc->sc_mask = 0x7F ; break; 37556876Sakito case CS8: 37656876Sakito sc->sc_mask = 0xFF ; break; 37756876Sakito } 37856876Sakito 37956876Sakito /* 38056876Sakito * parity 38156876Sakito */ 38256876Sakito 38356876Sakito /* 38456876Sakito * stop bit 38556876Sakito */ 38656876Sakito 38756876Sakito return (0); 38856876Sakito } 38956876Sakito 39056876Sakito 39156876Sakito /* 39256876Sakito * interrupt handling 39356876Sakito */ 39456876Sakito 39556876Sakito #ifdef BMD 39656876Sakito bmcintr(unit) 39756876Sakito register int unit; 39856876Sakito { 39956876Sakito register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr; 40056876Sakito register struct tty *tp; 40156876Sakito register u_char code; 40256876Sakito register int c; 40356876Sakito int s, rr; 40456876Sakito 40556876Sakito tp = &bmc_tty[unit]; 40656876Sakito rr = siogetreg(sio); 40756876Sakito 40856876Sakito if (rr & RR_RXRDY) { 40956876Sakito code = sio->sio_data; 41056876Sakito c = kbd_decode(code); 41156876Sakito if (c & KC_TYPE) /* skip special codes */ 41256876Sakito return; 41356876Sakito code = (c & KC_CHAR); 41456876Sakito if ((tp->t_state & TS_ISOPEN) != 0) 41556876Sakito (*linesw[tp->t_line].l_rint)(code, tp); 41656876Sakito } 41756876Sakito } 41856876Sakito #else 41956876Sakito bmcintr(unit) 42056876Sakito register int unit; 42156876Sakito { 42256876Sakito register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr; 42356876Sakito register u_char code; 42456876Sakito register struct tty *tp; 42556876Sakito int s, rr; 42656876Sakito 42756876Sakito tp = &bmc_tty[unit]; 42856876Sakito rr = siogetreg(sio); 42956876Sakito 43056876Sakito if (rr & RR_RXRDY) { 43156876Sakito code = sio->sio_data; 43256876Sakito if ((tp->t_state & TS_ISOPEN) != 0) 43356876Sakito (*linesw[tp->t_line].l_rint)(code, tp); 43456876Sakito } 43556876Sakito 43656876Sakito if (rr & RR_TXRDY) { 43756876Sakito sio->sio_cmd = WR0_RSTPEND; 43856876Sakito tp->t_state &= ~(TS_BUSY|TS_FLUSH); 43956876Sakito if (tp->t_line) 44056876Sakito (*linesw[tp->t_line].l_start)(tp); 44156876Sakito else 44256876Sakito bmcstart(tp); 44356876Sakito } 44456876Sakito 44556876Sakito } 44656876Sakito #endif 44756876Sakito 44856876Sakito /* 44956876Sakito * Following are all routines needed for SIO to act as console 45056876Sakito */ 45156876Sakito #include "../luna68k/cons.h" 45256876Sakito 45356876Sakito bmccnprobe(cp) 45456876Sakito register struct consdev *cp; 45556876Sakito { 45656876Sakito #ifdef BMC_NOCONSOLE 45756876Sakito cp->cn_pri = CN_DEAD; 45856876Sakito return; 45956876Sakito #else 46056876Sakito /* check DIP-SW setup */ 46156876Sakito /* check bitmap interface board */ 46256876Sakito 46356876Sakito /* locate the major number */ 46456876Sakito for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++) 46556876Sakito if (cdevsw[bmcmajor].d_open == bmcopen) 46656876Sakito break; 46756876Sakito 46856876Sakito /* initialize required fields */ 46956876Sakito cp->cn_dev = makedev(bmcmajor, 0); 47056876Sakito cp->cn_tp = &bmc_tty[0]; 47156876Sakito cp->cn_pri = CN_INTERNAL; 47256876Sakito 47356876Sakito bmc_config_done = 1; 47456876Sakito #endif 47556876Sakito } 47656876Sakito 47756876Sakito bmccninit(cp) 47856876Sakito struct consdev *cp; 47956876Sakito { 48056876Sakito int unit = bmcunit(cp->cn_dev); 48156876Sakito register struct bmc_softc *sc = &bmc_softc[0]; 48256876Sakito 48356876Sakito sioinit((struct siodevice *) SIO_HARDADDR, bmcdefaultrate); 48456876Sakito #ifdef BMD 48556876Sakito bmdinit(); 48656876Sakito #endif 48756876Sakito 48856876Sakito /* port assign */ 48956876Sakito sc->sc_pc = sio_port_assign(BMC_CNPORT, bmcmajor, 0, bmcintr); 49056876Sakito 49156876Sakito bmcconsole = unit; 49256876Sakito } 49356876Sakito 49456876Sakito bmccngetc(dev) 49556876Sakito dev_t dev; 49656876Sakito { 49756876Sakito struct bmc_softc *sc = &bmc_softc[bmcunit(dev)]; 49856876Sakito struct sio_portc *pc = sc->sc_pc; 49956876Sakito #ifdef BMD 50056876Sakito register int c; 50156876Sakito register u_char code; 50256876Sakito 50356876Sakito do { 50456876Sakito code = sio_imgetc(pc->pc_addr); 50556876Sakito } while ((c = kbd_decode(code)) & KC_TYPE); 50656876Sakito 50756876Sakito return(c); 50856876Sakito #else 50956876Sakito return(sio_imgetc(pc->pc_addr)); 51056876Sakito #endif 51156876Sakito } 51256876Sakito 51356876Sakito bmccnputc(dev, c) 51456876Sakito dev_t dev; 51556876Sakito int c; 51656876Sakito { 51756876Sakito struct bmc_softc *sc = &bmc_softc[bmcunit(dev)]; 51856876Sakito struct sio_portc *pc = sc->sc_pc; 51956876Sakito 52056876Sakito #ifdef BMD 52156876Sakito bmdputc(c); 52256876Sakito #else 52356876Sakito sio_imputc(pc->pc_addr, c); 52456876Sakito #endif 52556876Sakito } 52656876Sakito #endif 527