1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Solaris driver for ethernet cards based on the ADMtek Centaur
1959748cbddf37d4734c107dadfa449e076045e3gd *
1959748cbddf37d4734c107dadfa449e076045e3gd * Copyright (c) 2007 by Garrett D'Amore <garrett@damore.org>.
1959748cbddf37d4734c107dadfa449e076045e3gd * All rights reserved.
1959748cbddf37d4734c107dadfa449e076045e3gd *
1959748cbddf37d4734c107dadfa449e076045e3gd * Redistribution and use in source and binary forms, with or without
1959748cbddf37d4734c107dadfa449e076045e3gd * modification, are permitted provided that the following conditions
1959748cbddf37d4734c107dadfa449e076045e3gd * are met:
1959748cbddf37d4734c107dadfa449e076045e3gd * 1. Redistributions of source code must retain the above copyright
1959748cbddf37d4734c107dadfa449e076045e3gd * notice, this list of conditions and the following disclaimer.
1959748cbddf37d4734c107dadfa449e076045e3gd * 2. Redistributions in binary form must reproduce the above copyright
1959748cbddf37d4734c107dadfa449e076045e3gd * notice, this list of conditions and the following disclaimer in the
1959748cbddf37d4734c107dadfa449e076045e3gd * documentation and/or other materials provided with the distribution.
1959748cbddf37d4734c107dadfa449e076045e3gd * 3. Neither the name of the author nor the names of any co-contributors
1959748cbddf37d4734c107dadfa449e076045e3gd * may be used to endorse or promote products derived from this software
1959748cbddf37d4734c107dadfa449e076045e3gd * without specific prior written permission.
1959748cbddf37d4734c107dadfa449e076045e3gd *
1959748cbddf37d4734c107dadfa449e076045e3gd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
1959748cbddf37d4734c107dadfa449e076045e3gd * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1959748cbddf37d4734c107dadfa449e076045e3gd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1959748cbddf37d4734c107dadfa449e076045e3gd * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
1959748cbddf37d4734c107dadfa449e076045e3gd * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1959748cbddf37d4734c107dadfa449e076045e3gd * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1959748cbddf37d4734c107dadfa449e076045e3gd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1959748cbddf37d4734c107dadfa449e076045e3gd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1959748cbddf37d4734c107dadfa449e076045e3gd * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1959748cbddf37d4734c107dadfa449e076045e3gd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1959748cbddf37d4734c107dadfa449e076045e3gd * POSSIBILITY OF SUCH DAMAGE.
1959748cbddf37d4734c107dadfa449e076045e3gd */
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd * Use is subject to license terms.
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd */
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/varargs.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/types.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/modctl.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/conf.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/devops.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/stream.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/strsun.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/cmn_err.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/ethernet.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/kmem.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/time.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/crc32.h>
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore#include <sys/mii.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/miiregs.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/mac.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/mac_ether.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/ddi.h>
1959748cbddf37d4734c107dadfa449e076045e3gd#include <sys/sunddi.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/vlan.h>
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd#include "afe.h"
1959748cbddf37d4734c107dadfa449e076045e3gd#include "afeimpl.h"
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Driver globals.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/* table of supported devices */
1959748cbddf37d4734c107dadfa449e076045e3gdstatic afe_card_t afe_cards[] = {
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * ADMtek Centaur and Comet
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1317, 0x0981, "ADMtek AL981", MODEL_COMET },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1317, 0x0985, "ADMtek AN983", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1317, 0x1985, "ADMtek AN985", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1317, 0x9511, "ADMtek ADM9511", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1317, 0x9513, "ADMtek ADM9513", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Accton just relabels other companies' controllers
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1113, 0x1216, "Accton EN5251", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Models listed here.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x10b7, 0x9300, "3Com 3CSOHO100B-TX", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1113, 0xec02, "SMC SMC1244TX", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x10b8, 0x1255, "SMC SMC1255TX", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x111a, 0x1020, "Siemens SpeedStream PCI 10/100", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1113, 0x1207, "Accton EN1207F", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1113, 0x2242, "Accton EN2242", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1113, 0x2220, "Accton EN2220", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1113, 0x9216, "3M VOL-N100VF+TX", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1317, 0x0574, "Linksys LNE100TX", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1317, 0x0570, "Linksys NC100", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1385, 0x511a, "Netgear FA511", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x13d1, 0xab02, "AboCom FE2500", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x13d1, 0xab03, "AboCom PCM200", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x13d1, 0xab08, "AboCom FE2500MX", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1414, 0x0001, "Microsoft MN-120", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x16ec, 0x00ed, "U.S. Robotics USR997900", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1734, 0x100c, "Fujitsu-Siemens D1961", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1737, 0xab08, "Linksys PCMPC200", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x1737, 0xab09, "Linksys PCM200", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd { 0x17b3, 0xab08, "Hawking PN672TX", MODEL_CENTAUR },
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd#define ETHERVLANMTU (ETHERMAX + 4)
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Function prototypes
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_attach(dev_info_t *, ddi_attach_cmd_t);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_detach(dev_info_t *, ddi_detach_cmd_t);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_resume(dev_info_t *);
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amorestatic int afe_quiesce(dev_info_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_m_unicst(void *, const uint8_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_m_multicst(void *, boolean_t, const uint8_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_m_promisc(void *, boolean_t);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic mblk_t *afe_m_tx(void *, mblk_t *);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic void afe_m_ioctl(void *, queue_t *, mblk_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_m_stat(void *, uint_t, uint64_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_m_start(void *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_m_stop(void *);
96fb08b94cc33de779f46f36c30d77230f1a8c2fgdstatic int afe_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer void *);
96fb08b94cc33de779f46f36c30d77230f1a8c2fgdstatic int afe_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd const void *);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void afe_m_propinfo(void *, const char *, mac_prop_id_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic unsigned afe_intr(caddr_t);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_startmac(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_stopmac(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_resetrings(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic boolean_t afe_initialize(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_startall(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_stopall(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_resetall(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic afe_txbuf_t *afe_alloctxbuf(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_destroytxbuf(afe_txbuf_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic afe_rxbuf_t *afe_allocrxbuf(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_destroyrxbuf(afe_rxbuf_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic boolean_t afe_send(afe_t *, mblk_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_allocrxring(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_freerxring(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic int afe_alloctxring(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_freetxring(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_error(dev_info_t *, char *, ...);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_setrxfilt(afe_t *);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic int afe_watchdog(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic uint8_t afe_sromwidth(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic uint16_t afe_readsromword(afe_t *, unsigned);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_readsrom(afe_t *, unsigned, unsigned, char *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_getfactaddr(afe_t *, uchar_t *);
96fb08b94cc33de779f46f36c30d77230f1a8c2fgdstatic uint8_t afe_miireadbit(afe_t *);
96fb08b94cc33de779f46f36c30d77230f1a8c2fgdstatic void afe_miiwritebit(afe_t *, uint8_t);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_miitristate(afe_t *);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic uint16_t afe_miireadgeneral(afe_t *, uint8_t, uint8_t);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic void afe_miiwritegeneral(afe_t *, uint8_t, uint8_t, uint16_t);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic uint16_t afe_miireadcomet(afe_t *, uint8_t, uint8_t);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic void afe_miiwritecomet(afe_t *, uint8_t, uint8_t, uint16_t);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic uint16_t afe_mii_read(void *, uint8_t, uint8_t);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic void afe_mii_write(void *, uint8_t, uint8_t, uint16_t);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic void afe_mii_notify(void *, link_state_t);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic void afe_mii_reset(void *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_disableinterrupts(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_enableinterrupts(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic void afe_reclaim(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gdstatic mblk_t *afe_receive(afe_t *);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd#define KIOIP KSTAT_INTR_PTR(afep->afe_intrstat)
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorestatic mii_ops_t afe_mii_ops = {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore MII_OPS_VERSION,
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_mii_read,
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_mii_write,
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_mii_notify,
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_mii_reset
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore};
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gdstatic mac_callbacks_t afe_m_callbacks = {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
1959748cbddf37d4734c107dadfa449e076045e3gd afe_m_stat,
1959748cbddf37d4734c107dadfa449e076045e3gd afe_m_start,
1959748cbddf37d4734c107dadfa449e076045e3gd afe_m_stop,
1959748cbddf37d4734c107dadfa449e076045e3gd afe_m_promisc,
1959748cbddf37d4734c107dadfa449e076045e3gd afe_m_multicst,
1959748cbddf37d4734c107dadfa449e076045e3gd afe_m_unicst,
1959748cbddf37d4734c107dadfa449e076045e3gd afe_m_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_m_ioctl, /* mc_ioctl */
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd NULL, /* mc_getcapab */
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd NULL, /* mc_open */
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd NULL, /* mc_close */
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd afe_m_setprop,
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd afe_m_getprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer afe_m_propinfo
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Stream information
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdDDI_DEFINE_STREAM_OPS(afe_devops, nulldev, nulldev, afe_attach, afe_detach,
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore nodev, NULL, D_MP, NULL, afe_quiesce);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Module linkage information.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdstatic struct modldrv afe_modldrv = {
1959748cbddf37d4734c107dadfa449e076045e3gd &mod_driverops, /* drv_modops */
1959748cbddf37d4734c107dadfa449e076045e3gd "ADMtek Fast Ethernet", /* drv_linkinfo */
1959748cbddf37d4734c107dadfa449e076045e3gd &afe_devops /* drv_dev_ops */
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdstatic struct modlinkage afe_modlinkage = {
1959748cbddf37d4734c107dadfa449e076045e3gd MODREV_1, /* ml_rev */
1959748cbddf37d4734c107dadfa449e076045e3gd { &afe_modldrv, NULL } /* ml_linkage */
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Device attributes.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdstatic ddi_device_acc_attr_t afe_devattr = {
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DEVICE_ATTR_V0,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_STRUCTURE_LE_ACC,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_STRICTORDER_ACC
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdstatic ddi_device_acc_attr_t afe_bufattr = {
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DEVICE_ATTR_V0,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_NEVERSWAP_ACC,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_STRICTORDER_ACC
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdstatic ddi_dma_attr_t afe_dma_attr = {
1959748cbddf37d4734c107dadfa449e076045e3gd DMA_ATTR_V0, /* dma_attr_version */
1959748cbddf37d4734c107dadfa449e076045e3gd 0, /* dma_attr_addr_lo */
1959748cbddf37d4734c107dadfa449e076045e3gd 0xFFFFFFFFU, /* dma_attr_addr_hi */
1959748cbddf37d4734c107dadfa449e076045e3gd 0x7FFFFFFFU, /* dma_attr_count_max */
1959748cbddf37d4734c107dadfa449e076045e3gd 4, /* dma_attr_align */
1959748cbddf37d4734c107dadfa449e076045e3gd 0x3F, /* dma_attr_burstsizes */
1959748cbddf37d4734c107dadfa449e076045e3gd 1, /* dma_attr_minxfer */
1959748cbddf37d4734c107dadfa449e076045e3gd 0xFFFFFFFFU, /* dma_attr_maxxfer */
1959748cbddf37d4734c107dadfa449e076045e3gd 0xFFFFFFFFU, /* dma_attr_seg */
1959748cbddf37d4734c107dadfa449e076045e3gd 1, /* dma_attr_sgllen */
1959748cbddf37d4734c107dadfa449e076045e3gd 1, /* dma_attr_granular */
1959748cbddf37d4734c107dadfa449e076045e3gd 0 /* dma_attr_flags */
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Tx buffers can be arbitrarily aligned. Additionally, they can
1959748cbddf37d4734c107dadfa449e076045e3gd * cross a page boundary, so we use the two buffer addresses of the
1959748cbddf37d4734c107dadfa449e076045e3gd * chip to provide a two-entry scatter-gather list.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdstatic ddi_dma_attr_t afe_dma_txattr = {
1959748cbddf37d4734c107dadfa449e076045e3gd DMA_ATTR_V0, /* dma_attr_version */
1959748cbddf37d4734c107dadfa449e076045e3gd 0, /* dma_attr_addr_lo */
1959748cbddf37d4734c107dadfa449e076045e3gd 0xFFFFFFFFU, /* dma_attr_addr_hi */
1959748cbddf37d4734c107dadfa449e076045e3gd 0x7FFFFFFFU, /* dma_attr_count_max */
1959748cbddf37d4734c107dadfa449e076045e3gd 1, /* dma_attr_align */
1959748cbddf37d4734c107dadfa449e076045e3gd 0x3F, /* dma_attr_burstsizes */
1959748cbddf37d4734c107dadfa449e076045e3gd 1, /* dma_attr_minxfer */
1959748cbddf37d4734c107dadfa449e076045e3gd 0xFFFFFFFFU, /* dma_attr_maxxfer */
1959748cbddf37d4734c107dadfa449e076045e3gd 0xFFFFFFFFU, /* dma_attr_seg */
1959748cbddf37d4734c107dadfa449e076045e3gd 2, /* dma_attr_sgllen */
1959748cbddf37d4734c107dadfa449e076045e3gd 1, /* dma_attr_granular */
1959748cbddf37d4734c107dadfa449e076045e3gd 0 /* dma_attr_flags */
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Ethernet addresses.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdstatic uchar_t afe_broadcast[ETHERADDRL] = {
1959748cbddf37d4734c107dadfa449e076045e3gd 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
1959748cbddf37d4734c107dadfa449e076045e3gd};
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * DDI entry points.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gd_init(void)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int rv;
1959748cbddf37d4734c107dadfa449e076045e3gd mac_init_ops(&afe_devops, "afe");
1959748cbddf37d4734c107dadfa449e076045e3gd if ((rv = mod_install(&afe_modlinkage)) != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd mac_fini_ops(&afe_devops);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd return (rv);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gd_fini(void)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int rv;
1959748cbddf37d4734c107dadfa449e076045e3gd if ((rv = mod_remove(&afe_modlinkage)) == DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd mac_fini_ops(&afe_devops);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd return (rv);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gd_info(struct modinfo *modinfop)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd return (mod_info(&afe_modlinkage, modinfop));
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep;
1959748cbddf37d4734c107dadfa449e076045e3gd mac_register_t *macp;
1959748cbddf37d4734c107dadfa449e076045e3gd int inst = ddi_get_instance(dip);
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_acc_handle_t pci;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t venid;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t devid;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t svid;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t ssid;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t cachesize;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_card_t *cardp;
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd switch (cmd) {
1959748cbddf37d4734c107dadfa449e076045e3gd case DDI_RESUME:
1959748cbddf37d4734c107dadfa449e076045e3gd return (afe_resume(dip));
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case DDI_ATTACH:
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd default:
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* this card is a bus master, reject any slave-only slot */
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_slaveonly(dip) == DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "slot does not support PCI bus-master");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd /* PCI devices shouldn't generate hilevel interrupts */
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_intr_hilevel(dip, 0) != 0) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "hilevel interrupts not supported");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "unable to setup PCI config handle");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd venid = pci_config_get16(pci, PCI_VID);
1959748cbddf37d4734c107dadfa449e076045e3gd devid = pci_config_get16(pci, PCI_DID);
1959748cbddf37d4734c107dadfa449e076045e3gd svid = pci_config_get16(pci, PCI_SVID);
1959748cbddf37d4734c107dadfa449e076045e3gd ssid = pci_config_get16(pci, PCI_SSID);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Note: ADMtek boards seem to misprogram themselves with bogus
1959748cbddf37d4734c107dadfa449e076045e3gd * timings, which do not seem to work properly on SPARC. We
1959748cbddf37d4734c107dadfa449e076045e3gd * reprogram them zero (but only if they appear to be broken),
1959748cbddf37d4734c107dadfa449e076045e3gd * which seems to at least work. Its unclear that this is a
1959748cbddf37d4734c107dadfa449e076045e3gd * legal or wise practice to me, but it certainly works better
1959748cbddf37d4734c107dadfa449e076045e3gd * than the original values. (I would love to hear
1959748cbddf37d4734c107dadfa449e076045e3gd * suggestions for better values, or a better strategy.)
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd if ((pci_config_get8(pci, PCI_MINGNT) == 0xff) &&
1959748cbddf37d4734c107dadfa449e076045e3gd (pci_config_get8(pci, PCI_MAXLAT) == 0xff)) {
1959748cbddf37d4734c107dadfa449e076045e3gd pci_config_put8(pci, PCI_MINGNT, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd pci_config_put8(pci, PCI_MAXLAT, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * the last entry in the card table matches every possible
1959748cbddf37d4734c107dadfa449e076045e3gd * card, so the for-loop always terminates properly.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd cardp = NULL;
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < (sizeof (afe_cards) / sizeof (afe_card_t)); i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd if ((venid == afe_cards[i].card_venid) &&
1959748cbddf37d4734c107dadfa449e076045e3gd (devid == afe_cards[i].card_devid)) {
1959748cbddf37d4734c107dadfa449e076045e3gd cardp = &afe_cards[i];
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if ((svid == afe_cards[i].card_venid) &&
1959748cbddf37d4734c107dadfa449e076045e3gd (ssid == afe_cards[i].card_devid)) {
1959748cbddf37d4734c107dadfa449e076045e3gd cardp = &afe_cards[i];
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (cardp == NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd pci_config_teardown(&pci);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "Unable to identify PCI card");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model",
1959748cbddf37d4734c107dadfa449e076045e3gd cardp->card_cardname) != DDI_PROP_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd pci_config_teardown(&pci);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "Unable to create model property");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Grab the PCI cachesize -- we use this to program the
1959748cbddf37d4734c107dadfa449e076045e3gd * cache-optimization bus access bits.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd cachesize = pci_config_get8(pci, PCI_CLS);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* this cannot fail */
1959748cbddf37d4734c107dadfa449e076045e3gd afep = kmem_zalloc(sizeof (afe_t), KM_SLEEP);
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_set_driver_private(dip, afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* get the interrupt block cookie */
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_get_iblock_cookie(dip, 0, &afep->afe_icookie) != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "ddi_get_iblock_cookie failed");
1959748cbddf37d4734c107dadfa449e076045e3gd pci_config_teardown(&pci);
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(afep, sizeof (afe_t));
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_dip = dip;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_cardp = cardp;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_phyaddr = -1;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_cachesize = cachesize;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_forcefiber = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
1959748cbddf37d4734c107dadfa449e076045e3gd "fiber", 0);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_init(&afep->afe_xmtlock, NULL, MUTEX_DRIVER, afep->afe_icookie);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_init(&afep->afe_intrlock, NULL, MUTEX_DRIVER, afep->afe_icookie);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Enable bus master, IO space, and memory space accesses.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd pci_config_put16(pci, PCI_CMD,
1959748cbddf37d4734c107dadfa449e076045e3gd pci_config_get16(pci, PCI_CMD) | PCI_CMD_BME | PCI_CMD_MAE);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* we're done with this now, drop it */
1959748cbddf37d4734c107dadfa449e076045e3gd pci_config_teardown(&pci);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Initialize interrupt kstat. This should not normally fail, since
1959748cbddf37d4734c107dadfa449e076045e3gd * we don't use a persistent stat. We do it this way to avoid having
1959748cbddf37d4734c107dadfa449e076045e3gd * to test for it at run time on the hot path.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_intrstat = kstat_create("afe", inst, "intr", "controller",
1959748cbddf37d4734c107dadfa449e076045e3gd KSTAT_TYPE_INTR, 1, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_intrstat == NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "kstat_create failed");
1959748cbddf37d4734c107dadfa449e076045e3gd goto failed;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd kstat_install(afep->afe_intrstat);
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /*
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore * Set up the MII.
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if ((afep->afe_mii = mii_alloc(afep, dip, &afe_mii_ops)) == NULL) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore goto failed;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore }
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /*
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore * Centaur can support PAUSE, but Comet can't.
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if (AFE_MODEL(afep) == MODEL_CENTAUR) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_set_pauseable(afep->afe_mii, B_TRUE, B_FALSE);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore } else {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_set_pauseable(afep->afe_mii, B_FALSE, B_FALSE);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore }
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Map in the device registers.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_regs_map_setup(dip, 1, (caddr_t *)&afep->afe_regs,
1959748cbddf37d4734c107dadfa449e076045e3gd 0, 0, &afe_devattr, &afep->afe_regshandle)) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "ddi_regs_map_setup failed");
1959748cbddf37d4734c107dadfa449e076045e3gd goto failed;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Allocate DMA resources (descriptor rings and buffers).
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd if ((afe_allocrxring(afep) != DDI_SUCCESS) ||
1959748cbddf37d4734c107dadfa449e076045e3gd (afe_alloctxring(afep) != DDI_SUCCESS)) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "unable to allocate DMA resources");
1959748cbddf37d4734c107dadfa449e076045e3gd goto failed;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* Initialize the chip. */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd if (!afe_initialize(afep)) {
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd goto failed;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* Determine the number of address bits to our EEPROM. */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_sromwidth = afe_sromwidth(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Get the factory ethernet address. This becomes the current
1959748cbddf37d4734c107dadfa449e076045e3gd * ethernet address (it can be overridden later via ifconfig).
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_getfactaddr(afep, afep->afe_curraddr);
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_promisc = B_FALSE;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* make sure we add configure the initial filter */
1959748cbddf37d4734c107dadfa449e076045e3gd (void) afe_m_unicst(afep, afep->afe_curraddr);
1959748cbddf37d4734c107dadfa449e076045e3gd (void) afe_m_multicst(afep, B_TRUE, afe_broadcast);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Establish interrupt handler.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_add_intr(dip, 0, NULL, NULL, afe_intr, (caddr_t)afep) !=
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "unable to add interrupt");
1959748cbddf37d4734c107dadfa449e076045e3gd goto failed;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* TODO: do the power management stuff */
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "mac_alloc failed");
1959748cbddf37d4734c107dadfa449e076045e3gd goto failed;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1959748cbddf37d4734c107dadfa449e076045e3gd macp->m_driver = afep;
1959748cbddf37d4734c107dadfa449e076045e3gd macp->m_dip = dip;
1959748cbddf37d4734c107dadfa449e076045e3gd macp->m_src_addr = afep->afe_curraddr;
1959748cbddf37d4734c107dadfa449e076045e3gd macp->m_callbacks = &afe_m_callbacks;
1959748cbddf37d4734c107dadfa449e076045e3gd macp->m_min_sdu = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd macp->m_max_sdu = ETHERMTU;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz macp->m_margin = VLAN_TAGSZ;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (mac_register(macp, &afep->afe_mh) == DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd mac_free(macp);
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_SUCCESS);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* failed to register with MAC */
1959748cbddf37d4734c107dadfa449e076045e3gd mac_free(macp);
1959748cbddf37d4734c107dadfa449e076045e3gdfailed:
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_icookie != NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_remove_intr(dip, 0, afep->afe_icookie);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_intrstat) {
1959748cbddf37d4734c107dadfa449e076045e3gd kstat_delete(afep->afe_intrstat);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_destroy(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_destroy(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afe_freerxring(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_freetxring(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_regshandle != NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_regs_map_free(&afep->afe_regshandle);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(afep, sizeof (afe_t));
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afep = ddi_get_driver_private(dip);
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep == NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(dip, "no soft state in detach!");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd switch (cmd) {
1959748cbddf37d4734c107dadfa449e076045e3gd case DDI_DETACH:
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (mac_unregister(afep->afe_mh) != 0) {
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* make sure hardware is quiesced */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_flags &= ~AFE_RUNNING;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_stopall(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* clean up and shut down device */
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_remove_intr(dip, 0, afep->afe_icookie);
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /* clean up MII layer */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_free(afep->afe_mii);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd /* clean up kstats */
1959748cbddf37d4734c107dadfa449e076045e3gd kstat_delete(afep->afe_intrstat);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_prop_remove_all(dip);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* free up any left over buffers or DMA resources */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_freerxring(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_freetxring(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_regs_map_free(&afep->afe_regshandle);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_destroy(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_destroy(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(afep, sizeof (afe_t));
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_SUCCESS);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case DDI_SUSPEND:
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /* stop MII monitoring */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_suspend(afep->afe_mii);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd /* quiesce the hardware */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_flags |= AFE_SUSPENDED;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_stopall(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_SUCCESS);
1959748cbddf37d4734c107dadfa449e076045e3gd default:
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_resume(dev_info_t *dip)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if ((afep = ddi_get_driver_private(dip)) == NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_flags &= ~AFE_SUSPENDED;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* re-initialize chip */
1959748cbddf37d4734c107dadfa449e076045e3gd if (!afe_initialize(afep)) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip, "unable to resume chip!");
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_flags |= AFE_SUSPENDED;
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_SUCCESS);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* start the chip */
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_flags & AFE_RUNNING) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_startall(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* drop locks */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_resume(afep->afe_mii);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_SUCCESS);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amoreint
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amoreafe_quiesce(dev_info_t *dip)
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore{
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore afe_t *afep;
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore if ((afep = ddi_get_driver_private(dip)) == NULL) {
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore return (DDI_FAILURE);
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore }
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore SETBIT(afep, CSR_PAR, PAR_RESET);
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore /*
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore * At 66 MHz it is 16 nsec per access or more (always more)
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore * So we need 3,333 times to retry for 50 usec. We just
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore * round up to 5000 times. Unless the hardware is horked,
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore * it will always terminate *well* before that anyway.
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore */
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore for (int i = 0; i < 5000; i++) {
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore if ((GETCSR(afep, CSR_PAR) & PAR_RESET) == 0) {
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore return (DDI_SUCCESS);
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore }
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore }
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore /* hardware didn't quiesce - force a full reboot (PCI reset) */
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore return (DDI_FAILURE);
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore}
38415b019e7f06a9abdc4c863acc6ee8263c68a1Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_setrxfilt(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned rxen, pa0, pa1;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_flags & AFE_SUSPENDED) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* don't touch a suspended interface */
1959748cbddf37d4734c107dadfa449e076045e3gd return;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rxen = GETCSR(afep, CSR_NAR) & NAR_RX_ENABLE;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* stop receiver */
1959748cbddf37d4734c107dadfa449e076045e3gd if (rxen) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_stopmac(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* program promiscuous mode */
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_promisc)
1959748cbddf37d4734c107dadfa449e076045e3gd SETBIT(afep, CSR_NAR, NAR_RX_PROMISC);
1959748cbddf37d4734c107dadfa449e076045e3gd else
1959748cbddf37d4734c107dadfa449e076045e3gd CLRBIT(afep, CSR_NAR, NAR_RX_PROMISC);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* program mac address */
1959748cbddf37d4734c107dadfa449e076045e3gd pa0 = (afep->afe_curraddr[3] << 24) | (afep->afe_curraddr[2] << 16) |
1959748cbddf37d4734c107dadfa449e076045e3gd (afep->afe_curraddr[1] << 8) | afep->afe_curraddr[0];
1959748cbddf37d4734c107dadfa449e076045e3gd pa1 = (afep->afe_curraddr[5] << 8) | afep->afe_curraddr[4];
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_PAR0, pa0);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_PAR1, pa1);
1959748cbddf37d4734c107dadfa449e076045e3gd if (rxen) {
1959748cbddf37d4734c107dadfa449e076045e3gd SETBIT(afep, CSR_NAR, rxen);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* program multicast filter */
1959748cbddf37d4734c107dadfa449e076045e3gd if (AFE_MODEL(afep) == MODEL_COMET) {
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_mctab[0] || afep->afe_mctab[1]) {
1959748cbddf37d4734c107dadfa449e076045e3gd SETBIT(afep, CSR_NAR, NAR_RX_MULTI);
1959748cbddf37d4734c107dadfa449e076045e3gd } else {
1959748cbddf37d4734c107dadfa449e076045e3gd CLRBIT(afep, CSR_NAR, NAR_RX_MULTI);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd } else {
1959748cbddf37d4734c107dadfa449e076045e3gd CLRBIT(afep, CSR_NAR, NAR_RX_MULTI);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_MAR0, afep->afe_mctab[0]);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_MAR1, afep->afe_mctab[1]);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* restart receiver */
1959748cbddf37d4734c107dadfa449e076045e3gd if (rxen) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_startmac(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreint
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_watchdog(afe_t *afep)
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore{
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if ((afep->afe_txstall_time != 0) &&
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore (gethrtime() > afep->afe_txstall_time) &&
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore (afep->afe_txavail != AFE_TXRING)) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afep->afe_txstall_time = 0;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_error(afep->afe_dip, "TX stall detected!");
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore return (DDI_FAILURE);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore } else {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore return (DDI_SUCCESS);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore }
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore}
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd int index;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t crc;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t bit;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t newval, oldval;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd CRC32(crc, macaddr, ETHERADDRL, -1U, crc32_table);
1959748cbddf37d4734c107dadfa449e076045e3gd crc %= AFE_MCHASH;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* bit within a 32-bit word */
1959748cbddf37d4734c107dadfa449e076045e3gd index = crc / 32;
1959748cbddf37d4734c107dadfa449e076045e3gd bit = (1 << (crc % 32));
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd newval = oldval = afep->afe_mctab[index];
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (add) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_mccount[crc]++;
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_mccount[crc] == 1)
1959748cbddf37d4734c107dadfa449e076045e3gd newval |= bit;
1959748cbddf37d4734c107dadfa449e076045e3gd } else {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_mccount[crc]--;
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_mccount[crc] == 0)
1959748cbddf37d4734c107dadfa449e076045e3gd newval &= ~bit;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (newval != oldval) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_mctab[index] = newval;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_setrxfilt(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (0);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_m_promisc(void *arg, boolean_t on)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* exclusive access to the card while we reprogram it */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd /* save current promiscuous mode state for replay in resume */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_promisc = on;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afe_setrxfilt(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (0);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_m_unicst(void *arg, const uint8_t *macaddr)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* exclusive access to the card while we reprogram it */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd bcopy(macaddr, afep->afe_curraddr, ETHERADDRL);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_setrxfilt(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (0);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdmblk_t *
1959748cbddf37d4734c107dadfa449e076045e3gdafe_m_tx(void *arg, mblk_t *mp)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd mblk_t *nmp;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_flags & AFE_SUSPENDED) {
1959748cbddf37d4734c107dadfa449e076045e3gd while ((nmp = mp) != NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_carrier_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd mp = mp->b_next;
1959748cbddf37d4734c107dadfa449e076045e3gd freemsg(nmp);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd return (NULL);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd while (mp != NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd nmp = mp->b_next;
1959748cbddf37d4734c107dadfa449e076045e3gd mp->b_next = NULL;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (!afe_send(afep, mp)) {
1959748cbddf37d4734c107dadfa449e076045e3gd mp->b_next = nmp;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd mp = nmp;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (mp);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amorevoid
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore{
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_t *afep = arg;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if (mii_m_loop_ioctl(afep->afe_mii, wq, mp))
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore return;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore miocnak(wq, mp, 0, EINVAL);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore}
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Hardware management.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdstatic boolean_t
1959748cbddf37d4734c107dadfa449e076045e3gdafe_initialize(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned val;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t par, nar;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_intrlock));
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_xmtlock));
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd SETBIT(afep, CSR_PAR, PAR_RESET);
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 1; i < 10; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(5);
1959748cbddf37d4734c107dadfa449e076045e3gd val = GETCSR(afep, CSR_PAR);
1959748cbddf37d4734c107dadfa449e076045e3gd if (!(val & PAR_RESET)) {
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (i == 10) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip, "timed out waiting for reset!");
1959748cbddf37d4734c107dadfa449e076045e3gd return (B_FALSE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Updated Centaur data sheets show that the Comet and Centaur are
1959748cbddf37d4734c107dadfa449e076045e3gd * alike here (contrary to earlier versions of the data sheet).
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd /* XXX:? chip problems */
1959748cbddf37d4734c107dadfa449e076045e3gd /* par = PAR_MRLE | PAR_MRME | PAR_MWIE; */
1959748cbddf37d4734c107dadfa449e076045e3gd par = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd switch (afep->afe_cachesize) {
1959748cbddf37d4734c107dadfa449e076045e3gd case 8:
1959748cbddf37d4734c107dadfa449e076045e3gd par |= PAR_CALIGN_8 | PAR_BURST_8;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case 16:
1959748cbddf37d4734c107dadfa449e076045e3gd par |= PAR_CALIGN_16 | PAR_BURST_16;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case 32:
1959748cbddf37d4734c107dadfa449e076045e3gd par |= PAR_CALIGN_32 | PAR_BURST_32;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd default:
1959748cbddf37d4734c107dadfa449e076045e3gd par |= PAR_BURST_32;
1959748cbddf37d4734c107dadfa449e076045e3gd par &= ~(PAR_MWIE | PAR_MRLE | PAR_MRME);
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_PAR, par);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* enable transmit underrun auto-recovery */
1959748cbddf37d4734c107dadfa449e076045e3gd SETBIT(afep, CSR_CR, CR_TXURAUTOR);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afe_resetrings(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* clear the lost packet counter (cleared on read) */
1959748cbddf37d4734c107dadfa449e076045e3gd (void) GETCSR(afep, CSR_LPC);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd nar = GETCSR(afep, CSR_NAR);
1959748cbddf37d4734c107dadfa449e076045e3gd nar &= ~NAR_TR; /* clear tx threshold */
1959748cbddf37d4734c107dadfa449e076045e3gd nar |= NAR_SF; /* store-and-forward */
1959748cbddf37d4734c107dadfa449e076045e3gd nar |= NAR_HBD; /* disable SQE test */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_NAR, nar);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afe_setrxfilt(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (B_TRUE);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Serial EEPROM access - inspired by the FreeBSD implementation.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gduint8_t
1959748cbddf37d4734c107dadfa449e076045e3gdafe_sromwidth(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t eeread;
1959748cbddf37d4734c107dadfa449e076045e3gd uint8_t addrlen = 8;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd eeread = SPR_SROM_READ | SPR_SROM_SEL | SPR_SROM_CHIP;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread & ~SPR_SROM_CHIP);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* command bits first */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 4; i != 0; i >>= 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned val = (SROM_READCMD & i) ? SPR_SROM_DIN : 0;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread | val);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread | val | SPR_SROM_CLOCK);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd for (addrlen = 1; addrlen <= 12; addrlen++) {
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread | SPR_SROM_CLOCK);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd if (!(GETCSR(afep, CSR_SPR) & SPR_SROM_DOUT)) {
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* turn off accesses to the EEPROM */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread &~ SPR_SROM_CHIP);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return ((addrlen < 4 || addrlen > 12) ? 6 : addrlen);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * The words in EEPROM are stored in little endian order. We
1959748cbddf37d4734c107dadfa449e076045e3gd * shift bits out in big endian order, though. This requires
1959748cbddf37d4734c107dadfa449e076045e3gd * a byte swap on some platforms.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gduint16_t
1959748cbddf37d4734c107dadfa449e076045e3gdafe_readsromword(afe_t *afep, unsigned romaddr)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t word = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t retval;
1959748cbddf37d4734c107dadfa449e076045e3gd int eeread;
1959748cbddf37d4734c107dadfa449e076045e3gd uint8_t addrlen;
1959748cbddf37d4734c107dadfa449e076045e3gd int readcmd;
1959748cbddf37d4734c107dadfa449e076045e3gd uchar_t *ptr;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd eeread = SPR_SROM_READ | SPR_SROM_SEL | SPR_SROM_CHIP;
1959748cbddf37d4734c107dadfa449e076045e3gd addrlen = afep->afe_sromwidth;
1959748cbddf37d4734c107dadfa449e076045e3gd readcmd = (SROM_READCMD << addrlen) | romaddr;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (romaddr >= (1 << addrlen)) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* too big to fit! */
1959748cbddf37d4734c107dadfa449e076045e3gd return (0);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread & ~SPR_SROM_CHIP);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* command and address bits */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 4 + addrlen; i >= 0; i--) {
1959748cbddf37d4734c107dadfa449e076045e3gd short val = (readcmd & (1 << i)) ? SPR_SROM_DIN : 0;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread | val);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread | val | SPR_SROM_CLOCK);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < 16; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread | SPR_SROM_CLOCK);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd word <<= 1;
1959748cbddf37d4734c107dadfa449e076045e3gd if (GETCSR(afep, CSR_SPR) & SPR_SROM_DOUT) {
1959748cbddf37d4734c107dadfa449e076045e3gd word |= 1;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* turn off accesses to the EEPROM */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, eeread &~ SPR_SROM_CHIP);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Fix up the endianness thing. Note that the values
1959748cbddf37d4734c107dadfa449e076045e3gd * are stored in little endian format on the SROM.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd ptr = (uchar_t *)&word;
1959748cbddf37d4734c107dadfa449e076045e3gd retval = (ptr[1] << 8) | ptr[0];
1959748cbddf37d4734c107dadfa449e076045e3gd return (retval);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_readsrom(afe_t *afep, unsigned romaddr, unsigned len, char *dest)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t word;
1959748cbddf37d4734c107dadfa449e076045e3gd uint16_t *ptr = (uint16_t *)((void *)dest);
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < len; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd word = afe_readsromword(afep, romaddr + i);
1959748cbddf37d4734c107dadfa449e076045e3gd *ptr = word;
1959748cbddf37d4734c107dadfa449e076045e3gd ptr++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_getfactaddr(afe_t *afep, uchar_t *eaddr)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_readsrom(afep, SROM_ENADDR, ETHERADDRL / 2, (char *)eaddr);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * MII management.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_mii_reset(void *arg)
1959748cbddf37d4734c107dadfa449e076045e3gd{
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd int fiber;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore uint16_t mcr;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore uint16_t pilr;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore uint8_t phyaddr;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore * Its entirely possible that this belongs as a PHY specific
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore * override.
1959748cbddf37d4734c107dadfa449e076045e3gd */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if ((mii_get_id(afep->afe_mii) & 0xfffffff0) != 0x225410) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /* if its not an AN983B, we don't care */
1959748cbddf37d4734c107dadfa449e076045e3gd return;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore phyaddr = mii_get_addr(afep->afe_mii);
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore fiber = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore switch (afep->afe_forcefiber) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore case 0:
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /* UTP Port */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore fiber = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore case 1:
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /* Fiber Port */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore fiber = 1;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mcr = afe_mii_read(afep, phyaddr, PHY_MCR);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore switch (fiber) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore case 0:
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mcr &= ~MCR_FIBER;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore break;
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore case 1:
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mcr |= MCR_FIBER;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_mii_write(afep, phyaddr, PHY_MCR, mcr);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore drv_usecwait(500);
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /*
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore * work around for errata 983B_0416 -- duplex light flashes
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore * in 10 HDX. we just disable SQE testing on the device.
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore pilr = afe_mii_read(afep, phyaddr, PHY_PILR);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore pilr |= PILR_NOSQE;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_mii_write(afep, phyaddr, PHY_PILR, pilr);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_mii_notify(void *arg, link_state_t link)
1959748cbddf37d4734c107dadfa449e076045e3gd{
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if (AFE_MODEL(afep) == MODEL_CENTAUR) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if (mii_get_flowctrl(afep->afe_mii) == LINK_FLOWCTRL_BI) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore SETBIT(afep, CSR_CR, CR_PAUSE);
1959748cbddf37d4734c107dadfa449e076045e3gd } else {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore CLRBIT(afep, CSR_CR, CR_PAUSE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd }
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mac_link_update(afep->afe_mh, link);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_miitristate(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd uint32_t val = SPR_SROM_WRITE | SPR_MII_CTRL;
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, val);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, val | SPR_MII_CLOCK);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
96fb08b94cc33de779f46f36c30d77230f1a8c2fgdafe_miiwritebit(afe_t *afep, uint8_t bit)
1959748cbddf37d4734c107dadfa449e076045e3gd{
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd uint32_t val = bit ? SPR_MII_DOUT : 0;
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, val);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, val | SPR_MII_CLOCK);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
96fb08b94cc33de779f46f36c30d77230f1a8c2fgduint8_t
1959748cbddf37d4734c107dadfa449e076045e3gdafe_miireadbit(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd uint32_t val = SPR_MII_CTRL | SPR_SROM_READ;
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd uint8_t bit;
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, val);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd bit = (GETCSR(afep, CSR_SPR) & SPR_MII_DIN) ? 1 : 0;
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SPR, val | SPR_MII_CLOCK);
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(1);
1959748cbddf37d4734c107dadfa449e076045e3gd return (bit);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
96fb08b94cc33de779f46f36c30d77230f1a8c2fgduint16_t
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_mii_read(void *arg, uint8_t phy, uint8_t reg)
1959748cbddf37d4734c107dadfa449e076045e3gd{
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * ADMtek bugs ignore address decode bits -- they only
1959748cbddf37d4734c107dadfa449e076045e3gd * support PHY at 1.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd if (phy != 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd return (0xffff);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd switch (AFE_MODEL(afep)) {
1959748cbddf37d4734c107dadfa449e076045e3gd case MODEL_COMET:
1959748cbddf37d4734c107dadfa449e076045e3gd return (afe_miireadcomet(afep, phy, reg));
1959748cbddf37d4734c107dadfa449e076045e3gd case MODEL_CENTAUR:
1959748cbddf37d4734c107dadfa449e076045e3gd return (afe_miireadgeneral(afep, phy, reg));
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd return (0xffff);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
96fb08b94cc33de779f46f36c30d77230f1a8c2fgduint16_t
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_miireadgeneral(afe_t *afep, uint8_t phy, uint8_t reg)
1959748cbddf37d4734c107dadfa449e076045e3gd{
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd uint16_t value = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* send the 32 bit preamble */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < 32; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 1);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* send the start code - 01b */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 1);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* send the opcode for read, - 10b */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 1);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* next we send the 5 bit phy address */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0x10; i > 0; i >>= 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, (phy & i) ? 1 : 0);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* the 5 bit register address goes next */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0x10; i > 0; i >>= 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, (reg & i) ? 1 : 0);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* turnaround - tristate followed by logic 0 */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miitristate(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* read the 16 bit register value */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0x8000; i > 0; i >>= 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd value <<= 1;
1959748cbddf37d4734c107dadfa449e076045e3gd value |= afe_miireadbit(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miitristate(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd return (value);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
96fb08b94cc33de779f46f36c30d77230f1a8c2fgduint16_t
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_miireadcomet(afe_t *afep, uint8_t phy, uint8_t reg)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd if (phy != 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd return (0xffff);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd switch (reg) {
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_CONTROL:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_BMCR;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_STATUS:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_BMSR;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_PHYIDH:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_PHYIDR1;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_PHYIDL:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_PHYIDR2;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_AN_ADVERT:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_ANAR;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_AN_LPABLE:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_ANLPAR;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_AN_EXPANSION:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_ANER;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd default:
1959748cbddf37d4734c107dadfa449e076045e3gd return (0);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd return (GETCSR16(afep, reg) & 0xFFFF);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t val)
1959748cbddf37d4734c107dadfa449e076045e3gd{
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_t *afep = arg;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * ADMtek bugs ignore address decode bits -- they only
1959748cbddf37d4734c107dadfa449e076045e3gd * support PHY at 1.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd if (phy != 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd return;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd switch (AFE_MODEL(afep)) {
1959748cbddf37d4734c107dadfa449e076045e3gd case MODEL_COMET:
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritecomet(afep, phy, reg, val);
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MODEL_CENTAUR:
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritegeneral(afep, phy, reg, val);
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_miiwritegeneral(afe_t *afep, uint8_t phy, uint8_t reg, uint16_t val)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* send the 32 bit preamble */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < 32; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 1);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* send the start code - 01b */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 1);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* send the opcode for write, - 01b */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 1);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* next we send the 5 bit phy address */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0x10; i > 0; i >>= 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, (phy & i) ? 1 : 0);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* the 5 bit register address goes next */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0x10; i > 0; i >>= 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, (reg & i) ? 1 : 0);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /* turnaround - 1 bit followed by logic 0 */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore afe_miiwritebit(afep, 1);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* now write out our data (16 bits) */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0x8000; i > 0; i >>= 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miiwritebit(afep, (val & i) ? 1 : 0);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* idle mode */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_miitristate(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amoreafe_miiwritecomet(afe_t *afep, uint8_t phy, uint8_t reg, uint16_t val)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd if (phy != 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd return;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd switch (reg) {
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_CONTROL:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_BMCR;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_STATUS:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_BMSR;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_PHYIDH:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_PHYIDR1;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_PHYIDL:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_PHYIDR2;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_AN_ADVERT:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_ANAR;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_AN_LPABLE:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_ANLPAR;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case MII_AN_EXPANSION:
1959748cbddf37d4734c107dadfa449e076045e3gd reg = CSR_ANER;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd default:
1959748cbddf37d4734c107dadfa449e076045e3gd return;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR16(afep, reg, val);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_m_start(void *arg)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* grab exclusive access to the card */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afe_startall(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_flags |= AFE_RUNNING;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_start(afep->afe_mii);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd return (0);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_m_stop(void *arg)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_stop(afep->afe_mii);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd /* exclusive access to the hardware! */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afe_stopall(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_flags &= ~AFE_RUNNING;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_startmac(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd /* verify exclusive access to the card */
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_intrlock));
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_xmtlock));
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* start the card */
1959748cbddf37d4734c107dadfa449e076045e3gd SETBIT(afep, CSR_NAR, NAR_TX_ENABLE | NAR_RX_ENABLE);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_txavail != AFE_TXRING)
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_TDR, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* tell the mac that we are ready to go! */
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_flags & AFE_RUNNING)
1959748cbddf37d4734c107dadfa449e076045e3gd mac_tx_update(afep->afe_mh);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /* start watchdog timer */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore PUTCSR(afep, CSR_TIMER, TIMER_LOOP |
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore (AFE_WDOGTIMER * 1000 / TIMER_USEC));
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_stopmac(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* exclusive access to the hardware! */
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_intrlock));
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_xmtlock));
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd CLRBIT(afep, CSR_NAR, NAR_TX_ENABLE | NAR_RX_ENABLE);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * A 1518 byte frame at 10Mbps takes about 1.2 msec to drain.
1959748cbddf37d4734c107dadfa449e076045e3gd * We just add up to the nearest msec (2), which should be
1959748cbddf37d4734c107dadfa449e076045e3gd * plenty to complete.
1959748cbddf37d4734c107dadfa449e076045e3gd *
1959748cbddf37d4734c107dadfa449e076045e3gd * Note that some chips never seem to indicate the transition to
1959748cbddf37d4734c107dadfa449e076045e3gd * the stopped state properly. Experience shows that we can safely
1959748cbddf37d4734c107dadfa449e076045e3gd * proceed anyway, after waiting the requisite timeout.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 2000; i != 0; i -= 10) {
1959748cbddf37d4734c107dadfa449e076045e3gd if ((GETCSR(afep, CSR_SR) & (SR_TX_STATE | SR_RX_STATE)) == 0)
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd drv_usecwait(10);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* prevent an interrupt */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SR2, INT_RXSTOPPED | INT_TXSTOPPED);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore /* stop the watchdog timer */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore PUTCSR(afep, CSR_TIMER, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_resetrings(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* now we need to reset the pointers... */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_RDB, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_TDB, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* reset the descriptor ring pointers */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_rxhead = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txreclaim = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txsend = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txavail = AFE_TXRING;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* set up transmit descriptor ring */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < AFE_TXRING; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_desc_t *tmdp = &afep->afe_txdescp[i];
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned control = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd if (i == (AFE_TXRING - 1)) {
1959748cbddf37d4734c107dadfa449e076045e3gd control |= TXCTL_ENDRING;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd PUTTXDESC(afep, tmdp->desc_status, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTTXDESC(afep, tmdp->desc_control, control);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTTXDESC(afep, tmdp->desc_buffer1, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTTXDESC(afep, tmdp->desc_buffer2, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd SYNCTXDESC(afep, i, DDI_DMA_SYNC_FORDEV);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_TDB, afep->afe_txdesc_paddr);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* make the receive buffers available */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < AFE_RXRING; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_rxbuf_t *rxb = afep->afe_rxbufs[i];
1959748cbddf37d4734c107dadfa449e076045e3gd afe_desc_t *rmdp = &afep->afe_rxdescp[i];
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned control;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd control = AFE_BUFSZ & RXCTL_BUFLEN1;
1959748cbddf37d4734c107dadfa449e076045e3gd if (i == (AFE_RXRING - 1)) {
1959748cbddf37d4734c107dadfa449e076045e3gd control |= RXCTL_ENDRING;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd PUTRXDESC(afep, rmdp->desc_buffer1, rxb->rxb_paddr);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTRXDESC(afep, rmdp->desc_buffer2, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTRXDESC(afep, rmdp->desc_control, control);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTRXDESC(afep, rmdp->desc_status, RXSTAT_OWN);
1959748cbddf37d4734c107dadfa449e076045e3gd SYNCRXDESC(afep, i, DDI_DMA_SYNC_FORDEV);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_RDB, afep->afe_rxdesc_paddr);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_stopall(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_disableinterrupts(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_stopmac(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_startall(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_intrlock));
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_xmtlock));
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* make sure interrupts are disabled to begin */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_disableinterrupts(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* initialize the chip */
1959748cbddf37d4734c107dadfa449e076045e3gd (void) afe_initialize(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* now we can enable interrupts */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_enableinterrupts(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* start up the mac */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_startmac(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_resetall(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_stopall(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_startall(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdafe_txbuf_t *
1959748cbddf37d4734c107dadfa449e076045e3gdafe_alloctxbuf(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_cookie_t dmac;
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned ncookies;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_txbuf_t *txb;
1959748cbddf37d4734c107dadfa449e076045e3gd size_t len;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd txb = kmem_zalloc(sizeof (*txb), KM_SLEEP);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_dma_alloc_handle(afep->afe_dip, &afe_dma_txattr,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_SLEEP, NULL, &txb->txb_dmah) != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd return (NULL);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_dma_mem_alloc(txb->txb_dmah, AFE_BUFSZ, &afe_bufattr,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &txb->txb_buf, &len,
1959748cbddf37d4734c107dadfa449e076045e3gd &txb->txb_acch) != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd return (NULL);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_dma_addr_bind_handle(txb->txb_dmah, NULL, txb->txb_buf,
1959748cbddf37d4734c107dadfa449e076045e3gd len, DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
1959748cbddf37d4734c107dadfa449e076045e3gd &dmac, &ncookies) != DDI_DMA_MAPPED) {
1959748cbddf37d4734c107dadfa449e076045e3gd return (NULL);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd txb->txb_paddr = dmac.dmac_address;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (txb);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_destroytxbuf(afe_txbuf_t *txb)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd if (txb != NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd if (txb->txb_paddr)
1959748cbddf37d4734c107dadfa449e076045e3gd (void) ddi_dma_unbind_handle(txb->txb_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd if (txb->txb_acch)
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_mem_free(&txb->txb_acch);
1959748cbddf37d4734c107dadfa449e076045e3gd if (txb->txb_dmah)
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_free_handle(&txb->txb_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(txb, sizeof (*txb));
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdafe_rxbuf_t *
1959748cbddf37d4734c107dadfa449e076045e3gdafe_allocrxbuf(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_rxbuf_t *rxb;
1959748cbddf37d4734c107dadfa449e076045e3gd size_t len;
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned ccnt;
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_cookie_t dmac;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rxb = kmem_zalloc(sizeof (*rxb), KM_SLEEP);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_dma_alloc_handle(afep->afe_dip, &afe_dma_attr,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_SLEEP, NULL, &rxb->rxb_dmah) != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(rxb, sizeof (*rxb));
1959748cbddf37d4734c107dadfa449e076045e3gd return (NULL);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_dma_mem_alloc(rxb->rxb_dmah, AFE_BUFSZ, &afe_bufattr,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &rxb->rxb_buf, &len,
1959748cbddf37d4734c107dadfa449e076045e3gd &rxb->rxb_acch) != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_free_handle(&rxb->rxb_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(rxb, sizeof (*rxb));
1959748cbddf37d4734c107dadfa449e076045e3gd return (NULL);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (ddi_dma_addr_bind_handle(rxb->rxb_dmah, NULL, rxb->rxb_buf, len,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &dmac,
1959748cbddf37d4734c107dadfa449e076045e3gd &ccnt) != DDI_DMA_MAPPED) {
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_mem_free(&rxb->rxb_acch);
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_free_handle(&rxb->rxb_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(rxb, sizeof (*rxb));
1959748cbddf37d4734c107dadfa449e076045e3gd return (NULL);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd rxb->rxb_paddr = dmac.dmac_address;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (rxb);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_destroyrxbuf(afe_rxbuf_t *rxb)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd if (rxb) {
1959748cbddf37d4734c107dadfa449e076045e3gd (void) ddi_dma_unbind_handle(rxb->rxb_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_mem_free(&rxb->rxb_acch);
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_free_handle(&rxb->rxb_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(rxb, sizeof (*rxb));
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Allocate receive resources.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_allocrxring(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int rval;
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd size_t size;
1959748cbddf37d4734c107dadfa449e076045e3gd size_t len;
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_cookie_t dmac;
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned ncookies;
1959748cbddf37d4734c107dadfa449e076045e3gd caddr_t kaddr;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd size = AFE_RXRING * sizeof (afe_desc_t);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rval = ddi_dma_alloc_handle(afep->afe_dip, &afe_dma_attr,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_SLEEP, NULL, &afep->afe_rxdesc_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd if (rval != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip,
1959748cbddf37d4734c107dadfa449e076045e3gd "unable to allocate DMA handle for rx descriptors");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rval = ddi_dma_mem_alloc(afep->afe_rxdesc_dmah, size, &afe_devattr,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len,
1959748cbddf37d4734c107dadfa449e076045e3gd &afep->afe_rxdesc_acch);
1959748cbddf37d4734c107dadfa449e076045e3gd if (rval != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip,
1959748cbddf37d4734c107dadfa449e076045e3gd "unable to allocate DMA memory for rx descriptors");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rval = ddi_dma_addr_bind_handle(afep->afe_rxdesc_dmah, NULL, kaddr,
1959748cbddf37d4734c107dadfa449e076045e3gd size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
1959748cbddf37d4734c107dadfa449e076045e3gd &dmac, &ncookies);
1959748cbddf37d4734c107dadfa449e076045e3gd if (rval != DDI_DMA_MAPPED) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip,
1959748cbddf37d4734c107dadfa449e076045e3gd "unable to bind DMA for rx descriptors");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* because of afe_dma_attr */
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(ncookies == 1);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* we take the 32-bit physical address out of the cookie */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_rxdesc_paddr = dmac.dmac_address;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_rxdescp = (void *)kaddr;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* allocate buffer pointers (not the buffers themselves, yet) */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_rxbufs = kmem_zalloc(AFE_RXRING * sizeof (afe_rxbuf_t *),
1959748cbddf37d4734c107dadfa449e076045e3gd KM_SLEEP);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* now allocate rx buffers */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < AFE_RXRING; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_rxbuf_t *rxb = afe_allocrxbuf(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd if (rxb == NULL)
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_rxbufs[i] = rxb;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_SUCCESS);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Allocate transmit resources.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_alloctxring(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int rval;
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd size_t size;
1959748cbddf37d4734c107dadfa449e076045e3gd size_t len;
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_cookie_t dmac;
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned ncookies;
1959748cbddf37d4734c107dadfa449e076045e3gd caddr_t kaddr;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd size = AFE_TXRING * sizeof (afe_desc_t);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rval = ddi_dma_alloc_handle(afep->afe_dip, &afe_dma_attr,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_SLEEP, NULL, &afep->afe_txdesc_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd if (rval != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip,
1959748cbddf37d4734c107dadfa449e076045e3gd "unable to allocate DMA handle for tx descriptors");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rval = ddi_dma_mem_alloc(afep->afe_txdesc_dmah, size, &afe_devattr,
1959748cbddf37d4734c107dadfa449e076045e3gd DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &kaddr, &len,
1959748cbddf37d4734c107dadfa449e076045e3gd &afep->afe_txdesc_acch);
1959748cbddf37d4734c107dadfa449e076045e3gd if (rval != DDI_SUCCESS) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip,
1959748cbddf37d4734c107dadfa449e076045e3gd "unable to allocate DMA memory for tx descriptors");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rval = ddi_dma_addr_bind_handle(afep->afe_txdesc_dmah, NULL, kaddr,
1959748cbddf37d4734c107dadfa449e076045e3gd size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
1959748cbddf37d4734c107dadfa449e076045e3gd &dmac, &ncookies);
1959748cbddf37d4734c107dadfa449e076045e3gd if (rval != DDI_DMA_MAPPED) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip,
1959748cbddf37d4734c107dadfa449e076045e3gd "unable to bind DMA for tx descriptors");
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* because of afe_dma_attr */
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(ncookies == 1);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* we take the 32-bit physical address out of the cookie */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txdesc_paddr = dmac.dmac_address;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txdescp = (void *)kaddr;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* allocate buffer pointers (not the buffers themselves, yet) */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txbufs = kmem_zalloc(AFE_TXRING * sizeof (afe_txbuf_t *),
1959748cbddf37d4734c107dadfa449e076045e3gd KM_SLEEP);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* now allocate tx buffers */
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < AFE_TXRING; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_txbuf_t *txb = afe_alloctxbuf(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd if (txb == NULL)
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_FAILURE);
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txbufs[i] = txb;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_SUCCESS);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_freerxring(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < AFE_RXRING; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_destroyrxbuf(afep->afe_rxbufs[i]);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_rxbufs) {
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(afep->afe_rxbufs,
1959748cbddf37d4734c107dadfa449e076045e3gd AFE_RXRING * sizeof (afe_rxbuf_t *));
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_rxdesc_paddr)
1959748cbddf37d4734c107dadfa449e076045e3gd (void) ddi_dma_unbind_handle(afep->afe_rxdesc_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_rxdesc_acch)
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_mem_free(&afep->afe_rxdesc_acch);
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_rxdesc_dmah)
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_free_handle(&afep->afe_rxdesc_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_freetxring(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd int i;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd for (i = 0; i < AFE_TXRING; i++) {
1959748cbddf37d4734c107dadfa449e076045e3gd afe_destroytxbuf(afep->afe_txbufs[i]);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_txbufs) {
1959748cbddf37d4734c107dadfa449e076045e3gd kmem_free(afep->afe_txbufs,
1959748cbddf37d4734c107dadfa449e076045e3gd AFE_TXRING * sizeof (afe_txbuf_t *));
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_txdesc_paddr)
1959748cbddf37d4734c107dadfa449e076045e3gd (void) ddi_dma_unbind_handle(afep->afe_txdesc_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_txdesc_acch)
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_mem_free(&afep->afe_txdesc_acch);
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_txdesc_dmah)
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_dma_free_handle(&afep->afe_txdesc_dmah);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Interrupt service routine.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdunsigned
1959748cbddf37d4734c107dadfa449e076045e3gdafe_intr(caddr_t arg)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep = (void *)arg;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t status;
1959748cbddf37d4734c107dadfa449e076045e3gd mblk_t *mp = NULL;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore boolean_t doreset = B_FALSE;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_flags & AFE_SUSPENDED) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* we cannot receive interrupts! */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_INTR_UNCLAIMED);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* check interrupt status bits, did we interrupt? */
1959748cbddf37d4734c107dadfa449e076045e3gd status = GETCSR(afep, CSR_SR2) & INT_ALL;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status == 0) {
1959748cbddf37d4734c107dadfa449e076045e3gd KIOIP->intrs[KSTAT_INTR_SPURIOUS]++;
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_INTR_UNCLAIMED);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd /* ack the interrupt */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SR2, status);
1959748cbddf37d4734c107dadfa449e076045e3gd KIOIP->intrs[KSTAT_INTR_HARD]++;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (!(afep->afe_flags & AFE_RUNNING)) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* not running, don't touch anything */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_INTR_CLAIMED);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & (INT_RXOK|INT_RXNOBUF)) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* receive packets */
1959748cbddf37d4734c107dadfa449e076045e3gd mp = afe_receive(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & INT_RXNOBUF)
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_RDR, 0); /* wake up chip */
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & INT_TXOK) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* transmit completed */
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_reclaim(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if ((status & INT_TIMER) && (afe_watchdog(afep) != DDI_SUCCESS)) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore doreset = B_TRUE;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & (INT_RXSTOPPED|INT_TXSTOPPED|
1959748cbddf37d4734c107dadfa449e076045e3gd INT_RXJABBER|INT_TXJABBER|INT_TXUNDERFLOW)) {
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & (INT_RXJABBER | INT_TXJABBER)) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_jabber++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore doreset = B_TRUE;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & INT_BUSERR) {
1959748cbddf37d4734c107dadfa449e076045e3gd switch (GETCSR(afep, CSR_SR) & SR_BERR_TYPE) {
1959748cbddf37d4734c107dadfa449e076045e3gd case SR_BERR_PARITY:
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip, "PCI parity error");
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case SR_BERR_TARGET_ABORT:
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip, "PCI target abort");
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd case SR_BERR_MASTER_ABORT:
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip, "PCI master abort");
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd default:
1959748cbddf37d4734c107dadfa449e076045e3gd afe_error(afep->afe_dip, "Unknown PCI error");
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* reset the chip in an attempt to fix things */
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore doreset = B_TRUE;
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore }
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if (doreset) {
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd afe_resetall(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mutex_exit(&afep->afe_intrlock);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_reset(afep->afe_mii);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore } else {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mutex_exit(&afep->afe_intrlock);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if (status & INT_LINKCHG) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore mii_check(afep->afe_mii);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Send up packets. We do this outside of the intrlock.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd if (mp) {
1959748cbddf37d4734c107dadfa449e076045e3gd mac_rx(afep->afe_mh, NULL, mp);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (DDI_INTR_CLAIMED);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_enableinterrupts(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned mask = INT_WANTED;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_wantw)
1959748cbddf37d4734c107dadfa449e076045e3gd mask |= INT_TXOK;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_IER2, mask);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (AFE_MODEL(afep) == MODEL_COMET) {
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * On the Comet, this is the internal transceiver
1959748cbddf37d4734c107dadfa449e076045e3gd * interrupt. We program the Comet's built-in PHY to
1959748cbddf37d4734c107dadfa449e076045e3gd * enable certain interrupts.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR16(afep, CSR_XIE, XIE_LDE | XIE_ANCE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_disableinterrupts(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd /* disable further interrupts */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_IER2, INT_NONE);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* clear any pending interrupts */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_SR2, INT_ALL);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdboolean_t
1959748cbddf37d4734c107dadfa449e076045e3gdafe_send(afe_t *afep, mblk_t *mp)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd size_t len;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_txbuf_t *txb;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_desc_t *tmd;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t control;
1959748cbddf37d4734c107dadfa449e076045e3gd int txsend;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mutex_owned(&afep->afe_xmtlock));
1959748cbddf37d4734c107dadfa449e076045e3gd ASSERT(mp != NULL);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd len = msgsize(mp);
1959748cbddf37d4734c107dadfa449e076045e3gd if (len > ETHERVLANMTU) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_macxmt_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd freemsg(mp);
1959748cbddf37d4734c107dadfa449e076045e3gd return (B_TRUE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_txavail < AFE_TXRECLAIM)
1959748cbddf37d4734c107dadfa449e076045e3gd afe_reclaim(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_txavail == 0) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* no more tmds */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_wantw = B_TRUE;
1959748cbddf37d4734c107dadfa449e076045e3gd /* enable TX interrupt */
1959748cbddf37d4734c107dadfa449e076045e3gd afe_enableinterrupts(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd return (B_FALSE);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd txsend = afep->afe_txsend;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * For simplicity, we just do a copy into a preallocated
1959748cbddf37d4734c107dadfa449e076045e3gd * DMA buffer.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd txb = afep->afe_txbufs[txsend];
1959748cbddf37d4734c107dadfa449e076045e3gd mcopymsg(mp, txb->txb_buf); /* frees mp! */
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Statistics.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_opackets++;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_obytes += len;
1959748cbddf37d4734c107dadfa449e076045e3gd if (txb->txb_buf[0] & 0x1) {
1959748cbddf37d4734c107dadfa449e076045e3gd if (bcmp(txb->txb_buf, afe_broadcast, ETHERADDRL) != 0)
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_multixmt++;
1959748cbddf37d4734c107dadfa449e076045e3gd else
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_brdcstxmt++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* note len is already known to be a small unsigned */
1959748cbddf37d4734c107dadfa449e076045e3gd control = len | TXCTL_FIRST | TXCTL_LAST | TXCTL_INTCMPLTE;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (txsend == (AFE_TXRING - 1))
1959748cbddf37d4734c107dadfa449e076045e3gd control |= TXCTL_ENDRING;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd tmd = &afep->afe_txdescp[txsend];
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd SYNCTXBUF(txb, len, DDI_DMA_SYNC_FORDEV);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTTXDESC(afep, tmd->desc_control, control);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTTXDESC(afep, tmd->desc_buffer1, txb->txb_paddr);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTTXDESC(afep, tmd->desc_buffer2, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd PUTTXDESC(afep, tmd->desc_status, TXSTAT_OWN);
1959748cbddf37d4734c107dadfa449e076045e3gd /* sync the descriptor out to the device */
1959748cbddf37d4734c107dadfa449e076045e3gd SYNCTXDESC(afep, txsend, DDI_DMA_SYNC_FORDEV);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Note the new values of txavail and txsend.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txavail--;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txsend = (txsend + 1) % AFE_TXRING;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * It should never, ever take more than 5 seconds to drain
1959748cbddf37d4734c107dadfa449e076045e3gd * the ring. If it happens, then we are stuck!
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txstall_time = gethrtime() + (5 * 1000000000ULL);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * wake up the chip ... inside the lock to protect against DR suspend,
1959748cbddf37d4734c107dadfa449e076045e3gd * etc.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTCSR(afep, CSR_TDR, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (B_TRUE);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Reclaim buffers that have completed transmission.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_reclaim(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_desc_t *tmdp;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd while (afep->afe_txavail != AFE_TXRING) {
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t status;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t control;
1959748cbddf37d4734c107dadfa449e076045e3gd int index = afep->afe_txreclaim;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd tmdp = &afep->afe_txdescp[index];
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* sync it before we read it */
1959748cbddf37d4734c107dadfa449e076045e3gd SYNCTXDESC(afep, index, DDI_DMA_SYNC_FORKERNEL);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd control = GETTXDESC(afep, tmdp->desc_control);
1959748cbddf37d4734c107dadfa449e076045e3gd status = GETTXDESC(afep, tmdp->desc_status);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & TXSTAT_OWN) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* chip is still working on it, we're done */
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txavail++;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_txreclaim = (index + 1) % AFE_TXRING;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* in the most common successful case, all bits are clear */
1959748cbddf37d4734c107dadfa449e076045e3gd if (status == 0)
1959748cbddf37d4734c107dadfa449e076045e3gd continue;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if ((control & TXCTL_LAST) == 0)
1959748cbddf37d4734c107dadfa449e076045e3gd continue;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & TXSTAT_TXERR) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_errxmt++;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & TXSTAT_JABBER) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* transmit jabber timeout */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_macxmt_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (status &
1959748cbddf37d4734c107dadfa449e076045e3gd (TXSTAT_CARRLOST | TXSTAT_NOCARR)) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_carrier_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & TXSTAT_UFLOW) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_underflow++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & TXSTAT_LATECOL) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_tx_late_collisions++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & TXSTAT_EXCOLL) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_ex_collisions++;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_collisions += 16;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & TXSTAT_DEFER) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_defer_xmts++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* collision counting */
1959748cbddf37d4734c107dadfa449e076045e3gd if (TXCOLLCNT(status) == 1) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_collisions++;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_first_collisions++;
1959748cbddf37d4734c107dadfa449e076045e3gd } else if (TXCOLLCNT(status)) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_collisions += TXCOLLCNT(status);
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_multi_collisions += TXCOLLCNT(status);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_txavail >= AFE_TXRESCHED) {
1959748cbddf37d4734c107dadfa449e076045e3gd if (afep->afe_wantw) {
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * we were able to reclaim some packets, so
1959748cbddf37d4734c107dadfa449e076045e3gd * disable tx interrupts
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_wantw = B_FALSE;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_enableinterrupts(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd mac_tx_update(afep->afe_mh);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdmblk_t *
1959748cbddf37d4734c107dadfa449e076045e3gdafe_receive(afe_t *afep)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd unsigned len;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_rxbuf_t *rxb;
1959748cbddf37d4734c107dadfa449e076045e3gd afe_desc_t *rmd;
1959748cbddf37d4734c107dadfa449e076045e3gd uint32_t status;
1959748cbddf37d4734c107dadfa449e076045e3gd mblk_t *mpchain, **mpp, *mp;
1959748cbddf37d4734c107dadfa449e076045e3gd int head, cnt;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mpchain = NULL;
1959748cbddf37d4734c107dadfa449e076045e3gd mpp = &mpchain;
1959748cbddf37d4734c107dadfa449e076045e3gd head = afep->afe_rxhead;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* limit the number of packets we process to a half ring size */
1959748cbddf37d4734c107dadfa449e076045e3gd for (cnt = 0; cnt < AFE_RXRING / 2; cnt++) {
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd rmd = &afep->afe_rxdescp[head];
1959748cbddf37d4734c107dadfa449e076045e3gd rxb = afep->afe_rxbufs[head];
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd SYNCRXDESC(afep, head, DDI_DMA_SYNC_FORKERNEL);
1959748cbddf37d4734c107dadfa449e076045e3gd status = GETRXDESC(afep, rmd->desc_status);
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & RXSTAT_OWN) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* chip is still chewing on it */
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* discard the ethernet frame checksum */
1959748cbddf37d4734c107dadfa449e076045e3gd len = RXLENGTH(status) - ETHERFCSL;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if ((status & (RXSTAT_ERRS | RXSTAT_FIRST | RXSTAT_LAST)) !=
1959748cbddf37d4734c107dadfa449e076045e3gd (RXSTAT_FIRST | RXSTAT_LAST)) {
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_errrcv++;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * Abnormal status bits detected, analyze further.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd if ((status & (RXSTAT_LAST|RXSTAT_FIRST)) !=
1959748cbddf37d4734c107dadfa449e076045e3gd (RXSTAT_LAST|RXSTAT_FIRST)) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & RXSTAT_FIRST) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_toolong_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd } else if (status & RXSTAT_DESCERR) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_macrcv_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd } else if (status & RXSTAT_RUNT) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_runt++;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd } else if (status & RXSTAT_COLLSEEN) {
1959748cbddf37d4734c107dadfa449e076045e3gd /* this should really be rx_late_collisions */
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_macrcv_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd } else if (status & RXSTAT_DRIBBLE) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_align_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd } else if (status & RXSTAT_CRCERR) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_fcs_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd } else if (status & RXSTAT_OFLOW) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_overflow++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd else if (len > ETHERVLANMTU) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_errrcv++;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_toolong_errors++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /*
1959748cbddf37d4734c107dadfa449e076045e3gd * At this point, the chip thinks the packet is OK.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gd else {
1959748cbddf37d4734c107dadfa449e076045e3gd mp = allocb(len + AFE_HEADROOM, 0);
1959748cbddf37d4734c107dadfa449e076045e3gd if (mp == NULL) {
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_errrcv++;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_norcvbuf++;
1959748cbddf37d4734c107dadfa449e076045e3gd goto skip;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* sync the buffer before we look at it */
1959748cbddf37d4734c107dadfa449e076045e3gd SYNCRXBUF(rxb, len, DDI_DMA_SYNC_FORKERNEL);
1959748cbddf37d4734c107dadfa449e076045e3gd mp->b_rptr += AFE_HEADROOM;
1959748cbddf37d4734c107dadfa449e076045e3gd mp->b_wptr = mp->b_rptr + len;
1959748cbddf37d4734c107dadfa449e076045e3gd bcopy((char *)rxb->rxb_buf, mp->b_rptr, len);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_ipackets++;
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_rbytes += len;
1959748cbddf37d4734c107dadfa449e076045e3gd if (status & RXSTAT_GROUP) {
1959748cbddf37d4734c107dadfa449e076045e3gd if (bcmp(mp->b_rptr, afe_broadcast,
1959748cbddf37d4734c107dadfa449e076045e3gd ETHERADDRL) == 0)
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_brdcstrcv++;
1959748cbddf37d4734c107dadfa449e076045e3gd else
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_multircv++;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd *mpp = mp;
1959748cbddf37d4734c107dadfa449e076045e3gd mpp = &mp->b_next;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdskip:
1959748cbddf37d4734c107dadfa449e076045e3gd /* return ring entry to the hardware */
1959748cbddf37d4734c107dadfa449e076045e3gd PUTRXDESC(afep, rmd->desc_status, RXSTAT_OWN);
1959748cbddf37d4734c107dadfa449e076045e3gd SYNCRXDESC(afep, head, DDI_DMA_SYNC_FORDEV);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd /* advance to next RMD */
1959748cbddf37d4734c107dadfa449e076045e3gd head = (head + 1) % AFE_RXRING;
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd afep->afe_rxhead = head;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd return (mpchain);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
1959748cbddf37d4734c107dadfa449e076045e3gdafe_m_stat(void *arg, uint_t stat, uint64_t *val)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_enter(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd if ((afep->afe_flags & (AFE_RUNNING|AFE_SUSPENDED)) == AFE_RUNNING)
1959748cbddf37d4734c107dadfa449e076045e3gd afe_reclaim(afep);
1959748cbddf37d4734c107dadfa449e076045e3gd mutex_exit(&afep->afe_xmtlock);
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore if (mii_m_getstat(afep->afe_mii, stat, val) == 0) {
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore return (0);
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore }
1959748cbddf37d4734c107dadfa449e076045e3gd switch (stat) {
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_MULTIRCV:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_multircv;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_BRDCSTRCV:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_brdcstrcv;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_MULTIXMT:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_multixmt;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_BRDCSTXMT:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_brdcstxmt;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_IPACKETS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_ipackets;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_RBYTES:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_rbytes;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_OPACKETS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_opackets;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_OBYTES:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_obytes;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_NORCVBUF:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_norcvbuf;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_NOXMTBUF:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = 0;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_COLLISIONS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_collisions;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_IERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_errrcv;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_OERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_errxmt;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_ALIGN_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_align_errors;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_FCS_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_fcs_errors;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_SQE_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_sqe_errors;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_DEFER_XMTS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_defer_xmts;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_FIRST_COLLISIONS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_first_collisions;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_MULTI_COLLISIONS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_multi_collisions;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_TX_LATE_COLLISIONS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_tx_late_collisions;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_EX_COLLISIONS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_ex_collisions;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_MACXMT_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_macxmt_errors;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_CARRIER_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_carrier_errors;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_TOOLONG_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_toolong_errors;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_MACRCV_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_macrcv_errors;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_OVERFLOWS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_overflow;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case MAC_STAT_UNDERFLOWS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_underflow;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_TOOSHORT_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_runt;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd case ETHER_STAT_JABBER_ERRORS:
1959748cbddf37d4734c107dadfa449e076045e3gd *val = afep->afe_jabber;
1959748cbddf37d4734c107dadfa449e076045e3gd break;
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd default:
1959748cbddf37d4734c107dadfa449e076045e3gd return (ENOTSUP);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd return (0);
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
96fb08b94cc33de779f46f36c30d77230f1a8c2fgdint
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerafe_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer void *val)
1959748cbddf37d4734c107dadfa449e076045e3gd{
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (mii_m_getprop(afep->afe_mii, name, num, sz, val));
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gdint
96fb08b94cc33de779f46f36c30d77230f1a8c2fgdafe_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz,
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd const void *val)
1959748cbddf37d4734c107dadfa449e076045e3gd{
96fb08b94cc33de779f46f36c30d77230f1a8c2fgd afe_t *afep = arg;
1959748cbddf37d4734c107dadfa449e076045e3gd
bdb9230ac765cb7af3fc1f4119caf2c5720dceb3Garrett D'Amore return (mii_m_setprop(afep->afe_mii, name, num, sz, val));
1959748cbddf37d4734c107dadfa449e076045e3gd}
1959748cbddf37d4734c107dadfa449e076045e3gd
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerafe_m_propinfo(void *arg, const char *name, mac_prop_id_t num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t prh)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer afe_t *afep = arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mii_m_propinfo(afep->afe_mii, name, num, prh);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
1959748cbddf37d4734c107dadfa449e076045e3gd/*
1959748cbddf37d4734c107dadfa449e076045e3gd * Debugging and error reporting.
1959748cbddf37d4734c107dadfa449e076045e3gd */
1959748cbddf37d4734c107dadfa449e076045e3gdvoid
1959748cbddf37d4734c107dadfa449e076045e3gdafe_error(dev_info_t *dip, char *fmt, ...)
1959748cbddf37d4734c107dadfa449e076045e3gd{
1959748cbddf37d4734c107dadfa449e076045e3gd va_list ap;
1959748cbddf37d4734c107dadfa449e076045e3gd char buf[256];
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd va_start(ap, fmt);
1959748cbddf37d4734c107dadfa449e076045e3gd (void) vsnprintf(buf, sizeof (buf), fmt, ap);
1959748cbddf37d4734c107dadfa449e076045e3gd va_end(ap);
1959748cbddf37d4734c107dadfa449e076045e3gd
1959748cbddf37d4734c107dadfa449e076045e3gd if (dip) {
1959748cbddf37d4734c107dadfa449e076045e3gd cmn_err(CE_WARN, "%s%d: %s",
1959748cbddf37d4734c107dadfa449e076045e3gd ddi_driver_name(dip), ddi_get_instance(dip), buf);
1959748cbddf37d4734c107dadfa449e076045e3gd } else {
1959748cbddf37d4734c107dadfa449e076045e3gd cmn_err(CE_WARN, "afe: %s", buf);
1959748cbddf37d4734c107dadfa449e076045e3gd }
1959748cbddf37d4734c107dadfa449e076045e3gd}