[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

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