void rtl80x9_mediastatus(struct dp8390_softc *sc, struct ifmediareq *ifmr) { struct ifnet *ifp = &sc->sc_ec.ec_if; u_int8_t cr_proto = sc->cr_proto | ((ifp->if_flags & IFF_RUNNING) ? ED_CR_STA : ED_CR_STP); /* * Sigh, can detect which media is being used, but can't * detect if we have link or not. */ /* Set NIC to page 3 registers. */ NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_3); if (NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG0) & RTL3_CONFIG0_BNC) ifmr->ifm_active = IFM_ETHER|IFM_10_2; else { ifmr->ifm_active = IFM_ETHER|IFM_10_T; if (NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3) & RTL3_CONFIG3_FUDUP) ifmr->ifm_active |= IFM_FDX; } /* Set NIC to page 0 registers. */ NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_0); }
void rtl80x9_init_card(struct dp8390_softc *sc) { struct ifmedia *ifm = &sc->sc_media; struct ifnet *ifp = &sc->sc_ec.ec_if; u_int8_t cr_proto = sc->cr_proto | ((ifp->if_flags & IFF_RUNNING) ? ED_CR_STA : ED_CR_STP); u_int8_t reg; /* Set NIC to page 3 registers. */ NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_3); /* write enable config1-3. */ NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_EECR, RTL3_EECR_EEM1|RTL3_EECR_EEM0); /* First, set basic media type. */ reg = NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG2); reg &= ~(RTL3_CONFIG2_PL1|RTL3_CONFIG2_PL0); switch (IFM_SUBTYPE(ifm->ifm_cur->ifm_media)) { case IFM_AUTO: /* Nothing to do; both bits clear == auto-detect. */ break; case IFM_10_T: /* * According to docs, this should be: * reg |= RTL3_CONFIG2_PL0; * but this doesn't work, so make it the same as AUTO. */ break; case IFM_10_2: reg |= RTL3_CONFIG2_PL1|RTL3_CONFIG2_PL0; break; } NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG2, reg); /* Now, set duplex mode. */ reg = NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3); if (ifm->ifm_cur->ifm_media & IFM_FDX) reg |= RTL3_CONFIG3_FUDUP; else reg &= ~RTL3_CONFIG3_FUDUP; NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3, reg); /* write disable config1-3 */ NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_EECR, 0); /* Set NIC to page 0 registers. */ NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_0); }
hide void mc_reset_txdma(struct mc_softc *sc) { dbdma_command_t *cmd = sc->sc_txdmacmd; dbdma_regmap_t *dmareg = sc->sc_txdma; u_int8_t maccc; /* disable transmitter */ maccc = NIC_GET(sc, MACE_MACCC); NIC_PUT(sc, MACE_MACCC, maccc & ~ENXMT); dbdma_reset(dmareg); DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, 0, sc->sc_txbuf_phys, DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); cmd++; DBDMA_BUILD(cmd, DBDMA_CMD_STOP, 0, 0, 0, DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); out32rb(&dmareg->d_cmdptrhi, 0); out32rb(&dmareg->d_cmdptrlo, kvtop((void *)sc->sc_txdmacmd)); /* restore old value */ NIC_PUT(sc, MACE_MACCC, maccc); }
hide void mc_reset_rxdma(struct mc_softc *sc) { dbdma_command_t *cmd = sc->sc_rxdmacmd; dbdma_regmap_t *dmareg = sc->sc_rxdma; int i; u_int8_t maccc; /* Disable receiver, reset the DMA channels */ maccc = NIC_GET(sc, MACE_MACCC); NIC_PUT(sc, MACE_MACCC, maccc & ~ENRCV); dbdma_reset(dmareg); for (i = 0; i < MC_RXDMABUFS; i++) { DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, ETHERMTU + 22, sc->sc_rxbuf_phys + MC_BUFSIZE * i, DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); cmd++; } DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0, DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS); out32rb(&cmd->d_cmddep, kvtop((void *)sc->sc_rxdmacmd)); cmd++; dbdma_start(dmareg, sc->sc_rxdmacmd); sc->sc_tail = 0; /* Reenable receiver, reenable DMA */ NIC_PUT(sc, MACE_MACCC, maccc); }
void mc_reset_rxdma(struct mc_softc *sc) { dbdma_command_t *cmd = sc->sc_rxdmacmd; int i; u_int8_t maccc; /* Disable receiver, reset the DMA channels */ maccc = NIC_GET(sc, MACE_MACCC); NIC_PUT(sc, MACE_MACCC, maccc & ~ENRCV); dbdma_reset(sc->sc_rxdma); bzero(sc->sc_rxdmacmd, 8 * sizeof(dbdma_command_t)); for (i = 0; i < MC_RXDMABUFS; i++) { DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, MACE_BUFLEN, sc->sc_rxbuf_pa + MACE_BUFLEN * i, DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); cmd++; } DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0, DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS); dbdma_st32(&cmd->d_cmddep, sc->sc_rxdbdma->d_paddr); cmd++; sc->sc_tail = 0; dbdma_start(sc->sc_rxdma, sc->sc_rxdbdma); /* Reenable receiver, reenable DMA */ NIC_PUT(sc, MACE_MACCC, maccc); }
void mc_tint(struct mc_softc *sc) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; u_int8_t xmtrc, xmtfs; xmtrc = NIC_GET(sc, MACE_XMTRC); xmtfs = NIC_GET(sc, MACE_XMTFS); if ((xmtfs & XMTSV) == 0) return; if (xmtfs & UFLO) { printf("%s: underflow\n", sc->sc_dev.dv_xname); mc_reset(sc); return; } if (xmtfs & LCOL) { printf("%s: late collision\n", sc->sc_dev.dv_xname); ifp->if_oerrors++; ifp->if_collisions++; } if (xmtfs & MORE) /* Real number is unknown. */ ifp->if_collisions += 2; else if (xmtfs & ONE) ifp->if_collisions++; else if (xmtfs & RTRY) { printf("%s: excessive collisions\n", sc->sc_dev.dv_xname); ifp->if_collisions += 16; ifp->if_oerrors++; } if (xmtfs & LCAR) { sc->sc_havecarrier = 0; printf("%s: lost carrier\n", sc->sc_dev.dv_xname); ifp->if_oerrors++; } ifp->if_flags &= ~IFF_OACTIVE; ifp->if_timer = 0; mc_start(ifp); }
/* * Assume that the SONIC was initialized in MacOS. This should go away * when we can properly get the MAC address on the PBs. */ static int sn_obio_getaddr_kludge(struct sn_softc *sc, u_int8_t *lladdr) { int i, ors = 0; /* Shut down NIC */ NIC_PUT(sc, SNR_CR, CR_RST); wbflush(); NIC_PUT(sc, SNR_CEP, 15); /* For some reason, Apple fills top first. */ wbflush(); i = NIC_GET(sc, SNR_CAP2); wbflush(); ors |= i; lladdr[5] = i >> 8; lladdr[4] = i; i = NIC_GET(sc, SNR_CAP1); wbflush(); ors |= i; lladdr[3] = i >> 8; lladdr[2] = i; i = NIC_GET(sc, SNR_CAP0); wbflush(); ors |= i; lladdr[1] = i >> 8; lladdr[0] = i; NIC_PUT(sc, SNR_CR, 0); wbflush(); if (ors == 0) return (-1); return (0); }
static void camdump(struct sn_softc *sc) { int i; printf("CAM entries:\n"); NIC_PUT(sc, SNR_CR, CR_RST); wbflush(); for (i = 0; i < 16; i++) { ushort ap2, ap1, ap0; NIC_PUT(sc, SNR_CEP, i); wbflush(); ap2 = NIC_GET(sc, SNR_CAP2); ap1 = NIC_GET(sc, SNR_CAP1); ap0 = NIC_GET(sc, SNR_CAP0); printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0); } printf("CAM enable 0x%x\n", NIC_GET(sc, SNR_CEP)); NIC_PUT(sc, SNR_CR, 0); wbflush(); }
int mc_intr(void *arg) { struct mc_softc *sc = arg; struct ifnet *ifp = &sc->sc_arpcom.ac_if; u_int8_t ir; ir = NIC_GET(sc, MACE_IR) & ~NIC_GET(sc, MACE_IMR); if (ir & JAB) { #ifdef MCDEBUG printf("%s: jabber error\n", sc->sc_dev.dv_xname); #endif ifp->if_oerrors++; } if (ir & BABL) { #ifdef MCDEBUG printf("%s: babble\n", sc->sc_dev.dv_xname); #endif ifp->if_oerrors++; } if (ir & CERR) { #ifdef MCDEBUG printf("%s: collision error\n", sc->sc_dev.dv_xname); #endif ifp->if_collisions++; } /* * Pretend we have carrier; if we don't this will be cleared * shortly. */ sc->sc_havecarrier = 1; if (ir & XMTINT) mc_tint(sc); if (ir & RCVINT) mc_rint(sc); return(1); }
void ec_attach(struct device *parent, struct device *self, void *aux) { struct ec_softc *esc = (struct ec_softc *)self; struct dp8390_softc *sc = &esc->sc_dp8390; struct isa_attach_args *ia = aux; bus_space_tag_t nict, asict, memt; bus_space_handle_t nich, asich, memh; bus_size_t memsize; u_int8_t tmp; int i; printf("\n"); nict = asict = ia->ia_iot; memt = ia->ia_memt; /* * Hmm, a 16-bit card has 16k of memory, but only an 8k window * to it. */ memsize = 8192; /* Map the NIC space. */ if (bus_space_map(nict, ia->ia_iobase + ELINK2_NIC_OFFSET, ELINK2_NIC_PORTS, 0, &nich)) { printf("%s: can't map nic i/o space\n", sc->sc_dev.dv_xname); return; } /* Map the ASIC space. */ if (bus_space_map(asict, ia->ia_iobase + ELINK2_ASIC_OFFSET, ELINK2_ASIC_PORTS, 0, &asich)) { printf("%s: can't map asic i/o space\n", sc->sc_dev.dv_xname); return; } /* Map the memory space. */ if (bus_space_map(memt, ia->ia_maddr, memsize, 0, &memh)) { printf("%s: can't map shared memory\n", sc->sc_dev.dv_xname); return; } esc->sc_asict = asict; esc->sc_asich = asich; sc->sc_regt = nict; sc->sc_regh = nich; sc->sc_buft = memt; sc->sc_bufh = memh; /* Interface is always enabled. */ sc->sc_enabled = 1; /* Registers are linear. */ for (i = 0; i < 16; i++) sc->sc_reg_map[i] = i; /* Now we can use the NIC_{GET,PUT}() macros. */ /* * Reset NIC and ASIC. Enable on-board transeiver throughout * reset sequence since it will lock up if the cable isn't * connected if we don't. */ bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_RST | ELINK2_CR_XSEL); /* Wait for a while, then un-reset it. */ delay(50); /* * The 3Com ASIC defaults to rather strange settings for the CR * after a reset. It's important to set it again after the * following write (this is done when we map the PROM below). */ bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL); /* Wait a bit for the NIC to recover from the reset. */ delay(5000); /* * Get the station address from on-board ROM. * * First, map Ethernet address PROM over the top of where the NIC * registers normally appear. */ bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL | ELINK2_CR_EALO); for (i = 0; i < ETHER_ADDR_LEN; i++) sc->sc_arpcom.ac_enaddr[i] = NIC_GET(nict, nich, i); /* * Unmap PROM - select NIC registers. The proper setting of the * transciever is set in later in ec_init_card() via dp8390_init(). */ bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL); /* Determine if this is an 8-bit or 16-bit board. */ /* Select page 0 registers. */ NIC_PUT(nict, nich, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP); /* * Attempt to clear WTS. If it doesn't clear, then this is a * 16-bit board. */ NIC_PUT(nict, nich, ED_P0_DCR, 0); /* Select page 2 registers. */ NIC_PUT(nict, nich, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_2 | ED_CR_STP); /* The 3c503 forces the WTS bit to a one if this is a 16-bit board. */ if (NIC_GET(nict, nich, ED_P2_DCR) & ED_DCR_WTS) esc->sc_16bitp = 1; else esc->sc_16bitp = 0; printf("%s: 3Com 3c503 Ethernet (%s-bit)", sc->sc_dev.dv_xname, esc->sc_16bitp ? "16" : "8"); /* Select page 0 registers. */ NIC_PUT(nict, nich, ED_P2_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP); sc->cr_proto = ED_CR_RD2; /* * DCR gets: * * FIFO threshold to 8, No auto-init Remote DMA, * byte order=80x86. * * 16-bit cards also get word-wide DMA transfers. */ sc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (esc->sc_16bitp ? ED_DCR_WTS : 0); sc->test_mem = ec_fake_test_mem; sc->ring_copy = ec_ring_copy; sc->write_mbuf = ec_write_mbuf; sc->read_hdr = ec_read_hdr; sc->sc_media_init = ec_media_init; sc->sc_mediachange = ec_mediachange; sc->sc_mediastatus = ec_mediastatus; sc->mem_start = 0; sc->mem_size = memsize; /* Do generic parts of attach. */ if (dp8390_config(sc)) { printf(": configuration failed\n"); return; } /* * We need to override the way dp8390_config() set up our * shared memory. * * We have an entire 8k window to put the transmit buffers on the * 16-bit boards. But since the 16bit 3c503's shared memory is only * fast enough to overlap the loading of one full-size packet, trying * to load more than 2 buffers can actually leave the transmitter idle * during the load. So 2 seems the best value. (Although a mix of * variable-sized packets might change this assumption. Nonetheless, * we optimize for linear transfers of same-size packets.) */ if (esc->sc_16bitp) { if (sc->sc_dev.dv_cfdata->cf_flags & DP8390_NO_MULTI_BUFFERING) sc->txb_cnt = 1; else sc->txb_cnt = 2; sc->tx_page_start = ELINK2_TX_PAGE_OFFSET_16BIT; sc->rec_page_start = ELINK2_RX_PAGE_OFFSET_16BIT; sc->rec_page_stop = (memsize >> ED_PAGE_SHIFT) + sc->rec_page_start; sc->mem_ring = sc->mem_start; } else {
int snintr(void *arg) { struct sn_softc *sc = (struct sn_softc *)arg; int handled = 0; int isr; while ((isr = (NIC_GET(sc, SNR_ISR) & ISR_ALL)) != 0) { /* scrub the interrupts that we are going to service */ NIC_PUT(sc, SNR_ISR, isr); handled = 1; wbflush(); if (isr & (ISR_BR | ISR_LCD | ISR_TC)) printf("%s: unexpected interrupt status 0x%x\n", device_xname(sc->sc_dev), isr); if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT)) sonictxint(sc); if (isr & ISR_PKTRX) sonicrxint(sc); if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) { if (isr & ISR_HBL) /* * The repeater is not providing a heartbeat. * In itself this isn't harmful, lots of the * cheap repeater hubs don't supply a heartbeat. * So ignore the lack of heartbeat. Its only * if we can't detect a carrier that we have a * problem. */ ; if (isr & ISR_RDE) printf("%s: receive descriptors exhausted\n", device_xname(sc->sc_dev)); if (isr & ISR_RBE) printf("%s: receive buffers exhausted\n", device_xname(sc->sc_dev)); if (isr & ISR_RBAE) printf("%s: receive buffer area exhausted\n", device_xname(sc->sc_dev)); if (isr & ISR_RFO) printf("%s: receive FIFO overrun\n", device_xname(sc->sc_dev)); } if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) { #ifdef notdef if (isr & ISR_CRC) sc->sc_crctally++; if (isr & ISR_FAE) sc->sc_faetally++; if (isr & ISR_MP) sc->sc_mptally++; #endif } snstart(&sc->sc_if); } return handled; }
static void camprogram(struct sn_softc *sc) { struct ether_multistep step; struct ether_multi *enm; struct ifnet *ifp; int timeout; int mcount = 0; caminitialise(sc); ifp = &sc->sc_if; /* Always load our own address first. */ camentry(sc, mcount, CLLADDR(ifp->if_sadl)); mcount++; /* Assume we won't need allmulti bit. */ ifp->if_flags &= ~IFF_ALLMULTI; /* Loop through multicast addresses */ ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm); while (enm != NULL) { if (mcount == MAXCAM) { ifp->if_flags |= IFF_ALLMULTI; break; } if (memcmp(enm->enm_addrlo, enm->enm_addrhi, sizeof(enm->enm_addrlo)) != 0) { /* * SONIC's CAM is programmed with specific * addresses. It has no way to specify a range. * (Well, thats not exactly true. If the * range is small one could program each addr * within the range as a separate CAM entry) */ ifp->if_flags |= IFF_ALLMULTI; break; } /* program the CAM with the specified entry */ camentry(sc, mcount, enm->enm_addrlo); mcount++; ETHER_NEXT_MULTI(step, enm); } NIC_PUT(sc, SNR_CDP, LOWER(sc->v_cda)); NIC_PUT(sc, SNR_CDC, MAXCAM); NIC_PUT(sc, SNR_CR, CR_LCAM); wbflush(); timeout = 10000; while ((NIC_GET(sc, SNR_CR) & CR_LCAM) && timeout--) delay(10); if (timeout == 0) { /* XXX */ panic("%s: CAM initialisation failed", device_xname(sc->sc_dev)); } timeout = 10000; while (((NIC_GET(sc, SNR_ISR) & ISR_LCD) == 0) && timeout--) delay(10); if (NIC_GET(sc, SNR_ISR) & ISR_LCD) NIC_PUT(sc, SNR_ISR, ISR_LCD); else printf("%s: CAM initialisation without interrupt\n", device_xname(sc->sc_dev)); }
/* * stuff packet into sonic (at splnet) */ static inline u_int sonicput(struct sn_softc *sc, struct mbuf *m0, int mtd_next) { struct mtd *mtdp; struct mbuf *m; u_char *buff; void *txp; u_int len = 0; u_int totlen = 0; #ifdef whyonearthwouldyoudothis if (NIC_GET(sc, SNR_CR) & CR_TXP) return 0; #endif /* grab the replacement mtd */ mtdp = &sc->mtda[sc->mtd_free]; buff = mtdp->mtd_buf; /* this packet goes to mtdnext fill in the TDA */ mtdp->mtd_mbuf = m0; txp = mtdp->mtd_txp; /* Write to the config word. Every (NTDA/2)+1 packets we set an intr */ if (sc->mtd_pint == 0) { sc->mtd_pint = NTDA/2; SWO(sc->bitmode, txp, TXP_CONFIG, TCR_PINT); } else { sc->mtd_pint--; SWO(sc->bitmode, txp, TXP_CONFIG, 0); } for (m = m0; m; m = m->m_next) { u_char *data = mtod(m, u_char *); len = m->m_len; totlen += len; memcpy(buff, data, len); buff += len; } if (totlen >= TXBSIZE) { panic("%s: sonicput: packet overflow", device_xname(sc->sc_dev)); } SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO, LOWER(mtdp->mtd_vbuf)); SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI, UPPER(mtdp->mtd_vbuf)); if (totlen < ETHERMIN + ETHER_HDR_LEN) { int pad = ETHERMIN + ETHER_HDR_LEN - totlen; memset((char *)mtdp->mtd_buf + totlen, 0, pad); totlen = ETHERMIN + ETHER_HDR_LEN; } 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 */ SWO(sc->bitmode, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO, LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL); /* * 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)); /* make sure chip is running */ wbflush(); NIC_PUT(sc, SNR_CR, CR_TXP); wbflush(); sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */ return totlen; }
static int sninit(struct sn_softc *sc) { u_long s_rcr; int s; if (sc->sc_if.if_flags & IFF_RUNNING) /* already running */ return 0; s = splnet(); NIC_PUT(sc, SNR_CR, CR_RST); /* DCR only accessible in reset mode! */ /* config it */ NIC_PUT(sc, SNR_DCR, (sc->snr_dcr | (sc->bitmode ? DCR_DW32 : DCR_DW16))); NIC_PUT(sc, SNR_DCR2, sc->snr_dcr2); s_rcr = RCR_BRD | RCR_LBNONE; if (sc->sc_if.if_flags & IFF_PROMISC) s_rcr |= RCR_PRO; if (sc->sc_if.if_flags & IFF_ALLMULTI) s_rcr |= RCR_AMC; NIC_PUT(sc, SNR_RCR, s_rcr); #if 0 NIC_PUT(sc, SNR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN)); #else NIC_PUT(sc, SNR_IMR, IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN | IMR_BREN | IMR_HBLEN | IMR_RDEEN | IMR_RBEEN | IMR_RBAEEN | IMR_RFOEN); #endif /* clear pending interrupts */ NIC_PUT(sc, SNR_ISR, ISR_ALL); /* clear tally counters */ NIC_PUT(sc, SNR_CRCT, -1); NIC_PUT(sc, SNR_FAET, -1); NIC_PUT(sc, SNR_MPT, -1); initialise_tda(sc); initialise_rda(sc); initialise_rra(sc); sn_md_init(sc); /* MD initialization */ /* enable the chip */ NIC_PUT(sc, SNR_CR, 0); wbflush(); /* program the CAM */ camprogram(sc); /* get it to read resource descriptors */ NIC_PUT(sc, SNR_CR, CR_RRRA); wbflush(); while ((NIC_GET(sc, SNR_CR)) & CR_RRRA) continue; /* enable rx */ NIC_PUT(sc, SNR_CR, CR_RXEN); wbflush(); /* flag interface as "running" */ sc->sc_if.if_flags |= IFF_RUNNING; sc->sc_if.if_flags &= ~IFF_OACTIVE; splx(s); return 0; }
void mc_init(struct mc_softc *sc) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; u_int8_t maccc, ladrf[8]; int s, i; s = splnet(); NIC_PUT(sc, MACE_BIUCC, sc->sc_biucc); NIC_PUT(sc, MACE_FIFOCC, sc->sc_fifocc); NIC_PUT(sc, MACE_IMR, ~0); /* disable all interrupts */ NIC_PUT(sc, MACE_PLSCC, sc->sc_plscc); NIC_PUT(sc, MACE_UTR, RTRD); /* disable reserved test registers */ /* set MAC address */ NIC_PUT(sc, MACE_IAC, ADDRCHG); while (NIC_GET(sc, MACE_IAC) & ADDRCHG) ; NIC_PUT(sc, MACE_IAC, PHYADDR); for (i = 0; i < ETHER_ADDR_LEN; i++) out8rb(sc->sc_reg + MACE_REG(MACE_PADR) + i, sc->sc_enaddr[i]); /* set logical address filter */ mace_calcladrf(sc, ladrf); NIC_PUT(sc, MACE_IAC, ADDRCHG); while (NIC_GET(sc, MACE_IAC) & ADDRCHG) ; NIC_PUT(sc, MACE_IAC, LOGADDR); for (i = 0; i < 8; i++) out8rb(sc->sc_reg + MACE_REG(MACE_LADRF) + i, ladrf[i]); NIC_PUT(sc, MACE_XMTFC, APADXMT); /* * No need to autostrip padding on receive... Ethernet frames * don't have a length field, unlike 802.3 frames, so the MACE * can't figure out the length of the packet anyways. */ NIC_PUT(sc, MACE_RCVFC, 0); maccc = ENXMT | ENRCV; if (ifp->if_flags & IFF_PROMISC) maccc |= PROM; NIC_PUT(sc, MACE_MACCC, maccc); mc_reset_rxdma(sc); mc_reset_txdma(sc); /* * Enable all interrupts except receive, since we use the DMA * completion interrupt for that. */ NIC_PUT(sc, MACE_IMR, RCVINTM); /* flag interface as "running" */ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; splx(s); }
/* * Install interface into kernel networking data structures */ static void sn_obio_attach(struct device *parent, struct device *self, void *aux) { struct obio_attach_args *oa = (struct obio_attach_args *)aux; struct sn_softc *sc = (void *)self; u_int8_t myaddr[ETHER_ADDR_LEN]; int i; sc->snr_dcr = DCR_WAIT0 | DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16; sc->snr_dcr2 = 0; sc->slotno = 9; switch (current_mac_model->machineid) { case MACH_MACC610: case MACH_MACC650: case MACH_MACQ610: case MACH_MACQ650: case MACH_MACQ700: case MACH_MACQ800: case MACH_MACQ900: case MACH_MACQ950: sc->snr_dcr |= DCR_EXBUS; sc->bitmode = 1; break; case MACH_MACLC575: case MACH_MACP580: case MACH_MACQ630: break; case MACH_MACPB500: sc->snr_dcr |= DCR_SYNC | DCR_LBR; sc->bitmode = 0; /* 16 bit interface */ break; default: printf(": unsupported machine type\n"); return; } sc->sc_regt = oa->oa_tag; if (bus_space_map(sc->sc_regt, SONIC_REG_BASE, SN_REGSIZE, 0, &sc->sc_regh)) { printf(": failed to map space for SONIC regs.\n"); return; } /* regs are addressed as words, big-endian. */ for (i = 0; i < SN_NREGS; i++) { sc->sc_reg_map[i] = (bus_size_t)((i * 4) + 2); } /* * Kind of kludge this. Comm-slot cards do not really * have a visible type, as far as I can tell at this time, * so assume that MacOS had it properly configured and use * that configuration. */ switch (current_mac_model->machineid) { case MACH_MACLC575: case MACH_MACP580: case MACH_MACQ630: NIC_PUT(sc, SNR_CR, CR_RST); wbflush(); i = NIC_GET(sc, SNR_DCR); sc->snr_dcr |= (i & 0xfff0); sc->bitmode = (i & DCR_DW) ? 1 : 0; break; default: break; } if (sn_obio_getaddr(sc, myaddr) && sn_obio_getaddr_kludge(sc, myaddr)) { /* XXX kludge for PB */ printf(": failed to get MAC address.\n"); bus_space_unmap(sc->sc_regt, sc->sc_regh, SN_REGSIZE); return; } printf(": integrated ethernet adapter, "); /* snsetup returns 1 if something fails */ if (snsetup(sc, myaddr)) { bus_space_unmap(sc->sc_regt, sc->sc_regh, SN_REGSIZE); return; } if (mac68k_machine.aux_interrupts) intr_establish(snintr, sc, 3, sc->sc_dev.dv_xname); else add_nubus_intr(sc->slotno, IPL_NET, snintr, sc, sc->sc_dev.dv_xname); }