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

Annotation of sys/dev/cardbus/if_dc_cardbus.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_dc_cardbus.c,v 1.24 2007/05/08 00:04:47 deraadt Exp $      */
                      2:
                      3: #include <sys/param.h>
                      4: #include <sys/systm.h>
                      5: #include <sys/mbuf.h>
                      6: #include <sys/socket.h>
                      7: #include <sys/ioctl.h>
                      8: #include <sys/errno.h>
                      9: #include <sys/malloc.h>
                     10: #include <sys/kernel.h>
                     11: #include <sys/proc.h>
                     12: #include <sys/device.h>
                     13:
                     14: #include <net/if.h>
                     15: #include <net/if_dl.h>
                     16: #include <net/if_types.h>
                     17: #include <net/if_media.h>
                     18:
                     19: #include <netinet/in.h>
                     20: #include <netinet/if_ether.h>
                     21:
                     22: #include <dev/mii/mii.h>
                     23: #include <dev/mii/miivar.h>
                     24:
                     25: #include <machine/bus.h>
                     26:
                     27: #include <dev/pci/pcivar.h>
                     28: #include <dev/pci/pcireg.h>
                     29: #include <dev/pci/pcidevs.h>
                     30:
                     31: #include <dev/cardbus/cardbusvar.h>
                     32:
                     33: #include <dev/ic/dcreg.h>
                     34:
                     35: /* PCI configuration regs */
                     36: #define        PCI_CBIO        0x10
                     37: #define        PCI_CBMEM       0x14
                     38: #define        PCI_CFDA        0x40
                     39:
                     40: #define        DC_CFDA_SUSPEND 0x80000000
                     41: #define        DC_CFDA_STANDBY 0x40000000
                     42:
                     43: struct dc_cardbus_softc {
                     44:        struct dc_softc         sc_dc;
                     45:        int                     sc_intrline;
                     46:
                     47:        cardbus_devfunc_t       sc_ct;
                     48:        cardbustag_t            sc_tag;
                     49:        bus_size_t              sc_mapsize;
                     50:        int                     sc_actype;
                     51: };
                     52:
                     53: int dc_cardbus_match(struct device *, void *, void *);
                     54: void dc_cardbus_attach(struct device *, struct device *,void *);
                     55: int dc_cardbus_detach(struct device *, int);
                     56:
                     57: void dc_cardbus_setup(struct dc_cardbus_softc *csc);
                     58:
                     59: struct cfattach dc_cardbus_ca = {
                     60:        sizeof(struct dc_cardbus_softc), dc_cardbus_match, dc_cardbus_attach,
                     61:            dc_cardbus_detach
                     62: };
                     63:
                     64: const struct cardbus_matchid dc_cardbus_devices[] = {
                     65:        { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142 },
                     66:        { PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_X3201_3_21143 },
                     67:        { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN985 },
                     68:        { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN2242 },
                     69:        { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2500 },
                     70:        { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2500MX },
                     71:        { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_PCM200 },
                     72:        { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DRP32TXD },
                     73:        { PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_PCMPC200 },
                     74:        { PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_PCM200 },
                     75:        { PCI_VENDOR_HAWKING, PCI_PRODUCT_HAWKING_PN672TX },
                     76:        { PCI_VENDOR_MICROSOFT, PCI_PRODUCT_MICROSOFT_MN120 },
                     77: };
                     78:
                     79: int
                     80: dc_cardbus_match(parent, match, aux)
                     81:        struct device *parent;
                     82:        void *match, *aux;
                     83: {
                     84:        return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
                     85:            dc_cardbus_devices,
                     86:            sizeof(dc_cardbus_devices)/sizeof(dc_cardbus_devices[0])));
                     87: }
                     88:
                     89: void
                     90: dc_cardbus_attach(parent, self, aux)
                     91:        struct device *parent, *self;
                     92:        void *aux;
                     93: {
                     94:        struct dc_cardbus_softc *csc = (struct dc_cardbus_softc *)self;
                     95:        struct dc_softc *sc = &csc->sc_dc;
                     96:        struct cardbus_attach_args *ca = aux;
                     97:        struct cardbus_devfunc *ct = ca->ca_ct;
                     98:        cardbus_chipset_tag_t cc = ct->ct_cc;
                     99:        cardbus_function_tag_t cf = ct->ct_cf;
                    100:        cardbusreg_t reg;
                    101:        bus_addr_t addr;
                    102:
                    103:        sc->sc_dmat = ca->ca_dmat;
                    104:        csc->sc_ct = ct;
                    105:        csc->sc_tag = ca->ca_tag;
                    106:
                    107:        Cardbus_function_enable(ct);
                    108:
                    109:        if (Cardbus_mapreg_map(ct, PCI_CBIO,
                    110:            PCI_MAPREG_TYPE_IO, 0, &sc->dc_btag, &sc->dc_bhandle, &addr,
                    111:            &csc->sc_mapsize) == 0) {
                    112:
                    113:                csc->sc_actype = CARDBUS_IO_ENABLE;
                    114:        } else if (Cardbus_mapreg_map(ct, PCI_CBMEM,
                    115:            PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
                    116:            &sc->dc_btag, &sc->dc_bhandle, &addr, &csc->sc_mapsize) == 0) {
                    117:                csc->sc_actype = CARDBUS_MEM_ENABLE;
                    118:        } else {
                    119:                printf(": can\'t map device registers\n");
                    120:                return;
                    121:        }
                    122:
                    123:        csc->sc_intrline = ca->ca_intrline;
                    124:
                    125:        sc->dc_cachesize = cardbus_conf_read(cc, cf, ca->ca_tag, DC_PCI_CFLT)
                    126:            & 0xFF;
                    127:
                    128:        dc_cardbus_setup(csc);
                    129:
                    130:        /* Get the eeprom width, but XIRCOM has no eeprom */
                    131:        if (!(PCI_VENDOR(ca->ca_id) == PCI_VENDOR_XIRCOM &&
                    132:              PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143))
                    133:                dc_eeprom_width(sc);
                    134:
                    135:        switch (PCI_VENDOR(ca->ca_id)) {
                    136:        case PCI_VENDOR_DEC:
                    137:                if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_DEC_21142) {
                    138:                        sc->dc_type = DC_TYPE_21143;
                    139:                        sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
                    140:                        sc->dc_flags |= DC_REDUCED_MII_POLL;
                    141:                        dc_read_srom(sc, sc->dc_romwidth);
                    142:                        dc_parse_21143_srom(sc);
                    143:                }
                    144:                break;
                    145:        case PCI_VENDOR_XIRCOM:
                    146:                if (PCI_PRODUCT(ca->ca_id) ==
                    147:                    PCI_PRODUCT_XIRCOM_X3201_3_21143) {
                    148:                        sc->dc_type = DC_TYPE_XIRCOM;
                    149:                        sc->dc_flags |= DC_TX_INTR_ALWAYS|DC_TX_COALESCE |
                    150:                                        DC_TX_ALIGN;
                    151:                        sc->dc_pmode = DC_PMODE_MII;
                    152:
                    153:                        bcopy(ca->ca_cis.funce.network.netid,
                    154:                            &sc->sc_arpcom.ac_enaddr,
                    155:                            sizeof sc->sc_arpcom.ac_enaddr);
                    156:                }
                    157:                break;
                    158:        case PCI_VENDOR_ADMTEK:
                    159:        case PCI_VENDOR_ACCTON:
                    160:        case PCI_VENDOR_ABOCOM:
                    161:        case PCI_VENDOR_DLINK:
                    162:        case PCI_VENDOR_LINKSYS:
                    163:        case PCI_VENDOR_HAWKING:
                    164:        case PCI_VENDOR_MICROSOFT:
                    165:                if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ADMTEK_AN985 ||
                    166:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ACCTON_EN2242 ||
                    167:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_FE2500 ||
                    168:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_FE2500MX ||
                    169:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_PCM200 ||
                    170:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_DLINK_DRP32TXD ||
                    171:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_LINKSYS_PCMPC200 ||
                    172:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_LINKSYS_PCM200 ||
                    173:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_HAWKING_PN672TX ||
                    174:                    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_MICROSOFT_MN120) {
                    175:                        sc->dc_type = DC_TYPE_AN983;
                    176:                        sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_ADMTEK_WAR |
                    177:                                        DC_64BIT_HASH;
                    178:                        sc->dc_pmode = DC_PMODE_MII;
                    179:                        /* Don't read SROM for - auto-loaded on reset */
                    180:                }
                    181:                break;
                    182:        default:
                    183:                printf(": unknown device\n");
                    184:                return;
                    185:        }
                    186:
                    187:        /*
                    188:         * set latency timer, do we really need this?
                    189:         */
                    190:        reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_BHLC_REG);
                    191:        if (PCI_LATTIMER(reg) < 0x20) {
                    192:                reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
                    193:                reg |= (0x20 << PCI_LATTIMER_SHIFT);
                    194:                cardbus_conf_write(cc, cf, ca->ca_tag, PCI_BHLC_REG, reg);
                    195:        }
                    196:
                    197:        sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET,
                    198:            dc_intr, csc, sc->sc_dev.dv_xname);
                    199:        if (sc->sc_ih == NULL) {
                    200:                printf(": can't establish interrupt at %d\n",
                    201:                    ca->ca_intrline);
                    202:                return;
                    203:        } else
                    204:                printf(" irq %d", ca->ca_intrline);
                    205:
                    206:        dc_reset(sc);
                    207:
                    208:        sc->dc_revision = PCI_REVISION(ca->ca_class);
                    209:        dc_attach(sc);
                    210: }
                    211:
                    212: int
                    213: dc_detach(sc)
                    214:        struct dc_softc *sc;
                    215: {
                    216:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    217:
                    218:        if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
                    219:                mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
                    220:
                    221:        if (sc->dc_srom)
                    222:                free(sc->dc_srom, M_DEVBUF);
                    223:
                    224:        timeout_del(&sc->dc_tick_tmo);
                    225:
                    226:        ether_ifdetach(ifp);
                    227:        if_detach(ifp);
                    228:
                    229:        if (sc->sc_dhook != NULL)
                    230:                shutdownhook_disestablish(sc->sc_dhook);
                    231:        if (sc->sc_pwrhook != NULL)
                    232:                powerhook_disestablish(sc->sc_pwrhook);
                    233:
                    234:        return (0);
                    235: }
                    236:
                    237: int
                    238: dc_cardbus_detach(self, flags)
                    239:        struct device *self;
                    240:        int flags;
                    241: {
                    242:        struct dc_cardbus_softc *csc = (struct dc_cardbus_softc *)self;
                    243:        struct dc_softc *sc = &csc->sc_dc;
                    244:        struct cardbus_devfunc *ct = csc->sc_ct;
                    245:        int rv = 0;
                    246:
                    247:        rv = dc_detach(sc);
                    248:        if (rv)
                    249:                return (rv);
                    250:
                    251:        cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, sc->sc_ih);
                    252:
                    253:        /* unmap cardbus resources */
                    254:        Cardbus_mapreg_unmap(ct,
                    255:            csc->sc_actype == CARDBUS_IO_ENABLE ? PCI_CBIO : PCI_CBMEM,
                    256:            sc->dc_btag, sc->dc_bhandle, csc->sc_mapsize);
                    257:
                    258:        return (rv);
                    259: }
                    260:
                    261: void
                    262: dc_cardbus_setup(csc)
                    263:        struct dc_cardbus_softc *csc;
                    264: {
                    265:        cardbus_devfunc_t ct = csc->sc_ct;
                    266:        cardbus_chipset_tag_t cc = ct->ct_cc;
                    267:        cardbus_function_tag_t cf = ct->ct_cf;
                    268:        cardbusreg_t reg;
                    269:        int r;
                    270:
                    271:        /* wakeup the card if needed */
                    272:        reg = cardbus_conf_read(cc, cf, csc->sc_tag, PCI_CFDA);
                    273:        if (reg | (DC_CFDA_SUSPEND|DC_CFDA_STANDBY)) {
                    274:                cardbus_conf_write(cc, cf, csc->sc_tag, PCI_CFDA,
                    275:                    reg & ~(DC_CFDA_SUSPEND|DC_CFDA_STANDBY));
                    276:        }
                    277:
                    278:        if (cardbus_get_capability(cc, cf, csc->sc_tag, PCI_CAP_PWRMGMT, &r,
                    279:            0)) {
                    280:                r = cardbus_conf_read(cc, cf, csc->sc_tag, r + 4) & 3;
                    281:                if (r) {
                    282:                        printf("%s: awakening from state D%d\n",
                    283:                            csc->sc_dc.sc_dev.dv_xname, r);
                    284:                        cardbus_conf_write(cc, cf, csc->sc_tag, r + 4, 0);
                    285:                }
                    286:        }
                    287:
                    288:        (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_actype);
                    289:        (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
                    290:
                    291:        reg = cardbus_conf_read(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG);
                    292:        reg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
                    293:            PCI_COMMAND_MASTER_ENABLE;
                    294:        cardbus_conf_write(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg);
                    295:        reg = cardbus_conf_read(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG);
                    296: }

CVSweb