diff options
Diffstat (limited to 'sys/i386/isa/if_is.c')
| -rw-r--r-- | sys/i386/isa/if_is.c | 240 |
1 files changed, 182 insertions, 58 deletions
diff --git a/sys/i386/isa/if_is.c b/sys/i386/isa/if_is.c index becfe1748730..341885f36ed1 100644 --- a/sys/i386/isa/if_is.c +++ b/sys/i386/isa/if_is.c @@ -37,7 +37,6 @@ #include "net/if.h" #include "net/if_dl.h" #include "net/if_types.h" -#include "net/netisr.h" #ifdef INET #include "netinet/in.h" @@ -67,17 +66,23 @@ #define ETHER_MAX_LEN 1518 #define ETHER_ADDR_LEN 6 +char *card_type[] = {"Unknown", + "BICC Isolan", + "NE2100"}; + +char *ic_type[] = {"Unknown", + "Am7990 LANCE", + "Am79960 PCnet_ISA"}; + -/* - * Ethernet software status per interface. - * - * Each interface is referenced by a network interface structure, - * arpcom.ac_if, which the routing code uses to locate the interface. - * This structure contains the output queue for the interface, its address, ... - */ struct is_softc { struct arpcom arpcom; /* Ethernet common part */ - int iobase; /* IO base address of card */ + int iobase; + int rap; + int rdp; + int ic_type; /* Am 7990 or Am79960 */ + int card_type; + int is_debug; struct init_block *init_block; /* Lance initialisation block */ struct mds *rd; struct mds *td; @@ -90,11 +95,19 @@ struct is_softc { } is_softc[NIS] ; -int is_debug; /* Function prototypes */ -int is_probe(),is_attach(),is_watchdog(); -int is_ioctl(),is_init(),is_start(); +static int is_probe(struct isa_device *); +static int is_attach(struct isa_device *); +static void is_watchdog(int); +static int is_ioctl(struct ifnet *, int, caddr_t); +static void is_init(int); +static void is_start(struct ifnet *); +static void istint(int); +static void recv_print(int, int); +static void xmit_print(int, int); + + static inline void is_rint(int unit); static inline void isread(struct is_softc*, unsigned char*, int); @@ -107,64 +120,166 @@ struct isa_driver isdriver = { "is" }; +void iswrcsr(unit,port,val) int unit; u_short port; u_short val; { - int iobase; - - iobase = is_softc[unit].iobase; - outw(iobase+RAP,port); - outw(iobase+RDP,val); + outw(is_softc[unit].rap,port); + outw(is_softc[unit].rdp,val); } u_short isrdcsr(unit,port) int unit; u_short port; { - int iobase; - - iobase = is_softc[unit].iobase; - outw(iobase+RAP,port); - return(inw(iobase+RDP)); + outw(is_softc[unit].rap,port); + return(inw(is_softc[unit].rdp)); } +int is_probe(isa_dev) struct isa_device *isa_dev; { - int val,i,s; int unit = isa_dev->id_unit ; - register struct is_softc *is = &is_softc[unit]; + int nports; - is->iobase = isa_dev->id_iobase; +int i; + is_softc[unit].iobase = isa_dev->id_iobase; - /* Stop the lance chip, put it in known state */ - iswrcsr(unit,0,STOP); - DELAY(100); + /* + * It's impossible to do a non-invasive probe of the + * LANCE and PCnet_ISA. The LANCE requires setting the + * STOP bit to access the registers and the PCnet_ISA + * address port resets to an unknown state!! + */ + + /* + * Check for BICC cards first since for the NE2100 and + * PCnet-ISA cards this write will hit the Address PROM. + */ + +#ifdef DEBUG + printf("Dumping io space for is%d starting at %x\n",unit,is_softc[unit].iobase); + for (i=0; i< 32; i++) + printf(" %x ",inb(is_softc[unit].iobase+i)); + printf("\n"); +#endif /* DEBUG*/ + + if (nports = bicc_probe(unit)) + return (nports); + if (nports = ne2100_probe(unit)) + return (nports); + + + return (0); +} + +int +ne2100_probe(unit) + int unit; +{ +struct is_softc *is = &is_softc[unit]; +int i; - /* is there a lance? */ - iswrcsr(unit,3, 0xffff); - if (isrdcsr(unit,3) != 7) { - is->iobase = 0; - return (0); + is->rap = is->iobase + NE2100_RAP; + is->rdp = is->iobase + NE2100_RDP; + + if (is->ic_type = lance_probe(unit)) { + is->card_type = NE2100; + /* + * Extract the physical MAC address from ROM + */ + for(i=0;i<ETHER_ADDR_LEN;i++) + is->arpcom.ac_enaddr[i]=inb(is->iobase+i); + + /* + * Return number of I/O ports used by card + */ + return (24); } - iswrcsr(unit,3, 0); + return (0); +} + - /* Extract board address */ - for(i=0;i<ETHER_ADDR_LEN;i++) - is->arpcom.ac_enaddr[i]=inb(is->iobase+(i*2)); +int +bicc_probe(unit) + int unit; +{ +struct is_softc *is = &is_softc[unit]; +int i; - return (1); + is->rap = is->iobase + BICC_RAP; + is->rdp = is->iobase + BICC_RDP; + + if (is->ic_type = lance_probe(unit)) { + is->card_type = BICC; + + /* + * Extract the physical ethernet address from ROM + */ + + for(i=0;i<ETHER_ADDR_LEN;i++) + is->arpcom.ac_enaddr[i]=inb(is->iobase+(i*2)); + + /* + * Return number of I/O ports used by card + */ + return (16); + } + return (0); } +/* + * Determine which, if any, of the LANCE or + * PCnet-ISA are present on the card. + */ + +int +lance_probe(unit) + int unit; +{ +int type=0; + + /* + * Have to reset the LANCE to get any + * stable information from it. + */ + + iswrcsr(unit,0,STOP); + DELAY(100); + + if (isrdcsr(unit,0) != STOP) + /* + * This either isn't a LANCE + * or there's a major problem. + */ + return(0); + + /* + * Depending on which controller it is, CSR3 will have + * different settable bits. Write to them all and see which ones + * get set. + */ + + iswrcsr(unit,3, LANCE_MASK); + + if (isrdcsr(unit,3) == LANCE_MASK) + type = LANCE; + + if (isrdcsr(unit,3) == PCnet_ISA_MASK) + type = PCnet_ISA; + + return (type); +} /* * Reset of interface. */ -int -is_reset(int unit) +static void +is_reset(int unit, int uban) { int s; struct is_softc *is = &is_softc[unit]; @@ -267,22 +382,25 @@ is_attach(isa_dev) printf ("is%d: address %s\n", unit, ether_sprintf(is->arpcom.ac_enaddr)) ; + printf("%s, %s\n",ic_type[is->ic_type],card_type[is->card_type]); #if NBPFILTER > 0 bpfattach(&is->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); #endif + return 1; } -int +static void is_watchdog(unit) int unit; { log(LOG_ERR, "is%d: device timeout\n", unit); - is_reset(unit); + is_reset(unit, 0); } /* Lance initialisation block set up */ +void init_mem(unit) int unit; { @@ -353,6 +471,7 @@ init_mem(unit) * and transmit/receive descriptor rings. */ +static void is_init(unit) int unit; { @@ -413,6 +532,7 @@ is_init(unit) * and map it to the interface before starting the output. * called only at splimp or interrupt level. */ +static void is_start(ifp) struct ifnet *ifp; { @@ -491,7 +611,7 @@ is_start(ifp) /* copy trailer_header into a data structure */ m_copydata(m0, off, sizeof(struct trailer_header), - &trailer_header.ether_type); + (caddr_t)&trailer_header.ether_type); /* copy residual data */ resid = trailer_header.ether_residual - @@ -527,7 +647,7 @@ is_start(ifp) cdm->bcnt = -len; cdm->mcnt = 0; #ifdef ISDEBUG - if (is_debug) + if (is->is_debug) xmit_print(unit,is->last_td); #endif @@ -538,17 +658,18 @@ is_start(ifp) is->no_td = NTBUF; is->arpcom.ac_if.if_flags |= IFF_OACTIVE; #ifdef ISDEBUG - if (is_debug) + if (is->is_debug) printf("no_td = %x, last_td = %x\n",is->no_td, is->last_td); #endif - return(0); } /* * Controller interrupt. */ +void isintr(unit) + int unit; { register struct is_softc *is = &is_softc[unit]; u_short isr; @@ -574,14 +695,14 @@ isintr(unit) if (!(isr&RXON)) { printf("is%d: !(isr&RXON)\n", unit); is->arpcom.ac_if.if_ierrors++; - is_reset(unit); - return(1); + is_reset(unit, 0); + return; } if (!(isr&TXON)) { printf("is%d: !(isr&TXON)\n", unit); is->arpcom.ac_if.if_oerrors++; - is_reset(unit); - return(1); + is_reset(unit, 0); + return; } if (isr&RINT) { @@ -598,6 +719,7 @@ isintr(unit) } } +static void istint(unit) int unit; { @@ -612,7 +734,7 @@ istint(unit) i+=NTBUF; cdm = (is->td+i); #ifdef ISDEBUG - if (is_debug) + if (is->is_debug) printf("Trans cdm = %x\n",cdm); #endif if (cdm->flags&OWN) { @@ -669,13 +791,13 @@ static inline void is_rint(int unit) is->last_rd = rmd; printf("is%d: Chained buffer\n",unit); if ((cdm->flags & (OWN|ERR|STP|ENP)) != ENP) { - is_reset(unit); + is_reset(unit, 0); return; } }else { #ifdef ISDEBUG - if (is_debug) + if (is->is_debug) recv_print(unit,is->last_rd); #endif isread(is,is->rbuf+(BUFSIZE*rmd),(int)cdm->mcnt); @@ -686,7 +808,7 @@ static inline void is_rint(int unit) cdm->mcnt = 0; NEXTRDS; #ifdef ISDEBUG - if (is_debug) + if (is->is_debug) printf("is->last_rd = %x, cdm = %x\n",is->last_rd,cdm); #endif } /* while */ @@ -733,7 +855,6 @@ isread(struct is_softc *is, unsigned char *buf, int len) * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ - is->arpcom.ac_if.if_ipackets++; m = isget(buf, len, off, &is->arpcom.ac_if); if (m == 0) return; #if NBPFILTER > 0 @@ -851,6 +972,7 @@ isget(buf, totlen, off0, ifp) /* * Process an ioctl request. */ +int is_ioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; @@ -934,9 +1056,9 @@ is_ioctl(ifp, cmd, data) } #ifdef ISDEBUG if (ifp->if_flags & IFF_DEBUG) - is_debug = 1; + is->is_debug = 1; else - is_debug = 0; + is->is_debug = 0; #endif #if NBPFILTER > 0 if (ifp->if_flags & IFF_PROMISC) { @@ -973,6 +1095,7 @@ is_ioctl(ifp, cmd, data) } #ifdef ISDEBUG +void recv_print(unit,no) int unit,no; { @@ -994,7 +1117,8 @@ recv_print(unit,no) if (printed) printf("\n"); } - + +void xmit_print(unit,no) int unit,no; { |
