19865SSaurabh.Mishra@Sun.COM /*
29865SSaurabh.Mishra@Sun.COM * CDDL HEADER START
39865SSaurabh.Mishra@Sun.COM *
49865SSaurabh.Mishra@Sun.COM * The contents of this file are subject to the terms of the
59865SSaurabh.Mishra@Sun.COM * Common Development and Distribution License (the "License").
69865SSaurabh.Mishra@Sun.COM * You may not use this file except in compliance with the License.
79865SSaurabh.Mishra@Sun.COM *
89865SSaurabh.Mishra@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99865SSaurabh.Mishra@Sun.COM * or http://www.opensolaris.org/os/licensing.
109865SSaurabh.Mishra@Sun.COM * See the License for the specific language governing permissions
119865SSaurabh.Mishra@Sun.COM * and limitations under the License.
129865SSaurabh.Mishra@Sun.COM *
139865SSaurabh.Mishra@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149865SSaurabh.Mishra@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159865SSaurabh.Mishra@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169865SSaurabh.Mishra@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179865SSaurabh.Mishra@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189865SSaurabh.Mishra@Sun.COM *
199865SSaurabh.Mishra@Sun.COM * CDDL HEADER END
209865SSaurabh.Mishra@Sun.COM */
219865SSaurabh.Mishra@Sun.COM
229865SSaurabh.Mishra@Sun.COM /*
23*12917SCrisson.Hu@Sun.COM * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
249865SSaurabh.Mishra@Sun.COM */
259865SSaurabh.Mishra@Sun.COM #include <sys/stream.h>
269865SSaurabh.Mishra@Sun.COM #include <sys/strsun.h>
279865SSaurabh.Mishra@Sun.COM #include <sys/stat.h>
289865SSaurabh.Mishra@Sun.COM #include <sys/pci.h>
299865SSaurabh.Mishra@Sun.COM #include <sys/modctl.h>
309865SSaurabh.Mishra@Sun.COM #include <sys/kstat.h>
319865SSaurabh.Mishra@Sun.COM #include <sys/ethernet.h>
329865SSaurabh.Mishra@Sun.COM #include <sys/devops.h>
339865SSaurabh.Mishra@Sun.COM #include <sys/debug.h>
349865SSaurabh.Mishra@Sun.COM #include <sys/conf.h>
359865SSaurabh.Mishra@Sun.COM #include <sys/sysmacros.h>
369865SSaurabh.Mishra@Sun.COM #include <sys/dditypes.h>
379865SSaurabh.Mishra@Sun.COM #include <sys/ddi.h>
389865SSaurabh.Mishra@Sun.COM #include <sys/sunddi.h>
399865SSaurabh.Mishra@Sun.COM #include <sys/miiregs.h>
409865SSaurabh.Mishra@Sun.COM #include <sys/byteorder.h>
419865SSaurabh.Mishra@Sun.COM #include <sys/cyclic.h>
429865SSaurabh.Mishra@Sun.COM #include <sys/note.h>
439865SSaurabh.Mishra@Sun.COM #include <sys/crc32.h>
449865SSaurabh.Mishra@Sun.COM #include <sys/mac_provider.h>
459865SSaurabh.Mishra@Sun.COM #include <sys/mac_ether.h>
469865SSaurabh.Mishra@Sun.COM #include <sys/vlan.h>
479865SSaurabh.Mishra@Sun.COM #include <sys/errno.h>
489865SSaurabh.Mishra@Sun.COM #include <sys/sdt.h>
499865SSaurabh.Mishra@Sun.COM #include <sys/strsubr.h>
509865SSaurabh.Mishra@Sun.COM
519865SSaurabh.Mishra@Sun.COM #include "bfe.h"
529865SSaurabh.Mishra@Sun.COM #include "bfe_hw.h"
539865SSaurabh.Mishra@Sun.COM
549865SSaurabh.Mishra@Sun.COM
559865SSaurabh.Mishra@Sun.COM /*
569865SSaurabh.Mishra@Sun.COM * Broadcom BCM4401 chipsets use two rings :
579865SSaurabh.Mishra@Sun.COM *
589865SSaurabh.Mishra@Sun.COM * - One TX : For sending packets down the wire.
599865SSaurabh.Mishra@Sun.COM * - One RX : For receving packets.
609865SSaurabh.Mishra@Sun.COM *
619865SSaurabh.Mishra@Sun.COM * Each ring can have any number of descriptors (configured during attach).
629865SSaurabh.Mishra@Sun.COM * As of now we configure only 128 descriptor per ring (TX/RX). Each descriptor
639865SSaurabh.Mishra@Sun.COM * has address (desc_addr) and control (desc_ctl) which holds a DMA buffer for
649865SSaurabh.Mishra@Sun.COM * the packet and control information (like start/end of frame or end of table).
659865SSaurabh.Mishra@Sun.COM * The descriptor table is allocated first and then a DMA buffer (for a packet)
669865SSaurabh.Mishra@Sun.COM * is allocated and linked to each descriptor.
679865SSaurabh.Mishra@Sun.COM *
689865SSaurabh.Mishra@Sun.COM * Each descriptor entry is bfe_desc_t structure in bfe. During TX/RX
699865SSaurabh.Mishra@Sun.COM * interrupt, the stat register will point to current descriptor being
709865SSaurabh.Mishra@Sun.COM * processed.
719865SSaurabh.Mishra@Sun.COM *
729865SSaurabh.Mishra@Sun.COM * Here's an example of TX and RX ring :
739865SSaurabh.Mishra@Sun.COM *
749865SSaurabh.Mishra@Sun.COM * TX:
759865SSaurabh.Mishra@Sun.COM *
769865SSaurabh.Mishra@Sun.COM * Base of the descriptor table is programmed using BFE_DMATX_CTRL control
779865SSaurabh.Mishra@Sun.COM * register. Each 'addr' points to DMA buffer (or packet data buffer) to
789865SSaurabh.Mishra@Sun.COM * be transmitted and 'ctl' has the length of the packet (usually MTU).
799865SSaurabh.Mishra@Sun.COM *
809865SSaurabh.Mishra@Sun.COM * ----------------------|
819865SSaurabh.Mishra@Sun.COM * | addr |Descriptor 0 |
829865SSaurabh.Mishra@Sun.COM * | ctl | |
839865SSaurabh.Mishra@Sun.COM * ----------------------|
849865SSaurabh.Mishra@Sun.COM * | addr |Descriptor 1 | SOF (start of the frame)
859865SSaurabh.Mishra@Sun.COM * | ctl | |
869865SSaurabh.Mishra@Sun.COM * ----------------------|
879865SSaurabh.Mishra@Sun.COM * | ... |Descriptor... | EOF (end of the frame)
889865SSaurabh.Mishra@Sun.COM * | ... | |
899865SSaurabh.Mishra@Sun.COM * ----------------------|
909865SSaurabh.Mishra@Sun.COM * | addr |Descritor 127 |
919865SSaurabh.Mishra@Sun.COM * | ctl | EOT | EOT (End of Table)
929865SSaurabh.Mishra@Sun.COM * ----------------------|
939865SSaurabh.Mishra@Sun.COM *
949865SSaurabh.Mishra@Sun.COM * 'r_curr_desc' : pointer to current descriptor which can be used to transmit
959865SSaurabh.Mishra@Sun.COM * a packet.
969865SSaurabh.Mishra@Sun.COM * 'r_avail_desc' : decremented whenever a packet is being sent.
979865SSaurabh.Mishra@Sun.COM * 'r_cons_desc' : incremented whenever a packet is sent down the wire and
989865SSaurabh.Mishra@Sun.COM * notified by an interrupt to bfe driver.
999865SSaurabh.Mishra@Sun.COM *
1009865SSaurabh.Mishra@Sun.COM * RX:
1019865SSaurabh.Mishra@Sun.COM *
1029865SSaurabh.Mishra@Sun.COM * Base of the descriptor table is programmed using BFE_DMARX_CTRL control
1039865SSaurabh.Mishra@Sun.COM * register. Each 'addr' points to DMA buffer (or packet data buffer). 'ctl'
1049865SSaurabh.Mishra@Sun.COM * contains the size of the DMA buffer and all the DMA buffers are
1059865SSaurabh.Mishra@Sun.COM * pre-allocated during attach and hence the maxmium size of the packet is
1069865SSaurabh.Mishra@Sun.COM * also known (r_buf_len from the bfe_rint_t structure). During RX interrupt
1079865SSaurabh.Mishra@Sun.COM * the packet length is embedded in bfe_header_t which is added by the
1089865SSaurabh.Mishra@Sun.COM * chip in the beginning of the packet.
1099865SSaurabh.Mishra@Sun.COM *
1109865SSaurabh.Mishra@Sun.COM * ----------------------|
1119865SSaurabh.Mishra@Sun.COM * | addr |Descriptor 0 |
1129865SSaurabh.Mishra@Sun.COM * | ctl | |
1139865SSaurabh.Mishra@Sun.COM * ----------------------|
1149865SSaurabh.Mishra@Sun.COM * | addr |Descriptor 1 |
1159865SSaurabh.Mishra@Sun.COM * | ctl | |
1169865SSaurabh.Mishra@Sun.COM * ----------------------|
1179865SSaurabh.Mishra@Sun.COM * | ... |Descriptor... |
1189865SSaurabh.Mishra@Sun.COM * | ... | |
1199865SSaurabh.Mishra@Sun.COM * ----------------------|
1209865SSaurabh.Mishra@Sun.COM * | addr |Descriptor 127|
1219865SSaurabh.Mishra@Sun.COM * | ctl | EOT | EOT (End of Table)
1229865SSaurabh.Mishra@Sun.COM * ----------------------|
1239865SSaurabh.Mishra@Sun.COM *
1249865SSaurabh.Mishra@Sun.COM * 'r_curr_desc' : pointer to current descriptor while receving a packet.
1259865SSaurabh.Mishra@Sun.COM *
1269865SSaurabh.Mishra@Sun.COM */
1279865SSaurabh.Mishra@Sun.COM
1289865SSaurabh.Mishra@Sun.COM #define MODULE_NAME "bfe"
1299865SSaurabh.Mishra@Sun.COM
1309865SSaurabh.Mishra@Sun.COM /*
1319865SSaurabh.Mishra@Sun.COM * Used for checking PHY (link state, speed)
1329865SSaurabh.Mishra@Sun.COM */
1339865SSaurabh.Mishra@Sun.COM #define BFE_TIMEOUT_INTERVAL (1000 * 1000 * 1000)
1349865SSaurabh.Mishra@Sun.COM
1359865SSaurabh.Mishra@Sun.COM
1369865SSaurabh.Mishra@Sun.COM /*
1379865SSaurabh.Mishra@Sun.COM * Chip restart action and reason for restart
1389865SSaurabh.Mishra@Sun.COM */
1399865SSaurabh.Mishra@Sun.COM #define BFE_ACTION_RESTART 0x1 /* For restarting the chip */
1409865SSaurabh.Mishra@Sun.COM #define BFE_ACTION_RESTART_SETPROP 0x2 /* restart due to setprop */
1419865SSaurabh.Mishra@Sun.COM #define BFE_ACTION_RESTART_FAULT 0x4 /* restart due to fault */
1429865SSaurabh.Mishra@Sun.COM #define BFE_ACTION_RESTART_PKT 0x8 /* restart due to pkt timeout */
1439865SSaurabh.Mishra@Sun.COM
1449865SSaurabh.Mishra@Sun.COM static char bfe_ident[] = "bfe driver for Broadcom BCM4401 chipsets";
1459865SSaurabh.Mishra@Sun.COM
1469865SSaurabh.Mishra@Sun.COM /*
1479865SSaurabh.Mishra@Sun.COM * Function Prototypes for bfe driver.
1489865SSaurabh.Mishra@Sun.COM */
1499865SSaurabh.Mishra@Sun.COM static int bfe_check_link(bfe_t *);
1509865SSaurabh.Mishra@Sun.COM static void bfe_report_link(bfe_t *);
1519865SSaurabh.Mishra@Sun.COM static void bfe_chip_halt(bfe_t *);
1529865SSaurabh.Mishra@Sun.COM static void bfe_chip_reset(bfe_t *);
1539865SSaurabh.Mishra@Sun.COM static void bfe_tx_desc_init(bfe_ring_t *);
1549865SSaurabh.Mishra@Sun.COM static void bfe_rx_desc_init(bfe_ring_t *);
1559865SSaurabh.Mishra@Sun.COM static void bfe_set_rx_mode(bfe_t *);
1569865SSaurabh.Mishra@Sun.COM static void bfe_enable_chip_intrs(bfe_t *);
1579865SSaurabh.Mishra@Sun.COM static void bfe_chip_restart(bfe_t *);
1589865SSaurabh.Mishra@Sun.COM static void bfe_init_vars(bfe_t *);
1599865SSaurabh.Mishra@Sun.COM static void bfe_clear_stats(bfe_t *);
1609865SSaurabh.Mishra@Sun.COM static void bfe_gather_stats(bfe_t *);
1619865SSaurabh.Mishra@Sun.COM static void bfe_error(dev_info_t *, char *, ...);
1629865SSaurabh.Mishra@Sun.COM static int bfe_mac_getprop(void *, const char *, mac_prop_id_t, uint_t,
16311878SVenu.Iyer@Sun.COM void *);
1649865SSaurabh.Mishra@Sun.COM static int bfe_mac_setprop(void *, const char *, mac_prop_id_t, uint_t,
1659865SSaurabh.Mishra@Sun.COM const void *);
1669865SSaurabh.Mishra@Sun.COM static int bfe_tx_reclaim(bfe_ring_t *);
1679865SSaurabh.Mishra@Sun.COM int bfe_mac_set_ether_addr(void *, const uint8_t *);
1689865SSaurabh.Mishra@Sun.COM
1699865SSaurabh.Mishra@Sun.COM
1709865SSaurabh.Mishra@Sun.COM /*
1719865SSaurabh.Mishra@Sun.COM * Macros for ddi_dma_sync().
1729865SSaurabh.Mishra@Sun.COM */
1739865SSaurabh.Mishra@Sun.COM #define SYNC_DESC(r, s, l, d) \
1749865SSaurabh.Mishra@Sun.COM (void) ddi_dma_sync(r->r_desc_dma_handle, \
1759865SSaurabh.Mishra@Sun.COM (off_t)(s * sizeof (bfe_desc_t)), \
1769865SSaurabh.Mishra@Sun.COM (size_t)(l * sizeof (bfe_desc_t)), \
1779865SSaurabh.Mishra@Sun.COM d)
1789865SSaurabh.Mishra@Sun.COM
1799865SSaurabh.Mishra@Sun.COM #define SYNC_BUF(r, s, b, l, d) \
1809865SSaurabh.Mishra@Sun.COM (void) ddi_dma_sync(r->r_buf_dma[s].handle, \
1819865SSaurabh.Mishra@Sun.COM (off_t)(b), (size_t)(l), d)
1829865SSaurabh.Mishra@Sun.COM
1839865SSaurabh.Mishra@Sun.COM /*
1849865SSaurabh.Mishra@Sun.COM * Supported Broadcom BCM4401 Cards.
1859865SSaurabh.Mishra@Sun.COM */
1869865SSaurabh.Mishra@Sun.COM static bfe_cards_t bfe_cards[] = {
1879865SSaurabh.Mishra@Sun.COM { 0x14e4, 0x170c, "BCM4401 100Base-TX"},
1889865SSaurabh.Mishra@Sun.COM };
1899865SSaurabh.Mishra@Sun.COM
1909865SSaurabh.Mishra@Sun.COM
1919865SSaurabh.Mishra@Sun.COM /*
1929865SSaurabh.Mishra@Sun.COM * DMA attributes for device registers, packet data (buffer) and
1939865SSaurabh.Mishra@Sun.COM * descriptor table.
1949865SSaurabh.Mishra@Sun.COM */
1959865SSaurabh.Mishra@Sun.COM static struct ddi_device_acc_attr bfe_dev_attr = {
1969865SSaurabh.Mishra@Sun.COM DDI_DEVICE_ATTR_V0,
1979865SSaurabh.Mishra@Sun.COM DDI_STRUCTURE_LE_ACC,
1989865SSaurabh.Mishra@Sun.COM DDI_STRICTORDER_ACC
1999865SSaurabh.Mishra@Sun.COM };
2009865SSaurabh.Mishra@Sun.COM
2019865SSaurabh.Mishra@Sun.COM static struct ddi_device_acc_attr bfe_buf_attr = {
2029865SSaurabh.Mishra@Sun.COM DDI_DEVICE_ATTR_V0,
2039865SSaurabh.Mishra@Sun.COM DDI_NEVERSWAP_ACC, /* native endianness */
2049865SSaurabh.Mishra@Sun.COM DDI_STRICTORDER_ACC
2059865SSaurabh.Mishra@Sun.COM };
2069865SSaurabh.Mishra@Sun.COM
2079865SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t bfe_dma_attr_buf = {
2089865SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
2099865SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
2109865SSaurabh.Mishra@Sun.COM BFE_PCI_DMA - 1, /* dma_attr_addr_hi */
2119865SSaurabh.Mishra@Sun.COM 0x1fff, /* dma_attr_count_max */
2129865SSaurabh.Mishra@Sun.COM 8, /* dma_attr_align */
2139865SSaurabh.Mishra@Sun.COM 0, /* dma_attr_burstsizes */
2149865SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
2159865SSaurabh.Mishra@Sun.COM 0x1fff, /* dma_attr_maxxfer */
2169865SSaurabh.Mishra@Sun.COM BFE_PCI_DMA - 1, /* dma_attr_seg */
2179865SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
2189865SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
2199865SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
2209865SSaurabh.Mishra@Sun.COM };
2219865SSaurabh.Mishra@Sun.COM
2229865SSaurabh.Mishra@Sun.COM static ddi_dma_attr_t bfe_dma_attr_desc = {
2239865SSaurabh.Mishra@Sun.COM DMA_ATTR_V0, /* dma_attr_version */
2249865SSaurabh.Mishra@Sun.COM 0, /* dma_attr_addr_lo */
2259865SSaurabh.Mishra@Sun.COM BFE_PCI_DMA - 1, /* dma_attr_addr_hi */
2269865SSaurabh.Mishra@Sun.COM BFE_PCI_DMA - 1, /* dma_attr_count_max */
2279865SSaurabh.Mishra@Sun.COM BFE_DESC_ALIGN, /* dma_attr_align */
2289865SSaurabh.Mishra@Sun.COM 0, /* dma_attr_burstsizes */
2299865SSaurabh.Mishra@Sun.COM 1, /* dma_attr_minxfer */
2309865SSaurabh.Mishra@Sun.COM BFE_PCI_DMA - 1, /* dma_attr_maxxfer */
2319865SSaurabh.Mishra@Sun.COM BFE_PCI_DMA - 1, /* dma_attr_seg */
2329865SSaurabh.Mishra@Sun.COM 1, /* dma_attr_sgllen */
2339865SSaurabh.Mishra@Sun.COM 1, /* dma_attr_granular */
2349865SSaurabh.Mishra@Sun.COM 0 /* dma_attr_flags */
2359865SSaurabh.Mishra@Sun.COM };
2369865SSaurabh.Mishra@Sun.COM
2379865SSaurabh.Mishra@Sun.COM /*
2389865SSaurabh.Mishra@Sun.COM * Ethernet broadcast addresses.
2399865SSaurabh.Mishra@Sun.COM */
2409865SSaurabh.Mishra@Sun.COM static uchar_t bfe_broadcast[ETHERADDRL] = {
2419865SSaurabh.Mishra@Sun.COM 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
2429865SSaurabh.Mishra@Sun.COM };
2439865SSaurabh.Mishra@Sun.COM
2449865SSaurabh.Mishra@Sun.COM #define ASSERT_ALL_LOCKS(bfe) { \
2459865SSaurabh.Mishra@Sun.COM ASSERT(mutex_owned(&bfe->bfe_tx_ring.r_lock)); \
2469865SSaurabh.Mishra@Sun.COM ASSERT(rw_write_held(&bfe->bfe_rwlock)); \
2479865SSaurabh.Mishra@Sun.COM }
2489865SSaurabh.Mishra@Sun.COM
2499865SSaurabh.Mishra@Sun.COM /*
2509865SSaurabh.Mishra@Sun.COM * Debugging and error reproting code.
2519865SSaurabh.Mishra@Sun.COM */
2529865SSaurabh.Mishra@Sun.COM static void
bfe_error(dev_info_t * dip,char * fmt,...)2539865SSaurabh.Mishra@Sun.COM bfe_error(dev_info_t *dip, char *fmt, ...)
2549865SSaurabh.Mishra@Sun.COM {
2559865SSaurabh.Mishra@Sun.COM va_list ap;
2569865SSaurabh.Mishra@Sun.COM char buf[256];
2579865SSaurabh.Mishra@Sun.COM
2589865SSaurabh.Mishra@Sun.COM va_start(ap, fmt);
2599865SSaurabh.Mishra@Sun.COM (void) vsnprintf(buf, sizeof (buf), fmt, ap);
2609865SSaurabh.Mishra@Sun.COM va_end(ap);
2619865SSaurabh.Mishra@Sun.COM
2629865SSaurabh.Mishra@Sun.COM if (dip) {
2639865SSaurabh.Mishra@Sun.COM cmn_err(CE_WARN, "%s%d: %s",
2649865SSaurabh.Mishra@Sun.COM ddi_driver_name(dip), ddi_get_instance(dip), buf);
2659865SSaurabh.Mishra@Sun.COM } else {
2669865SSaurabh.Mishra@Sun.COM cmn_err(CE_WARN, "bfe: %s", buf);
2679865SSaurabh.Mishra@Sun.COM }
2689865SSaurabh.Mishra@Sun.COM }
2699865SSaurabh.Mishra@Sun.COM
2709865SSaurabh.Mishra@Sun.COM /*
2719865SSaurabh.Mishra@Sun.COM * Grabs all necessary locks to block any other operation on the chip.
2729865SSaurabh.Mishra@Sun.COM */
2739865SSaurabh.Mishra@Sun.COM static void
bfe_grab_locks(bfe_t * bfe)2749865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe_t *bfe)
2759865SSaurabh.Mishra@Sun.COM {
2769865SSaurabh.Mishra@Sun.COM bfe_ring_t *tx = &bfe->bfe_tx_ring;
2779865SSaurabh.Mishra@Sun.COM
2789865SSaurabh.Mishra@Sun.COM /*
2799865SSaurabh.Mishra@Sun.COM * Grab all the locks.
2809865SSaurabh.Mishra@Sun.COM * - bfe_rwlock : locks down whole chip including RX.
2819865SSaurabh.Mishra@Sun.COM * - tx's r_lock : locks down only TX side.
2829865SSaurabh.Mishra@Sun.COM */
2839865SSaurabh.Mishra@Sun.COM rw_enter(&bfe->bfe_rwlock, RW_WRITER);
2849865SSaurabh.Mishra@Sun.COM mutex_enter(&tx->r_lock);
2859865SSaurabh.Mishra@Sun.COM
2869865SSaurabh.Mishra@Sun.COM /*
2879865SSaurabh.Mishra@Sun.COM * Note that we don't use RX's r_lock.
2889865SSaurabh.Mishra@Sun.COM */
2899865SSaurabh.Mishra@Sun.COM }
2909865SSaurabh.Mishra@Sun.COM
2919865SSaurabh.Mishra@Sun.COM /*
2929865SSaurabh.Mishra@Sun.COM * Release lock on chip/drver.
2939865SSaurabh.Mishra@Sun.COM */
2949865SSaurabh.Mishra@Sun.COM static void
bfe_release_locks(bfe_t * bfe)2959865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe_t *bfe)
2969865SSaurabh.Mishra@Sun.COM {
2979865SSaurabh.Mishra@Sun.COM bfe_ring_t *tx = &bfe->bfe_tx_ring;
2989865SSaurabh.Mishra@Sun.COM
2999865SSaurabh.Mishra@Sun.COM /*
3009865SSaurabh.Mishra@Sun.COM * Release all the locks in the order in which they were grabbed.
3019865SSaurabh.Mishra@Sun.COM */
3029865SSaurabh.Mishra@Sun.COM mutex_exit(&tx->r_lock);
3039865SSaurabh.Mishra@Sun.COM rw_exit(&bfe->bfe_rwlock);
3049865SSaurabh.Mishra@Sun.COM }
3059865SSaurabh.Mishra@Sun.COM
3069865SSaurabh.Mishra@Sun.COM
3079865SSaurabh.Mishra@Sun.COM /*
3089865SSaurabh.Mishra@Sun.COM * It's used to make sure that the write to device register was successful.
3099865SSaurabh.Mishra@Sun.COM */
3109865SSaurabh.Mishra@Sun.COM static int
bfe_wait_bit(bfe_t * bfe,uint32_t reg,uint32_t bit,ulong_t t,const int clear)3119865SSaurabh.Mishra@Sun.COM bfe_wait_bit(bfe_t *bfe, uint32_t reg, uint32_t bit,
3129865SSaurabh.Mishra@Sun.COM ulong_t t, const int clear)
3139865SSaurabh.Mishra@Sun.COM {
3149865SSaurabh.Mishra@Sun.COM ulong_t i;
3159865SSaurabh.Mishra@Sun.COM uint32_t v;
3169865SSaurabh.Mishra@Sun.COM
3179865SSaurabh.Mishra@Sun.COM for (i = 0; i < t; i++) {
3189865SSaurabh.Mishra@Sun.COM v = INL(bfe, reg);
3199865SSaurabh.Mishra@Sun.COM
3209865SSaurabh.Mishra@Sun.COM if (clear && !(v & bit))
3219865SSaurabh.Mishra@Sun.COM break;
3229865SSaurabh.Mishra@Sun.COM
3239865SSaurabh.Mishra@Sun.COM if (!clear && (v & bit))
3249865SSaurabh.Mishra@Sun.COM break;
3259865SSaurabh.Mishra@Sun.COM
3269865SSaurabh.Mishra@Sun.COM drv_usecwait(10);
3279865SSaurabh.Mishra@Sun.COM }
3289865SSaurabh.Mishra@Sun.COM
3299865SSaurabh.Mishra@Sun.COM /* if device still didn't see the value */
3309865SSaurabh.Mishra@Sun.COM if (i == t)
3319865SSaurabh.Mishra@Sun.COM return (-1);
3329865SSaurabh.Mishra@Sun.COM
3339865SSaurabh.Mishra@Sun.COM return (0);
3349865SSaurabh.Mishra@Sun.COM }
3359865SSaurabh.Mishra@Sun.COM
3369865SSaurabh.Mishra@Sun.COM /*
3379865SSaurabh.Mishra@Sun.COM * PHY functions (read, write, stop, reset and startup)
3389865SSaurabh.Mishra@Sun.COM */
3399865SSaurabh.Mishra@Sun.COM static int
bfe_read_phy(bfe_t * bfe,uint32_t reg)3409865SSaurabh.Mishra@Sun.COM bfe_read_phy(bfe_t *bfe, uint32_t reg)
3419865SSaurabh.Mishra@Sun.COM {
3429865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII);
3439865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_MDIO_DATA, (BFE_MDIO_SB_START |
3449865SSaurabh.Mishra@Sun.COM (BFE_MDIO_OP_READ << BFE_MDIO_OP_SHIFT) |
3459865SSaurabh.Mishra@Sun.COM (bfe->bfe_phy_addr << BFE_MDIO_PMD_SHIFT) |
3469865SSaurabh.Mishra@Sun.COM (reg << BFE_MDIO_RA_SHIFT) |
3479865SSaurabh.Mishra@Sun.COM (BFE_MDIO_TA_VALID << BFE_MDIO_TA_SHIFT)));
3489865SSaurabh.Mishra@Sun.COM
3499865SSaurabh.Mishra@Sun.COM (void) bfe_wait_bit(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 10, 0);
3509865SSaurabh.Mishra@Sun.COM
3519865SSaurabh.Mishra@Sun.COM return ((INL(bfe, BFE_MDIO_DATA) & BFE_MDIO_DATA_DATA));
3529865SSaurabh.Mishra@Sun.COM }
3539865SSaurabh.Mishra@Sun.COM
3549865SSaurabh.Mishra@Sun.COM static void
bfe_write_phy(bfe_t * bfe,uint32_t reg,uint32_t val)3559865SSaurabh.Mishra@Sun.COM bfe_write_phy(bfe_t *bfe, uint32_t reg, uint32_t val)
3569865SSaurabh.Mishra@Sun.COM {
3579865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII);
3589865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_MDIO_DATA, (BFE_MDIO_SB_START |
3599865SSaurabh.Mishra@Sun.COM (BFE_MDIO_OP_WRITE << BFE_MDIO_OP_SHIFT) |
3609865SSaurabh.Mishra@Sun.COM (bfe->bfe_phy_addr << BFE_MDIO_PMD_SHIFT) |
3619865SSaurabh.Mishra@Sun.COM (reg << BFE_MDIO_RA_SHIFT) |
3629865SSaurabh.Mishra@Sun.COM (BFE_MDIO_TA_VALID << BFE_MDIO_TA_SHIFT) |
3639865SSaurabh.Mishra@Sun.COM (val & BFE_MDIO_DATA_DATA)));
3649865SSaurabh.Mishra@Sun.COM
3659865SSaurabh.Mishra@Sun.COM (void) bfe_wait_bit(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 10, 0);
3669865SSaurabh.Mishra@Sun.COM }
3679865SSaurabh.Mishra@Sun.COM
3689865SSaurabh.Mishra@Sun.COM /*
3699865SSaurabh.Mishra@Sun.COM * It resets the PHY layer.
3709865SSaurabh.Mishra@Sun.COM */
3719865SSaurabh.Mishra@Sun.COM static int
bfe_reset_phy(bfe_t * bfe)3729865SSaurabh.Mishra@Sun.COM bfe_reset_phy(bfe_t *bfe)
3739865SSaurabh.Mishra@Sun.COM {
3749865SSaurabh.Mishra@Sun.COM uint32_t i;
3759865SSaurabh.Mishra@Sun.COM
3769865SSaurabh.Mishra@Sun.COM bfe_write_phy(bfe, MII_CONTROL, MII_CONTROL_RESET);
3779865SSaurabh.Mishra@Sun.COM drv_usecwait(100);
3789865SSaurabh.Mishra@Sun.COM for (i = 0; i < 10; i++) {
3799865SSaurabh.Mishra@Sun.COM if (bfe_read_phy(bfe, MII_CONTROL) &
3809865SSaurabh.Mishra@Sun.COM MII_CONTROL_RESET) {
3819865SSaurabh.Mishra@Sun.COM drv_usecwait(500);
3829865SSaurabh.Mishra@Sun.COM continue;
3839865SSaurabh.Mishra@Sun.COM }
3849865SSaurabh.Mishra@Sun.COM
3859865SSaurabh.Mishra@Sun.COM break;
3869865SSaurabh.Mishra@Sun.COM }
3879865SSaurabh.Mishra@Sun.COM
3889865SSaurabh.Mishra@Sun.COM if (i == 10) {
3899865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "Timeout waiting for PHY to reset");
3909865SSaurabh.Mishra@Sun.COM bfe->bfe_phy_state = BFE_PHY_RESET_TIMEOUT;
3919865SSaurabh.Mishra@Sun.COM return (BFE_FAILURE);
3929865SSaurabh.Mishra@Sun.COM }
3939865SSaurabh.Mishra@Sun.COM
3949865SSaurabh.Mishra@Sun.COM bfe->bfe_phy_state = BFE_PHY_RESET_DONE;
3959865SSaurabh.Mishra@Sun.COM
3969865SSaurabh.Mishra@Sun.COM return (BFE_SUCCESS);
3979865SSaurabh.Mishra@Sun.COM }
3989865SSaurabh.Mishra@Sun.COM
3999865SSaurabh.Mishra@Sun.COM /*
4009865SSaurabh.Mishra@Sun.COM * Make sure timer function is out of our way and especially during
4019865SSaurabh.Mishra@Sun.COM * detach.
4029865SSaurabh.Mishra@Sun.COM */
4039865SSaurabh.Mishra@Sun.COM static void
bfe_stop_timer(bfe_t * bfe)4049865SSaurabh.Mishra@Sun.COM bfe_stop_timer(bfe_t *bfe)
4059865SSaurabh.Mishra@Sun.COM {
4069865SSaurabh.Mishra@Sun.COM if (bfe->bfe_periodic_id) {
4079865SSaurabh.Mishra@Sun.COM ddi_periodic_delete(bfe->bfe_periodic_id);
4089865SSaurabh.Mishra@Sun.COM bfe->bfe_periodic_id = NULL;
4099865SSaurabh.Mishra@Sun.COM }
4109865SSaurabh.Mishra@Sun.COM }
4119865SSaurabh.Mishra@Sun.COM
4129865SSaurabh.Mishra@Sun.COM /*
4139865SSaurabh.Mishra@Sun.COM * Stops the PHY
4149865SSaurabh.Mishra@Sun.COM */
4159865SSaurabh.Mishra@Sun.COM static void
bfe_stop_phy(bfe_t * bfe)4169865SSaurabh.Mishra@Sun.COM bfe_stop_phy(bfe_t *bfe)
4179865SSaurabh.Mishra@Sun.COM {
4189865SSaurabh.Mishra@Sun.COM bfe_write_phy(bfe, MII_CONTROL, MII_CONTROL_PWRDN |
4199865SSaurabh.Mishra@Sun.COM MII_CONTROL_ISOLATE);
4209865SSaurabh.Mishra@Sun.COM
4219865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.link = LINK_STATE_UNKNOWN;
4229865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 0;
4239865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN;
4249865SSaurabh.Mishra@Sun.COM
4259865SSaurabh.Mishra@Sun.COM bfe->bfe_phy_state = BFE_PHY_STOPPED;
4269865SSaurabh.Mishra@Sun.COM
4279865SSaurabh.Mishra@Sun.COM /*
4289865SSaurabh.Mishra@Sun.COM * Report the link status to MAC layer.
4299865SSaurabh.Mishra@Sun.COM */
4309865SSaurabh.Mishra@Sun.COM if (bfe->bfe_machdl != NULL)
4319865SSaurabh.Mishra@Sun.COM (void) bfe_report_link(bfe);
4329865SSaurabh.Mishra@Sun.COM }
4339865SSaurabh.Mishra@Sun.COM
4349865SSaurabh.Mishra@Sun.COM static int
bfe_probe_phy(bfe_t * bfe)4359865SSaurabh.Mishra@Sun.COM bfe_probe_phy(bfe_t *bfe)
4369865SSaurabh.Mishra@Sun.COM {
4379865SSaurabh.Mishra@Sun.COM int phy;
4389865SSaurabh.Mishra@Sun.COM uint32_t status;
4399865SSaurabh.Mishra@Sun.COM
4409865SSaurabh.Mishra@Sun.COM if (bfe->bfe_phy_addr) {
4419865SSaurabh.Mishra@Sun.COM status = bfe_read_phy(bfe, MII_STATUS);
4429865SSaurabh.Mishra@Sun.COM if (status != 0xffff && status != 0) {
4439865SSaurabh.Mishra@Sun.COM bfe_write_phy(bfe, MII_CONTROL, 0);
4449865SSaurabh.Mishra@Sun.COM return (BFE_SUCCESS);
4459865SSaurabh.Mishra@Sun.COM }
4469865SSaurabh.Mishra@Sun.COM }
4479865SSaurabh.Mishra@Sun.COM
4489865SSaurabh.Mishra@Sun.COM for (phy = 0; phy < 32; phy++) {
4499865SSaurabh.Mishra@Sun.COM bfe->bfe_phy_addr = phy;
4509865SSaurabh.Mishra@Sun.COM status = bfe_read_phy(bfe, MII_STATUS);
4519865SSaurabh.Mishra@Sun.COM if (status != 0xffff && status != 0) {
4529865SSaurabh.Mishra@Sun.COM bfe_write_phy(bfe, MII_CONTROL, 0);
4539865SSaurabh.Mishra@Sun.COM return (BFE_SUCCESS);
4549865SSaurabh.Mishra@Sun.COM }
4559865SSaurabh.Mishra@Sun.COM }
4569865SSaurabh.Mishra@Sun.COM
4579865SSaurabh.Mishra@Sun.COM return (BFE_FAILURE);
4589865SSaurabh.Mishra@Sun.COM }
4599865SSaurabh.Mishra@Sun.COM
4609865SSaurabh.Mishra@Sun.COM /*
4619865SSaurabh.Mishra@Sun.COM * This timeout function fires at BFE_TIMEOUT_INTERVAL to check the link
4629865SSaurabh.Mishra@Sun.COM * status.
4639865SSaurabh.Mishra@Sun.COM */
4649865SSaurabh.Mishra@Sun.COM static void
bfe_timeout(void * arg)4659865SSaurabh.Mishra@Sun.COM bfe_timeout(void *arg)
4669865SSaurabh.Mishra@Sun.COM {
4679865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
46810591SSaurabh.Mishra@Sun.COM int resched = 0;
4699865SSaurabh.Mishra@Sun.COM
4709865SSaurabh.Mishra@Sun.COM /*
4719865SSaurabh.Mishra@Sun.COM * We don't grab any lock because bfe can't go away.
4729865SSaurabh.Mishra@Sun.COM * untimeout() will wait for this timeout instance to complete.
4739865SSaurabh.Mishra@Sun.COM */
4749865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_action & BFE_ACTION_RESTART) {
4759865SSaurabh.Mishra@Sun.COM /*
4769865SSaurabh.Mishra@Sun.COM * Restart the chip.
4779865SSaurabh.Mishra@Sun.COM */
4789865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
4799865SSaurabh.Mishra@Sun.COM bfe_chip_restart(bfe);
4809865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action &= ~BFE_ACTION_RESTART;
4819865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_FAULT;
4829865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_PKT;
4839865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
4849865SSaurabh.Mishra@Sun.COM mac_tx_update(bfe->bfe_machdl);
4859865SSaurabh.Mishra@Sun.COM /* Restart will register a new timeout */
4869865SSaurabh.Mishra@Sun.COM return;
4879865SSaurabh.Mishra@Sun.COM }
4889865SSaurabh.Mishra@Sun.COM
4899865SSaurabh.Mishra@Sun.COM rw_enter(&bfe->bfe_rwlock, RW_READER);
4909865SSaurabh.Mishra@Sun.COM
4919865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state == BFE_CHIP_ACTIVE) {
4929865SSaurabh.Mishra@Sun.COM hrtime_t hr;
4939865SSaurabh.Mishra@Sun.COM
4949865SSaurabh.Mishra@Sun.COM hr = gethrtime();
4959865SSaurabh.Mishra@Sun.COM if (bfe->bfe_tx_stall_time != 0 &&
4969865SSaurabh.Mishra@Sun.COM hr > bfe->bfe_tx_stall_time) {
4979865SSaurabh.Mishra@Sun.COM DTRACE_PROBE2(chip__restart, int, bfe->bfe_unit,
4989865SSaurabh.Mishra@Sun.COM char *, "pkt timeout");
4999865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action |=
5009865SSaurabh.Mishra@Sun.COM (BFE_ACTION_RESTART | BFE_ACTION_RESTART_PKT);
5019865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_stall_time = 0;
5029865SSaurabh.Mishra@Sun.COM }
5039865SSaurabh.Mishra@Sun.COM }
5049865SSaurabh.Mishra@Sun.COM
5059865SSaurabh.Mishra@Sun.COM if (bfe->bfe_phy_state == BFE_PHY_STARTED) {
5069865SSaurabh.Mishra@Sun.COM /*
5079865SSaurabh.Mishra@Sun.COM * Report the link status to MAC layer if link status changed.
5089865SSaurabh.Mishra@Sun.COM */
5099865SSaurabh.Mishra@Sun.COM if (bfe_check_link(bfe)) {
5109865SSaurabh.Mishra@Sun.COM bfe_report_link(bfe);
5119865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip.link == LINK_STATE_UP) {
5129865SSaurabh.Mishra@Sun.COM uint32_t val, flow;
5139865SSaurabh.Mishra@Sun.COM
5149865SSaurabh.Mishra@Sun.COM val = INL(bfe, BFE_TX_CTRL);
5159865SSaurabh.Mishra@Sun.COM val &= ~BFE_TX_DUPLEX;
5169865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip.duplex == LINK_DUPLEX_FULL) {
5179865SSaurabh.Mishra@Sun.COM val |= BFE_TX_DUPLEX;
5189865SSaurabh.Mishra@Sun.COM flow = INL(bfe, BFE_RXCONF);
5199865SSaurabh.Mishra@Sun.COM flow &= ~BFE_RXCONF_FLOW;
5209865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_RXCONF, flow);
5219865SSaurabh.Mishra@Sun.COM
5229865SSaurabh.Mishra@Sun.COM flow = INL(bfe, BFE_MAC_FLOW);
5239865SSaurabh.Mishra@Sun.COM flow &= ~(BFE_FLOW_RX_HIWAT);
5249865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_MAC_FLOW, flow);
5259865SSaurabh.Mishra@Sun.COM }
5269865SSaurabh.Mishra@Sun.COM
52710591SSaurabh.Mishra@Sun.COM resched = 1;
52810591SSaurabh.Mishra@Sun.COM
5299865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_TX_CTRL, val);
5309865SSaurabh.Mishra@Sun.COM DTRACE_PROBE1(link__up,
5319865SSaurabh.Mishra@Sun.COM int, bfe->bfe_unit);
5329865SSaurabh.Mishra@Sun.COM }
5339865SSaurabh.Mishra@Sun.COM }
5349865SSaurabh.Mishra@Sun.COM }
5359865SSaurabh.Mishra@Sun.COM
5369865SSaurabh.Mishra@Sun.COM rw_exit(&bfe->bfe_rwlock);
53710591SSaurabh.Mishra@Sun.COM
53810591SSaurabh.Mishra@Sun.COM if (resched)
53910591SSaurabh.Mishra@Sun.COM mac_tx_update(bfe->bfe_machdl);
5409865SSaurabh.Mishra@Sun.COM }
5419865SSaurabh.Mishra@Sun.COM
5429865SSaurabh.Mishra@Sun.COM /*
5439865SSaurabh.Mishra@Sun.COM * Starts PHY layer.
5449865SSaurabh.Mishra@Sun.COM */
5459865SSaurabh.Mishra@Sun.COM static int
bfe_startup_phy(bfe_t * bfe)5469865SSaurabh.Mishra@Sun.COM bfe_startup_phy(bfe_t *bfe)
5479865SSaurabh.Mishra@Sun.COM {
5489865SSaurabh.Mishra@Sun.COM uint16_t bmsr, bmcr, anar;
5499865SSaurabh.Mishra@Sun.COM int prog, s;
5509865SSaurabh.Mishra@Sun.COM int phyid1, phyid2;
5519865SSaurabh.Mishra@Sun.COM
5529865SSaurabh.Mishra@Sun.COM if (bfe_probe_phy(bfe) == BFE_FAILURE) {
5539865SSaurabh.Mishra@Sun.COM bfe->bfe_phy_state = BFE_PHY_NOTFOUND;
5549865SSaurabh.Mishra@Sun.COM return (BFE_FAILURE);
5559865SSaurabh.Mishra@Sun.COM }
5569865SSaurabh.Mishra@Sun.COM
5579865SSaurabh.Mishra@Sun.COM (void) bfe_reset_phy(bfe);
5589865SSaurabh.Mishra@Sun.COM
5599865SSaurabh.Mishra@Sun.COM phyid1 = bfe_read_phy(bfe, MII_PHYIDH);
5609865SSaurabh.Mishra@Sun.COM phyid2 = bfe_read_phy(bfe, MII_PHYIDL);
5619865SSaurabh.Mishra@Sun.COM bfe->bfe_phy_id = (phyid1 << 16) | phyid2;
5629865SSaurabh.Mishra@Sun.COM
5639865SSaurabh.Mishra@Sun.COM bmsr = bfe_read_phy(bfe, MII_STATUS);
5649865SSaurabh.Mishra@Sun.COM anar = bfe_read_phy(bfe, MII_AN_ADVERT);
5659865SSaurabh.Mishra@Sun.COM
5669865SSaurabh.Mishra@Sun.COM again:
5679865SSaurabh.Mishra@Sun.COM anar &= ~(MII_ABILITY_100BASE_T4 |
5689865SSaurabh.Mishra@Sun.COM MII_ABILITY_100BASE_TX_FD | MII_ABILITY_100BASE_TX |
5699865SSaurabh.Mishra@Sun.COM MII_ABILITY_10BASE_T_FD | MII_ABILITY_10BASE_T);
5709865SSaurabh.Mishra@Sun.COM
5719865SSaurabh.Mishra@Sun.COM /*
5729865SSaurabh.Mishra@Sun.COM * Supported hardware modes are in bmsr.
5739865SSaurabh.Mishra@Sun.COM */
5749865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.bmsr = bmsr;
5759865SSaurabh.Mishra@Sun.COM
5769865SSaurabh.Mishra@Sun.COM /*
5779865SSaurabh.Mishra@Sun.COM * Assume no capabilities are supported in the hardware.
5789865SSaurabh.Mishra@Sun.COM */
5799865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_aneg = bfe->bfe_cap_100T4 =
5809865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_100fdx = bfe->bfe_cap_100hdx =
5819865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_10fdx = bfe->bfe_cap_10hdx = 0;
5829865SSaurabh.Mishra@Sun.COM
5839865SSaurabh.Mishra@Sun.COM /*
5849865SSaurabh.Mishra@Sun.COM * Assume property is set.
5859865SSaurabh.Mishra@Sun.COM */
5869865SSaurabh.Mishra@Sun.COM s = 1;
5879865SSaurabh.Mishra@Sun.COM if (!(bfe->bfe_chip_action & BFE_ACTION_RESTART_SETPROP)) {
5889865SSaurabh.Mishra@Sun.COM /*
5899865SSaurabh.Mishra@Sun.COM * Property is not set which means bfe_mac_setprop()
5909865SSaurabh.Mishra@Sun.COM * is not called on us.
5919865SSaurabh.Mishra@Sun.COM */
5929865SSaurabh.Mishra@Sun.COM s = 0;
5939865SSaurabh.Mishra@Sun.COM }
5949865SSaurabh.Mishra@Sun.COM
5959865SSaurabh.Mishra@Sun.COM bmcr = prog = 0;
5969865SSaurabh.Mishra@Sun.COM
5979865SSaurabh.Mishra@Sun.COM if (bmsr & MII_STATUS_100_BASEX_FD) {
5989865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_100fdx = 1;
5999865SSaurabh.Mishra@Sun.COM if (s == 0) {
6009865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_100BASE_TX_FD;
6019865SSaurabh.Mishra@Sun.COM bfe->bfe_adv_100fdx = 1;
6029865SSaurabh.Mishra@Sun.COM prog++;
6039865SSaurabh.Mishra@Sun.COM } else if (bfe->bfe_adv_100fdx) {
6049865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_100BASE_TX_FD;
6059865SSaurabh.Mishra@Sun.COM prog++;
6069865SSaurabh.Mishra@Sun.COM }
6079865SSaurabh.Mishra@Sun.COM }
6089865SSaurabh.Mishra@Sun.COM
6099865SSaurabh.Mishra@Sun.COM if (bmsr & MII_STATUS_100_BASE_T4) {
6109865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_100T4 = 1;
6119865SSaurabh.Mishra@Sun.COM if (s == 0) {
6129865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_100BASE_T4;
6139865SSaurabh.Mishra@Sun.COM bfe->bfe_adv_100T4 = 1;
6149865SSaurabh.Mishra@Sun.COM prog++;
6159865SSaurabh.Mishra@Sun.COM } else if (bfe->bfe_adv_100T4) {
6169865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_100BASE_T4;
6179865SSaurabh.Mishra@Sun.COM prog++;
6189865SSaurabh.Mishra@Sun.COM }
6199865SSaurabh.Mishra@Sun.COM }
6209865SSaurabh.Mishra@Sun.COM
6219865SSaurabh.Mishra@Sun.COM if (bmsr & MII_STATUS_100_BASEX) {
6229865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_100hdx = 1;
6239865SSaurabh.Mishra@Sun.COM if (s == 0) {
6249865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_100BASE_TX;
6259865SSaurabh.Mishra@Sun.COM bfe->bfe_adv_100hdx = 1;
6269865SSaurabh.Mishra@Sun.COM prog++;
6279865SSaurabh.Mishra@Sun.COM } else if (bfe->bfe_adv_100hdx) {
6289865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_100BASE_TX;
6299865SSaurabh.Mishra@Sun.COM prog++;
6309865SSaurabh.Mishra@Sun.COM }
6319865SSaurabh.Mishra@Sun.COM }
6329865SSaurabh.Mishra@Sun.COM
6339865SSaurabh.Mishra@Sun.COM if (bmsr & MII_STATUS_10_FD) {
6349865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_10fdx = 1;
6359865SSaurabh.Mishra@Sun.COM if (s == 0) {
6369865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_10BASE_T_FD;
6379865SSaurabh.Mishra@Sun.COM bfe->bfe_adv_10fdx = 1;
6389865SSaurabh.Mishra@Sun.COM prog++;
6399865SSaurabh.Mishra@Sun.COM } else if (bfe->bfe_adv_10fdx) {
6409865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_10BASE_T_FD;
6419865SSaurabh.Mishra@Sun.COM prog++;
6429865SSaurabh.Mishra@Sun.COM }
6439865SSaurabh.Mishra@Sun.COM }
6449865SSaurabh.Mishra@Sun.COM
6459865SSaurabh.Mishra@Sun.COM if (bmsr & MII_STATUS_10) {
6469865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_10hdx = 1;
6479865SSaurabh.Mishra@Sun.COM if (s == 0) {
6489865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_10BASE_T;
6499865SSaurabh.Mishra@Sun.COM bfe->bfe_adv_10hdx = 1;
6509865SSaurabh.Mishra@Sun.COM prog++;
6519865SSaurabh.Mishra@Sun.COM } else if (bfe->bfe_adv_10hdx) {
6529865SSaurabh.Mishra@Sun.COM anar |= MII_ABILITY_10BASE_T;
6539865SSaurabh.Mishra@Sun.COM prog++;
6549865SSaurabh.Mishra@Sun.COM }
6559865SSaurabh.Mishra@Sun.COM }
6569865SSaurabh.Mishra@Sun.COM
6579865SSaurabh.Mishra@Sun.COM if (bmsr & MII_STATUS_CANAUTONEG) {
6589865SSaurabh.Mishra@Sun.COM bfe->bfe_cap_aneg = 1;
6599865SSaurabh.Mishra@Sun.COM if (s == 0) {
6609865SSaurabh.Mishra@Sun.COM bfe->bfe_adv_aneg = 1;
6619865SSaurabh.Mishra@Sun.COM }
6629865SSaurabh.Mishra@Sun.COM }
6639865SSaurabh.Mishra@Sun.COM
6649865SSaurabh.Mishra@Sun.COM if (prog == 0) {
6659865SSaurabh.Mishra@Sun.COM if (s == 0) {
6669865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip,
6679865SSaurabh.Mishra@Sun.COM "No valid link mode selected. Powering down PHY");
6689865SSaurabh.Mishra@Sun.COM bfe_stop_phy(bfe);
6699865SSaurabh.Mishra@Sun.COM bfe_report_link(bfe);
6709865SSaurabh.Mishra@Sun.COM return (BFE_FAILURE);
6719865SSaurabh.Mishra@Sun.COM }
6729865SSaurabh.Mishra@Sun.COM
6739865SSaurabh.Mishra@Sun.COM /*
6749865SSaurabh.Mishra@Sun.COM * If property is set then user would have goofed up. So we
6759865SSaurabh.Mishra@Sun.COM * go back to default properties.
6769865SSaurabh.Mishra@Sun.COM */
6779865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_SETPROP;
6789865SSaurabh.Mishra@Sun.COM goto again;
6799865SSaurabh.Mishra@Sun.COM }
6809865SSaurabh.Mishra@Sun.COM
6819865SSaurabh.Mishra@Sun.COM if (bfe->bfe_adv_aneg && (bmsr & MII_STATUS_CANAUTONEG)) {
6829865SSaurabh.Mishra@Sun.COM bmcr = (MII_CONTROL_ANE | MII_CONTROL_RSAN);
6839865SSaurabh.Mishra@Sun.COM } else {
6849865SSaurabh.Mishra@Sun.COM if (bfe->bfe_adv_100fdx)
6859865SSaurabh.Mishra@Sun.COM bmcr = (MII_CONTROL_100MB | MII_CONTROL_FDUPLEX);
6869865SSaurabh.Mishra@Sun.COM else if (bfe->bfe_adv_100hdx)
6879865SSaurabh.Mishra@Sun.COM bmcr = MII_CONTROL_100MB;
6889865SSaurabh.Mishra@Sun.COM else if (bfe->bfe_adv_10fdx)
6899865SSaurabh.Mishra@Sun.COM bmcr = MII_CONTROL_FDUPLEX;
6909865SSaurabh.Mishra@Sun.COM else
6919865SSaurabh.Mishra@Sun.COM bmcr = 0; /* 10HDX */
6929865SSaurabh.Mishra@Sun.COM }
6939865SSaurabh.Mishra@Sun.COM
6949865SSaurabh.Mishra@Sun.COM if (prog)
6959865SSaurabh.Mishra@Sun.COM bfe_write_phy(bfe, MII_AN_ADVERT, anar);
6969865SSaurabh.Mishra@Sun.COM
6979865SSaurabh.Mishra@Sun.COM if (bmcr)
6989865SSaurabh.Mishra@Sun.COM bfe_write_phy(bfe, MII_CONTROL, bmcr);
6999865SSaurabh.Mishra@Sun.COM
7009865SSaurabh.Mishra@Sun.COM bfe->bfe_mii_anar = anar;
7019865SSaurabh.Mishra@Sun.COM bfe->bfe_mii_bmcr = bmcr;
7029865SSaurabh.Mishra@Sun.COM bfe->bfe_phy_state = BFE_PHY_STARTED;
7039865SSaurabh.Mishra@Sun.COM
7049865SSaurabh.Mishra@Sun.COM if (bfe->bfe_periodic_id == NULL) {
7059865SSaurabh.Mishra@Sun.COM bfe->bfe_periodic_id = ddi_periodic_add(bfe_timeout,
7069865SSaurabh.Mishra@Sun.COM (void *)bfe, BFE_TIMEOUT_INTERVAL, DDI_IPL_0);
7079865SSaurabh.Mishra@Sun.COM
7089865SSaurabh.Mishra@Sun.COM DTRACE_PROBE1(first__timeout, int, bfe->bfe_unit);
7099865SSaurabh.Mishra@Sun.COM }
7109865SSaurabh.Mishra@Sun.COM
7119865SSaurabh.Mishra@Sun.COM DTRACE_PROBE4(phy_started, int, bfe->bfe_unit,
7129865SSaurabh.Mishra@Sun.COM int, bmsr, int, bmcr, int, anar);
7139865SSaurabh.Mishra@Sun.COM
7149865SSaurabh.Mishra@Sun.COM return (BFE_SUCCESS);
7159865SSaurabh.Mishra@Sun.COM }
7169865SSaurabh.Mishra@Sun.COM
7179865SSaurabh.Mishra@Sun.COM /*
7189865SSaurabh.Mishra@Sun.COM * Reports link status back to MAC Layer.
7199865SSaurabh.Mishra@Sun.COM */
7209865SSaurabh.Mishra@Sun.COM static void
bfe_report_link(bfe_t * bfe)7219865SSaurabh.Mishra@Sun.COM bfe_report_link(bfe_t *bfe)
7229865SSaurabh.Mishra@Sun.COM {
7239865SSaurabh.Mishra@Sun.COM mac_link_update(bfe->bfe_machdl, bfe->bfe_chip.link);
7249865SSaurabh.Mishra@Sun.COM }
7259865SSaurabh.Mishra@Sun.COM
7269865SSaurabh.Mishra@Sun.COM /*
7279865SSaurabh.Mishra@Sun.COM * Reads PHY/MII registers and get the link status for us.
7289865SSaurabh.Mishra@Sun.COM */
7299865SSaurabh.Mishra@Sun.COM static int
bfe_check_link(bfe_t * bfe)7309865SSaurabh.Mishra@Sun.COM bfe_check_link(bfe_t *bfe)
7319865SSaurabh.Mishra@Sun.COM {
7329865SSaurabh.Mishra@Sun.COM uint16_t bmsr, bmcr, anar, anlpar;
7339865SSaurabh.Mishra@Sun.COM int speed, duplex, link;
7349865SSaurabh.Mishra@Sun.COM
7359865SSaurabh.Mishra@Sun.COM speed = bfe->bfe_chip.speed;
7369865SSaurabh.Mishra@Sun.COM duplex = bfe->bfe_chip.duplex;
7379865SSaurabh.Mishra@Sun.COM link = bfe->bfe_chip.link;
7389865SSaurabh.Mishra@Sun.COM
7399865SSaurabh.Mishra@Sun.COM bmsr = bfe_read_phy(bfe, MII_STATUS);
7409865SSaurabh.Mishra@Sun.COM bfe->bfe_mii_bmsr = bmsr;
7419865SSaurabh.Mishra@Sun.COM
7429865SSaurabh.Mishra@Sun.COM bmcr = bfe_read_phy(bfe, MII_CONTROL);
7439865SSaurabh.Mishra@Sun.COM
7449865SSaurabh.Mishra@Sun.COM anar = bfe_read_phy(bfe, MII_AN_ADVERT);
7459865SSaurabh.Mishra@Sun.COM bfe->bfe_mii_anar = anar;
7469865SSaurabh.Mishra@Sun.COM
7479865SSaurabh.Mishra@Sun.COM anlpar = bfe_read_phy(bfe, MII_AN_LPABLE);
7489865SSaurabh.Mishra@Sun.COM bfe->bfe_mii_anlpar = anlpar;
7499865SSaurabh.Mishra@Sun.COM
7509865SSaurabh.Mishra@Sun.COM bfe->bfe_mii_exp = bfe_read_phy(bfe, MII_AN_EXPANSION);
7519865SSaurabh.Mishra@Sun.COM
7529865SSaurabh.Mishra@Sun.COM /*
7539865SSaurabh.Mishra@Sun.COM * If exp register is not present in PHY.
7549865SSaurabh.Mishra@Sun.COM */
7559865SSaurabh.Mishra@Sun.COM if (bfe->bfe_mii_exp == 0xffff) {
7569865SSaurabh.Mishra@Sun.COM bfe->bfe_mii_exp = 0;
7579865SSaurabh.Mishra@Sun.COM }
7589865SSaurabh.Mishra@Sun.COM
7599865SSaurabh.Mishra@Sun.COM if ((bmsr & MII_STATUS_LINKUP) == 0) {
7609865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.link = LINK_STATE_DOWN;
7619865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 0;
7629865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN;
7639865SSaurabh.Mishra@Sun.COM goto done;
7649865SSaurabh.Mishra@Sun.COM }
7659865SSaurabh.Mishra@Sun.COM
7669865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.link = LINK_STATE_UP;
7679865SSaurabh.Mishra@Sun.COM
7689865SSaurabh.Mishra@Sun.COM if (!(bmcr & MII_CONTROL_ANE)) {
7699865SSaurabh.Mishra@Sun.COM /* Forced mode */
7709865SSaurabh.Mishra@Sun.COM if (bmcr & MII_CONTROL_100MB)
7719865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 100000000;
7729865SSaurabh.Mishra@Sun.COM else
7739865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 10000000;
7749865SSaurabh.Mishra@Sun.COM
7759865SSaurabh.Mishra@Sun.COM if (bmcr & MII_CONTROL_FDUPLEX)
7769865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_FULL;
7779865SSaurabh.Mishra@Sun.COM else
7789865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_HALF;
7799865SSaurabh.Mishra@Sun.COM
7809865SSaurabh.Mishra@Sun.COM } else if ((!(bmsr & MII_STATUS_CANAUTONEG)) ||
7819865SSaurabh.Mishra@Sun.COM (!(bmsr & MII_STATUS_ANDONE))) {
7829865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 0;
7839865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN;
7849865SSaurabh.Mishra@Sun.COM } else if (anar & anlpar & MII_ABILITY_100BASE_TX_FD) {
7859865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 100000000;
7869865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_FULL;
7879865SSaurabh.Mishra@Sun.COM } else if (anar & anlpar & MII_ABILITY_100BASE_T4) {
7889865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 100000000;
7899865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_HALF;
7909865SSaurabh.Mishra@Sun.COM } else if (anar & anlpar & MII_ABILITY_100BASE_TX) {
7919865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 100000000;
7929865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_HALF;
7939865SSaurabh.Mishra@Sun.COM } else if (anar & anlpar & MII_ABILITY_10BASE_T_FD) {
7949865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 10000000;
7959865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_FULL;
7969865SSaurabh.Mishra@Sun.COM } else if (anar & anlpar & MII_ABILITY_10BASE_T) {
7979865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 10000000;
7989865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_HALF;
7999865SSaurabh.Mishra@Sun.COM } else {
8009865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 0;
8019865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN;
8029865SSaurabh.Mishra@Sun.COM }
8039865SSaurabh.Mishra@Sun.COM
8049865SSaurabh.Mishra@Sun.COM done:
8059865SSaurabh.Mishra@Sun.COM /*
8069865SSaurabh.Mishra@Sun.COM * If speed or link status or duplex mode changed then report to
8079865SSaurabh.Mishra@Sun.COM * MAC layer which is done by the caller.
8089865SSaurabh.Mishra@Sun.COM */
8099865SSaurabh.Mishra@Sun.COM if (speed != bfe->bfe_chip.speed ||
8109865SSaurabh.Mishra@Sun.COM duplex != bfe->bfe_chip.duplex ||
8119865SSaurabh.Mishra@Sun.COM link != bfe->bfe_chip.link) {
8129865SSaurabh.Mishra@Sun.COM return (1);
8139865SSaurabh.Mishra@Sun.COM }
8149865SSaurabh.Mishra@Sun.COM
8159865SSaurabh.Mishra@Sun.COM return (0);
8169865SSaurabh.Mishra@Sun.COM }
8179865SSaurabh.Mishra@Sun.COM
8189865SSaurabh.Mishra@Sun.COM static void
bfe_cam_write(bfe_t * bfe,uchar_t * d,int index)8199865SSaurabh.Mishra@Sun.COM bfe_cam_write(bfe_t *bfe, uchar_t *d, int index)
8209865SSaurabh.Mishra@Sun.COM {
8219865SSaurabh.Mishra@Sun.COM uint32_t v;
8229865SSaurabh.Mishra@Sun.COM
8239865SSaurabh.Mishra@Sun.COM v = ((uint32_t)d[2] << 24);
8249865SSaurabh.Mishra@Sun.COM v |= ((uint32_t)d[3] << 16);
8259865SSaurabh.Mishra@Sun.COM v |= ((uint32_t)d[4] << 8);
8269865SSaurabh.Mishra@Sun.COM v |= (uint32_t)d[5];
8279865SSaurabh.Mishra@Sun.COM
8289865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_CAM_DATA_LO, v);
8299865SSaurabh.Mishra@Sun.COM v = (BFE_CAM_HI_VALID |
8309865SSaurabh.Mishra@Sun.COM (((uint32_t)d[0]) << 8) |
8319865SSaurabh.Mishra@Sun.COM (((uint32_t)d[1])));
8329865SSaurabh.Mishra@Sun.COM
8339865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_CAM_DATA_HI, v);
8349865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_CAM_CTRL, (BFE_CAM_WRITE |
8359865SSaurabh.Mishra@Sun.COM ((uint32_t)index << BFE_CAM_INDEX_SHIFT)));
8369865SSaurabh.Mishra@Sun.COM (void) bfe_wait_bit(bfe, BFE_CAM_CTRL, BFE_CAM_BUSY, 10, 1);
8379865SSaurabh.Mishra@Sun.COM }
8389865SSaurabh.Mishra@Sun.COM
8399865SSaurabh.Mishra@Sun.COM /*
8409865SSaurabh.Mishra@Sun.COM * Chip related functions (halt, reset, start).
8419865SSaurabh.Mishra@Sun.COM */
8429865SSaurabh.Mishra@Sun.COM static void
bfe_chip_halt(bfe_t * bfe)8439865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe_t *bfe)
8449865SSaurabh.Mishra@Sun.COM {
8459865SSaurabh.Mishra@Sun.COM /*
8469865SSaurabh.Mishra@Sun.COM * Disables interrupts.
8479865SSaurabh.Mishra@Sun.COM */
8489865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_INTR_MASK, 0);
8499865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_INTR_MASK);
8509865SSaurabh.Mishra@Sun.COM
8519865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_DISABLE);
8529865SSaurabh.Mishra@Sun.COM
8539865SSaurabh.Mishra@Sun.COM /*
8549865SSaurabh.Mishra@Sun.COM * Wait until TX and RX finish their job.
8559865SSaurabh.Mishra@Sun.COM */
8569865SSaurabh.Mishra@Sun.COM (void) bfe_wait_bit(bfe, BFE_ENET_CTRL, BFE_ENET_DISABLE, 20, 1);
8579865SSaurabh.Mishra@Sun.COM
8589865SSaurabh.Mishra@Sun.COM /*
8599865SSaurabh.Mishra@Sun.COM * Disables DMA engine.
8609865SSaurabh.Mishra@Sun.COM */
8619865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMARX_CTRL, 0);
8629865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMATX_CTRL, 0);
8639865SSaurabh.Mishra@Sun.COM
8649865SSaurabh.Mishra@Sun.COM drv_usecwait(10);
8659865SSaurabh.Mishra@Sun.COM
8669865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_HALT;
8679865SSaurabh.Mishra@Sun.COM }
8689865SSaurabh.Mishra@Sun.COM
8699865SSaurabh.Mishra@Sun.COM static void
bfe_chip_restart(bfe_t * bfe)8709865SSaurabh.Mishra@Sun.COM bfe_chip_restart(bfe_t *bfe)
8719865SSaurabh.Mishra@Sun.COM {
8729865SSaurabh.Mishra@Sun.COM DTRACE_PROBE2(chip__restart, int, bfe->bfe_unit,
8739865SSaurabh.Mishra@Sun.COM int, bfe->bfe_chip_action);
8749865SSaurabh.Mishra@Sun.COM
8759865SSaurabh.Mishra@Sun.COM /*
8769865SSaurabh.Mishra@Sun.COM * Halt chip and PHY.
8779865SSaurabh.Mishra@Sun.COM */
8789865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe);
8799865SSaurabh.Mishra@Sun.COM bfe_stop_phy(bfe);
8809865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_STOPPED;
8819865SSaurabh.Mishra@Sun.COM
8829865SSaurabh.Mishra@Sun.COM /*
8839865SSaurabh.Mishra@Sun.COM * Init variables.
8849865SSaurabh.Mishra@Sun.COM */
8859865SSaurabh.Mishra@Sun.COM bfe_init_vars(bfe);
8869865SSaurabh.Mishra@Sun.COM
8879865SSaurabh.Mishra@Sun.COM /*
8889865SSaurabh.Mishra@Sun.COM * Reset chip and start PHY.
8899865SSaurabh.Mishra@Sun.COM */
8909865SSaurabh.Mishra@Sun.COM bfe_chip_reset(bfe);
8919865SSaurabh.Mishra@Sun.COM
8929865SSaurabh.Mishra@Sun.COM /*
8939865SSaurabh.Mishra@Sun.COM * DMA descriptor rings.
8949865SSaurabh.Mishra@Sun.COM */
8959865SSaurabh.Mishra@Sun.COM bfe_tx_desc_init(&bfe->bfe_tx_ring);
8969865SSaurabh.Mishra@Sun.COM bfe_rx_desc_init(&bfe->bfe_rx_ring);
8979865SSaurabh.Mishra@Sun.COM
8989865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_ACTIVE;
8999865SSaurabh.Mishra@Sun.COM bfe_set_rx_mode(bfe);
9009865SSaurabh.Mishra@Sun.COM bfe_enable_chip_intrs(bfe);
9019865SSaurabh.Mishra@Sun.COM }
9029865SSaurabh.Mishra@Sun.COM
9039865SSaurabh.Mishra@Sun.COM /*
9049865SSaurabh.Mishra@Sun.COM * Disables core by stopping the clock.
9059865SSaurabh.Mishra@Sun.COM */
9069865SSaurabh.Mishra@Sun.COM static void
bfe_core_disable(bfe_t * bfe)9079865SSaurabh.Mishra@Sun.COM bfe_core_disable(bfe_t *bfe)
9089865SSaurabh.Mishra@Sun.COM {
9099865SSaurabh.Mishra@Sun.COM if ((INL(bfe, BFE_SBTMSLOW) & BFE_RESET))
9109865SSaurabh.Mishra@Sun.COM return;
9119865SSaurabh.Mishra@Sun.COM
9129865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBTMSLOW, (BFE_REJECT | BFE_CLOCK));
9139865SSaurabh.Mishra@Sun.COM (void) bfe_wait_bit(bfe, BFE_SBTMSLOW, BFE_REJECT, 100, 0);
9149865SSaurabh.Mishra@Sun.COM (void) bfe_wait_bit(bfe, BFE_SBTMSHIGH, BFE_BUSY, 100, 1);
9159865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBTMSLOW, (BFE_FGC | BFE_CLOCK | BFE_REJECT | BFE_RESET));
9169865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_SBTMSLOW);
9179865SSaurabh.Mishra@Sun.COM drv_usecwait(10);
9189865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBTMSLOW, (BFE_REJECT | BFE_RESET));
9199865SSaurabh.Mishra@Sun.COM drv_usecwait(10);
9209865SSaurabh.Mishra@Sun.COM }
9219865SSaurabh.Mishra@Sun.COM
9229865SSaurabh.Mishra@Sun.COM /*
9239865SSaurabh.Mishra@Sun.COM * Resets core.
9249865SSaurabh.Mishra@Sun.COM */
9259865SSaurabh.Mishra@Sun.COM static void
bfe_core_reset(bfe_t * bfe)9269865SSaurabh.Mishra@Sun.COM bfe_core_reset(bfe_t *bfe)
9279865SSaurabh.Mishra@Sun.COM {
9289865SSaurabh.Mishra@Sun.COM uint32_t val;
9299865SSaurabh.Mishra@Sun.COM
9309865SSaurabh.Mishra@Sun.COM /*
9319865SSaurabh.Mishra@Sun.COM * First disable the core.
9329865SSaurabh.Mishra@Sun.COM */
9339865SSaurabh.Mishra@Sun.COM bfe_core_disable(bfe);
9349865SSaurabh.Mishra@Sun.COM
9359865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBTMSLOW, (BFE_RESET | BFE_CLOCK | BFE_FGC));
9369865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_SBTMSLOW);
9379865SSaurabh.Mishra@Sun.COM drv_usecwait(1);
9389865SSaurabh.Mishra@Sun.COM
9399865SSaurabh.Mishra@Sun.COM if (INL(bfe, BFE_SBTMSHIGH) & BFE_SERR)
9409865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBTMSHIGH, 0);
9419865SSaurabh.Mishra@Sun.COM
9429865SSaurabh.Mishra@Sun.COM val = INL(bfe, BFE_SBIMSTATE);
9439865SSaurabh.Mishra@Sun.COM if (val & (BFE_IBE | BFE_TO))
9449865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBIMSTATE, val & ~(BFE_IBE | BFE_TO));
9459865SSaurabh.Mishra@Sun.COM
9469865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBTMSLOW, (BFE_CLOCK | BFE_FGC));
9479865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_SBTMSLOW);
9489865SSaurabh.Mishra@Sun.COM drv_usecwait(1);
9499865SSaurabh.Mishra@Sun.COM
9509865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBTMSLOW, BFE_CLOCK);
9519865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_SBTMSLOW);
9529865SSaurabh.Mishra@Sun.COM drv_usecwait(1);
9539865SSaurabh.Mishra@Sun.COM }
9549865SSaurabh.Mishra@Sun.COM
9559865SSaurabh.Mishra@Sun.COM static void
bfe_setup_config(bfe_t * bfe,uint32_t cores)9569865SSaurabh.Mishra@Sun.COM bfe_setup_config(bfe_t *bfe, uint32_t cores)
9579865SSaurabh.Mishra@Sun.COM {
9589865SSaurabh.Mishra@Sun.COM uint32_t bar_orig, val;
9599865SSaurabh.Mishra@Sun.COM
9609865SSaurabh.Mishra@Sun.COM /*
9619865SSaurabh.Mishra@Sun.COM * Change bar0 window to map sbtopci registers.
9629865SSaurabh.Mishra@Sun.COM */
9639865SSaurabh.Mishra@Sun.COM bar_orig = pci_config_get32(bfe->bfe_conf_handle, BFE_BAR0_WIN);
9649865SSaurabh.Mishra@Sun.COM pci_config_put32(bfe->bfe_conf_handle, BFE_BAR0_WIN, BFE_REG_PCI);
9659865SSaurabh.Mishra@Sun.COM
9669865SSaurabh.Mishra@Sun.COM /* Just read it and don't do anything */
9679865SSaurabh.Mishra@Sun.COM val = INL(bfe, BFE_SBIDHIGH) & BFE_IDH_CORE;
9689865SSaurabh.Mishra@Sun.COM
9699865SSaurabh.Mishra@Sun.COM val = INL(bfe, BFE_SBINTVEC);
9709865SSaurabh.Mishra@Sun.COM val |= cores;
9719865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SBINTVEC, val);
9729865SSaurabh.Mishra@Sun.COM
9739865SSaurabh.Mishra@Sun.COM val = INL(bfe, BFE_SSB_PCI_TRANS_2);
9749865SSaurabh.Mishra@Sun.COM val |= BFE_SSB_PCI_PREF | BFE_SSB_PCI_BURST;
9759865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_SSB_PCI_TRANS_2, val);
9769865SSaurabh.Mishra@Sun.COM
9779865SSaurabh.Mishra@Sun.COM /*
9789865SSaurabh.Mishra@Sun.COM * Restore bar0 window mapping.
9799865SSaurabh.Mishra@Sun.COM */
9809865SSaurabh.Mishra@Sun.COM pci_config_put32(bfe->bfe_conf_handle, BFE_BAR0_WIN, bar_orig);
9819865SSaurabh.Mishra@Sun.COM }
9829865SSaurabh.Mishra@Sun.COM
9839865SSaurabh.Mishra@Sun.COM /*
9849865SSaurabh.Mishra@Sun.COM * Resets chip and starts PHY.
9859865SSaurabh.Mishra@Sun.COM */
9869865SSaurabh.Mishra@Sun.COM static void
bfe_chip_reset(bfe_t * bfe)9879865SSaurabh.Mishra@Sun.COM bfe_chip_reset(bfe_t *bfe)
9889865SSaurabh.Mishra@Sun.COM {
9899865SSaurabh.Mishra@Sun.COM uint32_t val;
9909865SSaurabh.Mishra@Sun.COM
9919865SSaurabh.Mishra@Sun.COM /* Set the interrupt vector for the enet core */
9929865SSaurabh.Mishra@Sun.COM bfe_setup_config(bfe, BFE_INTVEC_ENET0);
9939865SSaurabh.Mishra@Sun.COM
9949865SSaurabh.Mishra@Sun.COM /* check if core is up */
9959865SSaurabh.Mishra@Sun.COM val = INL(bfe, BFE_SBTMSLOW) &
9969865SSaurabh.Mishra@Sun.COM (BFE_RESET | BFE_REJECT | BFE_CLOCK);
9979865SSaurabh.Mishra@Sun.COM
9989865SSaurabh.Mishra@Sun.COM if (val == BFE_CLOCK) {
9999865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_RCV_LAZY, 0);
10009865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_DISABLE);
10019865SSaurabh.Mishra@Sun.COM (void) bfe_wait_bit(bfe, BFE_ENET_CTRL,
10029865SSaurabh.Mishra@Sun.COM BFE_ENET_DISABLE, 10, 1);
10039865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMATX_CTRL, 0);
10049865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_DMARX_STAT);
10059865SSaurabh.Mishra@Sun.COM drv_usecwait(20000); /* 20 milli seconds */
10069865SSaurabh.Mishra@Sun.COM if (INL(bfe, BFE_DMARX_STAT) & BFE_STAT_EMASK) {
10079865SSaurabh.Mishra@Sun.COM (void) bfe_wait_bit(bfe, BFE_DMARX_STAT, BFE_STAT_SIDLE,
10089865SSaurabh.Mishra@Sun.COM 10, 0);
10099865SSaurabh.Mishra@Sun.COM }
10109865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMARX_CTRL, 0);
10119865SSaurabh.Mishra@Sun.COM }
10129865SSaurabh.Mishra@Sun.COM
10139865SSaurabh.Mishra@Sun.COM bfe_core_reset(bfe);
10149865SSaurabh.Mishra@Sun.COM bfe_clear_stats(bfe);
10159865SSaurabh.Mishra@Sun.COM
10169865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_MDIO_CTRL, 0x8d);
10179865SSaurabh.Mishra@Sun.COM val = INL(bfe, BFE_DEVCTRL);
10189865SSaurabh.Mishra@Sun.COM if (!(val & BFE_IPP))
10199865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_EPSEL);
10209865SSaurabh.Mishra@Sun.COM else if (INL(bfe, BFE_DEVCTRL & BFE_EPR)) {
10219865SSaurabh.Mishra@Sun.COM OUTL_AND(bfe, BFE_DEVCTRL, ~BFE_EPR);
10229865SSaurabh.Mishra@Sun.COM drv_usecwait(20000); /* 20 milli seconds */
10239865SSaurabh.Mishra@Sun.COM }
10249865SSaurabh.Mishra@Sun.COM
10259865SSaurabh.Mishra@Sun.COM OUTL_OR(bfe, BFE_MAC_CTRL, BFE_CTRL_CRC32_ENAB | BFE_CTRL_LED);
10269865SSaurabh.Mishra@Sun.COM
10279865SSaurabh.Mishra@Sun.COM OUTL_AND(bfe, BFE_MAC_CTRL, ~BFE_CTRL_PDOWN);
10289865SSaurabh.Mishra@Sun.COM
10299865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_RCV_LAZY, ((1 << BFE_LAZY_FC_SHIFT) &
10309865SSaurabh.Mishra@Sun.COM BFE_LAZY_FC_MASK));
10319865SSaurabh.Mishra@Sun.COM
10329865SSaurabh.Mishra@Sun.COM OUTL_OR(bfe, BFE_RCV_LAZY, 0);
10339865SSaurabh.Mishra@Sun.COM
10349865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_RXMAXLEN, bfe->bfe_rx_ring.r_buf_len);
10359865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_TXMAXLEN, bfe->bfe_tx_ring.r_buf_len);
10369865SSaurabh.Mishra@Sun.COM
10379865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_TX_WMARK, 56);
10389865SSaurabh.Mishra@Sun.COM
10399865SSaurabh.Mishra@Sun.COM /* Program DMA channels */
10409865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMATX_CTRL, BFE_TX_CTRL_ENABLE);
10419865SSaurabh.Mishra@Sun.COM
10429865SSaurabh.Mishra@Sun.COM /*
10439865SSaurabh.Mishra@Sun.COM * DMA addresses need to be added to BFE_PCI_DMA
10449865SSaurabh.Mishra@Sun.COM */
10459865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMATX_ADDR,
10469865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_ring.r_desc_cookie.dmac_laddress + BFE_PCI_DMA);
10479865SSaurabh.Mishra@Sun.COM
10489865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMARX_CTRL, (BFE_RX_OFFSET << BFE_RX_CTRL_ROSHIFT)
10499865SSaurabh.Mishra@Sun.COM | BFE_RX_CTRL_ENABLE);
10509865SSaurabh.Mishra@Sun.COM
10519865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMARX_ADDR,
10529865SSaurabh.Mishra@Sun.COM bfe->bfe_rx_ring.r_desc_cookie.dmac_laddress + BFE_PCI_DMA);
10539865SSaurabh.Mishra@Sun.COM
10549865SSaurabh.Mishra@Sun.COM (void) bfe_startup_phy(bfe);
10559865SSaurabh.Mishra@Sun.COM
10569865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_INITIALIZED;
10579865SSaurabh.Mishra@Sun.COM }
10589865SSaurabh.Mishra@Sun.COM
10599865SSaurabh.Mishra@Sun.COM /*
10609865SSaurabh.Mishra@Sun.COM * It enables interrupts. Should be the last step while starting chip.
10619865SSaurabh.Mishra@Sun.COM */
10629865SSaurabh.Mishra@Sun.COM static void
bfe_enable_chip_intrs(bfe_t * bfe)10639865SSaurabh.Mishra@Sun.COM bfe_enable_chip_intrs(bfe_t *bfe)
10649865SSaurabh.Mishra@Sun.COM {
10659865SSaurabh.Mishra@Sun.COM /* Enable the chip and core */
10669865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_ENABLE);
10679865SSaurabh.Mishra@Sun.COM
10689865SSaurabh.Mishra@Sun.COM /* Enable interrupts */
10699865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_INTR_MASK, BFE_IMASK_DEF);
10709865SSaurabh.Mishra@Sun.COM }
10719865SSaurabh.Mishra@Sun.COM
10729865SSaurabh.Mishra@Sun.COM /*
10739865SSaurabh.Mishra@Sun.COM * Common code to take care of setting RX side mode (filter).
10749865SSaurabh.Mishra@Sun.COM */
10759865SSaurabh.Mishra@Sun.COM static void
bfe_set_rx_mode(bfe_t * bfe)10769865SSaurabh.Mishra@Sun.COM bfe_set_rx_mode(bfe_t *bfe)
10779865SSaurabh.Mishra@Sun.COM {
10789865SSaurabh.Mishra@Sun.COM uint32_t val;
10799865SSaurabh.Mishra@Sun.COM int i;
10809865SSaurabh.Mishra@Sun.COM ether_addr_t mac[ETHERADDRL] = {0, 0, 0, 0, 0, 0};
10819865SSaurabh.Mishra@Sun.COM
10829865SSaurabh.Mishra@Sun.COM /*
10839865SSaurabh.Mishra@Sun.COM * We don't touch RX filter if we were asked to suspend. It's fine
10849865SSaurabh.Mishra@Sun.COM * if chip is not active (no interface is plumbed on us).
10859865SSaurabh.Mishra@Sun.COM */
10869865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state == BFE_CHIP_SUSPENDED)
10879865SSaurabh.Mishra@Sun.COM return;
10889865SSaurabh.Mishra@Sun.COM
10899865SSaurabh.Mishra@Sun.COM val = INL(bfe, BFE_RXCONF);
10909865SSaurabh.Mishra@Sun.COM
10919865SSaurabh.Mishra@Sun.COM val &= ~BFE_RXCONF_PROMISC;
10929865SSaurabh.Mishra@Sun.COM val &= ~BFE_RXCONF_DBCAST;
10939865SSaurabh.Mishra@Sun.COM
10949865SSaurabh.Mishra@Sun.COM if ((bfe->bfe_chip_mode & BFE_RX_MODE_ENABLE) == 0) {
10959865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_CAM_CTRL, 0);
10969865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_CAM_CTRL);
10979865SSaurabh.Mishra@Sun.COM } else if (bfe->bfe_chip_mode & BFE_RX_MODE_PROMISC) {
10989865SSaurabh.Mishra@Sun.COM val |= BFE_RXCONF_PROMISC;
10999865SSaurabh.Mishra@Sun.COM val &= ~BFE_RXCONF_DBCAST;
11009865SSaurabh.Mishra@Sun.COM } else {
11019865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state == BFE_CHIP_ACTIVE) {
11029865SSaurabh.Mishra@Sun.COM /* Flush everything */
11039865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_RXCONF, val |
11049865SSaurabh.Mishra@Sun.COM BFE_RXCONF_PROMISC | BFE_RXCONF_ALLMULTI);
11059865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_RXCONF);
11069865SSaurabh.Mishra@Sun.COM }
11079865SSaurabh.Mishra@Sun.COM
11089865SSaurabh.Mishra@Sun.COM /* Disable CAM */
11099865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_CAM_CTRL, 0);
11109865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_CAM_CTRL);
11119865SSaurabh.Mishra@Sun.COM
11129865SSaurabh.Mishra@Sun.COM /*
11139865SSaurabh.Mishra@Sun.COM * We receive all multicast packets.
11149865SSaurabh.Mishra@Sun.COM */
11159865SSaurabh.Mishra@Sun.COM val |= BFE_RXCONF_ALLMULTI;
11169865SSaurabh.Mishra@Sun.COM
11179865SSaurabh.Mishra@Sun.COM for (i = 0; i < BFE_MAX_MULTICAST_TABLE - 1; i++) {
11189865SSaurabh.Mishra@Sun.COM bfe_cam_write(bfe, (uchar_t *)mac, i);
11199865SSaurabh.Mishra@Sun.COM }
11209865SSaurabh.Mishra@Sun.COM
11219865SSaurabh.Mishra@Sun.COM bfe_cam_write(bfe, bfe->bfe_ether_addr, i);
11229865SSaurabh.Mishra@Sun.COM
11239865SSaurabh.Mishra@Sun.COM /* Enable CAM */
11249865SSaurabh.Mishra@Sun.COM OUTL_OR(bfe, BFE_CAM_CTRL, BFE_CAM_ENABLE);
11259865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_CAM_CTRL);
11269865SSaurabh.Mishra@Sun.COM }
11279865SSaurabh.Mishra@Sun.COM
11289865SSaurabh.Mishra@Sun.COM DTRACE_PROBE2(rx__mode__filter, int, bfe->bfe_unit,
11299865SSaurabh.Mishra@Sun.COM int, val);
11309865SSaurabh.Mishra@Sun.COM
11319865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_RXCONF, val);
11329865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_RXCONF);
11339865SSaurabh.Mishra@Sun.COM }
11349865SSaurabh.Mishra@Sun.COM
11359865SSaurabh.Mishra@Sun.COM /*
11369865SSaurabh.Mishra@Sun.COM * Reset various variable values to initial state.
11379865SSaurabh.Mishra@Sun.COM */
11389865SSaurabh.Mishra@Sun.COM static void
bfe_init_vars(bfe_t * bfe)11399865SSaurabh.Mishra@Sun.COM bfe_init_vars(bfe_t *bfe)
11409865SSaurabh.Mishra@Sun.COM {
11419865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_mode = BFE_RX_MODE_ENABLE;
11429865SSaurabh.Mishra@Sun.COM
11439865SSaurabh.Mishra@Sun.COM /* Initial assumption */
11449865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.link = LINK_STATE_UNKNOWN;
11459865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.speed = 0;
11469865SSaurabh.Mishra@Sun.COM bfe->bfe_chip.duplex = LINK_DUPLEX_UNKNOWN;
11479865SSaurabh.Mishra@Sun.COM
11489865SSaurabh.Mishra@Sun.COM bfe->bfe_periodic_id = NULL;
11499865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_UNINITIALIZED;
11509865SSaurabh.Mishra@Sun.COM
11519865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_stall_time = 0;
11529865SSaurabh.Mishra@Sun.COM }
11539865SSaurabh.Mishra@Sun.COM
11549865SSaurabh.Mishra@Sun.COM /*
11559865SSaurabh.Mishra@Sun.COM * Initializes TX side descriptor entries (bfe_desc_t). Each descriptor entry
11569865SSaurabh.Mishra@Sun.COM * has control (desc_ctl) and address (desc_addr) member.
11579865SSaurabh.Mishra@Sun.COM */
11589865SSaurabh.Mishra@Sun.COM static void
bfe_tx_desc_init(bfe_ring_t * r)11599865SSaurabh.Mishra@Sun.COM bfe_tx_desc_init(bfe_ring_t *r)
11609865SSaurabh.Mishra@Sun.COM {
11619865SSaurabh.Mishra@Sun.COM int i;
11629865SSaurabh.Mishra@Sun.COM uint32_t v;
11639865SSaurabh.Mishra@Sun.COM
11649865SSaurabh.Mishra@Sun.COM for (i = 0; i < r->r_ndesc; i++) {
11659865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_ctl),
11669865SSaurabh.Mishra@Sun.COM (r->r_buf_dma[i].len & BFE_DESC_LEN));
11679865SSaurabh.Mishra@Sun.COM
11689865SSaurabh.Mishra@Sun.COM /*
11699865SSaurabh.Mishra@Sun.COM * DMA addresses need to be added to BFE_PCI_DMA
11709865SSaurabh.Mishra@Sun.COM */
11719865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_addr),
11729865SSaurabh.Mishra@Sun.COM (r->r_buf_dma[i].cookie.dmac_laddress + BFE_PCI_DMA));
11739865SSaurabh.Mishra@Sun.COM }
11749865SSaurabh.Mishra@Sun.COM
11759865SSaurabh.Mishra@Sun.COM v = GET_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl));
11769865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl),
11779865SSaurabh.Mishra@Sun.COM v | BFE_DESC_EOT);
11789865SSaurabh.Mishra@Sun.COM
11799865SSaurabh.Mishra@Sun.COM (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV);
11809865SSaurabh.Mishra@Sun.COM
11819865SSaurabh.Mishra@Sun.COM r->r_curr_desc = 0;
11829865SSaurabh.Mishra@Sun.COM r->r_avail_desc = TX_NUM_DESC;
11839865SSaurabh.Mishra@Sun.COM r->r_cons_desc = 0;
11849865SSaurabh.Mishra@Sun.COM }
11859865SSaurabh.Mishra@Sun.COM
11869865SSaurabh.Mishra@Sun.COM /*
11879865SSaurabh.Mishra@Sun.COM * Initializes RX side descriptor entries (bfe_desc_t). Each descriptor entry
11889865SSaurabh.Mishra@Sun.COM * has control (desc_ctl) and address (desc_addr) member.
11899865SSaurabh.Mishra@Sun.COM */
11909865SSaurabh.Mishra@Sun.COM static void
bfe_rx_desc_init(bfe_ring_t * r)11919865SSaurabh.Mishra@Sun.COM bfe_rx_desc_init(bfe_ring_t *r)
11929865SSaurabh.Mishra@Sun.COM {
11939865SSaurabh.Mishra@Sun.COM int i;
11949865SSaurabh.Mishra@Sun.COM uint32_t v;
11959865SSaurabh.Mishra@Sun.COM
11969865SSaurabh.Mishra@Sun.COM for (i = 0; i < r->r_ndesc; i++) {
11979865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_ctl),
11989865SSaurabh.Mishra@Sun.COM (r->r_buf_dma[i].len& BFE_DESC_LEN));
11999865SSaurabh.Mishra@Sun.COM
12009865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_addr),
12019865SSaurabh.Mishra@Sun.COM (r->r_buf_dma[i].cookie.dmac_laddress + BFE_PCI_DMA));
12029865SSaurabh.Mishra@Sun.COM
12039865SSaurabh.Mishra@Sun.COM /* Initialize rx header (len, flags) */
12049865SSaurabh.Mishra@Sun.COM bzero(r->r_buf_dma[i].addr, sizeof (bfe_rx_header_t));
12059865SSaurabh.Mishra@Sun.COM
12069865SSaurabh.Mishra@Sun.COM (void) SYNC_BUF(r, i, 0, sizeof (bfe_rx_header_t),
12079865SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORDEV);
12089865SSaurabh.Mishra@Sun.COM }
12099865SSaurabh.Mishra@Sun.COM
12109865SSaurabh.Mishra@Sun.COM v = GET_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl));
12119865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl),
12129865SSaurabh.Mishra@Sun.COM v | BFE_DESC_EOT);
12139865SSaurabh.Mishra@Sun.COM
12149865SSaurabh.Mishra@Sun.COM (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV);
12159865SSaurabh.Mishra@Sun.COM
12169865SSaurabh.Mishra@Sun.COM /* TAIL of RX Descriptor */
12179865SSaurabh.Mishra@Sun.COM OUTL(r->r_bfe, BFE_DMARX_PTR, ((i) * sizeof (bfe_desc_t)));
12189865SSaurabh.Mishra@Sun.COM
12199865SSaurabh.Mishra@Sun.COM r->r_curr_desc = 0;
12209865SSaurabh.Mishra@Sun.COM r->r_avail_desc = RX_NUM_DESC;
12219865SSaurabh.Mishra@Sun.COM }
12229865SSaurabh.Mishra@Sun.COM
12239865SSaurabh.Mishra@Sun.COM static int
bfe_chip_start(bfe_t * bfe)12249865SSaurabh.Mishra@Sun.COM bfe_chip_start(bfe_t *bfe)
12259865SSaurabh.Mishra@Sun.COM {
122610591SSaurabh.Mishra@Sun.COM ASSERT_ALL_LOCKS(bfe);
12279865SSaurabh.Mishra@Sun.COM
12289865SSaurabh.Mishra@Sun.COM /*
12299865SSaurabh.Mishra@Sun.COM * Stop the chip first & then Reset the chip. At last enable interrupts.
12309865SSaurabh.Mishra@Sun.COM */
12319865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe);
12329865SSaurabh.Mishra@Sun.COM bfe_stop_phy(bfe);
12339865SSaurabh.Mishra@Sun.COM
12349865SSaurabh.Mishra@Sun.COM /*
12359865SSaurabh.Mishra@Sun.COM * Reset chip and start PHY.
12369865SSaurabh.Mishra@Sun.COM */
12379865SSaurabh.Mishra@Sun.COM bfe_chip_reset(bfe);
12389865SSaurabh.Mishra@Sun.COM
12399865SSaurabh.Mishra@Sun.COM /*
12409865SSaurabh.Mishra@Sun.COM * Initailize Descriptor Rings.
12419865SSaurabh.Mishra@Sun.COM */
12429865SSaurabh.Mishra@Sun.COM bfe_tx_desc_init(&bfe->bfe_tx_ring);
12439865SSaurabh.Mishra@Sun.COM bfe_rx_desc_init(&bfe->bfe_rx_ring);
12449865SSaurabh.Mishra@Sun.COM
12459865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_ACTIVE;
12469865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_mode |= BFE_RX_MODE_ENABLE;
12479865SSaurabh.Mishra@Sun.COM bfe_set_rx_mode(bfe);
12489865SSaurabh.Mishra@Sun.COM bfe_enable_chip_intrs(bfe);
12499865SSaurabh.Mishra@Sun.COM
12509865SSaurabh.Mishra@Sun.COM /* Check link, speed and duplex mode */
12519865SSaurabh.Mishra@Sun.COM (void) bfe_check_link(bfe);
12529865SSaurabh.Mishra@Sun.COM
12539865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
12549865SSaurabh.Mishra@Sun.COM }
12559865SSaurabh.Mishra@Sun.COM
12569865SSaurabh.Mishra@Sun.COM
12579865SSaurabh.Mishra@Sun.COM /*
12589865SSaurabh.Mishra@Sun.COM * Clear chip statistics.
12599865SSaurabh.Mishra@Sun.COM */
12609865SSaurabh.Mishra@Sun.COM static void
bfe_clear_stats(bfe_t * bfe)12619865SSaurabh.Mishra@Sun.COM bfe_clear_stats(bfe_t *bfe)
12629865SSaurabh.Mishra@Sun.COM {
12639865SSaurabh.Mishra@Sun.COM ulong_t r;
12649865SSaurabh.Mishra@Sun.COM
12659865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_MIB_CTRL, BFE_MIB_CLR_ON_READ);
12669865SSaurabh.Mishra@Sun.COM
12679865SSaurabh.Mishra@Sun.COM /*
12689865SSaurabh.Mishra@Sun.COM * Stat registers are cleared by reading.
12699865SSaurabh.Mishra@Sun.COM */
12709865SSaurabh.Mishra@Sun.COM for (r = BFE_TX_GOOD_O; r <= BFE_TX_PAUSE; r += 4)
12719865SSaurabh.Mishra@Sun.COM (void) INL(bfe, r);
12729865SSaurabh.Mishra@Sun.COM
12739865SSaurabh.Mishra@Sun.COM for (r = BFE_RX_GOOD_O; r <= BFE_RX_NPAUSE; r += 4)
12749865SSaurabh.Mishra@Sun.COM (void) INL(bfe, r);
12759865SSaurabh.Mishra@Sun.COM }
12769865SSaurabh.Mishra@Sun.COM
12779865SSaurabh.Mishra@Sun.COM /*
12789865SSaurabh.Mishra@Sun.COM * Collect chip statistics.
12799865SSaurabh.Mishra@Sun.COM */
12809865SSaurabh.Mishra@Sun.COM static void
bfe_gather_stats(bfe_t * bfe)12819865SSaurabh.Mishra@Sun.COM bfe_gather_stats(bfe_t *bfe)
12829865SSaurabh.Mishra@Sun.COM {
12839865SSaurabh.Mishra@Sun.COM ulong_t r;
12849865SSaurabh.Mishra@Sun.COM uint32_t *v;
12859865SSaurabh.Mishra@Sun.COM uint32_t txerr = 0, rxerr = 0, coll = 0;
12869865SSaurabh.Mishra@Sun.COM
12879865SSaurabh.Mishra@Sun.COM v = &bfe->bfe_hw_stats.tx_good_octets;
12889865SSaurabh.Mishra@Sun.COM for (r = BFE_TX_GOOD_O; r <= BFE_TX_PAUSE; r += 4) {
12899865SSaurabh.Mishra@Sun.COM *v += INL(bfe, r);
12909865SSaurabh.Mishra@Sun.COM v++;
12919865SSaurabh.Mishra@Sun.COM }
12929865SSaurabh.Mishra@Sun.COM
12939865SSaurabh.Mishra@Sun.COM v = &bfe->bfe_hw_stats.rx_good_octets;
12949865SSaurabh.Mishra@Sun.COM for (r = BFE_RX_GOOD_O; r <= BFE_RX_NPAUSE; r += 4) {
12959865SSaurabh.Mishra@Sun.COM *v += INL(bfe, r);
12969865SSaurabh.Mishra@Sun.COM v++;
12979865SSaurabh.Mishra@Sun.COM }
12989865SSaurabh.Mishra@Sun.COM
12999865SSaurabh.Mishra@Sun.COM /*
13009865SSaurabh.Mishra@Sun.COM * TX :
13019865SSaurabh.Mishra@Sun.COM * -------
13029865SSaurabh.Mishra@Sun.COM * tx_good_octets, tx_good_pkts, tx_octets
13039865SSaurabh.Mishra@Sun.COM * tx_pkts, tx_broadcast_pkts, tx_multicast_pkts
13049865SSaurabh.Mishra@Sun.COM * tx_len_64, tx_len_65_to_127, tx_len_128_to_255
13059865SSaurabh.Mishra@Sun.COM * tx_len_256_to_511, tx_len_512_to_1023, tx_len_1024_to_max
13069865SSaurabh.Mishra@Sun.COM * tx_jabber_pkts, tx_oversize_pkts, tx_fragment_pkts
13079865SSaurabh.Mishra@Sun.COM * tx_underruns, tx_total_cols, tx_single_cols
13089865SSaurabh.Mishra@Sun.COM * tx_multiple_cols, tx_excessive_cols, tx_late_cols
13099865SSaurabh.Mishra@Sun.COM * tx_defered, tx_carrier_lost, tx_pause_pkts
13109865SSaurabh.Mishra@Sun.COM *
13119865SSaurabh.Mishra@Sun.COM * RX :
13129865SSaurabh.Mishra@Sun.COM * -------
13139865SSaurabh.Mishra@Sun.COM * rx_good_octets, rx_good_pkts, rx_octets
13149865SSaurabh.Mishra@Sun.COM * rx_pkts, rx_broadcast_pkts, rx_multicast_pkts
13159865SSaurabh.Mishra@Sun.COM * rx_len_64, rx_len_65_to_127, rx_len_128_to_255
13169865SSaurabh.Mishra@Sun.COM * rx_len_256_to_511, rx_len_512_to_1023, rx_len_1024_to_max
13179865SSaurabh.Mishra@Sun.COM * rx_jabber_pkts, rx_oversize_pkts, rx_fragment_pkts
13189865SSaurabh.Mishra@Sun.COM * rx_missed_pkts, rx_crc_align_errs, rx_undersize
13199865SSaurabh.Mishra@Sun.COM * rx_crc_errs, rx_align_errs, rx_symbol_errs
13209865SSaurabh.Mishra@Sun.COM * rx_pause_pkts, rx_nonpause_pkts
13219865SSaurabh.Mishra@Sun.COM */
13229865SSaurabh.Mishra@Sun.COM
13239865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_carrier_errors =
13249865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.tx_carrier_lost;
13259865SSaurabh.Mishra@Sun.COM
13269865SSaurabh.Mishra@Sun.COM /* txerr += bfe->bfe_hw_stats.tx_carrier_lost; */
13279865SSaurabh.Mishra@Sun.COM
13289865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_ex_collisions =
13299865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.tx_excessive_cols;
13309865SSaurabh.Mishra@Sun.COM txerr += bfe->bfe_hw_stats.tx_excessive_cols;
13319865SSaurabh.Mishra@Sun.COM coll += bfe->bfe_hw_stats.tx_excessive_cols;
13329865SSaurabh.Mishra@Sun.COM
13339865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_fcs_errors =
13349865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.rx_crc_errs;
13359865SSaurabh.Mishra@Sun.COM rxerr += bfe->bfe_hw_stats.rx_crc_errs;
13369865SSaurabh.Mishra@Sun.COM
13379865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_first_collisions =
13389865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.tx_single_cols;
13399865SSaurabh.Mishra@Sun.COM coll += bfe->bfe_hw_stats.tx_single_cols;
13409865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_multi_collisions =
13419865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.tx_multiple_cols;
13429865SSaurabh.Mishra@Sun.COM coll += bfe->bfe_hw_stats.tx_multiple_cols;
13439865SSaurabh.Mishra@Sun.COM
13449865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_toolong_errors =
13459865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.rx_oversize_pkts;
13469865SSaurabh.Mishra@Sun.COM rxerr += bfe->bfe_hw_stats.rx_oversize_pkts;
13479865SSaurabh.Mishra@Sun.COM
13489865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_tooshort_errors =
13499865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.rx_undersize;
13509865SSaurabh.Mishra@Sun.COM rxerr += bfe->bfe_hw_stats.rx_undersize;
13519865SSaurabh.Mishra@Sun.COM
13529865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_tx_late_collisions +=
13539865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.tx_late_cols;
13549865SSaurabh.Mishra@Sun.COM
13559865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_defer_xmts +=
13569865SSaurabh.Mishra@Sun.COM bfe->bfe_hw_stats.tx_defered;
13579865SSaurabh.Mishra@Sun.COM
13589865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_macrcv_errors += rxerr;
13599865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_macxmt_errors += txerr;
13609865SSaurabh.Mishra@Sun.COM
13619865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.collisions += coll;
13629865SSaurabh.Mishra@Sun.COM }
13639865SSaurabh.Mishra@Sun.COM
13649865SSaurabh.Mishra@Sun.COM /*
13659865SSaurabh.Mishra@Sun.COM * Gets the state for dladm command and all.
13669865SSaurabh.Mishra@Sun.COM */
13679865SSaurabh.Mishra@Sun.COM int
bfe_mac_getstat(void * arg,uint_t stat,uint64_t * val)13689865SSaurabh.Mishra@Sun.COM bfe_mac_getstat(void *arg, uint_t stat, uint64_t *val)
13699865SSaurabh.Mishra@Sun.COM {
13709865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
13719865SSaurabh.Mishra@Sun.COM uint64_t v;
13729865SSaurabh.Mishra@Sun.COM int err = 0;
13739865SSaurabh.Mishra@Sun.COM
13749865SSaurabh.Mishra@Sun.COM rw_enter(&bfe->bfe_rwlock, RW_READER);
13759865SSaurabh.Mishra@Sun.COM
13769865SSaurabh.Mishra@Sun.COM
13779865SSaurabh.Mishra@Sun.COM switch (stat) {
13789865SSaurabh.Mishra@Sun.COM default:
13799865SSaurabh.Mishra@Sun.COM err = ENOTSUP;
13809865SSaurabh.Mishra@Sun.COM break;
13819865SSaurabh.Mishra@Sun.COM
13829865SSaurabh.Mishra@Sun.COM case MAC_STAT_IFSPEED:
13839865SSaurabh.Mishra@Sun.COM /*
13849865SSaurabh.Mishra@Sun.COM * MAC layer will ask for IFSPEED first and hence we
13859865SSaurabh.Mishra@Sun.COM * collect it only once.
13869865SSaurabh.Mishra@Sun.COM */
13879865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state == BFE_CHIP_ACTIVE) {
13889865SSaurabh.Mishra@Sun.COM /*
13899865SSaurabh.Mishra@Sun.COM * Update stats from the hardware.
13909865SSaurabh.Mishra@Sun.COM */
13919865SSaurabh.Mishra@Sun.COM bfe_gather_stats(bfe);
13929865SSaurabh.Mishra@Sun.COM }
13939865SSaurabh.Mishra@Sun.COM v = bfe->bfe_chip.speed;
13949865SSaurabh.Mishra@Sun.COM break;
13959865SSaurabh.Mishra@Sun.COM
13969865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_CAP_100T4:
13979865SSaurabh.Mishra@Sun.COM v = bfe->bfe_adv_100T4;
13989865SSaurabh.Mishra@Sun.COM break;
13999865SSaurabh.Mishra@Sun.COM
14009865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_CAP_100FDX:
14019865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anar & MII_ABILITY_100BASE_TX_FD) != 0;
14029865SSaurabh.Mishra@Sun.COM break;
14039865SSaurabh.Mishra@Sun.COM
14049865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_CAP_100HDX:
14059865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anar & MII_ABILITY_100BASE_TX) != 0;
14069865SSaurabh.Mishra@Sun.COM break;
14079865SSaurabh.Mishra@Sun.COM
14089865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_CAP_10FDX:
14099865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anar & MII_ABILITY_10BASE_T_FD) != 0;
14109865SSaurabh.Mishra@Sun.COM break;
14119865SSaurabh.Mishra@Sun.COM
14129865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_CAP_10HDX:
14139865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anar & MII_ABILITY_10BASE_T) != 0;
14149865SSaurabh.Mishra@Sun.COM break;
14159865SSaurabh.Mishra@Sun.COM
14169865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_CAP_ASMPAUSE:
14179865SSaurabh.Mishra@Sun.COM v = 0;
14189865SSaurabh.Mishra@Sun.COM break;
14199865SSaurabh.Mishra@Sun.COM
14209865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_CAP_AUTONEG:
14219865SSaurabh.Mishra@Sun.COM v = bfe->bfe_adv_aneg;
14229865SSaurabh.Mishra@Sun.COM break;
14239865SSaurabh.Mishra@Sun.COM
14249865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_CAP_PAUSE:
14259865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anar & MII_ABILITY_PAUSE) != 0;
14269865SSaurabh.Mishra@Sun.COM break;
14279865SSaurabh.Mishra@Sun.COM
14289865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ADV_REMFAULT:
14299865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anar & MII_AN_ADVERT_REMFAULT) != 0;
14309865SSaurabh.Mishra@Sun.COM break;
14319865SSaurabh.Mishra@Sun.COM
14329865SSaurabh.Mishra@Sun.COM case ETHER_STAT_ALIGN_ERRORS:
14339865SSaurabh.Mishra@Sun.COM /* MIB */
14349865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_align_errors;
14359865SSaurabh.Mishra@Sun.COM break;
14369865SSaurabh.Mishra@Sun.COM
14379865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_100T4:
14389865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_bmsr & MII_STATUS_100_BASE_T4) != 0;
14399865SSaurabh.Mishra@Sun.COM break;
14409865SSaurabh.Mishra@Sun.COM
14419865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_100FDX:
14429865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_bmsr & MII_STATUS_100_BASEX_FD) != 0;
14439865SSaurabh.Mishra@Sun.COM break;
14449865SSaurabh.Mishra@Sun.COM
14459865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_100HDX:
14469865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_bmsr & MII_STATUS_100_BASEX) != 0;
14479865SSaurabh.Mishra@Sun.COM break;
14489865SSaurabh.Mishra@Sun.COM
14499865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_10FDX:
14509865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_bmsr & MII_STATUS_10_FD) != 0;
14519865SSaurabh.Mishra@Sun.COM break;
14529865SSaurabh.Mishra@Sun.COM
14539865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_10HDX:
14549865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_bmsr & MII_STATUS_10) != 0;
14559865SSaurabh.Mishra@Sun.COM break;
14569865SSaurabh.Mishra@Sun.COM
14579865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_ASMPAUSE:
14589865SSaurabh.Mishra@Sun.COM v = 0;
14599865SSaurabh.Mishra@Sun.COM break;
14609865SSaurabh.Mishra@Sun.COM
14619865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_AUTONEG:
14629865SSaurabh.Mishra@Sun.COM v = ((bfe->bfe_mii_bmsr & MII_STATUS_CANAUTONEG) != 0);
14639865SSaurabh.Mishra@Sun.COM break;
14649865SSaurabh.Mishra@Sun.COM
14659865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_PAUSE:
14669865SSaurabh.Mishra@Sun.COM v = 1;
14679865SSaurabh.Mishra@Sun.COM break;
14689865SSaurabh.Mishra@Sun.COM
14699865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CAP_REMFAULT:
14709865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_bmsr & MII_STATUS_REMFAULT) != 0;
14719865SSaurabh.Mishra@Sun.COM break;
14729865SSaurabh.Mishra@Sun.COM
14739865SSaurabh.Mishra@Sun.COM case ETHER_STAT_CARRIER_ERRORS:
14749865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_carrier_errors;
14759865SSaurabh.Mishra@Sun.COM break;
14769865SSaurabh.Mishra@Sun.COM
14779865SSaurabh.Mishra@Sun.COM case ETHER_STAT_JABBER_ERRORS:
14789865SSaurabh.Mishra@Sun.COM err = ENOTSUP;
14799865SSaurabh.Mishra@Sun.COM break;
14809865SSaurabh.Mishra@Sun.COM
14819865SSaurabh.Mishra@Sun.COM case ETHER_STAT_DEFER_XMTS:
14829865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_defer_xmts;
14839865SSaurabh.Mishra@Sun.COM break;
14849865SSaurabh.Mishra@Sun.COM
14859865SSaurabh.Mishra@Sun.COM case ETHER_STAT_EX_COLLISIONS:
14869865SSaurabh.Mishra@Sun.COM /* MIB */
14879865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_ex_collisions;
14889865SSaurabh.Mishra@Sun.COM break;
14899865SSaurabh.Mishra@Sun.COM
14909865SSaurabh.Mishra@Sun.COM case ETHER_STAT_FCS_ERRORS:
14919865SSaurabh.Mishra@Sun.COM /* MIB */
14929865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_fcs_errors;
14939865SSaurabh.Mishra@Sun.COM break;
14949865SSaurabh.Mishra@Sun.COM
14959865SSaurabh.Mishra@Sun.COM case ETHER_STAT_FIRST_COLLISIONS:
14969865SSaurabh.Mishra@Sun.COM /* MIB */
14979865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_first_collisions;
14989865SSaurabh.Mishra@Sun.COM break;
14999865SSaurabh.Mishra@Sun.COM
15009865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LINK_ASMPAUSE:
15019865SSaurabh.Mishra@Sun.COM v = 0;
15029865SSaurabh.Mishra@Sun.COM break;
15039865SSaurabh.Mishra@Sun.COM
15049865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LINK_AUTONEG:
15059865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_bmcr & MII_CONTROL_ANE) != 0 &&
15069865SSaurabh.Mishra@Sun.COM (bfe->bfe_mii_bmsr & MII_STATUS_ANDONE) != 0;
15079865SSaurabh.Mishra@Sun.COM break;
15089865SSaurabh.Mishra@Sun.COM
15099865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LINK_DUPLEX:
15109865SSaurabh.Mishra@Sun.COM v = bfe->bfe_chip.duplex;
15119865SSaurabh.Mishra@Sun.COM break;
15129865SSaurabh.Mishra@Sun.COM
15139865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_CAP_100T4:
15149865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anlpar & MII_ABILITY_100BASE_T4) != 0;
15159865SSaurabh.Mishra@Sun.COM break;
15169865SSaurabh.Mishra@Sun.COM
15179865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_CAP_100FDX:
15189865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anlpar & MII_ABILITY_100BASE_TX_FD) != 0;
15199865SSaurabh.Mishra@Sun.COM break;
15209865SSaurabh.Mishra@Sun.COM
15219865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_CAP_100HDX:
15229865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anlpar & MII_ABILITY_100BASE_TX) != 0;
15239865SSaurabh.Mishra@Sun.COM break;
15249865SSaurabh.Mishra@Sun.COM
15259865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_CAP_10FDX:
15269865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anlpar & MII_ABILITY_10BASE_T_FD) != 0;
15279865SSaurabh.Mishra@Sun.COM break;
15289865SSaurabh.Mishra@Sun.COM
15299865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_CAP_10HDX:
15309865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anlpar & MII_ABILITY_10BASE_T) != 0;
15319865SSaurabh.Mishra@Sun.COM break;
15329865SSaurabh.Mishra@Sun.COM
15339865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_CAP_ASMPAUSE:
15349865SSaurabh.Mishra@Sun.COM v = 0;
15359865SSaurabh.Mishra@Sun.COM break;
15369865SSaurabh.Mishra@Sun.COM
15379865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_CAP_AUTONEG:
15389865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_exp & MII_AN_EXP_LPCANAN) != 0;
15399865SSaurabh.Mishra@Sun.COM break;
15409865SSaurabh.Mishra@Sun.COM
15419865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_CAP_PAUSE:
15429865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anlpar & MII_ABILITY_PAUSE) != 0;
15439865SSaurabh.Mishra@Sun.COM break;
15449865SSaurabh.Mishra@Sun.COM
15459865SSaurabh.Mishra@Sun.COM case ETHER_STAT_LP_REMFAULT:
15469865SSaurabh.Mishra@Sun.COM v = (bfe->bfe_mii_anlpar & MII_STATUS_REMFAULT) != 0;
15479865SSaurabh.Mishra@Sun.COM break;
15489865SSaurabh.Mishra@Sun.COM
15499865SSaurabh.Mishra@Sun.COM case ETHER_STAT_MACRCV_ERRORS:
15509865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_macrcv_errors;
15519865SSaurabh.Mishra@Sun.COM break;
15529865SSaurabh.Mishra@Sun.COM
15539865SSaurabh.Mishra@Sun.COM case ETHER_STAT_MACXMT_ERRORS:
15549865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_macxmt_errors;
15559865SSaurabh.Mishra@Sun.COM break;
15569865SSaurabh.Mishra@Sun.COM
15579865SSaurabh.Mishra@Sun.COM case ETHER_STAT_MULTI_COLLISIONS:
15589865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_multi_collisions;
15599865SSaurabh.Mishra@Sun.COM break;
15609865SSaurabh.Mishra@Sun.COM
15619865SSaurabh.Mishra@Sun.COM case ETHER_STAT_SQE_ERRORS:
15629865SSaurabh.Mishra@Sun.COM err = ENOTSUP;
15639865SSaurabh.Mishra@Sun.COM break;
15649865SSaurabh.Mishra@Sun.COM
15659865SSaurabh.Mishra@Sun.COM case ETHER_STAT_TOOLONG_ERRORS:
15669865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_toolong_errors;
15679865SSaurabh.Mishra@Sun.COM break;
15689865SSaurabh.Mishra@Sun.COM
15699865SSaurabh.Mishra@Sun.COM case ETHER_STAT_TOOSHORT_ERRORS:
15709865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_tooshort_errors;
15719865SSaurabh.Mishra@Sun.COM break;
15729865SSaurabh.Mishra@Sun.COM
15739865SSaurabh.Mishra@Sun.COM case ETHER_STAT_TX_LATE_COLLISIONS:
15749865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_tx_late_collisions;
15759865SSaurabh.Mishra@Sun.COM break;
15769865SSaurabh.Mishra@Sun.COM
15779865SSaurabh.Mishra@Sun.COM case ETHER_STAT_XCVR_ADDR:
15789865SSaurabh.Mishra@Sun.COM v = bfe->bfe_phy_addr;
15799865SSaurabh.Mishra@Sun.COM break;
15809865SSaurabh.Mishra@Sun.COM
15819865SSaurabh.Mishra@Sun.COM case ETHER_STAT_XCVR_ID:
15829865SSaurabh.Mishra@Sun.COM v = bfe->bfe_phy_id;
15839865SSaurabh.Mishra@Sun.COM break;
15849865SSaurabh.Mishra@Sun.COM
15859865SSaurabh.Mishra@Sun.COM case MAC_STAT_BRDCSTRCV:
15869865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.brdcstrcv;
15879865SSaurabh.Mishra@Sun.COM break;
15889865SSaurabh.Mishra@Sun.COM
15899865SSaurabh.Mishra@Sun.COM case MAC_STAT_BRDCSTXMT:
15909865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.brdcstxmt;
15919865SSaurabh.Mishra@Sun.COM break;
15929865SSaurabh.Mishra@Sun.COM
15939865SSaurabh.Mishra@Sun.COM case MAC_STAT_MULTIXMT:
15949865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.multixmt;
15959865SSaurabh.Mishra@Sun.COM break;
15969865SSaurabh.Mishra@Sun.COM
15979865SSaurabh.Mishra@Sun.COM case MAC_STAT_COLLISIONS:
15989865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.collisions;
15999865SSaurabh.Mishra@Sun.COM break;
16009865SSaurabh.Mishra@Sun.COM
16019865SSaurabh.Mishra@Sun.COM case MAC_STAT_IERRORS:
16029865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ierrors;
16039865SSaurabh.Mishra@Sun.COM break;
16049865SSaurabh.Mishra@Sun.COM
16059865SSaurabh.Mishra@Sun.COM case MAC_STAT_IPACKETS:
16069865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ipackets;
16079865SSaurabh.Mishra@Sun.COM break;
16089865SSaurabh.Mishra@Sun.COM
16099865SSaurabh.Mishra@Sun.COM case MAC_STAT_MULTIRCV:
16109865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.multircv;
16119865SSaurabh.Mishra@Sun.COM break;
16129865SSaurabh.Mishra@Sun.COM
16139865SSaurabh.Mishra@Sun.COM case MAC_STAT_NORCVBUF:
16149865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.norcvbuf;
16159865SSaurabh.Mishra@Sun.COM break;
16169865SSaurabh.Mishra@Sun.COM
16179865SSaurabh.Mishra@Sun.COM case MAC_STAT_NOXMTBUF:
16189865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.noxmtbuf;
16199865SSaurabh.Mishra@Sun.COM break;
16209865SSaurabh.Mishra@Sun.COM
16219865SSaurabh.Mishra@Sun.COM case MAC_STAT_OBYTES:
16229865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.obytes;
16239865SSaurabh.Mishra@Sun.COM break;
16249865SSaurabh.Mishra@Sun.COM
16259865SSaurabh.Mishra@Sun.COM case MAC_STAT_OERRORS:
16269865SSaurabh.Mishra@Sun.COM /* MIB */
16279865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.ether_stat_macxmt_errors;
16289865SSaurabh.Mishra@Sun.COM break;
16299865SSaurabh.Mishra@Sun.COM
16309865SSaurabh.Mishra@Sun.COM case MAC_STAT_OPACKETS:
16319865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.opackets;
16329865SSaurabh.Mishra@Sun.COM break;
16339865SSaurabh.Mishra@Sun.COM
16349865SSaurabh.Mishra@Sun.COM case MAC_STAT_RBYTES:
16359865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.rbytes;
16369865SSaurabh.Mishra@Sun.COM break;
16379865SSaurabh.Mishra@Sun.COM
16389865SSaurabh.Mishra@Sun.COM case MAC_STAT_UNDERFLOWS:
16399865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.underflows;
16409865SSaurabh.Mishra@Sun.COM break;
16419865SSaurabh.Mishra@Sun.COM
16429865SSaurabh.Mishra@Sun.COM case MAC_STAT_OVERFLOWS:
16439865SSaurabh.Mishra@Sun.COM v = bfe->bfe_stats.overflows;
16449865SSaurabh.Mishra@Sun.COM break;
16459865SSaurabh.Mishra@Sun.COM }
16469865SSaurabh.Mishra@Sun.COM
16479865SSaurabh.Mishra@Sun.COM rw_exit(&bfe->bfe_rwlock);
16489865SSaurabh.Mishra@Sun.COM
16499865SSaurabh.Mishra@Sun.COM *val = v;
16509865SSaurabh.Mishra@Sun.COM return (err);
16519865SSaurabh.Mishra@Sun.COM }
16529865SSaurabh.Mishra@Sun.COM
16539865SSaurabh.Mishra@Sun.COM int
bfe_mac_getprop(void * arg,const char * name,mac_prop_id_t num,uint_t sz,void * val)165411878SVenu.Iyer@Sun.COM bfe_mac_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
165511878SVenu.Iyer@Sun.COM void *val)
16569865SSaurabh.Mishra@Sun.COM {
16579865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
16589865SSaurabh.Mishra@Sun.COM int err = 0;
165911878SVenu.Iyer@Sun.COM
16609865SSaurabh.Mishra@Sun.COM switch (num) {
16619865SSaurabh.Mishra@Sun.COM case MAC_PROP_DUPLEX:
166211878SVenu.Iyer@Sun.COM ASSERT(sz >= sizeof (link_duplex_t));
166311878SVenu.Iyer@Sun.COM bcopy(&bfe->bfe_chip.duplex, val, sizeof (link_duplex_t));
16649865SSaurabh.Mishra@Sun.COM break;
16659865SSaurabh.Mishra@Sun.COM
16669865SSaurabh.Mishra@Sun.COM case MAC_PROP_SPEED:
166711878SVenu.Iyer@Sun.COM ASSERT(sz >= sizeof (uint64_t));
166811878SVenu.Iyer@Sun.COM bcopy(&bfe->bfe_chip.speed, val, sizeof (uint64_t));
16699865SSaurabh.Mishra@Sun.COM break;
16709865SSaurabh.Mishra@Sun.COM
16719865SSaurabh.Mishra@Sun.COM case MAC_PROP_AUTONEG:
167211878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_aneg;
16739865SSaurabh.Mishra@Sun.COM break;
16749865SSaurabh.Mishra@Sun.COM
16759865SSaurabh.Mishra@Sun.COM case MAC_PROP_ADV_100FDX_CAP:
167611878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_100fdx;
16779865SSaurabh.Mishra@Sun.COM break;
167811878SVenu.Iyer@Sun.COM
16799865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_100FDX_CAP:
168011878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_100fdx;
16819865SSaurabh.Mishra@Sun.COM break;
16829865SSaurabh.Mishra@Sun.COM
16839865SSaurabh.Mishra@Sun.COM case MAC_PROP_ADV_100HDX_CAP:
168411878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_100hdx;
16859865SSaurabh.Mishra@Sun.COM break;
168611878SVenu.Iyer@Sun.COM
16879865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_100HDX_CAP:
168811878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_100hdx;
16899865SSaurabh.Mishra@Sun.COM break;
16909865SSaurabh.Mishra@Sun.COM
16919865SSaurabh.Mishra@Sun.COM case MAC_PROP_ADV_10FDX_CAP:
169211878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_10fdx;
16939865SSaurabh.Mishra@Sun.COM break;
169411878SVenu.Iyer@Sun.COM
16959865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_10FDX_CAP:
169611878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_10fdx;
16979865SSaurabh.Mishra@Sun.COM break;
16989865SSaurabh.Mishra@Sun.COM
16999865SSaurabh.Mishra@Sun.COM case MAC_PROP_ADV_10HDX_CAP:
170011878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_10hdx;
17019865SSaurabh.Mishra@Sun.COM break;
170211878SVenu.Iyer@Sun.COM
17039865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_10HDX_CAP:
170411878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_10hdx;
17059865SSaurabh.Mishra@Sun.COM break;
17069865SSaurabh.Mishra@Sun.COM
17079865SSaurabh.Mishra@Sun.COM case MAC_PROP_ADV_100T4_CAP:
170811878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_100T4;
17099865SSaurabh.Mishra@Sun.COM break;
171011878SVenu.Iyer@Sun.COM
17119865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_100T4_CAP:
171211878SVenu.Iyer@Sun.COM *(uint8_t *)val = bfe->bfe_adv_100T4;
17139865SSaurabh.Mishra@Sun.COM break;
17149865SSaurabh.Mishra@Sun.COM
17159865SSaurabh.Mishra@Sun.COM default:
17169865SSaurabh.Mishra@Sun.COM err = ENOTSUP;
17179865SSaurabh.Mishra@Sun.COM }
17189865SSaurabh.Mishra@Sun.COM
17199865SSaurabh.Mishra@Sun.COM return (err);
17209865SSaurabh.Mishra@Sun.COM }
17219865SSaurabh.Mishra@Sun.COM
172211878SVenu.Iyer@Sun.COM
172311878SVenu.Iyer@Sun.COM static void
bfe_mac_propinfo(void * arg,const char * name,mac_prop_id_t num,mac_prop_info_handle_t prh)172411878SVenu.Iyer@Sun.COM bfe_mac_propinfo(void *arg, const char *name, mac_prop_id_t num,
172511878SVenu.Iyer@Sun.COM mac_prop_info_handle_t prh)
172611878SVenu.Iyer@Sun.COM {
172711878SVenu.Iyer@Sun.COM bfe_t *bfe = (bfe_t *)arg;
172811878SVenu.Iyer@Sun.COM
172911878SVenu.Iyer@Sun.COM switch (num) {
173011878SVenu.Iyer@Sun.COM case MAC_PROP_DUPLEX:
173111878SVenu.Iyer@Sun.COM case MAC_PROP_SPEED:
173211878SVenu.Iyer@Sun.COM case MAC_PROP_ADV_100FDX_CAP:
173311878SVenu.Iyer@Sun.COM case MAC_PROP_ADV_100HDX_CAP:
173411878SVenu.Iyer@Sun.COM case MAC_PROP_ADV_10FDX_CAP:
173511878SVenu.Iyer@Sun.COM case MAC_PROP_ADV_10HDX_CAP:
173611878SVenu.Iyer@Sun.COM case MAC_PROP_ADV_100T4_CAP:
1737*12917SCrisson.Hu@Sun.COM case MAC_PROP_EN_100T4_CAP:
173811878SVenu.Iyer@Sun.COM mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
173911878SVenu.Iyer@Sun.COM break;
174011878SVenu.Iyer@Sun.COM
174111878SVenu.Iyer@Sun.COM case MAC_PROP_AUTONEG:
174211878SVenu.Iyer@Sun.COM mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_aneg);
174311878SVenu.Iyer@Sun.COM break;
174411878SVenu.Iyer@Sun.COM
174511878SVenu.Iyer@Sun.COM case MAC_PROP_EN_100FDX_CAP:
174611878SVenu.Iyer@Sun.COM mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_100fdx);
174711878SVenu.Iyer@Sun.COM break;
174811878SVenu.Iyer@Sun.COM
174911878SVenu.Iyer@Sun.COM case MAC_PROP_EN_100HDX_CAP:
175011878SVenu.Iyer@Sun.COM mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_100hdx);
175111878SVenu.Iyer@Sun.COM break;
175211878SVenu.Iyer@Sun.COM
175311878SVenu.Iyer@Sun.COM case MAC_PROP_EN_10FDX_CAP:
175411878SVenu.Iyer@Sun.COM mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_10fdx);
175511878SVenu.Iyer@Sun.COM break;
175611878SVenu.Iyer@Sun.COM
175711878SVenu.Iyer@Sun.COM case MAC_PROP_EN_10HDX_CAP:
175811878SVenu.Iyer@Sun.COM mac_prop_info_set_default_uint8(prh, bfe->bfe_cap_10hdx);
175911878SVenu.Iyer@Sun.COM break;
176011878SVenu.Iyer@Sun.COM }
176111878SVenu.Iyer@Sun.COM }
176211878SVenu.Iyer@Sun.COM
176311878SVenu.Iyer@Sun.COM
17649865SSaurabh.Mishra@Sun.COM /*ARGSUSED*/
17659865SSaurabh.Mishra@Sun.COM int
bfe_mac_setprop(void * arg,const char * name,mac_prop_id_t num,uint_t sz,const void * val)17669865SSaurabh.Mishra@Sun.COM bfe_mac_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
17679865SSaurabh.Mishra@Sun.COM const void *val)
17689865SSaurabh.Mishra@Sun.COM {
17699865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
17709865SSaurabh.Mishra@Sun.COM uint8_t *advp;
17719865SSaurabh.Mishra@Sun.COM uint8_t *capp;
17729865SSaurabh.Mishra@Sun.COM int r = 0;
17739865SSaurabh.Mishra@Sun.COM
17749865SSaurabh.Mishra@Sun.COM switch (num) {
17759865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_100FDX_CAP:
17769865SSaurabh.Mishra@Sun.COM advp = &bfe->bfe_adv_100fdx;
17779865SSaurabh.Mishra@Sun.COM capp = &bfe->bfe_cap_100fdx;
17789865SSaurabh.Mishra@Sun.COM break;
17799865SSaurabh.Mishra@Sun.COM
17809865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_100HDX_CAP:
17819865SSaurabh.Mishra@Sun.COM advp = &bfe->bfe_adv_100hdx;
17829865SSaurabh.Mishra@Sun.COM capp = &bfe->bfe_cap_100hdx;
17839865SSaurabh.Mishra@Sun.COM break;
17849865SSaurabh.Mishra@Sun.COM
17859865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_10FDX_CAP:
17869865SSaurabh.Mishra@Sun.COM advp = &bfe->bfe_adv_10fdx;
17879865SSaurabh.Mishra@Sun.COM capp = &bfe->bfe_cap_10fdx;
17889865SSaurabh.Mishra@Sun.COM break;
17899865SSaurabh.Mishra@Sun.COM
17909865SSaurabh.Mishra@Sun.COM case MAC_PROP_EN_10HDX_CAP:
17919865SSaurabh.Mishra@Sun.COM advp = &bfe->bfe_adv_10hdx;
17929865SSaurabh.Mishra@Sun.COM capp = &bfe->bfe_cap_10hdx;
17939865SSaurabh.Mishra@Sun.COM break;
17949865SSaurabh.Mishra@Sun.COM
17959865SSaurabh.Mishra@Sun.COM case MAC_PROP_AUTONEG:
17969865SSaurabh.Mishra@Sun.COM advp = &bfe->bfe_adv_aneg;
17979865SSaurabh.Mishra@Sun.COM capp = &bfe->bfe_cap_aneg;
17989865SSaurabh.Mishra@Sun.COM break;
17999865SSaurabh.Mishra@Sun.COM
18009865SSaurabh.Mishra@Sun.COM default:
18019865SSaurabh.Mishra@Sun.COM return (ENOTSUP);
18029865SSaurabh.Mishra@Sun.COM }
18039865SSaurabh.Mishra@Sun.COM
18049865SSaurabh.Mishra@Sun.COM if (*capp == 0)
18059865SSaurabh.Mishra@Sun.COM return (ENOTSUP);
18069865SSaurabh.Mishra@Sun.COM
18079865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
18089865SSaurabh.Mishra@Sun.COM
18099865SSaurabh.Mishra@Sun.COM if (*advp != *(const uint8_t *)val) {
18109865SSaurabh.Mishra@Sun.COM *advp = *(const uint8_t *)val;
18119865SSaurabh.Mishra@Sun.COM
18129865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action = BFE_ACTION_RESTART_SETPROP;
18139865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state == BFE_CHIP_ACTIVE) {
18149865SSaurabh.Mishra@Sun.COM /*
18159865SSaurabh.Mishra@Sun.COM * We need to stop the timer before grabbing locks
18169865SSaurabh.Mishra@Sun.COM * otherwise we can land-up in deadlock with untimeout.
18179865SSaurabh.Mishra@Sun.COM */
18189865SSaurabh.Mishra@Sun.COM bfe_stop_timer(bfe);
18199865SSaurabh.Mishra@Sun.COM
18209865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action |= BFE_ACTION_RESTART;
18219865SSaurabh.Mishra@Sun.COM
18229865SSaurabh.Mishra@Sun.COM bfe_chip_restart(bfe);
18239865SSaurabh.Mishra@Sun.COM
18249865SSaurabh.Mishra@Sun.COM /*
18259865SSaurabh.Mishra@Sun.COM * We leave SETPROP because properties can be
18269865SSaurabh.Mishra@Sun.COM * temporary.
18279865SSaurabh.Mishra@Sun.COM */
18289865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action &= ~(BFE_ACTION_RESTART);
18299865SSaurabh.Mishra@Sun.COM r = 1;
18309865SSaurabh.Mishra@Sun.COM }
18319865SSaurabh.Mishra@Sun.COM }
18329865SSaurabh.Mishra@Sun.COM
18339865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
18349865SSaurabh.Mishra@Sun.COM
18359865SSaurabh.Mishra@Sun.COM /* kick-off a potential stopped downstream */
18369865SSaurabh.Mishra@Sun.COM if (r)
18379865SSaurabh.Mishra@Sun.COM mac_tx_update(bfe->bfe_machdl);
18389865SSaurabh.Mishra@Sun.COM
18399865SSaurabh.Mishra@Sun.COM return (0);
18409865SSaurabh.Mishra@Sun.COM }
18419865SSaurabh.Mishra@Sun.COM
18429865SSaurabh.Mishra@Sun.COM
18439865SSaurabh.Mishra@Sun.COM int
bfe_mac_set_ether_addr(void * arg,const uint8_t * ea)18449865SSaurabh.Mishra@Sun.COM bfe_mac_set_ether_addr(void *arg, const uint8_t *ea)
18459865SSaurabh.Mishra@Sun.COM {
18469865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
18479865SSaurabh.Mishra@Sun.COM
18489865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
18499865SSaurabh.Mishra@Sun.COM bcopy(ea, bfe->bfe_ether_addr, ETHERADDRL);
18509865SSaurabh.Mishra@Sun.COM bfe_set_rx_mode(bfe);
18519865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
18529865SSaurabh.Mishra@Sun.COM return (0);
18539865SSaurabh.Mishra@Sun.COM }
18549865SSaurabh.Mishra@Sun.COM
18559865SSaurabh.Mishra@Sun.COM int
bfe_mac_start(void * arg)18569865SSaurabh.Mishra@Sun.COM bfe_mac_start(void *arg)
18579865SSaurabh.Mishra@Sun.COM {
18589865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
18599865SSaurabh.Mishra@Sun.COM
186010591SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
186110591SSaurabh.Mishra@Sun.COM if (bfe_chip_start(bfe) == DDI_FAILURE) {
186210591SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
18639865SSaurabh.Mishra@Sun.COM return (EINVAL);
186410591SSaurabh.Mishra@Sun.COM }
186510591SSaurabh.Mishra@Sun.COM
186610591SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
186710591SSaurabh.Mishra@Sun.COM
186810591SSaurabh.Mishra@Sun.COM mac_tx_update(bfe->bfe_machdl);
18699865SSaurabh.Mishra@Sun.COM
18709865SSaurabh.Mishra@Sun.COM return (0);
18719865SSaurabh.Mishra@Sun.COM }
18729865SSaurabh.Mishra@Sun.COM
18739865SSaurabh.Mishra@Sun.COM void
bfe_mac_stop(void * arg)18749865SSaurabh.Mishra@Sun.COM bfe_mac_stop(void *arg)
18759865SSaurabh.Mishra@Sun.COM {
18769865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
18779865SSaurabh.Mishra@Sun.COM
18789865SSaurabh.Mishra@Sun.COM /*
18799865SSaurabh.Mishra@Sun.COM * We need to stop the timer before grabbing locks otherwise
18809865SSaurabh.Mishra@Sun.COM * we can land-up in deadlock with untimeout.
18819865SSaurabh.Mishra@Sun.COM */
18829865SSaurabh.Mishra@Sun.COM bfe_stop_timer(bfe);
18839865SSaurabh.Mishra@Sun.COM
18849865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
18859865SSaurabh.Mishra@Sun.COM
18869865SSaurabh.Mishra@Sun.COM /*
18879865SSaurabh.Mishra@Sun.COM * First halt the chip by disabling interrupts.
18889865SSaurabh.Mishra@Sun.COM */
18899865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe);
18909865SSaurabh.Mishra@Sun.COM bfe_stop_phy(bfe);
18919865SSaurabh.Mishra@Sun.COM
18929865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_STOPPED;
18939865SSaurabh.Mishra@Sun.COM
18949865SSaurabh.Mishra@Sun.COM /*
18959865SSaurabh.Mishra@Sun.COM * This will leave the PHY running.
18969865SSaurabh.Mishra@Sun.COM */
18979865SSaurabh.Mishra@Sun.COM bfe_chip_reset(bfe);
18989865SSaurabh.Mishra@Sun.COM
18999865SSaurabh.Mishra@Sun.COM /*
19009865SSaurabh.Mishra@Sun.COM * Disable RX register.
19019865SSaurabh.Mishra@Sun.COM */
19029865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_mode &= ~BFE_RX_MODE_ENABLE;
19039865SSaurabh.Mishra@Sun.COM bfe_set_rx_mode(bfe);
19049865SSaurabh.Mishra@Sun.COM
19059865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
19069865SSaurabh.Mishra@Sun.COM }
19079865SSaurabh.Mishra@Sun.COM
19089865SSaurabh.Mishra@Sun.COM /*
19099865SSaurabh.Mishra@Sun.COM * Send a packet down the wire.
19109865SSaurabh.Mishra@Sun.COM */
19119865SSaurabh.Mishra@Sun.COM static int
bfe_send_a_packet(bfe_t * bfe,mblk_t * mp)19129865SSaurabh.Mishra@Sun.COM bfe_send_a_packet(bfe_t *bfe, mblk_t *mp)
19139865SSaurabh.Mishra@Sun.COM {
19149865SSaurabh.Mishra@Sun.COM bfe_ring_t *r = &bfe->bfe_tx_ring;
19159865SSaurabh.Mishra@Sun.COM uint32_t cur = r->r_curr_desc;
19169865SSaurabh.Mishra@Sun.COM uint32_t next;
19179865SSaurabh.Mishra@Sun.COM size_t pktlen = msgsize(mp);
19189865SSaurabh.Mishra@Sun.COM uchar_t *buf;
19199865SSaurabh.Mishra@Sun.COM uint32_t v;
19209865SSaurabh.Mishra@Sun.COM
19219865SSaurabh.Mishra@Sun.COM ASSERT(MUTEX_HELD(&r->r_lock));
19229865SSaurabh.Mishra@Sun.COM ASSERT(mp != NULL);
19239865SSaurabh.Mishra@Sun.COM
19249865SSaurabh.Mishra@Sun.COM if (pktlen > r->r_buf_len) {
19259865SSaurabh.Mishra@Sun.COM freemsg(mp);
19269865SSaurabh.Mishra@Sun.COM return (BFE_SUCCESS);
19279865SSaurabh.Mishra@Sun.COM }
19289865SSaurabh.Mishra@Sun.COM
19299865SSaurabh.Mishra@Sun.COM /*
19309865SSaurabh.Mishra@Sun.COM * There is a big reason why we don't check for '0'. It becomes easy
19319865SSaurabh.Mishra@Sun.COM * for us to not roll over the ring since we are based on producer (tx)
19329865SSaurabh.Mishra@Sun.COM * and consumer (reclaim by an interrupt) model. Especially when we
19339865SSaurabh.Mishra@Sun.COM * run out of TX descriptor, chip will send a single interrupt and
19349865SSaurabh.Mishra@Sun.COM * both producer and consumer counter will be same. So we keep a
19359865SSaurabh.Mishra@Sun.COM * difference of 1 always.
19369865SSaurabh.Mishra@Sun.COM */
19379865SSaurabh.Mishra@Sun.COM if (r->r_avail_desc <= 1) {
19389865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.noxmtbuf++;
19399865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_resched = 1;
19409865SSaurabh.Mishra@Sun.COM return (BFE_FAILURE);
19419865SSaurabh.Mishra@Sun.COM }
19429865SSaurabh.Mishra@Sun.COM
19439865SSaurabh.Mishra@Sun.COM /*
19449865SSaurabh.Mishra@Sun.COM * Get the DMA buffer to hold packet.
19459865SSaurabh.Mishra@Sun.COM */
19469865SSaurabh.Mishra@Sun.COM buf = (uchar_t *)r->r_buf_dma[cur].addr;
19479865SSaurabh.Mishra@Sun.COM
19489865SSaurabh.Mishra@Sun.COM mcopymsg(mp, buf); /* it also frees mp */
19499865SSaurabh.Mishra@Sun.COM
19509865SSaurabh.Mishra@Sun.COM /*
19519865SSaurabh.Mishra@Sun.COM * Gather statistics.
19529865SSaurabh.Mishra@Sun.COM */
19539865SSaurabh.Mishra@Sun.COM if (buf[0] & 0x1) {
19549865SSaurabh.Mishra@Sun.COM if (bcmp(buf, bfe_broadcast, ETHERADDRL) != 0)
19559865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.multixmt++;
19569865SSaurabh.Mishra@Sun.COM else
19579865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.brdcstxmt++;
19589865SSaurabh.Mishra@Sun.COM }
19599865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.opackets++;
19609865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.obytes += pktlen;
19619865SSaurabh.Mishra@Sun.COM
19629865SSaurabh.Mishra@Sun.COM
19639865SSaurabh.Mishra@Sun.COM /*
19649865SSaurabh.Mishra@Sun.COM * Program the DMA descriptor (start and end of frame are same).
19659865SSaurabh.Mishra@Sun.COM */
19669865SSaurabh.Mishra@Sun.COM next = cur;
19679865SSaurabh.Mishra@Sun.COM v = (pktlen & BFE_DESC_LEN) | BFE_DESC_IOC | BFE_DESC_SOF |
19689865SSaurabh.Mishra@Sun.COM BFE_DESC_EOF;
19699865SSaurabh.Mishra@Sun.COM
19709865SSaurabh.Mishra@Sun.COM if (cur == (TX_NUM_DESC - 1))
19719865SSaurabh.Mishra@Sun.COM v |= BFE_DESC_EOT;
19729865SSaurabh.Mishra@Sun.COM
19739865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[cur].desc_ctl), v);
19749865SSaurabh.Mishra@Sun.COM
19759865SSaurabh.Mishra@Sun.COM /*
19769865SSaurabh.Mishra@Sun.COM * DMA addresses need to be added to BFE_PCI_DMA
19779865SSaurabh.Mishra@Sun.COM */
19789865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[cur].desc_addr),
19799865SSaurabh.Mishra@Sun.COM (r->r_buf_dma[cur].cookie.dmac_laddress + BFE_PCI_DMA));
19809865SSaurabh.Mishra@Sun.COM
19819865SSaurabh.Mishra@Sun.COM /*
19829865SSaurabh.Mishra@Sun.COM * Sync the packet data for the device.
19839865SSaurabh.Mishra@Sun.COM */
19849865SSaurabh.Mishra@Sun.COM (void) SYNC_BUF(r, cur, 0, pktlen, DDI_DMA_SYNC_FORDEV);
19859865SSaurabh.Mishra@Sun.COM
19869865SSaurabh.Mishra@Sun.COM /* Move to next descriptor slot */
19879865SSaurabh.Mishra@Sun.COM BFE_INC_SLOT(next, TX_NUM_DESC);
19889865SSaurabh.Mishra@Sun.COM
19899865SSaurabh.Mishra@Sun.COM (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV);
19909865SSaurabh.Mishra@Sun.COM
19919865SSaurabh.Mishra@Sun.COM r->r_curr_desc = next;
19929865SSaurabh.Mishra@Sun.COM
19939865SSaurabh.Mishra@Sun.COM /*
19949865SSaurabh.Mishra@Sun.COM * The order should be 1,2,3,... for BFE_DMATX_PTR if 0,1,2,3,...
19959865SSaurabh.Mishra@Sun.COM * descriptor slot are being programmed.
19969865SSaurabh.Mishra@Sun.COM */
19979865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_DMATX_PTR, next * sizeof (bfe_desc_t));
19989865SSaurabh.Mishra@Sun.COM FLUSH(bfe, BFE_DMATX_PTR);
19999865SSaurabh.Mishra@Sun.COM
20009865SSaurabh.Mishra@Sun.COM r->r_avail_desc--;
20019865SSaurabh.Mishra@Sun.COM
20029865SSaurabh.Mishra@Sun.COM /*
20039865SSaurabh.Mishra@Sun.COM * Let timeout know that it must reset the chip if a
20049865SSaurabh.Mishra@Sun.COM * packet is not sent down the wire for more than 5 seconds.
20059865SSaurabh.Mishra@Sun.COM */
20069865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_stall_time = gethrtime() + (5 * 1000000000ULL);
20079865SSaurabh.Mishra@Sun.COM
20089865SSaurabh.Mishra@Sun.COM return (BFE_SUCCESS);
20099865SSaurabh.Mishra@Sun.COM }
20109865SSaurabh.Mishra@Sun.COM
20119865SSaurabh.Mishra@Sun.COM mblk_t *
bfe_mac_transmit_packet(void * arg,mblk_t * mp)20129865SSaurabh.Mishra@Sun.COM bfe_mac_transmit_packet(void *arg, mblk_t *mp)
20139865SSaurabh.Mishra@Sun.COM {
20149865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
20159865SSaurabh.Mishra@Sun.COM bfe_ring_t *r = &bfe->bfe_tx_ring;
20169865SSaurabh.Mishra@Sun.COM mblk_t *nmp;
20179865SSaurabh.Mishra@Sun.COM
20189865SSaurabh.Mishra@Sun.COM mutex_enter(&r->r_lock);
20199865SSaurabh.Mishra@Sun.COM
20209865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state != BFE_CHIP_ACTIVE) {
202110591SSaurabh.Mishra@Sun.COM DTRACE_PROBE1(tx__chip__not__active, int, bfe->bfe_unit);
20229865SSaurabh.Mishra@Sun.COM
20239865SSaurabh.Mishra@Sun.COM freemsgchain(mp);
20249865SSaurabh.Mishra@Sun.COM mutex_exit(&r->r_lock);
20259865SSaurabh.Mishra@Sun.COM return (NULL);
20269865SSaurabh.Mishra@Sun.COM }
20279865SSaurabh.Mishra@Sun.COM
20289865SSaurabh.Mishra@Sun.COM
20299865SSaurabh.Mishra@Sun.COM while (mp != NULL) {
20309865SSaurabh.Mishra@Sun.COM nmp = mp->b_next;
20319865SSaurabh.Mishra@Sun.COM mp->b_next = NULL;
20329865SSaurabh.Mishra@Sun.COM
20339865SSaurabh.Mishra@Sun.COM if (bfe_send_a_packet(bfe, mp) == BFE_FAILURE) {
20349865SSaurabh.Mishra@Sun.COM mp->b_next = nmp;
20359865SSaurabh.Mishra@Sun.COM break;
20369865SSaurabh.Mishra@Sun.COM }
20379865SSaurabh.Mishra@Sun.COM mp = nmp;
20389865SSaurabh.Mishra@Sun.COM }
20399865SSaurabh.Mishra@Sun.COM
20409865SSaurabh.Mishra@Sun.COM mutex_exit(&r->r_lock);
20419865SSaurabh.Mishra@Sun.COM
20429865SSaurabh.Mishra@Sun.COM return (mp);
20439865SSaurabh.Mishra@Sun.COM }
20449865SSaurabh.Mishra@Sun.COM
20459865SSaurabh.Mishra@Sun.COM int
bfe_mac_set_promisc(void * arg,boolean_t promiscflag)20469865SSaurabh.Mishra@Sun.COM bfe_mac_set_promisc(void *arg, boolean_t promiscflag)
20479865SSaurabh.Mishra@Sun.COM {
20489865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (bfe_t *)arg;
20499865SSaurabh.Mishra@Sun.COM
20509865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
20519865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state != BFE_CHIP_ACTIVE) {
20529865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
20539865SSaurabh.Mishra@Sun.COM return (EIO);
20549865SSaurabh.Mishra@Sun.COM }
20559865SSaurabh.Mishra@Sun.COM
20569865SSaurabh.Mishra@Sun.COM if (promiscflag) {
20579865SSaurabh.Mishra@Sun.COM /* Set Promiscous on */
20589865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_mode |= BFE_RX_MODE_PROMISC;
20599865SSaurabh.Mishra@Sun.COM } else {
20609865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_mode &= ~BFE_RX_MODE_PROMISC;
20619865SSaurabh.Mishra@Sun.COM }
20629865SSaurabh.Mishra@Sun.COM
20639865SSaurabh.Mishra@Sun.COM bfe_set_rx_mode(bfe);
20649865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
20659865SSaurabh.Mishra@Sun.COM
20669865SSaurabh.Mishra@Sun.COM return (0);
20679865SSaurabh.Mishra@Sun.COM }
20689865SSaurabh.Mishra@Sun.COM
20699865SSaurabh.Mishra@Sun.COM int
bfe_mac_set_multicast(void * arg,boolean_t add,const uint8_t * macaddr)20709865SSaurabh.Mishra@Sun.COM bfe_mac_set_multicast(void *arg, boolean_t add, const uint8_t *macaddr)
20719865SSaurabh.Mishra@Sun.COM {
20729865SSaurabh.Mishra@Sun.COM /*
20739865SSaurabh.Mishra@Sun.COM * It was too much of pain to implement multicast in CAM. Instead
20749865SSaurabh.Mishra@Sun.COM * we never disable multicast filter.
20759865SSaurabh.Mishra@Sun.COM */
20769865SSaurabh.Mishra@Sun.COM return (0);
20779865SSaurabh.Mishra@Sun.COM }
20789865SSaurabh.Mishra@Sun.COM
20799865SSaurabh.Mishra@Sun.COM static mac_callbacks_t bfe_mac_callbacks = {
208011878SVenu.Iyer@Sun.COM MC_SETPROP | MC_GETPROP | MC_PROPINFO,
20819865SSaurabh.Mishra@Sun.COM bfe_mac_getstat, /* gets stats */
20829865SSaurabh.Mishra@Sun.COM bfe_mac_start, /* starts mac */
20839865SSaurabh.Mishra@Sun.COM bfe_mac_stop, /* stops mac */
20849865SSaurabh.Mishra@Sun.COM bfe_mac_set_promisc, /* sets promisc mode for snoop */
20859865SSaurabh.Mishra@Sun.COM bfe_mac_set_multicast, /* multicast implementation */
20869865SSaurabh.Mishra@Sun.COM bfe_mac_set_ether_addr, /* sets ethernet address (unicast) */
20879865SSaurabh.Mishra@Sun.COM bfe_mac_transmit_packet, /* transmits packet */
208811878SVenu.Iyer@Sun.COM NULL,
20899865SSaurabh.Mishra@Sun.COM NULL, /* ioctl */
20909865SSaurabh.Mishra@Sun.COM NULL, /* getcap */
20919865SSaurabh.Mishra@Sun.COM NULL, /* open */
20929865SSaurabh.Mishra@Sun.COM NULL, /* close */
20939865SSaurabh.Mishra@Sun.COM bfe_mac_setprop,
20949865SSaurabh.Mishra@Sun.COM bfe_mac_getprop,
209511878SVenu.Iyer@Sun.COM bfe_mac_propinfo
20969865SSaurabh.Mishra@Sun.COM };
20979865SSaurabh.Mishra@Sun.COM
20989865SSaurabh.Mishra@Sun.COM static void
bfe_error_handler(bfe_t * bfe,int intr_mask)20999865SSaurabh.Mishra@Sun.COM bfe_error_handler(bfe_t *bfe, int intr_mask)
21009865SSaurabh.Mishra@Sun.COM {
21019865SSaurabh.Mishra@Sun.COM uint32_t v;
21029865SSaurabh.Mishra@Sun.COM
21039865SSaurabh.Mishra@Sun.COM if (intr_mask & BFE_ISTAT_RFO) {
21049865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.overflows++;
210510591SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action |=
210610591SSaurabh.Mishra@Sun.COM (BFE_ACTION_RESTART | BFE_ACTION_RESTART_FAULT);
210710591SSaurabh.Mishra@Sun.COM goto action;
21089865SSaurabh.Mishra@Sun.COM }
21099865SSaurabh.Mishra@Sun.COM
21109865SSaurabh.Mishra@Sun.COM if (intr_mask & BFE_ISTAT_TFU) {
21119865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.underflows++;
21129865SSaurabh.Mishra@Sun.COM return;
21139865SSaurabh.Mishra@Sun.COM }
21149865SSaurabh.Mishra@Sun.COM
21159865SSaurabh.Mishra@Sun.COM /* Descriptor Protocol Error */
21169865SSaurabh.Mishra@Sun.COM if (intr_mask & BFE_ISTAT_DPE) {
21179865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip,
21189865SSaurabh.Mishra@Sun.COM "Descriptor Protocol Error. Halting Chip");
21199865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action |=
21209865SSaurabh.Mishra@Sun.COM (BFE_ACTION_RESTART | BFE_ACTION_RESTART_FAULT);
21219865SSaurabh.Mishra@Sun.COM goto action;
21229865SSaurabh.Mishra@Sun.COM }
21239865SSaurabh.Mishra@Sun.COM
21249865SSaurabh.Mishra@Sun.COM /* Descriptor Error */
21259865SSaurabh.Mishra@Sun.COM if (intr_mask & BFE_ISTAT_DSCE && halt == 0) {
21269865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "Descriptor Error. Restarting Chip");
21279865SSaurabh.Mishra@Sun.COM goto action;
21289865SSaurabh.Mishra@Sun.COM }
21299865SSaurabh.Mishra@Sun.COM
21309865SSaurabh.Mishra@Sun.COM /* Receive Descr. Underflow */
21319865SSaurabh.Mishra@Sun.COM if (intr_mask & BFE_ISTAT_RDU) {
21329865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip,
21339865SSaurabh.Mishra@Sun.COM "Receive Descriptor Underflow. Restarting Chip");
21349865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_macrcv_errors++;
21359865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action |=
21369865SSaurabh.Mishra@Sun.COM (BFE_ACTION_RESTART | BFE_ACTION_RESTART_FAULT);
21379865SSaurabh.Mishra@Sun.COM goto action;
21389865SSaurabh.Mishra@Sun.COM }
21399865SSaurabh.Mishra@Sun.COM
21409865SSaurabh.Mishra@Sun.COM v = INL(bfe, BFE_DMATX_STAT);
21419865SSaurabh.Mishra@Sun.COM
21429865SSaurabh.Mishra@Sun.COM /* Error while sending a packet */
21439865SSaurabh.Mishra@Sun.COM if (v & BFE_STAT_EMASK) {
21449865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ether_stat_macxmt_errors++;
21459865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip,
21469865SSaurabh.Mishra@Sun.COM "Error while sending a packet. Restarting Chip");
21479865SSaurabh.Mishra@Sun.COM }
21489865SSaurabh.Mishra@Sun.COM
21499865SSaurabh.Mishra@Sun.COM /* Error while receiving a packet */
21509865SSaurabh.Mishra@Sun.COM v = INL(bfe, BFE_DMARX_STAT);
21519865SSaurabh.Mishra@Sun.COM if (v & BFE_RX_FLAG_ERRORS) {
21529865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ierrors++;
21539865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip,
21549865SSaurabh.Mishra@Sun.COM "Error while receiving a packet. Restarting Chip");
21559865SSaurabh.Mishra@Sun.COM }
21569865SSaurabh.Mishra@Sun.COM
21579865SSaurabh.Mishra@Sun.COM
21589865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action |=
21599865SSaurabh.Mishra@Sun.COM (BFE_ACTION_RESTART | BFE_ACTION_RESTART_FAULT);
21609865SSaurabh.Mishra@Sun.COM
21619865SSaurabh.Mishra@Sun.COM action:
21629865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe);
21639865SSaurabh.Mishra@Sun.COM }
21649865SSaurabh.Mishra@Sun.COM
21659865SSaurabh.Mishra@Sun.COM /*
21669865SSaurabh.Mishra@Sun.COM * It will recycle a RX descriptor slot.
21679865SSaurabh.Mishra@Sun.COM */
21689865SSaurabh.Mishra@Sun.COM static void
bfe_rx_desc_buf_reinit(bfe_t * bfe,uint_t slot)21699865SSaurabh.Mishra@Sun.COM bfe_rx_desc_buf_reinit(bfe_t *bfe, uint_t slot)
21709865SSaurabh.Mishra@Sun.COM {
21719865SSaurabh.Mishra@Sun.COM bfe_ring_t *r = &bfe->bfe_rx_ring;
21729865SSaurabh.Mishra@Sun.COM uint32_t v;
21739865SSaurabh.Mishra@Sun.COM
21749865SSaurabh.Mishra@Sun.COM slot %= RX_NUM_DESC;
21759865SSaurabh.Mishra@Sun.COM
21769865SSaurabh.Mishra@Sun.COM bzero(r->r_buf_dma[slot].addr, sizeof (bfe_rx_header_t));
21779865SSaurabh.Mishra@Sun.COM
21789865SSaurabh.Mishra@Sun.COM (void) SYNC_BUF(r, slot, 0, BFE_RX_OFFSET, DDI_DMA_SYNC_FORDEV);
21799865SSaurabh.Mishra@Sun.COM
21809865SSaurabh.Mishra@Sun.COM v = r->r_buf_dma[slot].len & BFE_DESC_LEN;
21819865SSaurabh.Mishra@Sun.COM if (slot == (RX_NUM_DESC - 1))
21829865SSaurabh.Mishra@Sun.COM v |= BFE_DESC_EOT;
21839865SSaurabh.Mishra@Sun.COM
21849865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[slot].desc_ctl), v);
21859865SSaurabh.Mishra@Sun.COM
21869865SSaurabh.Mishra@Sun.COM /*
21879865SSaurabh.Mishra@Sun.COM * DMA addresses need to be added to BFE_PCI_DMA
21889865SSaurabh.Mishra@Sun.COM */
21899865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[slot].desc_addr),
21909865SSaurabh.Mishra@Sun.COM (r->r_buf_dma[slot].cookie.dmac_laddress + BFE_PCI_DMA));
21919865SSaurabh.Mishra@Sun.COM }
21929865SSaurabh.Mishra@Sun.COM
21939865SSaurabh.Mishra@Sun.COM /*
21949865SSaurabh.Mishra@Sun.COM * Gets called from interrupt context to handle RX interrupt.
21959865SSaurabh.Mishra@Sun.COM */
21969865SSaurabh.Mishra@Sun.COM static mblk_t *
bfe_receive(bfe_t * bfe,int intr_mask)21979865SSaurabh.Mishra@Sun.COM bfe_receive(bfe_t *bfe, int intr_mask)
21989865SSaurabh.Mishra@Sun.COM {
21999865SSaurabh.Mishra@Sun.COM int rxstat, current;
22009865SSaurabh.Mishra@Sun.COM mblk_t *mp = NULL, *rx_head, *rx_tail;
22019865SSaurabh.Mishra@Sun.COM uchar_t *rx_header;
22029865SSaurabh.Mishra@Sun.COM uint16_t len;
22039865SSaurabh.Mishra@Sun.COM uchar_t *bp;
22049865SSaurabh.Mishra@Sun.COM bfe_ring_t *r = &bfe->bfe_rx_ring;
22059865SSaurabh.Mishra@Sun.COM int i;
22069865SSaurabh.Mishra@Sun.COM
22079865SSaurabh.Mishra@Sun.COM rxstat = INL(bfe, BFE_DMARX_STAT);
22089865SSaurabh.Mishra@Sun.COM current = (rxstat & BFE_STAT_CDMASK) / sizeof (bfe_desc_t);
22099865SSaurabh.Mishra@Sun.COM i = r->r_curr_desc;
22109865SSaurabh.Mishra@Sun.COM
22119865SSaurabh.Mishra@Sun.COM rx_head = rx_tail = NULL;
22129865SSaurabh.Mishra@Sun.COM
22139865SSaurabh.Mishra@Sun.COM DTRACE_PROBE3(receive, int, bfe->bfe_unit,
22149865SSaurabh.Mishra@Sun.COM int, r->r_curr_desc,
22159865SSaurabh.Mishra@Sun.COM int, current);
22169865SSaurabh.Mishra@Sun.COM
22179865SSaurabh.Mishra@Sun.COM for (i = r->r_curr_desc; i != current;
22189865SSaurabh.Mishra@Sun.COM BFE_INC_SLOT(i, RX_NUM_DESC)) {
22199865SSaurabh.Mishra@Sun.COM
22209865SSaurabh.Mishra@Sun.COM /*
22219865SSaurabh.Mishra@Sun.COM * Sync the buffer associated with the descriptor table entry.
22229865SSaurabh.Mishra@Sun.COM */
22239865SSaurabh.Mishra@Sun.COM (void) SYNC_BUF(r, i, 0, r->r_buf_dma[i].len,
22249865SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORKERNEL);
22259865SSaurabh.Mishra@Sun.COM
22269865SSaurabh.Mishra@Sun.COM rx_header = (void *)r->r_buf_dma[i].addr;
22279865SSaurabh.Mishra@Sun.COM
22289865SSaurabh.Mishra@Sun.COM /*
22299865SSaurabh.Mishra@Sun.COM * We do this to make sure we are endian neutral. Chip is
22309865SSaurabh.Mishra@Sun.COM * big endian.
22319865SSaurabh.Mishra@Sun.COM *
22329865SSaurabh.Mishra@Sun.COM * The header looks like :-
22339865SSaurabh.Mishra@Sun.COM *
22349865SSaurabh.Mishra@Sun.COM * Offset 0 -> uint16_t len
22359865SSaurabh.Mishra@Sun.COM * Offset 2 -> uint16_t flags
22369865SSaurabh.Mishra@Sun.COM * Offset 4 -> uint16_t pad[12]
22379865SSaurabh.Mishra@Sun.COM */
22389865SSaurabh.Mishra@Sun.COM len = (rx_header[1] << 8) | rx_header[0];
22399865SSaurabh.Mishra@Sun.COM len -= 4; /* CRC bytes need to be removed */
22409865SSaurabh.Mishra@Sun.COM
22419865SSaurabh.Mishra@Sun.COM /*
22429865SSaurabh.Mishra@Sun.COM * Don't receive this packet if pkt length is greater than
22439865SSaurabh.Mishra@Sun.COM * MTU + VLAN_TAGSZ.
22449865SSaurabh.Mishra@Sun.COM */
22459865SSaurabh.Mishra@Sun.COM if (len > r->r_buf_len) {
22469865SSaurabh.Mishra@Sun.COM /* Recycle slot for later use */
22479865SSaurabh.Mishra@Sun.COM bfe_rx_desc_buf_reinit(bfe, i);
22489865SSaurabh.Mishra@Sun.COM continue;
22499865SSaurabh.Mishra@Sun.COM }
22509865SSaurabh.Mishra@Sun.COM
22519865SSaurabh.Mishra@Sun.COM if ((mp = allocb(len + VLAN_TAGSZ, BPRI_MED)) != NULL) {
22529865SSaurabh.Mishra@Sun.COM mp->b_rptr += VLAN_TAGSZ;
22539865SSaurabh.Mishra@Sun.COM bp = mp->b_rptr;
22549865SSaurabh.Mishra@Sun.COM mp->b_wptr = bp + len;
22559865SSaurabh.Mishra@Sun.COM
22569865SSaurabh.Mishra@Sun.COM /* sizeof (bfe_rx_header_t) + 2 */
22579865SSaurabh.Mishra@Sun.COM bcopy(r->r_buf_dma[i].addr +
22589865SSaurabh.Mishra@Sun.COM BFE_RX_OFFSET, bp, len);
22599865SSaurabh.Mishra@Sun.COM
22609865SSaurabh.Mishra@Sun.COM mp->b_next = NULL;
22619865SSaurabh.Mishra@Sun.COM if (rx_tail == NULL)
22629865SSaurabh.Mishra@Sun.COM rx_head = rx_tail = mp;
22639865SSaurabh.Mishra@Sun.COM else {
22649865SSaurabh.Mishra@Sun.COM rx_tail->b_next = mp;
22659865SSaurabh.Mishra@Sun.COM rx_tail = mp;
22669865SSaurabh.Mishra@Sun.COM }
22679865SSaurabh.Mishra@Sun.COM
22689865SSaurabh.Mishra@Sun.COM /* Number of packets received so far */
22699865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.ipackets++;
22709865SSaurabh.Mishra@Sun.COM
22719865SSaurabh.Mishra@Sun.COM /* Total bytes of packets received so far */
22729865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.rbytes += len;
22739865SSaurabh.Mishra@Sun.COM
22749865SSaurabh.Mishra@Sun.COM if (bcmp(mp->b_rptr, bfe_broadcast, ETHERADDRL) == 0)
22759865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.brdcstrcv++;
22769865SSaurabh.Mishra@Sun.COM else
22779865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.multircv++;
22789865SSaurabh.Mishra@Sun.COM } else {
22799865SSaurabh.Mishra@Sun.COM bfe->bfe_stats.norcvbuf++;
22809865SSaurabh.Mishra@Sun.COM /* Recycle the slot for later use */
22819865SSaurabh.Mishra@Sun.COM bfe_rx_desc_buf_reinit(bfe, i);
22829865SSaurabh.Mishra@Sun.COM break;
22839865SSaurabh.Mishra@Sun.COM }
22849865SSaurabh.Mishra@Sun.COM
22859865SSaurabh.Mishra@Sun.COM /*
22869865SSaurabh.Mishra@Sun.COM * Reinitialize the current descriptor slot's buffer so that
22879865SSaurabh.Mishra@Sun.COM * it can be reused.
22889865SSaurabh.Mishra@Sun.COM */
22899865SSaurabh.Mishra@Sun.COM bfe_rx_desc_buf_reinit(bfe, i);
22909865SSaurabh.Mishra@Sun.COM }
22919865SSaurabh.Mishra@Sun.COM
22929865SSaurabh.Mishra@Sun.COM r->r_curr_desc = i;
22939865SSaurabh.Mishra@Sun.COM
22949865SSaurabh.Mishra@Sun.COM (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV);
22959865SSaurabh.Mishra@Sun.COM
22969865SSaurabh.Mishra@Sun.COM return (rx_head);
22979865SSaurabh.Mishra@Sun.COM }
22989865SSaurabh.Mishra@Sun.COM
22999865SSaurabh.Mishra@Sun.COM static int
bfe_tx_reclaim(bfe_ring_t * r)23009865SSaurabh.Mishra@Sun.COM bfe_tx_reclaim(bfe_ring_t *r)
23019865SSaurabh.Mishra@Sun.COM {
23029865SSaurabh.Mishra@Sun.COM uint32_t cur, start;
23039865SSaurabh.Mishra@Sun.COM uint32_t v;
23049865SSaurabh.Mishra@Sun.COM
23059865SSaurabh.Mishra@Sun.COM cur = INL(r->r_bfe, BFE_DMATX_STAT) & BFE_STAT_CDMASK;
23069865SSaurabh.Mishra@Sun.COM cur = cur / sizeof (bfe_desc_t);
23079865SSaurabh.Mishra@Sun.COM
23089865SSaurabh.Mishra@Sun.COM /*
23099865SSaurabh.Mishra@Sun.COM * Start with the last descriptor consumed by the chip.
23109865SSaurabh.Mishra@Sun.COM */
23119865SSaurabh.Mishra@Sun.COM start = r->r_cons_desc;
23129865SSaurabh.Mishra@Sun.COM
23139865SSaurabh.Mishra@Sun.COM DTRACE_PROBE3(tx__reclaim, int, r->r_bfe->bfe_unit,
23149865SSaurabh.Mishra@Sun.COM int, start,
23159865SSaurabh.Mishra@Sun.COM int, cur);
23169865SSaurabh.Mishra@Sun.COM
23179865SSaurabh.Mishra@Sun.COM /*
23189865SSaurabh.Mishra@Sun.COM * There will be at least one descriptor to process.
23199865SSaurabh.Mishra@Sun.COM */
23209865SSaurabh.Mishra@Sun.COM while (start != cur) {
23219865SSaurabh.Mishra@Sun.COM r->r_avail_desc++;
23229865SSaurabh.Mishra@Sun.COM v = r->r_buf_dma[start].len & BFE_DESC_LEN;
23239865SSaurabh.Mishra@Sun.COM if (start == (TX_NUM_DESC - 1))
23249865SSaurabh.Mishra@Sun.COM v |= BFE_DESC_EOT;
23259865SSaurabh.Mishra@Sun.COM
23269865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[start].desc_ctl), v);
23279865SSaurabh.Mishra@Sun.COM PUT_DESC(r, (uint32_t *)&(r->r_desc[start].desc_addr),
23289865SSaurabh.Mishra@Sun.COM (r->r_buf_dma[start].cookie.dmac_laddress + BFE_PCI_DMA));
23299865SSaurabh.Mishra@Sun.COM
23309865SSaurabh.Mishra@Sun.COM /* Move to next descriptor in TX ring */
23319865SSaurabh.Mishra@Sun.COM BFE_INC_SLOT(start, TX_NUM_DESC);
23329865SSaurabh.Mishra@Sun.COM }
23339865SSaurabh.Mishra@Sun.COM
23349865SSaurabh.Mishra@Sun.COM (void) ddi_dma_sync(r->r_desc_dma_handle,
23359865SSaurabh.Mishra@Sun.COM 0, (r->r_ndesc * sizeof (bfe_desc_t)),
23369865SSaurabh.Mishra@Sun.COM DDI_DMA_SYNC_FORDEV);
23379865SSaurabh.Mishra@Sun.COM
23389865SSaurabh.Mishra@Sun.COM r->r_cons_desc = start; /* consumed pointer */
23399865SSaurabh.Mishra@Sun.COM r->r_bfe->bfe_tx_stall_time = 0;
23409865SSaurabh.Mishra@Sun.COM
23419865SSaurabh.Mishra@Sun.COM return (cur);
23429865SSaurabh.Mishra@Sun.COM }
23439865SSaurabh.Mishra@Sun.COM
23449865SSaurabh.Mishra@Sun.COM static int
bfe_tx_done(bfe_t * bfe,int intr_mask)23459865SSaurabh.Mishra@Sun.COM bfe_tx_done(bfe_t *bfe, int intr_mask)
23469865SSaurabh.Mishra@Sun.COM {
23479865SSaurabh.Mishra@Sun.COM bfe_ring_t *r = &bfe->bfe_tx_ring;
23489865SSaurabh.Mishra@Sun.COM int resched = 0;
23499865SSaurabh.Mishra@Sun.COM
23509865SSaurabh.Mishra@Sun.COM mutex_enter(&r->r_lock);
23519865SSaurabh.Mishra@Sun.COM (void) bfe_tx_reclaim(r);
23529865SSaurabh.Mishra@Sun.COM
23539865SSaurabh.Mishra@Sun.COM if (bfe->bfe_tx_resched) {
23549865SSaurabh.Mishra@Sun.COM resched = 1;
23559865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_resched = 0;
23569865SSaurabh.Mishra@Sun.COM }
23579865SSaurabh.Mishra@Sun.COM mutex_exit(&r->r_lock);
23589865SSaurabh.Mishra@Sun.COM
23599865SSaurabh.Mishra@Sun.COM return (resched);
23609865SSaurabh.Mishra@Sun.COM }
23619865SSaurabh.Mishra@Sun.COM
23629865SSaurabh.Mishra@Sun.COM /*
23639865SSaurabh.Mishra@Sun.COM * ISR for interrupt handling
23649865SSaurabh.Mishra@Sun.COM */
23659865SSaurabh.Mishra@Sun.COM static uint_t
bfe_interrupt(caddr_t arg1,caddr_t arg2)23669865SSaurabh.Mishra@Sun.COM bfe_interrupt(caddr_t arg1, caddr_t arg2)
23679865SSaurabh.Mishra@Sun.COM {
23689865SSaurabh.Mishra@Sun.COM bfe_t *bfe = (void *)arg1;
23699865SSaurabh.Mishra@Sun.COM uint32_t intr_stat;
23709865SSaurabh.Mishra@Sun.COM mblk_t *rx_head = NULL;
23719865SSaurabh.Mishra@Sun.COM int resched = 0;
23729865SSaurabh.Mishra@Sun.COM
23739865SSaurabh.Mishra@Sun.COM /*
23749865SSaurabh.Mishra@Sun.COM * Grab the lock to avoid stopping the chip while this interrupt
23759865SSaurabh.Mishra@Sun.COM * is handled.
23769865SSaurabh.Mishra@Sun.COM */
23779865SSaurabh.Mishra@Sun.COM rw_enter(&bfe->bfe_rwlock, RW_READER);
23789865SSaurabh.Mishra@Sun.COM
23799865SSaurabh.Mishra@Sun.COM /*
23809865SSaurabh.Mishra@Sun.COM * It's necessary to read intr stat again because masking interrupt
23819865SSaurabh.Mishra@Sun.COM * register does not really mask interrupts coming from the chip.
23829865SSaurabh.Mishra@Sun.COM */
23839865SSaurabh.Mishra@Sun.COM intr_stat = INL(bfe, BFE_INTR_STAT);
23849865SSaurabh.Mishra@Sun.COM intr_stat &= BFE_IMASK_DEF;
23859865SSaurabh.Mishra@Sun.COM OUTL(bfe, BFE_INTR_STAT, intr_stat);
23869865SSaurabh.Mishra@Sun.COM (void) INL(bfe, BFE_INTR_STAT);
23879865SSaurabh.Mishra@Sun.COM
23889865SSaurabh.Mishra@Sun.COM if (intr_stat == 0) {
23899865SSaurabh.Mishra@Sun.COM rw_exit(&bfe->bfe_rwlock);
23909865SSaurabh.Mishra@Sun.COM return (DDI_INTR_UNCLAIMED);
23919865SSaurabh.Mishra@Sun.COM }
23929865SSaurabh.Mishra@Sun.COM
239310591SSaurabh.Mishra@Sun.COM DTRACE_PROBE2(bfe__interrupt, int, bfe->bfe_unit,
239410591SSaurabh.Mishra@Sun.COM int, intr_stat);
239510591SSaurabh.Mishra@Sun.COM
23969865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state != BFE_CHIP_ACTIVE) {
23979865SSaurabh.Mishra@Sun.COM /*
23989865SSaurabh.Mishra@Sun.COM * If chip is suspended then we just return.
23999865SSaurabh.Mishra@Sun.COM */
24009865SSaurabh.Mishra@Sun.COM if (bfe->bfe_chip_state == BFE_CHIP_SUSPENDED) {
24019865SSaurabh.Mishra@Sun.COM rw_exit(&bfe->bfe_rwlock);
24029865SSaurabh.Mishra@Sun.COM DTRACE_PROBE1(interrupt__chip__is__suspend, int,
24039865SSaurabh.Mishra@Sun.COM bfe->bfe_unit);
24049865SSaurabh.Mishra@Sun.COM return (DDI_INTR_CLAIMED);
24059865SSaurabh.Mishra@Sun.COM }
24069865SSaurabh.Mishra@Sun.COM
24079865SSaurabh.Mishra@Sun.COM /*
24089865SSaurabh.Mishra@Sun.COM * Halt the chip again i.e basically disable interrupts.
24099865SSaurabh.Mishra@Sun.COM */
24109865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe);
24119865SSaurabh.Mishra@Sun.COM rw_exit(&bfe->bfe_rwlock);
24129865SSaurabh.Mishra@Sun.COM DTRACE_PROBE1(interrupt__chip__not__active, int,
24139865SSaurabh.Mishra@Sun.COM bfe->bfe_unit);
24149865SSaurabh.Mishra@Sun.COM return (DDI_INTR_CLAIMED);
24159865SSaurabh.Mishra@Sun.COM }
24169865SSaurabh.Mishra@Sun.COM
24179865SSaurabh.Mishra@Sun.COM /* A packet was received */
24189865SSaurabh.Mishra@Sun.COM if (intr_stat & BFE_ISTAT_RX) {
24199865SSaurabh.Mishra@Sun.COM rx_head = bfe_receive(bfe, intr_stat);
24209865SSaurabh.Mishra@Sun.COM }
24219865SSaurabh.Mishra@Sun.COM
24229865SSaurabh.Mishra@Sun.COM /* A packet was sent down the wire */
24239865SSaurabh.Mishra@Sun.COM if (intr_stat & BFE_ISTAT_TX) {
24249865SSaurabh.Mishra@Sun.COM resched = bfe_tx_done(bfe, intr_stat);
24259865SSaurabh.Mishra@Sun.COM }
24269865SSaurabh.Mishra@Sun.COM
24279865SSaurabh.Mishra@Sun.COM /* There was an error */
24289865SSaurabh.Mishra@Sun.COM if (intr_stat & BFE_ISTAT_ERRORS) {
24299865SSaurabh.Mishra@Sun.COM bfe_error_handler(bfe, intr_stat);
24309865SSaurabh.Mishra@Sun.COM }
24319865SSaurabh.Mishra@Sun.COM
24329865SSaurabh.Mishra@Sun.COM rw_exit(&bfe->bfe_rwlock);
24339865SSaurabh.Mishra@Sun.COM
24349865SSaurabh.Mishra@Sun.COM /*
24359865SSaurabh.Mishra@Sun.COM * Pass the list of packets received from chip to MAC layer.
24369865SSaurabh.Mishra@Sun.COM */
24379865SSaurabh.Mishra@Sun.COM if (rx_head) {
24389865SSaurabh.Mishra@Sun.COM mac_rx(bfe->bfe_machdl, 0, rx_head);
24399865SSaurabh.Mishra@Sun.COM }
24409865SSaurabh.Mishra@Sun.COM
24419865SSaurabh.Mishra@Sun.COM /*
24429865SSaurabh.Mishra@Sun.COM * Let the MAC start sending pkts to a potential stopped stream.
24439865SSaurabh.Mishra@Sun.COM */
24449865SSaurabh.Mishra@Sun.COM if (resched)
24459865SSaurabh.Mishra@Sun.COM mac_tx_update(bfe->bfe_machdl);
24469865SSaurabh.Mishra@Sun.COM
24479865SSaurabh.Mishra@Sun.COM return (DDI_INTR_CLAIMED);
24489865SSaurabh.Mishra@Sun.COM }
24499865SSaurabh.Mishra@Sun.COM
24509865SSaurabh.Mishra@Sun.COM /*
24519865SSaurabh.Mishra@Sun.COM * Removes registered interrupt handler.
24529865SSaurabh.Mishra@Sun.COM */
24539865SSaurabh.Mishra@Sun.COM static void
bfe_remove_intr(bfe_t * bfe)24549865SSaurabh.Mishra@Sun.COM bfe_remove_intr(bfe_t *bfe)
24559865SSaurabh.Mishra@Sun.COM {
24569865SSaurabh.Mishra@Sun.COM (void) ddi_intr_remove_handler(bfe->bfe_intrhdl);
24579865SSaurabh.Mishra@Sun.COM (void) ddi_intr_free(bfe->bfe_intrhdl);
24589865SSaurabh.Mishra@Sun.COM }
24599865SSaurabh.Mishra@Sun.COM
24609865SSaurabh.Mishra@Sun.COM /*
24619865SSaurabh.Mishra@Sun.COM * Add an interrupt for the driver.
24629865SSaurabh.Mishra@Sun.COM */
24639865SSaurabh.Mishra@Sun.COM static int
bfe_add_intr(bfe_t * bfe)24649865SSaurabh.Mishra@Sun.COM bfe_add_intr(bfe_t *bfe)
24659865SSaurabh.Mishra@Sun.COM {
24669865SSaurabh.Mishra@Sun.COM int nintrs = 1;
24679865SSaurabh.Mishra@Sun.COM int ret;
24689865SSaurabh.Mishra@Sun.COM
24699865SSaurabh.Mishra@Sun.COM ret = ddi_intr_alloc(bfe->bfe_dip, &bfe->bfe_intrhdl,
24709865SSaurabh.Mishra@Sun.COM DDI_INTR_TYPE_FIXED, /* type */
24719865SSaurabh.Mishra@Sun.COM 0, /* inumber */
24729865SSaurabh.Mishra@Sun.COM 1, /* count */
24739865SSaurabh.Mishra@Sun.COM &nintrs, /* actual nintrs */
24749865SSaurabh.Mishra@Sun.COM DDI_INTR_ALLOC_STRICT);
24759865SSaurabh.Mishra@Sun.COM
24769865SSaurabh.Mishra@Sun.COM if (ret != DDI_SUCCESS) {
24779865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "ddi_intr_alloc() failed"
24789865SSaurabh.Mishra@Sun.COM " : ret : %d", ret);
24799865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
24809865SSaurabh.Mishra@Sun.COM }
24819865SSaurabh.Mishra@Sun.COM
24829865SSaurabh.Mishra@Sun.COM ret = ddi_intr_add_handler(bfe->bfe_intrhdl, bfe_interrupt, bfe, NULL);
24839865SSaurabh.Mishra@Sun.COM if (ret != DDI_SUCCESS) {
24849865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "ddi_intr_add_handler() failed");
24859865SSaurabh.Mishra@Sun.COM (void) ddi_intr_free(bfe->bfe_intrhdl);
24869865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
24879865SSaurabh.Mishra@Sun.COM }
24889865SSaurabh.Mishra@Sun.COM
24899865SSaurabh.Mishra@Sun.COM ret = ddi_intr_get_pri(bfe->bfe_intrhdl, &bfe->bfe_intrpri);
24909865SSaurabh.Mishra@Sun.COM if (ret != DDI_SUCCESS) {
24919865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "ddi_intr_get_pri() failed");
24929865SSaurabh.Mishra@Sun.COM bfe_remove_intr(bfe);
24939865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
24949865SSaurabh.Mishra@Sun.COM }
24959865SSaurabh.Mishra@Sun.COM
24969865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
24979865SSaurabh.Mishra@Sun.COM }
24989865SSaurabh.Mishra@Sun.COM
24999865SSaurabh.Mishra@Sun.COM
25009865SSaurabh.Mishra@Sun.COM /*
25019865SSaurabh.Mishra@Sun.COM * Identify chipset family.
25029865SSaurabh.Mishra@Sun.COM */
25039865SSaurabh.Mishra@Sun.COM static int
bfe_identify_hardware(bfe_t * bfe)25049865SSaurabh.Mishra@Sun.COM bfe_identify_hardware(bfe_t *bfe)
25059865SSaurabh.Mishra@Sun.COM {
25069865SSaurabh.Mishra@Sun.COM uint16_t vid, did;
25079865SSaurabh.Mishra@Sun.COM int i;
25089865SSaurabh.Mishra@Sun.COM
25099865SSaurabh.Mishra@Sun.COM vid = pci_config_get16(bfe->bfe_conf_handle, PCI_CONF_VENID);
25109865SSaurabh.Mishra@Sun.COM did = pci_config_get16(bfe->bfe_conf_handle, PCI_CONF_DEVID);
25119865SSaurabh.Mishra@Sun.COM
25129865SSaurabh.Mishra@Sun.COM for (i = 0; i < (sizeof (bfe_cards) / sizeof (bfe_cards_t)); i++) {
25139865SSaurabh.Mishra@Sun.COM if (bfe_cards[i].vendor_id == vid &&
25149865SSaurabh.Mishra@Sun.COM bfe_cards[i].device_id == did) {
25159865SSaurabh.Mishra@Sun.COM return (BFE_SUCCESS);
25169865SSaurabh.Mishra@Sun.COM }
25179865SSaurabh.Mishra@Sun.COM }
25189865SSaurabh.Mishra@Sun.COM
25199865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "bfe driver is attaching to unknown pci%d,%d"
25209865SSaurabh.Mishra@Sun.COM " vendor/device-id card", vid, did);
25219865SSaurabh.Mishra@Sun.COM
25229865SSaurabh.Mishra@Sun.COM return (BFE_SUCCESS);
25239865SSaurabh.Mishra@Sun.COM }
25249865SSaurabh.Mishra@Sun.COM
25259865SSaurabh.Mishra@Sun.COM /*
25269865SSaurabh.Mishra@Sun.COM * Maps device registers.
25279865SSaurabh.Mishra@Sun.COM */
25289865SSaurabh.Mishra@Sun.COM static int
bfe_regs_map(bfe_t * bfe)25299865SSaurabh.Mishra@Sun.COM bfe_regs_map(bfe_t *bfe)
25309865SSaurabh.Mishra@Sun.COM {
25319865SSaurabh.Mishra@Sun.COM dev_info_t *dip = bfe->bfe_dip;
25329865SSaurabh.Mishra@Sun.COM int ret;
25339865SSaurabh.Mishra@Sun.COM
25349865SSaurabh.Mishra@Sun.COM ret = ddi_regs_map_setup(dip, 1, &bfe->bfe_mem_regset.addr, 0, 0,
25359865SSaurabh.Mishra@Sun.COM &bfe_dev_attr, &bfe->bfe_mem_regset.hdl);
25369865SSaurabh.Mishra@Sun.COM
25379865SSaurabh.Mishra@Sun.COM if (ret != DDI_SUCCESS) {
25389865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "ddi_regs_map_setup failed");
25399865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
25409865SSaurabh.Mishra@Sun.COM }
25419865SSaurabh.Mishra@Sun.COM
25429865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
25439865SSaurabh.Mishra@Sun.COM }
25449865SSaurabh.Mishra@Sun.COM
25459865SSaurabh.Mishra@Sun.COM static void
bfe_unmap_regs(bfe_t * bfe)25469865SSaurabh.Mishra@Sun.COM bfe_unmap_regs(bfe_t *bfe)
25479865SSaurabh.Mishra@Sun.COM {
25489865SSaurabh.Mishra@Sun.COM ddi_regs_map_free(&bfe->bfe_mem_regset.hdl);
25499865SSaurabh.Mishra@Sun.COM }
25509865SSaurabh.Mishra@Sun.COM
25519865SSaurabh.Mishra@Sun.COM static int
bfe_get_chip_config(bfe_t * bfe)25529865SSaurabh.Mishra@Sun.COM bfe_get_chip_config(bfe_t *bfe)
25539865SSaurabh.Mishra@Sun.COM {
25549865SSaurabh.Mishra@Sun.COM uint32_t prom[BFE_EEPROM_SIZE];
25559865SSaurabh.Mishra@Sun.COM int i;
25569865SSaurabh.Mishra@Sun.COM
25579865SSaurabh.Mishra@Sun.COM /*
25589865SSaurabh.Mishra@Sun.COM * Read EEPROM in prom[]
25599865SSaurabh.Mishra@Sun.COM */
25609865SSaurabh.Mishra@Sun.COM for (i = 0; i < BFE_EEPROM_SIZE; i++) {
25619865SSaurabh.Mishra@Sun.COM prom[i] = INL(bfe, BFE_EEPROM_BASE + i * sizeof (uint32_t));
25629865SSaurabh.Mishra@Sun.COM }
25639865SSaurabh.Mishra@Sun.COM
25649865SSaurabh.Mishra@Sun.COM bfe->bfe_dev_addr[0] = bfe->bfe_ether_addr[0] =
25659865SSaurabh.Mishra@Sun.COM INB(bfe, BFE_EEPROM_BASE + 79);
25669865SSaurabh.Mishra@Sun.COM
25679865SSaurabh.Mishra@Sun.COM bfe->bfe_dev_addr[1] = bfe->bfe_ether_addr[1] =
25689865SSaurabh.Mishra@Sun.COM INB(bfe, BFE_EEPROM_BASE + 78);
25699865SSaurabh.Mishra@Sun.COM
25709865SSaurabh.Mishra@Sun.COM bfe->bfe_dev_addr[2] = bfe->bfe_ether_addr[2] =
25719865SSaurabh.Mishra@Sun.COM INB(bfe, BFE_EEPROM_BASE + 81);
25729865SSaurabh.Mishra@Sun.COM
25739865SSaurabh.Mishra@Sun.COM bfe->bfe_dev_addr[3] = bfe->bfe_ether_addr[3] =
25749865SSaurabh.Mishra@Sun.COM INB(bfe, BFE_EEPROM_BASE + 80);
25759865SSaurabh.Mishra@Sun.COM
25769865SSaurabh.Mishra@Sun.COM bfe->bfe_dev_addr[4] = bfe->bfe_ether_addr[4] =
25779865SSaurabh.Mishra@Sun.COM INB(bfe, BFE_EEPROM_BASE + 83);
25789865SSaurabh.Mishra@Sun.COM
25799865SSaurabh.Mishra@Sun.COM bfe->bfe_dev_addr[5] = bfe->bfe_ether_addr[5] =
25809865SSaurabh.Mishra@Sun.COM INB(bfe, BFE_EEPROM_BASE + 82);
25819865SSaurabh.Mishra@Sun.COM
25829865SSaurabh.Mishra@Sun.COM bfe->bfe_phy_addr = -1;
25839865SSaurabh.Mishra@Sun.COM
25849865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
25859865SSaurabh.Mishra@Sun.COM }
25869865SSaurabh.Mishra@Sun.COM
25879865SSaurabh.Mishra@Sun.COM /*
25889865SSaurabh.Mishra@Sun.COM * Ring Management routines
25899865SSaurabh.Mishra@Sun.COM */
25909865SSaurabh.Mishra@Sun.COM static int
bfe_ring_buf_alloc(bfe_t * bfe,bfe_ring_t * r,int slot,int d)25919865SSaurabh.Mishra@Sun.COM bfe_ring_buf_alloc(bfe_t *bfe, bfe_ring_t *r, int slot, int d)
25929865SSaurabh.Mishra@Sun.COM {
25939865SSaurabh.Mishra@Sun.COM int err;
25949865SSaurabh.Mishra@Sun.COM uint_t count = 0;
25959865SSaurabh.Mishra@Sun.COM
25969865SSaurabh.Mishra@Sun.COM err = ddi_dma_alloc_handle(bfe->bfe_dip,
25979865SSaurabh.Mishra@Sun.COM &bfe_dma_attr_buf, DDI_DMA_SLEEP, NULL,
25989865SSaurabh.Mishra@Sun.COM &r->r_buf_dma[slot].handle);
25999865SSaurabh.Mishra@Sun.COM
26009865SSaurabh.Mishra@Sun.COM if (err != DDI_SUCCESS) {
26019865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, " bfe_ring_buf_alloc() :"
26029865SSaurabh.Mishra@Sun.COM " alloc_handle failed");
26039865SSaurabh.Mishra@Sun.COM goto fail0;
26049865SSaurabh.Mishra@Sun.COM }
26059865SSaurabh.Mishra@Sun.COM
26069865SSaurabh.Mishra@Sun.COM err = ddi_dma_mem_alloc(r->r_buf_dma[slot].handle,
26079865SSaurabh.Mishra@Sun.COM r->r_buf_len, &bfe_buf_attr, DDI_DMA_STREAMING,
26089865SSaurabh.Mishra@Sun.COM DDI_DMA_SLEEP, NULL, &r->r_buf_dma[slot].addr,
26099865SSaurabh.Mishra@Sun.COM &r->r_buf_dma[slot].len,
26109865SSaurabh.Mishra@Sun.COM &r->r_buf_dma[slot].acchdl);
26119865SSaurabh.Mishra@Sun.COM
26129865SSaurabh.Mishra@Sun.COM if (err != DDI_SUCCESS) {
26139865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, " bfe_ring_buf_alloc() :"
26149865SSaurabh.Mishra@Sun.COM " mem_alloc failed :%d", err);
26159865SSaurabh.Mishra@Sun.COM goto fail1;
26169865SSaurabh.Mishra@Sun.COM }
26179865SSaurabh.Mishra@Sun.COM
26189865SSaurabh.Mishra@Sun.COM err = ddi_dma_addr_bind_handle(r->r_buf_dma[slot].handle,
26199865SSaurabh.Mishra@Sun.COM NULL, r->r_buf_dma[slot].addr,
26209865SSaurabh.Mishra@Sun.COM r->r_buf_dma[slot].len,
26219865SSaurabh.Mishra@Sun.COM (DDI_DMA_RDWR | DDI_DMA_STREAMING),
26229865SSaurabh.Mishra@Sun.COM DDI_DMA_SLEEP, NULL,
26239865SSaurabh.Mishra@Sun.COM &r->r_buf_dma[slot].cookie,
26249865SSaurabh.Mishra@Sun.COM &count);
26259865SSaurabh.Mishra@Sun.COM
26269865SSaurabh.Mishra@Sun.COM if (err != DDI_DMA_MAPPED) {
26279865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, " bfe_ring_buf_alloc() :"
26289865SSaurabh.Mishra@Sun.COM " bind_handle failed");
26299865SSaurabh.Mishra@Sun.COM goto fail2;
26309865SSaurabh.Mishra@Sun.COM }
26319865SSaurabh.Mishra@Sun.COM
26329865SSaurabh.Mishra@Sun.COM if (count > 1) {
26339865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, " bfe_ring_buf_alloc() :"
26349865SSaurabh.Mishra@Sun.COM " more than one DMA cookie");
26359865SSaurabh.Mishra@Sun.COM (void) ddi_dma_unbind_handle(r->r_buf_dma[slot].handle);
26369865SSaurabh.Mishra@Sun.COM goto fail2;
26379865SSaurabh.Mishra@Sun.COM }
26389865SSaurabh.Mishra@Sun.COM
26399865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
26409865SSaurabh.Mishra@Sun.COM fail2:
26419865SSaurabh.Mishra@Sun.COM ddi_dma_mem_free(&r->r_buf_dma[slot].acchdl);
26429865SSaurabh.Mishra@Sun.COM fail1:
26439865SSaurabh.Mishra@Sun.COM ddi_dma_free_handle(&r->r_buf_dma[slot].handle);
26449865SSaurabh.Mishra@Sun.COM fail0:
26459865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
26469865SSaurabh.Mishra@Sun.COM }
26479865SSaurabh.Mishra@Sun.COM
26489865SSaurabh.Mishra@Sun.COM static void
bfe_ring_buf_free(bfe_ring_t * r,int slot)26499865SSaurabh.Mishra@Sun.COM bfe_ring_buf_free(bfe_ring_t *r, int slot)
26509865SSaurabh.Mishra@Sun.COM {
26519865SSaurabh.Mishra@Sun.COM if (r->r_buf_dma == NULL)
26529865SSaurabh.Mishra@Sun.COM return;
26539865SSaurabh.Mishra@Sun.COM
26549865SSaurabh.Mishra@Sun.COM (void) ddi_dma_unbind_handle(r->r_buf_dma[slot].handle);
26559865SSaurabh.Mishra@Sun.COM ddi_dma_mem_free(&r->r_buf_dma[slot].acchdl);
26569865SSaurabh.Mishra@Sun.COM ddi_dma_free_handle(&r->r_buf_dma[slot].handle);
26579865SSaurabh.Mishra@Sun.COM }
26589865SSaurabh.Mishra@Sun.COM
26599865SSaurabh.Mishra@Sun.COM static void
bfe_buffer_free(bfe_ring_t * r)26609865SSaurabh.Mishra@Sun.COM bfe_buffer_free(bfe_ring_t *r)
26619865SSaurabh.Mishra@Sun.COM {
26629865SSaurabh.Mishra@Sun.COM int i;
26639865SSaurabh.Mishra@Sun.COM
26649865SSaurabh.Mishra@Sun.COM for (i = 0; i < r->r_ndesc; i++) {
26659865SSaurabh.Mishra@Sun.COM bfe_ring_buf_free(r, i);
26669865SSaurabh.Mishra@Sun.COM }
26679865SSaurabh.Mishra@Sun.COM }
26689865SSaurabh.Mishra@Sun.COM
26699865SSaurabh.Mishra@Sun.COM static void
bfe_ring_desc_free(bfe_ring_t * r)26709865SSaurabh.Mishra@Sun.COM bfe_ring_desc_free(bfe_ring_t *r)
26719865SSaurabh.Mishra@Sun.COM {
26729865SSaurabh.Mishra@Sun.COM (void) ddi_dma_unbind_handle(r->r_desc_dma_handle);
26739865SSaurabh.Mishra@Sun.COM ddi_dma_mem_free(&r->r_desc_acc_handle);
26749865SSaurabh.Mishra@Sun.COM ddi_dma_free_handle(&r->r_desc_dma_handle);
26759865SSaurabh.Mishra@Sun.COM kmem_free(r->r_buf_dma, r->r_ndesc * sizeof (bfe_dma_t));
26769865SSaurabh.Mishra@Sun.COM
26779865SSaurabh.Mishra@Sun.COM r->r_buf_dma = NULL;
26789865SSaurabh.Mishra@Sun.COM r->r_desc = NULL;
26799865SSaurabh.Mishra@Sun.COM }
26809865SSaurabh.Mishra@Sun.COM
26819865SSaurabh.Mishra@Sun.COM
26829865SSaurabh.Mishra@Sun.COM static int
bfe_ring_desc_alloc(bfe_t * bfe,bfe_ring_t * r,int d)26839865SSaurabh.Mishra@Sun.COM bfe_ring_desc_alloc(bfe_t *bfe, bfe_ring_t *r, int d)
26849865SSaurabh.Mishra@Sun.COM {
26859865SSaurabh.Mishra@Sun.COM int err, i, fail = 0;
26869865SSaurabh.Mishra@Sun.COM caddr_t ring;
26879865SSaurabh.Mishra@Sun.COM size_t size_krnl = 0, size_dma = 0, ring_len = 0;
26889865SSaurabh.Mishra@Sun.COM ddi_dma_cookie_t cookie;
26899865SSaurabh.Mishra@Sun.COM uint_t count = 0;
26909865SSaurabh.Mishra@Sun.COM
26919865SSaurabh.Mishra@Sun.COM ASSERT(bfe != NULL);
26929865SSaurabh.Mishra@Sun.COM
26939865SSaurabh.Mishra@Sun.COM size_krnl = r->r_ndesc * sizeof (bfe_dma_t);
26949865SSaurabh.Mishra@Sun.COM size_dma = r->r_ndesc * sizeof (bfe_desc_t);
26959865SSaurabh.Mishra@Sun.COM r->r_buf_dma = kmem_zalloc(size_krnl, KM_SLEEP);
26969865SSaurabh.Mishra@Sun.COM
26979865SSaurabh.Mishra@Sun.COM
26989865SSaurabh.Mishra@Sun.COM err = ddi_dma_alloc_handle(bfe->bfe_dip, &bfe_dma_attr_desc,
26999865SSaurabh.Mishra@Sun.COM DDI_DMA_SLEEP, NULL, &r->r_desc_dma_handle);
27009865SSaurabh.Mishra@Sun.COM
27019865SSaurabh.Mishra@Sun.COM if (err != DDI_SUCCESS) {
27029865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "bfe_ring_desc_alloc() failed on"
27039865SSaurabh.Mishra@Sun.COM " ddi_dma_alloc_handle()");
27049865SSaurabh.Mishra@Sun.COM kmem_free(r->r_buf_dma, size_krnl);
27059865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
27069865SSaurabh.Mishra@Sun.COM }
27079865SSaurabh.Mishra@Sun.COM
27089865SSaurabh.Mishra@Sun.COM
27099865SSaurabh.Mishra@Sun.COM err = ddi_dma_mem_alloc(r->r_desc_dma_handle,
27109865SSaurabh.Mishra@Sun.COM size_dma, &bfe_buf_attr,
27119865SSaurabh.Mishra@Sun.COM DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
27129865SSaurabh.Mishra@Sun.COM &ring, &ring_len, &r->r_desc_acc_handle);
27139865SSaurabh.Mishra@Sun.COM
27149865SSaurabh.Mishra@Sun.COM if (err != DDI_SUCCESS) {
27159865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "bfe_ring_desc_alloc() failed on"
27169865SSaurabh.Mishra@Sun.COM " ddi_dma_mem_alloc()");
27179865SSaurabh.Mishra@Sun.COM ddi_dma_free_handle(&r->r_desc_dma_handle);
27189865SSaurabh.Mishra@Sun.COM kmem_free(r->r_buf_dma, size_krnl);
27199865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
27209865SSaurabh.Mishra@Sun.COM }
27219865SSaurabh.Mishra@Sun.COM
27229865SSaurabh.Mishra@Sun.COM err = ddi_dma_addr_bind_handle(r->r_desc_dma_handle,
27239865SSaurabh.Mishra@Sun.COM NULL, ring, ring_len,
27249865SSaurabh.Mishra@Sun.COM DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
27259865SSaurabh.Mishra@Sun.COM DDI_DMA_SLEEP, NULL,
27269865SSaurabh.Mishra@Sun.COM &cookie, &count);
27279865SSaurabh.Mishra@Sun.COM
27289865SSaurabh.Mishra@Sun.COM if (err != DDI_SUCCESS) {
27299865SSaurabh.Mishra@Sun.COM bfe_error(bfe->bfe_dip, "bfe_ring_desc_alloc() failed on"
27309865SSaurabh.Mishra@Sun.COM " ddi_dma_addr_bind_handle()");
27319865SSaurabh.Mishra@Sun.COM ddi_dma_mem_free(&r->r_desc_acc_handle);
27329865SSaurabh.Mishra@Sun.COM ddi_dma_free_handle(&r->r_desc_dma_handle);
27339865SSaurabh.Mishra@Sun.COM kmem_free(r->r_buf_dma, size_krnl);
27349865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
27359865SSaurabh.Mishra@Sun.COM }
27369865SSaurabh.Mishra@Sun.COM
27379865SSaurabh.Mishra@Sun.COM /*
27389865SSaurabh.Mishra@Sun.COM * We don't want to have multiple cookies. Descriptor should be
27399865SSaurabh.Mishra@Sun.COM * aligned to PAGESIZE boundary.
27409865SSaurabh.Mishra@Sun.COM */
27419865SSaurabh.Mishra@Sun.COM ASSERT(count == 1);
27429865SSaurabh.Mishra@Sun.COM
27439865SSaurabh.Mishra@Sun.COM /* The actual descriptor for the ring */
27449865SSaurabh.Mishra@Sun.COM r->r_desc_len = ring_len;
27459865SSaurabh.Mishra@Sun.COM r->r_desc_cookie = cookie;
27469865SSaurabh.Mishra@Sun.COM
27479865SSaurabh.Mishra@Sun.COM r->r_desc = (void *)ring;
27489865SSaurabh.Mishra@Sun.COM
27499865SSaurabh.Mishra@Sun.COM bzero(r->r_desc, size_dma);
27509865SSaurabh.Mishra@Sun.COM bzero(r->r_desc, ring_len);
27519865SSaurabh.Mishra@Sun.COM
27529865SSaurabh.Mishra@Sun.COM /* For each descriptor, allocate a DMA buffer */
27539865SSaurabh.Mishra@Sun.COM fail = 0;
27549865SSaurabh.Mishra@Sun.COM for (i = 0; i < r->r_ndesc; i++) {
27559865SSaurabh.Mishra@Sun.COM if (bfe_ring_buf_alloc(bfe, r, i, d) != DDI_SUCCESS) {
27569865SSaurabh.Mishra@Sun.COM i--;
27579865SSaurabh.Mishra@Sun.COM fail = 1;
27589865SSaurabh.Mishra@Sun.COM break;
27599865SSaurabh.Mishra@Sun.COM }
27609865SSaurabh.Mishra@Sun.COM }
27619865SSaurabh.Mishra@Sun.COM
27629865SSaurabh.Mishra@Sun.COM if (fail) {
27639865SSaurabh.Mishra@Sun.COM while (i-- >= 0) {
27649865SSaurabh.Mishra@Sun.COM bfe_ring_buf_free(r, i);
27659865SSaurabh.Mishra@Sun.COM }
27669865SSaurabh.Mishra@Sun.COM
27679865SSaurabh.Mishra@Sun.COM /* We don't need the descriptor anymore */
27689865SSaurabh.Mishra@Sun.COM bfe_ring_desc_free(r);
27699865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
27709865SSaurabh.Mishra@Sun.COM }
27719865SSaurabh.Mishra@Sun.COM
27729865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
27739865SSaurabh.Mishra@Sun.COM }
27749865SSaurabh.Mishra@Sun.COM
27759865SSaurabh.Mishra@Sun.COM static int
bfe_rings_alloc(bfe_t * bfe)27769865SSaurabh.Mishra@Sun.COM bfe_rings_alloc(bfe_t *bfe)
27779865SSaurabh.Mishra@Sun.COM {
27789865SSaurabh.Mishra@Sun.COM /* TX */
27799865SSaurabh.Mishra@Sun.COM mutex_init(&bfe->bfe_tx_ring.r_lock, NULL, MUTEX_DRIVER, NULL);
27809865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_ring.r_lockp = &bfe->bfe_tx_ring.r_lock;
27819865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_ring.r_buf_len = BFE_MTU + sizeof (struct ether_header) +
27829865SSaurabh.Mishra@Sun.COM VLAN_TAGSZ + ETHERFCSL;
27839865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_ring.r_ndesc = TX_NUM_DESC;
27849865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_ring.r_bfe = bfe;
27859865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_ring.r_avail_desc = TX_NUM_DESC;
27869865SSaurabh.Mishra@Sun.COM
27879865SSaurabh.Mishra@Sun.COM /* RX */
27889865SSaurabh.Mishra@Sun.COM mutex_init(&bfe->bfe_rx_ring.r_lock, NULL, MUTEX_DRIVER, NULL);
27899865SSaurabh.Mishra@Sun.COM bfe->bfe_rx_ring.r_lockp = &bfe->bfe_rx_ring.r_lock;
27909865SSaurabh.Mishra@Sun.COM bfe->bfe_rx_ring.r_buf_len = BFE_MTU + sizeof (struct ether_header) +
27919865SSaurabh.Mishra@Sun.COM VLAN_TAGSZ + ETHERFCSL + RX_HEAD_ROOM;
27929865SSaurabh.Mishra@Sun.COM bfe->bfe_rx_ring.r_ndesc = RX_NUM_DESC;
27939865SSaurabh.Mishra@Sun.COM bfe->bfe_rx_ring.r_bfe = bfe;
27949865SSaurabh.Mishra@Sun.COM bfe->bfe_rx_ring.r_avail_desc = RX_NUM_DESC;
27959865SSaurabh.Mishra@Sun.COM
27969865SSaurabh.Mishra@Sun.COM /* Allocate TX Ring */
27979865SSaurabh.Mishra@Sun.COM if (bfe_ring_desc_alloc(bfe, &bfe->bfe_tx_ring,
27989865SSaurabh.Mishra@Sun.COM DDI_DMA_WRITE) != DDI_SUCCESS)
27999865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
28009865SSaurabh.Mishra@Sun.COM
28019865SSaurabh.Mishra@Sun.COM /* Allocate RX Ring */
28029865SSaurabh.Mishra@Sun.COM if (bfe_ring_desc_alloc(bfe, &bfe->bfe_rx_ring,
28039865SSaurabh.Mishra@Sun.COM DDI_DMA_READ) != DDI_SUCCESS) {
28049865SSaurabh.Mishra@Sun.COM cmn_err(CE_NOTE, "RX ring allocation failed");
28059865SSaurabh.Mishra@Sun.COM bfe_ring_desc_free(&bfe->bfe_tx_ring);
28069865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
28079865SSaurabh.Mishra@Sun.COM }
28089865SSaurabh.Mishra@Sun.COM
28099865SSaurabh.Mishra@Sun.COM bfe->bfe_tx_ring.r_flags = BFE_RING_ALLOCATED;
28109865SSaurabh.Mishra@Sun.COM bfe->bfe_rx_ring.r_flags = BFE_RING_ALLOCATED;
28119865SSaurabh.Mishra@Sun.COM
28129865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
28139865SSaurabh.Mishra@Sun.COM }
28149865SSaurabh.Mishra@Sun.COM
28159865SSaurabh.Mishra@Sun.COM static int
bfe_resume(dev_info_t * dip)28169865SSaurabh.Mishra@Sun.COM bfe_resume(dev_info_t *dip)
28179865SSaurabh.Mishra@Sun.COM {
28189865SSaurabh.Mishra@Sun.COM bfe_t *bfe;
28199865SSaurabh.Mishra@Sun.COM int err = DDI_SUCCESS;
28209865SSaurabh.Mishra@Sun.COM
28219865SSaurabh.Mishra@Sun.COM if ((bfe = ddi_get_driver_private(dip)) == NULL) {
28229865SSaurabh.Mishra@Sun.COM bfe_error(dip, "Unexpected error (no driver private data)"
28239865SSaurabh.Mishra@Sun.COM " while resume");
28249865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
28259865SSaurabh.Mishra@Sun.COM }
28269865SSaurabh.Mishra@Sun.COM
28279865SSaurabh.Mishra@Sun.COM /*
28289865SSaurabh.Mishra@Sun.COM * Grab all the locks first.
28299865SSaurabh.Mishra@Sun.COM */
28309865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
28319865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_RESUME;
28329865SSaurabh.Mishra@Sun.COM
28339865SSaurabh.Mishra@Sun.COM bfe_init_vars(bfe);
28349865SSaurabh.Mishra@Sun.COM /* PHY will also start running */
28359865SSaurabh.Mishra@Sun.COM bfe_chip_reset(bfe);
28369865SSaurabh.Mishra@Sun.COM if (bfe_chip_start(bfe) == DDI_FAILURE) {
28379865SSaurabh.Mishra@Sun.COM bfe_error(dip, "Could not resume chip");
28389865SSaurabh.Mishra@Sun.COM err = DDI_FAILURE;
28399865SSaurabh.Mishra@Sun.COM }
284010591SSaurabh.Mishra@Sun.COM
28419865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
284210591SSaurabh.Mishra@Sun.COM
284310591SSaurabh.Mishra@Sun.COM if (err == DDI_SUCCESS)
284410591SSaurabh.Mishra@Sun.COM mac_tx_update(bfe->bfe_machdl);
284510591SSaurabh.Mishra@Sun.COM
28469865SSaurabh.Mishra@Sun.COM return (err);
28479865SSaurabh.Mishra@Sun.COM }
28489865SSaurabh.Mishra@Sun.COM
28499865SSaurabh.Mishra@Sun.COM static int
bfe_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)28509865SSaurabh.Mishra@Sun.COM bfe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
28519865SSaurabh.Mishra@Sun.COM {
28529865SSaurabh.Mishra@Sun.COM int unit;
28539865SSaurabh.Mishra@Sun.COM bfe_t *bfe;
28549865SSaurabh.Mishra@Sun.COM mac_register_t *macreg;
28559865SSaurabh.Mishra@Sun.COM int ret;
28569865SSaurabh.Mishra@Sun.COM
28579865SSaurabh.Mishra@Sun.COM switch (cmd) {
28589865SSaurabh.Mishra@Sun.COM case DDI_RESUME:
28599865SSaurabh.Mishra@Sun.COM return (bfe_resume(dip));
28609865SSaurabh.Mishra@Sun.COM
28619865SSaurabh.Mishra@Sun.COM case DDI_ATTACH:
28629865SSaurabh.Mishra@Sun.COM break;
28639865SSaurabh.Mishra@Sun.COM
28649865SSaurabh.Mishra@Sun.COM default:
28659865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
28669865SSaurabh.Mishra@Sun.COM }
28679865SSaurabh.Mishra@Sun.COM
28689865SSaurabh.Mishra@Sun.COM
28699865SSaurabh.Mishra@Sun.COM unit = ddi_get_instance(dip);
28709865SSaurabh.Mishra@Sun.COM
28719865SSaurabh.Mishra@Sun.COM bfe = kmem_zalloc(sizeof (bfe_t), KM_SLEEP);
28729865SSaurabh.Mishra@Sun.COM bfe->bfe_dip = dip;
28739865SSaurabh.Mishra@Sun.COM bfe->bfe_unit = unit;
28749865SSaurabh.Mishra@Sun.COM
28759865SSaurabh.Mishra@Sun.COM if (pci_config_setup(dip, &bfe->bfe_conf_handle) != DDI_SUCCESS) {
28769865SSaurabh.Mishra@Sun.COM bfe_error(dip, "pci_config_setup failed");
28779865SSaurabh.Mishra@Sun.COM goto fail0;
28789865SSaurabh.Mishra@Sun.COM }
28799865SSaurabh.Mishra@Sun.COM
28809865SSaurabh.Mishra@Sun.COM /*
28819865SSaurabh.Mishra@Sun.COM * Enable IO space, Bus Master and Memory Space accessess.
28829865SSaurabh.Mishra@Sun.COM */
28839865SSaurabh.Mishra@Sun.COM ret = pci_config_get16(bfe->bfe_conf_handle, PCI_CONF_COMM);
28849865SSaurabh.Mishra@Sun.COM pci_config_put16(bfe->bfe_conf_handle, PCI_CONF_COMM,
28859865SSaurabh.Mishra@Sun.COM PCI_COMM_IO | PCI_COMM_MAE | PCI_COMM_ME | ret);
28869865SSaurabh.Mishra@Sun.COM
28879865SSaurabh.Mishra@Sun.COM ddi_set_driver_private(dip, bfe);
28889865SSaurabh.Mishra@Sun.COM
28899865SSaurabh.Mishra@Sun.COM /* Identify hardware */
28909865SSaurabh.Mishra@Sun.COM if (bfe_identify_hardware(bfe) == BFE_FAILURE) {
28919865SSaurabh.Mishra@Sun.COM bfe_error(dip, "Could not identify device");
28929865SSaurabh.Mishra@Sun.COM goto fail1;
28939865SSaurabh.Mishra@Sun.COM }
28949865SSaurabh.Mishra@Sun.COM
28959865SSaurabh.Mishra@Sun.COM if (bfe_regs_map(bfe) != DDI_SUCCESS) {
28969865SSaurabh.Mishra@Sun.COM bfe_error(dip, "Could not map device registers");
28979865SSaurabh.Mishra@Sun.COM goto fail1;
28989865SSaurabh.Mishra@Sun.COM }
28999865SSaurabh.Mishra@Sun.COM
29009865SSaurabh.Mishra@Sun.COM (void) bfe_get_chip_config(bfe);
29019865SSaurabh.Mishra@Sun.COM
29029865SSaurabh.Mishra@Sun.COM /*
29039865SSaurabh.Mishra@Sun.COM * Register with MAC layer
29049865SSaurabh.Mishra@Sun.COM */
29059865SSaurabh.Mishra@Sun.COM if ((macreg = mac_alloc(MAC_VERSION)) == NULL) {
29069865SSaurabh.Mishra@Sun.COM bfe_error(dip, "mac_alloc() failed");
29079865SSaurabh.Mishra@Sun.COM goto fail2;
29089865SSaurabh.Mishra@Sun.COM }
29099865SSaurabh.Mishra@Sun.COM
29109865SSaurabh.Mishra@Sun.COM macreg->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
29119865SSaurabh.Mishra@Sun.COM macreg->m_driver = bfe;
29129865SSaurabh.Mishra@Sun.COM macreg->m_dip = dip;
29139865SSaurabh.Mishra@Sun.COM macreg->m_instance = unit;
29149865SSaurabh.Mishra@Sun.COM macreg->m_src_addr = bfe->bfe_ether_addr;
29159865SSaurabh.Mishra@Sun.COM macreg->m_callbacks = &bfe_mac_callbacks;
29169865SSaurabh.Mishra@Sun.COM macreg->m_min_sdu = 0;
29179865SSaurabh.Mishra@Sun.COM macreg->m_max_sdu = ETHERMTU;
29189865SSaurabh.Mishra@Sun.COM macreg->m_margin = VLAN_TAGSZ;
29199865SSaurabh.Mishra@Sun.COM
29209865SSaurabh.Mishra@Sun.COM if ((ret = mac_register(macreg, &bfe->bfe_machdl)) != 0) {
29219865SSaurabh.Mishra@Sun.COM bfe_error(dip, "mac_register() failed with %d error", ret);
29229865SSaurabh.Mishra@Sun.COM mac_free(macreg);
29239865SSaurabh.Mishra@Sun.COM goto fail2;
29249865SSaurabh.Mishra@Sun.COM }
29259865SSaurabh.Mishra@Sun.COM
29269865SSaurabh.Mishra@Sun.COM mac_free(macreg);
29279865SSaurabh.Mishra@Sun.COM
29289865SSaurabh.Mishra@Sun.COM rw_init(&bfe->bfe_rwlock, NULL, RW_DRIVER,
29299865SSaurabh.Mishra@Sun.COM DDI_INTR_PRI(bfe->bfe_intrpri));
29309865SSaurabh.Mishra@Sun.COM
29319865SSaurabh.Mishra@Sun.COM if (bfe_add_intr(bfe) != DDI_SUCCESS) {
29329865SSaurabh.Mishra@Sun.COM bfe_error(dip, "Could not add interrupt");
29339865SSaurabh.Mishra@Sun.COM goto fail3;
29349865SSaurabh.Mishra@Sun.COM }
29359865SSaurabh.Mishra@Sun.COM
29369865SSaurabh.Mishra@Sun.COM if (bfe_rings_alloc(bfe) != DDI_SUCCESS) {
29379865SSaurabh.Mishra@Sun.COM bfe_error(dip, "Could not allocate TX/RX Ring");
29389865SSaurabh.Mishra@Sun.COM goto fail4;
29399865SSaurabh.Mishra@Sun.COM }
29409865SSaurabh.Mishra@Sun.COM
29419865SSaurabh.Mishra@Sun.COM /* Init and then reset the chip */
29429865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_action = 0;
29439865SSaurabh.Mishra@Sun.COM bfe_init_vars(bfe);
29449865SSaurabh.Mishra@Sun.COM
29459865SSaurabh.Mishra@Sun.COM /* PHY will also start running */
29469865SSaurabh.Mishra@Sun.COM bfe_chip_reset(bfe);
29479865SSaurabh.Mishra@Sun.COM
29489865SSaurabh.Mishra@Sun.COM /*
29499865SSaurabh.Mishra@Sun.COM * Even though we enable the interrupts here but chip's interrupt
29509865SSaurabh.Mishra@Sun.COM * is not enabled yet. It will be enabled once we plumb the interface.
29519865SSaurabh.Mishra@Sun.COM */
29529865SSaurabh.Mishra@Sun.COM if (ddi_intr_enable(bfe->bfe_intrhdl) != DDI_SUCCESS) {
29539865SSaurabh.Mishra@Sun.COM bfe_error(dip, "Could not enable interrupt");
29549865SSaurabh.Mishra@Sun.COM goto fail4;
29559865SSaurabh.Mishra@Sun.COM }
29569865SSaurabh.Mishra@Sun.COM
29579865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
29589865SSaurabh.Mishra@Sun.COM
29599865SSaurabh.Mishra@Sun.COM fail4:
29609865SSaurabh.Mishra@Sun.COM bfe_remove_intr(bfe);
29619865SSaurabh.Mishra@Sun.COM fail3:
296211387SSurya.Prakki@Sun.COM (void) mac_unregister(bfe->bfe_machdl);
29639865SSaurabh.Mishra@Sun.COM fail2:
29649865SSaurabh.Mishra@Sun.COM bfe_unmap_regs(bfe);
29659865SSaurabh.Mishra@Sun.COM fail1:
29669865SSaurabh.Mishra@Sun.COM pci_config_teardown(&bfe->bfe_conf_handle);
29679865SSaurabh.Mishra@Sun.COM fail0:
29689865SSaurabh.Mishra@Sun.COM kmem_free(bfe, sizeof (bfe_t));
29699865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
29709865SSaurabh.Mishra@Sun.COM }
29719865SSaurabh.Mishra@Sun.COM
29729865SSaurabh.Mishra@Sun.COM static int
bfe_detach(dev_info_t * devinfo,ddi_detach_cmd_t cmd)29739865SSaurabh.Mishra@Sun.COM bfe_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
29749865SSaurabh.Mishra@Sun.COM {
29759865SSaurabh.Mishra@Sun.COM bfe_t *bfe;
29769865SSaurabh.Mishra@Sun.COM
29779865SSaurabh.Mishra@Sun.COM bfe = ddi_get_driver_private(devinfo);
29789865SSaurabh.Mishra@Sun.COM
29799865SSaurabh.Mishra@Sun.COM switch (cmd) {
29809865SSaurabh.Mishra@Sun.COM case DDI_DETACH:
29819865SSaurabh.Mishra@Sun.COM /*
29829865SSaurabh.Mishra@Sun.COM * We need to stop the timer before grabbing locks otherwise
29839865SSaurabh.Mishra@Sun.COM * we can land-up in deadlock with untimeout.
29849865SSaurabh.Mishra@Sun.COM */
29859865SSaurabh.Mishra@Sun.COM bfe_stop_timer(bfe);
29869865SSaurabh.Mishra@Sun.COM
29879865SSaurabh.Mishra@Sun.COM /*
29889865SSaurabh.Mishra@Sun.COM * First unregister with MAC layer before stopping DMA
29899865SSaurabh.Mishra@Sun.COM * engine.
29909865SSaurabh.Mishra@Sun.COM */
29919865SSaurabh.Mishra@Sun.COM if (mac_unregister(bfe->bfe_machdl) != DDI_SUCCESS)
29929865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
29939865SSaurabh.Mishra@Sun.COM
29949865SSaurabh.Mishra@Sun.COM bfe->bfe_machdl = NULL;
29959865SSaurabh.Mishra@Sun.COM
29969865SSaurabh.Mishra@Sun.COM /*
29979865SSaurabh.Mishra@Sun.COM * Quiesce the chip first.
29989865SSaurabh.Mishra@Sun.COM */
29999865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
30009865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe);
30019865SSaurabh.Mishra@Sun.COM bfe_stop_phy(bfe);
30029865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
30039865SSaurabh.Mishra@Sun.COM
30049865SSaurabh.Mishra@Sun.COM (void) ddi_intr_disable(bfe->bfe_intrhdl);
30059865SSaurabh.Mishra@Sun.COM
30069865SSaurabh.Mishra@Sun.COM /* Make sure timer is gone. */
30079865SSaurabh.Mishra@Sun.COM bfe_stop_timer(bfe);
30089865SSaurabh.Mishra@Sun.COM
30099865SSaurabh.Mishra@Sun.COM /*
30109865SSaurabh.Mishra@Sun.COM * Free the DMA resources for buffer and then descriptors
30119865SSaurabh.Mishra@Sun.COM */
30129865SSaurabh.Mishra@Sun.COM if (bfe->bfe_tx_ring.r_flags == BFE_RING_ALLOCATED) {
30139865SSaurabh.Mishra@Sun.COM /* TX */
30149865SSaurabh.Mishra@Sun.COM bfe_buffer_free(&bfe->bfe_tx_ring);
30159865SSaurabh.Mishra@Sun.COM bfe_ring_desc_free(&bfe->bfe_tx_ring);
30169865SSaurabh.Mishra@Sun.COM }
30179865SSaurabh.Mishra@Sun.COM
30189865SSaurabh.Mishra@Sun.COM if (bfe->bfe_rx_ring.r_flags == BFE_RING_ALLOCATED) {
30199865SSaurabh.Mishra@Sun.COM /* RX */
30209865SSaurabh.Mishra@Sun.COM bfe_buffer_free(&bfe->bfe_rx_ring);
30219865SSaurabh.Mishra@Sun.COM bfe_ring_desc_free(&bfe->bfe_rx_ring);
30229865SSaurabh.Mishra@Sun.COM }
30239865SSaurabh.Mishra@Sun.COM
30249865SSaurabh.Mishra@Sun.COM bfe_remove_intr(bfe);
30259865SSaurabh.Mishra@Sun.COM bfe_unmap_regs(bfe);
30269865SSaurabh.Mishra@Sun.COM pci_config_teardown(&bfe->bfe_conf_handle);
30279865SSaurabh.Mishra@Sun.COM
30289865SSaurabh.Mishra@Sun.COM mutex_destroy(&bfe->bfe_tx_ring.r_lock);
30299865SSaurabh.Mishra@Sun.COM mutex_destroy(&bfe->bfe_rx_ring.r_lock);
30309865SSaurabh.Mishra@Sun.COM rw_destroy(&bfe->bfe_rwlock);
30319865SSaurabh.Mishra@Sun.COM
30329865SSaurabh.Mishra@Sun.COM kmem_free(bfe, sizeof (bfe_t));
30339865SSaurabh.Mishra@Sun.COM
30349865SSaurabh.Mishra@Sun.COM ddi_set_driver_private(devinfo, NULL);
30359865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
30369865SSaurabh.Mishra@Sun.COM
30379865SSaurabh.Mishra@Sun.COM case DDI_SUSPEND:
30389865SSaurabh.Mishra@Sun.COM /*
30399865SSaurabh.Mishra@Sun.COM * We need to stop the timer before grabbing locks otherwise
30409865SSaurabh.Mishra@Sun.COM * we can land-up in deadlock with untimeout.
30419865SSaurabh.Mishra@Sun.COM */
30429865SSaurabh.Mishra@Sun.COM bfe_stop_timer(bfe);
30439865SSaurabh.Mishra@Sun.COM
30449865SSaurabh.Mishra@Sun.COM /*
30459865SSaurabh.Mishra@Sun.COM * Grab all the locks first.
30469865SSaurabh.Mishra@Sun.COM */
30479865SSaurabh.Mishra@Sun.COM bfe_grab_locks(bfe);
30489865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe);
30499865SSaurabh.Mishra@Sun.COM bfe_stop_phy(bfe);
30509865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_SUSPENDED;
30519865SSaurabh.Mishra@Sun.COM bfe_release_locks(bfe);
30529865SSaurabh.Mishra@Sun.COM
30539865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
30549865SSaurabh.Mishra@Sun.COM
30559865SSaurabh.Mishra@Sun.COM default:
30569865SSaurabh.Mishra@Sun.COM return (DDI_FAILURE);
30579865SSaurabh.Mishra@Sun.COM }
30589865SSaurabh.Mishra@Sun.COM }
30599865SSaurabh.Mishra@Sun.COM
30609865SSaurabh.Mishra@Sun.COM /*
30619865SSaurabh.Mishra@Sun.COM * Quiesce the card for fast reboot
30629865SSaurabh.Mishra@Sun.COM */
30639865SSaurabh.Mishra@Sun.COM int
bfe_quiesce(dev_info_t * dev_info)30649865SSaurabh.Mishra@Sun.COM bfe_quiesce(dev_info_t *dev_info)
30659865SSaurabh.Mishra@Sun.COM {
30669865SSaurabh.Mishra@Sun.COM bfe_t *bfe;
30679865SSaurabh.Mishra@Sun.COM
30689865SSaurabh.Mishra@Sun.COM bfe = ddi_get_driver_private(dev_info);
30699865SSaurabh.Mishra@Sun.COM
30709865SSaurabh.Mishra@Sun.COM bfe_chip_halt(bfe);
30719865SSaurabh.Mishra@Sun.COM bfe_stop_phy(bfe);
30729865SSaurabh.Mishra@Sun.COM bfe->bfe_chip_state = BFE_CHIP_QUIESCED;
30739865SSaurabh.Mishra@Sun.COM
30749865SSaurabh.Mishra@Sun.COM return (DDI_SUCCESS);
30759865SSaurabh.Mishra@Sun.COM }
30769865SSaurabh.Mishra@Sun.COM
30779865SSaurabh.Mishra@Sun.COM static struct cb_ops bfe_cb_ops = {
30789865SSaurabh.Mishra@Sun.COM nulldev, /* cb_open */
30799865SSaurabh.Mishra@Sun.COM nulldev, /* cb_close */
30809865SSaurabh.Mishra@Sun.COM nodev, /* cb_strategy */
30819865SSaurabh.Mishra@Sun.COM nodev, /* cb_print */
30829865SSaurabh.Mishra@Sun.COM nodev, /* cb_dump */
30839865SSaurabh.Mishra@Sun.COM nodev, /* cb_read */
30849865SSaurabh.Mishra@Sun.COM nodev, /* cb_write */
30859865SSaurabh.Mishra@Sun.COM nodev, /* cb_ioctl */
30869865SSaurabh.Mishra@Sun.COM nodev, /* cb_devmap */
30879865SSaurabh.Mishra@Sun.COM nodev, /* cb_mmap */
30889865SSaurabh.Mishra@Sun.COM nodev, /* cb_segmap */
30899865SSaurabh.Mishra@Sun.COM nochpoll, /* cb_chpoll */
30909865SSaurabh.Mishra@Sun.COM ddi_prop_op, /* cb_prop_op */
30919865SSaurabh.Mishra@Sun.COM NULL, /* cb_stream */
30929865SSaurabh.Mishra@Sun.COM D_MP | D_HOTPLUG, /* cb_flag */
30939865SSaurabh.Mishra@Sun.COM CB_REV, /* cb_rev */
30949865SSaurabh.Mishra@Sun.COM nodev, /* cb_aread */
30959865SSaurabh.Mishra@Sun.COM nodev /* cb_awrite */
30969865SSaurabh.Mishra@Sun.COM };
30979865SSaurabh.Mishra@Sun.COM
30989865SSaurabh.Mishra@Sun.COM static struct dev_ops bfe_dev_ops = {
30999865SSaurabh.Mishra@Sun.COM DEVO_REV, /* devo_rev */
31009865SSaurabh.Mishra@Sun.COM 0, /* devo_refcnt */
31019865SSaurabh.Mishra@Sun.COM NULL, /* devo_getinfo */
31029865SSaurabh.Mishra@Sun.COM nulldev, /* devo_identify */
31039865SSaurabh.Mishra@Sun.COM nulldev, /* devo_probe */
31049865SSaurabh.Mishra@Sun.COM bfe_attach, /* devo_attach */
31059865SSaurabh.Mishra@Sun.COM bfe_detach, /* devo_detach */
31069865SSaurabh.Mishra@Sun.COM nodev, /* devo_reset */
31079865SSaurabh.Mishra@Sun.COM &bfe_cb_ops, /* devo_cb_ops */
31089865SSaurabh.Mishra@Sun.COM NULL, /* devo_bus_ops */
31099865SSaurabh.Mishra@Sun.COM ddi_power, /* devo_power */
31109865SSaurabh.Mishra@Sun.COM bfe_quiesce /* devo_quiesce */
31119865SSaurabh.Mishra@Sun.COM };
31129865SSaurabh.Mishra@Sun.COM
31139865SSaurabh.Mishra@Sun.COM static struct modldrv bfe_modldrv = {
31149865SSaurabh.Mishra@Sun.COM &mod_driverops,
31159865SSaurabh.Mishra@Sun.COM bfe_ident,
31169865SSaurabh.Mishra@Sun.COM &bfe_dev_ops
31179865SSaurabh.Mishra@Sun.COM };
31189865SSaurabh.Mishra@Sun.COM
31199865SSaurabh.Mishra@Sun.COM static struct modlinkage modlinkage = {
31209865SSaurabh.Mishra@Sun.COM MODREV_1, (void *)&bfe_modldrv, NULL
31219865SSaurabh.Mishra@Sun.COM };
31229865SSaurabh.Mishra@Sun.COM
31239865SSaurabh.Mishra@Sun.COM int
_info(struct modinfo * modinfop)31249865SSaurabh.Mishra@Sun.COM _info(struct modinfo *modinfop)
31259865SSaurabh.Mishra@Sun.COM {
31269865SSaurabh.Mishra@Sun.COM return (mod_info(&modlinkage, modinfop));
31279865SSaurabh.Mishra@Sun.COM }
31289865SSaurabh.Mishra@Sun.COM
31299865SSaurabh.Mishra@Sun.COM int
_init(void)31309865SSaurabh.Mishra@Sun.COM _init(void)
31319865SSaurabh.Mishra@Sun.COM {
31329865SSaurabh.Mishra@Sun.COM int status;
31339865SSaurabh.Mishra@Sun.COM
31349865SSaurabh.Mishra@Sun.COM mac_init_ops(&bfe_dev_ops, MODULE_NAME);
31359865SSaurabh.Mishra@Sun.COM status = mod_install(&modlinkage);
31369865SSaurabh.Mishra@Sun.COM if (status == DDI_FAILURE)
31379865SSaurabh.Mishra@Sun.COM mac_fini_ops(&bfe_dev_ops);
31389865SSaurabh.Mishra@Sun.COM return (status);
31399865SSaurabh.Mishra@Sun.COM }
31409865SSaurabh.Mishra@Sun.COM
31419865SSaurabh.Mishra@Sun.COM int
_fini(void)31429865SSaurabh.Mishra@Sun.COM _fini(void)
31439865SSaurabh.Mishra@Sun.COM {
31449865SSaurabh.Mishra@Sun.COM int status;
31459865SSaurabh.Mishra@Sun.COM
31469865SSaurabh.Mishra@Sun.COM status = mod_remove(&modlinkage);
31479865SSaurabh.Mishra@Sun.COM if (status == 0) {
31489865SSaurabh.Mishra@Sun.COM mac_fini_ops(&bfe_dev_ops);
31499865SSaurabh.Mishra@Sun.COM }
31509865SSaurabh.Mishra@Sun.COM return (status);
31519865SSaurabh.Mishra@Sun.COM }
3152