Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Sep 1999 11:10:41 -0500 (CDT)
From:      Jason Young <doogie@anet-stl.com>
To:        current@freebsd.org
Subject:   3Com Megahertz 574B patches
Message-ID:  <Pine.BSF.3.96.990916110143.10899A-100000@earth.anet-stl.com>

next in thread | raw e-mail | index | archive | help

Here is a patch that gets my 3Com Megahertz 574B ethernet PC-card working. 
I'd submit it as a PR, but I'm not at all sure I'm doing the right thing
to detect it. The gist of the patch:

1) Reworked the probe routine to avoid having to set a flag to find my
card, mostly on account of I couldn't figure out how to set the flag. This
is the "I'm probably doing this wrong" part. 

2) Addition of the 574B's product ID. 

3) Output of some more useful info when booting verbosely. 

Jason Young
accessUS Chief Network Engineer

*** /home/doogie/if_ep.c	Tue Sep 14 11:22:12 1999
--- if_ep.c	Tue Sep 14 11:29:13 1999
***************
*** 162,171 ****
--- 162,172 ----
   */
  static int ep_pccard_init __P((struct pccard_devinfo *));
  static int ep_pccard_attach  __P((struct pccard_devinfo *));
  static void ep_unload __P((struct pccard_devinfo *));
  static int card_intr __P((struct pccard_devinfo *));
+ static int ep_pccard_identify (struct ep_board *epb, int unit); 
  
  PCCARD_MODULE(ep, ep_pccard_init, ep_unload, card_intr, 0, net_imask);
  
  /*
   * Initialize the device - called from Slot manager.
***************
*** 189,232 ****
      }
  
      /* get_e() requires these. */
      sc->ep_io_addr = is->id_iobase;
      sc->unit = is->id_unit;
-     epb->cmd_off = 0;
-     if (is->id_flags & EP_FLAGS_100TX) 
- 	epb->cmd_off = 2;
- 
      epb->epb_addr = is->id_iobase;
      epb->epb_used = 1;
-     epb->prod_id = get_e(sc, EEPROM_PROD_ID);
-     epb->mii_trans = 0;
  
!     /* product id */
!     switch (epb->prod_id) {
!       case 0x6055: /* 3C556 */
!       case 0x4057: /* 3C574 */
! 	epb->mii_trans = 1;
! 	break;
!       case 0x9058: /* 3C589 */
! 	break;
!       default:
! 	printf("ep%d: failed to come ready.\n", is->id_unit);
! 	return (ENXIO);
      }
  
      epb->res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
!     for (i = 0; i < 3; i++)
  	sc->epb->eth_addr[i] = get_e(sc, EEPROM_NODE_ADDR_0 + i);
  
      if (ep_pccard_attach(devi) == 0)
  	return (ENXIO);
  
      sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
      return (0);
  }
  
  static int
  ep_pccard_attach(devi)
      struct pccard_devinfo *devi;
  {
      struct isa_device *is = &devi->isahd;
      struct ep_softc *sc = ep_softc[is->id_unit];
--- 190,265 ----
      }
  
      /* get_e() requires these. */
      sc->ep_io_addr = is->id_iobase;
      sc->unit = is->id_unit;
      epb->epb_addr = is->id_iobase;
      epb->epb_used = 1;
  
!     /*
!      * XXX - Certain (newer?) 3Com cards need epb->cmd_off == 2. Sadly,
!      * you need to have a correct cmd_off in order to identify the card. 
!      * So we have to hit it with both and cross our virtual fingers. There's
!      * got to be a better way to do this. jyoung@accessus.net 09/11/1999
!      */
! 
!     epb->cmd_off = 0;
!     epb->prod_id = get_e(sc, EEPROM_PROD_ID);
!     if (bootverbose) printf("ep%d: Pass 1 of 2 detection failed (nonfatal)\n", is->id_unit);
!     if (!ep_pccard_identify(epb, is->id_unit)) {
! 	epb->cmd_off = 2;
! 	epb->prod_id = get_e(sc, EEPROM_PROD_ID);
! 	if (!ep_pccard_identify(epb, is->id_unit)) {
! 	    if (bootverbose) printf("ep%d: Pass 2 of 2 detection failed (fatal!)\n", is->id_unit);
! 	    printf("ep%d: Unit failed to come ready or product ID unknown! (id 0x%x)\n", is->id_unit, epb->prod_id);
! 	    return (ENXIO);
! 	}
      }
  
      epb->res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
