bfe.c revision dd52495f0d9ba8ff6d84921ec0500be837896554
43051d2742bbe5911de73322064cb573b6aff975Robert Mustacchi * CDDL HEADER START
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * The contents of this file are subject to the terms of the
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Common Development and Distribution License (the "License").
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * You may not use this file except in compliance with the License.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * See the License for the specific language governing permissions
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * and limitations under the License.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * When distributing Covered Code, include this CDDL HEADER in each
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * If applicable, add the following below this CDDL HEADER, with the
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * CDDL HEADER END
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Use is subject to license terms.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Broadcom BCM4401 chipsets use two rings :
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * - One TX : For sending packets down the wire.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * - One RX : For receving packets.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Each ring can have any number of descriptors (configured during attach).
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * As of now we configure only 128 descriptor per ring (TX/RX). Each descriptor
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * has address (desc_addr) and control (desc_ctl) which holds a DMA buffer for
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * the packet and control information (like start/end of frame or end of table).
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * The descriptor table is allocated first and then a DMA buffer (for a packet)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * is allocated and linked to each descriptor.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Each descriptor entry is bfe_desc_t structure in bfe. During TX/RX
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * interrupt, the stat register will point to current descriptor being
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * processed.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Here's an example of TX and RX ring :
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Base of the descriptor table is programmed using BFE_DMATX_CTRL control
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * register. Each 'addr' points to DMA buffer (or packet data buffer) to
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * be transmitted and 'ctl' has the length of the packet (usually MTU).
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | addr |Descriptor 0 |
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | addr |Descriptor 1 | SOF (start of the frame)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | ... |Descriptor... | EOF (end of the frame)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | addr |Descritor 127 |
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | ctl | EOT | EOT (End of Table)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * 'r_curr_desc' : pointer to current descriptor which can be used to transmit
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * 'r_avail_desc' : decremented whenever a packet is being sent.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * 'r_cons_desc' : incremented whenever a packet is sent down the wire and
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * notified by an interrupt to bfe driver.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Base of the descriptor table is programmed using BFE_DMARX_CTRL control
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * register. Each 'addr' points to DMA buffer (or packet data buffer). 'ctl'
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * contains the size of the DMA buffer and all the DMA buffers are
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * pre-allocated during attach and hence the maxmium size of the packet is
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * also known (r_buf_len from the bfe_rint_t structure). During RX interrupt
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * the packet length is embedded in bfe_header_t which is added by the
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * chip in the beginning of the packet.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | addr |Descriptor 0 |
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | addr |Descriptor 1 |
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | ... |Descriptor... |
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | addr |Descriptor 127|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * | ctl | EOT | EOT (End of Table)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * ----------------------|
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * 'r_curr_desc' : pointer to current descriptor while receving a packet.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Used for checking PHY (link state, speed)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe#define BFE_TIMEOUT_INTERVAL (1000 * 1000 * 1000)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Chip restart action and reason for restart
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe#define BFE_ACTION_RESTART 0x1 /* For restarting the chip */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe#define BFE_ACTION_RESTART_SETPROP 0x2 /* restart due to setprop */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe#define BFE_ACTION_RESTART_FAULT 0x4 /* restart due to fault */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe#define BFE_ACTION_RESTART_PKT 0x8 /* restart due to pkt timeout */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowestatic char bfe_ident[] = "bfe driver for Broadcom BCM4401 chipsets";
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Function Prototypes for bfe driver.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowestatic void bfe_error(dev_info_t *, char *, ...);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowestatic int bfe_mac_getprop(void *, const char *, mac_prop_id_t, uint_t,
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowestatic int bfe_mac_setprop(void *, const char *, mac_prop_id_t, uint_t,
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe const void *);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Loweint bfe_mac_set_ether_addr(void *, const uint8_t *);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Macros for ddi_dma_sync().
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe#define SYNC_DESC(r, s, l, d) \
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe#define SYNC_BUF(r, s, b, l, d) \
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Supported Broadcom BCM4401 Cards.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * DMA attributes for device registers, packet data (buffer) and
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * descriptor table.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowestatic struct ddi_device_acc_attr bfe_dev_attr = {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowestatic struct ddi_device_acc_attr bfe_buf_attr = {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe 0, /* dma_attr_addr_lo */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe 0, /* dma_attr_burstsizes */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe 0 /* dma_attr_flags */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe 0, /* dma_attr_addr_lo */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe 0, /* dma_attr_burstsizes */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe 0 /* dma_attr_flags */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Ethernet broadcast addresses.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe ASSERT(mutex_owned(&bfe->bfe_tx_ring.r_lock)); \
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Debugging and error reproting code.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe ddi_driver_name(dip), ddi_get_instance(dip), buf);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Grabs all necessary locks to block any other operation on the chip.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Grab all the locks.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * - bfe_rwlock : locks down whole chip including RX.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * - tx's r_lock : locks down only TX side.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Note that we don't use RX's r_lock.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Release lock on chip/drver.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Release all the locks in the order in which they were grabbed.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * It's used to make sure that the write to device register was successful.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowebfe_wait_bit(bfe_t *bfe, uint32_t reg, uint32_t bit,
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (i = 0; i < t; i++) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* if device still didn't see the value */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe return (-1);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * PHY functions (read, write, stop, reset and startup)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) bfe_wait_bit(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 10, 0);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe return ((INL(bfe, BFE_MDIO_DATA) & BFE_MDIO_DATA_DATA));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowebfe_write_phy(bfe_t *bfe, uint32_t reg, uint32_t val)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) bfe_wait_bit(bfe, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 10, 0);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * It resets the PHY layer.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe_write_phy(bfe, MII_CONTROL, MII_CONTROL_RESET);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (i = 0; i < 10; i++) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (i == 10) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe_error(bfe->bfe_dip, "Timeout waiting for PHY to reset");
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Make sure timer function is out of our way and especially during
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Stops the PHY
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe_write_phy(bfe, MII_CONTROL, MII_CONTROL_PWRDN |
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Report the link status to MAC layer.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * This timeout function fires at BFE_TIMEOUT_INTERVAL to check the link
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * We don't grab any lock because bfe can't go away.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * untimeout() will wait for this timeout instance to complete.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (bfe->bfe_chip_action & BFE_ACTION_RESTART) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Restart the chip.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_FAULT;
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_PKT;
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Restart will register a new timeout */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe DTRACE_PROBE2(chip__restart, int, bfe->bfe_unit,
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe char *, "pkt timeout");
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Report the link status to MAC layer if link status changed.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (bfe->bfe_chip.duplex == LINK_DUPLEX_FULL) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Starts PHY layer.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe MII_ABILITY_100BASE_TX_FD | MII_ABILITY_100BASE_TX |
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe MII_ABILITY_10BASE_T_FD | MII_ABILITY_10BASE_T);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Supported hardware modes are in bmsr.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Assume no capabilities are supported in the hardware.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Assume property is set.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (!(bfe->bfe_chip_action & BFE_ACTION_RESTART_SETPROP)) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Property is not set which means bfe_mac_setprop()
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * is not called on us.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (s == 0) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (s == 0) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (s == 0) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (s == 0) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (s == 0) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (s == 0) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (s == 0) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe "No valid link mode selected. Powering down PHY");
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * If property is set then user would have goofed up. So we
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * go back to default properties.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe->bfe_chip_action &= ~BFE_ACTION_RESTART_SETPROP;
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (bfe->bfe_adv_aneg && (bmsr & MII_STATUS_CANAUTONEG)) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bmcr = (MII_CONTROL_100MB | MII_CONTROL_FDUPLEX);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe->bfe_periodic_id = ddi_periodic_add(bfe_timeout,
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe DTRACE_PROBE1(first__timeout, int, bfe->bfe_unit);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Reports link status back to MAC Layer.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe mac_link_update(bfe->bfe_machdl, bfe->bfe_chip.link);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Reads PHY/MII registers and get the link status for us.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe->bfe_mii_exp = bfe_read_phy(bfe, MII_AN_EXPANSION);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * If exp register is not present in PHY.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Forced mode */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe } else if ((!(bmsr & MII_STATUS_CANAUTONEG)) ||
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe } else if (anar & anlpar & MII_ABILITY_100BASE_TX_FD) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe } else if (anar & anlpar & MII_ABILITY_100BASE_T4) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe } else if (anar & anlpar & MII_ABILITY_100BASE_TX) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe } else if (anar & anlpar & MII_ABILITY_10BASE_T_FD) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe } else if (anar & anlpar & MII_ABILITY_10BASE_T) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * If speed or link status or duplex mode changed then report to
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * MAC layer which is done by the caller.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowebfe_cam_write(bfe_t *bfe, uchar_t *d, int index)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) bfe_wait_bit(bfe, BFE_CAM_CTRL, BFE_CAM_BUSY, 10, 1);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Chip related functions (halt, reset, start).
43051d2742bbe5911de73322064cb573b6aff975Robert Mustacchi * Disables interrupts.
43051d2742bbe5911de73322064cb573b6aff975Robert Mustacchi OUTL(bfe, BFE_ENET_CTRL, BFE_ENET_DISABLE);
43051d2742bbe5911de73322064cb573b6aff975Robert Mustacchi * Wait until TX and RX finish their job.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) bfe_wait_bit(bfe, BFE_ENET_CTRL, BFE_ENET_DISABLE, 20, 1);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Disables DMA engine.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe DTRACE_PROBE2(chip__restart, int, bfe->bfe_unit,
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Halt chip and PHY.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Init variables.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Reset chip and start PHY.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * DMA descriptor rings.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Disables core by stopping the clock.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_SBTMSLOW, (BFE_REJECT | BFE_CLOCK));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) bfe_wait_bit(bfe, BFE_SBTMSLOW, BFE_REJECT, 100, 0);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) bfe_wait_bit(bfe, BFE_SBTMSHIGH, BFE_BUSY, 100, 1);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_SBTMSLOW, (BFE_FGC | BFE_CLOCK | BFE_REJECT | BFE_RESET));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_SBTMSLOW, (BFE_REJECT | BFE_RESET));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Resets core.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * First disable the core.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_SBTMSLOW, (BFE_RESET | BFE_CLOCK | BFE_FGC));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_SBIMSTATE, val & ~(BFE_IBE | BFE_TO));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_SBTMSLOW, (BFE_CLOCK | BFE_FGC));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Change bar0 window to map sbtopci registers.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bar_orig = pci_config_get32(bfe->bfe_conf_handle, BFE_BAR0_WIN);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe pci_config_put32(bfe->bfe_conf_handle, BFE_BAR0_WIN, BFE_REG_PCI);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Just read it and don't do anything */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Restore bar0 window mapping.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe pci_config_put32(bfe->bfe_conf_handle, BFE_BAR0_WIN, bar_orig);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Resets chip and starts PHY.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Set the interrupt vector for the enet core */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* check if core is up */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (INL(bfe, BFE_DMARX_STAT) & BFE_STAT_EMASK) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) bfe_wait_bit(bfe, BFE_DMARX_STAT, BFE_STAT_SIDLE,
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL_OR(bfe, BFE_MAC_CTRL, BFE_CTRL_CRC32_ENAB | BFE_CTRL_LED);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_RCV_LAZY, ((1 << BFE_LAZY_FC_SHIFT) &
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_RXMAXLEN, bfe->bfe_rx_ring.r_buf_len);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_TXMAXLEN, bfe->bfe_tx_ring.r_buf_len);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Program DMA channels */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * DMA addresses need to be added to BFE_PCI_DMA
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe->bfe_tx_ring.r_desc_cookie.dmac_laddress + BFE_PCI_DMA);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(bfe, BFE_DMARX_CTRL, (BFE_RX_OFFSET << BFE_RX_CTRL_ROSHIFT)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bfe->bfe_rx_ring.r_desc_cookie.dmac_laddress + BFE_PCI_DMA);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * It enables interrupts. Should be the last step while starting chip.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Enable the chip and core */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Enable interrupts */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Common code to take care of setting RX side mode (filter).
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe ether_addr_t mac[ETHERADDRL] = {0, 0, 0, 0, 0, 0};
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * We don't touch RX filter if we were asked to suspend. It's fine
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * if chip is not active (no interface is plumbed on us).
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if ((bfe->bfe_chip_mode & BFE_RX_MODE_ENABLE) == 0) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe } else if (bfe->bfe_chip_mode & BFE_RX_MODE_PROMISC) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Flush everything */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Disable CAM */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * We receive all multicast packets.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (i = 0; i < BFE_MAX_MULTICAST_TABLE - 1; i++) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Enable CAM */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe DTRACE_PROBE2(rx__mode__filter, int, bfe->bfe_unit,
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Reset various variable values to initial state.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Initial assumption */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Initializes TX side descriptor entries (bfe_desc_t). Each descriptor entry
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * has control (desc_ctl) and address (desc_addr) member.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (i = 0; i < r->r_ndesc; i++) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_ctl),
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * DMA addresses need to be added to BFE_PCI_DMA
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_addr),
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (r->r_buf_dma[i].cookie.dmac_laddress + BFE_PCI_DMA));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe v = GET_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe PUT_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl),
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Initializes RX side descriptor entries (bfe_desc_t). Each descriptor entry
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * has control (desc_ctl) and address (desc_addr) member.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (i = 0; i < r->r_ndesc; i++) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_ctl),
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe PUT_DESC(r, (uint32_t *)&(r->r_desc[i].desc_addr),
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (r->r_buf_dma[i].cookie.dmac_laddress + BFE_PCI_DMA));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Initialize rx header (len, flags) */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe bzero(r->r_buf_dma[i].addr, sizeof (bfe_rx_header_t));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) SYNC_BUF(r, i, 0, sizeof (bfe_rx_header_t),
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe v = GET_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe PUT_DESC(r, (uint32_t *)&(r->r_desc[i - 1].desc_ctl),
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe (void) SYNC_DESC(r, 0, r->r_ndesc, DDI_DMA_SYNC_FORDEV);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* TAIL of RX Descriptor */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe OUTL(r->r_bfe, BFE_DMARX_PTR, ((i) * sizeof (bfe_desc_t)));
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Stop the chip first & then Reset the chip. At last enable interrupts.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Reset chip and start PHY.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Initailize Descriptor Rings.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe /* Check link, speed and duplex mode */
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Clear chip statistics.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Stat registers are cleared by reading.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (r = BFE_TX_GOOD_O; r <= BFE_TX_PAUSE; r += 4)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (r = BFE_RX_GOOD_O; r <= BFE_RX_NPAUSE; r += 4)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Collect chip statistics.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (r = BFE_TX_GOOD_O; r <= BFE_TX_PAUSE; r += 4) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe for (r = BFE_RX_GOOD_O; r <= BFE_RX_NPAUSE; r += 4) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * tx_good_octets, tx_good_pkts, tx_octets
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * tx_pkts, tx_broadcast_pkts, tx_multicast_pkts
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * tx_len_64, tx_len_65_to_127, tx_len_128_to_255
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * tx_len_256_to_511, tx_len_512_to_1023, tx_len_1024_to_max
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * tx_jabber_pkts, tx_oversize_pkts, tx_fragment_pkts
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * tx_underruns, tx_total_cols, tx_single_cols
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * tx_multiple_cols, tx_excessive_cols, tx_late_cols
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * tx_defered, tx_carrier_lost, tx_pause_pkts
/* txerr += bfe->bfe_hw_stats.tx_carrier_lost; */
uint64_t v;
int err = 0;
switch (stat) {
case MAC_STAT_IFSPEED:
case ETHER_STAT_ADV_CAP_100T4:
case ETHER_STAT_ADV_CAP_10FDX:
case ETHER_STAT_ADV_CAP_10HDX:
case ETHER_STAT_ADV_CAP_PAUSE:
case ETHER_STAT_ADV_REMFAULT:
case ETHER_STAT_ALIGN_ERRORS:
case ETHER_STAT_CAP_100T4:
case ETHER_STAT_CAP_100FDX:
case ETHER_STAT_CAP_100HDX:
case ETHER_STAT_CAP_10FDX:
case ETHER_STAT_CAP_10HDX:
case ETHER_STAT_CAP_ASMPAUSE:
case ETHER_STAT_CAP_AUTONEG:
case ETHER_STAT_CAP_PAUSE:
case ETHER_STAT_CAP_REMFAULT:
case ETHER_STAT_JABBER_ERRORS:
case ETHER_STAT_DEFER_XMTS:
case ETHER_STAT_EX_COLLISIONS:
case ETHER_STAT_FCS_ERRORS:
case ETHER_STAT_LINK_ASMPAUSE:
case ETHER_STAT_LINK_AUTONEG:
case ETHER_STAT_LINK_DUPLEX:
case ETHER_STAT_LP_CAP_100T4:
case ETHER_STAT_LP_CAP_100FDX:
case ETHER_STAT_LP_CAP_100HDX:
case ETHER_STAT_LP_CAP_10FDX:
case ETHER_STAT_LP_CAP_10HDX:
case ETHER_STAT_LP_CAP_PAUSE:
case ETHER_STAT_LP_REMFAULT:
case ETHER_STAT_MACRCV_ERRORS:
case ETHER_STAT_MACXMT_ERRORS:
case ETHER_STAT_SQE_ERRORS:
case ETHER_STAT_XCVR_ADDR:
case ETHER_STAT_XCVR_ID:
case MAC_STAT_BRDCSTRCV:
case MAC_STAT_BRDCSTXMT:
case MAC_STAT_MULTIXMT:
case MAC_STAT_COLLISIONS:
case MAC_STAT_IERRORS:
case MAC_STAT_IPACKETS:
case MAC_STAT_MULTIRCV:
case MAC_STAT_NORCVBUF:
case MAC_STAT_NOXMTBUF:
case MAC_STAT_OBYTES:
case MAC_STAT_OERRORS:
case MAC_STAT_OPACKETS:
case MAC_STAT_RBYTES:
case MAC_STAT_UNDERFLOWS:
case MAC_STAT_OVERFLOWS:
*val = v;
return (err);
int err = 0;
if (sz == 0)
return (EINVAL);
switch (num) {
case MAC_PROP_DUPLEX:
sizeof (link_duplex_t));
case MAC_PROP_SPEED:
case MAC_PROP_AUTONEG:
case MAC_PROP_ADV_100FDX_CAP:
case MAC_PROP_EN_100FDX_CAP:
case MAC_PROP_ADV_100HDX_CAP:
case MAC_PROP_EN_100HDX_CAP:
case MAC_PROP_ADV_10FDX_CAP:
case MAC_PROP_EN_10FDX_CAP:
case MAC_PROP_ADV_10HDX_CAP:
case MAC_PROP_EN_10HDX_CAP:
case MAC_PROP_ADV_100T4_CAP:
case MAC_PROP_EN_100T4_CAP:
return (err);
const void *val)
switch (num) {
case MAC_PROP_EN_100FDX_CAP:
case MAC_PROP_EN_100HDX_CAP:
case MAC_PROP_EN_10FDX_CAP:
case MAC_PROP_EN_10HDX_CAP:
case MAC_PROP_EN_100T4_CAP:
case MAC_PROP_AUTONEG:
return (ENOTSUP);
if (*capp == 0)
return (ENOTSUP);
return (EINVAL);
uint32_t v;
return (BFE_SUCCESS);
return (BFE_FAILURE);
v |= BFE_DESC_EOT;
r->r_avail_desc--;
return (BFE_SUCCESS);
mblk_t *
return (NULL);
return (mp);
return (EIO);
if (promiscflag) {
uint32_t v;
goto action;
goto action;
goto action;
if (v & BFE_STAT_EMASK) {
if (v & BFE_RX_FLAG_ERRORS) {
uint32_t v;
v |= BFE_DESC_EOT;
static mblk_t *
i = r->r_curr_desc;
int, r->r_curr_desc,
int, current);
r->r_curr_desc = i;
return (rx_head);
uint32_t v;
int, start,
int, cur);
r->r_avail_desc++;
v |= BFE_DESC_EOT;
return (cur);
int resched = 0;
(void) bfe_tx_reclaim(r);
return (resched);
static uint_t
int resched = 0;
if (intr_stat == 0) {
return (DDI_INTR_UNCLAIMED);
return (DDI_INTR_CLAIMED);
return (DDI_INTR_CLAIMED);
if (rx_head) {
if (resched)
return (DDI_INTR_CLAIMED);
int ret;
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (BFE_SUCCESS);
return (BFE_SUCCESS);
int ret;
return (DDI_FAILURE);
return (DDI_SUCCESS);
for (i = 0; i < BFE_EEPROM_SIZE; i++) {
return (DDI_SUCCESS);
int err;
goto fail0;
goto fail1;
&count);
goto fail2;
goto fail2;
return (DDI_SUCCESS);
return (DDI_FAILURE);
for (i = 0; i < r->r_ndesc; i++) {
bfe_ring_buf_free(r, i);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
fail = 0;
for (i = 0; i < r->r_ndesc; i++) {
if (fail) {
bfe_ring_buf_free(r, i);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
return (DDI_FAILURE);
goto done;
done:
return (err);
int unit;
int ret;
switch (cmd) {
case DDI_RESUME:
case DDI_ATTACH:
return (DDI_FAILURE);
goto fail0;
goto fail1;
goto fail1;
goto fail2;
goto fail2;
goto fail3;
goto fail4;
goto fail4;
return (DDI_SUCCESS);
return (DDI_FAILURE);
switch (cmd) {
case DDI_DETACH:
return (DDI_FAILURE);
return (DDI_SUCCESS);
case DDI_SUSPEND:
return (DDI_SUCCESS);
return (DDI_FAILURE);
return (DDI_SUCCESS);
_init(void)
int status;
return (status);
_fini(void)
int status;
if (status == 0) {
return (status);