17c478bd9Sstevel@tonic-gate /* -*- Mode:C; c-basic-offset:4; -*- */
27c478bd9Sstevel@tonic-gate 
37c478bd9Sstevel@tonic-gate /*
47c478bd9Sstevel@tonic-gate    sis900.c: An SiS 900/7016 PCI Fast Ethernet driver for Etherboot
57c478bd9Sstevel@tonic-gate    Copyright (C) 2001 Entity Cyber, Inc.
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate    Revision:	1.0	March 1, 2001
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate    Author: Marty Connor (mdc@thinguin.org)
107c478bd9Sstevel@tonic-gate 
117c478bd9Sstevel@tonic-gate    Adapted from a Linux driver which was written by Donald Becker
127c478bd9Sstevel@tonic-gate    and modified by Ollie Lho and Chin-Shan Li of SiS Corporation.
137c478bd9Sstevel@tonic-gate    Rewritten for Etherboot by Marty Connor.
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate    This software may be used and distributed according to the terms
167c478bd9Sstevel@tonic-gate    of the GNU Public License (GPL), incorporated herein by reference.
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate    References:
197c478bd9Sstevel@tonic-gate    SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support,
207c478bd9Sstevel@tonic-gate    preliminary Rev. 1.0 Jan. 14, 1998
217c478bd9Sstevel@tonic-gate    SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support,
227c478bd9Sstevel@tonic-gate    preliminary Rev. 1.0 Nov. 10, 1998
237c478bd9Sstevel@tonic-gate    SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
247c478bd9Sstevel@tonic-gate    preliminary Rev. 1.0 Jan. 18, 1998
257c478bd9Sstevel@tonic-gate    http://www.sis.com.tw/support/databook.htm */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /* Revision History */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate   07 Dec 2003  timlegge - Enabled Multicast Support
317c478bd9Sstevel@tonic-gate   06 Dec 2003  timlegge - Fixed relocation issue in 5.2
327c478bd9Sstevel@tonic-gate   04 Jan 2002  Chien-Yu Chen, Doug Ambrisko, Marty Connor  Patch to Etherboot 5.0.5
337c478bd9Sstevel@tonic-gate      Added support for the SiS 630ET plus various bug fixes from linux kernel
347c478bd9Sstevel@tonic-gate      source 2.4.17.
357c478bd9Sstevel@tonic-gate   01 March 2001  mdc     1.0
367c478bd9Sstevel@tonic-gate      Initial Release.  Tested with PCI based sis900 card and ThinkNIC
377c478bd9Sstevel@tonic-gate      computer.
387c478bd9Sstevel@tonic-gate   20 March 2001 P.Koegel
397c478bd9Sstevel@tonic-gate      added support for sis630e and PHY ICS1893 and RTL8201
407c478bd9Sstevel@tonic-gate      Testet with SIS730S chipset + ICS1893
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /* Includes */
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #include "etherboot.h"
467c478bd9Sstevel@tonic-gate #include "nic.h"
477c478bd9Sstevel@tonic-gate #include "pci.h"
487c478bd9Sstevel@tonic-gate #include "timer.h"
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include "sis900.h"
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /* Globals */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate static int sis900_debug = 0;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static unsigned short vendor, dev_id;
577c478bd9Sstevel@tonic-gate static unsigned long ioaddr;
587c478bd9Sstevel@tonic-gate static u8 pci_revision;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate static unsigned int cur_phy;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate static unsigned int cur_rx;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate static BufferDesc txd;
657c478bd9Sstevel@tonic-gate static BufferDesc rxd[NUM_RX_DESC];
667c478bd9Sstevel@tonic-gate static unsigned char txb[TX_BUF_SIZE];
677c478bd9Sstevel@tonic-gate static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #if 0
707c478bd9Sstevel@tonic-gate static struct mac_chip_info {
717c478bd9Sstevel@tonic-gate     const char *name;
727c478bd9Sstevel@tonic-gate     u16 vendor_id, device_id, flags;
737c478bd9Sstevel@tonic-gate     int io_size;
747c478bd9Sstevel@tonic-gate } mac_chip_table[] = {
757c478bd9Sstevel@tonic-gate     { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900,
767c478bd9Sstevel@tonic-gate       PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
777c478bd9Sstevel@tonic-gate     { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016,
787c478bd9Sstevel@tonic-gate       PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
797c478bd9Sstevel@tonic-gate     {0,0,0,0,0} /* 0 terminated list. */
807c478bd9Sstevel@tonic-gate };
817c478bd9Sstevel@tonic-gate #endif
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate static void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
847c478bd9Sstevel@tonic-gate static void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
857c478bd9Sstevel@tonic-gate static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
867c478bd9Sstevel@tonic-gate static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
877c478bd9Sstevel@tonic-gate static void vt6103_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate static struct mii_chip_info {
907c478bd9Sstevel@tonic-gate     const char * name;
917c478bd9Sstevel@tonic-gate     u16 phy_id0;
927c478bd9Sstevel@tonic-gate     u16 phy_id1;
937c478bd9Sstevel@tonic-gate     void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex);
947c478bd9Sstevel@tonic-gate } mii_chip_table[] = {
957c478bd9Sstevel@tonic-gate     {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode},
967c478bd9Sstevel@tonic-gate     {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode},
977c478bd9Sstevel@tonic-gate     {"AMD 79C901 10BASE-T PHY",  0x0000, 0x35b9, amd79c901_read_mode},
987c478bd9Sstevel@tonic-gate     {"AMD 79C901 HomePNA PHY",   0x0000, 0x35c8, amd79c901_read_mode},
997c478bd9Sstevel@tonic-gate     {"ICS 1893 Integrated PHYceiver"   , 0x0015, 0xf441,ics1893_read_mode},
1007c478bd9Sstevel@tonic-gate     {"RTL 8201 10/100Mbps Phyceiver"   , 0x0000, 0x8201,rtl8201_read_mode},
1017c478bd9Sstevel@tonic-gate     {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode},
1027c478bd9Sstevel@tonic-gate     {0,0,0,0}
1037c478bd9Sstevel@tonic-gate };
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate static struct mii_phy {
1067c478bd9Sstevel@tonic-gate     struct mii_phy * next;
1077c478bd9Sstevel@tonic-gate     struct mii_chip_info * chip_info;
1087c478bd9Sstevel@tonic-gate     int phy_addr;
1097c478bd9Sstevel@tonic-gate     u16 status;
1107c478bd9Sstevel@tonic-gate } mii;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate // PCI to ISA bridge for SIS640E access
1137c478bd9Sstevel@tonic-gate static struct pci_id   pci_isa_bridge_list[] = {
1147c478bd9Sstevel@tonic-gate 	{ 0x1039, 0x0008,
1157c478bd9Sstevel@tonic-gate 		"SIS 85C503/5513 PCI to ISA bridge"},
1167c478bd9Sstevel@tonic-gate };
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate struct pci_driver sis_bridge_driver = {
1197c478bd9Sstevel@tonic-gate 	.type     = BRIDGE_DRIVER,
1207c478bd9Sstevel@tonic-gate 	.name     = "",
1217c478bd9Sstevel@tonic-gate 	.probe    = 0,
1227c478bd9Sstevel@tonic-gate 	.ids      = pci_isa_bridge_list,
1237c478bd9Sstevel@tonic-gate 	.id_count = sizeof(pci_isa_bridge_list)/sizeof(pci_isa_bridge_list[0]),
1247c478bd9Sstevel@tonic-gate 	.class    = 0,
1257c478bd9Sstevel@tonic-gate };
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate /* Function Prototypes */
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate static int sis900_probe(struct dev *dev, struct pci_device *pci);
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate static u16  sis900_read_eeprom(int location);
1327c478bd9Sstevel@tonic-gate static void sis900_mdio_reset(long mdio_addr);
1337c478bd9Sstevel@tonic-gate static void sis900_mdio_idle(long mdio_addr);
1347c478bd9Sstevel@tonic-gate static u16  sis900_mdio_read(int phy_id, int location);
1357c478bd9Sstevel@tonic-gate #if 0
1367c478bd9Sstevel@tonic-gate static void sis900_mdio_write(int phy_id, int location, int val);
1377c478bd9Sstevel@tonic-gate #endif
1387c478bd9Sstevel@tonic-gate static void sis900_init(struct nic *nic);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate static void sis900_reset(struct nic *nic);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate static void sis900_init_rxfilter(struct nic *nic);
1437c478bd9Sstevel@tonic-gate static void sis900_init_txd(struct nic *nic);
1447c478bd9Sstevel@tonic-gate static void sis900_init_rxd(struct nic *nic);
1457c478bd9Sstevel@tonic-gate static void sis900_set_rx_mode(struct nic *nic);
1467c478bd9Sstevel@tonic-gate static void sis900_check_mode(struct nic *nic);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate static void sis900_transmit(struct nic *nic, const char *d,
1497c478bd9Sstevel@tonic-gate                             unsigned int t, unsigned int s, const char *p);
1507c478bd9Sstevel@tonic-gate static int  sis900_poll(struct nic *nic, int retrieve);
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate static void sis900_disable(struct dev *dev);
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate static void sis900_irq(struct nic *nic, irq_action_t action);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate /**
1577c478bd9Sstevel@tonic-gate  *	sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
1587c478bd9Sstevel@tonic-gate  *	@pci_dev: the sis900 pci device
1597c478bd9Sstevel@tonic-gate  *	@net_dev: the net device to get address for
1607c478bd9Sstevel@tonic-gate  *
1617c478bd9Sstevel@tonic-gate  *	Older SiS900 and friends, use EEPROM to store MAC address.
1627c478bd9Sstevel@tonic-gate  *	MAC address is read from read_eeprom() into @net_dev->dev_addr.
1637c478bd9Sstevel@tonic-gate  */
1647c478bd9Sstevel@tonic-gate 
sis900_get_mac_addr(struct pci_device * pci_dev __unused,struct nic * nic)1657c478bd9Sstevel@tonic-gate static int sis900_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
1667c478bd9Sstevel@tonic-gate {
1677c478bd9Sstevel@tonic-gate 	u16 signature;
1687c478bd9Sstevel@tonic-gate 	int i;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	/* check to see if we have sane EEPROM */
1717c478bd9Sstevel@tonic-gate 	signature = (u16) sis900_read_eeprom( EEPROMSignature);
1727c478bd9Sstevel@tonic-gate 	if (signature == 0xffff || signature == 0x0000) {
1737c478bd9Sstevel@tonic-gate 		printf ("sis900_probe: Error EERPOM read %hX\n", signature);
1747c478bd9Sstevel@tonic-gate 		return 0;
1757c478bd9Sstevel@tonic-gate 	}
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	/* get MAC address from EEPROM */
1787c478bd9Sstevel@tonic-gate 	for (i = 0; i < 3; i++)
1797c478bd9Sstevel@tonic-gate 			((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
1807c478bd9Sstevel@tonic-gate 	return 1;
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate /**
1847c478bd9Sstevel@tonic-gate  *	sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
1857c478bd9Sstevel@tonic-gate  *	@pci_dev: the sis900 pci device
1867c478bd9Sstevel@tonic-gate  *	@net_dev: the net device to get address for
1877c478bd9Sstevel@tonic-gate  *
1887c478bd9Sstevel@tonic-gate  *	SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
1897c478bd9Sstevel@tonic-gate  *	is shared by
1907c478bd9Sstevel@tonic-gate  *	LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
1917c478bd9Sstevel@tonic-gate  *	and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
1927c478bd9Sstevel@tonic-gate  *	by LAN, otherwise is not. After MAC address is read from EEPROM, send
1937c478bd9Sstevel@tonic-gate  *	EEDONE signal to refuse EEPROM access by LAN.
1947c478bd9Sstevel@tonic-gate  *	The EEPROM map of SiS962 or SiS963 is different to SiS900.
1957c478bd9Sstevel@tonic-gate  *	The signature field in SiS962 or SiS963 spec is meaningless.
1967c478bd9Sstevel@tonic-gate  *	MAC address is read into @net_dev->dev_addr.
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate 
sis96x_get_mac_addr(struct pci_device * pci_dev __unused,struct nic * nic)1997c478bd9Sstevel@tonic-gate static int sis96x_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate /* 	long ioaddr = net_dev->base_addr; */
2027c478bd9Sstevel@tonic-gate 	long ee_addr = ioaddr + mear;
2037c478bd9Sstevel@tonic-gate 	u32 waittime = 0;
2047c478bd9Sstevel@tonic-gate 	int i;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	printf("Alternate function\n");
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	outl(EEREQ, ee_addr);
2097c478bd9Sstevel@tonic-gate 	while(waittime < 2000) {
2107c478bd9Sstevel@tonic-gate 		if(inl(ee_addr) & EEGNT) {
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 			/* get MAC address from EEPROM */
2137c478bd9Sstevel@tonic-gate 			for (i = 0; i < 3; i++)
2147c478bd9Sstevel@tonic-gate 			        ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 			outl(EEDONE, ee_addr);
2177c478bd9Sstevel@tonic-gate 			return 1;
2187c478bd9Sstevel@tonic-gate 		} else {
2197c478bd9Sstevel@tonic-gate 			udelay(1);
2207c478bd9Sstevel@tonic-gate 			waittime ++;
2217c478bd9Sstevel@tonic-gate 		}
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 	outl(EEDONE, ee_addr);
2247c478bd9Sstevel@tonic-gate 	return 0;
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate /**
2287c478bd9Sstevel@tonic-gate  *	sis630e_get_mac_addr: - Get MAC address for SiS630E model
2297c478bd9Sstevel@tonic-gate  *	@pci_dev: the sis900 pci device
2307c478bd9Sstevel@tonic-gate  *	@net_dev: the net device to get address for
2317c478bd9Sstevel@tonic-gate  *
2327c478bd9Sstevel@tonic-gate  *	SiS630E model, use APC CMOS RAM to store MAC address.
2337c478bd9Sstevel@tonic-gate  *	APC CMOS RAM is accessed through ISA bridge.
2347c478bd9Sstevel@tonic-gate  *	MAC address is read into @net_dev->dev_addr.
2357c478bd9Sstevel@tonic-gate  */
2367c478bd9Sstevel@tonic-gate 
sis630e_get_mac_addr(struct pci_device * pci_dev __unused,struct nic * nic)2377c478bd9Sstevel@tonic-gate static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	u8 reg;
2407c478bd9Sstevel@tonic-gate 	int i;
2417c478bd9Sstevel@tonic-gate 	struct pci_device	p[1];
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	/* find PCI to ISA bridge */
2447c478bd9Sstevel@tonic-gate 	memset(p, 0, sizeof(p));
2457c478bd9Sstevel@tonic-gate 	do {
2467c478bd9Sstevel@tonic-gate 		find_pci(BRIDGE_DRIVER, p);
2477c478bd9Sstevel@tonic-gate 	} while(p->driver && p->driver != &sis_bridge_driver);
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	/* error on failure */
2507c478bd9Sstevel@tonic-gate 	if (!p->driver)
2517c478bd9Sstevel@tonic-gate 	    return 0;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	pcibios_read_config_byte(p->bus,p->devfn, 0x48, &reg);
2547c478bd9Sstevel@tonic-gate 	pcibios_write_config_byte(p->bus,p->devfn, 0x48, reg | 0x40);
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	for (i = 0; i < ETH_ALEN; i++)
2577c478bd9Sstevel@tonic-gate 	{
2587c478bd9Sstevel@tonic-gate 		outb(0x09 + i, 0x70);
2597c478bd9Sstevel@tonic-gate 		((u8 *)(nic->node_addr))[i] = inb(0x71);
2607c478bd9Sstevel@tonic-gate 	}
2617c478bd9Sstevel@tonic-gate 	pcibios_write_config_byte(p->bus,p->devfn, 0x48, reg & ~0x40);
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	return 1;
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate /**
2677c478bd9Sstevel@tonic-gate  *      sis630e_get_mac_addr: - Get MAC address for SiS630E model
2687c478bd9Sstevel@tonic-gate  *      @pci_dev: the sis900 pci device
2697c478bd9Sstevel@tonic-gate  *      @net_dev: the net device to get address for
2707c478bd9Sstevel@tonic-gate  *
2717c478bd9Sstevel@tonic-gate  *      SiS630E model, use APC CMOS RAM to store MAC address.
2727c478bd9Sstevel@tonic-gate  *      APC CMOS RAM is accessed through ISA bridge.
2737c478bd9Sstevel@tonic-gate  *      MAC address is read into @net_dev->dev_addr.
2747c478bd9Sstevel@tonic-gate  */
2757c478bd9Sstevel@tonic-gate 
sis635_get_mac_addr(struct pci_device * pci_dev __unused,struct nic * nic)2767c478bd9Sstevel@tonic-gate static int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
2777c478bd9Sstevel@tonic-gate {
2787c478bd9Sstevel@tonic-gate         u32 rfcrSave;
2797c478bd9Sstevel@tonic-gate         u32 i;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate         rfcrSave = inl(rfcr + ioaddr);
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate         outl(rfcrSave | RELOAD, ioaddr + cr);
2857c478bd9Sstevel@tonic-gate         outl(0, ioaddr + cr);
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate         /* disable packet filtering before setting filter */
2887c478bd9Sstevel@tonic-gate         outl(rfcrSave & ~RFEN, rfcr + ioaddr);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate         /* load MAC addr to filter data register */
2917c478bd9Sstevel@tonic-gate         for (i = 0 ; i < 3 ; i++) {
2927c478bd9Sstevel@tonic-gate                 outl((i << RFADDR_shift), ioaddr + rfcr);
2937c478bd9Sstevel@tonic-gate                 *( ((u16 *)nic->node_addr) + i) = inw(ioaddr + rfdr);
2947c478bd9Sstevel@tonic-gate         }
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate         /* enable packet filitering */
2977c478bd9Sstevel@tonic-gate         outl(rfcrSave | RFEN, rfcr + ioaddr);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate         return 1;
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate /*
3037c478bd9Sstevel@tonic-gate  * Function: sis900_probe
3047c478bd9Sstevel@tonic-gate  *
3057c478bd9Sstevel@tonic-gate  * Description: initializes initializes the NIC, retrieves the
3067c478bd9Sstevel@tonic-gate  *    MAC address of the card, and sets up some globals required by
3077c478bd9Sstevel@tonic-gate  *    other routines.
3087c478bd9Sstevel@tonic-gate  *
3097c478bd9Sstevel@tonic-gate  * Side effects:
3107c478bd9Sstevel@tonic-gate  *            leaves the ioaddress of the sis900 chip in the variable ioaddr.
3117c478bd9Sstevel@tonic-gate  *            leaves the sis900 initialized, and ready to recieve packets.
3127c478bd9Sstevel@tonic-gate  *
3137c478bd9Sstevel@tonic-gate  * Returns:   struct nic *:          pointer to NIC data structure
3147c478bd9Sstevel@tonic-gate  */
3157c478bd9Sstevel@tonic-gate 
sis900_probe(struct dev * dev,struct pci_device * pci)3167c478bd9Sstevel@tonic-gate static int sis900_probe(struct dev *dev, struct pci_device *pci)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate     struct nic *nic = (struct nic *)dev;
3197c478bd9Sstevel@tonic-gate     int i;
3207c478bd9Sstevel@tonic-gate     int found=0;
3217c478bd9Sstevel@tonic-gate     int phy_addr;
3227c478bd9Sstevel@tonic-gate     u8 revision;
3237c478bd9Sstevel@tonic-gate     int ret;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate     if (pci->ioaddr == 0)
3267c478bd9Sstevel@tonic-gate         return 0;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate     nic->irqno  = 0;
3297c478bd9Sstevel@tonic-gate     nic->ioaddr = pci->ioaddr & ~3;
3307c478bd9Sstevel@tonic-gate     ioaddr  = pci->ioaddr & ~3;
3317c478bd9Sstevel@tonic-gate     vendor  = pci->vendor;
3327c478bd9Sstevel@tonic-gate     dev_id  = pci->dev_id;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate     /* wakeup chip */
3357c478bd9Sstevel@tonic-gate     pcibios_write_config_dword(pci->bus, pci->devfn, 0x40, 0x00000000);
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate     adjust_pci_device(pci);
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate     /* get MAC address */
3407c478bd9Sstevel@tonic-gate     ret = 0;
3417c478bd9Sstevel@tonic-gate     pcibios_read_config_byte(pci->bus,pci->devfn, PCI_REVISION, &revision);
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate     /* save for use later in sis900_reset() */
3447c478bd9Sstevel@tonic-gate     pci_revision = revision;
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate     if (revision == SIS630E_900_REV)
3477c478bd9Sstevel@tonic-gate         ret = sis630e_get_mac_addr(pci, nic);
3487c478bd9Sstevel@tonic-gate     else if ((revision > 0x81) && (revision <= 0x90))
3497c478bd9Sstevel@tonic-gate         ret = sis635_get_mac_addr(pci, nic);
3507c478bd9Sstevel@tonic-gate     else if (revision == SIS96x_900_REV)
3517c478bd9Sstevel@tonic-gate 	ret = sis96x_get_mac_addr(pci, nic);
3527c478bd9Sstevel@tonic-gate     else
3537c478bd9Sstevel@tonic-gate         ret = sis900_get_mac_addr(pci, nic);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate     if (ret == 0)
3567c478bd9Sstevel@tonic-gate     {
3577c478bd9Sstevel@tonic-gate         printf ("sis900_probe: Error MAC address not found\n");
3587c478bd9Sstevel@tonic-gate         return 0;
3597c478bd9Sstevel@tonic-gate     }
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate     /* 630ET : set the mii access mode as software-mode */
3627c478bd9Sstevel@tonic-gate     if (revision == SIS630ET_900_REV)
3637c478bd9Sstevel@tonic-gate 	outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate     printf("\nsis900_probe: MAC addr %! at ioaddr %#hX\n",
3667c478bd9Sstevel@tonic-gate            nic->node_addr, ioaddr);
3677c478bd9Sstevel@tonic-gate     printf("sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate     /* probe for mii transceiver */
3707c478bd9Sstevel@tonic-gate     /* search for total of 32 possible mii phy addresses */
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate     found = 0;
3737c478bd9Sstevel@tonic-gate     for (phy_addr = 0; phy_addr < 32; phy_addr++) {
3747c478bd9Sstevel@tonic-gate         u16 mii_status;
3757c478bd9Sstevel@tonic-gate         u16 phy_id0, phy_id1;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate         mii_status = sis900_mdio_read(phy_addr, MII_STATUS);
3787c478bd9Sstevel@tonic-gate         if (mii_status == 0xffff || mii_status == 0x0000)
3797c478bd9Sstevel@tonic-gate             /* the mii is not accessable, try next one */
3807c478bd9Sstevel@tonic-gate             continue;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate         phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
3837c478bd9Sstevel@tonic-gate         phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate         /* search our mii table for the current mii */
3867c478bd9Sstevel@tonic-gate         for (i = 0; mii_chip_table[i].phy_id1; i++) {
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate             if (phy_id0 == mii_chip_table[i].phy_id0) {
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate                 printf("sis900_probe: %s transceiver found at address %d.\n",
3917c478bd9Sstevel@tonic-gate                        mii_chip_table[i].name, phy_addr);
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate                 mii.chip_info = &mii_chip_table[i];
3947c478bd9Sstevel@tonic-gate                 mii.phy_addr  = phy_addr;
3957c478bd9Sstevel@tonic-gate                 mii.status    = sis900_mdio_read(phy_addr, MII_STATUS);
3967c478bd9Sstevel@tonic-gate                 mii.next      = NULL;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate                 found=1;
3997c478bd9Sstevel@tonic-gate                 break;
4007c478bd9Sstevel@tonic-gate             }
4017c478bd9Sstevel@tonic-gate         }
4027c478bd9Sstevel@tonic-gate     }
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate     if (found == 0) {
4057c478bd9Sstevel@tonic-gate         printf("sis900_probe: No MII transceivers found!\n");
4067c478bd9Sstevel@tonic-gate         return 0;
4077c478bd9Sstevel@tonic-gate     }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate     /* Arbitrarily select the last PHY found as current PHY */
4107c478bd9Sstevel@tonic-gate     cur_phy = mii.phy_addr;
4117c478bd9Sstevel@tonic-gate     printf("sis900_probe: Using %s as default\n",  mii.chip_info->name);
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate     /* initialize device */
4147c478bd9Sstevel@tonic-gate     sis900_init(nic);
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate     dev->disable  = sis900_disable;
4177c478bd9Sstevel@tonic-gate     nic->poll     = sis900_poll;
4187c478bd9Sstevel@tonic-gate     nic->transmit = sis900_transmit;
4197c478bd9Sstevel@tonic-gate     nic->irq      = sis900_irq;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate     return 1;
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate  * EEPROM Routines:  These functions read and write to EEPROM for
4267c478bd9Sstevel@tonic-gate  *    retrieving the MAC address and other configuration information about
4277c478bd9Sstevel@tonic-gate  *    the card.
4287c478bd9Sstevel@tonic-gate  */
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate /* Delay between EEPROM clock transitions. */
4317c478bd9Sstevel@tonic-gate #define eeprom_delay()  inl(ee_addr)
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate /* Function: sis900_read_eeprom
4347c478bd9Sstevel@tonic-gate  *
4357c478bd9Sstevel@tonic-gate  * Description: reads and returns a given location from EEPROM
4367c478bd9Sstevel@tonic-gate  *
4377c478bd9Sstevel@tonic-gate  * Arguments: int location:       requested EEPROM location
4387c478bd9Sstevel@tonic-gate  *
4397c478bd9Sstevel@tonic-gate  * Returns:   u16:                contents of requested EEPROM location
4407c478bd9Sstevel@tonic-gate  *
4417c478bd9Sstevel@tonic-gate  */
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate /* Read Serial EEPROM through EEPROM Access Register, Note that location is
4447c478bd9Sstevel@tonic-gate    in word (16 bits) unit */
sis900_read_eeprom(int location)4457c478bd9Sstevel@tonic-gate static u16 sis900_read_eeprom(int location)
4467c478bd9Sstevel@tonic-gate {
4477c478bd9Sstevel@tonic-gate     int i;
4487c478bd9Sstevel@tonic-gate     u16 retval = 0;
4497c478bd9Sstevel@tonic-gate     long ee_addr = ioaddr + mear;
4507c478bd9Sstevel@tonic-gate     u32 read_cmd = location | EEread;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate     outl(0, ee_addr);
4537c478bd9Sstevel@tonic-gate     eeprom_delay();
4547c478bd9Sstevel@tonic-gate     outl(EECLK, ee_addr);
4557c478bd9Sstevel@tonic-gate     eeprom_delay();
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate     /* Shift the read command (9) bits out. */
4587c478bd9Sstevel@tonic-gate     for (i = 8; i >= 0; i--) {
4597c478bd9Sstevel@tonic-gate         u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
4607c478bd9Sstevel@tonic-gate         outl(dataval, ee_addr);
4617c478bd9Sstevel@tonic-gate         eeprom_delay();
4627c478bd9Sstevel@tonic-gate         outl(dataval | EECLK, ee_addr);
4637c478bd9Sstevel@tonic-gate         eeprom_delay();
4647c478bd9Sstevel@tonic-gate     }
4657c478bd9Sstevel@tonic-gate     outb(EECS, ee_addr);
4667c478bd9Sstevel@tonic-gate     eeprom_delay();
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate     /* read the 16-bits data in */
4697c478bd9Sstevel@tonic-gate     for (i = 16; i > 0; i--) {
4707c478bd9Sstevel@tonic-gate         outl(EECS, ee_addr);
4717c478bd9Sstevel@tonic-gate         eeprom_delay();
4727c478bd9Sstevel@tonic-gate         outl(EECS | EECLK, ee_addr);
4737c478bd9Sstevel@tonic-gate         eeprom_delay();
4747c478bd9Sstevel@tonic-gate         retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
4757c478bd9Sstevel@tonic-gate         eeprom_delay();
4767c478bd9Sstevel@tonic-gate     }
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate     /* Terminate the EEPROM access. */
4797c478bd9Sstevel@tonic-gate     outl(0, ee_addr);
4807c478bd9Sstevel@tonic-gate     eeprom_delay();
4817c478bd9Sstevel@tonic-gate     outl(EECLK, ee_addr);
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate     return (retval);
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate #define sis900_mdio_delay()    inl(mdio_addr)
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate /*
4897c478bd9Sstevel@tonic-gate    Read and write the MII management registers using software-generated
4907c478bd9Sstevel@tonic-gate    serial MDIO protocol. Note that the command bits and data bits are
4917c478bd9Sstevel@tonic-gate    send out seperately
4927c478bd9Sstevel@tonic-gate */
4937c478bd9Sstevel@tonic-gate 
sis900_mdio_idle(long mdio_addr)4947c478bd9Sstevel@tonic-gate static void sis900_mdio_idle(long mdio_addr)
4957c478bd9Sstevel@tonic-gate {
4967c478bd9Sstevel@tonic-gate     outl(MDIO | MDDIR, mdio_addr);
4977c478bd9Sstevel@tonic-gate     sis900_mdio_delay();
4987c478bd9Sstevel@tonic-gate     outl(MDIO | MDDIR | MDC, mdio_addr);
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate /* Syncronize the MII management interface by shifting 32 one bits out. */
sis900_mdio_reset(long mdio_addr)5027c478bd9Sstevel@tonic-gate static void sis900_mdio_reset(long mdio_addr)
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate     int i;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate     for (i = 31; i >= 0; i--) {
5077c478bd9Sstevel@tonic-gate         outl(MDDIR | MDIO, mdio_addr);
5087c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5097c478bd9Sstevel@tonic-gate         outl(MDDIR | MDIO | MDC, mdio_addr);
5107c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5117c478bd9Sstevel@tonic-gate     }
5127c478bd9Sstevel@tonic-gate     return;
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate 
sis900_mdio_read(int phy_id,int location)5157c478bd9Sstevel@tonic-gate static u16 sis900_mdio_read(int phy_id, int location)
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate     long mdio_addr = ioaddr + mear;
5187c478bd9Sstevel@tonic-gate     int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
5197c478bd9Sstevel@tonic-gate     u16 retval = 0;
5207c478bd9Sstevel@tonic-gate     int i;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate     sis900_mdio_reset(mdio_addr);
5237c478bd9Sstevel@tonic-gate     sis900_mdio_idle(mdio_addr);
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate     for (i = 15; i >= 0; i--) {
5267c478bd9Sstevel@tonic-gate         int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
5277c478bd9Sstevel@tonic-gate         outl(dataval, mdio_addr);
5287c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5297c478bd9Sstevel@tonic-gate         outl(dataval | MDC, mdio_addr);
5307c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5317c478bd9Sstevel@tonic-gate     }
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate     /* Read the 16 data bits. */
5347c478bd9Sstevel@tonic-gate     for (i = 16; i > 0; i--) {
5357c478bd9Sstevel@tonic-gate         outl(0, mdio_addr);
5367c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5377c478bd9Sstevel@tonic-gate         retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
5387c478bd9Sstevel@tonic-gate         outl(MDC, mdio_addr);
5397c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5407c478bd9Sstevel@tonic-gate     }
5417c478bd9Sstevel@tonic-gate     outl(0x00, mdio_addr);
5427c478bd9Sstevel@tonic-gate     return retval;
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate #if 0
5467c478bd9Sstevel@tonic-gate static void sis900_mdio_write(int phy_id, int location, int value)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate     long mdio_addr = ioaddr + mear;
5497c478bd9Sstevel@tonic-gate     int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
5507c478bd9Sstevel@tonic-gate     int i;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate     sis900_mdio_reset(mdio_addr);
5537c478bd9Sstevel@tonic-gate     sis900_mdio_idle(mdio_addr);
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate     /* Shift the command bits out. */
5567c478bd9Sstevel@tonic-gate     for (i = 15; i >= 0; i--) {
5577c478bd9Sstevel@tonic-gate         int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
5587c478bd9Sstevel@tonic-gate         outb(dataval, mdio_addr);
5597c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5607c478bd9Sstevel@tonic-gate         outb(dataval | MDC, mdio_addr);
5617c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5627c478bd9Sstevel@tonic-gate     }
5637c478bd9Sstevel@tonic-gate     sis900_mdio_delay();
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate     /* Shift the value bits out. */
5667c478bd9Sstevel@tonic-gate     for (i = 15; i >= 0; i--) {
5677c478bd9Sstevel@tonic-gate         int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
5687c478bd9Sstevel@tonic-gate         outl(dataval, mdio_addr);
5697c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5707c478bd9Sstevel@tonic-gate         outl(dataval | MDC, mdio_addr);
5717c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5727c478bd9Sstevel@tonic-gate     }
5737c478bd9Sstevel@tonic-gate     sis900_mdio_delay();
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate     /* Clear out extra bits. */
5767c478bd9Sstevel@tonic-gate     for (i = 2; i > 0; i--) {
5777c478bd9Sstevel@tonic-gate         outb(0, mdio_addr);
5787c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5797c478bd9Sstevel@tonic-gate         outb(MDC, mdio_addr);
5807c478bd9Sstevel@tonic-gate         sis900_mdio_delay();
5817c478bd9Sstevel@tonic-gate     }
5827c478bd9Sstevel@tonic-gate     outl(0x00, mdio_addr);
5837c478bd9Sstevel@tonic-gate     return;
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate #endif
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate /* Function: sis900_init
5887c478bd9Sstevel@tonic-gate  *
5897c478bd9Sstevel@tonic-gate  * Description: resets the ethernet controller chip and various
5907c478bd9Sstevel@tonic-gate  *    data structures required for sending and receiving packets.
5917c478bd9Sstevel@tonic-gate  *
5927c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
5937c478bd9Sstevel@tonic-gate  *
5947c478bd9Sstevel@tonic-gate  * returns:   void.
5957c478bd9Sstevel@tonic-gate  */
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate static void
sis900_init(struct nic * nic)5987c478bd9Sstevel@tonic-gate sis900_init(struct nic *nic)
5997c478bd9Sstevel@tonic-gate {
6007c478bd9Sstevel@tonic-gate     /* Soft reset the chip. */
6017c478bd9Sstevel@tonic-gate     sis900_reset(nic);
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate     sis900_init_rxfilter(nic);
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate     sis900_init_txd(nic);
6067c478bd9Sstevel@tonic-gate     sis900_init_rxd(nic);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate     sis900_set_rx_mode(nic);
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate     sis900_check_mode(nic);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate     outl(RxENA| inl(ioaddr + cr), ioaddr + cr);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate /*
6167c478bd9Sstevel@tonic-gate  * Function: sis900_reset
6177c478bd9Sstevel@tonic-gate  *
6187c478bd9Sstevel@tonic-gate  * Description: disables interrupts and soft resets the controller chip
6197c478bd9Sstevel@tonic-gate  *
6207c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
6217c478bd9Sstevel@tonic-gate  *
6227c478bd9Sstevel@tonic-gate  * Returns:   void.
6237c478bd9Sstevel@tonic-gate  */
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate static void
sis900_reset(struct nic * nic __unused)6267c478bd9Sstevel@tonic-gate sis900_reset(struct nic *nic __unused)
6277c478bd9Sstevel@tonic-gate {
6287c478bd9Sstevel@tonic-gate     int i = 0;
6297c478bd9Sstevel@tonic-gate     u32 status = TxRCMP | RxRCMP;
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate     outl(0, ioaddr + ier);
6327c478bd9Sstevel@tonic-gate     outl(0, ioaddr + imr);
6337c478bd9Sstevel@tonic-gate     outl(0, ioaddr + rfcr);
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate     outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr);
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate     /* Check that the chip has finished the reset. */
6387c478bd9Sstevel@tonic-gate     while (status && (i++ < 1000)) {
6397c478bd9Sstevel@tonic-gate         status ^= (inl(isr + ioaddr) & status);
6407c478bd9Sstevel@tonic-gate     }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate     if( (pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) )
6437c478bd9Sstevel@tonic-gate             outl(PESEL | RND_CNT, ioaddr + cfg);
6447c478bd9Sstevel@tonic-gate     else
6457c478bd9Sstevel@tonic-gate             outl(PESEL, ioaddr + cfg);
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate /* Function: sis_init_rxfilter
6497c478bd9Sstevel@tonic-gate  *
6507c478bd9Sstevel@tonic-gate  * Description: sets receive filter address to our MAC address
6517c478bd9Sstevel@tonic-gate  *
6527c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
6537c478bd9Sstevel@tonic-gate  *
6547c478bd9Sstevel@tonic-gate  * returns:   void.
6557c478bd9Sstevel@tonic-gate  */
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate static void
sis900_init_rxfilter(struct nic * nic)6587c478bd9Sstevel@tonic-gate sis900_init_rxfilter(struct nic *nic)
6597c478bd9Sstevel@tonic-gate {
6607c478bd9Sstevel@tonic-gate     u32 rfcrSave;
6617c478bd9Sstevel@tonic-gate     int i;
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate     rfcrSave = inl(rfcr + ioaddr);
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate     /* disable packet filtering before setting filter */
6667c478bd9Sstevel@tonic-gate     outl(rfcrSave & ~RFEN, rfcr + ioaddr);
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate     /* load MAC addr to filter data register */
6697c478bd9Sstevel@tonic-gate     for (i = 0 ; i < 3 ; i++) {
6707c478bd9Sstevel@tonic-gate         u32 w;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate         w = (u32) *((u16 *)(nic->node_addr)+i);
6737c478bd9Sstevel@tonic-gate         outl((i << RFADDR_shift), ioaddr + rfcr);
6747c478bd9Sstevel@tonic-gate         outl(w, ioaddr + rfdr);
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate         if (sis900_debug > 0)
6777c478bd9Sstevel@tonic-gate             printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
6787c478bd9Sstevel@tonic-gate                    i, inl(ioaddr + rfdr));
6797c478bd9Sstevel@tonic-gate     }
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate     /* enable packet filitering */
6827c478bd9Sstevel@tonic-gate     outl(rfcrSave | RFEN, rfcr + ioaddr);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate /*
6867c478bd9Sstevel@tonic-gate  * Function: sis_init_txd
6877c478bd9Sstevel@tonic-gate  *
6887c478bd9Sstevel@tonic-gate  * Description: initializes the Tx descriptor
6897c478bd9Sstevel@tonic-gate  *
6907c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
6917c478bd9Sstevel@tonic-gate  *
6927c478bd9Sstevel@tonic-gate  * returns:   void.
6937c478bd9Sstevel@tonic-gate  */
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate static void
sis900_init_txd(struct nic * nic __unused)6967c478bd9Sstevel@tonic-gate sis900_init_txd(struct nic *nic __unused)
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate     txd.link   = (u32) 0;
6997c478bd9Sstevel@tonic-gate     txd.cmdsts = (u32) 0;
7007c478bd9Sstevel@tonic-gate     txd.bufptr = virt_to_bus(&txb[0]);
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate     /* load Transmit Descriptor Register */
7037c478bd9Sstevel@tonic-gate     outl(virt_to_bus(&txd), ioaddr + txdp);
7047c478bd9Sstevel@tonic-gate     if (sis900_debug > 0)
7057c478bd9Sstevel@tonic-gate         printf("sis900_init_txd: TX descriptor register loaded with: %X\n",
7067c478bd9Sstevel@tonic-gate                inl(ioaddr + txdp));
7077c478bd9Sstevel@tonic-gate }
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate /* Function: sis_init_rxd
7107c478bd9Sstevel@tonic-gate  *
7117c478bd9Sstevel@tonic-gate  * Description: initializes the Rx descriptor ring
7127c478bd9Sstevel@tonic-gate  *
7137c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
7147c478bd9Sstevel@tonic-gate  *
7157c478bd9Sstevel@tonic-gate  * Returns:   void.
7167c478bd9Sstevel@tonic-gate  */
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate static void
sis900_init_rxd(struct nic * nic __unused)7197c478bd9Sstevel@tonic-gate sis900_init_rxd(struct nic *nic __unused)
7207c478bd9Sstevel@tonic-gate {
7217c478bd9Sstevel@tonic-gate     int i;
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate     cur_rx = 0;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate     /* init RX descriptor */
7267c478bd9Sstevel@tonic-gate     for (i = 0; i < NUM_RX_DESC; i++) {
7277c478bd9Sstevel@tonic-gate         rxd[i].link   = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]);
7287c478bd9Sstevel@tonic-gate         rxd[i].cmdsts = (u32) RX_BUF_SIZE;
7297c478bd9Sstevel@tonic-gate         rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]);
7307c478bd9Sstevel@tonic-gate         if (sis900_debug > 0)
7317c478bd9Sstevel@tonic-gate             printf("sis900_init_rxd: rxd[%d]=%X link=%X cmdsts=%X bufptr=%X\n",
7327c478bd9Sstevel@tonic-gate                    i, &rxd[i], rxd[i].link, rxd[i].cmdsts, rxd[i].bufptr);
7337c478bd9Sstevel@tonic-gate     }
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate     /* load Receive Descriptor Register */
7367c478bd9Sstevel@tonic-gate     outl(virt_to_bus(&rxd[0]), ioaddr + rxdp);
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate     if (sis900_debug > 0)
7397c478bd9Sstevel@tonic-gate         printf("sis900_init_rxd: RX descriptor register loaded with: %X\n",
7407c478bd9Sstevel@tonic-gate                inl(ioaddr + rxdp));
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate /* Function: sis_init_rxd
7457c478bd9Sstevel@tonic-gate  *
7467c478bd9Sstevel@tonic-gate  * Description:
7477c478bd9Sstevel@tonic-gate  *    sets the receive mode to accept all broadcast packets and packets
7487c478bd9Sstevel@tonic-gate  *    with our MAC address, and reject all multicast packets.
7497c478bd9Sstevel@tonic-gate  *
7507c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
7517c478bd9Sstevel@tonic-gate  *
7527c478bd9Sstevel@tonic-gate  * Returns:   void.
7537c478bd9Sstevel@tonic-gate  */
7547c478bd9Sstevel@tonic-gate 
sis900_set_rx_mode(struct nic * nic __unused)7557c478bd9Sstevel@tonic-gate static void sis900_set_rx_mode(struct nic *nic __unused)
7567c478bd9Sstevel@tonic-gate {
7577c478bd9Sstevel@tonic-gate     int i, table_entries;
7587c478bd9Sstevel@tonic-gate     u32 rx_mode;
7597c478bd9Sstevel@tonic-gate     u16 mc_filter[16] = {0};	/* 256/128 bits multicast hash table */
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate     if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV))
7627c478bd9Sstevel@tonic-gate 	table_entries = 16;
7637c478bd9Sstevel@tonic-gate     else
7647c478bd9Sstevel@tonic-gate 	table_entries = 8;
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate     /* accept all multicast packet */
7677c478bd9Sstevel@tonic-gate     rx_mode = RFAAB | RFAAM;
7687c478bd9Sstevel@tonic-gate     for (i = 0; i < table_entries; i++)
7697c478bd9Sstevel@tonic-gate 		mc_filter[i] = 0xffff;
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate     /* update Multicast Hash Table in Receive Filter */
7727c478bd9Sstevel@tonic-gate     for (i = 0; i < table_entries; i++) {
7737c478bd9Sstevel@tonic-gate         /* why plus 0x04? That makes the correct value for hash table. */
7747c478bd9Sstevel@tonic-gate         outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
7757c478bd9Sstevel@tonic-gate         outl(mc_filter[i], ioaddr + rfdr);
7767c478bd9Sstevel@tonic-gate     }
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate     /* Accept Broadcast and multicast packets, destination addresses that match
7797c478bd9Sstevel@tonic-gate        our MAC address */
7807c478bd9Sstevel@tonic-gate     outl(RFEN | rx_mode, ioaddr + rfcr);
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate     return;
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate /* Function: sis900_check_mode
7867c478bd9Sstevel@tonic-gate  *
7877c478bd9Sstevel@tonic-gate  * Description: checks the state of transmit and receive
7887c478bd9Sstevel@tonic-gate  *    parameters on the NIC, and updates NIC registers to match
7897c478bd9Sstevel@tonic-gate  *
7907c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
7917c478bd9Sstevel@tonic-gate  *
7927c478bd9Sstevel@tonic-gate  * Returns:   void.
7937c478bd9Sstevel@tonic-gate  */
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate static void
sis900_check_mode(struct nic * nic)7967c478bd9Sstevel@tonic-gate sis900_check_mode(struct nic *nic)
7977c478bd9Sstevel@tonic-gate {
7987c478bd9Sstevel@tonic-gate     int speed, duplex;
7997c478bd9Sstevel@tonic-gate     u32 tx_flags = 0, rx_flags = 0;
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate     mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate     if( inl(ioaddr + cfg) & EDB_MASTER_EN ) {
8047c478bd9Sstevel@tonic-gate         tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
8057c478bd9Sstevel@tonic-gate 	rx_flags = DMA_BURST_64 << RxMXDMA_shift;
8067c478bd9Sstevel@tonic-gate     }
8077c478bd9Sstevel@tonic-gate     else {
8087c478bd9Sstevel@tonic-gate             tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
8097c478bd9Sstevel@tonic-gate             rx_flags = DMA_BURST_512 << RxMXDMA_shift;
8107c478bd9Sstevel@tonic-gate     }
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate     if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
8137c478bd9Sstevel@tonic-gate         rx_flags |= (RxDRNT_10 << RxDRNT_shift);
8147c478bd9Sstevel@tonic-gate         tx_flags |= (TxDRNT_10 << TxDRNT_shift);
8157c478bd9Sstevel@tonic-gate     }
8167c478bd9Sstevel@tonic-gate     else {
8177c478bd9Sstevel@tonic-gate         rx_flags |= (RxDRNT_100 << RxDRNT_shift);
8187c478bd9Sstevel@tonic-gate         tx_flags |= (TxDRNT_100 << TxDRNT_shift);
8197c478bd9Sstevel@tonic-gate     }
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate     if (duplex == FDX_CAPABLE_FULL_SELECTED) {
8227c478bd9Sstevel@tonic-gate         tx_flags |= (TxCSI | TxHBI);
8237c478bd9Sstevel@tonic-gate         rx_flags |= RxATX;
8247c478bd9Sstevel@tonic-gate     }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate     outl (tx_flags, ioaddr + txcfg);
8277c478bd9Sstevel@tonic-gate     outl (rx_flags, ioaddr + rxcfg);
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate /* Function: sis900_read_mode
8317c478bd9Sstevel@tonic-gate  *
8327c478bd9Sstevel@tonic-gate  * Description: retrieves and displays speed and duplex
8337c478bd9Sstevel@tonic-gate  *    parameters from the NIC
8347c478bd9Sstevel@tonic-gate  *
8357c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
8367c478bd9Sstevel@tonic-gate  *
8377c478bd9Sstevel@tonic-gate  * Returns:   void.
8387c478bd9Sstevel@tonic-gate  */
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate static void
sis900_read_mode(struct nic * nic __unused,int phy_addr,int * speed,int * duplex)8417c478bd9Sstevel@tonic-gate sis900_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
8427c478bd9Sstevel@tonic-gate {
8437c478bd9Sstevel@tonic-gate     int i = 0;
8447c478bd9Sstevel@tonic-gate     u32 status;
8457c478bd9Sstevel@tonic-gate     u16 phy_id0, phy_id1;
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate     /* STSOUT register is Latched on Transition, read operation updates it */
8487c478bd9Sstevel@tonic-gate     while (i++ < 2)
8497c478bd9Sstevel@tonic-gate         status = sis900_mdio_read(phy_addr, MII_STSOUT);
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate     *speed = HW_SPEED_10_MBPS;
8527c478bd9Sstevel@tonic-gate     *duplex = FDX_CAPABLE_HALF_SELECTED;
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate     if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX))
8557c478bd9Sstevel@tonic-gate 	*speed = HW_SPEED_100_MBPS;
8567c478bd9Sstevel@tonic-gate     if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX))
8577c478bd9Sstevel@tonic-gate 	*duplex = FDX_CAPABLE_FULL_SELECTED;
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate     /* Workaround for Realtek RTL8201 PHY issue */
8607c478bd9Sstevel@tonic-gate     phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
8617c478bd9Sstevel@tonic-gate     phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
8627c478bd9Sstevel@tonic-gate     if((phy_id0 == 0x0000) && ((phy_id1 & 0xFFF0) == 0x8200)){
8637c478bd9Sstevel@tonic-gate 	if(sis900_mdio_read(phy_addr, MII_CONTROL) & MII_CNTL_FDX)
8647c478bd9Sstevel@tonic-gate 	    *duplex = FDX_CAPABLE_FULL_SELECTED;
8657c478bd9Sstevel@tonic-gate 	if(sis900_mdio_read(phy_addr, 0x0019) & 0x01)
8667c478bd9Sstevel@tonic-gate 	    *speed = HW_SPEED_100_MBPS;
8677c478bd9Sstevel@tonic-gate     }
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate     if (status & MII_STSOUT_LINK_FAIL)
8707c478bd9Sstevel@tonic-gate         printf("sis900_read_mode: Media Link Off\n");
8717c478bd9Sstevel@tonic-gate     else
8727c478bd9Sstevel@tonic-gate         printf("sis900_read_mode: Media Link On %s %s-duplex \n",
8737c478bd9Sstevel@tonic-gate                *speed == HW_SPEED_100_MBPS ?
8747c478bd9Sstevel@tonic-gate                "100mbps" : "10mbps",
8757c478bd9Sstevel@tonic-gate                *duplex == FDX_CAPABLE_FULL_SELECTED ?
8767c478bd9Sstevel@tonic-gate                "full" : "half");
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate /* Function: amd79c901_read_mode
8807c478bd9Sstevel@tonic-gate  *
8817c478bd9Sstevel@tonic-gate  * Description: retrieves and displays speed and duplex
8827c478bd9Sstevel@tonic-gate  *    parameters from the NIC
8837c478bd9Sstevel@tonic-gate  *
8847c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
8857c478bd9Sstevel@tonic-gate  *
8867c478bd9Sstevel@tonic-gate  * Returns:   void.
8877c478bd9Sstevel@tonic-gate  */
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate static void
amd79c901_read_mode(struct nic * nic __unused,int phy_addr,int * speed,int * duplex)8907c478bd9Sstevel@tonic-gate amd79c901_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
8917c478bd9Sstevel@tonic-gate {
8927c478bd9Sstevel@tonic-gate     int i;
8937c478bd9Sstevel@tonic-gate     u16 status;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate     for (i = 0; i < 2; i++)
8967c478bd9Sstevel@tonic-gate         status = sis900_mdio_read(phy_addr, MII_STATUS);
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate     if (status & MII_STAT_CAN_AUTO) {
8997c478bd9Sstevel@tonic-gate         /* 10BASE-T PHY */
9007c478bd9Sstevel@tonic-gate         for (i = 0; i < 2; i++)
9017c478bd9Sstevel@tonic-gate             status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);
9027c478bd9Sstevel@tonic-gate         if (status & MII_STSSUM_SPD)
9037c478bd9Sstevel@tonic-gate             *speed = HW_SPEED_100_MBPS;
9047c478bd9Sstevel@tonic-gate         else
9057c478bd9Sstevel@tonic-gate             *speed = HW_SPEED_10_MBPS;
9067c478bd9Sstevel@tonic-gate         if (status & MII_STSSUM_DPLX)
9077c478bd9Sstevel@tonic-gate             *duplex = FDX_CAPABLE_FULL_SELECTED;
9087c478bd9Sstevel@tonic-gate         else
9097c478bd9Sstevel@tonic-gate             *duplex = FDX_CAPABLE_HALF_SELECTED;
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate         if (status & MII_STSSUM_LINK)
9127c478bd9Sstevel@tonic-gate             printf("amd79c901_read_mode: Media Link On %s %s-duplex \n",
9137c478bd9Sstevel@tonic-gate                    *speed == HW_SPEED_100_MBPS ?
9147c478bd9Sstevel@tonic-gate                    "100mbps" : "10mbps",
9157c478bd9Sstevel@tonic-gate                    *duplex == FDX_CAPABLE_FULL_SELECTED ?
9167c478bd9Sstevel@tonic-gate                    "full" : "half");
9177c478bd9Sstevel@tonic-gate         else
9187c478bd9Sstevel@tonic-gate             printf("amd79c901_read_mode: Media Link Off\n");
9197c478bd9Sstevel@tonic-gate     }
9207c478bd9Sstevel@tonic-gate     else {
9217c478bd9Sstevel@tonic-gate         /* HomePNA */
9227c478bd9Sstevel@tonic-gate         *speed = HW_SPEED_HOME;
9237c478bd9Sstevel@tonic-gate         *duplex = FDX_CAPABLE_HALF_SELECTED;
9247c478bd9Sstevel@tonic-gate         if (status & MII_STAT_LINK)
9257c478bd9Sstevel@tonic-gate             printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
9267c478bd9Sstevel@tonic-gate         else
9277c478bd9Sstevel@tonic-gate             printf("amd79c901_read_mode: Media Link Off\n");
9287c478bd9Sstevel@tonic-gate     }
9297c478bd9Sstevel@tonic-gate }
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate /**
9327c478bd9Sstevel@tonic-gate  *	ics1893_read_mode: - read media mode for ICS1893 PHY
9337c478bd9Sstevel@tonic-gate  *	@net_dev: the net device to read mode for
9347c478bd9Sstevel@tonic-gate  *	@phy_addr: mii phy address
9357c478bd9Sstevel@tonic-gate  *	@speed: the transmit speed to be determined
9367c478bd9Sstevel@tonic-gate  *	@duplex: the duplex mode to be determined
9377c478bd9Sstevel@tonic-gate  *
9387c478bd9Sstevel@tonic-gate  *	ICS1893 PHY use Quick Poll Detailed Status register
9397c478bd9Sstevel@tonic-gate  *	to determine the speed and duplex mode for sis900
9407c478bd9Sstevel@tonic-gate  */
9417c478bd9Sstevel@tonic-gate 
ics1893_read_mode(struct nic * nic __unused,int phy_addr,int * speed,int * duplex)9427c478bd9Sstevel@tonic-gate static void ics1893_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
9437c478bd9Sstevel@tonic-gate {
9447c478bd9Sstevel@tonic-gate 	int i = 0;
9457c478bd9Sstevel@tonic-gate 	u32 status;
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	/* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
9487c478bd9Sstevel@tonic-gate 	for (i = 0; i < 2; i++)
9497c478bd9Sstevel@tonic-gate 		status = sis900_mdio_read(phy_addr, MII_QPDSTS);
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 	if (status & MII_STSICS_SPD)
9527c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_100_MBPS;
9537c478bd9Sstevel@tonic-gate 	else
9547c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_10_MBPS;
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 	if (status & MII_STSICS_DPLX)
9577c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_FULL_SELECTED;
9587c478bd9Sstevel@tonic-gate 	else
9597c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_HALF_SELECTED;
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	if (status & MII_STSICS_LINKSTS)
9627c478bd9Sstevel@tonic-gate 		printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
9637c478bd9Sstevel@tonic-gate 		       *speed == HW_SPEED_100_MBPS ?
9647c478bd9Sstevel@tonic-gate 		       "100mbps" : "10mbps",
9657c478bd9Sstevel@tonic-gate 		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
9667c478bd9Sstevel@tonic-gate 		       "full" : "half");
9677c478bd9Sstevel@tonic-gate 	else
9687c478bd9Sstevel@tonic-gate 		printf("ics1893_read_mode: Media Link Off\n");
9697c478bd9Sstevel@tonic-gate }
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate /**
9727c478bd9Sstevel@tonic-gate  *	rtl8201_read_mode: - read media mode for rtl8201 phy
9737c478bd9Sstevel@tonic-gate  *	@nic: the net device to read mode for
9747c478bd9Sstevel@tonic-gate  *	@phy_addr: mii phy address
9757c478bd9Sstevel@tonic-gate  *	@speed: the transmit speed to be determined
9767c478bd9Sstevel@tonic-gate  *	@duplex: the duplex mode to be determined
9777c478bd9Sstevel@tonic-gate  *
9787c478bd9Sstevel@tonic-gate  *	read MII_STATUS register from rtl8201 phy
9797c478bd9Sstevel@tonic-gate  *	to determine the speed and duplex mode for sis900
9807c478bd9Sstevel@tonic-gate  */
9817c478bd9Sstevel@tonic-gate 
rtl8201_read_mode(struct nic * nic __unused,int phy_addr,int * speed,int * duplex)9827c478bd9Sstevel@tonic-gate static void rtl8201_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
9837c478bd9Sstevel@tonic-gate {
9847c478bd9Sstevel@tonic-gate 	u32 status;
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	status = sis900_mdio_read(phy_addr, MII_STATUS);
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate 	if (status & MII_STAT_CAN_TX_FDX) {
9897c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_100_MBPS;
9907c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_FULL_SELECTED;
9917c478bd9Sstevel@tonic-gate 	}
9927c478bd9Sstevel@tonic-gate 	else if (status & MII_STAT_CAN_TX) {
9937c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_100_MBPS;
9947c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_HALF_SELECTED;
9957c478bd9Sstevel@tonic-gate 	}
9967c478bd9Sstevel@tonic-gate 	else if (status & MII_STAT_CAN_T_FDX) {
9977c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_10_MBPS;
9987c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_FULL_SELECTED;
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 	else if (status & MII_STAT_CAN_T) {
10017c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_10_MBPS;
10027c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_HALF_SELECTED;
10037c478bd9Sstevel@tonic-gate 	}
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	if (status & MII_STAT_LINK)
10067c478bd9Sstevel@tonic-gate 		printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
10077c478bd9Sstevel@tonic-gate 		       *speed == HW_SPEED_100_MBPS ?
10087c478bd9Sstevel@tonic-gate 		       "100mbps" : "10mbps",
10097c478bd9Sstevel@tonic-gate 		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
10107c478bd9Sstevel@tonic-gate 		       "full" : "half");
10117c478bd9Sstevel@tonic-gate 	else
10127c478bd9Sstevel@tonic-gate 		printf("rtl8201_read_config_mode: Media Link Off\n");
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate /**
10167c478bd9Sstevel@tonic-gate  *	vt6103_read_mode: - read media mode for vt6103 phy
10177c478bd9Sstevel@tonic-gate  *	@nic: the net device to read mode for
10187c478bd9Sstevel@tonic-gate  *	@phy_addr: mii phy address
10197c478bd9Sstevel@tonic-gate  *	@speed: the transmit speed to be determined
10207c478bd9Sstevel@tonic-gate  *	@duplex: the duplex mode to be determined
10217c478bd9Sstevel@tonic-gate  *
10227c478bd9Sstevel@tonic-gate  *	read MII_STATUS register from rtl8201 phy
10237c478bd9Sstevel@tonic-gate  *	to determine the speed and duplex mode for sis900
10247c478bd9Sstevel@tonic-gate  */
10257c478bd9Sstevel@tonic-gate 
vt6103_read_mode(struct nic * nic __unused,int phy_addr,int * speed,int * duplex)10267c478bd9Sstevel@tonic-gate static void vt6103_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
10277c478bd9Sstevel@tonic-gate {
10287c478bd9Sstevel@tonic-gate 	u32 status;
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 	status = sis900_mdio_read(phy_addr, MII_STATUS);
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	if (status & MII_STAT_CAN_TX_FDX) {
10337c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_100_MBPS;
10347c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_FULL_SELECTED;
10357c478bd9Sstevel@tonic-gate 	}
10367c478bd9Sstevel@tonic-gate 	else if (status & MII_STAT_CAN_TX) {
10377c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_100_MBPS;
10387c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_HALF_SELECTED;
10397c478bd9Sstevel@tonic-gate 	}
10407c478bd9Sstevel@tonic-gate 	else if (status & MII_STAT_CAN_T_FDX) {
10417c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_10_MBPS;
10427c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_FULL_SELECTED;
10437c478bd9Sstevel@tonic-gate 	}
10447c478bd9Sstevel@tonic-gate 	else if (status & MII_STAT_CAN_T) {
10457c478bd9Sstevel@tonic-gate 		*speed = HW_SPEED_10_MBPS;
10467c478bd9Sstevel@tonic-gate 		*duplex = FDX_CAPABLE_HALF_SELECTED;
10477c478bd9Sstevel@tonic-gate 	}
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	if (status & MII_STAT_LINK)
10507c478bd9Sstevel@tonic-gate 		printf("vt6103_read_mode: Media Link On %s %s-duplex \n",
10517c478bd9Sstevel@tonic-gate 		       *speed == HW_SPEED_100_MBPS ?
10527c478bd9Sstevel@tonic-gate 		       "100mbps" : "10mbps",
10537c478bd9Sstevel@tonic-gate 		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
10547c478bd9Sstevel@tonic-gate 		       "full" : "half");
10557c478bd9Sstevel@tonic-gate 	else
10567c478bd9Sstevel@tonic-gate 		printf("vt6103_read_config_mode: Media Link Off\n");
10577c478bd9Sstevel@tonic-gate }
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate /* Function: sis900_transmit
10607c478bd9Sstevel@tonic-gate  *
10617c478bd9Sstevel@tonic-gate  * Description: transmits a packet and waits for completion or timeout.
10627c478bd9Sstevel@tonic-gate  *
10637c478bd9Sstevel@tonic-gate  * Arguments: char d[6]:          destination ethernet address.
10647c478bd9Sstevel@tonic-gate  *            unsigned short t:   ethernet protocol type.
10657c478bd9Sstevel@tonic-gate  *            unsigned short s:   size of the data-part of the packet.
10667c478bd9Sstevel@tonic-gate  *            char *p:            the data for the packet.
10677c478bd9Sstevel@tonic-gate  *
10687c478bd9Sstevel@tonic-gate  * Returns:   void.
10697c478bd9Sstevel@tonic-gate  */
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate static void
sis900_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)10727c478bd9Sstevel@tonic-gate sis900_transmit(struct nic  *nic,
10737c478bd9Sstevel@tonic-gate                 const char  *d,     /* Destination */
10747c478bd9Sstevel@tonic-gate                 unsigned int t,     /* Type */
10757c478bd9Sstevel@tonic-gate                 unsigned int s,     /* size */
10767c478bd9Sstevel@tonic-gate                 const char  *p)     /* Packet */
10777c478bd9Sstevel@tonic-gate {
10787c478bd9Sstevel@tonic-gate     u32 to, nstype;
10797c478bd9Sstevel@tonic-gate     u32 tx_status;
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate     /* Stop the transmitter */
10827c478bd9Sstevel@tonic-gate     outl(TxDIS | inl(ioaddr + cr), ioaddr + cr);
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate     /* load Transmit Descriptor Register */
10857c478bd9Sstevel@tonic-gate     outl(virt_to_bus(&txd), ioaddr + txdp);
10867c478bd9Sstevel@tonic-gate     if (sis900_debug > 1)
10877c478bd9Sstevel@tonic-gate         printf("sis900_transmit: TX descriptor register loaded with: %X\n",
10887c478bd9Sstevel@tonic-gate                inl(ioaddr + txdp));
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate     memcpy(txb, d, ETH_ALEN);
10917c478bd9Sstevel@tonic-gate     memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
10927c478bd9Sstevel@tonic-gate     nstype = htons(t);
10937c478bd9Sstevel@tonic-gate     memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
10947c478bd9Sstevel@tonic-gate     memcpy(txb + ETH_HLEN, p, s);
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate     s += ETH_HLEN;
10977c478bd9Sstevel@tonic-gate     s &= DSIZE;
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate     if (sis900_debug > 1)
11007c478bd9Sstevel@tonic-gate         printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate     /* pad to minimum packet size */
11037c478bd9Sstevel@tonic-gate     while (s < ETH_ZLEN)
11047c478bd9Sstevel@tonic-gate         txb[s++] = '\0';
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate     /* set the transmit buffer descriptor and enable Transmit State Machine */
11077c478bd9Sstevel@tonic-gate     txd.bufptr = virt_to_bus(&txb[0]);
11087c478bd9Sstevel@tonic-gate     txd.cmdsts = (u32) OWN | s;
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate     /* restart the transmitter */
11117c478bd9Sstevel@tonic-gate     outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate     if (sis900_debug > 1)
11147c478bd9Sstevel@tonic-gate         printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate     to = currticks() + TX_TIMEOUT;
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate     while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
11197c478bd9Sstevel@tonic-gate         /* wait */ ;
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate     if (currticks() >= to) {
11227c478bd9Sstevel@tonic-gate         printf("sis900_transmit: TX Timeout! Tx status %X.\n", tx_status);
11237c478bd9Sstevel@tonic-gate     }
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate     if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
11267c478bd9Sstevel@tonic-gate         /* packet unsuccessfully transmited */
11277c478bd9Sstevel@tonic-gate         printf("sis900_transmit: Transmit error, Tx status %X.\n", tx_status);
11287c478bd9Sstevel@tonic-gate     }
11297c478bd9Sstevel@tonic-gate     /* Disable interrupts by clearing the interrupt mask. */
11307c478bd9Sstevel@tonic-gate     outl(0, ioaddr + imr);
11317c478bd9Sstevel@tonic-gate }
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate /* Function: sis900_poll
11347c478bd9Sstevel@tonic-gate  *
11357c478bd9Sstevel@tonic-gate  * Description: checks for a received packet and returns it if found.
11367c478bd9Sstevel@tonic-gate  *
11377c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
11387c478bd9Sstevel@tonic-gate  *
11397c478bd9Sstevel@tonic-gate  * Returns:   1 if a packet was recieved.
11407c478bd9Sstevel@tonic-gate  *            0 if no pacet was recieved.
11417c478bd9Sstevel@tonic-gate  *
11427c478bd9Sstevel@tonic-gate  * Side effects:
11437c478bd9Sstevel@tonic-gate  *            Returns (copies) the packet to the array nic->packet.
11447c478bd9Sstevel@tonic-gate  *            Returns the length of the packet in nic->packetlen.
11457c478bd9Sstevel@tonic-gate  */
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate static int
sis900_poll(struct nic * nic,int retrieve)11487c478bd9Sstevel@tonic-gate sis900_poll(struct nic *nic, int retrieve)
11497c478bd9Sstevel@tonic-gate {
11507c478bd9Sstevel@tonic-gate     u32 rx_status = rxd[cur_rx].cmdsts;
11517c478bd9Sstevel@tonic-gate     int retstat = 0;
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate     if (sis900_debug > 2)
11547c478bd9Sstevel@tonic-gate         printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status);
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate     if (!(rx_status & OWN))
11577c478bd9Sstevel@tonic-gate         return retstat;
11587c478bd9Sstevel@tonic-gate 
11597c478bd9Sstevel@tonic-gate     if (sis900_debug > 1)
11607c478bd9Sstevel@tonic-gate         printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
11617c478bd9Sstevel@tonic-gate                cur_rx, rx_status);
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate     if ( ! retrieve ) return 1;
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate     nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate     if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
11687c478bd9Sstevel@tonic-gate         /* corrupted packet received */
11697c478bd9Sstevel@tonic-gate         printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
11707c478bd9Sstevel@tonic-gate                rx_status);
11717c478bd9Sstevel@tonic-gate         retstat = 0;
11727c478bd9Sstevel@tonic-gate     } else {
11737c478bd9Sstevel@tonic-gate         /* give packet to higher level routine */
11747c478bd9Sstevel@tonic-gate         memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
11757c478bd9Sstevel@tonic-gate         retstat = 1;
11767c478bd9Sstevel@tonic-gate     }
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate     /* return the descriptor and buffer to receive ring */
11797c478bd9Sstevel@tonic-gate     rxd[cur_rx].cmdsts = RX_BUF_SIZE;
11807c478bd9Sstevel@tonic-gate     rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]);
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate     if (++cur_rx == NUM_RX_DESC)
11837c478bd9Sstevel@tonic-gate         cur_rx = 0;
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate     /* re-enable the potentially idle receive state machine */
11867c478bd9Sstevel@tonic-gate     outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate     return retstat;
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate /* Function: sis900_disable
11937c478bd9Sstevel@tonic-gate  *
11947c478bd9Sstevel@tonic-gate  * Description: Turns off interrupts and stops Tx and Rx engines
11957c478bd9Sstevel@tonic-gate  *
11967c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
11977c478bd9Sstevel@tonic-gate  *
11987c478bd9Sstevel@tonic-gate  * Returns:   void.
11997c478bd9Sstevel@tonic-gate  */
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate static void
sis900_disable(struct dev * dev)12027c478bd9Sstevel@tonic-gate sis900_disable(struct dev *dev)
12037c478bd9Sstevel@tonic-gate {
12047c478bd9Sstevel@tonic-gate     struct nic *nic = (struct nic *)dev;
12057c478bd9Sstevel@tonic-gate     /* merge reset and disable */
12067c478bd9Sstevel@tonic-gate     sis900_init(nic);
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate     /* Disable interrupts by clearing the interrupt mask. */
12097c478bd9Sstevel@tonic-gate     outl(0, ioaddr + imr);
12107c478bd9Sstevel@tonic-gate     outl(0, ioaddr + ier);
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate     /* Stop the chip's Tx and Rx Status Machine */
12137c478bd9Sstevel@tonic-gate     outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
12147c478bd9Sstevel@tonic-gate }
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate /* Function: sis900_irq
12177c478bd9Sstevel@tonic-gate  *
12187c478bd9Sstevel@tonic-gate  * Description: Enable, Disable, or Force, interrupts
12197c478bd9Sstevel@tonic-gate  *
12207c478bd9Sstevel@tonic-gate  * Arguments: struct nic *nic:          NIC data structure
12217c478bd9Sstevel@tonic-gate  *            irq_action_t action:      Requested action
12227c478bd9Sstevel@tonic-gate  *
12237c478bd9Sstevel@tonic-gate  * Returns:   void.
12247c478bd9Sstevel@tonic-gate  */
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate static void
sis900_irq(struct nic * nic __unused,irq_action_t action __unused)12277c478bd9Sstevel@tonic-gate sis900_irq(struct nic *nic __unused, irq_action_t action __unused)
12287c478bd9Sstevel@tonic-gate {
12297c478bd9Sstevel@tonic-gate   switch ( action ) {
12307c478bd9Sstevel@tonic-gate   case DISABLE :
12317c478bd9Sstevel@tonic-gate     break;
12327c478bd9Sstevel@tonic-gate   case ENABLE :
12337c478bd9Sstevel@tonic-gate     break;
12347c478bd9Sstevel@tonic-gate   case FORCE :
12357c478bd9Sstevel@tonic-gate     break;
12367c478bd9Sstevel@tonic-gate   }
12377c478bd9Sstevel@tonic-gate }
12387c478bd9Sstevel@tonic-gate 
12397c478bd9Sstevel@tonic-gate static struct pci_id sis900_nics[] = {
12407c478bd9Sstevel@tonic-gate PCI_ROM(0x1039, 0x0900, "sis900",  "SIS900"),
12417c478bd9Sstevel@tonic-gate PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016"),
12427c478bd9Sstevel@tonic-gate };
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate struct pci_driver sis900_driver = {
12457c478bd9Sstevel@tonic-gate 	.type     = NIC_DRIVER,
12467c478bd9Sstevel@tonic-gate 	.name     = "SIS900",
12477c478bd9Sstevel@tonic-gate 	.probe    = sis900_probe,
12487c478bd9Sstevel@tonic-gate 	.ids      = sis900_nics,
12497c478bd9Sstevel@tonic-gate 	.id_count = sizeof(sis900_nics)/sizeof(sis900_nics[0]),
12507c478bd9Sstevel@tonic-gate 	.class    = 0,
12517c478bd9Sstevel@tonic-gate };
1252