diff options
-rw-r--r-- | sys/dev/rp/rp.c | 295 | ||||
-rw-r--r-- | sys/dev/rp/rp_pci.c | 2 | ||||
-rw-r--r-- | sys/dev/rp/rpreg.h | 16 |
3 files changed, 125 insertions, 188 deletions
diff --git a/sys/dev/rp/rp.c b/sys/dev/rp/rp.c index 809a2a4..690e221 100644 --- a/sys/dev/rp/rp.c +++ b/sys/dev/rp/rp.c @@ -117,6 +117,8 @@ Byte_t rp_sBitMapSetTbl[8] = 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 }; +static void rpfree(void *); + /*************************************************************************** Function: sReadAiopID Purpose: Read the AIOP idenfication number directly from an AIOP. @@ -572,21 +574,19 @@ static struct rp_port *p_rp_table[MAX_RP_PORTS]; * The top-level routines begin here */ -static void rpbreak(struct tty *, int); static void rpclose(struct tty *tp); static void rphardclose(struct tty *tp); static int rpmodem(struct tty *, int, int); static int rpparam(struct tty *, struct termios *); static void rpstart(struct tty *); -static void rpstop(struct tty *, int); -static t_open_t rpopen; +static int rpioctl(struct tty *, u_long, caddr_t, struct thread *); +static int rpopen(struct tty *); static void rp_do_receive(struct rp_port *rp, struct tty *tp, CHANNEL_t *cp, unsigned int ChanStatus) { - int spl; unsigned int CharNStat; - int i, ToRecv, wRecv, ch, ttynocopy; + int ToRecv, ch, err = 0; ToRecv = sGetRxCnt(cp); if(ToRecv == 0) @@ -608,22 +608,22 @@ static void rp_do_receive(struct rp_port *rp, struct tty *tp, FIFO one word at a time, pulling apart the character and the status. Update error counters depending on status. */ + tty_lock(tp); if(ChanStatus & STATMODE) { while(ToRecv) { - if(tp->t_state & TS_TBLOCK) { - break; - } CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp)); ch = CharNStat & 0xff; if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) - ch |= TTY_FE; + err |= TRE_FRAMING; else if (CharNStat & STMPARITYH) - ch |= TTY_PE; - else if (CharNStat & STMRCVROVRH) + err |= TRE_PARITY; + else if (CharNStat & STMRCVROVRH) { rp->rp_overflows++; + err |= TRE_OVERRUN; + } - ttyld_rint(tp, ch); + ttydisc_rint(tp, ch, err); ToRecv--; } /* @@ -634,42 +634,15 @@ static void rp_do_receive(struct rp_port *rp, struct tty *tp, sDisRxStatusMode(cp); } } else { - /* - * Avoid the grotesquely inefficient lineswitch routine - * (ttyinput) in "raw" mode. It usually takes about 450 - * instructions (that's without canonical processing or echo!). - * slinput is reasonably fast (usually 40 instructions plus - * call overhead). - */ ToRecv = sGetRxCnt(cp); - if ( tp->t_state & TS_CAN_BYPASS_L_RINT ) { - if ( ToRecv > RXFIFO_SIZE ) { - ToRecv = RXFIFO_SIZE; - } - for ( i = 0, wRecv = ToRecv >> 1; wRecv > 0; i += 2, wRecv-- ) { - le16enc(rp->RxBuf + i,rp_readch2(cp,sGetTxRxDataIO(cp))); - } - if ( ToRecv & 1 ) { - rp->RxBuf[(ToRecv-1)] = rp_readch1(cp,sGetTxRxDataIO(cp)); - } - tk_nin += ToRecv; - tk_rawcc += ToRecv; - tp->t_rawcc += ToRecv; - ttynocopy = b_to_q(rp->RxBuf, ToRecv, &tp->t_rawq); - ttwakeup(tp); - } else { - while (ToRecv) { - if(tp->t_state & TS_TBLOCK) { - break; - } - ch = (u_char) rp_readch1(cp,sGetTxRxDataIO(cp)); - spl = spltty(); - ttyld_rint(tp, ch); - splx(spl); - ToRecv--; - } + while (ToRecv) { + ch = rp_readch1(cp,sGetTxRxDataIO(cp)); + ttydisc_rint(tp, ch & 0xff, err); + ToRecv--; } } + ttydisc_rint_done(tp); + tty_unlock(tp); } static void rp_handle_port(struct rp_port *rp) @@ -687,21 +660,12 @@ static void rp_handle_port(struct rp_port *rp) IntMask = IntMask & rp->rp_intmask; ChanStatus = sGetChanStatus(cp); if(IntMask & RXF_TRIG) - if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { - rp_do_receive(rp, tp, cp, ChanStatus); - } + rp_do_receive(rp, tp, cp, ChanStatus); if(IntMask & DELTA_CD) { if(ChanStatus & CD_ACT) { - if(!(tp->t_state & TS_CARR_ON) ) { - (void)ttyld_modem(tp, 1); - } + (void)ttydisc_modem(tp, 1); } else { - if((tp->t_state & TS_CARR_ON)) { - (void)ttyld_modem(tp, 0); - if(ttyld_modem(tp, 0) == 0) { - rphardclose(tp); - } - } + (void)ttydisc_modem(tp, 0); } } /* oldcts = rp->rp_cts; @@ -740,15 +704,13 @@ static void rp_do_poll(void *not_used) for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; line++, rp++) { tp = rp->rp_tty; - if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { - count = sGetTxCnt(&rp->rp_channel); - if(count == 0) - tp->t_state &= ~(TS_BUSY); - if(!(tp->t_state & TS_TTSTOP) && - (count <= rp->rp_restart)) { - ttyld_start(tp); - } + tty_lock(tp); + count = sGetTxCnt(&rp->rp_channel); + if (count >= 0 && + (count <= rp->rp_restart)) { + rpstart(tp); } + tty_unlock(tp); } } if(rp_num_ports_open) @@ -756,10 +718,31 @@ static void rp_do_poll(void *not_used) (void *)NULL, POLL_INTERVAL); } +static struct ttydevsw rp_tty_class = { + .tsw_flags = TF_INITLOCK|TF_CALLOUT, + .tsw_open = rpopen, + .tsw_close = rpclose, + .tsw_outwakeup = rpstart, + .tsw_ioctl = rpioctl, + .tsw_param = rpparam, + .tsw_modem = rpmodem, + .tsw_free = rpfree, +}; + + +static void +rpfree(void *softc) +{ + struct rp_port *rp = softc; + CONTROLLER_t *ctlp = rp->rp_ctlp; + + atomic_subtract_32(&ctlp->free, 1); +} + int rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) { - int oldspl, unit; + int unit; int num_chan; int aiop, chan, port; int ChanStatus, line, count; @@ -775,7 +758,7 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) callout_handle_init(&rp_callout_handle); ctlp->rp = rp = (struct rp_port *) - malloc(sizeof(struct rp_port) * num_ports, M_TTYS, M_NOWAIT | M_ZERO); + malloc(sizeof(struct rp_port) * num_ports, M_DEVBUF, M_NOWAIT | M_ZERO); if (rp == NULL) { device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n"); retval = ENOMEM; @@ -785,26 +768,13 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) count = unit * 32; /* board times max ports per card SG */ bzero(rp, sizeof(struct rp_port) * num_ports); - oldspl = spltty(); rp_addr(unit) = rp; - splx(oldspl); port = 0; for(aiop=0; aiop < num_aiops; aiop++) { num_chan = sGetAiopNumChan(ctlp, aiop); for(chan=0; chan < num_chan; chan++, port++, rp++) { - tp = rp->rp_tty = ttyalloc(); - tp->t_sc = rp; - tp->t_param = rpparam; - tp->t_oproc = rpstart; - tp->t_stop = rpstop; - tp->t_break = rpbreak; - tp->t_modem = rpmodem; - tp->t_close = rpclose; - tp->t_open = rpopen; - tp->t_ififosize = 512; - tp->t_ispeedwat = (speed_t)-1; - tp->t_ospeedwat = (speed_t)-1; + rp->rp_tty = tp = tty_alloc(&rp_tty_class, rp, NULL); rp->rp_port = port; rp->rp_ctlp = ctlp; rp->rp_unit = unit; @@ -826,11 +796,13 @@ rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) rp->rp_cts = (ChanStatus & CTS_ACT) != 0; line = (unit << 5) | (aiop << 3) | chan; rp_table(line) = rp; - ttycreate(tp, TS_CALLOUT, "R%r%r", unit, port); + tty_makedev(tp, NULL, "R%r%r", unit, port); } } rp_ndevs++; + mtx_init(&ctlp->hwmtx, "rp_hwmtx", NULL, MTX_DEF); + ctlp->hwmtx_init = 1; return (0); nogo: @@ -842,7 +814,7 @@ nogo: void rp_releaseresource(CONTROLLER_t *ctlp) { - int i, s, unit; + int i, unit; struct rp_port *rp; @@ -850,21 +822,25 @@ rp_releaseresource(CONTROLLER_t *ctlp) if (rp_addr(unit) != NULL) { for (i = 0; i < rp_num_ports[unit]; i++) { rp = rp_addr(unit) + i; - ttyfree(rp->rp_tty); + atomic_add_32(&ctlp->free, 1); + tty_lock(rp->rp_tty); + tty_rel_gone(rp->rp_tty); } } + while (ctlp->free != 0) { + pause("rpwt", hz / 10); + } + if (ctlp->rp != NULL) { - s = spltty(); for (i = 0 ; i < sizeof(p_rp_addr) / sizeof(*p_rp_addr) ; i++) if (p_rp_addr[i] == ctlp->rp) p_rp_addr[i] = NULL; for (i = 0 ; i < sizeof(p_rp_table) / sizeof(*p_rp_table) ; i++) if (p_rp_table[i] == ctlp->rp) p_rp_table[i] = NULL; - splx(s); - free(ctlp->rp, M_DEVBUF); - ctlp->rp = NULL; + free(ctlp->rp, M_DEVBUF); + ctlp->rp = NULL; } } @@ -875,15 +851,13 @@ rp_untimeout(void) } static int -rpopen(struct tty *tp, struct cdev *dev) +rpopen(struct tty *tp) { struct rp_port *rp; - int oldspl, flags; + int flags; unsigned int IntMask, ChanStatus; - rp = dev->si_drv1; - - oldspl = spltty(); + rp = tty_softc(tp); flags = 0; flags |= SET_RTS; @@ -938,7 +912,7 @@ rpclose(struct tty *tp) { struct rp_port *rp; - rp = tp->t_sc; + rp = tty_softc(tp); rphardclose(tp); device_unbusy(rp->rp_ctlp->dev); } @@ -949,7 +923,7 @@ rphardclose(struct tty *tp) struct rp_port *rp; CHANNEL_t *cp; - rp = tp->t_sc; + rp = tty_softc(tp); cp = &rp->rp_channel; sFlushRxFIFO(cp); @@ -961,6 +935,7 @@ rphardclose(struct tty *tp) sDisTxSoftFlowCtl(cp); sClrTxXOFF(cp); +#ifdef DJA if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) { sClrDTR(cp); } @@ -970,18 +945,24 @@ rphardclose(struct tty *tp) tp->t_actout = FALSE; wakeup(&tp->t_actout); wakeup(TSA_CARR_ON(tp)); +#endif /* DJA */ } -static void -rpbreak(struct tty *tp, int sig) +static int +rpioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) { struct rp_port *rp; - rp = tp->t_sc; - if (sig) { + rp = tty_softc(tp); + switch (cmd) { + case TIOCSBRK: sSendBreak(&rp->rp_channel); - } else { + return (0); + case TIOCCBRK: sClrBreak(&rp->rp_channel); + return (0); + default: + return ENOIOCTL; } } @@ -991,7 +972,7 @@ rpmodem(struct tty *tp, int sigon, int sigoff) struct rp_port *rp; int i, j, k; - rp = tp->t_sc; + rp = tty_softc(tp); if (sigon != 0 || sigoff != 0) { i = j = 0; if (sigon & SER_DTR) @@ -1025,7 +1006,11 @@ rpmodem(struct tty *tp, int sigon, int sigoff) return (0); } -static struct speedtab baud_table[] = { +static struct +{ + int baud; + int conversion; +} baud_table[] = { {B0, 0}, {B50, BRD50}, {B75, BRD75}, {B110, BRD110}, {B134, BRD134}, {B150, BRD150}, {B200, BRD200}, {B300, BRD300}, {B600, BRD600}, @@ -1037,6 +1022,17 @@ static struct speedtab baud_table[] = { {-1, -1} }; +static int rp_convert_baud(int baud) { + int i; + + for (i = 0; baud_table[i].baud >= 0; i++) { + if (baud_table[i].baud == baud) + break; + } + + return baud_table[i].conversion; +} + static int rpparam(tp, t) struct tty *tp; @@ -1044,16 +1040,14 @@ rpparam(tp, t) { struct rp_port *rp; CHANNEL_t *cp; - int oldspl, cflag, iflag, oflag, lflag; + int cflag, iflag, oflag, lflag; int ospeed; #ifdef RPCLOCAL int devshift; #endif - - rp = tp->t_sc; + rp = tty_softc(tp); cp = &rp->rp_channel; - oldspl = spltty(); cflag = t->c_cflag; #ifdef RPCLOCAL @@ -1067,17 +1061,10 @@ rpparam(tp, t) oflag = t->c_oflag; lflag = t->c_lflag; - ospeed = ttspeedtab(t->c_ispeed, baud_table); + ospeed = rp_convert_baud(t->c_ispeed); if(ospeed < 0 || t->c_ispeed != t->c_ospeed) return(EINVAL); - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; - tp->t_cflag = cflag; - tp->t_iflag = iflag; - tp->t_oflag = oflag; - tp->t_lflag = lflag; - if(t->c_ospeed == 0) { sClrDTR(cp); return(0); @@ -1143,104 +1130,36 @@ rpparam(tp, t) } else { sDisRTSFlowCtl(cp); } - ttyldoptim(tp); - - if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) { - tp->t_state |= TS_CARR_ON; - wakeup(TSA_CARR_ON(tp)); - } - -/* tp->t_state |= TS_CAN_BYPASS_L_RINT; - flags = rp->rp_channel.TxControl[3]; - if(flags & SET_DTR) - else - if(flags & SET_RTS) - else -*/ - splx(oldspl); return(0); } static void -rpstart(tp) - struct tty *tp; +rpstart(struct tty *tp) { struct rp_port *rp; CHANNEL_t *cp; - struct clist *qp; char flags; - int spl, xmit_fifo_room; + int xmit_fifo_room; int i, count, wcount; - - rp = tp->t_sc; + rp = tty_softc(tp); cp = &rp->rp_channel; flags = rp->rp_channel.TxControl[3]; - spl = spltty(); - if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - splx(spl); - return; - } if(rp->rp_xmit_stopped) { sEnTransmit(cp); rp->rp_xmit_stopped = 0; } - count = sGetTxCnt(cp); - if(tp->t_outq.c_cc == 0) { - if((tp->t_state & TS_BUSY) && (count == 0)) { - tp->t_state &= ~TS_BUSY; - } - ttwwakeup(tp); - splx(spl); - return; - } xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); - qp = &tp->t_outq; - if(xmit_fifo_room > 0 && qp->c_cc > 0) { - tp->t_state |= TS_BUSY; - count = q_to_b( qp, rp->TxBuf, xmit_fifo_room ); + count = ttydisc_getc(tp, &rp->TxBuf, xmit_fifo_room); + if(xmit_fifo_room > 0) { for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) { - rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(rp->TxBuf + i)); + rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(&rp->TxBuf[i])); } if ( count & 1 ) { rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]); } } - rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0; - - ttwwakeup(tp); - splx(spl); -} - -static -void -rpstop(tp, flag) - register struct tty *tp; - int flag; -{ - struct rp_port *rp; - CHANNEL_t *cp; - int spl; - - rp = tp->t_sc; - cp = &rp->rp_channel; - - spl = spltty(); - - if(tp->t_state & TS_BUSY) { - if((tp->t_state&TS_TTSTOP) == 0) { - sFlushTxFIFO(cp); - } else { - if(rp->rp_xmit_stopped == 0) { - sDisTransmit(cp); - rp->rp_xmit_stopped = 1; - } - } - } - splx(spl); - rpstart(tp); } diff --git a/sys/dev/rp/rp_pci.c b/sys/dev/rp/rp_pci.c index 4c27b62..e8a1c68 100644 --- a/sys/dev/rp/rp_pci.c +++ b/sys/dev/rp/rp_pci.c @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #define RP_DEVICE_ID_6M 0x000C #define RP_DEVICE_ID_4M 0x000D #define RP_DEVICE_ID_UPCI_32 0x0801 +#define RP_DEVICE_ID_UPCI_16 0x0803 #define RP_DEVICE_ID_UPCI_8O 0x0805 /************************************************************************** @@ -180,6 +181,7 @@ rp_pciattach(device_t dev) ctlp->bus_ctlp = NULL; switch (pci_get_device(dev)) { + case RP_DEVICE_ID_UPCI_16: case RP_DEVICE_ID_UPCI_32: case RP_DEVICE_ID_UPCI_8O: ctlp->io_rid[0] = PCIR_BAR(2); diff --git a/sys/dev/rp/rpreg.h b/sys/dev/rp/rpreg.h index 735ba87..c8960eb 100644 --- a/sys/dev/rp/rpreg.h +++ b/sys/dev/rp/rpreg.h @@ -361,6 +361,10 @@ struct CONTROLLER_str int AiopID[AIOP_CTL_SIZE]; int AiopNumChan[AIOP_CTL_SIZE]; + struct mtx hwmtx; /* Spinlock protecting hardware. */ + int hwmtx_init; + int free; + /* Device and resource management */ device_t dev; /* device */ int io_num; /* Number of IO resources */ @@ -1005,6 +1009,18 @@ void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags); int rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports); void rp_releaseresource(CONTROLLER_t *ctlp); void rp_untimeout(void); +static __inline void +rp_lock(CONTROLLER_T *CtlP) +{ + if (CtlP->hwmtx_init != 0) + mtx_lock_spin(&CtlP->hwmtx); +} +static __inline void +rp_unlock(CONTROLLER_T *CtlP) +{ + if (CtlP->hwmtx_init != 0) + mtx_unlock_spin(&CtlP->hwmtx); +} #ifndef ROCKET_C extern Byte_t R[RDATASIZE]; |