root/dev/pci/if_xl_pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xl_pci_match
  2. xl_pci_attach
  3. xl_pci_intr_ack

    1 /*      $OpenBSD: if_xl_pci.c,v 1.22 2006/08/10 20:10:19 brad Exp $     */
    2 
    3 /*
    4  * Copyright (c) 1997, 1998, 1999
    5  *      Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Bill Paul.
   18  * 4. Neither the name of the author nor the names of any co-contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   32  * THE POSSIBILITY OF SUCH DAMAGE.
   33  *
   34  * $FreeBSD: if_xl.c,v 1.72 2000/01/09 21:12:59 wpaul Exp $
   35  */
   36 
   37 #include "bpfilter.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/protosw.h>
   43 #include <sys/socket.h>
   44 #include <sys/ioctl.h>
   45 #include <sys/errno.h>
   46 #include <sys/malloc.h>
   47 #include <sys/kernel.h>
   48 #include <sys/proc.h>   /* only for declaration of wakeup() used by vm.h */
   49 #include <sys/device.h>
   50 
   51 #include <net/if.h>
   52 #include <net/if_dl.h>
   53 #include <net/if_types.h>
   54 #include <net/if_media.h>
   55 
   56 #ifdef INET
   57 #include <netinet/in.h>
   58 #include <netinet/in_systm.h>
   59 #include <netinet/in_var.h>
   60 #include <netinet/ip.h>
   61 #include <netinet/if_ether.h>
   62 #endif
   63 
   64 #include <dev/mii/mii.h>
   65 #include <dev/mii/miivar.h>
   66 #include <dev/pci/pcireg.h>
   67 #include <dev/pci/pcivar.h>
   68 #include <dev/pci/pcidevs.h>
   69 
   70 #if NBPFILTER > 0
   71 #include <net/bpf.h>
   72 #endif
   73 
   74 /*
   75  * The following #define causes the code to use PIO to access the
   76  * chip's registers instead of memory mapped mode. The reason PIO mode
   77  * is on by default is that the Etherlink XL manual seems to indicate
   78  * that only the newer revision chips (3c905B) support both PIO and
   79  * memory mapped access. Since we want to be compatible with the older
   80  * bus master chips, we use PIO here. If you comment this out, the
   81  * driver will use memory mapped I/O, which may be faster but which
   82  * might not work on some devices.
   83  */
   84 #define XL_USEIOSPACE
   85 
   86 #define XL_PCI_FUNCMEM          0x0018
   87 #define XL_PCI_INTR             0x0004
   88 #define XL_PCI_INTRACK          0x8000
   89 
   90 #include <dev/ic/xlreg.h>
   91 
   92 int xl_pci_match(struct device *, void *, void *);
   93 void xl_pci_attach(struct device *, struct device *, void *);
   94 void xl_pci_intr_ack(struct xl_softc *);
   95 
   96 struct cfattach xl_pci_ca = {
   97         sizeof(struct xl_softc), xl_pci_match, xl_pci_attach,
   98 };
   99 
  100 const struct pci_matchid xl_pci_devices[] = {
  101         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CSOHO100TX },
  102         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900TPO },
  103         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900COMBO },
  104         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900B },
  105         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BCOMBO },
  106         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BTPC },
  107         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C900BFL },
  108         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905TX },
  109         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905T4 },
  110         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BTX },
  111         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BT4 },
  112         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BCOMBO },
  113         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905BFX },
  114         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C980TX },
  115         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C980CTX },
  116         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C905CTX },
  117         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C450 },
  118         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C555 },
  119         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C556 },
  120         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C556B },
  121         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C9201 },
  122         { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C920BEMBW },
  123 };
  124 
  125 int
  126 xl_pci_match(struct device *parent, void *match, void *aux)
  127 {
  128         return (pci_matchbyid((struct pci_attach_args *)aux, xl_pci_devices,
  129             sizeof(xl_pci_devices)/sizeof(xl_pci_devices[0])));
  130 }
  131 
  132 void
  133 xl_pci_attach(struct device *parent, struct device *self, void *aux)
  134 {
  135         struct xl_softc *sc = (struct xl_softc *)self;
  136         struct pci_attach_args *pa = aux;
  137         pci_chipset_tag_t pc = pa->pa_pc;
  138         pci_intr_handle_t ih;
  139         const char *intrstr = NULL;
  140         bus_size_t iosize, funsize;
  141         u_int32_t command;
  142 
  143         sc->sc_dmat = pa->pa_dmat;
  144 
  145         sc->xl_flags = 0;
  146 
  147         /* set required flags */
  148         switch (PCI_PRODUCT(pa->pa_id)) {
  149         case TC_DEVICEID_HURRICANE_555:
  150                 sc->xl_flags |= XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM;
  151                 break;
  152         case TC_DEVICEID_HURRICANE_556:
  153                 sc->xl_flags |= XL_FLAG_FUNCREG | XL_FLAG_PHYOK |
  154                     XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_WEIRDRESET;
  155                 sc->xl_flags |= XL_FLAG_INVERT_LED_PWR|XL_FLAG_INVERT_MII_PWR;
  156                 sc->xl_flags |= XL_FLAG_8BITROM;
  157                 break;
  158         case TC_DEVICEID_HURRICANE_556B:
  159                 sc->xl_flags |= XL_FLAG_FUNCREG | XL_FLAG_PHYOK |
  160                     XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_WEIRDRESET;
  161                 sc->xl_flags |= XL_FLAG_INVERT_LED_PWR|XL_FLAG_INVERT_MII_PWR;
  162                 break;
  163         case PCI_PRODUCT_3COM_3C9201:
  164         case PCI_PRODUCT_3COM_3C920BEMBW:
  165                 sc->xl_flags |= XL_FLAG_PHYOK;
  166                 break;
  167         case TC_DEVICEID_BOOMERANG_10_100BT:
  168                 sc->xl_flags |= XL_FLAG_NO_MMIO;
  169                 break;
  170         default:
  171                 break;
  172         }
  173 
  174         /*
  175          * If this is a 3c905B, we have to check one extra thing.
  176          * The 905B supports power management and may be placed in
  177          * a low-power mode (D3 mode), typically by certain operating
  178          * systems which shall not be named. The PCI BIOS is supposed
  179          * to reset the NIC and bring it out of low-power mode, but  
  180          * some do not. Consequently, we have to see if this chip    
  181          * supports power management, and if so, make sure it's not  
  182          * in low-power mode. If power management is available, the  
  183          * capid byte will be 0x01.
  184          * 
  185          * I _think_ that what actually happens is that the chip
  186          * loses its PCI configuration during the transition from
  187          * D3 back to D0; this means that it should be possible for
  188          * us to save the PCI iobase, membase and IRQ, put the chip
  189          * back in the D0 state, then restore the PCI config ourselves.
  190          */
  191         command = pci_conf_read(pc, pa->pa_tag, XL_PCI_CAPID) & 0xff;
  192         if (command == 0x01) {
  193 
  194                 command = pci_conf_read(pc, pa->pa_tag,
  195                     XL_PCI_PWRMGMTCTRL);
  196                 if (command & XL_PSTATE_MASK) {
  197                         u_int32_t io, mem, irq;
  198 
  199                         /* Save PCI config */
  200                         io = pci_conf_read(pc, pa->pa_tag, XL_PCI_LOIO);
  201                         mem = pci_conf_read(pc, pa->pa_tag, XL_PCI_LOMEM);
  202                         irq = pci_conf_read(pc, pa->pa_tag, XL_PCI_INTLINE);
  203 
  204                         /* Reset the power state. */
  205                         printf("%s: chip is in D%d power mode "
  206                             "-- setting to D0\n",
  207                             sc->sc_dev.dv_xname, command & XL_PSTATE_MASK);
  208                         command &= 0xFFFFFFFC;
  209                         pci_conf_write(pc, pa->pa_tag,
  210                             XL_PCI_PWRMGMTCTRL, command);
  211 
  212                         pci_conf_write(pc, pa->pa_tag, XL_PCI_LOIO, io);
  213                         pci_conf_write(pc, pa->pa_tag, XL_PCI_LOMEM, mem);
  214                         pci_conf_write(pc, pa->pa_tag, XL_PCI_INTLINE, irq);
  215                 }
  216         }
  217 
  218         /*
  219          * Map control/status registers.
  220          */
  221 #ifdef XL_USEIOSPACE
  222         if (pci_mapreg_map(pa, XL_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
  223             &sc->xl_btag, &sc->xl_bhandle, NULL, &iosize, 0)) {
  224                 printf(": can't map i/o space\n");
  225                 return;
  226         }
  227 #else
  228         if (pci_mapreg_map(pa, XL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
  229             &sc->xl_btag, &sc->xl_bhandle, NULL, &iosize, 0)) {
  230                 printf(": can't map i/o space\n");
  231                 return;
  232         }
  233 #endif
  234 
  235         if (sc->xl_flags & XL_FLAG_FUNCREG) {
  236                 if (pci_mapreg_map(pa, XL_PCI_FUNCMEM, PCI_MAPREG_TYPE_MEM, 0,
  237                     &sc->xl_funct, &sc->xl_funch, NULL, &funsize, 0)) {
  238                         printf(": can't map i/o space\n");
  239                         bus_space_unmap(sc->xl_btag, sc->xl_bhandle, iosize);
  240                         return;
  241                 }
  242                 sc->intr_ack = xl_pci_intr_ack;
  243         }
  244 
  245         /*
  246          * Allocate our interrupt.
  247          */
  248         if (pci_intr_map(pa, &ih)) {
  249                 printf(": couldn't map interrupt\n");
  250                 bus_space_unmap(sc->xl_btag, sc->xl_bhandle, iosize);
  251                 if (sc->xl_flags & XL_FLAG_FUNCREG)
  252                         bus_space_unmap(sc->xl_funct, sc->xl_funch, funsize);
  253                 return;
  254         }
  255 
  256         intrstr = pci_intr_string(pc, ih);
  257         sc->xl_intrhand = pci_intr_establish(pc, ih, IPL_NET, xl_intr, sc,
  258             self->dv_xname);
  259         if (sc->xl_intrhand == NULL) {
  260                 printf(": couldn't establish interrupt");
  261                 if (intrstr != NULL)
  262                         printf(" at %s", intrstr);
  263                 bus_space_unmap(sc->xl_btag, sc->xl_bhandle, iosize);
  264                 if (sc->xl_flags & XL_FLAG_FUNCREG)
  265                         bus_space_unmap(sc->xl_funct, sc->xl_funch, funsize);
  266                 return;
  267         }
  268         printf(": %s", intrstr);
  269 
  270         xl_attach(sc);
  271 }
  272 
  273 
  274 void            
  275 xl_pci_intr_ack(struct xl_softc *sc)
  276 {
  277         bus_space_write_4(sc->xl_funct, sc->xl_funch, XL_PCI_INTR,
  278             XL_PCI_INTRACK);
  279 }

/* [<][>][^][v][top][bottom][index][help] */