b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Copyright (c) 2010 Steven Stallion. All rights reserved.
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 * 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 * 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/* 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 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/* 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 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 Stallionstatic void efe_m_propinfo(void *, const char *, mac_prop_id_t,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/* ISR/periodic callbacks */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion/* Support functions */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic efe_ring_t *efe_ring_alloc(dev_info_t *, size_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic efe_buf_t *efe_buf_alloc(dev_info_t *, size_t);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic mblk_t *efe_recv_pkt(efe_t *, efe_desc_t *);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionstatic void efe_setmchash(efe_t *, uint16_t *);
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 Stallionstatic void efe_dprintf(dev_info_t *, int, const char *, ...);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven StallionDDI_DEFINE_STREAM_OPS(efe_dev_ops, nulldev, nulldev, efe_attach, efe_detach,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion "EPIC/100 Fast Ethernet", /* drv_linkinfo */
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 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 0, /* dma_attr_addr_lo */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion 0 /* dma_attr_flags */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Loadable module entry points.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if ((error = mod_install(&modlinkage)) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if ((error = mod_remove(&modlinkage)) == DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Autoconfiguration entry points.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * PCI configuration.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to setup PCI configuration!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion pci_config_get16(pci, PCI_CONF_COMM) | PCI_COMM_MAE | PCI_COMM_ME);
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 if (ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &count)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "no fixed interrupts available!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Initialize soft state.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep = kmem_zalloc(sizeof (efe_t), KM_SLEEP);
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 efep->efe_rx_ring = efe_ring_alloc(efep->efe_dip, RXDESCL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "unable to allocate rx ring!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_ring = efe_ring_alloc(efep->efe_dip, TXDESCL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "unable to allocate tx ring!");
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 efe_error(dip, "unable to allocate fixed interrupt!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_get_pri(efep->efe_intrh, &pri) != DDI_SUCCESS ||
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to get valid interrupt priority!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_init(&efep->efe_intrlock, NULL, MUTEX_DRIVER,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mutex_init(&efep->efe_txlock, NULL, MUTEX_DRIVER,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Initialize device.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Use factory address as default */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Enable the ISR.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_add_handler(efep->efe_intrh, efe_intr, efep, NULL)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to add interrupt handler!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_intr_enable(efep->efe_intrh) != DDI_SUCCESS) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to enable interrupt!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Allocate MII resources.
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 * Allocate MAC resources.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate mac resources!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (mac_register(macp, &efep->efe_mh) != 0) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to register with mac!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_intr_remove_handler(efep->efe_intrh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to unregister from mac!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) ddi_intr_remove_handler(efep->efe_intrh);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * MII entry points.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_mii_read(void *arg, uint8_t phy, uint8_t reg)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion reg << MMCTL_PHYREG | phy << MMCTL_PHYADDR);
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 efe_error(efep->efe_dip, "timed out reading from MII!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t data)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion reg << MMCTL_PHYREG | phy << MMCTL_PHYADDR);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < MII_DELAY_CYCLES; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (!(GETCSR(efep, CSR_MMCTL) & MMCTL_WRITE)) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "timed out writing to MII!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * MAC entry points.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_getstat(void *arg, uint_t stat, uint64_t *val)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (mii_m_getstat(efep->efe_miih, stat, val) == 0) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion CRC32(val, macaddr, ETHERADDRL, -1U, crc32_table);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (restart && efep->efe_flags & FLAG_RUNNING) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_unicst(void *arg, const uint8_t *macaddr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bcopy(macaddr, efep->efe_macaddr, ETHERADDRL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Kick the transmitter */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_COMMAND, COMMAND_TXQUEUED);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_setprop(void *arg, const char *name, mac_prop_id_t id,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mii_m_setprop(efep->efe_miih, name, id, valsize, val));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_getprop(void *arg, const char *name, mac_prop_id_t id,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (mii_m_getprop(efep->efe_miih, name, id, valsize, val));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_m_propinfo(void *arg, const char *name, mac_prop_id_t id,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion mii_m_propinfo(efep->efe_miih, name, id, state);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Kick the receiver */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_COMMAND, COMMAND_RXQUEUED);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "bus error; resetting!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Support functions.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion val = GENCTL_ONECOPY | GENCTL_RFT_128 | GENCTL_MRM;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion#endif /* _BIG_ENDIAN */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC32(rp, &dp->d_next, NEXTDESCADDR(rp, i));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC32(rp, &dp->d_next, NEXTDESCADDR(rp, i));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Assert internal clock source (AN 7.15) */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < RESET_TEST_CYCLES; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion RXCON_SEP | RXCON_RRF | RXCON_RBF | RXCON_RMF |
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < STOP_DELAY_CYCLES; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion uint32_t status = GETCSR(efep, CSR_INTSTAT);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(efep->efe_dip, "timed out stopping DMA engine!");
e65fcc69bb33b3f4525b0c2c9732ece17c90b196Richard Lowestatic inline void
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion rp = kmem_zalloc(sizeof (efe_ring_t), KM_SLEEP);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_dma_alloc_handle(dip, &efe_dma_attr, DDI_DMA_SLEEP, NULL,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate DMA handle!");
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 efe_error(dip, "unable to allocate descriptors!");
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 rp->r_bufpp = kmem_zalloc(BUFPSZ(len), KM_SLEEP);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = 0; i < len; ++i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion kmem_free(rp->r_bufpp, BUFPSZ(DESCLEN(rp)));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion bp = kmem_zalloc(sizeof (efe_buf_t), KM_SLEEP);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (ddi_dma_alloc_handle(dip, &efe_dma_attr, DDI_DMA_SLEEP, NULL,
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_error(dip, "unable to allocate DMA handle!");
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 efe_error(dip, "unable to allocate buffer!");
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 efe_error(dip, "unable to bind DMA handle to buffer!");
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion INTMASK_RCC | INTMASK_RQE | INTMASK_TXC | INTMASK_FATAL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_rx_desc, DDI_DMA_SYNC_FORKERNEL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Stop if device owns descriptor */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Release ownership to device */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_rx_desc, DDI_DMA_SYNC_FORDEV);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_rx_desc = NEXTDESC(rp, efep->efe_rx_desc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion len = GETDESC16(rp, &dp->d_len) - ETHERFCSL;
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORKERNEL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion status = GETDESC16(efep->efe_tx_ring, &dp->d_status);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Stop if device owns descriptor */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Packets must contain at least ETHERMIN octets.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion * Padded octets are zeroed out prior to sending.
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTDESC16(rp, &dp->d_control, TXCTL_LASTDESCR);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORDEV);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion if (bcmp(bp->b_kaddr, efe_broadcast, ETHERADDRL) == 0) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_desc = NEXTDESC(rp, efep->efe_tx_desc);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion SYNCDESC(rp, efep->efe_tx_sent, DDI_DMA_SYNC_FORKERNEL);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Stop if device owns descriptor */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efep->efe_tx_sent = NEXTDESC(rp, efep->efe_tx_sent);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion efe_eeprom_read(efep, macaddr, ETHERADDRL, 0x0);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion "factory address is %02x:%02x:%02x:%02x:%02x:%02x\n",
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion macaddr[0], macaddr[1], macaddr[2], macaddr[3],
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_eeprom_read(efe_t *efep, uint8_t *buf, size_t len, uint8_t addr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion ASSERT(len & ~0x1); /* non-zero; word-aligned */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion addrlen = (GETCSR(efep, CSR_EECTL) & EECTL_SIZE ?
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 Stallionefe_eeprom_readw(efe_t *efep, int addrlen, uint8_t addr)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Write Start Bit (SB) */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Write READ instruction */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Write EEPROM address */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion /* Read EEPROM word */
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion for (int i = EEPROM_WORDSZ - 1; i >= 0; --i) {
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS |
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion return (!!(GETCSR(efep, CSR_EECTL) & EECTL_EEDO));
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS |
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallionefe_dprintf(dev_info_t *dip, int level, const char *format, ...)
b3697b90e692e3e5d859fb77d285d4c056d99edaSteven Stallion (void) vsnprintf(buf, sizeof (buf), format, ap);