sfe.c revision 23d366e350386ec109bfa9b2cf91225729a1a26b
/*
*
* Copyright (c) 2002-2008 Masayuki Murayama. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
*
* 3. Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#pragma ident "%Z%%M% %I% %E% SMI" /* sfe device driver */
/*
* System Header files.
*/
#include <sys/byteorder.h>
#include <sys/ethernet.h>
#include "sfe_mii.h"
#include "sfe_util.h"
#include "sfereg.h"
/* Debugging support */
#ifdef DEBUG_LEVEL
static int sfe_debug = DEBUG_LEVEL;
#if DEBUG_LEVEL > 4
#define CONS "^"
#else
#define CONS "!"
#endif
#else
#define CONS "!"
#endif
/*
* Useful macros and typedefs
*/
/*
* Our configuration
*/
#define MAXTXFRAGS 1
#define MAXRXFRAGS 1
#ifndef TX_BUF_SIZE
#define TX_BUF_SIZE 64
#endif
#ifndef TX_RING_SIZE
#if MAXTXFRAGS == 1
#define TX_RING_SIZE TX_BUF_SIZE
#else
#endif
#endif
#ifndef RX_BUF_SIZE
#define RX_BUF_SIZE 256
#endif
#ifndef RX_RING_SIZE
#define RX_RING_SIZE RX_BUF_SIZE
#endif
#define OUR_INTR_BITS \
#define USE_MULTICAST_HASHTBL
static int sfe_tx_copy_thresh = 256;
static int sfe_rx_copy_thresh = 256;
/* special PHY registers for SIS900 */
#define MII_CONFIG1 0x0010
#define MII_CONFIG2 0x0011
#define MII_MASK 0x0013
#define MII_RESV 0x0014
#define PHY_MASK 0xfffffff0
#define PHY_SIS900_INTERNAL 0x001d8000
#define PHY_ICS1893 0x0015f440
/*
* Supported chips
*/
struct chip_info {
char *chip_name;
int chip_type;
#define CHIPTYPE_DP83815 0
#define CHIPTYPE_SIS900 1
};
/*
* Chip dependent MAC state
*/
struct sfe_dev {
/* misc HW information */
};
/*
* Hardware information
*/
struct chip_info sfe_chiptbl[] = {
};
/* ======================================================== */
/* mii operations */
static void sfe_mii_sync_dp83815(struct gem_dev *);
static void sfe_mii_sync_sis900(struct gem_dev *);
/* nic operations */
static int sfe_reset_chip_sis900(struct gem_dev *);
static int sfe_reset_chip_dp83815(struct gem_dev *);
static int sfe_init_chip(struct gem_dev *);
static int sfe_start_chip(struct gem_dev *);
static int sfe_stop_chip(struct gem_dev *);
static int sfe_set_media(struct gem_dev *);
static int sfe_set_rx_filter_dp83815(struct gem_dev *);
static int sfe_set_rx_filter_sis900(struct gem_dev *);
static int sfe_get_stats(struct gem_dev *);
static int sfe_attach_chip(struct gem_dev *);
/* descriptor operations */
/* interrupt handler */
/* ======================================================== */
/* mapping attributes */
/* Data access requirements. */
static struct ddi_device_acc_attr sfe_dev_attr = {
};
/* On sparc, Buffers should be native endian for speed */
static struct ddi_device_acc_attr sfe_buf_attr = {
DDI_NEVERSWAP_ACC, /* native endianness */
};
static ddi_dma_attr_t sfe_dma_attr_buf = {
DMA_ATTR_V0, /* dma_attr_version */
0, /* dma_attr_addr_lo */
0xffffffffull, /* dma_attr_addr_hi */
0x00000fffull, /* dma_attr_count_max */
0, /* patched later */ /* dma_attr_align */
0x000003fc, /* dma_attr_burstsizes */
1, /* dma_attr_minxfer */
0x00000fffull, /* dma_attr_maxxfer */
0xffffffffull, /* dma_attr_seg */
0, /* patched later */ /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
static ddi_dma_attr_t sfe_dma_attr_desc = {
DMA_ATTR_V0, /* dma_attr_version */
16, /* dma_attr_addr_lo */
0xffffffffull, /* dma_attr_addr_hi */
0xffffffffull, /* dma_attr_count_max */
16, /* dma_attr_align */
0x000003fc, /* dma_attr_burstsizes */
1, /* dma_attr_minxfer */
0xffffffffull, /* dma_attr_maxxfer */
0xffffffffull, /* dma_attr_seg */
1, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
/* ======================================================== */
/*
* HW manipulation routines
*/
/* ======================================================== */
#define SFE_EEPROM_DELAY(dp) \
#define EE_CMD_READ 6
#define EE_CMD_SHIFT 6
static uint16_t
{
int eedi;
int i;
/* ensure de-assert chip select */
/* assert chip select */
for (i = 8; i >= 0; i--) {
/* make command */
/* send 1 bit */
}
ret = 0;
for (i = 0; i < 16; i++) {
/* Get 1 bit */
}
return (ret);
}
static boolean_t
{
int i;
/* first of all, clear MAC address buffer */
/* get bit 0 */
/* get bit 1 - 16 */
for (i = 0; i < 16; i++) {
}
/* get bit 17 - 32 */
for (i = 0; i < 16; i++) {
}
/* get bit 33 - 47 */
for (i = 0; i < 15; i++) {
}
return (B_TRUE);
}
static boolean_t
{
int i;
for (i = 0; i < ETHERADDRL/2; i++) {
}
return (B_TRUE);
}
static dev_info_t *
{
return (NULL);
}
/* check brothers */
do {
/* found */
return (cur_node);
}
/* check children */
return (ret);
}
}
/* not found */
return (NULL);
}
static dev_info_t *
{
}
/* Avoid undefined symbol for non IA architectures */
static boolean_t
{
int i;
int reg;
/* this is not IA architecture */
return (B_FALSE);
}
return (B_FALSE);
}
return (B_FALSE);
}
/* enable to access CMOS RAM */
for (i = 0; i < ETHERADDRL; i++) {
}
/* disable to access CMOS RAM */
return (B_TRUE);
}
static boolean_t
{
int i;
uint16_t v;
/* disable packet filtering before reading filter */
/* load MAC addr from filter data register */
for (i = 0; i < ETHERADDRL; i += 2) {
}
/* re-enable packet filtering */
return (B_TRUE);
}
static boolean_t
{
int i;
/* rise request signal to access EEPROM */
if (i > 200) {
/* failed to acquire eeprom */
goto x;
}
drv_usecwait(10);
}
x:
/* release EEPROM */
return (ret);
}
static int
{
int i;
/* invalidate mac addr cache */
/* inhibit interrupt */
drv_usecwait(10);
done = 0;
if (i > 1000) {
return (GEM_FAILURE);
}
drv_usecwait(10);
}
}
/* Configuration register: enable PCI parity */
val = 0;
/* what is this ? */
val |= CFG_RND_CNT;
}
return (GEM_SUCCESS);
}
static int
{
int i;
/* invalidate mac addr cache */
/* inhibit interrupts */
drv_usecwait(10);
if (i > 100) {
return (GEM_FAILURE);
}
drv_usecwait(10);
}
/* Configuration register: enable PCI parity */
return (GEM_SUCCESS);
}
static int
{
/* Configuration register: have been set up in sfe_chip_reset */
/* PCI test control register: do nothing */
/* Interrupt status register : do nothing */
/* Interrupt mask register: clear, but leave lp->our_intr_bits */
/* Enhanced PHY Access register (sis900): do nothing */
/* Transmit Descriptor Pointer register: base addr of TX ring */
/* Receive descriptor pointer register: base addr of RX ring */
return (GEM_SUCCESS);
}
static uint_t
{
}
#ifdef DEBUG_LEVEL
static void
{
int i;
int j;
#define WORDS_PER_LINE 4
for (j = 0; j < WORDS_PER_LINE; j++) {
}
}
}
#endif
static uint_t sfe_rf_perfect_base_dp83815[] = {
};
static int
{
int i;
int j;
#if DEBUG_LEVEL > 0
"!%s: adding mcast(%d) %02x:%02x:%02x:%02x:%02x:%02x",
}
#endif
/* disable rx filter */
return (GEM_SUCCESS);
}
/*
* Set Receive filter control register
*/
/* all broadcast, all multicast, all physical */
/* all broadcast, all multicast, physical for the chip */
/*
* Use multicast hash table,
* accept all broadcast and physical for the chip.
*/
}
} else {
/*
* Use pattern mach filter for multicast address,
* accept all broadcast and physical for the chip
*/
/* need to enable corresponding pattern registers */
}
#if DEBUG_LEVEL > 1
"!%s: mac %02x:%02x:%02x:%02x:%02x:%02x"
" cache %02x:%02x:%02x:%02x:%02x:%02x",
#endif
/*
* XXX - need to *disable* rx filter to load mac address for
* the chip. otherwise, we cannot setup rxfilter correctly.
*/
/* setup perfect match register for my station address */
for (i = 0; i < ETHERADDRL; i += 2) {
}
}
#if DEBUG_LEVEL > 3
/* clear pattern ram */
for (j = 0x200; j < 0x380; j += 2) {
}
#endif
if (mode & RFCR_APAT_DP83815) {
/* setup multicast address into pattern match registers */
for (i = 0; i < ETHERADDRL; i += 2) {
sfe_rf_perfect_base_dp83815[j] + i*2);
}
}
/* setup pattern count registers */
}
if (mode & RFCR_MHEN_DP83815) {
/* Load Multicast hash table */
for (i = 0; i < 32; i++) {
/* for DP83815, index is in byte */
}
}
#if DEBUG_LEVEL > 2
#endif
/* Set rx filter mode and enable rx filter */
return (GEM_SUCCESS);
}
static int
{
int i;
int hash_size;
int hash_shift;
/* disalbe rx filter */
return (GEM_SUCCESS);
}
/*
* determine hardware hash table size in word.
*/
hash_shift = 25;
hash_shift = 24;
}
/* Set Receive filter control register */
/* all broadcast, all multicast, all physical */
/* all broadcast, all multicast, physical for the chip */
} else {
/* all broadcast, physical for the chip */
}
/* make hash table */
uint_t h;
}
/* Disable Rx filter and load mac address */
for (i = 0; i < ETHERADDRL/2; i++) {
/* For sis900, index is in word */
}
}
/* Load Multicast hash table */
for (i = 0; i < hash_size; i++) {
/* For sis900, index is in word */
(RFADDR_MULTICAST_SIS900 + i) << RFCR_RFADDR_SHIFT_SIS900);
}
/* Load rx filter mode and enable rx filter */
return (GEM_SUCCESS);
}
static int
{
/*
* setup interrupt mask, which shouldn't include ISR_TOK
* to improve performance.
*/
/* enable interrupt */
}
/* Kick RX */
return (GEM_SUCCESS);
}
/*
* Stop nic core gracefully.
*/
static int
{
int i;
/*
* Although we inhibit interrupt here, we don't clear soft copy of
* interrupt mask to avoid bogus interrupts.
*/
/* stop TX and RX immediately */
done = 0;
if (i > 1000) {
/*
* As gem layer will call sfe_reset_chip(),
* we don't neet to reset futher
*/
return (GEM_FAILURE);
}
drv_usecwait(10);
}
return (GEM_SUCCESS);
}
/*
* Setup media mode
*/
static uint_t
static uint_t
{
int i;
if (burstsize > 256) {
/* choose 512 */
return (0);
}
for (i = 1; i < 8; i++) {
if (burstsize <= sfe_mxdma_value[i]) {
break;
}
}
return (i);
}
static int
{
#ifdef DEBUG_LEVEL
extern int gem_speed_value[];
#endif
/* initialize txcfg and rxcfg */
if (dp->full_duplex) {
}
if (dp->full_duplex) {
}
/* select txmxdma and rxmxdma, maxmum burst length */
#ifdef DEBUG_SIS900_EDB
#else
#endif
if (val) {
/*
* sis900 built-in cores:
* max burst length must be fixed to 64
*/
txmxdma = 64;
rxmxdma = 64;
} else {
/*
* sis900 pci chipset:
* the vendor recommended to fix max burst length
* to 512
*/
txmxdma = 512;
rxmxdma = 512;
}
} else {
/*
* NS dp83815/816:
*/
}
/* tx high water mark */
/* determine tx_fill_threshold accroding drain threshold */
/* tune txmxdma not to exceed tx_fill_threshold */
for (; ; ) {
/* normalize txmxdma requested */
break;
}
/* select new txmxdma */
}
/* encode rxmxdma, maxmum burst length for rx */
/* receive starting threshold - it have only 5bit-wide field */
"%s: %s: tx: drain:%d(rest %d) fill:%d mxdma:%d,"
" rx: drain:%d mxdma:%d",
}
/* Flow control */
switch (dp->flow_control) {
case FLOW_CONTROL_SYMMETRIC:
case FLOW_CONTROL_RX_PAUSE:
break;
default:
break;
}
switch (dp->flow_control) {
case FLOW_CONTROL_SYMMETRIC:
case FLOW_CONTROL_RX_PAUSE:
break;
default:
break;
}
}
return (GEM_SUCCESS);
}
static int
{
/* do nothing */
return (GEM_SUCCESS);
}
/*
* descriptor manipulations
*/
static int
{
#if DEBUG_LEVEL > 2
int i;
CONS "%s: time:%d %s seqnum: %d, slot %d, frags: %d flags: %llx",
for (i = 0; i < frags; i++) {
}
#endif
/*
* write tx descriptor in reversed order.
*/
#if DEBUG_LEVEL > 3
flags |= GEM_TXFLAG_INTR;
#endif
if (flags & GEM_TXFLAG_HEAD) {
mark &= ~CMDSTS_OWN;
}
return (frags);
}
static void
{
if (nslot > 1) {
}
/*
* Let the Transmit Buffer Manager Fill state machine active.
*/
if (dp->mac_active) {
}
}
static void
{
#if DEBUG_LEVEL > 2
int i;
"%s: %s seqnum: %d, slot %d, frags: %d",
for (i = 0; i < frags; i++) {
}
#endif
/* for the last slot of the packet */
}
static uint_t
{
int cols;
#ifdef DEBUG_LEVEL
int i;
#endif
/* check status of the last descriptor */
tdp = (void *)
/*
* Don't use LE_32() directly to refer tdp->d_cmdsts.
* It is not atomic for big endian cpus.
*/
if (status & CMDSTS_OWN) {
/*
* not yet transmitted
*/
/* workaround for tx hang */
dp->mac_active) {
}
return (0);
}
if (status & CMDSTS_MORE) {
/* XXX - the hardware problem but don't panic the system */
/* avoid lint bug for %b format string including 32nd bit */
"%s: tx status bits incorrect: slot:%d, status:0x%x",
}
#if DEBUG_LEVEL > 3
if (delay >= 50) {
}
#endif
#if DEBUG_LEVEL > 3
for (i = 0; i < nfrag-1; i++) {
uint32_t s;
int n;
s = LE_32(
((struct sfe_desc *)((void *)
ASSERT(s & CMDSTS_MORE);
ASSERT((s & CMDSTS_OWN) == 0);
}
#endif
/*
* collect statistics
*/
/* failed to transmit the packet */
if (status & CMDSTS_TFU) {
} else if (status & CMDSTS_CRS) {
} else if (status & CMDSTS_OWC) {
} else {
}
} else if (!dp->full_duplex) {
if (cols > 0) {
if (cols == 1) {
} else /* (cols > 1) */ {
}
}
}
return (GEM_TX_DONE);
}
static uint64_t
{
flag = GEM_RX_DONE;
/* Dont read ISR because we cannot ack only to rx interrupt. */
/*
* Don't use LE_32() directly to refer rdp->d_cmdsts.
* It is not atomic for big endian cpus.
*/
if ((status & CMDSTS_OWN) == 0) {
/*
* No more received packets because
* this buffer is owned by NIC.
*/
return (0);
}
#define RX_ERR_BITS \
if (status & RX_ERR_BITS) {
/*
* Packet with error received
*/
"received, buffer status: %b",
/* collect statistics information */
if (status & CMDSTS_RXO) {
} else if (status & CMDSTS_RUNT) {
} else if (status & CMDSTS_CRCE) {
} else {
}
return (flag | GEM_RX_ERR);
}
/*
* this packet was received without errors
*/
}
#if DEBUG_LEVEL > 10
{
int i;
for (i = 0; i < 60; i += 10) {
"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
}
bp += 10;
}
#endif
}
static void
{
/* don't clear d_link field, which have a valid pointer */
/* make a link to this from the previous descriptor */
tdp = (void *)
}
static void
{
/* don't clear d_link field, which have a valid pointer */
/* make a link to this from the previous descriptor */
rdp = (void *)
}
static void
{
}
static void
{
}
/*
* Device depend interrupt handler
*/
static uint_t
{
/* read reason and clear interrupt */
lp->isr_pended = 0;
/* we are not the interrupt source */
return (DDI_INTR_UNCLAIMED);
}
CONS "%s: time:%ld %s:called: isr:0x%b rx_active_head: %d",
if (!dp->mac_active) {
/* the device is going to stop */
lp->our_intr_bits = 0;
return (DDI_INTR_CLAIMED);
}
ISR_RXDESC | ISR_RXOK)) {
(void) gem_receive(dp);
CONS "%s: rx fifo overrun: isr %b",
/* no need restart rx */
}
if (isr & ISR_RXIDLE) {
CONS "%s: rx buffer ran out: isr %b",
/*
* Make RXDP points the head of receive
* buffer list.
*/
/* Restart the receive engine */
}
}
ISR_TXIDLE | ISR_TXOK)) {
/* need to reclaim tx buffers */
if (gem_tx_done(dp)) {
flags |= INTR_RESTART_TX;
}
/*
* XXX - tx error statistics will be counted in
* sfe_tx_desc_stat() and no need to restart tx on errors.
*/
}
}
if (need_to_reset) {
flags |= INTR_RESTART_TX;
}
return (DDI_INTR_CLAIMED | flags);
}
/* ======================================================== */
/*
* HW depend MII routine
*/
/* ======================================================== */
/*
* MII routines for NS DP83815
*/
static void
{
/* do nothing */
}
static uint16_t
{
}
static void
{
}
static int
{
if (srr == SRR_REV_DP83815CVNG) {
/*
* NS datasheet says that DP83815CVNG needs following
* registers to be patched for optimizing its performance.
* A report said that CRC errors on RX disappeared
* with the patch.
*/
CONS "%s: PHY patched %04x %04x %04x %04x %04x",
/*
* Additional packets for later chipset
*/
CONS "%s: PHY patched %04x %04x",
}
return (gem_mii_config_default(dp));
}
static int
{
/* try external phy first */
dp->mii_phy_addr = 0;
return (GEM_SUCCESS);
}
/* switch to internal phy */
/* wait for PHY reset */
return (gem_mii_probe_default(dp));
}
static int
{
/* select internal phy */
} else {
/* select external phy */
}
return (GEM_SUCCESS);
}
/*
* MII routines for SiS900
*/
static void
{
int i;
/* send 32 ONE's to make MII line idle */
for (i = 0; i < 32; i++) {
MDIO_DELAY(dp);
MDIO_DELAY(dp);
}
}
static int
{
/* Do chip depend setup */
/* workaround for ICS1893 PHY */
}
/*
* SiS 630E has bugs on default values
* of PHY registers
*/
}
return (gem_mii_config_default(dp));
}
static uint16_t
{
int i;
for (i = 31; i >= 18; i--) {
MDIO_DELAY(dp);
MDIO_DELAY(dp);
}
/* turn around cycle */
MDIO_DELAY(dp);
/* get response from PHY */
MDIO_DELAY(dp);
#if DEBUG_LEBEL > 0
}
#else
MDIO_DELAY(dp);
#endif
/* terminate response cycle */
MDIO_DELAY(dp);
ret = 0; /* to avoid lint errors */
for (i = 16; i > 0; i--) {
MDIO_DELAY(dp);
}
/* send two idle(Z) bits to terminate the read cycle */
for (i = 0; i < 2; i++) {
MDIO_DELAY(dp);
MDIO_DELAY(dp);
}
return (ret);
}
static void
{
int i;
for (i = 31; i >= 0; i--) {
MDIO_DELAY(dp);
MDIO_DELAY(dp);
}
/* send two idle(Z) bits to terminate the write cycle. */
for (i = 0; i < 2; i++) {
MDIO_DELAY(dp);
MDIO_DELAY(dp);
}
}
static void
{
int i;
/* it doesn't have a internal PHY */
return;
}
for (i = 1; i < 10; i++) {
}
/* for 630E, rule to determine the equalizer value */
rev == SIS630ET_900_REV) {
if (max_value < 5) {
eq_value =
min_value + 2);
} else if (15 <= max_value) {
eq_value =
min_value + 6);
}
}
/* for 630B0&B1, rule to determine the equalizer value */
else
if (rev == SIS630A_900_REV &&
if (max_value == 0) {
eq_value = 3;
} else {
}
}
/* write equalizer value and setting */
} else {
if (rev == SIS630A_900_REV &&
reg14h |= 0x0200;
}
}
}
/* ======================================================== */
/*
* OS depend (device driver) routine
*/
/* ======================================================== */
static void
{
int rev;
/* sis630E */
/* 630S, 630EA1, 630ET, 635A */
/* sis962 or later */
} else {
/* sis900 */
}
lp->bridge_revid = 0;
/*
* read host bridge revision
*/
"%s: cannot find host bridge (pci1039,630)",
return;
}
return;
}
lp->bridge_revid =
}
}
static int
{
/* setup chip-depend get_mac_address function */
} else {
}
/* read MAC address */
"!%s: %s: failed to get factory mac address"
" please specify a mac address in sfe.conf",
return (GEM_FAILURE);
}
}
return (GEM_SUCCESS);
}
static int
{
int unit;
const char *drv_name;
int i;
#ifdef DEBUG_LEVEL
#endif
struct chip_info *p;
/*
* Common codes after power-up
*/
goto err;
}
#ifdef DEBUG_LEVEL
#endif
#ifdef DEBUG_BUILT_IN_SIS900
#endif
for (i = 0, p = sfe_chiptbl; i < CHIPTABLESIZE; i++, p++) {
/* found */
goto chip_found;
}
}
/* Not found */
goto err;
/* ensure D0 mode */
switch (cmd) {
case DDI_RESUME:
return (gem_resume(dip));
case DDI_ATTACH:
CONS "%s%d: ilr 0x%08x, latency_timer:0x%02x",
/*
* Map in the device registers.
*/
"%s%d: ddi_regs_map_setup failed",
goto err;
}
/*
* construct gem configuration
*/
/* name */
/* consistency on tx and rx */
/* map attributes */
/* dma attributes */
/* time out parameters */
if (p->chip_type == CHIPTYPE_DP83815) {
/* workaround for tx hang */
}
/* MII timeout parameters */
gcp->gc_mii_an_wait = 0;
/* setting for general PHY */
gcp->gc_mii_an_delay = 0;
/* I/O methods */
/* mac operation */
if (p->chip_type == CHIPTYPE_DP83815) {
} else {
}
#ifdef USE_MULTICAST_HASHTBL
#endif
if (p->chip_type == CHIPTYPE_DP83815) {
} else {
}
/* descriptor operation */
/* mii operations */
if (p->chip_type == CHIPTYPE_DP83815) {
} else {
}
lp->our_intr_bits = 0;
lp->isr_pended = 0;
goto err_freelp;
}
return (DDI_SUCCESS);
err:
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
static int
{
switch (cmd) {
case DDI_SUSPEND:
return (gem_suspend(dip));
case DDI_DETACH:
return (gem_do_detach(dip));
}
return (DDI_FAILURE);
}
/* ======================================================== */
/*
* OS depend (loadable streams driver) routine
*/
/* ======================================================== */
&mod_driverops, /* Type of module. This one is a driver */
ident,
&sfe_ops, /* driver ops */
};
static struct modlinkage modlinkage = {
};
/* ======================================================== */
/*
* Loadable module support
*/
/* ======================================================== */
int
_init(void)
{
int status;
if (status != DDI_SUCCESS) {
}
return (status);
}
/*
* _fini : done
*/
int
_fini(void)
{
int status;
if (status == DDI_SUCCESS) {
}
return (status);
}
int
{
}