15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* -*- Mode:C; c-basic-offset:4; -*- */
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   sis900.c: An SiS 900/7016 PCI Fast Ethernet driver for Etherboot
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Copyright (C) 2001 Entity Cyber, Inc.
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Revision:	1.0	March 1, 2001
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Author: Marty Connor (mdc@thinguin.org)
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Adapted from a Linux driver which was written by Donald Becker
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   and modified by Ollie Lho and Chin-Shan Li of SiS Corporation.
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Rewritten for Etherboot by Marty Connor.
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   This software may be used and distributed according to the terms
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   of the GNU Public License (GPL), incorporated herein by reference.
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   References:
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support,
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   preliminary Rev. 1.0 Jan. 14, 1998
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support,
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   preliminary Rev. 1.0 Nov. 10, 1998
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   preliminary Rev. 1.0 Jan. 18, 1998
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   http://www.sis.com.tw/support/databook.htm */
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Revision History */
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  01 March 2001  mdc     1.0
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Initial Release.  Tested with PCI based sis900 card and ThinkNIC
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     computer.
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  20 March 2001 P.Koegel
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     added support for sis630e and PHY ICS1893 and RTL8201
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     Testet with SIS730S chipset + ICS1893
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Includes */
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "etherboot.h"
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "nic.h"
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "pci.h"
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "cards.h"
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "sis900.h"
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Globals */
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int sis900_debug = 0;
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned short vendor, dev_id;
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned long ioaddr;
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned int cur_phy;
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned int cur_rx;
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic BufferDesc txd;
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic BufferDesc rxd[NUM_RX_DESC];
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef USE_LOWMEM_BUFFER
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define txb ((char *)0x10000 - TX_BUF_SIZE)
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define rxb ((char *)0x10000 - NUM_RX_DESC*RX_BUF_SIZE - TX_BUF_SIZE)
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned char txb[TX_BUF_SIZE];
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct mac_chip_info {
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    const char *name;
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 vendor_id, device_id, flags;
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int io_size;
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} mac_chip_table[] = {
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900,
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016,
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {0,0,0,0,0} /* 0 terminated list. */
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct mii_chip_info {
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    const char * name;
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 phy_id0;
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 phy_id1;
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex);
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} mii_chip_table[] = {
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode},
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode},
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"AMD 79C901 10BASE-T PHY",  0x0000, 0x35b9, amd79c901_read_mode},
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"AMD 79C901 HomePNA PHY",   0x0000, 0x35c8, amd79c901_read_mode},
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"ICS 1893 Integrated PHYceiver"   , 0x0015, 0xf441,ics1893_read_mode},
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {"RTL 8201 10/100Mbps Phyceiver"   , 0x0000, 0x8201,rtl8201_read_mode},
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {0,0,0,0}
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct mii_phy {
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    struct mii_phy * next;
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    struct mii_chip_info * chip_info;
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int phy_addr;
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 status;
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} mii;
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project// PCI to ISA bridge for SIS640E access
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct pci_device   pci_isa_bridge_list[] = {
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{ 0x1039, 0x0008,
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		"SIS 85C503/5513 PCI to ISA bridge", 0, 0, 0, 0},
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{0, 0, NULL, 0, 0, 0, 0}
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function Prototypes */
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *sis900_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci);
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16  sis900_read_eeprom(int location);
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_mdio_reset(long mdio_addr);
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_mdio_idle(long mdio_addr);
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16  sis900_mdio_read(int phy_id, int location);
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_mdio_write(int phy_id, int location, int val);
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_init(struct nic *nic);
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_reset(struct nic *nic);
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_init_rxfilter(struct nic *nic);
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_init_txd(struct nic *nic);
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_init_rxd(struct nic *nic);
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_set_rx_mode(struct nic *nic);
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_check_mode(struct nic *nic);
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_transmit(struct nic *nic, const char *d,
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                            unsigned int t, unsigned int s, const char *p);
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int  sis900_poll(struct nic *nic);
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_disable(struct nic *nic);
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@pci_dev: the sis900 pci device
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@net_dev: the net device to get address for
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	Older SiS900 and friends, use EEPROM to store MAC address.
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	MAC address is read from read_eeprom() into @net_dev->dev_addr.
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int sis900_get_mac_addr(struct pci_device * pci_dev , struct nic *nic)
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	u16 signature;
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int i;
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* check to see if we have sane EEPROM */
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	signature = (u16) sis900_read_eeprom( EEPROMSignature);
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (signature == 0xffff || signature == 0x0000) {
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf ("sis900_probe: Error EERPOM read %hX\n", signature);
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return 0;
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* get MAC address from EEPROM */
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i = 0; i < 3; i++)
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return 1;
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	sis630e_get_mac_addr: - Get MAC address for SiS630E model
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@pci_dev: the sis900 pci device
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@net_dev: the net device to get address for
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	SiS630E model, use APC CMOS RAM to store MAC address.
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	APC CMOS RAM is accessed through ISA bridge.
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	MAC address is read into @net_dev->dev_addr.
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int sis630e_get_mac_addr(struct pci_device * pci_dev, struct nic *nic)
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	u8 reg;
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int i;
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct pci_device	*p;
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	// find PCI to ISA bridge
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_pci_init(pci_isa_bridge_list);
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* the firts entry in this list should contain bus/devfn */
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    p = pci_isa_bridge_list;
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	pcibios_read_config_byte(p->bus,p->devfn, 0x48, &reg);
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	pcibios_write_config_byte(p->bus,p->devfn, 0x48, reg | 0x40);
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i = 0; i < ETH_ALEN; i++)
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(0x09 + i, 0x70);
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		((u8 *)(nic->node_addr))[i] = inb(0x71);
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	pcibios_write_config_byte(p->bus,p->devfn, 0x48, reg & ~0x40);
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return 1;
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Function: sis900_probe
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: initializes initializes the NIC, retrieves the
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    MAC address of the card, and sets up some globals required by
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    other routines.
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Side effects:
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *            leaves the ioaddress of the sis900 chip in the variable ioaddr.
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *            leaves the sis900 initialized, and ready to recieve packets.
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   struct nic *:          pointer to NIC data structure
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *sis900_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci)
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int found=0;
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int phy_addr;
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 signature;
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u8 revision;
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int ret;
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (io_addrs == 0 || *io_addrs == 0)
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return NULL;
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ioaddr  = *io_addrs & ~3;
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    vendor  = pci->vendor;
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    dev_id  = pci->dev_id;
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* wakeup chip */
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    pcibios_write_config_dword(pci->bus, pci->devfn, 0x40, 0x00000000);
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    adjust_pci_device(pci);
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* get MAC address */
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ret = 0;
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    pcibios_read_config_byte(pci->bus,pci->devfn, PCI_REVISION, &revision);
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV)
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       ret = sis630e_get_mac_addr(pci, nic);
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else if (revision == SIS630S_900_REV)
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        ret = sis630e_get_mac_addr(pci, nic);
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        ret = sis900_get_mac_addr(pci, nic);
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (ret == 0)
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf ("sis900_probe: Error MAC address not found\n");
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return NULL;
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("\nsis900_probe: MAC addr %! at ioaddr %#hX\n",
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project           nic->node_addr, ioaddr);
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id);
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* probe for mii transceiver */
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* search for total of 32 possible mii phy addresses */
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    found = 0;
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (phy_addr = 0; phy_addr < 32; phy_addr++) {
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u16 mii_status;
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u16 phy_id0, phy_id1;
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        mii_status = sis900_mdio_read(phy_addr, MII_STATUS);
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (mii_status == 0xffff || mii_status == 0x0000)
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            /* the mii is not accessable, try next one */
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            continue;
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* search our mii table for the current mii */
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; mii_chip_table[i].phy_id1; i++) {
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            if (phy_id0 == mii_chip_table[i].phy_id0) {
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("sis900_probe: %s transceiver found at address %d.\n",
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                       mii_chip_table[i].name, phy_addr);
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                mii.chip_info = &mii_chip_table[i];
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                mii.phy_addr  = phy_addr;
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                mii.status    = sis900_mdio_read(phy_addr, MII_STATUS);
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                mii.next      = NULL;
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                found=1;
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                break;
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            }
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (found == 0) {
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_probe: No MII transceivers found!\n");
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return NULL;
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Arbitrarily select the last PHY found as current PHY */
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    cur_phy = mii.phy_addr;
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    printf("sis900_probe: Using %s as default\n",  mii.chip_info->name);
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* initialize device */
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_init(nic);
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->reset    = sis900_init;
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->poll     = sis900_poll;
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->transmit = sis900_transmit;
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->disable  = sis900_disable;
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return nic;
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * EEPROM Routines:  These functions read and write to EEPROM for
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    retrieving the MAC address and other configuration information about
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    the card.
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Delay between EEPROM clock transitions. */
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define eeprom_delay()  inl(ee_addr)
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis900_read_eeprom
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: reads and returns a given location from EEPROM
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: int location:       requested EEPROM location
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
3325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   u16:                contents of requested EEPROM location
3335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
3345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
3355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Read Serial EEPROM through EEPROM Access Register, Note that location is
3375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   in word (16 bits) unit */
3385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16 sis900_read_eeprom(int location)
3395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
3415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 retval = 0;
3425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    long ee_addr = ioaddr + mear;
3435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 read_cmd = location | EEread;
3445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ee_addr);
3465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    eeprom_delay();
3475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(EECLK, ee_addr);
3485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    eeprom_delay();
3495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Shift the read command (9) bits out. */
3515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 8; i >= 0; i--) {
3525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
3535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(dataval, ee_addr);
3545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
3555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(dataval | EECLK, ee_addr);
3565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
3575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outb(EECS, ee_addr);
3595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    eeprom_delay();
3605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* read the 16-bits data in */
3625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 16; i > 0; i--) {
3635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(EECS, ee_addr);
3645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
3655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(EECS | EECLK, ee_addr);
3665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
3675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
3685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        eeprom_delay();
3695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Terminate the EEPROM access. */
3725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ee_addr);
3735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    eeprom_delay();
3745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(EECLK, ee_addr);
3755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return (retval);
3775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define sis900_mdio_delay()    inl(mdio_addr)
3805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
3835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   Read and write the MII management registers using software-generated
3845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   serial MDIO protocol. Note that the command bits and data bits are
3855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   send out seperately
3865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
3875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_mdio_idle(long mdio_addr)
3895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(MDIO | MDDIR, mdio_addr);
3915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_mdio_delay();
3925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(MDIO | MDDIR | MDC, mdio_addr);
3935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Syncronize the MII management interface by shifting 32 one bits out. */
3965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_mdio_reset(long mdio_addr)
3975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
3995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 31; i >= 0; i--) {
4015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(MDDIR | MDIO, mdio_addr);
4025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(MDDIR | MDIO | MDC, mdio_addr);
4045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return;
4075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic u16 sis900_mdio_read(int phy_id, int location)
4105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
4115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    long mdio_addr = ioaddr + mear;
4125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
4135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 retval = 0;
4145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
4155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_mdio_reset(mdio_addr);
4175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_mdio_idle(mdio_addr);
4185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 15; i >= 0; i--) {
4205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
4215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(dataval, mdio_addr);
4225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(dataval | MDC, mdio_addr);
4245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Read the 16 data bits. */
4285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 16; i > 0; i--) {
4295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(0, mdio_addr);
4305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
4325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(MDC, mdio_addr);
4335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return retval;
4365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_mdio_write(int phy_id, int location, int value)
4395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
4405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    long mdio_addr = ioaddr + mear;
4415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
4425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
4435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_mdio_reset(mdio_addr);
4455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_mdio_idle(mdio_addr);
4465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Shift the command bits out. */
4485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 15; i >= 0; i--) {
4495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
4505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outb(dataval, mdio_addr);
4515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outb(dataval | MDC, mdio_addr);
4535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_mdio_delay();
4565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Shift the value bits out. */
4585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 15; i >= 0; i--) {
4595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
4605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(dataval, mdio_addr);
4615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(dataval | MDC, mdio_addr);
4635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_mdio_delay();
4665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Clear out extra bits. */
4685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 2; i > 0; i--) {
4695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outb(0, mdio_addr);
4705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outb(MDC, mdio_addr);
4725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        sis900_mdio_delay();
4735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
4745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return;
4755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis900_init
4795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
4805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: resets the ethernet controller chip and various
4815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    data structures required for sending and receiving packets.
4825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
4835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
4845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
4855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * returns:   void.
4865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
4875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
4895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_init(struct nic *nic)
4905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
4915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Soft reset the chip. */
4925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_reset(nic);
4935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_init_rxfilter(nic);
4955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_init_txd(nic);
4975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_init_rxd(nic);
4985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_set_rx_mode(nic);
5005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    sis900_check_mode(nic);
5025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(RxENA, ioaddr + cr);
5045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
5085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Function: sis900_reset
5095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: disables interrupts and soft resets the controller chip
5115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
5135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   void.
5155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
5165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
5185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_reset(struct nic *nic)
5195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i = 0;
5215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 status = TxRCMP | RxRCMP;
5225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ioaddr + ier);
5245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ioaddr + imr);
5255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ioaddr + rfcr);
5265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(RxRESET | TxRESET | RESET, ioaddr + cr);
5285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Check that the chip has finished the reset. */
5305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while (status && (i++ < 1000)) {
5315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        status ^= (inl(isr + ioaddr) & status);
5325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
5335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(PESEL, ioaddr + cfg);
5345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis_init_rxfilter
5385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: sets receive filter address to our MAC address
5405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
5425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * returns:   void.
5445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
5455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
5475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_init_rxfilter(struct nic *nic)
5485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 rfcrSave;
5505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
5515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    rfcrSave = inl(rfcr + ioaddr);
5535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* disable packet filtering before setting filter */
5555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(rfcrSave & ~RFEN, rfcr);
5565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* load MAC addr to filter data register */
5585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 0 ; i < 3 ; i++) {
5595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        u32 w;
5605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        w = (u32) *((u16 *)(nic->node_addr)+i);
5625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl((i << RFADDR_shift), ioaddr + rfcr);
5635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl(w, ioaddr + rfdr);
5645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (sis900_debug > 0)
5665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
5675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   i, inl(ioaddr + rfdr));
5685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
5695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* enable packet filitering */
5715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(rfcrSave | RFEN, rfcr + ioaddr);
5725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
5765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Function: sis_init_txd
5775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: initializes the Tx descriptor
5795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
5815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
5825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * returns:   void.
5835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
5845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
5865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_init_txd(struct nic *nic)
5875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    txd.link   = (u32) 0;
5895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    txd.cmdsts = (u32) 0;
5905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    txd.bufptr = (u32) &txb[0];
5915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* load Transmit Descriptor Register */
5935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl((u32) &txd, ioaddr + txdp);
5945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (sis900_debug > 0)
5955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_init_txd: TX descriptor register loaded with: %X\n",
5965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               inl(ioaddr + txdp));
5975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis_init_rxd
6015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: initializes the Rx descriptor ring
6035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
6055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   void.
6075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
6085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
6105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_init_rxd(struct nic *nic)
6115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
6125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
6135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    cur_rx = 0;
6155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* init RX descriptor */
6175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 0; i < NUM_RX_DESC; i++) {
6185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        rxd[i].link   = (i+1 < NUM_RX_DESC) ? (u32) &rxd[i+1] : (u32) &rxd[0];
6195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        rxd[i].cmdsts = (u32) RX_BUF_SIZE;
6205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        rxd[i].bufptr = (u32) &rxb[i*RX_BUF_SIZE];
6215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (sis900_debug > 0)
6225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("sis900_init_rxd: rxd[%d]=%X link=%X cmdsts=%X bufptr=%X\n",
6235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   i, &rxd[i], rxd[i].link, rxd[i].cmdsts, rxd[i].bufptr);
6245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* load Receive Descriptor Register */
6275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl((u32) &rxd[0], ioaddr + rxdp);
6285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (sis900_debug > 0)
6305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_init_rxd: RX descriptor register loaded with: %X\n",
6315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               inl(ioaddr + rxdp));
6325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
6345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis_init_rxd
6375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description:
6395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    sets the receive mode to accept all broadcast packets and packets
6405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    with our MAC address, and reject all multicast packets.
6415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
6435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   void.
6455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
6465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void sis900_set_rx_mode(struct nic *nic)
6485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
6495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
6505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Configure Multicast Hash Table in Receive Filter
6525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       to reject all MCAST packets */
6535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 0; i < 8; i++) {
6545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* why plus 0x04? That makes the correct value for hash table. */
6555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
6565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        outl((u32)(0x0), ioaddr + rfdr);
6575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Accept Broadcast packets, destination addresses that match
6595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project       our MAC address */
6605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(RFEN | RFAAB, ioaddr + rfcr);
6615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return;
6635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
6645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis900_check_mode
6675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: checks the state of transmit and receive
6695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    parameters on the NIC, and updates NIC registers to match
6705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
6725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
6735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   void.
6745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
6755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
6775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_check_mode (struct nic *nic)
6785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
6795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int speed, duplex;
6805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 tx_flags = 0, rx_flags = 0;
6815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);
6835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    tx_flags = TxATP | (TX_DMA_BURST << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
6855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    rx_flags = RX_DMA_BURST << RxMXDMA_shift;
6865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
6885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        rx_flags |= (RxDRNT_10 << RxDRNT_shift);
6895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tx_flags |= (TxDRNT_10 << TxDRNT_shift);
6905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else {
6925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        rx_flags |= (RxDRNT_100 << RxDRNT_shift);
6935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tx_flags |= (TxDRNT_100 << TxDRNT_shift);
6945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
6955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (duplex == FDX_CAPABLE_FULL_SELECTED) {
6975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        tx_flags |= (TxCSI | TxHBI);
6985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        rx_flags |= RxATX;
6995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl (tx_flags, ioaddr + txcfg);
7025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl (rx_flags, ioaddr + rxcfg);
7035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
7045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis900_read_mode
7075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
7085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: retrieves and displays speed and duplex
7095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    parameters from the NIC
7105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
7115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
7125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
7135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   void.
7145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
7155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
7175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
7185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
7195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i = 0;
7205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 status;
7215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* STSOUT register is Latched on Transition, read operation updates it */
7235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while (i++ < 2)
7245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        status = sis900_mdio_read(phy_addr, MII_STSOUT);
7255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (status & MII_STSOUT_SPD)
7275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        *speed = HW_SPEED_100_MBPS;
7285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else
7295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        *speed = HW_SPEED_10_MBPS;
7305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (status & MII_STSOUT_DPLX)
7325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        *duplex = FDX_CAPABLE_FULL_SELECTED;
7335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else
7345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        *duplex = FDX_CAPABLE_HALF_SELECTED;
7355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (status & MII_STSOUT_LINK_FAIL)
7375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_read_mode: Media Link Off\n");
7385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else
7395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_read_mode: Media Link On %s %s-duplex \n",
7405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               *speed == HW_SPEED_100_MBPS ?
7415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               "100mbps" : "10mbps",
7425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               *duplex == FDX_CAPABLE_FULL_SELECTED ?
7435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               "full" : "half");
7445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
7455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: amd79c901_read_mode
7485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
7495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: retrieves and displays speed and duplex
7505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *    parameters from the NIC
7515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
7525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
7535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
7545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   void.
7555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
7565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
7585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectamd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
7595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
7605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int i;
7615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u16 status;
7625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    for (i = 0; i < 2; i++)
7645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        status = sis900_mdio_read(phy_addr, MII_STATUS);
7655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (status & MII_STAT_CAN_AUTO) {
7675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* 10BASE-T PHY */
7685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        for (i = 0; i < 2; i++)
7695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);
7705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (status & MII_STSSUM_SPD)
7715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            *speed = HW_SPEED_100_MBPS;
7725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else
7735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            *speed = HW_SPEED_10_MBPS;
7745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (status & MII_STSSUM_DPLX)
7755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            *duplex = FDX_CAPABLE_FULL_SELECTED;
7765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else
7775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            *duplex = FDX_CAPABLE_HALF_SELECTED;
7785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (status & MII_STSSUM_LINK)
7805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("amd79c901_read_mode: Media Link On %s %s-duplex \n",
7815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   *speed == HW_SPEED_100_MBPS ?
7825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   "100mbps" : "10mbps",
7835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   *duplex == FDX_CAPABLE_FULL_SELECTED ?
7845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                   "full" : "half");
7855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else
7865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("amd79c901_read_mode: Media Link Off\n");
7875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    else {
7895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* HomePNA */
7905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        *speed = HW_SPEED_HOME;
7915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        *duplex = FDX_CAPABLE_HALF_SELECTED;
7925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (status & MII_STAT_LINK)
7935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
7945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        else
7955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project            printf("amd79c901_read_mode: Media Link Off\n");
7965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
7975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
7985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**
8015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	ics1893_read_mode: - read media mode for ICS1893 PHY
8025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@net_dev: the net device to read mode for
8035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@phy_addr: mii phy address
8045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@speed: the transmit speed to be determined
8055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@duplex: the duplex mode to be determined
8065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
8075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	ICS1893 PHY use Quick Poll Detailed Status register
8085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	to determine the speed and duplex mode for sis900
8095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
8105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
8125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
8135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int i = 0;
8145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	u32 status;
8155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
8175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i = 0; i < 2; i++)
8185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		status = sis900_mdio_read(phy_addr, MII_QPDSTS);
8195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (status & MII_STSICS_SPD)
8215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*speed = HW_SPEED_100_MBPS;
8225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
8235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*speed = HW_SPEED_10_MBPS;
8245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (status & MII_STSICS_DPLX)
8265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*duplex = FDX_CAPABLE_FULL_SELECTED;
8275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
8285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*duplex = FDX_CAPABLE_HALF_SELECTED;
8295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (status & MII_STSICS_LINKSTS)
8315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
8325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       *speed == HW_SPEED_100_MBPS ?
8335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       "100mbps" : "10mbps",
8345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
8355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       "full" : "half");
8365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
8375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("ics1893_read_mode: Media Link Off\n");
8385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
8395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**
8415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	rtl8201_read_mode: - read media mode for rtl8201 phy
8425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@nic: the net device to read mode for
8435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@phy_addr: mii phy address
8445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@speed: the transmit speed to be determined
8455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	@duplex: the duplex mode to be determined
8465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
8475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	read MII_STATUS register from rtl8201 phy
8485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	to determine the speed and duplex mode for sis900
8495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
8505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
8525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
8535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	u32 status;
8545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	status = sis900_mdio_read(phy_addr, MII_STATUS);
8565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (status & MII_STAT_CAN_TX_FDX) {
8585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*speed = HW_SPEED_100_MBPS;
8595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*duplex = FDX_CAPABLE_FULL_SELECTED;
8605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
8615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else if (status & MII_STAT_CAN_TX) {
8625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*speed = HW_SPEED_100_MBPS;
8635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*duplex = FDX_CAPABLE_HALF_SELECTED;
8645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
8655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else if (status & MII_STAT_CAN_T_FDX) {
8665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*speed = HW_SPEED_10_MBPS;
8675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*duplex = FDX_CAPABLE_FULL_SELECTED;
8685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
8695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else if (status & MII_STAT_CAN_T) {
8705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*speed = HW_SPEED_10_MBPS;
8715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*duplex = FDX_CAPABLE_HALF_SELECTED;
8725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
8735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (status & MII_STAT_LINK)
8755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
8765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       *speed == HW_SPEED_100_MBPS ?
8775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       "100mbps" : "10mbps",
8785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
8795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		       "full" : "half");
8805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
8815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("rtl9201_read_config_mode: Media Link Off\n");
8825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
8835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis900_transmit
8855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
8865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: transmits a packet and waits for completion or timeout.
8875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
8885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: char d[6]:          destination ethernet address.
8895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *            unsigned short t:   ethernet protocol type.
8905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *            unsigned short s:   size of the data-part of the packet.
8915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *            char *p:            the data for the packet.
8925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
8935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   void.
8945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
8955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
8975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_transmit(struct nic  *nic,
8985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                const char  *d,     /* Destination */
8995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                unsigned int t,     /* Type */
9005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                unsigned int s,     /* size */
9015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                const char  *p)     /* Packet */
9025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
9035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 status, to, nstype;
9045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 tx_status;
9055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Stop the transmitter */
9075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(TxDIS, ioaddr + cr);
9085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* load Transmit Descriptor Register */
9105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl((u32) &txd, ioaddr + txdp);
9115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (sis900_debug > 1)
9125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_transmit: TX descriptor register loaded with: %X\n",
9135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               inl(ioaddr + txdp));
9145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(txb, d, ETH_ALEN);
9165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
9175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nstype = htons(t);
9185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
9195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    memcpy(txb + ETH_HLEN, p, s);
9205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    s += ETH_HLEN;
9225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    s &= DSIZE;
9235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (sis900_debug > 1)
9255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
9265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* pad to minimum packet size */
9285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while (s < ETH_ZLEN)
9295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        txb[s++] = '\0';
9305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* set the transmit buffer descriptor and enable Transmit State Machine */
9325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    txd.bufptr = (u32) &txb[0];
9335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    txd.cmdsts = (u32) OWN | s;
9345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* restart the transmitter */
9365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(TxENA, ioaddr + cr);
9375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (sis900_debug > 1)
9395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);
9405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    to = currticks() + TX_TIMEOUT;
9425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
9445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* wait */ ;
9455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (currticks() >= to) {
9475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_transmit: TX Timeout! Tx status %X.\n", tx_status);
9485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
9495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
9515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* packet unsuccessfully transmited */
9525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_transmit: Transmit error, Tx status %X.\n", tx_status);
9535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
9545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Disable interrupts by clearing the interrupt mask. */
9555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ioaddr + imr);
9565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
9575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis900_poll
9605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
9615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: checks for a received packet and returns it if found.
9625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
9635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
9645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
9655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   1 if a packet was recieved.
9665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *            0 if no pacet was recieved.
9675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
9685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Side effects:
9695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *            Returns (copies) the packet to the array nic->packet.
9705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *            Returns the length of the packet in nic->packetlen.
9715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
9725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int
9745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_poll(struct nic *nic)
9755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
9765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    u32 rx_status = rxd[cur_rx].cmdsts;
9775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    int retstat = 0;
9785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (sis900_debug > 2)
9805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status);
9815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (!(rx_status & OWN))
9835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        return retstat;
9845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (sis900_debug > 1)
9865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
9875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               cur_rx, rx_status);
9885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
9905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
9915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
9925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* corrupted packet received */
9935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
9945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project               rx_status);
9955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        retstat = 0;
9965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    } else {
9975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* give packet to higher level routine */
9985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
9995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        retstat = 1;
10005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
10015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* return the descriptor and buffer to receive ring */
10035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    rxd[cur_rx].cmdsts = RX_BUF_SIZE;
10045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    rxd[cur_rx].bufptr = (u32) &rxb[cur_rx*RX_BUF_SIZE];
10055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (++cur_rx == NUM_RX_DESC)
10075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        cur_rx = 0;
10085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* re-enable the potentially idle receive state machine */
10105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(RxENA , ioaddr + cr);
10115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return retstat;
10135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
10145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Function: sis900_disable
10175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
10185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Description: Turns off interrupts and stops Tx and Rx engines
10195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
10205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Arguments: struct nic *nic:          NIC data structure
10215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
10225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Returns:   void.
10235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
10245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void
10265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectsis900_disable(struct nic *nic)
10275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
10285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Disable interrupts by clearing the interrupt mask. */
10295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ioaddr + imr);
10305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(0, ioaddr + ier);
10315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
10325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    /* Stop the chip's Tx and Rx Status Machine */
10335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    outl(RxDIS | TxDIS, ioaddr + cr);
10345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1035