Subject: port-macppc/26340: Add support for the ethernet portion of the E100/Mercury board found in SuperMac/UMAX S900
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <macallan18@earthlink.net>
List: netbsd-bugs
Date: 07/15/2004 20:36:38
>Number:         26340
>Category:       port-macppc
>Synopsis:       Add support for the ethernet portion of the E100/Mercury board found in SuperMac/UMAX S900
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-macppc-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jul 15 23:01:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     Michael Lorenz
>Release:        2.0G
>Organization:
>Environment:
NetBSD Macallan 2.0G NetBSD 2.0G (MACALLAN) #66: Thu Jul 15 18:29:54 EDT 2004  ml@Macallan:/usr/src/sys/arch/macppc/compile/MACALLAN macppc
>Description:
This patch adds support for the ethernet portion of the UMAX E100 aka 
Mercury card found in a special slot in  UMAX/SuperMac S900 machines.
The E100 contains a Qlogic ISP 1240 UW-SCSI controller and a DEC 21140
fast etherne chip.
You need to add <options PCI_NETBSD_CONFIGURE> to your kernel config to
make it work.
The patch changes two files - if_tlp_pci.c and pci_machdep.c.
In machdep.c it adds support for pci_conf_hook to configure the ethernet
controller ( OpenFirmware doesn't see it for some reason ) before the normal
autoconfig runs. The hook makes sure to touch only real E100 boards and 
no other DEC21140s by looking only at the E100 slot and checking if the
SCSI part of the card is present too.
The changes in if_tlp_pci.c just add another quirk function for the E100 -
more or less the same as the Asante quirk, the only difference is the
reported board name and the NAC address to trigger it.
>How-To-Repeat:
Boot NetBSD on a S900 with a E100/Mercury card - the tlp driver won't be
able to use it.
>Fix:
Index: src/sys/arch/macppc/pci/pci_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/pci/pci_machdep.c,v
retrieving revision 1.25
diff --context -r1.25 pci_machdep.c
*** src/sys/arch/macppc/pci/pci_machdep.c       8 Apr 2004 23:58:24 -0000       
1.25
--- src/sys/arch/macppc/pci/pci_machdep.c       15 Jul 2004 22:54:17 -0000
***************
*** 64,71 ****
--- 64,76 ----
  #include <dev/pci/pcivar.h>
  #include <dev/pci/pcireg.h>
  
+ #include <sys/malloc.h>
+ #include <sys/extent.h>
+ #include <dev/pci/pciconf.h>
+ 
  #include <dev/ofw/openfirm.h>
  #include <dev/ofw/ofw_pci.h>
+ #include "opt_pci.h"
  
  static void fixpci __P((int, pci_chipset_tag_t));
  static int find_node_intr __P((int, u_int32_t *, u_int32_t *));
***************
*** 101,106 ****
--- 106,126 ----
        int node, nn, sz;
        int32_t busrange[2];
  
+ #ifdef PCI_NETBSD_CONFIGURE
+       /* 
+       FIXME: the extent ranges are purely guesswork, someone should change them... 
+       */
+       struct extent *ioext, *memext;
+       ioext  = extent_create("pciio",  0x00000000, 0x0fffffff, M_DEVBUF,
+                  NULL, 0, EX_NOWAIT);
+     memext = extent_create("pcimem", 0x80000000, 0xffffffff, M_DEVBUF,
+                  NULL, 0, EX_NOWAIT);
+       pci_configure_bus(pc, ioext, memext, NULL, 0,0);
+       extent_destroy(ioext);
+       extent_destroy(memext);
+ #endif
+ 
+ 
        for (node = pc->node; node; node = nn) {
                sz = OF_getprop(node, "bus-range", busrange, 8);
                if (sz == 8 && busrange[0] == bus) {
***************
*** 503,505 ****
--- 534,581 ----
  
        return -1;
  }
+ 
+ int
+ pci_conf_hook(pci_chipset_tag_t pc, int bus, int dev, int func, pcireg_t id)
+ {
+       /* check if there's an E100 board in 0:11:0 */
+       pcitag_t tag=pci_make_tag(pc,bus,dev,func);
+       if(tag==0x80008800)
+       {
+               if(id==0x00091011)
+               {
+                       pcireg_t mem, isp;
+                       pcitag_t tag_isp=pci_make_tag(pc,0,0xd,0);
+                       /* here we go. We shouldn't encounter this anywhere else than
+                          on a UMAX S900 with an E100 board */
+                       /* look at 00:0d:00 for a 10201077 ( Qlogic ISP ) to make
+                          sure we really have an E100 here */
+                       isp=pci_conf_read(pc,tag_isp,0);
+                       if(isp==0x10201077)
+                       {
+                               pci_conf_write(pc,tag,0x14,0x80900000);
+                               pci_conf_write(pc,tag,PCI_INTERRUPT_REG,0x00000117);
+                               mem=pci_conf_read(pc,tag,PCI_COMMAND_STATUS_REG);
+                               mem|=(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE);
+                               pci_conf_write(pc,tag,PCI_COMMAND_STATUS_REG,mem);
+                               return PCI_CONF_MAP_IO|PCI_CONF_MAP_MEM|PCI_CONF_ENABLE_IO|PCI_CONF_ENABLE_MEM|PCI_CONF_ENABLE_BM;
+                       }
+               }
+       }
+       return 0;
+ }
+ 
+ void pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int
+      func, int swiz, int *iline)
+ {
+       pcitag_t tag=pci_make_tag(pc,bus,dev,func);
+       pcireg_t id;
+       if(tag==0x80008800)
+       {
+               id=pci_conf_read(pc,tag,0);
+               if(id==0x00091011)
+               {
+                       *iline=23;
+               }
+       }
+ }

Index: src/sys/dev/pci/if_tlp_pci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_tlp_pci.c,v
retrieving revision 1.76
diff --context -r1.76 if_tlp_pci.c
*** src/sys/dev/pci/if_tlp_pci.c        17 Mar 2004 13:54:09 -0000      1.76
--- src/sys/dev/pci/if_tlp_pci.c        15 Jul 2004 22:57:43 -0000
***************
*** 224,229 ****
--- 224,231 ----
  
  void  tlp_pci_asante_21140_quirks __P((struct tulip_pci_softc *,
            const u_int8_t *));
+ void  tlp_pci_e100_quirks __P((struct tulip_pci_softc *,
+           const u_int8_t *));
  void  tlp_pci_smc_21140_quirks __P((struct tulip_pci_softc *,
            const u_int8_t *));
  void  tlp_pci_vpc_21140_quirks __P((struct tulip_pci_softc *,
***************
*** 232,237 ****
--- 234,240 ----
  const struct tlp_pci_quirks tlp_pci_21140_quirks[] = {
        { tlp_pci_dec_quirks,           { 0x08, 0x00, 0x2b } },
        { tlp_pci_dec_quirks,           { 0x00, 0x00, 0xf8 } },
+       { tlp_pci_e100_quirks,          { 0x00, 0xa0, 0x59 } }, // enable quirks for E100 Ethernet
        { tlp_pci_asante_21140_quirks,  { 0x00, 0x00, 0x94 } },
        { tlp_pci_adaptec_quirks,       { 0x00, 0x00, 0x92 } },
        { tlp_pci_adaptec_quirks,       { 0x00, 0x00, 0xd1 } },
***************
*** 357,363 ****
        const struct tulip_pci_product *tpp;
        u_int8_t enaddr[ETHER_ADDR_LEN];
        u_int32_t val = 0;
!       pcireg_t reg;
        int pmreg;
  
        sc->sc_devno = pa->pa_device;
--- 360,366 ----
        const struct tulip_pci_product *tpp;
        u_int8_t enaddr[ETHER_ADDR_LEN];
        u_int32_t val = 0;
!       pcireg_t reg, addr, size;
        int pmreg;
  
        sc->sc_devno = pa->pa_device;
***************
*** 545,557 ****
        /*
         * Map the device.
         */
        ioh_valid = (pci_mapreg_map(pa, TULIP_PCI_IOBA,
            PCI_MAPREG_TYPE_IO, 0,
            &iot, &ioh, NULL, NULL) == 0);
        memh_valid = (pci_mapreg_map(pa, TULIP_PCI_MMBA,
            PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
!           &memt, &memh, NULL, NULL) == 0);
! 
        if (memh_valid) {
                sc->sc_st = memt;
                sc->sc_sh = memh;
--- 548,560 ----
        /*
         * Map the device.
         */
+                
        ioh_valid = (pci_mapreg_map(pa, TULIP_PCI_IOBA,
            PCI_MAPREG_TYPE_IO, 0,
            &iot, &ioh, NULL, NULL) == 0);
        memh_valid = (pci_mapreg_map(pa, TULIP_PCI_MMBA,
            PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
!           &memt, &memh, &addr, &size) == 0);
        if (memh_valid) {
                sc->sc_st = memt;
                sc->sc_sh = memh;
***************
*** 1251,1256 ****
--- 1254,1275 ----
        sc->sc_mediasw = &tlp_sio_mii_mediasw;
  }
  
+ void tlp_pci_e100_quirks(psc, enaddr)
+       struct tulip_pci_softc *psc;
+       const u_int8_t *enaddr;
+ {
+       struct tulip_softc *sc = &psc->sc_tulip;
+ 
+       if (sc->sc_mediasw == &tlp_2114x_isv_mediasw)
+               return;
+ 
+       strcpy(sc->sc_name, "UMAX E100");
+ 
+       sc->sc_gp_dir = 0xbf;
+       sc->sc_reset = tlp_pci_asante_21140_reset;
+       sc->sc_mediasw = &tlp_sio_mii_mediasw;
+ }
+ 
  void
  tlp_pci_asante_21140_reset(sc)
        struct tulip_softc *sc;

>Release-Note:
>Audit-Trail:
>Unformatted: