Skip site navigation (1)Skip section navigation (2)
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>