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); }
static void initialise_rda(struct sn_softc *sc) { int i; char *p_rda = 0; uint32_t v_rda = 0; /* link the RDA's together into a circular list */ for (i = 0; i < (sc->sc_nrda - 1); i++) { p_rda = (char *)sc->p_rda + (i * RXPKT_SIZE(sc)); v_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc)); SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(v_rda)); SWO(bitmode, p_rda, RXPKT_INUSE, 1); } p_rda = (char *)sc->p_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc)); SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL); SWO(bitmode, p_rda, RXPKT_INUSE, 1); /* mark end of receive descriptor list */ sc->sc_rdamark = sc->sc_nrda - 1; sc->sc_rxmark = 0; NIC_PUT(sc, SNR_URDA, UPPER(sc->v_rda)); NIC_PUT(sc, SNR_CRDA, LOWER(sc->v_rda)); wbflush(); }
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); }
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); }
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); }
static void initialise_rra(struct sn_softc *sc) { int i; u_int v; int bitmode = sc->bitmode; if (bitmode) NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 2); else NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 1); NIC_PUT(sc, SNR_URRA, UPPER(sc->v_rra[0])); NIC_PUT(sc, SNR_RSA, LOWER(sc->v_rra[0])); /* rea must point just past the end of the rra space */ NIC_PUT(sc, SNR_REA, LOWER(sc->v_rea)); NIC_PUT(sc, SNR_RRP, LOWER(sc->v_rra[0])); NIC_PUT(sc, SNR_RSC, 0); /* fill up SOME of the rra with buffers */ for (i = 0; i < NRBA; i++) { v = SONIC_GETDMA(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(PAGE_SIZE/2)); SWO(bitmode, sc->p_rra[i], RXRSRC_WCLO, LOWER(PAGE_SIZE/2)); } sc->sc_rramark = NRBA; NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[sc->sc_rramark])); wbflush(); }
/* * close down an interface and free its buffers * Called on final close of device, or if sninit() fails * part way through. */ static int snstop(struct sn_softc *sc) { struct mtd *mtd; int s = splnet(); /* stick chip in reset */ NIC_PUT(sc, SNR_CR, CR_RST); wbflush(); /* free all receive buffers (currently static so nothing to do) */ /* free all pending transmit mbufs */ while (sc->mtd_hw != sc->mtd_free) { mtd = &sc->mtda[sc->mtd_hw]; if (mtd->mtd_mbuf) m_freem(mtd->mtd_mbuf); if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0; } sc->sc_if.if_timer = 0; sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP); splx(s); return 0; }
static void initialise_tda(struct sn_softc *sc) { struct mtd *mtd; int i; for (i = 0; i < NTDA; i++) { mtd = &sc->mtda[i]; mtd->mtd_mbuf = 0; } sc->mtd_hw = 0; sc->mtd_prev = NTDA - 1; sc->mtd_free = 0; sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO; sc->mtd_pint = NTDA/2; NIC_PUT(sc, SNR_UTDA, UPPER(sc->mtda[0].mtd_vtxp)); NIC_PUT(sc, SNR_CTDA, LOWER(sc->mtda[0].mtd_vtxp)); }
/* * 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(); }
/* * Close down an interface and free its buffers. * Called on final close of device, or if mcinit() fails * part way through. */ int mc_stop(struct mc_softc *sc) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; int s; s = splnet(); NIC_PUT(sc, MACE_BIUCC, SWRST); DELAY(100); ifp->if_timer = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); splx(s); return (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); }
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)); }
void ed_zbus_attach(device_t parent, device_t self, void *aux) { struct ed_zbus_softc *zsc = device_private(self); struct dp8390_softc *sc = &zsc->sc_dp8390; struct zbus_args *zap = aux; bus_space_handle_t promh; bus_addr_t memaddr, promaddr, regaddr; int i; zsc->sc_bst.base = (bus_addr_t)zap->va; zsc->sc_bst.absm = &amiga_bus_stride_1; if (zap->manid == HYDRA_MANID) { regaddr = HYDRA_REGADDR; memaddr = HYDRA_MEMADDR; promaddr = HYDRA_PROMADDR; } else { regaddr = ASDG_REGADDR; memaddr = ASDG_MEMADDR; promaddr = ASDG_PROMADDR; } sc->sc_dev = self; sc->sc_regt = &zsc->sc_bst; sc->sc_buft = &zsc->sc_bst; if (bus_space_map(sc->sc_regt, regaddr, 0x20, 0, &sc->sc_regh)) { aprint_error_dev(self, "can't map i/o space\n"); return; } if (bus_space_map(sc->sc_buft, memaddr, ED_ZBUS_MEMSIZE, 0, &sc->sc_bufh)) { aprint_error_dev(self, "can't map buffer space\n"); return; } /* SRAM buffer size is always 16K */ sc->mem_start = 0; sc->mem_size = ED_ZBUS_MEMSIZE; /* * Read the ethernet address from the PROM. * Interrupts must be inactive when reading the PROM, as the * interrupt line is shared with one of its address lines. */ NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_IMR, 0x00); NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_ISR, 0xff); if (bus_space_map(&zsc->sc_bst, promaddr, ETHER_ADDR_LEN * 2, 0, &promh) == 0) { for (i = 0; i < ETHER_ADDR_LEN; i++) sc->sc_enaddr[i] = bus_space_read_1(&zsc->sc_bst, promh, i * 2); bus_space_unmap(&zsc->sc_bst, promh, ETHER_ADDR_LEN * 2); } /* Initialize sc_reg_map[]. Registers have stride 2 on the bus. */ for (i = 0; i < 16; i++) sc->sc_reg_map[i] = i << 1; /* * Set 2 word FIFO threshold, no auto-init Remote DMA, * byte order 68k, word-wide DMA xfers. */ sc->dcr_reg = ED_DCR_FT0 | ED_DCR_WTS | ED_DCR_LS | ED_DCR_BOS; /* Remote DMA abort .*/ sc->cr_proto = ED_CR_RD2; /* * Override all functions which deal with the buffer, because * this implementation only allows 16-bit buffer accesses. */ sc->test_mem = ed_zbus_test_mem; sc->read_hdr = ed_zbus_read_hdr; sc->ring_copy = ed_zbus_ring_copy; sc->write_mbuf = ed_zbus_write_mbuf; sc->sc_flags = device_cfdata(self)->cf_flags; sc->is790 = 0; sc->sc_media_init = dp8390_media_init; sc->sc_enabled = 1; /* Do generic DS8390/WD83C690 config. */ if (dp8390_config(sc)) { bus_space_unmap(sc->sc_buft, sc->sc_bufh, ED_ZBUS_MEMSIZE); bus_space_unmap(sc->sc_regt, sc->sc_regh, 0x10); return; } /* establish level 2 interrupt handler */ zsc->sc_isr.isr_intr = dp8390_intr; zsc->sc_isr.isr_arg = sc; zsc->sc_isr.isr_ipl = 2; add_isr(&zsc->sc_isr); }
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 {
void mc_attach(struct device *parent, struct device *self, void *aux) { struct confargs *ca = aux; struct mc_softc *sc = (struct mc_softc *)self; struct ifnet *ifp = &sc->sc_arpcom.ac_if; u_int8_t lladdr[ETHER_ADDR_LEN]; int nseg, error; if (OF_getprop(ca->ca_node, "local-mac-address", lladdr, ETHER_ADDR_LEN) != ETHER_ADDR_LEN) { printf(": failed to get MAC address.\n"); return; } ca->ca_reg[0] += ca->ca_baseaddr; ca->ca_reg[2] += ca->ca_baseaddr; ca->ca_reg[4] += ca->ca_baseaddr; if ((sc->sc_reg = mapiodev(ca->ca_reg[0], ca->ca_reg[1])) == NULL) { printf(": cannot map registers\n"); return; } sc->sc_dmat = ca->ca_dmat; sc->sc_tail = 0; if ((sc->sc_txdma = mapiodev(ca->ca_reg[2], ca->ca_reg[3])) == NULL) { printf(": cannot map TX DMA registers\n"); goto notxdma; } if ((sc->sc_rxdma = mapiodev(ca->ca_reg[4], ca->ca_reg[5])) == NULL) { printf(": cannot map RX DMA registers\n"); goto norxdma; } if ((sc->sc_txdbdma = dbdma_alloc(sc->sc_dmat, 2)) == NULL) { printf(": cannot alloc TX DMA descriptors\n"); goto notxdbdma; } sc->sc_txdmacmd = sc->sc_txdbdma->d_addr; if ((sc->sc_rxdbdma = dbdma_alloc(sc->sc_dmat, 8 + 1)) == NULL) { printf(": cannot alloc RX DMA descriptors\n"); goto norxdbdma; } sc->sc_rxdmacmd = sc->sc_rxdbdma->d_addr; if ((error = bus_dmamem_alloc(sc->sc_dmat, MACE_BUFSZ, PAGE_SIZE, 0, sc->sc_bufseg, 1, &nseg, BUS_DMA_NOWAIT))) { printf(": cannot allocate DMA mem (%d)\n", error); goto nodmamem; } if ((error = bus_dmamem_map(sc->sc_dmat, sc->sc_bufseg, nseg, MACE_BUFSZ, &sc->sc_txbuf, BUS_DMA_NOWAIT))) { printf(": cannot map DMA mem (%d)\n", error); goto nodmamap; } if ((error = bus_dmamap_create(sc->sc_dmat, MACE_BUFSZ, 1, MACE_BUFSZ, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_bufmap))) { printf(": cannot create DMA map (%d)\n", error); goto nodmacreate; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_bufmap, sc->sc_txbuf, MACE_BUFSZ, NULL, BUS_DMA_NOWAIT))) { printf(": cannot load DMA map (%d)\n", error); goto nodmaload; } sc->sc_txbuf_pa = sc->sc_bufmap->dm_segs->ds_addr; sc->sc_rxbuf = sc->sc_txbuf + MACE_BUFLEN * MACE_TXBUFS; sc->sc_rxbuf_pa = sc->sc_txbuf_pa + MACE_BUFLEN * MACE_TXBUFS; printf(": irq %d,%d,%d", ca->ca_intr[0], ca->ca_intr[1], ca->ca_intr[2]); /* disable receive DMA */ dbdma_reset(sc->sc_rxdma); /* disable transmit DMA */ dbdma_reset(sc->sc_txdma); /* install interrupt handlers */ mac_intr_establish(parent, ca->ca_intr[2], IST_LEVEL, IPL_NET, mc_dmaintr, sc, sc->sc_dev.dv_xname); mac_intr_establish(parent, ca->ca_intr[0], IST_LEVEL, IPL_NET, mc_intr, sc, sc->sc_dev.dv_xname); sc->sc_biucc = XMTSP_64; sc->sc_fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST; sc->sc_plscc = PORTSEL_GPSI | ENPLSIO; /* reset the chip and disable all interrupts */ NIC_PUT(sc, MACE_BIUCC, SWRST); DELAY(100); NIC_PUT(sc, MACE_IMR, ~0); bcopy(lladdr, sc->sc_enaddr, ETHER_ADDR_LEN); bcopy(sc->sc_enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); printf(": address %s\n", ether_sprintf(lladdr)); bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_ioctl = mc_ioctl; ifp->if_start = mc_start; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; ifp->if_watchdog = mc_watchdog; ifp->if_timer = 0; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); ether_ifattach(ifp); return; nodmaload: bus_dmamap_destroy(sc->sc_dmat, sc->sc_bufmap); nodmacreate: bus_dmamem_unmap(sc->sc_dmat, sc->sc_txbuf, MACE_BUFSZ); nodmamap: bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, 1); nodmamem: dbdma_free(sc->sc_rxdbdma); norxdbdma: dbdma_free(sc->sc_txdbdma); notxdbdma: unmapiodev((void *)sc->sc_rxdma, ca->ca_reg[5]); norxdma: unmapiodev((void *)sc->sc_txdma, ca->ca_reg[3]); notxdma: unmapiodev(sc->sc_reg, ca->ca_reg[1]); }
/* * Receive interrupt routine */ static void sonicrxint(struct sn_softc *sc) { void * rda; int orra; int len; int rramark; int rdamark; uint16_t rxpkt_ptr; rda = (char *)sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); while (SRO(bitmode, rda, RXPKT_INUSE) == 0) { u_int status = SRO(bitmode, rda, RXPKT_STATUS); orra = RBASEQ(SRO(bitmode, rda, RXPKT_SEQNO)) & RRAMASK; rxpkt_ptr = SRO(bitmode, rda, RXPKT_PTRLO); len = SRO(bitmode, rda, RXPKT_BYTEC) - FCSSIZE; if (status & RCR_PRX) { void *pkt = (char *)sc->rbuf[orra & RBAMASK] + (rxpkt_ptr & PGOFSET); if (sonic_read(sc, pkt, len)) sc->sc_if.if_ipackets++; else sc->sc_if.if_ierrors++; } else sc->sc_if.if_ierrors++; /* * give receive buffer area back to chip. * * If this was the last packet in the RRA, give the RRA to * the chip again. * 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. */ if (status & RCR_LPKT) { void *tmp1, *tmp2; 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 */ SWO(bitmode, tmp2, RXRSRC_WCHI, 0); SWO(bitmode, tmp2, RXRSRC_WCLO, 0); sc->sc_rramark = (++rramark) & RRAMASK; NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[rramark])); wbflush(); } /* * give receive descriptor back to chip simple * list is circular */ rdamark = sc->sc_rdamark; SWO(bitmode, rda, RXPKT_INUSE, 1); SWO(bitmode, rda, RXPKT_RLINK, SRO(bitmode, rda, RXPKT_RLINK) | EOL); SWO(bitmode, ((char *)sc->p_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK, SRO(bitmode, ((char *)sc->p_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK) & ~EOL); sc->sc_rdamark = sc->sc_rxmark; if (++sc->sc_rxmark >= sc->sc_nrda) sc->sc_rxmark = 0; rda = (char *)sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); } }
/* * Transmit interrupt routine */ static void sonictxint(struct sn_softc *sc) { struct mtd *mtd; void *txp; unsigned short txp_status; int mtd_hw; struct ifnet *ifp = &sc->sc_if; mtd_hw = sc->mtd_hw; if (mtd_hw == sc->mtd_free) return; while (mtd_hw != sc->mtd_free) { mtd = &sc->mtda[mtd_hw]; txp = mtd->mtd_txp; if (SRO(sc->bitmode, txp, TXP_STATUS) == 0) { break; /* it hasn't really gone yet */ } #ifdef SNDEBUG { struct ether_header *eh; eh = (struct ether_header *) mtd->mtd_buf; printf("%s: xmit status=0x%x len=%d type=0x%x from %s", device_xname(sc->sc_dev), 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)); } #endif /* SNDEBUG */ ifp->if_flags &= ~IFF_OACTIVE; if (mtd->mtd_mbuf != 0) { m_freem(mtd->mtd_mbuf); mtd->mtd_mbuf = 0; } if (++mtd_hw == NTDA) mtd_hw = 0; txp_status = SRO(sc->bitmode, txp, TXP_STATUS); ifp->if_collisions += (txp_status & TCR_EXC) ? 16 : ((txp_status & TCR_NC) >> 12); if ((txp_status & TCR_PTX) == 0) { ifp->if_oerrors++; printf("%s: Tx packet status=0x%x\n", device_xname(sc->sc_dev), txp_status); /* XXX - DG This looks bogus */ if (mtd_hw != sc->mtd_free) { printf("resubmitting remaining packets\n"); mtd = &sc->mtda[mtd_hw]; NIC_PUT(sc, SNR_CTDA, LOWER(mtd->mtd_vtxp)); NIC_PUT(sc, SNR_CR, CR_TXP); wbflush(); break; } } } sc->mtd_hw = mtd_hw; return; }
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; }
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); }
/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ int sncsetup(struct snc_softc *sc, u_int8_t *lladdr) { u_int32_t p, pp; int i; int offset; /* * Put the pup in reset mode (sncinit() will fix it later), * stop the timer, disable all interrupts and clear any interrupts. */ NIC_PUT(sc, SNCR_CR, CR_STP); wbflush(); NIC_PUT(sc, SNCR_CR, CR_RST); wbflush(); NIC_PUT(sc, SNCR_IMR, 0); wbflush(); NIC_PUT(sc, SNCR_ISR, ISR_ALL); wbflush(); /* * because the SONIC is basically 16bit device it 'concatenates' * a higher buffer address to a 16 bit offset--this will cause wrap * around problems near the end of 64k !! */ p = pp = 0; for (i = 0; i < NRRA; i++) { sc->v_rra[i] = SONIC_GETDMA(p); p += RXRSRC_SIZE(sc); } sc->v_rea = SONIC_GETDMA(p); p = SOALIGN(sc, p); sc->v_cda = SONIC_GETDMA(p); p += CDA_SIZE(sc); p = SOALIGN(sc, p); for (i = 0; i < NTDA; i++) { struct mtd *mtdp = &sc->mtda[i]; mtdp->mtd_vtxp = SONIC_GETDMA(p); p += TXP_SIZE(sc); } p = SOALIGN(sc, p); if ((p - pp) > PAGE_SIZE) { device_printf (sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +" "TDA (%ld) > PAGE_SIZE (%d). Punt!\n", (u_long)sc->v_cda - (u_long)sc->v_rra[0], (u_long)sc->mtda[0].mtd_vtxp - (u_long)sc->v_cda, (u_long)p - (u_long)sc->mtda[0].mtd_vtxp, PAGE_SIZE); return(1); } p = pp + PAGE_SIZE; pp = p; sc->sc_nrda = PAGE_SIZE / RXPKT_SIZE(sc); sc->v_rda = SONIC_GETDMA(p); p = pp + PAGE_SIZE; for (i = 0; i < NRBA; i++) { sc->rbuf[i] = p; p += PAGE_SIZE; } pp = p; offset = TXBSIZE; for (i = 0; i < NTDA; i++) { struct mtd *mtdp = &sc->mtda[i]; mtdp->mtd_vbuf = SONIC_GETDMA(p); offset += TXBSIZE; if (offset < PAGE_SIZE) { p += TXBSIZE; } else { p = pp + PAGE_SIZE; pp = p; offset = TXBSIZE; } } return (0); }
/* * 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); }
/* * 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; }
/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ int snsetup(struct sn_softc *sc, uint8_t *lladdr) { struct ifnet *ifp = &sc->sc_if; uint8_t *p; uint8_t *pp; int i; if (sc->space == NULL) { aprint_error_dev(sc->sc_dev, "memory allocation for descriptors failed\n"); return 1; } /* * Put the pup in reset mode (sninit() will fix it later), * stop the timer, disable all interrupts and clear any interrupts. */ NIC_PUT(sc, SNR_CR, CR_STP); wbflush(); NIC_PUT(sc, SNR_CR, CR_RST); wbflush(); NIC_PUT(sc, SNR_IMR, 0); wbflush(); NIC_PUT(sc, SNR_ISR, ISR_ALL); wbflush(); /* * because the SONIC is basically 16bit device it 'concatenates' * a higher buffer address to a 16 bit offset--this will cause wrap * around problems near the end of 64k !! */ p = sc->space; pp = (uint8_t *)roundup((int)p, PAGE_SIZE); p = pp; for (i = 0; i < NRRA; i++) { sc->p_rra[i] = (void *)p; sc->v_rra[i] = SONIC_GETDMA(p); p += RXRSRC_SIZE(sc); } sc->v_rea = SONIC_GETDMA(p); p = (uint8_t *)SOALIGN(sc, p); sc->p_cda = (void *)(p); sc->v_cda = SONIC_GETDMA(p); p += CDA_SIZE(sc); p = (uint8_t *)SOALIGN(sc, p); for (i = 0; i < NTDA; i++) { struct mtd *mtdp = &sc->mtda[i]; mtdp->mtd_txp = (void *)p; mtdp->mtd_vtxp = SONIC_GETDMA(p); p += TXP_SIZE(sc); } p = (uint8_t *)SOALIGN(sc, p); if ((p - pp) > PAGE_SIZE) { aprint_error_dev(sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +" "TDA (%ld) > PAGE_SIZE (%d). Punt!\n", (ulong)sc->p_cda - (ulong)sc->p_rra[0], (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_cda, (ulong)p - (ulong)sc->mtda[0].mtd_txp, PAGE_SIZE); return 1; } p = pp + PAGE_SIZE; pp = p; sc->sc_nrda = PAGE_SIZE / RXPKT_SIZE(sc); sc->p_rda = (void *)p; sc->v_rda = SONIC_GETDMA(p); p = pp + PAGE_SIZE; for (i = 0; i < NRBA; i++) { sc->rbuf[i] = (void *)p; p += PAGE_SIZE; } pp = p; for (i = 0; i < NTDA; i++) { struct mtd *mtdp = &sc->mtda[i]; mtdp->mtd_buf = p; mtdp->mtd_vbuf = SONIC_GETDMA(p); p += TXBSIZE; } #ifdef SNDEBUG camdump(sc); #endif aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n", ether_sprintf(lladdr)); #ifdef SNDEBUG aprint_debug_dev(sc->sc_dev, "buffers: rra=%p cda=%p rda=%p tda=%p\n", device_xname(sc->sc_dev), sc->p_rra[0], sc->p_cda, sc->p_rda, sc->mtda[0].mtd_txp); #endif strcpy(ifp->if_xname, device_xname(sc->sc_dev)); ifp->if_softc = sc; ifp->if_ioctl = snioctl; ifp->if_start = snstart; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; ifp->if_watchdog = snwatchdog; if_attach(ifp); ether_ifattach(ifp, lladdr); return 0; }
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; }