iPXE
sundance.c
Go to the documentation of this file.
00001 /**************************************************************************
00002 *
00003 *    sundance.c -- Etherboot device driver for the Sundance ST201 "Alta".
00004 *    Written 2002-2002 by Timothy Legge <tlegge@rogers.com>
00005 *
00006 *    This program is free software; you can redistribute it and/or modify
00007 *    it under the terms of the GNU General Public License as published by
00008 *    the Free Software Foundation; either version 2 of the License, or
00009 *    (at your option) any later version.
00010 *
00011 *    This program is distributed in the hope that it will be useful,
00012 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *    GNU General Public License for more details.
00015 *
00016 *    You should have received a copy of the GNU General Public License
00017 *    along with this program; if not, write to the Free Software
00018 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00019 *    02110-1301, USA.
00020 *
00021 *    Portions of this code based on:
00022 *               sundance.c: A Linux device driver for the Sundance ST201 "Alta"
00023 *               Written 1999-2002 by Donald Becker
00024 *
00025 *               tulip.c: Tulip and Clone Etherboot Driver
00026 *               By Marty Conner
00027 *               Copyright (C) 2001 Entity Cyber, Inc.
00028 *
00029 *    Linux Driver Version LK1.09a, 10-Jul-2003 (2.4.25)
00030 *
00031 *    REVISION HISTORY:
00032 *    ================
00033 *    v1.1       01-01-2003      timlegge        Initial implementation
00034 *    v1.7       04-10-2003      timlegge        Transfers Linux Kernel (30 sec)
00035 *    v1.8       04-13-2003      timlegge        Fix multiple transmission bug
00036 *    v1.9       08-19-2003      timlegge        Support Multicast
00037 *    v1.10      01-17-2004      timlegge        Initial driver output cleanup
00038 *    v1.11      03-21-2004      timlegge        Remove unused variables
00039 *    v1.12      03-21-2004      timlegge        Remove excess MII defines
00040 *    v1.13      03-24-2004      timlegge        Update to Linux 2.4.25 driver
00041 *
00042 ****************************************************************************/
00043 
00044 FILE_LICENCE ( GPL2_OR_LATER );
00045 
00046 /* to get some global routines like printf */
00047 #include "etherboot.h"
00048 /* to get the interface to the body of the program */
00049 #include "nic.h"
00050 /* to get the PCI support functions, if this is a PCI NIC */
00051 #include <ipxe/pci.h>
00052 #include "mii.h"
00053 
00054 #define drv_version "v1.12"
00055 #define drv_date "2004-03-21"
00056 
00057 #define HZ 100
00058 
00059 /* Condensed operations for readability. */
00060 #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
00061 #define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
00062 
00063 /* Set the mtu */
00064 static int mtu = 1514;
00065 
00066 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
00067    The sundance uses a 64 element hash table based on the Ethernet CRC.  */
00068 // static int multicast_filter_limit = 32;
00069 
00070 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
00071    Setting to > 1518 effectively disables this feature.
00072    This chip can receive into any byte alignment buffers, so word-oriented
00073    archs do not need a copy-align of the IP header. */
00074 static int rx_copybreak = 0;
00075 static int flowctrl = 1;
00076 
00077 /* Allow forcing the media type */
00078 /* media[] specifies the media type the NIC operates at.
00079                  autosense      Autosensing active media.
00080                  10mbps_hd      10Mbps half duplex.
00081                  10mbps_fd      10Mbps full duplex.
00082                  100mbps_hd     100Mbps half duplex.
00083                  100mbps_fd     100Mbps full duplex.
00084 */
00085 static char media[] = "autosense";
00086 
00087 /* Operational parameters that are set at compile time. */
00088 
00089 /* As Etherboot uses a Polling driver  we can keep the number of rings
00090 to the minimum number required.  In general that is 1 transmit and 4 receive receive rings.  However some cards require that
00091 there be a minimum of 2 rings  */
00092 #define TX_RING_SIZE    2
00093 #define TX_QUEUE_LEN    10      /* Limit ring entries actually used.  */
00094 #define RX_RING_SIZE    4
00095 
00096 
00097 /* Operational parameters that usually are not changed. */
00098 /* Time in jiffies before concluding the transmitter is hung. */
00099 #define TX_TIME_OUT       (4*HZ)
00100 #define PKT_BUF_SZ      1536
00101 
00102 /* Offsets to the device registers.
00103    Unlike software-only systems, device drivers interact with complex hardware.
00104    It's not useful to define symbolic names for every register bit in the
00105    device.  The name can only partially document the semantics and make
00106    the driver longer and more difficult to read.
00107    In general, only the important configuration values or bits changed
00108    multiple times should be defined symbolically.
00109 */
00110 enum alta_offsets {
00111         DMACtrl = 0x00,
00112         TxListPtr = 0x04,
00113         TxDMABurstThresh = 0x08,
00114         TxDMAUrgentThresh = 0x09,
00115         TxDMAPollPeriod = 0x0a,
00116         RxDMAStatus = 0x0c,
00117         RxListPtr = 0x10,
00118         DebugCtrl0 = 0x1a,
00119         DebugCtrl1 = 0x1c,
00120         RxDMABurstThresh = 0x14,
00121         RxDMAUrgentThresh = 0x15,
00122         RxDMAPollPeriod = 0x16,
00123         LEDCtrl = 0x1a,
00124         ASICCtrl = 0x30,
00125         EEData = 0x34,
00126         EECtrl = 0x36,
00127         TxStartThresh = 0x3c,
00128         RxEarlyThresh = 0x3e,
00129         FlashAddr = 0x40,
00130         FlashData = 0x44,
00131         TxStatus = 0x46,
00132         TxFrameId = 0x47,
00133         DownCounter = 0x18,
00134         IntrClear = 0x4a,
00135         IntrEnable = 0x4c,
00136         IntrStatus = 0x4e,
00137         MACCtrl0 = 0x50,
00138         MACCtrl1 = 0x52,
00139         StationAddr = 0x54,
00140         MaxFrameSize = 0x5A,
00141         RxMode = 0x5c,
00142         MIICtrl = 0x5e,
00143         MulticastFilter0 = 0x60,
00144         MulticastFilter1 = 0x64,
00145         RxOctetsLow = 0x68,
00146         RxOctetsHigh = 0x6a,
00147         TxOctetsLow = 0x6c,
00148         TxOctetsHigh = 0x6e,
00149         TxFramesOK = 0x70,
00150         RxFramesOK = 0x72,
00151         StatsCarrierError = 0x74,
00152         StatsLateColl = 0x75,
00153         StatsMultiColl = 0x76,
00154         StatsOneColl = 0x77,
00155         StatsTxDefer = 0x78,
00156         RxMissed = 0x79,
00157         StatsTxXSDefer = 0x7a,
00158         StatsTxAbort = 0x7b,
00159         StatsBcastTx = 0x7c,
00160         StatsBcastRx = 0x7d,
00161         StatsMcastTx = 0x7e,
00162         StatsMcastRx = 0x7f,
00163         /* Aliased and bogus values! */
00164         RxStatus = 0x0c,
00165 };
00166 enum ASICCtrl_HiWord_bit {
00167         GlobalReset = 0x0001,
00168         RxReset = 0x0002,
00169         TxReset = 0x0004,
00170         DMAReset = 0x0008,
00171         FIFOReset = 0x0010,
00172         NetworkReset = 0x0020,
00173         HostReset = 0x0040,
00174         ResetBusy = 0x0400,
00175 };
00176 
00177 /* Bits in the interrupt status/mask registers. */
00178 enum intr_status_bits {
00179         IntrSummary = 0x0001, IntrPCIErr = 0x0002, IntrMACCtrl = 0x0008,
00180         IntrTxDone = 0x0004, IntrRxDone = 0x0010, IntrRxStart = 0x0020,
00181         IntrDrvRqst = 0x0040,
00182         StatsMax = 0x0080, LinkChange = 0x0100,
00183         IntrTxDMADone = 0x0200, IntrRxDMADone = 0x0400,
00184 };
00185 
00186 /* Bits in the RxMode register. */
00187 enum rx_mode_bits {
00188         AcceptAllIPMulti = 0x20, AcceptMultiHash = 0x10, AcceptAll = 0x08,
00189         AcceptBroadcast = 0x04, AcceptMulticast = 0x02, AcceptMyPhys =
00190             0x01,
00191 };
00192 /* Bits in MACCtrl. */
00193 enum mac_ctrl0_bits {
00194         EnbFullDuplex = 0x20, EnbRcvLargeFrame = 0x40,
00195         EnbFlowCtrl = 0x100, EnbPassRxCRC = 0x200,
00196 };
00197 enum mac_ctrl1_bits {
00198         StatsEnable = 0x0020, StatsDisable = 0x0040, StatsEnabled = 0x0080,
00199         TxEnable = 0x0100, TxDisable = 0x0200, TxEnabled = 0x0400,
00200         RxEnable = 0x0800, RxDisable = 0x1000, RxEnabled = 0x2000,
00201 };
00202 
00203 /* The Rx and Tx buffer descriptors.
00204    Using only 32 bit fields simplifies software endian correction.
00205    This structure must be aligned, and should avoid spanning cache lines.
00206 */
00207 struct netdev_desc {
00208         u32 next_desc;
00209         u32 status;
00210         u32 addr;
00211         u32 length;
00212 };
00213 
00214 /* Bits in netdev_desc.status */
00215 enum desc_status_bits {
00216         DescOwn = 0x8000,
00217         DescEndPacket = 0x4000,
00218         DescEndRing = 0x2000,
00219         LastFrag = 0x80000000,
00220         DescIntrOnTx = 0x8000,
00221         DescIntrOnDMADone = 0x80000000,
00222         DisableAlign = 0x00000001,
00223 };
00224 
00225 /**********************************************
00226 * Descriptor Ring and Buffer defination
00227 ***********************************************/
00228 /* Define the TX Descriptor */
00229 static struct netdev_desc tx_ring[TX_RING_SIZE];
00230 
00231 /* Define the RX Descriptor */
00232 static struct netdev_desc rx_ring[RX_RING_SIZE];
00233 
00234 /* Create a static buffer of size PKT_BUF_SZ for each RX and TX descriptor.
00235    All descriptors point to a part of this buffer */
00236 struct {
00237         unsigned char txb[PKT_BUF_SZ * TX_RING_SIZE];
00238         unsigned char rxb[RX_RING_SIZE * PKT_BUF_SZ];
00239 } rx_tx_buf __shared;
00240 #define rxb rx_tx_buf.rxb
00241 #define txb rx_tx_buf.txb
00242 
00243 /* FIXME: Move BASE to the private structure */
00244 static u32 BASE;
00245 #define EEPROM_SIZE     128
00246 
00247 enum pci_id_flags_bits {
00248         PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4,
00249         PCI_ADDR0 = 0 << 4, PCI_ADDR1 = 1 << 4, PCI_ADDR2 =
00250             2 << 4, PCI_ADDR3 = 3 << 4,
00251 };
00252 
00253 enum chip_capability_flags { CanHaveMII = 1, KendinPktDropBug = 2, };
00254 #define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO  | PCI_ADDR0)
00255 
00256 #define MII_CNT         4
00257 static struct sundance_private {
00258         const char *nic_name;
00259         /* Frequently used values */
00260 
00261         unsigned int cur_rx;    /* Producer/consumer ring indices */
00262         unsigned int mtu;
00263 
00264         /* These values keep track of the tranceiver/media in use */
00265         unsigned int flowctrl:1;
00266         unsigned int an_enable:1;
00267 
00268         unsigned int speed;
00269 
00270         /* MII tranceiver section */
00271         struct mii_if_info mii_if;
00272         int mii_preamble_required;
00273         unsigned char phys[MII_CNT];
00274         unsigned char pci_rev_id;
00275 } sdx;
00276 
00277 static struct sundance_private *sdc;
00278 
00279 /* Station Address location within the EEPROM */
00280 #define EEPROM_SA_OFFSET        0x10
00281 #define DEFAULT_INTR (IntrRxDMADone | IntrPCIErr | \
00282                         IntrDrvRqst | IntrTxDone | StatsMax | \
00283                         LinkChange)
00284 
00285 static int eeprom_read(long ioaddr, int location);
00286 static int mdio_read(struct nic *nic, int phy_id, unsigned int location);
00287 static void mdio_write(struct nic *nic, int phy_id, unsigned int location,
00288                        int value);
00289 static void set_rx_mode(struct nic *nic);
00290 
00291 static void check_duplex(struct nic *nic)
00292 {
00293         int mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA);
00294         int negotiated = mii_lpa & sdc->mii_if.advertising;
00295         int duplex;
00296 
00297         /* Force media */
00298         if (!sdc->an_enable || mii_lpa == 0xffff) {
00299                 if (sdc->mii_if.full_duplex)
00300                         outw(inw(BASE + MACCtrl0) | EnbFullDuplex,
00301                              BASE + MACCtrl0);
00302                 return;
00303         }
00304 
00305         /* Autonegotiation */
00306         duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
00307         if (sdc->mii_if.full_duplex != duplex) {
00308                 sdc->mii_if.full_duplex = duplex;
00309                 DBG ("%s: Setting %s-duplex based on MII #%d "
00310                          "negotiated capability %4.4x.\n", sdc->nic_name,
00311                          duplex ? "full" : "half", sdc->phys[0],
00312                          negotiated );
00313                 outw(inw(BASE + MACCtrl0) | duplex ? 0x20 : 0,
00314                      BASE + MACCtrl0);
00315         }
00316 }
00317 
00318 
00319 /**************************************************************************
00320  *  init_ring - setup the tx and rx descriptors
00321  *************************************************************************/
00322 static void init_ring(struct nic *nic __unused)
00323 {
00324         int i;
00325 
00326         sdc->cur_rx = 0;
00327 
00328         /* Initialize all the Rx descriptors */
00329         for (i = 0; i < RX_RING_SIZE; i++) {
00330                 rx_ring[i].next_desc = virt_to_le32desc(&rx_ring[i + 1]);
00331                 rx_ring[i].status = 0;
00332                 rx_ring[i].length = 0;
00333                 rx_ring[i].addr = 0;
00334         }
00335 
00336         /* Mark the last entry as wrapping the ring */
00337         rx_ring[i - 1].next_desc = virt_to_le32desc(&rx_ring[0]);
00338 
00339         for (i = 0; i < RX_RING_SIZE; i++) {
00340                 rx_ring[i].addr = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
00341                 rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LastFrag);
00342         }
00343 
00344         /* We only use one transmit buffer, but two
00345          * descriptors so transmit engines have somewhere
00346          * to point should they feel the need */
00347         tx_ring[0].status = 0x00000000;
00348         tx_ring[0].addr = virt_to_bus(&txb[0]);
00349         tx_ring[0].next_desc = 0;       /* virt_to_bus(&tx_ring[1]); */
00350 
00351         /* This descriptor is never used */
00352         tx_ring[1].status = 0x00000000;
00353         tx_ring[1].addr = 0;    /*virt_to_bus(&txb[0]); */
00354         tx_ring[1].next_desc = 0;
00355 
00356         /* Mark the last entry as wrapping the ring,
00357          * though this should never happen */
00358         tx_ring[1].length = cpu_to_le32(LastFrag | PKT_BUF_SZ);
00359 }
00360 
00361 /**************************************************************************
00362  *  RESET - Reset Adapter
00363  * ***********************************************************************/
00364 static void sundance_reset(struct nic *nic)
00365 {
00366         int i;
00367 
00368         init_ring(nic);
00369 
00370         outl(virt_to_le32desc(&rx_ring[0]), BASE + RxListPtr);
00371         /* The Tx List Pointer is written as packets are queued */
00372 
00373         /* Initialize other registers. */
00374         /* __set_mac_addr(dev); */
00375         {
00376                 u16 addr16;
00377 
00378                 addr16 = (nic->node_addr[0] | (nic->node_addr[1] << 8));
00379                 outw(addr16, BASE + StationAddr);
00380                 addr16 = (nic->node_addr[2] | (nic->node_addr[3] << 8));
00381                 outw(addr16, BASE + StationAddr + 2);
00382                 addr16 = (nic->node_addr[4] | (nic->node_addr[5] << 8));
00383                 outw(addr16, BASE + StationAddr + 4);
00384         }
00385 
00386         outw(sdc->mtu + 14, BASE + MaxFrameSize);
00387         if (sdc->mtu > 2047)    /* this will never happen with default options */
00388                 outl(inl(BASE + ASICCtrl) | 0x0c, BASE + ASICCtrl);
00389 
00390         set_rx_mode(nic);
00391 
00392         outw(0, BASE + DownCounter);
00393         /* Set the chip to poll every N*30nsec */
00394         outb(100, BASE + RxDMAPollPeriod);
00395 
00396         /* Fix DFE-580TX packet drop issue */
00397         if (sdc->pci_rev_id >= 0x14)
00398                 writeb(0x01, BASE + DebugCtrl1);
00399 
00400         outw(RxEnable | TxEnable, BASE + MACCtrl1);
00401 
00402         /* Construct a perfect filter frame with the mac address as first match
00403          * and broadcast for all others */
00404         for (i = 0; i < 192; i++)
00405                 txb[i] = 0xFF;
00406 
00407         txb[0] = nic->node_addr[0];
00408         txb[1] = nic->node_addr[1];
00409         txb[2] = nic->node_addr[2];
00410         txb[3] = nic->node_addr[3];
00411         txb[4] = nic->node_addr[4];
00412         txb[5] = nic->node_addr[5];
00413 
00414         DBG ( "%s: Done sundance_reset, status: Rx %hX Tx %hX "
00415               "MAC Control %hX, %hX %hX\n",
00416               sdc->nic_name, (int) inl(BASE + RxStatus),
00417               (int) inw(BASE + TxStatus), (int) inl(BASE + MACCtrl0),
00418               (int) inw(BASE + MACCtrl1), (int) inw(BASE + MACCtrl0) );
00419 }
00420 
00421 /**************************************************************************
00422 IRQ - Wait for a frame
00423 ***************************************************************************/
00424 static void sundance_irq ( struct nic *nic, irq_action_t action ) {
00425         unsigned int intr_status;
00426 
00427         switch ( action ) {
00428         case DISABLE :
00429         case ENABLE :
00430                 intr_status = inw(nic->ioaddr + IntrStatus);
00431                 intr_status = intr_status & ~DEFAULT_INTR;
00432                 if ( action == ENABLE ) 
00433                         intr_status = intr_status | DEFAULT_INTR;
00434                 outw(intr_status, nic->ioaddr + IntrEnable);
00435                 break;
00436         case FORCE :
00437                 outw(0x0200, BASE + ASICCtrl);
00438                 break;
00439         }
00440 }
00441 /**************************************************************************
00442 POLL - Wait for a frame
00443 ***************************************************************************/
00444 static int sundance_poll(struct nic *nic, int retrieve)
00445 {
00446         /* return true if there's an ethernet packet ready to read */
00447         /* nic->packet should contain data on return */
00448         /* nic->packetlen should contain length of data */
00449         int entry = sdc->cur_rx % RX_RING_SIZE;
00450         u32 frame_status = le32_to_cpu(rx_ring[entry].status);
00451         int intr_status;
00452         int pkt_len = 0;
00453 
00454         if (!(frame_status & DescOwn))
00455                 return 0;
00456 
00457         /* There is a packet ready */
00458         if(!retrieve)
00459                 return 1;
00460 
00461         intr_status = inw(nic->ioaddr + IntrStatus);
00462         outw(intr_status, nic->ioaddr + IntrStatus);
00463 
00464         pkt_len = frame_status & 0x1fff;
00465 
00466         if (frame_status & 0x001f4000) {
00467                 DBG ( "Polling frame_status error\n" ); /* Do we really care about this */
00468         } else {
00469                 if (pkt_len < rx_copybreak) {
00470                         /* FIXME: What should happen Will this ever occur */
00471                         printf("Poll Error: pkt_len < rx_copybreak");
00472                 } else {
00473                         nic->packetlen = pkt_len;
00474                         memcpy(nic->packet, rxb +
00475                                (sdc->cur_rx * PKT_BUF_SZ), nic->packetlen);
00476 
00477                 }
00478         }
00479         rx_ring[entry].length = cpu_to_le32(PKT_BUF_SZ | LastFrag);
00480         rx_ring[entry].status = 0;
00481         entry++;
00482         sdc->cur_rx = entry % RX_RING_SIZE;
00483         outw(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone), 
00484                 nic->ioaddr + IntrStatus);
00485         return 1;
00486 }
00487 
00488 /**************************************************************************
00489 TRANSMIT - Transmit a frame
00490 ***************************************************************************/
00491 static void sundance_transmit(struct nic *nic, const char *d,   /* Destination */
00492                               unsigned int t,   /* Type */
00493                               unsigned int s,   /* size */
00494                               const char *p)
00495 {                               /* Packet */
00496         u16 nstype;
00497         u32 to;
00498 
00499         /* Disable the Tx */
00500         outw(TxDisable, BASE + MACCtrl1);
00501 
00502         memcpy(txb, d, ETH_ALEN);
00503         memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
00504         nstype = htons((u16) t);
00505         memcpy(txb + 2 * ETH_ALEN, (u8 *) & nstype, 2);
00506         memcpy(txb + ETH_HLEN, p, s);
00507 
00508         s += ETH_HLEN;
00509         s &= 0x0FFF;
00510         while (s < ETH_ZLEN)
00511                 txb[s++] = '\0';
00512 
00513         /* Setup the transmit descriptor */
00514         tx_ring[0].length = cpu_to_le32(s | LastFrag);
00515         tx_ring[0].status = cpu_to_le32(0x00000001);
00516 
00517         /* Point to transmit descriptor */
00518         outl(virt_to_le32desc(&tx_ring[0]), BASE + TxListPtr);
00519 
00520         /* Enable Tx */
00521         outw(TxEnable, BASE + MACCtrl1);
00522         /* Trigger an immediate send */
00523         outw(0, BASE + TxStatus);
00524 
00525         to = currticks() + TX_TIME_OUT;
00526         while (!(tx_ring[0].status & 0x00010000) && (currticks() < to));        /* wait */
00527 
00528         if (currticks() >= to) {
00529                 printf("TX Time Out");
00530         }
00531         /* Disable Tx */
00532         outw(TxDisable, BASE + MACCtrl1);
00533 
00534 }
00535 
00536 /**************************************************************************
00537 DISABLE - Turn off ethernet interface
00538 ***************************************************************************/
00539 static void sundance_disable ( struct nic *nic __unused ) {
00540         /* put the card in its initial state */
00541         /* This function serves 3 purposes.
00542          * This disables DMA and interrupts so we don't receive
00543          *  unexpected packets or interrupts from the card after
00544          *  etherboot has finished.
00545          * This frees resources so etherboot may use
00546          *  this driver on another interface
00547          * This allows etherboot to reinitialize the interface
00548          *  if something is something goes wrong.
00549          */
00550         outw(0x0000, BASE + IntrEnable);
00551         /* Stop the Chipchips Tx and Rx Status */
00552         outw(TxDisable | RxDisable | StatsDisable, BASE + MACCtrl1);
00553 }
00554 
00555 static struct nic_operations sundance_operations = {
00556         .connect        = dummy_connect,
00557         .poll           = sundance_poll,
00558         .transmit       = sundance_transmit,
00559         .irq            = sundance_irq,
00560 
00561 };
00562 
00563 /**************************************************************************
00564 PROBE - Look for an adapter, this routine's visible to the outside
00565 ***************************************************************************/
00566 static int sundance_probe ( struct nic *nic, struct pci_device *pci ) {
00567 
00568         u8 ee_data[EEPROM_SIZE];
00569         u16 mii_ctl;
00570         int i;
00571         int speed;
00572 
00573         if (pci->ioaddr == 0)
00574                 return 0;
00575 
00576         /* BASE is used throughout to address the card */
00577         BASE = pci->ioaddr;
00578         printf(" sundance.c: Found %s Vendor=0x%hX Device=0x%hX\n",
00579                pci->id->name, pci->vendor, pci->device);
00580 
00581         /* Get the MAC Address by reading the EEPROM */
00582         for (i = 0; i < 3; i++) {
00583                 ((u16 *) ee_data)[i] =
00584                     le16_to_cpu(eeprom_read(BASE, i + EEPROM_SA_OFFSET));
00585         }
00586         /* Update the nic structure with the MAC Address */
00587         for (i = 0; i < ETH_ALEN; i++) {
00588                 nic->node_addr[i] = ee_data[i];
00589         }
00590 
00591         /* Set the card as PCI Bus Master */
00592         adjust_pci_device(pci);
00593 
00594 //      sdc->mii_if.dev = pci;
00595 //      sdc->mii_if.phy_id_mask = 0x1f;
00596 //      sdc->mii_if.reg_num_mask = 0x1f;
00597 
00598         /* point to private storage */
00599         sdc = &sdx;
00600 
00601         sdc->nic_name = pci->id->name;
00602         sdc->mtu = mtu;
00603 
00604         pci_read_config_byte(pci, PCI_REVISION, &sdc->pci_rev_id);
00605 
00606         DBG ( "Device revision id: %hx\n", sdc->pci_rev_id );
00607 
00608         /* Print out some hardware info */
00609         DBG ( "%s: %s at ioaddr %hX, ",
00610               pci->id->name, nic->node_addr, (unsigned int) BASE);
00611 
00612         sdc->mii_preamble_required = 0;
00613         if (1) {
00614                 int phy, phy_idx = 0;
00615                 sdc->phys[0] = 1;       /* Default Setting */
00616                 sdc->mii_preamble_required++;
00617                 for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
00618                         int mii_status = mdio_read(nic, phy, MII_BMSR);
00619                         if (mii_status != 0xffff && mii_status != 0x0000) {
00620                                 sdc->phys[phy_idx++] = phy;
00621                                 sdc->mii_if.advertising =
00622                                     mdio_read(nic, phy, MII_ADVERTISE);
00623                                 if ((mii_status & 0x0040) == 0)
00624                                         sdc->mii_preamble_required++;
00625                                 DBG 
00626                                     ( "%s: MII PHY found at address %d, status " "%hX advertising %hX\n", sdc->nic_name, phy, mii_status, sdc->mii_if.advertising );
00627                         }
00628                 }
00629                 sdc->mii_preamble_required--;
00630                 if (phy_idx == 0)
00631                         printf("%s: No MII transceiver found!\n",
00632                                sdc->nic_name);
00633                 sdc->mii_if.phy_id = sdc->phys[0];
00634         }
00635 
00636         /* Parse override configuration */
00637         sdc->an_enable = 1;
00638         if (strcasecmp(media, "autosense") != 0) {
00639                 sdc->an_enable = 0;
00640                 if (strcasecmp(media, "100mbps_fd") == 0 ||
00641                     strcasecmp(media, "4") == 0) {
00642                         sdc->speed = 100;
00643                         sdc->mii_if.full_duplex = 1;
00644                 } else if (strcasecmp(media, "100mbps_hd") == 0
00645                            || strcasecmp(media, "3") == 0) {
00646                         sdc->speed = 100;
00647                         sdc->mii_if.full_duplex = 0;
00648                 } else if (strcasecmp(media, "10mbps_fd") == 0 ||
00649                            strcasecmp(media, "2") == 0) {
00650                         sdc->speed = 10;
00651                         sdc->mii_if.full_duplex = 1;
00652                 } else if (strcasecmp(media, "10mbps_hd") == 0 ||
00653                            strcasecmp(media, "1") == 0) {
00654                         sdc->speed = 10;
00655                         sdc->mii_if.full_duplex = 0;
00656                 } else {
00657                         sdc->an_enable = 1;
00658                 }
00659         }
00660         if (flowctrl == 1)
00661                 sdc->flowctrl = 1;
00662 
00663         /* Fibre PHY? */
00664         if (inl(BASE + ASICCtrl) & 0x80) {
00665                 /* Default 100Mbps Full */
00666                 if (sdc->an_enable) {
00667                         sdc->speed = 100;
00668                         sdc->mii_if.full_duplex = 1;
00669                         sdc->an_enable = 0;
00670                 }
00671         }
00672 
00673         /* The Linux driver uses flow control and resets the link here.  This means the
00674            mii section from above would need to be re done I believe.  Since it serves
00675            no real purpose leave it out. */
00676 
00677         /* Force media type */
00678         if (!sdc->an_enable) {
00679                 mii_ctl = 0;
00680                 mii_ctl |= (sdc->speed == 100) ? BMCR_SPEED100 : 0;
00681                 mii_ctl |= (sdc->mii_if.full_duplex) ? BMCR_FULLDPLX : 0;
00682                 mdio_write(nic, sdc->phys[0], MII_BMCR, mii_ctl);
00683                 printf("Override speed=%d, %s duplex\n",
00684                        sdc->speed,
00685                        sdc->mii_if.full_duplex ? "Full" : "Half");
00686         }
00687 
00688         /* Reset the chip to erase previous misconfiguration */
00689         DBG ( "ASIC Control is %#x\n", inl(BASE + ASICCtrl) );
00690         outw(0x007f, BASE + ASICCtrl + 2);
00691 
00692         /*
00693         * wait for reset to complete
00694         * this is heavily inspired by the linux sundance driver
00695         * according to the linux driver it can take up to 1ms for the reset
00696         * to complete
00697         */
00698         i = 0;
00699         while(inl(BASE + ASICCtrl) & (ResetBusy << 16)) {
00700                 if(i++ >= 10) {
00701                         DBG("sundance: NIC reset did not complete.\n");
00702                         break;
00703                 }
00704                 udelay(100);
00705         }
00706 
00707         DBG ( "ASIC Control is now %#x.\n", inl(BASE + ASICCtrl) );
00708 
00709         sundance_reset(nic);
00710         if (sdc->an_enable) {
00711                 u16 mii_advertise, mii_lpa;
00712                 mii_advertise =
00713                     mdio_read(nic, sdc->phys[0], MII_ADVERTISE);
00714                 mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA);
00715                 mii_advertise &= mii_lpa;
00716                 if (mii_advertise & ADVERTISE_100FULL)
00717                         sdc->speed = 100;
00718                 else if (mii_advertise & ADVERTISE_100HALF)
00719                         sdc->speed = 100;
00720                 else if (mii_advertise & ADVERTISE_10FULL)
00721                         sdc->speed = 10;
00722                 else if (mii_advertise & ADVERTISE_10HALF)
00723                         sdc->speed = 10;
00724         } else {
00725                 mii_ctl = mdio_read(nic, sdc->phys[0], MII_BMCR);
00726                 speed = (mii_ctl & BMCR_SPEED100) ? 100 : 10;
00727                 sdc->speed = speed;
00728                 printf("%s: Link changed: %dMbps ,", sdc->nic_name, speed);
00729                 printf("%s duplex.\n", (mii_ctl & BMCR_FULLDPLX) ?
00730                        "full" : "half");
00731         }
00732         check_duplex(nic);
00733         if (sdc->flowctrl && sdc->mii_if.full_duplex) {
00734                 outw(inw(BASE + MulticastFilter1 + 2) | 0x0200,
00735                      BASE + MulticastFilter1 + 2);
00736                 outw(inw(BASE + MACCtrl0) | EnbFlowCtrl, BASE + MACCtrl0);
00737         }
00738         printf("%dMbps, %s-Duplex\n", sdc->speed,
00739                sdc->mii_if.full_duplex ? "Full" : "Half");
00740 
00741         /* point to NIC specific routines */
00742         nic->nic_op     = &sundance_operations;
00743 
00744         nic->irqno  = pci->irq;
00745         nic->ioaddr = BASE;
00746 
00747         return 1;
00748 }
00749 
00750 
00751 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
00752 static int eeprom_read(long ioaddr, int location)
00753 {
00754         int boguscnt = 10000;   /* Typical 1900 ticks */
00755         outw(0x0200 | (location & 0xff), ioaddr + EECtrl);
00756         do {
00757                 if (!(inw(ioaddr + EECtrl) & 0x8000)) {
00758                         return inw(ioaddr + EEData);
00759                 }
00760         }
00761         while (--boguscnt > 0);
00762         return 0;
00763 }
00764 
00765 /*  MII transceiver control section.
00766         Read and write the MII registers using software-generated serial
00767         MDIO protocol.  See the MII specifications or DP83840A data sheet
00768         for details.
00769 
00770         The maximum data clock rate is 2.5 Mhz.
00771         The timing is decoupled from the processor clock by flushing the write
00772         from the CPU write buffer with a following read, and using PCI
00773         transaction time. */
00774 
00775 #define mdio_in(mdio_addr) inb(mdio_addr)
00776 #define mdio_out(value, mdio_addr) outb(value, mdio_addr)
00777 #define mdio_delay(mdio_addr) inb(mdio_addr)
00778 
00779 enum mii_reg_bits {
00780         MDIO_ShiftClk = 0x0001, MDIO_Data = 0x0002, MDIO_EnbOutput =
00781             0x0004,
00782 };
00783 #define MDIO_EnbIn  (0)
00784 #define MDIO_WRITE0 (MDIO_EnbOutput)
00785 #define MDIO_WRITE1 (MDIO_Data | MDIO_EnbOutput)
00786 
00787 /* Generate the preamble required for initial synchronization and
00788    a few older transceivers. */
00789 static void mdio_sync(long mdio_addr)
00790 {
00791         int bits = 32;
00792 
00793         /* Establish sync by sending at least 32 logic ones. */
00794         while (--bits >= 0) {
00795                 mdio_out(MDIO_WRITE1, mdio_addr);
00796                 mdio_delay(mdio_addr);
00797                 mdio_out(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
00798                 mdio_delay(mdio_addr);
00799         }
00800 }
00801 
00802 static int
00803 mdio_read(struct nic *nic __unused, int phy_id, unsigned int location)
00804 {
00805         long mdio_addr = BASE + MIICtrl;
00806         int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
00807         int i, retval = 0;
00808 
00809         if (sdc->mii_preamble_required)
00810                 mdio_sync(mdio_addr);
00811 
00812         /* Shift the read command bits out. */
00813         for (i = 15; i >= 0; i--) {
00814                 int dataval =
00815                     (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
00816 
00817                 mdio_out(dataval, mdio_addr);
00818                 mdio_delay(mdio_addr);
00819                 mdio_out(dataval | MDIO_ShiftClk, mdio_addr);
00820                 mdio_delay(mdio_addr);
00821         }
00822         /* Read the two transition, 16 data, and wire-idle bits. */
00823         for (i = 19; i > 0; i--) {
00824                 mdio_out(MDIO_EnbIn, mdio_addr);
00825                 mdio_delay(mdio_addr);
00826                 retval = (retval << 1) | ((mdio_in(mdio_addr) & MDIO_Data)
00827                                           ? 1 : 0);
00828                 mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
00829                 mdio_delay(mdio_addr);
00830         }
00831         return (retval >> 1) & 0xffff;
00832 }
00833 
00834 static void
00835 mdio_write(struct nic *nic __unused, int phy_id,
00836            unsigned int location, int value)
00837 {
00838         long mdio_addr = BASE + MIICtrl;
00839         int mii_cmd =
00840             (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
00841         int i;
00842 
00843         if (sdc->mii_preamble_required)
00844                 mdio_sync(mdio_addr);
00845 
00846         /* Shift the command bits out. */
00847         for (i = 31; i >= 0; i--) {
00848                 int dataval =
00849                     (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
00850                 mdio_out(dataval, mdio_addr);
00851                 mdio_delay(mdio_addr);
00852                 mdio_out(dataval | MDIO_ShiftClk, mdio_addr);
00853                 mdio_delay(mdio_addr);
00854         }
00855         /* Clear out extra bits. */
00856         for (i = 2; i > 0; i--) {
00857                 mdio_out(MDIO_EnbIn, mdio_addr);
00858                 mdio_delay(mdio_addr);
00859                 mdio_out(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
00860                 mdio_delay(mdio_addr);
00861         }
00862         return;
00863 }
00864 
00865 static void set_rx_mode(struct nic *nic __unused)
00866 {
00867         int i;
00868         u16 mc_filter[4];       /* Multicast hash filter */
00869         u32 rx_mode;
00870 
00871         memset(mc_filter, 0xff, sizeof(mc_filter));
00872         rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
00873 
00874         if (sdc->mii_if.full_duplex && sdc->flowctrl)
00875                 mc_filter[3] |= 0x0200;
00876         for (i = 0; i < 4; i++)
00877                 outw(mc_filter[i], BASE + MulticastFilter0 + i * 2);
00878         outb(rx_mode, BASE + RxMode);
00879         return;
00880 }
00881 
00882 static struct pci_device_id sundance_nics[] = {
00883         PCI_ROM(0x13f0, 0x0201, "sundance", "ST201 Sundance 'Alta' based Adaptor", 0),
00884         PCI_ROM(0x1186, 0x1002, "dfe530txs", "D-Link DFE530TXS (Sundance ST201 Alta)", 0),
00885         PCI_ROM(0x13f0, 0x0200, "ip100a", "IC+ IP100A", 0),
00886 };
00887 
00888 PCI_DRIVER ( sundance_driver, sundance_nics, PCI_NO_CLASS );
00889 
00890 DRIVER ( "SUNDANCE/PCI", nic_driver, pci_driver, sundance_driver,
00891          sundance_probe, sundance_disable );
00892 
00893 /*
00894  * Local variables:
00895  *  c-basic-offset: 8
00896  *  c-indent-level: 8
00897  *  tab-width: 8
00898  * End:
00899  */