Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Jan 1996 10:37:28 +0500 (GMT+0500)
From:      "Serge A. Babkin" <babkin@hq.icb.chel.su>
To:        cher@test.phys.msu.su (Alicher O Alikhodjaev)
Cc:        hackers@freebsd.org, jkh@cdrom.com
Subject:   Re: 3c5x9 multicast
Message-ID:  <199601160537.KAA06551@hq.icb.chel.su>
In-Reply-To: <199601151322.QAA06200@test.phys.msu.su> from "Alicher O Alikhodjaev" at Jan 15, 96 04:22:30 pm

next in thread | previous in thread | raw e-mail | index | archive | help
> 
> 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 <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 *));
***************
*** 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



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