summaryrefslogtreecommitdiff
path: root/sys/arch/sparc
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1998-06-02 06:37:19 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1998-06-02 06:37:19 +0000
commit6e99aec8788fbc4a0478d9ceca57920aa2d7bcda (patch)
tree516614624d8aab2efb4144f814b7f8630f53dd31 /sys/arch/sparc
parente22665b32da4d75dad6c333e4554a61ed517d84f (diff)
newer fixes from plunky@skate.demon.co.uk
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r--sys/arch/sparc/dev/bppioctl.h61
-rw-r--r--sys/arch/sparc/dev/magma.c537
-rw-r--r--sys/arch/sparc/dev/magmareg.h29
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));