1dd52495fSSaurabh Misra /* 2dd52495fSSaurabh Misra * CDDL HEADER START 3dd52495fSSaurabh Misra * 4dd52495fSSaurabh Misra * The contents of this file are subject to the terms of the 5dd52495fSSaurabh Misra * Common Development and Distribution License (the "License"). 6dd52495fSSaurabh Misra * You may not use this file except in compliance with the License. 7dd52495fSSaurabh Misra * 8dd52495fSSaurabh Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9dd52495fSSaurabh Misra * or http://www.opensolaris.org/os/licensing. 10dd52495fSSaurabh Misra * See the License for the specific language governing permissions 11dd52495fSSaurabh Misra * and limitations under the License. 12dd52495fSSaurabh Misra * 13dd52495fSSaurabh Misra * When distributing Covered Code, include this CDDL HEADER in each 14dd52495fSSaurabh Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15dd52495fSSaurabh Misra * If applicable, add the following below this CDDL HEADER, with the 16dd52495fSSaurabh Misra * fields enclosed by brackets "[]" replaced with your own identifying 17dd52495fSSaurabh Misra * information: Portions Copyright [yyyy] [name of copyright owner] 18dd52495fSSaurabh Misra * 19dd52495fSSaurabh Misra * CDDL HEADER END 20dd52495fSSaurabh Misra */ 21dd52495fSSaurabh Misra 22dd52495fSSaurabh Misra /* 237a0c1e29SCrisson Guanghao Hu * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24dd52495fSSaurabh Misra */ 25dd52495fSSaurabh Misra #include <sys/stream.h> 26dd52495fSSaurabh Misra #include <sys/strsun.h> 27dd52495fSSaurabh Misra #include <sys/stat.h> 28dd52495fSSaurabh Misra #include <sys/pci.h> 29dd52495fSSaurabh Misra #include <sys/modctl.h> 30dd52495fSSaurabh Misra #include <sys/kstat.h> 31dd52495fSSaurabh Misra #include <sys/ethernet.h> 32dd52495fSSaurabh Misra #include <sys/devops.h> 33dd52495fSSaurabh Misra #include <sys/debug.h> 34dd52495fSSaurabh Misra #include <sys/conf.h> 35dd52495fSSaurabh Misra #include <sys/sysmacros.h> 36dd52495fSSaurabh Misra #include <sys/dditypes.h> 37dd52495fSSaurabh Misra #include <sys/ddi.h> 38dd52495fSSaurabh Misra #include <sys/sunddi.h> 39dd52495fSSaurabh Misra #include <sys/miiregs.h> 40dd52495fSSaurabh Misra #include <sys/byteorder.h> 41dd52495fSSaurabh Misra #include <sys/cyclic.h> 42dd52495fSSaurabh Misra #include <sys/note.h> 43dd52495fSSaurabh Misra #include <sys/crc32.h> 44dd52495fSSaurabh Misra #include <sys/mac_provider.h> 45dd52495fSSaurabh Misra #include <sys/mac_ether.h> 46dd52495fSSaurabh Misra #include <sys/vlan.h> 47dd52495fSSaurabh Misra #include <sys/errno.h> 48dd52495fSSaurabh Misra #include <sys/sdt.h> 49dd52495fSSaurabh Misra #include <sys/strsubr.h> 50dd52495fSSaurabh Misra 51dd52495fSSaurabh Misra #include "bfe.h" 52dd52495fSSaurabh Misra #include "bfe_hw.h" 53dd52495fSSaurabh Misra 54dd52495fSSaurabh Misra 55dd52495fSSaurabh Misra /* 56dd52495fSSaurabh Misra * Broadcom BCM4401 chipsets use two rings : 57dd52495fSSaurabh Misra * 58dd52495fSSaurabh Misra * - One TX : For sending packets down the wire. 59dd52495fSSaurabh Misra * - One RX : For receving packets. 60dd52495fSSaurabh Misra * 61dd52495fSSaurabh Misra * Each ring can have any number of descriptors (configured during attach). 62dd52495fSSaurabh Misra * As of now we configure only 128 descriptor per ring (TX/RX). Each descriptor 63dd52495fSSaurabh Misra * has address (desc_addr) and control (desc_ctl) which holds a DMA buffer for 64dd52495fSSaurabh Misra * the packet and control information (like start/end of frame or end of table). 65dd52495fSSaurabh Misra * The descriptor table is allocated first and then a DMA buffer (for a packet) 66dd52495fSSaurabh Misra * is allocated and linked to each descriptor. 67dd52495fSSaurabh Misra * 68dd52495fSSaurabh Misra * Each descriptor entry is bfe_desc_t structure in bfe. During TX/RX 69dd52495fSSaurabh Misra * interrupt, the stat register will point to current descriptor being 70dd52495fSSaurabh Misra * processed. 71dd52495fSSaurabh Misra * 72dd52495fSSaurabh Misra * Here's an example of TX and RX ring : 73dd52495fSSaurabh Misra * 74dd52495fSSaurabh Misra * TX: 75dd52495fSSaurabh Misra * 76dd52495fSSaurabh Misra * Base of the descriptor table is programmed using BFE_DMATX_CTRL control 77dd52495fSSaurabh Misra * register. Each 'addr' points to DMA buffer (or packet data buffer) to 78dd52495fSSaurabh Misra * be transmitted and 'ctl' has the length of the packet (usually MTU). 79dd52495fSSaurabh Misra * 80dd52495fSSaurabh Misra * ----------------------| 81dd52495fSSaurabh Misra * | addr |Descriptor 0 | 82dd52495fSSaurabh Misra * | ctl | | 83dd52495fSSaurabh Misra * ----------------------| 84dd52495fSSaurabh Misra * | addr |Descriptor 1 | SOF (start of the frame) 85dd52495fSSaurabh Misra * | ctl | | 86dd52495fSSaurabh Misra * ----------------------| 87dd52495fSSaurabh Misra * | ... |Descriptor... | EOF (end of the frame) 88dd52495fSSaurabh Misra * | ... | | 89dd52495fSSaurabh Misra * ----------------------| 90dd52495fSSaurabh Misra * | addr |Descritor 127 | 91dd52495fSSaurabh Misra * | ctl | EOT | EOT (End of Table) 92dd52495fSSaurabh Misra * ----------------------| 93dd52495fSSaurabh Misra * 94dd52495fSSaurabh Misra * 'r_curr_desc' : pointer to current descriptor which can be used to transmit 95dd52495fSSaurabh Misra * a packet. 96dd52495fSSaurabh Misra * 'r_avail_desc' : decremented whenever a packet is being sent. 97dd52495fSSaurabh Misra * 'r_cons_desc' : incremented whenever a packet is sent down the wire and 98dd52495fSSaurabh Misra * notified by an interrupt to bfe driver. 99dd52495fSSaurabh Misra * 100dd52495fSSaurabh Misra * RX: 101dd52495fSSaurabh Misra * 102dd52495fSSaurabh Misra * Base of the descriptor table is programmed using BFE_DMARX_CTRL control 103dd52495fSSaurabh Misra * register. Each 'addr' points to DMA buffer (or packet data buffer). 'ctl' 104dd52495fSSaurabh Misra * contains the size of the DMA buffer and all the DMA buffers are 105dd52495fSSaurabh Misra * pre-allocated during attach and hence the maxmium size of the packet is 106dd52495fSSaurabh Misra * also known (r_buf_len from the bfe_rint_t structure). During RX interrupt 107dd52495fSSaurabh Misra * the packet length is embedded in bfe_header_t which is added by the 108dd52495fSSaurabh Misra * chip in the beginning of the packet. 109dd52495fSSaurabh Misra * 110dd52495fSSaurabh Misra * ----------------------| 111dd52495fSSaurabh Misra * | addr |Descriptor 0 | 112dd52495fSSaurabh Misra * | ctl | | 113dd52495fSSaurabh Misra * ----------------------| 114dd52495fSSaurabh Misra * | addr |Descriptor 1 | 115dd52495fSSaurabh Misra * | ctl | | 116dd52495fSSaurabh Misra * ----------------------| 117dd52495fSSaurabh Misra * | ... |Descriptor... | 118dd52495fSSaurabh Misra * | ... | | 119dd52495fSSaurabh Misra * ----------------------| 120dd52495fSSaurabh Misra * | addr |Descriptor 127| 121dd52495fSSaurabh Misra * | ctl | EOT | EOT (End of Table) 122dd52495fSSaurabh Misra * ----------------------| 123dd52495fSSaurabh Misra * 124dd52495fSSaurabh Misra * 'r_curr_desc' : pointer to current descriptor while receving a packet. 125dd52495fSSaurabh Misra * 126dd52495fSSaurabh Misra */ 127dd52495fSSaurabh Misra 128dd52495fSSaurabh Misra #define MODULE_NAME "bfe" 129dd52495fSSaurabh Misra 130dd52495fSSaurabh Misra /* 131dd52495fSSaurabh Misra * Used for checking PHY (link state, speed) 132dd52495fSSaurabh Misra */ 133dd52495fSSaurabh Misra #define BFE_TIMEOUT_INTERVAL (1000 * 1000 * 1000) 134dd52495fSSaurabh Misra 135dd52495fSSaurabh Misra 136dd52495fSSaurabh Misra /* 137dd52495fSSaurabh Misra * Chip restart action and reason for restart 138dd52495fSSaurabh Misra */ 139dd52495fSSaurabh Misra #define BFE_ACTION_RESTART 0x1 /* For restarting the chip */ 140dd52495fSSaurabh Misra #define BFE_ACTION_RESTART_SETPROP 0x2 /* restart due to setprop */ 141dd52495fSSaurabh Misra #define BFE_ACTION_RESTART_FAULT 0x4 /* restart due to fault */ 142dd52495fSSaurabh Misra #define BFE_ACTION_RESTART_PKT 0x8 /* restart due to pkt timeout */ 143dd52495fSSaurabh Misra 144dd52495fSSaurabh Misra static char bfe_ident[] = "bfe driver for Broadcom BCM4401 chipsets"; 145dd52495fSSaurabh Misra 146dd52495fSSaurabh Misra /* 147dd52495fSSaurabh Misra * Function Prototypes for bfe driver. 148dd52495fSSaurabh Misra */ 149dd52495fSSaurabh Misra static int bfe_check_link(bfe_t *); 150dd52495fSSaurabh Misra static void bfe_report_link(bfe_t *); 151dd52495fSSaurabh Misra static void bfe_chip_halt(bfe_t *); 152dd52495fSSaurabh Misra static void bfe_chip_reset(bfe_t *); 153dd52495fSSaurabh Misra static void bfe_tx_desc_init(bfe_ring_t *); 154dd52495fSSaurabh Misra static void bfe_rx_desc_init(bfe_ring_t *); 155dd52495fSSaurabh Misra static void bfe_set_rx_mode(bfe_t *); 156dd52495fSSaurabh Misra static void bfe_enable_chip_intrs(bfe_t *); 157dd52495fSSaurabh Misra static void bfe_chip_restart(bfe_t *); 158dd52495fSSaurabh Misra static void bfe_init_vars(bfe_t *); 159dd52495fSSaurabh Misra static void bfe_clear_stats(bfe_t *); 160dd52495fSSaurabh Misra static void bfe_gather_stats(bfe_t *); 161dd52495fSSaurabh Misra static void bfe_error(dev_info_t *, char *, ...); 162dd52495fSSaurabh Misra static int bfe_mac_getprop(void *, const char *, mac_prop_id_t, uint_t, 1630dc2366fSVenugopal Iyer void *); 164dd52495fSSaurabh Misra static int bfe_mac_setprop(void *, const char *, mac_prop_id_t, uint_t, 165dd52495fSSaurabh Misra const void *); 166dd52495fSSaurabh Misra static int bfe_tx_reclaim(bfe_ring_t *); 167dd52495fSSaurabh Misra int bfe_mac_set_ether_addr(void *, const uint8_t *); 168dd52495fSSaurabh Misra 169dd52495fSSaurabh Misra 170dd52495fSSaurabh Misra /* 171dd52495fSSaurabh Misra * Macros for ddi_dma_sync(). 172dd52495fSSaurabh Misra */ 173dd52495fSSaurabh Misra #define SYNC_DESC(r, s, l, d) \ 174dd52495fSSaurabh Misra (void) ddi_dma_sync(r->r_desc_dma_handle, \ 175dd52495fSSaurabh Misra (off_t)(s * sizeof (bfe_desc_t)), \ 176dd52495fSSaurabh Misra (size_t)(l * sizeof (bfe_desc_t)), \ 177dd52495fSSaurabh Misra d) 178dd52495fSSaurabh Misra 179dd52495fSSaurabh Misra #define SYNC_BUF(r, s, b, l, d) \ 180dd52495fSSaurabh Misra (void) ddi_dma_sync(r->r_buf_dma[s].handle, \ 181dd52495fSSaurabh Misra (off_t)(b), (size_t)(l), d) 182dd52495fSSaurabh Misra 183dd52495fSSaurabh Misra /* 184dd52495fSSaurabh Misra * Supported Broadcom BCM4401 Cards. 185dd52495fSSaurabh Misra */ 186dd52495fSSaurabh Misra static bfe_cards_t bfe_cards[] = { 187dd52495fSSaurabh Misra { 0x14e4, 0x170c, "BCM4401 100Base-TX"}, 188dd52495fSSaurabh Misra }; 189dd52495fSSaurabh Misra 190dd52495fSSaurabh Misra 191dd52495fSSaurabh Misra /* 192dd52495fSSaurabh Misra * DMA attributes for device registers, packet data (buffer) and 193dd52495fSSaurabh Misra * descriptor table. 194dd52495fSSaurabh Misra */ 195dd52495fSSaurabh Misra static struct ddi_device_acc_attr bfe_dev_attr = { 196dd52495fSSaurabh Misra DDI_DEVICE_ATTR_V0, 197dd52495fSSaurabh Misra DDI_STRUCTURE_LE_ACC, 198dd52495fSSaurabh Misra DDI_STRICTORDER_ACC 199dd52495fSSaurabh Misra }; 200dd52495fSSaurabh Misra 201dd52495fSSaurabh Misra static struct ddi_device_acc_attr bfe_buf_attr = { 202dd52495fSSaurabh Misra DDI_DEVICE_ATTR_V0, 203dd52495fSSaurabh Misra DDI_NEVERSWAP_ACC, /* native endianness */ 204dd52495fSSaurabh Misra DDI_STRICTORDER_ACC 205dd52495fSSaurabh Misra }; 206dd52495fSSaurabh Misra 207dd52495fSSaurabh Misra static ddi_dma_attr_t bfe_dma_attr_buf = { 208dd52495fSSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */ 209dd52495fSSaurabh Misra 0, /* dma_attr_addr_lo */ 210dd52495fSSaurabh Misra BFE_PCI_DMA - 1, /* dma_attr_addr_hi */ 211dd52495fSSaurabh Misra 0x1fff, /* dma_attr_count_max */ 212dd52495fSSaurabh Misra 8, /* dma_attr_align */ 213dd52495fSSaurabh Misra 0, /* dma_attr_burstsizes */ 214dd52495fSSaurabh Misra 1, /* dma_attr_minxfer */ 215dd52495fSSaurabh Misra 0x1fff, /* dma_attr_maxxfer */ 216dd52495fSSaurabh Misra BFE_PCI_DMA - 1, /* dma_attr_seg */ 217dd52495fSSaurabh Misra 1, /* dma_attr_sgllen */ 218dd52495fSSaurabh Misra 1, /* dma_attr_granular */ 219dd52495fSSaurabh Misra 0 /* dma_attr_flags */ 220dd52495fSSaurabh Misra }; 221dd52495fSSaurabh Misra 222dd52495fSSaurabh Misra static ddi_dma_attr_t bfe_dma_attr_desc = { 223dd52495fSSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */ 224dd52495fSSaurabh Misra 0, /* dma_attr_addr_lo */ 225dd52495fSSaurabh Misra BFE_PCI_DMA - 1, /* dma_attr_addr_hi */ 226dd52495fSSaurabh Misra BFE_PCI_DMA - 1, /* dma_attr_count_max */ 227dd52495fSSaurabh Misra BFE_DESC_ALIGN, /* dma_attr_align */ 228dd52495fSSaurabh Misra 0, /* dma_attr_burstsizes */ 229dd52495fSSaurabh Misra 1, /* dma_attr_minxfer */ 230dd52495fSSaurabh Misra BFE_PCI_DMA - 1, /* dma_attr_maxxfer */ 231dd52495fSSaurabh Misra BFE_PCI_DMA - 1, /* dma_attr_seg */ 232dd52495fSSaurabh Misra 1, /* dma_attr_sgllen */ 233dd52495fSSaurabh Misra 1, /* dma_attr_granular */ 234dd52495fSSaurabh Misra 0 /* dma_attr_flags */ 235dd52495fSSaurabh Misra }; 236dd52495fSSaurabh Misra 237dd52495fSSaurabh Misra /* 238dd52495fSSaurabh Misra * Ethernet broadcast addresses. 239dd52495fSSaurabh Misra */ 240dd52495fSSaurabh Misra static uchar_t bfe_broadcast[ETHERADDRL] = { 241dd52495fSSaurabh Misra 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 242dd52495fSSaurabh Misra }; 243dd52495fSSaurabh Misra 244dd52495fSSaurabh Misra #define ASSERT_ALL_LOCKS(bfe) { \ 245dd52495fSSaurabh Misra ASSERT(mutex_owned(&bfe->bfe_tx_ring.r_lock)); \ 246dd52495fSSaurabh Misra ASSERT(rw_write_held(&bfe->bfe_rwlock)); \ 247dd52495fSSaurabh Misra } 248dd52495fSSaurabh Misra 249dd52495fSSaurabh Misra /* 250dd52495fSSaurabh Misra * Debugging and error reproting code. 251dd52495fSSaurabh Misra */ 252dd52495fSSaurabh Misra static void 253dd52495fSSaurabh Misra bfe_error(dev_info_t *dip, char *fmt, ...) 254dd52495fSSaurabh Misra { 255dd52495fSSaurabh Misra va_list ap; 256dd52495fSSaurabh Misra char buf[256]; 257dd52495fSSaurabh Misra 258dd52495fSSaurabh Misra va_start(ap, fmt); 259dd52495fSSaurabh Misra (void) vsnprintf(buf, sizeof (buf), fmt, ap); 260dd52495fSSaurabh Misra va_end(ap); 261dd52495fSSaurabh Misra 262dd52495fSSaurabh Misra if (dip) { 263dd52495fSSaurabh Misra cmn_err(CE_WARN, "%s%d: %s", 264dd52495fSSaurabh Misra ddi_driver_name(dip), ddi_get_instance(dip), buf); 265dd52495fSSaurabh Misra } else { 266dd52495fSSaurabh Misra cmn_err(CE_WARN, "bfe: %s", buf); 267dd52495fSSaurabh Misra } 268dd52495fSSaurabh Misra } 269dd52495fSSaurabh Misra 270dd52495fSSaurabh Misra /* 271dd52495fSSaurabh Misra * Grabs all necessary locks to block any other operation on the chip. 272dd52495fSSaurabh Misra */ 273dd52495fSSaurabh Misra static void 274dd52495fSSaurabh Misra bfe_grab_locks(bfe_t *bfe) 275dd52495fSSaurabh Misra { 276dd52495fSSaurabh Misra bfe_ring_t *tx = &bfe->bfe_tx_ring; 277dd52495fSSaurabh Misra 278dd52495fSSaurabh Misra /* 279dd52495fSSaurabh Misra * Grab all the locks. 280dd52495fSSaurabh Misra * - bfe_rwlock : locks down whole chip including RX. 281dd52495fSSaurabh Misra * - tx's r_lock : locks down only TX side. 282dd52495fSSaurabh Misra */ 283dd52495fSSaurabh Misra rw_enter(&bfe->bfe_rwlock, RW_WRITER); 284dd52495fSSaurabh Misra mutex_enter(&tx->r_lock); 285dd52495fSSaurabh Misra 286dd52495fSSaurabh Misra /* 287dd52495fSSaurabh Misra * Note that we don't use RX's r_lock. 288dd52495fSSaurabh Misra */ 289dd52495fSSaurabh Misra } 290dd52495fSSaurabh Misra 291dd52495fSSaurabh Misra /* 292dd52495fSSaurabh Misra * Release lock on chip/drver. 293dd52495fSSaurabh Misra */ 294dd52495fSSaurabh Misra static void 295dd52495fSSaurabh Misra bfe_release_locks(bfe_t *bfe) 296dd52495fSSaurabh Misra { 297dd52495fSSaurabh Misra bfe_ring_t *tx = &bfe->bfe_tx_ring; 298dd52495fSSaurabh Misra 299dd52495fSSaurabh Misra /* 300dd52495fSSaurabh Misra * Release all the locks in the order in which they were grabbed. 301dd52495fSSaurabh Misra */ 302dd52495fSSaurabh Misra mutex_exit(&tx->r_lock); 303dd52495fSSaurabh Misra rw_exit(&bfe->bfe_rwlock); 304dd52495fSSaurabh Misra } 305dd52495fSSaurabh Misra 306dd52495fSSaurabh Misra 307dd52495fSSaurabh Misra /* 308dd52495fSSaurabh Misra * It's used to make sure that the write to device register was successful. 309dd52495fSSaurabh Misra */ 310dd52495fSSaurabh Misra static int 311dd52495fSSaurabh Misra bfe_wait_bit(bfe_t *bfe, uint32_t reg, uint32_t bit, 312dd52495fSSaurabh Misra ulong_t t, const int clear) 313dd52495fSSaurabh Misra { 314dd52495fSSaurabh Misra ulong_t i; 315dd52495fSSaurabh Misra uint32_t v; 316dd52495fSSaurabh Misra 317dd52495fSSaurabh Misra for (i = 0; i < t; i++) { 318dd52495fSSaurabh Misra v = INL(bfe, reg); 319dd52495fSSaurabh Misra 320dd52495fSSaurabh Misra if (clear && !(v & bit)) 321dd52495fSSaurabh Misra break; 322dd52495fSSaurabh Misra 323dd52495fSSaurabh Misra if (!clear && (v & bit)) 324dd52495fSSaurabh Misra break; 325dd52495fSSaurabh Misra 326dd52495fSSaurabh Misra drv_usecwait(10); 327dd52495fSSaurabh Misra } 328dd52495fSSaurabh Misra 329dd52495fSSaurabh Misra /* if device still didn't see the value */ 330dd52495fSSaurabh Misra if (i == t) 331dd52495fSSaurabh Misra return (-1); 332dd52495fSSaurabh Misra 333dd52495fSSaurabh Misra return (0); 334dd52495fSSaurabh Misra } 335dd52495fSSaurabh Misra 336dd52495fSSaurabh Misra /* 337dd52495fSSaurabh Misra * PHY functions (read, write, stop, reset and startup) 338dd52495fSSaurabh Misra */ 339dd52495fSSaurabh Misra static int 340dd52495fSSaurabh Misra bfe_read_phy(bfe_t *bfe, uint32_t reg) 341dd52495fSSaurabh Misra { 342dd52495fSSaurabh Misra OUTL(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII); 343dd52495fSSaurabh Misra OUTL(bfe, BFE_MDIO_DATA, (BFE_MDIO_SB_START | 344dd52495fSSaurabh Misra (BFE_MDIO_OP_READ << BFE_MDIO_OP_SHIFT) | 345dd52495fSSaurabh Misra (bfe->bfe_phy_addr << BFE_MDIO_PMD_SHIFT) | 346dd52495fSSaurabh Misra (reg << BFE_MDIO_RA_SHIFT) | 347dd52495fSSaurabh Misra (BFE_MDIO_TA_VALID << BFE_MDIO_TA_SHIFT))); 348dd52495fSSaurabh Misra 349dd52495fSSaurabh Misra (void) bfe_wait_bit(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 10, 0); 350dd52495fSSaurabh Misra 351dd52495fSSaurabh Misra return ((INL(bfe, BFE_MDIO_DATA) & BFE_MDIO_DATA_DATA)); 352dd52495fSSaurabh Misra } 353dd52495fSSaurabh Misra 354dd52495fSSaurabh Misra static void 355dd52495fSSaurabh Misra bfe_write_phy(bfe_t *bfe, uint32_t reg, uint32_t val) 356dd52495fSSaurabh Misra { 357dd52495fSSaurabh Misra OUTL(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII); 358dd52495fSSaurabh Misra OUTL(bfe, BFE_MDIO_DATA, (BFE_MDIO_SB_START | 359dd52495fSSaurabh Misra (BFE_MDIO_OP_WRITE << BFE_MDIO_OP_SHIFT) | 360dd52495fSSaurabh Misra (bfe->bfe_phy_addr << BFE_MDIO_PMD_SHIFT) | 361dd52495fSSaurabh Misra (reg << BFE_MDIO_RA_SHIFT) | 362dd52495fSSaurabh Misra (BFE_MDIO_TA_VALID << BFE_MDIO_TA_SHIFT) | 363dd52495fSSaurabh Misra (val & BFE_MDIO_DATA_DATA))); 364dd52495fSSaurabh Misra 365dd52495fSSaurabh Misra (void) bfe_wait_bit(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 10, 0); 366dd52495fSSaurabh Misra } 367dd52495fSSaurabh Misra 368dd52495fSSaurabh Misra /* 369dd52495fSSaurabh Misra * It resets the PHY layer. 370dd52495fSSaurabh Misra */ 371dd52495fSSaurabh Misra static int 372dd52495fSSaurabh Misra bfe_reset_phy(bfe_t *bfe) 373dd52495fSSaurabh Misra { 374dd52495fSSaurabh Misra uint32_t i; 375dd52495fSSaurabh Misra 376dd52495fSSaurabh Misra bfe_write_phy(bfe, MII_CONTROL, MII_CONTROL_RESET); 377dd52495fSSaurabh Misra drv_usecwait(100); 378dd52495fSSaurabh Misra for (i = 0; i < 10; i++) { 379dd52495fSSaurabh Misra if (bfe_read_phy(bfe, MII_CONTROL) & 380dd52495fSSaurabh Misra MII_CONTROL_RESET) { 381dd52495fSSaurabh Misra drv_usecwait(500); 382dd52495fSSaurabh Misra continue; 383dd52495fSSaurabh Misra } 384dd52495fSSaurabh Misra 385dd52495fSSaurabh Misra break; 386dd52495fSSaurabh Misra } 387dd52495fSSaurabh Misra 388dd52495fSSaurabh Misra if (i == 10) { 389dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "Timeout waiting for PHY to reset"); 390dd52495fSSaurabh Misra bfe->bfe_phy_state = BFE_PHY_RESET_TIMEOUT; 391dd52495fSSaurabh Misra return (BFE_FAILURE); 392dd52495fSSaurabh Misra } 393dd52495fSSaurabh Misra 394dd52495fSSaurabh Misra bfe->bfe_phy_state = BFE_PHY_RESET_DONE; 395dd52495fSSaurabh Misra 396dd52495fSSaurabh Misra return (BFE_SUCCESS); 397dd52495fSSaurabh Misra } 398dd52495fSSaurabh Misra 399dd52495fSSaurabh Misra /* 400dd52495fSSaurabh Misra * Make sure timer function is out of our way and especially during 401dd52495fSSaurabh Misra * detach. 402dd52495fSSaurabh Misra */ 403dd52495fSSaurabh Misra static void 404dd52495fSSaurabh Misra bfe_stop_timer(bfe_t *bfe) 405dd52495fSSaurabh Misra { 406dd52495fSSaurabh Misra if (bfe->bfe_periodic_id) { 407dd52495fSSaurabh Misra ddi_periodic_delete(bfe->bfe_periodic_id); 408dd52495fSSaurabh Misra bfe->bfe_periodic_id = NULL; 409dd52495fSSaurabh Misra } 410dd52495fSSaurabh Misra } 411dd52495fSSaurabh Misra 412dd52495fSSaurabh Misra /* 413dd52495fSSaurabh Misra * Stops the PHY 414dd52495fSSaurabh Misra */ 415dd52495fSSaurabh Misra static void 416dd52495fSSaurabh Misra bfe_stop_phy(bfe_t *bfe) 417dd52495fSSaurabh Misra { 418dd52495fSSaurabh Misra bfe_write_phy(bfe, MII_CONTROL, MII_CONTROL_PWRDN | 419dd52495fSSaurabh Misra MII_CONTROL_ISOLATE); 420dd52495fSSaurabh Misra 421dd52495fSSaurabh Misra bfe->bfe_chip.link = LINK_STATE_UNKNOWN; 422dd52495fSSaurabh Misra bfe->bfe_chip.speed = 0; 423dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN; 424dd52495fSSaurabh Misra 425dd52495fSSaurabh Misra bfe->bfe_phy_state = BFE_PHY_STOPPED; 426dd52495fSSaurabh Misra 427dd52495fSSaurabh Misra /* 428dd52495fSSaurabh Misra * Report the link status to MAC layer. 429dd52495fSSaurabh Misra */ 430dd52495fSSaurabh Misra if (bfe->bfe_machdl != NULL) 431dd52495fSSaurabh Misra (void) bfe_report_link(bfe); 432dd52495fSSaurabh Misra } 433dd52495fSSaurabh Misra 434dd52495fSSaurabh Misra static int 435dd52495fSSaurabh Misra bfe_probe_phy(bfe_t *bfe) 436dd52495fSSaurabh Misra { 437dd52495fSSaurabh Misra int phy; 438dd52495fSSaurabh Misra uint32_t status; 439dd52495fSSaurabh Misra 440dd52495fSSaurabh Misra if (bfe->bfe_phy_addr) { 441dd52495fSSaurabh Misra status = bfe_read_phy(bfe, MII_STATUS); 442dd52495fSSaurabh Misra if (status != 0xffff && status != 0) { 443dd52495fSSaurabh Misra bfe_write_phy(bfe, MII_CONTROL, 0); 444dd52495fSSaurabh Misra return (BFE_SUCCESS); 445dd52495fSSaurabh Misra } 446dd52495fSSaurabh Misra } 447dd52495fSSaurabh Misra 448dd52495fSSaurabh Misra for (phy = 0; phy < 32; phy++) { 449dd52495fSSaurabh Misra bfe->bfe_phy_addr = phy; 450dd52495fSSaurabh Misra status = bfe_read_phy(bfe, MII_STATUS); 451dd52495fSSaurabh Misra if (status != 0xffff && status != 0) { 452dd52495fSSaurabh Misra bfe_write_phy(bfe, MII_CONTROL, 0); 453dd52495fSSaurabh Misra return (BFE_SUCCESS); 454dd52495fSSaurabh Misra } 455dd52495fSSaurabh Misra } 456dd52495fSSaurabh Misra 457dd52495fSSaurabh Misra return (BFE_FAILURE); 458dd52495fSSaurabh Misra } 459dd52495fSSaurabh Misra 460dd52495fSSaurabh Misra /* 461dd52495fSSaurabh Misra * This timeout function fires at BFE_TIMEOUT_INTERVAL to check the link 462dd52495fSSaurabh Misra * status. 463dd52495fSSaurabh Misra */ 464dd52495fSSaurabh Misra static void 465dd52495fSSaurabh Misra bfe_timeout(void *arg) 466dd52495fSSaurabh Misra { 467dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 468954c6b5eSSaurabh Misra int resched = 0; 469dd52495fSSaurabh Misra 470dd52495fSSaurabh Misra /* 471dd52495fSSaurabh Misra * We don't grab any lock because bfe can't go away. 472dd52495fSSaurabh Misra * untimeout() will wait for this timeout instance to complete. 473dd52495fSSaurabh Misra */ 474dd52495fSSaurabh Misra if (bfe->bfe_chip_action & BFE_ACTION_RESTART) { 475dd52495fSSaurabh Misra /* 476dd52495fSSaurabh Misra * Restart the chip. 477dd52495fSSaurabh Misra */ 478dd52495fSSaurabh Misra bfe_grab_locks(bfe); 479dd52495fSSaurabh Misra bfe_chip_restart(bfe); 480dd52495fSSaurabh Misra bfe->bfe_chip_action &= ~BFE_ACTION_RESTART; 481dd52495fSSaurabh Misra bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_FAULT; 482dd52495fSSaurabh Misra bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_PKT; 483dd52495fSSaurabh Misra bfe_release_locks(bfe); 484dd52495fSSaurabh Misra mac_tx_update(bfe->bfe_machdl); 485dd52495fSSaurabh Misra /* Restart will register a new timeout */ 486dd52495fSSaurabh Misra return; 487dd52495fSSaurabh Misra } 488dd52495fSSaurabh Misra 489dd52495fSSaurabh Misra rw_enter(&bfe->bfe_rwlock, RW_READER); 490dd52495fSSaurabh Misra 491dd52495fSSaurabh Misra if (bfe->bfe_chip_state == BFE_CHIP_ACTIVE) { 492dd52495fSSaurabh Misra hrtime_t hr; 493dd52495fSSaurabh Misra 494dd52495fSSaurabh Misra hr = gethrtime(); 495dd52495fSSaurabh Misra if (bfe->bfe_tx_stall_time != 0 && 496dd52495fSSaurabh Misra hr > bfe->bfe_tx_stall_time) { 497dd52495fSSaurabh Misra DTRACE_PROBE2(chip__restart, int, bfe->bfe_unit, 498dd52495fSSaurabh Misra char *, "pkt timeout"); 499dd52495fSSaurabh Misra bfe->bfe_chip_action |= 500dd52495fSSaurabh Misra (BFE_ACTION_RESTART | BFE_ACTION_RESTART_PKT); 501dd52495fSSaurabh Misra bfe->bfe_tx_stall_time = 0; 502dd52495fSSaurabh Misra } 503dd52495fSSaurabh Misra } 504dd52495fSSaurabh Misra 505dd52495fSSaurabh Misra if (bfe->bfe_phy_state == BFE_PHY_STARTED) { 506dd52495fSSaurabh Misra /* 507dd52495fSSaurabh Misra * Report the link status to MAC layer if link status changed. 508dd52495fSSaurabh Misra */ 509dd52495fSSaurabh Misra if (bfe_check_link(bfe)) { 510dd52495fSSaurabh Misra bfe_report_link(bfe); 511dd52495fSSaurabh Misra if (bfe->bfe_chip.link == LINK_STATE_UP) { 512dd52495fSSaurabh Misra uint32_t val, flow; 513dd52495fSSaurabh Misra 514dd52495fSSaurabh Misra val = INL(bfe, BFE_TX_CTRL); 515dd52495fSSaurabh Misra val &= ~BFE_TX_DUPLEX; 516dd52495fSSaurabh Misra if (bfe->bfe_chip.duplex == LINK_DUPLEX_FULL) { 517dd52495fSSaurabh Misra val |= BFE_TX_DUPLEX; 518dd52495fSSaurabh Misra flow = INL(bfe, BFE_RXCONF); 519dd52495fSSaurabh Misra flow &= ~BFE_RXCONF_FLOW; 520dd52495fSSaurabh Misra OUTL(bfe, BFE_RXCONF, flow); 521dd52495fSSaurabh Misra 522dd52495fSSaurabh Misra flow = INL(bfe, BFE_MAC_FLOW); 523dd52495fSSaurabh Misra flow &= ~(BFE_FLOW_RX_HIWAT); 524dd52495fSSaurabh Misra OUTL(bfe, BFE_MAC_FLOW, flow); 525dd52495fSSaurabh Misra } 526dd52495fSSaurabh Misra 527954c6b5eSSaurabh Misra resched = 1; 528954c6b5eSSaurabh Misra 529dd52495fSSaurabh Misra OUTL(bfe, BFE_TX_CTRL, val); 530dd52495fSSaurabh Misra DTRACE_PROBE1(link__up, 531dd52495fSSaurabh Misra int, bfe->bfe_unit); 532dd52495fSSaurabh Misra } 533dd52495fSSaurabh Misra } 534dd52495fSSaurabh Misra } 535dd52495fSSaurabh Misra 536dd52495fSSaurabh Misra rw_exit(&bfe->bfe_rwlock); 537954c6b5eSSaurabh Misra 538954c6b5eSSaurabh Misra if (resched) 539954c6b5eSSaurabh Misra mac_tx_update(bfe->bfe_machdl); 540dd52495fSSaurabh Misra } 541dd52495fSSaurabh Misra 542dd52495fSSaurabh Misra /* 543dd52495fSSaurabh Misra * Starts PHY layer. 544dd52495fSSaurabh Misra */ 545dd52495fSSaurabh Misra static int 546dd52495fSSaurabh Misra bfe_startup_phy(bfe_t *bfe) 547dd52495fSSaurabh Misra { 548dd52495fSSaurabh Misra uint16_t bmsr, bmcr, anar; 549dd52495fSSaurabh Misra int prog, s; 550dd52495fSSaurabh Misra int phyid1, phyid2; 551dd52495fSSaurabh Misra 552dd52495fSSaurabh Misra if (bfe_probe_phy(bfe) == BFE_FAILURE) { 553dd52495fSSaurabh Misra bfe->bfe_phy_state = BFE_PHY_NOTFOUND; 554dd52495fSSaurabh Misra return (BFE_FAILURE); 555dd52495fSSaurabh Misra } 556dd52495fSSaurabh Misra 557dd52495fSSaurabh Misra (void) bfe_reset_phy(bfe); 558dd52495fSSaurabh Misra 559dd52495fSSaurabh Misra phyid1 = bfe_read_phy(bfe, MII_PHYIDH); 560dd52495fSSaurabh Misra phyid2 = bfe_read_phy(bfe, MII_PHYIDL); 561dd52495fSSaurabh Misra bfe->bfe_phy_id = (phyid1 << 16) | phyid2; 562dd52495fSSaurabh Misra 563dd52495fSSaurabh Misra bmsr = bfe_read_phy(bfe, MII_STATUS); 564dd52495fSSaurabh Misra anar = bfe_read_phy(bfe, MII_AN_ADVERT); 565dd52495fSSaurabh Misra 566dd52495fSSaurabh Misra again: 567dd52495fSSaurabh Misra anar &= ~(MII_ABILITY_100BASE_T4 | 568dd52495fSSaurabh Misra MII_ABILITY_100BASE_TX_FD | MII_ABILITY_100BASE_TX | 569dd52495fSSaurabh Misra MII_ABILITY_10BASE_T_FD | MII_ABILITY_10BASE_T); 570dd52495fSSaurabh Misra 571dd52495fSSaurabh Misra /* 572dd52495fSSaurabh Misra * Supported hardware modes are in bmsr. 573dd52495fSSaurabh Misra */ 574dd52495fSSaurabh Misra bfe->bfe_chip.bmsr = bmsr; 575dd52495fSSaurabh Misra 576dd52495fSSaurabh Misra /* 577dd52495fSSaurabh Misra * Assume no capabilities are supported in the hardware. 578dd52495fSSaurabh Misra */ 579dd52495fSSaurabh Misra bfe->bfe_cap_aneg = bfe->bfe_cap_100T4 = 580dd52495fSSaurabh Misra bfe->bfe_cap_100fdx = bfe->bfe_cap_100hdx = 581dd52495fSSaurabh Misra bfe->bfe_cap_10fdx = bfe->bfe_cap_10hdx = 0; 582dd52495fSSaurabh Misra 583dd52495fSSaurabh Misra /* 584dd52495fSSaurabh Misra * Assume property is set. 585dd52495fSSaurabh Misra */ 586dd52495fSSaurabh Misra s = 1; 587dd52495fSSaurabh Misra if (!(bfe->bfe_chip_action & BFE_ACTION_RESTART_SETPROP)) { 588dd52495fSSaurabh Misra /* 589dd52495fSSaurabh Misra * Property is not set which means bfe_mac_setprop() 590dd52495fSSaurabh Misra * is not called on us. 591dd52495fSSaurabh Misra */ 592dd52495fSSaurabh Misra s = 0; 593dd52495fSSaurabh Misra } 594dd52495fSSaurabh Misra 595dd52495fSSaurabh Misra bmcr = prog = 0; 596dd52495fSSaurabh Misra 597dd52495fSSaurabh Misra if (bmsr & MII_STATUS_100_BASEX_FD) { 598dd52495fSSaurabh Misra bfe->bfe_cap_100fdx = 1; 599dd52495fSSaurabh Misra if (s == 0) { 600dd52495fSSaurabh Misra anar |= MII_ABILITY_100BASE_TX_FD; 601dd52495fSSaurabh Misra bfe->bfe_adv_100fdx = 1; 602dd52495fSSaurabh Misra prog++; 603dd52495fSSaurabh Misra } else if (bfe->bfe_adv_100fdx) { 604dd52495fSSaurabh Misra anar |= MII_ABILITY_100BASE_TX_FD; 605dd52495fSSaurabh Misra prog++; 606dd52495fSSaurabh Misra } 607dd52495fSSaurabh Misra } 608dd52495fSSaurabh Misra 609dd52495fSSaurabh Misra if (bmsr & MII_STATUS_100_BASE_T4) { 610dd52495fSSaurabh Misra bfe->bfe_cap_100T4 = 1; 611dd52495fSSaurabh Misra if (s == 0) { 612dd52495fSSaurabh Misra anar |= MII_ABILITY_100BASE_T4; 613dd52495fSSaurabh Misra bfe->bfe_adv_100T4 = 1; 614dd52495fSSaurabh Misra prog++; 615dd52495fSSaurabh Misra } else if (bfe->bfe_adv_100T4) { 616dd52495fSSaurabh Misra anar |= MII_ABILITY_100BASE_T4; 617dd52495fSSaurabh Misra prog++; 618dd52495fSSaurabh Misra } 619dd52495fSSaurabh Misra } 620dd52495fSSaurabh Misra 621dd52495fSSaurabh Misra if (bmsr & MII_STATUS_100_BASEX) { 622dd52495fSSaurabh Misra bfe->bfe_cap_100hdx = 1; 623dd52495fSSaurabh Misra if (s == 0) { 624dd52495fSSaurabh Misra anar |= MII_ABILITY_100BASE_TX; 625dd52495fSSaurabh Misra bfe->bfe_adv_100hdx = 1; 626dd52495fSSaurabh Misra prog++; 627dd52495fSSaurabh Misra } else if (bfe->bfe_adv_100hdx) { 628dd52495fSSaurabh Misra anar |= MII_ABILITY_100BASE_TX; 629dd52495fSSaurabh Misra prog++; 630dd52495fSSaurabh Misra } 631dd52495fSSaurabh Misra } 632dd52495fSSaurabh Misra 633dd52495fSSaurabh Misra if (bmsr & MII_STATUS_10_FD) { 634dd52495fSSaurabh Misra bfe->bfe_cap_10fdx = 1; 635dd52495fSSaurabh Misra if (s == 0) { 636dd52495fSSaurabh Misra anar |= MII_ABILITY_10BASE_T_FD; 637dd52495fSSaurabh Misra bfe->bfe_adv_10fdx = 1; 638dd52495fSSaurabh Misra prog++; 639dd52495fSSaurabh Misra } else if (bfe->bfe_adv_10fdx) { 640dd52495fSSaurabh Misra anar |= MII_ABILITY_10BASE_T_FD; 641dd52495fSSaurabh Misra prog++; 642dd52495fSSaurabh Misra } 643dd52495fSSaurabh Misra } 644dd52495fSSaurabh Misra 645dd52495fSSaurabh Misra if (bmsr & MII_STATUS_10) { 646dd52495fSSaurabh Misra bfe->bfe_cap_10hdx = 1; 647dd52495fSSaurabh Misra if (s == 0) { 648dd52495fSSaurabh Misra anar |= MII_ABILITY_10BASE_T; 649dd52495fSSaurabh Misra bfe->bfe_adv_10hdx = 1; 650dd52495fSSaurabh Misra prog++; 651dd52495fSSaurabh Misra } else if (bfe->bfe_adv_10hdx) { 652dd52495fSSaurabh Misra anar |= MII_ABILITY_10BASE_T; 653dd52495fSSaurabh Misra prog++; 654dd52495fSSaurabh Misra } 655dd52495fSSaurabh Misra } 656dd52495fSSaurabh Misra 657dd52495fSSaurabh Misra if (bmsr & MII_STATUS_CANAUTONEG) { 658dd52495fSSaurabh Misra bfe->bfe_cap_aneg = 1; 659dd52495fSSaurabh Misra if (s == 0) { 660dd52495fSSaurabh Misra bfe->bfe_adv_aneg = 1; 661dd52495fSSaurabh Misra } 662dd52495fSSaurabh Misra } 663dd52495fSSaurabh Misra 664dd52495fSSaurabh Misra if (prog == 0) { 665dd52495fSSaurabh Misra if (s == 0) { 666dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, 667dd52495fSSaurabh Misra "No valid link mode selected. Powering down PHY"); 668dd52495fSSaurabh Misra bfe_stop_phy(bfe); 669dd52495fSSaurabh Misra bfe_report_link(bfe); 670dd52495fSSaurabh Misra return (BFE_FAILURE); 671dd52495fSSaurabh Misra } 672dd52495fSSaurabh Misra 673dd52495fSSaurabh Misra /* 674dd52495fSSaurabh Misra * If property is set then user would have goofed up. So we 675dd52495fSSaurabh Misra * go back to default properties. 676dd52495fSSaurabh Misra */ 677dd52495fSSaurabh Misra bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_SETPROP; 678dd52495fSSaurabh Misra goto again; 679dd52495fSSaurabh Misra } 680dd52495fSSaurabh Misra 681dd52495fSSaurabh Misra if (bfe->bfe_adv_aneg && (bmsr & MII_STATUS_CANAUTONEG)) { 682dd52495fSSaurabh Misra bmcr = (MII_CONTROL_ANE | MII_CONTROL_RSAN); 683dd52495fSSaurabh Misra } else { 684dd52495fSSaurabh Misra if (bfe->bfe_adv_100fdx) 685dd52495fSSaurabh Misra bmcr = (MII_CONTROL_100MB | MII_CONTROL_FDUPLEX); 686dd52495fSSaurabh Misra else if (bfe->bfe_adv_100hdx) 687dd52495fSSaurabh Misra bmcr = MII_CONTROL_100MB; 688dd52495fSSaurabh Misra else if (bfe->bfe_adv_10fdx) 689dd52495fSSaurabh Misra bmcr = MII_CONTROL_FDUPLEX; 690dd52495fSSaurabh Misra else 691dd52495fSSaurabh Misra bmcr = 0; /* 10HDX */ 692dd52495fSSaurabh Misra } 693dd52495fSSaurabh Misra 694dd52495fSSaurabh Misra if (prog) 695dd52495fSSaurabh Misra bfe_write_phy(bfe, MII_AN_ADVERT, anar); 696dd52495fSSaurabh Misra 697dd52495fSSaurabh Misra if (bmcr) 698dd52495fSSaurabh Misra bfe_write_phy(bfe, MII_CONTROL, bmcr); 699dd52495fSSaurabh Misra 700dd52495fSSaurabh Misra bfe->bfe_mii_anar = anar; 701dd52495fSSaurabh Misra bfe->bfe_mii_bmcr = bmcr; 702dd52495fSSaurabh Misra bfe->bfe_phy_state = BFE_PHY_STARTED; 703dd52495fSSaurabh Misra 704dd52495fSSaurabh Misra if (bfe->bfe_periodic_id == NULL) { 705dd52495fSSaurabh Misra bfe->bfe_periodic_id = ddi_periodic_add(bfe_timeout, 706dd52495fSSaurabh Misra (void *)bfe, BFE_TIMEOUT_INTERVAL, DDI_IPL_0); 707dd52495fSSaurabh Misra 708dd52495fSSaurabh Misra DTRACE_PROBE1(first__timeout, int, bfe->bfe_unit); 709dd52495fSSaurabh Misra } 710dd52495fSSaurabh Misra 711dd52495fSSaurabh Misra DTRACE_PROBE4(phy_started, int, bfe->bfe_unit, 712dd52495fSSaurabh Misra int, bmsr, int, bmcr, int, anar); 713dd52495fSSaurabh Misra 714dd52495fSSaurabh Misra return (BFE_SUCCESS); 715dd52495fSSaurabh Misra } 716dd52495fSSaurabh Misra 717dd52495fSSaurabh Misra /* 718dd52495fSSaurabh Misra * Reports link status back to MAC Layer. 719dd52495fSSaurabh Misra */ 720dd52495fSSaurabh Misra static void 721dd52495fSSaurabh Misra bfe_report_link(bfe_t *bfe) 722dd52495fSSaurabh Misra { 723dd52495fSSaurabh Misra mac_link_update(bfe->bfe_machdl, bfe->bfe_chip.link); 724dd52495fSSaurabh Misra } 725dd52495fSSaurabh Misra 726dd52495fSSaurabh Misra /* 727dd52495fSSaurabh Misra * Reads PHY/MII registers and get the link status for us. 728dd52495fSSaurabh Misra */ 729dd52495fSSaurabh Misra static int 730dd52495fSSaurabh Misra bfe_check_link(bfe_t *bfe) 731dd52495fSSaurabh Misra { 732dd52495fSSaurabh Misra uint16_t bmsr, bmcr, anar, anlpar; 733dd52495fSSaurabh Misra int speed, duplex, link; 734dd52495fSSaurabh Misra 735dd52495fSSaurabh Misra speed = bfe->bfe_chip.speed; 736dd52495fSSaurabh Misra duplex = bfe->bfe_chip.duplex; 737dd52495fSSaurabh Misra link = bfe->bfe_chip.link; 738dd52495fSSaurabh Misra 739dd52495fSSaurabh Misra bmsr = bfe_read_phy(bfe, MII_STATUS); 740dd52495fSSaurabh Misra bfe->bfe_mii_bmsr = bmsr; 741dd52495fSSaurabh Misra 742dd52495fSSaurabh Misra bmcr = bfe_read_phy(bfe, MII_CONTROL); 743dd52495fSSaurabh Misra 744dd52495fSSaurabh Misra anar = bfe_read_phy(bfe, MII_AN_ADVERT); 745dd52495fSSaurabh Misra bfe->bfe_mii_anar = anar; 746dd52495fSSaurabh Misra 747dd52495fSSaurabh Misra anlpar = bfe_read_phy(bfe, MII_AN_LPABLE); 748dd52495fSSaurabh Misra bfe->bfe_mii_anlpar = anlpar; 749dd52495fSSaurabh Misra 750dd52495fSSaurabh Misra bfe->bfe_mii_exp = bfe_read_phy(bfe, MII_AN_EXPANSION); 751dd52495fSSaurabh Misra 752dd52495fSSaurabh Misra /* 753dd52495fSSaurabh Misra * If exp register is not present in PHY. 754dd52495fSSaurabh Misra */ 755dd52495fSSaurabh Misra if (bfe->bfe_mii_exp == 0xffff) { 756dd52495fSSaurabh Misra bfe->bfe_mii_exp = 0; 757dd52495fSSaurabh Misra } 758dd52495fSSaurabh Misra 759dd52495fSSaurabh Misra if ((bmsr & MII_STATUS_LINKUP) == 0) { 760dd52495fSSaurabh Misra bfe->bfe_chip.link = LINK_STATE_DOWN; 761dd52495fSSaurabh Misra bfe->bfe_chip.speed = 0; 762dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN; 763dd52495fSSaurabh Misra goto done; 764dd52495fSSaurabh Misra } 765dd52495fSSaurabh Misra 766dd52495fSSaurabh Misra bfe->bfe_chip.link = LINK_STATE_UP; 767dd52495fSSaurabh Misra 768dd52495fSSaurabh Misra if (!(bmcr & MII_CONTROL_ANE)) { 769dd52495fSSaurabh Misra /* Forced mode */ 770dd52495fSSaurabh Misra if (bmcr & MII_CONTROL_100MB) 771dd52495fSSaurabh Misra bfe->bfe_chip.speed = 100000000; 772dd52495fSSaurabh Misra else 773dd52495fSSaurabh Misra bfe->bfe_chip.speed = 10000000; 774dd52495fSSaurabh Misra 775dd52495fSSaurabh Misra if (bmcr & MII_CONTROL_FDUPLEX) 776dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_FULL; 777dd52495fSSaurabh Misra else 778dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_HALF; 779dd52495fSSaurabh Misra 780dd52495fSSaurabh Misra } else if ((!(bmsr & MII_STATUS_CANAUTONEG)) || 781dd52495fSSaurabh Misra (!(bmsr & MII_STATUS_ANDONE))) { 782dd52495fSSaurabh Misra bfe->bfe_chip.speed = 0; 783dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN; 784dd52495fSSaurabh Misra } else if (anar & anlpar & MII_ABILITY_100BASE_TX_FD) { 785dd52495fSSaurabh Misra bfe->bfe_chip.speed = 100000000; 786dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_FULL; 787dd52495fSSaurabh Misra } else if (anar & anlpar & MII_ABILITY_100BASE_T4) { 788dd52495fSSaurabh Misra bfe->bfe_chip.speed = 100000000; 789dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_HALF; 790dd52495fSSaurabh Misra } else if (anar & anlpar & MII_ABILITY_100BASE_TX) { 791dd52495fSSaurabh Misra bfe->bfe_chip.speed = 100000000; 792dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_HALF; 793dd52495fSSaurabh Misra } else if (anar & anlpar & MII_ABILITY_10BASE_T_FD) { 794dd52495fSSaurabh Misra bfe->bfe_chip.speed = 10000000; 795dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_FULL; 796dd52495fSSaurabh Misra } else if (anar & anlpar & MII_ABILITY_10BASE_T) { 797dd52495fSSaurabh Misra bfe->bfe_chip.speed = 10000000; 798dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_HALF; 799dd52495fSSaurabh Misra } else { 800dd52495fSSaurabh Misra bfe->bfe_chip.speed = 0; 801dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN; 802dd52495fSSaurabh Misra } 803dd52495fSSaurabh Misra 804dd52495fSSaurabh Misra done: 805dd52495fSSaurabh Misra /* 806dd52495fSSaurabh Misra * If speed or link status or duplex mode changed then report to 807dd52495fSSaurabh Misra * MAC layer which is done by the caller. 808dd52495fSSaurabh Misra */ 809dd52495fSSaurabh Misra if (speed != bfe->bfe_chip.speed || 810dd52495fSSaurabh Misra duplex != bfe->bfe_chip.duplex || 811dd52495fSSaurabh Misra link != bfe->bfe_chip.link) { 812dd52495fSSaurabh Misra return (1); 813dd52495fSSaurabh Misra } 814dd52495fSSaurabh Misra 815dd52495fSSaurabh Misra return (0); 816dd52495fSSaurabh Misra } 817dd52495fSSaurabh Misra 818dd52495fSSaurabh Misra static void 819dd52495fSSaurabh Misra bfe_cam_write(bfe_t *bfe, uchar_t *d, int index) 820dd52495fSSaurabh Misra { 821dd52495fSSaurabh Misra uint32_t v; 822dd52495fSSaurabh Misra 823dd52495fSSaurabh Misra v = ((uint32_t)d[2] << 24); 824dd52495fSSaurabh Misra v |= ((uint32_t)d[3] << 16); 825dd52495fSSaurabh Misra v |= ((uint32_t)d[4] << 8); 826dd52495fSSaurabh Misra v |= (uint32_t)d[5]; 827dd52495fSSaurabh Misra 828dd52495fSSaurabh Misra OUTL(bfe, BFE_CAM_DATA_LO, v); 829dd52495fSSaurabh Misra v = (BFE_CAM_HI_VALID | 830dd52495fSSaurabh Misra (((uint32_t)d[0]) << 8) | 831dd52495fSSaurabh Misra (((uint32_t)d[1]))); 832dd52495fSSaurabh Misra 833dd52495fSSaurabh Misra OUTL(bfe, BFE_CAM_DATA_HI, v); 834dd52495fSSaurabh Misra OUTL(bfe, BFE_CAM_CTRL, (BFE_CAM_WRITE | 835dd52495fSSaurabh Misra ((uint32_t)index << BFE_CAM_INDEX_SHIFT))); 836dd52495fSSaurabh Misra (void) bfe_wait_bit(bfe, BFE_CAM_CTRL, BFE_CAM_BUSY, 10, 1); 837dd52495fSSaurabh Misra } 838dd52495fSSaurabh Misra 839dd52495fSSaurabh Misra /* 840dd52495fSSaurabh Misra * Chip related functions (halt, reset, start). 841dd52495fSSaurabh Misra */ 842dd52495fSSaurabh Misra static void 843dd52495fSSaurabh Misra bfe_chip_halt(bfe_t *bfe) 844dd52495fSSaurabh Misra { 845dd52495fSSaurabh Misra /* 846dd52495fSSaurabh Misra * Disables interrupts. 847dd52495fSSaurabh Misra */ 848dd52495fSSaurabh Misra OUTL(bfe, BFE_INTR_MASK, 0); 849dd52495fSSaurabh Misra FLUSH(bfe, BFE_INTR_MASK); 850dd52495fSSaurabh Misra 851dd52495fSSaurabh Misra OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_DISABLE); 852dd52495fSSaurabh Misra 853dd52495fSSaurabh Misra /* 854dd52495fSSaurabh Misra * Wait until TX and RX finish their job. 855dd52495fSSaurabh Misra */ 856dd52495fSSaurabh Misra (void) bfe_wait_bit(bfe, BFE_ENET_CTRL, BFE_ENET_DISABLE, 20, 1); 857dd52495fSSaurabh Misra 858dd52495fSSaurabh Misra /* 859dd52495fSSaurabh Misra * Disables DMA engine. 860dd52495fSSaurabh Misra */ 861dd52495fSSaurabh Misra OUTL(bfe, BFE_DMARX_CTRL, 0); 862dd52495fSSaurabh Misra OUTL(bfe, BFE_DMATX_CTRL, 0); 863dd52495fSSaurabh Misra 864dd52495fSSaurabh Misra drv_usecwait(10); 865dd52495fSSaurabh Misra 866dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_HALT; 867dd52495fSSaurabh Misra } 868dd52495fSSaurabh Misra 869dd52495fSSaurabh Misra static void 870dd52495fSSaurabh Misra bfe_chip_restart(bfe_t *bfe) 871dd52495fSSaurabh Misra { 872dd52495fSSaurabh Misra DTRACE_PROBE2(chip__restart, int, bfe->bfe_unit, 873dd52495fSSaurabh Misra int, bfe->bfe_chip_action); 874dd52495fSSaurabh Misra 875dd52495fSSaurabh Misra /* 876dd52495fSSaurabh Misra * Halt chip and PHY. 877dd52495fSSaurabh Misra */ 878dd52495fSSaurabh Misra bfe_chip_halt(bfe); 879dd52495fSSaurabh Misra bfe_stop_phy(bfe); 880dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_STOPPED; 881dd52495fSSaurabh Misra 882dd52495fSSaurabh Misra /* 883dd52495fSSaurabh Misra * Init variables. 884dd52495fSSaurabh Misra */ 885dd52495fSSaurabh Misra bfe_init_vars(bfe); 886dd52495fSSaurabh Misra 887dd52495fSSaurabh Misra /* 888dd52495fSSaurabh Misra * Reset chip and start PHY. 889dd52495fSSaurabh Misra */ 890dd52495fSSaurabh Misra bfe_chip_reset(bfe); 891dd52495fSSaurabh Misra 892dd52495fSSaurabh Misra /* 893dd52495fSSaurabh Misra * DMA descriptor rings. 894dd52495fSSaurabh Misra */ 895dd52495fSSaurabh Misra bfe_tx_desc_init(&bfe->bfe_tx_ring); 896dd52495fSSaurabh Misra bfe_rx_desc_init(&bfe->bfe_rx_ring); 897dd52495fSSaurabh Misra 898dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_ACTIVE; 899dd52495fSSaurabh Misra bfe_set_rx_mode(bfe); 900dd52495fSSaurabh Misra bfe_enable_chip_intrs(bfe); 901dd52495fSSaurabh Misra } 902dd52495fSSaurabh Misra 903dd52495fSSaurabh Misra /* 904dd52495fSSaurabh Misra * Disables core by stopping the clock. 905dd52495fSSaurabh Misra */ 906dd52495fSSaurabh Misra static void 907dd52495fSSaurabh Misra bfe_core_disable(bfe_t *bfe) 908dd52495fSSaurabh Misra { 909dd52495fSSaurabh Misra if ((INL(bfe, BFE_SBTMSLOW) & BFE_RESET)) 910dd52495fSSaurabh Misra return; 911dd52495fSSaurabh Misra 912dd52495fSSaurabh Misra OUTL(bfe, BFE_SBTMSLOW, (BFE_REJECT | BFE_CLOCK)); 913dd52495fSSaurabh Misra (void) bfe_wait_bit(bfe, BFE_SBTMSLOW, BFE_REJECT, 100, 0); 914dd52495fSSaurabh Misra (void) bfe_wait_bit(bfe, BFE_SBTMSHIGH, BFE_BUSY, 100, 1); 915dd52495fSSaurabh Misra OUTL(bfe, BFE_SBTMSLOW, (BFE_FGC | BFE_CLOCK | BFE_REJECT | BFE_RESET)); 916dd52495fSSaurabh Misra FLUSH(bfe, BFE_SBTMSLOW); 917dd52495fSSaurabh Misra drv_usecwait(10); 918dd52495fSSaurabh Misra OUTL(bfe, BFE_SBTMSLOW, (BFE_REJECT | BFE_RESET)); 919dd52495fSSaurabh Misra drv_usecwait(10); 920dd52495fSSaurabh Misra } 921dd52495fSSaurabh Misra 922dd52495fSSaurabh Misra /* 923dd52495fSSaurabh Misra * Resets core. 924dd52495fSSaurabh Misra */ 925dd52495fSSaurabh Misra static void 926dd52495fSSaurabh Misra bfe_core_reset(bfe_t *bfe) 927dd52495fSSaurabh Misra { 928dd52495fSSaurabh Misra uint32_t val; 929dd52495fSSaurabh Misra 930dd52495fSSaurabh Misra /* 931dd52495fSSaurabh Misra * First disable the core. 932dd52495fSSaurabh Misra */ 933dd52495fSSaurabh Misra bfe_core_disable(bfe); 934dd52495fSSaurabh Misra 935dd52495fSSaurabh Misra OUTL(bfe, BFE_SBTMSLOW, (BFE_RESET | BFE_CLOCK | BFE_FGC)); 936dd52495fSSaurabh Misra FLUSH(bfe, BFE_SBTMSLOW); 937dd52495fSSaurabh Misra drv_usecwait(1); 938dd52495fSSaurabh Misra 939dd52495fSSaurabh Misra if (INL(bfe, BFE_SBTMSHIGH) & BFE_SERR) 940dd52495fSSaurabh Misra OUTL(bfe, BFE_SBTMSHIGH, 0); 941dd52495fSSaurabh Misra 942dd52495fSSaurabh Misra val = INL(bfe, BFE_SBIMSTATE); 943dd52495fSSaurabh Misra if (val & (BFE_IBE | BFE_TO)) 944dd52495fSSaurabh Misra OUTL(bfe, BFE_SBIMSTATE, val & ~(BFE_IBE | BFE_TO)); 945dd52495fSSaurabh Misra 946dd52495fSSaurabh Misra OUTL(bfe, BFE_SBTMSLOW, (BFE_CLOCK | BFE_FGC)); 947dd52495fSSaurabh Misra FLUSH(bfe, BFE_SBTMSLOW); 948dd52495fSSaurabh Misra drv_usecwait(1); 949dd52495fSSaurabh Misra 950dd52495fSSaurabh Misra OUTL(bfe, BFE_SBTMSLOW, BFE_CLOCK); 951dd52495fSSaurabh Misra FLUSH(bfe, BFE_SBTMSLOW); 952dd52495fSSaurabh Misra drv_usecwait(1); 953dd52495fSSaurabh Misra } 954dd52495fSSaurabh Misra 955dd52495fSSaurabh Misra static void 956dd52495fSSaurabh Misra bfe_setup_config(bfe_t *bfe, uint32_t cores) 957dd52495fSSaurabh Misra { 958dd52495fSSaurabh Misra uint32_t bar_orig, val; 959dd52495fSSaurabh Misra 960dd52495fSSaurabh Misra /* 961dd52495fSSaurabh Misra * Change bar0 window to map sbtopci registers. 962dd52495fSSaurabh Misra */ 963dd52495fSSaurabh Misra bar_orig = pci_config_get32(bfe->bfe_conf_handle, BFE_BAR0_WIN); 964dd52495fSSaurabh Misra pci_config_put32(bfe->bfe_conf_handle, BFE_BAR0_WIN, BFE_REG_PCI); 965dd52495fSSaurabh Misra 966dd52495fSSaurabh Misra /* Just read it and don't do anything */ 967dd52495fSSaurabh Misra val = INL(bfe, BFE_SBIDHIGH) & BFE_IDH_CORE; 968dd52495fSSaurabh Misra 969dd52495fSSaurabh Misra val = INL(bfe, BFE_SBINTVEC); 970dd52495fSSaurabh Misra val |= cores; 971dd52495fSSaurabh Misra OUTL(bfe, BFE_SBINTVEC, val); 972dd52495fSSaurabh Misra 973dd52495fSSaurabh Misra val = INL(bfe, BFE_SSB_PCI_TRANS_2); 974dd52495fSSaurabh Misra val |= BFE_SSB_PCI_PREF | BFE_SSB_PCI_BURST; 975dd52495fSSaurabh Misra OUTL(bfe, BFE_SSB_PCI_TRANS_2, val); 976dd52495fSSaurabh Misra 977dd52495fSSaurabh Misra /* 978dd52495fSSaurabh Misra * Restore bar0 window mapping. 979dd52495fSSaurabh Misra */ 980dd52495fSSaurabh Misra pci_config_put32(bfe->bfe_conf_handle, BFE_BAR0_WIN, bar_orig); 981dd52495fSSaurabh Misra } 982dd52495fSSaurabh Misra 983dd52495fSSaurabh Misra /* 984dd52495fSSaurabh Misra * Resets chip and starts PHY. 985dd52495fSSaurabh Misra */ 986dd52495fSSaurabh Misra static void 987dd52495fSSaurabh Misra bfe_chip_reset(bfe_t *bfe) 988dd52495fSSaurabh Misra { 989dd52495fSSaurabh Misra uint32_t val; 990dd52495fSSaurabh Misra 991dd52495fSSaurabh Misra /* Set the interrupt vector for the enet core */ 992dd52495fSSaurabh Misra bfe_setup_config(bfe, BFE_INTVEC_ENET0); 993dd52495fSSaurabh Misra 994dd52495fSSaurabh Misra /* check if core is up */ 995dd52495fSSaurabh Misra val = INL(bfe, BFE_SBTMSLOW) & 996dd52495fSSaurabh Misra (BFE_RESET | BFE_REJECT | BFE_CLOCK); 997dd52495fSSaurabh Misra 998dd52495fSSaurabh Misra if (val == BFE_CLOCK) { 999dd52495fSSaurabh Misra OUTL(bfe, BFE_RCV_LAZY, 0); 1000dd52495fSSaurabh Misra OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_DISABLE); 1001dd52495fSSaurabh Misra (void) bfe_wait_bit(bfe, BFE_ENET_CTRL, 1002dd52495fSSaurabh Misra BFE_ENET_DISABLE, 10, 1); 1003dd52495fSSaurabh Misra OUTL(bfe, BFE_DMATX_CTRL, 0); 1004dd52495fSSaurabh Misra FLUSH(bfe, BFE_DMARX_STAT); 1005dd52495fSSaurabh Misra drv_usecwait(20000); /* 20 milli seconds */ 1006dd52495fSSaurabh Misra if (INL(bfe, BFE_DMARX_STAT) & BFE_STAT_EMASK) { 1007dd52495fSSaurabh Misra (void) bfe_wait_bit(bfe, BFE_DMARX_STAT, BFE_STAT_SIDLE, 1008dd52495fSSaurabh Misra 10, 0); 1009dd52495fSSaurabh Misra } 1010dd52495fSSaurabh Misra OUTL(bfe, BFE_DMARX_CTRL, 0); 1011dd52495fSSaurabh Misra } 1012dd52495fSSaurabh Misra 1013dd52495fSSaurabh Misra bfe_core_reset(bfe); 1014dd52495fSSaurabh Misra bfe_clear_stats(bfe); 1015dd52495fSSaurabh Misra 1016dd52495fSSaurabh Misra OUTL(bfe, BFE_MDIO_CTRL, 0x8d); 1017dd52495fSSaurabh Misra val = INL(bfe, BFE_DEVCTRL); 1018dd52495fSSaurabh Misra if (!(val & BFE_IPP)) 1019dd52495fSSaurabh Misra OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_EPSEL); 1020dd52495fSSaurabh Misra else if (INL(bfe, BFE_DEVCTRL & BFE_EPR)) { 1021dd52495fSSaurabh Misra OUTL_AND(bfe, BFE_DEVCTRL, ~BFE_EPR); 1022dd52495fSSaurabh Misra drv_usecwait(20000); /* 20 milli seconds */ 1023dd52495fSSaurabh Misra } 1024dd52495fSSaurabh Misra 1025dd52495fSSaurabh Misra OUTL_OR(bfe, BFE_MAC_CTRL, BFE_CTRL_CRC32_ENAB | BFE_CTRL_LED); 1026dd52495fSSaurabh Misra 1027dd52495fSSaurabh Misra OUTL_AND(bfe, BFE_MAC_CTRL, ~BFE_CTRL_PDOWN); 1028dd52495fSSaurabh Misra 1029dd52495fSSaurabh Misra OUTL(bfe, BFE_RCV_LAZY, ((1 << BFE_LAZY_FC_SHIFT) & 1030dd52495fSSaurabh Misra BFE_LAZY_FC_MASK)); 1031dd52495fSSaurabh Misra 1032dd52495fSSaurabh Misra OUTL_OR(bfe, BFE_RCV_LAZY, 0); 1033dd52495fSSaurabh Misra 1034dd52495fSSaurabh Misra OUTL(bfe, BFE_RXMAXLEN, bfe->bfe_rx_ring.r_buf_len); 1035dd52495fSSaurabh Misra OUTL(bfe, BFE_TXMAXLEN, bfe->bfe_tx_ring.r_buf_len); 1036dd52495fSSaurabh Misra 1037dd52495fSSaurabh Misra OUTL(bfe, BFE_TX_WMARK, 56); 1038dd52495fSSaurabh Misra 1039dd52495fSSaurabh Misra /* Program DMA channels */ 1040dd52495fSSaurabh Misra OUTL(bfe, BFE_DMATX_CTRL, BFE_TX_CTRL_ENABLE); 1041dd52495fSSaurabh Misra 1042dd52495fSSaurabh Misra /* 1043dd52495fSSaurabh Misra * DMA addresses need to be added to BFE_PCI_DMA 1044dd52495fSSaurabh Misra */ 1045dd52495fSSaurabh Misra OUTL(bfe, BFE_DMATX_ADDR, 1046dd52495fSSaurabh Misra bfe->bfe_tx_ring.r_desc_cookie.dmac_laddress + BFE_PCI_DMA); 1047dd52495fSSaurabh Misra 1048dd52495fSSaurabh Misra OUTL(bfe, BFE_DMARX_CTRL, (BFE_RX_OFFSET << BFE_RX_CTRL_ROSHIFT) 1049dd52495fSSaurabh Misra | BFE_RX_CTRL_ENABLE); 1050dd52495fSSaurabh Misra 1051dd52495fSSaurabh Misra OUTL(bfe, BFE_DMARX_ADDR, 1052dd52495fSSaurabh Misra bfe->bfe_rx_ring.r_desc_cookie.dmac_laddress + BFE_PCI_DMA); 1053dd52495fSSaurabh Misra 1054dd52495fSSaurabh Misra (void) bfe_startup_phy(bfe); 1055dd52495fSSaurabh Misra 1056dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_INITIALIZED; 1057dd52495fSSaurabh Misra } 1058dd52495fSSaurabh Misra 1059dd52495fSSaurabh Misra /* 1060dd52495fSSaurabh Misra * It enables interrupts. Should be the last step while starting chip. 1061dd52495fSSaurabh Misra */ 1062dd52495fSSaurabh Misra static void 1063dd52495fSSaurabh Misra bfe_enable_chip_intrs(bfe_t *bfe) 1064dd52495fSSaurabh Misra { 1065dd52495fSSaurabh Misra /* Enable the chip and core */ 1066dd52495fSSaurabh Misra OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_ENABLE); 1067dd52495fSSaurabh Misra 1068dd52495fSSaurabh Misra /* Enable interrupts */ 1069dd52495fSSaurabh Misra OUTL(bfe, BFE_INTR_MASK, BFE_IMASK_DEF); 1070dd52495fSSaurabh Misra } 1071dd52495fSSaurabh Misra 1072dd52495fSSaurabh Misra /* 1073dd52495fSSaurabh Misra * Common code to take care of setting RX side mode (filter). 1074dd52495fSSaurabh Misra */ 1075dd52495fSSaurabh Misra static void 1076dd52495fSSaurabh Misra bfe_set_rx_mode(bfe_t *bfe) 1077dd52495fSSaurabh Misra { 1078dd52495fSSaurabh Misra uint32_t val; 1079dd52495fSSaurabh Misra int i; 1080dd52495fSSaurabh Misra ether_addr_t mac[ETHERADDRL] = {0, 0, 0, 0, 0, 0}; 1081dd52495fSSaurabh Misra 1082dd52495fSSaurabh Misra /* 1083dd52495fSSaurabh Misra * We don't touch RX filter if we were asked to suspend. It's fine 1084dd52495fSSaurabh Misra * if chip is not active (no interface is plumbed on us). 1085dd52495fSSaurabh Misra */ 1086dd52495fSSaurabh Misra if (bfe->bfe_chip_state == BFE_CHIP_SUSPENDED) 1087dd52495fSSaurabh Misra return; 1088dd52495fSSaurabh Misra 1089dd52495fSSaurabh Misra val = INL(bfe, BFE_RXCONF); 1090dd52495fSSaurabh Misra 1091dd52495fSSaurabh Misra val &= ~BFE_RXCONF_PROMISC; 1092dd52495fSSaurabh Misra val &= ~BFE_RXCONF_DBCAST; 1093dd52495fSSaurabh Misra 1094dd52495fSSaurabh Misra if ((bfe->bfe_chip_mode & BFE_RX_MODE_ENABLE) == 0) { 1095dd52495fSSaurabh Misra OUTL(bfe, BFE_CAM_CTRL, 0); 1096dd52495fSSaurabh Misra FLUSH(bfe, BFE_CAM_CTRL); 1097dd52495fSSaurabh Misra } else if (bfe->bfe_chip_mode & BFE_RX_MODE_PROMISC) { 1098dd52495fSSaurabh Misra val |= BFE_RXCONF_PROMISC; 1099dd52495fSSaurabh Misra val &= ~BFE_RXCONF_DBCAST; 1100dd52495fSSaurabh Misra } else { 1101dd52495fSSaurabh Misra if (bfe->bfe_chip_state == BFE_CHIP_ACTIVE) { 1102dd52495fSSaurabh Misra /* Flush everything */ 1103dd52495fSSaurabh Misra OUTL(bfe, BFE_RXCONF, val | 1104dd52495fSSaurabh Misra BFE_RXCONF_PROMISC | BFE_RXCONF_ALLMULTI); 1105dd52495fSSaurabh Misra FLUSH(bfe, BFE_RXCONF); 1106dd52495fSSaurabh Misra } 1107dd52495fSSaurabh Misra 1108dd52495fSSaurabh Misra /* Disable CAM */ 1109dd52495fSSaurabh Misra OUTL(bfe, BFE_CAM_CTRL, 0); 1110dd52495fSSaurabh Misra FLUSH(bfe, BFE_CAM_CTRL); 1111dd52495fSSaurabh Misra 1112dd52495fSSaurabh Misra /* 1113dd52495fSSaurabh Misra * We receive all multicast packets. 1114dd52495fSSaurabh Misra */ 1115dd52495fSSaurabh Misra val |= BFE_RXCONF_ALLMULTI; 1116dd52495fSSaurabh Misra 1117dd52495fSSaurabh Misra for (i = 0; i < BFE_MAX_MULTICAST_TABLE - 1; i++) { 1118dd52495fSSaurabh Misra bfe_cam_write(bfe, (uchar_t *)mac, i); 1119dd52495fSSaurabh Misra } 1120dd52495fSSaurabh Misra 1121dd52495fSSaurabh Misra bfe_cam_write(bfe, bfe->bfe_ether_addr, i); 1122dd52495fSSaurabh Misra 1123dd52495fSSaurabh Misra /* Enable CAM */ 1124dd52495fSSaurabh Misra OUTL_OR(bfe, BFE_CAM_CTRL, BFE_CAM_ENABLE); 1125dd52495fSSaurabh Misra FLUSH(bfe, BFE_CAM_CTRL); 1126dd52495fSSaurabh Misra } 1127dd52495fSSaurabh Misra 1128dd52495fSSaurabh Misra DTRACE_PROBE2(rx__mode__filter, int, bfe->bfe_unit, 1129dd52495fSSaurabh Misra int, val); 1130dd52495fSSaurabh Misra 1131dd52495fSSaurabh Misra OUTL(bfe, BFE_RXCONF, val); 1132dd52495fSSaurabh Misra FLUSH(bfe, BFE_RXCONF); 1133dd52495fSSaurabh Misra } 1134dd52495fSSaurabh Misra 1135dd52495fSSaurabh Misra /* 1136dd52495fSSaurabh Misra * Reset various variable values to initial state. 1137dd52495fSSaurabh Misra */ 1138dd52495fSSaurabh Misra static void 1139dd52495fSSaurabh Misra bfe_init_vars(bfe_t *bfe) 1140dd52495fSSaurabh Misra { 1141dd52495fSSaurabh Misra bfe->bfe_chip_mode = BFE_RX_MODE_ENABLE; 1142dd52495fSSaurabh Misra 1143dd52495fSSaurabh Misra /* Initial assumption */ 1144dd52495fSSaurabh Misra bfe->bfe_chip.link = LINK_STATE_UNKNOWN; 1145dd52495fSSaurabh Misra bfe->bfe_chip.speed = 0; 1146dd52495fSSaurabh Misra bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN; 1147dd52495fSSaurabh Misra 1148dd52495fSSaurabh Misra bfe->bfe_periodic_id = NULL; 1149dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_UNINITIALIZED; 1150dd52495fSSaurabh Misra 1151dd52495fSSaurabh Misra bfe->bfe_tx_stall_time = 0; 1152dd52495fSSaurabh Misra } 1153dd52495fSSaurabh Misra 1154dd52495fSSaurabh Misra /* 1155dd52495fSSaurabh Misra * Initializes TX side descriptor entries (bfe_desc_t). Each descriptor entry 1156dd52495fSSaurabh Misra * has control (desc_ctl) and address (desc_addr) member. 1157dd52495fSSaurabh Misra */ 1158dd52495fSSaurabh Misra static void 1159dd52495fSSaurabh Misra bfe_tx_desc_init(bfe_ring_t *r) 1160dd52495fSSaurabh Misra { 1161dd52495fSSaurabh Misra int i; 1162dd52495fSSaurabh Misra uint32_t v; 1163dd52495fSSaurabh Misra 1164dd52495fSSaurabh Misra for (i = 0; i < r->r_ndesc; i++) { 1165dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_ctl), 1166dd52495fSSaurabh Misra (r->r_buf_dma[i].len & BFE_DESC_LEN)); 1167dd52495fSSaurabh Misra 1168dd52495fSSaurabh Misra /* 1169dd52495fSSaurabh Misra * DMA addresses need to be added to BFE_PCI_DMA 1170dd52495fSSaurabh Misra */ 1171dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_addr), 1172dd52495fSSaurabh Misra (r->r_buf_dma[i].cookie.dmac_laddress + BFE_PCI_DMA)); 1173dd52495fSSaurabh Misra } 1174dd52495fSSaurabh Misra 1175dd52495fSSaurabh Misra v = GET_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl)); 1176dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl), 1177dd52495fSSaurabh Misra v | BFE_DESC_EOT); 1178dd52495fSSaurabh Misra 1179dd52495fSSaurabh Misra (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV); 1180dd52495fSSaurabh Misra 1181dd52495fSSaurabh Misra r->r_curr_desc = 0; 1182dd52495fSSaurabh Misra r->r_avail_desc = TX_NUM_DESC; 1183dd52495fSSaurabh Misra r->r_cons_desc = 0; 1184dd52495fSSaurabh Misra } 1185dd52495fSSaurabh Misra 1186dd52495fSSaurabh Misra /* 1187dd52495fSSaurabh Misra * Initializes RX side descriptor entries (bfe_desc_t). Each descriptor entry 1188dd52495fSSaurabh Misra * has control (desc_ctl) and address (desc_addr) member. 1189dd52495fSSaurabh Misra */ 1190dd52495fSSaurabh Misra static void 1191dd52495fSSaurabh Misra bfe_rx_desc_init(bfe_ring_t *r) 1192dd52495fSSaurabh Misra { 1193dd52495fSSaurabh Misra int i; 1194dd52495fSSaurabh Misra uint32_t v; 1195dd52495fSSaurabh Misra 1196dd52495fSSaurabh Misra for (i = 0; i < r->r_ndesc; i++) { 1197dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_ctl), 1198dd52495fSSaurabh Misra (r->r_buf_dma[i].len& BFE_DESC_LEN)); 1199dd52495fSSaurabh Misra 1200dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_addr), 1201dd52495fSSaurabh Misra (r->r_buf_dma[i].cookie.dmac_laddress + BFE_PCI_DMA)); 1202dd52495fSSaurabh Misra 1203dd52495fSSaurabh Misra /* Initialize rx header (len, flags) */ 1204dd52495fSSaurabh Misra bzero(r->r_buf_dma[i].addr, sizeof (bfe_rx_header_t)); 1205dd52495fSSaurabh Misra 1206dd52495fSSaurabh Misra (void) SYNC_BUF(r, i, 0, sizeof (bfe_rx_header_t), 1207dd52495fSSaurabh Misra DDI_DMA_SYNC_FORDEV); 1208dd52495fSSaurabh Misra } 1209dd52495fSSaurabh Misra 1210dd52495fSSaurabh Misra v = GET_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl)); 1211dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl), 1212dd52495fSSaurabh Misra v | BFE_DESC_EOT); 1213dd52495fSSaurabh Misra 1214dd52495fSSaurabh Misra (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV); 1215dd52495fSSaurabh Misra 1216dd52495fSSaurabh Misra /* TAIL of RX Descriptor */ 1217dd52495fSSaurabh Misra OUTL(r->r_bfe, BFE_DMARX_PTR, ((i) * sizeof (bfe_desc_t))); 1218dd52495fSSaurabh Misra 1219dd52495fSSaurabh Misra r->r_curr_desc = 0; 1220dd52495fSSaurabh Misra r->r_avail_desc = RX_NUM_DESC; 1221dd52495fSSaurabh Misra } 1222dd52495fSSaurabh Misra 1223dd52495fSSaurabh Misra static int 1224dd52495fSSaurabh Misra bfe_chip_start(bfe_t *bfe) 1225dd52495fSSaurabh Misra { 1226954c6b5eSSaurabh Misra ASSERT_ALL_LOCKS(bfe); 1227dd52495fSSaurabh Misra 1228dd52495fSSaurabh Misra /* 1229dd52495fSSaurabh Misra * Stop the chip first & then Reset the chip. At last enable interrupts. 1230dd52495fSSaurabh Misra */ 1231dd52495fSSaurabh Misra bfe_chip_halt(bfe); 1232dd52495fSSaurabh Misra bfe_stop_phy(bfe); 1233dd52495fSSaurabh Misra 1234dd52495fSSaurabh Misra /* 1235dd52495fSSaurabh Misra * Reset chip and start PHY. 1236dd52495fSSaurabh Misra */ 1237dd52495fSSaurabh Misra bfe_chip_reset(bfe); 1238dd52495fSSaurabh Misra 1239dd52495fSSaurabh Misra /* 1240dd52495fSSaurabh Misra * Initailize Descriptor Rings. 1241dd52495fSSaurabh Misra */ 1242dd52495fSSaurabh Misra bfe_tx_desc_init(&bfe->bfe_tx_ring); 1243dd52495fSSaurabh Misra bfe_rx_desc_init(&bfe->bfe_rx_ring); 1244dd52495fSSaurabh Misra 1245dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_ACTIVE; 1246dd52495fSSaurabh Misra bfe->bfe_chip_mode |= BFE_RX_MODE_ENABLE; 1247dd52495fSSaurabh Misra bfe_set_rx_mode(bfe); 1248dd52495fSSaurabh Misra bfe_enable_chip_intrs(bfe); 1249dd52495fSSaurabh Misra 1250dd52495fSSaurabh Misra /* Check link, speed and duplex mode */ 1251dd52495fSSaurabh Misra (void) bfe_check_link(bfe); 1252dd52495fSSaurabh Misra 1253dd52495fSSaurabh Misra return (DDI_SUCCESS); 1254dd52495fSSaurabh Misra } 1255dd52495fSSaurabh Misra 1256dd52495fSSaurabh Misra 1257dd52495fSSaurabh Misra /* 1258dd52495fSSaurabh Misra * Clear chip statistics. 1259dd52495fSSaurabh Misra */ 1260dd52495fSSaurabh Misra static void 1261dd52495fSSaurabh Misra bfe_clear_stats(bfe_t *bfe) 1262dd52495fSSaurabh Misra { 1263dd52495fSSaurabh Misra ulong_t r; 1264dd52495fSSaurabh Misra 1265dd52495fSSaurabh Misra OUTL(bfe, BFE_MIB_CTRL, BFE_MIB_CLR_ON_READ); 1266dd52495fSSaurabh Misra 1267dd52495fSSaurabh Misra /* 1268dd52495fSSaurabh Misra * Stat registers are cleared by reading. 1269dd52495fSSaurabh Misra */ 1270dd52495fSSaurabh Misra for (r = BFE_TX_GOOD_O; r <= BFE_TX_PAUSE; r += 4) 1271dd52495fSSaurabh Misra (void) INL(bfe, r); 1272dd52495fSSaurabh Misra 1273dd52495fSSaurabh Misra for (r = BFE_RX_GOOD_O; r <= BFE_RX_NPAUSE; r += 4) 1274dd52495fSSaurabh Misra (void) INL(bfe, r); 1275dd52495fSSaurabh Misra } 1276dd52495fSSaurabh Misra 1277dd52495fSSaurabh Misra /* 1278dd52495fSSaurabh Misra * Collect chip statistics. 1279dd52495fSSaurabh Misra */ 1280dd52495fSSaurabh Misra static void 1281dd52495fSSaurabh Misra bfe_gather_stats(bfe_t *bfe) 1282dd52495fSSaurabh Misra { 1283dd52495fSSaurabh Misra ulong_t r; 1284dd52495fSSaurabh Misra uint32_t *v; 1285dd52495fSSaurabh Misra uint32_t txerr = 0, rxerr = 0, coll = 0; 1286dd52495fSSaurabh Misra 1287dd52495fSSaurabh Misra v = &bfe->bfe_hw_stats.tx_good_octets; 1288dd52495fSSaurabh Misra for (r = BFE_TX_GOOD_O; r <= BFE_TX_PAUSE; r += 4) { 1289dd52495fSSaurabh Misra *v += INL(bfe, r); 1290dd52495fSSaurabh Misra v++; 1291dd52495fSSaurabh Misra } 1292dd52495fSSaurabh Misra 1293dd52495fSSaurabh Misra v = &bfe->bfe_hw_stats.rx_good_octets; 1294dd52495fSSaurabh Misra for (r = BFE_RX_GOOD_O; r <= BFE_RX_NPAUSE; r += 4) { 1295dd52495fSSaurabh Misra *v += INL(bfe, r); 1296dd52495fSSaurabh Misra v++; 1297dd52495fSSaurabh Misra } 1298dd52495fSSaurabh Misra 1299dd52495fSSaurabh Misra /* 1300dd52495fSSaurabh Misra * TX : 1301dd52495fSSaurabh Misra * ------- 1302dd52495fSSaurabh Misra * tx_good_octets, tx_good_pkts, tx_octets 1303dd52495fSSaurabh Misra * tx_pkts, tx_broadcast_pkts, tx_multicast_pkts 1304dd52495fSSaurabh Misra * tx_len_64, tx_len_65_to_127, tx_len_128_to_255 1305dd52495fSSaurabh Misra * tx_len_256_to_511, tx_len_512_to_1023, tx_len_1024_to_max 1306dd52495fSSaurabh Misra * tx_jabber_pkts, tx_oversize_pkts, tx_fragment_pkts 1307dd52495fSSaurabh Misra * tx_underruns, tx_total_cols, tx_single_cols 1308dd52495fSSaurabh Misra * tx_multiple_cols, tx_excessive_cols, tx_late_cols 1309dd52495fSSaurabh Misra * tx_defered, tx_carrier_lost, tx_pause_pkts 1310dd52495fSSaurabh Misra * 1311dd52495fSSaurabh Misra * RX : 1312dd52495fSSaurabh Misra * ------- 1313dd52495fSSaurabh Misra * rx_good_octets, rx_good_pkts, rx_octets 1314dd52495fSSaurabh Misra * rx_pkts, rx_broadcast_pkts, rx_multicast_pkts 1315dd52495fSSaurabh Misra * rx_len_64, rx_len_65_to_127, rx_len_128_to_255 1316dd52495fSSaurabh Misra * rx_len_256_to_511, rx_len_512_to_1023, rx_len_1024_to_max 1317dd52495fSSaurabh Misra * rx_jabber_pkts, rx_oversize_pkts, rx_fragment_pkts 1318dd52495fSSaurabh Misra * rx_missed_pkts, rx_crc_align_errs, rx_undersize 1319dd52495fSSaurabh Misra * rx_crc_errs, rx_align_errs, rx_symbol_errs 1320dd52495fSSaurabh Misra * rx_pause_pkts, rx_nonpause_pkts 1321dd52495fSSaurabh Misra */ 1322dd52495fSSaurabh Misra 1323dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_carrier_errors = 1324dd52495fSSaurabh Misra bfe->bfe_hw_stats.tx_carrier_lost; 1325dd52495fSSaurabh Misra 1326dd52495fSSaurabh Misra /* txerr += bfe->bfe_hw_stats.tx_carrier_lost; */ 1327dd52495fSSaurabh Misra 1328dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_ex_collisions = 1329dd52495fSSaurabh Misra bfe->bfe_hw_stats.tx_excessive_cols; 1330dd52495fSSaurabh Misra txerr += bfe->bfe_hw_stats.tx_excessive_cols; 1331dd52495fSSaurabh Misra coll += bfe->bfe_hw_stats.tx_excessive_cols; 1332dd52495fSSaurabh Misra 1333dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_fcs_errors = 1334dd52495fSSaurabh Misra bfe->bfe_hw_stats.rx_crc_errs; 1335dd52495fSSaurabh Misra rxerr += bfe->bfe_hw_stats.rx_crc_errs; 1336dd52495fSSaurabh Misra 1337dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_first_collisions = 1338dd52495fSSaurabh Misra bfe->bfe_hw_stats.tx_single_cols; 1339dd52495fSSaurabh Misra coll += bfe->bfe_hw_stats.tx_single_cols; 1340dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_multi_collisions = 1341dd52495fSSaurabh Misra bfe->bfe_hw_stats.tx_multiple_cols; 1342dd52495fSSaurabh Misra coll += bfe->bfe_hw_stats.tx_multiple_cols; 1343dd52495fSSaurabh Misra 1344dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_toolong_errors = 1345dd52495fSSaurabh Misra bfe->bfe_hw_stats.rx_oversize_pkts; 1346dd52495fSSaurabh Misra rxerr += bfe->bfe_hw_stats.rx_oversize_pkts; 1347dd52495fSSaurabh Misra 1348dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_tooshort_errors = 1349dd52495fSSaurabh Misra bfe->bfe_hw_stats.rx_undersize; 1350dd52495fSSaurabh Misra rxerr += bfe->bfe_hw_stats.rx_undersize; 1351dd52495fSSaurabh Misra 1352dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_tx_late_collisions += 1353dd52495fSSaurabh Misra bfe->bfe_hw_stats.tx_late_cols; 1354dd52495fSSaurabh Misra 1355dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_defer_xmts += 1356dd52495fSSaurabh Misra bfe->bfe_hw_stats.tx_defered; 1357dd52495fSSaurabh Misra 1358dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_macrcv_errors += rxerr; 1359dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_macxmt_errors += txerr; 1360dd52495fSSaurabh Misra 1361dd52495fSSaurabh Misra bfe->bfe_stats.collisions += coll; 1362dd52495fSSaurabh Misra } 1363dd52495fSSaurabh Misra 1364dd52495fSSaurabh Misra /* 1365dd52495fSSaurabh Misra * Gets the state for dladm command and all. 1366dd52495fSSaurabh Misra */ 1367dd52495fSSaurabh Misra int 1368dd52495fSSaurabh Misra bfe_mac_getstat(void *arg, uint_t stat, uint64_t *val) 1369dd52495fSSaurabh Misra { 1370dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 1371dd52495fSSaurabh Misra uint64_t v; 1372dd52495fSSaurabh Misra int err = 0; 1373dd52495fSSaurabh Misra 1374dd52495fSSaurabh Misra rw_enter(&bfe->bfe_rwlock, RW_READER); 1375dd52495fSSaurabh Misra 1376dd52495fSSaurabh Misra 1377dd52495fSSaurabh Misra switch (stat) { 1378dd52495fSSaurabh Misra default: 1379dd52495fSSaurabh Misra err = ENOTSUP; 1380dd52495fSSaurabh Misra break; 1381dd52495fSSaurabh Misra 1382dd52495fSSaurabh Misra case MAC_STAT_IFSPEED: 1383dd52495fSSaurabh Misra /* 1384dd52495fSSaurabh Misra * MAC layer will ask for IFSPEED first and hence we 1385dd52495fSSaurabh Misra * collect it only once. 1386dd52495fSSaurabh Misra */ 1387dd52495fSSaurabh Misra if (bfe->bfe_chip_state == BFE_CHIP_ACTIVE) { 1388dd52495fSSaurabh Misra /* 1389dd52495fSSaurabh Misra * Update stats from the hardware. 1390dd52495fSSaurabh Misra */ 1391dd52495fSSaurabh Misra bfe_gather_stats(bfe); 1392dd52495fSSaurabh Misra } 1393dd52495fSSaurabh Misra v = bfe->bfe_chip.speed; 1394dd52495fSSaurabh Misra break; 1395dd52495fSSaurabh Misra 1396dd52495fSSaurabh Misra case ETHER_STAT_ADV_CAP_100T4: 1397dd52495fSSaurabh Misra v = bfe->bfe_adv_100T4; 1398dd52495fSSaurabh Misra break; 1399dd52495fSSaurabh Misra 1400dd52495fSSaurabh Misra case ETHER_STAT_ADV_CAP_100FDX: 1401dd52495fSSaurabh Misra v = (bfe->bfe_mii_anar & MII_ABILITY_100BASE_TX_FD) != 0; 1402dd52495fSSaurabh Misra break; 1403dd52495fSSaurabh Misra 1404dd52495fSSaurabh Misra case ETHER_STAT_ADV_CAP_100HDX: 1405dd52495fSSaurabh Misra v = (bfe->bfe_mii_anar & MII_ABILITY_100BASE_TX) != 0; 1406dd52495fSSaurabh Misra break; 1407dd52495fSSaurabh Misra 1408dd52495fSSaurabh Misra case ETHER_STAT_ADV_CAP_10FDX: 1409dd52495fSSaurabh Misra v = (bfe->bfe_mii_anar & MII_ABILITY_10BASE_T_FD) != 0; 1410dd52495fSSaurabh Misra break; 1411dd52495fSSaurabh Misra 1412dd52495fSSaurabh Misra case ETHER_STAT_ADV_CAP_10HDX: 1413dd52495fSSaurabh Misra v = (bfe->bfe_mii_anar & MII_ABILITY_10BASE_T) != 0; 1414dd52495fSSaurabh Misra break; 1415dd52495fSSaurabh Misra 1416dd52495fSSaurabh Misra case ETHER_STAT_ADV_CAP_ASMPAUSE: 1417dd52495fSSaurabh Misra v = 0; 1418dd52495fSSaurabh Misra break; 1419dd52495fSSaurabh Misra 1420dd52495fSSaurabh Misra case ETHER_STAT_ADV_CAP_AUTONEG: 1421dd52495fSSaurabh Misra v = bfe->bfe_adv_aneg; 1422dd52495fSSaurabh Misra break; 1423dd52495fSSaurabh Misra 1424dd52495fSSaurabh Misra case ETHER_STAT_ADV_CAP_PAUSE: 1425dd52495fSSaurabh Misra v = (bfe->bfe_mii_anar & MII_ABILITY_PAUSE) != 0; 1426dd52495fSSaurabh Misra break; 1427dd52495fSSaurabh Misra 1428dd52495fSSaurabh Misra case ETHER_STAT_ADV_REMFAULT: 1429dd52495fSSaurabh Misra v = (bfe->bfe_mii_anar & MII_AN_ADVERT_REMFAULT) != 0; 1430dd52495fSSaurabh Misra break; 1431dd52495fSSaurabh Misra 1432dd52495fSSaurabh Misra case ETHER_STAT_ALIGN_ERRORS: 1433dd52495fSSaurabh Misra /* MIB */ 1434dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_align_errors; 1435dd52495fSSaurabh Misra break; 1436dd52495fSSaurabh Misra 1437dd52495fSSaurabh Misra case ETHER_STAT_CAP_100T4: 1438dd52495fSSaurabh Misra v = (bfe->bfe_mii_bmsr & MII_STATUS_100_BASE_T4) != 0; 1439dd52495fSSaurabh Misra break; 1440dd52495fSSaurabh Misra 1441dd52495fSSaurabh Misra case ETHER_STAT_CAP_100FDX: 1442dd52495fSSaurabh Misra v = (bfe->bfe_mii_bmsr & MII_STATUS_100_BASEX_FD) != 0; 1443dd52495fSSaurabh Misra break; 1444dd52495fSSaurabh Misra 1445dd52495fSSaurabh Misra case ETHER_STAT_CAP_100HDX: 1446dd52495fSSaurabh Misra v = (bfe->bfe_mii_bmsr & MII_STATUS_100_BASEX) != 0; 1447dd52495fSSaurabh Misra break; 1448dd52495fSSaurabh Misra 1449dd52495fSSaurabh Misra case ETHER_STAT_CAP_10FDX: 1450dd52495fSSaurabh Misra v = (bfe->bfe_mii_bmsr & MII_STATUS_10_FD) != 0; 1451dd52495fSSaurabh Misra break; 1452dd52495fSSaurabh Misra 1453dd52495fSSaurabh Misra case ETHER_STAT_CAP_10HDX: 1454dd52495fSSaurabh Misra v = (bfe->bfe_mii_bmsr & MII_STATUS_10) != 0; 1455dd52495fSSaurabh Misra break; 1456dd52495fSSaurabh Misra 1457dd52495fSSaurabh Misra case ETHER_STAT_CAP_ASMPAUSE: 1458dd52495fSSaurabh Misra v = 0; 1459dd52495fSSaurabh Misra break; 1460dd52495fSSaurabh Misra 1461dd52495fSSaurabh Misra case ETHER_STAT_CAP_AUTONEG: 1462dd52495fSSaurabh Misra v = ((bfe->bfe_mii_bmsr & MII_STATUS_CANAUTONEG) != 0); 1463dd52495fSSaurabh Misra break; 1464dd52495fSSaurabh Misra 1465dd52495fSSaurabh Misra case ETHER_STAT_CAP_PAUSE: 1466dd52495fSSaurabh Misra v = 1; 1467dd52495fSSaurabh Misra break; 1468dd52495fSSaurabh Misra 1469dd52495fSSaurabh Misra case ETHER_STAT_CAP_REMFAULT: 1470dd52495fSSaurabh Misra v = (bfe->bfe_mii_bmsr & MII_STATUS_REMFAULT) != 0; 1471dd52495fSSaurabh Misra break; 1472dd52495fSSaurabh Misra 1473dd52495fSSaurabh Misra case ETHER_STAT_CARRIER_ERRORS: 1474dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_carrier_errors; 1475dd52495fSSaurabh Misra break; 1476dd52495fSSaurabh Misra 1477dd52495fSSaurabh Misra case ETHER_STAT_JABBER_ERRORS: 1478dd52495fSSaurabh Misra err = ENOTSUP; 1479dd52495fSSaurabh Misra break; 1480dd52495fSSaurabh Misra 1481dd52495fSSaurabh Misra case ETHER_STAT_DEFER_XMTS: 1482dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_defer_xmts; 1483dd52495fSSaurabh Misra break; 1484dd52495fSSaurabh Misra 1485dd52495fSSaurabh Misra case ETHER_STAT_EX_COLLISIONS: 1486dd52495fSSaurabh Misra /* MIB */ 1487dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_ex_collisions; 1488dd52495fSSaurabh Misra break; 1489dd52495fSSaurabh Misra 1490dd52495fSSaurabh Misra case ETHER_STAT_FCS_ERRORS: 1491dd52495fSSaurabh Misra /* MIB */ 1492dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_fcs_errors; 1493dd52495fSSaurabh Misra break; 1494dd52495fSSaurabh Misra 1495dd52495fSSaurabh Misra case ETHER_STAT_FIRST_COLLISIONS: 1496dd52495fSSaurabh Misra /* MIB */ 1497dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_first_collisions; 1498dd52495fSSaurabh Misra break; 1499dd52495fSSaurabh Misra 1500dd52495fSSaurabh Misra case ETHER_STAT_LINK_ASMPAUSE: 1501dd52495fSSaurabh Misra v = 0; 1502dd52495fSSaurabh Misra break; 1503dd52495fSSaurabh Misra 1504dd52495fSSaurabh Misra case ETHER_STAT_LINK_AUTONEG: 1505dd52495fSSaurabh Misra v = (bfe->bfe_mii_bmcr & MII_CONTROL_ANE) != 0 && 1506dd52495fSSaurabh Misra (bfe->bfe_mii_bmsr & MII_STATUS_ANDONE) != 0; 1507dd52495fSSaurabh Misra break; 1508dd52495fSSaurabh Misra 1509dd52495fSSaurabh Misra case ETHER_STAT_LINK_DUPLEX: 1510dd52495fSSaurabh Misra v = bfe->bfe_chip.duplex; 1511dd52495fSSaurabh Misra break; 1512dd52495fSSaurabh Misra 1513dd52495fSSaurabh Misra case ETHER_STAT_LP_CAP_100T4: 1514dd52495fSSaurabh Misra v = (bfe->bfe_mii_anlpar & MII_ABILITY_100BASE_T4) != 0; 1515dd52495fSSaurabh Misra break; 1516dd52495fSSaurabh Misra 1517dd52495fSSaurabh Misra case ETHER_STAT_LP_CAP_100FDX: 1518dd52495fSSaurabh Misra v = (bfe->bfe_mii_anlpar & MII_ABILITY_100BASE_TX_FD) != 0; 1519dd52495fSSaurabh Misra break; 1520dd52495fSSaurabh Misra 1521dd52495fSSaurabh Misra case ETHER_STAT_LP_CAP_100HDX: 1522dd52495fSSaurabh Misra v = (bfe->bfe_mii_anlpar & MII_ABILITY_100BASE_TX) != 0; 1523dd52495fSSaurabh Misra break; 1524dd52495fSSaurabh Misra 1525dd52495fSSaurabh Misra case ETHER_STAT_LP_CAP_10FDX: 1526dd52495fSSaurabh Misra v = (bfe->bfe_mii_anlpar & MII_ABILITY_10BASE_T_FD) != 0; 1527dd52495fSSaurabh Misra break; 1528dd52495fSSaurabh Misra 1529dd52495fSSaurabh Misra case ETHER_STAT_LP_CAP_10HDX: 1530dd52495fSSaurabh Misra v = (bfe->bfe_mii_anlpar & MII_ABILITY_10BASE_T) != 0; 1531dd52495fSSaurabh Misra break; 1532dd52495fSSaurabh Misra 1533dd52495fSSaurabh Misra case ETHER_STAT_LP_CAP_ASMPAUSE: 1534dd52495fSSaurabh Misra v = 0; 1535dd52495fSSaurabh Misra break; 1536dd52495fSSaurabh Misra 1537dd52495fSSaurabh Misra case ETHER_STAT_LP_CAP_AUTONEG: 1538dd52495fSSaurabh Misra v = (bfe->bfe_mii_exp & MII_AN_EXP_LPCANAN) != 0; 1539dd52495fSSaurabh Misra break; 1540dd52495fSSaurabh Misra 1541dd52495fSSaurabh Misra case ETHER_STAT_LP_CAP_PAUSE: 1542dd52495fSSaurabh Misra v = (bfe->bfe_mii_anlpar & MII_ABILITY_PAUSE) != 0; 1543dd52495fSSaurabh Misra break; 1544dd52495fSSaurabh Misra 1545dd52495fSSaurabh Misra case ETHER_STAT_LP_REMFAULT: 1546dd52495fSSaurabh Misra v = (bfe->bfe_mii_anlpar & MII_STATUS_REMFAULT) != 0; 1547dd52495fSSaurabh Misra break; 1548dd52495fSSaurabh Misra 1549dd52495fSSaurabh Misra case ETHER_STAT_MACRCV_ERRORS: 1550dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_macrcv_errors; 1551dd52495fSSaurabh Misra break; 1552dd52495fSSaurabh Misra 1553dd52495fSSaurabh Misra case ETHER_STAT_MACXMT_ERRORS: 1554dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_macxmt_errors; 1555dd52495fSSaurabh Misra break; 1556dd52495fSSaurabh Misra 1557dd52495fSSaurabh Misra case ETHER_STAT_MULTI_COLLISIONS: 1558dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_multi_collisions; 1559dd52495fSSaurabh Misra break; 1560dd52495fSSaurabh Misra 1561dd52495fSSaurabh Misra case ETHER_STAT_SQE_ERRORS: 1562dd52495fSSaurabh Misra err = ENOTSUP; 1563dd52495fSSaurabh Misra break; 1564dd52495fSSaurabh Misra 1565dd52495fSSaurabh Misra case ETHER_STAT_TOOLONG_ERRORS: 1566dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_toolong_errors; 1567dd52495fSSaurabh Misra break; 1568dd52495fSSaurabh Misra 1569dd52495fSSaurabh Misra case ETHER_STAT_TOOSHORT_ERRORS: 1570dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_tooshort_errors; 1571dd52495fSSaurabh Misra break; 1572dd52495fSSaurabh Misra 1573dd52495fSSaurabh Misra case ETHER_STAT_TX_LATE_COLLISIONS: 1574dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_tx_late_collisions; 1575dd52495fSSaurabh Misra break; 1576dd52495fSSaurabh Misra 1577dd52495fSSaurabh Misra case ETHER_STAT_XCVR_ADDR: 1578dd52495fSSaurabh Misra v = bfe->bfe_phy_addr; 1579dd52495fSSaurabh Misra break; 1580dd52495fSSaurabh Misra 1581dd52495fSSaurabh Misra case ETHER_STAT_XCVR_ID: 1582dd52495fSSaurabh Misra v = bfe->bfe_phy_id; 1583dd52495fSSaurabh Misra break; 1584dd52495fSSaurabh Misra 1585dd52495fSSaurabh Misra case MAC_STAT_BRDCSTRCV: 1586dd52495fSSaurabh Misra v = bfe->bfe_stats.brdcstrcv; 1587dd52495fSSaurabh Misra break; 1588dd52495fSSaurabh Misra 1589dd52495fSSaurabh Misra case MAC_STAT_BRDCSTXMT: 1590dd52495fSSaurabh Misra v = bfe->bfe_stats.brdcstxmt; 1591dd52495fSSaurabh Misra break; 1592dd52495fSSaurabh Misra 1593dd52495fSSaurabh Misra case MAC_STAT_MULTIXMT: 1594dd52495fSSaurabh Misra v = bfe->bfe_stats.multixmt; 1595dd52495fSSaurabh Misra break; 1596dd52495fSSaurabh Misra 1597dd52495fSSaurabh Misra case MAC_STAT_COLLISIONS: 1598dd52495fSSaurabh Misra v = bfe->bfe_stats.collisions; 1599dd52495fSSaurabh Misra break; 1600dd52495fSSaurabh Misra 1601dd52495fSSaurabh Misra case MAC_STAT_IERRORS: 1602dd52495fSSaurabh Misra v = bfe->bfe_stats.ierrors; 1603dd52495fSSaurabh Misra break; 1604dd52495fSSaurabh Misra 1605dd52495fSSaurabh Misra case MAC_STAT_IPACKETS: 1606dd52495fSSaurabh Misra v = bfe->bfe_stats.ipackets; 1607dd52495fSSaurabh Misra break; 1608dd52495fSSaurabh Misra 1609dd52495fSSaurabh Misra case MAC_STAT_MULTIRCV: 1610dd52495fSSaurabh Misra v = bfe->bfe_stats.multircv; 1611dd52495fSSaurabh Misra break; 1612dd52495fSSaurabh Misra 1613dd52495fSSaurabh Misra case MAC_STAT_NORCVBUF: 1614dd52495fSSaurabh Misra v = bfe->bfe_stats.norcvbuf; 1615dd52495fSSaurabh Misra break; 1616dd52495fSSaurabh Misra 1617dd52495fSSaurabh Misra case MAC_STAT_NOXMTBUF: 1618dd52495fSSaurabh Misra v = bfe->bfe_stats.noxmtbuf; 1619dd52495fSSaurabh Misra break; 1620dd52495fSSaurabh Misra 1621dd52495fSSaurabh Misra case MAC_STAT_OBYTES: 1622dd52495fSSaurabh Misra v = bfe->bfe_stats.obytes; 1623dd52495fSSaurabh Misra break; 1624dd52495fSSaurabh Misra 1625dd52495fSSaurabh Misra case MAC_STAT_OERRORS: 1626dd52495fSSaurabh Misra /* MIB */ 1627dd52495fSSaurabh Misra v = bfe->bfe_stats.ether_stat_macxmt_errors; 1628dd52495fSSaurabh Misra break; 1629dd52495fSSaurabh Misra 1630dd52495fSSaurabh Misra case MAC_STAT_OPACKETS: 1631dd52495fSSaurabh Misra v = bfe->bfe_stats.opackets; 1632dd52495fSSaurabh Misra break; 1633dd52495fSSaurabh Misra 1634dd52495fSSaurabh Misra case MAC_STAT_RBYTES: 1635dd52495fSSaurabh Misra v = bfe->bfe_stats.rbytes; 1636dd52495fSSaurabh Misra break; 1637dd52495fSSaurabh Misra 1638dd52495fSSaurabh Misra case MAC_STAT_UNDERFLOWS: 1639dd52495fSSaurabh Misra v = bfe->bfe_stats.underflows; 1640dd52495fSSaurabh Misra break; 1641dd52495fSSaurabh Misra 1642dd52495fSSaurabh Misra case MAC_STAT_OVERFLOWS: 1643dd52495fSSaurabh Misra v = bfe->bfe_stats.overflows; 1644dd52495fSSaurabh Misra break; 1645dd52495fSSaurabh Misra } 1646dd52495fSSaurabh Misra 1647dd52495fSSaurabh Misra rw_exit(&bfe->bfe_rwlock); 1648dd52495fSSaurabh Misra 1649dd52495fSSaurabh Misra *val = v; 1650dd52495fSSaurabh Misra return (err); 1651dd52495fSSaurabh Misra } 1652dd52495fSSaurabh Misra 1653dd52495fSSaurabh Misra int 16540dc2366fSVenugopal Iyer bfe_mac_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz, 16550dc2366fSVenugopal Iyer void *val) 1656dd52495fSSaurabh Misra { 1657dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 1658dd52495fSSaurabh Misra int err = 0; 1659dd52495fSSaurabh Misra 1660dd52495fSSaurabh Misra switch (num) { 1661dd52495fSSaurabh Misra case MAC_PROP_DUPLEX: 16620dc2366fSVenugopal Iyer ASSERT(sz >= sizeof (link_duplex_t)); 16630dc2366fSVenugopal Iyer bcopy(&bfe->bfe_chip.duplex, val, sizeof (link_duplex_t)); 1664dd52495fSSaurabh Misra break; 1665dd52495fSSaurabh Misra 1666dd52495fSSaurabh Misra case MAC_PROP_SPEED: 16670dc2366fSVenugopal Iyer ASSERT(sz >= sizeof (uint64_t)); 1668dd52495fSSaurabh Misra bcopy(&bfe->bfe_chip.speed, val, sizeof (uint64_t)); 1669dd52495fSSaurabh Misra break; 1670dd52495fSSaurabh Misra 1671dd52495fSSaurabh Misra case MAC_PROP_AUTONEG: 16720dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_aneg; 1673dd52495fSSaurabh Misra break; 1674dd52495fSSaurabh Misra 1675dd52495fSSaurabh Misra case MAC_PROP_ADV_100FDX_CAP: 16760dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_100fdx; 1677dd52495fSSaurabh Misra break; 16780dc2366fSVenugopal Iyer 1679dd52495fSSaurabh Misra case MAC_PROP_EN_100FDX_CAP: 16800dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_100fdx; 1681dd52495fSSaurabh Misra break; 1682dd52495fSSaurabh Misra 1683dd52495fSSaurabh Misra case MAC_PROP_ADV_100HDX_CAP: 16840dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_100hdx; 1685dd52495fSSaurabh Misra break; 16860dc2366fSVenugopal Iyer 1687dd52495fSSaurabh Misra case MAC_PROP_EN_100HDX_CAP: 16880dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_100hdx; 1689dd52495fSSaurabh Misra break; 1690dd52495fSSaurabh Misra 1691dd52495fSSaurabh Misra case MAC_PROP_ADV_10FDX_CAP: 16920dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_10fdx; 1693dd52495fSSaurabh Misra break; 16940dc2366fSVenugopal Iyer 1695dd52495fSSaurabh Misra case MAC_PROP_EN_10FDX_CAP: 16960dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_10fdx; 1697dd52495fSSaurabh Misra break; 1698dd52495fSSaurabh Misra 1699dd52495fSSaurabh Misra case MAC_PROP_ADV_10HDX_CAP: 17000dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_10hdx; 1701dd52495fSSaurabh Misra break; 17020dc2366fSVenugopal Iyer 1703dd52495fSSaurabh Misra case MAC_PROP_EN_10HDX_CAP: 17040dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_10hdx; 1705dd52495fSSaurabh Misra break; 1706dd52495fSSaurabh Misra 1707dd52495fSSaurabh Misra case MAC_PROP_ADV_100T4_CAP: 17080dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_100T4; 1709dd52495fSSaurabh Misra break; 17100dc2366fSVenugopal Iyer 1711dd52495fSSaurabh Misra case MAC_PROP_EN_100T4_CAP: 17120dc2366fSVenugopal Iyer *(uint8_t *)val = bfe->bfe_adv_100T4; 1713dd52495fSSaurabh Misra break; 1714dd52495fSSaurabh Misra 1715dd52495fSSaurabh Misra default: 1716dd52495fSSaurabh Misra err = ENOTSUP; 1717dd52495fSSaurabh Misra } 1718dd52495fSSaurabh Misra 1719dd52495fSSaurabh Misra return (err); 1720dd52495fSSaurabh Misra } 1721dd52495fSSaurabh Misra 17220dc2366fSVenugopal Iyer 17230dc2366fSVenugopal Iyer static void 17240dc2366fSVenugopal Iyer bfe_mac_propinfo(void *arg, const char *name, mac_prop_id_t num, 17250dc2366fSVenugopal Iyer mac_prop_info_handle_t prh) 17260dc2366fSVenugopal Iyer { 17270dc2366fSVenugopal Iyer bfe_t *bfe = (bfe_t *)arg; 17280dc2366fSVenugopal Iyer 17290dc2366fSVenugopal Iyer switch (num) { 17300dc2366fSVenugopal Iyer case MAC_PROP_DUPLEX: 17310dc2366fSVenugopal Iyer case MAC_PROP_SPEED: 17320dc2366fSVenugopal Iyer case MAC_PROP_ADV_100FDX_CAP: 17330dc2366fSVenugopal Iyer case MAC_PROP_ADV_100HDX_CAP: 17340dc2366fSVenugopal Iyer case MAC_PROP_ADV_10FDX_CAP: 17350dc2366fSVenugopal Iyer case MAC_PROP_ADV_10HDX_CAP: 17360dc2366fSVenugopal Iyer case MAC_PROP_ADV_100T4_CAP: 17377a0c1e29SCrisson Guanghao Hu case MAC_PROP_EN_100T4_CAP: 17380dc2366fSVenugopal Iyer mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 17390dc2366fSVenugopal Iyer break; 17400dc2366fSVenugopal Iyer 17410dc2366fSVenugopal Iyer case MAC_PROP_AUTONEG: 17420dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_aneg); 17430dc2366fSVenugopal Iyer break; 17440dc2366fSVenugopal Iyer 17450dc2366fSVenugopal Iyer case MAC_PROP_EN_100FDX_CAP: 17460dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_100fdx); 17470dc2366fSVenugopal Iyer break; 17480dc2366fSVenugopal Iyer 17490dc2366fSVenugopal Iyer case MAC_PROP_EN_100HDX_CAP: 17500dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_100hdx); 17510dc2366fSVenugopal Iyer break; 17520dc2366fSVenugopal Iyer 17530dc2366fSVenugopal Iyer case MAC_PROP_EN_10FDX_CAP: 17540dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_10fdx); 17550dc2366fSVenugopal Iyer break; 17560dc2366fSVenugopal Iyer 17570dc2366fSVenugopal Iyer case MAC_PROP_EN_10HDX_CAP: 17580dc2366fSVenugopal Iyer mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_10hdx); 17590dc2366fSVenugopal Iyer break; 17600dc2366fSVenugopal Iyer } 17610dc2366fSVenugopal Iyer } 17620dc2366fSVenugopal Iyer 17630dc2366fSVenugopal Iyer 1764dd52495fSSaurabh Misra /*ARGSUSED*/ 1765dd52495fSSaurabh Misra int 1766dd52495fSSaurabh Misra bfe_mac_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz, 1767dd52495fSSaurabh Misra const void *val) 1768dd52495fSSaurabh Misra { 1769dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 1770dd52495fSSaurabh Misra uint8_t *advp; 1771dd52495fSSaurabh Misra uint8_t *capp; 1772dd52495fSSaurabh Misra int r = 0; 1773dd52495fSSaurabh Misra 1774dd52495fSSaurabh Misra switch (num) { 1775dd52495fSSaurabh Misra case MAC_PROP_EN_100FDX_CAP: 1776dd52495fSSaurabh Misra advp = &bfe->bfe_adv_100fdx; 1777dd52495fSSaurabh Misra capp = &bfe->bfe_cap_100fdx; 1778dd52495fSSaurabh Misra break; 1779dd52495fSSaurabh Misra 1780dd52495fSSaurabh Misra case MAC_PROP_EN_100HDX_CAP: 1781dd52495fSSaurabh Misra advp = &bfe->bfe_adv_100hdx; 1782dd52495fSSaurabh Misra capp = &bfe->bfe_cap_100hdx; 1783dd52495fSSaurabh Misra break; 1784dd52495fSSaurabh Misra 1785dd52495fSSaurabh Misra case MAC_PROP_EN_10FDX_CAP: 1786dd52495fSSaurabh Misra advp = &bfe->bfe_adv_10fdx; 1787dd52495fSSaurabh Misra capp = &bfe->bfe_cap_10fdx; 1788dd52495fSSaurabh Misra break; 1789dd52495fSSaurabh Misra 1790dd52495fSSaurabh Misra case MAC_PROP_EN_10HDX_CAP: 1791dd52495fSSaurabh Misra advp = &bfe->bfe_adv_10hdx; 1792dd52495fSSaurabh Misra capp = &bfe->bfe_cap_10hdx; 1793dd52495fSSaurabh Misra break; 1794dd52495fSSaurabh Misra 1795dd52495fSSaurabh Misra case MAC_PROP_AUTONEG: 1796dd52495fSSaurabh Misra advp = &bfe->bfe_adv_aneg; 1797dd52495fSSaurabh Misra capp = &bfe->bfe_cap_aneg; 1798dd52495fSSaurabh Misra break; 1799dd52495fSSaurabh Misra 1800dd52495fSSaurabh Misra default: 1801dd52495fSSaurabh Misra return (ENOTSUP); 1802dd52495fSSaurabh Misra } 1803dd52495fSSaurabh Misra 1804dd52495fSSaurabh Misra if (*capp == 0) 1805dd52495fSSaurabh Misra return (ENOTSUP); 1806dd52495fSSaurabh Misra 1807dd52495fSSaurabh Misra bfe_grab_locks(bfe); 1808dd52495fSSaurabh Misra 1809dd52495fSSaurabh Misra if (*advp != *(const uint8_t *)val) { 1810dd52495fSSaurabh Misra *advp = *(const uint8_t *)val; 1811dd52495fSSaurabh Misra 1812dd52495fSSaurabh Misra bfe->bfe_chip_action = BFE_ACTION_RESTART_SETPROP; 1813dd52495fSSaurabh Misra if (bfe->bfe_chip_state == BFE_CHIP_ACTIVE) { 1814dd52495fSSaurabh Misra /* 1815dd52495fSSaurabh Misra * We need to stop the timer before grabbing locks 1816dd52495fSSaurabh Misra * otherwise we can land-up in deadlock with untimeout. 1817dd52495fSSaurabh Misra */ 1818dd52495fSSaurabh Misra bfe_stop_timer(bfe); 1819dd52495fSSaurabh Misra 1820dd52495fSSaurabh Misra bfe->bfe_chip_action |= BFE_ACTION_RESTART; 1821dd52495fSSaurabh Misra 1822dd52495fSSaurabh Misra bfe_chip_restart(bfe); 1823dd52495fSSaurabh Misra 1824dd52495fSSaurabh Misra /* 1825dd52495fSSaurabh Misra * We leave SETPROP because properties can be 1826dd52495fSSaurabh Misra * temporary. 1827dd52495fSSaurabh Misra */ 1828dd52495fSSaurabh Misra bfe->bfe_chip_action &= ~(BFE_ACTION_RESTART); 1829dd52495fSSaurabh Misra r = 1; 1830dd52495fSSaurabh Misra } 1831dd52495fSSaurabh Misra } 1832dd52495fSSaurabh Misra 1833dd52495fSSaurabh Misra bfe_release_locks(bfe); 1834dd52495fSSaurabh Misra 1835dd52495fSSaurabh Misra /* kick-off a potential stopped downstream */ 1836dd52495fSSaurabh Misra if (r) 1837dd52495fSSaurabh Misra mac_tx_update(bfe->bfe_machdl); 1838dd52495fSSaurabh Misra 1839dd52495fSSaurabh Misra return (0); 1840dd52495fSSaurabh Misra } 1841dd52495fSSaurabh Misra 1842dd52495fSSaurabh Misra 1843dd52495fSSaurabh Misra int 1844dd52495fSSaurabh Misra bfe_mac_set_ether_addr(void *arg, const uint8_t *ea) 1845dd52495fSSaurabh Misra { 1846dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 1847dd52495fSSaurabh Misra 1848dd52495fSSaurabh Misra bfe_grab_locks(bfe); 1849dd52495fSSaurabh Misra bcopy(ea, bfe->bfe_ether_addr, ETHERADDRL); 1850dd52495fSSaurabh Misra bfe_set_rx_mode(bfe); 1851dd52495fSSaurabh Misra bfe_release_locks(bfe); 1852dd52495fSSaurabh Misra return (0); 1853dd52495fSSaurabh Misra } 1854dd52495fSSaurabh Misra 1855dd52495fSSaurabh Misra int 1856dd52495fSSaurabh Misra bfe_mac_start(void *arg) 1857dd52495fSSaurabh Misra { 1858dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 1859dd52495fSSaurabh Misra 1860954c6b5eSSaurabh Misra bfe_grab_locks(bfe); 1861954c6b5eSSaurabh Misra if (bfe_chip_start(bfe) == DDI_FAILURE) { 1862954c6b5eSSaurabh Misra bfe_release_locks(bfe); 1863dd52495fSSaurabh Misra return (EINVAL); 1864954c6b5eSSaurabh Misra } 1865954c6b5eSSaurabh Misra 1866954c6b5eSSaurabh Misra bfe_release_locks(bfe); 1867954c6b5eSSaurabh Misra 1868954c6b5eSSaurabh Misra mac_tx_update(bfe->bfe_machdl); 1869dd52495fSSaurabh Misra 1870dd52495fSSaurabh Misra return (0); 1871dd52495fSSaurabh Misra } 1872dd52495fSSaurabh Misra 1873dd52495fSSaurabh Misra void 1874dd52495fSSaurabh Misra bfe_mac_stop(void *arg) 1875dd52495fSSaurabh Misra { 1876dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 1877dd52495fSSaurabh Misra 1878dd52495fSSaurabh Misra /* 1879dd52495fSSaurabh Misra * We need to stop the timer before grabbing locks otherwise 1880dd52495fSSaurabh Misra * we can land-up in deadlock with untimeout. 1881dd52495fSSaurabh Misra */ 1882dd52495fSSaurabh Misra bfe_stop_timer(bfe); 1883dd52495fSSaurabh Misra 1884dd52495fSSaurabh Misra bfe_grab_locks(bfe); 1885dd52495fSSaurabh Misra 1886dd52495fSSaurabh Misra /* 1887dd52495fSSaurabh Misra * First halt the chip by disabling interrupts. 1888dd52495fSSaurabh Misra */ 1889dd52495fSSaurabh Misra bfe_chip_halt(bfe); 1890dd52495fSSaurabh Misra bfe_stop_phy(bfe); 1891dd52495fSSaurabh Misra 1892dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_STOPPED; 1893dd52495fSSaurabh Misra 1894dd52495fSSaurabh Misra /* 1895dd52495fSSaurabh Misra * This will leave the PHY running. 1896dd52495fSSaurabh Misra */ 1897dd52495fSSaurabh Misra bfe_chip_reset(bfe); 1898dd52495fSSaurabh Misra 1899dd52495fSSaurabh Misra /* 1900dd52495fSSaurabh Misra * Disable RX register. 1901dd52495fSSaurabh Misra */ 1902dd52495fSSaurabh Misra bfe->bfe_chip_mode &= ~BFE_RX_MODE_ENABLE; 1903dd52495fSSaurabh Misra bfe_set_rx_mode(bfe); 1904dd52495fSSaurabh Misra 1905dd52495fSSaurabh Misra bfe_release_locks(bfe); 1906dd52495fSSaurabh Misra } 1907dd52495fSSaurabh Misra 1908dd52495fSSaurabh Misra /* 1909dd52495fSSaurabh Misra * Send a packet down the wire. 1910dd52495fSSaurabh Misra */ 1911dd52495fSSaurabh Misra static int 1912dd52495fSSaurabh Misra bfe_send_a_packet(bfe_t *bfe, mblk_t *mp) 1913dd52495fSSaurabh Misra { 1914dd52495fSSaurabh Misra bfe_ring_t *r = &bfe->bfe_tx_ring; 1915dd52495fSSaurabh Misra uint32_t cur = r->r_curr_desc; 1916dd52495fSSaurabh Misra uint32_t next; 1917dd52495fSSaurabh Misra size_t pktlen = msgsize(mp); 1918dd52495fSSaurabh Misra uchar_t *buf; 1919dd52495fSSaurabh Misra uint32_t v; 1920dd52495fSSaurabh Misra 1921dd52495fSSaurabh Misra ASSERT(MUTEX_HELD(&r->r_lock)); 1922dd52495fSSaurabh Misra ASSERT(mp != NULL); 1923dd52495fSSaurabh Misra 1924dd52495fSSaurabh Misra if (pktlen > r->r_buf_len) { 1925dd52495fSSaurabh Misra freemsg(mp); 1926dd52495fSSaurabh Misra return (BFE_SUCCESS); 1927dd52495fSSaurabh Misra } 1928dd52495fSSaurabh Misra 1929dd52495fSSaurabh Misra /* 1930dd52495fSSaurabh Misra * There is a big reason why we don't check for '0'. It becomes easy 1931dd52495fSSaurabh Misra * for us to not roll over the ring since we are based on producer (tx) 1932dd52495fSSaurabh Misra * and consumer (reclaim by an interrupt) model. Especially when we 1933dd52495fSSaurabh Misra * run out of TX descriptor, chip will send a single interrupt and 1934dd52495fSSaurabh Misra * both producer and consumer counter will be same. So we keep a 1935dd52495fSSaurabh Misra * difference of 1 always. 1936dd52495fSSaurabh Misra */ 1937dd52495fSSaurabh Misra if (r->r_avail_desc <= 1) { 1938dd52495fSSaurabh Misra bfe->bfe_stats.noxmtbuf++; 1939dd52495fSSaurabh Misra bfe->bfe_tx_resched = 1; 1940dd52495fSSaurabh Misra return (BFE_FAILURE); 1941dd52495fSSaurabh Misra } 1942dd52495fSSaurabh Misra 1943dd52495fSSaurabh Misra /* 1944dd52495fSSaurabh Misra * Get the DMA buffer to hold packet. 1945dd52495fSSaurabh Misra */ 1946dd52495fSSaurabh Misra buf = (uchar_t *)r->r_buf_dma[cur].addr; 1947dd52495fSSaurabh Misra 1948dd52495fSSaurabh Misra mcopymsg(mp, buf); /* it also frees mp */ 1949dd52495fSSaurabh Misra 1950dd52495fSSaurabh Misra /* 1951dd52495fSSaurabh Misra * Gather statistics. 1952dd52495fSSaurabh Misra */ 1953dd52495fSSaurabh Misra if (buf[0] & 0x1) { 1954dd52495fSSaurabh Misra if (bcmp(buf, bfe_broadcast, ETHERADDRL) != 0) 1955dd52495fSSaurabh Misra bfe->bfe_stats.multixmt++; 1956dd52495fSSaurabh Misra else 1957dd52495fSSaurabh Misra bfe->bfe_stats.brdcstxmt++; 1958dd52495fSSaurabh Misra } 1959dd52495fSSaurabh Misra bfe->bfe_stats.opackets++; 1960dd52495fSSaurabh Misra bfe->bfe_stats.obytes += pktlen; 1961dd52495fSSaurabh Misra 1962dd52495fSSaurabh Misra 1963dd52495fSSaurabh Misra /* 1964dd52495fSSaurabh Misra * Program the DMA descriptor (start and end of frame are same). 1965dd52495fSSaurabh Misra */ 1966dd52495fSSaurabh Misra next = cur; 1967dd52495fSSaurabh Misra v = (pktlen & BFE_DESC_LEN) | BFE_DESC_IOC | BFE_DESC_SOF | 1968dd52495fSSaurabh Misra BFE_DESC_EOF; 1969dd52495fSSaurabh Misra 1970dd52495fSSaurabh Misra if (cur == (TX_NUM_DESC - 1)) 1971dd52495fSSaurabh Misra v |= BFE_DESC_EOT; 1972dd52495fSSaurabh Misra 1973dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[cur].desc_ctl), v); 1974dd52495fSSaurabh Misra 1975dd52495fSSaurabh Misra /* 1976dd52495fSSaurabh Misra * DMA addresses need to be added to BFE_PCI_DMA 1977dd52495fSSaurabh Misra */ 1978dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[cur].desc_addr), 1979dd52495fSSaurabh Misra (r->r_buf_dma[cur].cookie.dmac_laddress + BFE_PCI_DMA)); 1980dd52495fSSaurabh Misra 1981dd52495fSSaurabh Misra /* 1982dd52495fSSaurabh Misra * Sync the packet data for the device. 1983dd52495fSSaurabh Misra */ 1984dd52495fSSaurabh Misra (void) SYNC_BUF(r, cur, 0, pktlen, DDI_DMA_SYNC_FORDEV); 1985dd52495fSSaurabh Misra 1986dd52495fSSaurabh Misra /* Move to next descriptor slot */ 1987dd52495fSSaurabh Misra BFE_INC_SLOT(next, TX_NUM_DESC); 1988dd52495fSSaurabh Misra 1989dd52495fSSaurabh Misra (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV); 1990dd52495fSSaurabh Misra 1991dd52495fSSaurabh Misra r->r_curr_desc = next; 1992dd52495fSSaurabh Misra 1993dd52495fSSaurabh Misra /* 1994dd52495fSSaurabh Misra * The order should be 1,2,3,... for BFE_DMATX_PTR if 0,1,2,3,... 1995dd52495fSSaurabh Misra * descriptor slot are being programmed. 1996dd52495fSSaurabh Misra */ 1997dd52495fSSaurabh Misra OUTL(bfe, BFE_DMATX_PTR, next * sizeof (bfe_desc_t)); 1998dd52495fSSaurabh Misra FLUSH(bfe, BFE_DMATX_PTR); 1999dd52495fSSaurabh Misra 2000dd52495fSSaurabh Misra r->r_avail_desc--; 2001dd52495fSSaurabh Misra 2002dd52495fSSaurabh Misra /* 2003dd52495fSSaurabh Misra * Let timeout know that it must reset the chip if a 2004dd52495fSSaurabh Misra * packet is not sent down the wire for more than 5 seconds. 2005dd52495fSSaurabh Misra */ 2006dd52495fSSaurabh Misra bfe->bfe_tx_stall_time = gethrtime() + (5 * 1000000000ULL); 2007dd52495fSSaurabh Misra 2008dd52495fSSaurabh Misra return (BFE_SUCCESS); 2009dd52495fSSaurabh Misra } 2010dd52495fSSaurabh Misra 2011dd52495fSSaurabh Misra mblk_t * 2012dd52495fSSaurabh Misra bfe_mac_transmit_packet(void *arg, mblk_t *mp) 2013dd52495fSSaurabh Misra { 2014dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 2015dd52495fSSaurabh Misra bfe_ring_t *r = &bfe->bfe_tx_ring; 2016dd52495fSSaurabh Misra mblk_t *nmp; 2017dd52495fSSaurabh Misra 2018dd52495fSSaurabh Misra mutex_enter(&r->r_lock); 2019dd52495fSSaurabh Misra 2020dd52495fSSaurabh Misra if (bfe->bfe_chip_state != BFE_CHIP_ACTIVE) { 2021954c6b5eSSaurabh Misra DTRACE_PROBE1(tx__chip__not__active, int, bfe->bfe_unit); 2022dd52495fSSaurabh Misra 2023dd52495fSSaurabh Misra freemsgchain(mp); 2024dd52495fSSaurabh Misra mutex_exit(&r->r_lock); 2025dd52495fSSaurabh Misra return (NULL); 2026dd52495fSSaurabh Misra } 2027dd52495fSSaurabh Misra 2028dd52495fSSaurabh Misra 2029dd52495fSSaurabh Misra while (mp != NULL) { 2030dd52495fSSaurabh Misra nmp = mp->b_next; 2031dd52495fSSaurabh Misra mp->b_next = NULL; 2032dd52495fSSaurabh Misra 2033dd52495fSSaurabh Misra if (bfe_send_a_packet(bfe, mp) == BFE_FAILURE) { 2034dd52495fSSaurabh Misra mp->b_next = nmp; 2035dd52495fSSaurabh Misra break; 2036dd52495fSSaurabh Misra } 2037dd52495fSSaurabh Misra mp = nmp; 2038dd52495fSSaurabh Misra } 2039dd52495fSSaurabh Misra 2040dd52495fSSaurabh Misra mutex_exit(&r->r_lock); 2041dd52495fSSaurabh Misra 2042dd52495fSSaurabh Misra return (mp); 2043dd52495fSSaurabh Misra } 2044dd52495fSSaurabh Misra 2045dd52495fSSaurabh Misra int 2046dd52495fSSaurabh Misra bfe_mac_set_promisc(void *arg, boolean_t promiscflag) 2047dd52495fSSaurabh Misra { 2048dd52495fSSaurabh Misra bfe_t *bfe = (bfe_t *)arg; 2049dd52495fSSaurabh Misra 2050dd52495fSSaurabh Misra bfe_grab_locks(bfe); 2051dd52495fSSaurabh Misra if (bfe->bfe_chip_state != BFE_CHIP_ACTIVE) { 2052dd52495fSSaurabh Misra bfe_release_locks(bfe); 2053dd52495fSSaurabh Misra return (EIO); 2054dd52495fSSaurabh Misra } 2055dd52495fSSaurabh Misra 2056dd52495fSSaurabh Misra if (promiscflag) { 2057dd52495fSSaurabh Misra /* Set Promiscous on */ 2058dd52495fSSaurabh Misra bfe->bfe_chip_mode |= BFE_RX_MODE_PROMISC; 2059dd52495fSSaurabh Misra } else { 2060dd52495fSSaurabh Misra bfe->bfe_chip_mode &= ~BFE_RX_MODE_PROMISC; 2061dd52495fSSaurabh Misra } 2062dd52495fSSaurabh Misra 2063dd52495fSSaurabh Misra bfe_set_rx_mode(bfe); 2064dd52495fSSaurabh Misra bfe_release_locks(bfe); 2065dd52495fSSaurabh Misra 2066dd52495fSSaurabh Misra return (0); 2067dd52495fSSaurabh Misra } 2068dd52495fSSaurabh Misra 2069dd52495fSSaurabh Misra int 2070dd52495fSSaurabh Misra bfe_mac_set_multicast(void *arg, boolean_t add, const uint8_t *macaddr) 2071dd52495fSSaurabh Misra { 2072dd52495fSSaurabh Misra /* 2073dd52495fSSaurabh Misra * It was too much of pain to implement multicast in CAM. Instead 2074dd52495fSSaurabh Misra * we never disable multicast filter. 2075dd52495fSSaurabh Misra */ 2076dd52495fSSaurabh Misra return (0); 2077dd52495fSSaurabh Misra } 2078dd52495fSSaurabh Misra 2079dd52495fSSaurabh Misra static mac_callbacks_t bfe_mac_callbacks = { 20800dc2366fSVenugopal Iyer MC_SETPROP | MC_GETPROP | MC_PROPINFO, 2081dd52495fSSaurabh Misra bfe_mac_getstat, /* gets stats */ 2082dd52495fSSaurabh Misra bfe_mac_start, /* starts mac */ 2083dd52495fSSaurabh Misra bfe_mac_stop, /* stops mac */ 2084dd52495fSSaurabh Misra bfe_mac_set_promisc, /* sets promisc mode for snoop */ 2085dd52495fSSaurabh Misra bfe_mac_set_multicast, /* multicast implementation */ 2086dd52495fSSaurabh Misra bfe_mac_set_ether_addr, /* sets ethernet address (unicast) */ 2087dd52495fSSaurabh Misra bfe_mac_transmit_packet, /* transmits packet */ 20880dc2366fSVenugopal Iyer NULL, 2089dd52495fSSaurabh Misra NULL, /* ioctl */ 2090dd52495fSSaurabh Misra NULL, /* getcap */ 2091dd52495fSSaurabh Misra NULL, /* open */ 2092dd52495fSSaurabh Misra NULL, /* close */ 2093dd52495fSSaurabh Misra bfe_mac_setprop, 2094dd52495fSSaurabh Misra bfe_mac_getprop, 20950dc2366fSVenugopal Iyer bfe_mac_propinfo 2096dd52495fSSaurabh Misra }; 2097dd52495fSSaurabh Misra 2098dd52495fSSaurabh Misra static void 2099dd52495fSSaurabh Misra bfe_error_handler(bfe_t *bfe, int intr_mask) 2100dd52495fSSaurabh Misra { 2101dd52495fSSaurabh Misra uint32_t v; 2102dd52495fSSaurabh Misra 2103dd52495fSSaurabh Misra if (intr_mask & BFE_ISTAT_RFO) { 2104dd52495fSSaurabh Misra bfe->bfe_stats.overflows++; 2105954c6b5eSSaurabh Misra bfe->bfe_chip_action |= 2106954c6b5eSSaurabh Misra (BFE_ACTION_RESTART | BFE_ACTION_RESTART_FAULT); 2107954c6b5eSSaurabh Misra goto action; 2108dd52495fSSaurabh Misra } 2109dd52495fSSaurabh Misra 2110dd52495fSSaurabh Misra if (intr_mask & BFE_ISTAT_TFU) { 2111dd52495fSSaurabh Misra bfe->bfe_stats.underflows++; 2112dd52495fSSaurabh Misra return; 2113dd52495fSSaurabh Misra } 2114dd52495fSSaurabh Misra 2115dd52495fSSaurabh Misra /* Descriptor Protocol Error */ 2116dd52495fSSaurabh Misra if (intr_mask & BFE_ISTAT_DPE) { 2117dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, 2118dd52495fSSaurabh Misra "Descriptor Protocol Error. Halting Chip"); 2119dd52495fSSaurabh Misra bfe->bfe_chip_action |= 2120dd52495fSSaurabh Misra (BFE_ACTION_RESTART | BFE_ACTION_RESTART_FAULT); 2121dd52495fSSaurabh Misra goto action; 2122dd52495fSSaurabh Misra } 2123dd52495fSSaurabh Misra 2124dd52495fSSaurabh Misra /* Descriptor Error */ 2125*00d1eed8SRichard Lowe if (intr_mask & BFE_ISTAT_DSCE) { 2126dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "Descriptor Error. Restarting Chip"); 2127dd52495fSSaurabh Misra goto action; 2128dd52495fSSaurabh Misra } 2129dd52495fSSaurabh Misra 2130dd52495fSSaurabh Misra /* Receive Descr. Underflow */ 2131dd52495fSSaurabh Misra if (intr_mask & BFE_ISTAT_RDU) { 2132dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, 2133dd52495fSSaurabh Misra "Receive Descriptor Underflow. Restarting Chip"); 2134dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_macrcv_errors++; 2135dd52495fSSaurabh Misra bfe->bfe_chip_action |= 2136dd52495fSSaurabh Misra (BFE_ACTION_RESTART | BFE_ACTION_RESTART_FAULT); 2137dd52495fSSaurabh Misra goto action; 2138dd52495fSSaurabh Misra } 2139dd52495fSSaurabh Misra 2140dd52495fSSaurabh Misra v = INL(bfe, BFE_DMATX_STAT); 2141dd52495fSSaurabh Misra 2142dd52495fSSaurabh Misra /* Error while sending a packet */ 2143dd52495fSSaurabh Misra if (v & BFE_STAT_EMASK) { 2144dd52495fSSaurabh Misra bfe->bfe_stats.ether_stat_macxmt_errors++; 2145dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, 2146dd52495fSSaurabh Misra "Error while sending a packet. Restarting Chip"); 2147dd52495fSSaurabh Misra } 2148dd52495fSSaurabh Misra 2149dd52495fSSaurabh Misra /* Error while receiving a packet */ 2150dd52495fSSaurabh Misra v = INL(bfe, BFE_DMARX_STAT); 2151dd52495fSSaurabh Misra if (v & BFE_RX_FLAG_ERRORS) { 2152dd52495fSSaurabh Misra bfe->bfe_stats.ierrors++; 2153dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, 2154dd52495fSSaurabh Misra "Error while receiving a packet. Restarting Chip"); 2155dd52495fSSaurabh Misra } 2156dd52495fSSaurabh Misra 2157dd52495fSSaurabh Misra 2158dd52495fSSaurabh Misra bfe->bfe_chip_action |= 2159dd52495fSSaurabh Misra (BFE_ACTION_RESTART | BFE_ACTION_RESTART_FAULT); 2160dd52495fSSaurabh Misra 2161dd52495fSSaurabh Misra action: 2162dd52495fSSaurabh Misra bfe_chip_halt(bfe); 2163dd52495fSSaurabh Misra } 2164dd52495fSSaurabh Misra 2165dd52495fSSaurabh Misra /* 2166dd52495fSSaurabh Misra * It will recycle a RX descriptor slot. 2167dd52495fSSaurabh Misra */ 2168dd52495fSSaurabh Misra static void 2169dd52495fSSaurabh Misra bfe_rx_desc_buf_reinit(bfe_t *bfe, uint_t slot) 2170dd52495fSSaurabh Misra { 2171dd52495fSSaurabh Misra bfe_ring_t *r = &bfe->bfe_rx_ring; 2172dd52495fSSaurabh Misra uint32_t v; 2173dd52495fSSaurabh Misra 2174dd52495fSSaurabh Misra slot %= RX_NUM_DESC; 2175dd52495fSSaurabh Misra 2176dd52495fSSaurabh Misra bzero(r->r_buf_dma[slot].addr, sizeof (bfe_rx_header_t)); 2177dd52495fSSaurabh Misra 2178dd52495fSSaurabh Misra (void) SYNC_BUF(r, slot, 0, BFE_RX_OFFSET, DDI_DMA_SYNC_FORDEV); 2179dd52495fSSaurabh Misra 2180dd52495fSSaurabh Misra v = r->r_buf_dma[slot].len & BFE_DESC_LEN; 2181dd52495fSSaurabh Misra if (slot == (RX_NUM_DESC - 1)) 2182dd52495fSSaurabh Misra v |= BFE_DESC_EOT; 2183dd52495fSSaurabh Misra 2184dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[slot].desc_ctl), v); 2185dd52495fSSaurabh Misra 2186dd52495fSSaurabh Misra /* 2187dd52495fSSaurabh Misra * DMA addresses need to be added to BFE_PCI_DMA 2188dd52495fSSaurabh Misra */ 2189dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[slot].desc_addr), 2190dd52495fSSaurabh Misra (r->r_buf_dma[slot].cookie.dmac_laddress + BFE_PCI_DMA)); 2191dd52495fSSaurabh Misra } 2192dd52495fSSaurabh Misra 2193dd52495fSSaurabh Misra /* 2194dd52495fSSaurabh Misra * Gets called from interrupt context to handle RX interrupt. 2195dd52495fSSaurabh Misra */ 2196dd52495fSSaurabh Misra static mblk_t * 2197dd52495fSSaurabh Misra bfe_receive(bfe_t *bfe, int intr_mask) 2198dd52495fSSaurabh Misra { 2199dd52495fSSaurabh Misra int rxstat, current; 2200dd52495fSSaurabh Misra mblk_t *mp = NULL, *rx_head, *rx_tail; 2201dd52495fSSaurabh Misra uchar_t *rx_header; 2202dd52495fSSaurabh Misra uint16_t len; 2203dd52495fSSaurabh Misra uchar_t *bp; 2204dd52495fSSaurabh Misra bfe_ring_t *r = &bfe->bfe_rx_ring; 2205dd52495fSSaurabh Misra int i; 2206dd52495fSSaurabh Misra 2207dd52495fSSaurabh Misra rxstat = INL(bfe, BFE_DMARX_STAT); 2208dd52495fSSaurabh Misra current = (rxstat & BFE_STAT_CDMASK) / sizeof (bfe_desc_t); 2209dd52495fSSaurabh Misra i = r->r_curr_desc; 2210dd52495fSSaurabh Misra 2211dd52495fSSaurabh Misra rx_head = rx_tail = NULL; 2212dd52495fSSaurabh Misra 2213dd52495fSSaurabh Misra DTRACE_PROBE3(receive, int, bfe->bfe_unit, 2214dd52495fSSaurabh Misra int, r->r_curr_desc, 2215dd52495fSSaurabh Misra int, current); 2216dd52495fSSaurabh Misra 2217dd52495fSSaurabh Misra for (i = r->r_curr_desc; i != current; 2218dd52495fSSaurabh Misra BFE_INC_SLOT(i, RX_NUM_DESC)) { 2219dd52495fSSaurabh Misra 2220dd52495fSSaurabh Misra /* 2221dd52495fSSaurabh Misra * Sync the buffer associated with the descriptor table entry. 2222dd52495fSSaurabh Misra */ 2223dd52495fSSaurabh Misra (void) SYNC_BUF(r, i, 0, r->r_buf_dma[i].len, 2224dd52495fSSaurabh Misra DDI_DMA_SYNC_FORKERNEL); 2225dd52495fSSaurabh Misra 2226dd52495fSSaurabh Misra rx_header = (void *)r->r_buf_dma[i].addr; 2227dd52495fSSaurabh Misra 2228dd52495fSSaurabh Misra /* 2229dd52495fSSaurabh Misra * We do this to make sure we are endian neutral. Chip is 2230dd52495fSSaurabh Misra * big endian. 2231dd52495fSSaurabh Misra * 2232dd52495fSSaurabh Misra * The header looks like :- 2233dd52495fSSaurabh Misra * 2234dd52495fSSaurabh Misra * Offset 0 -> uint16_t len 2235dd52495fSSaurabh Misra * Offset 2 -> uint16_t flags 2236dd52495fSSaurabh Misra * Offset 4 -> uint16_t pad[12] 2237dd52495fSSaurabh Misra */ 2238dd52495fSSaurabh Misra len = (rx_header[1] << 8) | rx_header[0]; 2239dd52495fSSaurabh Misra len -= 4; /* CRC bytes need to be removed */ 2240dd52495fSSaurabh Misra 2241dd52495fSSaurabh Misra /* 2242dd52495fSSaurabh Misra * Don't receive this packet if pkt length is greater than 2243dd52495fSSaurabh Misra * MTU + VLAN_TAGSZ. 2244dd52495fSSaurabh Misra */ 2245dd52495fSSaurabh Misra if (len > r->r_buf_len) { 2246dd52495fSSaurabh Misra /* Recycle slot for later use */ 2247dd52495fSSaurabh Misra bfe_rx_desc_buf_reinit(bfe, i); 2248dd52495fSSaurabh Misra continue; 2249dd52495fSSaurabh Misra } 2250dd52495fSSaurabh Misra 2251dd52495fSSaurabh Misra if ((mp = allocb(len + VLAN_TAGSZ, BPRI_MED)) != NULL) { 2252dd52495fSSaurabh Misra mp->b_rptr += VLAN_TAGSZ; 2253dd52495fSSaurabh Misra bp = mp->b_rptr; 2254dd52495fSSaurabh Misra mp->b_wptr = bp + len; 2255dd52495fSSaurabh Misra 2256dd52495fSSaurabh Misra /* sizeof (bfe_rx_header_t) + 2 */ 2257dd52495fSSaurabh Misra bcopy(r->r_buf_dma[i].addr + 2258dd52495fSSaurabh Misra BFE_RX_OFFSET, bp, len); 2259dd52495fSSaurabh Misra 2260dd52495fSSaurabh Misra mp->b_next = NULL; 2261dd52495fSSaurabh Misra if (rx_tail == NULL) 2262dd52495fSSaurabh Misra rx_head = rx_tail = mp; 2263dd52495fSSaurabh Misra else { 2264dd52495fSSaurabh Misra rx_tail->b_next = mp; 2265dd52495fSSaurabh Misra rx_tail = mp; 2266dd52495fSSaurabh Misra } 2267dd52495fSSaurabh Misra 2268dd52495fSSaurabh Misra /* Number of packets received so far */ 2269dd52495fSSaurabh Misra bfe->bfe_stats.ipackets++; 2270dd52495fSSaurabh Misra 2271dd52495fSSaurabh Misra /* Total bytes of packets received so far */ 2272dd52495fSSaurabh Misra bfe->bfe_stats.rbytes += len; 2273dd52495fSSaurabh Misra 2274dd52495fSSaurabh Misra if (bcmp(mp->b_rptr, bfe_broadcast, ETHERADDRL) == 0) 2275dd52495fSSaurabh Misra bfe->bfe_stats.brdcstrcv++; 2276dd52495fSSaurabh Misra else 2277dd52495fSSaurabh Misra bfe->bfe_stats.multircv++; 2278dd52495fSSaurabh Misra } else { 2279dd52495fSSaurabh Misra bfe->bfe_stats.norcvbuf++; 2280dd52495fSSaurabh Misra /* Recycle the slot for later use */ 2281dd52495fSSaurabh Misra bfe_rx_desc_buf_reinit(bfe, i); 2282dd52495fSSaurabh Misra break; 2283dd52495fSSaurabh Misra } 2284dd52495fSSaurabh Misra 2285dd52495fSSaurabh Misra /* 2286dd52495fSSaurabh Misra * Reinitialize the current descriptor slot's buffer so that 2287dd52495fSSaurabh Misra * it can be reused. 2288dd52495fSSaurabh Misra */ 2289dd52495fSSaurabh Misra bfe_rx_desc_buf_reinit(bfe, i); 2290dd52495fSSaurabh Misra } 2291dd52495fSSaurabh Misra 2292dd52495fSSaurabh Misra r->r_curr_desc = i; 2293dd52495fSSaurabh Misra 2294dd52495fSSaurabh Misra (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV); 2295dd52495fSSaurabh Misra 2296dd52495fSSaurabh Misra return (rx_head); 2297dd52495fSSaurabh Misra } 2298dd52495fSSaurabh Misra 2299dd52495fSSaurabh Misra static int 2300dd52495fSSaurabh Misra bfe_tx_reclaim(bfe_ring_t *r) 2301dd52495fSSaurabh Misra { 2302dd52495fSSaurabh Misra uint32_t cur, start; 2303dd52495fSSaurabh Misra uint32_t v; 2304dd52495fSSaurabh Misra 2305dd52495fSSaurabh Misra cur = INL(r->r_bfe, BFE_DMATX_STAT) & BFE_STAT_CDMASK; 2306dd52495fSSaurabh Misra cur = cur / sizeof (bfe_desc_t); 2307dd52495fSSaurabh Misra 2308dd52495fSSaurabh Misra /* 2309dd52495fSSaurabh Misra * Start with the last descriptor consumed by the chip. 2310dd52495fSSaurabh Misra */ 2311dd52495fSSaurabh Misra start = r->r_cons_desc; 2312dd52495fSSaurabh Misra 2313dd52495fSSaurabh Misra DTRACE_PROBE3(tx__reclaim, int, r->r_bfe->bfe_unit, 2314dd52495fSSaurabh Misra int, start, 2315dd52495fSSaurabh Misra int, cur); 2316dd52495fSSaurabh Misra 2317dd52495fSSaurabh Misra /* 2318dd52495fSSaurabh Misra * There will be at least one descriptor to process. 2319dd52495fSSaurabh Misra */ 2320dd52495fSSaurabh Misra while (start != cur) { 2321dd52495fSSaurabh Misra r->r_avail_desc++; 2322dd52495fSSaurabh Misra v = r->r_buf_dma[start].len & BFE_DESC_LEN; 2323dd52495fSSaurabh Misra if (start == (TX_NUM_DESC - 1)) 2324dd52495fSSaurabh Misra v |= BFE_DESC_EOT; 2325dd52495fSSaurabh Misra 2326dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[start].desc_ctl), v); 2327dd52495fSSaurabh Misra PUT_DESC(r, (uint32_t *)&(r->r_desc[start].desc_addr), 2328dd52495fSSaurabh Misra (r->r_buf_dma[start].cookie.dmac_laddress + BFE_PCI_DMA)); 2329dd52495fSSaurabh Misra 2330dd52495fSSaurabh Misra /* Move to next descriptor in TX ring */ 2331dd52495fSSaurabh Misra BFE_INC_SLOT(start, TX_NUM_DESC); 2332dd52495fSSaurabh Misra } 2333dd52495fSSaurabh Misra 2334dd52495fSSaurabh Misra (void) ddi_dma_sync(r->r_desc_dma_handle, 2335dd52495fSSaurabh Misra 0, (r->r_ndesc * sizeof (bfe_desc_t)), 2336dd52495fSSaurabh Misra DDI_DMA_SYNC_FORDEV); 2337dd52495fSSaurabh Misra 2338dd52495fSSaurabh Misra r->r_cons_desc = start; /* consumed pointer */ 2339dd52495fSSaurabh Misra r->r_bfe->bfe_tx_stall_time = 0; 2340dd52495fSSaurabh Misra 2341dd52495fSSaurabh Misra return (cur); 2342dd52495fSSaurabh Misra } 2343dd52495fSSaurabh Misra 2344dd52495fSSaurabh Misra static int 2345dd52495fSSaurabh Misra bfe_tx_done(bfe_t *bfe, int intr_mask) 2346dd52495fSSaurabh Misra { 2347dd52495fSSaurabh Misra bfe_ring_t *r = &bfe->bfe_tx_ring; 2348dd52495fSSaurabh Misra int resched = 0; 2349dd52495fSSaurabh Misra 2350dd52495fSSaurabh Misra mutex_enter(&r->r_lock); 2351dd52495fSSaurabh Misra (void) bfe_tx_reclaim(r); 2352dd52495fSSaurabh Misra 2353dd52495fSSaurabh Misra if (bfe->bfe_tx_resched) { 2354dd52495fSSaurabh Misra resched = 1; 2355dd52495fSSaurabh Misra bfe->bfe_tx_resched = 0; 2356dd52495fSSaurabh Misra } 2357dd52495fSSaurabh Misra mutex_exit(&r->r_lock); 2358dd52495fSSaurabh Misra 2359dd52495fSSaurabh Misra return (resched); 2360dd52495fSSaurabh Misra } 2361dd52495fSSaurabh Misra 2362dd52495fSSaurabh Misra /* 2363dd52495fSSaurabh Misra * ISR for interrupt handling 2364dd52495fSSaurabh Misra */ 2365dd52495fSSaurabh Misra static uint_t 2366dd52495fSSaurabh Misra bfe_interrupt(caddr_t arg1, caddr_t arg2) 2367dd52495fSSaurabh Misra { 2368dd52495fSSaurabh Misra bfe_t *bfe = (void *)arg1; 2369dd52495fSSaurabh Misra uint32_t intr_stat; 2370dd52495fSSaurabh Misra mblk_t *rx_head = NULL; 2371dd52495fSSaurabh Misra int resched = 0; 2372dd52495fSSaurabh Misra 2373dd52495fSSaurabh Misra /* 2374dd52495fSSaurabh Misra * Grab the lock to avoid stopping the chip while this interrupt 2375dd52495fSSaurabh Misra * is handled. 2376dd52495fSSaurabh Misra */ 2377dd52495fSSaurabh Misra rw_enter(&bfe->bfe_rwlock, RW_READER); 2378dd52495fSSaurabh Misra 2379dd52495fSSaurabh Misra /* 2380dd52495fSSaurabh Misra * It's necessary to read intr stat again because masking interrupt 2381dd52495fSSaurabh Misra * register does not really mask interrupts coming from the chip. 2382dd52495fSSaurabh Misra */ 2383dd52495fSSaurabh Misra intr_stat = INL(bfe, BFE_INTR_STAT); 2384dd52495fSSaurabh Misra intr_stat &= BFE_IMASK_DEF; 2385dd52495fSSaurabh Misra OUTL(bfe, BFE_INTR_STAT, intr_stat); 2386dd52495fSSaurabh Misra (void) INL(bfe, BFE_INTR_STAT); 2387dd52495fSSaurabh Misra 2388dd52495fSSaurabh Misra if (intr_stat == 0) { 2389dd52495fSSaurabh Misra rw_exit(&bfe->bfe_rwlock); 2390dd52495fSSaurabh Misra return (DDI_INTR_UNCLAIMED); 2391dd52495fSSaurabh Misra } 2392dd52495fSSaurabh Misra 2393954c6b5eSSaurabh Misra DTRACE_PROBE2(bfe__interrupt, int, bfe->bfe_unit, 2394954c6b5eSSaurabh Misra int, intr_stat); 2395954c6b5eSSaurabh Misra 2396dd52495fSSaurabh Misra if (bfe->bfe_chip_state != BFE_CHIP_ACTIVE) { 2397dd52495fSSaurabh Misra /* 2398dd52495fSSaurabh Misra * If chip is suspended then we just return. 2399dd52495fSSaurabh Misra */ 2400dd52495fSSaurabh Misra if (bfe->bfe_chip_state == BFE_CHIP_SUSPENDED) { 2401dd52495fSSaurabh Misra rw_exit(&bfe->bfe_rwlock); 2402dd52495fSSaurabh Misra DTRACE_PROBE1(interrupt__chip__is__suspend, int, 2403dd52495fSSaurabh Misra bfe->bfe_unit); 2404dd52495fSSaurabh Misra return (DDI_INTR_CLAIMED); 2405dd52495fSSaurabh Misra } 2406dd52495fSSaurabh Misra 2407dd52495fSSaurabh Misra /* 2408dd52495fSSaurabh Misra * Halt the chip again i.e basically disable interrupts. 2409dd52495fSSaurabh Misra */ 2410dd52495fSSaurabh Misra bfe_chip_halt(bfe); 2411dd52495fSSaurabh Misra rw_exit(&bfe->bfe_rwlock); 2412dd52495fSSaurabh Misra DTRACE_PROBE1(interrupt__chip__not__active, int, 2413dd52495fSSaurabh Misra bfe->bfe_unit); 2414dd52495fSSaurabh Misra return (DDI_INTR_CLAIMED); 2415dd52495fSSaurabh Misra } 2416dd52495fSSaurabh Misra 2417dd52495fSSaurabh Misra /* A packet was received */ 2418dd52495fSSaurabh Misra if (intr_stat & BFE_ISTAT_RX) { 2419dd52495fSSaurabh Misra rx_head = bfe_receive(bfe, intr_stat); 2420dd52495fSSaurabh Misra } 2421dd52495fSSaurabh Misra 2422dd52495fSSaurabh Misra /* A packet was sent down the wire */ 2423dd52495fSSaurabh Misra if (intr_stat & BFE_ISTAT_TX) { 2424dd52495fSSaurabh Misra resched = bfe_tx_done(bfe, intr_stat); 2425dd52495fSSaurabh Misra } 2426dd52495fSSaurabh Misra 2427dd52495fSSaurabh Misra /* There was an error */ 2428dd52495fSSaurabh Misra if (intr_stat & BFE_ISTAT_ERRORS) { 2429dd52495fSSaurabh Misra bfe_error_handler(bfe, intr_stat); 2430dd52495fSSaurabh Misra } 2431dd52495fSSaurabh Misra 2432dd52495fSSaurabh Misra rw_exit(&bfe->bfe_rwlock); 2433dd52495fSSaurabh Misra 2434dd52495fSSaurabh Misra /* 2435dd52495fSSaurabh Misra * Pass the list of packets received from chip to MAC layer. 2436dd52495fSSaurabh Misra */ 2437dd52495fSSaurabh Misra if (rx_head) { 2438dd52495fSSaurabh Misra mac_rx(bfe->bfe_machdl, 0, rx_head); 2439dd52495fSSaurabh Misra } 2440dd52495fSSaurabh Misra 2441dd52495fSSaurabh Misra /* 2442dd52495fSSaurabh Misra * Let the MAC start sending pkts to a potential stopped stream. 2443dd52495fSSaurabh Misra */ 2444dd52495fSSaurabh Misra if (resched) 2445dd52495fSSaurabh Misra mac_tx_update(bfe->bfe_machdl); 2446dd52495fSSaurabh Misra 2447dd52495fSSaurabh Misra return (DDI_INTR_CLAIMED); 2448dd52495fSSaurabh Misra } 2449dd52495fSSaurabh Misra 2450dd52495fSSaurabh Misra /* 2451dd52495fSSaurabh Misra * Removes registered interrupt handler. 2452dd52495fSSaurabh Misra */ 2453dd52495fSSaurabh Misra static void 2454dd52495fSSaurabh Misra bfe_remove_intr(bfe_t *bfe) 2455dd52495fSSaurabh Misra { 2456dd52495fSSaurabh Misra (void) ddi_intr_remove_handler(bfe->bfe_intrhdl); 2457dd52495fSSaurabh Misra (void) ddi_intr_free(bfe->bfe_intrhdl); 2458dd52495fSSaurabh Misra } 2459dd52495fSSaurabh Misra 2460dd52495fSSaurabh Misra /* 2461dd52495fSSaurabh Misra * Add an interrupt for the driver. 2462dd52495fSSaurabh Misra */ 2463dd52495fSSaurabh Misra static int 2464dd52495fSSaurabh Misra bfe_add_intr(bfe_t *bfe) 2465dd52495fSSaurabh Misra { 2466dd52495fSSaurabh Misra int nintrs = 1; 2467dd52495fSSaurabh Misra int ret; 2468dd52495fSSaurabh Misra 2469dd52495fSSaurabh Misra ret = ddi_intr_alloc(bfe->bfe_dip, &bfe->bfe_intrhdl, 2470dd52495fSSaurabh Misra DDI_INTR_TYPE_FIXED, /* type */ 2471dd52495fSSaurabh Misra 0, /* inumber */ 2472dd52495fSSaurabh Misra 1, /* count */ 2473dd52495fSSaurabh Misra &nintrs, /* actual nintrs */ 2474dd52495fSSaurabh Misra DDI_INTR_ALLOC_STRICT); 2475dd52495fSSaurabh Misra 2476dd52495fSSaurabh Misra if (ret != DDI_SUCCESS) { 2477dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "ddi_intr_alloc() failed" 2478dd52495fSSaurabh Misra " : ret : %d", ret); 2479dd52495fSSaurabh Misra return (DDI_FAILURE); 2480dd52495fSSaurabh Misra } 2481dd52495fSSaurabh Misra 2482dd52495fSSaurabh Misra ret = ddi_intr_add_handler(bfe->bfe_intrhdl, bfe_interrupt, bfe, NULL); 2483dd52495fSSaurabh Misra if (ret != DDI_SUCCESS) { 2484dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "ddi_intr_add_handler() failed"); 2485dd52495fSSaurabh Misra (void) ddi_intr_free(bfe->bfe_intrhdl); 2486dd52495fSSaurabh Misra return (DDI_FAILURE); 2487dd52495fSSaurabh Misra } 2488dd52495fSSaurabh Misra 2489dd52495fSSaurabh Misra ret = ddi_intr_get_pri(bfe->bfe_intrhdl, &bfe->bfe_intrpri); 2490dd52495fSSaurabh Misra if (ret != DDI_SUCCESS) { 2491dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "ddi_intr_get_pri() failed"); 2492dd52495fSSaurabh Misra bfe_remove_intr(bfe); 2493dd52495fSSaurabh Misra return (DDI_FAILURE); 2494dd52495fSSaurabh Misra } 2495dd52495fSSaurabh Misra 2496dd52495fSSaurabh Misra return (DDI_SUCCESS); 2497dd52495fSSaurabh Misra } 2498dd52495fSSaurabh Misra 2499dd52495fSSaurabh Misra 2500dd52495fSSaurabh Misra /* 2501dd52495fSSaurabh Misra * Identify chipset family. 2502dd52495fSSaurabh Misra */ 2503dd52495fSSaurabh Misra static int 2504dd52495fSSaurabh Misra bfe_identify_hardware(bfe_t *bfe) 2505dd52495fSSaurabh Misra { 2506dd52495fSSaurabh Misra uint16_t vid, did; 2507dd52495fSSaurabh Misra int i; 2508dd52495fSSaurabh Misra 2509dd52495fSSaurabh Misra vid = pci_config_get16(bfe->bfe_conf_handle, PCI_CONF_VENID); 2510dd52495fSSaurabh Misra did = pci_config_get16(bfe->bfe_conf_handle, PCI_CONF_DEVID); 2511dd52495fSSaurabh Misra 2512dd52495fSSaurabh Misra for (i = 0; i < (sizeof (bfe_cards) / sizeof (bfe_cards_t)); i++) { 2513dd52495fSSaurabh Misra if (bfe_cards[i].vendor_id == vid && 2514dd52495fSSaurabh Misra bfe_cards[i].device_id == did) { 2515dd52495fSSaurabh Misra return (BFE_SUCCESS); 2516dd52495fSSaurabh Misra } 2517dd52495fSSaurabh Misra } 2518dd52495fSSaurabh Misra 2519dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "bfe driver is attaching to unknown pci%d,%d" 2520dd52495fSSaurabh Misra " vendor/device-id card", vid, did); 2521dd52495fSSaurabh Misra 2522dd52495fSSaurabh Misra return (BFE_SUCCESS); 2523dd52495fSSaurabh Misra } 2524dd52495fSSaurabh Misra 2525dd52495fSSaurabh Misra /* 2526dd52495fSSaurabh Misra * Maps device registers. 2527dd52495fSSaurabh Misra */ 2528dd52495fSSaurabh Misra static int 2529dd52495fSSaurabh Misra bfe_regs_map(bfe_t *bfe) 2530dd52495fSSaurabh Misra { 2531dd52495fSSaurabh Misra dev_info_t *dip = bfe->bfe_dip; 2532dd52495fSSaurabh Misra int ret; 2533dd52495fSSaurabh Misra 2534dd52495fSSaurabh Misra ret = ddi_regs_map_setup(dip, 1, &bfe->bfe_mem_regset.addr, 0, 0, 2535dd52495fSSaurabh Misra &bfe_dev_attr, &bfe->bfe_mem_regset.hdl); 2536dd52495fSSaurabh Misra 2537dd52495fSSaurabh Misra if (ret != DDI_SUCCESS) { 2538dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "ddi_regs_map_setup failed"); 2539dd52495fSSaurabh Misra return (DDI_FAILURE); 2540dd52495fSSaurabh Misra } 2541dd52495fSSaurabh Misra 2542dd52495fSSaurabh Misra return (DDI_SUCCESS); 2543dd52495fSSaurabh Misra } 2544dd52495fSSaurabh Misra 2545dd52495fSSaurabh Misra static void 2546dd52495fSSaurabh Misra bfe_unmap_regs(bfe_t *bfe) 2547dd52495fSSaurabh Misra { 2548dd52495fSSaurabh Misra ddi_regs_map_free(&bfe->bfe_mem_regset.hdl); 2549dd52495fSSaurabh Misra } 2550dd52495fSSaurabh Misra 2551dd52495fSSaurabh Misra static int 2552dd52495fSSaurabh Misra bfe_get_chip_config(bfe_t *bfe) 2553dd52495fSSaurabh Misra { 2554dd52495fSSaurabh Misra uint32_t prom[BFE_EEPROM_SIZE]; 2555dd52495fSSaurabh Misra int i; 2556dd52495fSSaurabh Misra 2557dd52495fSSaurabh Misra /* 2558dd52495fSSaurabh Misra * Read EEPROM in prom[] 2559dd52495fSSaurabh Misra */ 2560dd52495fSSaurabh Misra for (i = 0; i < BFE_EEPROM_SIZE; i++) { 2561dd52495fSSaurabh Misra prom[i] = INL(bfe, BFE_EEPROM_BASE + i * sizeof (uint32_t)); 2562dd52495fSSaurabh Misra } 2563dd52495fSSaurabh Misra 2564dd52495fSSaurabh Misra bfe->bfe_dev_addr[0] = bfe->bfe_ether_addr[0] = 2565dd52495fSSaurabh Misra INB(bfe, BFE_EEPROM_BASE + 79); 2566dd52495fSSaurabh Misra 2567dd52495fSSaurabh Misra bfe->bfe_dev_addr[1] = bfe->bfe_ether_addr[1] = 2568dd52495fSSaurabh Misra INB(bfe, BFE_EEPROM_BASE + 78); 2569dd52495fSSaurabh Misra 2570dd52495fSSaurabh Misra bfe->bfe_dev_addr[2] = bfe->bfe_ether_addr[2] = 2571dd52495fSSaurabh Misra INB(bfe, BFE_EEPROM_BASE + 81); 2572dd52495fSSaurabh Misra 2573dd52495fSSaurabh Misra bfe->bfe_dev_addr[3] = bfe->bfe_ether_addr[3] = 2574dd52495fSSaurabh Misra INB(bfe, BFE_EEPROM_BASE + 80); 2575dd52495fSSaurabh Misra 2576dd52495fSSaurabh Misra bfe->bfe_dev_addr[4] = bfe->bfe_ether_addr[4] = 2577dd52495fSSaurabh Misra INB(bfe, BFE_EEPROM_BASE + 83); 2578dd52495fSSaurabh Misra 2579dd52495fSSaurabh Misra bfe->bfe_dev_addr[5] = bfe->bfe_ether_addr[5] = 2580dd52495fSSaurabh Misra INB(bfe, BFE_EEPROM_BASE + 82); 2581dd52495fSSaurabh Misra 2582dd52495fSSaurabh Misra bfe->bfe_phy_addr = -1; 2583dd52495fSSaurabh Misra 2584dd52495fSSaurabh Misra return (DDI_SUCCESS); 2585dd52495fSSaurabh Misra } 2586dd52495fSSaurabh Misra 2587dd52495fSSaurabh Misra /* 2588dd52495fSSaurabh Misra * Ring Management routines 2589dd52495fSSaurabh Misra */ 2590dd52495fSSaurabh Misra static int 2591dd52495fSSaurabh Misra bfe_ring_buf_alloc(bfe_t *bfe, bfe_ring_t *r, int slot, int d) 2592dd52495fSSaurabh Misra { 2593dd52495fSSaurabh Misra int err; 2594dd52495fSSaurabh Misra uint_t count = 0; 2595dd52495fSSaurabh Misra 2596dd52495fSSaurabh Misra err = ddi_dma_alloc_handle(bfe->bfe_dip, 2597dd52495fSSaurabh Misra &bfe_dma_attr_buf, DDI_DMA_SLEEP, NULL, 2598dd52495fSSaurabh Misra &r->r_buf_dma[slot].handle); 2599dd52495fSSaurabh Misra 2600dd52495fSSaurabh Misra if (err != DDI_SUCCESS) { 2601dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, " bfe_ring_buf_alloc() :" 2602dd52495fSSaurabh Misra " alloc_handle failed"); 2603dd52495fSSaurabh Misra goto fail0; 2604dd52495fSSaurabh Misra } 2605dd52495fSSaurabh Misra 2606dd52495fSSaurabh Misra err = ddi_dma_mem_alloc(r->r_buf_dma[slot].handle, 2607dd52495fSSaurabh Misra r->r_buf_len, &bfe_buf_attr, DDI_DMA_STREAMING, 2608dd52495fSSaurabh Misra DDI_DMA_SLEEP, NULL, &r->r_buf_dma[slot].addr, 2609dd52495fSSaurabh Misra &r->r_buf_dma[slot].len, 2610dd52495fSSaurabh Misra &r->r_buf_dma[slot].acchdl); 2611dd52495fSSaurabh Misra 2612dd52495fSSaurabh Misra if (err != DDI_SUCCESS) { 2613dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, " bfe_ring_buf_alloc() :" 2614dd52495fSSaurabh Misra " mem_alloc failed :%d", err); 2615dd52495fSSaurabh Misra goto fail1; 2616dd52495fSSaurabh Misra } 2617dd52495fSSaurabh Misra 2618dd52495fSSaurabh Misra err = ddi_dma_addr_bind_handle(r->r_buf_dma[slot].handle, 2619dd52495fSSaurabh Misra NULL, r->r_buf_dma[slot].addr, 2620dd52495fSSaurabh Misra r->r_buf_dma[slot].len, 2621dd52495fSSaurabh Misra (DDI_DMA_RDWR | DDI_DMA_STREAMING), 2622dd52495fSSaurabh Misra DDI_DMA_SLEEP, NULL, 2623dd52495fSSaurabh Misra &r->r_buf_dma[slot].cookie, 2624dd52495fSSaurabh Misra &count); 2625dd52495fSSaurabh Misra 2626dd52495fSSaurabh Misra if (err != DDI_DMA_MAPPED) { 2627dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, " bfe_ring_buf_alloc() :" 2628dd52495fSSaurabh Misra " bind_handle failed"); 2629dd52495fSSaurabh Misra goto fail2; 2630dd52495fSSaurabh Misra } 2631dd52495fSSaurabh Misra 2632dd52495fSSaurabh Misra if (count > 1) { 2633dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, " bfe_ring_buf_alloc() :" 2634dd52495fSSaurabh Misra " more than one DMA cookie"); 2635dd52495fSSaurabh Misra (void) ddi_dma_unbind_handle(r->r_buf_dma[slot].handle); 2636dd52495fSSaurabh Misra goto fail2; 2637dd52495fSSaurabh Misra } 2638dd52495fSSaurabh Misra 2639dd52495fSSaurabh Misra return (DDI_SUCCESS); 2640dd52495fSSaurabh Misra fail2: 2641dd52495fSSaurabh Misra ddi_dma_mem_free(&r->r_buf_dma[slot].acchdl); 2642dd52495fSSaurabh Misra fail1: 2643dd52495fSSaurabh Misra ddi_dma_free_handle(&r->r_buf_dma[slot].handle); 2644dd52495fSSaurabh Misra fail0: 2645dd52495fSSaurabh Misra return (DDI_FAILURE); 2646dd52495fSSaurabh Misra } 2647dd52495fSSaurabh Misra 2648dd52495fSSaurabh Misra static void 2649dd52495fSSaurabh Misra bfe_ring_buf_free(bfe_ring_t *r, int slot) 2650dd52495fSSaurabh Misra { 2651dd52495fSSaurabh Misra if (r->r_buf_dma == NULL) 2652dd52495fSSaurabh Misra return; 2653dd52495fSSaurabh Misra 2654dd52495fSSaurabh Misra (void) ddi_dma_unbind_handle(r->r_buf_dma[slot].handle); 2655dd52495fSSaurabh Misra ddi_dma_mem_free(&r->r_buf_dma[slot].acchdl); 2656dd52495fSSaurabh Misra ddi_dma_free_handle(&r->r_buf_dma[slot].handle); 2657dd52495fSSaurabh Misra } 2658dd52495fSSaurabh Misra 2659dd52495fSSaurabh Misra static void 2660dd52495fSSaurabh Misra bfe_buffer_free(bfe_ring_t *r) 2661dd52495fSSaurabh Misra { 2662dd52495fSSaurabh Misra int i; 2663dd52495fSSaurabh Misra 2664dd52495fSSaurabh Misra for (i = 0; i < r->r_ndesc; i++) { 2665dd52495fSSaurabh Misra bfe_ring_buf_free(r, i); 2666dd52495fSSaurabh Misra } 2667dd52495fSSaurabh Misra } 2668dd52495fSSaurabh Misra 2669dd52495fSSaurabh Misra static void 2670dd52495fSSaurabh Misra bfe_ring_desc_free(bfe_ring_t *r) 2671dd52495fSSaurabh Misra { 2672dd52495fSSaurabh Misra (void) ddi_dma_unbind_handle(r->r_desc_dma_handle); 2673dd52495fSSaurabh Misra ddi_dma_mem_free(&r->r_desc_acc_handle); 2674dd52495fSSaurabh Misra ddi_dma_free_handle(&r->r_desc_dma_handle); 2675dd52495fSSaurabh Misra kmem_free(r->r_buf_dma, r->r_ndesc * sizeof (bfe_dma_t)); 2676dd52495fSSaurabh Misra 2677dd52495fSSaurabh Misra r->r_buf_dma = NULL; 2678dd52495fSSaurabh Misra r->r_desc = NULL; 2679dd52495fSSaurabh Misra } 2680dd52495fSSaurabh Misra 2681dd52495fSSaurabh Misra 2682dd52495fSSaurabh Misra static int 2683dd52495fSSaurabh Misra bfe_ring_desc_alloc(bfe_t *bfe, bfe_ring_t *r, int d) 2684dd52495fSSaurabh Misra { 2685dd52495fSSaurabh Misra int err, i, fail = 0; 2686dd52495fSSaurabh Misra caddr_t ring; 2687dd52495fSSaurabh Misra size_t size_krnl = 0, size_dma = 0, ring_len = 0; 2688dd52495fSSaurabh Misra ddi_dma_cookie_t cookie; 2689dd52495fSSaurabh Misra uint_t count = 0; 2690dd52495fSSaurabh Misra 2691dd52495fSSaurabh Misra ASSERT(bfe != NULL); 2692dd52495fSSaurabh Misra 2693dd52495fSSaurabh Misra size_krnl = r->r_ndesc * sizeof (bfe_dma_t); 2694dd52495fSSaurabh Misra size_dma = r->r_ndesc * sizeof (bfe_desc_t); 2695dd52495fSSaurabh Misra r->r_buf_dma = kmem_zalloc(size_krnl, KM_SLEEP); 2696dd52495fSSaurabh Misra 2697dd52495fSSaurabh Misra 2698dd52495fSSaurabh Misra err = ddi_dma_alloc_handle(bfe->bfe_dip, &bfe_dma_attr_desc, 2699dd52495fSSaurabh Misra DDI_DMA_SLEEP, NULL, &r->r_desc_dma_handle); 2700dd52495fSSaurabh Misra 2701dd52495fSSaurabh Misra if (err != DDI_SUCCESS) { 2702dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "bfe_ring_desc_alloc() failed on" 2703dd52495fSSaurabh Misra " ddi_dma_alloc_handle()"); 2704dd52495fSSaurabh Misra kmem_free(r->r_buf_dma, size_krnl); 2705dd52495fSSaurabh Misra return (DDI_FAILURE); 2706dd52495fSSaurabh Misra } 2707dd52495fSSaurabh Misra 2708dd52495fSSaurabh Misra 2709dd52495fSSaurabh Misra err = ddi_dma_mem_alloc(r->r_desc_dma_handle, 2710dd52495fSSaurabh Misra size_dma, &bfe_buf_attr, 2711dd52495fSSaurabh Misra DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, 2712dd52495fSSaurabh Misra &ring, &ring_len, &r->r_desc_acc_handle); 2713dd52495fSSaurabh Misra 2714dd52495fSSaurabh Misra if (err != DDI_SUCCESS) { 2715dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "bfe_ring_desc_alloc() failed on" 2716dd52495fSSaurabh Misra " ddi_dma_mem_alloc()"); 2717dd52495fSSaurabh Misra ddi_dma_free_handle(&r->r_desc_dma_handle); 2718dd52495fSSaurabh Misra kmem_free(r->r_buf_dma, size_krnl); 2719dd52495fSSaurabh Misra return (DDI_FAILURE); 2720dd52495fSSaurabh Misra } 2721dd52495fSSaurabh Misra 2722dd52495fSSaurabh Misra err = ddi_dma_addr_bind_handle(r->r_desc_dma_handle, 2723dd52495fSSaurabh Misra NULL, ring, ring_len, 2724dd52495fSSaurabh Misra DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 2725dd52495fSSaurabh Misra DDI_DMA_SLEEP, NULL, 2726dd52495fSSaurabh Misra &cookie, &count); 2727dd52495fSSaurabh Misra 2728dd52495fSSaurabh Misra if (err != DDI_SUCCESS) { 2729dd52495fSSaurabh Misra bfe_error(bfe->bfe_dip, "bfe_ring_desc_alloc() failed on" 2730dd52495fSSaurabh Misra " ddi_dma_addr_bind_handle()"); 2731dd52495fSSaurabh Misra ddi_dma_mem_free(&r->r_desc_acc_handle); 2732dd52495fSSaurabh Misra ddi_dma_free_handle(&r->r_desc_dma_handle); 2733dd52495fSSaurabh Misra kmem_free(r->r_buf_dma, size_krnl); 2734dd52495fSSaurabh Misra return (DDI_FAILURE); 2735dd52495fSSaurabh Misra } 2736dd52495fSSaurabh Misra 2737dd52495fSSaurabh Misra /* 2738dd52495fSSaurabh Misra * We don't want to have multiple cookies. Descriptor should be 2739dd52495fSSaurabh Misra * aligned to PAGESIZE boundary. 2740dd52495fSSaurabh Misra */ 2741dd52495fSSaurabh Misra ASSERT(count == 1); 2742dd52495fSSaurabh Misra 2743dd52495fSSaurabh Misra /* The actual descriptor for the ring */ 2744dd52495fSSaurabh Misra r->r_desc_len = ring_len; 2745dd52495fSSaurabh Misra r->r_desc_cookie = cookie; 2746dd52495fSSaurabh Misra 2747dd52495fSSaurabh Misra r->r_desc = (void *)ring; 2748dd52495fSSaurabh Misra 2749dd52495fSSaurabh Misra bzero(r->r_desc, size_dma); 2750dd52495fSSaurabh Misra bzero(r->r_desc, ring_len); 2751dd52495fSSaurabh Misra 2752dd52495fSSaurabh Misra /* For each descriptor, allocate a DMA buffer */ 2753dd52495fSSaurabh Misra fail = 0; 2754dd52495fSSaurabh Misra for (i = 0; i < r->r_ndesc; i++) { 2755dd52495fSSaurabh Misra if (bfe_ring_buf_alloc(bfe, r, i, d) != DDI_SUCCESS) { 2756dd52495fSSaurabh Misra i--; 2757dd52495fSSaurabh Misra fail = 1; 2758dd52495fSSaurabh Misra break; 2759dd52495fSSaurabh Misra } 2760dd52495fSSaurabh Misra } 2761dd52495fSSaurabh Misra 2762dd52495fSSaurabh Misra if (fail) { 2763dd52495fSSaurabh Misra while (i-- >= 0) { 2764dd52495fSSaurabh Misra bfe_ring_buf_free(r, i); 2765dd52495fSSaurabh Misra } 2766dd52495fSSaurabh Misra 2767dd52495fSSaurabh Misra /* We don't need the descriptor anymore */ 2768dd52495fSSaurabh Misra bfe_ring_desc_free(r); 2769dd52495fSSaurabh Misra return (DDI_FAILURE); 2770dd52495fSSaurabh Misra } 2771dd52495fSSaurabh Misra 2772dd52495fSSaurabh Misra return (DDI_SUCCESS); 2773dd52495fSSaurabh Misra } 2774dd52495fSSaurabh Misra 2775dd52495fSSaurabh Misra static int 2776dd52495fSSaurabh Misra bfe_rings_alloc(bfe_t *bfe) 2777dd52495fSSaurabh Misra { 2778dd52495fSSaurabh Misra /* TX */ 2779dd52495fSSaurabh Misra mutex_init(&bfe->bfe_tx_ring.r_lock, NULL, MUTEX_DRIVER, NULL); 2780dd52495fSSaurabh Misra bfe->bfe_tx_ring.r_lockp = &bfe->bfe_tx_ring.r_lock; 2781dd52495fSSaurabh Misra bfe->bfe_tx_ring.r_buf_len = BFE_MTU + sizeof (struct ether_header) + 2782dd52495fSSaurabh Misra VLAN_TAGSZ + ETHERFCSL; 2783dd52495fSSaurabh Misra bfe->bfe_tx_ring.r_ndesc = TX_NUM_DESC; 2784dd52495fSSaurabh Misra bfe->bfe_tx_ring.r_bfe = bfe; 2785dd52495fSSaurabh Misra bfe->bfe_tx_ring.r_avail_desc = TX_NUM_DESC; 2786dd52495fSSaurabh Misra 2787dd52495fSSaurabh Misra /* RX */ 2788dd52495fSSaurabh Misra mutex_init(&bfe->bfe_rx_ring.r_lock, NULL, MUTEX_DRIVER, NULL); 2789dd52495fSSaurabh Misra bfe->bfe_rx_ring.r_lockp = &bfe->bfe_rx_ring.r_lock; 2790dd52495fSSaurabh Misra bfe->bfe_rx_ring.r_buf_len = BFE_MTU + sizeof (struct ether_header) + 2791dd52495fSSaurabh Misra VLAN_TAGSZ + ETHERFCSL + RX_HEAD_ROOM; 2792dd52495fSSaurabh Misra bfe->bfe_rx_ring.r_ndesc = RX_NUM_DESC; 2793dd52495fSSaurabh Misra bfe->bfe_rx_ring.r_bfe = bfe; 2794dd52495fSSaurabh Misra bfe->bfe_rx_ring.r_avail_desc = RX_NUM_DESC; 2795dd52495fSSaurabh Misra 2796dd52495fSSaurabh Misra /* Allocate TX Ring */ 2797dd52495fSSaurabh Misra if (bfe_ring_desc_alloc(bfe, &bfe->bfe_tx_ring, 2798dd52495fSSaurabh Misra DDI_DMA_WRITE) != DDI_SUCCESS) 2799dd52495fSSaurabh Misra return (DDI_FAILURE); 2800dd52495fSSaurabh Misra 2801dd52495fSSaurabh Misra /* Allocate RX Ring */ 2802dd52495fSSaurabh Misra if (bfe_ring_desc_alloc(bfe, &bfe->bfe_rx_ring, 2803dd52495fSSaurabh Misra DDI_DMA_READ) != DDI_SUCCESS) { 2804dd52495fSSaurabh Misra cmn_err(CE_NOTE, "RX ring allocation failed"); 2805dd52495fSSaurabh Misra bfe_ring_desc_free(&bfe->bfe_tx_ring); 2806dd52495fSSaurabh Misra return (DDI_FAILURE); 2807dd52495fSSaurabh Misra } 2808dd52495fSSaurabh Misra 2809dd52495fSSaurabh Misra bfe->bfe_tx_ring.r_flags = BFE_RING_ALLOCATED; 2810dd52495fSSaurabh Misra bfe->bfe_rx_ring.r_flags = BFE_RING_ALLOCATED; 2811dd52495fSSaurabh Misra 2812dd52495fSSaurabh Misra return (DDI_SUCCESS); 2813dd52495fSSaurabh Misra } 2814dd52495fSSaurabh Misra 2815dd52495fSSaurabh Misra static int 2816dd52495fSSaurabh Misra bfe_resume(dev_info_t *dip) 2817dd52495fSSaurabh Misra { 2818dd52495fSSaurabh Misra bfe_t *bfe; 2819dd52495fSSaurabh Misra int err = DDI_SUCCESS; 2820dd52495fSSaurabh Misra 2821dd52495fSSaurabh Misra if ((bfe = ddi_get_driver_private(dip)) == NULL) { 2822dd52495fSSaurabh Misra bfe_error(dip, "Unexpected error (no driver private data)" 2823dd52495fSSaurabh Misra " while resume"); 2824dd52495fSSaurabh Misra return (DDI_FAILURE); 2825dd52495fSSaurabh Misra } 2826dd52495fSSaurabh Misra 2827dd52495fSSaurabh Misra /* 2828dd52495fSSaurabh Misra * Grab all the locks first. 2829dd52495fSSaurabh Misra */ 2830dd52495fSSaurabh Misra bfe_grab_locks(bfe); 2831dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_RESUME; 2832dd52495fSSaurabh Misra 2833dd52495fSSaurabh Misra bfe_init_vars(bfe); 2834dd52495fSSaurabh Misra /* PHY will also start running */ 2835dd52495fSSaurabh Misra bfe_chip_reset(bfe); 2836dd52495fSSaurabh Misra if (bfe_chip_start(bfe) == DDI_FAILURE) { 2837dd52495fSSaurabh Misra bfe_error(dip, "Could not resume chip"); 2838dd52495fSSaurabh Misra err = DDI_FAILURE; 2839dd52495fSSaurabh Misra } 2840954c6b5eSSaurabh Misra 2841dd52495fSSaurabh Misra bfe_release_locks(bfe); 2842954c6b5eSSaurabh Misra 2843954c6b5eSSaurabh Misra if (err == DDI_SUCCESS) 2844954c6b5eSSaurabh Misra mac_tx_update(bfe->bfe_machdl); 2845954c6b5eSSaurabh Misra 2846dd52495fSSaurabh Misra return (err); 2847dd52495fSSaurabh Misra } 2848dd52495fSSaurabh Misra 2849dd52495fSSaurabh Misra static int 2850dd52495fSSaurabh Misra bfe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2851dd52495fSSaurabh Misra { 2852dd52495fSSaurabh Misra int unit; 2853dd52495fSSaurabh Misra bfe_t *bfe; 2854dd52495fSSaurabh Misra mac_register_t *macreg; 2855dd52495fSSaurabh Misra int ret; 2856dd52495fSSaurabh Misra 2857dd52495fSSaurabh Misra switch (cmd) { 2858dd52495fSSaurabh Misra case DDI_RESUME: 2859dd52495fSSaurabh Misra return (bfe_resume(dip)); 2860dd52495fSSaurabh Misra 2861dd52495fSSaurabh Misra case DDI_ATTACH: 2862dd52495fSSaurabh Misra break; 2863dd52495fSSaurabh Misra 2864dd52495fSSaurabh Misra default: 2865dd52495fSSaurabh Misra return (DDI_FAILURE); 2866dd52495fSSaurabh Misra } 2867dd52495fSSaurabh Misra 2868dd52495fSSaurabh Misra 2869dd52495fSSaurabh Misra unit = ddi_get_instance(dip); 2870dd52495fSSaurabh Misra 2871dd52495fSSaurabh Misra bfe = kmem_zalloc(sizeof (bfe_t), KM_SLEEP); 2872dd52495fSSaurabh Misra bfe->bfe_dip = dip; 2873dd52495fSSaurabh Misra bfe->bfe_unit = unit; 2874dd52495fSSaurabh Misra 2875dd52495fSSaurabh Misra if (pci_config_setup(dip, &bfe->bfe_conf_handle) != DDI_SUCCESS) { 2876dd52495fSSaurabh Misra bfe_error(dip, "pci_config_setup failed"); 2877dd52495fSSaurabh Misra goto fail0; 2878dd52495fSSaurabh Misra } 2879dd52495fSSaurabh Misra 2880dd52495fSSaurabh Misra /* 2881dd52495fSSaurabh Misra * Enable IO space, Bus Master and Memory Space accessess. 2882dd52495fSSaurabh Misra */ 2883dd52495fSSaurabh Misra ret = pci_config_get16(bfe->bfe_conf_handle, PCI_CONF_COMM); 2884dd52495fSSaurabh Misra pci_config_put16(bfe->bfe_conf_handle, PCI_CONF_COMM, 2885dd52495fSSaurabh Misra PCI_COMM_IO | PCI_COMM_MAE | PCI_COMM_ME | ret); 2886dd52495fSSaurabh Misra 2887dd52495fSSaurabh Misra ddi_set_driver_private(dip, bfe); 2888dd52495fSSaurabh Misra 2889dd52495fSSaurabh Misra /* Identify hardware */ 2890dd52495fSSaurabh Misra if (bfe_identify_hardware(bfe) == BFE_FAILURE) { 2891dd52495fSSaurabh Misra bfe_error(dip, "Could not identify device"); 2892dd52495fSSaurabh Misra goto fail1; 2893dd52495fSSaurabh Misra } 2894dd52495fSSaurabh Misra 2895dd52495fSSaurabh Misra if (bfe_regs_map(bfe) != DDI_SUCCESS) { 2896dd52495fSSaurabh Misra bfe_error(dip, "Could not map device registers"); 2897dd52495fSSaurabh Misra goto fail1; 2898dd52495fSSaurabh Misra } 2899dd52495fSSaurabh Misra 2900dd52495fSSaurabh Misra (void) bfe_get_chip_config(bfe); 2901dd52495fSSaurabh Misra 2902dd52495fSSaurabh Misra /* 2903dd52495fSSaurabh Misra * Register with MAC layer 2904dd52495fSSaurabh Misra */ 2905dd52495fSSaurabh Misra if ((macreg = mac_alloc(MAC_VERSION)) == NULL) { 2906dd52495fSSaurabh Misra bfe_error(dip, "mac_alloc() failed"); 2907dd52495fSSaurabh Misra goto fail2; 2908dd52495fSSaurabh Misra } 2909dd52495fSSaurabh Misra 2910dd52495fSSaurabh Misra macreg->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 2911dd52495fSSaurabh Misra macreg->m_driver = bfe; 2912dd52495fSSaurabh Misra macreg->m_dip = dip; 2913dd52495fSSaurabh Misra macreg->m_instance = unit; 2914dd52495fSSaurabh Misra macreg->m_src_addr = bfe->bfe_ether_addr; 2915dd52495fSSaurabh Misra macreg->m_callbacks = &bfe_mac_callbacks; 2916dd52495fSSaurabh Misra macreg->m_min_sdu = 0; 2917dd52495fSSaurabh Misra macreg->m_max_sdu = ETHERMTU; 2918dd52495fSSaurabh Misra macreg->m_margin = VLAN_TAGSZ; 2919dd52495fSSaurabh Misra 2920dd52495fSSaurabh Misra if ((ret = mac_register(macreg, &bfe->bfe_machdl)) != 0) { 2921dd52495fSSaurabh Misra bfe_error(dip, "mac_register() failed with %d error", ret); 2922dd52495fSSaurabh Misra mac_free(macreg); 2923dd52495fSSaurabh Misra goto fail2; 2924dd52495fSSaurabh Misra } 2925dd52495fSSaurabh Misra 2926dd52495fSSaurabh Misra mac_free(macreg); 2927dd52495fSSaurabh Misra 2928dd52495fSSaurabh Misra rw_init(&bfe->bfe_rwlock, NULL, RW_DRIVER, 2929dd52495fSSaurabh Misra DDI_INTR_PRI(bfe->bfe_intrpri)); 2930dd52495fSSaurabh Misra 2931dd52495fSSaurabh Misra if (bfe_add_intr(bfe) != DDI_SUCCESS) { 2932dd52495fSSaurabh Misra bfe_error(dip, "Could not add interrupt"); 2933dd52495fSSaurabh Misra goto fail3; 2934dd52495fSSaurabh Misra } 2935dd52495fSSaurabh Misra 2936dd52495fSSaurabh Misra if (bfe_rings_alloc(bfe) != DDI_SUCCESS) { 2937dd52495fSSaurabh Misra bfe_error(dip, "Could not allocate TX/RX Ring"); 2938dd52495fSSaurabh Misra goto fail4; 2939dd52495fSSaurabh Misra } 2940dd52495fSSaurabh Misra 2941dd52495fSSaurabh Misra /* Init and then reset the chip */ 2942dd52495fSSaurabh Misra bfe->bfe_chip_action = 0; 2943dd52495fSSaurabh Misra bfe_init_vars(bfe); 2944dd52495fSSaurabh Misra 2945dd52495fSSaurabh Misra /* PHY will also start running */ 2946dd52495fSSaurabh Misra bfe_chip_reset(bfe); 2947dd52495fSSaurabh Misra 2948dd52495fSSaurabh Misra /* 2949dd52495fSSaurabh Misra * Even though we enable the interrupts here but chip's interrupt 2950dd52495fSSaurabh Misra * is not enabled yet. It will be enabled once we plumb the interface. 2951dd52495fSSaurabh Misra */ 2952dd52495fSSaurabh Misra if (ddi_intr_enable(bfe->bfe_intrhdl) != DDI_SUCCESS) { 2953dd52495fSSaurabh Misra bfe_error(dip, "Could not enable interrupt"); 2954dd52495fSSaurabh Misra goto fail4; 2955dd52495fSSaurabh Misra } 2956dd52495fSSaurabh Misra 2957dd52495fSSaurabh Misra return (DDI_SUCCESS); 2958dd52495fSSaurabh Misra 2959dd52495fSSaurabh Misra fail4: 2960dd52495fSSaurabh Misra bfe_remove_intr(bfe); 2961dd52495fSSaurabh Misra fail3: 2962c1374a13SSurya Prakki (void) mac_unregister(bfe->bfe_machdl); 2963dd52495fSSaurabh Misra fail2: 2964dd52495fSSaurabh Misra bfe_unmap_regs(bfe); 2965dd52495fSSaurabh Misra fail1: 2966dd52495fSSaurabh Misra pci_config_teardown(&bfe->bfe_conf_handle); 2967dd52495fSSaurabh Misra fail0: 2968dd52495fSSaurabh Misra kmem_free(bfe, sizeof (bfe_t)); 2969dd52495fSSaurabh Misra return (DDI_FAILURE); 2970dd52495fSSaurabh Misra } 2971dd52495fSSaurabh Misra 2972dd52495fSSaurabh Misra static int 2973dd52495fSSaurabh Misra bfe_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 2974dd52495fSSaurabh Misra { 2975dd52495fSSaurabh Misra bfe_t *bfe; 2976dd52495fSSaurabh Misra 2977dd52495fSSaurabh Misra bfe = ddi_get_driver_private(devinfo); 2978dd52495fSSaurabh Misra 2979dd52495fSSaurabh Misra switch (cmd) { 2980dd52495fSSaurabh Misra case DDI_DETACH: 2981dd52495fSSaurabh Misra /* 2982dd52495fSSaurabh Misra * We need to stop the timer before grabbing locks otherwise 2983dd52495fSSaurabh Misra * we can land-up in deadlock with untimeout. 2984dd52495fSSaurabh Misra */ 2985dd52495fSSaurabh Misra bfe_stop_timer(bfe); 2986dd52495fSSaurabh Misra 2987dd52495fSSaurabh Misra /* 2988dd52495fSSaurabh Misra * First unregister with MAC layer before stopping DMA 2989dd52495fSSaurabh Misra * engine. 2990dd52495fSSaurabh Misra */ 2991dd52495fSSaurabh Misra if (mac_unregister(bfe->bfe_machdl) != DDI_SUCCESS) 2992dd52495fSSaurabh Misra return (DDI_FAILURE); 2993dd52495fSSaurabh Misra 2994dd52495fSSaurabh Misra bfe->bfe_machdl = NULL; 2995dd52495fSSaurabh Misra 2996dd52495fSSaurabh Misra /* 2997dd52495fSSaurabh Misra * Quiesce the chip first. 2998dd52495fSSaurabh Misra */ 2999dd52495fSSaurabh Misra bfe_grab_locks(bfe); 3000dd52495fSSaurabh Misra bfe_chip_halt(bfe); 3001dd52495fSSaurabh Misra bfe_stop_phy(bfe); 3002dd52495fSSaurabh Misra bfe_release_locks(bfe); 3003dd52495fSSaurabh Misra 3004dd52495fSSaurabh Misra (void) ddi_intr_disable(bfe->bfe_intrhdl); 3005dd52495fSSaurabh Misra 3006dd52495fSSaurabh Misra /* Make sure timer is gone. */ 3007dd52495fSSaurabh Misra bfe_stop_timer(bfe); 3008dd52495fSSaurabh Misra 3009dd52495fSSaurabh Misra /* 3010dd52495fSSaurabh Misra * Free the DMA resources for buffer and then descriptors 3011dd52495fSSaurabh Misra */ 3012dd52495fSSaurabh Misra if (bfe->bfe_tx_ring.r_flags == BFE_RING_ALLOCATED) { 3013dd52495fSSaurabh Misra /* TX */ 3014dd52495fSSaurabh Misra bfe_buffer_free(&bfe->bfe_tx_ring); 3015dd52495fSSaurabh Misra bfe_ring_desc_free(&bfe->bfe_tx_ring); 3016dd52495fSSaurabh Misra } 3017dd52495fSSaurabh Misra 3018dd52495fSSaurabh Misra if (bfe->bfe_rx_ring.r_flags == BFE_RING_ALLOCATED) { 3019dd52495fSSaurabh Misra /* RX */ 3020dd52495fSSaurabh Misra bfe_buffer_free(&bfe->bfe_rx_ring); 3021dd52495fSSaurabh Misra bfe_ring_desc_free(&bfe->bfe_rx_ring); 3022dd52495fSSaurabh Misra } 3023dd52495fSSaurabh Misra 3024dd52495fSSaurabh Misra bfe_remove_intr(bfe); 3025dd52495fSSaurabh Misra bfe_unmap_regs(bfe); 3026dd52495fSSaurabh Misra pci_config_teardown(&bfe->bfe_conf_handle); 3027dd52495fSSaurabh Misra 3028dd52495fSSaurabh Misra mutex_destroy(&bfe->bfe_tx_ring.r_lock); 3029dd52495fSSaurabh Misra mutex_destroy(&bfe->bfe_rx_ring.r_lock); 3030dd52495fSSaurabh Misra rw_destroy(&bfe->bfe_rwlock); 3031dd52495fSSaurabh Misra 3032dd52495fSSaurabh Misra kmem_free(bfe, sizeof (bfe_t)); 3033dd52495fSSaurabh Misra 3034dd52495fSSaurabh Misra ddi_set_driver_private(devinfo, NULL); 3035dd52495fSSaurabh Misra return (DDI_SUCCESS); 3036dd52495fSSaurabh Misra 3037dd52495fSSaurabh Misra case DDI_SUSPEND: 3038dd52495fSSaurabh Misra /* 3039dd52495fSSaurabh Misra * We need to stop the timer before grabbing locks otherwise 3040dd52495fSSaurabh Misra * we can land-up in deadlock with untimeout. 3041dd52495fSSaurabh Misra */ 3042dd52495fSSaurabh Misra bfe_stop_timer(bfe); 3043dd52495fSSaurabh Misra 3044dd52495fSSaurabh Misra /* 3045dd52495fSSaurabh Misra * Grab all the locks first. 3046dd52495fSSaurabh Misra */ 3047dd52495fSSaurabh Misra bfe_grab_locks(bfe); 3048dd52495fSSaurabh Misra bfe_chip_halt(bfe); 3049dd52495fSSaurabh Misra bfe_stop_phy(bfe); 3050dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_SUSPENDED; 3051dd52495fSSaurabh Misra bfe_release_locks(bfe); 3052dd52495fSSaurabh Misra 3053dd52495fSSaurabh Misra return (DDI_SUCCESS); 3054dd52495fSSaurabh Misra 3055dd52495fSSaurabh Misra default: 3056dd52495fSSaurabh Misra return (DDI_FAILURE); 3057dd52495fSSaurabh Misra } 3058dd52495fSSaurabh Misra } 3059dd52495fSSaurabh Misra 3060dd52495fSSaurabh Misra /* 3061dd52495fSSaurabh Misra * Quiesce the card for fast reboot 3062dd52495fSSaurabh Misra */ 3063dd52495fSSaurabh Misra int 3064dd52495fSSaurabh Misra bfe_quiesce(dev_info_t *dev_info) 3065dd52495fSSaurabh Misra { 3066dd52495fSSaurabh Misra bfe_t *bfe; 3067dd52495fSSaurabh Misra 3068dd52495fSSaurabh Misra bfe = ddi_get_driver_private(dev_info); 3069dd52495fSSaurabh Misra 3070dd52495fSSaurabh Misra bfe_chip_halt(bfe); 3071dd52495fSSaurabh Misra bfe_stop_phy(bfe); 3072dd52495fSSaurabh Misra bfe->bfe_chip_state = BFE_CHIP_QUIESCED; 3073dd52495fSSaurabh Misra 3074dd52495fSSaurabh Misra return (DDI_SUCCESS); 3075dd52495fSSaurabh Misra } 3076dd52495fSSaurabh Misra 3077dd52495fSSaurabh Misra static struct cb_ops bfe_cb_ops = { 3078dd52495fSSaurabh Misra nulldev, /* cb_open */ 3079dd52495fSSaurabh Misra nulldev, /* cb_close */ 3080dd52495fSSaurabh Misra nodev, /* cb_strategy */ 3081dd52495fSSaurabh Misra nodev, /* cb_print */ 3082dd52495fSSaurabh Misra nodev, /* cb_dump */ 3083dd52495fSSaurabh Misra nodev, /* cb_read */ 3084dd52495fSSaurabh Misra nodev, /* cb_write */ 3085dd52495fSSaurabh Misra nodev, /* cb_ioctl */ 3086dd52495fSSaurabh Misra nodev, /* cb_devmap */ 3087dd52495fSSaurabh Misra nodev, /* cb_mmap */ 3088dd52495fSSaurabh Misra nodev, /* cb_segmap */ 3089dd52495fSSaurabh Misra nochpoll, /* cb_chpoll */ 3090dd52495fSSaurabh Misra ddi_prop_op, /* cb_prop_op */ 3091dd52495fSSaurabh Misra NULL, /* cb_stream */ 3092dd52495fSSaurabh Misra D_MP | D_HOTPLUG, /* cb_flag */ 3093dd52495fSSaurabh Misra CB_REV, /* cb_rev */ 3094dd52495fSSaurabh Misra nodev, /* cb_aread */ 3095dd52495fSSaurabh Misra nodev /* cb_awrite */ 3096dd52495fSSaurabh Misra }; 3097dd52495fSSaurabh Misra 3098dd52495fSSaurabh Misra static struct dev_ops bfe_dev_ops = { 3099dd52495fSSaurabh Misra DEVO_REV, /* devo_rev */ 3100dd52495fSSaurabh Misra 0, /* devo_refcnt */ 3101dd52495fSSaurabh Misra NULL, /* devo_getinfo */ 3102dd52495fSSaurabh Misra nulldev, /* devo_identify */ 3103dd52495fSSaurabh Misra nulldev, /* devo_probe */ 3104dd52495fSSaurabh Misra bfe_attach, /* devo_attach */ 3105dd52495fSSaurabh Misra bfe_detach, /* devo_detach */ 3106dd52495fSSaurabh Misra nodev, /* devo_reset */ 3107dd52495fSSaurabh Misra &bfe_cb_ops, /* devo_cb_ops */ 3108dd52495fSSaurabh Misra NULL, /* devo_bus_ops */ 3109dd52495fSSaurabh Misra ddi_power, /* devo_power */ 3110dd52495fSSaurabh Misra bfe_quiesce /* devo_quiesce */ 3111dd52495fSSaurabh Misra }; 3112dd52495fSSaurabh Misra 3113dd52495fSSaurabh Misra static struct modldrv bfe_modldrv = { 3114dd52495fSSaurabh Misra &mod_driverops, 3115dd52495fSSaurabh Misra bfe_ident, 3116dd52495fSSaurabh Misra &bfe_dev_ops 3117dd52495fSSaurabh Misra }; 3118dd52495fSSaurabh Misra 3119dd52495fSSaurabh Misra static struct modlinkage modlinkage = { 3120dd52495fSSaurabh Misra MODREV_1, (void *)&bfe_modldrv, NULL 3121dd52495fSSaurabh Misra }; 3122dd52495fSSaurabh Misra 3123dd52495fSSaurabh Misra int 3124dd52495fSSaurabh Misra _info(struct modinfo *modinfop) 3125dd52495fSSaurabh Misra { 3126dd52495fSSaurabh Misra return (mod_info(&modlinkage, modinfop)); 3127dd52495fSSaurabh Misra } 3128dd52495fSSaurabh Misra 3129dd52495fSSaurabh Misra int 3130dd52495fSSaurabh Misra _init(void) 3131dd52495fSSaurabh Misra { 3132dd52495fSSaurabh Misra int status; 3133dd52495fSSaurabh Misra 3134dd52495fSSaurabh Misra mac_init_ops(&bfe_dev_ops, MODULE_NAME); 3135dd52495fSSaurabh Misra status = mod_install(&modlinkage); 3136dd52495fSSaurabh Misra if (status == DDI_FAILURE) 3137dd52495fSSaurabh Misra mac_fini_ops(&bfe_dev_ops); 3138dd52495fSSaurabh Misra return (status); 3139dd52495fSSaurabh Misra } 3140dd52495fSSaurabh Misra 3141dd52495fSSaurabh Misra int 3142dd52495fSSaurabh Misra _fini(void) 3143dd52495fSSaurabh Misra { 3144dd52495fSSaurabh Misra int status; 3145dd52495fSSaurabh Misra 3146dd52495fSSaurabh Misra status = mod_remove(&modlinkage); 3147dd52495fSSaurabh Misra if (status == 0) { 3148dd52495fSSaurabh Misra mac_fini_ops(&bfe_dev_ops); 3149dd52495fSSaurabh Misra } 3150dd52495fSSaurabh Misra return (status); 3151dd52495fSSaurabh Misra } 3152