diff options
author | phk <phk@FreeBSD.org> | 2000-07-18 11:34:15 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2000-07-18 11:34:15 +0000 |
commit | 4c98e148e56342aa4f1e1046a1bb5ef07cceb032 (patch) | |
tree | 6e30549f3a01e8900c0af049944e9db42150cdc3 /sys/dev | |
parent | a27343321b84fcf37e10e8442c07507498ba625e (diff) | |
download | FreeBSD-src-4c98e148e56342aa4f1e1046a1bb5ef07cceb032.zip FreeBSD-src-4c98e148e56342aa4f1e1046a1bb5ef07cceb032.tar.gz |
Driver for LMC1504 card: four port E1 or fractional E1.
T1 support is possible but I have no T1 hardware to test with.
The vendor can be found at: www.lanmedia.com
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/musycc/musycc.c | 162 |
1 files changed, 115 insertions, 47 deletions
diff --git a/sys/dev/musycc/musycc.c b/sys/dev/musycc/musycc.c index 4315a6a..952763f 100644 --- a/sys/dev/musycc/musycc.c +++ b/sys/dev/musycc/musycc.c @@ -129,6 +129,8 @@ struct schan { u_long rx_drop; /* mbuf allocation failures */ u_long tx_limit; + int tx_next_md; /* index to the next MD */ + int tx_last_md; /* index to the last MD */ int rx_last_md; /* index to next MD */ int nmd; /* count of MD's. */ #if 0 @@ -314,6 +316,7 @@ init_ctrl(struct softc *sif) tsleep(sif, PZERO | PCATCH, "ds8370", hz); sif->reg->gbp = vtophys(sif->ram); sif->ram->grcd = 0x00000001; /* RXENBL */ + sif->ram->grcd |= 0x00000002; /* TXENBL */ sif->ram->grcd |= 0x00000004; /* SUBDSBL */ sif->ram->grcd |= 0x00000008; /* OOFABT */ #if 0 @@ -409,6 +412,40 @@ init_8370(u_int32_t *p) * Interrupts */ +static void +musycc_intr0_tx_eom(struct softc *sc, int ch) +{ + u_int32_t status; + struct schan *sch; + struct mbuf *m; + struct mdesc *md; + + sch = sc->chan[ch]; + if (sch == NULL || sch->state != UP) { + /* XXX: this should not happen once the driver is done */ + printf("Xmit packet on uninitialized channel %d\n", ch); + return; + } + if (sc->mdt[ch] == NULL) + return; /* XXX: can this happen ? */ + for (;;) { + if (sch->tx_last_md == sch->tx_next_md) + break; + md = &sc->mdt[ch][sch->tx_last_md]; + status = md->status; + if (status & 0x80000000) + break; /* Not our mdesc, done */ + m = md->m; + if (m) + m_freem(m); + md->m = NULL; + md->data = 0; + md->status = 0; + if (++sch->tx_last_md >= sch->nmd) + sch->tx_last_md = 0; + } +} + /* * Receive interrupt on controller *sc, channel ch * @@ -525,7 +562,7 @@ musycc_intr0(void *arg) break; case 3: /* EOM End Of Message */ if (csc->iqd[j] & 0x80000000) - ; /* tx */ + musycc_intr0_tx_eom(sc, ch); else musycc_intr0_rx_eom(sc, ch); break; @@ -640,10 +677,10 @@ barf: static int ng_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp, hook_p lasthook) { - struct softc *sif; + struct softc *sc; char *s, *r; - sif = node->private; + sc = node->private; if (msg->header.typecookie != NGM_GENERIC_COOKIE) goto out; @@ -656,7 +693,7 @@ ng_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, struct ng_mesg return (ENOMEM); } s = (char *)(*resp)->data; - sprintf(s, "Status for %s\n", sif->nodename); + sprintf(s, "Status for %s\n", sc->nodename); (*resp)->header.arglen = strlen(s) + 1; FREE(msg, M_NETGRAPH); return (0); @@ -732,7 +769,45 @@ static int ng_rcvdata(hook_p hook, struct mbuf *m, meta_p meta, struct mbuf **ret_m, meta_p *ret_meta) { - NG_FREE_DATA(m, meta); + struct softc *sc; + struct csoftc *csc; + struct schan *sch; + struct mdesc *md; + u_int32_t ch, u, len; + struct mbuf *m2; + + sch = hook->private; + sc = sch->sc; + csc = sc->csc; + ch = sch->chan; + + NG_FREE_META(meta); + meta = NULL; + + /* XXX: check channel state */ + + m2 = m; + len = m->m_pkthdr.len; + while (len) { + md = &sc->mdt[ch][sch->tx_next_md]; + + if (++sch->tx_next_md >= sch->nmd) + sch->tx_next_md = 0; + + md->data = vtophys(m->m_data); + len -= m->m_len; + u = 0x80000000; /* OWNER = MUSYCC */ + if (len > 0) { + md->m = 0; + } else { + u |= 1 << 29; /* EOM */ + md->m = m2; + } + + u |= m->m_len; + md->status = u; + m = m->m_next; + } return (0); } @@ -801,11 +876,8 @@ ng_connect(hook_p hook) /* Reread the Channel Configuration Descriptor for this channel */ sc->reg->srd = sc->last = 0x0b00 + ch; tsleep(&sc->last, PZERO + PCATCH, "con3", hz); -#if 0 - /* XXX: not yet xmit */ sc->reg->srd = sc->last = 0x0b20 + ch; tsleep(&sc->last, PZERO + PCATCH, "con4", hz); -#endif /* * Figure out how many receive buffers we want: 10 + nts * 2 @@ -814,6 +886,8 @@ ng_connect(hook_p hook) */ sch->nmd = nmd = 10 + nts * 2; sch->rx_last_md = 0; + sch->tx_next_md = 0; + sch->tx_last_md = 0; MALLOC(sc->mdt[ch], struct mdesc *, sizeof(struct mdesc) * nmd, M_MUSYCC, M_WAITOK); MALLOC(sc->mdr[ch], struct mdesc *, @@ -826,7 +900,7 @@ ng_connect(hook_p hook) sc->mdt[ch][i].next = vtophys(&sc->mdt[ch][i + 1]); sc->mdr[ch][i].next = vtophys(&sc->mdr[ch][i + 1]); } - sc->mdt[ch][i].status = 0x8000000; + sc->mdt[ch][i].status = 0; sc->mdt[ch][i].m = NULL; sc->mdt[ch][i].data = 0; @@ -846,11 +920,8 @@ ng_connect(hook_p hook) /* Activate the Channel */ sc->reg->srd = sc->last = 0x0800 + ch; tsleep(&sc->last, PZERO + PCATCH, "con3", hz); -#if 0 - /* XXX: not yet xmit */ sc->reg->srd = sc->last = 0x0820 + ch; tsleep(&sc->last, PZERO + PCATCH, "con4", hz); -#endif return (0); } @@ -890,11 +961,8 @@ ng_disconnect(hook_p hook) /* Deactivate the channel */ sc->reg->srd = sc->last = 0x0900 + sch->chan; tsleep(&sc->last, PZERO + PCATCH, "con3", hz); -#if 0 - /* XXX: not yet xmit */ sc->reg->srd = sc->last = 0x0920 + sch->chan; tsleep(&sc->last, PZERO + PCATCH, "con4", hz); -#endif for (i = 0; i < 32; i++) { if (sch->ts & (1 << i)) { @@ -965,7 +1033,7 @@ musycc_probe(device_t self) static int musycc_attach(device_t self) { - struct csoftc *sc; + struct csoftc *csc; struct resource *res; struct softc *sif; int rid, i, error; @@ -984,22 +1052,22 @@ musycc_attach(device_t self) f = pci_get_function(self); /* For function zero allocate a csoftc */ if (f == 0) { - MALLOC(sc, struct csoftc *, sizeof(*sc), M_MUSYCC, M_WAITOK); - bzero(sc, sizeof(*sc)); - sc->bus = pci_get_bus(self); - sc->slot = pci_get_slot(self); - LIST_INSERT_HEAD(&sc_list, sc, list); + MALLOC(csc, struct csoftc *, sizeof(*csc), M_MUSYCC, M_WAITOK); + bzero(csc, sizeof(*csc)); + csc->bus = pci_get_bus(self); + csc->slot = pci_get_slot(self); + LIST_INSERT_HEAD(&sc_list, csc, list); } else { - LIST_FOREACH(sc, &sc_list, list) { - if (sc->bus != pci_get_bus(self)) + LIST_FOREACH(csc, &sc_list, list) { + if (csc->bus != pci_get_bus(self)) continue; - if (sc->slot != pci_get_slot(self)) + if (csc->slot != pci_get_slot(self)) continue; break; } } - sc->f[f] = self; - device_set_softc(self, sc); + csc->f[f] = self; + device_set_softc(self, csc); rid = PCIR_MAPS; res = bus_alloc_resource(self, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE); @@ -1007,21 +1075,21 @@ musycc_attach(device_t self) device_printf(self, "Could not map memory\n"); return ENXIO; } - sc->virbase[f] = (u_char *)rman_get_virtual(res); - sc->physbase[f] = rman_get_start(res); + csc->virbase[f] = (u_char *)rman_get_virtual(res); + csc->physbase[f] = rman_get_start(res); /* Allocate interrupt */ rid = 0; - sc->irq[f] = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0, + csc->irq[f] = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); - if (sc->irq[f] == NULL) { + if (csc->irq[f] == NULL) { printf("couldn't map interrupt\n"); return(ENXIO); } - error = bus_setup_intr(self, sc->irq[f], INTR_TYPE_NET, - f == 0 ? musycc_intr0 : musycc_intr1, sc, &sc->intrhand[f]); + error = bus_setup_intr(self, csc->irq[f], INTR_TYPE_NET, + f == 0 ? musycc_intr0 : musycc_intr1, csc, &csc->intrhand[f]); if (error) { printf("couldn't set up irq\n"); @@ -1033,29 +1101,29 @@ musycc_attach(device_t self) for (i = 0; i < 2; i++) printf("f%d: device %p virtual %p physical %08x\n", - i, sc->f[i], sc->virbase[i], sc->physbase[i]); + i, csc->f[i], csc->virbase[i], csc->physbase[i]); - sc->reg = (struct globalr *)sc->virbase[0]; - sc->reg->glcd = 0x3f30; /* XXX: designer magic */ - u32p = (u_int32_t *)sc->virbase[1]; + csc->reg = (struct globalr *)csc->virbase[0]; + csc->reg->glcd = 0x3f30; /* XXX: designer magic */ + u32p = (u_int32_t *)csc->virbase[1]; if ((u32p[0x1200] & 0xffffff00) != 0x13760400) { printf("Not a LMC1504 (ID is 0x%08x). Bailing out.\n", u32p[0x1200]); return(ENXIO); } printf("Found <LanMedia LMC1504>\n"); - sc->nchan = 4; + csc->nchan = 4; u32p[0x1000] = 0xfe; /* XXX: control-register */ - for (i = 0; i < sc->nchan; i++) { - sif = &sc->serial[i]; - sif->csc = sc; + for (i = 0; i < csc->nchan; i++) { + sif = &csc->serial[i]; + sif->csc = csc; sif->last = 0xffffffff; sif->ds8370 = (u_int32_t *) - (sc->virbase[1] + i * 0x800); - sif->ds847x = sc->virbase[0] + i * 0x800; + (csc->virbase[1] + i * 0x800); + sif->ds847x = csc->virbase[0] + i * 0x800; sif->reg = (struct globalr *) - (sc->virbase[0] + i * 0x800); + (csc->virbase[0] + i * 0x800); MALLOC(sif->mycg, struct mycg *, sizeof(struct mycg), M_MUSYCC, M_WAITOK); bzero(sif->mycg, sizeof(struct mycg)); @@ -1069,13 +1137,13 @@ musycc_attach(device_t self) sif->node->private = sif; sprintf(sif->nodename, "pci%d-%d-%d-%d", device_get_unit(device_get_parent(self)), - sc->bus, - sc->slot, + csc->bus, + csc->slot, i); error = ng_name_node(sif->node, sif->nodename); } - sc->ram = (struct globalr *)&sc->serial[0].mycg->cg; - init_847x(sc); + csc->ram = (struct globalr *)&csc->serial[0].mycg->cg; + init_847x(csc); return 0; } |