b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Copyright (c) 2010 Steven Stallion. All rights reserved.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Redistribution and use in source and binary forms, with or without
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * modification, are permitted provided that the following conditions are
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * met:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * 1. Redistributions of source code must retain the above copyright
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * notice, this list of conditions and the following disclaimer.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * 2. Redistributions in binary form must reproduce the above
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * copyright notice, this list of conditions and the following
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * disclaimer in the documentation and/or other materials provided
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * with the distribution.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * 3. Neither the name of the copyright owner nor the names of any
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * contributors may be used to endorse or promote products derived
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * from this software without specific prior written permission.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/byteorder.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/types.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/errno.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/varargs.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/cmn_err.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/note.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/kmem.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/conf.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/devops.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/modctl.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/sysmacros.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/ddi.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/ddi_intr.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/sunddi.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/stream.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/strsun.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/pci.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/ethernet.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/vlan.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/crc32.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/mii.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/mac.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/mac_ether.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include <sys/mac_provider.h>
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#include "efe.h"
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/* Autoconfiguration entry points */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_attach(dev_info_t *, ddi_attach_cmd_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_detach(dev_info_t *, ddi_detach_cmd_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_quiesce(dev_info_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/* MII entry points */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic uint16_t efe_mii_read(void *, uint8_t, uint8_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_mii_write(void *, uint8_t, uint8_t, uint16_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_mii_notify(void *, link_state_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/* MAC entry points */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_m_getstat(void *, uint_t, uint64_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_m_start(void *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_m_stop(void *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_m_setpromisc(void *, boolean_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_m_multicst(void *, boolean_t, const uint8_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_m_unicst(void *, const uint8_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic mblk_t *efe_m_tx(void *, mblk_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion const void *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion void *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_m_propinfo(void *, const char *, mac_prop_id_t,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_prop_info_handle_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/* ISR/periodic callbacks */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic uint_t efe_intr(caddr_t, caddr_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/* Support functions */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_init(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_init_rx_ring(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_init_tx_ring(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_reset(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_start(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_stop(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_stop_dma(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic inline void efe_restart(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_suspend(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_resume(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic efe_ring_t *efe_ring_alloc(dev_info_t *, size_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_ring_free(efe_ring_t **);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic efe_buf_t *efe_buf_alloc(dev_info_t *, size_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_buf_free(efe_buf_t **);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_intr_enable(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_intr_disable(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic mblk_t *efe_recv(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic mblk_t *efe_recv_pkt(efe_t *, efe_desc_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic int efe_send(efe_t *, mblk_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_send_done(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_getaddr(efe_t *, uint8_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_setaddr(efe_t *, uint8_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_setmchash(efe_t *, uint16_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_eeprom_read(efe_t *, uint8_t *, size_t, uint8_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic uint16_t efe_eeprom_readw(efe_t *, int, uint8_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic inline int efe_eeprom_readbit(efe_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic inline void efe_eeprom_writebit(efe_t *, int);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_dprintf(dev_info_t *, int, const char *, ...);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#ifdef DEBUG
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#define efe_debug(dip, ...) \
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_dprintf((dip), CE_CONT, __VA_ARGS__)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#else
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#define efe_debug(dip, ...) /*EMPTY*/
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#endif
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#define efe_error(dip, ...) \
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_dprintf((dip), CE_WARN, __VA_ARGS__)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionextern struct mod_ops mod_driverops;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven StallionDDI_DEFINE_STREAM_OPS(efe_dev_ops, nulldev, nulldev, efe_attach, efe_detach,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion nodev, NULL, D_MP, NULL, efe_quiesce);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic struct modldrv modldrv = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion &mod_driverops, /* drv_modops */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion "EPIC/100 Fast Ethernet", /* drv_linkinfo */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion &efe_dev_ops /* drv_dev_ops */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic struct modlinkage modlinkage = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion MODREV_1, /* ml_rev */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion { &modldrv, NULL } /* ml_linkage */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic ddi_device_acc_attr_t efe_regs_acc_attr = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_STRUCTURE_LE_ACC, /* devacc_attr_endian_flags */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_STRICTORDER_ACC /* devacc_attr_dataorder */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic ddi_device_acc_attr_t efe_buf_acc_attr = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_STRICTORDER_ACC /* devacc_attr_dataorder */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic ddi_dma_attr_t efe_dma_attr = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DMA_ATTR_V0, /* dma_attr_version */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0, /* dma_attr_addr_lo */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0xFFFFFFFFUL, /* dma_attr_addr_hi */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0x7FFFFFFFUL, /* dma_attr_count_max */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 4, /* dma_attr_align */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0x7F, /* dma_attr_burstsizes */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 1, /* dma_attr_minxfer */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0xFFFFFFFFUL, /* dma_attr_maxxfer */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0xFFFFFFFFUL, /* dma_attr_seg */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 1, /* dma_attr_sgllen */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 1, /* dma_attr_granular */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0 /* dma_attr_flags */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic mii_ops_t efe_mii_ops = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion MII_OPS_VERSION, /* mii_version */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_mii_read, /* mii_read */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_mii_write, /* mii_write */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_mii_notify /* mii_notify */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic mac_callbacks_t efe_m_callbacks = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion MC_SETPROP | MC_GETPROP, /* mc_callbacks */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_getstat, /* mc_getstat */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_start, /* mc_start */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_stop, /* mc_stop */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_setpromisc, /* mc_setpromisc */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_multicst, /* mc_multicst */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_unicst, /* mc_unicst */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_tx, /* mc_tx */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion NULL, /* mc_reserved */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion NULL, /* mc_ioctl */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion NULL, /* mc_getcapab */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion NULL, /* mc_open */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion NULL, /* mc_close */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_setprop, /* mc_setprop */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_getprop, /* mc_getprop */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_m_propinfo /* mc_propinfo */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic uint8_t efe_broadcast[] = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic uint16_t efe_mchash_promisc[] = {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion};
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Loadable module entry points.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion_init(void)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion int error;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_init_ops(&efe_dev_ops, "efe");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if ((error = mod_install(&modlinkage)) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_fini_ops(&efe_dev_ops);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (error);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion_fini(void)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion int error;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if ((error = mod_remove(&modlinkage)) == DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_fini_ops(&efe_dev_ops);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (error);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion_info(struct modinfo *modinfop)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mod_info(&modlinkage, modinfop));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Autoconfiguration entry points.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_acc_handle_t pci;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion int types;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion int count;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion int actual;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint_t pri;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_register_t *macp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion switch (cmd) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case DDI_ATTACH:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case DDI_RESUME:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep = ddi_get_driver_private(dip);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (efe_resume(efep));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion default:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_FAILURE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * PCI configuration.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to setup PCI configuration!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_FAILURE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion pci_config_put16(pci, PCI_CONF_COMM,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion pci_config_get16(pci, PCI_CONF_COMM) | PCI_COMM_MAE | PCI_COMM_ME);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion pci_config_teardown(&pci);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_get_supported_types(dip, &types)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion != DDI_SUCCESS || !(types & DDI_INTR_TYPE_FIXED)) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "fixed interrupts not supported!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_FAILURE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &count)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion != DDI_SUCCESS || count != 1) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "no fixed interrupts available!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_FAILURE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Initialize soft state.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep = kmem_zalloc(sizeof (efe_t), KM_SLEEP);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_set_driver_private(dip, efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_dip = dip;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_regs_map_setup(dip, 1, (caddr_t *)&efep->efe_regs, 0, 0,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion &efe_regs_acc_attr, &efep->efe_regs_acch) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to setup register mapping!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_rx_ring = efe_ring_alloc(efep->efe_dip, RXDESCL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_rx_ring == NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "unable to allocate rx ring!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_ring = efe_ring_alloc(efep->efe_dip, TXDESCL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_tx_ring == NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "unable to allocate tx ring!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_alloc(dip, &efep->efe_intrh, DDI_INTR_TYPE_FIXED, 0,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion count, &actual, DDI_INTR_ALLOC_STRICT) != DDI_SUCCESS ||
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion actual != count) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate fixed interrupt!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_get_pri(efep->efe_intrh, &pri) != DDI_SUCCESS ||
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion pri >= ddi_intr_get_hilevel_pri()) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to get valid interrupt priority!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_init(&efep->efe_intrlock, NULL, MUTEX_DRIVER,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_INTR_PRI(pri));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_init(&efep->efe_txlock, NULL, MUTEX_DRIVER,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_INTR_PRI(pri));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Initialize device.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_reset(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Use factory address as default */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_getaddr(efep, efep->efe_macaddr);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Enable the ISR.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_add_handler(efep->efe_intrh, efe_intr, efep, NULL)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to add interrupt handler!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_enable(efep->efe_intrh) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to enable interrupt!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Allocate MII resources.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if ((efep->efe_miih = mii_alloc(efep, dip, &efe_mii_ops)) == NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate mii resources!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Allocate MAC resources.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate mac resources!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_driver = efep;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_dip = dip;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_src_addr = efep->efe_macaddr;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_callbacks = &efe_m_callbacks;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_min_sdu = 0;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_max_sdu = ETHERMTU;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_margin = VLAN_TAGSZ;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (mac_register(macp, &efep->efe_mh) != 0) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to register with mac!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_free(macp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_report_dev(dip);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_SUCCESS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionfailure:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (macp != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_free(macp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_miih != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_free(efep->efe_miih);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_intrh != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_intr_disable(efep->efe_intrh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_intr_remove_handler(efep->efe_intrh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_intr_free(efep->efe_intrh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_destroy(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_destroy(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_tx_ring != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_free(&efep->efe_tx_ring);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_rx_ring != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_free(&efep->efe_rx_ring);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_regs_acch != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_regs_map_free(&efep->efe_regs_acch);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion kmem_free(efep, sizeof (efe_t));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_FAILURE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = ddi_get_driver_private(dip);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion switch (cmd) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case DDI_DETACH:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case DDI_SUSPEND:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (efe_suspend(efep));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion default:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_FAILURE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (mac_unregister(efep->efe_mh) != 0) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to unregister from mac!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_FAILURE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_free(efep->efe_miih);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_intr_disable(efep->efe_intrh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_intr_remove_handler(efep->efe_intrh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_intr_free(efep->efe_intrh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_destroy(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_destroy(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_tx_ring != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_free(&efep->efe_tx_ring);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_rx_ring != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_free(&efep->efe_rx_ring);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_regs_map_free(&efep->efe_regs_acch);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion kmem_free(efep, sizeof (efe_t));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_SUCCESS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_quiesce(dev_info_t *dip)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = ddi_get_driver_private(dip);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(RESET_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_GENCTL, GENCTL_PWRDWN);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_SUCCESS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * MII entry points.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionuint16_t
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_mii_read(void *arg, uint8_t phy, uint8_t reg)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_MMCTL, MMCTL_READ |
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion reg << MMCTL_PHYREG | phy << MMCTL_PHYADDR);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < MII_DELAY_CYCLES; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (!(GETCSR(efep, CSR_MMCTL) & MMCTL_READ)) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return ((uint16_t)GETCSR(efep, CSR_MMDATA));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(MII_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "timed out reading from MII!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t data)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_MMDATA, data);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_MMCTL, MMCTL_WRITE |
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion reg << MMCTL_PHYREG | phy << MMCTL_PHYADDR);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < MII_DELAY_CYCLES; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (!(GETCSR(efep, CSR_MMCTL) & MMCTL_WRITE)) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(MII_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "timed out writing to MII!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_mii_notify(void *arg, link_state_t link)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_link_update(efep->efe_mh, link);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * MAC entry points.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_getstat(void *arg, uint_t stat, uint64_t *val)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (mii_m_getstat(efep->efe_miih, stat, val) == 0) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion switch (stat) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_MULTIRCV:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_multircv;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_BRDCSTRCV:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_brdcstrcv;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_MULTIXMT:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_multixmt;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_BRDCSTXMT:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_brdcstxmt;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_NORCVBUF:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_norcvbuf;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_IERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_ierrors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_NOXMTBUF:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_noxmtbuf;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_OERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_oerrors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_COLLISIONS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_collisions;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_RBYTES:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_rbytes;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_IPACKETS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_ipackets;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_OBYTES:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_obytes;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_OPACKETS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_opackets;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_UNDERFLOWS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_uflo;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case MAC_STAT_OVERFLOWS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_oflo;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_ALIGN_ERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_align_errors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_FCS_ERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_fcs_errors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_FIRST_COLLISIONS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_first_collisions;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_TX_LATE_COLLISIONS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_tx_late_collisions;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_DEFER_XMTS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_defer_xmts;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_EX_COLLISIONS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_ex_collisions;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_MACXMT_ERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_macxmt_errors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_CARRIER_ERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_carrier_errors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_TOOLONG_ERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_toolong_errors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_MACRCV_ERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_macrcv_errors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_TOOSHORT_ERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_runt_errors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion case ETHER_STAT_JABBER_ERRORS:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *val = efep->efe_jabber_errors;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion default:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (ENOTSUP);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_start(void *arg)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_start(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_flags |= FLAG_RUNNING;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_start(efep->efe_miih);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_stop(void *arg)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_stop(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_flags &= ~FLAG_RUNNING;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_stop(efep->efe_miih);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_setpromisc(void *arg, boolean_t on)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_SUSPENDED) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_promisc = on;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_RUNNING) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_restart(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint32_t val;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion int index;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion int bit;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion boolean_t restart = B_FALSE;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_SUSPENDED) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion CRC32(val, macaddr, ETHERADDRL, -1U, crc32_table);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion val %= MCHASHL;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion index = val / MCHASHSZ;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bit = 1U << (val % MCHASHSZ);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (add) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_mccount[val]++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_mccount[val] == 1) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_mchash[index] |= bit;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion restart = B_TRUE;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion } else {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_mccount[val]--;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_mccount[val] == 0) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_mchash[index] &= ~bit;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion restart = B_TRUE;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (restart && efep->efe_flags & FLAG_RUNNING) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_restart(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_unicst(void *arg, const uint8_t *macaddr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_SUSPENDED) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bcopy(macaddr, efep->efe_macaddr, ETHERADDRL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_RUNNING) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_restart(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionmblk_t *
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_tx(void *arg, mblk_t *mp)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_SUSPENDED) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion while (mp != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mblk_t *tmp = mp->b_next;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mp->b_next = NULL;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efe_send(efep, mp) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mp->b_next = tmp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mp = tmp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Kick the transmitter */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_COMMAND, COMMAND_TXQUEUED);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_setprop(void *arg, const char *name, mac_prop_id_t id,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint_t valsize, const void *val)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mii_m_setprop(efep->efe_miih, name, id, valsize, val));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_getprop(void *arg, const char *name, mac_prop_id_t id,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint_t valsize, void *val)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mii_m_getprop(efep->efe_miih, name, id, valsize, val));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_propinfo(void *arg, const char *name, mac_prop_id_t id,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_prop_info_handle_t state)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = arg;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_m_propinfo(efep->efe_miih, name, id, state);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * ISR/periodic callbacks.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionuint_t
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_intr(caddr_t arg1, caddr_t arg2)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_t *efep = (void *)arg1;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint32_t status;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mblk_t *mp = NULL;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion _NOTE(ARGUNUSED(arg2));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_SUSPENDED) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_INTR_UNCLAIMED);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion status = GETCSR(efep, CSR_INTSTAT);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (!(status & INTSTAT_ACTV)) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_INTR_UNCLAIMED);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_INTSTAT, status);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & INTSTAT_RCC) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mp = efe_recv(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & INTSTAT_RQE) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_ierrors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_macrcv_errors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Kick the receiver */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_COMMAND, COMMAND_RXQUEUED);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & INTSTAT_TXC) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_send_done(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & INTSTAT_FATAL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "bus error; resetting!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_restart(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (mp != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_rx(efep->efe_mh, NULL, mp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & INTSTAT_TXC) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mac_tx_update(efep->efe_mh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & INTSTAT_FATAL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_reset(efep->efe_miih);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_INTR_CLAIMED);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Support functions.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_init(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint32_t val;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_intrlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_txlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_reset(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion val = GENCTL_ONECOPY | GENCTL_RFT_128 | GENCTL_MRM;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#ifdef _BIG_ENDIAN
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion val |= GENCTL_BE;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#endif /* _BIG_ENDIAN */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_GENCTL, val);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_PBLCNT, BURSTLEN);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_init_rx_ring(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_init_tx_ring(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_setaddr(efep, efep->efe_macaddr);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_promisc) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_setmchash(efep, efe_mchash_promisc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion } else {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_setmchash(efep, efep->efe_mchash);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_init_rx_ring(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_t *rp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_intrlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp = efep->efe_rx_ring;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < DESCLEN(rp); ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_desc_t *dp = GETDESC(rp, i);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_t *bp = GETBUF(rp, i);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_status, RXSTAT_OWNER);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_len, 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC32(rp, &dp->d_bufaddr, BUFADDR(bp));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_buflen, BUFLEN(bp));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_control, 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC32(rp, &dp->d_next, NEXTDESCADDR(rp, i));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, i, DDI_DMA_SYNC_FORDEV);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_rx_desc = 0;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_PRCDAR, DESCADDR(rp, 0));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_init_tx_ring(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_t *rp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_txlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp = efep->efe_tx_ring;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < DESCLEN(rp); ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_desc_t *dp = GETDESC(rp, i);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_t *bp = GETBUF(rp, i);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_status, 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_len, 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC32(rp, &dp->d_bufaddr, BUFADDR(bp));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_buflen, BUFLEN(bp));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_control, 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC32(rp, &dp->d_next, NEXTDESCADDR(rp, i));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, i, DDI_DMA_SYNC_FORDEV);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_desc = 0;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_sent = 0;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_PTCDAR, DESCADDR(rp, 0));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_reset(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_intrlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_txlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(RESET_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Assert internal clock source (AN 7.15) */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < RESET_TEST_CYCLES; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_TEST, TEST_CLOCK);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_start(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_intrlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_txlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_init(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_RXCON,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion RXCON_SEP | RXCON_RRF | RXCON_RBF | RXCON_RMF |
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (efep->efe_promisc ? RXCON_PROMISC : 0));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_TXCON, TXCON_LB_3);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_intr_enable(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SETBIT(efep, CSR_COMMAND,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion COMMAND_START_RX | COMMAND_RXQUEUED);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_stop(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_intrlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_txlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_intr_disable(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_COMMAND, COMMAND_STOP_RX);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_stop_dma(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(RESET_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_GENCTL, GENCTL_PWRDWN);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_stop_dma(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_intrlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_txlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_COMMAND,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion COMMAND_STOP_RDMA | COMMAND_STOP_TDMA);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < STOP_DELAY_CYCLES; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint32_t status = GETCSR(efep, CSR_INTSTAT);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & INTSTAT_RXIDLE &&
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion status & INTSTAT_TXIDLE) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(STOP_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "timed out stopping DMA engine!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
e65fcc69bb33b3f4525b0c2c9732ece17c90b196Richard Lowestatic inline void
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_restart(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_stop(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_start(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_suspend(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_RUNNING) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_stop(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_flags |= FLAG_SUSPENDED;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_suspend(efep->efe_miih);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_SUCCESS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_resume(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_enter(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (efep->efe_flags & FLAG_RUNNING) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_start(efep);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_flags &= ~FLAG_SUSPENDED;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_txlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_exit(&efep->efe_intrlock);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_resume(efep->efe_miih);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_SUCCESS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_ring_t *
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_ring_alloc(dev_info_t *dip, size_t len)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_t *rp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion size_t rlen;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint_t ccount;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(len > 1);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp = kmem_zalloc(sizeof (efe_ring_t), KM_SLEEP);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp->r_len = len;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_dma_alloc_handle(dip, &efe_dma_attr, DDI_DMA_SLEEP, NULL,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion &rp->r_dmah) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate DMA handle!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_dma_mem_alloc(rp->r_dmah, DESCSZ(len), &efe_buf_acc_attr,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&rp->r_descp,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion &rlen, &rp->r_acch) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate descriptors!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_dma_addr_bind_handle(rp->r_dmah, NULL, (caddr_t)rp->r_descp,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DESCSZ(len), DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion NULL, &rp->r_dmac, &ccount) != DDI_DMA_MAPPED) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to bind DMA handle to descriptors!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp->r_bufpp = kmem_zalloc(BUFPSZ(len), KM_SLEEP);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < len; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_t *bp = efe_buf_alloc(dip, BUFSZ);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (bp == NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp->r_bufpp[i] = bp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (rp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionfailure:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_free(&rp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (NULL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_ring_free(efe_ring_t **rpp)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_t *rp = *rpp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(rp != NULL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < DESCLEN(rp); ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_t *bp = GETBUF(rp, i);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (bp != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_free(&bp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion kmem_free(rp->r_bufpp, BUFPSZ(DESCLEN(rp)));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (rp->r_descp != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_dma_unbind_handle(rp->r_dmah);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (rp->r_acch != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_dma_mem_free(&rp->r_acch);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (rp->r_dmah != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_dma_free_handle(&rp->r_dmah);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion kmem_free(rp, sizeof (efe_ring_t));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *rpp = NULL;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_buf_t *
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_buf_alloc(dev_info_t *dip, size_t len)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_t *bp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion size_t rlen;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint_t ccount;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bp = kmem_zalloc(sizeof (efe_buf_t), KM_SLEEP);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bp->b_len = len;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_dma_alloc_handle(dip, &efe_dma_attr, DDI_DMA_SLEEP, NULL,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion &bp->b_dmah) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate DMA handle!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_dma_mem_alloc(bp->b_dmah, len, &efe_buf_acc_attr,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &bp->b_kaddr, &rlen,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion &bp->b_acch) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate buffer!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_dma_addr_bind_handle(bp->b_dmah, NULL, bp->b_kaddr,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion len, DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion &bp->b_dmac, &ccount) != DDI_DMA_MAPPED) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to bind DMA handle to buffer!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion goto failure;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (bp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionfailure:
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_free(&bp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (NULL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_buf_free(efe_buf_t **bpp)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_t *bp = *bpp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(bp != NULL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (bp->b_kaddr != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_dma_unbind_handle(bp->b_dmah);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (bp->b_acch != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_dma_mem_free(&bp->b_acch);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (bp->b_dmah != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_dma_free_handle(&bp->b_dmah);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion kmem_free(bp, sizeof (efe_buf_t));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *bpp = NULL;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_intr_enable(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_INTMASK,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion INTMASK_RCC | INTMASK_RQE | INTMASK_TXC | INTMASK_FATAL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SETBIT(efep, CSR_GENCTL, GENCTL_INT);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_intr_disable(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_INTMASK, 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion CLRBIT(efep, CSR_GENCTL, GENCTL_INT);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionmblk_t *
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_recv(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_t *rp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mblk_t *mp = NULL;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mblk_t **mpp = &mp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_intrlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp = efep->efe_rx_ring;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (;;) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_desc_t *dp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t status;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion dp = GETDESC(rp, efep->efe_rx_desc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_rx_desc, DDI_DMA_SYNC_FORKERNEL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion status = GETDESC16(rp, &dp->d_status);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Stop if device owns descriptor */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & RXSTAT_OWNER) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & RXSTAT_PRI) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mblk_t *tmp = efe_recv_pkt(efep, dp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (tmp != NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion *mpp = tmp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mpp = &tmp->b_next;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion } else {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_ierrors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & RXSTAT_FAE) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_align_errors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & RXSTAT_CRC) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_fcs_errors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & RXSTAT_MP) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_oflo++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Release ownership to device */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_status, RXSTAT_OWNER);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_rx_desc, DDI_DMA_SYNC_FORDEV);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_rx_desc = NEXTDESC(rp, efep->efe_rx_desc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionmblk_t *
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_recv_pkt(efe_t *efep, efe_desc_t *dp)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_t *rp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_t *bp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t len;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mblk_t *mp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t status;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_intrlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp = efep->efe_rx_ring;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion len = GETDESC16(rp, &dp->d_len) - ETHERFCSL;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (len < ETHERMIN) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_ierrors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_runt_errors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (NULL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (len > ETHERMAX + VLAN_TAGSZ) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_ierrors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_toolong_errors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (NULL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mp = allocb(len, 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (mp == NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_ierrors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_norcvbuf++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (NULL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mp->b_wptr = mp->b_rptr + len;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bp = GETBUF(rp, efep->efe_rx_desc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCBUF(bp, DDI_DMA_SYNC_FORKERNEL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bcopy(bp->b_kaddr, mp->b_rptr, len);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_ipackets++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_rbytes += len;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion status = GETDESC16(rp, &dp->d_status);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & RXSTAT_BAR) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_brdcstrcv++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion } else if (status & RXSTAT_MAR) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_multircv++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionint
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_send(efe_t *efep, mblk_t *mp)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_t *rp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t len;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_desc_t *dp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t status;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_buf_t *bp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_txlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp = efep->efe_tx_ring;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion len = msgsize(mp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (len > ETHERMAX + VLAN_TAGSZ) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_oerrors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_macxmt_errors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion freemsg(mp);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_SUCCESS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion dp = GETDESC(rp, efep->efe_tx_desc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORKERNEL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion status = GETDESC16(efep->efe_tx_ring, &dp->d_status);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Stop if device owns descriptor */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_OWNER) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_FAILURE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bp = GETBUF(rp, efep->efe_tx_desc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mcopymsg(mp, bp->b_kaddr);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /*
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Packets must contain at least ETHERMIN octets.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Padded octets are zeroed out prior to sending.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (len < ETHERMIN) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bzero(bp->b_kaddr + len, ETHERMIN - len);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion len = ETHERMIN;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCBUF(bp, DDI_DMA_SYNC_FORDEV);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_status, TXSTAT_OWNER);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_len, len);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_control, TXCTL_LASTDESCR);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORDEV);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_opackets++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_obytes += len;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (*bp->b_kaddr & 0x01) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (bcmp(bp->b_kaddr, efe_broadcast, ETHERADDRL) == 0) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_brdcstxmt++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion } else {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_multixmt++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_desc = NEXTDESC(rp, efep->efe_tx_desc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (DDI_SUCCESS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_send_done(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_ring_t *rp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(mutex_owned(&efep->efe_txlock));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp = efep->efe_tx_ring;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (;;) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_desc_t *dp;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t status;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion dp = GETDESC(rp, efep->efe_tx_sent);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_tx_sent, DDI_DMA_SYNC_FORKERNEL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion status = GETDESC16(rp, &dp->d_status);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Stop if device owns descriptor */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_OWNER) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion break;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_PTX) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (!(status & TXSTAT_ND)) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_defer_xmts++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_COLL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_first_collisions++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion } else {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_oerrors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_CSL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_carrier_errors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_UFLO) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_uflo++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_OWC) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_late_collisions++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_DEFER) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_jabber_errors++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (status & TXSTAT_EXCOLL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_ex_collisions++;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_collisions +=
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (status >> TXSTAT_CCNT) & TXSTAT_CCNTMASK;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_sent = NEXTDESC(rp, efep->efe_tx_sent);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_getaddr(efe_t *efep, uint8_t *macaddr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_eeprom_read(efep, macaddr, ETHERADDRL, 0x0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_debug(efep->efe_dip,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion "factory address is %02x:%02x:%02x:%02x:%02x:%02x\n",
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macaddr[0], macaddr[1], macaddr[2], macaddr[3],
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macaddr[4], macaddr[5]);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_setaddr(efe_t *efep, uint8_t *macaddr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t val;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bcopy(macaddr, &val, sizeof (uint16_t));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_LAN0, val);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macaddr += sizeof (uint16_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bcopy(macaddr, &val, sizeof (uint16_t));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_LAN1, val);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macaddr += sizeof (uint16_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bcopy(macaddr, &val, sizeof (uint16_t));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_LAN2, val);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_setmchash(efe_t *efep, uint16_t *mchash)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_MC0, mchash[0]);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_MC1, mchash[1]);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_MC2, mchash[2]);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_MC3, mchash[3]);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_eeprom_read(efe_t *efep, uint8_t *buf, size_t len, uint8_t addr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion int addrlen;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(len & ~0x1); /* non-zero; word-aligned */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(EEPROM_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion addrlen = (GETCSR(efep, CSR_EECTL) & EECTL_SIZE ?
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion AT93C46_ADDRLEN : AT93C56_ADDRLEN);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < len / sizeof (uint16_t); ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t val = efe_eeprom_readw(efep, addrlen, addr + i);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bcopy(&val, buf, sizeof (uint16_t));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion buf += sizeof (uint16_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionuint16_t
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_eeprom_readw(efe_t *efep, int addrlen, uint8_t addr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint16_t val = 0;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(addrlen > 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Write Start Bit (SB) */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_eeprom_writebit(efep, 1);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Write READ instruction */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_eeprom_writebit(efep, 1);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_eeprom_writebit(efep, 0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Write EEPROM address */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = addrlen - 1; i >= 0; --i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_eeprom_writebit(efep, addr & 1U << i);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Read EEPROM word */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = EEPROM_WORDSZ - 1; i >= 0; --i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion val |= efe_eeprom_readbit(efep) << i;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion }
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(EEPROM_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (val);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallioninline int
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_eeprom_readbit(efe_t *efep)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(EEPROM_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS |
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion EECTL_EESK);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(EEPROM_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(EEPROM_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (!!(GETCSR(efep, CSR_EECTL) & EECTL_EEDO));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallioninline void
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_eeprom_writebit(efe_t *efep, int bit)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(EEPROM_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS |
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion EECTL_EESK | (bit ? EECTL_EEDI : 0));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(EEPROM_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion drv_usecwait(EEPROM_DELAY);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionvoid
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_dprintf(dev_info_t *dip, int level, const char *format, ...)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion{
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion va_list ap;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion char buf[255];
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion va_start(ap, format);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) vsnprintf(buf, sizeof (buf), format, ap);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion cmn_err(level, "?%s%d %s", ddi_driver_name(dip),
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ddi_get_instance(dip), buf);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion va_end(ap);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion}