--- usr/src/uts/common/io/bge/bge_chip2.c 2014-02-09 16:11:44.912645900 -0500 +++ usr/src/uts/common/io/bge/bge_chip2.c 2013-06-28 19:01:04.000000000 -0400 @@ -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_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_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_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 @@ 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 @@ 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 @@ * 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 @@ 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,32 @@ * 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 +563,14 @@ 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 +664,10 @@ 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 +676,8 @@ } #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 +712,10 @@ #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 +727,8 @@ } #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 +886,10 @@ 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 +948,10 @@ #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 +978,10 @@ 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 +991,8 @@ } #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 +1024,10 @@ 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 +1038,8 @@ } #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 +1079,10 @@ 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 +1098,8 @@ } #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 +1300,34 @@ (void) bge_mii_access(bgep, regno, data, MI_COMMS_COMMAND_WRITE); } +uint16_t bge_phydsp_read(bge_t *bgep, bge_regno_t regno); +#pragma no_inline(bge_phydsp_read) + +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); +} + +void bge_phydsp_write(bge_t *bgep, bge_regno_t regno, uint16_t data); +#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 */ @@ -1697,8 +1779,7 @@ * ENODEV if the NVmem device is missing or otherwise unusable * EPROTO on other h/w or s/w errors. */ -static int -bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp) +int bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp) { int err; @@ -1720,6 +1801,7 @@ 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 +1811,7 @@ 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 +1822,7 @@ 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 +1834,7 @@ 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 +1853,37 @@ 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 +2012,11 @@ 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 +2062,452 @@ } #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(MAJVERSION, MINVERSION)); + 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 +2539,6 @@ 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 +2548,7 @@ int err; uint_t i; - sys_ok = dev_ok = B_FALSE; + dev_ok = B_FALSE; cidp = &bgep->chipid; /* @@ -2026,13 +2591,31 @@ 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 +2631,6 @@ 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 +3033,15 @@ * 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 +3069,6 @@ 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 +3087,12 @@ "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 +3175,9 @@ 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 +3197,12 @@ * 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 +3262,14 @@ /* 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 +3289,16 @@ 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 +3355,27 @@ 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,23 +3447,19 @@ * 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; - } else if (bgep->param_link_speed == 10 || - bgep->param_link_speed == 100) + } + else if (bgep->param_link_speed == 10 || + bgep->param_link_speed == 100) macmode |= ETHERNET_MODE_PORTMODE_MII; else macmode |= ETHERNET_MODE_PORTMODE_GMII; @@ -3102,38 +3665,6 @@ 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 */ -}; - #ifndef __sparc static bge_regno_t quiesce_regs[] = { READ_DMA_MODE_REG, @@ -3185,30 +3716,44 @@ { 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 +3840,7 @@ * 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 +3854,9 @@ 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 +3865,6 @@ #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 +3904,8 @@ 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 +3942,26 @@ 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 +3969,7 @@ } } #endif + /* * Adapted from Broadcom document 570X-PG102-R, pp 102-116. * Updated to reflect Broadcom document 570X-PG104-R, pp 146-159. @@ -3434,17 +3984,13 @@ 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 +4005,8 @@ 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 +4016,23 @@ } #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 +4048,6 @@ (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 +4064,15 @@ * 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 +4124,20 @@ #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 +4154,26 @@ */ 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 +4285,11 @@ 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 +4297,23 @@ 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 @@ 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 @@ /* * 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_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 @@ * 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,12 @@ * 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 +4705,14 @@ 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 +4739,28 @@ 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 +4788,21 @@ 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 +4818,8 @@ retval = DDI_FAILURE; #endif + drv_usecwait(100); + /* * Step 91: disable auto-polling of PHY status */ @@ -4169,8 +4856,16 @@ * 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 +4908,17 @@ } #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 +4989,53 @@ 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 +5073,8 @@ * 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 +5126,12 @@ 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 +5149,31 @@ 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 +5204,6 @@ 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 +5255,7 @@ return (result); chip_stop: + #ifdef BGE_IPMI_ASF if (bgep->asf_enabled && bgep->asf_status == ASF_STAT_RUN) { /* @@ -4510,157 +5285,6 @@ #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 +5334,7 @@ /* * 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 +5345,6 @@ bge_t *bgep; uint_t result; boolean_t error; - boolean_t linkchg; int dma_state; bgep = (void *)arg; @@ -4740,7 +5361,6 @@ result = DDI_INTR_CLAIMED; error = B_FALSE; - linkchg = B_FALSE; mutex_enter(bgep->genlock); switch (bgep->bge_chip_state) { @@ -4748,7 +5368,18 @@ 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 +5458,6 @@ 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 +5487,6 @@ } 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,30 +5504,62 @@ bge_chip_cyclic(void *arg) { bge_t *bgep; + uint32_t regval; bgep = arg; switch (bgep->bge_chip_state) { default: +#if defined(__S11) || defined(__S12) return; +#else /* not __S11 or __S12 */ + goto bge_chip_cyclic_done; +#endif 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); + +#if !(defined(__S11) || defined(__S12)) +bge_chip_cyclic_done: + bgep->periodic_id = timeout(bge_chip_cyclic, bgep, BGE_CYCLIC_TIMEOUT); +#endif } @@ -5784,8 +6427,10 @@ 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 +6570,10 @@ break; } } + + if (mode == BGE_INIT_RESET || + mode == BGE_SUSPEND_RESET) + bge_ape_driver_state_change(bgep, mode); } @@ -5965,6 +6614,9 @@ default: break; } + + if (mode == BGE_SHUTDOWN_RESET) + bge_ape_driver_state_change(bgep, mode); } #endif /* BGE_IPMI_ASF */ --- usr/src/uts/common/io/bge/bge_impl.h 2014-02-09 16:11:49.053373800 -0500 +++ usr/src/uts/common/io/bge/bge_impl.h 2013-06-28 19:01:04.000000000 -0400 @@ -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 @@ #endif /* __sparcv9 */ #include #include -#include #include #include #include @@ -77,6 +82,18 @@ #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,9 +111,34 @@ */ extern int secpolicy_net_config(const cred_t *, boolean_t); -#include /* originally from cassini */ #include /* by fjlite out of intel */ +#if !(defined(__S11) || defined(__S12)) +/* missing defines in Solaris 10... */ +#define MII_AN_NXTPGLP 8 /* Link Part. Augo neg. Next Page */ +#define MII_MSCONTROL 9 /* 100Base-T2 and 1000 BaseT Ctrl. */ +#define MII_MSSTATUS 10 /* 100Base-T2 and 1000 BaseT Stat. */ +#define MII_EXTSTATUS 15 /* Extended status registers */ + +#define MII_CONTROL_1GB (1<<6) + +#define MII_AN_SELECTOR_8023 0x0001 + +#define MII_ABILITY_PAUSE (1<<10) +#define MII_ABILITY_ASMPAUSE (1<<11) + +#define MII_MSCONTROL_TEST_MASK (3<<13) +#define MII_MSCONTROL_MANUAL (1<<12) /* manual master/slave control */ +#define MII_MSCONTROL_MASTER (1<<11) +#define MII_MSCONTROL_MULTIPORT (1<<10) /* DCE, default 0 for NICs */ +#define MII_MSCONTROL_1000T_FD (1<<9) +#define MII_MSCONTROL_1000T (1<<8) + +#define MII_MSSTATUS_LP1000T_FD (1<<11) +#define MII_MSSTATUS_LP1000T (1<<10) +#endif + +#include "version.h" #include "bge.h" #include "bge_hw.h" @@ -133,6 +175,7 @@ #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 +211,7 @@ #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 +345,6 @@ #define BGE_LOWAT (256) #define BGE_HIWAT (256*1024) - /* * Basic data types, for clarity in distinguishing 'numbers' * used for different purposes ... @@ -593,6 +636,7 @@ */ 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 +671,7 @@ 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,12 +763,27 @@ /* * 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; + +#if defined(__S11) || defined(__S12) ddi_periodic_t periodic_id; /* periodical callback */ +#else /* not __S11 or __S12 */ + timeout_id_t periodic_id; /* periodical callback */ +#endif ddi_softintr_t factotum_id; /* factotum callback */ ddi_softintr_t drain_id; /* reschedule callback */ @@ -784,6 +844,8 @@ 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 +946,7 @@ 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 +1016,13 @@ 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 +1095,31 @@ */ #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 ... @@ -1147,11 +1207,21 @@ /* 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_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp); +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); @@ -1182,7 +1252,11 @@ int bge_chip_sync(bge_t *bgep); #endif void bge_chip_blank(void *arg, time_t ticks, uint_t count, int flag); +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) +extern mblk_t *bge_poll_ring(void *, int, int); +#else /* not __S11 or __S12 */ extern mblk_t *bge_poll_ring(void *, int); +#endif uint_t bge_chip_factotum(caddr_t arg); void bge_chip_cyclic(void *arg); enum ioc_reply bge_chip_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, @@ -1231,7 +1305,9 @@ 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 +1360,6 @@ #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 --- usr/src/uts/common/io/bge/bge_main2.c 2014-02-09 16:11:44.966358300 -0500 +++ usr/src/uts/common/io/bge/bge_main2.c 2013-06-28 19:01:04.000000000 -0400 @@ -20,19 +20,49 @@ */ /* - * 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" #include #include #include +#if defined(__S11) || defined(__S12) #include +#endif + +#if !(defined(__S11) || defined(__S12)) +#define mri_driver mr_driver +#define mri_start mr_start +#define mri_stop mr_stop +#define mri_intr mr_intr +#define mri_poll mr_poll +#define mri_tx mr_send +#define mgi_driver mrg_driver +#define mgi_start mrg_start +#define mgi_stop mrg_stop +#define mgi_count mrg_count +#define mgi_addmac mrg_addmac +#define mgi_remmac mrg_addmac +#define mr_gaddring mr_gadd_ring +#define mr_gremring mr_grem_ring +#endif /* not __S11 or __S12 */ + +#ifndef STRINGIFY +#define XSTRINGIFY(x) #x +#define STRINGIFY(x) XSTRINGIFY(x) +#endif /* * This is the string displayed by modinfo, etc. */ -static char bge_ident[] = "Broadcom Gb Ethernet"; +static char bge_ident[] = "Broadcom Gb Ethernet v" STRINGIFY(MAJVERSION) "." STRINGIFY(MINVERSION) "." STRINGIFY(REVVERSION); /* * Property names @@ -47,18 +77,25 @@ 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); +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) +static int bge_addmac(void *, const uint8_t *, uint64_t); +#else /* not __S11 or __S12 */ +static int bge_addmac(void *, const uint8_t *); +#endif +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 +103,7 @@ 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 +140,9 @@ 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 +160,52 @@ 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, +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) NULL, +#else /* not __S11 or __S12 */ + bge_m_unicst, +#endif 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 +554,6 @@ } 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 +606,11 @@ 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 +670,7 @@ { 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 +737,7 @@ } } #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 +1313,27 @@ 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 +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) + , 0 +#endif + ); + } + + 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 +1494,38 @@ 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 +1549,14 @@ * specified ring 'arg'. */ static int -bge_addmac(void *arg, const uint8_t *mac_addr) +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) +bge_addmac(void * arg, + const uint8_t * mac_addr, + uint64_t flags) +#else /* not __S11 or __S12 */ +bge_addmac(void * arg, + const uint8_t * mac_addr) +#endif { recv_ring_t *rrp = (recv_ring_t *)arg; bge_t *bgep = rrp->bgep; @@ -1440,6 +1569,10 @@ int slot; int err; +#if defined(__S11) || defined(__S12) + _NOTE(ARGUNUSED(flags)) +#endif + mutex_enter(bgep->genlock); if (bgep->unicst_addr_avail == 0) { mutex_exit(bgep->genlock); @@ -1579,8 +1712,13 @@ return (0); } + static int +#if defined(__S11) || defined(__S12) +bge_flag_intr_enable(mac_ring_driver_t ih) +#else /* not __S11 or __S12 */ bge_flag_intr_enable(mac_intr_handle_t ih) +#endif { recv_ring_t *rrp = (recv_ring_t *)ih; bge_t *bgep = rrp->bgep; @@ -1593,7 +1731,11 @@ } static int +#if defined(__S11) || defined(__S12) +bge_flag_intr_disable(mac_ring_driver_t ih) +#else /* not __S11 or __S12 */ bge_flag_intr_disable(mac_intr_handle_t ih) +#endif { recv_ring_t *rrp = (recv_ring_t *)ih; bge_t *bgep = rrp->bgep; @@ -1606,13 +1748,19 @@ } static int -bge_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) +bge_ring_start(mac_ring_driver_t rh +#if defined(__S11) || defined(__S12) + , uint64_t mr_gen_num +#endif + ) { recv_ring_t *rx_ring; rx_ring = (recv_ring_t *)rh; mutex_enter(rx_ring->rx_lock); +#if defined(__S11) || defined(__S12) rx_ring->ring_gen_num = mr_gen_num; +#endif mutex_exit(rx_ring->rx_lock); return (0); } @@ -1623,8 +1771,12 @@ * for given ring_group, noted by rg_index. */ void -bge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, - const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) +bge_fill_ring(void * arg, + mac_ring_type_t rtype, + const int rg_index, + const int index, + mac_ring_info_t * infop, + mac_ring_handle_t rh) { bge_t *bgep = arg; mac_intr_t *mintr; @@ -1641,13 +1793,17 @@ infop->mri_driver = (mac_ring_driver_t)rx_ring; infop->mri_start = bge_ring_start; infop->mri_stop = NULL; - infop->mri_poll = bge_poll_ring; +#if defined(__S11) || defined(__S12) infop->mri_stat = bge_rx_ring_stat; +#endif + infop->mri_poll = bge_poll_ring; mintr = &infop->mri_intr; +#if !(defined(__S11) || defined(__S12)) mintr->mi_handle = (mac_intr_handle_t)rx_ring; - mintr->mi_enable = bge_flag_intr_enable; - mintr->mi_disable = bge_flag_intr_disable; +#endif + mintr->mi_enable = (mac_intr_enable_t)bge_flag_intr_enable; + mintr->mi_disable = (mac_intr_disable_t)bge_flag_intr_disable; break; } @@ -1665,8 +1821,11 @@ * and use the same internal handle for rings and groups. */ 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) +bge_fill_group(void * arg, + mac_ring_type_t rtype, + const int rg_index, + mac_group_info_t * infop, + mac_group_handle_t gh) { bge_t *bgep = arg; @@ -1685,6 +1844,9 @@ infop->mgi_addmac = bge_addmac; infop->mgi_remmac = bge_remmac; infop->mgi_count = 1; +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) + infop->mgi_flags = MAC_GROUP_DEFAULT; +#endif break; } case MAC_RING_TYPE_TX: @@ -1694,11 +1856,13 @@ } } + /*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 +1871,34 @@ *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); +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) + cap_rings->mr_version = MAC_RINGS_VERSION_1; + cap_rings->mr_flags = MAC_RINGS_FLAGS_NONE; +#endif 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 +1999,8 @@ } } +#endif /* NOT_SUPPORTED_XXX */ + /* * Specific bge IOCTLs, the gld module handles the generic ones. */ @@ -1866,6 +2040,7 @@ case BGE_HARD_RESET: break; +#ifdef NOT_SUPPORTED_XXX case LB_GET_INFO_SIZE: case LB_GET_INFO: case LB_GET_MODE: @@ -1873,6 +2048,7 @@ /* FALLTHRU */ case LB_SET_MODE: break; +#endif } @@ -1916,12 +2092,14 @@ 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 +2172,7 @@ */ #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 +2766,11 @@ /* * 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 +2783,9 @@ 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 +2798,15 @@ if (err != DDI_SUCCESS) return (DDI_FAILURE); } - - dma_attr.dma_attr_flags &= ~DDI_DMA_RELAXED_ORDERING; + BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Tx Buffers (txbuffsize = %d)", + txbuffsize/BGE_SPLIT, + txbuffsize)); + + 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 +2819,21 @@ 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 +2843,260 @@ 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 +3233,6 @@ cidp->vendor_addr.set ? "" : "not ")); } - /*ARGSUSED*/ int bge_check_acc_handle(bge_t *bgep, ddi_acc_handle_t handle) @@ -2958,9 +3350,14 @@ * Clean up and free all BGE data structures */ if (bgep->periodic_id != NULL) { +#if defined(__S11) || defined(__S12) ddi_periodic_delete(bgep->periodic_id); +#else /* not __S11 or __S12 */ + untimeout(bgep->periodic_id); +#endif bgep->periodic_id = NULL; } + if (bgep->progress & PROGRESS_KSTATS) bge_fini_kstats(bgep); if (bgep->progress & PROGRESS_PHY) @@ -3008,8 +3405,11 @@ 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 +3493,207 @@ 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 +3709,10 @@ 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 @@ -3138,6 +3743,8 @@ bgep = kmem_zalloc(sizeof (*bgep), KM_SLEEP); bgep->pstats = kmem_zalloc(sizeof (bge_statistics_reg_t), KM_SLEEP); ddi_set_driver_private(devinfo, bgep); + snprintf(bgep->version, sizeof(bgep->version), "%d.%d.%d", + MAJVERSION, MINVERSION, REVVERSION); bgep->bge_guard = BGE_GUARD; bgep->devinfo = devinfo; bgep->param_drain_max = 64; @@ -3209,15 +3816,20 @@ * 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 { @@ -3264,6 +3876,8 @@ 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 +3896,37 @@ 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 +3938,31 @@ 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 +4147,18 @@ * Determine whether to override the chip's own MAC address */ bge_find_mac_address(bgep, cidp); +#if !(defined(__S11) || defined(__S12)) + { + 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; + } + } +#endif + + bge_read_fw_ver(bgep); bgep->unicst_addr_total = MAC_ADDRESS_REGS_MAX; bgep->unicst_addr_avail = MAC_ADDRESS_REGS_MAX; @@ -3492,7 +4174,10 @@ 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 @@ -3509,8 +4194,12 @@ * Register a periodical handler. * bge_chip_cyclic() is invoked in kernel context. */ +#if defined(__S11) || defined(__S12) bgep->periodic_id = ddi_periodic_add(bge_chip_cyclic, bgep, BGE_CYCLIC_PERIOD, DDI_IPL_0); +#else /* not __S11 or __S12 */ + bgep->periodic_id = timeout(bge_chip_cyclic, bgep, BGE_CYCLIC_TIMEOUT); +#endif bgep->progress |= PROGRESS_READY; ASSERT(bgep->bge_guard == BGE_GUARD); @@ -3702,8 +4391,10 @@ nodev, /* reset */ NULL, /* cb_ops */ D_MP, /* bus_ops */ - NULL, /* power */ - bge_quiesce /* quiesce */ + NULL /* power */ +#if defined(__S11) || defined(__S12) + , bge_quiesce /* quiesce */ +#endif ); static struct modldrv bge_modldrv = { --- usr/src/uts/common/io/bge/bge_recv2.c 2014-02-09 16:11:45.013234900 -0500 +++ usr/src/uts/common/io/bge/bge_recv2.c 2013-06-28 19:01:04.000000000 -0400 @@ -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. */ @@ -348,7 +353,14 @@ * a new interrupt firing and reaching before poll thread returns. */ mblk_t * -bge_poll_ring(void *arg, int bytes_to_pickup) +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) +bge_poll_ring(void * arg, + int bytes_to_pickup, + int num_pkts) +#else /* not __S11 or __S12 */ +bge_poll_ring(void * arg, + int bytes_to_pickup) +#endif { recv_ring_t *rrp = arg; bge_t *bgep = rrp->bgep; @@ -359,6 +371,10 @@ mblk_t *mp; size_t sz = 0; +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) + _NOTE(ARGUNUSED(num_pkts)) +#endif + mutex_enter(rrp->rx_lock); /* @@ -438,7 +454,11 @@ mutex_exit(rrp->rx_lock); if (mp != NULL) +#if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS) mac_rx_ring(bgep->mh, rrp->ring_handle, mp, rrp->ring_gen_num); +#else /* not __S11 or __S12 */ + mac_rx(bgep->mh, bgep->macRxResourceHandles[index], mp); +#endif } } --- usr/src/uts/common/io/bge/bge_hw.h 2014-02-09 16:11:49.038724500 -0500 +++ usr/src/uts/common/io/bge/bge_hw.h 2013-06-28 19:01:04.000000000 -0400 @@ -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 @@ #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 @@ (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 @@ #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 @@ #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 @@ #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 @@ * 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 @@ */ #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 @@ #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 @@ #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 @@ * 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 @@ * 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 @@ #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 @@ #define JUMBO_RCV_BD_REPLENISH_DEFAULT 0x00000020 /* 32 */ /* - * CPMU registers (5717/5718 only) + * CPMU registers (5717/18/19/20 only) */ -#define CPMU_STATUS_REG 0x362c -#define CPMU_STATUS_FUN_NUM 0x20000000 +#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 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 @@ * 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 @@ * 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 @@ #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 @@ /* * 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 @@ #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 @@ #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 @@ #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 --- usr/src/uts/common/io/bge/bge_kstats.c 2014-02-09 16:11:44.942920400 -0500 +++ usr/src/uts/common/io/bge/bge_kstats.c 2013-06-28 19:01:04.000000000 -0400 @@ -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 @@ { 18, "&supported" }, { 19, "&interface" }, + { 20, "nvtype" }, + + { 21, "asic_rev_prod_id" }, + { -1, NULL } }; @@ -343,6 +352,13 @@ 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); } @@ -379,6 +395,8 @@ { 25, "buff_mgr_status" }, { 26, "rcv_init_status" }, + { 27, "&version" }, + { -1, NULL } }; @@ -448,6 +466,8 @@ } mutex_exit(bgep->genlock); + bge_set_char_kstat(knp++, bgep->version); + return (0); } @@ -499,6 +519,7 @@ { MII_INTR_STATUS, "intr_status" }, { MII_INTR_MASK, "intr_mask" }, { MII_HCD_STATUS, "hcd_status" }, + { EEE_MODE_REG, "eee" }, { -1, NULL } }; @@ -540,6 +561,16 @@ 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 +598,7 @@ 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 +694,7 @@ 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 +766,8 @@ 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 +948,14 @@ *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 +1028,11 @@ *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 +1070,7 @@ *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 +1086,7 @@ mutex_exit(bgep->genlock); } break; +#endif case ETHER_STAT_LP_CAP_1000FDX: *val = bgep->param_lp_1000fdx; @@ -1086,6 +1124,7 @@ *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 +1140,7 @@ mutex_exit(bgep->genlock); } break; +#endif case ETHER_STAT_LINK_ASMPAUSE: *val = bgep->param_adv_asym_pause && @@ -1117,7 +1157,8 @@ 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: --- usr/src/uts/common/io/bge/bge_mii.c 2014-02-09 16:11:44.979054000 -0500 +++ usr/src/uts/common/io/bge/bge_mii.c 2013-06-28 19:01:04.000000000 -0400 @@ -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 @@ #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 @@ { uint16_t miicfg; uint32_t nicsig, niccfg; + int i; BGE_TRACE(("bge_phy_probe($%p)", (void *)bgep)); @@ -174,8 +198,11 @@ * 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)); /* @@ -527,7 +554,7 @@ } /* - * End of Broadcom-derived workaround code * + * End of Broadcom-derived workaround code */ static int @@ -536,12 +563,13 @@ 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 +587,7 @@ 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 +616,7 @@ 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 +651,11 @@ * 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 +666,246 @@ 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 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 +1137,10 @@ 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 +1152,18 @@ 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); @@ -898,13 +1178,20 @@ * known), there's nothing to do. */ 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 +1222,12 @@ */ 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 +1306,12 @@ 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 +1348,13 @@ * 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 +1582,34 @@ * 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 +1774,10 @@ } 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 +1802,8 @@ int bge_phys_init(bge_t *bgep) { + uint32_t regval; + BGE_TRACE(("bge_phys_init($%p)", (void *)bgep)); mutex_enter(bgep->genlock); @@ -1506,13 +1815,12 @@ * 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 +1914,15 @@ 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)); } + --- usr/src/uts/common/io/bge/bge_send.c 2014-02-09 16:11:45.076714200 -0500 +++ usr/src/uts/common/io/bge/bge_send.c 2013-06-28 19:01:04.000000000 -0400 @@ -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 @@ 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); --- usr/src/man/man7d/bge.7d 2014-02-08 15:37:07.006669300 -0500 +++ usr/src/man/man7d/bge.7d 2014-02-08 16:42:13.075223500 -0500 @@ -3,9 +3,9 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH BGE 7D "Apr 9, 2008" +.TH bge 7D "9 Apr 2008" "SunOS 5.11" "Devices" .SH NAME -bge \- SUNW,bge Gigabit Ethernet driver for Broadcom BCM57xx +bge \- Gigabit Ethernet driver for Broadcom BCM57xx NetXtreme Devices .SH SYNOPSIS .LP .nf @@ -15,54 +15,26 @@ .SH DESCRIPTION .sp .LP -The \fBbge\fR Gigabit Ethernet driver is a multi-threaded, loadable, clonable, -GLD-based STREAMS driver supporting the Data Link Provider Interface, -\fBdlpi\fR(7P), on Broadcom BCM57xx -(BCM5700/5701/5703/5704/5705/5705M/5714/5721/5751/5751M/5782/5788 on x86) -Gigabit Ethernet controllers fitted to the system motherboard. With the -exception of BCM5700/BCM5701/BCM5704S, these devices incorporate both MAC and -PHY functions and provide three-speed (copper) Ethernet operation on the RJ-45 -connectors. (BCM5700/BCM5701/BCM5704S do not have a PHY integrated into the MAC -chipset.) -.sp -.LP -The \fBbge\fR driver functions include controller initialization, frame -transmit and receive, promiscuous and multicast support, and error recovery and -reporting. -.sp -.LP -The \fBbge\fR driver and hardware support auto-negotiation, a protocol -specified by the 1000 Base-T standard. Auto-negotiation allows each device to -advertise its capabilities and discover those of its peer (link partner). The -highest common denominator supported by both link partners is automatically -selected, yielding the greatest available throughput, while requiring no manual -configuration. The \fBbge\fR driver also allows you to configure the advertised -capabilities to less than the maximum (where the full speed of the interface is -not required), or to force a specific mode of operation, irrespective of the -link partner's advertised capabilities. +The \fBbge\fR Gigabit Ethernet driver is a multi-threaded, loadable, clonable, GLD-based STREAMS driver supporting the Data Link Provider Interface, \fBdlpi\fR(7P), on Broadcom BCM57xx (BCM5700, 5701, 5702, 5703, 5704, 5705, 5714, 5715, 5717, 5718, 5719, 5720, 5721, 5722, 5723, 5725, 5727, 5751, 5753, 5754, 5755, 5756, 5780, 5782, 5784, 5785, 5786, 5787, 5788, 5789, 5901, 5906, 57780, 57788, 57790) Gigabit Ethernet controllers. With the exception of BCM5700, BCM5701, BCM5704S, these devices incorporate both MAC and PHY functions and provide three-speed (copper) Ethernet operation on the RJ-45 connectors. (BCM5700, BCM5701, BCM5704S do not have a PHY integrated into the MAC chipset.) +.sp +.LP +The \fBbge\fR driver functions include controller initialization, frame transmit and receive, promiscuous and multicast support, and error recovery and reporting. +.sp +.LP +The \fBbge\fR driver and hardware support auto-negotiation, a protocol specified by the 1000 Base-T standard. Auto-negotiation allows each device to advertise its capabilities and discover those of its peer (link partner). The highest common denominator supported by both link partners is automatically selected, yielding the greatest available throughput, while requiring no manual configuration. The \fBbge\fR driver also allows you to configure the advertised capabilities to less than the maximum (where the full speed of the interface is not required), or to force a specific mode of operation, irrespective of the link partner's advertised capabilities. .SH APPLICATION PROGRAMMING INTERFACE .sp .LP -The cloning character-special device, \fB/dev/bge\fR, is used to access all -BCM57xx devices ( (BCM5700/5701/5703/5704, 5705/5714/5721/5751/5751M/5782 on -x86) fitted to the system motherboard. +The cloning character-special device, \fB/dev/bge\fR, is used to access all BCM57xx devices (BCM5700, 5701, 5702, 5703, 5704, 5705, 5714, 5715, 5717, 5718, 5719, 5720, 5721, 5722, 5723, 5751, 5753, 5754, 5755, 5756, 5780, 5782, 5786, 5787, 5788, 5789, 5901, 5906). .sp .LP -The \fBbge\fR driver is managed by the \fBdladm\fR(1M) command line utility, -which allows VLANs to be defined on top of bge instances and for \fBbge\fR -instances to be aggregated. See \fBdladm\fR(1M) for more details. +The \fBbge\fR driver is managed by the \fBdladm\fR(1M) command line utility, which allows VLANs to be defined on top of bge instances and for \fBbge\fR instances to be aggregated. See \fBdladm\fR(1M) for more details. .sp .LP -You must send an explicit DL_ATTACH_REQ message to associate the opened stream -with a particular device (PPA). The PPA ID is interpreted as an unsigned -integer data type and indicates the corresponding device instance (unit) -number. The driver returns an error (DL_ERROR_ACK) if the PPA field value does -not correspond to a valid device instance number for the system. The device is -initialized on first attach and de-initialized (stopped) at last detach. +You must send an explicit DL_ATTACH_REQ message to associate the opened stream with a particular device (PPA). The PPA ID is interpreted as an unsigned integer data type and indicates the corresponding device instance (unit) number. The driver returns an error (DL_ERROR_ACK) if the PPA field value does not correspond to a valid device instance number for the system. The device is initialized on first attach and de-initialized (stopped) at last detach. .sp .LP -The values returned by the driver in the DL_INFO_ACK primitive in response to a -DL_INFO_REQ are: +The values returned by the driver in the DL_INFO_ACK primitive in response to a DL_INFO_REQ are: .RS +4 .TP .ie t \(bu @@ -91,27 +63,21 @@ .TP .ie t \(bu .el o -\fBSAP\fR length value is \fI-2\fR, meaning the physical address component is -followed immediately by a 2-byte \fBSAP\fR component within the \fBDLSAP\fR -address. +\fBSAP\fR length value is \fI-2\fR, meaning the physical address component is followed immediately by a 2-byte \fBSAP\fR component within the \fBDLSAP\fR address. .RE .RS +4 .TP .ie t \(bu .el o -Broadcast address value is the Ethernet/IEEE broadcast address -(FF:FF:FF:FF:FF:FF). +Broadcast address value is the Ethernet/IEEE broadcast address (FF:FF:FF:FF:FF:FF). .RE .sp .LP -Once in the DL_ATTACHED state, you must send a DL_BIND_REQ to associate a -particular Service Access Point (SAP) with the stream. +Once in the DL_ATTACHED state, you must send a DL_BIND_REQ to associate a particular Service Access Point (SAP) with the stream. .SH CONFIGURATION .sp .LP -By default, the \fBbge\fR driver performs auto-negotiation to select the link -speed and mode. Link speed and mode can be any one of the following, (as -described in the \fI IEEE803.2\fR standard): +There are a number of configuration properties that can be changed. These are modified in the \fBbge.conf\fR driver configuration file and take affect after the driver is reloaded. By default, the \fBbge\fR driver performs auto-negotiation to select the link speed and mode. Link speed and mode can be any one of the following, (as described in the \fI IEEE803.2\fR standard): .RS +4 .TP .ie t \(bu @@ -165,35 +131,27 @@ .RE .sp .LP -as the highest common denominator supported by both link partners. Because the -\fBbge\fR device supports all modes, the effect is to select the highest -throughput mode supported by the other device. +as the highest common denominator supported by both link partners. Because the \fBbge\fR device supports all modes, the effect is to select the highest throughput mode supported by the other device. .sp .LP -Alternatively, you can set the capabilities advertised by the \fBbge\fR device -using \fBdladm\fR(1M). The driver supports a number of parameters whose names -begin with \fBen_\fR (see below). Each of these parameters contains a boolean -value that determines whether the device advertises that mode of operation. If -\fBen_autoneg_cap\fR is set to 0, the driver forces the mode of operation -selected by the first non-zero parameter in priority order as listed below: +Alternatively, you can set the capabilities advertised by the \fBbge\fR device using \fBdladm\fR(1M). The driver supports a number of parameters whose names begin with \fBen_\fR (see below). Each of these parameters contains a boolean value that determines whether the device advertises that mode of operation. If \fBen_autoneg_cap\fR is set to 0, the driver forces the mode of operation selected by the first non-zero parameter in priority order as listed below: .sp .in +2 .nf (highest priority/greatest throughput) en_1000fdx_cap 1000Mbps full duplex - en_1000hdx_cap 1000Mbps half duplex - en_100fdx_cap 100Mbps full duplex - en_100hdx_cap 100Mbps half duplex - en_10fdx_cap 10Mbps full duplex - en_10hdx_cap 10Mbps half duplex + en_1000hdx_cap 1000Mpbs half duplex + en_100fdx_cap 100Mpbs full duplex + en_100hdx_cap 100Mpbs half duplex + en_10fdx_cap 10Mpbs full duplex + en_10hdx_cap 10Mpbs half duplex (lowest priority/least throughput) .fi .in -2 .sp .LP -For example, to prevent the device 'bge2' from advertising gigabit -capabilities, enter (as super-user): +For example, to prevent the device 'bge2' from advertising gigabit capabilities, enter (as super-user): .sp .in +2 .nf @@ -204,15 +162,10 @@ .sp .LP -All capabilities default to enabled. Note that changing any capability -parameter causes the link to go down while the link partners renegotiate the -link speed/duplex using the newly changed capabilities. +All capabilities default to enabled. Note that changing any capability parameter causes the link to go down while the link partners renegotiate the link speed/duplex using the newly changed capabilities. .sp .LP -The current settings of the parameters may be found using dladm show-ether. In -addition, the driver exports the current state, speed, duplex setting, and -working mode of the link via kstat parameters (these are read only and may not -be changed). For example, to check link state of device \fBbge0\fR: +The current settings of the parameters may be found using dladm show-dev. In addition, the driver exports the current state, speed, duplex setting, and working mode of the link via kstat parameters (these are read only and may not be changed). For example, to check link state of device \fBbge0\fR: .sp .in +2 .nf @@ -227,8 +180,7 @@ .sp .LP -The output above indicates that the link is up and running at 1Gbps full-duplex -with its rx/tx direction pause capability. +The output above indicates that the link is up and running at 1Gbps full-duplex with its rx/tx direction pause capability. .sp .LP To extract link state information for the same link using kstat: @@ -236,47 +188,48 @@ .in +2 .nf # kstat bge:0:mac:link_state -module: bge instance: 0 +module: bge instance: 0 name: mac class: net -link_state +link_state .fi .in -2 .sp .LP -The default MTU is 1500. To enable Jumbo Frames support, you can configure the -\fBbge\fR driver by defining the default_mtu property via \fBdladm\fR(1M) or in -\fBdriver.conf\fR(4) to greater than 1500 bytes (for example: -default_mtu=9000). Note that the largest jumbo size supported by bge is 9000 -bytes. Additionally, not all bge-derived devices currently support Jumbo -Frames. The following devices support Jumbo Frames up to 9KB: BCM5700, 5701, -5702, 5703C, 5703S, 5704C, 5704S, 5714C, 5714S, 5715C and 5715S. Other devices -currently do not support Jumbo Frames. +The default MTU is 1500. To enable Jumbo Frames support, you can configure the \fBbge\fR driver by defining the default_mtu property via \fBdladm\fR(1M) or in \fBbge.conf\fR to greater than 1500 bytes (for example: default_mtu=9000). Note that the largest jumbo size supported by bge is 9000 bytes. Additionally, not all bge-derived devices currently support Jumbo Frames. The following devices support Jumbo Frames up to 9KB: BCM5700, 5701, 5702, 5703C, 5703S, 5704C, 5704S, 5717/18/19/20, 5714C, 5714S, 5715C and 5715S. Other devices currently do not support Jumbo Frames. +.LP +BCM5717/18/19/20 devices support Energy Efficient Ethernet (EEE). This feature is turned off by default and can be turned on via the bge-eee property in the \fBdriver.conf\fR(4) file. .SH FILES .sp .ne 2 +.mk .na \fB\fB/kernel/drv/bge*\fR\fR .ad .RS 27n +.rt 32-bit ELF kernel module. (x86) .RE .sp .ne 2 +.mk .na \fB\fB/kernel/drv/amd64/bge\fR\fR .ad .RS 27n +.rt 64-bit ELF kernel module (x86). .RE .sp .ne 2 +.mk .na \fB\fB/kernel/drv/sparcv9/bge\fR\fR .ad .RS 27n +.rt 64-bit ELF kernel module (SPARC). .RE @@ -288,19 +241,19 @@ .sp .TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE +tab() box; +cw(2.75i) |cw(2.75i) +lw(2.75i) |lw(2.75i) +. +ATTRIBUTE TYPEATTRIBUTE VALUE _ -Architecture SPARC, x86 +ArchitectureSPARC, x86 .TE .SH SEE ALSO .sp .LP -\fBdladm\fR(1M), \fBdriver.conf\fR(4), \fBattributes\fR(5), \fBstreamio\fR(7I), -\fBdlpi\fR(7P) +\fBdladm\fR(1M), \fBdriver.conf\fR(4), \fBattributes\fR(5), \fBstreamio\fR(7I), \fBdlpi\fR(7P) .sp .LP \fIWriting Device Drivers\fR --- null 2014-02-09 17:36:36.903873100 -0500 +++ usr/src/uts/common/io/bge/version.h 2014-02-09 17:46:36.371921600 -0500 @@ -0,0 +1,10 @@ + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. + * All rights reserved. + */ + +#define MAJVERSION 0 +#define MINVERSION 0 +#define REVVERSION 1 + --- usr/src/pkg/manifests/driver-network-bge.mf 2014-02-06 19:04:47.000000000 -0500 +++ usr/src/pkg/manifests/driver-network-bge.mf 2014-02-09 19:28:50.294203900 -0500 @@ -24,6 +24,9 @@ # # +# Copyright 2014 Nexenta Systems, Inc. All rights reserved. +# + # The default for payload-bearing actions in this package is to appear in the # global zone only. See the include file for greater detail, as well as # information about overriding the defaults. @@ -57,9 +60,11 @@ alias=pci14e4,1649 \ alias=pci14e4,1653 \ alias=pci14e4,1654 \ + alias=pci14e4,1657 \ alias=pci14e4,1659 \ alias=pci14e4,165d \ alias=pci14e4,165e \ + alias=pci14e4,165f \ alias=pci14e4,1668 \ alias=pci14e4,1669 \ alias=pci14e4,166a \ @@ -77,11 +82,22 @@ alias=pci14e4,16a7 \ alias=pci14e4,16a8 \ alias=pci14e4,16c7 \ + alias=pciex14e4,16b1 \ + alias=pciex14e4,16b2 \ + alias=pciex14e4,16b3 \ + alias=pciex14e4,16b4 \ + alias=pciex14e4,16b5 \ + alias=pciex14e4,16b6 \ + alias=pciex14e4,16b7 \ + alias=pciex14e4,16f3 \ alias=pciex14e4,1655 \ alias=pciex14e4,1656 \ + alias=pciex14e4,1657 \ alias=pciex14e4,165a \ alias=pciex14e4,165b \ alias=pciex14e4,165c \ + alias=pciex14e4,165f \ + alias=pciex14e4,1665 \ alias=pciex14e4,1673 \ alias=pciex14e4,1674 \ alias=pciex14e4,1677 \ @@ -90,9 +106,20 @@ alias=pciex14e4,1680 \ alias=pciex14e4,1681 \ alias=pciex14e4,1684 \ + alias=pciex14e4,1688 \ + alias=pciex14e4,1689 \ + alias=pciex14e4,1690 \ + alias=pciex14e4,1691 \ alias=pciex14e4,1692 \ + alias=pciex14e4,1694 \ + alias=pciex14e4,1698 \ + alias=pciex14e4,1699 \ + alias=pciex14e4,169a \ + alias=pciex14e4,169b \ alias=pciex14e4,169d \ alias=pciex14e4,16fd \ + alias=pciex14e4,16f3 \ + alias=pciex14e4,16f7 \ alias=pciex14e4,1713 $(sparc_ONLY)driver name=bge clone_perms="bge 0666 root sys" \ perms="* 0666 root sys" \ @@ -133,3 +160,5 @@ license lic_CDDL license=lic_CDDL license usr/src/uts/common/io/bge/THIRDPARTYLICENSE \ license=usr/src/uts/common/io/bge/THIRDPARTYLICENSE + +