Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Oct 1995 10:00:04 +0500 (GMT+0500)
From:      "Serge A. Babkin" <babkin@hq.icb.chel.su>
To:        current@freebsd.org
Cc:        jkh@time.cdrom.com, bde@zeta.org.au
Subject:   3c509 in -current needs patching
Message-ID:  <199510170500.KAA23451@hq.icb.chel.su>

next in thread | raw e-mail | index | archive | help
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 <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,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 ----------------------------------



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199510170500.KAA23451>