15748Sduboff /*
25748Sduboff * sfe.c : DP83815/DP83816/SiS900 Fast Ethernet MAC driver for Solaris
35748Sduboff *
47116Sduboff * Copyright (c) 2002-2008 Masayuki Murayama. All rights reserved.
55748Sduboff *
65748Sduboff * Redistribution and use in source and binary forms, with or without
75748Sduboff * modification, are permitted provided that the following conditions are met:
85748Sduboff *
95748Sduboff * 1. Redistributions of source code must retain the above copyright notice,
105748Sduboff * this list of conditions and the following disclaimer.
115748Sduboff *
125748Sduboff * 2. Redistributions in binary form must reproduce the above copyright notice,
135748Sduboff * this list of conditions and the following disclaimer in the documentation
145748Sduboff * and/or other materials provided with the distribution.
155748Sduboff *
165748Sduboff * 3. Neither the name of the author nor the names of its contributors may be
175748Sduboff * used to endorse or promote products derived from this software without
185748Sduboff * specific prior written permission.
195748Sduboff *
205748Sduboff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
215748Sduboff * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
225748Sduboff * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
235748Sduboff * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
245748Sduboff * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
255748Sduboff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
265748Sduboff * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
275748Sduboff * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
285748Sduboff * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
295748Sduboff * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
305748Sduboff * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
315748Sduboff * DAMAGE.
325748Sduboff */
335748Sduboff
34*9694SScott.Rotondo@Sun.COM /* Avoid undefined symbol for non IA architectures */
35*9694SScott.Rotondo@Sun.COM #pragma weak inb
36*9694SScott.Rotondo@Sun.COM #pragma weak outb
37*9694SScott.Rotondo@Sun.COM
387656SSherry.Moore@Sun.COM /*
398611SSherry.Moore@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
407656SSherry.Moore@Sun.COM * Use is subject to license terms.
417656SSherry.Moore@Sun.COM */
425748Sduboff
435748Sduboff /*
445748Sduboff * System Header files.
455748Sduboff */
465748Sduboff #include <sys/types.h>
475748Sduboff #include <sys/conf.h>
485748Sduboff #include <sys/debug.h>
495748Sduboff #include <sys/kmem.h>
505748Sduboff #include <sys/modctl.h>
515748Sduboff #include <sys/errno.h>
525748Sduboff #include <sys/ddi.h>
535748Sduboff #include <sys/sunddi.h>
545748Sduboff #include <sys/byteorder.h>
555748Sduboff #include <sys/ethernet.h>
565748Sduboff #include <sys/pci.h>
575748Sduboff
585748Sduboff #include "sfe_mii.h"
595748Sduboff #include "sfe_util.h"
605748Sduboff #include "sfereg.h"
615748Sduboff
628611SSherry.Moore@Sun.COM char ident[] = "sis900/dp83815 driver v" "2.6.1t30os";
635748Sduboff
645748Sduboff /* Debugging support */
655748Sduboff #ifdef DEBUG_LEVEL
665748Sduboff static int sfe_debug = DEBUG_LEVEL;
675748Sduboff #if DEBUG_LEVEL > 4
685748Sduboff #define CONS "^"
695748Sduboff #else
705748Sduboff #define CONS "!"
715748Sduboff #endif
725748Sduboff #define DPRINTF(n, args) if (sfe_debug > (n)) cmn_err args
735748Sduboff #else
745748Sduboff #define CONS "!"
755748Sduboff #define DPRINTF(n, args)
765748Sduboff #endif
775748Sduboff
785748Sduboff /*
795748Sduboff * Useful macros and typedefs
805748Sduboff */
815748Sduboff #define ONESEC (drv_usectohz(1*1000000))
825748Sduboff #define ROUNDUP2(x, a) (((x) + (a) - 1) & ~((a) - 1))
835748Sduboff
845748Sduboff /*
855748Sduboff * Our configuration
865748Sduboff */
875748Sduboff #define MAXTXFRAGS 1
885748Sduboff #define MAXRXFRAGS 1
895748Sduboff
905748Sduboff #ifndef TX_BUF_SIZE
915748Sduboff #define TX_BUF_SIZE 64
925748Sduboff #endif
935748Sduboff #ifndef TX_RING_SIZE
945748Sduboff #if MAXTXFRAGS == 1
955748Sduboff #define TX_RING_SIZE TX_BUF_SIZE
965748Sduboff #else
975748Sduboff #define TX_RING_SIZE (TX_BUF_SIZE * 4)
985748Sduboff #endif
995748Sduboff #endif
1005748Sduboff
1015748Sduboff #ifndef RX_BUF_SIZE
1025748Sduboff #define RX_BUF_SIZE 256
1035748Sduboff #endif
1045748Sduboff #ifndef RX_RING_SIZE
1055748Sduboff #define RX_RING_SIZE RX_BUF_SIZE
1065748Sduboff #endif
1075748Sduboff
1085748Sduboff #define OUR_INTR_BITS \
1095748Sduboff (ISR_DPERR | ISR_SSERR | ISR_RMABT | ISR_RTABT | ISR_RXSOVR | \
1105748Sduboff ISR_TXURN | ISR_TXDESC | ISR_TXERR | \
1115748Sduboff ISR_RXORN | ISR_RXIDLE | ISR_RXOK | ISR_RXERR)
1125748Sduboff
1135748Sduboff #define USE_MULTICAST_HASHTBL
1145748Sduboff
1155748Sduboff static int sfe_tx_copy_thresh = 256;
1165748Sduboff static int sfe_rx_copy_thresh = 256;
1175748Sduboff
1185748Sduboff /* special PHY registers for SIS900 */
1195748Sduboff #define MII_CONFIG1 0x0010
1205748Sduboff #define MII_CONFIG2 0x0011
1215748Sduboff #define MII_MASK 0x0013
1225748Sduboff #define MII_RESV 0x0014
1235748Sduboff
1245748Sduboff #define PHY_MASK 0xfffffff0
1255748Sduboff #define PHY_SIS900_INTERNAL 0x001d8000
1265748Sduboff #define PHY_ICS1893 0x0015f440
1275748Sduboff
1285748Sduboff
1295748Sduboff #define SFE_DESC_SIZE 16 /* including pads rounding up to power of 2 */
1305748Sduboff
1315748Sduboff /*
1325748Sduboff * Supported chips
1335748Sduboff */
1345748Sduboff struct chip_info {
1355748Sduboff uint16_t venid;
1365748Sduboff uint16_t devid;
1375748Sduboff char *chip_name;
1385748Sduboff int chip_type;
1395748Sduboff #define CHIPTYPE_DP83815 0
1405748Sduboff #define CHIPTYPE_SIS900 1
1415748Sduboff };
1425748Sduboff
1435748Sduboff /*
1445748Sduboff * Chip dependent MAC state
1455748Sduboff */
1465748Sduboff struct sfe_dev {
1475748Sduboff /* misc HW information */
1485748Sduboff struct chip_info *chip;
1495748Sduboff uint32_t our_intr_bits;
1507116Sduboff uint32_t isr_pended;
1515748Sduboff uint32_t cr;
1525748Sduboff uint_t tx_drain_threshold;
1535748Sduboff uint_t tx_fill_threshold;
1545748Sduboff uint_t rx_drain_threshold;
1555748Sduboff uint_t rx_fill_threshold;
1565748Sduboff uint8_t revid; /* revision from PCI configuration */
1575748Sduboff boolean_t (*get_mac_addr)(struct gem_dev *);
1585748Sduboff uint8_t mac_addr[ETHERADDRL];
1595748Sduboff uint8_t bridge_revid;
1605748Sduboff };
1615748Sduboff
1625748Sduboff /*
1635748Sduboff * Hardware information
1645748Sduboff */
1655748Sduboff struct chip_info sfe_chiptbl[] = {
1665748Sduboff { 0x1039, 0x0900, "SiS900", CHIPTYPE_SIS900, },
1675748Sduboff { 0x100b, 0x0020, "DP83815/83816", CHIPTYPE_DP83815, },
1685748Sduboff { 0x1039, 0x7016, "SiS7016", CHIPTYPE_SIS900, },
1695748Sduboff };
1705748Sduboff #define CHIPTABLESIZE (sizeof (sfe_chiptbl)/sizeof (struct chip_info))
1715748Sduboff
1725748Sduboff /* ======================================================== */
1735748Sduboff
1745748Sduboff /* mii operations */
1755748Sduboff static void sfe_mii_sync_dp83815(struct gem_dev *);
1765748Sduboff static void sfe_mii_sync_sis900(struct gem_dev *);
1775748Sduboff static uint16_t sfe_mii_read_dp83815(struct gem_dev *, uint_t);
1785748Sduboff static uint16_t sfe_mii_read_sis900(struct gem_dev *, uint_t);
1795748Sduboff static void sfe_mii_write_dp83815(struct gem_dev *, uint_t, uint16_t);
1805748Sduboff static void sfe_mii_write_sis900(struct gem_dev *, uint_t, uint16_t);
1815748Sduboff static void sfe_set_eq_sis630(struct gem_dev *dp);
1825748Sduboff /* nic operations */
1835748Sduboff static int sfe_reset_chip_sis900(struct gem_dev *);
1845748Sduboff static int sfe_reset_chip_dp83815(struct gem_dev *);
1855748Sduboff static int sfe_init_chip(struct gem_dev *);
1865748Sduboff static int sfe_start_chip(struct gem_dev *);
1875748Sduboff static int sfe_stop_chip(struct gem_dev *);
1885748Sduboff static int sfe_set_media(struct gem_dev *);
1895748Sduboff static int sfe_set_rx_filter_dp83815(struct gem_dev *);
1905748Sduboff static int sfe_set_rx_filter_sis900(struct gem_dev *);
1915748Sduboff static int sfe_get_stats(struct gem_dev *);
1925748Sduboff static int sfe_attach_chip(struct gem_dev *);
1935748Sduboff
1945748Sduboff /* descriptor operations */
1955748Sduboff static int sfe_tx_desc_write(struct gem_dev *dp, int slot,
1965748Sduboff ddi_dma_cookie_t *dmacookie, int frags, uint64_t flags);
1975748Sduboff static void sfe_tx_start(struct gem_dev *dp, int startslot, int nslot);
1985748Sduboff static void sfe_rx_desc_write(struct gem_dev *dp, int slot,
1995748Sduboff ddi_dma_cookie_t *dmacookie, int frags);
2005748Sduboff static uint_t sfe_tx_desc_stat(struct gem_dev *dp, int slot, int ndesc);
2015748Sduboff static uint64_t sfe_rx_desc_stat(struct gem_dev *dp, int slot, int ndesc);
2025748Sduboff
2035748Sduboff static void sfe_tx_desc_init(struct gem_dev *dp, int slot);
2045748Sduboff static void sfe_rx_desc_init(struct gem_dev *dp, int slot);
2055748Sduboff static void sfe_tx_desc_clean(struct gem_dev *dp, int slot);
2065748Sduboff static void sfe_rx_desc_clean(struct gem_dev *dp, int slot);
2075748Sduboff
2085748Sduboff /* interrupt handler */
2095748Sduboff static uint_t sfe_interrupt(struct gem_dev *dp);
2105748Sduboff
2115748Sduboff /* ======================================================== */
2125748Sduboff
2135748Sduboff /* mapping attributes */
2145748Sduboff /* Data access requirements. */
2155748Sduboff static struct ddi_device_acc_attr sfe_dev_attr = {
2165748Sduboff DDI_DEVICE_ATTR_V0,
2175748Sduboff DDI_STRUCTURE_LE_ACC,
2185748Sduboff DDI_STRICTORDER_ACC
2195748Sduboff };
2205748Sduboff
2215748Sduboff /* On sparc, Buffers should be native endian for speed */
2225748Sduboff static struct ddi_device_acc_attr sfe_buf_attr = {
2235748Sduboff DDI_DEVICE_ATTR_V0,
2245748Sduboff DDI_NEVERSWAP_ACC, /* native endianness */
2255748Sduboff DDI_STRICTORDER_ACC
2265748Sduboff };
2275748Sduboff
2285748Sduboff static ddi_dma_attr_t sfe_dma_attr_buf = {
2295748Sduboff DMA_ATTR_V0, /* dma_attr_version */
2305748Sduboff 0, /* dma_attr_addr_lo */
2315748Sduboff 0xffffffffull, /* dma_attr_addr_hi */
2325748Sduboff 0x00000fffull, /* dma_attr_count_max */
2335748Sduboff 0, /* patched later */ /* dma_attr_align */
2345748Sduboff 0x000003fc, /* dma_attr_burstsizes */
2355748Sduboff 1, /* dma_attr_minxfer */
2365748Sduboff 0x00000fffull, /* dma_attr_maxxfer */
2375748Sduboff 0xffffffffull, /* dma_attr_seg */
2385748Sduboff 0, /* patched later */ /* dma_attr_sgllen */
2395748Sduboff 1, /* dma_attr_granular */
2405748Sduboff 0 /* dma_attr_flags */
2415748Sduboff };
2425748Sduboff
2435748Sduboff static ddi_dma_attr_t sfe_dma_attr_desc = {
2445748Sduboff DMA_ATTR_V0, /* dma_attr_version */
2455748Sduboff 16, /* dma_attr_addr_lo */
2465748Sduboff 0xffffffffull, /* dma_attr_addr_hi */
2475748Sduboff 0xffffffffull, /* dma_attr_count_max */
2485748Sduboff 16, /* dma_attr_align */
2495748Sduboff 0x000003fc, /* dma_attr_burstsizes */
2505748Sduboff 1, /* dma_attr_minxfer */
2515748Sduboff 0xffffffffull, /* dma_attr_maxxfer */
2525748Sduboff 0xffffffffull, /* dma_attr_seg */
2535748Sduboff 1, /* dma_attr_sgllen */
2545748Sduboff 1, /* dma_attr_granular */
2555748Sduboff 0 /* dma_attr_flags */
2565748Sduboff };
2575748Sduboff
2585748Sduboff uint32_t sfe_use_pcimemspace = 0;
2595748Sduboff
2605748Sduboff /* ======================================================== */
2615748Sduboff /*
2625748Sduboff * HW manipulation routines
2635748Sduboff */
2645748Sduboff /* ======================================================== */
2655748Sduboff
2665748Sduboff #define SFE_EEPROM_DELAY(dp) \
2675748Sduboff { (void) INL(dp, EROMAR); (void) INL(dp, EROMAR); }
2685748Sduboff #define EE_CMD_READ 6
2695748Sduboff #define EE_CMD_SHIFT 6
2705748Sduboff
2715748Sduboff static uint16_t
sfe_read_eeprom(struct gem_dev * dp,uint_t offset)2725748Sduboff sfe_read_eeprom(struct gem_dev *dp, uint_t offset)
2735748Sduboff {
2745748Sduboff int eedi;
2755748Sduboff int i;
2765748Sduboff uint16_t ret;
2775748Sduboff
2785748Sduboff /* ensure de-assert chip select */
2795748Sduboff OUTL(dp, EROMAR, 0);
2805748Sduboff SFE_EEPROM_DELAY(dp);
2815748Sduboff OUTL(dp, EROMAR, EROMAR_EESK);
2825748Sduboff SFE_EEPROM_DELAY(dp);
2835748Sduboff
2845748Sduboff /* assert chip select */
2855748Sduboff offset |= EE_CMD_READ << EE_CMD_SHIFT;
2865748Sduboff
2875748Sduboff for (i = 8; i >= 0; i--) {
2885748Sduboff /* make command */
2895748Sduboff eedi = ((offset >> i) & 1) << EROMAR_EEDI_SHIFT;
2905748Sduboff
2915748Sduboff /* send 1 bit */
2925748Sduboff OUTL(dp, EROMAR, EROMAR_EECS | eedi);
2935748Sduboff SFE_EEPROM_DELAY(dp);
2945748Sduboff OUTL(dp, EROMAR, EROMAR_EECS | eedi | EROMAR_EESK);
2955748Sduboff SFE_EEPROM_DELAY(dp);
2965748Sduboff }
2975748Sduboff
2985748Sduboff OUTL(dp, EROMAR, EROMAR_EECS);
2995748Sduboff
3005748Sduboff ret = 0;
3015748Sduboff for (i = 0; i < 16; i++) {
3025748Sduboff /* Get 1 bit */
3035748Sduboff OUTL(dp, EROMAR, EROMAR_EECS);
3045748Sduboff SFE_EEPROM_DELAY(dp);
3055748Sduboff OUTL(dp, EROMAR, EROMAR_EECS | EROMAR_EESK);
3065748Sduboff SFE_EEPROM_DELAY(dp);
3075748Sduboff
3085748Sduboff ret = (ret << 1) | ((INL(dp, EROMAR) >> EROMAR_EEDO_SHIFT) & 1);
3095748Sduboff }
3105748Sduboff
3115748Sduboff OUTL(dp, EROMAR, 0);
3125748Sduboff SFE_EEPROM_DELAY(dp);
3135748Sduboff
3145748Sduboff return (ret);
3155748Sduboff }
3165748Sduboff #undef SFE_EEPROM_DELAY
3175748Sduboff
3185748Sduboff static boolean_t
sfe_get_mac_addr_dp83815(struct gem_dev * dp)3195748Sduboff sfe_get_mac_addr_dp83815(struct gem_dev *dp)
3205748Sduboff {
3215748Sduboff uint8_t *mac;
3225748Sduboff uint_t val;
3235748Sduboff int i;
3245748Sduboff
3255748Sduboff #define BITSET(p, ix, v) (p)[(ix)/8] |= ((v) ? 1 : 0) << ((ix) & 0x7)
3265748Sduboff
3275748Sduboff DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
3285748Sduboff
3295748Sduboff mac = dp->dev_addr.ether_addr_octet;
3305748Sduboff
3315748Sduboff /* first of all, clear MAC address buffer */
3325748Sduboff bzero(mac, ETHERADDRL);
3335748Sduboff
3345748Sduboff /* get bit 0 */
3355748Sduboff val = sfe_read_eeprom(dp, 0x6);
3365748Sduboff BITSET(mac, 0, val & 1);
3375748Sduboff
3385748Sduboff /* get bit 1 - 16 */
3395748Sduboff val = sfe_read_eeprom(dp, 0x7);
3405748Sduboff for (i = 0; i < 16; i++) {
3415748Sduboff BITSET(mac, 1 + i, val & (1 << (15 - i)));
3425748Sduboff }
3435748Sduboff
3445748Sduboff /* get bit 17 - 32 */
3455748Sduboff val = sfe_read_eeprom(dp, 0x8);
3465748Sduboff for (i = 0; i < 16; i++) {
3475748Sduboff BITSET(mac, 17 + i, val & (1 << (15 - i)));
3485748Sduboff }
3495748Sduboff
3505748Sduboff /* get bit 33 - 47 */
3515748Sduboff val = sfe_read_eeprom(dp, 0x9);
3525748Sduboff for (i = 0; i < 15; i++) {
3535748Sduboff BITSET(mac, 33 + i, val & (1 << (15 - i)));
3545748Sduboff }
3555748Sduboff
3565748Sduboff return (B_TRUE);
3575748Sduboff #undef BITSET
3585748Sduboff }
3595748Sduboff
3605748Sduboff static boolean_t
sfe_get_mac_addr_sis900(struct gem_dev * dp)3615748Sduboff sfe_get_mac_addr_sis900(struct gem_dev *dp)
3625748Sduboff {
3635748Sduboff uint_t val;
3645748Sduboff int i;
3655748Sduboff uint8_t *mac;
3665748Sduboff
3675748Sduboff mac = dp->dev_addr.ether_addr_octet;
3685748Sduboff
3695748Sduboff for (i = 0; i < ETHERADDRL/2; i++) {
3705748Sduboff val = sfe_read_eeprom(dp, 0x8 + i);
3715748Sduboff *mac++ = (uint8_t)val;
3725748Sduboff *mac++ = (uint8_t)(val >> 8);
3735748Sduboff }
3745748Sduboff
3755748Sduboff return (B_TRUE);
3765748Sduboff }
3775748Sduboff
3785748Sduboff static dev_info_t *
sfe_search_pci_dev_subr(dev_info_t * cur_node,int vendor_id,int device_id)3795748Sduboff sfe_search_pci_dev_subr(dev_info_t *cur_node, int vendor_id, int device_id)
3805748Sduboff {
3815748Sduboff dev_info_t *child_id;
3825748Sduboff dev_info_t *ret;
3835748Sduboff int vid, did;
3845748Sduboff
3855748Sduboff if (cur_node == NULL) {
3865748Sduboff return (NULL);
3875748Sduboff }
3885748Sduboff
3895748Sduboff /* check brothers */
3905748Sduboff do {
3915748Sduboff vid = ddi_prop_get_int(DDI_DEV_T_ANY, cur_node,
3925748Sduboff DDI_PROP_DONTPASS, "vendor-id", -1);
3935748Sduboff did = ddi_prop_get_int(DDI_DEV_T_ANY, cur_node,
3945748Sduboff DDI_PROP_DONTPASS, "device-id", -1);
3955748Sduboff
3965748Sduboff if (vid == vendor_id && did == device_id) {
3975748Sduboff /* found */
3985748Sduboff return (cur_node);
3995748Sduboff }
4005748Sduboff
4015748Sduboff /* check children */
4025748Sduboff if ((child_id = ddi_get_child(cur_node)) != NULL) {
4035748Sduboff if ((ret = sfe_search_pci_dev_subr(child_id,
4045748Sduboff vendor_id, device_id)) != NULL) {
4055748Sduboff return (ret);
4065748Sduboff }
4075748Sduboff }
4085748Sduboff
4095748Sduboff } while ((cur_node = ddi_get_next_sibling(cur_node)) != NULL);
4105748Sduboff
4115748Sduboff /* not found */
4125748Sduboff return (NULL);
4135748Sduboff }
4145748Sduboff
4155748Sduboff static dev_info_t *
sfe_search_pci_dev(int vendor_id,int device_id)4165748Sduboff sfe_search_pci_dev(int vendor_id, int device_id)
4175748Sduboff {
4185748Sduboff return (sfe_search_pci_dev_subr(ddi_root_node(), vendor_id, device_id));
4195748Sduboff }
4205748Sduboff
4215748Sduboff static boolean_t
sfe_get_mac_addr_sis630e(struct gem_dev * dp)4225748Sduboff sfe_get_mac_addr_sis630e(struct gem_dev *dp)
4235748Sduboff {
4245748Sduboff int i;
4255748Sduboff dev_info_t *isa_bridge;
4265748Sduboff ddi_acc_handle_t isa_handle;
4275748Sduboff int reg;
4285748Sduboff
4295748Sduboff if (inb == NULL || outb == NULL) {
4305748Sduboff /* this is not IA architecture */
4315748Sduboff return (B_FALSE);
4325748Sduboff }
4335748Sduboff
4345748Sduboff if ((isa_bridge = sfe_search_pci_dev(0x1039, 0x8)) == NULL) {
4355748Sduboff cmn_err(CE_WARN, "%s: failed to find isa-bridge pci1039,8",
4365748Sduboff dp->name);
4375748Sduboff return (B_FALSE);
4385748Sduboff }
4395748Sduboff
4405748Sduboff if (pci_config_setup(isa_bridge, &isa_handle) != DDI_SUCCESS) {
4415748Sduboff cmn_err(CE_WARN, "%s: ddi_regs_map_setup failed",
4425748Sduboff dp->name);
4435748Sduboff return (B_FALSE);
4445748Sduboff }
4455748Sduboff
4465748Sduboff /* enable to access CMOS RAM */
4475748Sduboff reg = pci_config_get8(isa_handle, 0x48);
4485748Sduboff pci_config_put8(isa_handle, 0x48, reg | 0x40);
4495748Sduboff
4505748Sduboff for (i = 0; i < ETHERADDRL; i++) {
4515748Sduboff outb(0x70, 0x09 + i);
4525748Sduboff dp->dev_addr.ether_addr_octet[i] = inb(0x71);
4535748Sduboff }
4545748Sduboff
4555748Sduboff /* disable to access CMOS RAM */
4565748Sduboff pci_config_put8(isa_handle, 0x48, reg);
4575748Sduboff pci_config_teardown(&isa_handle);
4585748Sduboff
4595748Sduboff return (B_TRUE);
4605748Sduboff }
4615748Sduboff
4625748Sduboff static boolean_t
sfe_get_mac_addr_sis635(struct gem_dev * dp)4635748Sduboff sfe_get_mac_addr_sis635(struct gem_dev *dp)
4645748Sduboff {
4655748Sduboff int i;
4665748Sduboff uint32_t rfcr;
4675748Sduboff uint16_t v;
4685748Sduboff struct sfe_dev *lp = dp->private;
4695748Sduboff
4705748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
4715748Sduboff rfcr = INL(dp, RFCR);
4725748Sduboff
4735748Sduboff OUTL(dp, CR, lp->cr | CR_RELOAD);
4745748Sduboff OUTL(dp, CR, lp->cr);
4755748Sduboff
4765748Sduboff /* disable packet filtering before reading filter */
4775748Sduboff OUTL(dp, RFCR, rfcr & ~RFCR_RFEN);
4785748Sduboff
4795748Sduboff /* load MAC addr from filter data register */
4805748Sduboff for (i = 0; i < ETHERADDRL; i += 2) {
4815748Sduboff OUTL(dp, RFCR,
4825748Sduboff (RFADDR_MAC_SIS900 + (i/2)) << RFCR_RFADDR_SHIFT_SIS900);
4835748Sduboff v = INL(dp, RFDR);
4845748Sduboff dp->dev_addr.ether_addr_octet[i] = (uint8_t)v;
4855748Sduboff dp->dev_addr.ether_addr_octet[i+1] = (uint8_t)(v >> 8);
4865748Sduboff }
4875748Sduboff
4885748Sduboff /* re-enable packet filtering */
4895748Sduboff OUTL(dp, RFCR, rfcr | RFCR_RFEN);
4905748Sduboff
4915748Sduboff return (B_TRUE);
4925748Sduboff }
4935748Sduboff
4945748Sduboff static boolean_t
sfe_get_mac_addr_sis962(struct gem_dev * dp)4955748Sduboff sfe_get_mac_addr_sis962(struct gem_dev *dp)
4965748Sduboff {
4975748Sduboff boolean_t ret;
4985748Sduboff int i;
4995748Sduboff
5005748Sduboff ret = B_FALSE;
5015748Sduboff
5025748Sduboff /* rise request signal to access EEPROM */
5035748Sduboff OUTL(dp, MEAR, EROMAR_EEREQ);
5045748Sduboff for (i = 0; (INL(dp, MEAR) & EROMAR_EEGNT) == 0; i++) {
5055748Sduboff if (i > 200) {
5065748Sduboff /* failed to acquire eeprom */
5075748Sduboff cmn_err(CE_NOTE,
5085748Sduboff CONS "%s: failed to access eeprom", dp->name);
5095748Sduboff goto x;
5105748Sduboff }
5115748Sduboff drv_usecwait(10);
5125748Sduboff }
5135748Sduboff ret = sfe_get_mac_addr_sis900(dp);
5145748Sduboff x:
5155748Sduboff /* release EEPROM */
5165748Sduboff OUTL(dp, MEAR, EROMAR_EEDONE);
5175748Sduboff
5185748Sduboff return (ret);
5195748Sduboff }
5205748Sduboff
5215748Sduboff static int
sfe_reset_chip_sis900(struct gem_dev * dp)5225748Sduboff sfe_reset_chip_sis900(struct gem_dev *dp)
5235748Sduboff {
5245748Sduboff int i;
5255748Sduboff uint32_t done;
5265748Sduboff uint32_t val;
5275748Sduboff struct sfe_dev *lp = dp->private;
5285748Sduboff
5295748Sduboff DPRINTF(4, (CE_CONT, CONS "%s: %s called", dp->name, __func__));
5305748Sduboff
5315748Sduboff /* invalidate mac addr cache */
5325748Sduboff bzero(lp->mac_addr, sizeof (lp->mac_addr));
5335748Sduboff
5345748Sduboff lp->cr = 0;
5355748Sduboff
5365748Sduboff /* inhibit interrupt */
5375748Sduboff OUTL(dp, IMR, 0);
5387116Sduboff lp->isr_pended |= INL(dp, ISR) & lp->our_intr_bits;
5395748Sduboff
5407893SAlan.Duboff@Sun.COM OUTLINL(dp, RFCR, 0);
5415748Sduboff
5425748Sduboff OUTL(dp, CR, CR_RST | CR_TXR | CR_RXR);
5435748Sduboff drv_usecwait(10);
5445748Sduboff
5455748Sduboff done = 0;
5465748Sduboff for (i = 0; done != (ISR_TXRCMP | ISR_RXRCMP); i++) {
5475748Sduboff if (i > 1000) {
5485748Sduboff cmn_err(CE_WARN, "%s: chip reset timeout", dp->name);
5495748Sduboff return (GEM_FAILURE);
5505748Sduboff }
5515748Sduboff done |= INL(dp, ISR) & (ISR_TXRCMP | ISR_RXRCMP);
5525748Sduboff drv_usecwait(10);
5535748Sduboff }
5545748Sduboff
5555748Sduboff if (lp->revid == SIS630ET_900_REV) {
5565748Sduboff lp->cr |= CR_ACCESSMODE;
5575748Sduboff OUTL(dp, CR, lp->cr | INL(dp, CR));
5585748Sduboff }
5595748Sduboff
5605748Sduboff /* Configuration register: enable PCI parity */
5615748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b",
5625748Sduboff dp->name, INL(dp, CFG), CFG_BITS_SIS900));
5637116Sduboff val = 0;
5645748Sduboff if (lp->revid >= SIS635A_900_REV ||
5655748Sduboff lp->revid == SIS900B_900_REV) {
5665748Sduboff /* what is this ? */
5675748Sduboff val |= CFG_RND_CNT;
5685748Sduboff }
5695748Sduboff OUTL(dp, CFG, val);
5705748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b", dp->name,
5715748Sduboff INL(dp, CFG), CFG_BITS_SIS900));
5725748Sduboff
5735748Sduboff return (GEM_SUCCESS);
5745748Sduboff }
5755748Sduboff
5765748Sduboff static int
sfe_reset_chip_dp83815(struct gem_dev * dp)5775748Sduboff sfe_reset_chip_dp83815(struct gem_dev *dp)
5785748Sduboff {
5795748Sduboff int i;
5807116Sduboff uint32_t val;
5815748Sduboff struct sfe_dev *lp = dp->private;
5825748Sduboff
5835748Sduboff DPRINTF(4, (CE_CONT, CONS "%s: %s called", dp->name, __func__));
5845748Sduboff
5855748Sduboff /* invalidate mac addr cache */
5865748Sduboff bzero(lp->mac_addr, sizeof (lp->mac_addr));
5875748Sduboff
5885748Sduboff lp->cr = 0;
5895748Sduboff
5905748Sduboff /* inhibit interrupts */
5915748Sduboff OUTL(dp, IMR, 0);
5927116Sduboff lp->isr_pended |= INL(dp, ISR) & lp->our_intr_bits;
5935748Sduboff
5945748Sduboff OUTL(dp, RFCR, 0);
5955748Sduboff
5965748Sduboff OUTL(dp, CR, CR_RST);
5975748Sduboff drv_usecwait(10);
5985748Sduboff
5995748Sduboff for (i = 0; INL(dp, CR) & CR_RST; i++) {
6005748Sduboff if (i > 100) {
6015748Sduboff cmn_err(CE_WARN, "!%s: chip reset timeout", dp->name);
6025748Sduboff return (GEM_FAILURE);
6035748Sduboff }
6045748Sduboff drv_usecwait(10);
6055748Sduboff }
6065748Sduboff DPRINTF(0, (CE_CONT, "!%s: chip reset in %duS", dp->name, i*10));
6075748Sduboff
6085748Sduboff OUTL(dp, CCSR, CCSR_PMESTS);
6095748Sduboff OUTL(dp, CCSR, 0);
6105748Sduboff
6115748Sduboff /* Configuration register: enable PCI parity */
6125748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b",
6135748Sduboff dp->name, INL(dp, CFG), CFG_BITS_DP83815));
6147116Sduboff val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
6157116Sduboff OUTL(dp, CFG, val | CFG_PAUSE_ADV);
6165748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: cfg:%b", dp->name,
6175748Sduboff INL(dp, CFG), CFG_BITS_DP83815));
6185748Sduboff
6195748Sduboff return (GEM_SUCCESS);
6205748Sduboff }
6215748Sduboff
6225748Sduboff static int
sfe_init_chip(struct gem_dev * dp)6235748Sduboff sfe_init_chip(struct gem_dev *dp)
6245748Sduboff {
6255748Sduboff /* Configuration register: have been set up in sfe_chip_reset */
6265748Sduboff
6275748Sduboff /* PCI test control register: do nothing */
6285748Sduboff
6295748Sduboff /* Interrupt status register : do nothing */
6305748Sduboff
6315748Sduboff /* Interrupt mask register: clear, but leave lp->our_intr_bits */
6325748Sduboff OUTL(dp, IMR, 0);
6335748Sduboff
6345748Sduboff /* Enhanced PHY Access register (sis900): do nothing */
6355748Sduboff
6365748Sduboff /* Transmit Descriptor Pointer register: base addr of TX ring */
6375748Sduboff OUTL(dp, TXDP, dp->tx_ring_dma);
6385748Sduboff
6395748Sduboff /* Receive descriptor pointer register: base addr of RX ring */
6405748Sduboff OUTL(dp, RXDP, dp->rx_ring_dma);
6415748Sduboff
6425748Sduboff return (GEM_SUCCESS);
6435748Sduboff }
6445748Sduboff
6455748Sduboff static uint_t
sfe_mcast_hash(struct gem_dev * dp,uint8_t * addr)6465748Sduboff sfe_mcast_hash(struct gem_dev *dp, uint8_t *addr)
6475748Sduboff {
6485748Sduboff return (gem_ether_crc_be(addr, ETHERADDRL));
6495748Sduboff }
6505748Sduboff
6515748Sduboff #ifdef DEBUG_LEVEL
6525748Sduboff static void
sfe_rxfilter_dump(struct gem_dev * dp,int start,int end)6535748Sduboff sfe_rxfilter_dump(struct gem_dev *dp, int start, int end)
6545748Sduboff {
6555748Sduboff int i;
6565748Sduboff int j;
6575748Sduboff uint16_t ram[0x10];
6585748Sduboff
6595748Sduboff cmn_err(CE_CONT, "!%s: rx filter ram dump:", dp->name);
6605748Sduboff #define WORDS_PER_LINE 4
6615748Sduboff for (i = start; i < end; i += WORDS_PER_LINE*2) {
6625748Sduboff for (j = 0; j < WORDS_PER_LINE; j++) {
6635748Sduboff OUTL(dp, RFCR, RFADDR_MAC_DP83815 + i + j*2);
6645748Sduboff ram[j] = INL(dp, RFDR);
6655748Sduboff }
6665748Sduboff
6675748Sduboff cmn_err(CE_CONT, "!0x%02x: 0x%04x 0x%04x 0x%04x 0x%04x",
6685748Sduboff i, ram[0], ram[1], ram[2], ram[3]);
6695748Sduboff }
6705748Sduboff
6715748Sduboff #undef WORDS_PER_LINE
6725748Sduboff }
6735748Sduboff #endif
6745748Sduboff
6755748Sduboff static uint_t sfe_rf_perfect_base_dp83815[] = {
6765748Sduboff RFADDR_PMATCH0_DP83815,
6775748Sduboff RFADDR_PMATCH1_DP83815,
6785748Sduboff RFADDR_PMATCH2_DP83815,
6795748Sduboff RFADDR_PMATCH3_DP83815,
6805748Sduboff };
6815748Sduboff
6825748Sduboff static int
sfe_set_rx_filter_dp83815(struct gem_dev * dp)6835748Sduboff sfe_set_rx_filter_dp83815(struct gem_dev *dp)
6845748Sduboff {
6855748Sduboff int i;
6865748Sduboff int j;
6875748Sduboff uint32_t mode;
6885748Sduboff uint8_t *mac = dp->cur_addr.ether_addr_octet;
6895748Sduboff uint16_t hash_tbl[32];
6905748Sduboff struct sfe_dev *lp = dp->private;
6915748Sduboff
6925748Sduboff DPRINTF(1, (CE_CONT, CONS "%s: %s: called, mc_count:%d, mode:0x%b",
6935748Sduboff dp->name, __func__, dp->mc_count, dp->rxmode, RXMODE_BITS));
6945748Sduboff
6955748Sduboff #if DEBUG_LEVEL > 0
6965748Sduboff for (i = 0; i < dp->mc_count; i++) {
6975748Sduboff cmn_err(CE_CONT,
6985748Sduboff "!%s: adding mcast(%d) %02x:%02x:%02x:%02x:%02x:%02x",
6995748Sduboff dp->name, i,
7005748Sduboff dp->mc_list[i].addr.ether_addr_octet[0],
7015748Sduboff dp->mc_list[i].addr.ether_addr_octet[1],
7025748Sduboff dp->mc_list[i].addr.ether_addr_octet[2],
7035748Sduboff dp->mc_list[i].addr.ether_addr_octet[3],
7045748Sduboff dp->mc_list[i].addr.ether_addr_octet[4],
7055748Sduboff dp->mc_list[i].addr.ether_addr_octet[5]);
7065748Sduboff }
7075748Sduboff #endif
7085748Sduboff if ((dp->rxmode & RXMODE_ENABLE) == 0) {
7095748Sduboff /* disable rx filter */
7105748Sduboff OUTL(dp, RFCR, 0);
7115748Sduboff return (GEM_SUCCESS);
7125748Sduboff }
7135748Sduboff
7145748Sduboff /*
7155748Sduboff * Set Receive filter control register
7165748Sduboff */
7175748Sduboff if (dp->rxmode & RXMODE_PROMISC) {
7185748Sduboff /* all broadcast, all multicast, all physical */
7195748Sduboff mode = RFCR_AAB | RFCR_AAM | RFCR_AAP;
7205748Sduboff } else if ((dp->rxmode & RXMODE_ALLMULTI) || dp->mc_count > 16*32/2) {
7215748Sduboff /* all broadcast, all multicast, physical for the chip */
7225748Sduboff mode = RFCR_AAB | RFCR_AAM | RFCR_APM_DP83815;
7235748Sduboff } else if (dp->mc_count > 4) {
7245748Sduboff /*
7255748Sduboff * Use multicast hash table,
7265748Sduboff * accept all broadcast and physical for the chip.
7275748Sduboff */
7285748Sduboff mode = RFCR_AAB | RFCR_MHEN_DP83815 | RFCR_APM_DP83815;
7295748Sduboff
7305748Sduboff bzero(hash_tbl, sizeof (hash_tbl));
7315748Sduboff for (i = 0; i < dp->mc_count; i++) {
7325748Sduboff j = dp->mc_list[i].hash >> (32 - 9);
7335748Sduboff hash_tbl[j / 16] |= 1 << (j % 16);
7345748Sduboff }
7355748Sduboff } else {
7365748Sduboff /*
7375748Sduboff * Use pattern mach filter for multicast address,
7385748Sduboff * accept all broadcast and physical for the chip
7395748Sduboff */
7405748Sduboff /* need to enable corresponding pattern registers */
7415748Sduboff mode = RFCR_AAB | RFCR_APM_DP83815 |
7425748Sduboff (((1 << dp->mc_count) - 1) << RFCR_APAT_SHIFT);
7435748Sduboff }
7445748Sduboff
7455748Sduboff #if DEBUG_LEVEL > 1
7465748Sduboff cmn_err(CE_CONT,
7475748Sduboff "!%s: mac %02x:%02x:%02x:%02x:%02x:%02x"
7485748Sduboff " cache %02x:%02x:%02x:%02x:%02x:%02x",
7495748Sduboff dp->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
7505748Sduboff lp->mac_addr[0], lp->mac_addr[1],
7515748Sduboff lp->mac_addr[2], lp->mac_addr[3],
7525748Sduboff lp->mac_addr[4], lp->mac_addr[5]);
7535748Sduboff #endif
7545748Sduboff if (bcmp(mac, lp->mac_addr, ETHERADDRL) != 0) {
7555748Sduboff /*
7565748Sduboff * XXX - need to *disable* rx filter to load mac address for
7575748Sduboff * the chip. otherwise, we cannot setup rxfilter correctly.
7585748Sduboff */
7595748Sduboff /* setup perfect match register for my station address */
7605748Sduboff for (i = 0; i < ETHERADDRL; i += 2) {
7615748Sduboff OUTL(dp, RFCR, RFADDR_MAC_DP83815 + i);
7625748Sduboff OUTL(dp, RFDR, (mac[i+1] << 8) | mac[i]);
7635748Sduboff }
7645748Sduboff
7655748Sduboff bcopy(mac, lp->mac_addr, ETHERADDRL);
7665748Sduboff }
7675748Sduboff
7685748Sduboff #if DEBUG_LEVEL > 3
7695748Sduboff /* clear pattern ram */
7705748Sduboff for (j = 0x200; j < 0x380; j += 2) {
7715748Sduboff OUTL(dp, RFCR, j);
7725748Sduboff OUTL(dp, RFDR, 0);
7735748Sduboff }
7745748Sduboff #endif
7755748Sduboff if (mode & RFCR_APAT_DP83815) {
7765748Sduboff /* setup multicast address into pattern match registers */
7775748Sduboff for (j = 0; j < dp->mc_count; j++) {
7785748Sduboff mac = &dp->mc_list[j].addr.ether_addr_octet[0];
7795748Sduboff for (i = 0; i < ETHERADDRL; i += 2) {
7805748Sduboff OUTL(dp, RFCR,
7815748Sduboff sfe_rf_perfect_base_dp83815[j] + i*2);
7825748Sduboff OUTL(dp, RFDR, (mac[i+1] << 8) | mac[i]);
7835748Sduboff }
7845748Sduboff }
7855748Sduboff
7865748Sduboff /* setup pattern count registers */
7875748Sduboff OUTL(dp, RFCR, RFADDR_PCOUNT01_DP83815);
7885748Sduboff OUTL(dp, RFDR, (ETHERADDRL << 8) | ETHERADDRL);
7895748Sduboff OUTL(dp, RFCR, RFADDR_PCOUNT23_DP83815);
7905748Sduboff OUTL(dp, RFDR, (ETHERADDRL << 8) | ETHERADDRL);
7915748Sduboff }
7925748Sduboff
7935748Sduboff if (mode & RFCR_MHEN_DP83815) {
7945748Sduboff /* Load Multicast hash table */
7955748Sduboff for (i = 0; i < 32; i++) {
7965748Sduboff /* for DP83815, index is in byte */
7975748Sduboff OUTL(dp, RFCR, RFADDR_MULTICAST_DP83815 + i*2);
7985748Sduboff OUTL(dp, RFDR, hash_tbl[i]);
7995748Sduboff }
8005748Sduboff }
8015748Sduboff #if DEBUG_LEVEL > 2
8025748Sduboff sfe_rxfilter_dump(dp, 0, 0x10);
8035748Sduboff sfe_rxfilter_dump(dp, 0x200, 0x380);
8045748Sduboff #endif
8055748Sduboff /* Set rx filter mode and enable rx filter */
8065748Sduboff OUTL(dp, RFCR, RFCR_RFEN | mode);
8075748Sduboff
8085748Sduboff return (GEM_SUCCESS);
8095748Sduboff }
8105748Sduboff
8115748Sduboff static int
sfe_set_rx_filter_sis900(struct gem_dev * dp)8125748Sduboff sfe_set_rx_filter_sis900(struct gem_dev *dp)
8135748Sduboff {
8145748Sduboff int i;
8155748Sduboff uint32_t mode;
8165748Sduboff uint16_t hash_tbl[16];
8175748Sduboff uint8_t *mac = dp->cur_addr.ether_addr_octet;
8185748Sduboff int hash_size;
8195748Sduboff int hash_shift;
8205748Sduboff struct sfe_dev *lp = dp->private;
8215748Sduboff
8225748Sduboff DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
8235748Sduboff
8245748Sduboff if ((dp->rxmode & RXMODE_ENABLE) == 0) {
8257893SAlan.Duboff@Sun.COM /* disable rx filter */
8267893SAlan.Duboff@Sun.COM OUTLINL(dp, RFCR, 0);
8275748Sduboff return (GEM_SUCCESS);
8285748Sduboff }
8295748Sduboff
8305748Sduboff /*
8315748Sduboff * determine hardware hash table size in word.
8325748Sduboff */
8335748Sduboff hash_shift = 25;
8345748Sduboff if (lp->revid >= SIS635A_900_REV || lp->revid == SIS900B_900_REV) {
8355748Sduboff hash_shift = 24;
8365748Sduboff }
8375748Sduboff hash_size = (1 << (32 - hash_shift)) / 16;
8385748Sduboff bzero(hash_tbl, sizeof (hash_tbl));
8395748Sduboff
8405748Sduboff /* Set Receive filter control register */
8415748Sduboff
8425748Sduboff if (dp->rxmode & RXMODE_PROMISC) {
8435748Sduboff /* all broadcast, all multicast, all physical */
8445748Sduboff mode = RFCR_AAB | RFCR_AAM | RFCR_AAP;
8455748Sduboff } else if ((dp->rxmode & RXMODE_ALLMULTI) ||
8465748Sduboff dp->mc_count > hash_size*16/2) {
8475748Sduboff /* all broadcast, all multicast, physical for the chip */
8485748Sduboff mode = RFCR_AAB | RFCR_AAM;
8495748Sduboff } else {
8505748Sduboff /* all broadcast, physical for the chip */
8515748Sduboff mode = RFCR_AAB;
8525748Sduboff }
8535748Sduboff
8545748Sduboff /* make hash table */
8555748Sduboff for (i = 0; i < dp->mc_count; i++) {
8565748Sduboff uint_t h;
8575748Sduboff h = dp->mc_list[i].hash >> hash_shift;
8585748Sduboff hash_tbl[h / 16] |= 1 << (h % 16);
8595748Sduboff }
8605748Sduboff
8615748Sduboff if (bcmp(mac, lp->mac_addr, ETHERADDRL) != 0) {
8625748Sduboff /* Disable Rx filter and load mac address */
8635748Sduboff for (i = 0; i < ETHERADDRL/2; i++) {
8645748Sduboff /* For sis900, index is in word */
8657893SAlan.Duboff@Sun.COM OUTLINL(dp, RFCR,
8665748Sduboff (RFADDR_MAC_SIS900+i) << RFCR_RFADDR_SHIFT_SIS900);
8677893SAlan.Duboff@Sun.COM OUTLINL(dp, RFDR, (mac[i*2+1] << 8) | mac[i*2]);
8685748Sduboff }
8695748Sduboff
8705748Sduboff bcopy(mac, lp->mac_addr, ETHERADDRL);
8715748Sduboff }
8725748Sduboff
8735748Sduboff /* Load Multicast hash table */
8745748Sduboff for (i = 0; i < hash_size; i++) {
8755748Sduboff /* For sis900, index is in word */
8767893SAlan.Duboff@Sun.COM OUTLINL(dp, RFCR,
8775748Sduboff (RFADDR_MULTICAST_SIS900 + i) << RFCR_RFADDR_SHIFT_SIS900);
8787893SAlan.Duboff@Sun.COM OUTLINL(dp, RFDR, hash_tbl[i]);
8795748Sduboff }
8805748Sduboff
8815748Sduboff /* Load rx filter mode and enable rx filter */
8827893SAlan.Duboff@Sun.COM OUTLINL(dp, RFCR, RFCR_RFEN | mode);
8835748Sduboff
8845748Sduboff return (GEM_SUCCESS);
8855748Sduboff }
8865748Sduboff
8875748Sduboff static int
sfe_start_chip(struct gem_dev * dp)8885748Sduboff sfe_start_chip(struct gem_dev *dp)
8895748Sduboff {
8905748Sduboff struct sfe_dev *lp = dp->private;
8915748Sduboff
8925748Sduboff DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
8935748Sduboff
8945748Sduboff /*
8955748Sduboff * setup interrupt mask, which shouldn't include ISR_TOK
8965748Sduboff * to improve performance.
8975748Sduboff */
8985748Sduboff lp->our_intr_bits = OUR_INTR_BITS;
8995748Sduboff
9005748Sduboff /* enable interrupt */
9015748Sduboff if ((dp->misc_flag & GEM_NOINTR) == 0) {
9025748Sduboff OUTL(dp, IER, 1);
9035748Sduboff OUTL(dp, IMR, lp->our_intr_bits);
9045748Sduboff }
9055748Sduboff
9065748Sduboff /* Kick RX */
9075748Sduboff OUTL(dp, CR, lp->cr | CR_RXE);
9085748Sduboff
9095748Sduboff return (GEM_SUCCESS);
9105748Sduboff }
9115748Sduboff
9125748Sduboff /*
9135748Sduboff * Stop nic core gracefully.
9145748Sduboff */
9155748Sduboff static int
sfe_stop_chip(struct gem_dev * dp)9165748Sduboff sfe_stop_chip(struct gem_dev *dp)
9175748Sduboff {
9185748Sduboff struct sfe_dev *lp = dp->private;
9195748Sduboff uint32_t done;
9205748Sduboff int i;
9217116Sduboff uint32_t val;
9225748Sduboff
9235748Sduboff DPRINTF(4, (CE_CONT, CONS "%s: %s: called", dp->name, __func__));
9245748Sduboff
9255748Sduboff /*
9265748Sduboff * Although we inhibit interrupt here, we don't clear soft copy of
9275748Sduboff * interrupt mask to avoid bogus interrupts.
9285748Sduboff */
9295748Sduboff OUTL(dp, IMR, 0);
9305748Sduboff
9315748Sduboff /* stop TX and RX immediately */
9325748Sduboff OUTL(dp, CR, lp->cr | CR_TXR | CR_RXR);
9335748Sduboff
9345748Sduboff done = 0;
9355748Sduboff for (i = 0; done != (ISR_RXRCMP | ISR_TXRCMP); i++) {
9365748Sduboff if (i > 1000) {
9375748Sduboff /*
9385748Sduboff * As gem layer will call sfe_reset_chip(),
9395748Sduboff * we don't neet to reset futher
9405748Sduboff */
9415748Sduboff cmn_err(CE_NOTE, "!%s: %s: Tx/Rx reset timeout",
9425748Sduboff dp->name, __func__);
9435748Sduboff
9445748Sduboff return (GEM_FAILURE);
9455748Sduboff }
9467116Sduboff val = INL(dp, ISR);
9477116Sduboff done |= val & (ISR_RXRCMP | ISR_TXRCMP);
9487116Sduboff lp->isr_pended |= val & lp->our_intr_bits;
9495748Sduboff drv_usecwait(10);
9505748Sduboff }
9515748Sduboff
9525748Sduboff return (GEM_SUCCESS);
9535748Sduboff }
9545748Sduboff
9558611SSherry.Moore@Sun.COM #ifndef __sparc
9568611SSherry.Moore@Sun.COM /*
9578611SSherry.Moore@Sun.COM * Stop nic core gracefully for quiesce
9588611SSherry.Moore@Sun.COM */
9598611SSherry.Moore@Sun.COM static int
sfe_stop_chip_quiesce(struct gem_dev * dp)9608611SSherry.Moore@Sun.COM sfe_stop_chip_quiesce(struct gem_dev *dp)
9618611SSherry.Moore@Sun.COM {
9628611SSherry.Moore@Sun.COM struct sfe_dev *lp = dp->private;
9638611SSherry.Moore@Sun.COM uint32_t done;
9648611SSherry.Moore@Sun.COM int i;
9658611SSherry.Moore@Sun.COM uint32_t val;
9668611SSherry.Moore@Sun.COM
9678611SSherry.Moore@Sun.COM /*
9688611SSherry.Moore@Sun.COM * Although we inhibit interrupt here, we don't clear soft copy of
9698611SSherry.Moore@Sun.COM * interrupt mask to avoid bogus interrupts.
9708611SSherry.Moore@Sun.COM */
9718611SSherry.Moore@Sun.COM OUTL(dp, IMR, 0);
9728611SSherry.Moore@Sun.COM
9738611SSherry.Moore@Sun.COM /* stop TX and RX immediately */
9748611SSherry.Moore@Sun.COM OUTL(dp, CR, CR_TXR | CR_RXR);
9758611SSherry.Moore@Sun.COM
9768611SSherry.Moore@Sun.COM done = 0;
9778611SSherry.Moore@Sun.COM for (i = 0; done != (ISR_RXRCMP | ISR_TXRCMP); i++) {
9788611SSherry.Moore@Sun.COM if (i > 1000) {
9798611SSherry.Moore@Sun.COM /*
9808611SSherry.Moore@Sun.COM * As gem layer will call sfe_reset_chip(),
9818611SSherry.Moore@Sun.COM * we don't neet to reset futher
9828611SSherry.Moore@Sun.COM */
9838611SSherry.Moore@Sun.COM
9848611SSherry.Moore@Sun.COM return (DDI_FAILURE);
9858611SSherry.Moore@Sun.COM }
9868611SSherry.Moore@Sun.COM val = INL(dp, ISR);
9878611SSherry.Moore@Sun.COM done |= val & (ISR_RXRCMP | ISR_TXRCMP);
9888611SSherry.Moore@Sun.COM lp->isr_pended |= val & lp->our_intr_bits;
9898611SSherry.Moore@Sun.COM drv_usecwait(10);
9908611SSherry.Moore@Sun.COM }
9918611SSherry.Moore@Sun.COM return (DDI_SUCCESS);
9928611SSherry.Moore@Sun.COM }
9938611SSherry.Moore@Sun.COM #endif
9948611SSherry.Moore@Sun.COM
9955748Sduboff /*
9965748Sduboff * Setup media mode
9975748Sduboff */
9985748Sduboff static uint_t
9995748Sduboff sfe_mxdma_value[] = { 512, 4, 8, 16, 32, 64, 128, 256, };
10005748Sduboff
10015748Sduboff static uint_t
sfe_encode_mxdma(uint_t burstsize)10025748Sduboff sfe_encode_mxdma(uint_t burstsize)
10035748Sduboff {
10045748Sduboff int i;
10055748Sduboff
10065748Sduboff if (burstsize > 256) {
10075748Sduboff /* choose 512 */
10085748Sduboff return (0);
10095748Sduboff }
10105748Sduboff
10115748Sduboff for (i = 1; i < 8; i++) {
10125748Sduboff if (burstsize <= sfe_mxdma_value[i]) {
10135748Sduboff break;
10145748Sduboff }
10155748Sduboff }
10165748Sduboff return (i);
10175748Sduboff }
10185748Sduboff
10195748Sduboff static int
sfe_set_media(struct gem_dev * dp)10205748Sduboff sfe_set_media(struct gem_dev *dp)
10215748Sduboff {
10225748Sduboff uint32_t txcfg;
10235748Sduboff uint32_t rxcfg;
10245748Sduboff uint32_t pcr;
10255748Sduboff uint32_t val;
10265748Sduboff uint32_t txmxdma;
10275748Sduboff uint32_t rxmxdma;
10285748Sduboff struct sfe_dev *lp = dp->private;
10295748Sduboff #ifdef DEBUG_LEVEL
10305748Sduboff extern int gem_speed_value[];
10315748Sduboff #endif
10325748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: %s: %s duplex, %d Mbps",
10335748Sduboff dp->name, __func__,
10345748Sduboff dp->full_duplex ? "full" : "half", gem_speed_value[dp->speed]));
10355748Sduboff
10365748Sduboff /* initialize txcfg and rxcfg */
10375748Sduboff txcfg = TXCFG_ATP;
10385748Sduboff if (dp->full_duplex) {
10395748Sduboff txcfg |= (TXCFG_CSI | TXCFG_HBI);
10405748Sduboff }
10417116Sduboff rxcfg = RXCFG_AEP | RXCFG_ARP;
10425748Sduboff if (dp->full_duplex) {
10435748Sduboff rxcfg |= RXCFG_ATX;
10445748Sduboff }
10455748Sduboff
10465748Sduboff /* select txmxdma and rxmxdma, maxmum burst length */
10475748Sduboff if (lp->chip->chip_type == CHIPTYPE_SIS900) {
10485748Sduboff #ifdef DEBUG_SIS900_EDB
10495748Sduboff val = CFG_EDB_MASTER;
10505748Sduboff #else
10515748Sduboff val = INL(dp, CFG) & CFG_EDB_MASTER;
10525748Sduboff #endif
10535748Sduboff if (val) {
10545748Sduboff /*
10555748Sduboff * sis900 built-in cores:
10565748Sduboff * max burst length must be fixed to 64
10575748Sduboff */
10585748Sduboff txmxdma = 64;
10595748Sduboff rxmxdma = 64;
10605748Sduboff } else {
10615748Sduboff /*
10625748Sduboff * sis900 pci chipset:
10635748Sduboff * the vendor recommended to fix max burst length
10645748Sduboff * to 512
10655748Sduboff */
10665748Sduboff txmxdma = 512;
10675748Sduboff rxmxdma = 512;
10685748Sduboff }
10695748Sduboff } else {
10705748Sduboff /*
10715748Sduboff * NS dp83815/816:
10725748Sduboff * use user defined or default for tx/rx max burst length
10735748Sduboff */
10745748Sduboff txmxdma = max(dp->txmaxdma, 256);
10755748Sduboff rxmxdma = max(dp->rxmaxdma, 256);
10765748Sduboff }
10775748Sduboff
10785748Sduboff
10795748Sduboff /* tx high water mark */
10805748Sduboff lp->tx_drain_threshold = ROUNDUP2(dp->txthr, TXCFG_FIFO_UNIT);
10815748Sduboff
10825748Sduboff /* determine tx_fill_threshold accroding drain threshold */
10835748Sduboff lp->tx_fill_threshold =
10845748Sduboff TXFIFOSIZE - lp->tx_drain_threshold - TXCFG_FIFO_UNIT;
10855748Sduboff
10865748Sduboff /* tune txmxdma not to exceed tx_fill_threshold */
10875748Sduboff for (; ; ) {
10885748Sduboff /* normalize txmxdma requested */
10895748Sduboff val = sfe_encode_mxdma(txmxdma);
10905748Sduboff txmxdma = sfe_mxdma_value[val];
10915748Sduboff
10925748Sduboff if (txmxdma <= lp->tx_fill_threshold) {
10935748Sduboff break;
10945748Sduboff }
10955748Sduboff /* select new txmxdma */
10965748Sduboff txmxdma = txmxdma / 2;
10975748Sduboff }
10985748Sduboff txcfg |= val << TXCFG_MXDMA_SHIFT;
10995748Sduboff
11005748Sduboff /* encode rxmxdma, maxmum burst length for rx */
11015748Sduboff val = sfe_encode_mxdma(rxmxdma);
11027116Sduboff rxcfg |= val << RXCFG_MXDMA_SHIFT;
11035748Sduboff rxmxdma = sfe_mxdma_value[val];
11045748Sduboff
11055748Sduboff /* receive starting threshold - it have only 5bit-wide field */
11065748Sduboff val = ROUNDUP2(max(dp->rxthr, ETHERMIN), RXCFG_FIFO_UNIT);
11075748Sduboff lp->rx_drain_threshold =
11085748Sduboff min(val, (RXCFG_DRTH >> RXCFG_DRTH_SHIFT) * RXCFG_FIFO_UNIT);
11095748Sduboff
11105748Sduboff DPRINTF(0, (CE_CONT,
11115748Sduboff "%s: %s: tx: drain:%d(rest %d) fill:%d mxdma:%d,"
11125748Sduboff " rx: drain:%d mxdma:%d",
11135748Sduboff dp->name, __func__,
11145748Sduboff lp->tx_drain_threshold, TXFIFOSIZE - lp->tx_drain_threshold,
11155748Sduboff lp->tx_fill_threshold, txmxdma,
11165748Sduboff lp->rx_drain_threshold, rxmxdma));
11175748Sduboff
11185748Sduboff ASSERT(lp->tx_drain_threshold < 64*TXCFG_FIFO_UNIT);
11195748Sduboff ASSERT(lp->tx_fill_threshold < 64*TXCFG_FIFO_UNIT);
11205748Sduboff ASSERT(lp->rx_drain_threshold < 32*RXCFG_FIFO_UNIT);
11215748Sduboff
11225748Sduboff txcfg |= ((lp->tx_fill_threshold/TXCFG_FIFO_UNIT) << TXCFG_FLTH_SHIFT)
11235748Sduboff | (lp->tx_drain_threshold/TXCFG_FIFO_UNIT);
11245748Sduboff OUTL(dp, TXCFG, txcfg);
11255748Sduboff
11265748Sduboff rxcfg |= ((lp->rx_drain_threshold/RXCFG_FIFO_UNIT) << RXCFG_DRTH_SHIFT);
11275748Sduboff if (lp->chip->chip_type == CHIPTYPE_DP83815) {
11285748Sduboff rxcfg |= RXCFG_ALP_DP83815;
11295748Sduboff }
11305748Sduboff OUTL(dp, RXCFG, rxcfg);
11315748Sduboff
11325748Sduboff DPRINTF(0, (CE_CONT, CONS "%s: %s: txcfg:%b rxcfg:%b",
11335748Sduboff dp->name, __func__,
11345748Sduboff txcfg, TXCFG_BITS, rxcfg, RXCFG_BITS));
11355748Sduboff
11365748Sduboff /* Flow control */
11375748Sduboff if (lp->chip->chip_type == CHIPTYPE_DP83815) {
11385748Sduboff pcr = INL(dp, PCR);
11395748Sduboff switch (dp->flow_control) {
11405748Sduboff case FLOW_CONTROL_SYMMETRIC:
11415748Sduboff case FLOW_CONTROL_RX_PAUSE:
11425748Sduboff OUTL(dp, PCR, pcr | PCR_PSEN | PCR_PS_MCAST);
11435748Sduboff break;
11445748Sduboff
11455748Sduboff default:
11465748Sduboff OUTL(dp, PCR,
11475748Sduboff pcr & ~(PCR_PSEN | PCR_PS_MCAST | PCR_PS_DA));
11485748Sduboff break;
11495748Sduboff }
11505748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: PCR: %b", dp->name,
11515748Sduboff INL(dp, PCR), PCR_BITS));
11525748Sduboff
11535748Sduboff } else if (lp->chip->chip_type == CHIPTYPE_SIS900) {
11545748Sduboff switch (dp->flow_control) {
11555748Sduboff case FLOW_CONTROL_SYMMETRIC:
11565748Sduboff case FLOW_CONTROL_RX_PAUSE:
11575748Sduboff OUTL(dp, FLOWCTL, FLOWCTL_FLOWEN);
11585748Sduboff break;
11595748Sduboff default:
11605748Sduboff OUTL(dp, FLOWCTL, 0);
11615748Sduboff break;
11625748Sduboff }
11635748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: FLOWCTL: %b",
11645748Sduboff dp->name, INL(dp, FLOWCTL), FLOWCTL_BITS));
11655748Sduboff }
11665748Sduboff return (GEM_SUCCESS);
11675748Sduboff }
11685748Sduboff
11695748Sduboff static int
sfe_get_stats(struct gem_dev * dp)11705748Sduboff sfe_get_stats(struct gem_dev *dp)
11715748Sduboff {
11725748Sduboff /* do nothing */
11735748Sduboff return (GEM_SUCCESS);
11745748Sduboff }
11755748Sduboff
11765748Sduboff /*
11775748Sduboff * descriptor manipulations
11785748Sduboff */
11795748Sduboff static int
sfe_tx_desc_write(struct gem_dev * dp,int slot,ddi_dma_cookie_t * dmacookie,int frags,uint64_t flags)11805748Sduboff sfe_tx_desc_write(struct gem_dev *dp, int slot,
11815748Sduboff ddi_dma_cookie_t *dmacookie, int frags, uint64_t flags)
11825748Sduboff {
11835748Sduboff uint32_t mark;
11845748Sduboff struct sfe_desc *tdp;
11855748Sduboff ddi_dma_cookie_t *dcp;
11867116Sduboff uint32_t tmp0;
11877116Sduboff #if DEBUG_LEVEL > 2
11885748Sduboff int i;
11895748Sduboff
11905748Sduboff cmn_err(CE_CONT,
11915748Sduboff CONS "%s: time:%d %s seqnum: %d, slot %d, frags: %d flags: %llx",
11925748Sduboff dp->name, ddi_get_lbolt(), __func__,
11935748Sduboff dp->tx_desc_tail, slot, frags, flags);
11945748Sduboff
11955748Sduboff for (i = 0; i < frags; i++) {
11965748Sduboff cmn_err(CE_CONT, CONS "%d: addr: 0x%x, len: 0x%x",
11975748Sduboff i, dmacookie[i].dmac_address, dmacookie[i].dmac_size);
11987116Sduboff }
11995748Sduboff #endif
12005748Sduboff /*
12015748Sduboff * write tx descriptor in reversed order.
12025748Sduboff */
12035748Sduboff #if DEBUG_LEVEL > 3
12045748Sduboff flags |= GEM_TXFLAG_INTR;
12055748Sduboff #endif
12065748Sduboff mark = (flags & GEM_TXFLAG_INTR)
12077116Sduboff ? (CMDSTS_OWN | CMDSTS_INTR) : CMDSTS_OWN;
12085748Sduboff
12095748Sduboff ASSERT(frags == 1);
12105748Sduboff dcp = &dmacookie[0];
12115748Sduboff if (flags & GEM_TXFLAG_HEAD) {
12125748Sduboff mark &= ~CMDSTS_OWN;
12135748Sduboff }
12145748Sduboff
12155748Sduboff tdp = (void *)&dp->tx_ring[SFE_DESC_SIZE * slot];
12167116Sduboff tmp0 = (uint32_t)dcp->dmac_address;
12177116Sduboff mark |= (uint32_t)dcp->dmac_size;
12187116Sduboff tdp->d_bufptr = LE_32(tmp0);
12197116Sduboff tdp->d_cmdsts = LE_32(mark);
12205748Sduboff
12215748Sduboff return (frags);
12225748Sduboff }
12235748Sduboff
12245748Sduboff static void
sfe_tx_start(struct gem_dev * dp,int start_slot,int nslot)12255748Sduboff sfe_tx_start(struct gem_dev *dp, int start_slot, int nslot)
12265748Sduboff {
12277116Sduboff uint_t tx_ring_size = dp->gc.gc_tx_ring_size;
12285748Sduboff struct sfe_desc *tdp;
12295748Sduboff struct sfe_dev *lp = dp->private;
12305748Sduboff
12315748Sduboff if (nslot > 1) {
12325748Sduboff gem_tx_desc_dma_sync(dp,
12337116Sduboff SLOT(start_slot + 1, tx_ring_size),
12345748Sduboff nslot - 1, DDI_DMA_SYNC_FORDEV);
12355748Sduboff }
12365748Sduboff
12375748Sduboff tdp = (void *)&dp->tx_ring[SFE_DESC_SIZE * start_slot];
12385748Sduboff tdp->d_cmdsts |= LE_32(CMDSTS_OWN);
12395748Sduboff
12405748Sduboff gem_tx_desc_dma_sync(dp, start_slot, 1, DDI_DMA_SYNC_FORDEV);
12415748Sduboff
12425748Sduboff /*
12435748Sduboff * Let the Transmit Buffer Manager Fill state machine active.
12445748Sduboff */
12455748Sduboff if (dp->mac_active) {
12465748Sduboff OUTL(dp, CR, lp->cr | CR_TXE);
12475748Sduboff }
12485748Sduboff }
12495748Sduboff
12505748Sduboff static void
sfe_rx_desc_write(struct gem_dev * dp,int slot,ddi_dma_cookie_t * dmacookie,int frags)12515748Sduboff sfe_rx_desc_write(struct gem_dev *dp, int slot,
12525748Sduboff ddi_dma_cookie_t *dmacookie, int frags)
12535748Sduboff {
12545748Sduboff struct sfe_desc *rdp;
12557116Sduboff uint32_t tmp0;
12567116Sduboff uint32_t tmp1;
12575748Sduboff #if DEBUG_LEVEL > 2
12585748Sduboff int i;
12595748Sduboff
12605748Sduboff ASSERT(frags == 1);
12615748Sduboff
12625748Sduboff cmn_err(CE_CONT, CONS
12635748Sduboff "%s: %s seqnum: %d, slot %d, frags: %d",
12645748Sduboff dp->name, __func__, dp->rx_active_tail, slot, frags);
12655748Sduboff for (i = 0; i < frags; i++) {
12665748Sduboff cmn_err(CE_CONT, CONS " frag: %d addr: 0x%llx, len: 0x%lx",
12675748Sduboff i, dmacookie[i].dmac_address, dmacookie[i].dmac_size);
12685748Sduboff }
12695748Sduboff #endif
12705748Sduboff /* for the last slot of the packet */
12715748Sduboff rdp = (void *)&dp->rx_ring[SFE_DESC_SIZE * slot];
12725748Sduboff
12737116Sduboff tmp0 = (uint32_t)dmacookie->dmac_address;
12747116Sduboff tmp1 = CMDSTS_INTR | (uint32_t)dmacookie->dmac_size;
12757116Sduboff rdp->d_bufptr = LE_32(tmp0);
12767116Sduboff rdp->d_cmdsts = LE_32(tmp1);
12775748Sduboff }
12785748Sduboff
12795748Sduboff static uint_t
sfe_tx_desc_stat(struct gem_dev * dp,int slot,int ndesc)12805748Sduboff sfe_tx_desc_stat(struct gem_dev *dp, int slot, int ndesc)
12815748Sduboff {
12827116Sduboff uint_t tx_ring_size = dp->gc.gc_tx_ring_size;
12835748Sduboff struct sfe_desc *tdp;
12845748Sduboff uint32_t status;
12855748Sduboff int cols;
12867116Sduboff struct sfe_dev *lp = dp->private;
12875748Sduboff #ifdef DEBUG_LEVEL
12885748Sduboff int i;
12895748Sduboff clock_t delay;
12905748Sduboff #endif
12915748Sduboff /* check status of the last descriptor */
12925748Sduboff tdp = (void *)
12937116Sduboff &dp->tx_ring[SFE_DESC_SIZE * SLOT(slot + ndesc - 1, tx_ring_size)];
12945748Sduboff
12957116Sduboff /*
12967116Sduboff * Don't use LE_32() directly to refer tdp->d_cmdsts.
12977116Sduboff * It is not atomic for big endian cpus.
12987116Sduboff */
12997116Sduboff status = tdp->d_cmdsts;
13007116Sduboff status = LE_32(status);
13015748Sduboff
13025748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: time:%ld %s: slot:%d, status:0x%b",
13035748Sduboff dp->name, ddi_get_lbolt(), __func__,
13045748Sduboff slot, status, TXSTAT_BITS));
13055748Sduboff
13065748Sduboff if (status & CMDSTS_OWN) {
13075748Sduboff /*
13085748Sduboff * not yet transmitted
13095748Sduboff */
13107116Sduboff /* workaround for tx hang */
13117116Sduboff if (lp->chip->chip_type == CHIPTYPE_DP83815 &&
13127116Sduboff dp->mac_active) {
13137116Sduboff OUTL(dp, CR, lp->cr | CR_TXE);
13147116Sduboff }
13155748Sduboff return (0);
13165748Sduboff }
13175748Sduboff
13185748Sduboff if (status & CMDSTS_MORE) {
13195748Sduboff /* XXX - the hardware problem but don't panic the system */
13205748Sduboff /* avoid lint bug for %b format string including 32nd bit */
13215748Sduboff cmn_err(CE_NOTE, CONS
13225748Sduboff "%s: tx status bits incorrect: slot:%d, status:0x%x",
13235748Sduboff dp->name, slot, status);
13245748Sduboff }
13255748Sduboff
13265748Sduboff #if DEBUG_LEVEL > 3
13275748Sduboff delay = (ddi_get_lbolt() - dp->tx_buf_head->txb_stime) * 10;
13285748Sduboff if (delay >= 50) {
13295748Sduboff DPRINTF(0, (CE_NOTE, "%s: tx deferred %d mS: slot %d",
13305748Sduboff dp->name, delay, slot));
13315748Sduboff }
13325748Sduboff #endif
13335748Sduboff
13345748Sduboff #if DEBUG_LEVEL > 3
13355748Sduboff for (i = 0; i < nfrag-1; i++) {
13365748Sduboff uint32_t s;
13375748Sduboff int n;
13385748Sduboff
13397116Sduboff n = SLOT(slot + i, tx_ring_size);
13405748Sduboff s = LE_32(
13415748Sduboff ((struct sfe_desc *)((void *)
13425748Sduboff &dp->tx_ring[SFE_DESC_SIZE * n]))->d_cmdsts);
13435748Sduboff
13445748Sduboff ASSERT(s & CMDSTS_MORE);
13455748Sduboff ASSERT((s & CMDSTS_OWN) == 0);
13465748Sduboff }
13475748Sduboff #endif
13485748Sduboff
13495748Sduboff /*
13505748Sduboff * collect statistics
13515748Sduboff */
13525748Sduboff if ((status & CMDSTS_OK) == 0) {
13535748Sduboff
13545748Sduboff /* failed to transmit the packet */
13555748Sduboff
13565748Sduboff DPRINTF(0, (CE_CONT, CONS "%s: Transmit error, Tx status %b",
13575748Sduboff dp->name, status, TXSTAT_BITS));
13585748Sduboff
13595748Sduboff dp->stats.errxmt++;
13605748Sduboff
13615748Sduboff if (status & CMDSTS_TFU) {
13625748Sduboff dp->stats.underflow++;
13635748Sduboff } else if (status & CMDSTS_CRS) {
13645748Sduboff dp->stats.nocarrier++;
13655748Sduboff } else if (status & CMDSTS_OWC) {
13665748Sduboff dp->stats.xmtlatecoll++;
13675748Sduboff } else if ((!dp->full_duplex) && (status & CMDSTS_EC)) {
13685748Sduboff dp->stats.excoll++;
13695748Sduboff dp->stats.collisions += 16;
13705748Sduboff } else {
13715748Sduboff dp->stats.xmit_internal_err++;
13725748Sduboff }
13735748Sduboff } else if (!dp->full_duplex) {
13745748Sduboff cols = (status >> CMDSTS_CCNT_SHIFT) & CCNT_MASK;
13755748Sduboff
13765748Sduboff if (cols > 0) {
13775748Sduboff if (cols == 1) {
13785748Sduboff dp->stats.first_coll++;
13795748Sduboff } else /* (cols > 1) */ {
13805748Sduboff dp->stats.multi_coll++;
13815748Sduboff }
13825748Sduboff dp->stats.collisions += cols;
13835748Sduboff } else if (status & CMDSTS_TD) {
13845748Sduboff dp->stats.defer++;
13855748Sduboff }
13865748Sduboff }
13875748Sduboff return (GEM_TX_DONE);
13885748Sduboff }
13895748Sduboff
13905748Sduboff static uint64_t
sfe_rx_desc_stat(struct gem_dev * dp,int slot,int ndesc)13915748Sduboff sfe_rx_desc_stat(struct gem_dev *dp, int slot, int ndesc)
13925748Sduboff {
13935748Sduboff struct sfe_desc *rdp;
13945748Sduboff uint_t len;
13955748Sduboff uint_t flag;
13965748Sduboff uint32_t status;
13975748Sduboff
13985748Sduboff flag = GEM_RX_DONE;
13995748Sduboff
14005748Sduboff /* Dont read ISR because we cannot ack only to rx interrupt. */
14015748Sduboff
14025748Sduboff rdp = (void *)&dp->rx_ring[SFE_DESC_SIZE * slot];
14035748Sduboff
14047116Sduboff /*
14057116Sduboff * Don't use LE_32() directly to refer rdp->d_cmdsts.
14067116Sduboff * It is not atomic for big endian cpus.
14077116Sduboff */
14087116Sduboff status = rdp->d_cmdsts;
14097116Sduboff status = LE_32(status);
14105748Sduboff
14115748Sduboff DPRINTF(2, (CE_CONT, CONS "%s: time:%ld %s: slot:%d, status:0x%b",
14125748Sduboff dp->name, ddi_get_lbolt(), __func__,
14135748Sduboff slot, status, RXSTAT_BITS));
14145748Sduboff
14155748Sduboff if ((status & CMDSTS_OWN) == 0) {
14165748Sduboff /*
14175748Sduboff * No more received packets because
14185748Sduboff * this buffer is owned by NIC.
14195748Sduboff */
14205748Sduboff return (0);
14215748Sduboff }
14225748Sduboff
14235748Sduboff #define RX_ERR_BITS \
14245748Sduboff (CMDSTS_RXA | CMDSTS_RXO | CMDSTS_LONG | CMDSTS_RUNT | \
14255748Sduboff CMDSTS_ISE | CMDSTS_CRCE | CMDSTS_FAE | CMDSTS_MORE)
14265748Sduboff
14275748Sduboff if (status & RX_ERR_BITS) {
14285748Sduboff /*
14295748Sduboff * Packet with error received
14305748Sduboff */
14315748Sduboff DPRINTF(0, (CE_CONT, CONS "%s: Corrupted packet "
14325748Sduboff "received, buffer status: %b",
14335748Sduboff dp->name, status, RXSTAT_BITS));
14345748Sduboff
14355748Sduboff /* collect statistics information */
14365748Sduboff dp->stats.errrcv++;
14375748Sduboff
14385748Sduboff if (status & CMDSTS_RXO) {
14395748Sduboff dp->stats.overflow++;
14405748Sduboff } else if (status & (CMDSTS_LONG | CMDSTS_MORE)) {
14415748Sduboff dp->stats.frame_too_long++;
14425748Sduboff } else if (status & CMDSTS_RUNT) {
14435748Sduboff dp->stats.runt++;
14445748Sduboff } else if (status & (CMDSTS_ISE | CMDSTS_FAE)) {
14455748Sduboff dp->stats.frame++;
14465748Sduboff } else if (status & CMDSTS_CRCE) {
14475748Sduboff dp->stats.crc++;
14485748Sduboff } else {
14495748Sduboff dp->stats.rcv_internal_err++;
14505748Sduboff }
14515748Sduboff
14525748Sduboff return (flag | GEM_RX_ERR);
14535748Sduboff }
14545748Sduboff
14555748Sduboff /*
14565748Sduboff * this packet was received without errors
14575748Sduboff */
14585748Sduboff if ((len = (status & CMDSTS_SIZE)) >= ETHERFCSL) {
14595748Sduboff len -= ETHERFCSL;
14605748Sduboff }
14615748Sduboff
14625748Sduboff #if DEBUG_LEVEL > 10
14635748Sduboff {
14645748Sduboff int i;
14655748Sduboff uint8_t *bp = dp->rx_buf_head->rxb_buf;
14665748Sduboff
14675748Sduboff cmn_err(CE_CONT, CONS "%s: len:%d", dp->name, len);
14685748Sduboff
14695748Sduboff for (i = 0; i < 60; i += 10) {
14705748Sduboff cmn_err(CE_CONT, CONS
14715748Sduboff "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
14725748Sduboff bp[0], bp[1], bp[2], bp[3], bp[4],
14735748Sduboff bp[5], bp[6], bp[7], bp[8], bp[9]);
14745748Sduboff }
14755748Sduboff bp += 10;
14765748Sduboff }
14775748Sduboff #endif
14785748Sduboff return (flag | (len & GEM_RX_LEN));
14795748Sduboff }
14805748Sduboff
14815748Sduboff static void
sfe_tx_desc_init(struct gem_dev * dp,int slot)14825748Sduboff sfe_tx_desc_init(struct gem_dev *dp, int slot)
14835748Sduboff {
14847116Sduboff uint_t tx_ring_size = dp->gc.gc_tx_ring_size;
14855748Sduboff struct sfe_desc *tdp;
14865748Sduboff uint32_t here;
14875748Sduboff
14885748Sduboff tdp = (void *)&dp->tx_ring[SFE_DESC_SIZE * slot];
14895748Sduboff
14905748Sduboff /* don't clear d_link field, which have a valid pointer */
14915748Sduboff tdp->d_cmdsts = 0;
14925748Sduboff
14935748Sduboff /* make a link to this from the previous descriptor */
14945748Sduboff here = ((uint32_t)dp->tx_ring_dma) + SFE_DESC_SIZE*slot;
14955748Sduboff
14965748Sduboff tdp = (void *)
14977116Sduboff &dp->tx_ring[SFE_DESC_SIZE * SLOT(slot - 1, tx_ring_size)];
14985748Sduboff tdp->d_link = LE_32(here);
14995748Sduboff }
15005748Sduboff
15015748Sduboff static void
sfe_rx_desc_init(struct gem_dev * dp,int slot)15025748Sduboff sfe_rx_desc_init(struct gem_dev *dp, int slot)
15035748Sduboff {
15047116Sduboff uint_t rx_ring_size = dp->gc.gc_rx_ring_size;
15055748Sduboff struct sfe_desc *rdp;
15065748Sduboff uint32_t here;
15075748Sduboff
15085748Sduboff rdp = (void *)&dp->rx_ring[SFE_DESC_SIZE * slot];
15095748Sduboff
15105748Sduboff /* don't clear d_link field, which have a valid pointer */
15115748Sduboff rdp->d_cmdsts = LE_32(CMDSTS_OWN);
15125748Sduboff
15135748Sduboff /* make a link to this from the previous descriptor */
15145748Sduboff here = ((uint32_t)dp->rx_ring_dma) + SFE_DESC_SIZE*slot;
15155748Sduboff
15165748Sduboff rdp = (void *)
15177116Sduboff &dp->rx_ring[SFE_DESC_SIZE * SLOT(slot - 1, rx_ring_size)];
15185748Sduboff rdp->d_link = LE_32(here);
15195748Sduboff }
15205748Sduboff
15215748Sduboff static void
sfe_tx_desc_clean(struct gem_dev * dp,int slot)15225748Sduboff sfe_tx_desc_clean(struct gem_dev *dp, int slot)
15235748Sduboff {
15245748Sduboff struct sfe_desc *tdp;
15255748Sduboff
15265748Sduboff tdp = (void *)&dp->tx_ring[SFE_DESC_SIZE * slot];
15275748Sduboff tdp->d_cmdsts = 0;
15285748Sduboff }
15295748Sduboff
15305748Sduboff static void
sfe_rx_desc_clean(struct gem_dev * dp,int slot)15315748Sduboff sfe_rx_desc_clean(struct gem_dev *dp, int slot)
15325748Sduboff {
15335748Sduboff struct sfe_desc *rdp;
15345748Sduboff
15355748Sduboff rdp = (void *)&dp->rx_ring[SFE_DESC_SIZE * slot];
15365748Sduboff rdp->d_cmdsts = LE_32(CMDSTS_OWN);
15375748Sduboff }
15385748Sduboff
15395748Sduboff /*
15405748Sduboff * Device depend interrupt handler
15415748Sduboff */
15425748Sduboff static uint_t
sfe_interrupt(struct gem_dev * dp)15435748Sduboff sfe_interrupt(struct gem_dev *dp)
15445748Sduboff {
15457116Sduboff uint_t rx_ring_size = dp->gc.gc_rx_ring_size;
15465748Sduboff uint32_t isr;
15477116Sduboff uint32_t isr_bogus;
15485748Sduboff uint_t flags = 0;
15495748Sduboff boolean_t need_to_reset = B_FALSE;
15505748Sduboff struct sfe_dev *lp = dp->private;
15515748Sduboff
15525748Sduboff /* read reason and clear interrupt */
15535748Sduboff isr = INL(dp, ISR);
15545748Sduboff
15557116Sduboff isr_bogus = lp->isr_pended;
15567116Sduboff lp->isr_pended = 0;
15577116Sduboff
15587116Sduboff if (((isr | isr_bogus) & lp->our_intr_bits) == 0) {
15595748Sduboff /* we are not the interrupt source */
15605748Sduboff return (DDI_INTR_UNCLAIMED);
15615748Sduboff }
15625748Sduboff
15635748Sduboff DPRINTF(3, (CE_CONT,
15645748Sduboff CONS "%s: time:%ld %s:called: isr:0x%b rx_active_head: %d",
15655748Sduboff dp->name, ddi_get_lbolt(), __func__,
15665748Sduboff isr, INTR_BITS, dp->rx_active_head));
15675748Sduboff
15685748Sduboff if (!dp->mac_active) {
15695748Sduboff /* the device is going to stop */
15705748Sduboff lp->our_intr_bits = 0;
15715748Sduboff return (DDI_INTR_CLAIMED);
15725748Sduboff }
15735748Sduboff
15745748Sduboff isr &= lp->our_intr_bits;
15755748Sduboff
15765748Sduboff if (isr & (ISR_RXSOVR | ISR_RXORN | ISR_RXIDLE | ISR_RXERR |
15775748Sduboff ISR_RXDESC | ISR_RXOK)) {
15785748Sduboff (void) gem_receive(dp);
15795748Sduboff
15805748Sduboff if (isr & (ISR_RXSOVR | ISR_RXORN)) {
15815748Sduboff DPRINTF(0, (CE_CONT,
15825748Sduboff CONS "%s: rx fifo overrun: isr %b",
15835748Sduboff dp->name, isr, INTR_BITS));
15845748Sduboff /* no need restart rx */
15855748Sduboff dp->stats.overflow++;
15865748Sduboff }
15875748Sduboff
15885748Sduboff if (isr & ISR_RXIDLE) {
15895748Sduboff DPRINTF(0, (CE_CONT,
15905748Sduboff CONS "%s: rx buffer ran out: isr %b",
15915748Sduboff dp->name, isr, INTR_BITS));
15925748Sduboff
15935748Sduboff dp->stats.norcvbuf++;
15945748Sduboff
15955748Sduboff /*
15965748Sduboff * Make RXDP points the head of receive
15975748Sduboff * buffer list.
15985748Sduboff */
15995748Sduboff OUTL(dp, RXDP, dp->rx_ring_dma +
16005748Sduboff SFE_DESC_SIZE *
16017116Sduboff SLOT(dp->rx_active_head, rx_ring_size));
16025748Sduboff
16035748Sduboff /* Restart the receive engine */
16045748Sduboff OUTL(dp, CR, lp->cr | CR_RXE);
16055748Sduboff }
16065748Sduboff }
16075748Sduboff
16085748Sduboff if (isr & (ISR_TXURN | ISR_TXERR | ISR_TXDESC |
16095748Sduboff ISR_TXIDLE | ISR_TXOK)) {
16105748Sduboff /* need to reclaim tx buffers */
16115748Sduboff if (gem_tx_done(dp)) {
16125748Sduboff flags |= INTR_RESTART_TX;
16135748Sduboff }
16145748Sduboff /*
16155748Sduboff * XXX - tx error statistics will be counted in
16165748Sduboff * sfe_tx_desc_stat() and no need to restart tx on errors.
16175748Sduboff */
16185748Sduboff }
16195748Sduboff
16205748Sduboff if (isr & (ISR_DPERR | ISR_SSERR | ISR_RMABT | ISR_RTABT)) {
16215748Sduboff cmn_err(CE_WARN, "%s: ERROR interrupt: isr %b.",
16225748Sduboff dp->name, isr, INTR_BITS);
16235748Sduboff need_to_reset = B_TRUE;
16245748Sduboff }
16255748Sduboff reset:
16265748Sduboff if (need_to_reset) {
16275748Sduboff (void) gem_restart_nic(dp, GEM_RESTART_KEEP_BUF);
16285748Sduboff flags |= INTR_RESTART_TX;
16295748Sduboff }
16305748Sduboff
16315748Sduboff DPRINTF(5, (CE_CONT, CONS "%s: %s: return: isr: %b",
16325748Sduboff dp->name, __func__, isr, INTR_BITS));
16335748Sduboff
16345748Sduboff return (DDI_INTR_CLAIMED | flags);
16355748Sduboff }
16365748Sduboff
16375748Sduboff /* ======================================================== */
16385748Sduboff /*
16395748Sduboff * HW depend MII routine
16405748Sduboff */
16415748Sduboff /* ======================================================== */
16425748Sduboff
16435748Sduboff /*
16445748Sduboff * MII routines for NS DP83815
16455748Sduboff */
16465748Sduboff static void
sfe_mii_sync_dp83815(struct gem_dev * dp)16475748Sduboff sfe_mii_sync_dp83815(struct gem_dev *dp)
16485748Sduboff {
16495748Sduboff /* do nothing */
16505748Sduboff }
16515748Sduboff
16525748Sduboff static uint16_t
sfe_mii_read_dp83815(struct gem_dev * dp,uint_t offset)16535748Sduboff sfe_mii_read_dp83815(struct gem_dev *dp, uint_t offset)
16545748Sduboff {
16555748Sduboff DPRINTF(4, (CE_CONT, CONS"%s: %s: offset 0x%x",
16565748Sduboff dp->name, __func__, offset));
16575748Sduboff return ((uint16_t)INL(dp, MII_REGS_BASE + offset*4));
16585748Sduboff }
16595748Sduboff
16605748Sduboff static void
sfe_mii_write_dp83815(struct gem_dev * dp,uint_t offset,uint16_t val)16615748Sduboff sfe_mii_write_dp83815(struct gem_dev *dp, uint_t offset, uint16_t val)
16625748Sduboff {
16635748Sduboff DPRINTF(4, (CE_CONT, CONS"%s: %s: offset 0x%x 0x%x",
16645748Sduboff dp->name, __func__, offset, val));
16655748Sduboff OUTL(dp, MII_REGS_BASE + offset*4, val);
16665748Sduboff }
16675748Sduboff
16685748Sduboff static int
sfe_mii_config_dp83815(struct gem_dev * dp)16695748Sduboff sfe_mii_config_dp83815(struct gem_dev *dp)
16705748Sduboff {
16715748Sduboff uint32_t srr;
16725748Sduboff
16735748Sduboff srr = INL(dp, SRR) & SRR_REV;
16745748Sduboff
16755748Sduboff DPRINTF(0, (CE_CONT, CONS "%s: srr:0x%04x %04x %04x %04x %04x %04x",
16765748Sduboff dp->name, srr,
16775748Sduboff INW(dp, 0x00cc), /* PGSEL */
16785748Sduboff INW(dp, 0x00e4), /* PMDCSR */
16795748Sduboff INW(dp, 0x00fc), /* TSTDAT */
16805748Sduboff INW(dp, 0x00f4), /* DSPCFG */
16815748Sduboff INW(dp, 0x00f8))); /* SDCFG */
16825748Sduboff
16837116Sduboff if (srr == SRR_REV_DP83815CVNG) {
16845748Sduboff /*
16855748Sduboff * NS datasheet says that DP83815CVNG needs following
16865748Sduboff * registers to be patched for optimizing its performance.
16877116Sduboff * A report said that CRC errors on RX disappeared
16885748Sduboff * with the patch.
16895748Sduboff */
16905748Sduboff OUTW(dp, 0x00cc, 0x0001); /* PGSEL */
16915748Sduboff OUTW(dp, 0x00e4, 0x189c); /* PMDCSR */
16925748Sduboff OUTW(dp, 0x00fc, 0x0000); /* TSTDAT */
16935748Sduboff OUTW(dp, 0x00f4, 0x5040); /* DSPCFG */
16945748Sduboff OUTW(dp, 0x00f8, 0x008c); /* SDCFG */
16957116Sduboff OUTW(dp, 0x00cc, 0x0000); /* PGSEL */
16965748Sduboff
16975748Sduboff DPRINTF(0, (CE_CONT,
16985748Sduboff CONS "%s: PHY patched %04x %04x %04x %04x %04x",
16995748Sduboff dp->name,
17005748Sduboff INW(dp, 0x00cc), /* PGSEL */
17015748Sduboff INW(dp, 0x00e4), /* PMDCSR */
17025748Sduboff INW(dp, 0x00fc), /* TSTDAT */
17035748Sduboff INW(dp, 0x00f4), /* DSPCFG */
17045748Sduboff INW(dp, 0x00f8))); /* SDCFG */
17057116Sduboff } else if (((srr ^ SRR_REV_DP83815DVNG) & 0xff00) == 0 ||
17067116Sduboff ((srr ^ SRR_REV_DP83816AVNG) & 0xff00) == 0) {
17077116Sduboff /*
17087116Sduboff * Additional packets for later chipset
17097116Sduboff */
17107116Sduboff OUTW(dp, 0x00cc, 0x0001); /* PGSEL */
17117116Sduboff OUTW(dp, 0x00e4, 0x189c); /* PMDCSR */
17127116Sduboff OUTW(dp, 0x00cc, 0x0000); /* PGSEL */
17137116Sduboff
17147116Sduboff DPRINTF(0, (CE_CONT,
17157116Sduboff CONS "%s: PHY patched %04x %04x",
17167116Sduboff dp->name,
17177116Sduboff INW(dp, 0x00cc), /* PGSEL */
17187116Sduboff INW(dp, 0x00e4))); /* PMDCSR */
17195748Sduboff }
17205748Sduboff
17215748Sduboff return (gem_mii_config_default(dp));
17225748Sduboff }
17235748Sduboff
17247116Sduboff static int
sfe_mii_probe_dp83815(struct gem_dev * dp)17257116Sduboff sfe_mii_probe_dp83815(struct gem_dev *dp)
17267116Sduboff {
17277116Sduboff uint32_t val;
17287116Sduboff
17297116Sduboff /* try external phy first */
17307116Sduboff DPRINTF(0, (CE_CONT, CONS "%s: %s: trying external phy",
17317116Sduboff dp->name, __func__));
17327116Sduboff dp->mii_phy_addr = 0;
17337116Sduboff dp->gc.gc_mii_sync = &sfe_mii_sync_sis900;
17347116Sduboff dp->gc.gc_mii_read = &sfe_mii_read_sis900;
17357116Sduboff dp->gc.gc_mii_write = &sfe_mii_write_sis900;
17367116Sduboff
17377116Sduboff val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
17387116Sduboff OUTL(dp, CFG, val | CFG_EXT_PHY | CFG_PHY_DIS);
17397116Sduboff
17407116Sduboff if (gem_mii_probe_default(dp) == GEM_SUCCESS) {
17417116Sduboff return (GEM_SUCCESS);
17427116Sduboff }
17437116Sduboff
17447116Sduboff /* switch to internal phy */
17457116Sduboff DPRINTF(0, (CE_CONT, CONS "%s: %s: switching to internal phy",
17467116Sduboff dp->name, __func__));
17477116Sduboff dp->mii_phy_addr = -1;
17487116Sduboff dp->gc.gc_mii_sync = &sfe_mii_sync_dp83815;
17497116Sduboff dp->gc.gc_mii_read = &sfe_mii_read_dp83815;
17507116Sduboff dp->gc.gc_mii_write = &sfe_mii_write_dp83815;
17517116Sduboff
17527116Sduboff val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
17537116Sduboff OUTL(dp, CFG, val | CFG_PAUSE_ADV | CFG_PHY_RST);
17547116Sduboff drv_usecwait(100); /* keep to assert RST bit for a while */
17557116Sduboff OUTL(dp, CFG, val | CFG_PAUSE_ADV);
17567116Sduboff
17577116Sduboff /* wait for PHY reset */
17587116Sduboff delay(drv_usectohz(10000));
17597116Sduboff
17607116Sduboff return (gem_mii_probe_default(dp));
17617116Sduboff }
17627116Sduboff
17637116Sduboff static int
sfe_mii_init_dp83815(struct gem_dev * dp)17647116Sduboff sfe_mii_init_dp83815(struct gem_dev *dp)
17657116Sduboff {
17667116Sduboff uint32_t val;
17677116Sduboff
17687116Sduboff val = INL(dp, CFG) & (CFG_ANEG_SEL | CFG_PHY_CFG);
17697116Sduboff
17707116Sduboff if (dp->mii_phy_addr == -1) {
17717116Sduboff /* select internal phy */
17727116Sduboff OUTL(dp, CFG, val | CFG_PAUSE_ADV);
17737116Sduboff } else {
17747116Sduboff /* select external phy */
17757116Sduboff OUTL(dp, CFG, val | CFG_EXT_PHY | CFG_PHY_DIS);
17767116Sduboff }
17777116Sduboff
17787116Sduboff return (GEM_SUCCESS);
17797116Sduboff }
17805748Sduboff
17815748Sduboff /*
17825748Sduboff * MII routines for SiS900
17835748Sduboff */
17847116Sduboff #define MDIO_DELAY(dp) {(void) INL(dp, MEAR); (void) INL(dp, MEAR); }
17855748Sduboff static void
sfe_mii_sync_sis900(struct gem_dev * dp)17865748Sduboff sfe_mii_sync_sis900(struct gem_dev *dp)
17875748Sduboff {
17885748Sduboff int i;
17895748Sduboff
17907116Sduboff /* send 32 ONE's to make MII line idle */
17915748Sduboff for (i = 0; i < 32; i++) {
17925748Sduboff OUTL(dp, MEAR, MEAR_MDDIR | MEAR_MDIO);
17935748Sduboff MDIO_DELAY(dp);
17945748Sduboff OUTL(dp, MEAR, MEAR_MDDIR | MEAR_MDIO | MEAR_MDC);
17955748Sduboff MDIO_DELAY(dp);
17965748Sduboff }
17975748Sduboff }
17985748Sduboff
17995748Sduboff static int
sfe_mii_config_sis900(struct gem_dev * dp)18005748Sduboff sfe_mii_config_sis900(struct gem_dev *dp)
18015748Sduboff {
18025748Sduboff struct sfe_dev *lp = dp->private;
18035748Sduboff
18045748Sduboff /* Do chip depend setup */
18055748Sduboff if ((dp->mii_phy_id & PHY_MASK) == PHY_ICS1893) {
18065748Sduboff /* workaround for ICS1893 PHY */
18075748Sduboff gem_mii_write(dp, 0x0018, 0xD200);
18085748Sduboff }
18095748Sduboff
18105748Sduboff if (lp->revid == SIS630E_900_REV) {
18115748Sduboff /*
18125748Sduboff * SiS 630E has bugs on default values
18135748Sduboff * of PHY registers
18145748Sduboff */
18155748Sduboff gem_mii_write(dp, MII_AN_ADVERT, 0x05e1);
18165748Sduboff gem_mii_write(dp, MII_CONFIG1, 0x0022);
18175748Sduboff gem_mii_write(dp, MII_CONFIG2, 0xff00);
18185748Sduboff gem_mii_write(dp, MII_MASK, 0xffc0);
18195748Sduboff }
18205748Sduboff sfe_set_eq_sis630(dp);
18215748Sduboff
18225748Sduboff return (gem_mii_config_default(dp));
18235748Sduboff }
18245748Sduboff
18255748Sduboff static uint16_t
sfe_mii_read_sis900(struct gem_dev * dp,uint_t reg)18265748Sduboff sfe_mii_read_sis900(struct gem_dev *dp, uint_t reg)
18275748Sduboff {
18285748Sduboff uint32_t cmd;
18295748Sduboff uint16_t ret;
18305748Sduboff int i;
18315748Sduboff uint32_t data;
18325748Sduboff
18335748Sduboff cmd = MII_READ_CMD(dp->mii_phy_addr, reg);
18345748Sduboff
18355748Sduboff for (i = 31; i >= 18; i--) {
18365748Sduboff data = ((cmd >> i) & 1) << MEAR_MDIO_SHIFT;
18375748Sduboff OUTL(dp, MEAR, data | MEAR_MDDIR);
18385748Sduboff MDIO_DELAY(dp);
18395748Sduboff OUTL(dp, MEAR, data | MEAR_MDDIR | MEAR_MDC);
18405748Sduboff MDIO_DELAY(dp);
18415748Sduboff }
18425748Sduboff
18435748Sduboff /* turn around cycle */
18447116Sduboff OUTL(dp, MEAR, 0);
18455748Sduboff MDIO_DELAY(dp);
18465748Sduboff
18475748Sduboff /* get response from PHY */
18485748Sduboff OUTL(dp, MEAR, MEAR_MDC);
18495748Sduboff MDIO_DELAY(dp);
18507116Sduboff
18515748Sduboff OUTL(dp, MEAR, 0);
18525748Sduboff #if DEBUG_LEBEL > 0
18537116Sduboff (void) INL(dp, MEAR); /* delay */
18545748Sduboff if (INL(dp, MEAR) & MEAR_MDIO) {
18555748Sduboff cmn_err(CE_WARN, "%s: PHY@%d not responded",
18565748Sduboff dp->name, dp->mii_phy_addr);
18575748Sduboff }
18587116Sduboff #else
18597116Sduboff MDIO_DELAY(dp);
18605748Sduboff #endif
18615748Sduboff /* terminate response cycle */
18625748Sduboff OUTL(dp, MEAR, MEAR_MDC);
18637116Sduboff MDIO_DELAY(dp);
18645748Sduboff
18655748Sduboff ret = 0; /* to avoid lint errors */
18665748Sduboff for (i = 16; i > 0; i--) {
18675748Sduboff OUTL(dp, MEAR, 0);
18687116Sduboff (void) INL(dp, MEAR); /* delay */
18695748Sduboff ret = (ret << 1) | ((INL(dp, MEAR) >> MEAR_MDIO_SHIFT) & 1);
18705748Sduboff OUTL(dp, MEAR, MEAR_MDC);
18715748Sduboff MDIO_DELAY(dp);
18725748Sduboff }
18735748Sduboff
18747116Sduboff /* send two idle(Z) bits to terminate the read cycle */
18757116Sduboff for (i = 0; i < 2; i++) {
18767116Sduboff OUTL(dp, MEAR, 0);
18777116Sduboff MDIO_DELAY(dp);
18787116Sduboff OUTL(dp, MEAR, MEAR_MDC);
18797116Sduboff MDIO_DELAY(dp);
18807116Sduboff }
18815748Sduboff
18825748Sduboff return (ret);
18835748Sduboff }
18845748Sduboff
18855748Sduboff static void
sfe_mii_write_sis900(struct gem_dev * dp,uint_t reg,uint16_t val)18865748Sduboff sfe_mii_write_sis900(struct gem_dev *dp, uint_t reg, uint16_t val)
18875748Sduboff {
18885748Sduboff uint32_t cmd;
18895748Sduboff int i;
18905748Sduboff uint32_t data;
18915748Sduboff
18925748Sduboff cmd = MII_WRITE_CMD(dp->mii_phy_addr, reg, val);
18935748Sduboff
18945748Sduboff for (i = 31; i >= 0; i--) {
18955748Sduboff data = ((cmd >> i) & 1) << MEAR_MDIO_SHIFT;
18965748Sduboff OUTL(dp, MEAR, data | MEAR_MDDIR);
18975748Sduboff MDIO_DELAY(dp);
18985748Sduboff OUTL(dp, MEAR, data | MEAR_MDDIR | MEAR_MDC);
18995748Sduboff MDIO_DELAY(dp);
19005748Sduboff }
19015748Sduboff
19027116Sduboff /* send two idle(Z) bits to terminate the write cycle. */
19035748Sduboff for (i = 0; i < 2; i++) {
19047116Sduboff OUTL(dp, MEAR, 0);
19055748Sduboff MDIO_DELAY(dp);
19067116Sduboff OUTL(dp, MEAR, MEAR_MDC);
19075748Sduboff MDIO_DELAY(dp);
19085748Sduboff }
19095748Sduboff }
19105748Sduboff #undef MDIO_DELAY
19115748Sduboff
19125748Sduboff static void
sfe_set_eq_sis630(struct gem_dev * dp)19135748Sduboff sfe_set_eq_sis630(struct gem_dev *dp)
19145748Sduboff {
19155748Sduboff uint16_t reg14h;
19165748Sduboff uint16_t eq_value;
19175748Sduboff uint16_t max_value;
19185748Sduboff uint16_t min_value;
19195748Sduboff int i;
19205748Sduboff uint8_t rev;
19215748Sduboff struct sfe_dev *lp = dp->private;
19225748Sduboff
19235748Sduboff rev = lp->revid;
19245748Sduboff
19255748Sduboff if (!(rev == SIS630E_900_REV || rev == SIS630EA1_900_REV ||
19265748Sduboff rev == SIS630A_900_REV || rev == SIS630ET_900_REV)) {
19275748Sduboff /* it doesn't have a internal PHY */
19285748Sduboff return;
19295748Sduboff }
19305748Sduboff
19315748Sduboff if (dp->mii_state == MII_STATE_LINKUP) {
19325748Sduboff reg14h = gem_mii_read(dp, MII_RESV);
19335748Sduboff gem_mii_write(dp, MII_RESV, (0x2200 | reg14h) & 0xBFFF);
19345748Sduboff
19355748Sduboff eq_value = (0x00f8 & gem_mii_read(dp, MII_RESV)) >> 3;
19365748Sduboff max_value = min_value = eq_value;
19375748Sduboff for (i = 1; i < 10; i++) {
19385748Sduboff eq_value = (0x00f8 & gem_mii_read(dp, MII_RESV)) >> 3;
19395748Sduboff max_value = max(eq_value, max_value);
19405748Sduboff min_value = min(eq_value, min_value);
19415748Sduboff }
19425748Sduboff
19435748Sduboff /* for 630E, rule to determine the equalizer value */
19445748Sduboff if (rev == SIS630E_900_REV || rev == SIS630EA1_900_REV ||
19455748Sduboff rev == SIS630ET_900_REV) {
19465748Sduboff if (max_value < 5) {
19475748Sduboff eq_value = max_value;
19485748Sduboff } else if (5 <= max_value && max_value < 15) {
19495748Sduboff eq_value =
19505748Sduboff max(max_value + 1,
19515748Sduboff min_value + 2);
19525748Sduboff } else if (15 <= max_value) {
19535748Sduboff eq_value =
19545748Sduboff max(max_value + 5,
19555748Sduboff min_value + 6);
19565748Sduboff }
19575748Sduboff }
19585748Sduboff /* for 630B0&B1, rule to determine the equalizer value */
19595748Sduboff else
19605748Sduboff if (rev == SIS630A_900_REV &&
19615748Sduboff (lp->bridge_revid == SIS630B0 ||
19625748Sduboff lp->bridge_revid == SIS630B1)) {
19635748Sduboff
19645748Sduboff if (max_value == 0) {
19655748Sduboff eq_value = 3;
19665748Sduboff } else {
19675748Sduboff eq_value = (max_value + min_value + 1)/2;
19685748Sduboff }
19695748Sduboff }
19705748Sduboff /* write equalizer value and setting */
19715748Sduboff reg14h = gem_mii_read(dp, MII_RESV) & ~0x02f8;
19725748Sduboff reg14h |= 0x6000 | (eq_value << 3);
19735748Sduboff gem_mii_write(dp, MII_RESV, reg14h);
19745748Sduboff } else {
19755748Sduboff reg14h = (gem_mii_read(dp, MII_RESV) & ~0x4000) | 0x2000;
19765748Sduboff if (rev == SIS630A_900_REV &&
19775748Sduboff (lp->bridge_revid == SIS630B0 ||
19785748Sduboff lp->bridge_revid == SIS630B1)) {
19795748Sduboff
19805748Sduboff reg14h |= 0x0200;
19815748Sduboff }
19825748Sduboff gem_mii_write(dp, MII_RESV, reg14h);
19835748Sduboff }
19845748Sduboff }
19855748Sduboff
19865748Sduboff /* ======================================================== */
19875748Sduboff /*
19885748Sduboff * OS depend (device driver) routine
19895748Sduboff */
19905748Sduboff /* ======================================================== */
19915748Sduboff static void
sfe_chipinfo_init_sis900(struct gem_dev * dp)19925748Sduboff sfe_chipinfo_init_sis900(struct gem_dev *dp)
19935748Sduboff {
19945748Sduboff int rev;
19955748Sduboff struct sfe_dev *lp = (struct sfe_dev *)dp->private;
19965748Sduboff
19975748Sduboff rev = lp->revid;
19985748Sduboff
19995748Sduboff if (rev == SIS630E_900_REV /* 0x81 */) {
20005748Sduboff /* sis630E */
20015748Sduboff lp->get_mac_addr = &sfe_get_mac_addr_sis630e;
20025748Sduboff } else if (rev > 0x81 && rev <= 0x90) {
20035748Sduboff /* 630S, 630EA1, 630ET, 635A */
20045748Sduboff lp->get_mac_addr = &sfe_get_mac_addr_sis635;
20055748Sduboff } else if (rev == SIS962_900_REV /* 0x91 */) {
20065748Sduboff /* sis962 or later */
20075748Sduboff lp->get_mac_addr = &sfe_get_mac_addr_sis962;
20085748Sduboff } else {
20095748Sduboff /* sis900 */
20105748Sduboff lp->get_mac_addr = &sfe_get_mac_addr_sis900;
20115748Sduboff }
20125748Sduboff
20135748Sduboff lp->bridge_revid = 0;
20145748Sduboff
20155748Sduboff if (rev == SIS630E_900_REV || rev == SIS630EA1_900_REV ||
20165748Sduboff rev == SIS630A_900_REV || rev == SIS630ET_900_REV) {
20175748Sduboff /*
20185748Sduboff * read host bridge revision
20195748Sduboff */
20205748Sduboff dev_info_t *bridge;
20215748Sduboff ddi_acc_handle_t bridge_handle;
20225748Sduboff
20235748Sduboff if ((bridge = sfe_search_pci_dev(0x1039, 0x630)) == NULL) {
20245748Sduboff cmn_err(CE_WARN,
20255748Sduboff "%s: cannot find host bridge (pci1039,630)",
20265748Sduboff dp->name);
20275748Sduboff return;
20285748Sduboff }
20295748Sduboff
20305748Sduboff if (pci_config_setup(bridge, &bridge_handle) != DDI_SUCCESS) {
20315748Sduboff cmn_err(CE_WARN, "%s: pci_config_setup failed",
20325748Sduboff dp->name);
20335748Sduboff return;
20345748Sduboff }
20355748Sduboff
20365748Sduboff lp->bridge_revid =
20375748Sduboff pci_config_get8(bridge_handle, PCI_CONF_REVID);
20385748Sduboff pci_config_teardown(&bridge_handle);
20395748Sduboff }
20405748Sduboff }
20415748Sduboff
20425748Sduboff static int
sfe_attach_chip(struct gem_dev * dp)20435748Sduboff sfe_attach_chip(struct gem_dev *dp)
20445748Sduboff {
20455748Sduboff struct sfe_dev *lp = (struct sfe_dev *)dp->private;
20465748Sduboff
20475748Sduboff DPRINTF(4, (CE_CONT, CONS "!%s: %s called", dp->name, __func__));
20485748Sduboff
20495748Sduboff /* setup chip-depend get_mac_address function */
20505748Sduboff if (lp->chip->chip_type == CHIPTYPE_SIS900) {
20515748Sduboff sfe_chipinfo_init_sis900(dp);
20525748Sduboff } else {
20535748Sduboff lp->get_mac_addr = &sfe_get_mac_addr_dp83815;
20545748Sduboff }
20555748Sduboff
20565748Sduboff /* read MAC address */
20575748Sduboff if (!(lp->get_mac_addr)(dp)) {
20585748Sduboff cmn_err(CE_WARN,
20595748Sduboff "!%s: %s: failed to get factory mac address"
20605748Sduboff " please specify a mac address in sfe.conf",
20615748Sduboff dp->name, __func__);
20625748Sduboff return (GEM_FAILURE);
20635748Sduboff }
20645748Sduboff
20655748Sduboff if (lp->chip->chip_type == CHIPTYPE_DP83815) {
20665748Sduboff dp->mii_phy_addr = -1; /* no need to scan PHY */
20675748Sduboff dp->misc_flag |= GEM_VLAN_SOFT;
20685748Sduboff dp->txthr += 4; /* VTAG_SIZE */
20695748Sduboff }
20705748Sduboff dp->txthr = min(dp->txthr, TXFIFOSIZE - 2);
20715748Sduboff
20725748Sduboff return (GEM_SUCCESS);
20735748Sduboff }
20745748Sduboff
20755748Sduboff static int
sfeattach(dev_info_t * dip,ddi_attach_cmd_t cmd)20765748Sduboff sfeattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
20775748Sduboff {
20785748Sduboff int unit;
20795748Sduboff const char *drv_name;
20805748Sduboff int i;
20815748Sduboff ddi_acc_handle_t conf_handle;
20825748Sduboff uint16_t vid;
20835748Sduboff uint16_t did;
20845748Sduboff uint8_t rev;
20855748Sduboff #ifdef DEBUG_LEVEL
20865748Sduboff uint32_t iline;
20875748Sduboff uint8_t latim;
20885748Sduboff #endif
20895748Sduboff struct chip_info *p;
20905748Sduboff struct gem_dev *dp;
20915748Sduboff struct sfe_dev *lp;
20925748Sduboff caddr_t base;
20935748Sduboff ddi_acc_handle_t regs_ha;
20945748Sduboff struct gem_conf *gcp;
20955748Sduboff
20965748Sduboff unit = ddi_get_instance(dip);
20975748Sduboff drv_name = ddi_driver_name(dip);
20985748Sduboff
20995748Sduboff DPRINTF(3, (CE_CONT, CONS "%s%d: sfeattach: called", drv_name, unit));
21005748Sduboff
21015748Sduboff /*
21025748Sduboff * Common codes after power-up
21035748Sduboff */
21045748Sduboff if (pci_config_setup(dip, &conf_handle) != DDI_SUCCESS) {
21055748Sduboff cmn_err(CE_WARN, "%s%d: ddi_regs_map_setup failed",
21065748Sduboff drv_name, unit);
21075748Sduboff goto err;
21085748Sduboff }
21095748Sduboff
21105748Sduboff vid = pci_config_get16(conf_handle, PCI_CONF_VENID);
21115748Sduboff did = pci_config_get16(conf_handle, PCI_CONF_DEVID);
21125748Sduboff rev = pci_config_get16(conf_handle, PCI_CONF_REVID);
21135748Sduboff #ifdef DEBUG_LEVEL
21147116Sduboff iline = pci_config_get32(conf_handle, PCI_CONF_ILINE);
21157116Sduboff latim = pci_config_get8(conf_handle, PCI_CONF_LATENCY_TIMER);
21165748Sduboff #endif
21175748Sduboff #ifdef DEBUG_BUILT_IN_SIS900
21185748Sduboff rev = SIS630E_900_REV;
21195748Sduboff #endif
21205748Sduboff for (i = 0, p = sfe_chiptbl; i < CHIPTABLESIZE; i++, p++) {
21215748Sduboff if (p->venid == vid && p->devid == did) {
21225748Sduboff /* found */
21235748Sduboff goto chip_found;
21245748Sduboff }
21255748Sduboff }
21265748Sduboff
21275748Sduboff /* Not found */
21285748Sduboff cmn_err(CE_WARN,
21295748Sduboff "%s%d: sfe_attach: wrong PCI venid/devid (0x%x, 0x%x)",
21305748Sduboff drv_name, unit, vid, did);
21315748Sduboff pci_config_teardown(&conf_handle);
21325748Sduboff goto err;
21335748Sduboff
21345748Sduboff chip_found:
21355748Sduboff pci_config_put16(conf_handle, PCI_CONF_COMM,
21365748Sduboff PCI_COMM_IO | PCI_COMM_MAE | PCI_COMM_ME |
21375748Sduboff pci_config_get16(conf_handle, PCI_CONF_COMM));
21385748Sduboff
21395748Sduboff /* ensure D0 mode */
21405748Sduboff (void) gem_pci_set_power_state(dip, conf_handle, PCI_PMCSR_D0);
21415748Sduboff
21425748Sduboff pci_config_teardown(&conf_handle);
21435748Sduboff
21445748Sduboff switch (cmd) {
21455748Sduboff case DDI_RESUME:
21465748Sduboff return (gem_resume(dip));
21475748Sduboff
21485748Sduboff case DDI_ATTACH:
21495748Sduboff
21505748Sduboff DPRINTF(0, (CE_CONT,
21515748Sduboff CONS "%s%d: ilr 0x%08x, latency_timer:0x%02x",
21525748Sduboff drv_name, unit, iline, latim));
21535748Sduboff
21545748Sduboff /*
21555748Sduboff * Map in the device registers.
21565748Sduboff */
21575748Sduboff if (gem_pci_regs_map_setup(dip,
21585748Sduboff (sfe_use_pcimemspace && p->chip_type == CHIPTYPE_DP83815)
21595748Sduboff ? PCI_ADDR_MEM32 : PCI_ADDR_IO, PCI_ADDR_MASK,
21605748Sduboff &sfe_dev_attr, &base, ®s_ha) != DDI_SUCCESS) {
21615748Sduboff cmn_err(CE_WARN,
21625748Sduboff "%s%d: ddi_regs_map_setup failed",
21635748Sduboff drv_name, unit);
21645748Sduboff goto err;
21655748Sduboff }
21665748Sduboff
21675748Sduboff /*
21685748Sduboff * construct gem configuration
21695748Sduboff */
21705748Sduboff gcp = kmem_zalloc(sizeof (*gcp), KM_SLEEP);
21715748Sduboff
21725748Sduboff /* name */
21735748Sduboff (void) sprintf(gcp->gc_name, "%s%d", drv_name, unit);
21745748Sduboff
21755748Sduboff /* consistency on tx and rx */
21765748Sduboff gcp->gc_tx_buf_align = sizeof (uint8_t) - 1;
21775748Sduboff gcp->gc_tx_max_frags = MAXTXFRAGS;
21785748Sduboff gcp->gc_tx_max_descs_per_pkt = gcp->gc_tx_max_frags;
21795748Sduboff gcp->gc_tx_desc_unit_shift = 4; /* 16 byte */
21805748Sduboff gcp->gc_tx_buf_size = TX_BUF_SIZE;
21815748Sduboff gcp->gc_tx_buf_limit = gcp->gc_tx_buf_size;
21825748Sduboff gcp->gc_tx_ring_size = TX_RING_SIZE;
21835748Sduboff gcp->gc_tx_ring_limit = gcp->gc_tx_ring_size;
21845748Sduboff gcp->gc_tx_auto_pad = B_TRUE;
21855748Sduboff gcp->gc_tx_copy_thresh = sfe_tx_copy_thresh;
21865748Sduboff gcp->gc_tx_desc_write_oo = B_TRUE;
21875748Sduboff
21885748Sduboff gcp->gc_rx_buf_align = sizeof (uint8_t) - 1;
21895748Sduboff gcp->gc_rx_max_frags = MAXRXFRAGS;
21905748Sduboff gcp->gc_rx_desc_unit_shift = 4;
21915748Sduboff gcp->gc_rx_ring_size = RX_RING_SIZE;
21925748Sduboff gcp->gc_rx_buf_max = RX_BUF_SIZE;
21935748Sduboff gcp->gc_rx_copy_thresh = sfe_rx_copy_thresh;
21945748Sduboff
21955748Sduboff /* map attributes */
21965748Sduboff gcp->gc_dev_attr = sfe_dev_attr;
21975748Sduboff gcp->gc_buf_attr = sfe_buf_attr;
21985748Sduboff gcp->gc_desc_attr = sfe_buf_attr;
21995748Sduboff
22005748Sduboff /* dma attributes */
22015748Sduboff gcp->gc_dma_attr_desc = sfe_dma_attr_desc;
22025748Sduboff
22035748Sduboff gcp->gc_dma_attr_txbuf = sfe_dma_attr_buf;
22045748Sduboff gcp->gc_dma_attr_txbuf.dma_attr_align = gcp->gc_tx_buf_align+1;
22055748Sduboff gcp->gc_dma_attr_txbuf.dma_attr_sgllen = gcp->gc_tx_max_frags;
22065748Sduboff
22075748Sduboff gcp->gc_dma_attr_rxbuf = sfe_dma_attr_buf;
22085748Sduboff gcp->gc_dma_attr_rxbuf.dma_attr_align = gcp->gc_rx_buf_align+1;
22095748Sduboff gcp->gc_dma_attr_rxbuf.dma_attr_sgllen = gcp->gc_rx_max_frags;
22105748Sduboff
22115748Sduboff /* time out parameters */
22125748Sduboff gcp->gc_tx_timeout = 3*ONESEC;
22135748Sduboff gcp->gc_tx_timeout_interval = ONESEC;
22147116Sduboff if (p->chip_type == CHIPTYPE_DP83815) {
22157116Sduboff /* workaround for tx hang */
22167116Sduboff gcp->gc_tx_timeout_interval = ONESEC/20; /* 50mS */
22177116Sduboff }
22185748Sduboff
22195748Sduboff /* MII timeout parameters */
22205748Sduboff gcp->gc_mii_link_watch_interval = ONESEC;
22215748Sduboff gcp->gc_mii_an_watch_interval = ONESEC/5;
22225748Sduboff gcp->gc_mii_reset_timeout = MII_RESET_TIMEOUT; /* 1 sec */
22235748Sduboff gcp->gc_mii_an_timeout = MII_AN_TIMEOUT; /* 5 sec */
22245748Sduboff gcp->gc_mii_an_wait = 0;
22255748Sduboff gcp->gc_mii_linkdown_timeout = MII_LINKDOWN_TIMEOUT;
22265748Sduboff
22275748Sduboff /* setting for general PHY */
22285748Sduboff gcp->gc_mii_an_delay = 0;
22295748Sduboff gcp->gc_mii_linkdown_action = MII_ACTION_RSA;
22305748Sduboff gcp->gc_mii_linkdown_timeout_action = MII_ACTION_RESET;
22315748Sduboff gcp->gc_mii_dont_reset = B_FALSE;
22325748Sduboff
22335748Sduboff
22345748Sduboff /* I/O methods */
22355748Sduboff
22365748Sduboff /* mac operation */
22375748Sduboff gcp->gc_attach_chip = &sfe_attach_chip;
22385748Sduboff if (p->chip_type == CHIPTYPE_DP83815) {
22395748Sduboff gcp->gc_reset_chip = &sfe_reset_chip_dp83815;
22405748Sduboff } else {
22415748Sduboff gcp->gc_reset_chip = &sfe_reset_chip_sis900;
22425748Sduboff }
22435748Sduboff gcp->gc_init_chip = &sfe_init_chip;
22445748Sduboff gcp->gc_start_chip = &sfe_start_chip;
22455748Sduboff gcp->gc_stop_chip = &sfe_stop_chip;
22465748Sduboff #ifdef USE_MULTICAST_HASHTBL
22475748Sduboff gcp->gc_multicast_hash = &sfe_mcast_hash;
22485748Sduboff #endif
22495748Sduboff if (p->chip_type == CHIPTYPE_DP83815) {
22505748Sduboff gcp->gc_set_rx_filter = &sfe_set_rx_filter_dp83815;
22515748Sduboff } else {
22525748Sduboff gcp->gc_set_rx_filter = &sfe_set_rx_filter_sis900;
22535748Sduboff }
22545748Sduboff gcp->gc_set_media = &sfe_set_media;
22555748Sduboff gcp->gc_get_stats = &sfe_get_stats;
22565748Sduboff gcp->gc_interrupt = &sfe_interrupt;
22575748Sduboff
22585748Sduboff /* descriptor operation */
22595748Sduboff gcp->gc_tx_desc_write = &sfe_tx_desc_write;
22605748Sduboff gcp->gc_tx_start = &sfe_tx_start;
22615748Sduboff gcp->gc_rx_desc_write = &sfe_rx_desc_write;
22625748Sduboff gcp->gc_rx_start = NULL;
22635748Sduboff
22645748Sduboff gcp->gc_tx_desc_stat = &sfe_tx_desc_stat;
22655748Sduboff gcp->gc_rx_desc_stat = &sfe_rx_desc_stat;
22665748Sduboff gcp->gc_tx_desc_init = &sfe_tx_desc_init;
22675748Sduboff gcp->gc_rx_desc_init = &sfe_rx_desc_init;
22685748Sduboff gcp->gc_tx_desc_clean = &sfe_tx_desc_clean;
22695748Sduboff gcp->gc_rx_desc_clean = &sfe_rx_desc_clean;
22705748Sduboff
22715748Sduboff /* mii operations */
22725748Sduboff if (p->chip_type == CHIPTYPE_DP83815) {
22737116Sduboff gcp->gc_mii_probe = &sfe_mii_probe_dp83815;
22747116Sduboff gcp->gc_mii_init = &sfe_mii_init_dp83815;
22755748Sduboff gcp->gc_mii_config = &sfe_mii_config_dp83815;
22765748Sduboff gcp->gc_mii_sync = &sfe_mii_sync_dp83815;
22775748Sduboff gcp->gc_mii_read = &sfe_mii_read_dp83815;
22785748Sduboff gcp->gc_mii_write = &sfe_mii_write_dp83815;
22795748Sduboff gcp->gc_mii_tune_phy = NULL;
22805748Sduboff gcp->gc_flow_control = FLOW_CONTROL_NONE;
22815748Sduboff } else {
22825748Sduboff gcp->gc_mii_probe = &gem_mii_probe_default;
22835748Sduboff gcp->gc_mii_init = NULL;
22845748Sduboff gcp->gc_mii_config = &sfe_mii_config_sis900;
22855748Sduboff gcp->gc_mii_sync = &sfe_mii_sync_sis900;
22865748Sduboff gcp->gc_mii_read = &sfe_mii_read_sis900;
22875748Sduboff gcp->gc_mii_write = &sfe_mii_write_sis900;
22885748Sduboff gcp->gc_mii_tune_phy = &sfe_set_eq_sis630;
22895748Sduboff gcp->gc_flow_control = FLOW_CONTROL_RX_PAUSE;
22905748Sduboff }
22915748Sduboff
22925748Sduboff lp = kmem_zalloc(sizeof (*lp), KM_SLEEP);
22935748Sduboff lp->chip = p;
22945748Sduboff lp->revid = rev;
22957116Sduboff lp->our_intr_bits = 0;
22967116Sduboff lp->isr_pended = 0;
22975748Sduboff
22985748Sduboff cmn_err(CE_CONT, CONS "%s%d: chip:%s rev:0x%02x",
22995748Sduboff drv_name, unit, p->chip_name, rev);
23005748Sduboff
23015748Sduboff dp = gem_do_attach(dip, 0, gcp, base, ®s_ha,
23025748Sduboff lp, sizeof (*lp));
23035748Sduboff kmem_free(gcp, sizeof (*gcp));
23045748Sduboff
23055748Sduboff if (dp == NULL) {
23065748Sduboff goto err_freelp;
23075748Sduboff }
23085748Sduboff
23095748Sduboff return (DDI_SUCCESS);
23105748Sduboff
23115748Sduboff err_freelp:
23125748Sduboff kmem_free(lp, sizeof (struct sfe_dev));
23135748Sduboff err:
23145748Sduboff return (DDI_FAILURE);
23155748Sduboff }
23165748Sduboff return (DDI_FAILURE);
23175748Sduboff }
23185748Sduboff
23195748Sduboff static int
sfedetach(dev_info_t * dip,ddi_detach_cmd_t cmd)23205748Sduboff sfedetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
23215748Sduboff {
23225748Sduboff switch (cmd) {
23235748Sduboff case DDI_SUSPEND:
23245748Sduboff return (gem_suspend(dip));
23255748Sduboff
23265748Sduboff case DDI_DETACH:
23275748Sduboff return (gem_do_detach(dip));
23285748Sduboff }
23295748Sduboff return (DDI_FAILURE);
23305748Sduboff }
23315748Sduboff
23328611SSherry.Moore@Sun.COM /*
23338611SSherry.Moore@Sun.COM * quiesce(9E) entry point.
23348611SSherry.Moore@Sun.COM *
23358611SSherry.Moore@Sun.COM * This function is called when the system is single-threaded at high
23368611SSherry.Moore@Sun.COM * PIL with preemption disabled. Therefore, this function must not be
23378611SSherry.Moore@Sun.COM * blocked.
23388611SSherry.Moore@Sun.COM *
23398611SSherry.Moore@Sun.COM * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
23408611SSherry.Moore@Sun.COM * DDI_FAILURE indicates an error condition and should almost never happen.
23418611SSherry.Moore@Sun.COM */
23428611SSherry.Moore@Sun.COM #ifdef __sparc
23438611SSherry.Moore@Sun.COM #define sfe_quiesce ddi_quiesce_not_supported
23448611SSherry.Moore@Sun.COM #else
23458611SSherry.Moore@Sun.COM static int
sfe_quiesce(dev_info_t * dip)23468611SSherry.Moore@Sun.COM sfe_quiesce(dev_info_t *dip)
23478611SSherry.Moore@Sun.COM {
23488611SSherry.Moore@Sun.COM struct gem_dev *dp;
23498611SSherry.Moore@Sun.COM int ret = 0;
23508611SSherry.Moore@Sun.COM
23518611SSherry.Moore@Sun.COM dp = GEM_GET_DEV(dip);
23528611SSherry.Moore@Sun.COM
23538611SSherry.Moore@Sun.COM if (dp == NULL)
23548611SSherry.Moore@Sun.COM return (DDI_FAILURE);
23558611SSherry.Moore@Sun.COM
23568611SSherry.Moore@Sun.COM ret = sfe_stop_chip_quiesce(dp);
23578611SSherry.Moore@Sun.COM
23588611SSherry.Moore@Sun.COM return (ret);
23598611SSherry.Moore@Sun.COM }
23608611SSherry.Moore@Sun.COM #endif
23618611SSherry.Moore@Sun.COM
23625748Sduboff /* ======================================================== */
23635748Sduboff /*
23645748Sduboff * OS depend (loadable streams driver) routine
23655748Sduboff */
23665748Sduboff /* ======================================================== */
23675748Sduboff DDI_DEFINE_STREAM_OPS(sfe_ops, nulldev, nulldev, sfeattach, sfedetach,
23688611SSherry.Moore@Sun.COM nodev, NULL, D_MP, NULL, sfe_quiesce);
23695748Sduboff
23705748Sduboff static struct modldrv modldrv = {
23715748Sduboff &mod_driverops, /* Type of module. This one is a driver */
23725748Sduboff ident,
23735748Sduboff &sfe_ops, /* driver ops */
23745748Sduboff };
23755748Sduboff
23765748Sduboff static struct modlinkage modlinkage = {
23775748Sduboff MODREV_1, &modldrv, NULL
23785748Sduboff };
23795748Sduboff
23805748Sduboff /* ======================================================== */
23815748Sduboff /*
23825748Sduboff * Loadable module support
23835748Sduboff */
23845748Sduboff /* ======================================================== */
23855748Sduboff int
_init(void)23865748Sduboff _init(void)
23875748Sduboff {
23885748Sduboff int status;
23895748Sduboff
23905748Sduboff DPRINTF(2, (CE_CONT, CONS "sfe: _init: called"));
23915748Sduboff gem_mod_init(&sfe_ops, "sfe");
23925748Sduboff status = mod_install(&modlinkage);
23935748Sduboff if (status != DDI_SUCCESS) {
23945748Sduboff gem_mod_fini(&sfe_ops);
23955748Sduboff }
23965748Sduboff return (status);
23975748Sduboff }
23985748Sduboff
23995748Sduboff /*
24005748Sduboff * _fini : done
24015748Sduboff */
24025748Sduboff int
_fini(void)24035748Sduboff _fini(void)
24045748Sduboff {
24055748Sduboff int status;
24065748Sduboff
24075748Sduboff DPRINTF(2, (CE_CONT, CONS "sfe: _fini: called"));
24085748Sduboff status = mod_remove(&modlinkage);
24095748Sduboff if (status == DDI_SUCCESS) {
24105748Sduboff gem_mod_fini(&sfe_ops);
24115748Sduboff }
24125748Sduboff return (status);
24135748Sduboff }
24145748Sduboff
24155748Sduboff int
_info(struct modinfo * modinfop)24165748Sduboff _info(struct modinfo *modinfop)
24175748Sduboff {
24185748Sduboff return (mod_info(&modlinkage, modinfop));
24195748Sduboff }
2420