diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_vr.c | 287 | ||||
-rw-r--r-- | sys/dev/pci/if_vrreg.h | 36 |
2 files changed, 251 insertions, 72 deletions
diff --git a/sys/dev/pci/if_vr.c b/sys/dev/pci/if_vr.c index 8f779ac75b9..d5f8e884696 100644 --- a/sys/dev/pci/if_vr.c +++ b/sys/dev/pci/if_vr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vr.c,v 1.30 2003/02/09 10:53:24 jason Exp $ */ +/* $OpenBSD: if_vr.c,v 1.31 2003/02/19 14:38:22 miod Exp $ */ /* * Copyright (c) 1997, 1998 @@ -31,7 +31,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/pci/if_vr.c,v 1.40 2001/02/06 10:11:48 phk Exp $ + * $FreeBSD: src/sys/pci/if_vr.c,v 1.61 2003/02/01 01:27:05 silby Exp $ */ /* @@ -97,6 +97,7 @@ #include <dev/pci/pcidevs.h> #define VR_USEIOSPACE +#undef VR_USESWSHIFT #include <dev/pci/if_vrreg.h> @@ -148,36 +149,37 @@ int vr_list_tx_init(struct vr_softc *); #define VR_SETBIT(sc, reg, x) \ CSR_WRITE_1(sc, reg, \ - CSR_READ_1(sc, reg) | x) + CSR_READ_1(sc, reg) | (x)) #define VR_CLRBIT(sc, reg, x) \ CSR_WRITE_1(sc, reg, \ - CSR_READ_1(sc, reg) & ~x) + CSR_READ_1(sc, reg) & ~(x)) #define VR_SETBIT16(sc, reg, x) \ CSR_WRITE_2(sc, reg, \ - CSR_READ_2(sc, reg) | x) + CSR_READ_2(sc, reg) | (x)) #define VR_CLRBIT16(sc, reg, x) \ CSR_WRITE_2(sc, reg, \ - CSR_READ_2(sc, reg) & ~x) + CSR_READ_2(sc, reg) & ~(x)) #define VR_SETBIT32(sc, reg, x) \ CSR_WRITE_4(sc, reg, \ - CSR_READ_4(sc, reg) | x) + CSR_READ_4(sc, reg) | (x)) #define VR_CLRBIT32(sc, reg, x) \ CSR_WRITE_4(sc, reg, \ - CSR_READ_4(sc, reg) & ~x) + CSR_READ_4(sc, reg) & ~(x)) #define SIO_SET(x) \ CSR_WRITE_1(sc, VR_MIICMD, \ - CSR_READ_1(sc, VR_MIICMD) | x) + CSR_READ_1(sc, VR_MIICMD) | (x)) #define SIO_CLR(x) \ CSR_WRITE_1(sc, VR_MIICMD, \ - CSR_READ_1(sc, VR_MIICMD) & ~x) + CSR_READ_1(sc, VR_MIICMD) & ~(x)) +#ifdef VR_USESWSHIFT /* * Sync the PHYs by setting data bit and strobing the clock 32 times. */ @@ -224,6 +226,7 @@ vr_mii_send(sc, bits, cnt) SIO_SET(VR_MIICMD_CLK); } } +#endif /* * Read an PHY register through the MII. @@ -233,6 +236,7 @@ vr_mii_readreg(sc, frame) struct vr_softc *sc; struct vr_mii_frame *frame; +#ifdef VR_USESWSHIFT { int i, ack, s; @@ -276,9 +280,9 @@ vr_mii_readreg(sc, frame) /* 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); - ack = CSR_READ_4(sc, VR_MIICMD) & VR_MIICMD_DATAOUT; /* * Now try reading data bits. If the ack failed, we still @@ -319,6 +323,34 @@ fail: return(1); return(0); } +#else +{ + int s, i; + + s = splimp(); + + /* Set the PHY-address */ + CSR_WRITE_1(sc, VR_PHYADDR, (CSR_READ_1(sc, VR_PHYADDR)& 0xe0)| + frame->mii_phyaddr); + + /* Set the register-address */ + CSR_WRITE_1(sc, VR_MIIADDR, frame->mii_regaddr); + VR_SETBIT(sc, VR_MIICMD, VR_MIICMD_READ_ENB); + + for (i = 0; i < 10000; i++) { + if ((CSR_READ_1(sc, VR_MIICMD) & VR_MIICMD_READ_ENB) == 0) + break; + DELAY(1); + } + + frame->mii_data = CSR_READ_2(sc, VR_MIIDATA); + + (void)splx(s); + + return(0); +} +#endif + /* * Write to a PHY register through the MII. @@ -328,6 +360,7 @@ vr_mii_writereg(sc, frame) struct vr_softc *sc; struct vr_mii_frame *frame; +#ifdef VR_USESWSHIFT { int s; @@ -373,6 +406,33 @@ vr_mii_writereg(sc, frame) return(0); } +#else +{ + int s, i; + + s = splimp(); + + /* Set the PHY-address */ + CSR_WRITE_1(sc, VR_PHYADDR, (CSR_READ_1(sc, VR_PHYADDR)& 0xe0)| + frame->mii_phyaddr); + + /* Set the register-address and data to write */ + CSR_WRITE_1(sc, VR_MIIADDR, frame->mii_regaddr); + CSR_WRITE_2(sc, VR_MIIDATA, frame->mii_data); + + VR_SETBIT(sc, VR_MIICMD, VR_MIICMD_WRITE_ENB); + + for (i = 0; i < 10000; i++) { + if ((CSR_READ_1(sc, VR_MIICMD) & VR_MIICMD_WRITE_ENB) == 0) + break; + DELAY(1); + } + + (void)splx(s); + + return(0); +} +#endif int vr_miibus_readreg(dev, phy, reg) @@ -382,6 +442,14 @@ vr_miibus_readreg(dev, phy, reg) struct vr_softc *sc = (struct vr_softc *)dev; struct vr_mii_frame frame; + switch (sc->vr_revid) { + case REV_ID_VT6102_APOLLO: + if (phy != 1) + return 0; + default: + break; + } + bzero((char *)&frame, sizeof(frame)); frame.mii_phyaddr = phy; @@ -399,6 +467,14 @@ vr_miibus_writereg(dev, phy, reg, data) struct vr_softc *sc = (struct vr_softc *)dev; struct vr_mii_frame frame; + switch (sc->vr_revid) { + case REV_ID_VT6102_APOLLO: + if (phy != 1) + return; + default: + break; + } + bzero((char *)&frame, sizeof(frame)); frame.mii_phyaddr = phy; @@ -546,8 +622,17 @@ vr_reset(sc) if (!(CSR_READ_2(sc, VR_COMMAND) & VR_CMD_RESET)) break; } - if (i == VR_TIMEOUT) - printf("%s: reset never completed!\n", sc->sc_dev.dv_xname); + if (i == VR_TIMEOUT) { + if (sc->vr_revid < REV_ID_VT3065_A) + printf("%s: reset never completed!\n", + sc->sc_dev.dv_xname); + else { + /* Use newer force reset command */ + printf("%s: Using force reset command.\n", + sc->sc_dev.dv_xname); + VR_SETBIT(sc, VR_MISC_CR1, VR_MISCCR1_FORSRST); + } + } /* Wait a little while for the chip to get its brains in order. */ DELAY(1000); @@ -604,10 +689,10 @@ vr_attach(parent, self, aux) * Handle power management nonsense. */ command = pci_conf_read(pa->pa_pc, pa->pa_tag, - VR_PCI_CAPID) & 0x000000FF; + VR_PCI_CAPID) & 0x000000ff; if (command == 0x01) { command = pci_conf_read(pa->pa_pc, pa->pa_tag, - VR_PCI_PWRMGMTCTRL); + VR_PCI_PWRMGMTCTRL); if (command & VR_PSTATE_MASK) { u_int32_t iobase, membase, irq; @@ -697,6 +782,15 @@ vr_attach(parent, self, aux) vr_reset(sc); /* + * Turn on bit2 (MIION) in PCI configuration register 0x53 during + * initialization and disable AUTOPOLL. + */ + pci_conf_write(pa->pa_pc, pa->pa_tag, VR_PCI_MODE, + pci_conf_read(pa->pa_pc, pa->pa_tag, VR_PCI_MODE) | + (VR_MODE3_MIION << 24)); + VR_CLRBIT(sc, VR_MIICMD, VR_MIICMD_AUTOPOLL); + + /* * Get station address. The way the Rhine chips work, * you're not allowed to directly access the EEPROM once * they've been programmed a special way. Consequently, @@ -929,33 +1023,23 @@ vr_rxeof(sc) */ if (rxstat & VR_RXSTAT_RXERR) { ifp->if_ierrors++; - printf("%s: rx error: ", sc->sc_dev.dv_xname); - switch(rxstat & 0x000000FF) { - case VR_RXSTAT_CRCERR: - printf("crc error\n"); - break; - case VR_RXSTAT_FRAMEALIGNERR: - printf("frame alignment error\n"); - break; - case VR_RXSTAT_FIFOOFLOW: - printf("FIFO overflow\n"); - break; - case VR_RXSTAT_GIANT: - printf("received giant packet\n"); - break; - case VR_RXSTAT_RUNT: - printf("received runt packet\n"); - break; - case VR_RXSTAT_BUSERR: - printf("system bus error\n"); - break; - case VR_RXSTAT_BUFFERR: - printf("rx buffer error\n"); - break; - default: - printf("unknown rx error\n"); - break; - } + printf("%s: rx error (%02x):", + sc->sc_dev.dv_xname, rxstat & 0x000000ff); + if (rxstat & VR_RXSTAT_CRCERR) + printf(" crc error"); + if (rxstat & VR_RXSTAT_FRAMEALIGNERR) + printf(" frame alignment error"); + if (rxstat & VR_RXSTAT_FIFOOFLOW) + printf(" FIFO overflow"); + if (rxstat & VR_RXSTAT_GIANT) + printf(" received giant packet"); + if (rxstat & VR_RXSTAT_RUNT) + printf(" received runt packet"); + if (rxstat & VR_RXSTAT_BUSERR) + printf(" system bus error"); + if (rxstat & VR_RXSTAT_BUFFERR) + printf(" rx buffer error"); + printf("\n"); vr_newbuf(sc, cur_rx, m); continue; } @@ -1002,9 +1086,29 @@ void vr_rxeoc(sc) struct vr_softc *sc; { + struct ifnet *ifp; + int i; + + ifp = &sc->arpcom.ac_if; + + ifp->if_ierrors++; + + VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_RX_ON); + DELAY(10000); + + for (i = 0x400; + i && (CSR_READ_2(sc, VR_COMMAND) & VR_CMD_RX_ON); + i--) + ; /* Wait for receiver to stop */ + + if (!i) { + printf("%s: rx shutdown error!\n", sc->sc_dev.dv_xname); + sc->vr_flags |= VR_F_RESTART; + return; + } vr_rxeof(sc); - VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_RX_ON); + CSR_WRITE_4(sc, VR_RXADDR, vtophys(sc->vr_cdata.vr_rx_head->vr_ptr)); VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_ON); VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_GO); @@ -1026,8 +1130,8 @@ vr_txeof(sc) ifp = &sc->arpcom.ac_if; - /* Clear the timeout timer. */ - ifp->if_timer = 0; + /* Reset the timeout timer; if_txeoc will clear it. */ + ifp->if_timer = 5; /* Sanity check. */ if (sc->vr_cdata.vr_tx_head == NULL) @@ -1039,10 +1143,28 @@ vr_txeof(sc) */ while(sc->vr_cdata.vr_tx_head->vr_mbuf != NULL) { u_int32_t txstat; + int i; cur_tx = sc->vr_cdata.vr_tx_head; txstat = cur_tx->vr_ptr->vr_status; + if ((txstat & VR_TXSTAT_ABRT) || + (txstat & VR_TXSTAT_UDF)) { + for (i = 0x400; + i && (CSR_READ_2(sc, VR_COMMAND) & VR_CMD_TX_ON); + i--) + ; /* Wait for chip to shutdown */ + if (!i) { + printf("%s: tx shutdown timeout\n", + sc->sc_dev.dv_xname); + sc->vr_flags |= VR_F_RESTART; + break; + } + VR_TXOWN(cur_tx) = VR_TXSTAT_OWN; + CSR_WRITE_4(sc, VR_TXADDR, vtophys(cur_tx->vr_ptr)); + break; + } + if (txstat & VR_TXSTAT_OWN) break; @@ -1085,11 +1207,10 @@ vr_txeoc(sc) ifp = &sc->arpcom.ac_if; - ifp->if_timer = 0; - if (sc->vr_cdata.vr_tx_head == NULL) { ifp->if_flags &= ~IFF_OACTIVE; sc->vr_cdata.vr_tx_tail = NULL; + ifp->if_timer = 0; } return; @@ -1103,6 +1224,14 @@ vr_tick(xsc) int s; s = splimp(); + if (sc->vr_flags & VR_F_RESTART) { + printf("%s: restarting\n", sc->sc_dev.dv_xname); + vr_stop(sc); + vr_reset(sc); + vr_init(sc); + sc->vr_flags &= ~VR_F_RESTART; + } + mii_tick(&sc->sc_mii); timeout_add(&sc->sc_to, hz); splx(s); @@ -1143,30 +1272,46 @@ vr_intr(arg) if (status & VR_ISR_RX_OK) vr_rxeof(sc); + if (status & VR_ISR_RX_DROPPED) { + printf("%s: rx packet lost\n", sc->sc_dev.dv_xname); + ifp->if_ierrors++; + } + if ((status & VR_ISR_RX_ERR) || (status & VR_ISR_RX_NOBUF) || - (status & VR_ISR_RX_NOBUF) || (status & VR_ISR_RX_OFLOW) || - (status & VR_ISR_RX_DROPPED)) { - vr_rxeof(sc); + (status & VR_ISR_RX_NOBUF) || (status & VR_ISR_RX_OFLOW)) { + printf("%s: receive error (%04x)", + sc->sc_dev.dv_xname, status); + if (status & VR_ISR_RX_NOBUF) + printf(" no buffers"); + if (status & VR_ISR_RX_OFLOW) + printf(" overflow"); + if (status & VR_ISR_RX_DROPPED) + printf(" packet lost"); + printf("\n"); vr_rxeoc(sc); } - if (status & VR_ISR_TX_OK) { - vr_txeof(sc); - vr_txeoc(sc); + if ((status & VR_ISR_BUSERR) || (status & VR_ISR_TX_UNDERRUN)) { + vr_reset(sc); + vr_init(sc); + break; } - if ((status & VR_ISR_TX_UNDERRUN)||(status & VR_ISR_TX_ABRT)){ - ifp->if_oerrors++; + if ((status & VR_ISR_TX_OK) || (status & VR_ISR_TX_ABRT) || + (status & VR_ISR_TX_ABRT2) || (status & VR_ISR_UDFI)) { vr_txeof(sc); - if (sc->vr_cdata.vr_tx_head != NULL) { - VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_ON); - VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_GO); - } - } - - if (status & VR_ISR_BUSERR) { - vr_reset(sc); - vr_init(sc); + if ((status & VR_ISR_UDFI) || + (status & VR_ISR_TX_ABRT2) || + (status & VR_ISR_TX_ABRT)) { + ifp->if_oerrors++; + if (sc->vr_cdata.vr_tx_head != NULL) { + VR_SETBIT16(sc, VR_COMMAND, + VR_CMD_TX_ON); + VR_SETBIT16(sc, VR_COMMAND, + VR_CMD_TX_GO); + } + } else + vr_txeoc(sc); } } @@ -1332,8 +1477,6 @@ vr_start(ifp) * Set a timeout in case the chip goes out to lunch. */ ifp->if_timer = 5; - - return; } void @@ -1359,18 +1502,22 @@ vr_init(xsc) for (i = 0; i < ETHER_ADDR_LEN; i++) CSR_WRITE_1(sc, VR_PAR0 + i, sc->arpcom.ac_enaddr[i]); + /* Set DMA size */ + VR_CLRBIT(sc, VR_BCR0, VR_BCR0_DMA_LENGTH); + VR_SETBIT(sc, VR_BCR0, VR_BCR0_DMA_STORENFWD); + /* - * BCR0 and BCR1 can override the RXCFG and TXCFG registers, + * BCR0 and BCR1 can override the RXCFG and TXCFG registers, * so we must set both. */ VR_CLRBIT(sc, VR_BCR0, VR_BCR0_RX_THRESH); - VR_SETBIT(sc, VR_BCR0, VR_BCR0_RXTHRESHSTORENFWD); - + VR_SETBIT(sc, VR_BCR0, VR_BCR0_RXTHRESH128BYTES); + VR_CLRBIT(sc, VR_BCR1, VR_BCR1_TX_THRESH); VR_SETBIT(sc, VR_BCR1, VR_BCR1_TXTHRESHSTORENFWD); VR_CLRBIT(sc, VR_RXCFG, VR_RXCFG_RX_THRESH); - VR_SETBIT(sc, VR_RXCFG, VR_RXTHRESH_STORENFWD); + VR_SETBIT(sc, VR_RXCFG, VR_RXTHRESH_128BYTES); VR_CLRBIT(sc, VR_TXCFG, VR_TXCFG_TX_THRESH); VR_SETBIT(sc, VR_TXCFG, VR_TXTHRESH_STORENFWD); diff --git a/sys/dev/pci/if_vrreg.h b/sys/dev/pci/if_vrreg.h index 5cec54cf7dd..8602ea1fedc 100644 --- a/sys/dev/pci/if_vrreg.h +++ b/sys/dev/pci/if_vrreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vrreg.h,v 1.6 2003/02/09 10:53:24 jason Exp $ */ +/* $OpenBSD: if_vrreg.h,v 1.7 2003/02/19 14:38:23 miod Exp $ */ /* * Copyright (c) 1997, 1998 @@ -31,7 +31,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/pci/if_vrreg.h,v 1.10 2001/02/09 06:11:21 bmilekic Exp $ + * $FreeBSD: src/sys/pci/if_vrreg.h,v 1.17 2003/02/01 01:27:05 silby Exp $ */ /* @@ -83,6 +83,10 @@ #define VR_CRC_CNT 0x7E #define VR_STICKHW 0x83 +/* Misc Registers */ +#define VR_MISC_CR1 0x81 +#define VR_MISCCR1_FORSRST 0x40 + /* * RX config bits. */ @@ -151,6 +155,8 @@ #define VR_ISR_STATSOFLOW 0x0080 /* stats counter oflow */ #define VR_ISR_RX_EARLY 0x0100 /* rx early */ #define VR_ISR_LINKSTAT 0x0200 /* MII status change */ +#define VR_ISR_ETI 0x0200 /* Tx early (3043/3071) */ +#define VR_ISR_UDFI 0x0200 /* Tx FIFO underflow (3065) */ #define VR_ISR_RX_OFLOW 0x0400 /* rx FIFO overflow */ #define VR_ISR_RX_DROPPED 0x0800 #define VR_ISR_RX_NOBUF2 0x1000 @@ -370,6 +376,7 @@ struct vr_desc { #define VR_TXSTAT_ABRT 0x00000100 #define VR_TXSTAT_LATECOLL 0x00000200 #define VR_TXSTAT_CARRLOST 0x00000400 +#define VR_TXSTAT_UDF 0x00000800 #define VR_TXSTAT_BUSERR 0x00002000 #define VR_TXSTAT_JABTIMEO 0x00004000 #define VR_TXSTAT_ERRSUM 0x00008000 @@ -454,12 +461,16 @@ struct vr_softc { bus_space_tag_t vr_btag; /* bus space tag */ bus_dma_tag_t sc_dmat; struct vr_type *vr_info; /* Rhine adapter info */ + u_int8_t vr_revid; /* Rhine chip revision */ + u_int8_t vr_flags; /* See VR_F_* below */ struct vr_list_data *vr_ldata; struct vr_chain_data vr_cdata; struct mii_data sc_mii; struct timeout sc_to; }; +#define VR_F_RESTART 0x01 /* Restart unit on next tick */ + /* * register space access macros */ @@ -493,6 +504,8 @@ struct vr_softc { #define VIA_DEVICEID_RHINE 0x3043 #define VIA_DEVICEID_RHINE_II 0x6100 #define VIA_DEVICEID_RHINE_II_2 0x3065 +#define VIA_DEVICEID_RHINE_III 0x3106 +#define VIA_DEVICEID_RHINE_III_M 0x3053 /* * Delta Electronics device ID. @@ -516,6 +529,21 @@ struct vr_softc { /* + * VIA Rhine revision IDs + */ + +#define REV_ID_VT3043_E 0x04 +#define REV_ID_VT3071_A 0x20 +#define REV_ID_VT3071_B 0x21 +#define REV_ID_VT3065_A 0x40 +#define REV_ID_VT3065_B 0x41 +#define REV_ID_VT3065_C 0x42 +#define REV_ID_VT6102_APOLLO 0x74 +#define REV_ID_VT3106 0x80 +#define REV_ID_VT3106_J 0x80 /* 0x80-0x8F */ +#define REV_ID_VT3106_S 0x90 /* 0x90-0xA0 */ + +/* * PCI low memory base and low I/O base register, and * other PCI registers. */ @@ -524,6 +552,7 @@ struct vr_softc { #define VR_PCI_DEVICE_ID 0x02 #define VR_PCI_COMMAND 0x04 #define VR_PCI_STATUS 0x06 +#define VR_PCI_REVID 0x08 #define VR_PCI_CLASSCODE 0x09 #define VR_PCI_LATENCY_TIMER 0x0D #define VR_PCI_HEADER_TYPE 0x0E @@ -536,6 +565,9 @@ struct vr_softc { #define VR_PCI_MINLAT 0x0F #define VR_PCI_RESETOPT 0x48 #define VR_PCI_EEPROM_DATA 0x4C +#define VR_PCI_MODE 0x50 + +#define VR_MODE3_MIION 0x04 /* power management registers */ #define VR_PCI_CAPID 0xDC /* 8 bits */ |