diff options
author | RajithaY <rajithax.yerrumsetty@intel.com> | 2017-04-25 03:31:15 -0700 |
---|---|---|
committer | Rajitha Yerrumchetty <rajithax.yerrumsetty@intel.com> | 2017-05-22 06:48:08 +0000 |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/roms/ipxe/src/drivers/net/sundance.c | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/roms/ipxe/src/drivers/net/sundance.c')
-rw-r--r-- | qemu/roms/ipxe/src/drivers/net/sundance.c | 899 |
1 files changed, 0 insertions, 899 deletions
diff --git a/qemu/roms/ipxe/src/drivers/net/sundance.c b/qemu/roms/ipxe/src/drivers/net/sundance.c deleted file mode 100644 index 9127fa2cd..000000000 --- a/qemu/roms/ipxe/src/drivers/net/sundance.c +++ /dev/null @@ -1,899 +0,0 @@ -/************************************************************************** -* -* sundance.c -- Etherboot device driver for the Sundance ST201 "Alta". -* Written 2002-2002 by Timothy Legge <tlegge@rogers.com> -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -* 02110-1301, USA. -* -* Portions of this code based on: -* sundance.c: A Linux device driver for the Sundance ST201 "Alta" -* Written 1999-2002 by Donald Becker -* -* tulip.c: Tulip and Clone Etherboot Driver -* By Marty Conner -* Copyright (C) 2001 Entity Cyber, Inc. -* -* Linux Driver Version LK1.09a, 10-Jul-2003 (2.4.25) -* -* REVISION HISTORY: -* ================ -* v1.1 01-01-2003 timlegge Initial implementation -* v1.7 04-10-2003 timlegge Transfers Linux Kernel (30 sec) -* v1.8 04-13-2003 timlegge Fix multiple transmission bug -* v1.9 08-19-2003 timlegge Support Multicast -* v1.10 01-17-2004 timlegge Initial driver output cleanup -* v1.11 03-21-2004 timlegge Remove unused variables -* v1.12 03-21-2004 timlegge Remove excess MII defines -* v1.13 03-24-2004 timlegge Update to Linux 2.4.25 driver -* -****************************************************************************/ - -FILE_LICENCE ( GPL2_OR_LATER ); - -/* to get some global routines like printf */ -#include "etherboot.h" -/* to get the interface to the body of the program */ -#include "nic.h" -/* to get the PCI support functions, if this is a PCI NIC */ -#include <ipxe/pci.h> -#include "mii.h" - -#define drv_version "v1.12" -#define drv_date "2004-03-21" - -#define HZ 100 - -/* Condensed operations for readability. */ -#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) -#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) - -/* Set the mtu */ -static int mtu = 1514; - -/* Maximum number of multicast addresses to filter (vs. rx-all-multicast). - The sundance uses a 64 element hash table based on the Ethernet CRC. */ -// static int multicast_filter_limit = 32; - -/* Set the copy breakpoint for the copy-only-tiny-frames scheme. - Setting to > 1518 effectively disables this feature. - This chip can receive into any byte alignment buffers, so word-oriented - archs do not need a copy-align of the IP header. */ -static int rx_copybreak = 0; -static int flowctrl = 1; - -/* Allow forcing the media type */ -/* media[] specifies the media type the NIC operates at. - autosense Autosensing active media. - 10mbps_hd 10Mbps half duplex. - 10mbps_fd 10Mbps full duplex. - 100mbps_hd 100Mbps half duplex. - 100mbps_fd 100Mbps full duplex. -*/ -static char media[] = "autosense"; - -/* Operational parameters that are set at compile time. */ - -/* As Etherboot uses a Polling driver we can keep the number of rings -to the minimum number required. In general that is 1 transmit and 4 receive receive rings. However some cards require that -there be a minimum of 2 rings */ -#define TX_RING_SIZE 2 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ -#define RX_RING_SIZE 4 - - -/* Operational parameters that usually are not changed. */ -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIME_OUT (4*HZ) -#define PKT_BUF_SZ 1536 - -/* Offsets to the device registers. - Unlike software-only systems, device drivers interact with complex hardware. - It's not useful to define symbolic names for every register bit in the - device. The name can only partially document the semantics and make - the driver longer and more difficult to read. - In general, only the important configuration values or bits changed - multiple times should be defined symbolically. -*/ -enum alta_offsets { - DMACtrl = 0x00, - TxListPtr = 0x04, - TxDMABurstThresh = 0x08, - TxDMAUrgentThresh = 0x09, - TxDMAPollPeriod = 0x0a, - RxDMAStatus = 0x0c, - RxListPtr = 0x10, - DebugCtrl0 = 0x1a, - DebugCtrl1 = 0x1c, - RxDMABurstThresh = 0x14, - RxDMAUrgentThresh = 0x15, - RxDMAPollPeriod = 0x16, - LEDCtrl = 0x1a, - ASICCtrl = 0x30, - EEData = 0x34, - EECtrl = 0x36, - TxStartThresh = 0x3c, - RxEarlyThresh = 0x3e, - FlashAddr = 0x40, - FlashData = 0x44, - TxStatus = 0x46, - TxFrameId = 0x47, - DownCounter = 0x18, - IntrClear = 0x4a, - IntrEnable = 0x4c, - IntrStatus = 0x4e, - MACCtrl0 = 0x50, - MACCtrl1 = 0x52, - StationAddr = 0x54, - MaxFrameSize = 0x5A, - RxMode = 0x5c, - MIICtrl = 0x5e, - MulticastFilter0 = 0x60, - MulticastFilter1 = 0x64, - RxOctetsLow = 0x68, - RxOctetsHigh = 0x6a, - TxOctetsLow = 0x6c, - TxOctetsHigh = 0x6e, - TxFramesOK = 0x70, - RxFramesOK = 0x72, - StatsCarrierError = 0x74, - StatsLateColl = 0x75, - StatsMultiColl = 0x76, - StatsOneColl = 0x77, - StatsTxDefer = 0x78, - RxMissed = 0x79, - StatsTxXSDefer = 0x7a, - StatsTxAbort = 0x7b, - StatsBcastTx = 0x7c, - StatsBcastRx = 0x7d, - StatsMcastTx = 0x7e, - StatsMcastRx = 0x7f, - /* Aliased and bogus values! */ - RxStatus = 0x0c, -}; -enum ASICCtrl_HiWord_bit { - GlobalReset = 0x0001, - RxReset = 0x0002, - TxReset = 0x0004, - DMAReset = 0x0008, - FIFOReset = 0x0010, - NetworkReset = 0x0020, - HostReset = 0x0040, - ResetBusy = 0x0400, -}; - -/* Bits in the interrupt status/mask registers. */ -enum intr_status_bits { - IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008, - IntrTxDone = 0x0004, IntrRxDone = 0x0010, IntrRxStart = 0x0020, - IntrDrvRqst = 0x0040, - StatsMax = 0x0080, LinkChange = 0x0100, - IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400, -}; - -/* Bits in the RxMode register. */ -enum rx_mode_bits { - AcceptAllIPMulti = 0x20, AcceptMultiHash = 0x10, AcceptAll = 0x08, - AcceptBroadcast = 0x04, AcceptMulticast = 0x02, AcceptMyPhys = - 0x01, -}; -/* Bits in MACCtrl. */ -enum mac_ctrl0_bits { - EnbFullDuplex = 0x20, EnbRcvLargeFrame = 0x40, - EnbFlowCtrl = 0x100, EnbPassRxCRC = 0x200, -}; -enum mac_ctrl1_bits { - StatsEnable = 0x0020, StatsDisable = 0x0040, StatsEnabled = 0x0080, - TxEnable = 0x0100, TxDisable = 0x0200, TxEnabled = 0x0400, - RxEnable = 0x0800, RxDisable = 0x1000, RxEnabled = 0x2000, -}; - -/* The Rx and Tx buffer descriptors. - Using only 32 bit fields simplifies software endian correction. - This structure must be aligned, and should avoid spanning cache lines. -*/ -struct netdev_desc { - u32 next_desc; - u32 status; - u32 addr; - u32 length; -}; - -/* Bits in netdev_desc.status */ -enum desc_status_bits { - DescOwn = 0x8000, - DescEndPacket = 0x4000, - DescEndRing = 0x2000, - LastFrag = 0x80000000, - DescIntrOnTx = 0x8000, - DescIntrOnDMADone = 0x80000000, - DisableAlign = 0x00000001, -}; - -/********************************************** -* Descriptor Ring and Buffer defination -***********************************************/ -/* Define the TX Descriptor */ -static struct netdev_desc tx_ring[TX_RING_SIZE]; - -/* Define the RX Descriptor */ -static struct netdev_desc rx_ring[RX_RING_SIZE]; - -/* Create a static buffer of size PKT_BUF_SZ for each RX and TX descriptor. - All descriptors point to a part of this buffer */ -struct { - unsigned char txb[PKT_BUF_SZ * TX_RING_SIZE]; - unsigned char rxb[RX_RING_SIZE * PKT_BUF_SZ]; -} rx_tx_buf __shared; -#define rxb rx_tx_buf.rxb -#define txb rx_tx_buf.txb - -/* FIXME: Move BASE to the private structure */ -static u32 BASE; -#define EEPROM_SIZE 128 - -enum pci_id_flags_bits { - PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4, - PCI_ADDR0 = 0 << 4, PCI_ADDR1 = 1 << 4, PCI_ADDR2 = - 2 << 4, PCI_ADDR3 = 3 << 4, -}; - -enum chip_capability_flags { CanHaveMII = 1, KendinPktDropBug = 2, }; -#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO | PCI_ADDR0) - -#define MII_CNT 4 -static struct sundance_private { - const char *nic_name; - /* Frequently used values */ - - unsigned int cur_rx; /* Producer/consumer ring indices */ - unsigned int mtu; - - /* These values keep track of the tranceiver/media in use */ - unsigned int flowctrl:1; - unsigned int an_enable:1; - - unsigned int speed; - - /* MII tranceiver section */ - struct mii_if_info mii_if; - int mii_preamble_required; - unsigned char phys[MII_CNT]; - unsigned char pci_rev_id; -} sdx; - -static struct sundance_private *sdc; - -/* Station Address location within the EEPROM */ -#define EEPROM_SA_OFFSET 0x10 -#define DEFAULT_INTR (IntrRxDMADone | IntrPCIErr | \ - IntrDrvRqst | IntrTxDone | StatsMax | \ - LinkChange) - -static int eeprom_read(long ioaddr, int location); -static int mdio_read(struct nic *nic, int phy_id, unsigned int location); -static void mdio_write(struct nic *nic, int phy_id, unsigned int location, - int value); -static void set_rx_mode(struct nic *nic); - -static void check_duplex(struct nic *nic) -{ - int mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA); - int negotiated = mii_lpa & sdc->mii_if.advertising; - int duplex; - - /* Force media */ - if (!sdc->an_enable || mii_lpa == 0xffff) { - if (sdc->mii_if.full_duplex) - outw(inw(BASE + MACCtrl0) | EnbFullDuplex, - BASE + MACCtrl0); - return; - } - - /* Autonegotiation */ - duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; - if (sdc->mii_if.full_duplex != duplex) { - sdc->mii_if.full_duplex = duplex; - DBG ("%s: Setting %s-duplex based on MII #%d " - "negotiated capability %4.4x.\n", sdc->nic_name, - duplex ? "full" : "half", sdc->phys[0], - negotiated ); - outw(inw(BASE + MACCtrl0) | duplex ? 0x20 : 0, - BASE + MACCtrl0); - } -} - - -/************************************************************************** - * init_ring - setup the tx and rx descriptors - *************************************************************************/ -static void init_ring(struct nic *nic __unused) -{ - int i; - - sdc->cur_rx = 0; - - /* Initialize all the Rx descriptors */ - for (i = 0; i < RX_RING_SIZE; i++) { - rx_ring[i].next_desc = virt_to_le32desc(&rx_ring[i + 1]); - rx_ring[i].status = 0; - rx_ring[i].length = 0; - rx_ring[i].addr = 0; - } - - /* Mark the last entry as wrapping the ring */ - rx_ring[i - 1].next_desc = virt_to_le32desc(&rx_ring[0]); - - for (i = 0; i < RX_RING_SIZE; i++) { - rx_ring[i].addr = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]); - rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LastFrag); - } - - /* We only use one transmit buffer, but two - * descriptors so transmit engines have somewhere - * to point should they feel the need */ - tx_ring[0].status = 0x00000000; - tx_ring[0].addr = virt_to_bus(&txb[0]); - tx_ring[0].next_desc = 0; /* virt_to_bus(&tx_ring[1]); */ - - /* This descriptor is never used */ - tx_ring[1].status = 0x00000000; - tx_ring[1].addr = 0; /*virt_to_bus(&txb[0]); */ - tx_ring[1].next_desc = 0; - - /* Mark the last entry as wrapping the ring, - * though this should never happen */ - tx_ring[1].length = cpu_to_le32(LastFrag | PKT_BUF_SZ); -} - -/************************************************************************** - * RESET - Reset Adapter - * ***********************************************************************/ -static void sundance_reset(struct nic *nic) -{ - int i; - - init_ring(nic); - - outl(virt_to_le32desc(&rx_ring[0]), BASE + RxListPtr); - /* The Tx List Pointer is written as packets are queued */ - - /* Initialize other registers. */ - /* __set_mac_addr(dev); */ - { - u16 addr16; - - addr16 = (nic->node_addr[0] | (nic->node_addr[1] << 8)); - outw(addr16, BASE + StationAddr); - addr16 = (nic->node_addr[2] | (nic->node_addr[3] << 8)); - outw(addr16, BASE + StationAddr + 2); - addr16 = (nic->node_addr[4] | (nic->node_addr[5] << 8)); - outw(addr16, BASE + StationAddr + 4); - } - - outw(sdc->mtu + 14, BASE + MaxFrameSize); - if (sdc->mtu > 2047) /* this will never happen with default options */ - outl(inl(BASE + ASICCtrl) | 0x0c, BASE + ASICCtrl); - - set_rx_mode(nic); - - outw(0, BASE + DownCounter); - /* Set the chip to poll every N*30nsec */ - outb(100, BASE + RxDMAPollPeriod); - - /* Fix DFE-580TX packet drop issue */ - if (sdc->pci_rev_id >= 0x14) - writeb(0x01, BASE + DebugCtrl1); - - outw(RxEnable | TxEnable, BASE + MACCtrl1); - - /* Construct a perfect filter frame with the mac address as first match - * and broadcast for all others */ - for (i = 0; i < 192; i++) - txb[i] = 0xFF; - - txb[0] = nic->node_addr[0]; - txb[1] = nic->node_addr[1]; - txb[2] = nic->node_addr[2]; - txb[3] = nic->node_addr[3]; - txb[4] = nic->node_addr[4]; - txb[5] = nic->node_addr[5]; - - DBG ( "%s: Done sundance_reset, status: Rx %hX Tx %hX " - "MAC Control %hX, %hX %hX\n", - sdc->nic_name, (int) inl(BASE + RxStatus), - (int) inw(BASE + TxStatus), (int) inl(BASE + MACCtrl0), - (int) inw(BASE + MACCtrl1), (int) inw(BASE + MACCtrl0) ); -} - -/************************************************************************** -IRQ - Wait for a frame -***************************************************************************/ -static void sundance_irq ( struct nic *nic, irq_action_t action ) { - unsigned int intr_status; - - switch ( action ) { - case DISABLE : - case ENABLE : - intr_status = inw(nic->ioaddr + IntrStatus); - intr_status = intr_status & ~DEFAULT_INTR; - if ( action == ENABLE ) - intr_status = intr_status | DEFAULT_INTR; - outw(intr_status, nic->ioaddr + IntrEnable); - break; - case FORCE : - outw(0x0200, BASE + ASICCtrl); - break; - } -} -/************************************************************************** -POLL - Wait for a frame -***************************************************************************/ -static int sundance_poll(struct nic *nic, int retrieve) -{ - /* return true if there's an ethernet packet ready to read */ - /* nic->packet should contain data on return */ - /* nic->packetlen should contain length of data */ - int entry = sdc->cur_rx % RX_RING_SIZE; - u32 frame_status = le32_to_cpu(rx_ring[entry].status); - int intr_status; - int pkt_len = 0; - - if (!(frame_status & DescOwn)) - return 0; - - /* There is a packet ready */ - if(!retrieve) - return 1; - - intr_status = inw(nic->ioaddr + IntrStatus); - outw(intr_status, nic->ioaddr + IntrStatus); - - pkt_len = frame_status & 0x1fff; - - if (frame_status & 0x001f4000) { - DBG ( "Polling frame_status error\n" ); /* Do we really care about this */ - } else { - if (pkt_len < rx_copybreak) { - /* FIXME: What should happen Will this ever occur */ - printf("Poll Error: pkt_len < rx_copybreak"); - } else { - nic->packetlen = pkt_len; - memcpy(nic->packet, rxb + - (sdc->cur_rx * PKT_BUF_SZ), nic->packetlen); - - } - } - rx_ring[entry].length = cpu_to_le32(PKT_BUF_SZ | LastFrag); - rx_ring[entry].status = 0; - entry++; - sdc->cur_rx = entry % RX_RING_SIZE; - outw(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone), - nic->ioaddr + IntrStatus); - return 1; -} - -/************************************************************************** -TRANSMIT - Transmit a frame -***************************************************************************/ -static void sundance_transmit(struct nic *nic, const char *d, /* Destination */ - unsigned int t, /* Type */ - unsigned int s, /* size */ - const char *p) -{ /* Packet */ - u16 nstype; - u32 to; - - /* Disable the Tx */ - outw(TxDisable, BASE + MACCtrl1); - - memcpy(txb, d, ETH_ALEN); - memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN); - nstype = htons((u16) t); - memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2); - memcpy(txb + ETH_HLEN, p, s); - - s += ETH_HLEN; - s &= 0x0FFF; - while (s < ETH_ZLEN) - txb[s++] = '\0'; - - /* Setup the transmit descriptor */ - tx_ring[0].length = cpu_to_le32(s | LastFrag); - tx_ring[0].status = cpu_to_le32(0x00000001); - - /* Point to transmit descriptor */ - outl(virt_to_le32desc(&tx_ring[0]), BASE + TxListPtr); - - /* Enable Tx */ - outw(TxEnable, BASE + MACCtrl1); - /* Trigger an immediate send */ - outw(0, BASE + TxStatus); - - to = currticks() + TX_TIME_OUT; - while (!(tx_ring[0].status & 0x00010000) && (currticks() < to)); /* wait */ - - if (currticks() >= to) { - printf("TX Time Out"); - } - /* Disable Tx */ - outw(TxDisable, BASE + MACCtrl1); - -} - -/************************************************************************** -DISABLE - Turn off ethernet interface -***************************************************************************/ -static void sundance_disable ( struct nic *nic __unused ) { - /* put the card in its initial state */ - /* This function serves 3 purposes. - * This disables DMA and interrupts so we don't receive - * unexpected packets or interrupts from the card after - * etherboot has finished. - * This frees resources so etherboot may use - * this driver on another interface - * This allows etherboot to reinitialize the interface - * if something is something goes wrong. - */ - outw(0x0000, BASE + IntrEnable); - /* Stop the Chipchips Tx and Rx Status */ - outw(TxDisable | RxDisable | StatsDisable, BASE + MACCtrl1); -} - -static struct nic_operations sundance_operations = { - .connect = dummy_connect, - .poll = sundance_poll, - .transmit = sundance_transmit, - .irq = sundance_irq, - -}; - -/************************************************************************** -PROBE - Look for an adapter, this routine's visible to the outside -***************************************************************************/ -static int sundance_probe ( struct nic *nic, struct pci_device *pci ) { - - u8 ee_data[EEPROM_SIZE]; - u16 mii_ctl; - int i; - int speed; - - if (pci->ioaddr == 0) - return 0; - - /* BASE is used throughout to address the card */ - BASE = pci->ioaddr; - printf(" sundance.c: Found %s Vendor=0x%hX Device=0x%hX\n", - pci->id->name, pci->vendor, pci->device); - - /* Get the MAC Address by reading the EEPROM */ - for (i = 0; i < 3; i++) { - ((u16 *) ee_data)[i] = - le16_to_cpu(eeprom_read(BASE, i + EEPROM_SA_OFFSET)); - } - /* Update the nic structure with the MAC Address */ - for (i = 0; i < ETH_ALEN; i++) { - nic->node_addr[i] = ee_data[i]; - } - - /* Set the card as PCI Bus Master */ - adjust_pci_device(pci); - -// sdc->mii_if.dev = pci; -// sdc->mii_if.phy_id_mask = 0x1f; -// sdc->mii_if.reg_num_mask = 0x1f; - - /* point to private storage */ - sdc = &sdx; - - sdc->nic_name = pci->id->name; - sdc->mtu = mtu; - - pci_read_config_byte(pci, PCI_REVISION, &sdc->pci_rev_id); - - DBG ( "Device revision id: %hx\n", sdc->pci_rev_id ); - - /* Print out some hardware info */ - DBG ( "%s: %s at ioaddr %hX, ", - pci->id->name, nic->node_addr, (unsigned int) BASE); - - sdc->mii_preamble_required = 0; - if (1) { - int phy, phy_idx = 0; - sdc->phys[0] = 1; /* Default Setting */ - sdc->mii_preamble_required++; - for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) { - int mii_status = mdio_read(nic, phy, MII_BMSR); - if (mii_status != 0xffff && mii_status != 0x0000) { - sdc->phys[phy_idx++] = phy; - sdc->mii_if.advertising = - mdio_read(nic, phy, MII_ADVERTISE); - if ((mii_status & 0x0040) == 0) - sdc->mii_preamble_required++; - DBG - ( "%s: MII PHY found at address %d, status " "%hX advertising %hX\n", sdc->nic_name, phy, mii_status, sdc->mii_if.advertising ); - } - } - sdc->mii_preamble_required--; - if (phy_idx == 0) - printf("%s: No MII transceiver found!\n", - sdc->nic_name); - sdc->mii_if.phy_id = sdc->phys[0]; - } - - /* Parse override configuration */ - sdc->an_enable = 1; - if (strcasecmp(media, "autosense") != 0) { - sdc->an_enable = 0; - if (strcasecmp(media, "100mbps_fd") == 0 || - strcasecmp(media, "4") == 0) { - sdc->speed = 100; - sdc->mii_if.full_duplex = 1; - } else if (strcasecmp(media, "100mbps_hd") == 0 - || strcasecmp(media, "3") == 0) { - sdc->speed = 100; - sdc->mii_if.full_duplex = 0; - } else if (strcasecmp(media, "10mbps_fd") == 0 || - strcasecmp(media, "2") == 0) { - sdc->speed = 10; - sdc->mii_if.full_duplex = 1; - } else if (strcasecmp(media, "10mbps_hd") == 0 || - strcasecmp(media, "1") == 0) { - sdc->speed = 10; - sdc->mii_if.full_duplex = 0; - } else { - sdc->an_enable = 1; - } - } - if (flowctrl == 1) - sdc->flowctrl = 1; - - /* Fibre PHY? */ - if (inl(BASE + ASICCtrl) & 0x80) { - /* Default 100Mbps Full */ - if (sdc->an_enable) { - sdc->speed = 100; - sdc->mii_if.full_duplex = 1; - sdc->an_enable = 0; - } - } - - /* The Linux driver uses flow control and resets the link here. This means the - mii section from above would need to be re done I believe. Since it serves - no real purpose leave it out. */ - - /* Force media type */ - if (!sdc->an_enable) { - mii_ctl = 0; - mii_ctl |= (sdc->speed == 100) ? BMCR_SPEED100 : 0; - mii_ctl |= (sdc->mii_if.full_duplex) ? BMCR_FULLDPLX : 0; - mdio_write(nic, sdc->phys[0], MII_BMCR, mii_ctl); - printf("Override speed=%d, %s duplex\n", - sdc->speed, - sdc->mii_if.full_duplex ? "Full" : "Half"); - } - - /* Reset the chip to erase previous misconfiguration */ - DBG ( "ASIC Control is %#x\n", inl(BASE + ASICCtrl) ); - outw(0x007f, BASE + ASICCtrl + 2); - - /* - * wait for reset to complete - * this is heavily inspired by the linux sundance driver - * according to the linux driver it can take up to 1ms for the reset - * to complete - */ - i = 0; - while(inl(BASE + ASICCtrl) & (ResetBusy << 16)) { - if(i++ >= 10) { - DBG("sundance: NIC reset did not complete.\n"); - break; - } - udelay(100); - } - - DBG ( "ASIC Control is now %#x.\n", inl(BASE + ASICCtrl) ); - - sundance_reset(nic); - if (sdc->an_enable) { - u16 mii_advertise, mii_lpa; - mii_advertise = - mdio_read(nic, sdc->phys[0], MII_ADVERTISE); - mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA); - mii_advertise &= mii_lpa; - if (mii_advertise & ADVERTISE_100FULL) - sdc->speed = 100; - else if (mii_advertise & ADVERTISE_100HALF) - sdc->speed = 100; - else if (mii_advertise & ADVERTISE_10FULL) - sdc->speed = 10; - else if (mii_advertise & ADVERTISE_10HALF) - sdc->speed = 10; - } else { - mii_ctl = mdio_read(nic, sdc->phys[0], MII_BMCR); - speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10; - sdc->speed = speed; - printf("%s: Link changed: %dMbps ,", sdc->nic_name, speed); - printf("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ? - "full" : "half"); - } - check_duplex(nic); - if (sdc->flowctrl && sdc->mii_if.full_duplex) { - outw(inw(BASE + MulticastFilter1 + 2) | 0x0200, - BASE + MulticastFilter1 + 2); - outw(inw(BASE + MACCtrl0) | EnbFlowCtrl, BASE + MACCtrl0); - } - printf("%dMbps, %s-Duplex\n", sdc->speed, - sdc->mii_if.full_duplex ? "Full" : "Half"); - - /* point to NIC specific routines */ - nic->nic_op = &sundance_operations; - - nic->irqno = pci->irq; - nic->ioaddr = BASE; - - return 1; -} - - -/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */ -static int eeprom_read(long ioaddr, int location) -{ - int boguscnt = 10000; /* Typical 1900 ticks */ - outw(0x0200 | (location & 0xff), ioaddr + EECtrl); - do { - if (!(inw(ioaddr + EECtrl) & 0x8000)) { - return inw(ioaddr + EEData); - } - } - while (--boguscnt > 0); - return 0; -} - -/* MII transceiver control section. - Read and write the MII registers using software-generated serial - MDIO protocol. See the MII specifications or DP83840A data sheet - for details. - - The maximum data clock rate is 2.5 Mhz. - The timing is decoupled from the processor clock by flushing the write - from the CPU write buffer with a following read, and using PCI - transaction time. */ - -#define mdio_in(mdio_addr) inb(mdio_addr) -#define mdio_out(value, mdio_addr) outb(value, mdio_addr) -#define mdio_delay(mdio_addr) inb(mdio_addr) - -enum mii_reg_bits { - MDIO_ShiftClk = 0x0001, MDIO_Data = 0x0002, MDIO_EnbOutput = - 0x0004, -}; -#define MDIO_EnbIn (0) -#define MDIO_WRITE0 (MDIO_EnbOutput) -#define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput) - -/* Generate the preamble required for initial synchronization and - a few older transceivers. */ -static void mdio_sync(long mdio_addr) -{ - int bits = 32; - - /* Establish sync by sending at least 32 logic ones. */ - while (--bits >= 0) { - mdio_out(MDIO_WRITE1, mdio_addr); - mdio_delay(mdio_addr); - mdio_out(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr); - mdio_delay(mdio_addr); - } -} - -static int -mdio_read(struct nic *nic __unused, int phy_id, unsigned int location) -{ - long mdio_addr = BASE + MIICtrl; - int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; - int i, retval = 0; - - if (sdc->mii_preamble_required) - mdio_sync(mdio_addr); - - /* Shift the read command bits out. */ - for (i = 15; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - - mdio_out(dataval, mdio_addr); - mdio_delay(mdio_addr); - mdio_out(dataval | MDIO_ShiftClk, mdio_addr); - mdio_delay(mdio_addr); - } - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - mdio_out(MDIO_EnbIn, mdio_addr); - mdio_delay(mdio_addr); - retval = (retval << 1) | ((mdio_in(mdio_addr) & MDIO_Data) - ? 1 : 0); - mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); - mdio_delay(mdio_addr); - } - return (retval >> 1) & 0xffff; -} - -static void -mdio_write(struct nic *nic __unused, int phy_id, - unsigned int location, int value) -{ - long mdio_addr = BASE + MIICtrl; - int mii_cmd = - (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; - int i; - - if (sdc->mii_preamble_required) - mdio_sync(mdio_addr); - - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - mdio_out(dataval, mdio_addr); - mdio_delay(mdio_addr); - mdio_out(dataval | MDIO_ShiftClk, mdio_addr); - mdio_delay(mdio_addr); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - mdio_out(MDIO_EnbIn, mdio_addr); - mdio_delay(mdio_addr); - mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); - mdio_delay(mdio_addr); - } - return; -} - -static void set_rx_mode(struct nic *nic __unused) -{ - int i; - u16 mc_filter[4]; /* Multicast hash filter */ - u32 rx_mode; - - memset(mc_filter, 0xff, sizeof(mc_filter)); - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - - if (sdc->mii_if.full_duplex && sdc->flowctrl) - mc_filter[3] |= 0x0200; - for (i = 0; i < 4; i++) - outw(mc_filter[i], BASE + MulticastFilter0 + i * 2); - outb(rx_mode, BASE + RxMode); - return; -} - -static struct pci_device_id sundance_nics[] = { - PCI_ROM(0x13f0, 0x0201, "sundance", "ST201 Sundance 'Alta' based Adaptor", 0), - PCI_ROM(0x1186, 0x1002, "dfe530txs", "D-Link DFE530TXS (Sundance ST201 Alta)", 0), - PCI_ROM(0x13f0, 0x0200, "ip100a", "IC+ IP100A", 0), -}; - -PCI_DRIVER ( sundance_driver, sundance_nics, PCI_NO_CLASS ); - -DRIVER ( "SUNDANCE/PCI", nic_driver, pci_driver, sundance_driver, - sundance_probe, sundance_disable ); - -/* - * Local variables: - * c-basic-offset: 8 - * c-indent-level: 8 - * tab-width: 8 - * End: - */ |