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

Annotation of sys/dev/pci/if_che.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_che.c,v 1.8 2007/05/30 05:11:53 reyk Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2007 Claudio Jeker <claudio@openbsd.org>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: #include "bpfilter.h"
        !            20:
        !            21: #include <sys/param.h>
        !            22: #include <sys/systm.h>
        !            23: #include <sys/sockio.h>
        !            24: #include <sys/mbuf.h>
        !            25: #include <sys/kernel.h>
        !            26: #include <sys/socket.h>
        !            27: #include <sys/malloc.h>
        !            28: #include <sys/device.h>
        !            29:
        !            30: #include <machine/bus.h>
        !            31:
        !            32: #include <dev/pci/pcireg.h>
        !            33: #include <dev/pci/pcivar.h>
        !            34: #include <dev/pci/pcidevs.h>
        !            35:
        !            36: #include <net/if.h>
        !            37: #include <net/if_dl.h>
        !            38: #include <net/if_media.h>
        !            39: #include <net/if_types.h>
        !            40:
        !            41: #if NBPFILTER > 0
        !            42: #include <net/bpf.h>
        !            43: #endif
        !            44:
        !            45: #include <netinet/in.h>
        !            46: #include <netinet/if_ether.h>
        !            47:
        !            48: #include <dev/mii/mii.h>
        !            49: #include <dev/mii/miivar.h>
        !            50:
        !            51: /* registers & defines */
        !            52:
        !            53: #define CHE_PCI_BAR            0x10
        !            54: #define CHE_PCI_CAP_ID_VPD     0x03
        !            55: #define CHE_PCI_VPD_DATA       0x4
        !            56: #define CHE_PCI_F_VPD_ADDR     0x80000000
        !            57: #define CHE_PCI_VPD_BASE       0xc00
        !            58:
        !            59: #define CHE_REG_T3DBG_GPIO_EN  0xd0
        !            60: #define CHE_T3DBG_F_GPIO11_OEN         0x08000000
        !            61: #define CHE_T3DBG_F_GPIO10_OEN         0x04000000
        !            62: #define CHE_T3DBG_F_GPIO9_OEN          0x02000000
        !            63: #define CHE_T3DBG_F_GPIO8_OEN          0x01000000
        !            64: #define CHE_T3DBG_F_GPIO7_OEN          0x00800000
        !            65: #define CHE_T3DBG_F_GPIO6_OEN          0x00400000
        !            66: #define CHE_T3DBG_F_GPIO5_OEN          0x00200000
        !            67: #define CHE_T3DBG_F_GPIO4_OEN          0x00100000
        !            68: #define CHE_T3DBG_F_GPIO3_OEN          0x00080000
        !            69: #define CHE_T3DBG_F_GPIO2_OEN          0x00040000
        !            70: #define CHE_T3DBG_F_GPIO1_OEN          0x00020000
        !            71: #define CHE_T3DBG_F_GPIO0_OEN          0x00010000
        !            72: #define CHE_T3DBG_F_GPIO11_OUT_VAL     0x00000800
        !            73: #define CHE_T3DBG_F_GPIO10_OUT_VAL     0x00000400
        !            74: #define CHE_T3DBG_F_GPIO9_OUT_VAL      0x00000200
        !            75: #define CHE_T3DBG_F_GPIO8_OUT_VAL      0x00000100
        !            76: #define CHE_T3DBG_F_GPIO7_OUT_VAL      0x00000080
        !            77: #define CHE_T3DBG_F_GPIO6_OUT_VAL      0x00000040
        !            78: #define CHE_T3DBG_F_GPIO5_OUT_VAL      0x00000020
        !            79: #define CHE_T3DBG_F_GPIO4_OUT_VAL      0x00000010
        !            80: #define CHE_T3DBG_F_GPIO3_OUT_VAL      0x00000008
        !            81: #define CHE_T3DBG_F_GPIO2_OUT_VAL      0x00000004
        !            82: #define CHE_T3DBG_F_GPIO1_OUT_VAL      0x00000002
        !            83: #define CHE_T3DBG_F_GPIO0_OUT_VAL      0x00000001
        !            84: #define CHE_REG_I2C_CFG                0x6a0
        !            85: #define CHE_I2C_CLKDIV(_x)     ((_x) && 0xfff)
        !            86: #define CHE_REG_MI1_CFG                0x6b0
        !            87: #define CHE_REG_MI1_ADDR       0x6b4
        !            88: #define CHE_REG_MI1_DATA       0x6b8
        !            89: #define CHE_REG_MI1_OP         0x6bc
        !            90: #define CHE_MI1_F_BUSY         (1U << 31)
        !            91: #define CHE_MI1_F_ST           0x8
        !            92: #define CHE_MI1_F_PREEN                0x4
        !            93: #define CHE_MI1_F_MDIINV       0x2
        !            94: #define CHE_MI1_F_MDIEN                0x1
        !            95: #define CHE_MI1_CLKDIV(_x)     ((_x) << 5)
        !            96: #define CHE_MI1_PHYADDR(_x)    ((_x) << 5)
        !            97: #define CHE_MI1_OP(_x)         ((_x) & 0x3)
        !            98: #define CHE_REG_PL_RST         0x6f0
        !            99: #define CHE_RST_F_CRSTWRM      0x2
        !           100: #define CHE_RST_F_CRSTWRMMODE  0x1
        !           101: #define CHE_REG_PL_REV         0x6f4
        !           102: #define CHE_REG_XGM_PORT_CFG   0x8b8
        !           103: #define CHE_XGMAC0_0_BASE_ADDR 0x800
        !           104: #define CHE_XGMAC0_1_BASE_ADDR 0xa00
        !           105: #define CHE_XGM_REG(_r, _i)    \
        !           106:     ((_r) + (_i) * (CHE_XGMAC0_1_BASE_ADDR - CHE_XGMAC0_0_BASE_ADDR))
        !           107: #define CHE_XGM_PORTSPEED(_x)  ((_x) << 1)
        !           108: #define CHE_XGM_F_ENRGMII      0x1
        !           109: #define CHE_XGM_F_CLKDIVRESET  0x8
        !           110:
        !           111: /* serial flash and firmware definitions */
        !           112: #define CHE_REG_SF_DATA                0x6d8
        !           113: #define CHE_REG_SF_OP          0x6dc
        !           114: #define CHE_SF_SEC_SIZE                (64 * 1024)     /* serial flash sector size */
        !           115: #define CHE_SF_SIZE            (8 * CHE_SF_SEC_SIZE)   /* serial flash size */
        !           116: #define CHE_SF_PROG_PAGE       2
        !           117: #define CHE_SF_WR_DISABLE      4
        !           118: #define CHE_SF_RD_STATUS       5       /* read status register */
        !           119: #define CHE_SF_WR_ENABLE       6
        !           120: #define CHE_SF_RD_DATA         11
        !           121: #define CHE_SF_SEC_ERASE       216
        !           122: #define CHE_SF_F_BUSY          (1U << 31)
        !           123: #define CHE_SF_F_OP            0x1
        !           124: #define CHE_SF_CONT(_x)                ((_x) << 3)
        !           125: #define CHE_SF_BYTECNT_MASK    0x3
        !           126: #define CHE_SF_BYTECNT(_x)     (((_x) & CHE_SF_BYTECNT_MASK) << 1)
        !           127:
        !           128: #define FW_FLASH_BOOT_ADDR     0x70000 /* start address of FW in flash */
        !           129: #define FW_VERS_ADDR           0x77ffc /* flash address holding FW version */
        !           130: #define FW_VERS_TYPE_N3                0
        !           131: #define FW_VERS_TYPE_T3                1
        !           132: #define FW_VERS_TYPE(_x)       (((_x) >> 28) & 0xf)
        !           133: #define FW_VERS_MAJOR(_x)      (((_x) >> 16) & 0xfff)
        !           134: #define FW_VERS_MINOR(_x)      (((_x) >> 8) & 0xff)
        !           135: #define FW_VERS_MICRO(_x)      ((_x) & 0xff)
        !           136:
        !           137: /* Partial EEPROM Vital Product Data structure. */
        !           138: struct che_vpd {
        !           139:        u_int8_t        id_tag;
        !           140:        u_int8_t        id_len[2];
        !           141:        u_int8_t        id_data[16];
        !           142:        u_int8_t        vpdr_tag;
        !           143:        u_int8_t        vpdr_len[2];
        !           144:        u_int8_t        pn_name[2];             /* part number */
        !           145:        u_int8_t        pn_len;
        !           146:        u_int8_t        pn_data[16];
        !           147:        u_int8_t        ec_name[2];             /* EC level */
        !           148:        u_int8_t        ec_len;
        !           149:        u_int8_t        ec_data[16];
        !           150:        u_int8_t        sn_name[2];             /* serial number */
        !           151:        u_int8_t        sn_len;
        !           152:        u_int8_t        sn_data[16];
        !           153:        u_int8_t        na_name[2];             /* MAC address base */
        !           154:        u_int8_t        na_len;
        !           155:        u_int8_t        na_data[12];
        !           156:        u_int8_t        cclk_name[2];           /* core clock */
        !           157:        u_int8_t        cclk_len;
        !           158:        u_int8_t        cclk_data[6];
        !           159:        u_int8_t        mclk_name[2];           /* mem clock */
        !           160:        u_int8_t        mclk_len;
        !           161:        u_int8_t        mclk_data[6];
        !           162:        u_int8_t        uclk_name[2];           /* uP clock */
        !           163:        u_int8_t        uclk_len;
        !           164:        u_int8_t        uclk_data[6];
        !           165:        u_int8_t        mdc_name[2];            /* MDIO clock */
        !           166:        u_int8_t        mdc_len;
        !           167:        u_int8_t        mdc_data[6];
        !           168:        u_int8_t        mt_name[2];             /* mem timing */
        !           169:        u_int8_t        mt_len;
        !           170:        u_int8_t        mt_data[2];
        !           171:        u_int8_t        xaui0cfg_name[2];       /* XAUI0 config */
        !           172:        u_int8_t        xaui0cfg_len;
        !           173:        u_int8_t        xaui0cfg_data[6];
        !           174:        u_int8_t        xaui1cfg_name[2];       /* XAUI1 config */
        !           175:        u_int8_t        xaui1cfg_len;
        !           176:        u_int8_t        xaui1cfg_data[6];
        !           177:        u_int8_t        port0_name[2];          /* PHY0 */
        !           178:        u_int8_t        port0_len;
        !           179:        u_int8_t        port0_data[2];
        !           180:        u_int8_t        port1_name[2];          /* PHY1 */
        !           181:        u_int8_t        port1_len;
        !           182:        u_int8_t        port1_data[2];
        !           183:        u_int8_t        port2_name[2];          /* PHY2 */
        !           184:        u_int8_t        port2_len;
        !           185:        u_int8_t        port2_data[2];
        !           186:        u_int8_t        port3_name[2];          /* PHY3 */
        !           187:        u_int8_t        port3_len;
        !           188:        u_int8_t        port3_data[2];
        !           189:        u_int8_t        rv_name[2];             /* csum */
        !           190:        u_int8_t        rv_len;
        !           191:        u_int8_t        rv_data[1];
        !           192:        u_int8_t        pad[4];                 /* for multiple-of-4 sizing */
        !           193: } __packed;
        !           194:
        !           195:
        !           196: #define DEVNAME(_sc)   ((_sc)->sc_dev.dv_xname)
        !           197:
        !           198: /* the pci controller */
        !           199:
        !           200: struct cheg_softc {
        !           201:        struct device           sc_dev;
        !           202:
        !           203:        bus_dma_tag_t           sc_dmat;
        !           204:
        !           205:        bus_space_tag_t         sc_memt;
        !           206:        bus_space_handle_t      sc_memh;
        !           207:        bus_size_t              sc_mems;
        !           208:
        !           209:        u_int32_t               sc_rev;         /* card revision */
        !           210:        u_int32_t               sc_cclk;        /* core clock */
        !           211:        u_int32_t               sc_mdc;         /* mdio clock */
        !           212:
        !           213:        pci_vendor_id_t         sc_product;
        !           214: };
        !           215:
        !           216: int            cheg_match(struct device *, void *, void *);
        !           217: void           cheg_attach(struct device *, struct device *, void *);
        !           218: int            cheg_print(void *, const char *);
        !           219:
        !           220: struct cfattach cheg_ca = {
        !           221:        sizeof(struct cheg_softc),
        !           222:        cheg_match,
        !           223:        cheg_attach
        !           224: };
        !           225:
        !           226: struct cfdriver cheg_cd = {
        !           227:        NULL, "cheg", DV_DULL
        !           228: };
        !           229:
        !           230: /* glue between the controller and the port */
        !           231:
        !           232: struct che_attach_args {
        !           233:        struct pci_attach_args  *caa_pa;
        !           234:        pci_intr_handle_t       caa_ih;
        !           235:        int                     caa_port;
        !           236:        u_int8_t                caa_lladdr[ETHER_ADDR_LEN];
        !           237: };
        !           238:
        !           239: /* che itself */
        !           240:
        !           241: struct che_softc {
        !           242:        struct device           sc_dev;
        !           243:        struct arpcom           sc_ac;
        !           244:        struct mii_data         sc_mii;
        !           245:
        !           246:        struct cheg_softc       *sc_cheg;
        !           247:        void                    *sc_ih;
        !           248:        int                     sc_port;
        !           249: };
        !           250:
        !           251: int            che_match(struct device *, void *, void *);
        !           252: void           che_attach(struct device *, struct device *, void *);
        !           253:
        !           254: struct cfattach che_ca = {
        !           255:        sizeof(struct che_softc),
        !           256:        che_match,
        !           257:        che_attach
        !           258: };
        !           259:
        !           260: struct cfdriver che_cd = {
        !           261:        NULL, "che", DV_IFNET
        !           262: };
        !           263:
        !           264: int            che_write_flash_reg(struct cheg_softc *, size_t, int,
        !           265:                    u_int32_t);
        !           266: int            che_read_flash_reg(struct cheg_softc *, size_t, int,
        !           267:                    u_int32_t *);
        !           268: int            che_read_flash_multi4(struct cheg_softc *, u_int, u_int32_t *,
        !           269:                    size_t);
        !           270: int            che_read_eeprom(struct cheg_softc *, struct pci_attach_args *,
        !           271:                    pcireg_t, pcireg_t *);
        !           272: int            che_get_vpd(struct cheg_softc *, struct pci_attach_args *,
        !           273:                    void *, size_t);
        !           274: void           che_conv_lladdr(char *, u_int8_t *);
        !           275: u_int32_t      che_conv_num(char *, size_t);
        !           276: void           che_reset(struct cheg_softc *);
        !           277: int            che_ioctl(struct ifnet *, u_long, caddr_t);
        !           278: void           che_watchdog(struct ifnet *);
        !           279: void           che_start(struct ifnet *);
        !           280:
        !           281: /* ifmedia & mii helper functions */
        !           282: int    che_ifmedia_upd(struct ifnet *);
        !           283: void   che_ifmedia_sts(struct ifnet *, struct ifmediareq *);
        !           284: int    che_miibus_readreg(struct device *, int, int);
        !           285: void   che_miibus_writereg(struct device *, int, int, int);
        !           286: int    che_miibus_ind_readreg(struct device *, int, int);
        !           287: void   che_miibus_ind_writereg(struct device *, int, int, int);
        !           288: void   che_miibus_statchg(struct device *);
        !           289:
        !           290: /* bus_space wrappers */
        !           291: u_int32_t      che_read(struct cheg_softc *, bus_size_t);
        !           292: void           che_write(struct cheg_softc *, bus_size_t, u_int32_t);
        !           293: int            che_waitfor(struct cheg_softc *, bus_size_t, u_int32_t, int);
        !           294:
        !           295: /* HW low-level functions */
        !           296: void   che_hw_init(struct cheg_softc *);
        !           297:
        !           298: /* cheg */
        !           299: struct cheg_device {
        !           300:        pci_vendor_id_t cd_vendor;
        !           301:        pci_vendor_id_t cd_product;
        !           302:        u_int           cd_nports;
        !           303: };
        !           304:
        !           305: const struct cheg_device *cheg_lookup(struct pci_attach_args *);
        !           306:
        !           307: const struct cheg_device che_devices[] = {
        !           308:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_PE9000, 2 },
        !           309:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T302E, 2 },
        !           310:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T302X, 2 },
        !           311:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T310E, 1 },
        !           312:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T310X, 1 },
        !           313:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T320E, 2 },
        !           314:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T320X, 2 },
        !           315:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T3B02, 2 },
        !           316:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T3B10, 1 },
        !           317:         { PCI_VENDOR_CHELSIO, PCI_PRODUCT_CHELSIO_T3B20, 2 }
        !           318: };
        !           319:
        !           320: const struct cheg_device *
        !           321: cheg_lookup(struct pci_attach_args *pa)
        !           322: {
        !           323:        int i;
        !           324:        const struct cheg_device *cd;
        !           325:
        !           326:        for (i = 0; i < sizeof(che_devices)/sizeof(che_devices[0]); i++) {
        !           327:                cd = &che_devices[i];
        !           328:                if (cd->cd_vendor == PCI_VENDOR(pa->pa_id) &&
        !           329:                    cd->cd_product == PCI_PRODUCT(pa->pa_id))
        !           330:                        return (cd);
        !           331:        }
        !           332:
        !           333:        return (NULL);
        !           334: }
        !           335:
        !           336: int
        !           337: cheg_match(struct device *parent, void *match, void *aux)
        !           338: {
        !           339:        struct pci_attach_args *pa = aux;
        !           340:
        !           341:        if (cheg_lookup(pa) != NULL)
        !           342:                return (1);
        !           343:
        !           344:        return (0);
        !           345: }
        !           346:
        !           347: void
        !           348: cheg_attach(struct device *parent, struct device *self, void *aux)
        !           349: {
        !           350:        struct cheg_softc *sc = (struct cheg_softc *)self;
        !           351:        struct pci_attach_args *pa = aux;
        !           352:        const struct cheg_device *cd;
        !           353:        struct che_attach_args caa;
        !           354:        struct che_vpd vpd;
        !           355:        pcireg_t memtype;
        !           356:        u_int32_t vers;
        !           357:        u_int i;
        !           358:
        !           359:        bzero(&caa, sizeof(caa));
        !           360:        cd = cheg_lookup(pa);
        !           361:
        !           362:        sc->sc_dmat = pa->pa_dmat;
        !           363:
        !           364:        memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, CHE_PCI_BAR);
        !           365:        if (pci_mapreg_map(pa, CHE_PCI_BAR, memtype, 0, &sc->sc_memt,
        !           366:            &sc->sc_memh, NULL, &sc->sc_mems, 0) != 0) {
        !           367:                printf(": unable to map host registers\n");
        !           368:                return;
        !           369:        }
        !           370:
        !           371:        if (pci_intr_map(pa, &caa.caa_ih) != 0) {
        !           372:                printf(": unable to map interrupt\n");
        !           373:                goto unmap;
        !           374:        }
        !           375:
        !           376:        sc->sc_rev = che_read(sc, CHE_REG_PL_REV);
        !           377:
        !           378:        /* reset the beast */
        !           379:        che_reset(sc);
        !           380:
        !           381:        if (che_read_flash_multi4(sc, FW_VERS_ADDR, &vers, 1) != 0) {
        !           382:                printf(": unable to read flash version\n");
        !           383:                goto unmap;
        !           384:        }
        !           385:
        !           386:        if (che_get_vpd(sc, pa, &vpd, sizeof(vpd)/sizeof(u_int32_t)) != 0) {
        !           387:                printf(": unable to get vital product data\n");
        !           388:                goto unmap;
        !           389:        }
        !           390:
        !           391:        printf(": %s revision %d firmware %s-%d.%d.%d\n",
        !           392:            pci_intr_string(pa->pa_pc, caa.caa_ih), sc->sc_rev,
        !           393:            FW_VERS_TYPE(vers) ? "T" : "N",
        !           394:            FW_VERS_MAJOR(vers), FW_VERS_MINOR(vers), FW_VERS_MICRO(vers));
        !           395:
        !           396:        sc->sc_product = PCI_PRODUCT(pa->pa_id);
        !           397:        sc->sc_cclk = che_conv_num(vpd.cclk_data, sizeof(vpd.cclk_data));
        !           398:        sc->sc_mdc = che_conv_num(vpd.mdc_data, sizeof(vpd.mdc_data));
        !           399:
        !           400:        che_hw_init(sc);
        !           401:
        !           402:        caa.caa_pa = pa;
        !           403:        che_conv_lladdr(vpd.na_data, caa.caa_lladdr);
        !           404:
        !           405:        for (i = 0; i < cd->cd_nports; i++) {
        !           406:                caa.caa_port = i;
        !           407:
        !           408:                config_found(self, &caa, cheg_print);
        !           409:
        !           410:                /*
        !           411:                 * The VPD EEPROM stores only the base Ethernet address for the
        !           412:                 * card. The last octet is increased by one for every additional
        !           413:                 * port.
        !           414:                 */
        !           415:                caa.caa_lladdr[5] += 1;
        !           416:        }
        !           417:
        !           418:        return;
        !           419:
        !           420: unmap:
        !           421:        bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
        !           422:        sc->sc_mems = 0;
        !           423: }
        !           424:
        !           425: int
        !           426: cheg_print(void *aux, const char *pnp)
        !           427: {
        !           428:        struct che_attach_args *caa = aux;
        !           429:
        !           430:        if (pnp != NULL)
        !           431:                printf("\"%s\" at %s", che_cd.cd_name, pnp);
        !           432:
        !           433:        printf(" port %d", caa->caa_port);
        !           434:
        !           435:        return (UNCONF);
        !           436: }
        !           437:
        !           438: int
        !           439: che_match(struct device *parent, void *match, void *aux)
        !           440: {
        !           441:        return (1);
        !           442: }
        !           443:
        !           444: void
        !           445: che_attach(struct device *parent, struct device *self, void *aux)
        !           446: {
        !           447:        struct cheg_softc *gsc = (struct cheg_softc *)parent;
        !           448:        struct che_softc *sc = (struct che_softc *)self;
        !           449:        struct che_attach_args *caa = aux;
        !           450:        struct ifnet *ifp;
        !           451:
        !           452:        sc->sc_cheg = gsc;
        !           453:
        !           454:        sc->sc_port = caa->caa_port;
        !           455:        bcopy(caa->caa_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
        !           456:
        !           457:        printf(": address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr));
        !           458:
        !           459:        ifp = &sc->sc_ac.ac_if;
        !           460:        ifp->if_softc = sc;
        !           461:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           462:        ifp->if_ioctl = che_ioctl;
        !           463:        ifp->if_start = che_start;
        !           464:        ifp->if_watchdog = che_watchdog;
        !           465:        ifp->if_hardmtu = MCLBYTES - ETHER_HDR_LEN - ETHER_CRC_LEN; /* XXX */
        !           466:        strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
        !           467:        IFQ_SET_MAXLEN(&ifp->if_snd, 400);
        !           468:        IFQ_SET_READY(&ifp->if_snd);
        !           469:
        !           470:        ifmedia_init(&sc->sc_mii.mii_media, 0,
        !           471:            che_ifmedia_upd, che_ifmedia_sts);
        !           472:
        !           473:        sc->sc_mii.mii_ifp = ifp;
        !           474:        sc->sc_mii.mii_readreg = che_miibus_ind_readreg;
        !           475:        sc->sc_mii.mii_writereg = che_miibus_ind_writereg;
        !           476:        sc->sc_mii.mii_statchg = che_miibus_statchg;
        !           477:
        !           478:        mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
        !           479:            MII_OFFSET_ANY, MIIF_DOPAUSE | MIIF_HAVEFIBER);
        !           480:
        !           481:        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
        !           482:                printf("%s: no PHY found!\n", sc->sc_dev.dv_xname);
        !           483:                ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL,
        !           484:                    0, NULL);
        !           485:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL);
        !           486:        } else
        !           487:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
        !           488:
        !           489:        if_attach(ifp);
        !           490:        ether_ifattach(ifp);
        !           491:
        !           492:        return;
        !           493: }
        !           494:
        !           495: int
        !           496: che_write_flash_reg(struct cheg_softc *sc, size_t bcnt, int cont, u_int32_t v)
        !           497: {
        !           498:        if (che_read(sc, CHE_REG_SF_OP) & CHE_SF_F_BUSY)
        !           499:                return (EBUSY);
        !           500:
        !           501:        che_write(sc, CHE_REG_SF_DATA, v);
        !           502:        che_write(sc, CHE_REG_SF_OP, CHE_SF_CONT(cont) |
        !           503:            CHE_SF_BYTECNT(bcnt - 1) | CHE_SF_F_OP);
        !           504:
        !           505:        return (che_waitfor(sc, CHE_REG_SF_OP, CHE_SF_F_BUSY, 5));
        !           506: }
        !           507:
        !           508: int
        !           509: che_read_flash_reg(struct cheg_softc *sc, size_t bcnt, int cont, u_int32_t *vp)
        !           510: {
        !           511:        if (che_read(sc, CHE_REG_SF_OP) & CHE_SF_F_BUSY)
        !           512:                return (EBUSY);
        !           513:
        !           514:        che_write(sc, CHE_REG_SF_OP, CHE_SF_CONT(cont) |
        !           515:            CHE_SF_BYTECNT(bcnt - 1));
        !           516:
        !           517:        if (che_waitfor(sc, CHE_REG_SF_OP, CHE_SF_F_BUSY, 5))
        !           518:                return (EAGAIN);
        !           519:
        !           520:        *vp = che_read(sc, CHE_REG_SF_DATA);
        !           521:        return (0);
        !           522: }
        !           523:
        !           524: int
        !           525: che_read_flash_multi4(struct cheg_softc *sc, u_int addr, u_int32_t *datap,
        !           526:        size_t count)
        !           527: {
        !           528:        int rv;
        !           529:
        !           530:        if (addr + count * sizeof(u_int32_t) > CHE_SF_SIZE || (addr & 3))
        !           531:                panic("%s: che_read_flash_multi4 bad params\n", DEVNAME(sc));
        !           532:
        !           533:        addr = swap32(addr) | CHE_SF_RD_DATA;
        !           534:
        !           535:        if ((rv = che_write_flash_reg(sc, 4, 1, addr)))
        !           536:                return (rv);
        !           537:        if ((rv = che_read_flash_reg(sc, 1, 1, datap)))
        !           538:                return (rv);
        !           539:
        !           540:        while (count) {
        !           541:                if ((rv = che_read_flash_reg(sc, 4, count > 1, datap)))
        !           542:                        return (rv);
        !           543:                count--;
        !           544:                datap++;
        !           545:        }
        !           546:        return (0);
        !           547: }
        !           548:
        !           549: int
        !           550: che_read_eeprom(struct cheg_softc *sc, struct pci_attach_args *pa,
        !           551:     pcireg_t addr, pcireg_t *dp)
        !           552: {
        !           553:        pcireg_t rv, base;
        !           554:        int i = 4;
        !           555:
        !           556:        if (!pci_get_capability(pa->pa_pc, pa->pa_tag, CHE_PCI_CAP_ID_VPD,
        !           557:            &base, NULL)) {
        !           558:                printf("%s: VPD EEPROM not found\n",
        !           559:                    DEVNAME(sc), addr);
        !           560:                return EIO;
        !           561:        }
        !           562:
        !           563:        addr <<= 16;
        !           564:        pci_conf_write(pa->pa_pc, pa->pa_tag, base, addr);
        !           565:
        !           566:        while(i--) {
        !           567:                delay(10);
        !           568:                rv = pci_conf_read(pa->pa_pc, pa->pa_tag, base);
        !           569:                if (rv & CHE_PCI_F_VPD_ADDR)
        !           570:                        break;
        !           571:        }
        !           572:        if (!(rv & CHE_PCI_F_VPD_ADDR)) {
        !           573:                printf("%s: reading EEPROM address 0x%x failed\n",
        !           574:                    DEVNAME(sc), addr);
        !           575:                return EIO;
        !           576:        }
        !           577:
        !           578:        *dp = pci_conf_read(pa->pa_pc, pa->pa_tag, base + CHE_PCI_VPD_DATA);
        !           579:        return (0);
        !           580: }
        !           581:
        !           582: int
        !           583: che_get_vpd(struct cheg_softc *sc, struct pci_attach_args *pa,
        !           584:     void *vpd, size_t dwords)
        !           585: {
        !           586:        pcireg_t dw0, *dw = vpd;
        !           587:        int i;
        !           588:        u_int16_t addr;
        !           589:
        !           590:        /*
        !           591:         * Card information is normally at CHE_PCI_VPD_BASE but some early
        !           592:         * cards had it at 0.
        !           593:         */
        !           594:        if (che_read_eeprom(sc, pa, CHE_PCI_VPD_BASE, &dw0))
        !           595:                return (1);
        !           596:
        !           597:        /* we compare the id_tag which is least significant byte */
        !           598:        addr = ((dw0 & 0xff) == 0x82) ? CHE_PCI_VPD_BASE : 0;
        !           599:
        !           600:        for (i = 0; i < dwords; i++) {
        !           601:                if (che_read_eeprom(sc, pa, addr + i * 4, &dw[i]))
        !           602:                        return (1);
        !           603:        }
        !           604:
        !           605:        return (0);
        !           606: }
        !           607:
        !           608: /*
        !           609:  * VPD mac addr is stored as ASCII string so we need to convert it to a
        !           610:  * sane representation form.
        !           611:  */
        !           612: void
        !           613: che_conv_lladdr(char *mac, u_int8_t *lladdr)
        !           614: {
        !           615:        int i;
        !           616:        u_int8_t digit;
        !           617:
        !           618:        bzero(lladdr, ETHER_ADDR_LEN);
        !           619:
        !           620:        for (i = 0; i < ETHER_ADDR_LEN * 2; i++) {
        !           621:                if (mac[i] >= '0' && mac[i] <= '9')
        !           622:                        digit = mac[i] - '0';
        !           623:                else if (mac[i] >= 'A' && mac[i] <= 'F')
        !           624:                        digit = mac[i] - 'A' + 10;
        !           625:                else if (mac[i] >= 'a' && mac[i] <= 'f')
        !           626:                        digit = mac[i] - 'a' + 10;
        !           627:
        !           628:                if ((i & 1) == 0)
        !           629:                        digit <<= 4;
        !           630:
        !           631:                lladdr[i/2] |= digit;
        !           632:        }
        !           633: }
        !           634:
        !           635: u_int32_t
        !           636: che_conv_num(char *num, size_t len)
        !           637: {
        !           638:        size_t i;
        !           639:        u_int32_t n = 0;
        !           640:
        !           641:        for (i = 0; i < len; i++) {
        !           642:                if (num[i] >= '0' && num[i] <= '9')
        !           643:                        n = 10 * n + (num[i] - '0');
        !           644:                else
        !           645:                        break;
        !           646:        }
        !           647:        return (n);
        !           648: }
        !           649:
        !           650: void
        !           651: che_reset(struct cheg_softc *sc)
        !           652: {
        !           653:        che_write(sc, CHE_REG_PL_RST, CHE_RST_F_CRSTWRM |
        !           654:            CHE_RST_F_CRSTWRMMODE);
        !           655:
        !           656:        /* Give the card some time to boot */
        !           657:        delay(500);
        !           658: }
        !           659:
        !           660: int
        !           661: che_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
        !           662: {
        !           663:        return (EIO);
        !           664: }
        !           665:
        !           666: void
        !           667: che_watchdog(struct ifnet *ifp)
        !           668: {
        !           669:        /* XXX */
        !           670: }
        !           671:
        !           672: void
        !           673: che_start(struct ifnet *ifp)
        !           674: {
        !           675:        /* XXX */
        !           676: }
        !           677:
        !           678: int
        !           679: che_ifmedia_upd(struct ifnet *ifp)
        !           680: {
        !           681:        struct che_softc *sc = ifp->if_softc;
        !           682:
        !           683:        mii_mediachg(&sc->sc_mii);
        !           684:        return (0);
        !           685: }
        !           686:
        !           687: void
        !           688: che_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
        !           689: {
        !           690:        struct che_softc *sc = ifp->if_softc;
        !           691:
        !           692:        mii_pollstat(&sc->sc_mii);
        !           693:        ifmr->ifm_active = sc->sc_mii.mii_media_active;
        !           694:        ifmr->ifm_status = sc->sc_mii.mii_media_status;
        !           695: }
        !           696:
        !           697: int
        !           698: che_miibus_readreg(struct device *dev, int phy, int reg)
        !           699: {
        !           700:        struct che_softc *sc = (struct che_softc *)dev;
        !           701:        u_int32_t addr = CHE_MI1_PHYADDR(phy) | reg;
        !           702:
        !           703:        che_write(sc->sc_cheg, CHE_REG_MI1_ADDR, addr);
        !           704:        che_write(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_OP(2));
        !           705:
        !           706:        if (che_waitfor(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_F_BUSY, 20))
        !           707:                return (0);
        !           708:
        !           709:        return ((int)che_read(sc->sc_cheg, CHE_REG_MI1_DATA));
        !           710: }
        !           711:
        !           712: void
        !           713: che_miibus_writereg(struct device *dev, int phy, int reg, int val)
        !           714: {
        !           715:        struct che_softc *sc = (struct che_softc *)dev;
        !           716:        u_int32_t addr = CHE_MI1_PHYADDR(phy) | reg;
        !           717:
        !           718:        che_write(sc->sc_cheg, CHE_REG_MI1_ADDR, addr);
        !           719:        che_write(sc->sc_cheg, CHE_REG_MI1_DATA, val);
        !           720:        che_write(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_OP(1));
        !           721:        che_waitfor(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_F_BUSY, 20);
        !           722: }
        !           723:
        !           724: int
        !           725: che_miibus_ind_readreg(struct device *dev, int phy, int reg)
        !           726: {
        !           727:        struct che_softc *sc = (struct che_softc *)dev;
        !           728:
        !           729:        che_write(sc->sc_cheg, CHE_REG_MI1_ADDR, CHE_MI1_PHYADDR(phy));
        !           730:        che_write(sc->sc_cheg, CHE_REG_MI1_DATA, reg);
        !           731:        che_write(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_OP(0));
        !           732:
        !           733:        if (che_waitfor(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_F_BUSY, 20))
        !           734:                return (0);
        !           735:
        !           736:        che_write(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_OP(3));
        !           737:
        !           738:        if (che_waitfor(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_F_BUSY, 20))
        !           739:                return (0);
        !           740:
        !           741:        return ((int)che_read(sc->sc_cheg, CHE_REG_MI1_DATA));
        !           742: }
        !           743:
        !           744: void
        !           745: che_miibus_ind_writereg(struct device *dev, int phy, int reg, int val)
        !           746: {
        !           747:        struct che_softc *sc = (struct che_softc *)dev;
        !           748:
        !           749:        che_write(sc->sc_cheg, CHE_REG_MI1_ADDR, CHE_MI1_PHYADDR(phy));
        !           750:        che_write(sc->sc_cheg, CHE_REG_MI1_DATA, reg);
        !           751:        che_write(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_OP(0));
        !           752:
        !           753:        if (che_waitfor(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_F_BUSY, 20))
        !           754:                return;
        !           755:
        !           756:        che_write(sc->sc_cheg, CHE_REG_MI1_DATA, val);
        !           757:        che_write(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_OP(1));
        !           758:
        !           759:        che_waitfor(sc->sc_cheg, CHE_REG_MI1_OP, CHE_MI1_F_BUSY, 20);
        !           760: }
        !           761:
        !           762: void
        !           763: che_miibus_statchg(struct device *dev)
        !           764: {
        !           765:        struct che_softc *sc = (struct che_softc *)dev;
        !           766:        //struct mii_data *mii = &sc->sc_mii;
        !           767:
        !           768:        printf("%s: che_miibus_statchg\n", DEVNAME(sc));
        !           769: }
        !           770:
        !           771: u_int32_t
        !           772: che_read(struct cheg_softc *sc, bus_size_t r)
        !           773: {
        !           774:         bus_space_barrier(sc->sc_memt, sc->sc_memh, r, 4,
        !           775:            BUS_SPACE_BARRIER_READ);
        !           776:        return (bus_space_read_4(sc->sc_memt, sc->sc_memh, r));
        !           777: }
        !           778:
        !           779: void
        !           780: che_write(struct cheg_softc *sc, bus_size_t r, u_int32_t v)
        !           781: {
        !           782:        bus_space_write_4(sc->sc_memt, sc->sc_memh, r, v);
        !           783:         bus_space_barrier(sc->sc_memt, sc->sc_memh, r, 4,
        !           784:            BUS_SPACE_BARRIER_WRITE);
        !           785: }
        !           786:
        !           787: int
        !           788: che_waitfor(struct cheg_softc *sc, bus_size_t r, u_int32_t mask, int tries)
        !           789: {
        !           790:        u_int32_t v;
        !           791:        int i;
        !           792:
        !           793:        for (i = 0; i < tries; i++) {
        !           794:                v = che_read(sc, r);
        !           795:                if ((v & mask) == 0)
        !           796:                        return (0);
        !           797:                delay(10);
        !           798:        }
        !           799:        return (EAGAIN);
        !           800: }
        !           801:
        !           802: void
        !           803: che_hw_init(struct cheg_softc *sc)
        !           804: {
        !           805:        u_int32_t       mi1_reg;
        !           806:        u_int32_t       i2c_reg;
        !           807:        u_int32_t       gpio_reg;
        !           808:        u_int32_t       port_reg;
        !           809:
        !           810:        mi1_reg = CHE_MI1_F_PREEN |
        !           811:            CHE_MI1_CLKDIV(sc->sc_cclk / (2 * sc->sc_mdc) - 1);
        !           812:
        !           813:        i2c_reg = CHE_I2C_CLKDIV(sc->sc_cclk / 80 - 1); /* 80KHz */
        !           814:
        !           815:        gpio_reg =  CHE_T3DBG_F_GPIO0_OEN | CHE_T3DBG_F_GPIO0_OUT_VAL;
        !           816:
        !           817:        switch (sc->sc_product) {
        !           818:        case PCI_PRODUCT_CHELSIO_PE9000:
        !           819:                gpio_reg |= CHE_T3DBG_F_GPIO2_OEN | CHE_T3DBG_F_GPIO2_OUT_VAL |
        !           820:                    CHE_T3DBG_F_GPIO4_OEN | CHE_T3DBG_F_GPIO4_OUT_VAL;
        !           821:                port_reg = CHE_XGM_PORTSPEED(2);
        !           822:                break;
        !           823:        case PCI_PRODUCT_CHELSIO_T302E:
        !           824:        case PCI_PRODUCT_CHELSIO_T302X:
        !           825:        case PCI_PRODUCT_CHELSIO_T3B02:
        !           826:                gpio_reg |= CHE_T3DBG_F_GPIO2_OEN | CHE_T3DBG_F_GPIO2_OUT_VAL |
        !           827:                    CHE_T3DBG_F_GPIO4_OEN | CHE_T3DBG_F_GPIO4_OUT_VAL;
        !           828:                port_reg = CHE_XGM_PORTSPEED(2);
        !           829:                break;
        !           830:        case PCI_PRODUCT_CHELSIO_T310E:
        !           831:        case PCI_PRODUCT_CHELSIO_T310X:
        !           832:        case PCI_PRODUCT_CHELSIO_T3B10:
        !           833:                mi1_reg |= CHE_MI1_F_ST;
        !           834:                gpio_reg |= CHE_T3DBG_F_GPIO1_OEN | CHE_T3DBG_F_GPIO1_OUT_VAL |
        !           835:                    CHE_T3DBG_F_GPIO6_OEN | CHE_T3DBG_F_GPIO6_OUT_VAL |
        !           836:                    CHE_T3DBG_F_GPIO7_OEN |
        !           837:                    CHE_T3DBG_F_GPIO10_OEN | CHE_T3DBG_F_GPIO10_OUT_VAL;
        !           838:                port_reg = CHE_XGM_PORTSPEED(3);
        !           839:                port_reg |= CHE_XGM_F_ENRGMII;
        !           840:                break;
        !           841:        case PCI_PRODUCT_CHELSIO_T320X:
        !           842:        case PCI_PRODUCT_CHELSIO_T320E:
        !           843:        case PCI_PRODUCT_CHELSIO_T3B20:
        !           844:                mi1_reg |= CHE_MI1_F_ST;
        !           845:                gpio_reg |= CHE_T3DBG_F_GPIO1_OEN | CHE_T3DBG_F_GPIO1_OUT_VAL |
        !           846:                    CHE_T3DBG_F_GPIO2_OEN |
        !           847:                    CHE_T3DBG_F_GPIO4_OEN |
        !           848:                    CHE_T3DBG_F_GPIO5_OEN | CHE_T3DBG_F_GPIO5_OUT_VAL |
        !           849:                    CHE_T3DBG_F_GPIO6_OEN | CHE_T3DBG_F_GPIO6_OUT_VAL |
        !           850:                    CHE_T3DBG_F_GPIO7_OEN |
        !           851:                    CHE_T3DBG_F_GPIO10_OEN | CHE_T3DBG_F_GPIO10_OUT_VAL |
        !           852:                    CHE_T3DBG_F_GPIO11_OEN;
        !           853:                port_reg = CHE_XGM_PORTSPEED(3);
        !           854:                port_reg |= CHE_XGM_F_ENRGMII;
        !           855:                break;
        !           856:        }
        !           857:
        !           858:        if (sc->sc_rev == 0)
        !           859:                port_reg |= CHE_XGM_F_ENRGMII;
        !           860:
        !           861:        /* write all registers */
        !           862:        che_write(sc, CHE_REG_MI1_CFG, mi1_reg);
        !           863:        che_write(sc, CHE_REG_I2C_CFG, i2c_reg);
        !           864:        che_write(sc, CHE_REG_T3DBG_GPIO_EN, gpio_reg);
        !           865:
        !           866:        che_write(sc, CHE_REG_XGM_PORT_CFG, port_reg);
        !           867:        (void)che_read(sc, CHE_REG_XGM_PORT_CFG);
        !           868:
        !           869:        port_reg |= CHE_XGM_F_CLKDIVRESET;
        !           870:
        !           871:        che_write(sc, CHE_REG_XGM_PORT_CFG, port_reg);
        !           872:        (void)che_read(sc, CHE_REG_XGM_PORT_CFG);
        !           873:        che_write(sc, CHE_XGM_REG(CHE_REG_XGM_PORT_CFG, 1), port_reg);
        !           874:        (void)che_read(sc, CHE_REG_XGM_PORT_CFG);
        !           875: }

CVSweb