-/* $OpenBSD: if_sn.c,v 1.9 1997/03/12 13:20:31 briggs Exp $
-*/
+/* $OpenBSD: if_sn.c,v 1.10 1997/03/14 14:11:34 briggs Exp $ */
/*
* National Semiconductor SONIC Driver
#include "nubus.h"
-#define SWR(a, x) (a) = (x)
-#define SRD(a) ((a) & 0xffff)
+/*
+ * Register access macros:
+ * SWR is "Sonic Write Register"
+ * SRD is "Sonic Read Register"
+ */
+#define SWR(a, x) (a) = (x)
+#define SRD(a) ((a) & 0xffff)
#define wbflush()
static void snwatchdog __P((struct ifnet *));
static int sninit __P((struct sn_softc *sc));
static int snstop __P((struct sn_softc *sc));
-static int sonicput32 __P((struct sn_softc *sc, struct mbuf *m0));
-static int sonicput16 __P((struct sn_softc *sc, struct mbuf *m0));
+static int sonicput __P((struct sn_softc *sc, struct mbuf *m0));
static void snintr __P((void *, int));
static int snioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
static void snstart __P((struct ifnet *ifp));
static void snreset __P((struct sn_softc *sc));
-static void sntxint16 __P((struct sn_softc *));
-static void sntxint32 __P((struct sn_softc *));
-static void snrxint16 __P((struct sn_softc *));
-static void snrxint32 __P((struct sn_softc *));
-
void camdump __P((struct sn_softc *sc));
+struct cfdriver sn_cd = {
+ NULL, "sn", DV_IFNET
+};
+
#undef assert
#undef _assert
#ifdef NDEBUG
-#define assert(e) ((void)0)
-#define _assert(e) ((void)0)
+#define assert(e) ((void)0)
+#define _assert(e) ((void)0)
#else
-#define _assert(e) assert(e)
+#define _assert(e) assert(e)
#ifdef __STDC__
-#define assert(e) ((e) ? (void)0 : __assert("sn ", __FILE__, __LINE__, #e))
-#else /* PCC */
-#define assert(e) ((e) ? (void)0 : __assert("sn "__FILE__, __LINE__, "e"))
+#define assert(e) ((e) ? (void)0 : __assert("sn ", __FILE__, __LINE__, #e))
+#else /* PCC */
+#define assert(e) ((e) ? (void)0 : __assert("sn "__FILE__, __LINE__, "e"))
#endif
#endif
int ethdebug = 0;
-#define ROUNDUP(p, N) (((int) p + N - 1) & ~(N - 1))
+/*
+ * SONIC buffers need to be aligned 16 or 32 bit aligned.
+ * These macros calculate and verify alignment.
+ */
+#define ROUNDUP(p, N) (((int) p + N - 1) & ~(N - 1))
+
+#define SOALIGN(m, array) (m ? (ROUNDUP(array, 4)) : (ROUNDUP(array, 2)))
#define LOWER(x) ((unsigned)(x) & 0xffff)
#define UPPER(x) ((unsigned)(x) >> 16)
/*
- * Nicely aligned pointers into the SONIC buffers
- * p_ points at physical (K1_SEG) addresses.
+ * Interface exists: make available by filling in network interface
+ * record. System will initialize the interface when it is ready
+ * to accept packets.
*/
-
-/* Meta transmit descriptors */
-struct mtd {
- struct mtd *mtd_link;
- void *mtd_txp;
- int mtd_vtxp;
- unsigned char *mtd_buf;
-} mtda[NTDA];
-
-struct mtd *mtdfree; /* list of free meta transmit descriptors */
-struct mtd *mtdhead; /* head of descriptors assigned to chip */
-struct mtd *mtdtail; /* tail of descriptors assigned to chip */
-struct mtd *mtdnext; /* next descriptor to give to chip */
-
-void mtd_free __P((struct mtd *));
-struct mtd *mtd_alloc __P((void));
-
-struct cfdriver sn_cd = {
- NULL, "sn", DV_IFNET
-};
-
void
snsetup(sc)
struct sn_softc *sc;
*/
p = &sc->space[0];
pp = (unsigned char *)ROUNDUP ((int)p, NBPG);
+ p = pp;
- if ((RRASIZE + CDASIZE + RDASIZE + TDASIZE) > NBPG) {
- printf ("sn: sizeof RRA (%d) + CDA (%d) + "
- "RDA (%d) + TDA (%d) > NBPG (%d). Punt!\n",
- RRASIZE, CDASIZE, RDASIZE, TDASIZE, NBPG);
- return;
+ for (i = 0; i < NRRA; i++) {
+ sc->p_rra[i] = (void *)p;
+ sc->v_rra[i] = kvtop(p);
+ p += RXRSRC_SIZE(sc);
}
+ sc->v_rea = kvtop(p);
- p = pp;
- sc->p_rra = (void *) p;
- sc->v_rra = kvtop((caddr_t) sc->p_rra);
- p += RRASIZE;
+ p = (unsigned char *)SOALIGN(sc, p);
sc->p_cda = (void *) (p);
- sc->v_cda = kvtop((caddr_t) sc->p_cda);
- p += CDASIZE;
+ sc->v_cda = kvtop(p);
+ p += CDA_SIZE(sc);
- sc->p_rda = (void *) p;
- sc->v_rda = kvtop((caddr_t) sc->p_rda);
- p += RDASIZE;
+ p = (unsigned char *)SOALIGN(sc, p);
+
+ for (i = 0; i < NRDA; i++) {
+ sc->p_rda[i] = (void *) p;
+ sc->v_rda[i] = kvtop(p);
+ p += RXPKT_SIZE(sc);
+ }
+
+ p = (unsigned char *)SOALIGN(sc, p);
+
+ for (i = 0; i < NTDA; i++) {
+ struct mtd *mtdp = &sc->mtda[i];
+ mtdp->mtd_txp = (void *)p;
+ mtdp->mtd_vtxp = kvtop(p);
+ p += TXP_SIZE(sc);
+ }
- sc->p_tda = (void *) p;
- sc->v_tda = kvtop((caddr_t) sc->p_tda);
- p += TDASIZE;
+ p = (unsigned char *)SOALIGN(sc, p);
+
+ if ((p - pp) > NBPG) {
+ printf ("sn: sizeof RRA (%ld) + CDA (%ld) +"
+ "RDA (%ld) + TDA (%ld) > NBPG (%d). Punt!\n",
+ (ulong)sc->p_cda - (ulong)sc->p_rra[0],
+ (ulong)sc->p_rda[0] - (ulong)sc->p_cda,
+ (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_rda[0],
+ (ulong)p - (ulong)sc->mtda[0].mtd_txp,
+ NBPG);
+ return;
+ }
p = pp + NBPG;
printf(" address %s\n", ether_sprintf(sc->sc_enaddr));
#if 0
-printf("sonic buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x\n",
- sc->p_rra, sc->p_cda, sc->p_rda, sc->p_tda);
+printf("sonic buffers: rra=%p cda=0x%x rda=0x%x tda=0x%x\n",
+ sc->p_rra[0], sc->p_cda, sc->p_rda[0], sc->mtda[0].mtd_txp);
#endif
bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
ifp->if_start = snstart;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_watchdog = snwatchdog;
-
#if NBPFILTER > 0
bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
-
if_attach(ifp);
ether_ifattach(ifp);
- if (sc->sc_is16) {
- sc->rxint = snrxint16;
- sc->txint = sntxint16;
- } else {
- sc->rxint = snrxint32;
- sc->txint = sntxint32;
- }
add_nubus_intr(sc->slotno, snintr, (void *) sc);
}
struct ifaddr *ifa;
struct sn_softc *sc = ifp->if_softc;
int s = splnet(), err = 0;
- int temp;
+ int temp;
switch (cmd) {
(ifp->if_flags & IFF_RUNNING) == 0)
(void)sninit(ifp->if_softc);
/*
- * If the state of the promiscuous bit changes, the
-interface
+ * If the state of the promiscuous bit changes, the interface
* must be reset to effect the change.
*/
if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
{
struct sn_softc *sc = ifp->if_softc;
struct mbuf *m;
- int len;
+ int len;
if ((sc->sc_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
return;
return;
}
+ if (sc->sc_csr->s_cr & CR_TXP) {
+ return;
+ }
+
IF_DEQUEUE(&sc->sc_if.if_snd, m);
if (m == 0)
return;
* the Tx ring, then send the packet directly. Otherwise append
* it to the o/p queue.
*/
- if (sc->sc_is16) {
- len = sonicput16(sc, m);
- } else {
- len = sonicput32(sc, m);
- }
+ len = sonicput(sc, m);
#if 0
if (len != m->m_pkthdr.len) {
printf("snstart: len %d != m->m_pkthdr.len %d.\n",
sc->txb_inuse++;
sc->sc_if.if_opackets++; /* # of pkts */
- sc->sc_sum.ls_opacks++; /* # of pkts */
+ sc->sc_sum.ls_opacks++; /* # of pkts */
/* Jump back for possibly more punishment. */
goto outloop;
* the address or switch the i/f on.
*/
void caminitialise __P((struct sn_softc *));
-void camentry __P((struct sn_softc *, int, unsigned char *));
+void camentry __P((struct sn_softc *, int, unsigned char *ea));
void camprogram __P((struct sn_softc *));
void initialise_tda __P((struct sn_softc *));
void initialise_rda __P((struct sn_softc *));
s = splnet();
- csr->s_cr = CR_RST; /* s_dcr only accessable reset mode! */
+ csr->s_cr = CR_RST; /* s_dcr only accessable reset mode! */
/* config it */
- csr->s_dcr = sc->s_dcr;
+ csr->s_dcr = sc->s_dcr | (sc->bitmode ? DCR_DW32 : DCR_DW16);
csr->s_rcr = RCR_BRD | RCR_LBNONE;
csr->s_imr = IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN;
/* free all receive buffers (currently static so nothing to do) */
/* free all pending transmit mbufs */
- while ((mtd = mtdhead) != NULL) {
- mtdhead = mtdhead->mtd_link;
+ while (sc->mtd_hw != sc->mtd_free) {
+ mtd = &sc->mtda[sc->mtd_hw];
mtd->mtd_buf = 0;
- mtd_free(mtd);
+ if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0;
}
- mtdnext = mtd_alloc();
sc->txb_inuse = 0;
sc->sc_if.if_timer = 0;
struct ifnet *ifp;
{
struct sn_softc *sc = ifp->if_softc;
- int temp;
- u_long status;
+ struct mtd *mtd;
+ int temp;
- if (mtdhead && mtdhead->mtd_buf) {
+ if (sc->mtd_hw != sc->mtd_free) {
/* something still pending for transmit */
- if (sc->sc_is16) {
- status = ((struct _short_TXpkt *)
- mtdhead->mtd_txp)->status;
- } else {
- status = ((struct TXpkt *) mtdhead->mtd_txp)->status;
- }
- if (status == 0)
+ mtd = &sc->mtda[sc->mtd_hw];
+ if (SRO(sc->bitmode, mtd->mtd_txp, TXP_STATUS) == 0)
log(LOG_ERR, "%s: Tx - timeout\n",
sc->sc_dev.dv_xname);
else
log(LOG_ERR, "%s: Tx - lost interrupt\n",
- sc->sc_dev.dv_xname);
+ sc->sc_dev.dv_xname);
temp = sc->sc_if.if_flags & IFF_UP;
snreset(sc);
sc->sc_if.if_flags |= temp;
}
/*
- * stuff packet into sonic (at splnet) (16-bit)
+ * stuff packet into sonic (at splnet)
*/
static int
-sonicput16(sc, m0)
+sonicput(sc, m0)
struct sn_softc *sc;
struct mbuf *m0;
{
- struct sonic_reg *csr = sc->sc_csr;
- unsigned char *buff, *buffer, *data;
- struct _short_TXpkt *txp;
- struct mtd *mtdnew;
- struct mbuf *m;
- unsigned int len = 0;
- unsigned int totlen = 0;
+ struct sonic_reg *csr = sc->sc_csr;
+ unsigned char *buff, *buffer;
+ void *txp;
+ struct mtd *mtdp;
+ struct mbuf *m;
+ unsigned int len = 0;
+ unsigned int totlen = 0;
+ int mtd_free = sc->mtd_free;
+ int mtd_next;
+ int txb_new = sc->txb_new;
/* grab the replacement mtd */
- if ((mtdnew = mtd_alloc()) == 0)
- return (0);
-
- /* We are guaranteed, if we get here, that the xmit buffer is free. */
- buff = buffer = sc->tbuf[sc->txb_new];
-
- /* this packet goes to mdtnext fill in the TDA */
- mtdnext->mtd_buf = buffer;
- txp = mtdnext->mtd_txp;
- SWR(txp->config, 0);
-
- for (m = m0; m; m = m->m_next) {
- data = mtod(m, u_char *);
- len = m->m_len;
- totlen += len;
- bcopy(data, buff, len);
- buff += len;
- }
- if (totlen >= TXBSIZE) {
- panic("packet overflow in sonicput.");
- }
- SWR(txp->u[0].frag_ptrlo, LOWER(sc->vtbuf[sc->txb_new]));
- SWR(txp->u[0].frag_ptrhi, UPPER(sc->vtbuf[sc->txb_new]));
- SWR(txp->u[0].frag_size, totlen);
-
- if (totlen < ETHERMIN + sizeof(struct ether_header)) {
- int pad = ETHERMIN + sizeof(struct ether_header) - totlen;
- bzero(buffer + totlen, pad);
- SWR(txp->u[0].frag_size, pad + SRD(txp->u[0].frag_size));
- totlen = ETHERMIN + sizeof(struct ether_header);
- }
- SWR(txp->frag_count, 1);
- SWR(txp->pkt_size, totlen);
+ mtdp = &sc->mtda[mtd_free];
- /* link onto the next mtd that will be used */
- SWR(txp->u[1].tlink, LOWER(mtdnew->mtd_vtxp) | EOL);
-
- if (mtdhead == 0) {
- /* no current transmit list start with this one */
- mtdtail = mtdhead = mtdnext;
- csr->s_ctda = LOWER(mtdnext->mtd_vtxp);
- } else {
- /*
- * have a transmit list append it to end note
- * mtdnext is already physicaly linked to mtdtail in
- * mtdtail->mtd_txp->u[mtdtail->mtd_txp->frag_count].tlink
- */
- struct _short_TXpkt *tp;
+ if ((mtd_next = mtd_free + 1) == NTDA)
+ mtd_next = 0;
- tp = (struct _short_TXpkt *) mtdtail->mtd_txp;
- SWR(tp->u[tp->frag_count].tlink,
- SRD(tp->u[tp->frag_count].tlink) & ~EOL);
- mtdtail = mtdnext;
- }
- mtdnext->mtd_link = mtdnew;
- mtdnext = mtdnew;
-
- /* make sure chip is running */
- wbflush();
- csr->s_cr = CR_TXP;
- wbflush();
- sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
- return (totlen);
-}
-
-/*
- * 32-bit version of sonicput
- */
-static int
-sonicput32(sc, m0)
- struct sn_softc *sc;
- struct mbuf *m0;
-{
- struct sonic_reg *csr = sc->sc_csr;
- unsigned char *buff, *buffer, *data;
- struct TXpkt *txp;
- struct mtd *mtdnew;
- struct mbuf *m;
- unsigned int len = 0;
- unsigned int totlen = 0;
-
- /* grab the replacement mtd */
- if ((mtdnew = mtd_alloc()) == 0)
+ if (mtd_next == sc->mtd_hw) {
return (0);
+ }
/* We are guaranteed, if we get here, that the xmit buffer is free. */
- buff = buffer = sc->tbuf[sc->txb_new];
+ buff = buffer = sc->tbuf[txb_new];
- /* this packet goes to mdtnext fill in the TDA */
- mtdnext->mtd_buf = buffer;
- txp = mtdnext->mtd_txp;
- SWR(txp->config, 0);
+ /* this packet goes to mtdnext fill in the TDA */
+ mtdp->mtd_buf = buffer;
+ txp = mtdp->mtd_txp;
+ SWO(sc->bitmode, txp, TXP_CONFIG, 0);
for (m = m0; m; m = m->m_next) {
- data = mtod(m, u_char *);
+ unsigned char *data = mtod(m, u_char *);
len = m->m_len;
totlen += len;
bcopy(data, buff, len);
if (totlen >= TXBSIZE) {
panic("packet overflow in sonicput.");
}
- SWR(txp->u[0].frag_ptrlo, LOWER(sc->vtbuf[sc->txb_new]));
- SWR(txp->u[0].frag_ptrhi, UPPER(sc->vtbuf[sc->txb_new]));
- SWR(txp->u[0].frag_size, totlen);
+ SWO(sc->bitmode, txp, TXP_FRAGOFF+(0*TXP_FRAGSIZE)+TXP_FPTRLO,
+ LOWER(sc->vtbuf[txb_new]));
+ SWO(sc->bitmode, txp, TXP_FRAGOFF+(0*TXP_FRAGSIZE)+TXP_FPTRHI,
+ UPPER(sc->vtbuf[txb_new]));
if (totlen < ETHERMIN + sizeof(struct ether_header)) {
int pad = ETHERMIN + sizeof(struct ether_header) - totlen;
bzero(buffer + totlen, pad);
- SWR(txp->u[0].frag_size, pad + SRD(txp->u[0].frag_size));
totlen = ETHERMIN + sizeof(struct ether_header);
}
- SWR(txp->frag_count, 1);
- SWR(txp->pkt_size, totlen);
+
+ SWO(sc->bitmode, txp, TXP_FRAGOFF+(0*TXP_FRAGSIZE)+TXP_FSIZE,
+ totlen);
+ SWO(sc->bitmode, txp, TXP_FRAGCNT, 1);
+ SWO(sc->bitmode, txp, TXP_PKTSIZE, totlen);
/* link onto the next mtd that will be used */
- SWR(txp->u[1].tlink, LOWER(mtdnew->mtd_vtxp) | EOL);
+ SWO(sc->bitmode, txp, TXP_FRAGOFF+(1*TXP_FRAGSIZE)+TXP_FPTRLO,
+ LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL);
- if (mtdhead == 0) {
- /* no current transmit list start with this one */
- mtdtail = mtdhead = mtdnext;
- csr->s_ctda = LOWER(mtdnext->mtd_vtxp);
- } else {
- /*
- * have a transmit list append it to end note
- * mtdnext is already physicaly linked to mtdtail in
- * mtdtail->mtd_txp->u[mtdtail->mtd_txp->frag_count].tlink
- */
- struct TXpkt *tp;
+ /*
+ * The previous txp.tlink currently contains a pointer to
+ * our txp | EOL. Want to clear the EOL, so write our
+ * pointer to the previous txp.
+ */
+ SWO(sc->bitmode, sc->mtda[sc->mtd_prev].mtd_txp, sc->mtd_tlinko,
+ LOWER(mtdp->mtd_vtxp));
- tp = (struct TXpkt *) mtdtail->mtd_txp;
- SWR(tp->u[tp->frag_count].tlink,
- SRD(tp->u[tp->frag_count].tlink) & ~EOL);
- mtdtail = mtdnext;
- }
- mtdnext->mtd_link = mtdnew;
- mtdnext = mtdnew;
+ sc->mtd_prev = mtd_free;
+ sc->mtd_free = mtd_next;
/* make sure chip is running */
wbflush();
csr->s_cr = CR_TXP;
wbflush();
- sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
+ sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
+
return (totlen);
}
+void sonictxint __P((struct sn_softc *));
+void sonicrxint __P((struct sn_softc *));
+
int sonic_read __P((struct sn_softc *, caddr_t, int));
struct mbuf *sonic_get __P((struct sn_softc *, struct ether_header *, int));
-void
-mtd_free(mtd)
- struct mtd *mtd;
-{
- mtd->mtd_link = mtdfree;
- mtdfree = mtd;
-}
-
-struct mtd *
-mtd_alloc()
-{
- struct mtd *mtd = mtdfree;
-
- if (mtd) {
- mtdfree = mtd->mtd_link;
- mtd->mtd_link = 0;
- }
- return (mtd);
-}
-
/*
* CAM support
*/
caminitialise(sc)
struct sn_softc *sc;
{
- int i;
+ int i;
+ void *p_cda = sc->p_cda;
+ int bitmode = sc->bitmode;
- if (sc->sc_is16) {
- struct _short_CDA *p_cda;
-
- p_cda = (struct _short_CDA *) sc->p_cda;
- for (i = 0; i < MAXCAM; i++)
- SWR(p_cda->desc[i].cam_ep, i);
- SWR(p_cda->enable, 0);
- } else {
- struct CDA *p_cda;
-
- p_cda = (struct CDA *) sc->p_cda;
- for (i = 0; i < MAXCAM; i++)
- SWR(p_cda->desc[i].cam_ep, i);
- SWR(p_cda->enable, 0);
- }
+ for (i = 0; i < MAXCAM; i++)
+ SWO(bitmode, p_cda, (CDA_CAMDESC * i + CDA_CAMEP), i);
+ SWO(bitmode, p_cda, CDA_ENABLE, 0);
}
void
camentry(sc, entry, ea)
- struct sn_softc *sc;
int entry;
unsigned char *ea;
+ struct sn_softc *sc;
{
- if (sc->sc_is16) {
- struct _short_CDA *p_cda;
-
- p_cda = (struct _short_CDA *) sc->p_cda;
- SWR(p_cda->desc[entry].cam_ep, entry);
- SWR(p_cda->desc[entry].cam_ap2, (ea[5] << 8) | ea[4]);
- SWR(p_cda->desc[entry].cam_ap1, (ea[3] << 8) | ea[2]);
- SWR(p_cda->desc[entry].cam_ap0, (ea[1] << 8) | ea[0]);
- SWR(p_cda->enable, SRD(p_cda->enable) | (1 << entry));
- } else {
- struct CDA *p_cda;
-
- p_cda = (struct CDA *) sc->p_cda;
- SWR(p_cda->desc[entry].cam_ep, entry);
- SWR(p_cda->desc[entry].cam_ap2, (ea[5] << 8) | ea[4]);
- SWR(p_cda->desc[entry].cam_ap1, (ea[3] << 8) | ea[2]);
- SWR(p_cda->desc[entry].cam_ap0, (ea[1] << 8) | ea[0]);
- SWR(p_cda->enable, SRD(p_cda->enable) | (1 << entry));
- }
+ int bitmode = sc->bitmode;
+ void *p_cda = sc->p_cda;
+ int camoffset = entry * CDA_CAMDESC;
+
+ SWO(bitmode, p_cda, camoffset + CDA_CAMEP, entry);
+ SWO(bitmode, p_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]);
+ SWO(bitmode, p_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]);
+ SWO(bitmode, p_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]);
+ SWO(bitmode, p_cda, CDA_ENABLE, (1 << entry));
}
void
{
struct sonic_reg *csr;
struct mtd *mtd;
- int i, psize;
- u_long p;
+ int i;
csr = sc->sc_csr;
- mtdfree = mtdhead = mtdtail = (struct mtd *) 0;
-
- p = (u_long) sc->p_tda;
- psize = (sc->sc_is16 ?
- sizeof(struct _short_TXpkt) : sizeof(struct TXpkt));
-
for (i = 0; i < NTDA; i++) {
- mtd = &mtda[i];
- mtd->mtd_txp = (struct TXpkt *) p;
- mtd->mtd_vtxp = kvtop((caddr_t) mtd->mtd_txp);
+ mtd = &sc->mtda[i];
mtd->mtd_buf = 0;
- mtd_free(mtd);
- p += psize;
}
- mtdnext = mtd_alloc();
- csr->s_utda = UPPER(sc->v_tda);
+ sc->mtd_hw = 0;
+ sc->mtd_prev = NTDA-1;
+ sc->mtd_free = 0;
+ sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO;
+
+ csr->s_utda = UPPER(sc->mtda[0].mtd_vtxp);
+ csr->s_ctda = LOWER(sc->mtda[0].mtd_vtxp);
}
void
struct sn_softc *sc;
{
struct sonic_reg *csr;
+ int bitmode = sc->bitmode;
int i;
csr = sc->sc_csr;
/* link the RDA's together into a circular list */
- if (sc->sc_is16) {
- int v_rda;
- struct _short_RXpkt *p_rda;
-
- p_rda = (struct _short_RXpkt *) sc->p_rda;
- for (i = 0; i < (NRDA - 1); i++) {
- SWR(p_rda[i].rlink,
- LOWER(v_rda + (i + 1) * sizeof(struct _short_RXpkt)));
- SWR(p_rda[i].in_use, 1);
- }
- SWR(p_rda[NRDA - 1].rlink, LOWER(v_rda) | EOL);
- SWR(p_rda[NRDA - 1].in_use, 1);
-
- /* mark end of receive descriptor list */
- sc->sc_lrxp = &p_rda[NRDA - 1];
- } else {
- int v_rda;
- struct RXpkt *p_rda;
-
- v_rda = sc->v_rda;
- p_rda = (struct RXpkt *) sc->p_rda;
- for (i = 0; i < (NRDA - 1); i++) {
- SWR(p_rda[i].rlink,
- LOWER(v_rda + (i + 1) * sizeof(struct RXpkt)));
- SWR(p_rda[i].in_use, 1);
- }
- SWR(p_rda[NRDA - 1].rlink, LOWER(v_rda) | EOL);
- SWR(p_rda[NRDA - 1].in_use, 1);
-
- /* mark end of receive descriptor list */
- sc->sc_lrxp = &p_rda[NRDA - 1];
+ for (i = 0; i < (NRDA - 1); i++) {
+ SWO(bitmode, sc->p_rda[i], RXPKT_RLINK, LOWER(sc->v_rda[i+1]));
+ SWO(bitmode, sc->p_rda[i], RXPKT_INUSE, 1);
}
+ SWO(bitmode, sc->p_rda[NRDA - 1], RXPKT_RLINK, LOWER(sc->v_rda[0]) | EOL);
+ SWO(bitmode, sc->p_rda[NRDA - 1], RXPKT_INUSE, 1);
+
+ /* mark end of receive descriptor list */
+ sc->sc_rdamark = NRDA - 1;
sc->sc_rxmark = 0;
- csr->s_urda = UPPER(sc->v_rda);
- csr->s_crda = LOWER(sc->v_rda);
+ SWR(csr->s_urda, UPPER(sc->v_rda[0]));
+ SWR(csr->s_crda, LOWER(sc->v_rda[0]));
wbflush();
}
struct sn_softc *sc;
{
struct sonic_reg *csr;
- int i;
- int rr_size;
+ int i;
+ unsigned int v;
+ int bitmode = sc->bitmode;
csr = sc->sc_csr;
- if (sc->sc_is16) {
- rr_size = sizeof(struct _short_RXrsrc);
- csr->s_eobc = RBASIZE(sc) / 2 - 1; /* must be >= MAXETHERPKT */
- } else {
- rr_size = sizeof(struct RXrsrc);
- csr->s_eobc = RBASIZE(sc) / 2 - 2; /* must be >= MAXETHERPKT */
- }
- csr->s_urra = UPPER(sc->v_rra);
- csr->s_rsa = LOWER(sc->v_rra);
- csr->s_rea = LOWER(sc->v_rra + (NRRA * rr_size));
- csr->s_rrp = LOWER(sc->v_rra);
+ if (bitmode)
+ csr->s_eobc = RBASIZE(sc) / 2 - 2; /* must be >= MAXETHERPKT */
+ else
+ csr->s_eobc = RBASIZE(sc) / 2 - 1; /* must be >= MAXETHERPKT */
+ csr->s_urra = UPPER(sc->v_rra[0]);
+ csr->s_rsa = LOWER(sc->v_rra[0]);
+ /* rea must point just past the end of the rra space */
+ csr->s_rea = LOWER(sc->v_rea);
+ csr->s_rrp = LOWER(sc->v_rra[0]);
/* fill up SOME of the rra with buffers */
- if (sc->sc_is16) {
- struct _short_RXrsrc *p_rra;
-
- p_rra = (struct _short_RXrsrc *) sc->p_rra;
- for (i = 0; i < NRBA; i++) {
- SWR(p_rra[i].buff_ptrhi, UPPER(kvtop(sc->rbuf[i])));
- SWR(p_rra[i].buff_ptrlo, LOWER(kvtop(sc->rbuf[i])));
- SWR(p_rra[i].buff_wchi, UPPER(RBASIZE(sc) / 2));
- SWR(p_rra[i].buff_wclo, LOWER(RBASIZE(sc) / 2));
- }
- } else {
- struct RXrsrc *p_rra;
-
- p_rra = (struct RXrsrc *) sc->p_rra;
- for (i = 0; i < NRBA; i++) {
- SWR(p_rra[i].buff_ptrhi, UPPER(kvtop(sc->rbuf[i])));
- SWR(p_rra[i].buff_ptrlo, LOWER(kvtop(sc->rbuf[i])));
- SWR(p_rra[i].buff_wchi, UPPER(RBASIZE(sc) / 2));
- SWR(p_rra[i].buff_wclo, LOWER(RBASIZE(sc) / 2));
- }
+ for (i = 0; i < NRBA; i++) {
+ v = kvtop(sc->rbuf[i]);
+ SWO(bitmode, sc->p_rra[i], RXRSRC_PTRHI, UPPER(v));
+ SWO(bitmode, sc->p_rra[i], RXRSRC_PTRLO, LOWER(v));
+ SWO(bitmode, sc->p_rra[i], RXRSRC_WCHI, UPPER(RBASIZE(sc) / 2));
+ SWO(bitmode, sc->p_rra[i], RXRSRC_WCLO, LOWER(RBASIZE(sc) / 2));
}
sc->sc_rramark = NRBA;
- csr->s_rwp = LOWER(sc->v_rra + (sc->sc_rramark * rr_size));
+ csr->s_rwp = LOWER(sc->v_rra[sc->sc_rramark]);
wbflush();
}
static void
snintr(arg, slot)
- void *arg;
- int slot;
+ void *arg;
+ int slot;
{
- struct sn_softc *sc = (struct sn_softc *)arg;
+ struct sn_softc *sc = (struct sn_softc *)arg;
struct sonic_reg *csr = sc->sc_csr;
- int isr;
+ int isr;
while ((isr = (csr->s_isr & ISR_ALL)) != 0) {
/* scrub the interrupts that we are going to service */
printf("sonic: unexpected interrupt status 0x%x\n", isr);
if (isr & (ISR_TXDN | ISR_TXER))
- (*sc->txint)(sc);
+ sonictxint(sc);
if (isr & ISR_PKTRX)
- (*sc->rxint)(sc);
+ sonicrxint(sc);
if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
if (isr & ISR_HBL)
}
/*
- * Transmit interrupt routine (16-bit)
- */
-static void
-sntxint16(sc)
- struct sn_softc *sc;
-{
- struct _short_TXpkt *txp;
- struct sonic_reg *csr;
- struct mtd *mtd;
-
- if (mtdhead == (struct mtd *) 0)
- return;
-
- csr = sc->sc_csr;
-
- while ((mtd = mtdhead) != NULL) {
- if (mtd->mtd_buf == 0)
- break;
-
- txp = (struct _short_TXpkt *) mtd->mtd_txp;
-
- if (SRD(txp->status) == 0) /* it hasn't really gone yet */
- return;
-
- if (ethdebug) {
- struct ether_header *eh;
-
- eh = (struct ether_header *) mtd->mtd_buf;
- printf("xmit status=0x%x len=%d type=0x%x from %s",
- txp->status,
- txp->pkt_size,
- htons(eh->ether_type),
- ether_sprintf(eh->ether_shost));
- printf(" (to %s)\n", ether_sprintf(eh->ether_dhost));
- }
- sc->txb_inuse--;
- mtd->mtd_buf = 0;
- mtdhead = mtd->mtd_link;
-
- mtd_free(mtd);
-
- /* XXX - Do stats here. */
-
- if ((SRD(txp->status) & TCR_PTX) == 0) {
- printf("sonic: Tx packet status=0x%x\n", txp->status);
-
- /* XXX - DG This looks bogus */
- if (mtdhead != mtdnext) {
- printf("resubmitting remaining packets\n");
- csr->s_ctda = LOWER(mtdhead->mtd_vtxp);
- csr->s_cr = CR_TXP;
- wbflush();
- return;
- }
- }
- }
- /* mtdhead should be at mtdnext (go) */
- mtdhead = 0;
-}
-
-/*
- * Transmit interrupt routine (32-bit)
+ * Transmit interrupt routine
*/
-static void
-sntxint32(sc)
+void
+sonictxint(sc)
struct sn_softc *sc;
{
- struct TXpkt *txp;
+ void *txp;
struct sonic_reg *csr;
- struct mtd *mtd;
+ struct mtd *mtd;
+ /* XXX DG make mtd_hw a local var */
- if (mtdhead == (struct mtd *) 0)
+ if (sc->mtd_hw == sc->mtd_free)
return;
csr = sc->sc_csr;
- while ((mtd = mtdhead) != NULL) {
+ while (sc->mtd_hw != sc->mtd_free) {
+ mtd = &sc->mtda[sc->mtd_hw];
if (mtd->mtd_buf == 0)
break;
txp = mtd->mtd_txp;
- if (SRD(txp->status) == 0) /* it hasn't really gone yet */
- return;
+ if (SRO(sc->bitmode, txp, TXP_STATUS) == 0)
+ return; /* it hasn't really gone yet */
if (ethdebug) {
struct ether_header *eh;
eh = (struct ether_header *) mtd->mtd_buf;
- printf("xmit status=0x%lx len=%ld type=0x%x from %s",
- txp->status,
- txp->pkt_size,
+ printf("xmit status=0x%x len=%d type=0x%x from %s",
+ SRO(sc->bitmode, txp, TXP_STATUS),
+ SRO(sc->bitmode, txp, TXP_PKTSIZE),
htons(eh->ether_type),
ether_sprintf(eh->ether_shost));
printf(" (to %s)\n", ether_sprintf(eh->ether_dhost));
}
sc->txb_inuse--;
mtd->mtd_buf = 0;
- mtdhead = mtd->mtd_link;
-
- mtd_free(mtd);
+ if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0;
/* XXX - Do stats here. */
- if ((SRD(txp->status) & TCR_PTX) == 0) {
- printf("sonic: Tx packet status=0x%lx\n", txp->status);
+ if ((SRO(sc->bitmode, txp, TXP_STATUS) & TCR_PTX) == 0) {
+ printf("sonic: Tx packet status=0x%x\n",
+ SRO(sc->bitmode, txp, TXP_STATUS));
/* XXX - DG This looks bogus */
- if (mtdhead != mtdnext) {
+ if (sc->mtd_hw != sc->mtd_free) {
printf("resubmitting remaining packets\n");
- csr->s_ctda = LOWER(mtdhead->mtd_vtxp);
+ mtd = &sc->mtda[sc->mtd_hw];
+ csr->s_ctda = LOWER(mtd->mtd_vtxp);
csr->s_cr = CR_TXP;
wbflush();
return;
}
}
}
- /* mtdhead should be at mtdnext (go) */
- mtdhead = 0;
}
/*
- * Receive interrupt routine (16-bit)
+ * Receive interrupt routine
*/
-static void
-snrxint16(sc)
+void
+sonicrxint(sc)
struct sn_softc *sc;
{
struct sonic_reg *csr = sc->sc_csr;
- struct _short_RXpkt *rxp, *p_rda;
- struct _short_RXrsrc *p_rra;
- int orra;
+ void *rda;
+ int orra;
int len;
+ int rramark;
+ int rdamark;
+ int bitmode = sc->bitmode;
+ void *tmp1;
+ void *tmp2;
- p_rra = (struct _short_RXrsrc *) sc->p_rra;
- p_rda = (struct _short_RXpkt *) sc->p_rda;
- rxp = &p_rda[sc->sc_rxmark];
+ rda = sc->p_rda[sc->sc_rxmark];
- while (SRD(rxp->in_use) == 0) {
- unsigned status = SRD(rxp->status);
+ while (SRO(bitmode, rda, RXPKT_INUSE) == 0) {
+ unsigned status = SRO(bitmode, rda, RXPKT_STATUS);
if ((status & RCR_LPKT) == 0)
printf("sonic: more than one packet in RBA!\n");
- orra = RBASEQ(SRD(rxp->seq_no)) & RRAMASK;
- len = SRD(rxp->byte_count)
- - sizeof(struct ether_header) - FCSSIZE;
+ orra = RBASEQ(SRO(bitmode, rda, RXPKT_SEQNO)) & RRAMASK;
+ len = SRO(bitmode, rda, RXPKT_BYTEC) -
+ sizeof(struct ether_header) - FCSSIZE;
if (status & RCR_PRX) {
if (sonic_read(sc, sc->rbuf[orra & RBAMASK], len)) {
sc->sc_if.if_ipackets++;
* sonic read didnt copy it out then we would have to
* wait !!
* (dont bother add it back in again straight away)
- */
- p_rra[sc->sc_rramark] = p_rra[orra];
-
- /* zap old rra for fun */
- p_rra[orra].buff_wchi = 0;
- p_rra[orra].buff_wclo = 0;
-
- sc->sc_rramark = (sc->sc_rramark + 1) & RRAMASK;
- csr->s_rwp = LOWER(sc->v_rra +
- (sc->sc_rramark * sizeof(struct _short_RXrsrc)));
- wbflush();
-
- /*
- * give receive descriptor back to chip simple
- * list is circular
- */
- SWR(rxp->in_use, 1);
- SWR(rxp->rlink, SRD(rxp->rlink) | EOL);
- SWR(((struct _short_RXpkt *) sc->sc_lrxp)->rlink,
- SRD(((struct _short_RXpkt *) sc->sc_lrxp)->rlink) & ~EOL);
- sc->sc_lrxp = (void *) rxp;
-
- if (++sc->sc_rxmark >= NRDA)
- sc->sc_rxmark = 0;
- rxp = &p_rda[sc->sc_rxmark];
- }
-}
-
-/*
- * Receive interrupt routine (normal 32-bit)
- */
-static void
-snrxint32(sc)
- struct sn_softc *sc;
-{
- struct sonic_reg *csr = sc->sc_csr;
- struct RXpkt *rxp, *p_rda;
- struct RXrsrc *p_rra;
- int orra;
- int len;
-
- p_rra = (struct RXrsrc *) sc->p_rra;
- p_rda = (struct RXpkt *) sc->p_rda;
- rxp = &p_rda[sc->sc_rxmark];
-
- while (SRD(rxp->in_use) == 0) {
- unsigned status = SRD(rxp->status);
- if ((status & RCR_LPKT) == 0)
- printf("sonic: more than one packet in RBA!\n");
-
- orra = RBASEQ(SRD(rxp->seq_no)) & RRAMASK;
- len = SRD(rxp->byte_count)
- - sizeof(struct ether_header) - FCSSIZE;
- if (status & RCR_PRX) {
- if (sonic_read(sc, sc->rbuf[orra & RBAMASK], len)) {
- sc->sc_if.if_ipackets++;
- sc->sc_sum.ls_ipacks++;
- sc->sc_missed = 0;
- }
- } else
- sc->sc_if.if_ierrors++;
-
- /*
- * give receive buffer area back to chip.
*
- * orra is now empty of packets and can be freed if
- * sonic read didnt copy it out then we would have to
- * wait !!
- * (dont bother add it back in again straight away)
+ * Really, we're doing p_rra[rramark] = p_rra[orra] but
+ * we have to use the macros because SONIC might be in
+ * 16 or 32 bit mode.
*/
- p_rra[sc->sc_rramark] = p_rra[orra];
+ rramark = sc->sc_rramark;
+ tmp1 = sc->p_rra[rramark];
+ tmp2 = sc->p_rra[orra];
+ SWO(bitmode, tmp1, RXRSRC_PTRLO,
+ SRO(bitmode, tmp2, RXRSRC_PTRLO));
+ SWO(bitmode, tmp1, RXRSRC_PTRHI,
+ SRO(bitmode, tmp2, RXRSRC_PTRHI));
+ SWO(bitmode, tmp1, RXRSRC_WCLO,
+ SRO(bitmode, tmp2, RXRSRC_WCLO));
+ SWO(bitmode, tmp1, RXRSRC_WCHI,
+ SRO(bitmode, tmp2, RXRSRC_WCHI));
/* zap old rra for fun */
- p_rra[orra].buff_wchi = 0;
- p_rra[orra].buff_wclo = 0;
+ SWO(bitmode, tmp2, RXRSRC_WCHI, 0);
+ SWO(bitmode, tmp2, RXRSRC_WCLO, 0);
- sc->sc_rramark = (sc->sc_rramark + 1) & RRAMASK;
- csr->s_rwp = LOWER(sc->v_rra +
- (sc->sc_rramark * sizeof(struct RXrsrc)));
+ sc->sc_rramark = (++rramark) & RRAMASK;
+ csr->s_rwp = LOWER(sc->v_rra[rramark]);
wbflush();
/*
* give receive descriptor back to chip simple
* list is circular
*/
- SWR(rxp->in_use, 1);
- SWR(rxp->rlink, SRD(rxp->rlink) | EOL);
- SWR(((struct RXpkt *) sc->sc_lrxp)->rlink,
- SRD(((struct RXpkt *) sc->sc_lrxp)->rlink) & ~EOL);
- sc->sc_lrxp = (void *) rxp;
+ rdamark = sc->sc_rdamark;
+ SWO(bitmode, rda, RXPKT_INUSE, 1);
+ SWO(bitmode, rda, RXPKT_RLINK,
+ SRO(bitmode, rda, RXPKT_RLINK) | EOL);
+ SWO(bitmode, sc->p_rda[rdamark], RXPKT_RLINK,
+ SRO(bitmode, sc->p_rda[rdamark], RXPKT_RLINK) & ~EOL);
+ sc->sc_rdamark = sc->sc_rxmark;
if (++sc->sc_rxmark >= NRDA)
sc->sc_rxmark = 0;
- rxp = &p_rda[sc->sc_rxmark];
+ rda = sc->p_rda[sc->sc_rxmark];
}
}
struct mbuf *m;
/*
- * Get pointer to ethernet header (in input buffer).
- * Deal with trailer protocol: if type is PUP trailer
- * get true type from first 16-bit word past data.
- * Remember that type was trailer by setting off.
- */
+ * Get pointer to ethernet header (in input buffer).
+ * Deal with trailer protocol: if type is PUP trailer
+ * get true type from first 16-bit word past data.
+ * Remember that type was trailer by setting off.
+ */
et = (struct ether_header *)pkt;
if (ethdebug) {
/*
* Check if there's a bpf filter listening on this interface.
* If so, hand off the raw packet to enet, then discard things
- * not destined for us (but be sure to keep
-broadcast/multicast).
+ * not destined for us (but be sure to keep broadcast/multicast).
*/
if (sc->sc_if.if_bpf) {
bpf_tap(sc->sc_if.if_bpf, pkt,
return(1);
}
-#define sonicdataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
+#define sonicdataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
/*
* munge the received packet into an mbuf chain
struct mbuf *m;
struct mbuf *top = 0, **mp = ⊤
int len;
- char *spkt = sonicdataaddr(eh, 0, caddr_t);
- char *epkt = spkt + datalen;
- char *cp = spkt;
+ char *spkt = sonicdataaddr(eh, 0, caddr_t);
+ char *epkt = spkt + datalen;
+ char *cp = spkt;
epkt = cp + datalen;
MGETHDR(m, M_DONTWAIT, MT_DATA);
len = m->m_len;
} else {
/*
- * Place initial small packet/header at end of mbuf.
- */
+ * Place initial small packet/header at end of mbuf.
+ */
if (len < m->m_len) {
if (top == 0 && len + max_linkhdr <= m->m_len)
m->m_data += max_linkhdr;
-/* $OpenBSD: if_snvar.h,v 1.1 1997/03/12 13:20:33 briggs Exp $ */
+/* $OpenBSD: if_snvar.h,v 1.2 1997/03/14 14:11:36 briggs Exp $ */
/*
* Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk)
* if_sonic.h -- National Semiconductor DP83932BVF (SONIC)
*/
+/*
+ * Memory access macros. Since we handle SONIC in 16 bit mode (PB5X0)
+ * and 32 bit mode (everything else) using a single GENERIC kernel
+ * binary, all structures have to be accessed using macros which can
+ * adjust the offsets appropriately.
+ */
+#define SWO(m, a, o, x) (m ? (*(u_int32_t *)((u_int32_t *)a + o) = (x)) : \
+ (*(u_int16_t *)((u_int16_t *)a + o) = (x)))
+#define SRO(m, a, o) (m ? (*(u_int32_t *)((u_int32_t *)a + o) & 0xffff) : \
+ (*(u_int16_t *)((u_int16_t *)a + o) & 0xffff))
+
/*
* buffer sizes in 32 bit mode
* 1 TXpkt is 4 hdr words + (3 * FRAGMAX) + 1 link word
* 1 Rda is 4 words == 16 bytes
*/
-#define NRRA 32 /* # receive resource descriptors */
-#define RRAMASK 0x1f /* the reason why it must be power of two */
-
#define NRBA 16 /* # receive buffers < NRRA */
#define RBAMASK 0x0f
-#define NRDA NRBA /* # receive descriptors */
+#define NRDA NRBA
#define NTDA 4 /* # transmit descriptors */
-
-#define CDASIZE sizeof(struct CDA)
-#define RRASIZE (NRRA*sizeof(struct RXrsrc))
-#define RDASIZE (NRDA*sizeof(struct RXpkt))
-#define TDASIZE (NTDA*sizeof(struct TXpkt))
+#define NRRA 32 /* # receive resource descriptors */
+#define RRAMASK 0x1f /* the reason why it must be power of two */
#define FCSSIZE 4 /* size of FCS appended to packets */
* maximum receive packet size plus 2 byte pad to make each
* one aligned. 4 byte slop (required for eobc)
*/
-#define RBASIZE(sc) \
- (sizeof(struct ether_header) + ETHERMTU + FCSSIZE + \
- ((sc)->sc_is16 ? 2 : 6))
+#define RBASIZE(sc) (sizeof(struct ether_header) + ETHERMTU + FCSSIZE + \
+ ((sc)->bitmode ? 6 : 2))
/*
* transmit buffer area
int ls_maxslots; /* max ring slots on transmit */
};
+typedef struct mtd {
+ void *mtd_txp;
+ int mtd_vtxp;
+ unsigned char *mtd_buf;
+} mtd_t;
+
/*
* The sn_softc for Mac68k if_sn.
*/
typedef struct sn_softc {
- struct device sc_dev;
- struct arpcom sc_arpcom;
-#define sc_if sc_arpcom.ac_if /* network visible interface */
-#define sc_enaddr sc_arpcom.ac_enaddr /* hardware ethernet address */
+ struct device sc_dev;
+ struct arpcom sc_arpcom;
+#define sc_if sc_arpcom.ac_if /* network visible interface */
+#define sc_enaddr sc_arpcom.ac_enaddr /* hardware ethernet address */
bus_space_tag_t sc_regt;
bus_space_handle_t sc_regh;
- int sc_is16;
-
- unsigned int s_dcr; /* DCR for this instance */
- int slotno;
+ struct sn_stats sc_sum;
+ short sc_iflags;
+ unsigned short bitmode; /* 32 bit mode == 1, 16 == 0 */
- struct sonic_reg *sc_csr; /* hardware pointer */
+ unsigned int s_dcr; /* DCR for this instance */
+ int slotno; /* Slot number */
+ struct sonic_reg *sc_csr; /* hardware pointer */
+ int sc_rxmark; /* pos. in rx ring for reading buffs */
- int sc_rxmark; /* pos. in rx ring for reading bufs */
+ int sc_rramark; /* index into p_rra of wp */
+ void *p_rra[NRRA]; /* RX resource descs */
+ int v_rra[NRRA]; /* DMA addresses of p_rra */
+ int v_rea; /* ptr to the end of the rra space */
- int sc_rramark; /* index into rra of wp */
+ int sc_rdamark;
+ void *p_rda[NRDA];
+ int v_rda[NRDA];
- int sc_txhead; /* index of first TDA passed to chip */
- int sc_missed; /* missed packet counter */
+ caddr_t rbuf[NRBA];
- int txb_cnt; /* total number of xmit buffers */
- int txb_inuse; /* number of active xmit buffers */
- int txb_new; /* index of next open slot. */
+ int sc_txhead; /*XXX idx of first TDA passed to chip */
+ int sc_missed; /* missed packet counter */
- void *sc_lrxp; /* last RDA available to chip */
+ int txb_cnt; /* total number of xmit buffers */
+ int txb_inuse; /* number of active xmit buffers */
+ int txb_new; /* index of next open slot. */
- struct sn_stats sc_sum;
- short sc_iflags;
+ struct mtd mtda[NTDA];
+ int mtd_hw; /* idx of first mtd given to hw */
+ int mtd_prev; /* idx of last mtd given to hardware */
+ int mtd_free; /* next free mtd to use */
+ int mtd_tlinko; /*
+ * offset of tlink of last txp given
+ * to SONIC. Need to clear EOL on
+ * this word to add a desc.
+ */
- void *p_rra; /* struct RXrsrc: receiver resource descriptors */
- int v_rra; /* DMA address of rra */
- void *p_rda; /* struct RXpkt: receiver desriptors */
- int v_rda;
- void *p_tda; /* struct TXpkt: transmitter descriptors */
- int v_tda;
- void *p_cda; /* struct CDA: CAM descriptors */
- int v_cda; /* DMA address of CDA */
+ caddr_t tbuf[NTXB];
+ int vtbuf[NTXB]; /* DMA address of tbuf */
- void (*rxint) __P((struct sn_softc *));
- void (*txint) __P((struct sn_softc *));
+ void *p_cda;
+ int v_cda;
- caddr_t rbuf[NRBA];
- caddr_t tbuf[NTXB];
- int vtbuf[NTXB];
- unsigned char space[(1 + 1 + 8 + 5) * NBPG];
+ unsigned char space[(1 + 1 + 8 + 5) * NBPG];
} sn_softc_t;
-
/*
* Accessing SONIC data structures and registers as 32 bit values
* makes code endianess independent. The SONIC is however always in
* will be received. Note that more than one packet may be
* packed into a single buffer if constraints permit.
*/
-struct RXrsrc {
- u_long buff_ptrlo; /* buffer address LO */
- u_long buff_ptrhi; /* buffer address HI */
- u_long buff_wclo; /* buffer size (16bit words) LO */
- u_long buff_wchi; /* buffer size (16bit words) HI */
-};
-struct _short_RXrsrc {
- u_short buff_ptrlo; /* buffer address LO */
- u_short buff_ptrhi; /* buffer address HI */
- u_short buff_wclo; /* buffer size (16bit words) LO */
- u_short buff_wchi; /* buffer size (16bit words) HI */
-};
+#define RXRSRC_PTRLO 0 /* buffer address LO */
+#define RXRSRC_PTRHI 1 /* buffer address HI */
+#define RXRSRC_WCLO 2 /* buffer size (16bit words) LO */
+#define RXRSRC_WCHI 3 /* buffer size (16bit words) HI */
+
+#define RXRSRC_SIZE(sc) (sc->bitmode ? (4 * 4) : (4 * 2))
/*
* Receive Descriptor
* This structure holds information about packets received.
*/
-struct RXpkt {
- u_long status; /* + receive status */
- u_long byte_count; /* + packet byte count (including FCS) */
- u_long pkt_ptrlo; /* + packet data LO (in RBA) */
- u_long pkt_ptrhi; /* + packet data HI (in RBA) */
- u_long seq_no; /* + RBA sequence numbers */
- u_long rlink; /* link to next receive descriptor */
- u_long in_use; /* + packet available to SONIC */
-};
-struct _short_RXpkt {
- u_short status; /* + receive status */
- u_short byte_count; /* + packet byte count (including FCS) */
- u_short pkt_ptrlo; /* + packet data LO (in RBA) */
- u_short pkt_ptrhi; /* + packet data HI (in RBA) */
- u_short seq_no; /* + RBA sequence numbers */
- u_short rlink; /* link to next receive descriptor */
- u_short in_use; /* + packet available to SONIC */
-};
+#define RXPKT_STATUS 0
+#define RXPKT_BYTEC 1
+#define RXPKT_PTRLO 2
+#define RXPKT_PTRHI 3
+#define RXPKT_SEQNO 4
+#define RXPKT_RLINK 5
+#define RXPKT_INUSE 6
+#define RXPKT_SIZE(sc) (sc->bitmode ? (7 * 4) : (7 * 2))
+
#define RBASEQ(x) (((x)>>8)&0xff)
#define PSNSEQ(x) ((x) & 0xff)
* Transmit Descriptor
* This structure holds information about packets to be transmitted.
*/
-#define FRAGMAX 16 /* maximum number of fragments in a packet */
-struct TXpkt {
- u_long status; /* + transmitted packet status */
- u_long config; /* transmission configuration */
- u_long pkt_size; /* entire packet size in bytes */
- u_long frag_count; /* # fragments in packet */
- struct {
- u_long frag_ptrlo; /* pointer to packet fragment LO */
- u_long frag_ptrhi; /* pointer to packet fragment HI */
- u_long frag_size; /* fragment size */
- } u[FRAGMAX];
- u_long :32; /* This makes tcp->u[FRAGMAX].u_link.link valid! */
-};
-struct _short_TXpkt {
- u_short status; /* + transmitted packet status */
- u_short config; /* transmission configuration */
- u_short pkt_size; /* entire packet size in bytes */
- u_short frag_count; /* # fragments in packet */
- struct {
- u_short frag_ptrlo; /* pointer to packet fragment LO */
- u_short frag_ptrhi; /* pointer to packet fragment HI */
- u_short frag_size; /* fragment size */
- } u[FRAGMAX];
- u_short :16; /* This makes tcp->u[FRAGMAX].u_link.link valid! */
-};
+#define FRAGMAX 16 /* maximum number of fragments in a packet */
-#define tlink frag_ptrlo
+#define TXP_STATUS 0 /* + transmitted packet status */
+#define TXP_CONFIG 1 /* transmission configuration */
+#define TXP_PKTSIZE 2 /* entire packet size in bytes */
+#define TXP_FRAGCNT 3 /* # fragments in packet */
-#define EOL 0x0001 /* end of list marker for link fields */
+#define TXP_FRAGOFF 4 /* offset to first fragment */
+#define TXP_FRAGSIZE 3 /* size of each fragment desc */
+#define TXP_FPTRLO 0 /* ptr to packet fragment LO */
+#define TXP_FPTRHI 1 /* ptr to packet fragment HI */
+#define TXP_FSIZE 2 /* fragment size */
-#define MAXCAM 16 /* number of user entries in CAM */
-struct CDA {
- struct {
- u_long cam_ep; /* CAM Entry Pointer */
- u_long cam_ap0; /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
- u_long cam_ap1; /* CAM Address Port 1 xx-xx-YY-YY-xxxx */
- u_long cam_ap2; /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
- } desc[MAXCAM];
- u_long enable; /* mask enabling CAM entries */
-};
-struct _short_CDA {
- struct {
- u_short cam_ep; /* CAM Entry Pointer */
- u_short cam_ap0; /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
- u_short cam_ap1; /* CAM Address Port 1 xx-xx-YY-YY-xxxx */
- u_short cam_ap2; /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
- } desc[MAXCAM];
- u_short enable; /* mask enabling CAM entries */
-};
+#define TXP_WORDS TXP_FRAGOFF + FRAGMAX*TXP_FSIZE + 1 /* 1 for tlink */
+#define TXP_SIZE(sc) ((sc->bitmode) ? (TXP_WORDS*4) : (TXP_WORDS*2))
+
+#define EOL 0x0001 /* end of list marker for link fields */
+
+/*
+ * CDA, the CAM descriptor area. The SONIC has a 16 entry CAM to
+ * match incoming addresses against. It is programmed via DMA
+ * from a memory region.
+ */
+#define MAXCAM 16 /* number of user entries in CAM */
+#define CDA_CAMDESC 4 /* # words i na descriptor */
+#define CDA_CAMEP 0 /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
+#define CDA_CAMAP0 1 /* CAM Address Port 1 xx-xx-YY-YY-xx-xx */
+#define CDA_CAMAP1 2 /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
+#define CDA_CAMAP2 3
+#define CDA_ENABLE 64 /* mask enabling CAM entries */
+#define CDA_SIZE(sc) ((4*16 + 1) * ((sc->bitmode) ? 4 : 2))
void snsetup __P((struct sn_softc *sc));