[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     ! 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