f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * sfe.c : DP83815/DP83816/SiS900 Fast Ethernet MAC driver for Solaris
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff *
23d366e350386ec109bfa9b2cf91225729a1a26bduboff * Copyright (c) 2002-2008 Masayuki Murayama. All rights reserved.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff *
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Redistribution and use in source and binary forms, with or without
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * modification, are permitted provided that the following conditions are met:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff *
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * 1. Redistributions of source code must retain the above copyright notice,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * this list of conditions and the following disclaimer.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff *
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * 2. Redistributions in binary form must reproduce the above copyright notice,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * this list of conditions and the following disclaimer in the documentation
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * and/or other materials provided with the distribution.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff *
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * 3. Neither the name of the author nor the names of its contributors may be
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * used to endorse or promote products derived from this software without
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * specific prior written permission.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff *
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * DAMAGE.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
d67944fbe3fa0b31893a7116a09b0718eecf6078Scott Rotondo/* Avoid undefined symbol for non IA architectures */
d67944fbe3fa0b31893a7116a09b0718eecf6078Scott Rotondo#pragma weak inb
d67944fbe3fa0b31893a7116a09b0718eecf6078Scott Rotondo#pragma weak outb
d67944fbe3fa0b31893a7116a09b0718eecf6078Scott Rotondo
193974072f41a843678abf5f61979c748687e66bSherry Moore/*
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
193974072f41a843678abf5f61979c748687e66bSherry Moore * Use is subject to license terms.
193974072f41a843678abf5f61979c748687e66bSherry Moore */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * System Header files.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/types.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/conf.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/debug.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/kmem.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/modctl.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/errno.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/ddi.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/sunddi.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/byteorder.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/ethernet.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include <sys/pci.h>
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include "sfe_mii.h"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include "sfe_util.h"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#include "sfereg.h"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moorechar ident[] = "sis900/dp83815 driver v" "2.6.1t30os";
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* Debugging support */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef DEBUG_LEVEL
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_debug = DEBUG_LEVEL;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 4
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define CONS "^"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#else
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define CONS "!"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define DPRINTF(n, args) if (sfe_debug > (n)) cmn_err args
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#else
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define CONS "!"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define DPRINTF(n, args)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Useful macros and typedefs
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define ONESEC (drv_usectohz(1*1000000))
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define ROUNDUP2(x, a) (((x) + (a) - 1) & ~((a) - 1))
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Our configuration
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define MAXTXFRAGS 1
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define MAXRXFRAGS 1
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifndef TX_BUF_SIZE
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define TX_BUF_SIZE 64
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifndef TX_RING_SIZE
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if MAXTXFRAGS == 1
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define TX_RING_SIZE TX_BUF_SIZE
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#else
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define TX_RING_SIZE (TX_BUF_SIZE * 4)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifndef RX_BUF_SIZE
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define RX_BUF_SIZE 256
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifndef RX_RING_SIZE
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define RX_RING_SIZE RX_BUF_SIZE
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define OUR_INTR_BITS \
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (ISR_DPERR | ISR_SSERR | ISR_RMABT | ISR_RTABT | ISR_RXSOVR | \
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ISR_TXURN | ISR_TXDESC | ISR_TXERR | \
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ISR_RXORN | ISR_RXIDLE | ISR_RXOK | ISR_RXERR)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define USE_MULTICAST_HASHTBL
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_tx_copy_thresh = 256;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_rx_copy_thresh = 256;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* special PHY registers for SIS900 */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define MII_CONFIG1 0x0010
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define MII_CONFIG2 0x0011
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define MII_MASK 0x0013
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define MII_RESV 0x0014
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define PHY_MASK 0xfffffff0
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define PHY_SIS900_INTERNAL 0x001d8000
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define PHY_ICS1893 0x0015f440
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define SFE_DESC_SIZE 16 /* including pads rounding up to power of 2 */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Supported chips
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstruct chip_info {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t venid;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t devid;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff char *chip_name;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int chip_type;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define CHIPTYPE_DP83815 0
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define CHIPTYPE_SIS900 1
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Chip dependent MAC state
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstruct sfe_dev {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* misc HW information */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct chip_info *chip;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t our_intr_bits;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t isr_pended;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t cr;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t tx_drain_threshold;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t tx_fill_threshold;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t rx_drain_threshold;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t rx_fill_threshold;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t revid; /* revision from PCI configuration */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff boolean_t (*get_mac_addr)(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t mac_addr[ETHERADDRL];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t bridge_revid;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Hardware information
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstruct chip_info sfe_chiptbl[] = {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff { 0x1039, 0x0900, "SiS900", CHIPTYPE_SIS900, },
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff { 0x100b, 0x0020, "DP83815/83816", CHIPTYPE_DP83815, },
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff { 0x1039, 0x7016, "SiS7016", CHIPTYPE_SIS900, },
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define CHIPTABLESIZE (sizeof (sfe_chiptbl)/sizeof (struct chip_info))
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* mii operations */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_mii_sync_dp83815(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_mii_sync_sis900(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint16_t sfe_mii_read_dp83815(struct gem_dev *, uint_t);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint16_t sfe_mii_read_sis900(struct gem_dev *, uint_t);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_mii_write_dp83815(struct gem_dev *, uint_t, uint16_t);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_mii_write_sis900(struct gem_dev *, uint_t, uint16_t);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_set_eq_sis630(struct gem_dev *dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* nic operations */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_reset_chip_sis900(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_reset_chip_dp83815(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_init_chip(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_start_chip(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_stop_chip(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_set_media(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_set_rx_filter_dp83815(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_set_rx_filter_sis900(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_get_stats(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_attach_chip(struct gem_dev *);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* descriptor operations */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int sfe_tx_desc_write(struct gem_dev *dp, int slot,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_dma_cookie_t *dmacookie, int frags, uint64_t flags);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_tx_start(struct gem_dev *dp, int startslot, int nslot);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_rx_desc_write(struct gem_dev *dp, int slot,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_dma_cookie_t *dmacookie, int frags);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint_t sfe_tx_desc_stat(struct gem_dev *dp, int slot, int ndesc);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint64_t sfe_rx_desc_stat(struct gem_dev *dp, int slot, int ndesc);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_tx_desc_init(struct gem_dev *dp, int slot);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_rx_desc_init(struct gem_dev *dp, int slot);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_tx_desc_clean(struct gem_dev *dp, int slot);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void sfe_rx_desc_clean(struct gem_dev *dp, int slot);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* interrupt handler */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint_t sfe_interrupt(struct gem_dev *dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* mapping attributes */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* Data access requirements. */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic struct ddi_device_acc_attr sfe_dev_attr = {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DDI_DEVICE_ATTR_V0,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DDI_STRUCTURE_LE_ACC,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DDI_STRICTORDER_ACC
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* On sparc, Buffers should be native endian for speed */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic struct ddi_device_acc_attr sfe_buf_attr = {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DDI_DEVICE_ATTR_V0,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DDI_NEVERSWAP_ACC, /* native endianness */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DDI_STRICTORDER_ACC
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic ddi_dma_attr_t sfe_dma_attr_buf = {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DMA_ATTR_V0, /* dma_attr_version */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0, /* dma_attr_addr_lo */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0xffffffffull, /* dma_attr_addr_hi */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0x00000fffull, /* dma_attr_count_max */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0, /* patched later */ /* dma_attr_align */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0x000003fc, /* dma_attr_burstsizes */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 1, /* dma_attr_minxfer */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0x00000fffull, /* dma_attr_maxxfer */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0xffffffffull, /* dma_attr_seg */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0, /* patched later */ /* dma_attr_sgllen */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 1, /* dma_attr_granular */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0 /* dma_attr_flags */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic ddi_dma_attr_t sfe_dma_attr_desc = {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DMA_ATTR_V0, /* dma_attr_version */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 16, /* dma_attr_addr_lo */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0xffffffffull, /* dma_attr_addr_hi */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0xffffffffull, /* dma_attr_count_max */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 16, /* dma_attr_align */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0x000003fc, /* dma_attr_burstsizes */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 1, /* dma_attr_minxfer */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0xffffffffull, /* dma_attr_maxxfer */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0xffffffffull, /* dma_attr_seg */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 1, /* dma_attr_sgllen */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 1, /* dma_attr_granular */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff 0 /* dma_attr_flags */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffuint32_t sfe_use_pcimemspace = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * HW manipulation routines
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define SFE_EEPROM_DELAY(dp) \
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff { (void) INL(dp, EROMAR); (void) INL(dp, EROMAR); }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define EE_CMD_READ 6
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define EE_CMD_SHIFT 6
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint16_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_read_eeprom(struct gem_dev *dp, uint_t offset)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int eedi;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t ret;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* ensure de-assert chip select */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, EROMAR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff SFE_EEPROM_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, EROMAR, EROMAR_EESK);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff SFE_EEPROM_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* assert chip select */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff offset |= EE_CMD_READ << EE_CMD_SHIFT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 8; i >= 0; i--) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* make command */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff eedi = ((offset >> i) & 1) << EROMAR_EEDI_SHIFT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* send 1 bit */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, EROMAR, EROMAR_EECS | eedi);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff SFE_EEPROM_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, EROMAR, EROMAR_EECS | eedi | EROMAR_EESK);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff SFE_EEPROM_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, EROMAR, EROMAR_EECS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ret = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < 16; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Get 1 bit */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, EROMAR, EROMAR_EECS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff SFE_EEPROM_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, EROMAR, EROMAR_EECS | EROMAR_EESK);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff SFE_EEPROM_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ret = (ret << 1) | ((INL(dp, EROMAR) >> EROMAR_EEDO_SHIFT) & 1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, EROMAR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff SFE_EEPROM_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (ret);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#undef SFE_EEPROM_DELAY
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic boolean_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_get_mac_addr_dp83815(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t *mac;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t val;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define BITSET(p, ix, v) (p)[(ix)/8] |= ((v) ? 1 : 0) << ((ix) & 0x7)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mac = dp->dev_addr.ether_addr_octet;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* first of all, clear MAC address buffer */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bzero(mac, ETHERADDRL);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* get bit 0 */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = sfe_read_eeprom(dp, 0x6);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff BITSET(mac, 0, val & 1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* get bit 1 - 16 */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = sfe_read_eeprom(dp, 0x7);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < 16; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff BITSET(mac, 1 + i, val & (1 << (15 - i)));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* get bit 17 - 32 */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = sfe_read_eeprom(dp, 0x8);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < 16; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff BITSET(mac, 17 + i, val & (1 << (15 - i)));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* get bit 33 - 47 */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = sfe_read_eeprom(dp, 0x9);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < 15; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff BITSET(mac, 33 + i, val & (1 << (15 - i)));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (B_TRUE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#undef BITSET
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic boolean_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_get_mac_addr_sis900(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t val;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t *mac;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mac = dp->dev_addr.ether_addr_octet;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < ETHERADDRL/2; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = sfe_read_eeprom(dp, 0x8 + i);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff *mac++ = (uint8_t)val;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff *mac++ = (uint8_t)(val >> 8);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (B_TRUE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic dev_info_t *
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_search_pci_dev_subr(dev_info_t *cur_node, int vendor_id, int device_id)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dev_info_t *child_id;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dev_info_t *ret;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int vid, did;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (cur_node == NULL) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (NULL);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* check brothers */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff do {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff vid = ddi_prop_get_int(DDI_DEV_T_ANY, cur_node,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DDI_PROP_DONTPASS, "vendor-id", -1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff did = ddi_prop_get_int(DDI_DEV_T_ANY, cur_node,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DDI_PROP_DONTPASS, "device-id", -1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (vid == vendor_id && did == device_id) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* found */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (cur_node);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* check children */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((child_id = ddi_get_child(cur_node)) != NULL) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((ret = sfe_search_pci_dev_subr(child_id,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff vendor_id, device_id)) != NULL) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (ret);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } while ((cur_node = ddi_get_next_sibling(cur_node)) != NULL);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* not found */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (NULL);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic dev_info_t *
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_search_pci_dev(int vendor_id, int device_id)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (sfe_search_pci_dev_subr(ddi_root_node(), vendor_id, device_id));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic boolean_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_get_mac_addr_sis630e(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dev_info_t *isa_bridge;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_acc_handle_t isa_handle;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int reg;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (inb == NULL || outb == NULL) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* this is not IA architecture */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (B_FALSE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((isa_bridge = sfe_search_pci_dev(0x1039, 0x8)) == NULL) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN, "%s: failed to find isa-bridge pci1039,8",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (B_FALSE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (pci_config_setup(isa_bridge, &isa_handle) != DDI_SUCCESS) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN, "%s: ddi_regs_map_setup failed",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (B_FALSE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* enable to access CMOS RAM */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff reg = pci_config_get8(isa_handle, 0x48);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_put8(isa_handle, 0x48, reg | 0x40);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < ETHERADDRL; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff outb(0x70, 0x09 + i);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->dev_addr.ether_addr_octet[i] = inb(0x71);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* disable to access CMOS RAM */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_put8(isa_handle, 0x48, reg);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_teardown(&isa_handle);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (B_TRUE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic boolean_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_get_mac_addr_sis635(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t rfcr;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t v;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rfcr = INL(dp, RFCR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, lp->cr | CR_RELOAD);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, lp->cr);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* disable packet filtering before reading filter */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, rfcr & ~RFCR_RFEN);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* load MAC addr from filter data register */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < ETHERADDRL; i += 2) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (RFADDR_MAC_SIS900 + (i/2)) << RFCR_RFADDR_SHIFT_SIS900);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff v = INL(dp, RFDR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->dev_addr.ether_addr_octet[i] = (uint8_t)v;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->dev_addr.ether_addr_octet[i+1] = (uint8_t)(v >> 8);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* re-enable packet filtering */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, rfcr | RFCR_RFEN);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (B_TRUE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic boolean_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_get_mac_addr_sis962(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff boolean_t ret;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ret = B_FALSE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* rise request signal to access EEPROM */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, EROMAR_EEREQ);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; (INL(dp, MEAR) & EROMAR_EEGNT) == 0; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (i > 200) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* failed to acquire eeprom */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_NOTE,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff CONS "%s: failed to access eeprom", dp->name);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff goto x;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_usecwait(10);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ret = sfe_get_mac_addr_sis900(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffx:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* release EEPROM */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, EROMAR_EEDONE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (ret);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_reset_chip_sis900(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t done;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t val;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS "%s: %s called", dp->name, __func__));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* invalidate mac addr cache */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bzero(lp->mac_addr, sizeof (lp->mac_addr));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->cr = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* inhibit interrupt */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, IMR, 0);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff lp->isr_pended |= INL(dp, ISR) & lp->our_intr_bits;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
915ebf8da9f4ef3e7b2e34dd367f64d358a628d9Alan Duboff OUTLINL(dp, RFCR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, CR_RST | CR_TXR | CR_RXR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_usecwait(10);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff done = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; done != (ISR_TXRCMP | ISR_RXRCMP); i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (i > 1000) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN, "%s: chip reset timeout", dp->name);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_FAILURE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff done |= INL(dp, ISR) & (ISR_TXRCMP | ISR_RXRCMP);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_usecwait(10);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->revid == SIS630ET_900_REV) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->cr |= CR_ACCESSMODE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, lp->cr | INL(dp, CR));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Configuration register: enable PCI parity */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, INL(dp, CFG), CFG_BITS_SIS900));
23d366e350386ec109bfa9b2cf91225729a1a26bduboff val = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->revid >= SIS635A_900_REV ||
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->revid == SIS900B_900_REV) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* what is this ? */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val |= CFG_RND_CNT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CFG, val);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b", dp->name,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INL(dp, CFG), CFG_BITS_SIS900));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_reset_chip_dp83815(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t val;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS "%s: %s called", dp->name, __func__));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* invalidate mac addr cache */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bzero(lp->mac_addr, sizeof (lp->mac_addr));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->cr = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* inhibit interrupts */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, IMR, 0);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff lp->isr_pended |= INL(dp, ISR) & lp->our_intr_bits;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, CR_RST);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_usecwait(10);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; INL(dp, CR) & CR_RST; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (i > 100) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN, "!%s: chip reset timeout", dp->name);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_FAILURE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_usecwait(10);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT, "!%s: chip reset in %duS", dp->name, i*10));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CCSR, CCSR_PMESTS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CCSR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Configuration register: enable PCI parity */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, INL(dp, CFG), CFG_BITS_DP83815));
23d366e350386ec109bfa9b2cf91225729a1a26bduboff val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, CFG, val | CFG_PAUSE_ADV);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b", dp->name,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INL(dp, CFG), CFG_BITS_DP83815));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_init_chip(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Configuration register: have been set up in sfe_chip_reset */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* PCI test control register: do nothing */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Interrupt status register : do nothing */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Interrupt mask register: clear, but leave lp->our_intr_bits */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, IMR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Enhanced PHY Access register (sis900): do nothing */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Transmit Descriptor Pointer register: base addr of TX ring */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, TXDP, dp->tx_ring_dma);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Receive descriptor pointer register: base addr of RX ring */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RXDP, dp->rx_ring_dma);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mcast_hash(struct gem_dev *dp, uint8_t *addr)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (gem_ether_crc_be(addr, ETHERADDRL));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef DEBUG_LEVEL
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_rxfilter_dump(struct gem_dev *dp, int start, int end)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int j;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t ram[0x10];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT, "!%s: rx filter ram dump:", dp->name);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define WORDS_PER_LINE 4
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = start; i < end; i += WORDS_PER_LINE*2) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (j = 0; j < WORDS_PER_LINE; j++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, RFADDR_MAC_DP83815 + i + j*2);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ram[j] = INL(dp, RFDR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT, "!0x%02x: 0x%04x 0x%04x 0x%04x 0x%04x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff i, ram[0], ram[1], ram[2], ram[3]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#undef WORDS_PER_LINE
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint_t sfe_rf_perfect_base_dp83815[] = {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff RFADDR_PMATCH0_DP83815,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff RFADDR_PMATCH1_DP83815,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff RFADDR_PMATCH2_DP83815,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff RFADDR_PMATCH3_DP83815,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_set_rx_filter_dp83815(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int j;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t mode;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t *mac = dp->cur_addr.ether_addr_octet;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t hash_tbl[32];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(1, (CE_CONT, CONS "%s: %s: called, mc_count:%d, mode:0x%b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__, dp->mc_count, dp->rxmode, RXMODE_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 0
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < dp->mc_count; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "!%s: adding mcast(%d) %02x:%02x:%02x:%02x:%02x:%02x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, i,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->mc_list[i].addr.ether_addr_octet[0],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->mc_list[i].addr.ether_addr_octet[1],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->mc_list[i].addr.ether_addr_octet[2],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->mc_list[i].addr.ether_addr_octet[3],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->mc_list[i].addr.ether_addr_octet[4],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->mc_list[i].addr.ether_addr_octet[5]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((dp->rxmode & RXMODE_ENABLE) == 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* disable rx filter */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Set Receive filter control register
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (dp->rxmode & RXMODE_PROMISC) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* all broadcast, all multicast, all physical */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mode = RFCR_AAB | RFCR_AAM | RFCR_AAP;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if ((dp->rxmode & RXMODE_ALLMULTI) || dp->mc_count > 16*32/2) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* all broadcast, all multicast, physical for the chip */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mode = RFCR_AAB | RFCR_AAM | RFCR_APM_DP83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (dp->mc_count > 4) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Use multicast hash table,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * accept all broadcast and physical for the chip.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mode = RFCR_AAB | RFCR_MHEN_DP83815 | RFCR_APM_DP83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bzero(hash_tbl, sizeof (hash_tbl));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < dp->mc_count; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff j = dp->mc_list[i].hash >> (32 - 9);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff hash_tbl[j / 16] |= 1 << (j % 16);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Use pattern mach filter for multicast address,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * accept all broadcast and physical for the chip
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* need to enable corresponding pattern registers */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mode = RFCR_AAB | RFCR_APM_DP83815 |
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (((1 << dp->mc_count) - 1) << RFCR_APAT_SHIFT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 1
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "!%s: mac %02x:%02x:%02x:%02x:%02x:%02x"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff " cache %02x:%02x:%02x:%02x:%02x:%02x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->mac_addr[0], lp->mac_addr[1],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->mac_addr[2], lp->mac_addr[3],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->mac_addr[4], lp->mac_addr[5]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (bcmp(mac, lp->mac_addr, ETHERADDRL) != 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * XXX - need to *disable* rx filter to load mac address for
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * the chip. otherwise, we cannot setup rxfilter correctly.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* setup perfect match register for my station address */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < ETHERADDRL; i += 2) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, RFADDR_MAC_DP83815 + i);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFDR, (mac[i+1] << 8) | mac[i]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bcopy(mac, lp->mac_addr, ETHERADDRL);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 3
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* clear pattern ram */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (j = 0x200; j < 0x380; j += 2) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, j);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFDR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (mode & RFCR_APAT_DP83815) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* setup multicast address into pattern match registers */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (j = 0; j < dp->mc_count; j++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mac = &dp->mc_list[j].addr.ether_addr_octet[0];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < ETHERADDRL; i += 2) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff sfe_rf_perfect_base_dp83815[j] + i*2);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFDR, (mac[i+1] << 8) | mac[i]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* setup pattern count registers */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, RFADDR_PCOUNT01_DP83815);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFDR, (ETHERADDRL << 8) | ETHERADDRL);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, RFADDR_PCOUNT23_DP83815);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFDR, (ETHERADDRL << 8) | ETHERADDRL);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (mode & RFCR_MHEN_DP83815) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Load Multicast hash table */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < 32; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* for DP83815, index is in byte */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, RFADDR_MULTICAST_DP83815 + i*2);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFDR, hash_tbl[i]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 2
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff sfe_rxfilter_dump(dp, 0, 0x10);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff sfe_rxfilter_dump(dp, 0x200, 0x380);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Set rx filter mode and enable rx filter */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RFCR, RFCR_RFEN | mode);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_set_rx_filter_sis900(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t mode;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t hash_tbl[16];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t *mac = dp->cur_addr.ether_addr_octet;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int hash_size;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int hash_shift;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((dp->rxmode & RXMODE_ENABLE) == 0) {
915ebf8da9f4ef3e7b2e34dd367f64d358a628d9Alan Duboff /* disable rx filter */
915ebf8da9f4ef3e7b2e34dd367f64d358a628d9Alan Duboff OUTLINL(dp, RFCR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * determine hardware hash table size in word.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff hash_shift = 25;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->revid >= SIS635A_900_REV || lp->revid == SIS900B_900_REV) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff hash_shift = 24;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff hash_size = (1 << (32 - hash_shift)) / 16;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bzero(hash_tbl, sizeof (hash_tbl));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Set Receive filter control register */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (dp->rxmode & RXMODE_PROMISC) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* all broadcast, all multicast, all physical */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mode = RFCR_AAB | RFCR_AAM | RFCR_AAP;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if ((dp->rxmode & RXMODE_ALLMULTI) ||
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->mc_count > hash_size*16/2) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* all broadcast, all multicast, physical for the chip */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mode = RFCR_AAB | RFCR_AAM;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* all broadcast, physical for the chip */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mode = RFCR_AAB;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* make hash table */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < dp->mc_count; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t h;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff h = dp->mc_list[i].hash >> hash_shift;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff hash_tbl[h / 16] |= 1 << (h % 16);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (bcmp(mac, lp->mac_addr, ETHERADDRL) != 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Disable Rx filter and load mac address */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < ETHERADDRL/2; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* For sis900, index is in word */
915ebf8da9f4ef3e7b2e34dd367f64d358a628d9Alan Duboff OUTLINL(dp, RFCR,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (RFADDR_MAC_SIS900+i) << RFCR_RFADDR_SHIFT_SIS900);
915ebf8da9f4ef3e7b2e34dd367f64d358a628d9Alan Duboff OUTLINL(dp, RFDR, (mac[i*2+1] << 8) | mac[i*2]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bcopy(mac, lp->mac_addr, ETHERADDRL);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Load Multicast hash table */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < hash_size; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* For sis900, index is in word */
915ebf8da9f4ef3e7b2e34dd367f64d358a628d9Alan Duboff OUTLINL(dp, RFCR,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (RFADDR_MULTICAST_SIS900 + i) << RFCR_RFADDR_SHIFT_SIS900);
915ebf8da9f4ef3e7b2e34dd367f64d358a628d9Alan Duboff OUTLINL(dp, RFDR, hash_tbl[i]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Load rx filter mode and enable rx filter */
915ebf8da9f4ef3e7b2e34dd367f64d358a628d9Alan Duboff OUTLINL(dp, RFCR, RFCR_RFEN | mode);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_start_chip(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * setup interrupt mask, which shouldn't include ISR_TOK
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * to improve performance.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->our_intr_bits = OUR_INTR_BITS;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* enable interrupt */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((dp->misc_flag & GEM_NOINTR) == 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, IER, 1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, IMR, lp->our_intr_bits);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Kick RX */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, lp->cr | CR_RXE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Stop nic core gracefully.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_stop_chip(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t done;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t val;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Although we inhibit interrupt here, we don't clear soft copy of
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * interrupt mask to avoid bogus interrupts.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, IMR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* stop TX and RX immediately */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, lp->cr | CR_TXR | CR_RXR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff done = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; done != (ISR_RXRCMP | ISR_TXRCMP); i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (i > 1000) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * As gem layer will call sfe_reset_chip(),
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * we don't neet to reset futher
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_NOTE, "!%s: %s: Tx/Rx reset timeout",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_FAILURE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
23d366e350386ec109bfa9b2cf91225729a1a26bduboff val = INL(dp, ISR);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff done |= val & (ISR_RXRCMP | ISR_TXRCMP);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff lp->isr_pended |= val & lp->our_intr_bits;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_usecwait(10);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore#ifndef __sparc
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore/*
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * Stop nic core gracefully for quiesce
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore */
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moorestatic int
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Mooresfe_stop_chip_quiesce(struct gem_dev *dp)
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore{
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore struct sfe_dev *lp = dp->private;
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore uint32_t done;
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore int i;
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore uint32_t val;
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore /*
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * Although we inhibit interrupt here, we don't clear soft copy of
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * interrupt mask to avoid bogus interrupts.
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore */
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore OUTL(dp, IMR, 0);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore /* stop TX and RX immediately */
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore OUTL(dp, CR, CR_TXR | CR_RXR);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore done = 0;
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore for (i = 0; done != (ISR_RXRCMP | ISR_TXRCMP); i++) {
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore if (i > 1000) {
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore /*
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * As gem layer will call sfe_reset_chip(),
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * we don't neet to reset futher
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore */
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore return (DDI_FAILURE);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore }
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore val = INL(dp, ISR);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore done |= val & (ISR_RXRCMP | ISR_TXRCMP);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore lp->isr_pended |= val & lp->our_intr_bits;
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore drv_usecwait(10);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore }
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore return (DDI_SUCCESS);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore}
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore#endif
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Setup media mode
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mxdma_value[] = { 512, 4, 8, 16, 32, 64, 128, 256, };
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_encode_mxdma(uint_t burstsize)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (burstsize > 256) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* choose 512 */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 1; i < 8; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (burstsize <= sfe_mxdma_value[i]) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff break;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (i);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_set_media(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t txcfg;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t rxcfg;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t pcr;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t val;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t txmxdma;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t rxmxdma;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef DEBUG_LEVEL
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff extern int gem_speed_value[];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: %s: %s duplex, %d Mbps",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->full_duplex ? "full" : "half", gem_speed_value[dp->speed]));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* initialize txcfg and rxcfg */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txcfg = TXCFG_ATP;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (dp->full_duplex) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txcfg |= (TXCFG_CSI | TXCFG_HBI);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
23d366e350386ec109bfa9b2cf91225729a1a26bduboff rxcfg = RXCFG_AEP | RXCFG_ARP;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (dp->full_duplex) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rxcfg |= RXCFG_ATX;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* select txmxdma and rxmxdma, maxmum burst length */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->chip->chip_type == CHIPTYPE_SIS900) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef DEBUG_SIS900_EDB
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = CFG_EDB_MASTER;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#else
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = INL(dp, CFG) & CFG_EDB_MASTER;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (val) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * sis900 built-in cores:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * max burst length must be fixed to 64
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txmxdma = 64;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rxmxdma = 64;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * sis900 pci chipset:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * the vendor recommended to fix max burst length
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * to 512
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txmxdma = 512;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rxmxdma = 512;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * NS dp83815/816:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * use user defined or default for tx/rx max burst length
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txmxdma = max(dp->txmaxdma, 256);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rxmxdma = max(dp->rxmaxdma, 256);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* tx high water mark */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->tx_drain_threshold = ROUNDUP2(dp->txthr, TXCFG_FIFO_UNIT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* determine tx_fill_threshold accroding drain threshold */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->tx_fill_threshold =
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff TXFIFOSIZE - lp->tx_drain_threshold - TXCFG_FIFO_UNIT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* tune txmxdma not to exceed tx_fill_threshold */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (; ; ) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* normalize txmxdma requested */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = sfe_encode_mxdma(txmxdma);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txmxdma = sfe_mxdma_value[val];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (txmxdma <= lp->tx_fill_threshold) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff break;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* select new txmxdma */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txmxdma = txmxdma / 2;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txcfg |= val << TXCFG_MXDMA_SHIFT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* encode rxmxdma, maxmum burst length for rx */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = sfe_encode_mxdma(rxmxdma);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff rxcfg |= val << RXCFG_MXDMA_SHIFT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rxmxdma = sfe_mxdma_value[val];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* receive starting threshold - it have only 5bit-wide field */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff val = ROUNDUP2(max(dp->rxthr, ETHERMIN), RXCFG_FIFO_UNIT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->rx_drain_threshold =
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff min(val, (RXCFG_DRTH >> RXCFG_DRTH_SHIFT) * RXCFG_FIFO_UNIT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "%s: %s: tx: drain:%d(rest %d) fill:%d mxdma:%d,"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff " rx: drain:%d mxdma:%d",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->tx_drain_threshold, TXFIFOSIZE - lp->tx_drain_threshold,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->tx_fill_threshold, txmxdma,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->rx_drain_threshold, rxmxdma));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ASSERT(lp->tx_drain_threshold < 64*TXCFG_FIFO_UNIT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ASSERT(lp->tx_fill_threshold < 64*TXCFG_FIFO_UNIT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ASSERT(lp->rx_drain_threshold < 32*RXCFG_FIFO_UNIT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txcfg |= ((lp->tx_fill_threshold/TXCFG_FIFO_UNIT) << TXCFG_FLTH_SHIFT)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff | (lp->tx_drain_threshold/TXCFG_FIFO_UNIT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, TXCFG, txcfg);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rxcfg |= ((lp->rx_drain_threshold/RXCFG_FIFO_UNIT) << RXCFG_DRTH_SHIFT);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->chip->chip_type == CHIPTYPE_DP83815) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rxcfg |= RXCFG_ALP_DP83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RXCFG, rxcfg);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT, CONS "%s: %s: txcfg:%b rxcfg:%b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff txcfg, TXCFG_BITS, rxcfg, RXCFG_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Flow control */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->chip->chip_type == CHIPTYPE_DP83815) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pcr = INL(dp, PCR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff switch (dp->flow_control) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff case FLOW_CONTROL_SYMMETRIC:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff case FLOW_CONTROL_RX_PAUSE:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, PCR, pcr | PCR_PSEN | PCR_PS_MCAST);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff break;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff default:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, PCR,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pcr & ~(PCR_PSEN | PCR_PS_MCAST | PCR_PS_DA));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff break;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: PCR: %b", dp->name,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INL(dp, PCR), PCR_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (lp->chip->chip_type == CHIPTYPE_SIS900) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff switch (dp->flow_control) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff case FLOW_CONTROL_SYMMETRIC:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff case FLOW_CONTROL_RX_PAUSE:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, FLOWCTL, FLOWCTL_FLOWEN);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff break;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff default:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, FLOWCTL, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff break;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: FLOWCTL: %b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, INL(dp, FLOWCTL), FLOWCTL_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_get_stats(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* do nothing */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * descriptor manipulations
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_tx_desc_write(struct gem_dev *dp, int slot,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_dma_cookie_t *dmacookie, int frags, uint64_t flags)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t mark;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *tdp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_dma_cookie_t *dcp;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t tmp0;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff#if DEBUG_LEVEL > 2
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff CONS "%s: time:%d %s seqnum: %d, slot %d, frags: %d flags: %llx",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, ddi_get_lbolt(), __func__,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->tx_desc_tail, slot, frags, flags);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < frags; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT, CONS "%d: addr: 0x%x, len: 0x%x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff i, dmacookie[i].dmac_address, dmacookie[i].dmac_size);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * write tx descriptor in reversed order.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 3
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff flags |= GEM_TXFLAG_INTR;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mark = (flags & GEM_TXFLAG_INTR)
23d366e350386ec109bfa9b2cf91225729a1a26bduboff ? (CMDSTS_OWN | CMDSTS_INTR) : CMDSTS_OWN;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ASSERT(frags == 1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dcp = &dmacookie[0];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (flags & GEM_TXFLAG_HEAD) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff mark &= ~CMDSTS_OWN;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp = (void *)&dp->tx_ring[SFE_DESC_SIZE * slot];
23d366e350386ec109bfa9b2cf91225729a1a26bduboff tmp0 = (uint32_t)dcp->dmac_address;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff mark |= (uint32_t)dcp->dmac_size;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff tdp->d_bufptr = LE_32(tmp0);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff tdp->d_cmdsts = LE_32(mark);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (frags);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_tx_start(struct gem_dev *dp, int start_slot, int nslot)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint_t tx_ring_size = dp->gc.gc_tx_ring_size;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *tdp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (nslot > 1) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_tx_desc_dma_sync(dp,
23d366e350386ec109bfa9b2cf91225729a1a26bduboff SLOT(start_slot + 1, tx_ring_size),
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff nslot - 1, DDI_DMA_SYNC_FORDEV);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp = (void *)&dp->tx_ring[SFE_DESC_SIZE * start_slot];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp->d_cmdsts |= LE_32(CMDSTS_OWN);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_tx_desc_dma_sync(dp, start_slot, 1, DDI_DMA_SYNC_FORDEV);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Let the Transmit Buffer Manager Fill state machine active.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (dp->mac_active) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, lp->cr | CR_TXE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_rx_desc_write(struct gem_dev *dp, int slot,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_dma_cookie_t *dmacookie, int frags)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *rdp;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t tmp0;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t tmp1;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 2
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ASSERT(frags == 1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT, CONS
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "%s: %s seqnum: %d, slot %d, frags: %d",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__, dp->rx_active_tail, slot, frags);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < frags; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT, CONS " frag: %d addr: 0x%llx, len: 0x%lx",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff i, dmacookie[i].dmac_address, dmacookie[i].dmac_size);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* for the last slot of the packet */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rdp = (void *)&dp->rx_ring[SFE_DESC_SIZE * slot];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff tmp0 = (uint32_t)dmacookie->dmac_address;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff tmp1 = CMDSTS_INTR | (uint32_t)dmacookie->dmac_size;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff rdp->d_bufptr = LE_32(tmp0);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff rdp->d_cmdsts = LE_32(tmp1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_tx_desc_stat(struct gem_dev *dp, int slot, int ndesc)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint_t tx_ring_size = dp->gc.gc_tx_ring_size;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *tdp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t status;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int cols;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef DEBUG_LEVEL
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff clock_t delay;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* check status of the last descriptor */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp = (void *)
23d366e350386ec109bfa9b2cf91225729a1a26bduboff &dp->tx_ring[SFE_DESC_SIZE * SLOT(slot + ndesc - 1, tx_ring_size)];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /*
23d366e350386ec109bfa9b2cf91225729a1a26bduboff * Don't use LE_32() directly to refer tdp->d_cmdsts.
23d366e350386ec109bfa9b2cf91225729a1a26bduboff * It is not atomic for big endian cpus.
23d366e350386ec109bfa9b2cf91225729a1a26bduboff */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff status = tdp->d_cmdsts;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff status = LE_32(status);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: time:%ld %s: slot:%d, status:0x%b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, ddi_get_lbolt(), __func__,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff slot, status, TXSTAT_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (status & CMDSTS_OWN) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * not yet transmitted
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* workaround for tx hang */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff if (lp->chip->chip_type == CHIPTYPE_DP83815 &&
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->mac_active) {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, CR, lp->cr | CR_TXE);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (status & CMDSTS_MORE) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* XXX - the hardware problem but don't panic the system */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* avoid lint bug for %b format string including 32nd bit */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_NOTE, CONS
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "%s: tx status bits incorrect: slot:%d, status:0x%x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, slot, status);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 3
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff delay = (ddi_get_lbolt() - dp->tx_buf_head->txb_stime) * 10;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (delay >= 50) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_NOTE, "%s: tx deferred %d mS: slot %d",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, delay, slot));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 3
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < nfrag-1; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t s;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int n;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff n = SLOT(slot + i, tx_ring_size);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff s = LE_32(
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ((struct sfe_desc *)((void *)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff &dp->tx_ring[SFE_DESC_SIZE * n]))->d_cmdsts);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ASSERT(s & CMDSTS_MORE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ASSERT((s & CMDSTS_OWN) == 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * collect statistics
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((status & CMDSTS_OK) == 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* failed to transmit the packet */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT, CONS "%s: Transmit error, Tx status %b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, status, TXSTAT_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.errxmt++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (status & CMDSTS_TFU) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.underflow++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (status & CMDSTS_CRS) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.nocarrier++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (status & CMDSTS_OWC) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.xmtlatecoll++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if ((!dp->full_duplex) && (status & CMDSTS_EC)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.excoll++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.collisions += 16;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.xmit_internal_err++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (!dp->full_duplex) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cols = (status >> CMDSTS_CCNT_SHIFT) & CCNT_MASK;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (cols > 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (cols == 1) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.first_coll++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else /* (cols > 1) */ {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.multi_coll++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.collisions += cols;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (status & CMDSTS_TD) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.defer++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_TX_DONE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint64_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_rx_desc_stat(struct gem_dev *dp, int slot, int ndesc)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *rdp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t len;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t flag;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t status;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff flag = GEM_RX_DONE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Dont read ISR because we cannot ack only to rx interrupt. */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rdp = (void *)&dp->rx_ring[SFE_DESC_SIZE * slot];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /*
23d366e350386ec109bfa9b2cf91225729a1a26bduboff * Don't use LE_32() directly to refer rdp->d_cmdsts.
23d366e350386ec109bfa9b2cf91225729a1a26bduboff * It is not atomic for big endian cpus.
23d366e350386ec109bfa9b2cf91225729a1a26bduboff */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff status = rdp->d_cmdsts;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff status = LE_32(status);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "%s: time:%ld %s: slot:%d, status:0x%b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, ddi_get_lbolt(), __func__,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff slot, status, RXSTAT_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((status & CMDSTS_OWN) == 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * No more received packets because
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * this buffer is owned by NIC.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#define RX_ERR_BITS \
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (CMDSTS_RXA | CMDSTS_RXO | CMDSTS_LONG | CMDSTS_RUNT | \
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff CMDSTS_ISE | CMDSTS_CRCE | CMDSTS_FAE | CMDSTS_MORE)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (status & RX_ERR_BITS) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Packet with error received
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT, CONS "%s: Corrupted packet "
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "received, buffer status: %b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, status, RXSTAT_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* collect statistics information */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.errrcv++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (status & CMDSTS_RXO) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.overflow++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (status & (CMDSTS_LONG | CMDSTS_MORE)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.frame_too_long++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (status & CMDSTS_RUNT) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.runt++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (status & (CMDSTS_ISE | CMDSTS_FAE)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.frame++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (status & CMDSTS_CRCE) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.crc++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.rcv_internal_err++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (flag | GEM_RX_ERR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * this packet was received without errors
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((len = (status & CMDSTS_SIZE)) >= ETHERFCSL) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff len -= ETHERFCSL;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEVEL > 10
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t *bp = dp->rx_buf_head->rxb_buf;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT, CONS "%s: len:%d", dp->name, len);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < 60; i += 10) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT, CONS
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bp[0], bp[1], bp[2], bp[3], bp[4],
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bp[5], bp[6], bp[7], bp[8], bp[9]);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff bp += 10;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (flag | (len & GEM_RX_LEN));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_tx_desc_init(struct gem_dev *dp, int slot)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint_t tx_ring_size = dp->gc.gc_tx_ring_size;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *tdp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t here;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp = (void *)&dp->tx_ring[SFE_DESC_SIZE * slot];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* don't clear d_link field, which have a valid pointer */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp->d_cmdsts = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* make a link to this from the previous descriptor */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff here = ((uint32_t)dp->tx_ring_dma) + SFE_DESC_SIZE*slot;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp = (void *)
23d366e350386ec109bfa9b2cf91225729a1a26bduboff &dp->tx_ring[SFE_DESC_SIZE * SLOT(slot - 1, tx_ring_size)];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp->d_link = LE_32(here);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_rx_desc_init(struct gem_dev *dp, int slot)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint_t rx_ring_size = dp->gc.gc_rx_ring_size;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *rdp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t here;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rdp = (void *)&dp->rx_ring[SFE_DESC_SIZE * slot];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* don't clear d_link field, which have a valid pointer */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rdp->d_cmdsts = LE_32(CMDSTS_OWN);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* make a link to this from the previous descriptor */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff here = ((uint32_t)dp->rx_ring_dma) + SFE_DESC_SIZE*slot;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rdp = (void *)
23d366e350386ec109bfa9b2cf91225729a1a26bduboff &dp->rx_ring[SFE_DESC_SIZE * SLOT(slot - 1, rx_ring_size)];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rdp->d_link = LE_32(here);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_tx_desc_clean(struct gem_dev *dp, int slot)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *tdp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp = (void *)&dp->tx_ring[SFE_DESC_SIZE * slot];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff tdp->d_cmdsts = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_rx_desc_clean(struct gem_dev *dp, int slot)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_desc *rdp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rdp = (void *)&dp->rx_ring[SFE_DESC_SIZE * slot];
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rdp->d_cmdsts = LE_32(CMDSTS_OWN);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Device depend interrupt handler
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_interrupt(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint_t rx_ring_size = dp->gc.gc_rx_ring_size;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t isr;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t isr_bogus;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint_t flags = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff boolean_t need_to_reset = B_FALSE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* read reason and clear interrupt */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff isr = INL(dp, ISR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff isr_bogus = lp->isr_pended;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff lp->isr_pended = 0;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff if (((isr | isr_bogus) & lp->our_intr_bits) == 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* we are not the interrupt source */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (DDI_INTR_UNCLAIMED);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(3, (CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff CONS "%s: time:%ld %s:called: isr:0x%b rx_active_head: %d",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, ddi_get_lbolt(), __func__,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff isr, INTR_BITS, dp->rx_active_head));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (!dp->mac_active) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* the device is going to stop */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->our_intr_bits = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (DDI_INTR_CLAIMED);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff isr &= lp->our_intr_bits;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (isr & (ISR_RXSOVR | ISR_RXORN | ISR_RXIDLE | ISR_RXERR |
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ISR_RXDESC | ISR_RXOK)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (void) gem_receive(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (isr & (ISR_RXSOVR | ISR_RXORN)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff CONS "%s: rx fifo overrun: isr %b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, isr, INTR_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* no need restart rx */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.overflow++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (isr & ISR_RXIDLE) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff CONS "%s: rx buffer ran out: isr %b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, isr, INTR_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->stats.norcvbuf++;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Make RXDP points the head of receive
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * buffer list.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, RXDP, dp->rx_ring_dma +
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff SFE_DESC_SIZE *
23d366e350386ec109bfa9b2cf91225729a1a26bduboff SLOT(dp->rx_active_head, rx_ring_size));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Restart the receive engine */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, CR, lp->cr | CR_RXE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (isr & (ISR_TXURN | ISR_TXERR | ISR_TXDESC |
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ISR_TXIDLE | ISR_TXOK)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* need to reclaim tx buffers */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (gem_tx_done(dp)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff flags |= INTR_RESTART_TX;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * XXX - tx error statistics will be counted in
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * sfe_tx_desc_stat() and no need to restart tx on errors.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (isr & (ISR_DPERR | ISR_SSERR | ISR_RMABT | ISR_RTABT)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN, "%s: ERROR interrupt: isr %b.",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, isr, INTR_BITS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff need_to_reset = B_TRUE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffreset:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (need_to_reset) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (void) gem_restart_nic(dp, GEM_RESTART_KEEP_BUF);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff flags |= INTR_RESTART_TX;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(5, (CE_CONT, CONS "%s: %s: return: isr: %b",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__, isr, INTR_BITS));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (DDI_INTR_CLAIMED | flags);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * HW depend MII routine
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * MII routines for NS DP83815
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mii_sync_dp83815(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* do nothing */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint16_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mii_read_dp83815(struct gem_dev *dp, uint_t offset)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS"%s: %s: offset 0x%x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__, offset));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return ((uint16_t)INL(dp, MII_REGS_BASE + offset*4));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mii_write_dp83815(struct gem_dev *dp, uint_t offset, uint16_t val)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS"%s: %s: offset 0x%x 0x%x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__, offset, val));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MII_REGS_BASE + offset*4, val);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mii_config_dp83815(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t srr;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff srr = INL(dp, SRR) & SRR_REV;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT, CONS "%s: srr:0x%04x %04x %04x %04x %04x %04x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, srr,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00cc), /* PGSEL */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00e4), /* PMDCSR */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00fc), /* TSTDAT */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00f4), /* DSPCFG */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00f8))); /* SDCFG */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff if (srr == SRR_REV_DP83815CVNG) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * NS datasheet says that DP83815CVNG needs following
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * registers to be patched for optimizing its performance.
23d366e350386ec109bfa9b2cf91225729a1a26bduboff * A report said that CRC errors on RX disappeared
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * with the patch.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTW(dp, 0x00cc, 0x0001); /* PGSEL */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTW(dp, 0x00e4, 0x189c); /* PMDCSR */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTW(dp, 0x00fc, 0x0000); /* TSTDAT */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTW(dp, 0x00f4, 0x5040); /* DSPCFG */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTW(dp, 0x00f8, 0x008c); /* SDCFG */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTW(dp, 0x00cc, 0x0000); /* PGSEL */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff CONS "%s: PHY patched %04x %04x %04x %04x %04x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00cc), /* PGSEL */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00e4), /* PMDCSR */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00fc), /* TSTDAT */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00f4), /* DSPCFG */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff INW(dp, 0x00f8))); /* SDCFG */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff } else if (((srr ^ SRR_REV_DP83815DVNG) & 0xff00) == 0 ||
23d366e350386ec109bfa9b2cf91225729a1a26bduboff ((srr ^ SRR_REV_DP83816AVNG) & 0xff00) == 0) {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /*
23d366e350386ec109bfa9b2cf91225729a1a26bduboff * Additional packets for later chipset
23d366e350386ec109bfa9b2cf91225729a1a26bduboff */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTW(dp, 0x00cc, 0x0001); /* PGSEL */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTW(dp, 0x00e4, 0x189c); /* PMDCSR */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTW(dp, 0x00cc, 0x0000); /* PGSEL */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff DPRINTF(0, (CE_CONT,
23d366e350386ec109bfa9b2cf91225729a1a26bduboff CONS "%s: PHY patched %04x %04x",
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->name,
23d366e350386ec109bfa9b2cf91225729a1a26bduboff INW(dp, 0x00cc), /* PGSEL */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff INW(dp, 0x00e4))); /* PMDCSR */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (gem_mii_config_default(dp));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboffstatic int
23d366e350386ec109bfa9b2cf91225729a1a26bduboffsfe_mii_probe_dp83815(struct gem_dev *dp)
23d366e350386ec109bfa9b2cf91225729a1a26bduboff{
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t val;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* try external phy first */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff DPRINTF(0, (CE_CONT, CONS "%s: %s: trying external phy",
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->name, __func__));
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->mii_phy_addr = 0;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->gc.gc_mii_sync = &sfe_mii_sync_sis900;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->gc.gc_mii_read = &sfe_mii_read_sis900;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->gc.gc_mii_write = &sfe_mii_write_sis900;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, CFG, val | CFG_EXT_PHY | CFG_PHY_DIS);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff if (gem_mii_probe_default(dp) == GEM_SUCCESS) {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff return (GEM_SUCCESS);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff }
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* switch to internal phy */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff DPRINTF(0, (CE_CONT, CONS "%s: %s: switching to internal phy",
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->name, __func__));
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->mii_phy_addr = -1;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->gc.gc_mii_sync = &sfe_mii_sync_dp83815;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->gc.gc_mii_read = &sfe_mii_read_dp83815;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff dp->gc.gc_mii_write = &sfe_mii_write_dp83815;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, CFG, val | CFG_PAUSE_ADV | CFG_PHY_RST);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff drv_usecwait(100); /* keep to assert RST bit for a while */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, CFG, val | CFG_PAUSE_ADV);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* wait for PHY reset */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff delay(drv_usectohz(10000));
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff return (gem_mii_probe_default(dp));
23d366e350386ec109bfa9b2cf91225729a1a26bduboff}
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboffstatic int
23d366e350386ec109bfa9b2cf91225729a1a26bduboffsfe_mii_init_dp83815(struct gem_dev *dp)
23d366e350386ec109bfa9b2cf91225729a1a26bduboff{
23d366e350386ec109bfa9b2cf91225729a1a26bduboff uint32_t val;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff if (dp->mii_phy_addr == -1) {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* select internal phy */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, CFG, val | CFG_PAUSE_ADV);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff } else {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* select external phy */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, CFG, val | CFG_EXT_PHY | CFG_PHY_DIS);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff }
23d366e350386ec109bfa9b2cf91225729a1a26bduboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff return (GEM_SUCCESS);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * MII routines for SiS900
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff#define MDIO_DELAY(dp) {(void) INL(dp, MEAR); (void) INL(dp, MEAR); }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mii_sync_sis900(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* send 32 ONE's to make MII line idle */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < 32; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, MEAR_MDDIR | MEAR_MDIO);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, MEAR_MDDIR | MEAR_MDIO | MEAR_MDC);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mii_config_sis900(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Do chip depend setup */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((dp->mii_phy_id & PHY_MASK) == PHY_ICS1893) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* workaround for ICS1893 PHY */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mii_write(dp, 0x0018, 0xD200);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->revid == SIS630E_900_REV) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * SiS 630E has bugs on default values
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * of PHY registers
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mii_write(dp, MII_AN_ADVERT, 0x05e1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mii_write(dp, MII_CONFIG1, 0x0022);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mii_write(dp, MII_CONFIG2, 0xff00);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mii_write(dp, MII_MASK, 0xffc0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff sfe_set_eq_sis630(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (gem_mii_config_default(dp));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic uint16_t
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mii_read_sis900(struct gem_dev *dp, uint_t reg)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t cmd;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t ret;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t data;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmd = MII_READ_CMD(dp->mii_phy_addr, reg);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 31; i >= 18; i--) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff data = ((cmd >> i) & 1) << MEAR_MDIO_SHIFT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, data | MEAR_MDDIR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, data | MEAR_MDDIR | MEAR_MDC);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* turn around cycle */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, MEAR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* get response from PHY */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, MEAR_MDC);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, MEAR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#if DEBUG_LEBEL > 0
23d366e350386ec109bfa9b2cf91225729a1a26bduboff (void) INL(dp, MEAR); /* delay */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (INL(dp, MEAR) & MEAR_MDIO) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN, "%s: PHY@%d not responded",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, dp->mii_phy_addr);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
23d366e350386ec109bfa9b2cf91225729a1a26bduboff#else
23d366e350386ec109bfa9b2cf91225729a1a26bduboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* terminate response cycle */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, MEAR_MDC);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ret = 0; /* to avoid lint errors */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 16; i > 0; i--) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, 0);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff (void) INL(dp, MEAR); /* delay */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ret = (ret << 1) | ((INL(dp, MEAR) >> MEAR_MDIO_SHIFT) & 1);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, MEAR_MDC);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* send two idle(Z) bits to terminate the read cycle */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff for (i = 0; i < 2; i++) {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, MEAR, 0);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff MDIO_DELAY(dp);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, MEAR, MEAR_MDC);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff MDIO_DELAY(dp);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (ret);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_mii_write_sis900(struct gem_dev *dp, uint_t reg, uint16_t val)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t cmd;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t data;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmd = MII_WRITE_CMD(dp->mii_phy_addr, reg, val);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 31; i >= 0; i--) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff data = ((cmd >> i) & 1) << MEAR_MDIO_SHIFT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, data | MEAR_MDDIR);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff OUTL(dp, MEAR, data | MEAR_MDDIR | MEAR_MDC);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* send two idle(Z) bits to terminate the write cycle. */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0; i < 2; i++) {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, MEAR, 0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff OUTL(dp, MEAR, MEAR_MDC);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MDIO_DELAY(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#undef MDIO_DELAY
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_set_eq_sis630(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t reg14h;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t eq_value;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t max_value;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t min_value;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t rev;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rev = lp->revid;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (!(rev == SIS630E_900_REV || rev == SIS630EA1_900_REV ||
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rev == SIS630A_900_REV || rev == SIS630ET_900_REV)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* it doesn't have a internal PHY */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (dp->mii_state == MII_STATE_LINKUP) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff reg14h = gem_mii_read(dp, MII_RESV);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mii_write(dp, MII_RESV, (0x2200 | reg14h) & 0xBFFF);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff eq_value = (0x00f8 & gem_mii_read(dp, MII_RESV)) >> 3;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff max_value = min_value = eq_value;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 1; i < 10; i++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff eq_value = (0x00f8 & gem_mii_read(dp, MII_RESV)) >> 3;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff max_value = max(eq_value, max_value);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff min_value = min(eq_value, min_value);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* for 630E, rule to determine the equalizer value */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (rev == SIS630E_900_REV || rev == SIS630EA1_900_REV ||
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rev == SIS630ET_900_REV) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (max_value < 5) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff eq_value = max_value;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (5 <= max_value && max_value < 15) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff eq_value =
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff max(max_value + 1,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff min_value + 2);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (15 <= max_value) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff eq_value =
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff max(max_value + 5,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff min_value + 6);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* for 630B0&B1, rule to determine the equalizer value */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff else
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (rev == SIS630A_900_REV &&
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (lp->bridge_revid == SIS630B0 ||
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->bridge_revid == SIS630B1)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (max_value == 0) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff eq_value = 3;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff eq_value = (max_value + min_value + 1)/2;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* write equalizer value and setting */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff reg14h = gem_mii_read(dp, MII_RESV) & ~0x02f8;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff reg14h |= 0x6000 | (eq_value << 3);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mii_write(dp, MII_RESV, reg14h);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff reg14h = (gem_mii_read(dp, MII_RESV) & ~0x4000) | 0x2000;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (rev == SIS630A_900_REV &&
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (lp->bridge_revid == SIS630B0 ||
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->bridge_revid == SIS630B1)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff reg14h |= 0x0200;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mii_write(dp, MII_RESV, reg14h);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * OS depend (device driver) routine
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic void
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_chipinfo_init_sis900(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int rev;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = (struct sfe_dev *)dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rev = lp->revid;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (rev == SIS630E_900_REV /* 0x81 */) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* sis630E */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->get_mac_addr = &sfe_get_mac_addr_sis630e;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (rev > 0x81 && rev <= 0x90) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* 630S, 630EA1, 630ET, 635A */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->get_mac_addr = &sfe_get_mac_addr_sis635;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else if (rev == SIS962_900_REV /* 0x91 */) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* sis962 or later */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->get_mac_addr = &sfe_get_mac_addr_sis962;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* sis900 */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->get_mac_addr = &sfe_get_mac_addr_sis900;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->bridge_revid = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (rev == SIS630E_900_REV || rev == SIS630EA1_900_REV ||
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rev == SIS630A_900_REV || rev == SIS630ET_900_REV) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * read host bridge revision
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dev_info_t *bridge;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_acc_handle_t bridge_handle;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if ((bridge = sfe_search_pci_dev(0x1039, 0x630)) == NULL) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "%s: cannot find host bridge (pci1039,630)",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (pci_config_setup(bridge, &bridge_handle) != DDI_SUCCESS) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN, "%s: pci_config_setup failed",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->bridge_revid =
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_get8(bridge_handle, PCI_CONF_REVID);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_teardown(&bridge_handle);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfe_attach_chip(struct gem_dev *dp)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp = (struct sfe_dev *)dp->private;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(4, (CE_CONT, CONS "!%s: %s called", dp->name, __func__));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* setup chip-depend get_mac_address function */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->chip->chip_type == CHIPTYPE_SIS900) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff sfe_chipinfo_init_sis900(dp);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->get_mac_addr = &sfe_get_mac_addr_dp83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* read MAC address */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (!(lp->get_mac_addr)(dp)) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "!%s: %s: failed to get factory mac address"
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff " please specify a mac address in sfe.conf",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->name, __func__);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_FAILURE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (lp->chip->chip_type == CHIPTYPE_DP83815) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->mii_phy_addr = -1; /* no need to scan PHY */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->misc_flag |= GEM_VLAN_SOFT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->txthr += 4; /* VTAG_SIZE */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp->txthr = min(dp->txthr, TXFIFOSIZE - 2);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (GEM_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfeattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int unit;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff const char *drv_name;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int i;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_acc_handle_t conf_handle;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t vid;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint16_t did;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t rev;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef DEBUG_LEVEL
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint32_t iline;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff uint8_t latim;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct chip_info *p;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct gem_dev *dp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct sfe_dev *lp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff caddr_t base;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ddi_acc_handle_t regs_ha;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff struct gem_conf *gcp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff unit = ddi_get_instance(dip);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_name = ddi_driver_name(dip);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(3, (CE_CONT, CONS "%s%d: sfeattach: called", drv_name, unit));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Common codes after power-up
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (pci_config_setup(dip, &conf_handle) != DDI_SUCCESS) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN, "%s%d: ddi_regs_map_setup failed",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_name, unit);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff goto err;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff vid = pci_config_get16(conf_handle, PCI_CONF_VENID);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff did = pci_config_get16(conf_handle, PCI_CONF_DEVID);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rev = pci_config_get16(conf_handle, PCI_CONF_REVID);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef DEBUG_LEVEL
23d366e350386ec109bfa9b2cf91225729a1a26bduboff iline = pci_config_get32(conf_handle, PCI_CONF_ILINE);
23d366e350386ec109bfa9b2cf91225729a1a26bduboff latim = pci_config_get8(conf_handle, PCI_CONF_LATENCY_TIMER);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef DEBUG_BUILT_IN_SIS900
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff rev = SIS630E_900_REV;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff for (i = 0, p = sfe_chiptbl; i < CHIPTABLESIZE; i++, p++) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (p->venid == vid && p->devid == did) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* found */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff goto chip_found;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* Not found */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "%s%d: sfe_attach: wrong PCI venid/devid (0x%x, 0x%x)",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_name, unit, vid, did);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_teardown(&conf_handle);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff goto err;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffchip_found:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_put16(conf_handle, PCI_CONF_COMM,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff PCI_COMM_IO | PCI_COMM_MAE | PCI_COMM_ME |
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_get16(conf_handle, PCI_CONF_COMM));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* ensure D0 mode */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (void) gem_pci_set_power_state(dip, conf_handle, PCI_PMCSR_D0);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff pci_config_teardown(&conf_handle);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff switch (cmd) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff case DDI_RESUME:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (gem_resume(dip));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff case DDI_ATTACH:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(0, (CE_CONT,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff CONS "%s%d: ilr 0x%08x, latency_timer:0x%02x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_name, unit, iline, latim));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Map in the device registers.
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (gem_pci_regs_map_setup(dip,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (sfe_use_pcimemspace && p->chip_type == CHIPTYPE_DP83815)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ? PCI_ADDR_MEM32 : PCI_ADDR_IO, PCI_ADDR_MASK,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff &sfe_dev_attr, &base, &regs_ha) != DDI_SUCCESS) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_WARN,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff "%s%d: ddi_regs_map_setup failed",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_name, unit);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff goto err;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * construct gem configuration
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp = kmem_zalloc(sizeof (*gcp), KM_SLEEP);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* name */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff (void) sprintf(gcp->gc_name, "%s%d", drv_name, unit);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* consistency on tx and rx */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_buf_align = sizeof (uint8_t) - 1;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_max_frags = MAXTXFRAGS;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_max_descs_per_pkt = gcp->gc_tx_max_frags;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_desc_unit_shift = 4; /* 16 byte */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_buf_size = TX_BUF_SIZE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_buf_limit = gcp->gc_tx_buf_size;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_ring_size = TX_RING_SIZE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_ring_limit = gcp->gc_tx_ring_size;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_auto_pad = B_TRUE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_copy_thresh = sfe_tx_copy_thresh;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_desc_write_oo = B_TRUE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_buf_align = sizeof (uint8_t) - 1;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_max_frags = MAXRXFRAGS;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_desc_unit_shift = 4;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_ring_size = RX_RING_SIZE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_buf_max = RX_BUF_SIZE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_copy_thresh = sfe_rx_copy_thresh;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* map attributes */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_dev_attr = sfe_dev_attr;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_buf_attr = sfe_buf_attr;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_desc_attr = sfe_buf_attr;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* dma attributes */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_dma_attr_desc = sfe_dma_attr_desc;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_dma_attr_txbuf = sfe_dma_attr_buf;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_dma_attr_txbuf.dma_attr_align = gcp->gc_tx_buf_align+1;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_dma_attr_txbuf.dma_attr_sgllen = gcp->gc_tx_max_frags;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_dma_attr_rxbuf = sfe_dma_attr_buf;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_dma_attr_rxbuf.dma_attr_align = gcp->gc_rx_buf_align+1;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_dma_attr_rxbuf.dma_attr_sgllen = gcp->gc_rx_max_frags;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* time out parameters */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_timeout = 3*ONESEC;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_timeout_interval = ONESEC;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff if (p->chip_type == CHIPTYPE_DP83815) {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff /* workaround for tx hang */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff gcp->gc_tx_timeout_interval = ONESEC/20; /* 50mS */
23d366e350386ec109bfa9b2cf91225729a1a26bduboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* MII timeout parameters */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_link_watch_interval = ONESEC;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_an_watch_interval = ONESEC/5;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_reset_timeout = MII_RESET_TIMEOUT; /* 1 sec */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_an_timeout = MII_AN_TIMEOUT; /* 5 sec */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_an_wait = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_linkdown_timeout = MII_LINKDOWN_TIMEOUT;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* setting for general PHY */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_an_delay = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_linkdown_action = MII_ACTION_RSA;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_linkdown_timeout_action = MII_ACTION_RESET;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_dont_reset = B_FALSE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* I/O methods */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* mac operation */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_attach_chip = &sfe_attach_chip;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (p->chip_type == CHIPTYPE_DP83815) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_reset_chip = &sfe_reset_chip_dp83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_reset_chip = &sfe_reset_chip_sis900;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_init_chip = &sfe_init_chip;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_start_chip = &sfe_start_chip;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_stop_chip = &sfe_stop_chip;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#ifdef USE_MULTICAST_HASHTBL
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_multicast_hash = &sfe_mcast_hash;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff#endif
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (p->chip_type == CHIPTYPE_DP83815) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_set_rx_filter = &sfe_set_rx_filter_dp83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_set_rx_filter = &sfe_set_rx_filter_sis900;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_set_media = &sfe_set_media;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_get_stats = &sfe_get_stats;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_interrupt = &sfe_interrupt;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* descriptor operation */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_desc_write = &sfe_tx_desc_write;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_start = &sfe_tx_start;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_desc_write = &sfe_rx_desc_write;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_start = NULL;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_desc_stat = &sfe_tx_desc_stat;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_desc_stat = &sfe_rx_desc_stat;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_desc_init = &sfe_tx_desc_init;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_desc_init = &sfe_rx_desc_init;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_tx_desc_clean = &sfe_tx_desc_clean;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_rx_desc_clean = &sfe_rx_desc_clean;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff /* mii operations */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (p->chip_type == CHIPTYPE_DP83815) {
23d366e350386ec109bfa9b2cf91225729a1a26bduboff gcp->gc_mii_probe = &sfe_mii_probe_dp83815;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff gcp->gc_mii_init = &sfe_mii_init_dp83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_config = &sfe_mii_config_dp83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_sync = &sfe_mii_sync_dp83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_read = &sfe_mii_read_dp83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_write = &sfe_mii_write_dp83815;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_tune_phy = NULL;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_flow_control = FLOW_CONTROL_NONE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff } else {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_probe = &gem_mii_probe_default;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_init = NULL;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_config = &sfe_mii_config_sis900;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_sync = &sfe_mii_sync_sis900;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_read = &sfe_mii_read_sis900;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_write = &sfe_mii_write_sis900;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_mii_tune_phy = &sfe_set_eq_sis630;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gcp->gc_flow_control = FLOW_CONTROL_RX_PAUSE;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp = kmem_zalloc(sizeof (*lp), KM_SLEEP);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->chip = p;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp->revid = rev;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff lp->our_intr_bits = 0;
23d366e350386ec109bfa9b2cf91225729a1a26bduboff lp->isr_pended = 0;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff cmn_err(CE_CONT, CONS "%s%d: chip:%s rev:0x%02x",
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff drv_name, unit, p->chip_name, rev);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff dp = gem_do_attach(dip, 0, gcp, base, &regs_ha,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff lp, sizeof (*lp));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff kmem_free(gcp, sizeof (*gcp));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (dp == NULL) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff goto err_freelp;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (DDI_SUCCESS);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615dubofferr_freelp:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff kmem_free(lp, sizeof (struct sfe_dev));
f8919bdadda3ebb97bd55cc14a16e0271ed57615dubofferr:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (DDI_FAILURE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (DDI_FAILURE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic int
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffsfedetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff switch (cmd) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff case DDI_SUSPEND:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (gem_suspend(dip));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff case DDI_DETACH:
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (gem_do_detach(dip));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (DDI_FAILURE);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore/*
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * quiesce(9E) entry point.
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore *
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * This function is called when the system is single-threaded at high
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * PIL with preemption disabled. Therefore, this function must not be
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * blocked.
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore *
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore * DDI_FAILURE indicates an error condition and should almost never happen.
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore */
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore#ifdef __sparc
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore#define sfe_quiesce ddi_quiesce_not_supported
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore#else
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moorestatic int
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Mooresfe_quiesce(dev_info_t *dip)
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore{
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore struct gem_dev *dp;
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore int ret = 0;
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore dp = GEM_GET_DEV(dip);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore if (dp == NULL)
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore return (DDI_FAILURE);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore ret = sfe_stop_chip_quiesce(dp);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore return (ret);
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore}
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore#endif
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * OS depend (loadable streams driver) routine
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffDDI_DEFINE_STREAM_OPS(sfe_ops, nulldev, nulldev, sfeattach, sfedetach,
53560dfa94d868e9016a1b90f971fb538dc2009aSherry Moore nodev, NULL, D_MP, NULL, sfe_quiesce);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic struct modldrv modldrv = {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff &mod_driverops, /* Type of module. This one is a driver */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff ident,
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff &sfe_ops, /* driver ops */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffstatic struct modlinkage modlinkage = {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff MODREV_1, &modldrv, NULL
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff};
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * Loadable module support
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/* ======================================================== */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffint
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff_init(void)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int status;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "sfe: _init: called"));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mod_init(&sfe_ops, "sfe");
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff status = mod_install(&modlinkage);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (status != DDI_SUCCESS) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mod_fini(&sfe_ops);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (status);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff/*
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff * _fini : done
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff */
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffint
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff_fini(void)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff int status;
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff DPRINTF(2, (CE_CONT, CONS "sfe: _fini: called"));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff status = mod_remove(&modlinkage);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff if (status == DDI_SUCCESS) {
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff gem_mod_fini(&sfe_ops);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff }
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (status);
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboffint
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff_info(struct modinfo *modinfop)
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff{
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff return (mod_info(&modlinkage, modinfop));
f8919bdadda3ebb97bd55cc14a16e0271ed57615duboff}