aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>2005-04-25 07:08:42 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>2005-04-25 07:08:42 +0000
commite4ee89af6ffec66fdd030640366e02992712e238 (patch)
tree64178f39cd4462aec89c7ee457419609dc22cb4b /sys
parentc146a15791e181350af619830c3e9f3bd720d045 (diff)
downloadsrc-e4ee89af6ffec66fdd030640366e02992712e238.tar.gz
src-e4ee89af6ffec66fdd030640366e02992712e238.zip
Retire the musycc E1/T1 driver
Notes
Notes: svn path=/head/; revision=145497
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/musycc/musycc.c1567
1 files changed, 0 insertions, 1567 deletions
diff --git a/sys/dev/musycc/musycc.c b/sys/dev/musycc/musycc.c
deleted file mode 100644
index d9503f915815..000000000000
--- a/sys/dev/musycc/musycc.c
+++ /dev/null
@@ -1,1567 +0,0 @@
-/*-
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Card state machine:
- * -------------------
- *
- * This is the state engine which drives the card "as such" which in reality
- * means the MUSYCC chip.
- *
- * State Description
- *
- * IDLE The card is in this state when no channels are configured.
- * This is the state we leave the card in after _attach()
- *
- * INIT The card is being initialized
- *
- * RUNNING The card is running
- *
- * FAULT The card is hosed and being reset
- *
- * ------------------
- * / \
- * v |
- * IDLE ---> INIT ---> RUNNING
- * ^ |
- * | |
- * | v
- * FAULT
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/malloc.h>
-#include <sys/bus.h>
-#include <sys/mbuf.h>
-#include <sys/queue.h>
-#include <machine/bus.h>
-#include <machine/clock.h>
-#include <sys/rman.h>
-#include <machine/resource.h>
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-#include "pci_if.h"
-
-
-#include <netgraph/ng_message.h>
-#include <netgraph/netgraph.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-static MALLOC_DEFINE(M_MUSYCC, "musycc", "MUSYCC related");
-
-static int maxlatency = 250;
-SYSCTL_INT(_debug, OID_AUTO, musycc_maxlatency, CTLFLAG_RW, &maxlatency, 0,
- "The number of milliseconds a packet is allowed to spend in the output queue. "
- "If the output queue is longer than this number of milliseconds when the packet "
- "arrives for output, the packet will be dropped."
-);
-
-static int debug = 0;
-SYSCTL_INT(_debug, OID_AUTO, musycc_debug, CTLFLAG_RW, &debug, 0, "");
-
-struct softc;
-static void init_8370(struct softc *sc);
-static u_int32_t parse_ts(const char *s, int *nbit);
-
-/*
- * Device driver initialization stuff
- */
-
-static devclass_t musycc_devclass;
-
-/* XXX: Notice, these babies must be aligned to 2k boundaries [5-7] */
-struct groupr {
- u_int32_t thp[32]; /* Transmit Head Pointer [5-29] */
- u_int32_t tmp[32]; /* Transmit Message Pointer [5-30] */
- u_int32_t rhp[32]; /* Receive Head Pointer [5-29] */
- u_int32_t rmp[32]; /* Receive Message Pointer [5-30] */
- u_int8_t ttsm[128]; /* Time Slot Map [5-22] */
- u_int8_t tscm[256]; /* Subchannel Map [5-24] */
- u_int32_t tcct[32]; /* Channel Configuration [5-26] */
- u_int8_t rtsm[128]; /* Time Slot Map [5-22] */
- u_int8_t rscm[256]; /* Subchannel Map [5-24] */
- u_int32_t rcct[32]; /* Channel Configuration [5-26] */
- u_int32_t __glcd; /* Global Configuration Descriptor [5-10] */
- u_int32_t __iqp; /* Interrupt Queue Pointer [5-36] */
- u_int32_t __iql; /* Interrupt Queue Length [5-36] */
- u_int32_t grcd; /* Group Configuration Descriptor [5-16] */
- u_int32_t mpd; /* Memory Protection Descriptor [5-18] */
- u_int32_t mld; /* Message Length Descriptor [5-20] */
- u_int32_t pcd; /* Port Configuration Descriptor [5-19] */
- u_int32_t __rbist; /* Receive BIST status [5-4] */
- u_int32_t __tbist; /* Receive BIST status [5-4] */
-};
-
-struct globalr {
- u_int32_t gbp; /* Group Base Pointer */
- u_int32_t dacbp; /* Dual Address Cycle Base Pointer */
- u_int32_t srd; /* Service Request Descriptor */
- u_int32_t isd; /* Interrupt Service Descriptor */
- u_int32_t __thp[28]; /* Transmit Head Pointer [5-29] */
- u_int32_t __tmp[32]; /* Transmit Message Pointer [5-30] */
- u_int32_t __rhp[32]; /* Receive Head Pointer [5-29] */
- u_int32_t __rmp[32]; /* Receive Message Pointer [5-30] */
- u_int8_t ttsm[128]; /* Time Slot Map [5-22] */
- u_int8_t tscm[256]; /* Subchannel Map [5-24] */
- u_int32_t tcct[32]; /* Channel Configuration [5-26] */
- u_int8_t rtsm[128]; /* Time Slot Map [5-22] */
- u_int8_t rscm[256]; /* Subchannel Map [5-24] */
- u_int32_t rcct[32]; /* Channel Configuration [5-26] */
- u_int32_t glcd; /* Global Configuration Descriptor [5-10] */
- u_int32_t iqp; /* Interrupt Queue Pointer [5-36] */
- u_int32_t iql; /* Interrupt Queue Length [5-36] */
- u_int32_t grcd; /* Group Configuration Descriptor [5-16] */
- u_int32_t mpd; /* Memory Protection Descriptor [5-18] */
- u_int32_t mld; /* Message Length Descriptor [5-20] */
- u_int32_t pcd; /* Port Configuration Descriptor [5-19] */
- u_int32_t rbist; /* Receive BIST status [5-4] */
- u_int32_t tbist; /* Receive BIST status [5-4] */
-};
-
-/*
- * Because the chan_group must be 2k aligned we create this super
- * structure so we can use the remaining 476 bytes for something useful
- */
-
-struct mycg {
- struct groupr cg;
-};
-
-struct mdesc {
- u_int32_t status;
- u_int32_t data;
- u_int32_t next;
- /* Software only */
- struct mbuf *m;
- struct mdesc *snext;
-};
-
-#define NPORT 8
-
-#define NHDLC 32
-
-#define NIQD 32
-
-struct softc;
-
-struct schan {
- enum {DOWN, UP} state;
- struct softc *sc;
- int chan;
- u_int32_t ts;
- char hookname[8];
-
- hook_p hook;
-
- u_long rx_drop; /* mbuf allocation failures */
- u_long tx_limit;
- u_long tx_pending;
- struct mdesc *tx_next_md; /* next MD */
- struct mdesc *tx_last_md; /* last MD */
- int rx_last_md; /* index to next MD */
- int nmd; /* count of MD's. */
-
- time_t last_recv;
- time_t last_rdrop;
- time_t last_rxerr;
- u_long crc_error;
- u_long dribble_error;
- u_long long_error;
- u_long abort_error;
- u_long short_error;
- u_long txn, rxn;
-
- time_t last_xmit;
- time_t last_txerr;
-
- time_t last_txdrop;
- u_long tx_drop;
-
-#if 0
-
-
- u_long rx_error;
-
- u_long overflow_error;
-
- int last_error;
- int prev_error;
-
-#endif
-};
-
-enum framing {WHOKNOWS, E1, E1U, T1, T1U};
-enum clocksource {EXT, INT};
-
-struct softc {
- enum framing framing;
- enum clocksource clocksource;
- int nhooks;
- u_int32_t last;
- struct csoftc *csc;
- u_int32_t *ds8370;
- void *ds847x;
- struct globalr *reg;
- struct groupr *ram;
- struct mycg *mycg;
- struct mdesc *mdt[NHDLC];
- struct mdesc *mdr[NHDLC];
- node_p node; /* NG node */
- char nodename[NG_NODESIZ]; /* NG nodename */
- struct schan *chan[NHDLC];
- u_long cnt_ferr;
- u_long cnt_cerr;
- u_long cnt_lcv;
- u_long cnt_febe;
- u_long cnt_berr;
- u_long cnt_fred;
- u_long cnt_cofa;
- u_long cnt_sef;
-};
-
-/*
- * SoftC for the entire card.
- */
-
-struct csoftc {
- enum { C_IDLE, C_INIT, C_RUNNING, C_FAULT } state;
-
- int unit, bus, slot;
- LIST_ENTRY(csoftc) list;
-
- device_t f[2];
- struct resource *irq[2];
- void *intrhand[2];
- vm_offset_t physbase[2];
- u_char *virbase[2];
-
- u_int creg, *cregp;
- int nchan;
- struct softc serial[NPORT];
-
- struct globalr *reg;
- struct globalr *ram;
- u_int32_t iqd[NIQD];
-};
-
-/*
- *
- */
-
-#define NG_NODETYPE "lmc1504"
-
-static ng_constructor_t musycc_constructor;
-static ng_rcvmsg_t musycc_rcvmsg;
-static ng_shutdown_t musycc_shutdown;
-static ng_newhook_t musycc_newhook;
-static ng_connect_t musycc_connect;
-static ng_rcvdata_t musycc_rcvdata;
-static ng_disconnect_t musycc_disconnect;
-
-static struct ng_type ngtypestruct = {
- .version = NG_ABI_VERSION,
- .name = NG_NODETYPE,
- .constructor = musycc_constructor,
- .rcvmsg = musycc_rcvmsg,
- .shutdown = musycc_shutdown,
- .newhook = musycc_newhook,
- .connect = musycc_connect,
- .rcvdata = musycc_rcvdata,
- .disconnect = musycc_disconnect,
-};
-
-/*
- *
- */
-
-static u_int32_t
-parse_ts(const char *s, int *nbit)
-{
- unsigned r;
- int i, j;
- char *p;
-
- r = 0;
- j = -1;
- *nbit = 0;
- while(*s) {
- i = strtol(s, &p, 0);
- if (i < 0 || i > 31)
- return (0);
- while (j != -1 && j < i) {
- r |= 1 << j++;
- (*nbit)++;
- }
- j = -1;
- r |= 1 << i;
- (*nbit)++;
- if (*p == ',') {
- s = p + 1;
- continue;
- } else if (*p == '-') {
- j = i + 1;
- s = p + 1;
- continue;
- } else if (!*p) {
- break;
- } else {
- return (0);
- }
- }
- return (r);
-}
-
-/*
- *
- */
-
-
-static LIST_HEAD(, csoftc) sc_list = LIST_HEAD_INITIALIZER(&sc_list);
-
-static void
-poke_847x(void *dummy)
-{
- int i;
- struct csoftc *csc;
-
- timeout(poke_847x, NULL, 1);
- LIST_FOREACH(csc, &sc_list, list) {
- i = (csc->creg >> 24 & 0xf);
- csc->creg &= ~0xf000000;
- i++;
- csc->creg |= (i & 0xf) << 24;
- *csc->cregp = csc->creg;
-#if 0
- for (i = 0; i < sc->nchan; i++) {
- if (sc->serial[i].last == 0xffffffff) {
- sc->serial[i].reg->srd = 0;
- sc->serial[i].last = 0;
- return;
- }
- }
-#endif
- }
-}
-
-static void
-init_card(struct csoftc *csc)
-{
-
- printf("init_card(%p)\n", csc);
-
- csc->state = C_INIT;
- csc->reg->srd = 0x100;
- tsleep(csc, PZERO | PCATCH, "icard", hz / 10);
- csc->reg->gbp = vtophys(csc->ram);
- csc->ram->glcd = 0x3f30; /* XXX: designer magic */
-
- csc->ram->iqp = vtophys(csc->iqd);
- csc->ram->iql = NIQD - 1;
- csc->ram->dacbp = 0; /* 32bit only */
-
- csc->reg->srd = csc->serial[0].last = 0x400;
- tsleep(&csc->serial[0].last, PZERO | PCATCH, "con1", hz);
- timeout(poke_847x, NULL, 1);
- csc->state = C_RUNNING;
-}
-
-static void
-init_ctrl(struct softc *sc)
-{
- int i;
-
- printf("init_ctrl(%p) [%s] [%08x]\n", sc, sc->nodename, sc->csc->reg->glcd);
- init_8370(sc);
- tsleep(sc, PZERO | PCATCH, "ds8370", hz);
- printf("%s: glcd: [%08x]\n", sc->nodename, sc->csc->reg->glcd);
- sc->reg->gbp = vtophys(sc->ram);
- sc->ram->grcd = 0x00000001; /* RXENBL */
- sc->ram->grcd |= 0x00000002; /* TXENBL */
- sc->ram->grcd |= 0x00000004; /* SUBDSBL */
- if (sc->framing == E1 || sc->framing == T1)
- sc->ram->grcd |= 0x00000008; /* OOFABT */
- else
- sc->ram->grcd |= 0x00000000; /* !OOFABT */
-
- sc->ram->grcd |= 0x00000020; /* MSKCOFA */
-
- sc->ram->grcd |= 0x00000440; /* POLLTH=1 */
-
- sc->ram->mpd = 0; /* Memory Protection NI [5-18] */
-
- sc->ram->pcd = 0x0000001; /* PORTMD=1 (E1/32ts) */
- sc->ram->pcd |= 1 << 5; /* TSYNC_EDGE */
- sc->ram->pcd |= 1 << 9; /* TRITX */
-
- /* Message length descriptor */
- /* XXX: MTU */
- sc->ram->mld = 1600;
- sc->ram->mld |= (1600 << 16);
-
- for (i = 0; i < NHDLC; i++) {
- sc->ram->ttsm[i] = 0;
- sc->ram->rtsm[i] = 0;
- }
- sc->reg->srd = sc->last = 0x500;
- tsleep(&sc->last, PZERO | PCATCH, "con1", hz);
- sc->reg->srd = sc->last = 0x520;
- tsleep(&sc->last, PZERO | PCATCH, "con1", hz);
-}
-
-/*
- *
- */
-
-static void
-status_chans(struct softc *sc, char *s)
-{
- int i;
- struct schan *scp;
-
- s += strlen(s);
- for (i = 0; i < NHDLC; i++) {
- scp = sc->chan[i];
- if (scp == NULL)
- continue;
- sprintf(s + strlen(s), "c%2d:", i);
- sprintf(s + strlen(s), " ts %08x", scp->ts);
- sprintf(s + strlen(s), " RX %lus/%lus",
- (long)(time_second - scp->last_recv),
- (long)(time_second - scp->last_rxerr));
- sprintf(s + strlen(s), " TX %lus/%lus/%lus",
- (long)(time_second - scp->last_xmit),
- (long)(time_second - scp->last_txerr),
- (long)(time_second - scp->last_txdrop));
- sprintf(s + strlen(s), " TXdrop %lu Pend %lu",
- scp->tx_drop,
- scp->tx_pending);
- sprintf(s + strlen(s), " CRC %lu Dribble %lu Long %lu Short %lu Abort %lu",
- scp->crc_error,
- scp->dribble_error,
- scp->long_error,
- scp->short_error,
- scp->abort_error);
- sprintf(s + strlen(s), "\n TX: %lu RX: %lu\n",
- scp->txn, scp->rxn);
- }
-}
-
-
-/*
- *
- */
-
-static void
-status_8370(struct softc *sc, char *s)
-{
- u_int32_t *p = sc->ds8370;
-
- s += strlen(s);
- sprintf(s, "Framer: "); s += strlen(s);
- switch (sc->framing) {
- case WHOKNOWS: sprintf(s, "(unconfigured)\n"); break;
- case E1: sprintf(s, "(e1)\n"); break;
- case E1U: sprintf(s, "(e1u)\n"); break;
- case T1: sprintf(s, "(t1)\n"); break;
- case T1U: sprintf(s, "(t1u)\n"); break;
- default: sprintf(s, "(mode %d XXX?)\n", sc->framing); break;
- }
- s += strlen(s);
- sprintf(s, " Red alarms:"); s += strlen(s);
- if (p[0x47] & 0x08) { sprintf(s, " ALOS"); s += strlen(s); }
- if (p[0x47] & 0x04) { sprintf(s, " LOS"); s += strlen(s); }
- if (sc->framing == E1 || sc->framing == T1) {
- if (p[0x47] & 0x02) { sprintf(s, " LOF"); s += strlen(s); }
- }
- sprintf(s, "\n Yellow alarms:"); s += strlen(s);
- if (p[0x47] & 0x80) { sprintf(s, " RMYEL"); s += strlen(s); }
- if (p[0x47] & 0x40) { sprintf(s, " RYEL"); s += strlen(s); }
- sprintf(s, "\n Blue alarms:"); s += strlen(s);
- if (p[0x47] & 0x10) { sprintf(s, " AIS"); s += strlen(s); }
- sprintf(s, "\n"); s += strlen(s);
- sprintf(s, "\n Various alarms:"); s += strlen(s);
- if (p[0x48] & 0x10) { sprintf(s, " TSHORT"); s += strlen(s); }
- sprintf(s, "\n Counters:"); s += strlen(s);
- if (sc->framing == E1) {
- sprintf(s, " FERR=%lu", sc->cnt_ferr); s += strlen(s);
- }
- sprintf(s, " CERR=%lu", sc->cnt_cerr); s += strlen(s);
- sprintf(s, " LCV=%lu", sc->cnt_lcv); s += strlen(s);
- sprintf(s, " FEBE=%lu", sc->cnt_febe); s += strlen(s);
- sprintf(s, " BERR=%lu", sc->cnt_berr); s += strlen(s);
- sprintf(s, " FRED=%lu", sc->cnt_fred); s += strlen(s);
- sprintf(s, " COFA=%lu", sc->cnt_cofa); s += strlen(s);
- sprintf(s, " SEF=%lu", sc->cnt_sef); s += strlen(s);
- sprintf(s, "\n"); s += strlen(s);
-}
-
-static void
-dump_8370(struct softc *sc, char *s, int offset)
-{
- int i, j;
- u_int32_t *p = sc->ds8370;
-
- s += strlen(s);
- for (i = 0; i < 0x100; i += 16) {
- sprintf(s, "%03x: ", i + offset);
- s += strlen(s);
- for (j = 0; j < 0x10; j ++) {
- sprintf(s, " %02x", p[i + j + offset] & 0xff);
- s += strlen(s);
- }
- sprintf(s, "\n");
- s += strlen(s);
- }
-}
-
-static void
-init_8370(struct softc *sc)
-{
- int i;
- u_int32_t *p = sc->ds8370;
-
- p[0x001] = 0x80; /* CR0 - Reset */
- DELAY(20);
- p[0x001] = 0x00; /* CR0 - E1, RFRAME: FAS only */
- DELAY(20);
- if (sc->clocksource == INT)
- p[0x002] = 0x40; /* JAT_CR - XXX */
- else
- p[0x002] = 0x20; /* JAT_CR - XXX */
- p[0x00D] = 0x01; /* IER6 - ONESEC */
- p[0x014] = 0x00; /* LOOP - */
- p[0x015] = 0x00; /* DL3_TS - */
- p[0x016] = 0x00; /* DL3_BIT - */
- p[0x017] = 0x00; /* DL3_BIT - */
- p[0x018] = 0xFF; /* PIO - XXX */
- p[0x019] = 0x3c; /* POE - CLADO_OE|RCKO_OE */
- if (sc->clocksource == INT)
- p[0x01A] = 0x37; /* CMUX - RSBCKI(RSBCKI), TSBCKI(CLADO), CLADO(RCKO), TCKI(CLADO) */
- else
- p[0x01A] = 0x37; /* CMUX - RSBCKI(RSBCKI), TSBCKI(RSBCKI), CLADO(RCKO), TCKI(RCKO) */
-
- /* I.431/G.775 */
- p[0x020] = 0x41; /* LIU_CR - SQUELCH */
- p[0x022] = 0xb1; /* RLIU_CR - */
- p[0x024] = 0x1d; /* VGA_MAX - */
- p[0x027] = 0xba; /* DSLICE - */
- p[0x028] = 0xda; /* EQ_OUT - */
- p[0x02a] = 0xa6; /* PRE_EQ - */
-
- if (sc->framing == E1U || sc->framing == T1U)
- p[0x040] = 0x49; /* RCRO - XXX */
- else
- p[0x040] = 0x09; /* RCRO - XXX */
-
- p[0x041] = 0x00; /* RPATT - XXX */
- p[0x045] = 0x00; /* RALM - XXX */
- p[0x046] = 0x05; /* LATCH - LATCH_CNT|LATCH_ALM */
-
- p[0x068] = 0x4c; /* TLIU_CR - TERM|Pulse=6 */
- p[0x070] = 0x04; /* TCR0 - TFRAME=4 */
-
- if (sc->framing == E1U || sc->framing == T1U)
- p[0x071] = 0x41; /* TCR1 - TZCS */
- else
- p[0x071] = 0x51; /* TCR1 - TZCS */
-
- if (sc->framing == E1U || sc->framing == T1U)
- p[0x072] = 0x00;
- else
- p[0x072] = 0x1b; /* TCR1 - INS_YEL|INS_MF|INS_CRC|INS_FBIT */
-
- p[0x073] = 0x00; /* TERROR */
- p[0x074] = 0x00; /* TMAN */
-
- if (sc->framing == E1U || sc->framing == T1U)
- p[0x075] = 0x0; /* TALM */
- else
- p[0x075] = 0x10; /* TALM - AUTO_YEL */
-
- p[0x076] = 0x00; /* TPATT */
- p[0x077] = 0x00; /* TLP */
-
- p[0x090] = 0x05; /* CLAD_CR - XXX */
- p[0x091] = 0x01; /* CSEL - 2048kHz */
-
- if (sc->framing == E1U || sc->framing == T1U) {
- p[0x0a0] = 0x00;
- p[0x0a6] = 0x00;
- p[0x0b1] = 0x00;
- }
-
- p[0x0d0] = 0x46; /* SBI_CR - SBI=6 */
- p[0x0d1] = 0x70; /* RSB_CR - XXX */
- p[0x0d2] = 0x00; /* RSYNC_BIT - 0 */
- p[0x0d3] = 0x00; /* RSYNC_TS - 0 */
- p[0x0d4] = 0x30; /* TSB_CR - XXX */
- p[0x0d5] = 0x00; /* TSYNC_BIT - 0 */
- p[0x0d6] = 0x00; /* TSYNC_TS - 0 */
- if (sc->framing == E1U || sc->framing == T1U)
- p[0x0d7] = 0x05; /* RSIG_CR - 0 | FRZ_OFF*/
- else
- p[0x0d7] = 0x01; /* RSIG_CR - 0 */
- p[0x0d8] = 0x00; /* RSIG_FRM - 0 */
- for (i = 0; i < 32; i ++) {
- p[0x0e0 + i] = 0x0d; /* SBC$i - RINDO|TINDO|ASSIGN */
- p[0x100 + i] = 0x00; /* TPC$i - 0 */
- p[0x180 + i] = 0x00; /* RPC$i - 0 */
- }
-}
-
-/*
- * Interrupts
- */
-
-static void
-musycc_intr0_tx_eom(struct softc *sc, int ch)
-{
- struct schan *sch;
- 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);
- }
- if (sc->mdt[ch] == NULL)
- return; /* XXX: can this happen ? */
- for (;;) {
- md = sch->tx_last_md;
- if (md->status == 0)
- break;
- if (md->status & 0x80000000)
- break; /* Not our mdesc, done */
- sch->tx_last_md = md->snext;
- md->data = 0;
- if (md->m != NULL) {
- sch->tx_pending -= md->m->m_pkthdr.len;
- m_freem(md->m);
- md->m = NULL;
- }
- md->status = 0;
- }
-}
-
-/*
- * Receive interrupt on controller *sc, channel ch
- *
- * We perambulate the Rx descriptor ring until we hit
- * a mdesc which isn't ours to take.
- */
-
-static void
-musycc_intr0_rx_eom(struct softc *sc, int ch)
-{
- u_int32_t status, error;
- struct schan *sch;
- struct mbuf *m, *m2;
- struct mdesc *md;
-
- sch = sc->chan[ch];
- if (sch == NULL || sch->state != UP) {
- /* XXX: this should not happen once the driver is done */
- printf("Received packet on uninitialized channel %d\n", ch);
- return;
- }
- if (sc->mdr[ch] == NULL)
- return; /* XXX: can this happen ? */
- for (;;) {
- md = &sc->mdr[ch][sch->rx_last_md];
- status = md->status;
- if (!(status & 0x80000000))
- break; /* Not our mdesc, done */
- m = md->m;
- m->m_len = m->m_pkthdr.len = status & 0x3fff;
- error = (status >> 16) & 0xf;
- if (error == 0) {
- MGETHDR(m2, M_DONTWAIT, MT_DATA);
- if (m2 != NULL) {
- MCLGET(m2, M_DONTWAIT);
- if((m2->m_flags & M_EXT) != 0) {
- /* Substitute the mbuf+cluster. */
- md->m = m2;
- md->data = vtophys(m2->m_data);
- /* Pass the received mbuf upwards. */
- sch->last_recv = time_second;
- NG_SEND_DATA_ONLY(error, sch->hook, m);
- } else {
- /*
- * We didn't get a mbuf cluster,
- * drop received packet, free the
- * mbuf we cannot use and recycle
- * the mbuf+cluster we already had.
- */
- m_freem(m2);
- sch->last_rdrop = time_second;
- sch->rx_drop++;
- }
- } else {
- /*
- * We didn't get a mbuf, drop received packet
- * and recycle the "old" mbuf+cluster.
- */
- sch->last_rdrop = time_second;
- sch->rx_drop++;
- }
- } else if (error == 9) {
- sch->last_rxerr = time_second;
- sch->crc_error++;
- } else if (error == 10) {
- sch->last_rxerr = time_second;
- sch->dribble_error++;
- } else if (error == 11) {
- sch->last_rxerr = time_second;
- sch->abort_error++;
- } else if (error == 12) {
- sch->last_rxerr = time_second;
- sch->long_error++;
- } else {
- sch->last_rxerr = time_second;
- /* Receive error, print some useful info */
- printf("%s %s: RX 0x%08x ", sch->sc->nodename,
- sch->hookname, status);
- /* Don't print a lot, just the begining will do */
- if (m->m_len > 16)
- m->m_len = m->m_pkthdr.len = 16;
- m_print(m, -1);
- printf("\n");
- }
- md->status = 1600; /* XXX: MTU */
- /* Check next mdesc in the ring */
- if (++sch->rx_last_md >= sch->nmd)
- sch->rx_last_md = 0;
- }
-}
-
-static void
-musycc_intr0(void *arg)
-{
- int i, j, g, ch, ev, er;
- struct csoftc *csc;
- u_int32_t u, u1, n, c;
- struct softc *sc;
-
- csc = arg;
-
- for (;;) {
- u = csc->reg->isd;
- c = u & 0x7fff;
- n = u >> 16;
- if (c == 0)
- return;
- if (debug & 1)
- printf("%s: IRQ: %08x n = %d c = %d\n", csc->serial[0].nodename, u, n, c);
- for (i = 0; i < c; i++) {
- j = (n + i) % NIQD;
- u1 = csc->iqd[j];
- g = (u1 >> 29) & 0x3;
- g |= (u1 >> (14-2)) & 0x4;
- ch = (u1 >> 24) & 0x1f;
- ev = (u1 >> 20) & 0xf;
- er = (u1 >> 16) & 0xf;
- sc = &csc->serial[g];
- if (debug & 2) {
- printf("%08x %d", u1, g);
- printf("/%s", u1 & 0x80000000 ? "T" : "R");
- printf("/%02d", ch);
- printf(" %02d", ev);
- printf(":%02d", er);
- printf("\n");
- }
- switch (ev) {
- case 1: /* SACK Service Request Acknowledge */
-#if 0
- printf("%s: SACK: %08x group=%d", sc->nodename, csc->iqd[j], g);
- printf("/%s", csc->iqd[j] & 0x80000000 ? "T" : "R");
- printf(" cmd %08x (%08x) \n", sc->last, sc->reg->srd);
-#endif
- sc->last = 0xffffffff;
- wakeup(&sc->last);
- break;
- case 5: /* CHABT Change To Abort Code (0x7e -> 0xff) */
- case 6: /* CHIC Change To Idle Code (0xff -> 0x7e) */
- break;
- case 3: /* EOM End Of Message */
- if (csc->iqd[j] & 0x80000000)
- musycc_intr0_tx_eom(sc, ch);
- else
- musycc_intr0_rx_eom(sc, ch);
- break;
- case 0:
- if (er == 13) { /* SHT */
- sc->chan[ch]->last_rxerr = time_second;
- sc->chan[ch]->short_error++;
- break;
- }
- /* FALLTHROUGH */
- default:
- musycc_intr0_tx_eom(sc, ch);
- musycc_intr0_rx_eom(sc, ch);
-#if 1
- printf("huh ? %08x %d", u1, g);
- printf("/%s", u1 & 0x80000000 ? "T" : "R");
- printf("/%02d", ch);
- printf(" %02d", ev);
- printf(":%02d", er);
- printf("\n");
-#endif
- }
- csc->iqd[j] = 0xffffffff;
- j++;
- j %= NIQD;
- csc->reg->isd = j << 16;
- }
- }
-}
-
-static void
-musycc_intr1(void *arg)
-{
- int i;
- struct csoftc *csc;
- struct softc *sc;
- u_int32_t *u;
- u_int8_t irr;
-
- csc = arg;
-
- for (i = 0; i < csc->nchan; i++) {
- sc = &csc->serial[i];
- u = sc->ds8370;
- irr = u[3];
- if (irr == 0)
- continue;
- if (u[0x5] & 1) { /* ONESEC */
- sc->cnt_ferr += u[0x50] & 0xff;
- sc->cnt_ferr += (u[0x51] & 0xff) << 8;
- sc->cnt_cerr += u[0x52] & 0xff;
- sc->cnt_cerr += (u[0x53] & 0xff) << 8;
- sc->cnt_lcv += u[0x54] & 0xff;
- sc->cnt_lcv += (u[0x55] & 0xff) << 8;
- sc->cnt_febe += u[0x56] & 0xff;
- sc->cnt_febe += (u[0x57] & 0xff) << 8;
- sc->cnt_berr += u[0x58] & 0xff;
- sc->cnt_berr += (u[0x59] & 0xff) << 8;
- sc->cnt_fred += (u[0x5a] & 0xf0) >> 4;
- sc->cnt_cofa += (u[0x5a] & 0x0c) >> 2;
- sc->cnt_sef += u[0x5a] & 0x03;
- }
- if (debug & 4) {
- int j;
-
- printf("musycc_intr1:%d %02x", i, irr);
- for (j = 4; j < 0x14; j++)
- printf(" %02x", u[j] & 0xff);
- printf("\n");
- }
- }
-}
-
-/*
- * NetGraph Stuff
- */
-
-static int
-musycc_constructor(node_p node)
-{
-
- return (EINVAL);
-}
-
-static int
-musycc_shutdown(node_p nodep)
-{
-
- return (EINVAL);
-}
-
-static void
-musycc_config(node_p node, char *set, char *ret)
-{
- struct softc *sc;
- struct csoftc *csc;
- enum framing wframing;
- int i;
-
- sc = NG_NODE_PRIVATE(node);
- csc = sc->csc;
- if (csc->state == C_IDLE)
- init_card(csc);
- while (csc->state != C_RUNNING)
- tsleep(&csc->state, PZERO | PCATCH, "crun", hz/10);
- if (set != NULL) {
- if (!strncmp(set, "line ", 5)) {
- wframing = sc->framing;
- if (!strcmp(set, "line e1")) {
- wframing = E1;
- } else if (!strcmp(set, "line e1u")) {
- wframing = E1U;
- } else {
- strcat(ret, "ENOGROK\n");
- return;
- }
- if (wframing == sc->framing)
- return;
- if (sc->nhooks > 0) {
- sprintf(ret, "Cannot change line when %d hooks open\n", sc->nhooks);
- return;
- }
- sc->framing = wframing;
- init_ctrl(sc);
- return;
- }
- if (!strcmp(set, "clock source internal")) {
- sc->clocksource = INT;
- init_ctrl(sc);
- } else if (!strcmp(set, "clock source line")) {
- sc->clocksource = EXT;
- init_ctrl(sc);
- } else if (!strcmp(set, "show 8370 0")) {
- dump_8370(sc, ret, 0);
- } else if (!strcmp(set, "show 8370 1")) {
- dump_8370(sc, ret, 0x100);
- } else if (!strncmp(set, "creg", 4)) {
- i = strtol(set + 5, 0, 0);
- printf("set creg %d\n", i);
- csc->creg = 0xfe | (i << 24);
- *csc->cregp = csc->creg;
-/*
- } else if (!strcmp(set, "reset")) {
- reset_group(sc, ret);
- } else if (!strcmp(set, "reset all")) {
- reset_card(sc, ret);
-*/
- } else {
- printf("%s CONFIG SET [%s]\n", sc->nodename, set);
- goto barf;
- }
-
- return;
- }
- if (sc->framing == E1)
- strcat(ret, "line e1\n");
- else if (sc->framing == E1U)
- strcat(ret, "line e1u\n");
- if (sc->clocksource == INT)
- strcat(ret, "clock source internal\n");
- else
- strcat(ret, "clock source line\n");
- return;
-barf:
- strcpy(ret, "Syntax Error\n");
- strcat(ret, "\tline {e1|e1u}\n");
- strcat(ret, "\tshow 8370 {0|1}\n");
- return;
-}
-
-/*
- * Handle status and config enquiries.
- * Respond with a synchronous response.
- */
-static int
-musycc_rcvmsg(node_p node, item_p item, hook_p lasthook)
-{
- struct softc *sc;
- struct ng_mesg *resp = NULL;
- char *s, *r;
- int error = 0;
- struct ng_mesg *msg;
-
-
- NGI_GET_MSG(item, msg);
- sc = NG_NODE_PRIVATE(node);
- if (msg->header.typecookie != NGM_GENERIC_COOKIE)
- goto out;
-
- if (msg->header.cmd == NGM_TEXT_STATUS) {
- NG_MKRESPONSE(resp, msg,
- sizeof(struct ng_mesg) + NG_TEXTRESPONSE, M_NOWAIT);
- if (resp == NULL) {
- error = ENOMEM;
- goto out;
- }
- s = (char *)resp->data;
- status_8370(sc, s);
- status_chans(sc,s);
- resp->header.arglen = strlen(s) + 1;
- NG_FREE_MSG(msg);
-
- } else if (msg->header.cmd == NGM_TEXT_CONFIG) {
- if (msg->header.arglen) {
- s = (char *)msg->data;
- } else {
- s = NULL;
- }
-
- NG_MKRESPONSE(resp, msg,
- sizeof(struct ng_mesg) + NG_TEXTRESPONSE, M_NOWAIT);
- if (resp == NULL) {
- error = ENOMEM;
- goto out;
- }
- r = (char *)resp->data;
- *r = '\0';
- musycc_config(node, s, r);
- resp->header.arglen = strlen(r) + 1;
- NG_FREE_MSG(msg);
- } else {
- error = EINVAL;
- }
-
-out:
- /* Take care of synchronous response, if any */
- NG_RESPOND_MSG(error, node, item, resp);
- NG_FREE_MSG(msg);
- return (error);
-}
-
-static int
-musycc_newhook(node_p node, hook_p hook, const char *name)
-{
- struct softc *sc;
- struct csoftc *csc;
- struct schan *sch;
- u_int32_t ts, chan;
- int nbit;
-
- sc = NG_NODE_PRIVATE(node);
- csc = sc->csc;
-
- while (csc->state != C_RUNNING)
- tsleep(&csc->state, PZERO | PCATCH, "crun", hz/10);
-
- if (sc->framing == WHOKNOWS)
- return (EINVAL);
-
- if (name[0] != 't' || name[1] != 's')
- return (EINVAL);
- ts = parse_ts(name + 2, &nbit);
- if (ts == 0)
- return (EINVAL);
- chan = ffs(ts) - 1;
-
- if (sc->framing == E1U && nbit == 32)
- ;
- else if (sc->framing == T1U && nbit == 24)
- ;
- else if (ts & 1)
- return (EINVAL);
-
- if (sc->chan[chan] == NULL) {
- MALLOC(sch, struct schan *, sizeof(*sch), M_MUSYCC, M_WAITOK | M_ZERO);
- sch->sc = sc;
- sch->state = DOWN;
- sch->chan = chan;
- sprintf(sch->hookname, name); /* XXX overflow ? */
- sc->chan[chan] = sch;
- } else if (sc->chan[chan]->state == UP) {
- return (EBUSY);
- }
- sc->nhooks++;
- sch = sc->chan[chan];
- sch->ts = ts;
- sch->hook = hook;
- sch->tx_limit = nbit * 8;
- NG_HOOK_SET_PRIVATE(hook, sch);
- return(0);
-}
-
-static int
-musycc_rcvdata(hook_p hook, item_p item)
-{
-
- struct softc *sc;
- struct csoftc *csc;
- struct schan *sch;
- struct mdesc *md, *md0;
- u_int32_t u, u0, len;
- struct mbuf *m2;
- struct mbuf *m;
-
- sch = NG_HOOK_PRIVATE(hook);
- sc = sch->sc;
- csc = sc->csc;
-
- if (csc->state != C_RUNNING) {
- printf("csc->state = %d\n", csc->state);
- NG_FREE_ITEM(item);
- return (0);
- }
-
-
- if (sch->state != UP) {
- printf("sch->state = %d\n", sch->state);
- NG_FREE_ITEM(item);
- return (0);
- }
- NGI_GET_M(item, m);
- NG_FREE_ITEM(item);
- if (sch->tx_pending + m->m_pkthdr.len > sch->tx_limit * maxlatency) {
- sch->tx_drop++;
- sch->last_txdrop = time_second;
- NG_FREE_M(m);
- return (0);
- }
-
- /* find out if we have enough txmd's */
- m2 = m;
- md = sch->tx_next_md;
- for (len = m2->m_pkthdr.len; len; m2 = m2->m_next) {
- if (m2->m_len == 0)
- continue;
- if (md->status != 0) {
- sch->tx_drop++;
- sch->last_txdrop = time_second;
- NG_FREE_M(m);
- return (0);
- }
- len -= m2->m_len;
- md = md->snext;
- }
-
- m2 = m;
- md = md0 = sch->tx_next_md;
- u0 = 0;
- for (len = m->m_pkthdr.len; len > 0; m = m->m_next) {
- if (m->m_len == 0)
- continue;
- if (md->status != 0) {
- printf("Out of tx md(2)\n");
- sch->last_txerr = time_second;
- sch->tx_drop++;
- sch->last_txdrop = time_second;
- NG_FREE_M(m);
- break;
- }
-
- md->data = vtophys(m->m_data);
- if (md == md0)
- u = 0x00000000; /* OWNER = CPU */
- else
- u = 0x80000000; /* OWNER = MUSYCC */
- u |= m->m_len;
- len -= m->m_len;
- if (len > 0) {
- md->m = NULL;
- if (md == md0)
- u0 = u;
- else
- md->status = u;
- md = md->snext;
- continue;
- }
- u |= 0x20000000; /* EOM */
- md->m = m2;
- sch->tx_pending += m2->m_pkthdr.len;
- if (md == md0) {
- u |= 0x80000000; /* OWNER = MUSYCC */
- md->status = u;
- } else {
- md->status = u;
- md0->status = u0 | 0x80000000; /* OWNER = MUSYCC */
- }
- sch->last_xmit = time_second;
- sch->tx_next_md = md->snext;
- }
- sch->txn++;
- return (0);
-}
-
-static int
-musycc_connect(hook_p hook)
-{
- struct softc *sc;
- struct csoftc *csc;
- struct schan *sch;
- int nts, nbuf, i, nmd, ch;
- struct mbuf *m;
-
- sch = NG_HOOK_PRIVATE(hook);
- sc = sch->sc;
- csc = sc->csc;
- ch = sch->chan;
-
- while (csc->state != C_RUNNING)
- tsleep(&csc->state, PZERO | PCATCH, "crun", hz/10);
-
- if (sch->state == UP)
- return (0);
- sch->state = UP;
-
- /* Setup the Time Slot Map */
- nts = 0;
- for (i = ch; i < 32; i++) {
- if (sch->ts & (1 << i)) {
- sc->ram->rtsm[i] = ch | (4 << 5);
- sc->ram->ttsm[i] = ch | (4 << 5);
- nts++;
- }
- }
-
- /*
- * Find the length of the first run of timeslots.
- * XXX: find the longest instead.
- */
- nbuf = 0;
- for (i = ch; i < 32; i++) {
- if (sch->ts & (1 << i))
- nbuf++;
- else
- break;
- }
-
- printf("Connect ch= %d ts= %08x nts= %d nbuf = %d\n",
- ch, sch->ts, nts, nbuf);
-
- /* Reread the Time Slot Map */
- sc->reg->srd = sc->last = 0x1800;
- tsleep(&sc->last, PZERO | PCATCH, "con1", hz);
- sc->reg->srd = sc->last = 0x1820;
- tsleep(&sc->last, PZERO | PCATCH, "con2", hz);
-
- /* Set the channel mode */
- sc->ram->tcct[ch] = 0x2800; /* HDLC-FCS16 | MAXSEL[2] */
- sc->ram->rcct[ch] = 0x2800; /* HDLC-FCS16 | MAXSEL[2] */
-
- /*
- * Allocate the FIFO space
- * We don't do subchanneling so we can use 128 dwords [4-13]
- */
- sc->ram->tcct[ch] |= (1 + 2 * (nbuf - 1)) << 16; /* BUFFLEN */
- sc->ram->rcct[ch] |= (1 + 2 * (nbuf - 1)) << 16; /* BUFFLEN */
- sc->ram->tcct[ch] |= ((ch * 2) << 24); /* BUFFLOC */
- sc->ram->rcct[ch] |= ((ch * 2) << 24); /* BUFFLOC */
-
- /* Reread the Channel Configuration Descriptor for this channel */
- sc->reg->srd = sc->last = 0x0b00 + ch;
- tsleep(&sc->last, PZERO | PCATCH, "con3", hz);
- sc->reg->srd = sc->last = 0x0b20 + ch;
- tsleep(&sc->last, PZERO | PCATCH, "con4", hz);
-
- /*
- * Figure out how many receive buffers we want: 10 + nts * 2
- * 1 timeslot, 50 bytes packets -> 68msec
- * 31 timeslots, 50 bytes packets -> 14msec
- */
- sch->nmd = nmd = 200 + nts * 4;
- sch->rx_last_md = 0;
- MALLOC(sc->mdt[ch], struct mdesc *,
- sizeof(struct mdesc) * nmd, M_MUSYCC, M_WAITOK);
- MALLOC(sc->mdr[ch], struct mdesc *,
- sizeof(struct mdesc) * nmd, M_MUSYCC, M_WAITOK);
- for (i = 0; i < nmd; i++) {
- if (i == nmd - 1) {
- sc->mdt[ch][i].snext = &sc->mdt[ch][0];
- sc->mdt[ch][i].next = vtophys(sc->mdt[ch][i].snext);
- sc->mdr[ch][i].snext = &sc->mdr[ch][0];
- sc->mdr[ch][i].next = vtophys(sc->mdr[ch][i].snext);
- } else {
- sc->mdt[ch][i].snext = &sc->mdt[ch][i + 1];
- sc->mdt[ch][i].next = vtophys(sc->mdt[ch][i].snext);
- sc->mdr[ch][i].snext = &sc->mdr[ch][i + 1];
- sc->mdr[ch][i].next = vtophys(sc->mdr[ch][i].snext);
- }
- sc->mdt[ch][i].status = 0;
- sc->mdt[ch][i].m = NULL;
- sc->mdt[ch][i].data = 0;
-
- MGETHDR(m, M_TRYWAIT, MT_DATA);
- if (m == NULL)
- goto errfree;
- MCLGET(m, M_TRYWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- /* We've waited mbuf_wait and still got nothing.
- We're calling with M_TRYWAIT anyway - a little
- defensive programming costs us very little - if
- anything at all in the case of error. */
- m_free(m);
- goto errfree;
- }
- sc->mdr[ch][i].m = m;
- sc->mdr[ch][i].data = vtophys(m->m_data);
- sc->mdr[ch][i].status = 1600; /* MTU */
- }
- sch->tx_last_md = sch->tx_next_md = &sc->mdt[ch][0];
-
- /* Configure it into the chip */
- sc->ram->thp[ch] = vtophys(&sc->mdt[ch][0]);
- sc->ram->tmp[ch] = vtophys(&sc->mdt[ch][0]);
- sc->ram->rhp[ch] = vtophys(&sc->mdr[ch][0]);
- sc->ram->rmp[ch] = vtophys(&sc->mdr[ch][0]);
-
- /* Activate the Channel */
- sc->reg->srd = sc->last = 0x0800 + ch;
- tsleep(&sc->last, PZERO | PCATCH, "con4", hz);
- sc->reg->srd = sc->last = 0x0820 + ch;
- tsleep(&sc->last, PZERO | PCATCH, "con3", hz);
- NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
-
- return (0);
-
-errfree:
- while (i > 0) {
- /* Don't leak all the previously allocated mbufs in this loop */
- i--;
- m_free(sc->mdr[ch][i].m);
- }
- FREE(sc->mdt[ch], M_MUSYCC);
- FREE(sc->mdr[ch], M_MUSYCC);
- return (ENOBUFS);
-}
-
-static int
-musycc_disconnect(hook_p hook)
-{
- struct softc *sc;
- struct csoftc *csc;
- struct schan *sch;
- int i, ch;
-
- sch = NG_HOOK_PRIVATE(hook);
- sc = sch->sc;
- csc = sc->csc;
- ch = sch->chan;
-
- while (csc->state != C_RUNNING)
- tsleep(&csc->state, PZERO | PCATCH, "crun", hz/10);
-
- /* Deactivate the channel */
- sc->reg->srd = sc->last = 0x0900 + sch->chan;
- tsleep(&sc->last, PZERO | PCATCH, "con3", hz);
- sc->reg->srd = sc->last = 0x0920 + sch->chan;
- tsleep(&sc->last, PZERO | PCATCH, "con4", hz);
-
- if (sch->state == DOWN)
- return (0);
- sch->state = DOWN;
-
- sc->ram->thp[ch] = 0;
- sc->ram->tmp[ch] = 0;
- sc->ram->rhp[ch] = 0;
- sc->ram->rmp[ch] = 0;
- for (i = 0; i < sch->nmd; i++) {
- if (sc->mdt[ch][i].m != NULL)
- m_freem(sc->mdt[ch][i].m);
- if (sc->mdr[ch][i].m != NULL)
- m_freem(sc->mdr[ch][i].m);
- }
- FREE(sc->mdt[ch], M_MUSYCC);
- sc->mdt[ch] = NULL;
- FREE(sc->mdr[ch], M_MUSYCC);
- sc->mdr[ch] = NULL;
-
- for (i = 0; i < 32; i++) {
- if (sch->ts & (1 << i)) {
- sc->ram->rtsm[i] = 0;
- sc->ram->ttsm[i] = 0;
- }
- }
- sc->nhooks--;
- sch->tx_pending = 0;
-
- return (0);
-}
-
-
-
-/*
- * PCI initialization stuff
- */
-
-static int
-musycc_probe(device_t self)
-{
- char desc[40];
-
- if (sizeof(struct groupr) != 1572) {
- printf("sizeof(struct groupr) = %zd, should be 1572\n",
- sizeof(struct groupr));
- return(ENXIO);
- }
-
- if (sizeof(struct globalr) != 1572) {
- printf("sizeof(struct globalr) = %zd, should be 1572\n",
- sizeof(struct globalr));
- return(ENXIO);
- }
-
- if (sizeof(struct mycg) > 2048) {
- printf("sizeof(struct mycg) = %zd, should be <= 2048\n",
- sizeof(struct mycg));
- return(ENXIO);
- }
-
- switch (pci_get_devid(self)) {
- case 0x8471109e: strcpy(desc, "CN8471 MUSYCC"); break;
- case 0x8472109e: strcpy(desc, "CN8472 MUSYCC"); break;
- case 0x8474109e: strcpy(desc, "CN8474 MUSYCC"); break;
- case 0x8478109e: strcpy(desc, "CN8478 MUSYCC"); break;
- default:
- return (ENXIO);
- }
-
- switch (pci_get_function(self)) {
- case 0: strcat(desc, " Network controller"); break;
- case 1: strcat(desc, " Ebus bridge"); break;
- default:
- return (ENXIO);
- }
-
- device_set_desc_copy(self, desc);
- return BUS_PROBE_DEFAULT;
-}
-
-static int
-musycc_attach(device_t self)
-{
- struct csoftc *csc;
- struct resource *res;
- struct softc *sc;
- int rid, i, error;
- int f;
- u_int32_t *u32p, u;
- static int once;
-
- if (!once) {
- once++;
- error = ng_newtype(&ngtypestruct);
- if (error != 0)
- printf("ng_newtype() failed %d\n", error);
- }
- printf("We have %zd pad bytes in mycg\n", 2048 - sizeof(struct mycg));
-
- f = pci_get_function(self);
- /* For function zero allocate a csoftc */
- if (f == 0) {
- MALLOC(csc, struct csoftc *, sizeof(*csc), M_MUSYCC, M_WAITOK | M_ZERO);
- csc->bus = pci_get_bus(self);
- csc->slot = pci_get_slot(self);
- LIST_INSERT_HEAD(&sc_list, csc, list);
- } else {
- LIST_FOREACH(csc, &sc_list, list) {
- if (csc->bus != pci_get_bus(self))
- continue;
- if (csc->slot != pci_get_slot(self))
- continue;
- break;
- }
- }
- csc->f[f] = self;
- device_set_softc(self, csc);
- rid = PCIR_BAR(0);
- res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
- if (res == NULL) {
- device_printf(self, "Could not map memory\n");
- return ENXIO;
- }
- csc->virbase[f] = (u_char *)rman_get_virtual(res);
- csc->physbase[f] = rman_get_start(res);
-
- /* Allocate interrupt */
- rid = 0;
- csc->irq[f] = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
-
- if (csc->irq[f] == NULL) {
- printf("couldn't map interrupt\n");
- return(ENXIO);
- }
-
- 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");
- return(ENXIO);
- }
-
- if (f == 0)
- return (0);
-
- for (i = 0; i < 2; i++)
- printf("f%d: device %p virtual %p physical %08jx\n",
- i, csc->f[i], csc->virbase[i], (uintmax_t)csc->physbase[i]);
-
- csc->reg = (struct globalr *)csc->virbase[0];
- csc->reg->glcd = 0x3f30; /* XXX: designer magic */
- u32p = (u_int32_t *)csc->virbase[1];
- u = u32p[0x1200];
- if ((u & 0xffff0000) != 0x13760000) {
- printf("Not a LMC1504 (ID is 0x%08x). Bailing out.\n", u);
- return(ENXIO);
- }
- csc->nchan = (u >> 8) & 0xf;
- printf("Found <LanMedia LMC1504 Rev %d Chan %d>\n", (u >> 12) & 0xf, csc->nchan);
-
- csc->creg = 0xfe;
- csc->cregp = &u32p[0x1000];
- *csc->cregp = csc->creg;
- for (i = 0; i < csc->nchan; i++) {
- sc = &csc->serial[i];
- sc->csc = csc;
- sc->last = 0xffffffff;
- sc->ds8370 = (u_int32_t *)
- (csc->virbase[1] + i * 0x800);
- sc->ds847x = csc->virbase[0] + i * 0x800;
- sc->reg = (struct globalr *)
- (csc->virbase[0] + i * 0x800);
- MALLOC(sc->mycg, struct mycg *,
- sizeof(struct mycg), M_MUSYCC, M_WAITOK | M_ZERO);
- sc->ram = &sc->mycg->cg;
-
- error = ng_make_node_common(&ngtypestruct, &sc->node);
- if (error) {
- printf("ng_make_node_common() failed %d\n", error);
- continue;
- }
- NG_NODE_SET_PRIVATE(sc->node, sc);
- sprintf(sc->nodename, "sync-%d-%d-%d",
- csc->bus,
- csc->slot,
- i);
- error = ng_name_node(sc->node, sc->nodename);
- /* XXX Apparently failure isn't a problem */
- }
- csc->ram = (struct globalr *)&csc->serial[0].mycg->cg;
- sc = &csc->serial[0];
- sc->reg->srd = sc->last = 0x100;
- csc->state = C_IDLE;
-
- return 0;
-}
-
-static device_method_t musycc_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, musycc_probe),
- DEVMETHOD(device_attach, musycc_attach),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- {0, 0}
-};
-
-static driver_t musycc_driver = {
- "musycc",
- musycc_methods,
- 0
-};
-
-DRIVER_MODULE(musycc, pci, musycc_driver, musycc_devclass, 0, 0);
-