diff options
Diffstat (limited to 'usr/src/uts/common/io/bge/bge_chip2.c')
-rw-r--r-- | usr/src/uts/common/io/bge/bge_chip2.c | 1462 |
1 files changed, 1048 insertions, 414 deletions
diff --git a/usr/src/uts/common/io/bge/bge_chip2.c b/usr/src/uts/common/io/bge/bge_chip2.c index f687ce4892..7790c2df6e 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; @@ -3102,38 +3668,6 @@ bge_chip_sync(bge_t *bgep) return (retval); } -/* - * This array defines the sequence of state machine control registers - * in which the <enable> 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 */ -}; - #ifndef __sparc static bge_regno_t quiesce_regs[] = { READ_DMA_MODE_REG, @@ -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 <check> 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 */ |