154008Sfujita /* 254008Sfujita * Copyright (c) 1992 OMRON Corporation. 354008Sfujita * Copyright (c) 1992 The Regents of the University of California. 454008Sfujita * All rights reserved. 554008Sfujita * 654008Sfujita * This code is derived from software contributed to Berkeley by 754008Sfujita * OMRON Corporation. 854008Sfujita * 954008Sfujita * %sccs.include.redist.c% 1054008Sfujita * 11*57850Sakito * @(#)sio.c 7.7 (Berkeley) 02/04/93 1254008Sfujita */ 1354008Sfujita 1454008Sfujita /* 1554008Sfujita * sio.c -- NEC uPD7201A UART Device Driver 1656873Sakito * remaked by A.Fujita, NOV-5-1992 1754008Sfujita */ 1854008Sfujita 1954008Sfujita #include "sio.h" 2054008Sfujita #if NSIO > 0 2154008Sfujita 2256873Sakito #include "bmc.h" 2354008Sfujita 2457058Sakito #include <sys/param.h> 2557058Sakito #include <sys/systm.h> 2657058Sakito #include <sys/ioctl.h> 2757058Sakito #include <sys/proc.h> 2857058Sakito #include <sys/tty.h> 2957058Sakito #include <sys/conf.h> 3057058Sakito #include <sys/file.h> 3157058Sakito #include <sys/uio.h> 3257058Sakito #include <sys/kernel.h> 3357058Sakito #include <sys/syslog.h> 3454008Sfujita 3557058Sakito #include <luna68k/dev/device.h> 3657058Sakito #include <luna68k/dev/sioreg.h> 3757058Sakito #include <luna68k/dev/siovar.h> 3854008Sfujita 3956873Sakito struct sio_portc *sio_port_assign(); 4057291Sakito struct sio_portc *sio_port_get(); 4154008Sfujita 4256873Sakito int sioprobe(); 4356873Sakito int sioopen(); 4456873Sakito void siostart(); 4556873Sakito int sioparam(); 4656873Sakito int siointr(); 4754008Sfujita 4854008Sfujita struct driver siodriver = { 4954008Sfujita sioprobe, "sio", 5054008Sfujita }; 5154008Sfujita 5256873Sakito #define NPORT 2 /* uPD7201A has 2 serial-port */ 5356873Sakito #define NLINE 1 /* number of active line */ 5454008Sfujita 5556873Sakito struct sio_portc sio_portc[NPORT] = { 5656873Sakito { -1, -1, (struct siodevice *) 0x51000000, (int (*)()) 0 }, 5756873Sakito { -1, -1, (struct siodevice *) 0x51000004, (int (*)()) 0 } 5856873Sakito }; 5954008Sfujita 6056873Sakito struct sio_softc sio_softc[NLINE]; 6154008Sfujita 6256873Sakito int sio_init_done = 0; 6356873Sakito int siounitbase = 0; /* This counter is used unit number assignment */ 6454008Sfujita 6556873Sakito int siosoftCAR; 6656873Sakito int sio_active; 6757126Sakito int sioconsole = -1; 6856873Sakito int siodefaultrate = TTYDEF_SPEED; 6957291Sakito int siomajor = 12; 7054008Sfujita 7156873Sakito struct tty sio_tty[NLINE]; 7254008Sfujita 7356873Sakito struct speedtab siospeedtab[] = { 7456873Sakito 2400, WR4_BAUD24, 7556873Sakito 4800, WR4_BAUD48, 7656873Sakito 9600, WR4_BAUD96, 7754008Sfujita }; 7854008Sfujita 7956873Sakito #define siounit(x) minor(x) 8054008Sfujita 8157126Sakito extern struct tty *constty; 8254008Sfujita 8354008Sfujita /* 8456873Sakito * probe routines 8554008Sfujita */ 8654008Sfujita 8754008Sfujita sioprobe(hd) 8854008Sfujita register struct hp_device *hd; 8954008Sfujita { 9056873Sakito register int port; 9156873Sakito register struct sio_portc *pc; 9256873Sakito register struct sio_softc *sc; 9354008Sfujita 9456873Sakito sioinit((struct siodevice *) hd->hp_addr, siodefaultrate); 9554008Sfujita 9656873Sakito /* locate the major number */ 9756873Sakito for (siomajor = 0; siomajor < nchrdev; siomajor++) 9856873Sakito if (cdevsw[siomajor].d_open == sioopen) 9956873Sakito break; 10054008Sfujita 10156873Sakito for (port = 0; port < NPORT; port++) { 10256873Sakito pc = &sio_portc[port]; 10354008Sfujita 10456873Sakito if (pc->pc_major != -1) { 10556873Sakito printf("%s%d: port %d, address 0x%x, intr 0x%x (console)\n", 10656873Sakito (pc->pc_major == siomajor ? "sio" : "bmc" ), 10756873Sakito pc->pc_unit, port, pc->pc_addr, pc->pc_intr); 10856873Sakito continue; 10956873Sakito } 11054008Sfujita 11156873Sakito pc->pc_addr = 11256873Sakito (struct siodevice *)((u_long) hd->hp_addr + (sizeof(struct siodevice) * port)); 11356873Sakito #if NBMC > 0 11456873Sakito if (bmcinit(port)) 11556873Sakito continue; 11656873Sakito #endif 11756873Sakito if (++siounitbase < NLINE) { 11856873Sakito pc->pc_major = siomajor; 11956873Sakito pc->pc_intr = siointr; 12056873Sakito pc->pc_unit = siounitbase; 12156873Sakito printf("sio%d: port %d, address 0x%x\n", pc->pc_unit, port, pc->pc_addr); 12254008Sfujita 12356873Sakito sc = &sio_softc[pc->pc_unit]; 12456873Sakito sc->sc_pc = pc; 12554008Sfujita 12656873Sakito sio_active |= 1 << pc->pc_unit; 12756873Sakito siosoftCAR |= 1 << pc->pc_unit; 12856873Sakito } 12956873Sakito } 13056873Sakito } 13154008Sfujita 13256873Sakito struct sio_portc * 13356873Sakito sio_port_assign(port, major, unit, intr) 13456873Sakito int port, major, unit; 13556873Sakito int (*intr)(); 13656873Sakito { 13757291Sakito register struct sio_portc *pc; 13854008Sfujita 13957291Sakito pc = &sio_portc[port]; 14057291Sakito 14157291Sakito /* 14257291Sakito if ((pc->pc_major != -1) && (major != 2)) 14356873Sakito return((struct sio_portc *) 0); 14457291Sakito */ 14556873Sakito pc->pc_major = major; 14656873Sakito pc->pc_intr = intr; 14756873Sakito pc->pc_unit = unit; 14854008Sfujita 14956873Sakito return(pc); 15054008Sfujita } 15154008Sfujita 15257291Sakito struct sio_portc * 15357291Sakito sio_port_get(port) 15457291Sakito int port; 15557291Sakito { 15657291Sakito register struct sio_portc *pc; 15756873Sakito 15857291Sakito pc = &sio_portc[port]; 15957291Sakito 16057291Sakito return(pc); 16157291Sakito } 16257291Sakito 16357291Sakito int 16457291Sakito sio_port_info() 16557291Sakito { 16657291Sakito printf("sio_port_info[sio.c]:\t{%d} major = %d, unit = %d, intr = 0x%x\n", 16757291Sakito 0, sio_portc[0].pc_major, sio_portc[0].pc_unit, sio_portc[0].pc_intr); 16857291Sakito printf("sio_port_info[sio.c]:\t{%d} major = %d, unit = %d, intr = 0x%x\n", 16957291Sakito 1, sio_portc[1].pc_major, sio_portc[1].pc_unit, sio_portc[1].pc_intr); 17057291Sakito } 17157291Sakito 17257291Sakito 17356873Sakito /* 17456873Sakito * entry routines 17556873Sakito */ 17656873Sakito 17754008Sfujita /* ARGSUSED */ 17854008Sfujita #ifdef __STDC__ 17954008Sfujita sioopen(dev_t dev, int flag, int mode, struct proc *p) 18054008Sfujita #else 18154008Sfujita sioopen(dev, flag, mode, p) 18254008Sfujita dev_t dev; 18354008Sfujita int flag, mode; 18454008Sfujita struct proc *p; 18554008Sfujita #endif 18654008Sfujita { 18754008Sfujita register struct tty *tp; 18854008Sfujita register int unit; 18954008Sfujita int error = 0; 19054008Sfujita 19154008Sfujita unit = siounit(dev); 19256873Sakito if (unit >= NLINE || (sio_active & (1 << unit)) == 0) 19354008Sfujita return (ENXIO); 19454008Sfujita tp = &sio_tty[unit]; 19554008Sfujita tp->t_oproc = siostart; 19654008Sfujita tp->t_param = sioparam; 19754008Sfujita tp->t_dev = dev; 19854008Sfujita if ((tp->t_state & TS_ISOPEN) == 0) { 19954008Sfujita tp->t_state |= TS_WOPEN; 20054008Sfujita ttychars(tp); 20154008Sfujita if (tp->t_ispeed == 0) { 20254008Sfujita tp->t_iflag = TTYDEF_IFLAG; 20354008Sfujita tp->t_oflag = TTYDEF_OFLAG; 20456873Sakito /* tp->t_cflag = TTYDEF_CFLAG; */ 20554008Sfujita tp->t_cflag = (CREAD | CS8 | HUPCL); 20654008Sfujita tp->t_lflag = TTYDEF_LFLAG; 20754008Sfujita tp->t_ispeed = tp->t_ospeed = siodefaultrate; 20854008Sfujita } 20954008Sfujita sioparam(tp, &tp->t_termios); 21054008Sfujita ttsetwater(tp); 21154008Sfujita } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 21254008Sfujita return (EBUSY); 21356873Sakito (void) siomctl(dev, WR5_DTR | WR5_RTS, DMSET); 21456873Sakito if ((siosoftCAR & (1 << unit)) || (siomctl(dev, 0, DMGET) & RR0_DCD)) 21556873Sakito tp->t_state |= TS_CARR_ON; 21654008Sfujita (void) spltty(); 21754008Sfujita while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 21854008Sfujita (tp->t_state & TS_CARR_ON) == 0) { 21954008Sfujita tp->t_state |= TS_WOPEN; 22054008Sfujita if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 22154008Sfujita ttopen, 0)) 22254008Sfujita break; 22354008Sfujita } 22454008Sfujita (void) spl0(); 22554008Sfujita if (error == 0) 22654008Sfujita error = (*linesw[tp->t_line].l_open)(dev, tp); 22754008Sfujita return (error); 22854008Sfujita } 22956873Sakito 23054008Sfujita /*ARGSUSED*/ 23154008Sfujita sioclose(dev, flag, mode, p) 23254008Sfujita dev_t dev; 23354008Sfujita int flag, mode; 23454008Sfujita struct proc *p; 23554008Sfujita { 23654008Sfujita register struct tty *tp; 23754008Sfujita register int unit; 23854008Sfujita 23954008Sfujita unit = siounit(dev); 24054008Sfujita tp = &sio_tty[unit]; 24154008Sfujita (*linesw[tp->t_line].l_close)(tp, flag); 24256873Sakito (void) siomctl(dev, WR5_BREAK, DMBIS); 24356873Sakito if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 24456873Sakito (tp->t_state&TS_ISOPEN) == 0) 24556873Sakito (void) siomctl(dev, 0, DMSET); 24654008Sfujita ttyclose(tp); 24754008Sfujita return (0); 24854008Sfujita } 24954008Sfujita 25054008Sfujita sioread(dev, uio, flag) 25154008Sfujita dev_t dev; 25254008Sfujita struct uio *uio; 25354008Sfujita { 25454008Sfujita register struct tty *tp = &sio_tty[siounit(dev)]; 25554008Sfujita 25654008Sfujita return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 25754008Sfujita } 25854008Sfujita 25954008Sfujita siowrite(dev, uio, flag) 26054008Sfujita dev_t dev; 26154008Sfujita struct uio *uio; 26254008Sfujita { 26357126Sakito register int unit = siounit(dev); 26457126Sakito register struct tty *tp = &sio_tty[unit]; 26554008Sfujita 26657126Sakito if ((unit == sioconsole) && constty && 26757126Sakito (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN)) 26857126Sakito tp = constty; 26957126Sakito 27054008Sfujita return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 27154008Sfujita } 27254008Sfujita 27356873Sakito /* 27456873Sakito * Stop output on a line. 27556873Sakito */ 27656873Sakito /*ARGSUSED*/ 27756873Sakito siostop(tp, flag) 27856873Sakito register struct tty *tp; 27954008Sfujita { 28056873Sakito register int s; 28154008Sfujita 28256873Sakito s = spltty(); 28356873Sakito if (tp->t_state & TS_BUSY) { 28456873Sakito if ((tp->t_state&TS_TTSTOP)==0) 28556873Sakito tp->t_state |= TS_FLUSH; 28654008Sfujita } 28756873Sakito splx(s); 28854008Sfujita } 28954008Sfujita 29054008Sfujita sioioctl(dev, cmd, data, flag, p) 29154008Sfujita dev_t dev; 29254008Sfujita int cmd; 29354008Sfujita caddr_t data; 29454008Sfujita int flag; 29554008Sfujita struct proc *p; 29654008Sfujita { 29754008Sfujita register struct tty *tp; 29854008Sfujita register int unit = siounit(dev); 29954008Sfujita register int error; 30056873Sakito 30154008Sfujita tp = &sio_tty[unit]; 30254008Sfujita error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 30354008Sfujita if (error >= 0) 30454008Sfujita return (error); 30554008Sfujita error = ttioctl(tp, cmd, data, flag); 30654008Sfujita if (error >= 0) 30754008Sfujita return (error); 30854008Sfujita 30954008Sfujita switch (cmd) { 31054008Sfujita 31154008Sfujita case TIOCSBRK: 31256873Sakito (void) siomctl(dev, WR5_BREAK, DMBIS); 31356873Sakito break; 31456873Sakito 31554008Sfujita case TIOCCBRK: 31656873Sakito (void) siomctl(dev, WR5_BREAK, DMBIC); 31756873Sakito break; 31856873Sakito 31954008Sfujita case TIOCSDTR: 32056873Sakito (void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIS); 32156873Sakito break; 32256873Sakito 32354008Sfujita case TIOCCDTR: 32456873Sakito (void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIC); 32556873Sakito break; 32656873Sakito 32754008Sfujita case TIOCMSET: 32856873Sakito (void) siomctl(dev, *(int *)data, DMSET); 32956873Sakito break; 33056873Sakito 33154008Sfujita case TIOCMBIS: 33256873Sakito (void) siomctl(dev, *(int *)data, DMBIS); 33356873Sakito break; 33456873Sakito 33554008Sfujita case TIOCMBIC: 33656873Sakito (void) siomctl(dev, *(int *)data, DMBIC); 33756873Sakito break; 33856873Sakito 33954008Sfujita case TIOCMGET: 34056873Sakito *(int *)data = siomctl(dev, 0, DMGET); 34156873Sakito break; 34256873Sakito 34354008Sfujita default: 34454008Sfujita return (ENOTTY); 34554008Sfujita } 34654008Sfujita return (0); 34754008Sfujita } 34854008Sfujita 34954008Sfujita 35056873Sakito /* 35156873Sakito * 35256873Sakito */ 35356873Sakito 35454008Sfujita void 35554008Sfujita siostart(tp) 35654008Sfujita register struct tty *tp; 35754008Sfujita { 35854008Sfujita register struct siodevice *sio; 35956873Sakito register int rr; 36056873Sakito int s, unit, c; 36154008Sfujita 36254008Sfujita unit = siounit(tp->t_dev); 36356873Sakito sio = sio_softc[unit].sc_pc->pc_addr; 36454008Sfujita s = spltty(); 36554008Sfujita if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 36654008Sfujita goto out; 36754008Sfujita if (tp->t_outq.c_cc <= tp->t_lowat) { 36854008Sfujita if (tp->t_state&TS_ASLEEP) { 36954008Sfujita tp->t_state &= ~TS_ASLEEP; 37054008Sfujita wakeup((caddr_t)&tp->t_outq); 37154008Sfujita } 37254008Sfujita selwakeup(&tp->t_wsel); 37354008Sfujita } 37454008Sfujita if (tp->t_outq.c_cc == 0) 37554008Sfujita goto out; 37656873Sakito rr = siogetreg(sio); 37754008Sfujita if (rr & RR_TXRDY) { 37854008Sfujita c = getc(&tp->t_outq); 37954008Sfujita tp->t_state |= TS_BUSY; 38054008Sfujita sio->sio_data = c; 38154008Sfujita } 38254008Sfujita out: 38354008Sfujita splx(s); 38454008Sfujita } 38556873Sakito 38656873Sakito sioparam(tp, t) 38756873Sakito register struct tty *tp; 38856873Sakito register struct termios *t; 38956873Sakito { 39056873Sakito int unit = siounit(tp->t_dev); 39156873Sakito register struct siodevice *sio; 39256873Sakito register cflag = t->c_cflag; 39356873Sakito register u_char wr; 39456873Sakito int ospeed = ttspeedtab(t->c_ospeed, siospeedtab); 39556873Sakito 39656873Sakito sio = sio_softc[unit].sc_pc->pc_addr; 39756873Sakito 39856873Sakito switch (cflag & CSIZE) { 39956873Sakito case CS5: 40056873Sakito case CS6: 40156873Sakito case CS7: 40256873Sakito case CS8: 40356873Sakito break; 40456873Sakito } 40556873Sakito 40656873Sakito wr = ospeed; 40756873Sakito 40856873Sakito if (cflag & PARENB) { 40956873Sakito wr |= WR4_PARENAB; 41056873Sakito if ((cflag&PARODD) == 0) 41156873Sakito wr |= WR4_EPARITY; 41256873Sakito } 41356873Sakito 41456873Sakito if (cflag & CSTOPB) 41556873Sakito wr |= WR4_STOP2; /* 2 stop bit */ 41656873Sakito else 41756873Sakito wr |= WR4_STOP1; /* 1 stop bit */ 41856873Sakito 41956873Sakito (void) sioreg(sio, WR4, wr); 42056873Sakito 42156873Sakito return (0); 42256873Sakito } 42356873Sakito 42456873Sakito siomctl() 42556873Sakito { 42656873Sakito return (0); 42756873Sakito } 42856873Sakito 42956873Sakito 43054008Sfujita /* 43156873Sakito * Interrupt handling 43254008Sfujita */ 43356873Sakito 43456873Sakito void 43556873Sakito _siointr() 43654008Sfujita { 43756873Sakito register int port; 43856873Sakito register struct sio_portc *pc; 43954008Sfujita 44056873Sakito for (port = 0; port < NPORT; port++) { 44156873Sakito pc = &sio_portc[port]; 44256873Sakito 44356873Sakito if (pc->pc_major != -1) 44456873Sakito (pc->pc_intr)(pc->pc_unit); 44554008Sfujita } 44654008Sfujita } 44754008Sfujita 44856873Sakito siointr(unit) 44956873Sakito register int unit; 45056873Sakito { 45156873Sakito register struct siodevice *sio = sio_softc[unit].sc_pc->pc_addr; 45256873Sakito register u_char code; 45356873Sakito register struct tty *tp; 45456873Sakito int s, rr; 45556873Sakito 45656873Sakito tp = &sio_tty[unit]; 457*57850Sakito 458*57850Sakito start: 45956873Sakito rr = siogetreg(sio); 460*57850Sakito if (rr & RR_RXRDY) { 461*57850Sakito if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) { 462*57850Sakito sioeint(unit, rr, sio); 463*57850Sakito goto start; 464*57850Sakito } 46556873Sakito 46656873Sakito code = sio->sio_data; 46756873Sakito if ((tp->t_state & TS_ISOPEN) != 0) 46856873Sakito (*linesw[tp->t_line].l_rint)(code, tp); 469*57850Sakito 470*57850Sakito while ((rr = siogetreg(sio)) & RR_RXRDY) { 471*57850Sakito code = sio->sio_data; 472*57850Sakito if ((tp->t_state & TS_ISOPEN) != 0) 473*57850Sakito (*linesw[tp->t_line].l_rint)(code, tp); 474*57850Sakito } 47556873Sakito } 47656873Sakito 47756873Sakito if (rr & RR_TXRDY) { 47856873Sakito sio->sio_cmd = WR0_RSTPEND; 47956873Sakito tp->t_state &= ~(TS_BUSY|TS_FLUSH); 48056873Sakito if (tp->t_line) 48156873Sakito (*linesw[tp->t_line].l_start)(tp); 48256873Sakito else 48356873Sakito siostart(tp); 48456873Sakito } 48556873Sakito } 48656873Sakito 487*57850Sakito sioeint(unit, stat, sio) 488*57850Sakito register int unit, stat; 489*57850Sakito register struct siodevice *sio; 490*57850Sakito { 491*57850Sakito register struct tty *tp; 492*57850Sakito register int code; 493*57850Sakito 494*57850Sakito tp = &sio_tty[unit]; 495*57850Sakito 496*57850Sakito code = sio->sio_data; 497*57850Sakito 498*57850Sakito sio->sio_cmd = WR0_ERRRST; 499*57850Sakito 500*57850Sakito if ((tp->t_state & TS_ISOPEN) == 0) 501*57850Sakito return; 502*57850Sakito 503*57850Sakito if (stat & RR_FRAMING) 504*57850Sakito code |= TTY_FE; 505*57850Sakito else if (stat & RR_PARITY) 506*57850Sakito code |= TTY_PE; 507*57850Sakito 508*57850Sakito (*linesw[tp->t_line].l_rint)(code, tp); 509*57850Sakito } 510*57850Sakito 51154008Sfujita /* 51254008Sfujita * Following are all routines needed for SIO to act as console 51354008Sfujita */ 51457058Sakito #include <luna68k/luna68k/cons.h> 51554008Sfujita 51654008Sfujita siocnprobe(cp) 51756873Sakito register struct consdev *cp; 51854008Sfujita { 51956873Sakito register int unit = 0; 52054008Sfujita 52154008Sfujita /* locate the major number */ 52254008Sfujita for (siomajor = 0; siomajor < nchrdev; siomajor++) 52354008Sfujita if (cdevsw[siomajor].d_open == sioopen) 52454008Sfujita break; 52554008Sfujita 52656873Sakito siounitbase = -1; 52754008Sfujita 52854008Sfujita /* initialize required fields */ 52954008Sfujita cp->cn_dev = makedev(siomajor, unit); 53056873Sakito cp->cn_tp = &sio_tty[unit]; 53154008Sfujita cp->cn_pri = CN_NORMAL; 53254008Sfujita } 53354008Sfujita 53454008Sfujita siocninit(cp) 53554008Sfujita struct consdev *cp; 53654008Sfujita { 53754008Sfujita int unit = siounit(cp->cn_dev); 53856873Sakito register struct sio_softc *sc = &sio_softc[unit]; 53954008Sfujita 54056873Sakito sioinit((struct siodevice *) SIO_HARDADDR, siodefaultrate); 54156873Sakito 54256873Sakito /* port assign */ 54356873Sakito sc->sc_pc = sio_port_assign(0, siomajor, unit, siointr); 54456873Sakito 54554008Sfujita sioconsole = unit; 54656873Sakito siounitbase = 0; 54756873Sakito 54856873Sakito sio_active |= 1 << unit; 54956873Sakito siosoftCAR |= 1 << unit; 55054008Sfujita } 55154008Sfujita 55254008Sfujita siocngetc(dev) 55354008Sfujita dev_t dev; 55454008Sfujita { 55556873Sakito struct sio_softc *sc = &sio_softc[siounit(dev)]; 55656873Sakito struct sio_portc *pc = sc->sc_pc; 55754008Sfujita 55856873Sakito return(sio_imgetc(pc->pc_addr)); 55954008Sfujita } 56054008Sfujita 56154008Sfujita siocnputc(dev, c) 56254008Sfujita dev_t dev; 56354008Sfujita int c; 56454008Sfujita { 56556873Sakito struct sio_softc *sc = &sio_softc[siounit(dev)]; 56656873Sakito struct sio_portc *pc = sc->sc_pc; 56754008Sfujita 56856873Sakito sio_imputc(pc->pc_addr, c); 56956873Sakito } 57054008Sfujita 57154008Sfujita 57256873Sakito /* 57356873Sakito * sio raw-level routines 57456873Sakito */ 57554008Sfujita 57656873Sakito sioinit(sio0, rate) 57756873Sakito register struct siodevice *sio0; 57856873Sakito register int rate; 57956873Sakito { 58056873Sakito register struct siodevice *sio1; 58156873Sakito int s; 58254008Sfujita 58356873Sakito rate = ttspeedtab(rate, siospeedtab); 58454008Sfujita 58556873Sakito if (sio_init_done) 58656873Sakito return; 58754008Sfujita 58856873Sakito sio1 = (struct siodevice *) ((u_long) sio0 + sizeof(struct siodevice)); 58954008Sfujita 59054008Sfujita s = splhigh(); 59154008Sfujita 59256873Sakito sioreg(sio0, WR0, WR0_CHANRST); /* Channel-A Reset */ 59354008Sfujita 59456873Sakito sioreg(sio0, WR2, (WR2_VEC86 | WR2_INTR_1)); /* Set CPU BUS Interface Mode */ 59556873Sakito sioreg(sio1, WR2, 0); /* Set Interrupt Vector */ 59654008Sfujita 59756873Sakito sioreg(sio0, WR0, WR0_RSTINT); /* Reset E/S Interrupt */ 59856873Sakito sioreg(sio0, WR4, (rate | WR4_STOP1 | WR4_NPARITY)); /* Tx/Rx */ 59956873Sakito sioreg(sio0, WR3, (WR3_RX8BIT | WR3_RXENBL)); /* Rx */ 60056873Sakito sioreg(sio0, WR5, (WR5_TX8BIT | WR5_TXENBL)); /* Tx */ 60156873Sakito sioreg(sio0, WR0, WR0_RSTINT); /* Reset E/S Interrupt */ 60256873Sakito sioreg(sio0, WR1, (WR1_RXALLS | WR1_TXENBL)); 60354008Sfujita 60456873Sakito sioreg(sio1, WR0, WR0_CHANRST); /* Channel-B Reset */ 60554008Sfujita 60656873Sakito sioreg(sio1, WR0, WR0_RSTINT); /* Reset E/S Interrupt */ 60756873Sakito sioreg(sio1, WR4, (rate | WR4_STOP1 | WR4_NPARITY)); /* Tx/Rx */ 60856873Sakito sioreg(sio1, WR3, (WR3_RX8BIT | WR3_RXENBL)); /* Rx */ 60956873Sakito sioreg(sio1, WR5, (WR5_TX8BIT | WR5_TXENBL)); /* Tx */ 61056873Sakito sioreg(sio1, WR0, WR0_RSTINT); /* Reset E/S Interrupt */ 61156873Sakito sioreg(sio1, WR1, (WR1_RXALLS | WR1_TXENBL)); 61256873Sakito 61354008Sfujita splx(s); 61456873Sakito 61556873Sakito sio_init_done = 1; 61654008Sfujita } 61754008Sfujita 61856873Sakito sio_imgetc(sio) 61956873Sakito register struct siodevice *sio; 62054008Sfujita { 62156873Sakito register int rr0, rr1; 62256873Sakito int c, s; 62354008Sfujita 62456873Sakito s = splhigh(); 62556873Sakito while (((rr0 = sioreg(sio, RR0, 0)) & RR0_RXAVAIL) == 0) 62656873Sakito ; 62756873Sakito c = sio->sio_data; 62856873Sakito sioreg(sio, WR0, WR0_RSTPEND); 62956873Sakito splx(s); 63056873Sakito return (c); 63154008Sfujita } 63254008Sfujita 63356873Sakito sio_imputc(sio, c) 63456873Sakito register struct siodevice *sio; 63554008Sfujita int c; 63654008Sfujita { 63754008Sfujita register u_char code; 63856873Sakito register int rr; 63956873Sakito int s; 64054008Sfujita 64154008Sfujita s = splhigh(); 64254008Sfujita 64356873Sakito sioreg(sio, WR1, WR1_RXALLS); 64456873Sakito 64554008Sfujita do { 64654008Sfujita DELAY(1); 64756873Sakito rr = siogetreg(sio); 64854008Sfujita } while (!(rr & RR_TXRDY)); 64956873Sakito 65056873Sakito code = (c & 0xFF); 65154008Sfujita sio->sio_data = code; 65254008Sfujita 65354008Sfujita do { 65454008Sfujita DELAY(1); 65556873Sakito rr = siogetreg(sio); 65654008Sfujita } while (!(rr & RR_TXRDY)); 65754008Sfujita 65856873Sakito sioreg(sio, WR1, (WR1_RXALLS | WR1_TXENBL)); 65956873Sakito 66054008Sfujita splx(s); 66154008Sfujita } 66254008Sfujita 66356873Sakito /* 66456873Sakito * uPD7201A register operation 66556873Sakito */ 66654008Sfujita 66754008Sfujita int 66856873Sakito siogetreg(sio) 66956873Sakito register struct siodevice *sio; 67054008Sfujita { 67154008Sfujita register int rr = 0; 67254008Sfujita 67354008Sfujita rr = sio->sio_stat; 67454008Sfujita rr <<= 8; 67554008Sfujita sio->sio_cmd = 1; /* Select RR1 */ 67654008Sfujita rr |= sio->sio_stat; 67754008Sfujita 67854008Sfujita return(rr); 67954008Sfujita } 68054008Sfujita 68154008Sfujita int 68256873Sakito sioreg(sio, reg, val) 68356873Sakito register struct siodevice *sio; 68454008Sfujita register int reg, val; 68554008Sfujita { 68654008Sfujita if (isStatusReg(reg)) { 68756873Sakito if (reg != 0) 68856873Sakito sio->sio_cmd = reg; 68956873Sakito val = sio->sio_stat; 69054008Sfujita } else { 69156873Sakito if (reg != 0) 69256873Sakito sio->sio_cmd = reg; 69356873Sakito sio->sio_cmd = val; 69454008Sfujita } 69556873Sakito 69656873Sakito return(val); 69754008Sfujita } 69854008Sfujita #endif 699