176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* -*- Mode:C; c-basic-offset:4; -*- */ 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900.c: An SiS 900/7016 PCI Fast Ethernet driver for Etherboot 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Copyright (C) 2001 Entity Cyber, Inc. 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Revision: 1.0 March 1, 2001 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Author: Marty Connor (mdc@etherboot.org) 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Adapted from a Linux driver which was written by Donald Becker 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman and modified by Ollie Lho and Chin-Shan Li of SiS Corporation. 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Rewritten for Etherboot by Marty Connor. 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman This software may be used and distributed according to the terms 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman of the GNU Public License (GPL), incorporated herein by reference. 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman References: 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support, 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman preliminary Rev. 1.0 Jan. 14, 1998 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support, 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman preliminary Rev. 1.0 Nov. 10, 1998 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution, 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman preliminary Rev. 1.0 Jan. 18, 1998 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman http://www.sis.com.tw/support/databook.htm */ 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2776d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL_ANY ); 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Revision History */ 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 07 Dec 2003 timlegge - Enabled Multicast Support 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 06 Dec 2003 timlegge - Fixed relocation issue in 5.2 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 04 Jan 2002 Chien-Yu Chen, Doug Ambrisko, Marty Connor Patch to Etherboot 5.0.5 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Added support for the SiS 630ET plus various bug fixes from linux kernel 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman source 2.4.17. 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 01 March 2001 mdc 1.0 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Initial Release. Tested with PCI based sis900 card and ThinkNIC 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman computer. 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20 March 2001 P.Koegel 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman added support for sis630e and PHY ICS1893 and RTL8201 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Testet with SIS730S chipset + ICS1893 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/ 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Includes */ 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "etherboot.h" 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/pci.h> 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "nic.h" 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "sis900.h" 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Globals */ 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct nic_operations sis900_operations; 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sis900_debug = 0; 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic unsigned short vendor, dev_id; 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic unsigned long ioaddr; 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic u8 pci_revision; 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic unsigned int cur_phy; 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic unsigned int cur_rx; 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct { 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BufferDesc txd; 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BufferDesc rxd[NUM_RX_DESC]; 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned char txb[TX_BUF_SIZE]; 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]; 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} sis900_bufs __shared; 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define txd sis900_bufs.txd 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define rxd sis900_bufs.rxd 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define txb sis900_bufs.txb 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define rxb sis900_bufs.rxb 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct mac_chip_info { 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *name; 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 vendor_id, device_id, flags; 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int io_size; 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} mac_chip_table[] = { 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900, 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE}, 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016, 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE}, 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {0,0,0,0,0} /* 0 terminated list. */ 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void vt6103_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct mii_chip_info { 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char * name; 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 phy_id0; 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 phy_id1; 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex); 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} mii_chip_table[] = { 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode}, 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode}, 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {"SiS 900 on Foxconn 661 7MI", 0x0143, 0xBC70, sis900_read_mode}, 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {"AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, amd79c901_read_mode}, 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {"AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, amd79c901_read_mode}, 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {"ICS 1893 Integrated PHYceiver" , 0x0015, 0xf440,ics1893_read_mode}, 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// {"NS 83851 PHY",0x2000, 0x5C20, MIX }, 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {"RTL 8201 10/100Mbps Phyceiver" , 0x0000, 0x8200,rtl8201_read_mode}, 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode}, 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman {0,0,0,0} 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct mii_phy { 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct mii_phy * next; 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct mii_chip_info * chip_info; 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int phy_addr; 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 status; 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} mii; 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// PCI to ISA bridge for SIS640E access 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct pci_device_id pci_isa_bridge_list[] = { 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman { .vendor = 0x1039, .device = 0x0008, 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .name = "SIS 85C503/5513 PCI to ISA bridge"}, 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13376d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPCI_DRIVER( sis_bridge_pci_driver, pci_isa_bridge_list, PCI_NO_CLASS ); 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct device_driver sis_bridge_driver = { 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .name = "SIS ISA bridge", 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .bus_driver = &pci_driver, 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .bus_driver_info = ( struct bus_driver_info * ) &sis_bridge_pci_driver, 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function Prototypes */ 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sis900_probe(struct nic *nic,struct pci_device *pci); 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic u16 sis900_read_eeprom(int location); 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_mdio_reset(long mdio_addr); 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_mdio_idle(long mdio_addr); 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic u16 sis900_mdio_read(int phy_id, int location); 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_mdio_write(int phy_id, int location, int val); 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_init(struct nic *nic); 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_reset(struct nic *nic); 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_init_rxfilter(struct nic *nic); 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_init_txd(struct nic *nic); 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_init_rxd(struct nic *nic); 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_set_rx_mode(struct nic *nic); 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_check_mode(struct nic *nic); 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_transmit(struct nic *nic, const char *d, 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int t, unsigned int s, const char *p); 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sis900_poll(struct nic *nic, int retrieve); 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_disable(struct nic *nic); 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_irq(struct nic *nic, irq_action_t action); 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @pci_dev: the sis900 pci device 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @net_dev: the net device to get address for 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Older SiS900 and friends, use EEPROM to store MAC address. 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MAC address is read from read_eeprom() into @net_dev->dev_addr. 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sis900_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic) 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 signature; 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* check to see if we have sane EEPROM */ 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman signature = (u16) sis900_read_eeprom( EEPROMSignature); 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (signature == 0xffff || signature == 0x0000) { 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ("sis900_probe: Error EERPOM read %hX\n", signature); 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* get MAC address from EEPROM */ 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < 3; i++) 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr); 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @pci_dev: the sis900 pci device 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @net_dev: the net device to get address for 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * is shared by 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * by LAN, otherwise is not. After MAC address is read from EEPROM, send 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * EEDONE signal to refuse EEPROM access by LAN. 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * The EEPROM map of SiS962 or SiS963 is different to SiS900. 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * The signature field in SiS962 or SiS963 spec is meaningless. 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MAC address is read into @net_dev->dev_addr. 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sis96x_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic) 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* long ioaddr = net_dev->base_addr; */ 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman long ee_addr = ioaddr + mear; 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 waittime = 0; 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("Alternate function\n"); 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(EEREQ, ee_addr); 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while(waittime < 2000) { 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if(inl(ee_addr) & EEGNT) { 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* get MAC address from EEPROM */ 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < 3; i++) 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr); 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(EEDONE, ee_addr); 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman udelay(1); 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman waittime ++; 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(EEDONE, ee_addr); 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * sis630e_get_mac_addr: - Get MAC address for SiS630E model 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @pci_dev: the sis900 pci device 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @net_dev: the net device to get address for 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * SiS630E model, use APC CMOS RAM to store MAC address. 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * APC CMOS RAM is accessed through ISA bridge. 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MAC address is read into @net_dev->dev_addr. 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic) 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 reg; 25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct bus_loc bus_loc; 25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman union { 25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct bus_dev bus_dev; 26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct pci_device isa_bridge; 26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } u; 26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* find PCI to ISA bridge */ 26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&bus_loc, 0, sizeof(bus_loc)); 26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! find_by_driver ( &bus_loc, &u.bus_dev, &sis_bridge_driver, 0 ) ) 26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_read_config_byte(&u.isa_bridge, 0x48, ®); 26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40); 27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < ETH_ALEN; i++) 27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman { 27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(0x09 + i, 0x70); 27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ((u8 *)(nic->node_addr))[i] = inb(0x71); 27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40); 27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Does not work with current bus/device model */ 28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset ( nic->node_addr, 0, sizeof ( nic->node_addr ) ); 28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * sis630e_get_mac_addr: - Get MAC address for SiS630E model 28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @pci_dev: the sis900 pci device 28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @net_dev: the net device to get address for 29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * SiS630E model, use APC CMOS RAM to store MAC address. 29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * APC CMOS RAM is accessed through ISA bridge. 29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MAC address is read into @net_dev->dev_addr. 29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic) 29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 rfcrSave; 29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 i; 30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rfcrSave = inl(rfcr + ioaddr); 30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(rfcrSave | RELOAD, ioaddr + cr); 30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ioaddr + cr); 30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* disable packet filtering before setting filter */ 30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(rfcrSave & ~RFEN, rfcr + ioaddr); 30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* load MAC addr to filter data register */ 31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0 ; i < 3 ; i++) { 31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl((i << RFADDR_shift), ioaddr + rfcr); 31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *( ((u16 *)nic->node_addr) + i) = inw(ioaddr + rfdr); 31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* enable packet filitering */ 31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(rfcrSave | RFEN, rfcr + ioaddr); 31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Function: sis900_probe 32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: initializes initializes the NIC, retrieves the 32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MAC address of the card, and sets up some globals required by 32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * other routines. 32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Side effects: 33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * leaves the ioaddress of the sis900 chip in the variable ioaddr. 33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * leaves the sis900 initialized, and ready to recieve packets. 33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: struct nic *: pointer to NIC data structure 33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int sis900_probe ( struct nic *nic, struct pci_device *pci ) { 33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int found=0; 34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int phy_addr; 34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 revision; 34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ret; 34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (pci->ioaddr == 0) 34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->irqno = 0; 34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->ioaddr = pci->ioaddr; 34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ioaddr = pci->ioaddr; 35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman vendor = pci->vendor; 35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dev_id = pci->device; 35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* wakeup chip */ 35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_write_config_dword(pci, 0x40, 0x00000000); 35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman adjust_pci_device(pci); 35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* get MAC address */ 36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ret = 0; 36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_read_config_byte(pci, PCI_REVISION, &revision); 36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* save for use later in sis900_reset() */ 36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_revision = revision; 36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (revision == SIS630E_900_REV) 36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ret = sis630e_get_mac_addr(pci, nic); 36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if ((revision > 0x81) && (revision <= 0x90)) 36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ret = sis635_get_mac_addr(pci, nic); 37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (revision == SIS96x_900_REV) 37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ret = sis96x_get_mac_addr(pci, nic); 37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ret = sis900_get_mac_addr(pci, nic); 37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (ret == 0) 37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman { 37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf ("sis900_probe: Error MAC address not found\n"); 37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 630ET : set the mii access mode as software-mode */ 38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (revision == SIS630ET_900_REV) 38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr); 38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG( "sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id ); 38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* probe for mii transceiver */ 38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* search for total of 32 possible mii phy addresses */ 38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman found = 0; 39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (phy_addr = 0; phy_addr < 32; phy_addr++) { 39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 mii_status; 39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 phy_id0, phy_id1; 39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_status = sis900_mdio_read(phy_addr, MII_STATUS); 39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (mii_status == 0xffff || mii_status == 0x0000) 39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* the mii is not accessable, try next one */ 39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman continue; 39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0); 40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1); 40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* search our mii table for the current mii */ 40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; mii_chip_table[i].phy_id1; i++) { 40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((phy_id0 == mii_chip_table[i].phy_id0) && 40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ((phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){ 40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_probe: %s transceiver found at address %d.\n", 41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii_chip_table[i].name, phy_addr); 41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii.chip_info = &mii_chip_table[i]; 41376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii.phy_addr = phy_addr; 41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii.status = sis900_mdio_read(phy_addr, MII_STATUS); 41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii.next = NULL; 41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman found=1; 41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 42176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (found == 0) { 42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_probe: No MII transceivers found!\n"); 42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Arbitrarily select the last PHY found as current PHY */ 42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cur_phy = mii.phy_addr; 43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_probe: Using %s as default\n", mii.chip_info->name); 43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* initialize device */ 43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_init(nic); 43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->nic_op = &sis900_operations; 43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * EEPROM Routines: These functions read and write to EEPROM for 44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * retrieving the MAC address and other configuration information about 44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the card. 44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Delay between EEPROM clock transitions. */ 44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define eeprom_delay() inl(ee_addr) 45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis900_read_eeprom 45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: reads and returns a given location from EEPROM 45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: int location: requested EEPROM location 45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: u16: contents of requested EEPROM location 45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 46076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Read Serial EEPROM through EEPROM Access Register, Note that location is 46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman in word (16 bits) unit */ 46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic u16 sis900_read_eeprom(int location) 46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 retval = 0; 46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman long ee_addr = ioaddr + mear; 46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 read_cmd = location | EEread; 47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ee_addr); 47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(EECS, ee_addr); 47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Shift the read command (9) bits out. */ 47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 8; i >= 0; i--) { 47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS; 47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(dataval, ee_addr); 48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(dataval | EECLK, ee_addr); 48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(EECS, ee_addr); 48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* read the 16-bits data in */ 48876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 16; i > 0; i--) { 48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(EECS, ee_addr); 49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(EECS | EECLK, ee_addr); 49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0); 49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Terminate the EEPROM access. */ 49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ee_addr); 49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman eeprom_delay(); 50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// outl(EECLK, ee_addr); 50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return (retval); 50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define sis900_mdio_delay() inl(mdio_addr) 50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman Read and write the MII management registers using software-generated 51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman serial MDIO protocol. Note that the command bits and data bits are 51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman send out seperately 51276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/ 51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_mdio_idle(long mdio_addr) 51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(MDIO | MDDIR, mdio_addr); 51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(MDIO | MDDIR | MDC, mdio_addr); 51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Syncronize the MII management interface by shifting 32 one bits out. */ 52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_mdio_reset(long mdio_addr) 52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 31; i >= 0; i--) { 52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(MDDIR | MDIO, mdio_addr); 52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(MDDIR | MDIO | MDC, mdio_addr); 53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic u16 sis900_mdio_read(int phy_id, int location) 53676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman long mdio_addr = ioaddr + mear; 53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift); 53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 retval = 0; 54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_reset(mdio_addr); 54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_idle(mdio_addr); 54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 15; i >= 0; i--) { 54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR; 54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(dataval, mdio_addr); 54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(dataval | MDC, mdio_addr); 55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Read the 16 data bits. */ 55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 16; i > 0; i--) { 55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, mdio_addr); 55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0); 55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(MDC, mdio_addr); 55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0x00, mdio_addr); 56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return retval; 56376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if 0 56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_mdio_write(int phy_id, int location, int value) 56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman long mdio_addr = ioaddr + mear; 56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift); 57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_reset(mdio_addr); 57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_idle(mdio_addr); 57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 57576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Shift the command bits out. */ 57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 15; i >= 0; i--) { 57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR; 57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(dataval, mdio_addr); 57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(dataval | MDC, mdio_addr); 58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Shift the value bits out. */ 58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 15; i >= 0; i--) { 58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR; 58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(dataval, mdio_addr); 58976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 59076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(dataval | MDC, mdio_addr); 59176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 59276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 59376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 59476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 59576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Clear out extra bits. */ 59676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 2; i > 0; i--) { 59776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(0, mdio_addr); 59876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 59976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(MDC, mdio_addr); 60076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_mdio_delay(); 60176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 60276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0x00, mdio_addr); 60376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 60476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 60576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 60676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 60776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 60876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis900_init 60976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 61076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: resets the ethernet controller chip and various 61176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * data structures required for sending and receiving packets. 61276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 61376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 61476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 61576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * returns: void. 61676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 61776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 61876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 61976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_init(struct nic *nic) 62076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 62176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Soft reset the chip. */ 62276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_reset(nic); 62376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 62476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_init_rxfilter(nic); 62576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 62676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_init_txd(nic); 62776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_init_rxd(nic); 62876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 62976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_set_rx_mode(nic); 63076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_check_mode(nic); 63276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(RxENA| inl(ioaddr + cr), ioaddr + cr); 63476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 63576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 63776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 63876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Function: sis900_reset 63976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 64076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: disables interrupts and soft resets the controller chip 64176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 64276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 64376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 64476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 64576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 64676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 64776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 64876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_reset(struct nic *nic __unused) 64976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 65076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i = 0; 65176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 status = TxRCMP | RxRCMP; 65276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ioaddr + ier); 65476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ioaddr + imr); 65576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ioaddr + rfcr); 65676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr); 65876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 65976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Check that the chip has finished the reset. */ 66076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (status && (i++ < 1000)) { 66176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status ^= (inl(isr + ioaddr) & status); 66276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 66376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 66476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( (pci_revision >= SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) ) 66576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(PESEL | RND_CNT, ioaddr + cfg); 66676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 66776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(PESEL, ioaddr + cfg); 66876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 66976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 67076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 67176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis_init_rxfilter 67276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 67376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: sets receive filter address to our MAC address 67476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 67576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 67676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 67776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * returns: void. 67876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 67976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 68176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_init_rxfilter(struct nic *nic) 68276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 68376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 rfcrSave; 68476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 68576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rfcrSave = inl(rfcr + ioaddr); 68776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 68876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* disable packet filtering before setting filter */ 68976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(rfcrSave & ~RFEN, rfcr + ioaddr); 69076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 69176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* load MAC addr to filter data register */ 69276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0 ; i < 3 ; i++) { 69376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 w; 69476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 69576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman w = (u32) *((u16 *)(nic->node_addr)+i); 69676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl((i << RFADDR_shift), ioaddr + rfcr); 69776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(w, ioaddr + rfdr); 69876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 69976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 0) 70076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n", 70176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i, inl(ioaddr + rfdr)); 70276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 70376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 70476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* enable packet filitering */ 70576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(rfcrSave | RFEN, rfcr + ioaddr); 70676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 70776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 70876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 70976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 71076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Function: sis_init_txd 71176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 71276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: initializes the Tx descriptor 71376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 71476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 71576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 71676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * returns: void. 71776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 71876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 71976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 72076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_init_txd(struct nic *nic __unused) 72176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 72276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txd.link = (u32) 0; 72376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txd.cmdsts = (u32) 0; 72476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txd.bufptr = virt_to_bus(&txb[0]); 72576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 72676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* load Transmit Descriptor Register */ 72776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(virt_to_bus(&txd), ioaddr + txdp); 72876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 0) 72976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_init_txd: TX descriptor register loaded with: %X\n", 73076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman inl(ioaddr + txdp)); 73176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 73276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 73376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 73476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis_init_rxd 73576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 73676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: initializes the Rx descriptor ring 73776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 73876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 73976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 74076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 74176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 74276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 74476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_init_rxd(struct nic *nic __unused) 74576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 74676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 74776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 74876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cur_rx = 0; 74976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 75076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* init RX descriptor */ 75176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < NUM_RX_DESC; i++) { 75276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rxd[i].link = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]); 75376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rxd[i].cmdsts = (u32) RX_BUF_SIZE; 75476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]); 75576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 0) 75676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n", 75776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i, &rxd[i], (unsigned int) rxd[i].link, (unsigned int) rxd[i].cmdsts, 75876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (unsigned int) rxd[i].bufptr); 75976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 76076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 76176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* load Receive Descriptor Register */ 76276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(virt_to_bus(&rxd[0]), ioaddr + rxdp); 76376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 76476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 0) 76576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_init_rxd: RX descriptor register loaded with: %X\n", 76676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman inl(ioaddr + rxdp)); 76776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 76876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 76976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 77076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 77176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis_init_rxd 77276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 77376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: 77476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * sets the receive mode to accept all broadcast packets and packets 77576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * with our MAC address, and reject all multicast packets. 77676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 77776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 77876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 77976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 78076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 78176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 78276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void sis900_set_rx_mode(struct nic *nic __unused) 78376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 78476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i, table_entries; 78576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 rx_mode; 78676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */ 78776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 78876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV)) 78976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman table_entries = 16; 79076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 79176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman table_entries = 8; 79276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 79376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* accept all multicast packet */ 79476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_mode = RFAAB | RFAAM; 79576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < table_entries; i++) 79676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mc_filter[i] = 0xffff; 79776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 79876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* update Multicast Hash Table in Receive Filter */ 79976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < table_entries; i++) { 80076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* why plus 0x04? That makes the correct value for hash table. */ 80176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr); 80276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(mc_filter[i], ioaddr + rfdr); 80376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 80476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 80576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Accept Broadcast and multicast packets, destination addresses that match 80676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman our MAC address */ 80776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(RFEN | rx_mode, ioaddr + rfcr); 80876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 80976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 81076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 81176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 81276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 81376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis900_check_mode 81476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 81576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: checks the state of transmit and receive 81676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * parameters on the NIC, and updates NIC registers to match 81776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 81876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 81976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 82076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 82176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 82276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 82376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 82476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_check_mode(struct nic *nic) 82576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 82676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int speed, duplex; 82776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 tx_flags = 0, rx_flags = 0; 82876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 82976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex); 83076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 83176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if( inl(ioaddr + cfg) & EDB_MASTER_EN ) { 83276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); 83376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_flags = DMA_BURST_64 << RxMXDMA_shift; 83476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 83576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else { 83676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); 83776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_flags = DMA_BURST_512 << RxMXDMA_shift; 83876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 83976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 84076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) { 84176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_flags |= (RxDRNT_10 << RxDRNT_shift); 84276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_flags |= (TxDRNT_10 << TxDRNT_shift); 84376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 84476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else { 84576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_flags |= (RxDRNT_100 << RxDRNT_shift); 84676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_flags |= (TxDRNT_100 << TxDRNT_shift); 84776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 84876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 84976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (duplex == FDX_CAPABLE_FULL_SELECTED) { 85076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman tx_flags |= (TxCSI | TxHBI); 85176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rx_flags |= RxATX; 85276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 85376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 85476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl (tx_flags, ioaddr + txcfg); 85576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl (rx_flags, ioaddr + rxcfg); 85676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 85776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 85876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 85976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis900_read_mode 86076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 86176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: retrieves and displays speed and duplex 86276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * parameters from the NIC 86376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 86476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 86576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 86676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 86776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 86876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 86976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 87076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex) 87176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 87276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i = 0; 87376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 status; 87476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 phy_id0, phy_id1; 87576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 87676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* STSOUT register is Latched on Transition, read operation updates it */ 87776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman do { 87876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = sis900_mdio_read(phy_addr, MII_STSOUT); 87976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } while (i++ < 2); 88076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 88176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_10_MBPS; 88276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_HALF_SELECTED; 88376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 88476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX)) 88576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_100_MBPS; 88676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX)) 88776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_FULL_SELECTED; 88876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 88976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Workaround for Realtek RTL8201 PHY issue */ 89076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0); 89176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1); 89276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if((phy_id0 == 0x0000) && ((phy_id1 & 0xFFF0) == 0x8200)){ 89376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if(sis900_mdio_read(phy_addr, MII_CONTROL) & MII_CNTL_FDX) 89476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_FULL_SELECTED; 89576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if(sis900_mdio_read(phy_addr, 0x0019) & 0x01) 89676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_100_MBPS; 89776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 89876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 89976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STSOUT_LINK_FAIL) 90076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_read_mode: Media Link Off\n"); 90176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 90276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_read_mode: Media Link On %s %s-duplex \n", 90376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed == HW_SPEED_100_MBPS ? 90476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "100mbps" : "10mbps", 90576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex == FDX_CAPABLE_FULL_SELECTED ? 90676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "full" : "half"); 90776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 90876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 90976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 91076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: amd79c901_read_mode 91176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 91276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: retrieves and displays speed and duplex 91376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * parameters from the NIC 91476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 91576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 91676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 91776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 91876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 91976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 92076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 92176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanamd79c901_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex) 92276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 92376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 92476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u16 status; 92576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 92676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < 2; i++) 92776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = sis900_mdio_read(phy_addr, MII_STATUS); 92876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 92976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STAT_CAN_AUTO) { 93076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 10BASE-T PHY */ 93176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < 2; i++) 93276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY); 93376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STSSUM_SPD) 93476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_100_MBPS; 93576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 93676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_10_MBPS; 93776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STSSUM_DPLX) 93876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_FULL_SELECTED; 93976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 94076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_HALF_SELECTED; 94176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 94276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STSSUM_LINK) 94376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("amd79c901_read_mode: Media Link On %s %s-duplex \n", 94476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed == HW_SPEED_100_MBPS ? 94576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "100mbps" : "10mbps", 94676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex == FDX_CAPABLE_FULL_SELECTED ? 94776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "full" : "half"); 94876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 94976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("amd79c901_read_mode: Media Link Off\n"); 95076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 95176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else { 95276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* HomePNA */ 95376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_HOME; 95476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_HALF_SELECTED; 95576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STAT_LINK) 95676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n"); 95776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 95876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("amd79c901_read_mode: Media Link Off\n"); 95976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 96076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 96176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 96276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 96376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 96476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ics1893_read_mode: - read media mode for ICS1893 PHY 96576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @net_dev: the net device to read mode for 96676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @phy_addr: mii phy address 96776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @speed: the transmit speed to be determined 96876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @duplex: the duplex mode to be determined 96976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 97076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ICS1893 PHY use Quick Poll Detailed Status register 97176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * to determine the speed and duplex mode for sis900 97276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 97376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 97476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void ics1893_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex) 97576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 97676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i = 0; 97776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 status; 97876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 97976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* MII_QPDSTS is Latched, read twice in succession will reflect the current state */ 98076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (i = 0; i < 2; i++) 98176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = sis900_mdio_read(phy_addr, MII_QPDSTS); 98276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 98376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STSICS_SPD) 98476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_100_MBPS; 98576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 98676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_10_MBPS; 98776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 98876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STSICS_DPLX) 98976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_FULL_SELECTED; 99076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 99176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_HALF_SELECTED; 99276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 99376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STSICS_LINKSTS) 99476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("ics1893_read_mode: Media Link On %s %s-duplex \n", 99576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed == HW_SPEED_100_MBPS ? 99676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "100mbps" : "10mbps", 99776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex == FDX_CAPABLE_FULL_SELECTED ? 99876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "full" : "half"); 99976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 100076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("ics1893_read_mode: Media Link Off\n"); 100176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 100276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 100376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 100476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * rtl8201_read_mode: - read media mode for rtl8201 phy 100576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @nic: the net device to read mode for 100676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @phy_addr: mii phy address 100776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @speed: the transmit speed to be determined 100876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @duplex: the duplex mode to be determined 100976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 101076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * read MII_STATUS register from rtl8201 phy 101176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * to determine the speed and duplex mode for sis900 101276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 101376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 101476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void rtl8201_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex) 101576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 101676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 status; 101776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 101876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = sis900_mdio_read(phy_addr, MII_STATUS); 101976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 102076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STAT_CAN_TX_FDX) { 102176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_100_MBPS; 102276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_FULL_SELECTED; 102376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 102476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (status & MII_STAT_CAN_TX) { 102576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_100_MBPS; 102676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_HALF_SELECTED; 102776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 102876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (status & MII_STAT_CAN_T_FDX) { 102976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_10_MBPS; 103076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_FULL_SELECTED; 103176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 103276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (status & MII_STAT_CAN_T) { 103376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_10_MBPS; 103476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_HALF_SELECTED; 103576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 103676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 103776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STAT_LINK) 103876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("rtl8201_read_mode: Media Link On %s %s-duplex \n", 103976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed == HW_SPEED_100_MBPS ? 104076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "100mbps" : "10mbps", 104176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex == FDX_CAPABLE_FULL_SELECTED ? 104276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "full" : "half"); 104376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 104476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("rtl8201_read_config_mode: Media Link Off\n"); 104576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 104676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 104776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 104876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * vt6103_read_mode: - read media mode for vt6103 phy 104976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @nic: the net device to read mode for 105076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @phy_addr: mii phy address 105176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @speed: the transmit speed to be determined 105276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @duplex: the duplex mode to be determined 105376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 105476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * read MII_STATUS register from rtl8201 phy 105576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * to determine the speed and duplex mode for sis900 105676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 105776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 105876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void vt6103_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex) 105976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 106076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 status; 106176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 106276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman status = sis900_mdio_read(phy_addr, MII_STATUS); 106376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 106476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STAT_CAN_TX_FDX) { 106576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_100_MBPS; 106676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_FULL_SELECTED; 106776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 106876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (status & MII_STAT_CAN_TX) { 106976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_100_MBPS; 107076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_HALF_SELECTED; 107176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 107276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (status & MII_STAT_CAN_T_FDX) { 107376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_10_MBPS; 107476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_FULL_SELECTED; 107576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 107676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (status & MII_STAT_CAN_T) { 107776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed = HW_SPEED_10_MBPS; 107876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex = FDX_CAPABLE_HALF_SELECTED; 107976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 108076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 108176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (status & MII_STAT_LINK) 108276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("vt6103_read_mode: Media Link On %s %s-duplex \n", 108376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *speed == HW_SPEED_100_MBPS ? 108476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "100mbps" : "10mbps", 108576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *duplex == FDX_CAPABLE_FULL_SELECTED ? 108676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "full" : "half"); 108776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 108876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("vt6103_read_config_mode: Media Link Off\n"); 108976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 109076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 109176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis900_transmit 109276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 109376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: transmits a packet and waits for completion or timeout. 109476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 109576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: char d[6]: destination ethernet address. 109676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * unsigned short t: ethernet protocol type. 109776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * unsigned short s: size of the data-part of the packet. 109876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * char *p: the data for the packet. 109976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 110076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 110176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 110276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 110376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 110476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_transmit(struct nic *nic, 110576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *d, /* Destination */ 110676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int t, /* Type */ 110776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int s, /* size */ 110876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *p) /* Packet */ 110976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 111076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 to, nstype; 111176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman volatile u32 tx_status; 111276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 111376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Stop the transmitter */ 111476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(TxDIS | inl(ioaddr + cr), ioaddr + cr); 111576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 111676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* load Transmit Descriptor Register */ 111776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(virt_to_bus(&txd), ioaddr + txdp); 111876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 1) 111976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_transmit: TX descriptor register loaded with: %X\n", 112076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman inl(ioaddr + txdp)); 112176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 112276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(txb, d, ETH_ALEN); 112376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN); 112476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nstype = htons(t); 112576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2); 112676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(txb + ETH_HLEN, p, s); 112776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 112876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s += ETH_HLEN; 112976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s &= DSIZE; 113076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 113176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 1) 113276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t); 113376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 113476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* pad to minimum packet size */ 113576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (s < ETH_ZLEN) 113676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txb[s++] = '\0'; 113776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 113876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* set the transmit buffer descriptor and enable Transmit State Machine */ 113976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txd.bufptr = virt_to_bus(&txb[0]); 114076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman txd.cmdsts = (u32) OWN | s; 114176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 114276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* restart the transmitter */ 114376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(TxENA | inl(ioaddr + cr), ioaddr + cr); 114476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 114576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 1) 114676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s); 114776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 114876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman to = currticks() + TX_TIMEOUT; 114976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 115076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to)) 115176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* wait */ ; 115276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 115376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (currticks() >= to) { 115476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_transmit: TX Timeout! Tx status %X.\n", 115576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (unsigned int) tx_status); 115676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 115776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 115876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (tx_status & (ABORT | UNDERRUN | OWCOLL)) { 115976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* packet unsuccessfully transmited */ 116076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_transmit: Transmit error, Tx status %X.\n", 116176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (unsigned int) tx_status); 116276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 116376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Disable interrupts by clearing the interrupt mask. */ 116476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ioaddr + imr); 116576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 116676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 116776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 116876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis900_poll 116976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 117076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: checks for a received packet and returns it if found. 117176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 117276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 117376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 117476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: 1 if a packet was recieved. 117576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 0 if no pacet was recieved. 117676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 117776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Side effects: 117876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns (copies) the packet to the array nic->packet. 117976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns the length of the packet in nic->packetlen. 118076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 118176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 118276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int 118376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_poll(struct nic *nic, int retrieve) 118476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 118576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 rx_status = rxd[cur_rx].cmdsts; 118676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 intr_status; 118776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int retstat = 0; 118876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 118976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* acknowledge interrupts by reading interrupt status register */ 119076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman intr_status = inl(ioaddr + isr); 119176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 119276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 2) 119376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, 119476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (unsigned int) rx_status); 119576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 119676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(rx_status & OWN)) 119776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return retstat; 119876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 119976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sis900_debug > 1) 120076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n", 120176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cur_rx, (unsigned int) rx_status); 120276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 120376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! retrieve ) return 1; 120476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 120576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nic->packetlen = (rx_status & DSIZE) - CRC_SIZE; 120676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 120776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) { 120876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* corrupted packet received */ 120976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("sis900_poll: Corrupted packet received, buffer status = %X\n", 121076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (unsigned int) rx_status); 121176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman retstat = 0; 121276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 121376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* give packet to higher level routine */ 121476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen); 121576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman retstat = 1; 121676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 121776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 121876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* return the descriptor and buffer to receive ring */ 121976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rxd[cur_rx].cmdsts = RX_BUF_SIZE; 122076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]); 122176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 122276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (++cur_rx == NUM_RX_DESC) 122376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cur_rx = 0; 122476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 122576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* re-enable the potentially idle receive state machine */ 122676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(RxENA | inl(ioaddr + cr), ioaddr + cr); 122776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 122876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return retstat; 122976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 123076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 123176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 123276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 123376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis900_disable 123476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 123576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: Turns off interrupts and stops Tx and Rx engines 123676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 123776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 123876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 123976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 124076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 124176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 124276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 124376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_disable ( struct nic *nic ) { 124476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 124576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_init(nic); 124676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 124776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Disable interrupts by clearing the interrupt mask. */ 124876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ioaddr + imr); 124976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ioaddr + ier); 125076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 125176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Stop the chip's Tx and Rx Status Machine */ 125276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr); 125376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 125476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 125576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 125676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Function: sis900_irq 125776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 125876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Description: Enable, Disable, or Force, interrupts 125976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 126076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Arguments: struct nic *nic: NIC data structure 126176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * irq_action_t action: Requested action 126276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 126376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns: void. 126476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 126576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 126676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void 126776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmansis900_irq(struct nic *nic __unused, irq_action_t action __unused) 126876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 126976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch ( action ) { 127076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case DISABLE : 127176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl(0, ioaddr + imr); 127276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 127376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case ENABLE : 127476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr); 127576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 127676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case FORCE : 127776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 127876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 127976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 128076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 128176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct nic_operations sis900_operations = { 128276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .connect = dummy_connect, 128376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .poll = sis900_poll, 128476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .transmit = sis900_transmit, 128576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .irq = sis900_irq, 128676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 128776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 128876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct pci_device_id sis900_nics[] = { 128976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPCI_ROM(0x1039, 0x0900, "sis900", "SIS900", 0), 129076d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016", 0), 129176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 129276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 129376d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanPCI_DRIVER ( sis900_driver, sis900_nics, PCI_NO_CLASS ); 129476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 129576d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanDRIVER ( "SIS900", nic_driver, pci_driver, sis900_driver, 129676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sis900_probe, sis900_disable ); 129776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 129876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 129976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Local variables: 130076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * c-basic-offset: 8 130176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * c-indent-level: 8 130276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * tab-width: 8 130376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * End: 130476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1305