diff --git a/usr/src/uts/common/io/bge/bge_chip2.c b/usr/src/uts/common/io/bge/bge_chip2.c index f687ce4..7790c2d 100644 --- a/usr/src/uts/common/io/bge/bge_chip2.c +++ b/usr/src/uts/common/io/bge/bge_chip2.c @@ -20,16 +20,19 @@ */ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010-2013, by Broadcom, Inc. + * All Rights Reserved. */ /* - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. + * All rights reserved. */ #include "bge_impl.h" #define PIO_ADDR(bgep, offset) ((void *)((caddr_t)(bgep)->io_regs+(offset))) +#define APE_ADDR(bgep, offset) ((void *)((caddr_t)(bgep)->ape_regs+(offset))) /* * Future features ... ? @@ -54,11 +57,6 @@ boolean_t bge_enable_msi = B_TRUE; boolean_t bge_relaxed_ordering = B_TRUE; /* - * Property names - */ -static char knownids_propname[] = "bge-known-subsystems"; - -/* * Patchable globals: * * bge_autorecover @@ -98,7 +96,7 @@ static uint32_t bge_dma_rwctrl_5714 = PDRWCR_VAR_5714; static uint32_t bge_dma_rwctrl_5715 = PDRWCR_VAR_5715; uint32_t bge_rx_ticks_norm = 128; -uint32_t bge_tx_ticks_norm = 2048; /* 8 for FJ2+ !?!? */ +uint32_t bge_tx_ticks_norm = 512; uint32_t bge_rx_count_norm = 8; uint32_t bge_tx_count_norm = 128; @@ -243,8 +241,10 @@ bge_ind_get32(bge_t *bgep, bge_regno_t regno) BGE_TRACE(("bge_ind_get32($%p, 0x%lx)", (void *)bgep, regno)); #ifdef __sparc - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { regno = LE_32(regno); + } #endif pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_RIAAR, regno); val = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_RIADR); @@ -268,8 +268,10 @@ bge_ind_put32(bge_t *bgep, bge_regno_t regno, uint32_t val) val = LE_32(val); #ifdef __sparc - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { regno = LE_32(regno); + } #endif pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_RIAAR, regno); pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_RIADR, val); @@ -327,6 +329,8 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma) ddi_acc_handle_t handle; uint16_t command; uint32_t mhcr; + uint32_t prodid; + uint32_t pci_state; uint16_t value16; int i; @@ -360,10 +364,23 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma) * byte-swapped value to it. So we just write zero first for simplicity. */ cidp->device = pci_config_get16(handle, PCI_CONF_DEVID); - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { pci_config_put32(handle, PCI_CONF_BGE_MHCR, 0); + } + mhcr = pci_config_get32(handle, PCI_CONF_BGE_MHCR); - cidp->asic_rev = mhcr & MHCR_CHIP_REV_MASK; + cidp->asic_rev = (mhcr & MHCR_CHIP_REV_MASK); + cidp->asic_rev_prod_id = 0; + if ((cidp->asic_rev & 0xf0000000) == CHIP_ASIC_REV_USE_PROD_ID_REG) { + prodid = CHIP_ASIC_REV_PROD_ID_REG; + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { + prodid = CHIP_ASIC_REV_PROD_ID_GEN2_REG; + } + cidp->asic_rev_prod_id = pci_config_get32(handle, prodid); + } + cidp->businfo = pci_config_get32(handle, PCI_CONF_BGE_PCISTATE); cidp->command = pci_config_get16(handle, PCI_CONF_COMM); @@ -374,6 +391,12 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma) cidp->clsize = pci_config_get8(handle, PCI_CONF_CACHE_LINESZ); cidp->latency = pci_config_get8(handle, PCI_CONF_LATENCY_TIMER); + /* 5717 C0 is treated just like 5720 A0 */ + if (pci_config_get16(bgep->cfg_handle, PCI_CONF_DEVID) == + DEVICE_ID_5717_C0) { + cidp->device = DEVICE_ID_5720; + } + BGE_DEBUG(("bge_chip_cfg_init: %s bus is %s and %s; #INTA is %s", cidp->businfo & PCISTATE_BUS_IS_PCI ? "PCI" : "PCI-X", cidp->businfo & PCISTATE_BUS_IS_FAST ? "fast" : "slow", @@ -445,25 +468,31 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma) * see whether the host is truly up to date, and regenerate * its interrupt if not. */ - mhcr = MHCR_ENABLE_INDIRECT_ACCESS | - MHCR_ENABLE_TAGGED_STATUS_MODE | - MHCR_MASK_INTERRUPT_MODE | - MHCR_CLEAR_INTERRUPT_INTA; - + mhcr = MHCR_ENABLE_INDIRECT_ACCESS | + MHCR_ENABLE_PCI_STATE_RW | + MHCR_ENABLE_TAGGED_STATUS_MODE | + MHCR_MASK_INTERRUPT_MODE | + MHCR_CLEAR_INTERRUPT_INTA; if (bgep->intr_type == DDI_INTR_TYPE_FIXED) mhcr |= MHCR_MASK_PCI_INT_OUTPUT; #ifdef _BIG_ENDIAN mhcr |= MHCR_ENABLE_ENDIAN_WORD_SWAP | MHCR_ENABLE_ENDIAN_BYTE_SWAP; #endif /* _BIG_ENDIAN */ - - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) - pci_config_put32(handle, PCI_CONF_BGE_MHCR, 0); pci_config_put32(handle, PCI_CONF_BGE_MHCR, mhcr); #ifdef BGE_IPMI_ASF bgep->asf_wordswapped = B_FALSE; #endif + + pci_state = (PCISTATE_EXT_ROM_ENABLE | PCISTATE_EXT_ROM_RETRY); + /* allow reads and writes to the APE register and memory space */ + if (bgep->ape_enabled) { + pci_state |= PCISTATE_ALLOW_APE_CTLSPC_WR | + PCISTATE_ALLOW_APE_SHMEM_WR | PCISTATE_ALLOW_APE_PSPACE_WR; + } + pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_PCISTATE, pci_state); + /* * Step 1 (also step 7): Enable PCI Memory Space accesses * Disable Memory Write/Invalidate @@ -533,9 +562,14 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma) if (DEVICE_5723_SERIES_CHIPSETS(bgep)) { bge_cfg_clr16(bgep, PCI_CONF_DEV_CTRL_5723, DEV_CTRL_NO_SNOOP | DEV_CTRL_RELAXED); - } else + } else if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { + bge_cfg_clr16(bgep, PCI_CONF_DEV_CTRL_5717, + DEV_CTRL_NO_SNOOP | DEV_CTRL_RELAXED); + } else { bge_cfg_clr16(bgep, PCI_CONF_DEV_CTRL, DEV_CTRL_NO_SNOOP | DEV_CTRL_RELAXED); + } } } @@ -629,8 +663,10 @@ bge_reg_get64(bge_t *bgep, bge_regno_t regno) uint64_t regval; #ifdef __amd64 - if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + if (DEVICE_5723_SERIES_CHIPSETS(bgep) || + bge_get_em64t_type() || + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { regval = ddi_get32(bgep->io_handle, PIO_ADDR(bgep, regno + 4)); regval <<= 32; regval |= ddi_get32(bgep->io_handle, PIO_ADDR(bgep, regno)); @@ -639,7 +675,8 @@ bge_reg_get64(bge_t *bgep, bge_regno_t regno) } #elif defined(__sparc) if (DEVICE_5723_SERIES_CHIPSETS(bgep) || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { regval = ddi_get32(bgep->io_handle, PIO_ADDR(bgep, regno)); regval <<= 32; regval |= ddi_get32(bgep->io_handle, PIO_ADDR(bgep, regno + 4)); @@ -674,8 +711,10 @@ bge_reg_put64(bge_t *bgep, bge_regno_t regno, uint64_t data) #endif /* _LITTLE_ENDIAN */ #ifdef __amd64 - if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + if (DEVICE_5723_SERIES_CHIPSETS(bgep) || + bge_get_em64t_type() || + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { ddi_put32(bgep->io_handle, PIO_ADDR(bgep, regno), (uint32_t)data); BGE_PCICHK(bgep); @@ -687,7 +726,8 @@ bge_reg_put64(bge_t *bgep, bge_regno_t regno, uint64_t data) } #elif defined(__sparc) if (DEVICE_5723_SERIES_CHIPSETS(bgep) || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { ddi_put32(bgep->io_handle, PIO_ADDR(bgep, regno + 4), (uint32_t)data); BGE_PCICHK(bgep); @@ -845,8 +885,10 @@ bge_nic_setwin(bge_t *bgep, bge_regno_t base) B_TRUE : B_FALSE); } #ifdef __sparc - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { base = LE_32(base); + } #endif pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MWBAR, base); } @@ -905,8 +947,10 @@ bge_nic_put32(bge_t *bgep, bge_regno_t addr, uint32_t data) #endif #ifdef __sparc - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { addr = LE_32(addr); + } pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MWBAR, addr); data = LE_32(data); pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MWDAR, data); @@ -933,8 +977,10 @@ bge_nic_get64(bge_t *bgep, bge_regno_t addr) addr += NIC_MEM_WINDOW_OFFSET; #ifdef __amd64 - if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + if (DEVICE_5723_SERIES_CHIPSETS(bgep) || + bge_get_em64t_type() || + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { data = ddi_get32(bgep->io_handle, PIO_ADDR(bgep, addr + 4)); data <<= 32; @@ -944,7 +990,8 @@ bge_nic_get64(bge_t *bgep, bge_regno_t addr) } #elif defined(__sparc) if (DEVICE_5723_SERIES_CHIPSETS(bgep) || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { data = ddi_get32(bgep->io_handle, PIO_ADDR(bgep, addr)); data <<= 32; data |= ddi_get32(bgep->io_handle, @@ -976,8 +1023,10 @@ bge_nic_put64(bge_t *bgep, bge_regno_t addr, uint64_t data) addr += NIC_MEM_WINDOW_OFFSET; #ifdef __amd64 - if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + if (DEVICE_5723_SERIES_CHIPSETS(bgep) || + bge_get_em64t_type() || + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr + 4), (uint32_t)data); BGE_PCICHK(bgep); @@ -988,7 +1037,8 @@ bge_nic_put64(bge_t *bgep, bge_regno_t addr, uint64_t data) } #elif defined(__sparc) if (DEVICE_5723_SERIES_CHIPSETS(bgep) || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr + 4), (uint32_t)data); BGE_PCICHK(bgep); @@ -1028,8 +1078,10 @@ bge_nic_putrcb(bge_t *bgep, bge_regno_t addr, bge_rcb_t *rcbp) p = (void *)rcbp; #ifdef __amd64 - if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + if (DEVICE_5723_SERIES_CHIPSETS(bgep) || + bge_get_em64t_type() || + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr), (uint32_t)(*p)); ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr + 4), @@ -1045,7 +1097,8 @@ bge_nic_putrcb(bge_t *bgep, bge_regno_t addr, bge_rcb_t *rcbp) } #elif defined(__sparc) if (DEVICE_5723_SERIES_CHIPSETS(bgep) || - DEVICE_5717_SERIES_CHIPSETS(bgep)) { + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr + 4), (uint32_t)(*p)); ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr), @@ -1246,6 +1299,32 @@ bge_mii_put16(bge_t *bgep, bge_regno_t regno, uint16_t data) (void) bge_mii_access(bgep, regno, data, MI_COMMS_COMMAND_WRITE); } +uint16_t +bge_phydsp_read(bge_t *bgep, bge_regno_t regno) +{ + BGE_TRACE(("bge_phydsp_read($%p, 0x%lx)", + (void *)bgep, regno)); + + ASSERT(mutex_owned(bgep->genlock)); + + bge_mii_put16(bgep, MII_DSP_ADDRESS, regno); + return bge_mii_get16(bgep, MII_DSP_RW_PORT); +} + +#pragma no_inline(bge_phydsp_write) + +void +bge_phydsp_write(bge_t *bgep, bge_regno_t regno, uint16_t data) +{ + BGE_TRACE(("bge_phydsp_write($%p, 0x%lx, 0x%x)", + (void *)bgep, regno, data)); + + ASSERT(mutex_owned(bgep->genlock)); + + bge_mii_put16(bgep, MII_DSP_ADDRESS, regno); + bge_mii_put16(bgep, MII_DSP_RW_PORT, data); +} + #undef BGE_DBG #define BGE_DBG BGE_DBG_SEEPROM /* debug flag for this code */ @@ -1720,6 +1799,7 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp) if (DEVICE_5721_SERIES_CHIPSETS(bgep) || DEVICE_5723_SERIES_CHIPSETS(bgep) || DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep) || DEVICE_5714_SERIES_CHIPSETS(bgep)) { bge_reg_set32(bgep, NVM_ACCESS_REG, NVM_ACCESS_ENABLE); @@ -1729,6 +1809,7 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp) if (DEVICE_5721_SERIES_CHIPSETS(bgep) || DEVICE_5723_SERIES_CHIPSETS(bgep) || DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep) || DEVICE_5714_SERIES_CHIPSETS(bgep)) { bge_reg_clr32(bgep, NVM_ACCESS_REG, NVM_ACCESS_ENABLE); @@ -1739,6 +1820,7 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp) if (DEVICE_5721_SERIES_CHIPSETS(bgep) || DEVICE_5723_SERIES_CHIPSETS(bgep) || DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep) || DEVICE_5714_SERIES_CHIPSETS(bgep)) { bge_reg_set32(bgep, NVM_ACCESS_REG, NVM_WRITE_ENABLE|NVM_ACCESS_ENABLE); @@ -1750,6 +1832,7 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp) if (DEVICE_5721_SERIES_CHIPSETS(bgep) || DEVICE_5723_SERIES_CHIPSETS(bgep) || DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep) || DEVICE_5714_SERIES_CHIPSETS(bgep)) { bge_reg_clr32(bgep, NVM_ACCESS_REG, NVM_WRITE_ENABLE|NVM_ACCESS_ENABLE); @@ -1768,6 +1851,42 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp) return (err); } +static uint32_t +bge_nvmem_access_cmd(bge_t *bgep, boolean_t read) +{ + switch (bgep->chipid.nvtype) { + case BGE_NVTYPE_NONE: + case BGE_NVTYPE_UNKNOWN: + default: + return 0; + + case BGE_NVTYPE_SEEPROM: + case BGE_NVTYPE_LEGACY_SEEPROM: + return (read ? BGE_SEE_READ : BGE_SEE_WRITE); + + case BGE_NVTYPE_UNBUFFERED_FLASH: + case BGE_NVTYPE_BUFFERED_FLASH: + return (read ? BGE_FLASH_READ : BGE_FLASH_WRITE); + } +} + + +int +bge_nvmem_read32(bge_t *bgep, bge_regno_t addr, uint32_t *dp) +{ + return (bge_nvmem_rw32(bgep, bge_nvmem_access_cmd(bgep, B_TRUE), + addr, dp)); +} + + +int +bge_nvmem_write32(bge_t *bgep, bge_regno_t addr, uint32_t *dp) +{ + return (bge_nvmem_rw32(bgep, bge_nvmem_access_cmd(bgep, B_FALSE), + addr, dp)); +} + + /* * Attempt to get a MAC address from the SEEPROM or Flash, if any */ @@ -1896,7 +2015,11 @@ bge_nvmem_id(bge_t *bgep) case DEVICE_ID_5705_2: case DEVICE_ID_5717: case DEVICE_ID_5718: + case DEVICE_ID_5719: + case DEVICE_ID_5720: case DEVICE_ID_5724: + case DEVICE_ID_5725: + case DEVICE_ID_5727: case DEVICE_ID_57780: case DEVICE_ID_5780: case DEVICE_ID_5782: @@ -1942,6 +2065,453 @@ bge_nvmem_id(bge_t *bgep) } #undef BGE_DBG +#define BGE_DBG BGE_DBG_APE /* debug flag for this code */ + +uint32_t bge_ape_get32(bge_t *bgep, bge_regno_t regno); +#pragma inline(bge_ape_get32) + +uint32_t +bge_ape_get32(bge_t *bgep, bge_regno_t regno) +{ + BGE_TRACE(("bge_ape_get32($%p, 0x%lx)", + (void *)bgep, regno)); + + return (ddi_get32(bgep->ape_handle, APE_ADDR(bgep, regno))); +} + +void bge_ape_put32(bge_t *bgep, bge_regno_t regno, uint32_t data); +#pragma inline(bge_ape_put32) + +void +bge_ape_put32(bge_t *bgep, bge_regno_t regno, uint32_t data) +{ + BGE_TRACE(("bge_ape_put32($%p, 0x%lx, 0x%x)", + (void *)bgep, regno, data)); + + ddi_put32(bgep->ape_handle, APE_ADDR(bgep, regno), data); + BGE_PCICHK(bgep); +} + +void +bge_ape_lock_init(bge_t *bgep) +{ + int i; + uint32_t regbase; + uint32_t bit; + + BGE_TRACE(("bge_ape_lock_init($%p)", (void *)bgep)); + + if (bgep->chipid.device == DEVICE_ID_5761) + regbase = BGE_APE_LOCK_GRANT; + else + regbase = BGE_APE_PER_LOCK_GRANT; + + /* Make sure the driver hasn't any stale locks. */ + for (i = BGE_APE_LOCK_PHY0; i <= BGE_APE_LOCK_GPIO; i++) { + switch (i) { + case BGE_APE_LOCK_PHY0: + case BGE_APE_LOCK_PHY1: + case BGE_APE_LOCK_PHY2: + case BGE_APE_LOCK_PHY3: + bit = APE_LOCK_GRANT_DRIVER; + break; + default: + if (!bgep->pci_func) + bit = APE_LOCK_GRANT_DRIVER; + else + bit = 1 << bgep->pci_func; + } + bge_ape_put32(bgep, regbase + 4 * i, bit); + } +} + +static int +bge_ape_lock(bge_t *bgep, int locknum) +{ + int i, off; + int ret = 0; + uint32_t status; + uint32_t req; + uint32_t gnt; + uint32_t bit; + + BGE_TRACE(("bge_ape_lock($%p, 0x%x)", (void *)bgep, locknum)); + + if (!bgep->ape_enabled) + return (0); + + switch (locknum) { + case BGE_APE_LOCK_GPIO: + if (bgep->chipid.device == DEVICE_ID_5761) + return (0); + case BGE_APE_LOCK_GRC: + case BGE_APE_LOCK_MEM: + if (!bgep->pci_func) + bit = APE_LOCK_REQ_DRIVER; + else + bit = 1 << bgep->pci_func; + break; + case BGE_APE_LOCK_PHY0: + case BGE_APE_LOCK_PHY1: + case BGE_APE_LOCK_PHY2: + case BGE_APE_LOCK_PHY3: + bit = APE_LOCK_REQ_DRIVER; + break; + default: + return (-1); + } + + if (bgep->chipid.device == DEVICE_ID_5761) { + req = BGE_APE_LOCK_REQ; + gnt = BGE_APE_LOCK_GRANT; + } else { + req = BGE_APE_PER_LOCK_REQ; + gnt = BGE_APE_PER_LOCK_GRANT; + } + + off = 4 * locknum; + + bge_ape_put32(bgep, req + off, bit); + + /* Wait for up to 1 millisecond to acquire lock. */ + for (i = 0; i < 100; i++) { + status = bge_ape_get32(bgep, gnt + off); + if (status == bit) + break; + drv_usecwait(10); + } + + if (status != bit) { + /* Revoke the lock request. */ + bge_ape_put32(bgep, gnt + off, bit); + ret = -1; + } + + return (ret); +} + +static void +bge_ape_unlock(bge_t *bgep, int locknum) +{ + uint32_t gnt; + uint32_t bit; + + BGE_TRACE(("bge_ape_unlock($%p, 0x%x)", (void *)bgep, locknum)); + + if (!bgep->ape_enabled) + return; + + switch (locknum) { + case BGE_APE_LOCK_GPIO: + if (bgep->chipid.device == DEVICE_ID_5761) + return; + case BGE_APE_LOCK_GRC: + case BGE_APE_LOCK_MEM: + if (!bgep->pci_func) + bit = APE_LOCK_GRANT_DRIVER; + else + bit = 1 << bgep->pci_func; + break; + case BGE_APE_LOCK_PHY0: + case BGE_APE_LOCK_PHY1: + case BGE_APE_LOCK_PHY2: + case BGE_APE_LOCK_PHY3: + bit = APE_LOCK_GRANT_DRIVER; + break; + default: + return; + } + + if (bgep->chipid.device == DEVICE_ID_5761) + gnt = BGE_APE_LOCK_GRANT; + else + gnt = BGE_APE_PER_LOCK_GRANT; + + bge_ape_put32(bgep, gnt + 4 * locknum, bit); +} + +/* wait for pending event to finish, if successful returns with MEM locked */ +static int +bge_ape_event_lock(bge_t *bgep, uint32_t timeout_us) +{ + uint32_t apedata; + + BGE_TRACE(("bge_ape_event_lock($%p, %d)", (void *)bgep, timeout_us)); + + ASSERT(timeout_us > 0); + + while (timeout_us) { + if (bge_ape_lock(bgep, BGE_APE_LOCK_MEM)) + return (-1); + + apedata = bge_ape_get32(bgep, BGE_APE_EVENT_STATUS); + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + break; + + bge_ape_unlock(bgep, BGE_APE_LOCK_MEM); + + drv_usecwait(10); + timeout_us -= (timeout_us > 10) ? 10 : timeout_us; + } + + return (timeout_us ? 0 : -1); +} + +/* wait for pending event to finish, returns non-zero if not finished */ +static int +bge_ape_wait_for_event(bge_t *bgep, uint32_t timeout_us) +{ + uint32_t i; + uint32_t apedata; + + BGE_TRACE(("bge_ape_wait_for_event($%p, %d)", (void *)bgep, timeout_us)); + + ASSERT(timeout_us > 0); + + for (i = 0; i < timeout_us / 10; i++) { + apedata = bge_ape_get32(bgep, BGE_APE_EVENT_STATUS); + + if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING)) + break; + + drv_usecwait(10); + } + + return (i == timeout_us / 10); +} + +int +bge_ape_scratchpad_read(bge_t *bgep, uint32_t *data, uint32_t base_off, + uint32_t lenToRead) +{ + int err; + uint32_t i; + uint32_t bufoff; + uint32_t msgoff; + uint32_t maxlen; + uint32_t apedata; + + BGE_TRACE(("bge_ape_scratchpad_read($%p, %p, 0x%0x, %d)", + (void *)bgep, (void*)data, base_off, lenToRead)); + + if (!bgep->ape_has_ncsi) + return (0); + + apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG); + if (apedata != APE_SEG_SIG_MAGIC) + return (-1); + + apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS); + if (!(apedata & APE_FW_STATUS_READY)) + return (-1); + + bufoff = (bge_ape_get32(bgep, BGE_APE_SEG_MSG_BUF_OFF) + + BGE_APE_SHMEM_BASE); + msgoff = bufoff + 2 * sizeof(uint32_t); + maxlen = bge_ape_get32(bgep, BGE_APE_SEG_MSG_BUF_LEN); + + while (lenToRead) { + uint32_t transferLen; + + /* Cap xfer sizes to scratchpad limits. */ + transferLen = (lenToRead > maxlen) ? maxlen : lenToRead; + lenToRead -= transferLen; + + apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS); + if (!(apedata & APE_FW_STATUS_READY)) + return (-1); + + /* Wait for up to 1 millisecond for APE to service previous event. */ + err = bge_ape_event_lock(bgep, 1000); + if (err) + return (err); + + apedata = (APE_EVENT_STATUS_DRIVER_EVNT | + APE_EVENT_STATUS_SCRTCHPD_READ | + APE_EVENT_STATUS_EVENT_PENDING); + bge_ape_put32(bgep, BGE_APE_EVENT_STATUS, apedata); + + bge_ape_put32(bgep, bufoff, base_off); + bge_ape_put32(bgep, bufoff + sizeof(uint32_t), transferLen); + + bge_ape_unlock(bgep, BGE_APE_LOCK_MEM); + bge_ape_put32(bgep, BGE_APE_EVENT, APE_EVENT_1); + + base_off += transferLen; + + if (bge_ape_wait_for_event(bgep, 30000)) + return (-1); + + for (i = 0; transferLen; i += 4, transferLen -= 4) { + uint32_t val = bge_ape_get32(bgep, msgoff + i); + memcpy(data, &val, sizeof(uint32_t)); + data++; + } + } + + return (0); +} + +int +bge_ape_scratchpad_write(bge_t *bgep, uint32_t dstoff, uint32_t *data, + uint32_t lenToWrite) +{ + int err; + uint32_t i; + uint32_t bufoff; + uint32_t msgoff; + uint32_t maxlen; + uint32_t apedata; + + BGE_TRACE(("bge_ape_scratchpad_write($%p, %d, %p, %d)", + (void *)bgep, dstoff, data, lenToWrite)); + + if (!bgep->ape_has_ncsi) + return (0); + + apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG); + if (apedata != APE_SEG_SIG_MAGIC) + return (-1); + + apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS); + if (!(apedata & APE_FW_STATUS_READY)) + return (-1); + + bufoff = (bge_ape_get32(bgep, BGE_APE_SEG_MSG_BUF_OFF) + + BGE_APE_SHMEM_BASE); + msgoff = bufoff + 2 * sizeof(uint32_t); + maxlen = bge_ape_get32(bgep, BGE_APE_SEG_MSG_BUF_LEN); + + while (lenToWrite) { + uint32_t transferLen; + + /* Cap xfer sizes to scratchpad limits. */ + transferLen = (lenToWrite > maxlen) ? maxlen : lenToWrite; + lenToWrite -= transferLen; + + /* Wait for up to 1 millisecond for + * APE to service previous event. + */ + err = bge_ape_event_lock(bgep, 1000); + if (err) + return (err); + + bge_ape_put32(bgep, bufoff, dstoff); + bge_ape_put32(bgep, bufoff + sizeof(uint32_t), transferLen); + apedata = msgoff; + + dstoff += transferLen; + + for (i = 0; transferLen; i += 4, transferLen -= 4) { + bge_ape_put32(bgep, apedata, *data++); + apedata += sizeof(uint32_t); + } + + apedata = (APE_EVENT_STATUS_DRIVER_EVNT | + APE_EVENT_STATUS_SCRTCHPD_WRITE | + APE_EVENT_STATUS_EVENT_PENDING); + bge_ape_put32(bgep, BGE_APE_EVENT_STATUS, apedata); + + bge_ape_unlock(bgep, BGE_APE_LOCK_MEM); + bge_ape_put32(bgep, BGE_APE_EVENT, APE_EVENT_1); + } + + return (0); +} + +static int +bge_ape_send_event(bge_t *bgep, uint32_t event) +{ + int err; + uint32_t apedata; + + BGE_TRACE(("bge_ape_send_event($%p, %d)", (void *)bgep, event)); + + apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG); + if (apedata != APE_SEG_SIG_MAGIC) + return (-1); + + apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS); + if (!(apedata & APE_FW_STATUS_READY)) + return (-1); + + /* Wait for up to 1 millisecond for APE to service previous event. */ + err = bge_ape_event_lock(bgep, 1000); + if (err) + return (err); + + bge_ape_put32(bgep, BGE_APE_EVENT_STATUS, + event | APE_EVENT_STATUS_EVENT_PENDING); + + bge_ape_unlock(bgep, BGE_APE_LOCK_MEM); + bge_ape_put32(bgep, BGE_APE_EVENT, APE_EVENT_1); + + return 0; +} + +static void +bge_ape_driver_state_change(bge_t *bgep, int mode) +{ + uint32_t event; + uint32_t apedata; + + BGE_TRACE(("bge_ape_driver_state_change($%p, %d)", + (void *)bgep, mode)); + + if (!bgep->ape_enabled) + return; + + switch (mode) { + case BGE_INIT_RESET: + bge_ape_put32(bgep, BGE_APE_HOST_SEG_SIG, + APE_HOST_SEG_SIG_MAGIC); + bge_ape_put32(bgep, BGE_APE_HOST_SEG_LEN, + APE_HOST_SEG_LEN_MAGIC); + apedata = bge_ape_get32(bgep, BGE_APE_HOST_INIT_COUNT); + bge_ape_put32(bgep, BGE_APE_HOST_INIT_COUNT, ++apedata); + bge_ape_put32(bgep, BGE_APE_HOST_DRIVER_ID, + APE_HOST_DRIVER_ID_MAGIC(1, 0)); + bge_ape_put32(bgep, BGE_APE_HOST_BEHAVIOR, + APE_HOST_BEHAV_NO_PHYLOCK); + bge_ape_put32(bgep, BGE_APE_HOST_DRVR_STATE, + BGE_APE_HOST_DRVR_STATE_START); + + event = APE_EVENT_STATUS_STATE_START; + break; + case BGE_SHUTDOWN_RESET: + /* With the interface we are currently using, + * APE does not track driver state. Wiping + * out the HOST SEGMENT SIGNATURE forces + * the APE to assume OS absent status. + */ + bge_ape_put32(bgep, BGE_APE_HOST_SEG_SIG, 0x0); + +#if 0 + if (WOL supported) { + bge_ape_put32(bgep, BGE_APE_HOST_WOL_SPEED, + BGE_APE_HOST_WOL_SPEED_AUTO); + apedata = BGE_APE_HOST_DRVR_STATE_WOL; + } else +#endif + apedata = BGE_APE_HOST_DRVR_STATE_UNLOAD; + + bge_ape_put32(bgep, BGE_APE_HOST_DRVR_STATE, apedata); + + event = APE_EVENT_STATUS_STATE_UNLOAD; + break; + case BGE_SUSPEND_RESET: + event = APE_EVENT_STATUS_STATE_SUSPEND; + break; + default: + return; + } + + event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE; + + bge_ape_send_event(bgep, event); +} + +#undef BGE_DBG #define BGE_DBG BGE_DBG_CHIP /* debug flag for this code */ static void @@ -1973,7 +2543,6 @@ int bge_chip_id_init(bge_t *bgep) { char buf[MAXPATHLEN]; /* any risk of stack overflow? */ - boolean_t sys_ok; boolean_t dev_ok; chip_id_t *cidp; uint32_t subid; @@ -1983,7 +2552,7 @@ bge_chip_id_init(bge_t *bgep) int err; uint_t i; - sys_ok = dev_ok = B_FALSE; + dev_ok = B_FALSE; cidp = &bgep->chipid; /* @@ -2026,13 +2595,31 @@ bge_chip_id_init(bge_t *bgep) switch (cidp->device) { case DEVICE_ID_5717: case DEVICE_ID_5718: + case DEVICE_ID_5719: + case DEVICE_ID_5720: case DEVICE_ID_5724: - if (cidp->device == DEVICE_ID_5717) + case DEVICE_ID_5725: + case DEVICE_ID_5727: + if (cidp->device == DEVICE_ID_5717) { cidp->chip_label = 5717; - else if (cidp->device == DEVICE_ID_5718) + } else if (cidp->device == DEVICE_ID_5718) { cidp->chip_label = 5718; - else + } else if (cidp->device == DEVICE_ID_5719) { + cidp->chip_label = 5719; + } else if (cidp->device == DEVICE_ID_5720) { + if (pci_config_get16(bgep->cfg_handle, PCI_CONF_DEVID) == + DEVICE_ID_5717_C0) { + cidp->chip_label = 5717; + } else { + cidp->chip_label = 5720; + } + } else if (cidp->device == DEVICE_ID_5724) { cidp->chip_label = 5724; + } else if (cidp->device == DEVICE_ID_5725) { + cidp->chip_label = 5725; + } else /* (cidp->device == DEVICE_ID_5727) */ { + cidp->chip_label = 5727; + } cidp->msi_enabled = bge_enable_msi; #ifdef __sparc cidp->mask_pci_int = LE_32(MHCR_MASK_PCI_INT_OUTPUT); @@ -2048,7 +2635,6 @@ bge_chip_id_init(bge_t *bgep) cidp->bge_mlcr_default = MLCR_DEFAULT_5717; cidp->rx_rings = BGE_RECV_RINGS_MAX_5705; cidp->tx_rings = BGE_SEND_RINGS_MAX_5705; - cidp->flags |= CHIP_FLAG_NO_JUMBO; cidp->statistic_type = BGE_STAT_REG; dev_ok = B_TRUE; break; @@ -2451,10 +3037,15 @@ bge_chip_id_init(bge_t *bgep) * For BCM5714/5715, there is only one standard receive ring. So the * std buffer size should be set to BGE_JUMBO_BUFF_SIZE when jumbo * feature is enabled. + * + * For the BCM5718 family we hijack the standard receive ring for + * the jumboframe traffic, keeps it simple. */ if (!(cidp->flags & CHIP_FLAG_NO_JUMBO) && (cidp->default_mtu > BGE_DEFAULT_MTU)) { - if (DEVICE_5714_SERIES_CHIPSETS(bgep)) { + if (DEVICE_5714_SERIES_CHIPSETS(bgep) || + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { cidp->mbuf_lo_water_rdma = RDMA_MBUF_LOWAT_5714_JUMBO; cidp->mbuf_lo_water_rmac = @@ -2482,57 +3073,6 @@ bge_chip_id_init(bge_t *bgep) cidp->nvtype = bge_nvmem_id(bgep); /* - * Now, we want to check whether this device is part of a - * supported subsystem (e.g., on the motherboard of a Sun - * branded platform). - * - * Rule 1: If the Subsystem Vendor ID is "Sun", then it's OK ;-) - */ - if (cidp->subven == VENDOR_ID_SUN) - sys_ok = B_TRUE; - - /* - * Rule 2: If it's on the list on known subsystems, then it's OK. - * Note: 0x14e41647 should *not* appear in the list, but the code - * doesn't enforce that. - */ - err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, bgep->devinfo, - DDI_PROP_DONTPASS, knownids_propname, &ids, &i); - if (err == DDI_PROP_SUCCESS) { - /* - * Got the list; scan for a matching subsystem vendor/device - */ - subid = (cidp->subven << 16) | cidp->subdev; - while (i--) - if (ids[i] == subid) - sys_ok = B_TRUE; - ddi_prop_free(ids); - } - - /* - * Rule 3: If it's a Taco/ENWS motherboard device, then it's OK - * - * Unfortunately, early SunBlade 1500s and 2500s didn't reprogram - * the Subsystem Vendor ID, so it defaults to Broadcom. Therefore, - * we have to check specially for the exact device paths to the - * motherboard devices on those platforms ;-( - * - * Note: we can't just use the "supported-subsystems" mechanism - * above, because the entry would have to be 0x14e41647 -- which - * would then accept *any* plugin card that *didn't* contain a - * (valid) SEEPROM ;-( - */ - sysname = ddi_node_name(ddi_root_node()); - devname = ddi_pathname(bgep->devinfo, buf); - ASSERT(strlen(devname) > 0); - if (strcmp(sysname, "SUNW,Sun-Blade-1500") == 0) /* Taco */ - if (strcmp(devname, "/pci@1f,700000/network@2") == 0) - sys_ok = B_TRUE; - if (strcmp(sysname, "SUNW,Sun-Blade-2500") == 0) /* ENWS */ - if (strcmp(devname, "/pci@1c,600000/network@3") == 0) - sys_ok = B_TRUE; - - /* * Now check what we've discovered: is this truly a supported * chip on (the motherboard of) a supported platform? * @@ -2551,16 +3091,12 @@ bge_chip_id_init(bge_t *bgep) "Device 'pci%04x,%04x' (%d) revision %d not supported", cidp->vendor, cidp->device, cidp->chip_label, cidp->revision); -#if BGE_DEBUGGING - else if (!sys_ok) - bge_problem(bgep, - "%d-based subsystem 'pci%04x,%04x' not validated", - cidp->chip_label, cidp->subven, cidp->subdev); -#endif else cidp->flags |= CHIP_FLAG_SUPPORTED; + if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) return (EIO); + return (0); } @@ -2643,7 +3179,9 @@ static boolean_t bge_chip_reset_engine(bge_t *bgep, bge_regno_t regno) { uint32_t regval; + uint16_t val16; uint32_t val32; + uint32_t mhcr; regval = bge_reg_get32(bgep, regno); @@ -2663,11 +3201,12 @@ bge_chip_reset_engine(bge_t *bgep, bge_regno_t regno) * while the reset bit is written. * See:P500 of 57xx-PG102-RDS.pdf. */ - if (DEVICE_5705_SERIES_CHIPSETS(bgep)|| - DEVICE_5717_SERIES_CHIPSETS(bgep)|| - DEVICE_5721_SERIES_CHIPSETS(bgep)|| - DEVICE_5723_SERIES_CHIPSETS(bgep)|| - DEVICE_5714_SERIES_CHIPSETS(bgep)|| + if (DEVICE_5705_SERIES_CHIPSETS(bgep) || + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep) || + DEVICE_5721_SERIES_CHIPSETS(bgep) || + DEVICE_5723_SERIES_CHIPSETS(bgep) || + DEVICE_5714_SERIES_CHIPSETS(bgep) || DEVICE_5906_SERIES_CHIPSETS(bgep)) { regval |= MISC_CONFIG_GPHY_POWERDOWN_OVERRIDE; if (bgep->chipid.pci_type == BGE_PCI_E) { @@ -2727,6 +3266,14 @@ bge_chip_reset_engine(bge_t *bgep, bge_regno_t regno) /* PCI-E device need more reset time */ drv_usecwait(120000); + /* + * (re)Disable interrupts as the bit can be reset after a + * core clock reset. + */ + mhcr = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR); + pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, + mhcr | MHCR_MASK_PCI_INT_OUTPUT); + /* Set PCIE max payload size and clear error status. */ if ((bgep->chipid.chip_label == 5721) || (bgep->chipid.chip_label == 5751) || @@ -2746,6 +3293,16 @@ bge_chip_reset_engine(bge_t *bgep, bge_regno_t regno) pci_config_put16(bgep->cfg_handle, PCI_CONF_DEV_STUS_5723, DEVICE_ERROR_STUS); } + + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { + val16 = pci_config_get16(bgep->cfg_handle, + PCI_CONF_DEV_CTRL_5717); + val16 &= ~READ_REQ_SIZE_MASK; + val16 |= READ_REQ_SIZE_2K; + pci_config_put16(bgep->cfg_handle, + PCI_CONF_DEV_CTRL_5717, val16); + } } BGE_PCICHK(bgep); @@ -2802,13 +3359,27 @@ bge_chip_disable_engine(bge_t *bgep, bge_regno_t regno, uint32_t morebits) return (B_TRUE); default: - regval = bge_reg_get32(bgep, regno); - regval &= ~STATE_MACHINE_ENABLE_BIT; - regval &= ~morebits; - bge_reg_put32(bgep, regno, regval); - return (bge_chip_poll_engine(bgep, regno, - STATE_MACHINE_ENABLE_BIT, 0)); + if (DEVICE_5704_SERIES_CHIPSETS(bgep)) { + break; + } + + if ((regno == RCV_LIST_SELECTOR_MODE_REG) || + (regno == DMA_COMPLETION_MODE_REG) || + (regno == MBUF_CLUSTER_FREE_MODE_REG) || + (regno == BUFFER_MANAGER_MODE_REG) || + (regno == MEMORY_ARBITER_MODE_REG)) { + return B_TRUE; + } + + break; } + + regval = bge_reg_get32(bgep, regno); + regval &= ~STATE_MACHINE_ENABLE_BIT; + regval &= ~morebits; + bge_reg_put32(bgep, regno, regval); + + return bge_chip_poll_engine(bgep, regno, STATE_MACHINE_ENABLE_BIT, 0); } /* @@ -2880,18 +3451,13 @@ bge_sync_mac_modes(bge_t *bgep) * Reprogram the Ethernet MAC mode ... */ macmode = regval = bge_reg_get32(bgep, ETHERNET_MAC_MODE_REG); - if ((bgep->chipid.flags & CHIP_FLAG_SERDES) && - (bgep->param_loop_mode != BGE_LOOP_INTERNAL_MAC)) - if (DEVICE_5714_SERIES_CHIPSETS(bgep)) - macmode |= ETHERNET_MODE_LINK_POLARITY; - else - macmode &= ~ETHERNET_MODE_LINK_POLARITY; - else - macmode |= ETHERNET_MODE_LINK_POLARITY; + macmode &= ~ETHERNET_MODE_LINK_POLARITY; macmode &= ~ETHERNET_MODE_PORTMODE_MASK; if ((bgep->chipid.flags & CHIP_FLAG_SERDES) && (bgep->param_loop_mode != BGE_LOOP_INTERNAL_MAC)) { - if (DEVICE_5714_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep) || + DEVICE_5714_SERIES_CHIPSETS(bgep)) macmode |= ETHERNET_MODE_PORTMODE_GMII; else macmode |= ETHERNET_MODE_PORTMODE_TBI; @@ -3099,40 +3665,8 @@ bge_chip_sync(bge_t *bgep) retval = DDI_FAILURE; #endif } - return (retval); -} - -/* - * This array defines the sequence of state machine control registers - * in which the bit must be cleared to bring the chip to a - * clean stop. Taken from Broadcom document 570X-PG102-R, p116. - */ -static bge_regno_t shutdown_engine_regs[] = { - RECEIVE_MAC_MODE_REG, - RCV_BD_INITIATOR_MODE_REG, - RCV_LIST_PLACEMENT_MODE_REG, - RCV_LIST_SELECTOR_MODE_REG, /* BCM5704 series only */ - RCV_DATA_BD_INITIATOR_MODE_REG, - RCV_DATA_COMPLETION_MODE_REG, - RCV_BD_COMPLETION_MODE_REG, - - SEND_BD_SELECTOR_MODE_REG, - SEND_BD_INITIATOR_MODE_REG, - SEND_DATA_INITIATOR_MODE_REG, - READ_DMA_MODE_REG, - SEND_DATA_COMPLETION_MODE_REG, - DMA_COMPLETION_MODE_REG, /* BCM5704 series only */ - SEND_BD_COMPLETION_MODE_REG, - TRANSMIT_MAC_MODE_REG, - - HOST_COALESCE_MODE_REG, - WRITE_DMA_MODE_REG, - MBUF_CLUSTER_FREE_MODE_REG, /* BCM5704 series only */ - FTQ_RESET_REG, /* special - see code */ - BUFFER_MANAGER_MODE_REG, /* BCM5704 series only */ - MEMORY_ARBITER_MODE_REG, /* BCM5704 series only */ - BGE_REGNO_NONE /* terminator */ -}; + return (retval); +} #ifndef __sparc static bge_regno_t quiesce_regs[] = { @@ -3185,30 +3719,44 @@ bge_chip_stop(bge_t *bgep, boolean_t fault) { bge_regno_t regno; bge_regno_t *rbp; - boolean_t ok; + boolean_t ok = B_TRUE; BGE_TRACE(("bge_chip_stop($%p)", (void *)bgep)); ASSERT(mutex_owned(bgep->genlock)); - rbp = shutdown_engine_regs; - /* - * When driver try to shutdown the BCM5705/5788/5721/5751/ - * 5752/5714 and 5715 chipsets,the buffer manager and the mem - * -ory arbiter should not be disabled. - */ - for (ok = B_TRUE; (regno = *rbp) != BGE_REGNO_NONE; ++rbp) { - if (DEVICE_5704_SERIES_CHIPSETS(bgep)) - ok &= bge_chip_disable_engine(bgep, regno, 0); - else if ((regno != RCV_LIST_SELECTOR_MODE_REG) && - (regno != DMA_COMPLETION_MODE_REG) && - (regno != MBUF_CLUSTER_FREE_MODE_REG)&& - (regno != BUFFER_MANAGER_MODE_REG) && - (regno != MEMORY_ARBITER_MODE_REG)) - ok &= bge_chip_disable_engine(bgep, - regno, 0); - } + pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, + (pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR) | + MHCR_MASK_PCI_INT_OUTPUT)); + + ok &= bge_chip_disable_engine(bgep, RECEIVE_MAC_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, RCV_BD_INITIATOR_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, RCV_LIST_PLACEMENT_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, RCV_LIST_SELECTOR_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, RCV_DATA_BD_INITIATOR_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, RCV_DATA_COMPLETION_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, RCV_BD_COMPLETION_MODE_REG, 0); + + ok &= bge_chip_disable_engine(bgep, SEND_BD_SELECTOR_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, SEND_BD_INITIATOR_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, SEND_DATA_INITIATOR_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, READ_DMA_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, SEND_DATA_COMPLETION_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, DMA_COMPLETION_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, SEND_BD_COMPLETION_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, TRANSMIT_MAC_MODE_REG, 0); + + bge_reg_clr32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_ENABLE_TDE); + drv_usecwait(40); + + ok &= bge_chip_disable_engine(bgep, HOST_COALESCE_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, WRITE_DMA_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, MBUF_CLUSTER_FREE_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, FTQ_RESET_REG, 0); + ok &= bge_chip_disable_engine(bgep, BUFFER_MANAGER_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, MEMORY_ARBITER_MODE_REG, 0); + ok &= bge_chip_disable_engine(bgep, MEMORY_ARBITER_MODE_REG, 0); if (!ok && !fault) ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED); @@ -3295,8 +3843,7 @@ bge_poll_firmware(bge_t *bgep) * GENCOMM word as "the upper half of a 64-bit quantity" makes * it work correctly on both big- and little-endian hosts. */ - if (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) == - MHCR_CHIP_ASIC_REV_5906) { + if (MHCR_CHIP_ASIC_REV(bgep) == MHCR_CHIP_ASIC_REV_5906) { for (i = 0; i < 1000; ++i) { drv_usecwait(1000); val = bge_reg_get32(bgep, VCPU_STATUS_REG); @@ -3310,6 +3857,9 @@ bge_poll_firmware(bge_t *bgep) for (i = 0; i < 1000; ++i) { drv_usecwait(1000); gen = bge_nic_get64(bgep, NIC_MEM_GENCOMM) >> 32; + if (i == 0 && DEVICE_5704_SERIES_CHIPSETS(bgep)) + drv_usecwait(100000); + mac = bge_reg_get64(bgep, MAC_ADDRESS_REG(0)); #ifdef BGE_IPMI_ASF if (!bgep->asf_enabled) { #endif @@ -3318,7 +3868,6 @@ bge_poll_firmware(bge_t *bgep) #ifdef BGE_IPMI_ASF } #endif - mac = bge_reg_get64(bgep, MAC_ADDRESS_REG(0)); if (mac != 0ULL) break; if (bgep->bge_chip_state != BGE_CHIP_INITIAL) @@ -3358,7 +3907,8 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) chip_id_t chipid; uint64_t mac; uint64_t magic; - uint32_t modeflags; + uint32_t tmp; + uint32_t mhcr_base; uint32_t mhcr; uint32_t sx0; uint32_t i, tries; @@ -3395,24 +3945,26 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) break; } + mhcr_base = MHCR_ENABLE_INDIRECT_ACCESS | + MHCR_ENABLE_PCI_STATE_RW | + MHCR_ENABLE_TAGGED_STATUS_MODE | + MHCR_MASK_INTERRUPT_MODE | + MHCR_MASK_PCI_INT_OUTPUT | + MHCR_CLEAR_INTERRUPT_INTA; + #ifdef BGE_IPMI_ASF if (bgep->asf_enabled) { -#ifdef __sparc - mhcr = MHCR_ENABLE_INDIRECT_ACCESS | - MHCR_ENABLE_TAGGED_STATUS_MODE | - MHCR_MASK_INTERRUPT_MODE | - MHCR_MASK_PCI_INT_OUTPUT | - MHCR_CLEAR_INTERRUPT_INTA | - MHCR_ENABLE_ENDIAN_WORD_SWAP | - MHCR_ENABLE_ENDIAN_BYTE_SWAP; - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) - pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, - 0); + mhcr = mhcr_base; +#ifdef _BIG_ENDIAN + mhcr |= (MHCR_ENABLE_ENDIAN_WORD_SWAP | + MHCR_ENABLE_ENDIAN_BYTE_SWAP); +#endif pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcr); + bge_reg_put32(bgep, MEMORY_ARBITER_MODE_REG, bge_reg_get32(bgep, MEMORY_ARBITER_MODE_REG) | MEMORY_ARBITER_ENABLE); -#endif + if (asf_mode == ASF_MODE_INIT) { bge_asf_pre_reset_operations(bgep, BGE_INIT_RESET); } else if (asf_mode == ASF_MODE_SHUTDOWN) { @@ -3420,6 +3972,7 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) } } #endif + /* * Adapted from Broadcom document 570X-PG102-R, pp 102-116. * Updated to reflect Broadcom document 570X-PG104-R, pp 146-159. @@ -3434,17 +3987,13 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) if (!bge_chip_enable_engine(bgep, MEMORY_ARBITER_MODE_REG, 0)) retval = DDI_FAILURE; - mhcr = MHCR_ENABLE_INDIRECT_ACCESS | - MHCR_ENABLE_TAGGED_STATUS_MODE | - MHCR_MASK_INTERRUPT_MODE | - MHCR_MASK_PCI_INT_OUTPUT | - MHCR_CLEAR_INTERRUPT_INTA; -#ifdef _BIG_ENDIAN - mhcr |= MHCR_ENABLE_ENDIAN_WORD_SWAP | MHCR_ENABLE_ENDIAN_BYTE_SWAP; -#endif /* _BIG_ENDIAN */ - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) - pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, 0); + mhcr = mhcr_base; +#ifdef _BIG_ENDIAN + mhcr |= (MHCR_ENABLE_ENDIAN_WORD_SWAP | + MHCR_ENABLE_ENDIAN_BYTE_SWAP); +#endif pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcr); + #ifdef BGE_IPMI_ASF if (bgep->asf_enabled) bgep->asf_wordswapped = B_FALSE; @@ -3459,6 +4008,8 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) BGE_DEBUG(("%s: fail to acquire nvram lock", bgep->ifname)); + bge_ape_lock(bgep, BGE_APE_LOCK_GRC); + #ifdef BGE_IPMI_ASF if (!bgep->asf_enabled) { #endif @@ -3468,8 +4019,23 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) } #endif + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { + bge_reg_set32(bgep, FAST_BOOT_PC, 0); + if (!bge_chip_enable_engine(bgep, MEMORY_ARBITER_MODE_REG, 0)) + retval = DDI_FAILURE; + } + + mhcr = mhcr_base; +#ifdef _BIG_ENDIAN + mhcr |= (MHCR_ENABLE_ENDIAN_WORD_SWAP | + MHCR_ENABLE_ENDIAN_BYTE_SWAP); +#endif + pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcr); + if (!bge_chip_reset_engine(bgep, MISC_CONFIG_REG)) retval = DDI_FAILURE; + bge_chip_cfg_init(bgep, &chipid, enable_dma); /* @@ -3485,7 +4051,6 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) (bgep->chipid.chip_label == 5906)) bge_reg_set32(bgep, TLP_CONTROL_REG, TLP_DATA_FIFO_PROTECT); - /* * Step 9: enable MAC memory arbiter,bit30 and bit31 of 5714/5715 should * not be changed. @@ -3502,17 +4067,15 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) * Steps 14-15: Configure DMA endianness options. See * the comments on the setting of the MHCR above. */ -#ifdef _BIG_ENDIAN - modeflags = MODE_WORD_SWAP_FRAME | MODE_BYTE_SWAP_FRAME | - MODE_WORD_SWAP_NONFRAME | MODE_BYTE_SWAP_NONFRAME; -#else - modeflags = MODE_WORD_SWAP_FRAME | MODE_BYTE_SWAP_FRAME; -#endif /* _BIG_ENDIAN */ + tmp = MODE_WORD_SWAP_FRAME | MODE_BYTE_SWAP_FRAME; +#ifdef _BIG_ENDIAN + tmp |= (MODE_WORD_SWAP_NONFRAME | MODE_BYTE_SWAP_NONFRAME); +#endif #ifdef BGE_IPMI_ASF if (bgep->asf_enabled) - modeflags |= MODE_HOST_STACK_UP; + tmp |= MODE_HOST_STACK_UP; #endif - bge_reg_put32(bgep, MODE_CONTROL_REG, modeflags); + bge_reg_put32(bgep, MODE_CONTROL_REG, tmp); #ifdef BGE_IPMI_ASF if (bgep->asf_enabled) { @@ -3564,11 +4127,20 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) #endif } #endif + + bge_ape_unlock(bgep, BGE_APE_LOCK_GRC); + /* * Steps 16-17: poll for firmware completion */ mac = bge_poll_firmware(bgep); + if (bgep->chipid.device == DEVICE_ID_5720) { + tmp = bge_reg_get32(bgep, CPMU_CLCK_ORIDE_REG); + bge_reg_put32(bgep, CPMU_CLCK_ORIDE_REG, + (tmp & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN)); + } + /* * Step 18: enable external memory -- doesn't apply. * @@ -3585,12 +4157,24 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma) */ bge_reg_put32(bgep, MISC_LOCAL_CONTROL_REG, bgep->chipid.bge_mlcr_default); + + if ((bgep->chipid.flags & CHIP_FLAG_SERDES) && + DEVICE_5714_SERIES_CHIPSETS(bgep)) { + tmp = bge_reg_get32(bgep, SERDES_RX_CONTROL); + tmp |= SERDES_RX_CONTROL_SIG_DETECT; + bge_reg_put32(bgep, SERDES_RX_CONTROL, tmp); + } + bge_reg_set32(bgep, SERIAL_EEPROM_ADDRESS_REG, SEEPROM_ACCESS_INIT); /* * Step 20: clear the Ethernet MAC mode register */ - bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, 0); + if (bgep->ape_enabled) + bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, + ETHERNET_MODE_APE_TX_EN | ETHERNET_MODE_APE_RX_EN); + else + bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, 0); /* * Step 21: restore cache-line-size, latency timer, and @@ -3702,8 +4286,11 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) uint32_t stats_mask; uint32_t dma_wrprio; uint64_t ring; + uint32_t reg; uint32_t regval; + uint32_t mhcr; int retval = DDI_SUCCESS; + int i; BGE_TRACE(("bge_chip_start($%p)", (void *)bgep)); @@ -3711,6 +4298,22 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) ASSERT(mutex_owned(bgep->genlock)); ASSERT(bgep->bge_chip_state == BGE_CHIP_RESET); + /* Initialize EEE, enable MAC control of LPI */ + bge_eee_init(bgep); + + if (bgep->ape_enabled) { + /* + * Allow reads and writes to the + * APE register and memory space. + */ + regval = pci_config_get32(bgep->cfg_handle, + PCI_CONF_BGE_PCISTATE); + regval |= PCISTATE_ALLOW_APE_CTLSPC_WR | + PCISTATE_ALLOW_APE_SHMEM_WR | PCISTATE_ALLOW_APE_PSPACE_WR; + pci_config_put32(bgep->cfg_handle, + PCI_CONF_BGE_PCISTATE, regval); + } + /* * Taken from Broadcom document 570X-PG102-R, pp 102-116. * The document specifies 95 separate steps to fully @@ -3746,6 +4349,37 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) MODE_HOST_SEND_BDS | MODE_HOST_STACK_UP); + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { + reg = (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5762) + ? RDMA_RSRV_CTRL_REG2 : RDMA_RSRV_CTRL_REG; + regval = bge_reg_get32(bgep, reg); + if ((bgep->chipid.device == DEVICE_ID_5719) || + (bgep->chipid.device == DEVICE_ID_5720) || + (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5762)) { + regval &= ~(RDMA_RSRV_CTRL_TXMRGN_MASK | + RDMA_RSRV_CTRL_FIFO_LWM_MASK | + RDMA_RSRV_CTRL_FIFO_HWM_MASK); + regval |= (RDMA_RSRV_CTRL_TXMRGN_320B | + RDMA_RSRV_CTRL_FIFO_LWM_1_5K | + RDMA_RSRV_CTRL_FIFO_HWM_1_5K); + } + /* Enable the DMA FIFO Overrun fix. */ + bge_reg_put32(bgep, reg, + (regval | RDMA_RSRV_CTRL_FIFO_OFLW_FIX)); + + if ((CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5719) || + (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5720) || + (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5762)) { + reg = (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5762) + ? RDMA_CORR_CTRL_REG2 : RDMA_CORR_CTRL_REG; + regval = bge_reg_get32(bgep, reg); + bge_reg_put32(bgep, reg, (regval | + RDMA_CORR_CTRL_BLEN_BD_4K | + RDMA_CORR_CTRL_BLEN_LSO_4K)); + } + } + /* * Step 28: Configure checksum options: * Solaris supports the hardware default checksum options. @@ -3818,16 +4452,23 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) /* * Steps 34-36: enable buffer manager & internal h/w queues */ - if (!bge_chip_enable_engine(bgep, BUFFER_MANAGER_MODE_REG, - STATE_MACHINE_ATTN_ENABLE_BIT)) + regval = STATE_MACHINE_ATTN_ENABLE_BIT; + if (bgep->chipid.device == DEVICE_ID_5719) + regval |= BUFFER_MANAGER_MODE_NO_TX_UNDERRUN; + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) + regval |= BUFFER_MANAGER_MODE_MBLOW_ATTN_ENABLE; + if (!bge_chip_enable_engine(bgep, BUFFER_MANAGER_MODE_REG, regval)) retval = DDI_FAILURE; + if (!bge_chip_enable_engine(bgep, FTQ_RESET_REG, 0)) retval = DDI_FAILURE; /* * Steps 37-39: initialise Receive Buffer (Producer) RCBs */ - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) { + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { buff_ring_t *brp = &bgep->buff[BGE_STD_BUFF_RING]; bge_reg_put64(bgep, STD_RCV_BD_RING_RCB_REG, brp->desc.cookie.dmac_laddress); @@ -3926,7 +4567,7 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) */ bge_reg_put32(bgep, RCV_LP_CONFIG_REG, RCV_LP_CONFIG(bgep->chipid.rx_rings)); - switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) { + switch (MHCR_CHIP_ASIC_REV(bgep)) { case MHCR_CHIP_ASIC_REV_5700: case MHCR_CHIP_ASIC_REV_5701: case MHCR_CHIP_ASIC_REV_5703: @@ -4008,12 +4649,28 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) * Receive List selector.Pay attention:0x3400 is not exist in BCM5714 * and BCM5715. */ + + if (bgep->chipid.device == DEVICE_ID_5719) { + for (i = 0; i < BGE_NUM_RDMA_CHANNELS; i++) { + if (bge_reg_get32(bgep, (BGE_RDMA_LENGTH + (i << 2))) > + bgep->chipid.default_mtu) + break; + } + if (i < BGE_NUM_RDMA_CHANNELS) { + regval = bge_reg_get32(bgep, RDMA_CORR_CTRL_REG); + regval |= RDMA_CORR_CTRL_TX_LENGTH_WA; + bge_reg_put32(bgep, RDMA_CORR_CTRL_REG, regval); + bgep->rdma_length_bug_on_5719 = B_TRUE; + } + } + if (bgep->chipid.tx_rings <= COALESCE_64_BYTE_RINGS && bgep->chipid.rx_rings <= COALESCE_64_BYTE_RINGS) coalmode = COALESCE_64_BYTE_STATUS; else coalmode = 0; - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) coalmode = COALESCE_CLR_TICKS_RX; if (!bge_chip_enable_engine(bgep, HOST_COALESCE_MODE_REG, coalmode)) retval = DDI_FAILURE; @@ -4032,6 +4689,11 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) * Step 72: Enable MAC DMA engines * Step 73: Clear & enable MAC statistics */ + if (bgep->ape_enabled) { + /* XXX put32 instead of set32 ? */ + bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, + ETHERNET_MODE_APE_TX_EN | ETHERNET_MODE_APE_RX_EN); + } bge_reg_set32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_ENABLE_FHDE | ETHERNET_MODE_ENABLE_RDE | @@ -4042,6 +4704,14 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) ETHERNET_MODE_CLEAR_TX_STATS | ETHERNET_MODE_CLEAR_RX_STATS); + drv_usecwait(140); + + if (bgep->ape_enabled) { + /* Write our heartbeat update interval to APE. */ + bge_ape_put32(bgep, BGE_APE_HOST_HEARTBEAT_INT_MS, + APE_HOST_HEARTBEAT_INT_DISABLE); + } + /* * Step 74: configure the MLCR (Miscellaneous Local Control * Register); not required, as we set up the MLCR in step 10 @@ -4068,23 +4738,28 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) retval = DDI_FAILURE; dma_wrprio = (bge_dma_wrprio << DMA_PRIORITY_SHIFT) | ALL_DMA_ATTN_BITS; - if ((MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) == - MHCR_CHIP_ASIC_REV_5755) || - (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) == - MHCR_CHIP_ASIC_REV_5723) || - (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) == - MHCR_CHIP_ASIC_REV_5906)) { + /* the 5723 check here covers all newer chip families (OK) */ + if ((MHCR_CHIP_ASIC_REV(bgep) == MHCR_CHIP_ASIC_REV_5755) || + (MHCR_CHIP_ASIC_REV(bgep) == MHCR_CHIP_ASIC_REV_5723) || + (MHCR_CHIP_ASIC_REV(bgep) == MHCR_CHIP_ASIC_REV_5906)) { dma_wrprio |= DMA_STATUS_TAG_FIX_CQ12384; } if (!bge_chip_enable_engine(bgep, WRITE_DMA_MODE_REG, dma_wrprio)) retval = DDI_FAILURE; + + drv_usecwait(40); + if (DEVICE_5723_SERIES_CHIPSETS(bgep) || - DEVICE_5717_SERIES_CHIPSETS(bgep)) + DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) bge_dma_rdprio = 0; if (!bge_chip_enable_engine(bgep, READ_DMA_MODE_REG, (bge_dma_rdprio << DMA_PRIORITY_SHIFT) | ALL_DMA_ATTN_BITS)) retval = DDI_FAILURE; + + drv_usecwait(40); + if (!bge_chip_enable_engine(bgep, RCV_DATA_COMPLETION_MODE_REG, STATE_MACHINE_ATTN_ENABLE_BIT)) retval = DDI_FAILURE; @@ -4112,12 +4787,21 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) STATE_MACHINE_ATTN_ENABLE_BIT)) retval = DDI_FAILURE; + drv_usecwait(40); + /* * Step 88: download firmware -- doesn't apply * Steps 89-90: enable Transmit & Receive MAC Engines */ - if (!bge_chip_enable_engine(bgep, TRANSMIT_MAC_MODE_REG, 0)) + regval = 0; + if (DEVICE_5717_SERIES_CHIPSETS(bgep)) { + regval |= TRANSMIT_MODE_MBUF_LOCKUP_FIX; + } + if (!bge_chip_enable_engine(bgep, TRANSMIT_MAC_MODE_REG, regval)) retval = DDI_FAILURE; + + drv_usecwait(100); + #ifdef BGE_IPMI_ASF if (!bgep->asf_enabled) { if (!bge_chip_enable_engine(bgep, RECEIVE_MAC_MODE_REG, @@ -4133,6 +4817,8 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) retval = DDI_FAILURE; #endif + drv_usecwait(100); + /* * Step 91: disable auto-polling of PHY status */ @@ -4169,8 +4855,16 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) * restart autoneg (if required) */ if (reset_phys) + { if (bge_phys_update(bgep) == DDI_FAILURE) retval = DDI_FAILURE; + /* forcing a mac link update here */ + bge_phys_check(bgep); + bgep->link_state = (bgep->param_link_up) ? LINK_STATE_UP : + LINK_STATE_DOWN; + bge_sync_mac_modes(bgep); + mac_link_update(bgep->mh, bgep->link_state); + } /* * Extra step (DSG): hand over all the Receive Buffers to the chip @@ -4213,6 +4907,17 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys) } #endif + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { + bge_cfg_clr16(bgep, PCI_CONF_DEV_CTRL_5717, + DEV_CTRL_NO_SNOOP | DEV_CTRL_RELAXED); +#if 0 + mhcr = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR); + pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, + (mhcr | MHCR_TLP_MINOR_ERR_TOLERANCE)); +#endif + } + /* * Step 97: enable PCI interrupts!!! */ @@ -4283,6 +4988,53 @@ bge_wake_factotum(bge_t *bgep) mutex_exit(bgep->softintrlock); } +static void +bge_intr_error_handler(bge_t *bgep) +{ + uint32_t flow; + uint32_t rdma; + uint32_t wdma; + uint32_t tmac; + uint32_t rmac; + uint32_t rxrs; + uint32_t emac; + uint32_t msis; + uint32_t txrs = 0; + + ASSERT(mutex_owned(bgep->genlock)); + + /* + * Read all the registers that show the possible + * reasons for the ERROR bit to be asserted + */ + flow = bge_reg_get32(bgep, FLOW_ATTN_REG); + rdma = bge_reg_get32(bgep, READ_DMA_STATUS_REG); + wdma = bge_reg_get32(bgep, WRITE_DMA_STATUS_REG); + tmac = bge_reg_get32(bgep, TRANSMIT_MAC_STATUS_REG); + rmac = bge_reg_get32(bgep, RECEIVE_MAC_STATUS_REG); + rxrs = bge_reg_get32(bgep, RX_RISC_STATE_REG); + emac = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG); + msis = bge_reg_get32(bgep, MSI_STATUS_REG); + if (DEVICE_5704_SERIES_CHIPSETS(bgep)) + txrs = bge_reg_get32(bgep, TX_RISC_STATE_REG); + + BGE_DEBUG(("factotum($%p) flow 0x%x rdma 0x%x wdma 0x%x emac 0x%x msis 0x%x", + (void *)bgep, flow, rdma, wdma, emac, msis)); + BGE_DEBUG(("factotum($%p) tmac 0x%x rmac 0x%x rxrs 0x%08x txrs 0x%08x", + (void *)bgep, tmac, rmac, rxrs, txrs)); + + /* + * For now, just clear all the errors ... + */ + if (DEVICE_5704_SERIES_CHIPSETS(bgep)) + bge_reg_put32(bgep, TX_RISC_STATE_REG, ~0); + bge_reg_put32(bgep, RX_RISC_STATE_REG, ~0); + bge_reg_put32(bgep, RECEIVE_MAC_STATUS_REG, ~0); + bge_reg_put32(bgep, WRITE_DMA_STATUS_REG, ~0); + bge_reg_put32(bgep, READ_DMA_STATUS_REG, ~0); + bge_reg_put32(bgep, FLOW_ATTN_REG, ~0); +} + /* * bge_intr() -- handle chip interrupts */ @@ -4320,7 +5072,8 @@ bge_intr(caddr_t arg1, caddr_t arg2) * bit is *zero* when the interrupt is asserted. */ regval = bge_reg_get32(bgep, MISC_LOCAL_CONTROL_REG); - if (!(DEVICE_5717_SERIES_CHIPSETS(bgep)) && + if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) && (regval & MLCR_INTA_STATE)) { if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) @@ -4372,8 +5125,9 @@ bge_intr(caddr_t arg1, caddr_t arg2) mutex_exit(bgep->genlock); return (DDI_INTR_CLAIMED); } - retval = bge_status_sync(bgep, STATUS_FLAG_UPDATED, - &flags); + + retval = bge_status_sync(bgep, STATUS_FLAG_UPDATED | + STATUS_FLAG_LINK_CHANGED | STATUS_FLAG_ERROR, &flags); if (retval != DDI_FM_OK) { bgep->bge_dma_error = B_TRUE; goto chip_stop; @@ -4391,6 +5145,28 @@ bge_intr(caddr_t arg1, caddr_t arg2) DDI_FM_OK) goto chip_stop; + if (flags & STATUS_FLAG_LINK_CHANGED) { + BGE_DEBUG(("bge_intr($%p) ($%p) link event", arg1, arg2)); + if (bge_phys_check(bgep)) { + bgep->link_state = bgep->param_link_up ? + LINK_STATE_UP : LINK_STATE_DOWN; + bge_sync_mac_modes(bgep); + mac_link_update(bgep->mh, bgep->link_state); + } + + if (bge_check_acc_handle(bgep, bgep->io_handle) != + DDI_FM_OK) + goto chip_stop; + } + + if (flags & STATUS_FLAG_ERROR) { + bge_intr_error_handler(bgep); + + if (bge_check_acc_handle(bgep, bgep->io_handle) != + DDI_FM_OK) + goto chip_stop; + } + /* * Drop the mutex while we: * Receive any newly-arrived packets @@ -4421,15 +5197,6 @@ bge_intr(caddr_t arg1, caddr_t arg2) bgep->missed_dmas = 0; } - /* - * Check for exceptional conditions that we need to handle - * - * Link status changed - * Status block not updated - */ - if (flags & STATUS_FLAG_LINK_CHANGED) - bge_wake_factotum(bgep); - if (bgep->missed_dmas) { /* * Probably due to the internal status tag not @@ -4481,6 +5248,7 @@ bge_intr(caddr_t arg1, caddr_t arg2) return (result); chip_stop: + #ifdef BGE_IPMI_ASF if (bgep->asf_enabled && bgep->asf_status == ASF_STAT_RUN) { /* @@ -4510,157 +5278,6 @@ chip_stop: #undef BGE_DBG #define BGE_DBG BGE_DBG_FACT /* debug flag for this code */ -static void bge_factotum_error_handler(bge_t *bgep); -#pragma no_inline(bge_factotum_error_handler) - -static void -bge_factotum_error_handler(bge_t *bgep) -{ - uint32_t flow; - uint32_t rdma; - uint32_t wdma; - uint32_t tmac; - uint32_t rmac; - uint32_t rxrs; - uint32_t txrs = 0; - - ASSERT(mutex_owned(bgep->genlock)); - - /* - * Read all the registers that show the possible - * reasons for the ERROR bit to be asserted - */ - flow = bge_reg_get32(bgep, FLOW_ATTN_REG); - rdma = bge_reg_get32(bgep, READ_DMA_STATUS_REG); - wdma = bge_reg_get32(bgep, WRITE_DMA_STATUS_REG); - tmac = bge_reg_get32(bgep, TRANSMIT_MAC_STATUS_REG); - rmac = bge_reg_get32(bgep, RECEIVE_MAC_STATUS_REG); - rxrs = bge_reg_get32(bgep, RX_RISC_STATE_REG); - if (DEVICE_5704_SERIES_CHIPSETS(bgep)) - txrs = bge_reg_get32(bgep, TX_RISC_STATE_REG); - - BGE_DEBUG(("factotum($%p) flow 0x%x rdma 0x%x wdma 0x%x", - (void *)bgep, flow, rdma, wdma)); - BGE_DEBUG(("factotum($%p) tmac 0x%x rmac 0x%x rxrs 0x%08x txrs 0x%08x", - (void *)bgep, tmac, rmac, rxrs, txrs)); - - /* - * For now, just clear all the errors ... - */ - if (DEVICE_5704_SERIES_CHIPSETS(bgep)) - bge_reg_put32(bgep, TX_RISC_STATE_REG, ~0); - bge_reg_put32(bgep, RX_RISC_STATE_REG, ~0); - bge_reg_put32(bgep, RECEIVE_MAC_STATUS_REG, ~0); - bge_reg_put32(bgep, WRITE_DMA_STATUS_REG, ~0); - bge_reg_put32(bgep, READ_DMA_STATUS_REG, ~0); - bge_reg_put32(bgep, FLOW_ATTN_REG, ~0); -} - -/* - * Handler for hardware link state change. - * - * When this routine is called, the hardware link state has changed - * and the new state is reflected in the param_* variables. Here - * we must update the softstate and reprogram the MAC to match. - */ -static void bge_factotum_link_handler(bge_t *bgep); -#pragma no_inline(bge_factotum_link_handler) - -static void -bge_factotum_link_handler(bge_t *bgep) -{ - ASSERT(mutex_owned(bgep->genlock)); - - /* - * Update the s/w link_state - */ - if (bgep->param_link_up) - bgep->link_state = LINK_STATE_UP; - else - bgep->link_state = LINK_STATE_DOWN; - - /* - * Reprogram the MAC modes to match - */ - bge_sync_mac_modes(bgep); -} - -static boolean_t bge_factotum_link_check(bge_t *bgep, int *dma_state); -#pragma no_inline(bge_factotum_link_check) - -static boolean_t -bge_factotum_link_check(bge_t *bgep, int *dma_state) -{ - boolean_t check; - uint64_t flags; - uint32_t tmac_status; - - ASSERT(mutex_owned(bgep->genlock)); - - /* - * Get & clear the writable status bits in the Tx status register - * (some bits are write-1-to-clear, others are just readonly). - */ - tmac_status = bge_reg_get32(bgep, TRANSMIT_MAC_STATUS_REG); - bge_reg_put32(bgep, TRANSMIT_MAC_STATUS_REG, tmac_status); - - /* - * Get & clear the ERROR and LINK_CHANGED bits from the status block - */ - *dma_state = bge_status_sync(bgep, STATUS_FLAG_ERROR | - STATUS_FLAG_LINK_CHANGED, &flags); - if (*dma_state != DDI_FM_OK) - return (B_FALSE); - - /* - * Clear any errors flagged in the status block ... - */ - if (flags & STATUS_FLAG_ERROR) - bge_factotum_error_handler(bgep); - - /* - * We need to check the link status if: - * the status block says there's been a link change - * or there's any discrepancy between the various - * flags indicating the link state (link_state, - * param_link_up, and the LINK STATE bit in the - * Transmit MAC status register). - */ - check = (flags & STATUS_FLAG_LINK_CHANGED) != 0; - switch (bgep->link_state) { - case LINK_STATE_UP: - check |= (bgep->param_link_up == B_FALSE); - check |= ((tmac_status & TRANSMIT_STATUS_LINK_UP) == 0); - break; - - case LINK_STATE_DOWN: - check |= (bgep->param_link_up != B_FALSE); - check |= ((tmac_status & TRANSMIT_STATUS_LINK_UP) != 0); - break; - - default: - check = B_TRUE; - break; - } - - /* - * If is false, we're sure the link hasn't changed. - * If true, however, it's not yet definitive; we have to call - * bge_phys_check() to determine whether the link has settled - * into a new state yet ... and if it has, then call the link - * state change handler.But when the chip is 5700 in Dell 6650 - * ,even if check is false, the link may have changed.So we - * have to call bge_phys_check() to determine the link state. - */ - if (check || bgep->chipid.device == DEVICE_ID_5700) { - check = bge_phys_check(bgep); - if (check) - bge_factotum_link_handler(bgep); - } - - return (check); -} - /* * Factotum routine to check for Tx stall, using the 'watchdog' counter */ @@ -4710,9 +5327,7 @@ bge_factotum_stall_check(bge_t *bgep) /* * The factotum is woken up when there's something to do that we'd rather * not do from inside a hardware interrupt handler or high-level cyclic. - * Its two main tasks are: - * reset & restart the chip after an error - * check the link status whenever necessary + * Its main task is to reset & restart the chip after an error. */ uint_t bge_chip_factotum(caddr_t arg); #pragma no_inline(bge_chip_factotum) @@ -4723,7 +5338,6 @@ bge_chip_factotum(caddr_t arg) bge_t *bgep; uint_t result; boolean_t error; - boolean_t linkchg; int dma_state; bgep = (void *)arg; @@ -4740,7 +5354,6 @@ bge_chip_factotum(caddr_t arg) result = DDI_INTR_CLAIMED; error = B_FALSE; - linkchg = B_FALSE; mutex_enter(bgep->genlock); switch (bgep->bge_chip_state) { @@ -4748,7 +5361,16 @@ bge_chip_factotum(caddr_t arg) break; case BGE_CHIP_RUNNING: - linkchg = bge_factotum_link_check(bgep, &dma_state); + + if (bgep->chipid.device == DEVICE_ID_5700) { + if (bge_phys_check(bgep)) { + bgep->link_state = (bgep->param_link_up) ? + LINK_STATE_UP : LINK_STATE_DOWN; + bge_sync_mac_modes(bgep); + mac_link_update(bgep->mh, bgep->link_state); + } + } + error = bge_factotum_stall_check(bgep); if (dma_state != DDI_FM_OK) { bgep->bge_dma_error = B_TRUE; @@ -4827,7 +5449,6 @@ bge_chip_factotum(caddr_t arg) break; } - /* * If an error is detected, stop the chip now, marking it as * faulty, so that it will be reset next time through ... @@ -4857,25 +5478,6 @@ bge_chip_factotum(caddr_t arg) } mutex_exit(bgep->genlock); - /* - * If the link state changed, tell the world about it. - * Note: can't do this while still holding the mutex. - */ - if (bgep->link_update_timer == BGE_LINK_UPDATE_TIMEOUT && - bgep->link_state != LINK_STATE_UNKNOWN) - linkchg = B_TRUE; - else if (bgep->link_update_timer < BGE_LINK_UPDATE_TIMEOUT && - bgep->link_state == LINK_STATE_DOWN) - linkchg = B_FALSE; - - if (linkchg) { - mac_link_update(bgep->mh, bgep->link_state); - bgep->link_update_timer = BGE_LINK_UPDATE_DONE; - } - if (bgep->manual_reset) { - bgep->manual_reset = B_FALSE; - } - return (result); } @@ -4893,6 +5495,7 @@ void bge_chip_cyclic(void *arg) { bge_t *bgep; + uint32_t regval; bgep = arg; @@ -4901,22 +5504,44 @@ bge_chip_cyclic(void *arg) return; case BGE_CHIP_RUNNING: + + /* XXX I really don't like this forced interrupt... */ bge_reg_set32(bgep, HOST_COALESCE_MODE_REG, COALESCE_NOW); if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED); - if (bgep->link_update_timer < BGE_LINK_UPDATE_TIMEOUT) - bgep->link_update_timer++; - break; case BGE_CHIP_FAULT: case BGE_CHIP_ERROR: + break; } + mutex_enter(bgep->genlock); + + if (bgep->eee_lpi_wait && !--bgep->eee_lpi_wait) { + BGE_DEBUG(("eee cyclic, lpi enabled")); + bge_eee_enable(bgep); + } + + if (bgep->rdma_length_bug_on_5719) { + if ((bge_reg_get32(bgep, STAT_IFHCOUT_UPKGS_REG) + + bge_reg_get32(bgep, STAT_IFHCOUT_MPKGS_REG) + + bge_reg_get32(bgep, STAT_IFHCOUT_BPKGS_REG)) > + BGE_NUM_RDMA_CHANNELS) { + regval = bge_reg_get32(bgep, RDMA_CORR_CTRL_REG); + regval &= ~RDMA_CORR_CTRL_TX_LENGTH_WA; + bge_reg_put32(bgep, RDMA_CORR_CTRL_REG, regval); + bgep->rdma_length_bug_on_5719 = B_FALSE; + } + } + + mutex_exit(bgep->genlock); + bge_wake_factotum(bgep); + } @@ -5784,8 +6409,10 @@ bge_nic_read32(bge_t *bgep, bge_regno_t addr) addr = addr + 4; } #else - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { addr = LE_32(addr); + } #endif pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MWBAR, addr); @@ -5925,6 +6552,10 @@ bge_asf_pre_reset_operations(bge_t *bgep, uint32_t mode) break; } } + + if (mode == BGE_INIT_RESET || + mode == BGE_SUSPEND_RESET) + bge_ape_driver_state_change(bgep, mode); } @@ -5965,6 +6596,9 @@ bge_asf_post_reset_new_mode(bge_t *bgep, uint32_t mode) default: break; } + + if (mode == BGE_SHUTDOWN_RESET) + bge_ape_driver_state_change(bgep, mode); } #endif /* BGE_IPMI_ASF */ diff --git a/usr/src/uts/common/io/bge/bge_hw.h b/usr/src/uts/common/io/bge/bge_hw.h index f8e6c4d..506b977 100644 --- a/usr/src/uts/common/io/bge/bge_hw.h +++ b/usr/src/uts/common/io/bge/bge_hw.h @@ -20,7 +20,13 @@ */ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010-2013, by Broadcom, Inc. + * All Rights Reserved. + */ + +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. + * All rights reserved. */ #ifndef _BGE_HW_H @@ -64,8 +70,13 @@ extern "C" { #define DEVICE_ID_5705C 0x1653 #define DEVICE_ID_5705_2 0x1654 #define DEVICE_ID_5717 0x1655 +#define DEVICE_ID_5717_C0 0x1665 #define DEVICE_ID_5718 0x1656 +#define DEVICE_ID_5719 0x1657 +#define DEVICE_ID_5720 0x165f #define DEVICE_ID_5724 0x165c +#define DEVICE_ID_5725 0x1643 +#define DEVICE_ID_5727 0x16f3 #define DEVICE_ID_5705M 0x165d #define DEVICE_ID_5705MA3 0x165e #define DEVICE_ID_5705F 0x166e @@ -187,9 +198,15 @@ extern "C" { (bgep->chipid.device == DEVICE_ID_5789)) #define DEVICE_5717_SERIES_CHIPSETS(bgep) \ - (bgep->chipid.device == DEVICE_ID_5717) ||\ + ((bgep->chipid.device == DEVICE_ID_5717) ||\ (bgep->chipid.device == DEVICE_ID_5718) ||\ - (bgep->chipid.device == DEVICE_ID_5724) + (bgep->chipid.device == DEVICE_ID_5719) ||\ + (bgep->chipid.device == DEVICE_ID_5720) ||\ + (bgep->chipid.device == DEVICE_ID_5724)) + +#define DEVICE_5725_SERIES_CHIPSETS(bgep) \ + ((bgep->chipid.device == DEVICE_ID_5725) ||\ + (bgep->chipid.device == DEVICE_ID_5727)) #define DEVICE_5723_SERIES_CHIPSETS(bgep) \ ((bgep->chipid.device == DEVICE_ID_5723) ||\ @@ -230,11 +247,13 @@ extern "C" { #define MHCR_ENABLE_INDIRECT_ACCESS 0x00000080 #define MHCR_ENABLE_REGISTER_WORD_SWAP 0x00000040 #define MHCR_ENABLE_CLOCK_CONTROL_WRITE 0x00000020 -#define MHCR_ENABLE_PCI_STATE_WRITE 0x00000010 +#define MHCR_ENABLE_PCI_STATE_RW 0x00000010 #define MHCR_ENABLE_ENDIAN_WORD_SWAP 0x00000008 #define MHCR_ENABLE_ENDIAN_BYTE_SWAP 0x00000004 #define MHCR_MASK_PCI_INT_OUTPUT 0x00000002 #define MHCR_CLEAR_INTERRUPT_INTA 0x00000001 +#define MHCR_BOUNDARY_CHECK 0x00002000 +#define MHCR_TLP_MINOR_ERR_TOLERANCE 0x00008000 #define MHCR_CHIP_REV_5700_B0 0x71000000 #define MHCR_CHIP_REV_5700_B2 0x71020000 @@ -304,12 +323,11 @@ extern "C" { #define MHCR_CHIP_REV_5906_A1 0xc0010000 #define MHCR_CHIP_REV_5906_A2 0xc0020000 -#define MHCR_CHIP_REV_5723_A0 0xf0000000 -#define MHCR_CHIP_REV_5723_A1 0xf0010000 -#define MHCR_CHIP_REV_5723_A2 0xf0020000 -#define MHCR_CHIP_REV_5723_B0 0xf1000000 +#define CHIP_ASIC_REV_USE_PROD_ID_REG 0xf0000000 +#define MHCR_CHIP_ASIC_REV(bgep) ((bgep)->chipid.asic_rev & 0xf0000000) +#define CHIP_ASIC_REV_PROD_ID(bgep) ((bgep)->chipid.asic_rev_prod_id) +#define CHIP_ASIC_REV(bgep) ((bgep)->chipid.asic_rev_prod_id >> 12) -#define MHCR_CHIP_ASIC_REV(ChipRevId) ((ChipRevId) & 0xf0000000) #define MHCR_CHIP_ASIC_REV_5700 (0x7 << 28) #define MHCR_CHIP_ASIC_REV_5701 (0x0 << 28) #define MHCR_CHIP_ASIC_REV_5703 (0x1 << 28) @@ -323,8 +341,30 @@ extern "C" { #define MHCR_CHIP_ASIC_REV_5755 ((uint32_t)0xa << 28) #define MHCR_CHIP_ASIC_REV_5715 ((uint32_t)0x9 << 28) #define MHCR_CHIP_ASIC_REV_5906 ((uint32_t)0xc << 28) +/* (0xf << 28) touches all 5717 and 5725 series as well (OK) */ #define MHCR_CHIP_ASIC_REV_5723 ((uint32_t)0xf << 28) +#define CHIP_ASIC_REV_5723 0x5784 +#define CHIP_ASIC_REV_5761 0x5761 +#define CHIP_ASIC_REV_5785 0x5785 +#define CHIP_ASIC_REV_57780 0x57780 + +#define CHIP_ASIC_REV_5717 0x5717 +#define CHIP_ASIC_REV_5719 0x5719 +#define CHIP_ASIC_REV_5720 0x5720 +#define CHIP_ASIC_REV_5762 0x5762 /* 5725/5727 */ + +#define CHIP_ASIC_REV_PROD_ID_REG 0x000000bc +#define CHIP_ASIC_REV_PROD_ID_GEN2_REG 0x000000f4 + +#define CHIP_ASIC_REV_5717_B0 0x05717100 +#define CHIP_ASIC_REV_5717_C0 0x05717200 +#define CHIP_ASIC_REV_5718_B0 0x05717100 +#define CHIP_ASIC_REV_5719_A0 0x05719000 +#define CHIP_ASIC_REV_5719_A1 0x05719001 +#define CHIP_ASIC_REV_5720_A0 0x05720000 +#define CHIP_ASIC_REV_5725_A0 0x05762000 +#define CHIP_ASIC_REV_5727_B0 0x05762100 /* * PCI DMA read/write Control Register, in PCI config space @@ -374,6 +414,9 @@ extern "C" { * is set in the MHCR, EXCEPT for the RETRY_SAME_DMA bit which is always RW */ #define PCI_CONF_BGE_PCISTATE 0x70 +#define PCISTATE_ALLOW_APE_CTLSPC_WR 0x00010000 +#define PCISTATE_ALLOW_APE_SHMEM_WR 0x00020000 +#define PCISTATE_ALLOW_APE_PSPACE_WR 0x00040000 #define PCISTATE_RETRY_SAME_DMA 0x00002000 #define PCISTATE_FLAT_VIEW 0x00000100 #define PCISTATE_EXT_ROM_RETRY 0x00000040 @@ -458,7 +501,10 @@ extern "C" { */ #define PCI_CONF_DEV_CTRL 0xd8 #define PCI_CONF_DEV_CTRL_5723 0xd4 +#define PCI_CONF_DEV_CTRL_5717 0xb4 +#define READ_REQ_SIZE_MASK 0x7000 #define READ_REQ_SIZE_MAX 0x5000 +#define READ_REQ_SIZE_2K 0x4000 #define DEV_CTRL_NO_SNOOP 0x0800 #define DEV_CTRL_RELAXED 0x0010 @@ -497,7 +543,7 @@ extern "C" { #define NIC_MEM_SHADOW_SEND_7_8 0x7000 /* bogus */ #define NIC_MEM_SHADOW_SEND_9_16 0x8000 /* bogus */ #define NIC_MEM_SHADOW_BUFF_STD 0x6000 -#define NIC_MEM_SHADOW_BUFF_STD_5717 0x40000 +#define NIC_MEM_SHADOW_BUFF_STD_5717 0x40000 #define NIC_MEM_SHADOW_BUFF_JUMBO 0x7000 #define NIC_MEM_SHADOW_BUFF_MINI 0x8000 /* bogus */ #define NIC_MEM_SHADOW_SEND_RING(ring, nslots) (0x4000 + 4*(ring)*(nslots)) @@ -540,9 +586,31 @@ extern "C" { #define HOST_COALESCE_MODE_REG 0x3c00 #define MEMORY_ARBITER_MODE_REG 0x4000 #define BUFFER_MANAGER_MODE_REG 0x4400 +#define BUFFER_MANAGER_MODE_NO_TX_UNDERRUN 0x80000000 +#define BUFFER_MANAGER_MODE_MBLOW_ATTN_ENABLE 0x00000010 #define READ_DMA_MODE_REG 0x4800 #define WRITE_DMA_MODE_REG 0x4c00 #define DMA_COMPLETION_MODE_REG 0x6400 +#define FAST_BOOT_PC 0x6894 + +#define RDMA_RSRV_CTRL_REG 0x4900 +#define RDMA_RSRV_CTRL_REG2 0x4890 +#define RDMA_RSRV_CTRL_FIFO_OFLW_FIX 0x00000004 +#define RDMA_RSRV_CTRL_FIFO_LWM_1_5K 0x00000c00 +#define RDMA_RSRV_CTRL_FIFO_LWM_MASK 0x00000ff0 +#define RDMA_RSRV_CTRL_FIFO_HWM_1_5K 0x000c0000 +#define RDMA_RSRV_CTRL_FIFO_HWM_MASK 0x000ff000 +#define RDMA_RSRV_CTRL_TXMRGN_320B 0x28000000 +#define RDMA_RSRV_CTRL_TXMRGN_MASK 0xffe00000 + +#define RDMA_CORR_CTRL_REG 0x4910 +#define RDMA_CORR_CTRL_REG2 0x48a0 +#define RDMA_CORR_CTRL_BLEN_BD_4K 0x00030000 +#define RDMA_CORR_CTRL_BLEN_LSO_4K 0x000c0000 +#define RDMA_CORR_CTRL_TX_LENGTH_WA 0x02000000 + +#define BGE_NUM_RDMA_CHANNELS 4 +#define BGE_RDMA_LENGTH 0x4be0 /* * Other bits in some of the above state machine control registers @@ -552,6 +620,7 @@ extern "C" { * Transmit MAC Mode Register * (TRANSMIT_MAC_MODE_REG, 0x045c) */ +#define TRANSMIT_MODE_MBUF_LOCKUP_FIX 0x00000100 #define TRANSMIT_MODE_LONG_PAUSE 0x00000040 #define TRANSMIT_MODE_BIG_BACKOFF 0x00000020 #define TRANSMIT_MODE_FLOW_CONTROL 0x00000010 @@ -682,6 +751,8 @@ extern "C" { * Ethernet MAC Mode Register */ #define ETHERNET_MAC_MODE_REG 0x0400 +#define ETHERNET_MODE_APE_TX_EN 0x10000000 +#define ETHERNET_MODE_APE_RX_EN 0x08000000 #define ETHERNET_MODE_ENABLE_FHDE 0x00800000 #define ETHERNET_MODE_ENABLE_RDE 0x00400000 #define ETHERNET_MODE_ENABLE_TDE 0x00200000 @@ -970,8 +1041,12 @@ extern "C" { #define SERDES_STATUS_COMMA_DETECTED 0x00000100 #define SERDES_STATUS_RXSTAT 0x000000ff +/* 5780/5714 only */ +#define SERDES_RX_CONTROL 0x000005b0 +#define SERDES_RX_CONTROL_SIG_DETECT 0x00000400 + /* - * SGMII Status Register (5717/5718 only) + * SGMII Status Register (5717/18/19/20 only) */ #define SGMII_STATUS_REG 0x5B4 #define MEDIA_SELECTION_MODE 0x00000100 @@ -1069,10 +1144,53 @@ extern "C" { #define JUMBO_RCV_BD_REPLENISH_DEFAULT 0x00000020 /* 32 */ /* - * CPMU registers (5717/5718 only) + * CPMU registers (5717/18/19/20 only) + */ +#define CPMU_CLCK_ORIDE_REG 0x3624 +#define CPMU_CLCK_ORIDE_MAC_ORIDE_EN 0x80000000 +#define CPMU_STATUS_REG 0x362c +#define CPMU_STATUS_FUNC_NUM 0x20000000 +#define CPMU_STATUS_FUNC_NUM_SHIFT 29 +#define CPMU_STATUS_FUNC_NUM_5719 0xc0000000 +#define CPMU_STATUS_FUNC_NUM_5719_SHIFT 30 + +/* + * EEE registers (5718/19/20 only) */ -#define CPMU_STATUS_REG 0x362c -#define CPMU_STATUS_FUN_NUM 0x20000000 +#define EEE_MODE_REG 0x36b0 +#define EEE_MODE_APE_TX_DET_EN 0x00000004 +#define EEE_MODE_ERLY_L1_XIT_DET 0x00000008 +#define EEE_MODE_SND_IDX_DET_EN 0x00000040 +#define EEE_MODE_LPI_ENABLE 0x00000080 +#define EEE_MODE_LPI_IN_TX 0x00000100 +#define EEE_MODE_LPI_IN_RX 0x00000200 +#define EEE_MODE_EEE_ENABLE 0x00100000 + +#define EEE_DEBOUNCE_T1_CONTROL_REG 0x36b4 +#define EEE_DEBOUNCE_T1_PCIEXIT_2047US 0x07ff0000 +#define EEE_DEBOUNCE_T1_LNKIDLE_2047US 0x000007ff + +#define EEE_DEBOUNCE_T2_CONTROL_REG 0x36b8 +#define EEE_DEBOUNCE_T2_APE_TX_2047US 0x07ff0000 +#define EEE_DEBOUNCE_T2_TXIDXEQ_2047US 0x000007ff + +#define EEE_LINK_IDLE_CONTROL_REG 0x36bc +#define EEE_LINK_IDLE_PCIE_NL0 0x01000000 +#define EEE_LINK_IDLE_UART_IDL 0x00000004 +#define EEE_LINK_IDLE_APE_TX_MT 0x00000002 + +#define EEE_CONTROL_REG 0x36d0 +#define EEE_CONTROL_EXIT_16_5_US 0x0000019d +#define EEE_CONTROL_EXIT_36_US 0x00000384 +#define EEE_CONTROL_EXIT_20_1_US 0x000001f8 + +/* Clause 45 expansion registers */ +#define EEE_CL45_D7_RESULT_STAT 0x803e +#define EEE_CL45_D7_RESULT_STAT_LP_100TX 0x0002 +#define EEE_CL45_D7_RESULT_STAT_LP_1000T 0x0004 + +#define MDIO_MMD_AN 0x0007 +#define MDIO_AN_EEE_ADV 0x003c /* * Host Coalescing Engine Control Registers @@ -1259,25 +1377,43 @@ extern "C" { * Miscellaneous Local Control Register (MLCR) */ #define MISC_LOCAL_CONTROL_REG 0x6808 + #define MLCR_PCI_CTRL_SELECT 0x10000000 #define MLCR_LEGACY_PCI_MODE 0x08000000 #define MLCR_AUTO_SEEPROM_ACCESS 0x01000000 #define MLCR_SSRAM_CYCLE_DESELECT 0x00800000 #define MLCR_SSRAM_TYPE 0x00400000 #define MLCR_BANK_SELECT 0x00200000 + +#define MLCR_SRAM_SIZE_16M 0x00180000 +#define MLCR_SRAM_SIZE_8M 0x00140000 +#define MLCR_SRAM_SIZE_4M 0x00100000 +#define MLCR_SRAM_SIZE_2M 0x000c0000 +#define MLCR_SRAM_SIZE_1M 0x00080000 +#define MLCR_SRAM_SIZE_512K 0x00040000 +#define MLCR_SRAM_SIZE_256K 0x00000000 #define MLCR_SRAM_SIZE_MASK 0x001c0000 -#define MLCR_ENABLE_EXTERNAL_MEMORY 0x00020000 +#define MLCR_ENABLE_EXTERNAL_MEMORY 0x00020000 #define MLCR_MISC_PINS_OUTPUT_2 0x00010000 + #define MLCR_MISC_PINS_OUTPUT_1 0x00008000 #define MLCR_MISC_PINS_OUTPUT_0 0x00004000 #define MLCR_MISC_PINS_OUTPUT_ENABLE_2 0x00002000 #define MLCR_MISC_PINS_OUTPUT_ENABLE_1 0x00001000 + #define MLCR_MISC_PINS_OUTPUT_ENABLE_0 0x00000800 #define MLCR_MISC_PINS_INPUT_2 0x00000400 /* R/O */ #define MLCR_MISC_PINS_INPUT_1 0x00000200 /* R/O */ #define MLCR_MISC_PINS_INPUT_0 0x00000100 /* R/O */ +#define MLCR_GPIO_OUTPUT3 0x00000080 +#define MLCR_GPIO_OE3 0x00000040 +#define MLCR_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */ +#define MLCR_GPIO_INPUT3 0x00000020 +#define MLCR_GPIO_UART_SEL 0x00000010 /* 5755 only */ +#define MLCR_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */ + #define MLCR_INT_ON_ATTN 0x00000008 /* R/W */ #define MLCR_SET_INT 0x00000004 /* W/O */ #define MLCR_CLR_INT 0x00000002 /* W/O */ @@ -1292,9 +1428,20 @@ extern "C" { * just this fashion. It has to be set as an OUTPUT and driven LOW to * enable writing. Otherwise, the SEEPROM is protected. */ -#define MLCR_DEFAULT 0x0101c000 -#define MLCR_DEFAULT_5714 0x1901c000 -#define MLCR_DEFAULT_5717 0x01000000 +#define MLCR_DEFAULT (MLCR_AUTO_SEEPROM_ACCESS | \ + MLCR_MISC_PINS_OUTPUT_2 | \ + MLCR_MISC_PINS_OUTPUT_1 | \ + MLCR_MISC_PINS_OUTPUT_0) + +#define MLCR_DEFAULT_5714 (MLCR_PCI_CTRL_SELECT | \ + MLCR_LEGACY_PCI_MODE | \ + MLCR_AUTO_SEEPROM_ACCESS | \ + MLCR_MISC_PINS_OUTPUT_2 | \ + MLCR_MISC_PINS_OUTPUT_1 | \ + MLCR_MISC_PINS_OUTPUT_0 | \ + MLCR_USE_SIG_DETECT) + +#define MLCR_DEFAULT_5717 (MLCR_AUTO_SEEPROM_ACCESS) /* * Serial EEPROM Data/Address Registers (auto-access mode) @@ -1351,31 +1498,58 @@ extern "C" { #define NVM_CFG1_FLASH_MODE 0x00000001 #define NVM_SW_ARBITRATION_REG 0x7020 -#define NVM_READ_REQ3 0X00008000 -#define NVM_READ_REQ2 0X00004000 -#define NVM_READ_REQ1 0X00002000 -#define NVM_READ_REQ0 0X00001000 -#define NVM_WON_REQ3 0X00000800 -#define NVM_WON_REQ2 0X00000400 -#define NVM_WON_REQ1 0X00000200 -#define NVM_WON_REQ0 0X00000100 -#define NVM_RESET_REQ3 0X00000080 -#define NVM_RESET_REQ2 0X00000040 -#define NVM_RESET_REQ1 0X00000020 -#define NVM_RESET_REQ0 0X00000010 -#define NVM_SET_REQ3 0X00000008 -#define NVM_SET_REQ2 0X00000004 -#define NVM_SET_REQ1 0X00000002 -#define NVM_SET_REQ0 0X00000001 +#define NVM_READ_REQ3 0x00008000 +#define NVM_READ_REQ2 0x00004000 +#define NVM_READ_REQ1 0x00002000 +#define NVM_READ_REQ0 0x00001000 +#define NVM_WON_REQ3 0x00000800 +#define NVM_WON_REQ2 0x00000400 +#define NVM_WON_REQ1 0x00000200 +#define NVM_WON_REQ0 0x00000100 +#define NVM_RESET_REQ3 0x00000080 +#define NVM_RESET_REQ2 0x00000040 +#define NVM_RESET_REQ1 0x00000020 +#define NVM_RESET_REQ0 0x00000010 +#define NVM_SET_REQ3 0x00000008 +#define NVM_SET_REQ2 0x00000004 +#define NVM_SET_REQ1 0x00000002 +#define NVM_SET_REQ0 0x00000001 + +#define EEPROM_MAGIC 0x669955aa +#define EEPROM_MAGIC_FW 0xa5000000 +#define EEPROM_MAGIC_FW_MSK 0xff000000 +#define EEPROM_SB_FORMAT_MASK 0x00e00000 +#define EEPROM_SB_FORMAT_1 0x00200000 +#define EEPROM_SB_REVISION_MASK 0x001f0000 +#define EEPROM_SB_REVISION_0 0x00000000 +#define EEPROM_SB_REVISION_2 0x00020000 +#define EEPROM_SB_REVISION_3 0x00030000 +#define EEPROM_SB_REVISION_4 0x00040000 +#define EEPROM_SB_REVISION_5 0x00050000 +#define EEPROM_SB_REVISION_6 0x00060000 +#define EEPROM_MAGIC_HW 0xabcd +#define EEPROM_MAGIC_HW_MSK 0xffff + +#define NVM_DIR_START 0x18 +#define NVM_DIR_END 0x78 +#define NVM_DIRENT_SIZE 0xc +#define NVM_DIRTYPE_SHIFT 24 +#define NVM_DIRTYPE_LENMSK 0x003fffff +#define NVM_DIRTYPE_ASFINI 1 +#define NVM_DIRTYPE_EXTVPD 20 +#define NVM_PTREV_BCVER 0x94 +#define NVM_BCVER_MAJMSK 0x0000ff00 +#define NVM_BCVER_MAJSFT 8 +#define NVM_BCVER_MINMSK 0x000000ff /* * NVM access register * Applicable to BCM5721,BCM5751,BCM5752,BCM5714 * and BCM5715 only. */ -#define NVM_ACCESS_REG 0X7024 -#define NVM_WRITE_ENABLE 0X00000002 -#define NVM_ACCESS_ENABLE 0X00000001 +#define NVM_ACCESS_REG 0x7024 +#define NVM_WRITE_ENABLE 0x00000002 +#define NVM_ACCESS_ENABLE 0x00000001 /* * TLP Control Register @@ -1406,6 +1580,24 @@ extern "C" { /* * Vendor-specific MII registers */ + +#define MII_MMD_CTRL 0x0d /* MMD Access Control register */ +#define MII_MMD_CTRL_DATA_NOINC 0x4000 +#define MII_MMD_ADDRESS_DATA 0x0e /* MMD Address Data register */ + +#define MII_RXR_COUNTERS 0x14 /* Local/Remote Rx Counts */ +#define MII_DSP_RW_PORT 0x15 /* DSP read/write port */ +#define MII_DSP_CONTROL 0x16 /* DSP control register */ +#define MII_DSP_ADDRESS 0x17 /* DSP address register */ + +#define MII_DSP_TAP26 0x001a +#define MII_DSP_TAP26_ALNOKO 0x0001 +#define MII_DSP_TAP26_RMRXSTO 0x0002 +#define MII_DSP_TAP26_OPCSINPT 0x0004 + +#define MII_DSP_CH34TP2 0x4022 +#define MII_DSP_CH34TP2_HIBW01 0x017b + #define MII_EXT_CONTROL MII_VENDOR(0) #define MII_EXT_STATUS MII_VENDOR(1) #define MII_RCV_ERR_COUNT MII_VENDOR(2) @@ -1491,6 +1683,9 @@ extern "C" { #define MII_AUX_CTRL_MISC_WRITE_ENABLE 0x8000 #define MII_AUX_CTRL_MISC_WIRE_SPEED 0x0010 +#define MII_AUX_CTRL_TX_6DB 0x0400 +#define MII_AUX_CTRL_SMDSP_ENA 0x0800 + /* * Write this value to the AUX control register * to select which shadow register will be read @@ -1611,6 +1806,7 @@ typedef struct { #define SBD_FLAG_IP_CKSUM 0x0002 #define SBD_FLAG_PACKET_END 0x0004 #define SBD_FLAG_IP_FRAG 0x0008 +#define SBD_FLAG_JMB_PKT 0x0008 #define SBD_FLAG_IP_FRAG_END 0x0010 #define SBD_FLAG_VLAN_TAG 0x0040 @@ -2095,6 +2291,83 @@ typedef struct { #endif /* BGE_IPMI_ASF */ +/* APE registers. Accessible through BAR1 */ +#define BGE_APE_GPIO_MSG 0x0008 +#define BGE_APE_GPIO_MSG_SHIFT 4 +#define BGE_APE_EVENT 0x000c +#define APE_EVENT_1 0x00000001 +#define BGE_APE_LOCK_REQ 0x002c +#define APE_LOCK_REQ_DRIVER 0x00001000 +#define BGE_APE_LOCK_GRANT 0x004c +#define APE_LOCK_GRANT_DRIVER 0x00001000 +#define BGE_APE_STICKY_TMR 0x00b0 + +/* APE shared memory. Accessible through BAR1 */ +#define BGE_APE_SHMEM_BASE 0x4000 +#define BGE_APE_SEG_SIG 0x4000 +#define APE_SEG_SIG_MAGIC 0x41504521 +#define BGE_APE_FW_STATUS 0x400c +#define APE_FW_STATUS_READY 0x00000100 +#define BGE_APE_FW_FEATURES 0x4010 +#define BGE_APE_FW_FEATURE_NCSI 0x00000002 +#define BGE_APE_FW_VERSION 0x4018 +#define APE_FW_VERSION_MAJMSK 0xff000000 +#define APE_FW_VERSION_MAJSFT 24 +#define APE_FW_VERSION_MINMSK 0x00ff0000 +#define APE_FW_VERSION_MINSFT 16 +#define APE_FW_VERSION_REVMSK 0x0000ff00 +#define APE_FW_VERSION_REVSFT 8 +#define APE_FW_VERSION_BLDMSK 0x000000ff +#define BGE_APE_SEG_MSG_BUF_OFF 0x401c +#define BGE_APE_SEG_MSG_BUF_LEN 0x4020 +#define BGE_APE_HOST_SEG_SIG 0x4200 +#define APE_HOST_SEG_SIG_MAGIC 0x484f5354 +#define BGE_APE_HOST_SEG_LEN 0x4204 +#define APE_HOST_SEG_LEN_MAGIC 0x00000020 +#define BGE_APE_HOST_INIT_COUNT 0x4208 +#define BGE_APE_HOST_DRIVER_ID 0x420c +#define APE_HOST_DRIVER_ID_SOLARIS 0xf4000000 +#define APE_HOST_DRIVER_ID_MAGIC(maj, min) \ + (APE_HOST_DRIVER_ID_SOLARIS | (maj & 0xff) << 16 | (min & 0xff) << 8) +#define BGE_APE_HOST_BEHAVIOR 0x4210 +#define APE_HOST_BEHAV_NO_PHYLOCK 0x00000001 +#define BGE_APE_HOST_HEARTBEAT_INT_MS 0x4214 +#define APE_HOST_HEARTBEAT_INT_DISABLE 0 +#define APE_HOST_HEARTBEAT_INT_5SEC 5000 +#define BGE_APE_HOST_HEARTBEAT_COUNT 0x4218 +#define BGE_APE_HOST_DRVR_STATE 0x421c +#define BGE_APE_HOST_DRVR_STATE_START 0x00000001 +#define BGE_APE_HOST_DRVR_STATE_UNLOAD 0x00000002 +#define BGE_APE_HOST_DRVR_STATE_WOL 0x00000003 +#define BGE_APE_HOST_WOL_SPEED 0x4224 +#define BGE_APE_HOST_WOL_SPEED_AUTO 0x00008000 + +#define BGE_APE_EVENT_STATUS 0x4300 + +#define APE_EVENT_STATUS_DRIVER_EVNT 0x00000010 +#define APE_EVENT_STATUS_STATE_CHNGE 0x00000500 +#define APE_EVENT_STATUS_SCRTCHPD_READ 0x00001600 +#define APE_EVENT_STATUS_SCRTCHPD_WRITE 0x00001700 +#define APE_EVENT_STATUS_STATE_START 0x00010000 +#define APE_EVENT_STATUS_STATE_UNLOAD 0x00020000 +#define APE_EVENT_STATUS_STATE_WOL 0x00030000 +#define APE_EVENT_STATUS_STATE_SUSPEND 0x00040000 +#define APE_EVENT_STATUS_EVENT_PENDING 0x80000000 + +#define BGE_APE_PER_LOCK_REQ 0x8400 +#define APE_LOCK_PER_REQ_DRIVER 0x00001000 +#define BGE_APE_PER_LOCK_GRANT 0x8420 +#define APE_PER_LOCK_GRANT_DRIVER 0x00001000 + +/* APE convenience enumerations. */ +#define BGE_APE_LOCK_PHY0 0 +#define BGE_APE_LOCK_GRC 1 +#define BGE_APE_LOCK_PHY1 2 +#define BGE_APE_LOCK_PHY2 3 +#define BGE_APE_LOCK_MEM 4 +#define BGE_APE_LOCK_PHY3 5 +#define BGE_APE_LOCK_GPIO 7 + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/io/bge/bge_impl.h b/usr/src/uts/common/io/bge/bge_impl.h index 772c989..ccc57b9 100644 --- a/usr/src/uts/common/io/bge/bge_impl.h +++ b/usr/src/uts/common/io/bge/bge_impl.h @@ -20,7 +20,13 @@ */ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010-2013, by Broadcom, Inc. + * All Rights Reserved. + */ + +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. + * All rights reserved. */ #ifndef _BGE_IMPL_H @@ -45,7 +51,6 @@ extern "C" { #endif /* __sparcv9 */ #include #include -#include #include #include #include @@ -77,6 +82,18 @@ extern "C" { #include #endif +#ifndef VLAN_TAGSZ +#define VLAN_TAGSZ 4 +#endif + +#define BGE_STR_SIZE 32 + +#ifndef OFFSETOF +#define OFFSETOF(_s, _f) \ + ((uint32_t)((uint8_t *)(&((_s *)0)->_f) - \ + (uint8_t *)((uint8_t *) 0))) +#endif + /* * *may* already have provided the typedef ether_addr_t; * but of course C doesn't provide a way to check this directly. So here @@ -94,7 +111,6 @@ typedef uchar_t ether_addr_t[ETHERADDRL]; */ extern int secpolicy_net_config(const cred_t *, boolean_t); -#include /* originally from cassini */ #include /* by fjlite out of intel */ #include "bge.h" @@ -133,6 +149,7 @@ extern int secpolicy_net_config(const cred_t *, boolean_t); #define BGE_PCI_CONFIG_RNUMBER 0 #define BGE_PCI_OPREGS_RNUMBER 1 +#define BGE_PCI_APEREGS_RNUMBER 2 #define BGE_DMA_MODE DDI_DMA_STREAMING #define BGE_HEADROOM 34 @@ -168,6 +185,7 @@ extern int secpolicy_net_config(const cred_t *, boolean_t); #define BGE_HALFTICK 268435456LL /* 2**28 ns! */ #define BGE_CYCLIC_PERIOD (4*BGE_HALFTICK) /* ~1.0s */ +#define BGE_CYCLIC_TIMEOUT (drv_usectohz(1000000)) /* ~1.0s */ #define BGE_SERDES_STABLE_TIME (3*BGE_HALFTICK) /* ~0.8s */ #define BGE_PHY_STABLE_TIME (11*BGE_HALFTICK) /* ~3.0s */ #define BGE_LINK_SETTLE_TIME (111*BGE_HALFTICK) /* ~30.0s */ @@ -301,7 +319,6 @@ extern int secpolicy_net_config(const cred_t *, boolean_t); #define BGE_LOWAT (256) #define BGE_HIWAT (256*1024) - /* * Basic data types, for clarity in distinguishing 'numbers' * used for different purposes ... @@ -593,6 +610,7 @@ enum bge_nvmem_type { */ typedef struct { uint32_t asic_rev; /* masked from MHCR */ + uint32_t asic_rev_prod_id; /* new revision ID format */ uint32_t businfo; /* from private reg */ uint16_t command; /* saved during attach */ @@ -627,6 +645,7 @@ typedef struct { uint32_t rx_rings; /* from bge.conf */ uint32_t tx_rings; /* from bge.conf */ + uint32_t eee; /* from bge.conf */ uint32_t default_mtu; /* from bge.conf */ uint64_t hw_mac_addr; /* from chip register */ @@ -718,11 +737,22 @@ typedef struct bge { /* * These fields are set by attach() and unchanged thereafter ... */ + char version[BGE_STR_SIZE]; +#define BGE_FW_VER_SIZE 32 + char fw_version[BGE_FW_VER_SIZE]; dev_info_t *devinfo; /* device instance */ + uint32_t pci_bus; /* from "regs" prop */ + uint32_t pci_dev; /* from "regs" prop */ + uint32_t pci_func; /* from "regs" prop */ mac_handle_t mh; /* mac module handle */ ddi_acc_handle_t cfg_handle; /* DDI I/O handle */ ddi_acc_handle_t io_handle; /* DDI I/O handle */ void *io_regs; /* mapped registers */ + ddi_acc_handle_t ape_handle; /* DDI I/O handle */ + void *ape_regs; /* mapped registers */ + boolean_t ape_enabled; + boolean_t ape_has_ncsi; + ddi_periodic_t periodic_id; /* periodical callback */ ddi_softintr_t factotum_id; /* factotum callback */ ddi_softintr_t drain_id; /* reschedule callback */ @@ -784,6 +814,8 @@ typedef struct bge { recv_ring_t recv[BGE_RECV_RINGS_MAX]; /* 16*0x0090 */ send_ring_t send[BGE_SEND_RINGS_MAX]; /* 16*0x0100 */ + mac_resource_handle_t macRxResourceHandles[BGE_RECV_RINGS_MAX]; + /* * Locks: * @@ -884,6 +916,7 @@ typedef struct bge { uint64_t tx_resched; uint32_t factotum_flag; /* softint pending */ uintptr_t pagemask; + boolean_t rdma_length_bug_on_5719; /* * NDD parameters (protected by genlock) @@ -953,12 +986,13 @@ typedef struct bge { uint32_t param_drain_max; uint64_t param_link_speed; link_duplex_t param_link_duplex; + uint32_t eee_lpi_wait; - - uint32_t link_update_timer; uint64_t timestamp; } bge_t; +#define CATC_TRIGGER(bgep, data) bge_reg_put32(bgep, 0x0a00, (data)) + /* * 'Progress' bit flags ... */ @@ -1031,35 +1065,31 @@ typedef struct bge { */ #define BGE_DBG_STOP 0x00000001 /* early debug_enter() */ #define BGE_DBG_TRACE 0x00000002 /* general flow tracing */ - +#define BGE_DBG_APE 0x00000004 /* low-level APE access */ +#define BGE_DBG_HPSD 0x00000008 /* low-level HPSD access*/ #define BGE_DBG_REGS 0x00000010 /* low-level accesses */ #define BGE_DBG_MII 0x00000020 /* low-level MII access */ #define BGE_DBG_SEEPROM 0x00000040 /* low-level SEEPROM IO */ #define BGE_DBG_CHIP 0x00000080 /* low(ish)-level code */ - #define BGE_DBG_RECV 0x00000100 /* receive-side code */ #define BGE_DBG_SEND 0x00000200 /* packet-send code */ - #define BGE_DBG_INT 0x00001000 /* interrupt handler */ #define BGE_DBG_FACT 0x00002000 /* factotum (softint) */ - #define BGE_DBG_PHY 0x00010000 /* Copper PHY code */ #define BGE_DBG_SERDES 0x00020000 /* SerDes code */ #define BGE_DBG_PHYS 0x00040000 /* Physical layer code */ #define BGE_DBG_LINK 0x00080000 /* Link status check */ - #define BGE_DBG_INIT 0x00100000 /* initialisation */ #define BGE_DBG_NEMO 0x00200000 /* nemo interaction */ #define BGE_DBG_ADDR 0x00400000 /* address-setting code */ #define BGE_DBG_STATS 0x00800000 /* statistics */ - #define BGE_DBG_IOCTL 0x01000000 /* ioctl handling */ #define BGE_DBG_LOOP 0x02000000 /* loopback ioctl code */ #define BGE_DBG_PPIO 0x04000000 /* Peek/poke ioctls */ #define BGE_DBG_BADIOC 0x08000000 /* unknown ioctls */ - #define BGE_DBG_MCTL 0x10000000 /* mctl (csum) code */ #define BGE_DBG_NDD 0x20000000 /* NDD operations */ +#define BGE_DBG_MEM 0x40000000 /* memory allocations and chunking */ /* * Debugging ... @@ -1067,7 +1097,7 @@ typedef struct bge { #ifdef DEBUG #define BGE_DEBUGGING 1 #else -#define BGE_DEBUGGING 0 +#define BGE_DEBUGGING 1 #endif /* DEBUG */ @@ -1107,6 +1137,9 @@ typedef struct bge { #define BGE_LDB(b, args) BGE_XDB(b, bgep->debug, (*bge_db(bgep)), args) #define BGE_CDB(f, args) BGE_XDB(BGE_DBG, bgep->debug, f, args) +#define DEVNAME(_sc) ((_sc)->ifname) +#define DPRINTF(f, ...) do { cmn_err(CE_NOTE, (f), __VA_ARGS__); } while (0) + /* * Conditional-print macros. * @@ -1147,11 +1180,20 @@ typedef struct bge { /* bge_chip.c */ uint16_t bge_mii_get16(bge_t *bgep, bge_regno_t regno); void bge_mii_put16(bge_t *bgep, bge_regno_t regno, uint16_t value); +uint16_t bge_phydsp_read(bge_t *bgep, bge_regno_t regno); +void bge_phydsp_write(bge_t *bgep, bge_regno_t regno, uint16_t value); uint32_t bge_reg_get32(bge_t *bgep, bge_regno_t regno); void bge_reg_put32(bge_t *bgep, bge_regno_t regno, uint32_t value); void bge_reg_set32(bge_t *bgep, bge_regno_t regno, uint32_t bits); void bge_reg_clr32(bge_t *bgep, bge_regno_t regno, uint32_t bits); +uint32_t bge_ape_get32(bge_t *bgep, bge_regno_t regno); +void bge_ape_put32(bge_t *bgep, bge_regno_t regno, uint32_t value); void bge_mbx_put(bge_t *bgep, bge_regno_t regno, uint64_t value); +void bge_ape_lock_init(bge_t *bgep); +int bge_ape_scratchpad_read(bge_t *bgep, uint32_t *data, uint32_t base_off, uint32_t lenToRead); +int bge_ape_scratchpad_write(bge_t *bgep, uint32_t dstoff, uint32_t *data, uint32_t lenToWrite); +int bge_nvmem_read32(bge_t *bgep, bge_regno_t addr, uint32_t *dp); +int bge_nvmem_write32(bge_t *bgep, bge_regno_t addr, uint32_t *dp); void bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma); int bge_chip_id_init(bge_t *bgep); void bge_chip_coalesce_update(bge_t *bgep); @@ -1231,7 +1273,9 @@ void bge_intr_enable(bge_t *bgep); void bge_intr_disable(bge_t *bgep); int bge_reprogram(bge_t *); -/* bge_phys.c */ +/* bge_mii.c */ +void bge_eee_init(bge_t *bgep); +void bge_eee_enable(bge_t * bgep); int bge_phys_init(bge_t *bgep); void bge_phys_reset(bge_t *bgep); int bge_phys_idle(bge_t *bgep); @@ -1284,9 +1328,6 @@ void bge_adj_volt_5906(bge_t *bgep); #define BGE_ASF_HEARTBEAT_INTERVAL 1500000 -#define BGE_LINK_UPDATE_TIMEOUT 10 /* ~ 5 sec */ -#define BGE_LINK_UPDATE_DONE (BGE_LINK_UPDATE_TIMEOUT+1) - #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/io/bge/bge_kstats.c b/usr/src/uts/common/io/bge/bge_kstats.c index c10a1b4..9df3595 100644 --- a/usr/src/uts/common/io/bge/bge_kstats.c +++ b/usr/src/uts/common/io/bge/bge_kstats.c @@ -20,6 +20,11 @@ */ /* + * Copyright (c) 2010-2013, by Broadcom, Inc. + * All Rights Reserved. + */ + +/* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -286,6 +291,10 @@ static const bge_ksindex_t bge_chipid[] = { { 18, "&supported" }, { 19, "&interface" }, + { 20, "nvtype" }, + + { 21, "asic_rev_prod_id" }, + { -1, NULL } }; @@ -343,6 +352,13 @@ bge_chipid_update(kstat_t *ksp, int flag) bge_set_char_kstat(knp++, tmp & CHIP_FLAG_SERDES ? "serdes" : "copper"); + (knp++)->value.ui64 = + ((bgep->chipid.nvtype == BGE_NVTYPE_NONE) || + (bgep->chipid.nvtype == BGE_NVTYPE_UNKNOWN)) ? + 0 : bgep->chipid.nvtype; + + (knp++)->value.ui64 = bgep->chipid.asic_rev_prod_id; + return (0); } @@ -499,6 +515,7 @@ static const bge_ksindex_t bge_phydata[] = { { MII_INTR_STATUS, "intr_status" }, { MII_INTR_MASK, "intr_mask" }, { MII_HCD_STATUS, "hcd_status" }, + { EEE_MODE_REG, "eee" }, { -1, NULL } }; @@ -540,6 +557,16 @@ bge_phydata_update(kstat_t *ksp, int flag) knp->value.ui64 |= bge_mii_get16(bgep, MII_PHYIDL); break; + case EEE_MODE_REG: + knp->value.ui64 = 0; + if (bgep->link_state == LINK_STATE_UP) + { + knp->value.ui64 = + (bge_reg_get32(bgep, EEE_MODE_REG) & 0x80) ? + 1 : 0; + } + break; + default: knp->value.ui64 = bge_mii_get16(bgep, ksip->index); break; @@ -567,7 +594,7 @@ bge_setup_named_kstat(bge_t *bgep, int instance, char *name, size /= sizeof (bge_ksindex_t); ksp = kstat_create(BGE_DRIVER_NAME, instance, name, "net", - KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT); + KSTAT_TYPE_NAMED, size-1, 0); if (ksp == NULL) return (NULL); @@ -663,7 +690,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) bge_statistics_t *bstp; bge_statistics_reg_t *pstats; - if (bgep->bge_chip_state == BGE_CHIP_FAULT) { + if (bgep->bge_chip_state != BGE_CHIP_RUNNING) { return (EINVAL); } @@ -735,7 +762,8 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) switch (stat) { case MAC_STAT_IFSPEED: - *val = bgep->param_link_speed * 1000000ull; + *val = (bgep->link_state != LINK_STATE_UNKNOWN) ? + (bgep->param_link_speed * 1000000ull) : 0; break; case MAC_STAT_MULTIRCV: @@ -916,12 +944,14 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) *val = pstats->dot3StatsFrameTooLongs; break; +#if (MAC_VERSION > 1) case ETHER_STAT_TOOSHORT_ERRORS: if (bgep->chipid.statistic_type == BGE_STAT_BLK) *val = bstp->s.etherStatsUndersizePkts; else *val = pstats->etherStatsUndersizePkts; break; +#endif case ETHER_STAT_XCVR_ADDR: *val = bgep->phy_mii_addr; @@ -994,9 +1024,11 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) *val = 1; break; +#if (MAC_VERSION > 1) case ETHER_STAT_CAP_REMFAULT: *val = 1; break; +#endif case ETHER_STAT_ADV_CAP_1000FDX: *val = bgep->param_adv_1000fdx; @@ -1034,6 +1066,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) *val = bgep->param_adv_autoneg; break; +#if (MAC_VERSION > 1) case ETHER_STAT_ADV_REMFAULT: if (bgep->chipid.flags & CHIP_FLAG_SERDES) *val = 0; @@ -1049,6 +1082,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) mutex_exit(bgep->genlock); } break; +#endif case ETHER_STAT_LP_CAP_1000FDX: *val = bgep->param_lp_1000fdx; @@ -1086,6 +1120,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) *val = bgep->param_lp_autoneg; break; +#if (MAC_VERSION > 1) case ETHER_STAT_LP_REMFAULT: if (bgep->chipid.flags & CHIP_FLAG_SERDES) *val = 0; @@ -1101,6 +1136,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) mutex_exit(bgep->genlock); } break; +#endif case ETHER_STAT_LINK_ASMPAUSE: *val = bgep->param_adv_asym_pause && @@ -1117,7 +1153,8 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val) break; case ETHER_STAT_LINK_DUPLEX: - *val = bgep->param_link_duplex; + *val = (bgep->link_state != LINK_STATE_UNKNOWN) ? + bgep->param_link_duplex : LINK_DUPLEX_UNKNOWN; break; default: diff --git a/usr/src/uts/common/io/bge/bge_main2.c b/usr/src/uts/common/io/bge/bge_main2.c index f191f31..d186645 100644 --- a/usr/src/uts/common/io/bge/bge_main2.c +++ b/usr/src/uts/common/io/bge/bge_main2.c @@ -20,7 +20,13 @@ */ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010-2013, by Broadcom, Inc. + * All Rights Reserved. + */ + +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. + * All rights reserved. */ #include "bge_impl.h" @@ -29,6 +35,12 @@ #include #include + +#ifndef STRINGIFY +#define XSTRINGIFY(x) #x +#define STRINGIFY(x) XSTRINGIFY(x) +#endif + /* * This is the string displayed by modinfo, etc. */ @@ -47,18 +59,21 @@ static char subdev_propname[] = "subsystem-id"; static char subven_propname[] = "subsystem-vendor-id"; static char rxrings_propname[] = "bge-rx-rings"; static char txrings_propname[] = "bge-tx-rings"; +static char eee_propname[] = "bge-eee"; static char fm_cap[] = "fm-capable"; static char default_mtu[] = "default_mtu"; static int bge_add_intrs(bge_t *, int); static void bge_rem_intrs(bge_t *); static int bge_unicst_set(void *, const uint8_t *, int); +static int bge_addmac(void *, const uint8_t *); +static int bge_remmac(void *, const uint8_t *); /* * Describes the chip's DMA engine */ static ddi_dma_attr_t dma_attr = { - DMA_ATTR_V0, /* dma_attr version */ + DMA_ATTR_V0, /* dma_attr_version */ 0x0000000000000000ull, /* dma_attr_addr_lo */ 0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */ 0x00000000FFFFFFFFull, /* dma_attr_count_max */ @@ -66,7 +81,7 @@ static ddi_dma_attr_t dma_attr = { 0x00000FFF, /* dma_attr_burstsizes */ 0x00000001, /* dma_attr_minxfer */ 0x000000000000FFFFull, /* dma_attr_maxxfer */ - 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ + 0x00000000FFFFFFFFull, /* dma_attr_seg */ 1, /* dma_attr_sgllen */ 0x00000001, /* dma_attr_granular */ DDI_DMA_FLAGERR /* dma_attr_flags */ @@ -103,7 +118,9 @@ static ddi_device_acc_attr_t bge_data_accattr = { static int bge_m_start(void *); static void bge_m_stop(void *); static int bge_m_promisc(void *, boolean_t); +static int bge_m_unicst(void * pArg, const uint8_t *); static int bge_m_multicst(void *, boolean_t, const uint8_t *); +static void bge_m_resources(void * arg); static void bge_m_ioctl(void *, queue_t *, mblk_t *); static boolean_t bge_m_getcapab(void *, mac_capab_t, void *); static int bge_unicst_set(void *, const uint8_t *, @@ -121,26 +138,48 @@ static int bge_get_priv_prop(bge_t *, const char *, uint_t, static void bge_priv_propinfo(const char *, mac_prop_info_handle_t); -#define BGE_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | \ - MC_GETPROP | MC_PROPINFO) - static mac_callbacks_t bge_m_callbacks = { - BGE_M_CALLBACK_FLAGS, + MC_IOCTL +#ifdef MC_RESOURCES + | MC_RESOURCES +#endif +#ifdef MC_SETPROP + | MC_SETPROP +#endif +#ifdef MC_GETPROP + | MC_GETPROP +#endif +#ifdef MC_PROPINFO + | MC_PROPINFO +#endif + | MC_GETCAPAB, bge_m_stat, bge_m_start, bge_m_stop, bge_m_promisc, bge_m_multicst, - NULL, + bge_m_unicst, bge_m_tx, +#ifdef MC_RESOURCES + bge_m_resources, +#else NULL, +#endif bge_m_ioctl, bge_m_getcapab, +#ifdef MC_OPEN NULL, NULL, +#endif +#ifdef MC_SETPROP bge_m_setprop, +#endif +#ifdef MC_GETPROP bge_m_getprop, +#endif +#ifdef MC_PROPINFO bge_m_propinfo +#endif }; char *bge_priv_prop[] = { @@ -489,7 +528,6 @@ bge_m_stop(void *arg) } else bge_stop(bgep); - bgep->link_update_timer = 0; bgep->link_state = LINK_STATE_UNKNOWN; mac_link_update(bgep->mh, bgep->link_state); @@ -542,6 +580,11 @@ bge_m_start(void *arg) if ((bgep->asf_status == ASF_STAT_RUN) && (bgep->asf_pseudostop)) { bgep->bge_mac_state = BGE_MAC_STARTED; + /* forcing a mac link update here */ + bge_phys_check(bgep); + bgep->link_state = (bgep->param_link_up) ? LINK_STATE_UP : + LINK_STATE_DOWN; + mac_link_update(bgep->mh, bgep->link_state); mutex_exit(bgep->genlock); return (0); } @@ -601,7 +644,7 @@ bge_unicst_set(void *arg, const uint8_t *macaddr, int slot) { bge_t *bgep = arg; /* private device info */ - BGE_TRACE(("bge_m_unicst_set($%p, %s)", arg, + BGE_TRACE(("bge_unicst_set($%p, %s)", arg, ether_sprintf((void *)macaddr))); /* * Remember the new current address in the driver state @@ -668,7 +711,7 @@ bge_unicst_set(void *arg, const uint8_t *macaddr, int slot) } } #endif - BGE_DEBUG(("bge_m_unicst_set($%p) done", arg)); + BGE_DEBUG(("bge_unicst_set($%p) done", arg)); if (bge_check_acc_handle(bgep, bgep->cfg_handle) != DDI_FM_OK) { ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED); mutex_exit(bgep->genlock); @@ -1244,6 +1287,21 @@ bge_priv_propinfo(const char *pr_name, mac_prop_info_handle_t mph) mac_prop_info_set_default_str(mph, valstr); } + +static int +bge_m_unicst(void * arg, const uint8_t * mac_addr) +{ + bge_t *bgep = arg; + int i; + + /* XXX sets the mac address for all ring slots... OK? */ + for (i = 0; i < MIN(bgep->chipid.rx_rings, MAC_ADDRESS_REGS_MAX); i++) + bge_addmac(&bgep->recv[i], mac_addr); + + return (0); +} + + /* * Compute the index of the required bit in the multicast hash map. * This must mirror the way the hardware actually does it! @@ -1404,6 +1462,37 @@ bge_m_promisc(void *arg, boolean_t on) return (0); } +#ifdef MC_RESOURCES + +static void +bge_blank(void * arg, time_t tick_cnt, uint_t pkt_cnt) +{ + (void)arg; + (void)tick_cnt; + (void)pkt_cnt; +} + +static void +bge_m_resources(void * arg) +{ + bge_t *bgep = arg; + mac_rx_fifo_t mrf; + int i; + + mrf.mrf_type = MAC_RX_FIFO; + mrf.mrf_blank = bge_blank; + mrf.mrf_arg = (void *)bgep; + mrf.mrf_normal_blank_time = 25; + mrf.mrf_normal_pkt_count = 8; + + for (i = 0; i < BGE_RECV_RINGS_MAX; i++) { + bgep->macRxResourceHandles[i] = + mac_resource_add(bgep->mh, (mac_resource_t *)&mrf); + } +} + +#endif /* MC_RESOURCES */ + /* * Find the slot for the specified unicast address */ @@ -1427,7 +1516,7 @@ bge_unicst_find(bge_t *bgep, const uint8_t *mac_addr) * specified ring 'arg'. */ static int -bge_addmac(void *arg, const uint8_t *mac_addr) +bge_addmac(void *arg, const uint8_t * mac_addr) { recv_ring_t *rrp = (recv_ring_t *)arg; bge_t *bgep = rrp->bgep; @@ -1440,6 +1529,8 @@ bge_addmac(void *arg, const uint8_t *mac_addr) int slot; int err; + _NOTE(ARGUNUSED(flags)) + mutex_enter(bgep->genlock); if (bgep->unicst_addr_avail == 0) { mutex_exit(bgep->genlock); @@ -1579,8 +1670,9 @@ bge_remmac(void *arg, const uint8_t *mac_addr) return (0); } + static int -bge_flag_intr_enable(mac_intr_handle_t ih) +bge_flag_intr_enable(mac_ring_driver_t ih) { recv_ring_t *rrp = (recv_ring_t *)ih; bge_t *bgep = rrp->bgep; @@ -1593,7 +1685,7 @@ bge_flag_intr_enable(mac_intr_handle_t ih) } static int -bge_flag_intr_disable(mac_intr_handle_t ih) +bge_flag_intr_disable(mac_ring_driver_t ih) { recv_ring_t *rrp = (recv_ring_t *)ih; bge_t *bgep = rrp->bgep; @@ -1645,9 +1737,8 @@ bge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, infop->mri_stat = bge_rx_ring_stat; mintr = &infop->mri_intr; - mintr->mi_handle = (mac_intr_handle_t)rx_ring; - mintr->mi_enable = bge_flag_intr_enable; - mintr->mi_disable = bge_flag_intr_disable; + mintr->mi_enable = (mac_intr_enable_t)bge_flag_intr_enable; + mintr->mi_disable = (mac_intr_disable_t)bge_flag_intr_disable; break; } @@ -1666,7 +1757,7 @@ bge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, */ void bge_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index, - mac_group_info_t *infop, mac_group_handle_t gh) + mac_group_info_t * infop, mac_group_handle_t gh) { bge_t *bgep = arg; @@ -1694,11 +1785,13 @@ bge_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index, } } + /*ARGSUSED*/ static boolean_t bge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) { bge_t *bgep = arg; + mac_capab_rings_t *cap_rings; switch (cap) { case MAC_CAPAB_HCKSUM: { @@ -1707,26 +1800,30 @@ bge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) *txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM; break; } - case MAC_CAPAB_RINGS: { - mac_capab_rings_t *cap_rings = cap_data; + + case MAC_CAPAB_RINGS: + cap_rings = (mac_capab_rings_t *)cap_data; /* Temporarily disable multiple tx rings. */ if (cap_rings->mr_type != MAC_RING_TYPE_RX) return (B_FALSE); cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; - cap_rings->mr_rnum = cap_rings->mr_gnum = + cap_rings->mr_rnum = + cap_rings->mr_gnum = MIN(bgep->chipid.rx_rings, MAC_ADDRESS_REGS_MAX); cap_rings->mr_rget = bge_fill_ring; cap_rings->mr_gget = bge_fill_group; break; - } + default: return (B_FALSE); } return (B_TRUE); } +#ifdef NOT_SUPPORTED_XXX + /* * Loopback ioctl code */ @@ -1827,6 +1924,8 @@ bge_loop_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp) } } +#endif /* NOT_SUPPORTED_XXX */ + /* * Specific bge IOCTLs, the gld module handles the generic ones. */ @@ -1866,6 +1965,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) case BGE_HARD_RESET: break; +#ifdef NOT_SUPPORTED_XXX case LB_GET_INFO_SIZE: case LB_GET_INFO: case LB_GET_MODE: @@ -1873,6 +1973,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) /* FALLTHRU */ case LB_SET_MODE: break; +#endif } @@ -1916,12 +2017,14 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) status = bge_chip_ioctl(bgep, wq, mp, iocp); break; +#ifdef NOT_SUPPORTED_XXX case LB_GET_INFO_SIZE: case LB_GET_INFO: case LB_GET_MODE: case LB_SET_MODE: status = bge_loop_ioctl(bgep, wq, mp, iocp); break; +#endif } @@ -1994,7 +2097,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) */ #undef BGE_DBG -#define BGE_DBG BGE_DBG_INIT /* debug flag for this code */ +#define BGE_DBG BGE_DBG_MEM /* debug flag for this code */ /* * Allocate an area of memory and a DMA handle for accessing it */ @@ -2588,8 +2691,11 @@ bge_alloc_bufs(bge_t *bgep) /* * Enable PCI relaxed ordering only for RX/TX data buffers */ - if (bge_relaxed_ordering) - dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; + if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep))) { + if (bge_relaxed_ordering) + dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING; + } /* * Allocate memory & handles for RX buffers @@ -2602,6 +2708,9 @@ bge_alloc_bufs(bge_t *bgep) if (err != DDI_SUCCESS) return (DDI_FAILURE); } + BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Rx Buffers (rxbuffsize = %d)", + rxbuffsize/BGE_SPLIT, + rxbuffsize)); /* * Allocate memory & handles for TX buffers @@ -2614,8 +2723,15 @@ bge_alloc_bufs(bge_t *bgep) if (err != DDI_SUCCESS) return (DDI_FAILURE); } + BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Tx Buffers (txbuffsize = %d)", + txbuffsize/BGE_SPLIT, + txbuffsize)); - dma_attr.dma_attr_flags &= ~DDI_DMA_RELAXED_ORDERING; + if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep))) { + /* no relaxed ordering for descriptors rings? */ + dma_attr.dma_attr_flags &= ~DDI_DMA_RELAXED_ORDERING; + } /* * Allocate memory & handles for receive return rings @@ -2628,14 +2744,21 @@ bge_alloc_bufs(bge_t *bgep) if (err != DDI_SUCCESS) return (DDI_FAILURE); } + BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Rx Descs cons (rx_rings = %d, rxdescsize = %d)", + rxdescsize/rx_rings, + rx_rings, + rxdescsize)); /* - * Allocate memory & handles for buffer (producer) descriptor rings + * Allocate memory & handles for buffer (producer) descriptor rings. + * Note that split=rx_rings. */ err = bge_alloc_dma_mem(bgep, rxbuffdescsize, &bge_desc_accattr, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &bgep->rx_desc[split]); if (err != DDI_SUCCESS) return (DDI_FAILURE); + BGE_DEBUG(("DMA ALLOC: allocated 1 chunks for Rx Descs prod (rxbuffdescsize = %d)", + rxdescsize)); /* * Allocate memory & handles for TX descriptor rings, @@ -2645,65 +2768,260 @@ bge_alloc_bufs(bge_t *bgep) DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &bgep->tx_desc); if (err != DDI_SUCCESS) return (DDI_FAILURE); + BGE_DEBUG(("DMA ALLOC: allocated 1 chunks for Tx Descs / Status Block / Stats (txdescdize = %d)", + txdescsize)); /* * Now carve up each of the allocated areas ... */ + + /* rx buffers */ for (split = 0; split < BGE_SPLIT; ++split) { area = bgep->rx_buff[split]; + + BGE_DEBUG(("RXB CHNK %d INIT: va=%p alen=%d off=%d pa=%llx psz=%d", + split, + area.mem_va, + area.alength, + area.offset, + area.cookie.dmac_laddress, + area.cookie.dmac_size)); + bge_slice_chunk(&bgep->buff[BGE_STD_BUFF_RING].buf[split], &area, BGE_STD_SLOTS_USED/BGE_SPLIT, bgep->chipid.std_buf_size); + + BGE_DEBUG(("RXB SLCE %d STND: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + split, + bgep->buff[BGE_STD_BUFF_RING].buf[split].mem_va, + bgep->buff[BGE_STD_BUFF_RING].buf[split].alength, + bgep->buff[BGE_STD_BUFF_RING].buf[split].offset, + bgep->buff[BGE_STD_BUFF_RING].buf[split].cookie.dmac_laddress, + bgep->buff[BGE_STD_BUFF_RING].buf[split].cookie.dmac_size, + BGE_STD_SLOTS_USED/BGE_SPLIT, + bgep->chipid.std_buf_size)); + bge_slice_chunk(&bgep->buff[BGE_JUMBO_BUFF_RING].buf[split], &area, bgep->chipid.jumbo_slots/BGE_SPLIT, bgep->chipid.recv_jumbo_size); + + if ((bgep->chipid.jumbo_slots / BGE_SPLIT) > 0) + { + BGE_DEBUG(("RXB SLCE %d JUMB: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + split, + bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].mem_va, + bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].alength, + bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].offset, + bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].cookie.dmac_laddress, + bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].cookie.dmac_size, + bgep->chipid.jumbo_slots/BGE_SPLIT, + bgep->chipid.recv_jumbo_size)); + } + bge_slice_chunk(&bgep->buff[BGE_MINI_BUFF_RING].buf[split], &area, BGE_MINI_SLOTS_USED/BGE_SPLIT, BGE_MINI_BUFF_SIZE); + + if ((BGE_MINI_SLOTS_USED / BGE_SPLIT) > 0) + { + BGE_DEBUG(("RXB SLCE %d MINI: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + split, + bgep->buff[BGE_MINI_BUFF_RING].buf[split].mem_va, + bgep->buff[BGE_MINI_BUFF_RING].buf[split].alength, + bgep->buff[BGE_MINI_BUFF_RING].buf[split].offset, + bgep->buff[BGE_MINI_BUFF_RING].buf[split].cookie.dmac_laddress, + bgep->buff[BGE_MINI_BUFF_RING].buf[split].cookie.dmac_size, + BGE_MINI_SLOTS_USED/BGE_SPLIT, + BGE_MINI_BUFF_SIZE)); + } + + BGE_DEBUG(("RXB CHNK %d DONE: va=%p alen=%d off=%d pa=%llx psz=%d", + split, + area.mem_va, + area.alength, + area.offset, + area.cookie.dmac_laddress, + area.cookie.dmac_size)); } + /* tx buffers */ for (split = 0; split < BGE_SPLIT; ++split) { area = bgep->tx_buff[split]; - for (ring = 0; ring < tx_rings; ++ring) + + BGE_DEBUG(("TXB CHNK %d INIT: va=%p alen=%d off=%d pa=%llx psz=%d", + split, + area.mem_va, + area.alength, + area.offset, + area.cookie.dmac_laddress, + area.cookie.dmac_size)); + + for (ring = 0; ring < tx_rings; ++ring) { bge_slice_chunk(&bgep->send[ring].buf[0][split], &area, BGE_SEND_BUF_NUM/BGE_SPLIT, bgep->chipid.snd_buff_size); - for (; ring < BGE_SEND_RINGS_MAX; ++ring) + + BGE_DEBUG(("TXB SLCE %d RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + split, ring, + bgep->send[ring].buf[0][split].mem_va, + bgep->send[ring].buf[0][split].alength, + bgep->send[ring].buf[0][split].offset, + bgep->send[ring].buf[0][split].cookie.dmac_laddress, + bgep->send[ring].buf[0][split].cookie.dmac_size, + BGE_SEND_BUF_NUM/BGE_SPLIT, + bgep->chipid.snd_buff_size)); + } + + for (; ring < BGE_SEND_RINGS_MAX; ++ring) { bge_slice_chunk(&bgep->send[ring].buf[0][split], &area, 0, bgep->chipid.snd_buff_size); + } + + BGE_DEBUG(("TXB CHNK %d DONE: va=%p alen=%d off=%d pa=%llx psz=%d", + split, + area.mem_va, + area.alength, + area.offset, + area.cookie.dmac_laddress, + area.cookie.dmac_size)); } - for (ring = 0; ring < rx_rings; ++ring) + for (ring = 0; ring < rx_rings; ++ring) { bge_slice_chunk(&bgep->recv[ring].desc, &bgep->rx_desc[ring], bgep->chipid.recv_slots, sizeof (bge_rbd_t)); - area = bgep->rx_desc[rx_rings]; - for (; ring < BGE_RECV_RINGS_MAX; ++ring) + BGE_DEBUG(("RXD CONS RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + ring, + bgep->recv[ring].desc.mem_va, + bgep->recv[ring].desc.alength, + bgep->recv[ring].desc.offset, + bgep->recv[ring].desc.cookie.dmac_laddress, + bgep->recv[ring].desc.cookie.dmac_size, + bgep->chipid.recv_slots, + sizeof(bge_rbd_t))); + } + + /* dma alloc for rxbuffdescsize is located at bgep->rx_desc[#rings] */ + area = bgep->rx_desc[rx_rings]; /* note rx_rings = one beyond rings */ + + for (; ring < BGE_RECV_RINGS_MAX; ++ring) /* skip unused rings */ bge_slice_chunk(&bgep->recv[ring].desc, &area, 0, sizeof (bge_rbd_t)); + + BGE_DEBUG(("RXD PROD INIT: va=%p alen=%d off=%d pa=%llx psz=%d", + area.mem_va, + area.alength, + area.offset, + area.cookie.dmac_laddress, + area.cookie.dmac_size)); + bge_slice_chunk(&bgep->buff[BGE_STD_BUFF_RING].desc, &area, BGE_STD_SLOTS_USED, sizeof (bge_rbd_t)); + BGE_DEBUG(("RXD PROD STND: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + bgep->buff[BGE_STD_BUFF_RING].desc.mem_va, + bgep->buff[BGE_STD_BUFF_RING].desc.alength, + bgep->buff[BGE_STD_BUFF_RING].desc.offset, + bgep->buff[BGE_STD_BUFF_RING].desc.cookie.dmac_laddress, + bgep->buff[BGE_STD_BUFF_RING].desc.cookie.dmac_size, + BGE_STD_SLOTS_USED, + sizeof(bge_rbd_t))); + bge_slice_chunk(&bgep->buff[BGE_JUMBO_BUFF_RING].desc, &area, bgep->chipid.jumbo_slots, sizeof (bge_rbd_t)); + BGE_DEBUG(("RXD PROD JUMB: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + bgep->buff[BGE_JUMBO_BUFF_RING].desc.mem_va, + bgep->buff[BGE_JUMBO_BUFF_RING].desc.alength, + bgep->buff[BGE_JUMBO_BUFF_RING].desc.offset, + bgep->buff[BGE_JUMBO_BUFF_RING].desc.cookie.dmac_laddress, + bgep->buff[BGE_JUMBO_BUFF_RING].desc.cookie.dmac_size, + bgep->chipid.jumbo_slots, + sizeof(bge_rbd_t))); + bge_slice_chunk(&bgep->buff[BGE_MINI_BUFF_RING].desc, &area, BGE_MINI_SLOTS_USED, sizeof (bge_rbd_t)); + BGE_DEBUG(("RXD PROD MINI: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + bgep->buff[BGE_MINI_BUFF_RING].desc.mem_va, + bgep->buff[BGE_MINI_BUFF_RING].desc.alength, + bgep->buff[BGE_MINI_BUFF_RING].desc.offset, + bgep->buff[BGE_MINI_BUFF_RING].desc.cookie.dmac_laddress, + bgep->buff[BGE_MINI_BUFF_RING].desc.cookie.dmac_size, + BGE_MINI_SLOTS_USED, + sizeof(bge_rbd_t))); + + BGE_DEBUG(("RXD PROD DONE: va=%p alen=%d off=%d pa=%llx psz=%d", + area.mem_va, + area.alength, + area.offset, + area.cookie.dmac_laddress, + area.cookie.dmac_size)); + ASSERT(area.alength == 0); area = bgep->tx_desc; - for (ring = 0; ring < tx_rings; ++ring) + + BGE_DEBUG(("TXD INIT: va=%p alen=%d off=%d pa=%llx psz=%d", + area.mem_va, + area.alength, + area.offset, + area.cookie.dmac_laddress, + area.cookie.dmac_size)); + + for (ring = 0; ring < tx_rings; ++ring) { bge_slice_chunk(&bgep->send[ring].desc, &area, BGE_SEND_SLOTS_USED, sizeof (bge_sbd_t)); - for (; ring < BGE_SEND_RINGS_MAX; ++ring) + + BGE_DEBUG(("TXD RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + ring, + bgep->send[ring].desc.mem_va, + bgep->send[ring].desc.alength, + bgep->send[ring].desc.offset, + bgep->send[ring].desc.cookie.dmac_laddress, + bgep->send[ring].desc.cookie.dmac_size, + BGE_SEND_SLOTS_USED, + sizeof(bge_sbd_t))); + } + + for (; ring < BGE_SEND_RINGS_MAX; ++ring) /* skip unused rings */ bge_slice_chunk(&bgep->send[ring].desc, &area, 0, sizeof (bge_sbd_t)); + bge_slice_chunk(&bgep->statistics, &area, 1, sizeof (bge_statistics_t)); + BGE_DEBUG(("TXD STATISTICS: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + bgep->statistics.mem_va, + bgep->statistics.alength, + bgep->statistics.offset, + bgep->statistics.cookie.dmac_laddress, + bgep->statistics.cookie.dmac_size, + 1, + sizeof(bge_statistics_t))); + bge_slice_chunk(&bgep->status_block, &area, 1, sizeof (bge_status_t)); + BGE_DEBUG(("TXD STATUS BLOCK: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)", + bgep->status_block.mem_va, + bgep->status_block.alength, + bgep->status_block.offset, + bgep->status_block.cookie.dmac_laddress, + bgep->status_block.cookie.dmac_size, + 1, + sizeof(bge_status_t))); + + BGE_DEBUG(("TXD DONE: va=%p alen=%d off=%d pa=%llx psz=%d", + area.mem_va, + area.alength, + area.offset, + area.cookie.dmac_laddress, + area.cookie.dmac_size)); + ASSERT(area.alength == BGE_STATUS_PADDING); + DMA_ZERO(bgep->status_block); return (DDI_SUCCESS); } +#undef BGE_DBG +#define BGE_DBG BGE_DBG_INIT /* debug flag for this code */ + /* * This routine frees the transmit and receive buffers and descriptors. * Make sure the chip is stopped before calling it! @@ -2840,7 +3158,6 @@ bge_find_mac_address(bge_t *bgep, chip_id_t *cidp) cidp->vendor_addr.set ? "" : "not ")); } - /*ARGSUSED*/ int bge_check_acc_handle(bge_t *bgep, ddi_acc_handle_t handle) @@ -2961,6 +3278,7 @@ bge_unattach(bge_t *bgep) ddi_periodic_delete(bgep->periodic_id); bgep->periodic_id = NULL; } + if (bgep->progress & PROGRESS_KSTATS) bge_fini_kstats(bgep); if (bgep->progress & PROGRESS_PHY) @@ -3008,8 +3326,11 @@ bge_unattach(bge_t *bgep) ddi_remove_softintr(bgep->drain_id); if (bgep->progress & PROGRESS_BUFS) bge_free_bufs(bgep); - if (bgep->progress & PROGRESS_REGS) + if (bgep->progress & PROGRESS_REGS) { ddi_regs_map_free(&bgep->io_handle); + if (bgep->ape_enabled) + ddi_regs_map_free(&bgep->ape_handle); + } if (bgep->progress & PROGRESS_CFG) pci_config_teardown(&bgep->cfg_handle); @@ -3093,6 +3414,209 @@ bge_resume(dev_info_t *devinfo) return (DDI_SUCCESS); } +static int +bge_fw_img_is_valid(bge_t *bgep, uint32_t offset) +{ + uint32_t val; + + if (bge_nvmem_read32(bgep, offset, &val) || + (val & 0xfc000000) != 0x0c000000 || + bge_nvmem_read32(bgep, offset + 4, &val) || + val != 0) + return (0); + + return (1); +} + +static void +bge_read_mgmtfw_ver(bge_t *bgep) +{ + uint32_t val; + uint32_t offset; + uint32_t start; + int i, vlen; + + for (offset = NVM_DIR_START; + offset < NVM_DIR_END; + offset += NVM_DIRENT_SIZE) { + if (bge_nvmem_read32(bgep, offset, &val)) + return; + + if ((val >> NVM_DIRTYPE_SHIFT) == NVM_DIRTYPE_ASFINI) + break; + } + + if (offset == NVM_DIR_END) + return; + + if (bge_nvmem_read32(bgep, offset - 4, &start)) + return; + + if (bge_nvmem_read32(bgep, offset + 4, &offset) || + !bge_fw_img_is_valid(bgep, offset) || + bge_nvmem_read32(bgep, offset + 8, &val)) + return; + + offset += val - start; + + vlen = strlen(bgep->fw_version); + + bgep->fw_version[vlen++] = ','; + bgep->fw_version[vlen++] = ' '; + + for (i = 0; i < 4; i++) { + uint32_t v; + + if (bge_nvmem_read32(bgep, offset, &v)) + return; + + v = BE_32(v); + + offset += sizeof(v); + + if (vlen > BGE_FW_VER_SIZE - sizeof(v)) { + memcpy(&bgep->fw_version[vlen], &v, BGE_FW_VER_SIZE - vlen); + break; + } + + memcpy(&bgep->fw_version[vlen], &v, sizeof(v)); + vlen += sizeof(v); + } +} + +static void +bge_read_dash_ver(bge_t *bgep) +{ + int vlen; + uint32_t apedata; + char *fwtype; + + if (!bgep->ape_enabled || !bgep->asf_enabled) + return; + + apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG); + if (apedata != APE_SEG_SIG_MAGIC) + return; + + apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS); + if (!(apedata & APE_FW_STATUS_READY)) + return; + + apedata = bge_ape_get32(bgep, BGE_APE_FW_VERSION); + + if (bge_ape_get32(bgep, BGE_APE_FW_FEATURES) & + BGE_APE_FW_FEATURE_NCSI) { + bgep->ape_has_ncsi = B_TRUE; + fwtype = "NCSI"; + } else if ((bgep->chipid.device == DEVICE_ID_5725) || + (bgep->chipid.device == DEVICE_ID_5727)) { + fwtype = "SMASH"; + } else { + fwtype = "DASH"; + } + + vlen = strlen(bgep->fw_version); + + snprintf(&bgep->fw_version[vlen], BGE_FW_VER_SIZE - vlen, + " %s v%d.%d.%d.%d", fwtype, + (apedata & APE_FW_VERSION_MAJMSK) >> APE_FW_VERSION_MAJSFT, + (apedata & APE_FW_VERSION_MINMSK) >> APE_FW_VERSION_MINSFT, + (apedata & APE_FW_VERSION_REVMSK) >> APE_FW_VERSION_REVSFT, + (apedata & APE_FW_VERSION_BLDMSK)); +} + +static void +bge_read_bc_ver(bge_t *bgep) +{ + uint32_t val; + uint32_t offset; + uint32_t start; + uint32_t ver_offset; + int i, dst_off; + uint32_t major; + uint32_t minor; + boolean_t newver = B_FALSE; + + if (bge_nvmem_read32(bgep, 0xc, &offset) || + bge_nvmem_read32(bgep, 0x4, &start)) + return; + + if (bge_nvmem_read32(bgep, offset, &val)) + return; + + if ((val & 0xfc000000) == 0x0c000000) { + if (bge_nvmem_read32(bgep, offset + 4, &val)) + return; + + if (val == 0) + newver = B_TRUE; + } + + dst_off = strlen(bgep->fw_version); + + if (newver) { + if (((BGE_FW_VER_SIZE - dst_off) < 16) || + bge_nvmem_read32(bgep, offset + 8, &ver_offset)) + return; + + offset = offset + ver_offset - start; + for (i = 0; i < 16; i += 4) { + if (bge_nvmem_read32(bgep, offset + i, &val)) + return; + val = BE_32(val); + memcpy(bgep->fw_version + dst_off + i, &val, + sizeof(val)); + } + } else { + if (bge_nvmem_read32(bgep, NVM_PTREV_BCVER, &ver_offset)) + return; + + major = (ver_offset & NVM_BCVER_MAJMSK) >> NVM_BCVER_MAJSFT; + minor = ver_offset & NVM_BCVER_MINMSK; + snprintf(&bgep->fw_version[dst_off], BGE_FW_VER_SIZE - dst_off, + "v%d.%02d", major, minor); + } +} + +static void +bge_read_fw_ver(bge_t *bgep) +{ + uint32_t val; + uint32_t magic; + + *bgep->fw_version = 0; + + if ((bgep->chipid.nvtype == BGE_NVTYPE_NONE) || + (bgep->chipid.nvtype == BGE_NVTYPE_UNKNOWN)) { + snprintf(bgep->fw_version, sizeof(bgep->fw_version), "sb"); + return; + } + + mutex_enter(bgep->genlock); + + bge_nvmem_read32(bgep, 0, &magic); + + if (magic == EEPROM_MAGIC) { + bge_read_bc_ver(bgep); + } else { + /* ignore other configs for now */ + mutex_exit(bgep->genlock); + return; + } + + if (bgep->ape_enabled) { + if (bgep->asf_enabled) { + bge_read_dash_ver(bgep); + } + } else if (bgep->asf_enabled) { + bge_read_mgmtfw_ver(bgep); + } + + mutex_exit(bgep->genlock); + + bgep->fw_version[BGE_FW_VER_SIZE - 1] = 0; /* safety */ +} + /* * attach(9E) -- Attach a device to the system * @@ -3108,6 +3632,10 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) int instance; int err; int intr_types; + int *props = NULL; + uint_t numProps; + uint32_t regval; + uint32_t pci_state_reg; #ifdef BGE_IPMI_ASF uint32_t mhcrValue; #ifdef __sparc @@ -3209,15 +3737,20 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) * has been set in PCI_CONF_COMM already, we need to write the * byte-swapped value to it. So we just write zero first for simplicity. */ - if (DEVICE_5717_SERIES_CHIPSETS(bgep)) + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, 0); +#else + mhcrValue = MHCR_ENABLE_INDIRECT_ACCESS | + MHCR_ENABLE_TAGGED_STATUS_MODE | + MHCR_MASK_INTERRUPT_MODE | + MHCR_MASK_PCI_INT_OUTPUT | + MHCR_CLEAR_INTERRUPT_INTA; +#endif pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcrValue); bge_ind_put32(bgep, MEMORY_ARBITER_MODE_REG, bge_ind_get32(bgep, MEMORY_ARBITER_MODE_REG) | MEMORY_ARBITER_ENABLE); -#else - mhcrValue = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR); -#endif if (mhcrValue & MHCR_ENABLE_ENDIAN_WORD_SWAP) { bgep->asf_wordswapped = B_TRUE; } else { @@ -3231,7 +3764,7 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) } bgep->progress |= PROGRESS_CFG; cidp = &bgep->chipid; - bzero(cidp, sizeof (*cidp)); + bzero(cidp, sizeof(*cidp)); bge_chip_cfg_init(bgep, cidp, B_FALSE); if (bge_check_acc_handle(bgep, bgep->cfg_handle) != DDI_FM_OK) { ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_LOST); @@ -3264,6 +3797,8 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) DDI_PROP_DONTPASS, rxrings_propname, cidp->rx_rings); cidp->tx_rings = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS, txrings_propname, cidp->tx_rings); + cidp->eee = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, + DDI_PROP_DONTPASS, eee_propname, cidp->eee); cidp->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, DDI_PROP_DONTPASS, default_mtu, BGE_DEFAULT_MTU); @@ -3282,6 +3817,36 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) goto attach_fail; } bgep->io_regs = regs; + + bgep->ape_enabled = B_FALSE; + bgep->ape_regs = NULL; + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { + err = ddi_regs_map_setup(devinfo, BGE_PCI_APEREGS_RNUMBER, + ®s, 0, 0, &bge_reg_accattr, &bgep->ape_handle); + if (err != DDI_SUCCESS) { + ddi_regs_map_free(&bgep->io_handle); + bge_problem(bgep, "ddi_regs_map_setup() failed"); + goto attach_fail; + } + bgep->ape_regs = regs; + bgep->ape_enabled = B_TRUE; + + /* + * Allow reads and writes to the + * APE register and memory space. + */ + + pci_state_reg = pci_config_get32(bgep->cfg_handle, + PCI_CONF_BGE_PCISTATE); + pci_state_reg |= PCISTATE_ALLOW_APE_CTLSPC_WR | + PCISTATE_ALLOW_APE_SHMEM_WR | PCISTATE_ALLOW_APE_PSPACE_WR; + pci_config_put32(bgep->cfg_handle, + PCI_CONF_BGE_PCISTATE, pci_state_reg); + + bge_ape_lock_init(bgep); + } + bgep->progress |= PROGRESS_REGS; /* @@ -3293,6 +3858,29 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) goto attach_fail; } + err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, bgep->devinfo, + 0, "reg", &props, &numProps); + if ((err == DDI_PROP_SUCCESS) && (numProps > 0)) { + bgep->pci_bus = PCI_REG_BUS_G(props[0]); + bgep->pci_dev = PCI_REG_DEV_G(props[0]); + bgep->pci_func = PCI_REG_FUNC_G(props[0]); + ddi_prop_free(props); + } + + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) { + regval = bge_reg_get32(bgep, CPMU_STATUS_REG); + if ((bgep->chipid.device == DEVICE_ID_5719) || + (bgep->chipid.device == DEVICE_ID_5720)) { + bgep->pci_func = + ((regval & CPMU_STATUS_FUNC_NUM_5719) >> + CPMU_STATUS_FUNC_NUM_5719_SHIFT); + } else { + bgep->pci_func = ((regval & CPMU_STATUS_FUNC_NUM) >> + CPMU_STATUS_FUNC_NUM_SHIFT); + } + } + err = bge_alloc_bufs(bgep); if (err != DDI_SUCCESS) { bge_problem(bgep, "DMA buffer allocation failed"); @@ -3477,6 +4065,16 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) * Determine whether to override the chip's own MAC address */ bge_find_mac_address(bgep, cidp); + { + int slot; + for (slot = 0; slot < MAC_ADDRESS_REGS_MAX; slot++) { + ethaddr_copy(cidp->vendor_addr.addr, + bgep->curr_addr[slot].addr); + bgep->curr_addr[slot].set = 1; + } + } + + bge_read_fw_ver(bgep); bgep->unicst_addr_total = MAC_ADDRESS_REGS_MAX; bgep->unicst_addr_avail = MAC_ADDRESS_REGS_MAX; @@ -3492,7 +4090,10 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) macp->m_max_sdu = cidp->ethmax_size - sizeof (struct ether_header); macp->m_margin = VLAN_TAGSZ; macp->m_priv_props = bge_priv_prop; - macp->m_v12n = MAC_VIRT_LEVEL1; + +#if defined(ILLUMOS) + bge_m_unicst(bgep, cidp->vendor_addr.addr); +#endif /* * Finally, we're ready to register ourselves with the MAC layer diff --git a/usr/src/uts/common/io/bge/bge_mii.c b/usr/src/uts/common/io/bge/bge_mii.c index f24b6a3..68823b3 100644 --- a/usr/src/uts/common/io/bge/bge_mii.c +++ b/usr/src/uts/common/io/bge/bge_mii.c @@ -20,7 +20,13 @@ */ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010-2013, by Broadcom, Inc. + * All Rights Reserved. + */ + +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. + * All rights reserved. */ #include "bge_impl.h" @@ -143,6 +149,23 @@ bge_phydump(bge_t *bgep, uint16_t mii_status, uint16_t aux) #endif /* BGE_DEBUGGING */ +static void +bge_phy_toggle_auxctl_smdsp(bge_t *bgep, + boolean_t enable) +{ + uint16_t val; + + val = bge_mii_get16(bgep, MII_AUX_CONTROL); + + if (enable) { + val |= MII_AUX_CTRL_SMDSP_ENA; + } else { + val &= ~MII_AUX_CTRL_SMDSP_ENA; + } + + bge_mii_put16(bgep, MII_AUX_CONTROL, (val | MII_AUX_CTRL_TX_6DB)); +} + /* * Basic low-level function to probe for a PHY * @@ -153,6 +176,7 @@ bge_phy_probe(bge_t *bgep) { uint16_t miicfg; uint32_t nicsig, niccfg; + int i; BGE_TRACE(("bge_phy_probe($%p)", (void *)bgep)); @@ -174,8 +198,10 @@ bge_phy_probe(bge_t *bgep) * order to clear any sticky bits (but they should * have been cleared by the RESET, I think). */ - miicfg = bge_mii_get16(bgep, MII_STATUS); - miicfg = bge_mii_get16(bgep, MII_STATUS); + for (i = 0; i < 100; i++) { + drv_usecwait(40); + miicfg = bge_mii_get16(bgep, MII_STATUS); + } BGE_DEBUG(("bge_phy_probe: status 0x%x", miicfg)); /* @@ -190,7 +216,7 @@ bge_phy_probe(bge_t *bgep) case 0xffff: return (B_FALSE); - default : + default: return (B_TRUE); } } @@ -527,7 +553,7 @@ bge_phy_bit_err_fix(bge_t *bgep) } /* - * End of Broadcom-derived workaround code * + * End of Broadcom-derived workaround code */ static int @@ -536,12 +562,13 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown) uint16_t phy_status; boolean_t reset_ok; uint16_t extctrl, auxctrl; + int i; BGE_TRACE(("bge_restart_copper($%p, %d)", (void *)bgep, powerdown)); ASSERT(mutex_owned(bgep->genlock)); - switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) { + switch (MHCR_CHIP_ASIC_REV(bgep)) { default: /* * Shouldn't happen; it means we don't recognise this chip. @@ -559,7 +586,7 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown) case MHCR_CHIP_ASIC_REV_5906: case MHCR_CHIP_ASIC_REV_5700: case MHCR_CHIP_ASIC_REV_5701: - case MHCR_CHIP_ASIC_REV_5723: + case MHCR_CHIP_ASIC_REV_5723: /* 5717 and 5725 series as well */ case MHCR_CHIP_ASIC_REV_5721_5751: /* * Just a plain reset; the "check" code breaks these chips @@ -588,7 +615,7 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown) break; } - switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) { + switch (MHCR_CHIP_ASIC_REV(bgep)) { case MHCR_CHIP_ASIC_REV_5705: case MHCR_CHIP_ASIC_REV_5721_5751: bge_phy_bit_err_fix(bgep); @@ -623,8 +650,10 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown) * order to clear any sticky bits (but they should * have been cleared by the RESET, I think). */ - phy_status = bge_mii_get16(bgep, MII_STATUS); - phy_status = bge_mii_get16(bgep, MII_STATUS); + for (i = 0; i < 100; i++) { + drv_usecwait(40); + phy_status = bge_mii_get16(bgep, MII_STATUS); + } BGE_DEBUG(("bge_restart_copper: status 0x%x", phy_status)); /* @@ -635,6 +664,232 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown) return (DDI_SUCCESS); } +boolean_t +bge_eee_cap(bge_t * bgep) +{ + if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep))) { + /* EEE is not supported on this chip */ + BGE_DEBUG(("bge_eee: eee not supported (device 0x%x)", + bgep->chipid.device)); + return (B_FALSE); + } + + switch (CHIP_ASIC_REV_PROD_ID(bgep)) { + case CHIP_ASIC_REV_5717_B0: /* = CHIP_ASIC_REV_5718_B0 */ + case CHIP_ASIC_REV_5717_C0: + /* case CHIP_ASIC_REV_5718_B0: */ + case CHIP_ASIC_REV_5719_A0: + case CHIP_ASIC_REV_5719_A1: + case CHIP_ASIC_REV_5720_A0: + case CHIP_ASIC_REV_5725_A0: + case CHIP_ASIC_REV_5727_B0: + return (B_TRUE); + + default: + /* EEE is not supported on this asic rev */ + BGE_DEBUG(("bge_eee: eee not supported (asic rev 0x%08x)", + bgep->chipid.asic_rev)); + return (B_FALSE); + } +} + +void +bge_eee_init(bge_t * bgep) +{ + uint32_t val; + + BGE_TRACE(("bge_eee_init($%p)", (void *)bgep)); + + ASSERT(mutex_owned(bgep->genlock)); + + if (!bge_eee_cap(bgep)) { + return; + } + + /* Enable MAC control of LPI */ + + val = (EEE_LINK_IDLE_PCIE_NL0 | EEE_LINK_IDLE_UART_IDL); + if (DEVICE_5725_SERIES_CHIPSETS(bgep)) + val |= EEE_LINK_IDLE_APE_TX_MT; + bge_reg_put32(bgep, EEE_LINK_IDLE_CONTROL_REG, val); + + bge_reg_put32(bgep, EEE_CONTROL_REG, EEE_CONTROL_EXIT_20_1_US); + + val = EEE_MODE_ERLY_L1_XIT_DET | EEE_MODE_LPI_IN_TX | + EEE_MODE_LPI_IN_RX | EEE_MODE_EEE_ENABLE; + + if (bgep->chipid.device != DEVICE_ID_5717) + val |= EEE_MODE_SND_IDX_DET_EN; + + //val |= EEE_MODE_APE_TX_DET_EN; + + if (!bgep->chipid.eee) { + val = 0; + } + + bge_reg_put32(bgep, EEE_MODE_REG, val); + + /* Set EEE timer debounce values */ + + bge_reg_put32(bgep, EEE_DEBOUNCE_T1_CONTROL_REG, + EEE_DEBOUNCE_T1_PCIEXIT_2047US | EEE_DEBOUNCE_T1_LNKIDLE_2047US); + + bge_reg_put32(bgep, EEE_DEBOUNCE_T2_CONTROL_REG, + EEE_DEBOUNCE_T2_APE_TX_2047US | EEE_DEBOUNCE_T2_TXIDXEQ_2047US); +} + +void +bge_eee_autoneg(bge_t * bgep, boolean_t adv_100fdx, boolean_t adv_1000fdx) +{ + uint32_t val; + uint16_t mii_val; + + BGE_TRACE(("bge_eee_autoneg($%p)", (void *)bgep)); + + ASSERT(mutex_owned(bgep->genlock)); + + if (!bge_eee_cap(bgep)) { + return; + } + + /* Disable LPI Requests */ + val = bge_reg_get32(bgep, EEE_MODE_REG); + val &= ~EEE_MODE_LPI_ENABLE; + bge_reg_put32(bgep, EEE_MODE_REG, val); + + bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE); + + mii_val = 0; + + if (bgep->chipid.eee) { + if (adv_100fdx) { + mii_val |= EEE_CL45_D7_RESULT_STAT_LP_100TX; + } + if (adv_1000fdx) { + mii_val |= EEE_CL45_D7_RESULT_STAT_LP_1000T; + } + } + + /* Enable EEE advertisement for the specified mode(s)... */ + bge_mii_put16(bgep, MII_MMD_CTRL, MDIO_MMD_AN); + bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA, MDIO_AN_EEE_ADV); + bge_mii_put16(bgep, MII_MMD_CTRL, + MII_MMD_CTRL_DATA_NOINC | MDIO_MMD_AN); + bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA, mii_val); + + /* Setup PHY DSP for EEE */ + switch (bgep->chipid.device) { + case DEVICE_ID_5717: + case DEVICE_ID_5718: + case DEVICE_ID_5719: + /* If we advertised any EEE advertisements above... */ + if (mii_val) { + mii_val = (MII_DSP_TAP26_ALNOKO | + MII_DSP_TAP26_RMRXSTO | + MII_DSP_TAP26_OPCSINPT); + } + bge_phydsp_write(bgep, MII_DSP_TAP26, mii_val); + /* fall through */ + case DEVICE_ID_5720: + case DEVICE_ID_5725: + case DEVICE_ID_5727: + mii_val = bge_phydsp_read(bgep, MII_DSP_CH34TP2); + bge_phydsp_write(bgep, MII_DSP_CH34TP2, + (mii_val | MII_DSP_CH34TP2_HIBW01)); + } + + bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE); +} + +void +bge_eee_adjust(bge_t * bgep) +{ + uint32_t val; + uint16_t mii_val; + + BGE_TRACE(("bge_eee_adjust($%p, %d)", (void *)bgep)); + + ASSERT(mutex_owned(bgep->genlock)); + + if (!bge_eee_cap(bgep)) { + return; + } + + bgep->eee_lpi_wait = 0; + + /* Check for PHY link status */ + if (bgep->param_link_up) { + BGE_DEBUG(("bge_eee_adjust: link status up")); + + /* + * XXX if duplex full and speed is 1000 or 100 then do the + * following... + */ + + if (bgep->param_link_speed == 1000) { + BGE_DEBUG(("bge_eee_adjust: eee timing for 1000Mb")); + bge_reg_put32(bgep, EEE_CONTROL_REG, + EEE_CONTROL_EXIT_16_5_US); + } else if (bgep->param_link_speed == 100) { + BGE_DEBUG(("bge_eee_adjust: eee timing for 100Mb")); + bge_reg_put32(bgep, EEE_CONTROL_REG, + EEE_CONTROL_EXIT_36_US); + } + + /* Read PHY's EEE negotiation status */ + bge_mii_put16(bgep, MII_MMD_CTRL, MDIO_MMD_AN); + bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA, + EEE_CL45_D7_RESULT_STAT); + bge_mii_put16(bgep, MII_MMD_CTRL, + MII_MMD_CTRL_DATA_NOINC | MDIO_MMD_AN); + mii_val = bge_mii_get16(bgep, MII_MMD_ADDRESS_DATA); + + /* Enable EEE LPI request if EEE negotiated */ + if ((mii_val == EEE_CL45_D7_RESULT_STAT_LP_1000T) || + (mii_val == EEE_CL45_D7_RESULT_STAT_LP_100TX)) { + BGE_DEBUG(("bge_eee_adjust: eee negotiaton success, lpi scheduled")); + bgep->eee_lpi_wait = 2; + } else { + BGE_DEBUG(("bge_eee_adjust: eee negotiation failed")); + } + } else { + BGE_DEBUG(("bge_eee_adjust: link status down")); + } + + if (!bgep->eee_lpi_wait) { + if (bgep->param_link_up) { + bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE); + bge_phydsp_write(bgep, MII_DSP_TAP26, 0); + bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE); + } + + /* Disable LPI requests */ + val = bge_reg_get32(bgep, EEE_MODE_REG); + val &= ~EEE_MODE_LPI_ENABLE; + bge_reg_put32(bgep, EEE_MODE_REG, val); + } +} + +void +bge_eee_enable(bge_t * bgep) +{ + uint32_t val; + + /* XXX check for EEE for 5717 family... */ + + if (bgep->param_link_speed == 1000) { + bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE); + bge_phydsp_write(bgep, MII_DSP_TAP26, + MII_DSP_TAP26_ALNOKO | MII_DSP_TAP26_RMRXSTO); + bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE); + } + + val = bge_reg_get32(bgep, EEE_MODE_REG); + val |= EEE_MODE_LPI_ENABLE; + bge_reg_put32(bgep, EEE_MODE_REG, val); +} + /* * Synchronise the (copper) PHY's speed/duplex/autonegotiation capabilities * and advertisements with the required settings as specified by the various @@ -866,6 +1121,10 @@ bge_update_copper(bge_t *bgep) break; } #endif /* BGE_COPPER_WIRESPEED */ + + /* enable EEE on those chips that support it */ + bge_eee_autoneg(bgep, adv_100fdx, adv_1000fdx); + return (DDI_SUCCESS); } @@ -877,13 +1136,17 @@ bge_check_copper(bge_t *bgep, boolean_t recheck) uint16_t aux; uint_t mode; boolean_t linkup; + int i; /* * Step 10: read the status from the PHY (which is self-clearing * on read!); also read & clear the main (Ethernet) MAC status * (the relevant bits of this are write-one-to-clear). */ - mii_status = bge_mii_get16(bgep, MII_STATUS); + for (i = 0; i < 100; i++) { + drv_usecwait(40); + mii_status = bge_mii_get16(bgep, MII_STATUS); + } emac_status = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG); bge_reg_put32(bgep, ETHERNET_MAC_STATUS_REG, emac_status); @@ -897,14 +1160,19 @@ bge_check_copper(bge_t *bgep, boolean_t recheck) * we not forcing a recheck (i.e. the link state was already * known), there's nothing to do. */ - if (mii_status == bgep->phy_gen_status && !recheck) + if (mii_status == bgep->phy_gen_status && !recheck) { + BGE_DEBUG(("bge_check_copper: no link change")); return (B_FALSE); + } do { /* * Step 11: read AUX STATUS register to find speed/duplex */ - aux = bge_mii_get16(bgep, MII_AUX_STATUS); + for (i = 0; i < 2000; i++) { + drv_usecwait(10); + aux = bge_mii_get16(bgep, MII_AUX_STATUS); + } BGE_CDB(bge_phydump, (bgep, mii_status, aux)); /* @@ -935,7 +1203,12 @@ bge_check_copper(bge_t *bgep, boolean_t recheck) */ bgep->phy_aux_status = aux; bgep->phy_gen_status = mii_status; - mii_status = bge_mii_get16(bgep, MII_STATUS); + + for (i = 0; i < 100; i++) + { + drv_usecwait(40); + mii_status = bge_mii_get16(bgep, MII_STATUS); + } } while (mii_status != bgep->phy_gen_status); /* @@ -1014,10 +1287,12 @@ bge_check_copper(bge_t *bgep, boolean_t recheck) bgep->param_link_duplex = bge_copper_link_duplex[mode]; } - BGE_DEBUG(("bge_check_copper: link now %s speed %d duplex %d", - UPORDOWN(bgep->param_link_up), - bgep->param_link_speed, - bgep->param_link_duplex)); + bge_eee_adjust(bgep); + + bge_log(bgep, "bge_check_copper: link now %s speed %d duplex %d", + UPORDOWN(bgep->param_link_up), + bgep->param_link_speed, + bgep->param_link_duplex); return (B_TRUE); } @@ -1054,13 +1329,13 @@ bge_restart_serdes(bge_t *bgep, boolean_t powerdown) * appropriately for the SerDes interface ... */ macmode = bge_reg_get32(bgep, ETHERNET_MAC_MODE_REG); - if (DEVICE_5714_SERIES_CHIPSETS(bgep)) { - macmode |= ETHERNET_MODE_LINK_POLARITY; - macmode &= ~ETHERNET_MODE_PORTMODE_MASK; + macmode &= ~ETHERNET_MODE_LINK_POLARITY; + macmode &= ~ETHERNET_MODE_PORTMODE_MASK; + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep) || + DEVICE_5714_SERIES_CHIPSETS(bgep)) { macmode |= ETHERNET_MODE_PORTMODE_GMII; } else { - macmode &= ~ETHERNET_MODE_LINK_POLARITY; - macmode &= ~ETHERNET_MODE_PORTMODE_MASK; macmode |= ETHERNET_MODE_PORTMODE_TBI; } bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, macmode); @@ -1288,21 +1563,34 @@ bge_check_serdes(bge_t *bgep, boolean_t recheck) * to BCM5705, BCM5788, BCM5721, BCM5751, BCM5752, * BCM5714, and BCM5715 devices. */ - if (DEVICE_5714_SERIES_CHIPSETS(bgep)) { + if (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep) || + DEVICE_5714_SERIES_CHIPSETS(bgep)) { tx_status = bge_reg_get32(bgep, TRANSMIT_MAC_STATUS_REG); linkup = BIS(tx_status, TRANSMIT_STATUS_LINK_UP); emac_status = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG); bgep->serdes_status = emac_status; + /* clear write-one-to-clear bits in MAC status */ + if ((emac_status & ETHERNET_STATUS_MI_COMPLETE) && + (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep))) { + emac_status |= ETHERNET_STATUS_SYNC_CHANGED | + ETHERNET_STATUS_CFG_CHANGED; + } + bge_reg_put32(bgep, + ETHERNET_MAC_STATUS_REG, emac_status); + /* + * If the link status has not changed then then + * break. If it has loop around and recheck again. + * Keep looping until the link status has not + * changed. + */ if ((linkup && linkup_old) || (!linkup && !linkup_old)) { - emac_status &= ~ETHERNET_STATUS_LINK_CHANGED; - emac_status &= ~ETHERNET_STATUS_RECEIVING_CFG; break; } - emac_status |= ETHERNET_STATUS_LINK_CHANGED; - emac_status |= ETHERNET_STATUS_RECEIVING_CFG; if (linkup) linkup_old = B_TRUE; else @@ -1467,10 +1755,10 @@ bge_check_serdes(bge_t *bgep, boolean_t recheck) } bgep->link_state = LINK_STATE_UNKNOWN; - BGE_DEBUG(("bge_check_serdes: link now %s speed %d duplex %d", - UPORDOWN(bgep->param_link_up), - bgep->param_link_speed, - bgep->param_link_duplex)); + bge_log(bgep, "bge_check_serdes: link now %s speed %d duplex %d", + UPORDOWN(bgep->param_link_up), + bgep->param_link_speed, + bgep->param_link_duplex); return (B_TRUE); } @@ -1495,6 +1783,8 @@ static const phys_ops_t serdes_ops = { int bge_phys_init(bge_t *bgep) { + uint32_t regval; + BGE_TRACE(("bge_phys_init($%p)", (void *)bgep)); mutex_enter(bgep->genlock); @@ -1506,13 +1796,12 @@ bge_phys_init(bge_t *bgep) * BCM800x PHY. */ bgep->phy_mii_addr = 1; + if (DEVICE_5717_SERIES_CHIPSETS(bgep)) { - int regval = bge_reg_get32(bgep, CPMU_STATUS_REG); - if (regval & CPMU_STATUS_FUN_NUM) - bgep->phy_mii_addr += 1; + bgep->phy_mii_addr = (bgep->pci_func + 1); regval = bge_reg_get32(bgep, SGMII_STATUS_REG); if (regval & MEDIA_SELECTION_MODE) - bgep->phy_mii_addr += 7; + bgep->phy_mii_addr += 7; /* sgmii */ } if (bge_phy_probe(bgep)) { @@ -1606,18 +1895,15 @@ bge_phys_update(bge_t *bgep) boolean_t bge_phys_check(bge_t *bgep) { - int32_t orig_state; - boolean_t recheck; - BGE_TRACE(("bge_phys_check($%p)", (void *)bgep)); ASSERT(mutex_owned(bgep->genlock)); - orig_state = bgep->link_state; - recheck = orig_state == LINK_STATE_UNKNOWN; - recheck = (*bgep->physops->phys_check)(bgep, recheck); - if (!recheck) - return (B_FALSE); - - return (B_TRUE); + /* + * Force a link recheck if current state is unknown. + * phys_check() returns TRUE if the link status changed, + * FALSE otherwise. + */ + return ((*bgep->physops->phys_check)(bgep, + (bgep->link_state == LINK_STATE_UNKNOWN))); } diff --git a/usr/src/uts/common/io/bge/bge_send.c b/usr/src/uts/common/io/bge/bge_send.c index 28080d9..87e0c01 100644 --- a/usr/src/uts/common/io/bge/bge_send.c +++ b/usr/src/uts/common/io/bge/bge_send.c @@ -20,7 +20,13 @@ */ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010-2013, by Broadcom, Inc. + * All Rights Reserved. + */ + +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. + * All rights reserved. */ #include "bge_impl.h" @@ -443,6 +449,11 @@ start_tx: hw_sbd_p->flags |= SBD_FLAG_IP_CKSUM; if (pktp->pflags & HCK_FULLCKSUM) hw_sbd_p->flags |= SBD_FLAG_TCP_UDP_CKSUM; + if (!(bgep->chipid.flags & CHIP_FLAG_NO_JUMBO) && + (DEVICE_5717_SERIES_CHIPSETS(bgep) || + DEVICE_5725_SERIES_CHIPSETS(bgep)) && + (txbuf->copy_len > ETHERMAX)) + hw_sbd_p->flags |= SBD_FLAG_JMB_PKT; hw_sbd_p->flags |= SBD_FLAG_PACKET_END; txfill_next = NEXT(txfill_next, BGE_SEND_BUF_MAX);