/* * Read a word of data stored in the EEPROM at address 'addr.' */ uint16_t rtk_read_eeprom(struct rtk_softc *sc, int addr, int addr_len) { uint16_t word; int i; /* Enter EEPROM access mode. */ CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_PROGRAM); EE_DELAY(); EE_SET(RTK_EE_SEL); /* * Send address of word we want to read. */ rtk_eeprom_putbyte(sc, addr, addr_len); /* * Start reading bits from EEPROM. */ word = 0; for (i = 16; i > 0; i--) { EE_SET(RTK_EE_CLK); EE_DELAY(); if (CSR_READ_1(sc, RTK_EECMD) & RTK_EE_DATAOUT) word |= 1 << (i - 1); EE_CLR(RTK_EE_CLK); EE_DELAY(); } /* Turn off EEPROM access mode. */ CSR_WRITE_1(sc, RTK_EECMD, RTK_EEMODE_OFF); return word; }
/* * Program the 64-bit multicast hash filter. */ static void vr_setmulti(struct vr_softc *sc) { struct ifnet *ifp; int h = 0; uint32_t hashes[2] = { 0, 0 }; struct ether_multistep step; struct ether_multi *enm; int mcnt = 0; uint8_t rxfilt; ifp = &sc->vr_ec.ec_if; rxfilt = CSR_READ_1(sc, VR_RXCFG); if (ifp->if_flags & IFF_PROMISC) { allmulti: ifp->if_flags |= IFF_ALLMULTI; rxfilt |= VR_RXCFG_RX_MULTI; CSR_WRITE_1(sc, VR_RXCFG, rxfilt); CSR_WRITE_4(sc, VR_MAR0, 0xFFFFFFFF); CSR_WRITE_4(sc, VR_MAR1, 0xFFFFFFFF); return; } /* first, zot all the existing hash bits */ CSR_WRITE_4(sc, VR_MAR0, 0); CSR_WRITE_4(sc, VR_MAR1, 0); /* now program new ones */ ETHER_FIRST_MULTI(step, &sc->vr_ec, enm); while (enm != NULL) { if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN) != 0) goto allmulti; h = vr_calchash(enm->enm_addrlo); if (h < 32) hashes[0] |= (1 << h); else hashes[1] |= (1 << (h - 32)); ETHER_NEXT_MULTI(step, enm); mcnt++; } ifp->if_flags &= ~IFF_ALLMULTI; if (mcnt) rxfilt |= VR_RXCFG_RX_MULTI; else rxfilt &= ~VR_RXCFG_RX_MULTI; CSR_WRITE_4(sc, VR_MAR0, hashes[0]); CSR_WRITE_4(sc, VR_MAR1, hashes[1]); CSR_WRITE_1(sc, VR_RXCFG, rxfilt); }
static void issue28(struct dvata_chan *chan, int64_t bno, int nblk) { CSR_WRITE_1(chan->cmd + _NSECT, nblk); CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 0) & 0xff); CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 8) & 0xff); CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 16) & 0xff); CSR_WRITE_1(chan->cmd + _DEV, ((bno >> 24) & 0xf) | ATA_DEV_LBA); CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_READ); }
static void set_xfermode(struct dkdev_ata *l, int n) { struct dvata_chan *chan = &l->chan[n]; CSR_WRITE_1(chan->cmd + _FEA, ATA_XFER); CSR_WRITE_1(chan->cmd + _NSECT, XFER_PIO0); CSR_WRITE_1(chan->cmd + _DEV, ATA_DEV_OBS); /* ??? */ CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_SETF); spinwait_unbusy(l, n, 1000, NULL); }
int perform_atareset(struct dkdev_ata *l, int n) { struct dvata_chan *chan = &l->chan[n]; CSR_WRITE_1(chan->ctl, ATA_DREQ); delay(10); CSR_WRITE_1(chan->ctl, ATA_SRST|ATA_DREQ); delay(10); CSR_WRITE_1(chan->ctl, ATA_DREQ); return spinwait_unbusy(l, n, 1000, NULL); }
/* clear idle and standby timers to spin up the drive */ void wakeup_drive(struct dkdev_ata *l, int n) { struct dvata_chan *chan = &l->chan[n]; CSR_WRITE_1(chan->cmd + _NSECT, 0); CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_IDLE); (void)CSR_READ_1(chan->alt); delay(10 * 1000); CSR_WRITE_1(chan->cmd + _NSECT, 0); CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_STANDBY); (void)CSR_READ_1(chan->alt); delay(10 * 1000); }
static void issue48(struct dvata_chan *chan, int64_t bno, int nblk) { CSR_WRITE_1(chan->cmd + _NSECT, 0); /* always less than 256 */ CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 24) & 0xff); CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 32) & 0xff); CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 40) & 0xff); CSR_WRITE_1(chan->cmd + _NSECT, nblk); CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 0) & 0xff); CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 8) & 0xff); CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 16) & 0xff); CSR_WRITE_1(chan->cmd + _DEV, ATA_DEV_LBA); CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_READ_EXT); }
static void vr_mii_bitbang_write(device_t self, uint32_t val) { struct vr_softc *sc = device_private(self); CSR_WRITE_1(sc, VR_MIICMD, (val & 0xff) | VR_MIICMD_DIRECTPGM); }
/* * Write to a PHY register through the MII. */ static void vr_mii_writereg(device_t self, int phy, int reg, int val) { struct vr_softc *sc = device_private(self); CSR_WRITE_1(sc, VR_MIICMD, VR_MIICMD_DIRECTPGM); mii_bitbang_writereg(self, &vr_mii_bitbang_ops, phy, reg, val); }
/* * Read an PHY register through the MII. */ static int vr_mii_readreg(device_t self, int phy, int reg) { struct vr_softc *sc = device_private(self); CSR_WRITE_1(sc, VR_MIICMD, VR_MIICMD_DIRECTPGM); return (mii_bitbang_readreg(self, &vr_mii_bitbang_ops, phy, reg)); }
int atachkpwr(struct dkdev_ata *l, int n) { struct dvata_chan *chan = &l->chan[n]; CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_CHKPWR); (void)CSR_READ_1(chan->alt); delay(10 * 1000); return CSR_READ_1(chan->cmd + _NSECT); }
/* * Bring device up. */ void ex_init(void) { int i; ex_waitcmd(); EtherStop(); /* * Set the station address and clear the station mask. The latter * is needed for 90x cards, 0 is the default for 90xB cards. */ GO_WINDOW(2); for (i = 0; i < 6; i++) { CSR_WRITE_1(ELINK_W2_ADDR_0 + i, myethaddr[i]); CSR_WRITE_1(ELINK_W2_RECVMASK_0 + i, 0); } GO_WINDOW(3); CSR_WRITE_2(ELINK_COMMAND, RX_RESET); ex_waitcmd(); CSR_WRITE_2(ELINK_COMMAND, TX_RESET); ex_waitcmd(); CSR_WRITE_2(ELINK_COMMAND, SET_INTR_MASK | 0); /* disable */ CSR_WRITE_2(ELINK_COMMAND, ACK_INTR | 0xff); ex_set_media(); CSR_WRITE_2(ELINK_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST); CSR_WRITE_4(ELINK_DNLISTPTR, 0); CSR_WRITE_2(ELINK_COMMAND, TX_ENABLE); CSR_WRITE_4(ELINK_UPLISTPTR, RECVBUF_PHYS); CSR_WRITE_2(ELINK_COMMAND, RX_ENABLE); CSR_WRITE_2(ELINK_COMMAND, ELINK_UPUNSTALL); GO_WINDOW(1); }
void ste_iff(struct ste_softc *sc) { struct ifnet *ifp = &sc->arpcom.ac_if; struct arpcom *ac = &sc->arpcom; struct ether_multi *enm; struct ether_multistep step; u_int32_t rxmode, hashes[2]; int h = 0; rxmode = CSR_READ_1(sc, STE_RX_MODE); rxmode &= ~(STE_RXMODE_ALLMULTI | STE_RXMODE_BROADCAST | STE_RXMODE_MULTIHASH | STE_RXMODE_PROMISC | STE_RXMODE_UNICAST); bzero(hashes, sizeof(hashes)); ifp->if_flags &= ~IFF_ALLMULTI; /* * Always accept broadcast frames. * Always accept frames destined to our station address. */ rxmode |= STE_RXMODE_BROADCAST | STE_RXMODE_UNICAST; if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { ifp->if_flags |= IFF_ALLMULTI; rxmode |= STE_RXMODE_ALLMULTI; if (ifp->if_flags & IFF_PROMISC) rxmode |= STE_RXMODE_PROMISC; } else { rxmode |= STE_RXMODE_MULTIHASH; /* now program new ones */ ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) & 0x3F; if (h < 32) hashes[0] |= (1 << h); else hashes[1] |= (1 << (h - 32)); ETHER_NEXT_MULTI(step, enm); } } CSR_WRITE_2(sc, STE_MAR0, hashes[0] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR1, (hashes[0] >> 16) & 0xFFFF); CSR_WRITE_2(sc, STE_MAR2, hashes[1] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR3, (hashes[1] >> 16) & 0xFFFF); CSR_WRITE_1(sc, STE_RX_MODE, rxmode); }
/* * Read EEPROM data. * XXX what to do if EEPROM doesn't unbusy? */ uint16_t ex_read_eeprom(int offset) { uint16_t data = 0; GO_WINDOW(0); if (ex_eeprom_busy()) goto out; CSR_WRITE_1(ELINK_W0_EEPROM_COMMAND, READ_EEPROM | (offset & 0x3f)); if (ex_eeprom_busy()) goto out; data = CSR_READ_2(ELINK_W0_EEPROM_DATA); out: return data; }
void rtk_reset(struct rtk_softc *sc) { int i; CSR_WRITE_1(sc, RTK_COMMAND, RTK_CMD_RESET); for (i = 0; i < RTK_TIMEOUT; i++) { DELAY(10); if ((CSR_READ_1(sc, RTK_COMMAND) & RTK_CMD_RESET) == 0) break; } if (i == RTK_TIMEOUT) printf("%s: reset never completed!\n", device_xname(sc->sc_dev)); }
static int probe_drive(struct dkdev_ata *l, int n) { struct dvata_chan *chan = &l->chan[n]; uint16_t *p; int i; CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_IDENT); (void)CSR_READ_1(chan->alt); delay(10 * 1000); if (spinwait_unbusy(l, n, 1000, NULL) == 0) return 0; p = (uint16_t *)l->iobuf; for (i = 0; i < 512; i += 2) { /* need to have bswap16 */ *p++ = iole16toh(chan->cmd + _DAT); } (void)CSR_READ_1(chan->cmd + _STS); return 1; }
/* Probe routine. See if the card is there and at the right place. */ static int el_probe(device_t dev) { struct el_softc *sc; u_short base; /* Just for convenience */ u_char station_addr[ETHER_ADDR_LEN]; int i, rid; /* Grab some info for our structure */ sc = device_get_softc(dev); if (isa_get_logicalid(dev)) /* skip PnP probes */ return (ENXIO); if ((base = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) return (ENXIO); /* First check the base */ if((base < 0x280) || (base > 0x3f0)) { device_printf(dev, "ioaddr must be between 0x280 and 0x3f0\n"); return(ENXIO); } /* Temporarily map the resources. */ rid = 0; sc->el_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, EL_IOSIZ, RF_ACTIVE); if (sc->el_res == NULL) return(ENXIO); sc->el_btag = rman_get_bustag(sc->el_res); sc->el_bhandle = rman_get_bushandle(sc->el_res); mtx_init(&sc->el_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); EL_LOCK(sc); /* Now attempt to grab the station address from the PROM * and see if it contains the 3com vendor code. */ dprintf(("Probing 3c501 at 0x%x...\n",base)); /* Reset the board */ dprintf(("Resetting board...\n")); CSR_WRITE_1(sc,EL_AC,EL_AC_RESET); DELAY(5); CSR_WRITE_1(sc,EL_AC,0); dprintf(("Reading station address...\n")); /* Now read the address */ for(i=0;i<ETHER_ADDR_LEN;i++) { CSR_WRITE_1(sc,EL_GPBL,i); station_addr[i] = CSR_READ_1(sc,EL_EAW); } /* Now release resources */ bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->el_res); EL_UNLOCK(sc); mtx_destroy(&sc->el_mtx); dprintf(("Address is %6D\n",station_addr, ":")); /* If the vendor code is ok, return a 1. We'll assume that * whoever configured this system is right about the IRQ. */ if((station_addr[0] != 0x02) || (station_addr[1] != 0x60) || (station_addr[2] != 0x8c)) { dprintf(("Bad vendor code.\n")); return(ENXIO); } else { dprintf(("Vendor code ok.\n")); /* Copy the station address into the arpcom structure */ bcopy(station_addr,sc->arpcom.ac_enaddr,ETHER_ADDR_LEN); } device_set_desc(dev, "3Com 3c501 Ethernet"); return(0); }
/* * Read an PHY register through the MII. */ static int vr_mii_readreg(struct vr_softc *sc, struct vr_mii_frame *frame) #ifdef VR_USESWSHIFT { int i, ack; /* Set up frame for RX. */ frame->mii_stdelim = VR_MII_STARTDELIM; frame->mii_opcode = VR_MII_READOP; frame->mii_turnaround = 0; frame->mii_data = 0; CSR_WRITE_1(sc, VR_MIICMD, 0); VR_SETBIT(sc, VR_MIICMD, VR_MIICMD_DIRECTPGM); /* Turn on data xmit. */ SIO_SET(VR_MIICMD_DIR); vr_mii_sync(sc); /* Send command/address info. */ vr_mii_send(sc, frame->mii_stdelim, 2); vr_mii_send(sc, frame->mii_opcode, 2); vr_mii_send(sc, frame->mii_phyaddr, 5); vr_mii_send(sc, frame->mii_regaddr, 5); /* Idle bit. */ SIO_CLR((VR_MIICMD_CLK|VR_MIICMD_DATAIN)); DELAY(1); SIO_SET(VR_MIICMD_CLK); DELAY(1); /* Turn off xmit. */ SIO_CLR(VR_MIICMD_DIR); /* Check for ack */ SIO_CLR(VR_MIICMD_CLK); DELAY(1); ack = CSR_READ_4(sc, VR_MIICMD) & VR_MIICMD_DATAOUT; SIO_SET(VR_MIICMD_CLK); DELAY(1); /* * Now try reading data bits. If the ack failed, we still * need to clock through 16 cycles to keep the PHY(s) in sync. */ if (ack) { for(i = 0; i < 16; i++) { SIO_CLR(VR_MIICMD_CLK); DELAY(1); SIO_SET(VR_MIICMD_CLK); DELAY(1); } goto fail; } for (i = 0x8000; i; i >>= 1) { SIO_CLR(VR_MIICMD_CLK); DELAY(1); if (!ack) { if (CSR_READ_4(sc, VR_MIICMD) & VR_MIICMD_DATAOUT) frame->mii_data |= i; DELAY(1); } SIO_SET(VR_MIICMD_CLK); DELAY(1); } fail: SIO_CLR(VR_MIICMD_CLK); DELAY(1); SIO_SET(VR_MIICMD_CLK); DELAY(1); if (ack) return(1); return(0); }
/* * Non-destructive identify. */ static void ex_isa_identify(driver_t *driver, device_t parent) { device_t child; bus_addr_t ioport; u_char enaddr[6]; u_int irq; int tmp; const char * desc; struct ex_softc sc; int rid; if (bootverbose) printf("ex_isa_identify()\n"); for (ioport = 0x200; ioport < 0x3a0; ioport += 0x10) { rid = 0; sc.ioport = bus_alloc_resource(parent, SYS_RES_IOPORT, &rid, ioport, ioport, 0x10, RF_ACTIVE); if (sc.ioport == NULL) continue; /* No board found at address */ if (!ex_look_for_card(&sc)) { bus_release_resource(parent, SYS_RES_IOPORT, rid, sc.ioport); continue; } if (bootverbose) printf("ex: Found card at 0x%03lx!\n", (unsigned long)ioport); /* Board in PnP mode */ if (ex_eeprom_read(&sc, EE_W0) & EE_W0_PNP) { /* Reset the card. */ CSR_WRITE_1(&sc, CMD_REG, Reset_CMD); DELAY(500); if (bootverbose) printf("ex: card at 0x%03lx in PnP mode!\n", (unsigned long)ioport); bus_release_resource(parent, SYS_RES_IOPORT, rid, sc.ioport); continue; } bzero(enaddr, sizeof(enaddr)); /* Reset the card. */ CSR_WRITE_1(&sc, CMD_REG, Reset_CMD); DELAY(400); ex_get_address(&sc, enaddr); tmp = ex_eeprom_read(&sc, EE_W1) & EE_W1_INT_SEL; /* work out which set of irq <-> internal tables to use */ if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) { irq = plus_ee2irqmap[tmp]; desc = "Intel Pro/10+"; } else { irq = ee2irqmap[tmp]; desc = "Intel Pro/10"; } bus_release_resource(parent, SYS_RES_IOPORT, rid, sc.ioport); child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ex", -1); device_set_desc_copy(child, desc); device_set_driver(child, driver); bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, EX_IOSIZE); if (bootverbose) printf("ex: Adding board at 0x%03lx, irq %d\n", (unsigned long)ioport, irq); } return; }
static int ex_isa_probe(device_t dev) { bus_addr_t iobase; u_int irq; char * irq2ee; u_char * ee2irq; u_char enaddr[6]; int tmp; int error; struct ex_softc *sc = device_get_softc(dev); /* Check isapnp ids */ error = ISA_PNP_PROBE(device_get_parent(dev), dev, ex_ids); /* If the card had a PnP ID that didn't match any we know about */ if (error == ENXIO) return(error); /* If we had some other problem. */ if (!(error == 0 || error == ENOENT)) return(error); error = ex_alloc_resources(dev); if (error != 0) goto bad; iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0); if (!ex_look_for_card(sc)) { if (bootverbose) printf("ex: no card found at 0x%03lx.\n", (unsigned long)iobase); error = ENXIO; goto bad; } if (bootverbose) printf("ex: ex_isa_probe() found card at 0x%03lx\n", (unsigned long)iobase); /* * Reset the card. */ CSR_WRITE_1(sc, CMD_REG, Reset_CMD); DELAY(800); ex_get_address(sc, enaddr); /* work out which set of irq <-> internal tables to use */ if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) { irq2ee = plus_irq2eemap; ee2irq = plus_ee2irqmap; } else { irq2ee = irq2eemap; ee2irq = ee2irqmap; } tmp = ex_eeprom_read(sc, EE_W1) & EE_W1_INT_SEL; irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0); if (irq > 0) { /* This will happen if board is in PnP mode. */ if (ee2irq[tmp] != irq) { device_printf(dev, "WARNING: IRQ mismatch: EEPROM %d, using %d\n", ee2irq[tmp], irq); } } else { irq = ee2irq[tmp]; bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); } if (irq == 0) { printf("ex: invalid IRQ.\n"); error = ENXIO; } bad:; ex_release_resources(dev); return (error); }