!     for (i = 0; i < 3; i++) 
  	sc->epb->eth_addr[i] = get_e(sc, EEPROM_NODE_ADDR_0 + i);
  
      if (ep_pccard_attach(devi) == 0)
  	return (ENXIO);
  
      sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
      return (0);
  }
  
  static int
+ ep_pccard_identify(epb, unit)
+     struct ep_board *epb;
+     int unit;
+ {
+     /* Determine device type and associated MII capabilities  */
+     switch (epb->prod_id) {
+ 	case 0x6055: /* 3C556 */
+ 	    if (bootverbose) printf("ep%d: 3Com 3C556\n", unit);
+ 	    epb->mii_trans = 1;
+ 	    return (1);
+ 	    break; /* NOTREACHED */
+ 	case 0x4057: /* 3C574 */
+ 	    if (bootverbose) printf("ep%d: 3Com 3C574\n", unit);
+ 	    epb->mii_trans = 1;
+ 	    return (1);
+ 	    break; /* NOTREACHED */
+ 	case 0x4b57: /* 3C574B */
+ 	    if (bootverbose) printf("ep%d: 3Com 3C574B, Megahertz 3CCFE574BT or Fast Etherlink 3C574-TX\n", unit);
+ 	    epb->mii_trans = 1;
+ 	    return (1);
+ 	    break; /* NOTREACHED */
+ 	case 0x9058: /* 3C589 */
+ 	    if (bootverbose) printf("ep%d: 3Com Etherlink III 3C589[B/C/D]\n", unit);
+ 	    epb->mii_trans = 0;
+ 	    return (1);
+ 	    break; /* NOTREACHED */
+     }
+     return (0);
+ }
+ 
+ static int
  ep_pccard_attach(devi)
      struct pccard_devinfo *devi;
  {
      struct isa_device *is = &devi->isahd;
      struct ep_softc *sc = ep_softc[is->id_unit];
***************
*** 239,249 ****
      }
      if (config & IS_UTP) {
  	sc->ep_connectors |= UTP;
      }
      if (!(sc->ep_connectors & 7))
! 	printf("ep%d: No connectors or MII.\n", is->id_unit);
      sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
  
      /* ROM size = 0, ROM base = 0 */
      /* For now, ignore AUTO SELECT feature of 3C589B and later. */
      outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000);
--- 272,284 ----
      }
      if (config & IS_UTP) {
  	sc->ep_connectors |= UTP;
      }
      if (!(sc->ep_connectors & 7))
! 	/* (Apparently) non-fatal */
! 	if(bootverbose) printf("ep%d: No connectors or MII.\n", is->id_unit);
! 
      sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
  
      /* ROM size = 0, ROM base = 0 */
      /* For now, ignore AUTO SELECT feature of 3C589B and later. */
      outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000);
***************
*** 253,263 ****
  
      outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
  
      if (sc->epb->mii_trans) {
  	/*
! 	 * turn on the MII tranceiver
  	 */
  	GO_WINDOW(3);
  	outw(BASE + EP_W3_OPTIONS, 0x8040);
  	DELAY(1000);
  	outw(BASE + EP_W3_OPTIONS, 0xc040);
--- 288,298 ----
  
      outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
  
      if (sc->epb->mii_trans) {
  	/*
! 	 * turn on the MII transciever
  	 */
  	GO_WINDOW(3);
  	outw(BASE + EP_W3_OPTIONS, 0x8040);
  	DELAY(1000);
  	outw(BASE + EP_W3_OPTIONS, 0xc040);



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.990916110143.10899A-100000>