From owner-freebsd-hackers Mon Jan 15 21:39:10 1996 Return-Path: owner-hackers Received: (from root@localhost) by freefall.freebsd.org (8.7.3/8.7.3) id VAA13404 for hackers-outgoing; Mon, 15 Jan 1996 21:39:10 -0800 (PST) Received: from hq.icb.chel.su (icb-rich-gw.icb.chel.su [193.125.10.34]) by freefall.freebsd.org (8.7.3/8.7.3) with SMTP id VAA13323 for ; Mon, 15 Jan 1996 21:37:29 -0800 (PST) Received: from localhost (babkin@localhost) by hq.icb.chel.su (8.6.5/8.6.5) id KAA06551; Tue, 16 Jan 1996 10:37:28 +0500 From: "Serge A. Babkin" Message-Id: <199601160537.KAA06551@hq.icb.chel.su> Subject: Re: 3c5x9 multicast To: cher@test.phys.msu.su (Alicher O Alikhodjaev) Date: Tue, 16 Jan 1996 10:37:28 +0500 (GMT+0500) Cc: hackers@freebsd.org, jkh@cdrom.com In-Reply-To: <199601151322.QAA06200@test.phys.msu.su> from "Alicher O Alikhodjaev" at Jan 15, 96 04:22:30 pm X-Mailer: ELM [version 2.4 PL23] Content-Type: text Sender: owner-hackers@freebsd.org Precedence: bulk > > SUMMARY: > This patch adds multicast support for 3c5x9 (ep) driver > INSTALLATION: > cd /sys # your local kernel source tree > patch -p < this_file > # then rebuild your kernel > > =================================================================== > *** i386/isa/if_ep.c.cur Thu Dec 28 17:57:32 1995 > --- i386/isa/if_ep.c Mon Jan 15 15:59:14 1996 > *************** [ skipped ] There already were at least two patches doing the same. But none of them is commited yet. The following patch does multicast, support for PnP, resolving conflicts between 3c509 and 3c507 drivers, slightly more right changes of the device state. The only problem with it is that it was made about 2 months ago for that's day -current and may have problems when applied to current -current. Perhaps it will be not bad if somebody from the core team will commit it. Thank you in advance! -SB ----------------------------cut here ------------------------------------ *** if_ep.c Sun Nov 5 10:57:47 1995 --- /sys/i386/isa/if_ep.c Mon Nov 20 14:15:32 1995 *************** *** 105,110 **** --- 105,111 ---- #include #include #include + #include static int epprobe __P((struct isa_device *)); static int epattach __P((struct isa_device *)); *************** *** 113,118 **** --- 114,120 ---- static void epmbufempty __P((struct ep_softc *)); void epinit __P((int)); + void epintr __P((int)); void epread __P((struct ep_softc *)); void epreset __P((int)); void epstart __P((struct ifnet *)); *************** *** 121,126 **** --- 123,129 ---- 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]; *************** *** 158,168 **** 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) --- 161,167 ---- int ep_current_tag = EP_LAST_TAG + 1; ! struct ep_board ep_board[EP_MAX_BOARDS + 1]; static int eeprom_rdy(is) *************** *** 178,188 **** 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)) { --- 177,187 ---- 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)) { *************** *** 207,236 **** * 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--; --- 206,267 ---- * 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--; *************** *** 270,287 **** 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; } } --- 301,320 ---- 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,330 **** { struct ep_softc *sc = &ep_softc[is->id_unit]; u_short k; 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: --- 341,365 ---- { struct ep_softc *sc = &ep_softc[is->id_unit]; u_short k; + int i; 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: *************** *** 399,405 **** 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])); } --- 434,440 ---- 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])); } *************** *** 426,432 **** ifp->if_unit = is->id_unit; ifp->if_name = "ep"; ifp->if_mtu = ETHERMTU; ! ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; ifp->if_init = epinit; ifp->if_output = ether_output; ifp->if_start = epstart; --- 461,467 ---- ifp->if_unit = is->id_unit; ifp->if_name = "ep"; ifp->if_mtu = ETHERMTU; ! ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = epinit; ifp->if_output = ether_output; ifp->if_start = epstart; *************** *** 435,441 **** 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. --- 470,478 ---- 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. *************** *** 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); --- 851,863 ---- sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf, sc->rx_overrunl, sc->tx_underrun); #else ! ! #ifdef DIAGNOSTIC ! printf("ep%d: Status: %x (input buffer overflow)\n", unit, status); ! #else ! ++sc->arpcom.ac_if.if_ierrors; ! #endif ! #endif epinit(unit); splx(x); *************** *** 1134,1139 **** --- 1177,1186 ---- 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: *************** *** 1192,1197 **** --- 1239,1249 ---- } 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); *************** *** 1204,1209 **** --- 1256,1262 ---- } /* NOTREACHED */ + #if 0 if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0) epinit(ifp->if_unit); *************** *** 1216,1221 **** --- 1269,1275 ---- ep_frst(F_PROMISC); epinit(ifp->if_unit); } + #endif break; #ifdef notdef *************** *** 1234,1241 **** } else { ifp->if_mtu = ifr->ifr_mtu; } ! break; ! default: error = EINVAL; } --- 1288,1302 ---- } 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 --- /sys/i386/isa/if_epreg.h Mon Nov 20 14:15:32 1995 *************** *** 71,76 **** --- 71,78 ---- #define F_ACCESS_32_BITS 0x100 + struct ep_board *epb; + #ifdef EP_LOCAL_STATS short tx_underrun; short rx_no_first; *************** *** 80,85 **** --- 82,98 ---- 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