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

Generated on Tue Apr 6 20:01:04 2010 for gPXE by  doxygen 1.5.7.1