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