summaryrefslogtreecommitdiffstats
path: root/sys/dev/musycc
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2000-07-18 11:34:15 +0000
committerphk <phk@FreeBSD.org>2000-07-18 11:34:15 +0000
commit4c98e148e56342aa4f1e1046a1bb5ef07cceb032 (patch)
tree6e30549f3a01e8900c0af049944e9db42150cdc3 /sys/dev/musycc
parenta27343321b84fcf37e10e8442c07507498ba625e (diff)
downloadFreeBSD-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/musycc')
-rw-r--r--sys/dev/musycc/musycc.c162
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;
}
OpenPOWER on IntegriCloud