From owner-freebsd-current Mon Oct 16 21:56:28 1995 Return-Path: owner-current Received: (from root@localhost) by freefall.freebsd.org (8.6.12/8.6.6) id VAA09360 for current-outgoing; Mon, 16 Oct 1995 21:56:28 -0700 Received: from hq.icb.chel.su (icb-rich-gw.icb.chel.su [193.125.10.34]) by freefall.freebsd.org (8.6.12/8.6.6) with ESMTP id VAA09349 for ; Mon, 16 Oct 1995 21:56:14 -0700 Received: from localhost (babkin@localhost) by hq.icb.chel.su (8.6.5/8.6.5) id KAA23451; Tue, 17 Oct 1995 10:00:05 +0500 From: "Serge A. Babkin" Message-Id: <199510170500.KAA23451@hq.icb.chel.su> Subject: 3c509 in -current needs patching To: current@freebsd.org Date: Tue, 17 Oct 1995 10:00:04 +0500 (GMT+0500) Cc: jkh@time.cdrom.com, bde@zeta.org.au X-Mailer: ELM [version 2.4 PL23] Content-Type: text Content-Length: 14485 Sender: owner-current@freebsd.org Precedence: bulk I have already sent this to Jordan but got no answer, so may be the mail was lost. Or may be Jordan is too busy to aooly this patch and had saved it for the future. Excuse me if so. I have found that the 'ep' driver in -current is relatively old and omits many new improvements (including multicasting and understanding of cards with plug-n-play mode on). I have carefully reviewed this patch so that it should preserve all latest improvements in -current. Serge --------------------------- cut here ---------------------------------- *** if_ep.c Thu Sep 7 09:13:34 1995 --- if_ep.c Fri Oct 13 09:02:28 1995 *************** *************** *** 100,105 **** --- 98,104 ---- #include #include #include + #include static int epprobe __P((struct isa_device *)); static int epattach __P((struct isa_device *)); *************** *** 117,122 **** --- 116,122 ---- static int send_ID_sequence __P((int)); static int get_eeprom_data __P((int, int)); + static struct ep_board *ep_look_for_board_at(struct isa_device *); struct ep_softc ep_softc[NEP]; *************** *** 132,145 **** }; static struct kern_devconf kdc_ep[NEP] = { { ! 0, 0, 0, /* filled in by dev_attach */ "ep", 0, { MDDT_ISA, 0, "net" }, isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, ! &kdc_isa0, /* parent */ ! 0, /* parentdata */ ! DC_UNCONFIGURED, /* state */ "3Com 3C509 Ethernet adapter", ! DC_CLS_NETIF /* class */ } }; static inline void --- 132,145 ---- }; static struct kern_devconf kdc_ep[NEP] = { { ! 0, 0, 0, /* filled in by dev_attach */ "ep", 0, { MDDT_ISA, 0, "net" }, isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, ! &kdc_isa0, /* parent */ ! 0, /* parentdata */ ! DC_UNCONFIGURED, /* state */ "3Com 3C509 Ethernet adapter", ! DC_CLS_NETIF /* class */ } }; static inline void *************** *** 154,164 **** int ep_current_tag = EP_LAST_TAG + 1; ! struct { ! int epb_addr; /* address of this board */ ! char epb_used; /* was this entry already used for configuring ? */ ! } ! ep_board[EP_MAX_BOARDS + 1]; static int eeprom_rdy(is) --- 154,160 ---- int ep_current_tag = EP_LAST_TAG + 1; ! struct ep_board ep_board[EP_MAX_BOARDS + 1]; static int eeprom_rdy(is) *************** *** 174,184 **** return (1); } ! static int ep_look_for_board_at(is) struct isa_device *is; { ! int data, i, j, io_base, id_port = EP_ID_PORT; int nisa = 0, neisa = 0; if (ep_current_tag == (EP_LAST_TAG + 1)) { --- 170,180 ---- return (1); } ! static struct ep_board * ep_look_for_board_at(is) struct isa_device *is; { ! int data, i, j, io_base, id_port = ELINK_ID_PORT; int nisa = 0, neisa = 0; if (ep_current_tag == (EP_LAST_TAG + 1)) { *************** *** 203,232 **** * Once activated, all the registers are mapped in the range * x000 - x00F, where x is the slot number. */ ep_board[neisa].epb_used = 0; ep_board[neisa++].epb_addr = j * EP_EISA_START; } ep_current_tag--; /* Look for the ISA boards. Init and leave them actived */ outb(id_port, 0xc0); /* Global reset */ DELAY(10000); for (i = 0; i < EP_MAX_BOARDS; i++) { outb(id_port, 0); outb(id_port, 0); send_ID_sequence(id_port); data = get_eeprom_data(id_port, EEPROM_MFG_ID); if (data != MFG_ID) break; /* resolve contention using the Ethernet address */ for (j = 0; j < 3; j++) ! data = get_eeprom_data(id_port, j); ep_board[neisa+nisa].epb_used = 0; ep_board[neisa+nisa++].epb_addr = ! (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200; outb(id_port, ep_current_tag); /* tags board */ outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG); ep_current_tag--; --- 199,260 ---- * Once activated, all the registers are mapped in the range * x000 - x00F, where x is the slot number. */ + ep_board[neisa].epb_isa = 0; ep_board[neisa].epb_used = 0; ep_board[neisa++].epb_addr = j * EP_EISA_START; } ep_current_tag--; /* Look for the ISA boards. Init and leave them actived */ + outb(id_port, 0); + outb(id_port, 0); + + #if 0 + send_ID_sequence(id_port); + #else + elink_idseq(0xCF); + #endif + + #if 0 outb(id_port, 0xc0); /* Global reset */ + #else + elink_reset(); + #endif DELAY(10000); for (i = 0; i < EP_MAX_BOARDS; i++) { outb(id_port, 0); outb(id_port, 0); + #if 0 send_ID_sequence(id_port); + #else + elink_idseq(0xCF); + #endif data = get_eeprom_data(id_port, EEPROM_MFG_ID); if (data != MFG_ID) break; /* resolve contention using the Ethernet address */ + + for (j = 0; j < 3; j++) + get_eeprom_data(id_port, j); + + /* and save this address for later use */ + for (j = 0; j < 3; j++) ! ep_board[neisa+nisa].eth_addr[j] = get_eeprom_data(id_port, j); ! ! ep_board[neisa+nisa].res_cfg = ! get_eeprom_data(id_port, EEPROM_RESOURCE_CFG); ! ! ep_board[neisa+nisa].prod_id = ! get_eeprom_data(id_port, EEPROM_PROD_ID); + ep_board[neisa].epb_isa = 1; ep_board[neisa+nisa].epb_used = 0; ep_board[neisa+nisa++].epb_addr = ! (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200; ! outb(id_port, ep_current_tag); /* tags board */ outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG); ep_current_tag--; *************** *** 266,283 **** IS_BASE=ep_board[i].epb_addr; ep_board[i].epb_used=1; ! return 1; } else { for (i=0; ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE; i++); ! if( ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE) return 0; if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) printf("ep%d: 3c5x9 at 0x%x in test mode. Erase pencil mark!\n", is->id_unit, IS_BASE); ep_board[i].epb_used=1; ! return 1; } } --- 294,313 ---- IS_BASE=ep_board[i].epb_addr; ep_board[i].epb_used=1; ! ! return &ep_board[i]; } else { for (i=0; ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE; i++); ! if( ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE) return 0; if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) printf("ep%d: 3c5x9 at 0x%x in test mode. Erase pencil mark!\n", is->id_unit, IS_BASE); ep_board[i].epb_used=1; ! ! return &ep_board[i]; } } *************** *** 308,327 **** ep_registerdev(is); ! if (!ep_look_for_board_at(is)) return (0); /* * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be * 0x9[0-f]50 */ GO_WINDOW(0); ! k = get_e(is, EEPROM_PROD_ID); if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) { printf("epprobe: ignoring model %04x\n", k); return (0); } ! k = get_e(is, EEPROM_RESOURCE_CFG); k >>= 12; /* Now we have two cases again: --- 338,358 ---- ep_registerdev(is); ! if(( sc->epb=ep_look_for_board_at(is) )==0) return (0); /* * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be * 0x9[0-f]50 */ GO_WINDOW(0); ! k = sc->epb->epb_isa ? sc->epb->prod_id : get_e(is, EEPROM_PROD_ID); if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) { printf("epprobe: ignoring model %04x\n", k); return (0); } ! k = sc->epb->epb_isa ? sc->epb->res_cfg : get_e(is, EEPROM_RESOURCE_CFG); ! k >>= 12; /* Now we have two cases again: *************** *** 396,402 **** p = (u_short *) & sc->arpcom.ac_enaddr; for (i = 0; i < 3; i++) { GO_WINDOW(0); ! p[i] = htons(get_e(is, i)); GO_WINDOW(2); outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i])); } --- 427,433 ---- p = (u_short *) & sc->arpcom.ac_enaddr; for (i = 0; i < 3; i++) { GO_WINDOW(0); ! p[i] = htons( sc->epb->epb_isa ? sc->epb->eth_addr[i] : get_e(is, i) ); GO_WINDOW(2); outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i])); } *************** *** 423,429 **** ifp->if_unit = is->id_unit; ifp->if_name = "ep"; ifp->if_mtu = ETHERMTU; ! ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; ifp->if_init = epinit; ifp->if_output = ether_output; ifp->if_start = epstart; --- 454,461 ---- ifp->if_unit = is->id_unit; ifp->if_name = "ep"; ifp->if_mtu = ETHERMTU; ! ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | ! IFF_SIMPLEX | IFF_NOTRAILERS; ifp->if_init = epinit; ifp->if_output = ether_output; ifp->if_start = epstart; *************** *** 432,438 **** ifp->if_timer=1; if_attach(ifp); ! kdc_ep[is->id_unit].kdc_state = DC_BUSY; /* * Fill the hardware address into ifa_addr if we find an AF_LINK entry. --- 464,472 ---- ifp->if_timer=1; if_attach(ifp); ! ! /* device attach does transition from UNCONFIGURED to IDLE state */ ! kdc_ep[is->id_unit].kdc_state=DC_IDLE; /* * Fill the hardware address into ifa_addr if we find an AF_LINK entry. *************** *** 475,481 **** #endif ep_fset(F_RX_FIRST); sc->top = sc->mcur = 0; ! #if NBPFILTER > 0 bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); #endif --- 509,515 ---- #endif ep_fset(F_RX_FIRST); sc->top = sc->mcur = 0; ! #if NBPFILTER > 0 bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); #endif *************** *** 536,547 **** outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS); ! if(ifp->if_flags & IFF_PROMISC) ! outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | ! FIL_GROUP | FIL_BRDCST | FIL_ALL); ! else ! outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | ! FIL_GROUP | FIL_BRDCST); /* * S.B. --- 570,581 ---- outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS); ! if(ifp->if_flags & IFF_PROMISC) ! outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | ! FIL_GROUP | FIL_BRDCST | FIL_ALL); ! else ! outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | ! FIL_GROUP | FIL_BRDCST); /* * S.B. *************** *** 814,820 **** sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf, sc->rx_overrunl, sc->tx_underrun); #else ! printf("ep%d: Status: %x\n", unit, status); #endif epinit(unit); splx(x); --- 848,860 ---- sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf, sc->rx_overrunl, sc->tx_underrun); #else ! ! #ifdef nightmaremessages ! printf("ep%d: Status: %x (input buffer overflow)\n", unit, status); ! #else ! ++sc->arpcom.ac_if.if_ierrors; ! #endif ! #endif epinit(unit); splx(x); *************** *** 1129,1139 **** struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; s = splimp(); switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: --- 1169,1183 ---- struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; s = splimp(); switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; + + /* netifs are BUSY when UP */ + kdc_ep[ifp->if_unit].kdc_state=DC_BUSY; + switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: *************** *** 1164,1179 **** break; } break; ! case SIOCGIFADDR: ! { ! struct sockaddr *sa; ! ! sa = (struct sockaddr *) & ifr->ifr_data; ! bcopy((caddr_t) sc->arpcom.ac_enaddr, (caddr_t) sa->sa_data, ETHER_ADDR_LEN); } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { ifp->if_flags &= ~IFF_RUNNING; epstop(ifp->if_unit); --- 1208,1228 ---- break; } break; ! case SIOCSGIFADDR: ! { ! struct sockaddr *sa; ! ! sa = (struct sockaddr *) & ifr->ifr_data; ! bcopy((caddr_t) sc->arpcom.ac_enaddr, (caddr_t) sa->sa_data, ETHER_ADDR_LEN); } break; case SIOCSIFFLAGS: + /* UP controls BUSY/IDLE */ + kdc_ep[ifp->if_unit].kdc_state= ( (ifp->if_flags & IFF_UP) + ? DC_BUSY + : DC_IDLE ); + if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { ifp->if_flags &= ~IFF_RUNNING; epstop(ifp->if_unit); *************** *** 1186,1191 **** --- 1235,1241 ---- } /* NOTREACHED */ + #if 0 if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0) epinit(ifp->if_unit); *************** *** 1198,1203 **** --- 1248,1254 ---- ep_frst(F_PROMISC); epinit(ifp->if_unit); } + #endif break; #ifdef notdef *************** *** 1216,1223 **** } else { ifp->if_mtu = ifr->ifr_mtu; } ! break; ! default: error = EINVAL; } --- 1267,1281 ---- } else { ifp->if_mtu = ifr->ifr_mtu; } ! break; ! case SIOCADDMULTI: ! case SIOCDELMULTI: ! /* Now this driver has no support for programmable ! * multicast filters. If some day it will gain this ! * support this part of code must be extended. ! */ ! error=0; ! break; default: error = EINVAL; } *** if_epreg.h Thu Sep 7 09:03:48 1995 --- if_epreg.h Fri Aug 4 09:00:36 1995 *************** *************** *** 71,76 **** --- 70,77 ---- #define F_ACCESS_32_BITS 0x100 + struct ep_board *epb; + #ifdef EP_LOCAL_STATS short tx_underrun; short rx_no_first; *************** *** 80,85 **** --- 81,97 ---- short rx_overrunl; #endif }; + + struct ep_board { + int epb_addr; /* address of this board */ + char epb_used; /* was this entry already used for configuring ? */ + /* data from EEPROM for later use */ + char epb_isa; /* flag: this is an ISA card */ + u_short eth_addr[3]; /* Ethernet address */ + u_short prod_id; /* product ID */ + u_short res_cfg; /* resource configuration */ + }; + /* * Some global constants --------------------------- cut here ----------------------------------