diff options
Diffstat (limited to 'sys/i386/isa/if_lnc.c')
-rw-r--r-- | sys/i386/isa/if_lnc.c | 229 |
1 files changed, 156 insertions, 73 deletions
diff --git a/sys/i386/isa/if_lnc.c b/sys/i386/isa/if_lnc.c index ebd2eba..2765353 100644 --- a/sys/i386/isa/if_lnc.c +++ b/sys/i386/isa/if_lnc.c @@ -60,6 +60,7 @@ * */ +#include "pci.h" #include "lnc.h" #if NLNC > 0 @@ -131,14 +132,14 @@ static struct lnc_softc { #ifdef LNC_MULTICAST static void lnc_setladrf __P((struct lnc_softc *sc)); #endif -static void lnc_stop __P((int unit)); -static void lnc_reset __P((int unit)); +static void lnc_stop __P((struct lnc_softc *sc)); +static void lnc_reset __P((struct lnc_softc *sc)); static void lnc_free_mbufs __P((struct lnc_softc *sc)); static int alloc_mbuf_cluster __P((struct lnc_softc *sc, struct host_ring_entry *desc)); static struct mbuf *chain_mbufs __P((struct lnc_softc *sc, int start_of_packet, int pkt_len)); static struct mbuf *mbuf_packet __P((struct lnc_softc *sc, int start_of_packet, int pkt_len)); -static void lnc_rint __P((int unit)); -static void lnc_tint __P((int unit)); +static void lnc_rint __P((struct lnc_softc *sc)); +static void lnc_tint __P((struct lnc_softc *sc)); static int lnc_probe __P((struct isa_device *isa_dev)); static int ne2100_probe __P((struct isa_device *isa_dev)); static int bicc_probe __P((struct isa_device *isa_dev)); @@ -146,19 +147,25 @@ static int dec_macaddr_extract __P((u_char ring[], struct lnc_softc *sc)); static int depca_probe __P((struct isa_device *isa_dev)); static int lance_probe __P((int unit)); static int pcnet_probe __P((int unit)); -static int lnc_attach __P((struct isa_device *isa_dev)); -static void lnc_init __P((int unit)); +static int lnc_attach __P((struct lnc_softc *sc, int unit)); +static int lnc_attach_isa __P((struct isa_device *isa_dev)); +static void lnc_init __P((struct lnc_softc *sc)); static int mbuf_to_buffer __P((struct mbuf *m, char *buffer)); static struct mbuf *chain_to_cluster __P((struct mbuf *m)); static void lnc_start __P((struct ifnet *ifp)); static int lnc_ioctl __P((struct ifnet *ifp, int command, caddr_t data)); static void lnc_watchdog __P((struct ifnet *ifp)); #ifdef DEBUG -static void lnc_dump_state __P((int unit)); +static void lnc_dump_state __P((struct lnc_softc *sc)); static void mbuf_dump_chain __P((struct mbuf *m)); #endif -struct isa_driver lncdriver = {lnc_probe, lnc_attach, "lnc"}; +#if NPCI > 0 +void *lnc_attach_ne2100_pci __P((int unit, unsigned iobase)); +#endif +void lncintr_sc __P((struct lnc_softc *sc)); + +struct isa_driver lncdriver = {lnc_probe, lnc_attach_isa, "lnc"}; static struct kern_devconf kdc_lnc = { 0, 0, 0, /* filled in by dev_attach */ @@ -172,17 +179,17 @@ static struct kern_devconf kdc_lnc = { }; static inline void -write_csr(int unit, u_short port, u_short val) +write_csr(struct lnc_softc *sc, u_short port, u_short val) { - outw(lnc_softc[unit].rap, port); - outw(lnc_softc[unit].rdp, val); + outw(sc->rap, port); + outw(sc->rdp, val); } static inline u_short -read_csr(int unit, u_short port) +read_csr(struct lnc_softc *sc, u_short port) { - outw(lnc_softc[unit].rap, port); - return (inw(lnc_softc[unit].rdp)); + outw(sc->rap, port); + return (inw(sc->rdp)); } static inline void @@ -221,6 +228,9 @@ lnc_registerdev(struct isa_device *isa_dev) kdc->kdc_description = "PCnet-32 VL-Bus Ethernet controller"; break; case PCnet_PCI: + /* + * XXX - This should never be the case ... + */ kdc->kdc_description = "PCnet-PCI Ethernet controller"; break; default: @@ -305,15 +315,15 @@ lnc_setladrf(struct lnc_softc *sc) #endif /* LNC_MULTICAST */ static void -lnc_stop(int unit) +lnc_stop(struct lnc_softc *sc) { - write_csr(unit, CSR0, STOP); + write_csr(sc, CSR0, STOP); } static void -lnc_reset(int unit) +lnc_reset(struct lnc_softc *sc) { - lnc_init(unit); + lnc_init(sc); } static void @@ -481,9 +491,9 @@ mbuf_packet(struct lnc_softc *sc, int start_of_packet, int pkt_len) static inline void -lnc_rint(int unit) +lnc_rint(struct lnc_softc *sc) { - register struct lnc_softc *sc = &lnc_softc[unit]; + int unit = sc->arpcom.ac_if.if_unit; struct host_ring_entry *next, *start; int start_of_packet; struct mbuf *head; @@ -540,7 +550,7 @@ lnc_rint(int unit) if (flags & STP) { log(LOG_ERR, "lnc%d: Start of packet found before end of previous in receive ring -- Resetting\n", unit); - lnc_reset(unit); + lnc_reset(sc); return; } if (flags & OWN) { @@ -553,7 +563,7 @@ lnc_rint(int unit) break; } else { log(LOG_ERR, "lnc%d: End of received packet not found-- Resetting\n", unit); - lnc_reset(unit); + lnc_reset(sc); return; } } @@ -671,9 +681,9 @@ lnc_rint(int unit) } static inline void -lnc_tint(int unit) +lnc_tint(struct lnc_softc *sc) { - register struct lnc_softc *sc = &lnc_softc[unit]; + int unit = sc->arpcom.ac_if.if_unit; struct host_ring_entry *next, *start; int start_of_packet; int lookahead; @@ -742,7 +752,7 @@ lnc_tint(int unit) if (next->md->md1 & STP) { log(LOG_ERR, "lnc%d: Start of packet found before end of previous in transmit ring -- Resetting\n", unit); - lnc_reset(unit); + lnc_reset(sc); return; } if (next->md->md1 & OWN) { @@ -755,7 +765,7 @@ lnc_tint(int unit) break; } else { log(LOG_ERR, "lnc%d: End of transmitted packet not found -- Resetting\n", unit); - lnc_reset(unit); + lnc_reset(sc); return; } } @@ -814,7 +824,7 @@ lnc_tint(int unit) log(LOG_ERR, "lnc%d: Transmit buffer error -- Resetting\n", unit); } else log(LOG_ERR, "lnc%d: Transmit underflow error -- Resetting\n", unit); - lnc_reset(unit); + lnc_reset(sc); return; } do { @@ -1057,16 +1067,18 @@ depca_probe(struct isa_device * isa_dev) static int lance_probe(int unit) { - write_csr(unit, CSR0, STOP); + struct lnc_softc *sc = &lnc_softc[unit]; + + write_csr(sc, CSR0, STOP); - if ((inw(lnc_softc[unit].rdp) & STOP) && !(read_csr(unit, CSR3))) { + if ((inw(sc->rdp) & STOP) && !(read_csr(sc, CSR3))) { /* * Check to see if it's a C-LANCE. For the LANCE the INEA bit * cannot be set while the STOP bit is. This restriction is * removed for the C-LANCE. */ - write_csr(unit, CSR0, INEA); - if (read_csr(unit, CSR0) & INEA) + write_csr(sc, CSR0, INEA); + if (read_csr(sc, CSR0) & INEA) return (C_LANCE); else return (LANCE); @@ -1077,6 +1089,8 @@ lance_probe(int unit) static int pcnet_probe(int unit) { + struct lnc_softc *sc = &lnc_softc[unit]; + u_long chip_id; int type; @@ -1088,9 +1102,9 @@ pcnet_probe(int unit) if (type = lance_probe(unit)) { - chip_id = read_csr(unit, CSR89); + chip_id = read_csr(sc, CSR89); chip_id <<= 16; - chip_id |= read_csr(unit, CSR88); + chip_id |= read_csr(sc, CSR88); if (chip_id & AMD_MASK) { chip_id >>= 12; switch (chip_id & PART_MASK) { @@ -1101,7 +1115,7 @@ pcnet_probe(int unit) case Am79C965: return (PCnet_32); case Am79C970: - return (PCnet_PCI); + return (0); default: break; } @@ -1111,9 +1125,8 @@ pcnet_probe(int unit) } static int -lnc_attach(struct isa_device * isa_dev) +lnc_attach(struct lnc_softc *sc, int unit) { - struct lnc_softc *sc = &lnc_softc[isa_dev->id_unit]; int lnc_mem_size; /* @@ -1144,20 +1157,20 @@ lnc_attach(struct isa_device * isa_dev) sc->recv_ring = malloc(lnc_mem_size, M_DEVBUF, M_NOWAIT); if (!sc->recv_ring) { - log(LOG_ERR, "lnc%d: Couldn't allocate memory for NIC\n", isa_dev->id_unit); + log(LOG_ERR, "lnc%d: Couldn't allocate memory for NIC\n", unit); return (0); /* XXX -- attach failed -- not tested in * calling routines */ } + /* + * XXX - Shouldn't this be skipped for the EISA and PCI versions ??? + * Print the message but do not return for the PCnet_PCI ! + */ if ((sc->nic.mem_mode != SHMEM) && (kvtop(sc->recv_ring) > 0x1000000)) { - log(LOG_ERR, "lnc%d: Memory allocated above 16Mb limit\n", isa_dev->id_unit); - return (0); + log(LOG_ERR, "lnc%d: Memory allocated above 16Mb limit\n", unit); + if (sc->nic.ic != PCnet_PCI) + return (0); } - if ((sc->nic.mem_mode != SHMEM) && - (sc->nic.ic != PCnet_32) && - (sc->nic.ic != PCnet_PCI)) - isa_dmacascade(isa_dev->id_drq); - /* Set default mode */ sc->nic.mode = NORMAL; @@ -1165,7 +1178,7 @@ lnc_attach(struct isa_device * isa_dev) sc->arpcom.ac_if.if_softc = sc; sc->arpcom.ac_if.if_name = lncdriver.name; - sc->arpcom.ac_if.if_unit = isa_dev->id_unit; + sc->arpcom.ac_if.if_unit = unit; sc->arpcom.ac_if.if_mtu = ETHERMTU; sc->arpcom.ac_if.if_flags = IFF_BROADCAST | IFF_SIMPLEX; sc->arpcom.ac_if.if_timer = 0; @@ -1185,9 +1198,12 @@ lnc_attach(struct isa_device * isa_dev) ether_ifattach(&sc->arpcom.ac_if); sc->kdc.kdc_state = DC_IDLE; + if (sc->kdc.kdc_description == NULL) + sc->kdc.kdc_description = "Lance Ethernet controller"; + printf("lnc%d: %s, address %6D\n", - isa_dev->id_unit, - sc->kdc.kdc_description, + unit, + sc->kdc.kdc_description, sc->arpcom.ac_enaddr, ":"); #if NBPFILTER > 0 @@ -1197,10 +1213,70 @@ lnc_attach(struct isa_device * isa_dev) return (1); } -static void -lnc_init(int unit) +static int +lnc_attach_isa(struct isa_device * isa_dev) { + int unit = isa_dev->id_unit; struct lnc_softc *sc = &lnc_softc[unit]; + + int result = lnc_attach (sc, unit); + if (result == 0) + return (0); + /* + * XXX - is it safe to call isa_dmacascade() after if_attach() + * and ether_ifattach() have been called in lnc_attach() ??? + */ + if ((sc->nic.mem_mode != SHMEM) && + (sc->nic.ic != PCnet_32) && + (sc->nic.ic != PCnet_PCI)) + isa_dmacascade(isa_dev->id_drq); + + return result; +} + +#if NPCI > 0 +void * +lnc_attach_ne2100_pci(int unit, unsigned iobase) +{ + struct lnc_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); + + if (!sc) + return sc; + + bzero (sc, sizeof *sc); + + /* + * Copied from ne2100_probe() + */ + sc->rap = iobase + PCNET_RAP; + sc->rdp = iobase + PCNET_RDP; + + sc->nic.ic = PCnet_PCI; + sc->nic.ident = NE2100; + sc->nic.mem_mode = DMA_FIXED; + + /* XXX - For now just use the defines */ + sc->nrdre = NRDRE; + sc->ntdre = NTDRE; + + /* Extract MAC address from PROM */ + { + int i; + for (i = 0; i < ETHER_ADDR_LEN; i++) + sc->arpcom.ac_enaddr[i] = inb(iobase + i); + } + + if (lnc_attach(sc, unit) == 0) { + free(sc, M_DEVBUF); + return NULL; + } + return sc; +} +#endif + +static void +lnc_init(struct lnc_softc *sc) +{ int s, i; char *lnc_mem; @@ -1212,7 +1288,7 @@ lnc_init(int unit) /* Shut down interface */ s = splimp(); - lnc_stop(unit); + lnc_stop(sc); sc->arpcom.ac_if.if_flags |= IFF_BROADCAST | IFF_SIMPLEX; /* XXX??? */ /* @@ -1326,8 +1402,8 @@ lnc_init(int unit) /* Give the LANCE the physical address of the initialisation block */ - write_csr(unit, CSR1, kvtop(sc->init_block)); - write_csr(unit, CSR2, (kvtop(sc->init_block) >> 16) & 0xff); + write_csr(sc, CSR1, kvtop(sc->init_block)); + write_csr(sc, CSR2, (kvtop(sc->init_block) >> 16) & 0xff); /* * Depending on which controller this is, CSR3 has different meanings. @@ -1337,13 +1413,13 @@ lnc_init(int unit) * */ - write_csr(unit, CSR3, 0); + write_csr(sc, CSR3, 0); /* Let's see if it starts */ - write_csr(unit, CSR0, INIT); + write_csr(sc, CSR0, INIT); for (i = 0; i < 1000; i++) - if (read_csr(unit, CSR0) & IDON) + if (read_csr(sc, CSR0) & IDON) break; /* @@ -1353,17 +1429,18 @@ lnc_init(int unit) * time. */ - if (read_csr(unit, CSR0) & IDON) { + if (read_csr(sc, CSR0) & IDON) { /* * Enable interrupts, start the LANCE, mark the interface as * running and transmit any pending packets. */ - write_csr(unit, CSR0, STRT | INEA); + write_csr(sc, CSR0, STRT | INEA); sc->arpcom.ac_if.if_flags |= IFF_RUNNING; sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; lnc_start(&sc->arpcom.ac_if); } else - log(LOG_ERR, "lnc%d: Initialisation failed\n", unit); + log(LOG_ERR, "lnc%d: Initialisation failed\n", + sc->arpcom.ac_if.if_unit); splx(s); } @@ -1390,9 +1467,9 @@ lnc_init(int unit) */ void -lncintr(int unit) +lncintr_sc(struct lnc_softc *sc) { - struct lnc_softc *sc = &lnc_softc[unit]; + int unit = sc->arpcom.ac_if.if_unit; u_short csr0; /* @@ -1432,18 +1509,18 @@ lncintr(int unit) if (csr0 & MERR) { log(LOG_ERR, "lnc%d: Memory error -- Resetting\n", unit); LNCSTATS(merr) - lnc_reset(unit); + lnc_reset(sc); continue; } } if (csr0 & RINT) { LNCSTATS(rint) - lnc_rint(unit); + lnc_rint(sc); } if (csr0 & TINT) { LNCSTATS(tint) sc->arpcom.ac_if.if_timer = 0; - lnc_tint(unit); + lnc_tint(sc); } /* @@ -1456,6 +1533,13 @@ lncintr(int unit) } } +void +lncintr(int unit) +{ + struct lnc_softc *sc = &lnc_softc[unit]; + lncintr_sc (sc); +} + @@ -1542,7 +1626,7 @@ lnc_start(struct ifnet *ifp) if (no_entries_needed > (NDESC(sc->ntdre) - sc->pending_transmits)) if (!(head = chain_to_cluster(head))) { log(LOG_ERR, "lnc%d: Couldn't get mbuf for transmit packet -- Resetting \n ",ifp->if_unit); - lnc_reset(ifp->if_unit); + lnc_reset(sc); return; } else if ((sc->nic.ic == LANCE) || (sc->nic.ic == C_LANCE)) { @@ -1676,12 +1760,12 @@ lnc_ioctl(struct ifnet * ifp, int command, caddr_t data) switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: - lnc_init(ifp->if_unit); + lnc_init(sc); arp_ifinit((struct arpcom *)ifp, ifa); break; #endif default: - lnc_init(ifp->if_unit); + lnc_init(sc); break; } break; @@ -1696,11 +1780,11 @@ lnc_ioctl(struct ifnet * ifp, int command, caddr_t data) if (ifp->if_flags & IFF_PROMISC) { if (!(sc->nic.mode & PROM)) { sc->nic.mode |= PROM; - lnc_init(ifp->if_unit); + lnc_init(sc); } } else if (sc->nic.mode & PROM) { sc->nic.mode &= ~PROM; - lnc_init(ifp->if_unit); + lnc_init(sc); } if ((ifp->if_flags & IFF_UP) == 0 && (ifp->if_flags & IFF_RUNNING) != 0) { @@ -1708,7 +1792,7 @@ lnc_ioctl(struct ifnet * ifp, int command, caddr_t data) * If interface is marked down and it is running, * then stop it. */ - lnc_stop(ifp->if_unit); + lnc_stop(sc); ifp->if_flags &= ~IFF_RUNNING; } else if ((ifp->if_flags & IFF_UP) != 0 && (ifp->if_flags & IFF_RUNNING) == 0) { @@ -1716,7 +1800,7 @@ lnc_ioctl(struct ifnet * ifp, int command, caddr_t data) * If interface is marked up and it is stopped, then * start it. */ - lnc_init(ifp->if_unit); + lnc_init(sc); } sc->kdc.kdc_state = ((ifp->if_flags & IFF_UP) ? DC_BUSY : DC_IDLE); @@ -1756,14 +1840,13 @@ lnc_watchdog(struct ifnet *ifp) { log(LOG_ERR, "lnc%d: Device timeout -- Resetting\n", ifp->if_unit); ifp->if_oerrors++; - lnc_reset(ifp->if_unit); + lnc_reset(ifp->if_softc); } #ifdef DEBUG static void -lnc_dump_state(int unit) +lnc_dump_state( struct lnc_softc *sc) { - struct lnc_softc *sc = &lnc_softc[unit]; int i; printf("\nDriver/NIC [%d] state dump\n", unit); |