summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorchopps <chopps@NetBSD.org>2000-01-04 06:36:29 +0000
committerchopps <chopps@NetBSD.org>2000-01-04 06:36:29 +0000
commitd8a4f43d0fe2900aef1913e50664e5d0361d53b4 (patch)
treec296370fa1ecad5ca3fbc50dfcac6986d074d191 /sys
parenta4d9bd94846762413002c014699fd645a5ba8b19 (diff)
convert to support non-dma IO (for the isa Riscom/N2).
allow the user to set and use the internal baud rate generator fix the transmission ring logic to support more than 1 frame per interrupt add autodetection of the base clock frequency. cleanup the receive ring logic support dynamically resizing the low-water mark on the fifo in response to buffer underruns on transmit.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/hd64570.c1336
-rw-r--r--sys/dev/ic/hd64570reg.h209
-rw-r--r--sys/dev/ic/hd64570var.h145
3 files changed, 1103 insertions, 587 deletions
diff --git a/sys/dev/ic/hd64570.c b/sys/dev/ic/hd64570.c
index 9d945197813..db77e83fd73 100644
--- a/sys/dev/ic/hd64570.c
+++ b/sys/dev/ic/hd64570.c
@@ -1,6 +1,7 @@
-/* $NetBSD: hd64570.c,v 1.7 1999/10/23 22:20:11 erh Exp $ */
+/* $NetBSD: hd64570.c,v 1.8 2000/01/04 06:36:29 chopps Exp $ */
/*
+ * Copyright (c) 1999 Christian E. Hopps
* Copyright (c) 1998 Vixie Enterprises
* All rights reserved.
*
@@ -37,34 +38,6 @@
*/
/*
- * hd64570:
- * From the hitachi docs:
- * The HD64570 serial communications adaptor (SCA) peripheral chip enables
- * a host microprocessor to perform asynchronous, byte-synchronous, or
- * bit-synchronous serial communication. Its two full-duplex,
- * multiprotocol serial channels support a wide variety of protocols,
- * including frame relay, LAPB, LAPD, bisync and DDCMP. Its build-in
- * direct memory access controller (DMAC) is equipped with a 32-stage
- * FIFO and can execure chained-block transfers. Due to its DMAC and
- * 16-bit bus interface, the SCA supports serial data transfer rates up
- * to 12 Mbits/s without monopolizing the bus, even in full-duplex
- * communication. Other on-chip features of the SCA, including four
- * types of MPU interfaces, a bus arbiter, timers, and an interrupt
- * controller, provide added functionality in a wide range of
- * applications, such as frame relay exchanges/system multiplexes, private
- * branch exchanges, computer networks, workstations, ISDN terminals,
- * and facsimile.
- *
- * For more info: http://semiconductor.hitachi.com
- * ----
- *
- * This driver not only talks to the HD64570 chip, but also implements
- * a version of the HDLC protocol that includes the CISCO keepalive
- * protocol. It publishes itself as a network interface that can
- * handle IP traffic only.
- */
-
-/*
* TODO:
*
* o teach the receive logic about errors, and about long frames that
@@ -85,6 +58,10 @@
* a single descriptor.
* o use bus_dmamap_sync() with the right offset and lengths, rather
* than cheating and always sync'ing the whole region.
+ *
+ * o perhaps allow rx and tx to be in more than one page
+ * if not using dma. currently the assumption is that
+ * rx uses a page and tx uses a page.
*/
#include "bpfilter.h"
@@ -128,9 +105,10 @@
#define SCA_DEBUG_RXPKT 0x0010
#define SCA_DEBUG_TXPKT 0x0020
#define SCA_DEBUG_INTR 0x0040
+#define SCA_DEBUG_CLOCK 0x0080
#if 0
-#define SCA_DEBUG_LEVEL ( SCA_DEBUG_TX )
+#define SCA_DEBUG_LEVEL ( 0xFFFF )
#else
#define SCA_DEBUG_LEVEL 0
#endif
@@ -146,37 +124,10 @@ u_int32_t sca_debug = SCA_DEBUG_LEVEL;
#define SCA_DPRINTF(l, x)
#endif
-#define SCA_MTU 1500 /* hard coded */
-
-/*
- * buffers per tx and rx channels, per port, and the size of each.
- * Don't use these constants directly, as they are really only hints.
- * Use the calculated values stored in struct sca_softc instead.
- *
- * Each must be at least 2, receive would be better at around 20 or so.
- *
- * XXX Due to a damned near impossible to track down bug, transmit buffers
- * MUST be 2, no more, no less.
- */
-#ifndef SCA_NtxBUFS
-#define SCA_NtxBUFS 2
-#endif
-#ifndef SCA_NrxBUFS
-#define SCA_NrxBUFS 20
-#endif
-#ifndef SCA_BSIZE
-#define SCA_BSIZE (SCA_MTU + 4) /* room for HDLC as well */
-#endif
-
#if 0
#define SCA_USE_FASTQ /* use a split queue, one for fast traffic */
#endif
-static inline void sca_write_1(struct sca_softc *, u_int, u_int8_t);
-static inline void sca_write_2(struct sca_softc *, u_int, u_int16_t);
-static inline u_int8_t sca_read_1(struct sca_softc *, u_int);
-static inline u_int16_t sca_read_2(struct sca_softc *, u_int);
-
static inline void msci_write_1(sca_port_t *, u_int, u_int8_t);
static inline u_int8_t msci_read_1(sca_port_t *, u_int);
@@ -185,19 +136,17 @@ static inline void dmac_write_2(sca_port_t *, u_int, u_int16_t);
static inline u_int8_t dmac_read_1(sca_port_t *, u_int);
static inline u_int16_t dmac_read_2(sca_port_t *, u_int);
-static int sca_alloc_dma(struct sca_softc *);
-static void sca_setup_dma_memory(struct sca_softc *);
static void sca_msci_init(struct sca_softc *, sca_port_t *);
static void sca_dmac_init(struct sca_softc *, sca_port_t *);
static void sca_dmac_rxinit(sca_port_t *);
static int sca_dmac_intr(sca_port_t *, u_int8_t);
-static int sca_msci_intr(struct sca_softc *, u_int8_t);
+static int sca_msci_intr(sca_port_t *, u_int8_t);
static void sca_get_packets(sca_port_t *);
-static void sca_frame_process(sca_port_t *, sca_desc_t *, u_int8_t *);
-static int sca_frame_avail(sca_port_t *, int *);
-static void sca_frame_skip(sca_port_t *, int);
+static int sca_frame_avail(sca_port_t *);
+static void sca_frame_process(sca_port_t *);
+static void sca_frame_read_done(sca_port_t *);
static void sca_port_starttx(sca_port_t *);
@@ -210,35 +159,19 @@ static int sca_ioctl __P((struct ifnet *, u_long, caddr_t));
static void sca_start __P((struct ifnet *));
static void sca_watchdog __P((struct ifnet *));
-static struct mbuf *sca_mbuf_alloc(caddr_t, u_int);
+static struct mbuf *sca_mbuf_alloc(struct sca_softc *, caddr_t, u_int);
#if SCA_DEBUG_LEVEL > 0
static void sca_frame_print(sca_port_t *, sca_desc_t *, u_int8_t *);
#endif
-static inline void
-sca_write_1(struct sca_softc *sc, u_int reg, u_int8_t val)
-{
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, SCADDR(reg), val);
-}
-static inline void
-sca_write_2(struct sca_softc *sc, u_int reg, u_int16_t val)
-{
- bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCADDR(reg), val);
-}
+#define sca_read_1(sc, reg) (sc)->sc_read_1(sc, reg)
+#define sca_read_2(sc, reg) (sc)->sc_read_2(sc, reg)
+#define sca_write_1(sc, reg, val) (sc)->sc_write_1(sc, reg, val)
+#define sca_write_2(sc, reg, val) (sc)->sc_write_2(sc, reg, val)
-static inline u_int8_t
-sca_read_1(struct sca_softc *sc, u_int reg)
-{
- return bus_space_read_1(sc->sc_iot, sc->sc_ioh, SCADDR(reg));
-}
-
-static inline u_int16_t
-sca_read_2(struct sca_softc *sc, u_int reg)
-{
- return bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCADDR(reg));
-}
+#define sca_page_addr(sc, addr) ((bus_addr_t)(addr) & (sc)->scu_pagemask)
static inline void
msci_write_1(sca_port_t *scp, u_int reg, u_int8_t val)
@@ -276,26 +209,131 @@ dmac_read_2(sca_port_t *scp, u_int reg)
return sca_read_2(scp->sca, scp->dmac_off + reg);
}
-int
-sca_init(struct sca_softc *sc, u_int nports)
+/*
+ * read the chain pointer
+ */
+static inline u_int16_t
+sca_desc_read_chainp(struct sca_softc *sc, struct sca_desc *dp)
{
- /*
- * Do a little sanity check: check number of ports.
- */
- if (nports < 1 || nports > 2)
- return 1;
+ if (sc->sc_usedma)
+ return ((dp)->sd_chainp);
+ return (bus_space_read_2(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp) + offsetof(struct sca_desc, sd_chainp)));
+}
- /*
- * remember the details
- */
- sc->sc_numports = nports;
+/*
+ * write the chain pointer
+ */
+static inline void
+sca_desc_write_chainp(struct sca_softc *sc, struct sca_desc *dp, u_int16_t cp)
+{
+ if (sc->sc_usedma)
+ (dp)->sd_chainp = cp;
+ else
+ bus_space_write_2(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp)
+ + offsetof(struct sca_desc, sd_chainp), cp);
+}
+/*
+ * read the buffer pointer
+ */
+static inline u_int32_t
+sca_desc_read_bufp(struct sca_softc *sc, struct sca_desc *dp)
+{
+ u_int32_t address;
+
+ if (sc->sc_usedma)
+ address = dp->sd_bufp | dp->sd_hbufp << 16;
+ else {
+ address = bus_space_read_2(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp) + offsetof(struct sca_desc, sd_bufp));
+ address |= bus_space_read_1(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp)
+ + offsetof(struct sca_desc, sd_hbufp)) << 16;
+ }
+ return (address);
+}
+
+/*
+ * write the buffer pointer
+ */
+static inline void
+sca_desc_write_bufp(struct sca_softc *sc, struct sca_desc *dp, u_int32_t bufp)
+{
+ if (sc->sc_usedma) {
+ dp->sd_bufp = bufp & 0xFFFF;
+ dp->sd_hbufp = (bufp & 0x00FF0000) >> 16;
+ } else {
+ bus_space_write_2(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp) + offsetof(struct sca_desc, sd_bufp),
+ bufp & 0xFFFF);
+ bus_space_write_1(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp) + offsetof(struct sca_desc, sd_hbufp),
+ (bufp & 0x00FF0000) >> 16);
+ }
+}
+
+/*
+ * read the buffer length
+ */
+static inline u_int16_t
+sca_desc_read_buflen(struct sca_softc *sc, struct sca_desc *dp)
+{
+ if (sc->sc_usedma)
+ return ((dp)->sd_buflen);
+ return (bus_space_read_2(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp) + offsetof(struct sca_desc, sd_buflen)));
+}
+
+/*
+ * write the buffer length
+ */
+static inline void
+sca_desc_write_buflen(struct sca_softc *sc, struct sca_desc *dp, u_int16_t len)
+{
+ if (sc->sc_usedma)
+ (dp)->sd_buflen = len;
+ else
+ bus_space_write_2(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp)
+ + offsetof(struct sca_desc, sd_buflen), len);
+}
+
+/*
+ * read the descriptor status
+ */
+static inline u_int8_t
+sca_desc_read_stat(struct sca_softc *sc, struct sca_desc *dp)
+{
+ if (sc->sc_usedma)
+ return ((dp)->sd_stat);
+ return (bus_space_read_1(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp) + offsetof(struct sca_desc, sd_stat)));
+}
+
+/*
+ * write the descriptor status
+ */
+static inline void
+sca_desc_write_stat(struct sca_softc *sc, struct sca_desc *dp, u_int8_t stat)
+{
+ if (sc->sc_usedma)
+ (dp)->sd_stat = stat;
+ else
+ bus_space_write_1(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, dp) + offsetof(struct sca_desc, sd_stat),
+ stat);
+}
+
+void
+sca_init(struct sca_softc *sc)
+{
/*
- * allocate the memory and chop it into bits.
+ * Do a little sanity check: check number of ports.
*/
- if (sca_alloc_dma(sc) != 0)
- return 1;
- sca_setup_dma_memory(sc);
+ if (sc->sc_numports < 1 || sc->sc_numports > 2)
+ panic("sca can\'t handle more than 2 or less than 1 ports");
/*
* disable DMA and MSCI interrupts
@@ -308,9 +346,13 @@ sca_init(struct sca_softc *sc, u_int nports)
/*
* configure interrupt system
*/
- sca_write_1(sc, SCA_ITCR, 0); /* use ivr, no int ack */
+ sca_write_1(sc, SCA_ITCR,
+ SCA_ITCR_INTR_PRI_MSCI | SCA_ITCR_ACK_NONE | SCA_ITCR_VOUT_IVR);
+#if 0
+ /* these are for the intrerrupt ack cycle which we don't use */
sca_write_1(sc, SCA_IVR, 0x40);
sca_write_1(sc, SCA_IMVR, 0x40);
+#endif
/*
* set wait control register to zero wait states
@@ -347,7 +389,6 @@ sca_init(struct sca_softc *sc, u_int nports)
* Should check to see if the chip is responding, but for now
* assume it is.
*/
- return 0;
}
/*
@@ -367,15 +408,15 @@ sca_port_attach(struct sca_softc *sc, u_int port)
if (port == 0) {
scp->msci_off = SCA_MSCI_OFF_0;
scp->dmac_off = SCA_DMAC_OFF_0;
- if(sc->parent != NULL)
- ntwo_unit=sc->parent->dv_unit * 2 + 0;
+ if(sc->sc_parent != NULL)
+ ntwo_unit=sc->sc_parent->dv_unit * 2 + 0;
else
ntwo_unit = 0; /* XXX */
} else {
scp->msci_off = SCA_MSCI_OFF_1;
scp->dmac_off = SCA_DMAC_OFF_1;
- if(sc->parent != NULL)
- ntwo_unit=sc->parent->dv_unit * 2 + 1;
+ if(sc->sc_parent != NULL)
+ ntwo_unit=sc->sc_parent->dv_unit * 2 + 1;
else
ntwo_unit = 1; /* XXX */
}
@@ -407,11 +448,11 @@ sca_port_attach(struct sca_softc *sc, u_int port)
bpfattach(&scp->sp_bpf, ifp, DLT_HDLC, HDLC_HDRLEN);
#endif
- if (sc->parent == NULL)
+ if (sc->sc_parent == NULL)
printf("%s: port %d\n", ifp->if_xname, port);
else
printf("%s at %s port %d\n",
- ifp->if_xname, sc->parent->dv_xname, port);
+ ifp->if_xname, sc->sc_parent->dv_xname, port);
/*
* reset the last seen times on the cisco keepalive protocol
@@ -420,45 +461,120 @@ sca_port_attach(struct sca_softc *sc, u_int port)
scp->cka_lastrx = 0;
}
+#if 0
+/*
+ * returns log2(div), sets 'tmc' for the required freq 'hz'
+ */
+static u_int8_t
+sca_msci_get_baud_rate_values(u_int32_t hz, u_int8_t *tmcp)
+{
+ u_int32_t tmc, div;
+ u_int32_t clock;
+
+ /* clock hz = (chipclock / tmc) / 2^(div); */
+ /*
+ * TD == tmc * 2^(n)
+ *
+ * note:
+ * 1 <= TD <= 256 TD is inc of 1
+ * 2 <= TD <= 512 TD is inc of 2
+ * 4 <= TD <= 1024 TD is inc of 4
+ * ...
+ * 512 <= TD <= 256*512 TD is inc of 512
+ *
+ * so note there are overlaps. We lose prec
+ * as div increases so we wish to minize div.
+ *
+ * basically we want to do
+ *
+ * tmc = chip / hz, but have tmc <= 256
+ */
+
+ /* assume system clock is 9.8304Mhz or 9830400hz */
+ clock = clock = 9830400 >> 1;
+
+ /* round down */
+ div = 0;
+ while ((tmc = clock / hz) > 256 || (tmc == 256 && (clock / tmc) > hz)) {
+ clock >>= 1;
+ div++;
+ }
+ if (clock / tmc > hz)
+ tmc++;
+ if (!tmc)
+ tmc = 1;
+
+ if (div > SCA_RXS_DIV_512) {
+ /* set to maximums */
+ div = SCA_RXS_DIV_512;
+ tmc = 0;
+ }
+
+ *tmcp = (tmc & 0xFF); /* 0 == 256 */
+ return (div & 0xFF);
+}
+#endif
+
/*
* initialize the port's MSCI
*/
static void
sca_msci_init(struct sca_softc *sc, sca_port_t *scp)
{
+ /* reset the channel */
msci_write_1(scp, SCA_CMD0, SCA_CMD_RESET);
+
msci_write_1(scp, SCA_MD00,
( SCA_MD0_CRC_1
| SCA_MD0_CRC_CCITT
| SCA_MD0_CRC_ENABLE
| SCA_MD0_MODE_HDLC));
+#if 0
+ /* immediately send receive reset so the above takes */
+ msci_write_1(scp, SCA_CMD0, SCA_CMD_RXRESET);
+#endif
+
msci_write_1(scp, SCA_MD10, SCA_MD1_NOADDRCHK);
msci_write_1(scp, SCA_MD20,
- (SCA_MD2_DUPLEX | SCA_MD2_NRZ));
+ (SCA_MD2_DUPLEX | SCA_MD2_ADPLLx8 | SCA_MD2_NRZ));
- /*
- * reset the port (and lower RTS)
- */
+ /* be safe and do it again */
msci_write_1(scp, SCA_CMD0, SCA_CMD_RXRESET);
+
+ /* setup underrun and idle control, and initial RTS state */
msci_write_1(scp, SCA_CTL0,
- (SCA_CTL_IDLPAT | SCA_CTL_UDRNC | SCA_CTL_RTS));
+ (SCA_CTL_IDLC_PATTERN
+ | SCA_CTL_UDRNC_AFTER_FCS
+ | SCA_CTL_RTS_LOW));
+
+ /* reset the transmitter */
msci_write_1(scp, SCA_CMD0, SCA_CMD_TXRESET);
/*
- * select the RX clock as the TX clock, and set for external
- * clock source.
+ * set the clock sources
*/
- msci_write_1(scp, SCA_RXS0, 0);
- msci_write_1(scp, SCA_TXS0, 0);
+ msci_write_1(scp, SCA_RXS0, scp->sp_rxs);
+ msci_write_1(scp, SCA_TXS0, scp->sp_txs);
+ msci_write_1(scp, SCA_TMC0, scp->sp_tmc);
+
+ /* set external clock generate as requested */
+ sc->sc_clock_callback(sc->sc_aux, scp->sp_port, scp->sp_eclock);
/*
* XXX don't pay attention to CTS or CD changes right now. I can't
* simulate one, and the transmitter will try to transmit even if
* CD isn't there anyway, so nothing bad SHOULD happen.
*/
+#if 0
msci_write_1(scp, SCA_IE00, 0);
msci_write_1(scp, SCA_IE10, 0); /* 0x0c == CD and CTS changes only */
+#else
+ /* this would deliver transmitter underrun to ST1/ISR1 */
+ msci_write_1(scp, SCA_IE10, SCA_ST1_UDRN);
+ msci_write_1(scp, SCA_IE00, SCA_ST0_TXINT);
+#endif
msci_write_1(scp, SCA_IE20, 0);
+
msci_write_1(scp, SCA_FIE0, 0);
msci_write_1(scp, SCA_SA00, 0);
@@ -467,7 +583,22 @@ sca_msci_init(struct sca_softc *sc, sca_port_t *scp)
msci_write_1(scp, SCA_IDL0, 0x7e);
msci_write_1(scp, SCA_RRC0, 0x0e);
- msci_write_1(scp, SCA_TRC00, 0x10);
+ /* msci_write_1(scp, SCA_TRC00, 0x10); */
+ /*
+ * the correct values here are important for avoiding underruns
+ * for any value less than or equal to TRC0 txrdy is activated
+ * which will start the dmac transfer to the fifo.
+ * for buffer size >= TRC1 + 1 txrdy is cleared which will stop dma.
+ *
+ * thus if we are using a very fast clock that empties the fifo
+ * quickly, delays in the dmac starting to fill the fifo can
+ * lead to underruns so we want a fairly full fifo to still
+ * cause the dmac to start. for cards with on board ram this
+ * has no effect on system performance. For cards that dma
+ * to/from system memory it will cause more, shorter,
+ * bus accesses rather than fewer longer ones.
+ */
+ msci_write_1(scp, SCA_TRC00, 0x00);
msci_write_1(scp, SCA_TRC10, 0x1f);
}
@@ -484,26 +615,43 @@ sca_dmac_init(struct sca_softc *sc, sca_port_t *scp)
u_int32_t buf_p;
int i;
- bus_dmamap_sync(sc->sc_dmat, sc->sc_dmam,
- 0, sc->sc_allocsize, BUS_DMASYNC_PREWRITE);
+ if (sc->sc_usedma)
+ bus_dmamap_sync(sc->scu_dmat, sc->scu_dmam, 0, sc->scu_allocsize,
+ BUS_DMASYNC_PREWRITE);
+ else {
+ /*
+ * XXX assumes that all tx desc and bufs in same page
+ */
+ sc->scu_page_on(sc);
+ sc->scu_set_page(sc, scp->sp_txdesc_p);
+ }
- desc = scp->txdesc;
- desc_p = scp->txdesc_p;
- buf_p = scp->txbuf_p;
- scp->txcur = 0;
- scp->txinuse = 0;
+ desc = scp->sp_txdesc;
+ desc_p = scp->sp_txdesc_p;
+ buf_p = scp->sp_txbuf_p;
+ scp->sp_txcur = 0;
+ scp->sp_txinuse = 0;
+
+#ifdef DEBUG
+ /* make sure that we won't wrap */
+ if ((desc_p & 0xffff0000) !=
+ ((desc_p + sizeof(*desc) * scp->sp_ntxdesc) & 0xffff0000))
+ panic("sca: tx descriptors cross architecural boundry");
+ if ((buf_p & 0xff000000) !=
+ ((buf_p + SCA_BSIZE * scp->sp_ntxdesc) & 0xff000000))
+ panic("sca: tx buffers cross architecural boundry");
+#endif
- for (i = 0 ; i < SCA_NtxBUFS ; i++) {
+ for (i = 0 ; i < scp->sp_ntxdesc ; i++) {
/*
* desc_p points to the physcial address of the NEXT desc
*/
desc_p += sizeof(sca_desc_t);
- desc->cp = desc_p & 0x0000ffff;
- desc->bp = buf_p & 0x0000ffff;
- desc->bpb = (buf_p & 0x00ff0000) >> 16;
- desc->len = SCA_BSIZE;
- desc->stat = 0;
+ sca_desc_write_chainp(sc, desc, desc_p & 0x0000ffff);
+ sca_desc_write_bufp(sc, desc, buf_p);
+ sca_desc_write_buflen(sc, desc, SCA_BSIZE);
+ sca_desc_write_stat(sc, desc, 0);
desc++; /* point to the next descriptor */
buf_p += SCA_BSIZE;
@@ -513,8 +661,7 @@ sca_dmac_init(struct sca_softc *sc, sca_port_t *scp)
* "heal" the circular list by making the last entry point to the
* first.
*/
- desc--;
- desc->cp = scp->txdesc_p & 0x0000ffff;
+ sca_desc_write_chainp(sc, desc - 1, scp->sp_txdesc_p & 0x0000ffff);
/*
* Now, initialize the transmit DMA logic
@@ -524,31 +671,48 @@ sca_dmac_init(struct sca_softc *sc, sca_port_t *scp)
dmac_write_1(scp, SCA_DSR1, 0);
dmac_write_1(scp, SCA_DCR1, SCA_DCR_ABRT);
dmac_write_1(scp, SCA_DMR1, SCA_DMR_TMOD | SCA_DMR_NF);
+ /* XXX1
dmac_write_1(scp, SCA_DIR1,
(SCA_DIR_EOT | SCA_DIR_BOF | SCA_DIR_COF));
+ */
+ dmac_write_1(scp, SCA_DIR1,
+ (SCA_DIR_EOM | SCA_DIR_EOT | SCA_DIR_BOF | SCA_DIR_COF));
dmac_write_1(scp, SCA_CPB1,
- (u_int8_t)((scp->txdesc_p & 0x00ff0000) >> 16));
+ (u_int8_t)((scp->sp_txdesc_p & 0x00ff0000) >> 16));
/*
* now, do the same thing for receive descriptors
+ *
+ * XXX assumes that all rx desc and bufs in same page
*/
- desc = scp->rxdesc;
- desc_p = scp->rxdesc_p;
- buf_p = scp->rxbuf_p;
- scp->rxstart = 0;
- scp->rxend = SCA_NrxBUFS - 1;
+ if (!sc->sc_usedma)
+ sc->scu_set_page(sc, scp->sp_rxdesc_p);
+
+ desc = scp->sp_rxdesc;
+ desc_p = scp->sp_rxdesc_p;
+ buf_p = scp->sp_rxbuf_p;
+
+#ifdef DEBUG
+ /* make sure that we won't wrap */
+ if ((desc_p & 0xffff0000) !=
+ ((desc_p + sizeof(*desc) * scp->sp_nrxdesc) & 0xffff0000))
+ panic("sca: rx descriptors cross architecural boundry");
+ if ((buf_p & 0xff000000) !=
+ ((buf_p + SCA_BSIZE * scp->sp_nrxdesc) & 0xff000000))
+ panic("sca: rx buffers cross architecural boundry");
+#endif
- for (i = 0 ; i < SCA_NrxBUFS ; i++) {
+ for (i = 0 ; i < scp->sp_nrxdesc; i++) {
/*
* desc_p points to the physcial address of the NEXT desc
*/
desc_p += sizeof(sca_desc_t);
- desc->cp = desc_p & 0x0000ffff;
- desc->bp = buf_p & 0x0000ffff;
- desc->bpb = (buf_p & 0x00ff0000) >> 16;
- desc->len = SCA_BSIZE;
- desc->stat = 0x00;
+ sca_desc_write_chainp(sc, desc, desc_p & 0x0000ffff);
+ sca_desc_write_bufp(sc, desc, buf_p);
+ /* sca_desc_write_buflen(sc, desc, SCA_BSIZE); */
+ sca_desc_write_buflen(sc, desc, 0);
+ sca_desc_write_stat(sc, desc, 0);
desc++; /* point to the next descriptor */
buf_p += SCA_BSIZE;
@@ -558,13 +722,15 @@ sca_dmac_init(struct sca_softc *sc, sca_port_t *scp)
* "heal" the circular list by making the last entry point to the
* first.
*/
- desc--;
- desc->cp = scp->rxdesc_p & 0x0000ffff;
+ sca_desc_write_chainp(sc, desc - 1, scp->sp_rxdesc_p & 0x0000ffff);
sca_dmac_rxinit(scp);
- bus_dmamap_sync(sc->sc_dmat, sc->sc_dmam,
- 0, sc->sc_allocsize, BUS_DMASYNC_POSTWRITE);
+ if (sc->sc_usedma)
+ bus_dmamap_sync(sc->scu_dmat, sc->scu_dmam,
+ 0, sc->scu_allocsize, BUS_DMASYNC_POSTWRITE);
+ else
+ sc->scu_page_off(sc);
}
/*
@@ -582,18 +748,22 @@ sca_dmac_rxinit(sca_port_t *scp)
dmac_write_1(scp, SCA_DMR0, SCA_DMR_TMOD | SCA_DMR_NF);
dmac_write_2(scp, SCA_BFLL0, SCA_BSIZE);
+ /* reset descriptors to initial state */
+ scp->sp_rxstart = 0;
+ scp->sp_rxend = scp->sp_nrxdesc - 1;
+
/*
* CPB == chain pointer base
* CDA == current descriptor address
* EDA == error descriptor address (overwrite position)
+ * because cda can't be eda when starting we always
+ * have a single buffer gap between cda and eda
*/
dmac_write_1(scp, SCA_CPB0,
- (u_int8_t)((scp->rxdesc_p & 0x00ff0000) >> 16));
- dmac_write_2(scp, SCA_CDAL0,
- (u_int16_t)(scp->rxdesc_p & 0xffff));
- dmac_write_2(scp, SCA_EDAL0,
- (u_int16_t)(scp->rxdesc_p
- + sizeof(sca_desc_t) * SCA_NrxBUFS));
+ (u_int8_t)((scp->sp_rxdesc_p & 0x00ff0000) >> 16));
+ dmac_write_2(scp, SCA_CDAL0, (u_int16_t)(scp->sp_rxdesc_p & 0xffff));
+ dmac_write_2(scp, SCA_EDAL0, (u_int16_t)
+ (scp->sp_rxdesc_p + (sizeof(sca_desc_t) * scp->sp_rxend)));
/*
* enable receiver DMA
@@ -603,173 +773,6 @@ sca_dmac_rxinit(sca_port_t *scp)
dmac_write_1(scp, SCA_DSR0, SCA_DSR_DE);
}
-static int
-sca_alloc_dma(struct sca_softc *sc)
-{
- u_int allocsize;
- int err;
- int rsegs;
- u_int bpp;
-
- SCA_DPRINTF(SCA_DEBUG_DMA,
- ("sizeof sca_desc_t: %d bytes\n", sizeof (sca_desc_t)));
-
- bpp = sc->sc_numports * (SCA_NtxBUFS + SCA_NrxBUFS);
-
- allocsize = bpp * (SCA_BSIZE + sizeof (sca_desc_t));
-
- /*
- * sanity checks:
- *
- * Check the total size of the data buffers, and so on. The total
- * DMAable space needs to fit within a single 16M region, and the
- * descriptors need to fit within a 64K region.
- */
- if (allocsize > 16 * 1024 * 1024)
- return 1;
- if (bpp * sizeof (sca_desc_t) > 64 * 1024)
- return 1;
-
- sc->sc_allocsize = allocsize;
-
- /*
- * Allocate one huge chunk of memory.
- */
- if (bus_dmamem_alloc(sc->sc_dmat,
- allocsize,
- SCA_DMA_ALIGNMENT,
- SCA_DMA_BOUNDRY,
- &sc->sc_seg, 1, &rsegs, BUS_DMA_NOWAIT) != 0) {
- printf("Could not allocate DMA memory\n");
- return 1;
- }
- SCA_DPRINTF(SCA_DEBUG_DMA,
- ("DMA memory allocated: %d bytes\n", allocsize));
-
- if (bus_dmamem_map(sc->sc_dmat, &sc->sc_seg, 1, allocsize,
- &sc->sc_dma_addr, BUS_DMA_NOWAIT) != 0) {
- printf("Could not map DMA memory into kernel space\n");
- return 1;
- }
- SCA_DPRINTF(SCA_DEBUG_DMA, ("DMA memory mapped\n"));
-
- if (bus_dmamap_create(sc->sc_dmat, allocsize, 2,
- allocsize, SCA_DMA_BOUNDRY,
- BUS_DMA_NOWAIT, &sc->sc_dmam) != 0) {
- printf("Could not create DMA map\n");
- return 1;
- }
- SCA_DPRINTF(SCA_DEBUG_DMA, ("DMA map created\n"));
-
- err = bus_dmamap_load(sc->sc_dmat, sc->sc_dmam, sc->sc_dma_addr,
- allocsize, NULL, BUS_DMA_NOWAIT);
- if (err != 0) {
- printf("Could not load DMA segment: %d\n", err);
- return 1;
- }
- SCA_DPRINTF(SCA_DEBUG_DMA, ("DMA map loaded\n"));
-
- return 0;
-}
-
-/*
- * Take the memory allocated with sca_alloc_dma() and divide it among the
- * two ports.
- */
-static void
-sca_setup_dma_memory(struct sca_softc *sc)
-{
- sca_port_t *scp0, *scp1;
- u_int8_t *vaddr0;
- u_int32_t paddr0;
- u_long addroff;
-
- /*
- * remember the physical address to 24 bits only, since the upper
- * 8 bits is programed into the device at a different layer.
- */
- paddr0 = (sc->sc_dmam->dm_segs[0].ds_addr & 0x00ffffff);
- vaddr0 = sc->sc_dma_addr;
-
- /*
- * if we have only one port it gets the full range. If we have
- * two we need to do a little magic to divide things up.
- *
- * The descriptors will all end up in the front of the area, while
- * the remainder of the buffer is used for transmit and receive
- * data.
- *
- * -------------------- start of memory
- * tx desc port 0
- * rx desc port 0
- * tx desc port 1
- * rx desc port 1
- * tx buffer port 0
- * rx buffer port 0
- * tx buffer port 1
- * rx buffer port 1
- * -------------------- end of memory
- */
- scp0 = &sc->sc_ports[0];
- scp1 = &sc->sc_ports[1];
-
- scp0->txdesc_p = paddr0;
- scp0->txdesc = (sca_desc_t *)vaddr0;
- addroff = sizeof(sca_desc_t) * SCA_NtxBUFS;
-
- /*
- * point to the range following the tx descriptors, and
- * set the rx descriptors there.
- */
- scp0->rxdesc_p = paddr0 + addroff;
- scp0->rxdesc = (sca_desc_t *)(vaddr0 + addroff);
- addroff += sizeof(sca_desc_t) * SCA_NrxBUFS;
-
- if (sc->sc_numports == 2) {
- scp1->txdesc_p = paddr0 + addroff;
- scp1->txdesc = (sca_desc_t *)(vaddr0 + addroff);
- addroff += sizeof(sca_desc_t) * SCA_NtxBUFS;
-
- scp1->rxdesc_p = paddr0 + addroff;
- scp1->rxdesc = (sca_desc_t *)(vaddr0 + addroff);
- addroff += sizeof(sca_desc_t) * SCA_NrxBUFS;
- }
-
- /*
- * point to the memory following the descriptors, and set the
- * transmit buffer there.
- */
- scp0->txbuf_p = paddr0 + addroff;
- scp0->txbuf = vaddr0 + addroff;
- addroff += SCA_BSIZE * SCA_NtxBUFS;
-
- /*
- * lastly, skip over the transmit buffer and set up pointers into
- * the receive buffer.
- */
- scp0->rxbuf_p = paddr0 + addroff;
- scp0->rxbuf = vaddr0 + addroff;
- addroff += SCA_BSIZE * SCA_NrxBUFS;
-
- if (sc->sc_numports == 2) {
- scp1->txbuf_p = paddr0 + addroff;
- scp1->txbuf = vaddr0 + addroff;
- addroff += SCA_BSIZE * SCA_NtxBUFS;
-
- scp1->rxbuf_p = paddr0 + addroff;
- scp1->rxbuf = vaddr0 + addroff;
- addroff += SCA_BSIZE * SCA_NrxBUFS;
- }
-
- /*
- * as a consistancy check, addroff should be equal to the allocation
- * size.
- */
- if (sc->sc_allocsize != addroff)
- printf("ERROR: sc_allocsize != addroff: %lu != %lu\n",
- sc->sc_allocsize, addroff);
-}
-
/*
* Queue the packet for our start routine to transmit
*/
@@ -958,21 +961,39 @@ sca_start(ifp)
struct sca_softc *sc = scp->sca;
struct mbuf *m, *mb_head;
sca_desc_t *desc;
- u_int8_t *buf;
+ u_int8_t *buf, stat;
u_int32_t buf_p;
int nexttx;
int trigger_xmit;
+ u_int len;
+
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: enter start\n"));
/*
* can't queue when we are full or transmitter is busy
*/
- if ((scp->txinuse >= (SCA_NtxBUFS - 1))
+#ifdef oldcode
+ if ((scp->sp_txinuse >= (scp->sp_ntxdesc - 1))
|| ((ifp->if_flags & IFF_OACTIVE) == IFF_OACTIVE))
return;
+#else
+ if (scp->sp_txinuse
+ || ((ifp->if_flags & IFF_OACTIVE) == IFF_OACTIVE))
+ return;
+#endif
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: txinuse %d\n", scp->sp_txinuse));
- bus_dmamap_sync(sc->sc_dmat, sc->sc_dmam,
- 0, sc->sc_allocsize,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ /*
+ * XXX assume that all tx desc and bufs in same page
+ */
+ if (sc->sc_usedma)
+ bus_dmamap_sync(sc->scu_dmat, sc->scu_dmam,
+ 0, sc->scu_allocsize,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ else {
+ sc->scu_page_on(sc);
+ sc->scu_set_page(sc, scp->sp_txdesc_p);
+ }
trigger_xmit = 0;
@@ -987,28 +1008,42 @@ sca_start(ifp)
if (mb_head == NULL)
goto start_xmit;
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: got mbuf\n"));
+#ifdef oldcode
if (scp->txinuse != 0) {
/* Kill EOT interrupts on the previous descriptor. */
- desc = &scp->txdesc[scp->txcur];
- desc->stat &= ~SCA_DESC_EOT;
+ desc = &scp->sp_txdesc[scp->txcur];
+ stat = sca_desc_read_stat(sc, desc);
+ sca_desc_write_stat(sc, desc, stat & ~SCA_DESC_EOT);
/* Figure out what the next free descriptor is. */
- if ((scp->txcur + 1) == SCA_NtxBUFS)
- nexttx = 0;
- else
- nexttx = scp->txcur + 1;
+ nexttx = (scp->sp_txcur + 1) % scp->sp_ntxdesc;
} else
nexttx = 0;
+#endif /* oldcode */
+
+ if (scp->sp_txinuse)
+ nexttx = (scp->sp_txcur + 1) % scp->sp_ntxdesc;
+ else
+ nexttx = 0;
- desc = &scp->txdesc[nexttx];
- buf = scp->txbuf + SCA_BSIZE * nexttx;
- buf_p = scp->txbuf_p + SCA_BSIZE * nexttx;
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: nexttx %d\n", nexttx));
- desc->bp = (u_int16_t)(buf_p & 0x0000ffff);
- desc->bpb = (u_int8_t)((buf_p & 0x00ff0000) >> 16);
- desc->stat = SCA_DESC_EOT | SCA_DESC_EOM; /* end of frame and xfer */
- desc->len = 0;
+ buf = scp->sp_txbuf + SCA_BSIZE * nexttx;
+ buf_p = scp->sp_txbuf_p + SCA_BSIZE * nexttx;
+ /* XXX hoping we can delay the desc write till after we don't drop. */
+ desc = &scp->sp_txdesc[nexttx];
+
+ /* XXX isn't this set already?? */
+ sca_desc_write_bufp(sc, desc, buf_p);
+ len = 0;
+
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: buf %x buf_p %x\n", (u_int)buf, buf_p));
+
+#if 0 /* uncomment this for a core in cc1 */
+X
+#endif
/*
* Run through the chain, copying data into the descriptor as we
* go. If it won't fit in one transmission block, drop the packet.
@@ -1016,16 +1051,29 @@ sca_start(ifp)
*/
for (m = mb_head ; m != NULL ; m = m->m_next) {
if (m->m_len != 0) {
- desc->len += m->m_len;
- if (desc->len > SCA_BSIZE) {
+ len += m->m_len;
+ if (len > SCA_BSIZE) {
m_freem(mb_head);
goto txloop;
}
- bcopy(mtod(m, u_int8_t *), buf, m->m_len);
+ SCA_DPRINTF(SCA_DEBUG_TX,
+ ("TX: about to mbuf len %d\n", m->m_len));
+
+ if (sc->sc_usedma)
+ bcopy(mtod(m, u_int8_t *), buf, m->m_len);
+ else
+ bus_space_write_region_1(sc->scu_memt,
+ sc->scu_memh, sca_page_addr(sc, buf_p),
+ mtod(m, u_int8_t *), m->m_len);
buf += m->m_len;
+ buf_p += m->m_len;
}
}
+ /* set the buffer, the length, and mark end of frame and end of xfer */
+ sca_desc_write_buflen(sc, desc, len);
+ sca_desc_write_stat(sc, desc, SCA_DESC_EOM);
+
ifp->if_opackets++;
#if NBPFILTER > 0
@@ -1038,27 +1086,44 @@ sca_start(ifp)
m_freem(mb_head);
- if (scp->txinuse != 0) {
- scp->txcur++;
- if (scp->txcur == SCA_NtxBUFS)
- scp->txcur = 0;
- }
- scp->txinuse++;
+ scp->sp_txcur = nexttx;
+ scp->sp_txinuse++;
trigger_xmit = 1;
SCA_DPRINTF(SCA_DEBUG_TX,
- ("TX: inuse %d index %d\n", scp->txinuse, scp->txcur));
+ ("TX: inuse %d index %d\n", scp->sp_txinuse, scp->sp_txcur));
- if (scp->txinuse < (SCA_NtxBUFS - 1))
+ /*
+ * XXX so didn't this used to limit us to 1?! - multi may be untested
+ * sp_ntxdesc used to be hard coded to 2 with claim of a too hard
+ * to find bug
+ */
+#ifdef oldcode
+ if (scp->sp_txinuse < (scp->sp_ntxdesc - 1))
+#endif
+ if (scp->sp_txinuse < scp->sp_ntxdesc)
goto txloop;
start_xmit:
- bus_dmamap_sync(sc->sc_dmat, sc->sc_dmam,
- 0, sc->sc_allocsize,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: trigger_xmit %d\n", trigger_xmit));
+
+ if (trigger_xmit != 0) {
+ /* set EOT on final descriptor */
+ desc = &scp->sp_txdesc[scp->sp_txcur];
+ stat = sca_desc_read_stat(sc, desc);
+ sca_desc_write_stat(sc, desc, stat | SCA_DESC_EOT);
+ }
+
+ if (sc->sc_usedma)
+ bus_dmamap_sync(sc->scu_dmat, sc->scu_dmam, 0,
+ sc->scu_allocsize,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
if (trigger_xmit != 0)
sca_port_starttx(scp);
+
+ if (!sc->sc_usedma)
+ sc->scu_page_off(sc);
}
static void
@@ -1075,6 +1140,8 @@ sca_hardintr(struct sca_softc *sc)
ret = 0; /* non-zero means we processed at least one interrupt */
+ SCA_DPRINTF(SCA_DEBUG_INTR, ("sca_hardintr entered\n"));
+
while (1) {
/*
* read SCA interrupts
@@ -1091,17 +1158,25 @@ sca_hardintr(struct sca_softc *sc)
isr0, isr1, isr2));
/*
- * check DMA interrupt
+ * check DMAC interrupt
*/
if (isr1 & 0x0f)
ret += sca_dmac_intr(&sc->sc_ports[0],
isr1 & 0x0f);
+
if (isr1 & 0xf0)
ret += sca_dmac_intr(&sc->sc_ports[1],
- (isr1 & 0xf0) >> 4);
+ (isr1 & 0xf0) >> 4);
- if (isr0)
- ret += sca_msci_intr(sc, isr0);
+ /*
+ * mcsi intterupts
+ */
+ if (isr0 & 0x0f)
+ ret += sca_msci_intr(&sc->sc_ports[0], isr0 & 0x0f);
+
+ if (isr0 & 0xf0)
+ ret += sca_msci_intr(&sc->sc_ports[1],
+ (isr0 & 0xf0) >> 4);
#if 0 /* We don't GET timer interrupts, we have them disabled (msci IE20) */
if (isr2)
@@ -1123,9 +1198,9 @@ sca_dmac_intr(sca_port_t *scp, u_int8_t isr)
/*
* Check transmit channel
*/
- if (isr & 0x0c) {
+ if (isr & (SCA_ISR1_DMAC_TX0A | SCA_ISR1_DMAC_TX0B)) {
SCA_DPRINTF(SCA_DEBUG_INTR,
- ("TX INTERRUPT port %d\n", scp->sp_port));
+ ("TX INTERRUPT port %d\n", scp->sp_port));
dsr = 1;
while (dsr != 0) {
@@ -1152,8 +1227,8 @@ sca_dmac_intr(sca_port_t *scp, u_int8_t isr)
scp->sp_if.if_xname);
scp->sp_if.if_flags &= ~IFF_OACTIVE;
- scp->txcur = 0;
- scp->txinuse = 0;
+ scp->sp_txcur = 0;
+ scp->sp_txinuse = 0;
}
/*
@@ -1171,8 +1246,8 @@ sca_dmac_intr(sca_port_t *scp, u_int8_t isr)
* transmitter restart.
*/
scp->sp_if.if_flags &= ~IFF_OACTIVE;
- scp->txcur = 0;
- scp->txinuse = 0;
+ scp->sp_txcur = 0;
+ scp->sp_txinuse = 0;
}
/*
@@ -1183,11 +1258,14 @@ sca_dmac_intr(sca_port_t *scp, u_int8_t isr)
*/
if (dsr & SCA_DSR_EOT) {
SCA_DPRINTF(SCA_DEBUG_TX,
- ("Transmit completed.\n"));
+ ("Transmit completed. cda %x eda %x dsr %x\n",
+ dmac_read_2(scp, SCA_CDAL1),
+ dmac_read_2(scp, SCA_EDAL1),
+ dsr));
scp->sp_if.if_flags &= ~IFF_OACTIVE;
- scp->txcur = 0;
- scp->txinuse = 0;
+ scp->sp_txcur = 0;
+ scp->sp_txinuse = 0;
/*
* check for more packets
@@ -1199,9 +1277,9 @@ sca_dmac_intr(sca_port_t *scp, u_int8_t isr)
/*
* receive channel check
*/
- if (isr & 0x03) {
- SCA_DPRINTF(SCA_DEBUG_INTR,
- ("RX INTERRUPT port %d\n", mch));
+ if (isr & (SCA_ISR1_DMAC_RX0A | SCA_ISR1_DMAC_RX0B)) {
+ SCA_DPRINTF(SCA_DEBUG_INTR, ("RX INTERRUPT port %d\n",
+ (scp == &scp->sca->sc_ports[0] ? 0 : 1)));
dsr = 1;
while (dsr != 0) {
@@ -1256,118 +1334,156 @@ sca_dmac_intr(sca_port_t *scp, u_int8_t isr)
}
static int
-sca_msci_intr(struct sca_softc *sc, u_int8_t isr)
+sca_msci_intr(sca_port_t *scp, u_int8_t isr)
{
- printf("Got msci interrupt XXX\n");
-
- return 0;
+ u_int8_t st1, trc0;
+
+ /* get and clear the specific interrupt -- should act on it :)*/
+ if ((st1 = msci_read_1(scp, SCA_ST10))) {
+ /* clear the interrupt */
+ msci_write_1(scp, SCA_ST10, st1);
+
+ if (st1 & SCA_ST1_UDRN) {
+ /* underrun -- try to increase ready control */
+ trc0 = msci_read_1(scp, SCA_TRC00);
+ if (trc0 == 0x1f)
+ printf("TX: underun - fifo depth maxed\n");
+ else {
+ if ((trc0 += 2) > 0x1f)
+ trc0 = 0x1f;
+ SCA_DPRINTF(SCA_DEBUG_TX,
+ ("TX: udrn - incr fifo to %d\n", trc0));
+ msci_write_1(scp, SCA_TRC00, trc0);
+ }
+ }
+ }
+ return (0);
}
static void
sca_get_packets(sca_port_t *scp)
{
- int descidx;
- sca_desc_t *desc;
- u_int8_t *buf;
+ struct sca_softc *sc;
- bus_dmamap_sync(scp->sca->sc_dmat, scp->sca->sc_dmam,
- 0, scp->sca->sc_allocsize,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ SCA_DPRINTF(SCA_DEBUG_RX, ("RX: sca_get_packets\n"));
- /*
- * Loop while there are packets to receive. After each is processed,
- * call sca_frame_skip() to update the DMA registers to the new
- * state.
- */
- while (sca_frame_avail(scp, &descidx)) {
- desc = &scp->rxdesc[descidx];
- buf = scp->rxbuf + SCA_BSIZE * descidx;
+ sc = scp->sca;
+ if (sc->sc_usedma)
+ bus_dmamap_sync(sc->scu_dmat, sc->scu_dmam,
+ 0, sc->scu_allocsize,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ else {
+ /*
+ * XXX this code is unable to deal with rx stuff
+ * in more than 1 page
+ */
+ sc->scu_page_on(sc);
+ sc->scu_set_page(sc, scp->sp_rxdesc_p);
+ }
- sca_frame_process(scp, desc, buf);
-#if SCA_DEBUG_LEVEL > 0
- if (sca_debug & SCA_DEBUG_RXPKT)
- sca_frame_print(scp, desc, buf);
-#endif
- sca_frame_skip(scp, descidx);
+ /* process as many frames as are available */
+ while (sca_frame_avail(scp)) {
+ sca_frame_process(scp);
+ sca_frame_read_done(scp);
}
- bus_dmamap_sync(scp->sca->sc_dmat, scp->sca->sc_dmam,
- 0, scp->sca->sc_allocsize,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ if (sc->sc_usedma)
+ bus_dmamap_sync(sc->scu_dmat, sc->scu_dmam,
+ 0, sc->scu_allocsize,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ else
+ sc->scu_page_off(sc);
}
/*
* Starting with the first descriptor we wanted to read into, up to but
* not including the current SCA read descriptor, look for a packet.
+ *
+ * must be called at splnet()
*/
static int
-sca_frame_avail(sca_port_t *scp, int *descindx)
+sca_frame_avail(sca_port_t *scp)
{
- u_int16_t cda;
- int cdaidx;
- u_int32_t desc_p; /* physical address (lower 16 bits) */
- sca_desc_t *desc;
- u_int8_t rxstat;
+ struct sca_softc *sc;
+ u_int16_t cda;
+ u_int32_t desc_p; /* physical address (lower 16 bits) */
+ sca_desc_t *desc;
+ u_int8_t rxstat;
+ int cdaidx, toolong;
/*
* Read the current descriptor from the SCA.
*/
+ sc = scp->sca;
cda = dmac_read_2(scp, SCA_CDAL0);
/*
* calculate the index of the current descriptor
*/
- desc_p = cda - (u_int16_t)(scp->rxdesc_p & 0x0000ffff);
+ desc_p = (scp->sp_rxdesc_p & 0xFFFF);
+ desc_p = cda - desc_p;
cdaidx = desc_p / sizeof(sca_desc_t);
- if (cdaidx >= SCA_NrxBUFS)
- return 0;
+ SCA_DPRINTF(SCA_DEBUG_RX,
+ ("RX: cda %x desc_p %x cdaidx %u, nrxdesc %d rxstart %d\n",
+ cda, desc_p, cdaidx, scp->sp_nrxdesc, scp->sp_rxstart));
- for (;;) {
- /*
- * if the SCA is reading into the first descriptor, we somehow
- * got this interrupt incorrectly. Just return that there are
- * no packets ready.
- */
- if (cdaidx == scp->rxstart)
- return 0;
+ /* note confusion */
+ if (cdaidx >= scp->sp_nrxdesc)
+ panic("current descriptor index out of range");
+ /* see if we have a valid frame available */
+ toolong = 0;
+ for (; scp->sp_rxstart != cdaidx; sca_frame_read_done(scp)) {
/*
* We might have a valid descriptor. Set up a pointer
* to the kva address for it so we can more easily examine
* the contents.
*/
- desc = &scp->rxdesc[scp->rxstart];
+ desc = &scp->sp_rxdesc[scp->sp_rxstart];
+ rxstat = sca_desc_read_stat(scp->sca, desc);
+
+ SCA_DPRINTF(SCA_DEBUG_RX, ("port %d RX: idx %d rxstat %x\n",
+ scp->sp_port, scp->sp_rxstart, rxstat));
- rxstat = desc->stat;
+ SCA_DPRINTF(SCA_DEBUG_RX, ("port %d RX: buflen %d\n",
+ scp->sp_port, sca_desc_read_buflen(scp->sca, desc)));
/*
* check for errors
*/
- if (rxstat & SCA_DESC_ERRORS)
- goto nextpkt;
+ if (rxstat & SCA_DESC_ERRORS) {
+ /*
+ * consider an error condition the end
+ * of a frame
+ */
+ scp->sp_if.if_ierrors++;
+ toolong = 0;
+ continue;
+ }
/*
- * full packet? Good.
+ * if we aren't skipping overlong frames
+ * we are done, otherwise reset and look for
+ * another good frame
*/
if (rxstat & SCA_DESC_EOM) {
- *descindx = scp->rxstart;
- return 1;
+ if (!toolong)
+ return (1);
+ toolong = 0;
+ } else if (!toolong) {
+ /*
+ * we currently don't deal with frames
+ * larger than a single buffer (fixed MTU)
+ */
+ scp->sp_if.if_ierrors++;
+ toolong = 1;
}
-
- /*
- * increment the rxstart address, since this frame is
- * somehow damaged. Skip over it in later calls.
- * XXX This breaks multidescriptor receives, so each
- * frame HAS to fit within one descriptor's buffer
- * space now...
- */
- nextpkt:
- scp->rxstart++;
- if (scp->rxstart == SCA_NrxBUFS)
- scp->rxstart = 0;
+ SCA_DPRINTF(SCA_DEBUG_RX, ("RX: idx %d no EOM\n",
+ scp->sp_rxstart));
}
+ SCA_DPRINTF(SCA_DEBUG_RX, ("RX: returning none\n"));
return 0;
}
@@ -1378,46 +1494,66 @@ sca_frame_avail(sca_port_t *scp, int *descindx)
* MUST BE CALLED AT splnet()
*/
static void
-sca_frame_process(sca_port_t *scp, sca_desc_t *desc, u_int8_t *p)
+sca_frame_process(sca_port_t *scp)
{
- hdlc_header_t *hdlc;
- cisco_pkt_t *cisco, *ncisco;
- u_int16_t len;
- struct mbuf *m;
- u_int8_t *nbuf;
- u_int32_t t = (time.tv_sec - boottime.tv_sec) * 1000;
struct ifqueue *ifq;
+ hdlc_header_t *hdlc;
+ cisco_pkt_t *cisco;
+ sca_desc_t *desc;
+ struct mbuf *m;
+ u_int8_t *bufp;
+ u_int16_t len;
+ u_int32_t t;
- len = desc->len;
+ t = (time.tv_sec - boottime.tv_sec) * 1000;
+ desc = &scp->sp_rxdesc[scp->sp_rxstart];
+ bufp = scp->sp_rxbuf + SCA_BSIZE * scp->sp_rxstart;
+ len = sca_desc_read_buflen(scp->sca, desc);
+ SCA_DPRINTF(SCA_DEBUG_RX,
+ ("RX: desc %lx bufp %lx len %d\n", (bus_addr_t)desc,
+ (bus_addr_t)bufp, len));
+
+#if SCA_DEBUG_LEVEL > 0
+ if (sca_debug & SCA_DEBUG_RXPKT)
+ sca_frame_print(scp, desc, bufp);
+#endif
/*
* skip packets that are too short
*/
if (len < sizeof(hdlc_header_t))
return;
-#if NBPFILTER > 0
- if (scp->sp_bpf)
- bpf_tap(scp->sp_bpf, p, len);
-#endif
+ m = sca_mbuf_alloc(scp->sca, bufp, len);
+ if (m == NULL) {
+ SCA_DPRINTF(SCA_DEBUG_RX, ("RX: no mbuf!\n"));
+ scp->sp_if.if_iqdrops++;
+ return;
+ }
/*
* read and then strip off the HDLC information
*/
- hdlc = (hdlc_header_t *)p;
+ m = m_pullup(m, sizeof(hdlc_header_t));
+ if (m == NULL) {
+ SCA_DPRINTF(SCA_DEBUG_RX, ("RX: no m_pullup!\n"));
+ scp->sp_if.if_ierrors++;
+ scp->sp_if.if_iqdrops++;
+ }
+
+#if NBPFILTER > 0
+ if (scp->sp_bpf)
+ bpf_mtap(scp->sp_bpf, m);
+#endif
scp->sp_if.if_ipackets++;
scp->sp_if.if_lastchange = time;
+ hdlc = mtod(m, hdlc_header_t *);
switch (ntohs(hdlc->protocol)) {
case HDLC_PROTOCOL_IP:
SCA_DPRINTF(SCA_DEBUG_RX, ("Received IP packet\n"));
- m = sca_mbuf_alloc(p, len);
- if (m == NULL) {
- scp->sp_if.if_iqdrops++;
- return;
- }
m->m_pkthdr.rcvif = &scp->sp_if;
if (IF_QFULL(&ipintrq)) {
@@ -1446,23 +1582,21 @@ sca_frame_process(sca_port_t *scp, sca_desc_t *desc, u_int8_t *p)
SCA_DPRINTF(SCA_DEBUG_CISCO,
("short CISCO packet %d, wanted %d\n",
len, CISCO_PKT_LEN));
+ m_freem(m);
return;
}
- /*
- * allocate an mbuf and copy the important bits of data
- * into it.
- */
- m = sca_mbuf_alloc(p, HDLC_HDRLEN + CISCO_PKT_LEN);
- if (m == NULL)
- return;
+ m = m_pullup(m, sizeof(cisco_pkt_t));
+ if (m == NULL) {
+ SCA_DPRINTF(SCA_DEBUG_RX, ("RX: no m_pullup!\n"));
+ scp->sp_if.if_ierrors++;
+ scp->sp_if.if_iqdrops++;
+ break;
+ }
- nbuf = mtod(m, u_int8_t *);
- ncisco = (cisco_pkt_t *)(nbuf + HDLC_HDRLEN);
+ cisco = (cisco_pkt_t *)(mtod(m, u_int8_t *) + HDLC_HDRLEN);
m->m_pkthdr.rcvif = &scp->sp_if;
- cisco = (cisco_pkt_t *)(p + HDLC_HDRLEN);
-
switch (ntohl(cisco->type)) {
case CISCO_ADDR_REQ:
printf("Got CISCO addr_req, ignoring\n");
@@ -1475,6 +1609,7 @@ sca_frame_process(sca_port_t *scp, sca_desc_t *desc, u_int8_t *p)
break;
case CISCO_KEEPALIVE_REQ:
+
SCA_DPRINTF(SCA_DEBUG_CISCO,
("Received KA, mseq %d,"
" yseq %d, rel 0x%04x, t0"
@@ -1489,10 +1624,10 @@ sca_frame_process(sca_port_t *scp, sca_desc_t *desc, u_int8_t *p)
/*
* schedule the transmit right here.
*/
- ncisco->par2 = cisco->par1;
- ncisco->par1 = htonl(scp->cka_lasttx);
- ncisco->time0 = htons((u_int16_t)(t >> 16));
- ncisco->time1 = htons((u_int16_t)(t & 0x0000ffff));
+ cisco->par2 = cisco->par1;
+ cisco->par1 = htonl(scp->cka_lasttx);
+ cisco->time0 = htons((u_int16_t)(t >> 16));
+ cisco->time1 = htons((u_int16_t)(t & 0x0000ffff));
ifq = &scp->linkq;
if (IF_QFULL(ifq)) {
@@ -1504,6 +1639,13 @@ sca_frame_process(sca_port_t *scp, sca_desc_t *desc, u_int8_t *p)
sca_start(&scp->sp_if);
+ /* since start may have reset this fix */
+ if (!scp->sca->sc_usedma) {
+ scp->sca->scu_set_page(scp->sca,
+ scp->sp_rxdesc_p);
+ scp->sca->scu_page_on(scp->sca);
+ }
+
break;
default:
@@ -1520,6 +1662,7 @@ sca_frame_process(sca_port_t *scp, sca_desc_t *desc, u_int8_t *p)
SCA_DPRINTF(SCA_DEBUG_RX,
("Unknown/unexpected ethertype 0x%04x\n",
ntohs(hdlc->protocol)));
+ m_freem(m);
}
}
@@ -1533,19 +1676,33 @@ sca_frame_print(sca_port_t *scp, sca_desc_t *desc, u_int8_t *p)
{
int i;
int nothing_yet = 1;
+ struct sca_softc *sc;
+ u_int len;
- printf("descriptor va %p: cp 0x%x bpb 0x%0x bp 0x%0x stat 0x%0x len %d\n",
- desc, desc->cp, desc->bpb, desc->bp, desc->stat, desc->len);
-
- for (i = 0 ; i < desc->len ; i++) {
- if (nothing_yet == 1 && *p == 0) {
+ sc = scp->sca;
+ printf("desc va %p: chainp 0x%x bufp 0x%0x stat 0x%0x len %d\n",
+ desc,
+ sca_desc_read_chainp(sc, desc),
+ sca_desc_read_bufp(sc, desc),
+ sca_desc_read_stat(sc, desc),
+ (len = sca_desc_read_buflen(sc, desc)));
+
+ for (i = 0 ; i < len && i < 256; i++) {
+ if (nothing_yet == 1 &&
+ (sc->sc_usedma ? *p
+ : bus_space_read_1(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, p))) == 0) {
p++;
continue;
}
nothing_yet = 0;
if (i % 16 == 0)
printf("\n");
- printf("%02x ", *p++);
+ printf("%02x ",
+ (sc->sc_usedma ? *p
+ : bus_space_read_1(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, p))));
+ p++;
}
if (i % 16 != 1)
@@ -1554,22 +1711,24 @@ sca_frame_print(sca_port_t *scp, sca_desc_t *desc, u_int8_t *p)
#endif
/*
- * skip all frames before the descriptor index "indx" -- we do this by
- * moving the rxstart pointer to the index following this one, and
- * setting the end descriptor to this index.
+ * adjust things becuase we have just read the current starting
+ * frame
+ *
+ * must be called at splnet()
*/
static void
-sca_frame_skip(sca_port_t *scp, int indx)
+sca_frame_read_done(sca_port_t *scp)
{
- u_int32_t desc_p;
+ u_int16_t edesc_p;
- scp->rxstart++;
- if (scp->rxstart == SCA_NrxBUFS)
- scp->rxstart = 0;
+ /* update where our indicies are */
+ scp->sp_rxend = scp->sp_rxstart;
+ scp->sp_rxstart = (scp->sp_rxstart + 1) % scp->sp_nrxdesc;
- desc_p = scp->rxdesc_p * sizeof(sca_desc_t) * indx;
- dmac_write_2(scp, SCA_EDAL0,
- (u_int16_t)(desc_p & 0x0000ffff));
+ /* update the error [end] descriptor */
+ edesc_p = (u_int16_t)scp->sp_rxdesc_p +
+ (sizeof(sca_desc_t) * scp->sp_rxend);
+ dmac_write_2(scp, SCA_EDAL0, edesc_p);
}
/*
@@ -1579,6 +1738,9 @@ static void
sca_port_up(sca_port_t *scp)
{
struct sca_softc *sc = scp->sca;
+#if 0
+ u_int8_t ier0, ier1;
+#endif
/*
* reset things
@@ -1591,28 +1753,43 @@ sca_port_up(sca_port_t *scp)
* clear in-use flag
*/
scp->sp_if.if_flags &= ~IFF_OACTIVE;
+ scp->sp_if.if_flags |= IFF_RUNNING;
/*
* raise DTR
*/
- sc->dtr_callback(sc->dtr_aux, scp->sp_port, 1);
+ sc->sc_dtr_callback(sc->sc_aux, scp->sp_port, 1);
/*
* raise RTS
*/
msci_write_1(scp, SCA_CTL0,
- msci_read_1(scp, SCA_CTL0) & ~SCA_CTL_RTS);
+ (msci_read_1(scp, SCA_CTL0) & ~SCA_CTL_RTS_MASK)
+ | SCA_CTL_RTS_HIGH);
+#if 0
/*
- * enable interrupts
+ * enable interrupts (no timer IER2)
*/
+ ier0 = SCA_IER0_MSCI_RXRDY0 | SCA_IER0_MSCI_TXRDY0
+ | SCA_IER0_MSCI_RXINT0 | SCA_IER0_MSCI_TXINT0;
+ ier1 = SCA_IER1_DMAC_RX0A | SCA_IER1_DMAC_RX0B
+ | SCA_IER1_DMAC_TX0A | SCA_IER1_DMAC_TX0B;
+ if (scp->sp_port == 1) {
+ ier0 <<= 4;
+ ier1 <<= 4;
+ }
+ sca_write_1(sc, SCA_IER0, sca_read_1(sc, SCA_IER0) | ier0);
+ sca_write_1(sc, SCA_IER1, sca_read_1(sc, SCA_IER1) | ier1);
+#else
if (scp->sp_port == 0) {
sca_write_1(sc, SCA_IER0, sca_read_1(sc, SCA_IER0) | 0x0f);
sca_write_1(sc, SCA_IER1, sca_read_1(sc, SCA_IER1) | 0x0f);
- } else {
+ } else {
sca_write_1(sc, SCA_IER0, sca_read_1(sc, SCA_IER0) | 0xf0);
sca_write_1(sc, SCA_IER1, sca_read_1(sc, SCA_IER1) | 0xf0);
}
+#endif
/*
* enable transmit and receive
@@ -1623,8 +1800,8 @@ sca_port_up(sca_port_t *scp)
/*
* reset internal state
*/
- scp->txinuse = 0;
- scp->txcur = 0;
+ scp->sp_txinuse = 0;
+ scp->sp_txcur = 0;
scp->cka_lasttx = time.tv_usec;
scp->cka_lastrx = 0;
}
@@ -1636,28 +1813,45 @@ static void
sca_port_down(sca_port_t *scp)
{
struct sca_softc *sc = scp->sca;
+#if 0
+ u_int8_t ier0, ier1;
+#endif
/*
* lower DTR
*/
- sc->dtr_callback(sc->dtr_aux, scp->sp_port, 0);
+ sc->sc_dtr_callback(sc->sc_aux, scp->sp_port, 0);
/*
* lower RTS
*/
msci_write_1(scp, SCA_CTL0,
- msci_read_1(scp, SCA_CTL0) | SCA_CTL_RTS);
+ (msci_read_1(scp, SCA_CTL0) & ~SCA_CTL_RTS_MASK)
+ | SCA_CTL_RTS_LOW);
/*
* disable interrupts
*/
+#if 0
+ ier0 = SCA_IER0_MSCI_RXRDY0 | SCA_IER0_MSCI_TXRDY0
+ | SCA_IER0_MSCI_RXINT0 | SCA_IER0_MSCI_TXINT0;
+ ier1 = SCA_IER1_DMAC_RX0A | SCA_IER1_DMAC_RX0B
+ | SCA_IER1_DMAC_TX0A | SCA_IER1_DMAC_TX0B;
+ if (scp->sp_port == 1) {
+ ier0 <<= 4;
+ ier1 <<= 4;
+ }
+ sca_write_1(sc, SCA_IER0, sca_read_1(sc, SCA_IER0) & ~ier0);
+ sca_write_1(sc, SCA_IER1, sca_read_1(sc, SCA_IER1) & ~ier1);
+#else
if (scp->sp_port == 0) {
sca_write_1(sc, SCA_IER0, sca_read_1(sc, SCA_IER0) & 0xf0);
sca_write_1(sc, SCA_IER1, sca_read_1(sc, SCA_IER1) & 0xf0);
- } else {
+ } else {
sca_write_1(sc, SCA_IER0, sca_read_1(sc, SCA_IER0) & 0x0f);
sca_write_1(sc, SCA_IER1, sca_read_1(sc, SCA_IER1) & 0x0f);
}
+#endif
/*
* disable transmit and receive
@@ -1668,7 +1862,7 @@ sca_port_down(sca_port_t *scp)
/*
* no, we're not in use anymore
*/
- scp->sp_if.if_flags &= ~IFF_OACTIVE;
+ scp->sp_if.if_flags &= ~(IFF_OACTIVE|IFF_RUNNING);
}
/*
@@ -1697,22 +1891,26 @@ sca_port_starttx(sca_port_t *scp)
sc = scp->sca;
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: starttx\n"));
+
if (((scp->sp_if.if_flags & IFF_OACTIVE) == IFF_OACTIVE)
- || scp->txinuse == 0)
+ || scp->sp_txinuse == 0)
return;
+
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: setting oactive\n"));
+
scp->sp_if.if_flags |= IFF_OACTIVE;
/*
* We have something to do, since we have at least one packet
* waiting, and we are not already marked as active.
*/
- enddesc = scp->txcur;
- enddesc++;
- if (enddesc == SCA_NtxBUFS)
- enddesc = 0;
+ enddesc = (scp->sp_txcur + 1) % scp->sp_ntxdesc;
+ startdesc_p = scp->sp_txdesc_p;
+ enddesc_p = scp->sp_txdesc_p + sizeof(sca_desc_t) * enddesc;
- startdesc_p = scp->txdesc_p;
- enddesc_p = scp->txdesc_p + sizeof(sca_desc_t) * enddesc;
+ SCA_DPRINTF(SCA_DEBUG_TX, ("TX: start %x end %x\n",
+ startdesc_p, enddesc_p));
dmac_write_2(scp, SCA_EDAL1, (u_int16_t)(enddesc_p & 0x0000ffff));
dmac_write_2(scp, SCA_CDAL1,
@@ -1730,7 +1928,7 @@ sca_port_starttx(sca_port_t *scp)
* otherwise let the caller handle copying the data in.
*/
static struct mbuf *
-sca_mbuf_alloc(caddr_t p, u_int len)
+sca_mbuf_alloc(struct sca_softc *sc, caddr_t p, u_int len)
{
struct mbuf *m;
@@ -1753,10 +1951,142 @@ sca_mbuf_alloc(caddr_t p, u_int len)
return NULL;
}
}
- if (p != NULL)
- bcopy(p, mtod(m, caddr_t), len);
+ if (p != NULL) {
+ /* XXX do we need to sync here? */
+ if (sc->sc_usedma)
+ bcopy(p, mtod(m, caddr_t), len);
+ else
+ bus_space_read_region_1(sc->scu_memt, sc->scu_memh,
+ sca_page_addr(sc, p), mtod(m, u_int8_t *), len);
+ }
m->m_len = len;
m->m_pkthdr.len = len;
return (m);
}
+
+/*
+ * get the base clock
+ */
+void
+sca_get_base_clock(struct sca_softc *sc)
+{
+ struct timeval btv, ctv, dtv;
+ u_int64_t bcnt;
+ u_int32_t cnt;
+ u_int16_t subcnt;
+
+ /* disable the timer, set prescale to 0 */
+ sca_write_1(sc, SCA_TCSR0, 0);
+ sca_write_1(sc, SCA_TEPR0, 0);
+
+ /* reset the counter */
+ (void)sca_read_1(sc, SCA_TCSR0);
+ subcnt = sca_read_2(sc, SCA_TCNTL0);
+
+ /* count to max */
+ sca_write_2(sc, SCA_TCONRL0, 0xffff);
+
+ cnt = 0;
+ microtime(&btv);
+ /* start the timer -- no interrupt enable */
+ sca_write_1(sc, SCA_TCSR0, SCA_TCSR_TME);
+ for (;;) {
+ microtime(&ctv);
+
+ /* end around 3/4 of a second */
+ timersub(&ctv, &btv, &dtv);
+ if (dtv.tv_usec >= 750000)
+ break;
+
+ /* spin */
+ while (!(sca_read_1(sc, SCA_TCSR0) & SCA_TCSR_CMF))
+ ;
+ /* reset the timer */
+ (void)sca_read_2(sc, SCA_TCNTL0);
+ cnt++;
+ }
+
+ /* stop the timer */
+ sca_write_1(sc, SCA_TCSR0, 0);
+
+ subcnt = sca_read_2(sc, SCA_TCNTL0);
+ /* add the slop in and get the total timer ticks */
+ cnt = (cnt << 16) | subcnt;
+
+ /* cnt is 1/8 the actual time */
+ bcnt = cnt * 8;
+ /* make it proportional to 3/4 of a second */
+ bcnt *= (u_int64_t)750000;
+ bcnt /= (u_int64_t)dtv.tv_usec;
+ cnt = bcnt;
+
+ /* make it Hz */
+ cnt *= 4;
+ cnt /= 3;
+
+ SCA_DPRINTF(SCA_DEBUG_CLOCK,
+ ("sca: unadjusted base %lu Hz\n", (u_long)cnt));
+
+ /*
+ * round to the nearest 200 -- this allows for +-3 ticks error
+ */
+ sc->sc_baseclock = ((cnt + 100) / 200) * 200;
+}
+
+/*
+ * print the information about the clock on the ports
+ */
+void
+sca_print_clock_info(struct sca_softc *sc)
+{
+ struct sca_port *scp;
+ u_int32_t mhz, div;
+ int i;
+
+ printf("%s: base clock %d Hz\n", sc->sc_parent->dv_xname,
+ sc->sc_baseclock);
+
+ /* print the information about the port clock selection */
+ for (i = 0; i < sc->sc_numports; i++) {
+ scp = &sc->sc_ports[i];
+ mhz = sc->sc_baseclock / (scp->sp_tmc ? scp->sp_tmc : 256);
+ div = scp->sp_rxs & SCA_RXS_DIV_MASK;
+
+ printf("%s: rx clock: ", scp->sp_if.if_xname);
+ switch (scp->sp_rxs & SCA_RXS_CLK_MASK) {
+ case SCA_RXS_CLK_LINE:
+ printf("line");
+ break;
+ case SCA_RXS_CLK_LINE_SN:
+ printf("line with noise suppression");
+ break;
+ case SCA_RXS_CLK_INTERNAL:
+ printf("internal %d Hz", (mhz >> div));
+ break;
+ case SCA_RXS_CLK_ADPLL_OUT:
+ printf("adpll using internal %d Hz", (mhz >> div));
+ break;
+ case SCA_RXS_CLK_ADPLL_IN:
+ printf("adpll using line clock");
+ break;
+ }
+ printf(" tx clock: ");
+ div = scp->sp_txs & SCA_TXS_DIV_MASK;
+ switch (scp->sp_txs & SCA_TXS_CLK_MASK) {
+ case SCA_TXS_CLK_LINE:
+ printf("line\n");
+ break;
+ case SCA_TXS_CLK_INTERNAL:
+ printf("internal %d Hz\n", (mhz >> div));
+ break;
+ case SCA_TXS_CLK_RXCLK:
+ printf("rxclock\n");
+ break;
+ }
+ if (scp->sp_eclock)
+ printf("%s: outputting line clock\n",
+ scp->sp_if.if_xname);
+ }
+}
+
diff --git a/sys/dev/ic/hd64570reg.h b/sys/dev/ic/hd64570reg.h
index 3c0bc9abc4f..a2a580f8afa 100644
--- a/sys/dev/ic/hd64570reg.h
+++ b/sys/dev/ic/hd64570reg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: hd64570reg.h,v 1.2 1998/10/28 16:26:01 kleink Exp $ */
+/* $NetBSD: hd64570reg.h,v 1.3 2000/01/04 06:36:29 chopps Exp $ */
/*
* Copyright (c) 1998 Vixie Enterprises
@@ -72,15 +72,6 @@ typedef struct hdlc_header {
* Hitachi HD64570 defininitions
*/
-/*
- * At least one implementation uses a somewhat strange register address
- * mapping. If a card doesn't, define this to be a pass-through
- * macro. (The ntwo driver needs this...)
- */
-#ifndef SCADDR
-#define SCADDR(y) (((y) & 0x0002) ? (((y) & 0x00fd) + 0x100) : (y))
-#endif
-
/* SCA Control Registers */
#define SCA_PABR0 2
#define SCA_PABR1 3
@@ -205,15 +196,53 @@ typedef struct hdlc_header {
#define SCA_BARL2 0xC0 /* buffer address reg */
#define SCA_BARH2 0xC1 /* buffer address reg */
#define SCA_BARB2 0xC2 /* buffer address reg */
+#define SCA_CDAL2 0xC8
#define SCA_DSR2 0xD0 /* DMA Status reg */
/* DMA Channel 3 Registers (memory -> MSCI) */
#define SCA_BARL3 0xE0 /* buffer address reg */
#define SCA_BARH3 0xE1 /* buffer address reg */
#define SCA_BARB3 0xE2 /* buffer address reg */
+#define SCA_CDAL3 0xE8
#define SCA_DSR3 0xF0 /* DMA Status reg */
/*
+ * Timer Registers
+ */
+
+/* Timer up-counter */
+#define SCA_TCNTL0 0x60 /* channel 0 */
+#define SCA_TCNTH0 0x61 /* channel 0 */
+#define SCA_TCNTL1 0x68 /* channel 1 */
+#define SCA_TCNTH1 0x69 /* channel 1 */
+#define SCA_TCNTL2 0x70 /* channel 2 */
+#define SCA_TCNTH2 0x71 /* channel 2 */
+#define SCA_TCNTL3 0x78 /* channel 3 */
+#define SCA_TCNTH3 0x79 /* channel 3 */
+
+/* Timer constant register */
+#define SCA_TCONRL0 0x62 /* channel 0 */
+#define SCA_TCONRH0 0x63 /* channel 0 */
+#define SCA_TCONRL1 0x6a /* channel 1 */
+#define SCA_TCONRH1 0x6b /* channel 1 */
+#define SCA_TCONRL2 0x72 /* channel 2 */
+#define SCA_TCONRH2 0x73 /* channel 2 */
+#define SCA_TCONRL3 0x7a /* channel 3 */
+#define SCA_TCONRH3 0x7b /* channel 3 */
+
+/* Timer control/status register */
+#define SCA_TCSR0 0x64 /* channel 0 */
+#define SCA_TCSR1 0x6c /* channel 1 */
+#define SCA_TCSR2 0x74 /* channel 2 */
+#define SCA_TCSR3 0x7c /* channel 3 */
+
+/* Timer expand prescale register */
+#define SCA_TEPR0 0x65 /* channel 0 */
+#define SCA_TEPR1 0x6d /* channel 1 */
+#define SCA_TEPR2 0x75 /* channel 2 */
+#define SCA_TEPR3 0x7d /* channel 3 */
+
+/*
* SCA HD64570 Register Definitions
*/
@@ -273,41 +302,49 @@ typedef struct hdlc_header {
#define SCA_MD2_FM0 0xC0
#define SCA_MD2_FM1 0xA0
-#define SCA_CTL_RTS 0x01
-#define SCA_CTL_IDLPAT 0x10
-#define SCA_CTL_UDRNC 0x20
-
-#define SCA_RXS_DIV_MASK 0x0F
-#define SCA_RXS_DIV1 0x00
-#define SCA_RXS_DIV2 0x01
-#define SCA_RXS_DIV4 0x02
-#define SCA_RXS_DIV8 0x03
-#define SCA_RXS_DIV16 0x04
-#define SCA_RXS_DIV32 0x05
-#define SCA_RXS_DIV64 0x06
-#define SCA_RXS_DIV128 0x07
-#define SCA_RXS_DIV256 0x08
-#define SCA_RXS_DIV512 0x09
-#define SCA_RXS_CLK_RXC0 0x00
-#define SCA_RXS_CLK_RXC1 0x20
-#define SCA_RXS_CLK_INT 0x40
-#define SCA_RXS_CLK_ADPLL_OUT 0x60
-#define SCA_RXS_CLK_ADPLL_IN 0x70
-
-#define SCA_TXS_DIV_MASK 0x0F
-#define SCA_TXS_DIV1 0x00
-#define SCA_TXS_DIV2 0x01
-#define SCA_TXS_DIV4 0x02
-#define SCA_TXS_DIV8 0x03
-#define SCA_TXS_DIV16 0x04
-#define SCA_TXS_DIV32 0x05
-#define SCA_TXS_DIV64 0x06
-#define SCA_TXS_DIV128 0x07
-#define SCA_TXS_DIV256 0x08
-#define SCA_TXS_DIV512 0x09
-#define SCA_TXS_CLK_TXC 0x00
-#define SCA_TXS_CLK_INT 0x40
-#define SCA_TXS_CLK_RX 0x60
+#define SCA_CTL_RTS_MASK 0x01 /* control state of RTS */
+#define SCA_CTL_RTS_HIGH 0x00 /* raise RTS (low !RTS) */
+#define SCA_CTL_RTS_LOW 0x01 /* lower RTS (raise !RTS) */
+#define SCA_CTL_IDLC_MASK 0x10 /* control idle state */
+#define SCA_CTL_IDLC_MARK 0x00 /* transmit mark in idle state */
+#define SCA_CTL_IDLC_PATTERN 0x10 /* tranmist idle pattern */
+#define SCA_CTL_UDRNC_MASK 0x20 /* control underun state */
+#define SCA_CTL_UDRNC_AFTER_ABORT 0x00 /* idle after aborting trans */
+#define SCA_CTL_UDRNC_AFTER_FCS 0x20 /* idle after FCS and flag trans */
+
+#define SCA_RXS_DIV_MASK 0x0F /* BRG divisor is 2^(value) */
+#define SCA_RXS_DIV_1 0x00 /* 1 */
+#define SCA_RXS_DIV_2 0x01 /* 2 */
+#define SCA_RXS_DIV_4 0x02 /* 4 */
+#define SCA_RXS_DIV_8 0x03 /* 8 */
+#define SCA_RXS_DIV_16 0x04 /* 16 */
+#define SCA_RXS_DIV_32 0x05 /* 32 */
+#define SCA_RXS_DIV_64 0x06 /* 64 */
+#define SCA_RXS_DIV_128 0x07 /* 128 */
+#define SCA_RXS_DIV_256 0x08 /* 256 */
+#define SCA_RXS_DIV_512 0x09 /* 512 */
+#define SCA_RXS_CLK_MASK 0x70 /* which clock source */
+#define SCA_RXS_CLK_LINE 0x00 /* RXC line input */
+#define SCA_RXS_CLK_LINE_SN 0x20 /* RXC line with noise suppression */
+#define SCA_RXS_CLK_INTERNAL 0x40 /* Baud Rate Gen. output */
+#define SCA_RXS_CLK_ADPLL_OUT 0x60 /* BRG out for ADPLL clock */
+#define SCA_RXS_CLK_ADPLL_IN 0x70 /* line input for ADPLL clock */
+
+#define SCA_TXS_DIV_MASK 0x0F /* BRG divisor is 2^(valud) */
+#define SCA_TXS_DIV_1 0x00 /* 1 */
+#define SCA_TXS_DIV_2 0x01 /* 2 */
+#define SCA_TXS_DIV_4 0x02 /* 4 */
+#define SCA_TXS_DIV_8 0x03 /* 8 */
+#define SCA_TXS_DIV_16 0x04 /* 16 */
+#define SCA_TXS_DIV_32 0x05 /* 32 */
+#define SCA_TXS_DIV_64 0x06 /* 64 */
+#define SCA_TXS_DIV_128 0x07 /* 128 */
+#define SCA_TXS_DIV_256 0x08 /* 256 */
+#define SCA_TXS_DIV_512 0x09 /* 512 */
+#define SCA_TXS_CLK_MASK 0x70 /* which clock source */
+#define SCA_TXS_CLK_LINE 0x00 /* TXC line input */
+#define SCA_TXS_CLK_INTERNAL 0x40 /* Baud Rate Gen. output */
+#define SCA_TXS_CLK_RXCLK 0x60 /* Recieve clock */
#define SCA_ST0_RXRDY 0x01
#define SCA_ST0_TXRDY 0x02
@@ -359,6 +396,72 @@ typedef struct hdlc_header {
#define SCA_IE2_SHRT 0x40
#define SCA_IE2_EOM 0x80
+
+/*
+ * Interrupt status register bits
+ */
+#define SCA_ISR0_MSCI_RXRDY0 0x01 /* rx ready port 0 int */
+#define SCA_ISR0_MSCI_TXRDY0 0x02 /* tx ready port 0 int */
+#define SCA_ISR0_MSCI_RXINT0 0x04 /* rx error port 0 int */
+#define SCA_ISR0_MSCI_TXINT0 0x08 /* tx error port 0 int */
+#define SCA_ISR0_MSCI_RXRDY1 0x10 /* rx ready port 1 int */
+#define SCA_ISR0_MSCI_TXRDY1 0x20 /* tx ready port 1 int */
+#define SCA_ISR0_MSCI_RXINT1 0x40 /* rx error port 1 int */
+#define SCA_ISR0_MSCI_TXINT1 0x80 /* tx error port 1 int */
+
+#define SCA_ISR1_DMAC_RX0A 0x01 /* dmac channel 0 int a */
+#define SCA_ISR1_DMAC_RX0B 0x02 /* dmac channel 0 int b */
+#define SCA_ISR1_DMAC_TX0A 0x04 /* dmac channel 1 int a */
+#define SCA_ISR1_DMAC_TX0B 0x08 /* dmac channel 1 int b */
+#define SCA_ISR1_DMAC_RX1A 0x10 /* dmac channel 2 int a */
+#define SCA_ISR1_DMAC_RX1B 0x20 /* dmac channel 2 int b */
+#define SCA_ISR1_DMAC_TX1A 0x40 /* dmac channel 3 int a */
+#define SCA_ISR1_DMAC_TX1B 0x80 /* dmac channel 3 int b */
+
+#define SCA_ISR2_TIMER_IRQ0 0x10 /* timer channel 0 int */
+#define SCA_ISR2_TIMER_IRQ1 0x20 /* timer channel 1 int */
+#define SCA_ISR2_TIMER_IRQ2 0x40 /* timer channel 2 int */
+#define SCA_ISR2_TIMER_IRQ3 0x80 /* timer channel 3 int */
+
+/* masks/values for the Interrupt Control Register (ITCR) */
+#define SCA_ITCR_INTR_PRI_MASK 0x80 /* priority of intrerrupts */
+#define SCA_ITCR_INTR_PRI_MSCI 0x00 /* msci over dmac */
+#define SCA_ITCR_INTR_PRI_DMAC 0x80 /* dmac over msci */
+#define SCA_ITCR_ACK_MASK 0x60 /* mask for intr ack cycle setting */
+#define SCA_ITCR_ACK_NONE 0x00 /* no intr ack cycle */
+#define SCA_ITCR_ACK_SINGLE 0x20 /* single intr ack cycle */
+#define SCA_ITCR_ACK_DOUBLE 0x40 /* double intr ack cycle */
+#define SCA_ITCR_ACK_RESV 0x60 /* reserverd */
+#define SCA_ITCR_VOUT_MASK 0x10 /* vector output */
+#define SCA_ITCR_VOUT_IVR 0x00 /* use IVR */
+#define SCA_ITCR_VOUT_IMVR 0x10 /* use IMVR */
+
+/*
+ * Interrupt enable register bits
+ */
+#define SCA_IER0_MSCI_RXRDY0 0x01 /* enable rx ready port 0 int */
+#define SCA_IER0_MSCI_TXRDY0 0x02 /* enable tx ready port 0 int */
+#define SCA_IER0_MSCI_RXINT0 0x04 /* enable rx error port 0 int */
+#define SCA_IER0_MSCI_TXINT0 0x08 /* enable tx error port 0 int */
+#define SCA_IER0_MSCI_RXRDY1 0x10 /* enable rx ready port 1 int */
+#define SCA_IER0_MSCI_TXRDY1 0x20 /* enable tx ready port 1 int */
+#define SCA_IER0_MSCI_RXINT1 0x40 /* enable rx error port 1 int */
+#define SCA_IER0_MSCI_TXINT1 0x80 /* enable tx error port 1 int */
+
+#define SCA_IER1_DMAC_RX0A 0x01 /* enable dmac channel 0 int a */
+#define SCA_IER1_DMAC_RX0B 0x02 /* enable dmac channel 0 int b */
+#define SCA_IER1_DMAC_TX0A 0x04 /* enable dmac channel 1 int a */
+#define SCA_IER1_DMAC_TX0B 0x08 /* enable dmac channel 1 int b */
+#define SCA_IER1_DMAC_RX1A 0x10 /* enable dmac channel 2 int a */
+#define SCA_IER1_DMAC_RX1B 0x20 /* enable dmac channel 2 int b */
+#define SCA_IER1_DMAC_TX1A 0x40 /* enable dmac channel 3 int a */
+#define SCA_IER1_DMAC_TX1B 0x80 /* enable dmac channel 3 int b */
+
+#define SCA_IER2_TIMER_IRQ0 0x10 /* enable timer channel 0 int */
+#define SCA_IER2_TIMER_IRQ1 0x20 /* enable timer channel 1 int */
+#define SCA_IER2_TIMER_IRQ2 0x40 /* enable timer channel 2 int */
+#define SCA_IER2_TIMER_IRQ3 0x80 /* enable timer channel 3 int */
+
/* This is for RRC, TRC0 and TRC1. */
#define SCA_RCR_MASK 0x1F
@@ -457,6 +560,22 @@ typedef struct hdlc_header {
#define ST3_CTS 8 /* modem input /CTS bit */
#define ST3_DCD 4 /* modem input /DCD bit */
+/*
+ * timer register values
+ */
+#define SCA_TCSR_TME 0x10 /* timer enable */
+#define SCA_TCSR_ECMI 0x40 /* interrupt enable */
+#define SCA_TCSR_CMF 0x80 /* timer complete */
+
+#define SCA_TEPR_DIV_1 0x00 /* 2^(n) prescale divisor */
+#define SCA_TEPR_DIV_2 0x01
+#define SCA_TEPR_DIV_4 0x02
+#define SCA_TEPR_DIV_8 0x03
+#define SCA_TEPR_DIV_16 0x04
+#define SCA_TEPR_DIV_32 0x05
+#define SCA_TEPR_DIV_64 0x06
+#define SCA_TEPR_DIV_128 0x06
+
/* TX and RX Clock Source */
#define CLK_LINE 0x00 /* TX/RX line input */
diff --git a/sys/dev/ic/hd64570var.h b/sys/dev/ic/hd64570var.h
index 57490268f23..9f4fb2ec977 100644
--- a/sys/dev/ic/hd64570var.h
+++ b/sys/dev/ic/hd64570var.h
@@ -1,6 +1,7 @@
-/* $NetBSD: hd64570var.h,v 1.2 1998/10/28 16:26:01 kleink Exp $ */
+/* $NetBSD: hd64570var.h,v 1.3 2000/01/04 06:36:29 chopps Exp $ */
/*
+ * Copyright (c) 1999 Christian E. Hopps
* Copyright (c) 1998 Vixie Enterprises
* All rights reserved.
*
@@ -43,6 +44,13 @@
#define SCA_USE_FASTQ /* use a split queue, one for fast traffic */
+#define SCA_MTU 1500 /* hard coded */
+
+#ifndef SCA_BSIZE
+#define SCA_BSIZE (SCA_MTU + 4) /* room for HDLC as well */
+#endif
+
+
struct sca_softc;
typedef struct sca_port sca_port_t;
typedef struct sca_desc sca_desc_t;
@@ -51,13 +59,13 @@ typedef struct sca_desc sca_desc_t;
* device DMA descriptor
*/
struct sca_desc {
- u_int16_t cp; /* chain pointer */
- u_int16_t bp; /* buffer pointer (low bits) */
- u_int8_t bpb; /* buffer pointer (high bits) */
- u_int8_t unused0;
- u_int16_t len; /* total length */
- u_int8_t stat; /* status */
- u_int8_t unused1;
+ u_int16_t sd_chainp; /* chain pointer */
+ u_int16_t sd_bufp; /* buffer pointer (low bits) */
+ u_int8_t sd_hbufp; /* buffer pointer (high bits) */
+ u_int8_t sd_unused0;
+ u_int16_t sd_buflen; /* total length */
+ u_int8_t sd_stat; /* status */
+ u_int8_t sd_unused1;
};
#define SCA_DESC_EOT 0x01
#define SCA_DESC_CRC 0x04
@@ -84,23 +92,39 @@ struct sca_port {
u_int32_t cka_lastrx;
/*
+ * clock values, clockrate = sysclock / tmc / 2^div;
+ */
+ u_int8_t sp_eclock; /* enable external clock generate */
+ u_int8_t sp_rxs; /* recv clock source */
+ u_int8_t sp_txs; /* transmit clock source */
+ u_int8_t sp_tmc; /* clock constant */
+
+ /*
* start of each important bit of information for transmit and
* receive buffers.
+ *
+ * note: for non-dma the phys and virtual version should be
+ * the same value and should be an _offset_ from the beginning
+ * of mapped memory described by sc_memt/sc_memh.
*/
- u_int32_t txdesc_p;
- sca_desc_t *txdesc;
- u_int32_t txbuf_p;
- u_int8_t *txbuf;
- volatile u_int txcur; /* last descriptor in chain */
- volatile u_int txinuse; /* descriptors in use */
- volatile u_int txstart; /* start descriptor */
-
- u_int32_t rxdesc_p;
- sca_desc_t *rxdesc;
- u_int32_t rxbuf_p;
- u_int8_t *rxbuf;
- u_int rxstart; /* index of first descriptor */
- u_int rxend; /* index of last descriptor */
+ u_int sp_ntxdesc; /* number of tx descriptors */
+ u_int32_t sp_txdesc_p; /* paddress of first tx desc */
+ sca_desc_t *sp_txdesc; /* vaddress of first tx desc */
+ u_int32_t sp_txbuf_p; /* paddress of first tx buffer */
+ u_int8_t *sp_txbuf; /* vaddress of first tx buffer */
+
+ volatile u_int sp_txcur; /* last descriptor in chain */
+ volatile u_int sp_txinuse; /* descriptors in use */
+ volatile u_int sp_txstart; /* start descriptor */
+
+ u_int sp_nrxdesc; /* number of rx descriptors */
+ u_int32_t sp_rxdesc_p; /* paddress of first rx desc */
+ sca_desc_t *sp_rxdesc; /* vaddress of first rx desc */
+ u_int32_t sp_rxbuf_p; /* paddress of first rx buffer */
+ u_int8_t *sp_rxbuf; /* vaddress of first rx buffer */
+
+ u_int sp_rxstart; /* index of first descriptor */
+ u_int sp_rxend; /* index of last descriptor */
struct ifnet sp_if; /* the network information */
struct ifqueue linkq; /* link-level packets are high prio */
@@ -119,8 +143,9 @@ struct sca_port {
* softc structure for the chip itself
*/
struct sca_softc {
- struct device *parent; /* our parent device, or NULL */
- int sc_numports; /* number of ports present */
+ struct device *sc_parent; /* our parent device, or NULL */
+ int sc_numports; /* number of ports present */
+ u_int32_t sc_baseclock; /* the base operating clock */
/*
* a callback into the parent, since the SCA chip has no control
@@ -129,24 +154,66 @@ struct sca_softc {
*
* If the function pointer is NULL, no callback is specified.
*/
- void (*dtr_callback) __P((void *aux, int port, int state));
- void *dtr_aux;
-
- sca_port_t sc_ports[2];
- bus_space_handle_t sc_ioh;
- bus_space_tag_t sc_iot;
-
- bus_dma_tag_t sc_dmat; /* bus dma tag */
- bus_dmamap_t sc_dmam; /* bus dma map */
- bus_dma_segment_t sc_seg; /* bus dma segment allocated */
- caddr_t sc_dma_addr; /* kva address of segment */
- u_long sc_allocsize; /* size of region */
+ void *sc_aux;
+ void (*sc_dtr_callback)(void *aux, int port, int state);
+ void (*sc_clock_callback)(void *aux, int port, int state);
+
+ /* used to read and write the device registers */
+ u_int8_t (*sc_read_1)(struct sca_softc *, u_int);
+ u_int16_t (*sc_read_2)(struct sca_softc *, u_int);
+ void (*sc_write_1)(struct sca_softc *, u_int, u_int8_t);
+ void (*sc_write_2)(struct sca_softc *, u_int, u_int16_t);
+
+ sca_port_t sc_ports[2];
+
+ bus_space_tag_t sc_iot; /* io space for registers */
+ bus_space_handle_t sc_ioh; /* io space for registers */
+
+ int sc_usedma;
+ union {
+ struct {
+ bus_space_tag_t p_memt; /* mem for non-dma */
+ bus_space_handle_t p_memh; /* mem for non-dma */
+ bus_space_handle_t p_sca_ioh[16]; /* io for sca regs */
+ bus_size_t p_pagesize; /* memory page size */
+ bus_size_t p_pagemask; /* memory page mask */
+ u_int p_pageshift; /* memory page shift */
+ bus_size_t p_npages; /* num mem pages */
+
+ void (*p_set_page)(struct sca_softc *, bus_addr_t);
+ void (*p_page_on)(struct sca_softc *);
+ void (*p_page_off)(struct sca_softc *);
+ } u_paged;
+ struct {
+ bus_dma_tag_t d_dmat; /* bus dma tag */
+ bus_dmamap_t d_dmam; /* bus dma map */
+ bus_dma_segment_t d_seg; /* bus dma segment */
+ caddr_t d_dma_addr; /* kva of segment */
+ bus_size_t d_allocsize; /* size of region */
+ } u_dma;
+ } sc_u;
};
-
-
-int sca_init(struct sca_softc *, u_int);
+#define scu_memt sc_u.u_paged.p_memt
+#define scu_memh sc_u.u_paged.p_memh
+#define scu_sca_ioh sc_u.u_paged.p_sca_ioh
+#define scu_pagesize sc_u.u_paged.p_pagesize
+#define scu_pagemask sc_u.u_paged.p_pagemask
+#define scu_pageshift sc_u.u_paged.p_pageshift
+#define scu_npages sc_u.u_paged.p_npages
+#define scu_set_page sc_u.u_paged.p_set_page
+#define scu_page_on sc_u.u_paged.p_page_on
+#define scu_page_off sc_u.u_paged.p_page_off
+#define scu_dmat sc_u.u_dma.d_dmat
+#define scu_dmam sc_u.u_dma.d_dmam
+#define scu_seg sc_u.u_dma.d_seg
+#define scu_dma_addr sc_u.u_dma.d_dma_addr
+#define scu_allocsize sc_u.u_dma.d_allocsize
+
+void sca_init(struct sca_softc *);
void sca_port_attach(struct sca_softc *, u_int);
int sca_hardintr(struct sca_softc *);
void sca_shutdown(struct sca_softc *);
+void sca_get_base_clock(struct sca_softc *);
+void sca_print_clock_info(struct sca_softc *);
#endif /* _DEV_IC_HD64570VAR_H_ */