diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1998-06-02 06:37:19 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1998-06-02 06:37:19 +0000 |
commit | 6e99aec8788fbc4a0478d9ceca57920aa2d7bcda (patch) | |
tree | 516614624d8aab2efb4144f814b7f8630f53dd31 /sys/arch/sparc | |
parent | e22665b32da4d75dad6c333e4554a61ed517d84f (diff) |
newer fixes from plunky@skate.demon.co.uk
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r-- | sys/arch/sparc/dev/bppioctl.h | 61 | ||||
-rw-r--r-- | sys/arch/sparc/dev/magma.c | 537 | ||||
-rw-r--r-- | sys/arch/sparc/dev/magmareg.h | 29 |
3 files changed, 482 insertions, 145 deletions
diff --git a/sys/arch/sparc/dev/bppioctl.h b/sys/arch/sparc/dev/bppioctl.h new file mode 100644 index 00000000000..3b1e82703fe --- /dev/null +++ b/sys/arch/sparc/dev/bppioctl.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1998 Iain Hibbert + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name Iain Hibbert may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * bppioctl.h + */ + +#ifndef _IOCTL_ +#include <sys/ioctl.h> +#endif + +struct bpp_param { + int bp_burst; /* chars to send/recv in one call */ + int bp_timeout; /* timeout: -1 blocking, 0 non blocking >0 ms */ + int bp_delay; /* delay between polls (ms) */ +}; + +#define BPP_BLOCK -1 +#define BPP_NOBLOCK 0 + +/* defaults */ +#define BPP_BURST 1024 +#define BPP_TIMEOUT BPP_BLOCK +#define BPP_DELAY 10 + +/* limits */ +#define BPP_BURST_MIN 1 +#define BPP_BURST_MAX 1024 +#define BPP_DELAY_MIN 0 +#define BPP_DELAY_MAX 30000 + +/* status bits */ +#define BPP_BUSY (1<<0) +#define BPP_PAPER (1<<1) + +/* ioctl commands */ +#define BPPIOCSPARAM _IOW('P', 0x1, struct bpp_param) +#define BPPIOCGPARAM _IOR('P', 0x2, struct bpp_param) +#define BPPIOCGSTAT _IOR('P', 0x4, int) diff --git a/sys/arch/sparc/dev/magma.c b/sys/arch/sparc/dev/magma.c index 4a0fc416a4c..58bb91018da 100644 --- a/sys/arch/sparc/dev/magma.c +++ b/sys/arch/sparc/dev/magma.c @@ -64,6 +64,7 @@ #include <dev/ic/cd1400reg.h> #include <dev/ic/cd1190reg.h> +#include "bppioctl.h" #include "magmareg.h" /* @@ -470,9 +471,24 @@ int needsoftint = 0; int port = rivr >> 4; if( rivr & (1<<3) ) { /* parallel port */ - struct mbpp_port *mbpp = &sc->ms_mbpp->ms_port[port]; + struct mbpp_port *mbpp; + int n_chars; + mbpp = &sc->ms_mbpp->ms_port[port]; cd = mbpp->mp_cd1400; + + /* don't think we have to handle exceptions */ + n_chars = cd1400_read_reg(cd, CD1400_RDCR); + while( n_chars-- ) { + if( mbpp->mp_cnt == 0 ) { + SET(mbpp->mp_flags, MBPPF_WAKEUP); + needsoftint = 1; + break; + } + *mbpp->mp_ptr = cd1400_read_reg(cd, CD1400_RDSR); + mbpp->mp_ptr++; + mbpp->mp_cnt--; + } } else { /* serial port */ register struct mtty_port *mtty; register u_char *ptr, n_chars, line_stat; @@ -544,27 +560,23 @@ int needsoftint = 0; mbpp = &sc->ms_mbpp->ms_port[port]; cd = mbpp->mp_cd1400; - /* if we have anything to send, then send what we can.. otherwise - * shut off the interrupts and signal for a wakeup (can't be done - * at this spl because its sleeping in spltty() in mbppwrite - */ - - if( mbpp->mp_txc ) { + if( mbpp->mp_cnt ) { int count = 0; - while( count++ < CD1400_PAR_FIFO_SIZE && mbpp->mp_txc ) { - cd1400_write_reg(cd, CD1400_TDR, *mbpp->mp_txp); - mbpp->mp_txc--; - mbpp->mp_txp++; + /* fill the fifo */ + while( mbpp->mp_cnt && count++ < CD1400_PAR_FIFO_SIZE ) { + cd1400_write_reg(cd, CD1400_TDR, *mbpp->mp_ptr); + mbpp->mp_ptr++; + mbpp->mp_cnt--; } } else { - register int srer; - - srer = cd1400_read_reg(cd, CD1400_SRER); - CLR(srer, CD1400_SRER_TXRDY); - cd1400_write_reg(cd, CD1400_SRER, srer); - - SET(mbpp->mp_flags, MBPPF_DONE); + /* fifo is empty and we got no more data to send, so shut + * off interrupts and signal for a wakeup, which can't be + * done here in case we beat mbpp_send to the tsleep call + * (we are running at >spltty) + */ + cd1400_write_reg(cd, CD1400_SRER, 0); + SET(mbpp->mp_flags, MBPPF_WAKEUP); needsoftint = 1; } } else { /* serial port */ @@ -675,78 +687,81 @@ int s, flags; /* * check the tty ports (if any) to see what needs doing */ - if( mtty ) for( port = 0 ; port < mtty->ms_nports ; port++ ) { - struct mtty_port *mp = &mtty->ms_port[port]; - struct tty *tp = mp->mp_tty; + if( mtty ) { + for( port = 0 ; port < mtty->ms_nports ; port++ ) { + struct mtty_port *mp = &mtty->ms_port[port]; + struct tty *tp = mp->mp_tty; - if( !ISSET(tp->t_state, TS_ISOPEN) ) continue; + if( !ISSET(tp->t_state, TS_ISOPEN) ) continue; - /* - * handle any received data - */ - while( mp->mp_rget != mp->mp_rput ) { - u_char stat; - int data; + /* + * handle any received data + */ + while( mp->mp_rget != mp->mp_rput ) { + u_char stat; + int data; - stat = mp->mp_rget[0]; - data = mp->mp_rget[1]; - mp->mp_rget = ((mp->mp_rget + 2) == mp->mp_rend) ? mp->mp_rbuf : (mp->mp_rget + 2); + stat = mp->mp_rget[0]; + data = mp->mp_rget[1]; + mp->mp_rget = ((mp->mp_rget + 2) == mp->mp_rend) ? mp->mp_rbuf : (mp->mp_rget + 2); - if( stat & (CD1400_RDSR_BREAK | CD1400_RDSR_FE) ) - data |= TTY_FE; - if( stat & CD1400_RDSR_PE ) - data |= TTY_PE; + if( stat & (CD1400_RDSR_BREAK | CD1400_RDSR_FE) ) + data |= TTY_FE; + if( stat & CD1400_RDSR_PE ) + data |= TTY_PE; - if( stat & CD1400_RDSR_OE ) - log(LOG_WARNING, "%s%x: fifo overflow\n", mtty->ms_dev.dv_xname, port); + if( stat & CD1400_RDSR_OE ) + log(LOG_WARNING, "%s%x: fifo overflow\n", mtty->ms_dev.dv_xname, port); - (*linesw[tp->t_line].l_rint)(data, tp); - serviced = 1; - } + (*linesw[tp->t_line].l_rint)(data, tp); + serviced = 1; + } - s = splhigh(); /* block out hard interrupt routine */ - flags = mp->mp_flags; - CLR(mp->mp_flags, MTTYF_DONE | MTTYF_CARRIER_CHANGED | MTTYF_RING_OVERFLOW); - splx(s); /* ok */ + s = splhigh(); /* block out hard interrupt routine */ + flags = mp->mp_flags; + CLR(mp->mp_flags, MTTYF_DONE | MTTYF_CARRIER_CHANGED | MTTYF_RING_OVERFLOW); + splx(s); /* ok */ - if( ISSET(flags, MTTYF_CARRIER_CHANGED) ) { - dprintf(("%s%x: cd %s\n", mtty->ms_dev.dv_xname, port, mp->mp_carrier ? "on" : "off")); - (*linesw[tp->t_line].l_modem)(tp, mp->mp_carrier); - serviced = 1; - } + if( ISSET(flags, MTTYF_CARRIER_CHANGED) ) { + dprintf(("%s%x: cd %s\n", mtty->ms_dev.dv_xname, port, mp->mp_carrier ? "on" : "off")); + (*linesw[tp->t_line].l_modem)(tp, mp->mp_carrier); + serviced = 1; + } - if( ISSET(flags, MTTYF_RING_OVERFLOW) ) { - log(LOG_WARNING, "%s%x: ring buffer overflow\n", mtty->ms_dev.dv_xname, port); - serviced = 1; - } + if( ISSET(flags, MTTYF_RING_OVERFLOW) ) { + log(LOG_WARNING, "%s%x: ring buffer overflow\n", mtty->ms_dev.dv_xname, port); + serviced = 1; + } - if( ISSET(flags, MTTYF_DONE) ) { - ndflush(&tp->t_outq, mp->mp_txp - tp->t_outq.c_cf); - CLR(tp->t_state, TS_BUSY); - (*linesw[tp->t_line].l_start)(tp); /* might be some more */ - serviced = 1; - } - } /* for(each mtty...) */ + if( ISSET(flags, MTTYF_DONE) ) { + ndflush(&tp->t_outq, mp->mp_txp - tp->t_outq.c_cf); + CLR(tp->t_state, TS_BUSY); + (*linesw[tp->t_line].l_start)(tp); /* might be some more */ + serviced = 1; + } + } /* for(each mtty...) */ + } /* * check the bpp ports (if any) to see what needs doing */ - if( mbpp ) for( port = 0 ; port < mbpp->ms_nports ; port++ ) { - struct mbpp_port *mp = &mbpp->ms_port[port]; + if( mbpp ) { + for( port = 0 ; port < mbpp->ms_nports ; port++ ) { + struct mbpp_port *mp = &mbpp->ms_port[port]; - if( !ISSET(mp->mp_flags, MBPPF_OPEN) ) continue; + if( !ISSET(mp->mp_flags, MBPPF_OPEN) ) continue; - s = splhigh(); - flags = mp->mp_flags; - CLR(mp->mp_flags, MBPPF_DONE); - splx(s); + s = splhigh(); /* block out hard intr routine */ + flags = mp->mp_flags; + CLR(mp->mp_flags, MBPPF_WAKEUP); + splx(s); - if( ISSET(flags, MBPPF_DONE) ) { - wakeup(mp); - serviced = 1; - } - - } /* for(each mbpp...) */ + if( ISSET(flags, MBPPF_WAKEUP) ) { + wakeup(mp); + serviced = 1; + } + } /* for(each mbpp...) */ + } return(serviced); } @@ -1355,6 +1370,11 @@ int s, opt; * mbppwrite write to mbpp * mbppioctl do ioctl on mbpp * mbppselect do select on mbpp + * mbpp_rw general rw routine + * mbpp_timeout rw timeout + * mbpp_start rw start after delay + * mbpp_send send data + * mbpp_recv recv data */ int @@ -1376,7 +1396,7 @@ void *args; struct magma_softc *sc = (struct magma_softc *)parent; struct mbpp_softc *ms = (struct mbpp_softc *)dev; struct mbpp_port *mp; -int port = 0; +int port; sc->ms_mbpp = ms; dprintf((" addr 0x%x", ms)); @@ -1388,17 +1408,6 @@ int port = 0; mp->mp_cd1190 = &sc->ms_cd1190[port]; else mp->mp_cd1400 = &sc->ms_cd1400[0]; - - mp->mp_txbuf = malloc(MBPP_TXBUF_SIZE, M_DEVBUF, M_NOWAIT); - if( mp->mp_txbuf == NULL ) break; - - /* - * default strobe and timeout settings - */ - mp->mp_read_strobe = 1000; /* 1 microsecond */ - mp->mp_read_timeout = 5 * hz; /* 5 seconds */ - mp->mp_write_strobe = 1000; /* 1 microsecond */ - mp->mp_write_timeout = 5 * hz; /* 5 seconds */ } ms->ms_nports = port; @@ -1419,7 +1428,7 @@ int card = MAGMA_CARD(dev); int port = MAGMA_PORT(dev); struct mbpp_softc *ms; struct mbpp_port *mp; -int error = 0, s; +int s; if( card >= mbpp_cd.cd_ndevs || (ms = mbpp_cd.cd_devs[card]) == NULL || port >= ms->ms_nports ) return(ENXIO); @@ -1434,22 +1443,27 @@ int error = 0, s; SET(mp->mp_flags, MBPPF_OPEN); splx(s); - if( mp->mp_cd1400 ) { /* CD1400 chip */ + /* set defaults */ + mp->mp_burst = BPP_BURST; + mp->mp_timeout = mbpp_mstohz(BPP_TIMEOUT); + mp->mp_delay = mbpp_mstohz(BPP_DELAY); + + /* init chips */ + if( mp->mp_cd1400 ) { /* CD1400 */ struct cd1400 *cd = mp->mp_cd1400; /* set up CD1400 channel */ s = spltty(); cd1400_write_reg(cd, CD1400_CAR, 0); cd1400_write_ccr(cd, CD1400_CCR_CMDRESET); - cd1400_write_reg(cd, CD1400_TBPR, (mp->mp_write_strobe * cd->cd_clock / 2000)); cd1400_write_reg(cd, CD1400_LIVR, (1<<3)); - cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN); splx(s); - } else { /* CD1190 chip */ - error = ENXIO; + } else { /* CD1190 */ + mp->mp_flags = 0; + return(ENXIO); } - return(error); + return(0); } /* @@ -1465,19 +1479,7 @@ struct proc *p; struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)]; struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; - if( mp->mp_cd1400 ) { - struct cd1400 *cd = mp->mp_cd1400; - int s; - - s = spltty(); - /* turn off the channel */ - cd1400_write_reg(cd, CD1400_CAR, 0); - cd1400_write_ccr(cd, CD1400_CCR_CMDRESET); - splx(s); - } - mp->mp_flags = 0; - return(0); } @@ -1490,7 +1492,7 @@ dev_t dev; struct uio *uio; int flags; { - return(ENODEV); + return( mbpp_rw(dev, uio) ); } /* @@ -1502,33 +1504,7 @@ dev_t dev; struct uio *uio; int flags; { -struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)]; -register struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; -int error = 0; -int s; - - while( uio->uio_resid ) { - mp->mp_txc = MIN(uio->uio_resid, MBPP_TXBUF_SIZE); - mp->mp_txp = mp->mp_txbuf; - - error = uiomove((caddr_t)mp->mp_txp, mp->mp_txc, uio); - if( error ) break; - - s = spltty(); - if( mp->mp_cd1400 ) - cd1400_enable_transmitter(mp->mp_cd1400, 0); - error = tsleep(mp, PCATCH | PZERO, "mbppwrite", mp->mp_write_timeout); - splx(s); - - if( error ) break; - } /* while(more to send...) */ - - if( error == EWOULDBLOCK ) { - log(LOG_INFO, "%s%d: write timeout\n", ms->ms_dev.dv_xname, MAGMA_PORT(dev)); - /* XXX check paper out, printer offline etc.. */ - } - - return(error); + return( mbpp_rw(dev, uio) ); } /* @@ -1542,8 +1518,42 @@ caddr_t data; int flags; struct proc *p; { - /* we want to be able to get & set strobe and timeout values */ - return(ENODEV); +struct mbpp_softc *ms = mbpp_cd.cd_devs[MAGMA_CARD(dev)]; +register struct mbpp_port *mp = &ms->ms_port[MAGMA_PORT(dev)]; +struct bpp_param *bp; +int error = 0; +int s; + + switch(cmd) { + case BPPIOCSPARAM: + bp = (struct bpp_param *)data; + if( bp->bp_burst < BPP_BURST_MIN || bp->bp_burst > BPP_BURST_MAX || + bp->bp_delay < BPP_DELAY_MIN || bp->bp_delay > BPP_DELAY_MIN ) { + error = EINVAL; + } else { + mp->mp_burst = bp->bp_burst; + mp->mp_timeout = mbpp_mstohz(bp->bp_timeout); + mp->mp_delay = mbpp_mstohz(bp->bp_delay); + } + break; + case BPPIOCGPARAM: + bp = (struct bpp_param *)data; + bp->bp_burst = mp->mp_burst; + bp->bp_timeout = mbpp_hztoms(mp->mp_timeout); + bp->bp_delay = mbpp_hztoms(mp->mp_delay); + break; + case BPPIOCGSTAT: + /* XXX make this more generic */ + s = spltty(); + cd1400_write_reg(mp->mp_cd1400, CD1400_CAR, 0); + *(int *)data = cd1400_read_reg(mp->mp_cd1400, CD1400_PSVR); + splx(s); + break; + default: + error = ENOTTY; + } + + return(error); } /* @@ -1558,4 +1568,263 @@ struct proc *p; return(ENODEV); } +int +mbpp_rw(dev, uio) +dev_t dev; +struct uio *uio; +{ +int card = MAGMA_CARD(dev); +int port = MAGMA_PORT(dev); +struct mbpp_softc *ms = mbpp_cd.cd_devs[card]; +register struct mbpp_port *mp = &ms->ms_port[port]; +caddr_t buffer, ptr; +int buflen, cnt, len; +int s, error = 0; +int gotdata = 0; + + if( uio->uio_resid == 0 ) + return(0); + + buflen = min(uio->uio_resid, mp->mp_burst); + buffer = malloc(buflen, M_DEVBUF, M_WAITOK); + if( buffer == NULL ) + return(ENOMEM); + + SET(mp->mp_flags, MBPPF_UIO); + + /* + * start timeout, if needed + */ + if( mp->mp_timeout > 0 ) { + SET(mp->mp_flags, MBPPF_TIMEOUT); + timeout(mbpp_timeout, mp, mp->mp_timeout); + } + + len = cnt = 0; + while( uio->uio_resid > 0 ) { + len = min(buflen, uio->uio_resid); + ptr = buffer; + + if( uio->uio_rw == UIO_WRITE ) { + error = uiomove(ptr, len, uio); + if( error ) break; + } +again: /* goto bad */ + /* timed out? */ + if( !ISSET(mp->mp_flags, MBPPF_UIO) ) + break; + + /* + * perform the operation + */ + if( uio->uio_rw == UIO_WRITE ) { + cnt = mbpp_send(mp, ptr, len); + } else { + cnt = mbpp_recv(mp, ptr, len); + } + + if( uio->uio_rw == UIO_READ ) { + if( cnt ) { + error = uiomove(ptr, cnt, uio); + if( error ) break; + gotdata++; + } + else if( gotdata ) /* consider us done */ + break; + } + + /* timed out? */ + if( !ISSET(mp->mp_flags, MBPPF_UIO) ) + break; + + /* + * poll delay? + */ + if( mp->mp_delay > 0 ) { + s = splsoftclock(); + SET(mp->mp_flags, MBPPF_DELAY); + timeout(mbpp_start, mp, mp->mp_delay); + error = tsleep(mp, PCATCH | PZERO, "mbppdelay", 0); + splx(s); + if( error ) break; + } + + /* + * don't call uiomove again until we used all the data we grabbed + */ + if( uio->uio_rw == UIO_WRITE && cnt != len ) { + ptr += cnt; + len -= cnt; + cnt = 0; + goto again; + } + } + + /* + * clear timeouts + */ + s = splsoftclock(); + if( ISSET(mp->mp_flags, MBPPF_TIMEOUT) ) { + untimeout(mbpp_timeout, mp); + CLR(mp->mp_flags, MBPPF_TIMEOUT); + } + if( ISSET(mp->mp_flags, MBPPF_DELAY) ) { + untimeout(mbpp_start, mp); + CLR(mp->mp_flags, MBPPF_DELAY); + } + splx(s); + + /* + * adjust for those chars that we uiomoved but never actually wrote + */ + if( uio->uio_rw == UIO_WRITE && cnt != len ) { + uio->uio_resid += (len - cnt); + } + + free(buffer, M_DEVBUF); + return(error); +} + +void +mbpp_timeout(arg) +void *arg; +{ +struct mbpp_port *mp = arg; + + CLR(mp->mp_flags, MBPPF_UIO | MBPPF_TIMEOUT); + wakeup(mp); +} + +void +mbpp_start(arg) +void *arg; +{ +struct mbpp_port *mp = arg; + + CLR(mp->mp_flags, MBPPF_DELAY); + wakeup(mp); +} + +int +mbpp_send(mp, ptr, len) +struct mbpp_port *mp; +caddr_t ptr; +int len; +{ +int s; +struct cd1400 *cd = mp->mp_cd1400; + + /* set up io information */ + mp->mp_ptr = ptr; + mp->mp_cnt = len; + + /* start transmitting */ + s = spltty(); + if( cd ) { + cd1400_write_reg(cd, CD1400_CAR, 0); + + /* output strobe width ~1microsecond */ + cd1400_write_reg(cd, CD1400_TBPR, 10); + + /* enable channel */ + cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN); + cd1400_write_reg(cd, CD1400_SRER, CD1400_SRER_TXRDY); + } + + /* ZZzzz... */ + tsleep(mp, PCATCH | PZERO, "mbpp_send", 0); + + /* stop transmitting */ + if( cd ) { + cd1400_write_reg(cd, CD1400_CAR, 0); + + /* disable transmitter */ + cd1400_write_reg(cd, CD1400_SRER, 0); + cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTDIS); + + /* flush fifo */ + cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); + } + splx(s); + + /* return number of chars sent */ + return(len - mp->mp_cnt); +} + +int +mbpp_recv(mp, ptr, len) +struct mbpp_port *mp; +caddr_t ptr; +int len; +{ +int s; +struct cd1400 *cd = mp->mp_cd1400; + + /* set up io information */ + mp->mp_ptr = ptr; + mp->mp_cnt = len; + + /* start receiving */ + s = spltty(); + if( cd ) { + int rcor, rbpr; + + cd1400_write_reg(cd, CD1400_CAR, 0); + + /* input strobe at 100kbaud (10microseconds) */ + cd1400_compute_baud(100000, cd->cd_clock, &rcor, &rbpr); + cd1400_write_reg(cd, CD1400_RCOR, rcor); + cd1400_write_reg(cd, CD1400_RBPR, rbpr); + + /* rx threshold */ + cd1400_write_reg(cd, CD1400_COR3, MBPP_RX_FIFO_THRESHOLD); + cd1400_write_ccr(cd, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); + + /* enable channel */ + cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_RCVEN); + cd1400_write_reg(cd, CD1400_SRER, CD1400_SRER_RXDATA); + } + + /* ZZzzz... */ + tsleep(mp, PCATCH | PZERO, "mbpp_recv", 0); + + /* stop receiving */ + if( cd ) { + cd1400_write_reg(cd, CD1400_CAR, 0); + + /* disable receiving */ + cd1400_write_reg(cd, CD1400_SRER, 0); + cd1400_write_ccr(cd, CD1400_CCR_CMDCHANCTL | CD1400_CCR_RCVDIS); + } + splx(s); + + /* return number of chars received */ + return(len - mp->mp_cnt); +} + +int +mbpp_hztoms(h) +int h; +{ +int m = h; + + if( m > 0 ) + m = m * 1000 / hz; + return(m); +} + +int +mbpp_mstohz(m) +int m; +{ +int h = m; + + if( h > 0 ) { + h = h * hz / 1000; + if( h == 0 ) + h = 1000 / hz; + } + return(h); +} + #endif /* NMAGMA */ diff --git a/sys/arch/sparc/dev/magmareg.h b/sys/arch/sparc/dev/magmareg.h index 97857dd5a7a..94d9d0a6ecb 100644 --- a/sys/arch/sparc/dev/magmareg.h +++ b/sys/arch/sparc/dev/magmareg.h @@ -158,7 +158,7 @@ struct mtty_softc { struct mtty_port ms_port[MAGMA_MAX_TTY]; }; -#define MBPP_TXBUF_SIZE (CD1400_PAR_FIFO_SIZE * 10) +#define MBPP_RX_FIFO_THRESHOLD 25 struct mbpp_port { struct cd1400 *mp_cd1400; /* for LC2+1Sp card */ @@ -166,19 +166,20 @@ struct mbpp_port { int mp_flags; - int mp_read_strobe; /* strobe width in ns */ - int mp_read_timeout; /* timeout after this many seconds */ + struct bpp_param mp_param; +#define mp_burst mp_param.bp_burst +#define mp_timeout mp_param.bp_timeout +#define mp_delay mp_param.bp_delay - int mp_write_strobe; /* strobe width in ns */ - int mp_write_timeout; /* timeout after this many seconds */ - - u_char *mp_txbuf; /* transmit buffer */ - u_char *mp_txp; /* transmit pointer */ - int mp_txc; /* transmit counter */ + u_char *mp_ptr; /* pointer to io data */ + int mp_cnt; /* count of io chars */ }; #define MBPPF_OPEN (1<<0) -#define MBPPF_DONE (1<<1) +#define MBPPF_TIMEOUT (1<<1) +#define MBPPF_UIO (1<<2) +#define MBPPF_DELAY (1<<3) +#define MBPPF_WAKEUP (1<<4) struct mbpp_softc { struct device ms_dev; /* device info */ @@ -192,7 +193,6 @@ struct mbpp_softc { #define SET(t, f) ((t) |= (f)) #define CLR(t, f) ((t) &= ~(f)) #define ISSET(t, f) ((t) & (f)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) /* internal function prototypes */ @@ -215,3 +215,10 @@ void mtty_start __P((struct tty *)); int mbpp_match __P((struct device *, void *, void *)); void mbpp_attach __P((struct device *, struct device *, void *)); +int mbpp_rw __P((dev_t, struct uio *)); +void mbpp_timeout __P((void *)); +void mbpp_start __P((void *)); +int mbpp_send __P((struct mbpp_port *, caddr_t, int)); +int mbpp_recv __P((struct mbpp_port *, caddr_t, int)); +int mbpp_hztoms __P((int)); +int mbpp_mstohz __P((int)); |