Date: Wed, 26 Jul 1995 14:32:37 +0600 (GMT+0600) From: "Serge A. Babkin" <babkin@hq.icb.chel.su> To: rgrimes@gndrsh.aac.dev.com (Rodney W. Grimes) Cc: current@freebsd.org Subject: Re: ep driver Message-ID: <199507260832.OAA06959@hq.icb.chel.su> In-Reply-To: <199506221628.JAA06007@gndrsh.aac.dev.com> from "Rodney W. Grimes" at Jun 22, 95 09:28:14 am
next in thread | previous in thread | raw e-mail | index | archive | help
> These patches should really be sent to -current now as we are > no longer in a release code freeze. Recently I have finally got the 950622-SNAP and found that the ep driver in it is enough old. Commit please this patch to -current. It does: - understands 3C509 cards in "plug-n-play" mode - understands the cards after soft reboot from MS-DOS - doesn't conflict with ie driver - has multicast support ------------------------------- cut here ------------------------------- *** if_ep.c.205 Tue Jul 18 09:29:52 1995 --- if_ep.c Wed Jul 26 14:29:44 1995 *************** *** 38,45 **** */ /* - * $Id: if_ep.c,v 1.28 1995/05/30 08:02:07 rgrimes Exp $ - * * Promiscuous mode added and interrupt logic slightly changed * to reduce the number of adapter failures. Transceiver select * logic changed to use value from EEPROM. Autoconfiguration --- 38,43 ---- *************** *** 100,105 **** --- 98,104 ---- #include <i386/isa/isa_device.h> #include <i386/isa/icu.h> #include <i386/isa/if_epreg.h> + #include <i386/isa/elink.h> 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,143 **** }; 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 */ } }; --- 132,143 ---- }; 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_BUSY, /* network interfaces are always ``open'' */ "3Com 3C509 Ethernet adapter", DC_CLS_NETIF /* class */ } }; *************** *** 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,189 **** 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)) { /* Come here just one time */ ! /* Look for the EISA boards, leave them activated */ for(j = 1; j < 16; j++) { io_base = (j * EP_EISA_START) | EP_EISA_W0; --- 170,185 ---- 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)) { /* Come here just one time */ ! /* Look for the EISA boards, leave them activated */ for(j = 1; j < 16; j++) { io_base = (j * EP_EISA_START) | EP_EISA_W0; *************** *** 191,197 **** continue; /* we must found 0x1f if the board is EISA configurated */ ! if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f) continue; /* Reset and Enable the card */ --- 187,193 ---- continue; /* we must found 0x1f if the board is EISA configurated */ ! if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f) continue; /* Reset and Enable the card */ *************** *** 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]; } } *************** *** 306,327 **** u_short k; int i; ! 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: --- 336,356 ---- u_short k; int i; ! 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])); } --- 425,431 ---- 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; --- 452,459 ---- 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. --- 462,468 ---- ifp->if_timer=1; if_attach(ifp); ! ep_registerdev(is); /* * Fill the hardware address into ifa_addr if we find an AF_LINK entry. *************** *** 455,464 **** sc->rx_avg_pkt = 128; /* ! * NOTE: In all this I multiply everything by 64. ! * W_s = the speed the CPU is able to write to the TX FIFO. * T_s = the speed the board sends the info to the Ether. ! * W_s/T_s = 16 (represents 16/64) => W_s = 25 % of T_s. * This will give us for a packet of 1500 bytes * tx_start_thresh=1125 and for a pkt of 64 bytes tx_start_threshold=48. * We prefer to start thinking the CPU is much slower than the Ethernet --- 485,494 ---- sc->rx_avg_pkt = 128; /* ! * NOTE: In all this I multiply everything by 64. ! * W_s = the speed the CPU is able to write to the TX FIFO. * T_s = the speed the board sends the info to the Ether. ! * W_s/T_s = 16 (represents 16/64) => W_s = 25 % of T_s. * This will give us for a packet of 1500 bytes * tx_start_thresh=1125 and for a pkt of 64 bytes tx_start_threshold=48. * We prefer to start thinking the CPU is much slower than the Ethernet *************** *** 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. --- 566,577 ---- 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); --- 844,850 ---- 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); *************** *** 865,871 **** outw(BASE + EP_COMMAND, C_INTR_LATCH); /* ACK int Latch */ ! if ((status = inw(BASE + EP_STATUS)) & S_5_INTS) goto rescan; /* re-enable Ints */ --- 895,901 ---- outw(BASE + EP_COMMAND, C_INTR_LATCH); /* ACK int Latch */ ! if ((status = inw(BASE + EP_STATUS)) & S_5_INTS) goto rescan; /* re-enable Ints */ *************** *** 1175,1180 **** --- 1205,1211 ---- } /* NOTREACHED */ + #if 0 if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0) epinit(ifp->if_unit); *************** *** 1187,1192 **** --- 1218,1224 ---- ep_frst(F_PROMISC); epinit(ifp->if_unit); } + #endif break; #ifdef notdef *************** *** 1195,1212 **** sizeof(sc->sc_addr)); break; #endif ! case SIOCSIFMTU: /* * Set the interface MTU. */ ! if (ifr->ifr_mtu > ETHERMTU) { ! error = EINVAL; } else { ! ifp->if_mtu = ifr->ifr_mtu; } ! break; default: error = EINVAL; } --- 1227,1255 ---- sizeof(sc->sc_addr)); break; #endif ! case SIOCSIFMTU: /* * Set the interface MTU. */ ! if (ifr->ifr_mtu > ETHERMTU) { ! error = EINVAL; } else { ! ifp->if_mtu = ifr->ifr_mtu; } ! break; ! case SIOCADDMULTI: ! case SIOCDELMULTI: ! error= (cmd==SIOCADDMULTI) ? ! ether_addmulti(ifr, &sc->arpcom) : ! ether_delmulti(ifr, &sc->arpcom); + if(error=ENETRESET) { + epinit(ifp->if_unit); + error=0; + } + + break; default: error = EINVAL; } *** if_epreg.h.205 Tue Jul 18 09:29:43 1995 --- if_epreg.h Wed Jul 26 14:19:14 1995 *************** *** 31,37 **** */ /* - * $Id: if_epreg.h,v 1.8 1995/05/30 08:02:09 rgrimes Exp $ * * Promiscuous mode added and interrupt logic slightly changed * to reduce the number of adapter failures. Transceiver select --- 31,36 ---- *************** *** 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 ------------------------------- Serge Babkin ! (babkin@hq.icb.chel.su) ! Headquarter of Joint Stock Commercial Bank "Chelindbank" ! Chelyabinsk, Russia
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199507260832.OAA06959>