[BACK]Return to if_xl_pci.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/if_xl_pci.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb