Synced across updates from Etherboot 5.4 tree
authorMichael Brown <mcb30@etherboot.org>
Thu, 19 May 2005 16:47:19 +0000 (16:47 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 19 May 2005 16:47:19 +0000 (16:47 +0000)
32 files changed:
1  2 
src/arch/armnommu/Config
src/arch/armnommu/core/serial.c
src/arch/armnommu/drivers/net/p2001_eth.c
src/arch/armnommu/include/hardware.h
src/arch/armnommu/include/lxt971a.h
src/arch/armnommu/include/stdint.h
src/arch/e1/include/stdint.h
src/arch/i386/core/freebsd_loader.c
src/arch/i386/include/stdint.h
src/arch/ia64/include/stdint.h
src/core/config.c
src/drivers/net/3c515.c
src/drivers/net/davicom.c
src/drivers/net/depca.c
src/drivers/net/dmfe.c
src/drivers/net/eepro.c
src/drivers/net/eepro100.c
src/drivers/net/forcedeth.c
src/drivers/net/mtd80x.c
src/drivers/net/natsemi.c
src/drivers/net/ns83820.c
src/drivers/net/pcnet32.c
src/drivers/net/r8169.c
src/drivers/net/sis900.h
src/drivers/net/sundance.c
src/drivers/net/tg3.c
src/drivers/net/tg3.h
src/drivers/net/tlan.h
src/drivers/net/tulip.c
src/drivers/net/w89c840.c
src/include/pci_ids.h
src/util/makerom.pl

@@@ -17,6 -17,6 +17,12 @@@ CFLAGS+= -DRAWADDR=0x4010000
  # NIC Debug Outputs
  #CFLAGS+= -DDEBUG_NIC
  
++# Reduced Media Independent Interface
++# MAZBR LPEC2001: MII (Intel LXT971ALE at 0..1)
++# Elmeg D@VOS   : RMII        (Altima AC104-QF at 4..7)
++# Telekom XI521 : RMII        (Altima AC104-QF at 4..7)
++#CFLAGS+= -DRMII
++
  # Fixed MAC address
  # p2001_eth has no flash and fixed mac address
  #CFLAGS+=     -DMAC_HW_ADDR_DRV="'H','Y','L','N','X','1'"
@@@ -17,7 -17,7 +17,7 @@@ void serial_putc(int ch
  {
        /* wait for room in the 32 byte tx FIFO */
        while ((P2001_UART->r.STATUS & 0x3f) > /* 30 */ 0) ;
--      P2001_UART->w.TX1 = ch & 0xff;
++      P2001_UART->w.TX[0] = ch & 0xff;
  }
  
  /*
@@@ -27,7 -27,7 +27,7 @@@
  int serial_getc(void)
  {
        while (((P2001_UART->r.STATUS >> 6) & 0x3f) == 0) ;
--      return P2001_UART->r.RX1 & 0xff;
++      return P2001_UART->r.RX[0] & 0xff;
  }
  
  /*
@@@ -1,10 -1,10 +1,10 @@@
  /**************************************************************************
--Etherboot -  BOOTP/TFTP Bootstrap Program
--P2001 NIC driver for Etherboot
--***************************************************************************/
++ * Etherboot -  BOOTP/TFTP Bootstrap Program
++ * P2001 NIC driver for Etherboot
++ **************************************************************************/
  
  /*
-- *  Copyright (C) 2004 Tobias Lorenz
++ *  Copyright (C) 2005 Tobias Lorenz
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
@@@ -19,7 -19,7 +19,7 @@@
  #include "isa.h"
  
  #include "hardware.h"
--#include "lxt971a.h"
++#include "mii.h"
  #include "timer.h"
  
  
@@@ -31,25 -31,25 +31,20 @@@ static unsigned char MAC_HW_ADDR[6]={MA
  #define DMA_BUF_SIZE  2048    /* Buffer size */
  static DMA_DSC txd              __attribute__ ((__section__(".dma.desc")));
  static DMA_DSC rxd[NUM_RX_DESC] __attribute__ ((__section__(".dma.desc")));
--static unsigned char rxb[NUM_RX_DESC * DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
--static unsigned char txb[              DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
++static char rxb[NUM_RX_DESC * DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
++static char txb[              DMA_BUF_SIZE] __attribute__ ((__section__(".dma.buffer")));
  static unsigned int cur_rx;
  
  /* Device selectors */
  static unsigned int cur_channel;      // DMA channel    : 0..3
  static unsigned int cur_phy;          // PHY Address    : 0..31
  static P2001_ETH_regs_ptr EU;         // Ethernet Unit  : 0x0018_000 with _=0..3
--static P2001_ETH_regs_ptr MU;         // Management Unit: 0x00180000
  
--#define MDIO_MAXCOUNT 1000                    /* mdio abort */
--static unsigned int mdio_error;                       /* mdio error */
--
--/* Function prototypes */
--static void         p2001_eth_mdio_init ();
--static void         p2001_eth_mdio_write(unsigned int phyadr, unsigned int regadr, unsigned int data);
--static unsigned int p2001_eth_mdio_read (unsigned int phyadr, unsigned int regadr);
--extern unsigned int p2001_eth_mdio_error;
++/* mdio handling */
++static int          p2001_eth_mdio_read (int phy_id, int location);
++static void         p2001_eth_mdio_write(int phy_id, int location, int val);
  
++/* net_device functions */
  static int          p2001_eth_poll      (struct nic *nic, int retrieve);
  static void         p2001_eth_transmit  (struct nic *nic, const char *d,
                                        unsigned int t, unsigned int s, const char *p);
@@@ -60,103 -60,103 +55,107 @@@ static void         p2001_eth_ini
  static void         p2001_eth_disable   (struct dev *dev);
  
  static int          p2001_eth_check_link(unsigned int phy);
++static int          link;
++static void         p2001_eth_phyreset  ();
  static int          p2001_eth_probe     (struct dev *dev, unsigned short *probe_addrs __unused);
  
++/* Supported MII list */
++static struct mii_chip_info {
++      const char * name;
++      unsigned int physid;    // (MII_PHYSID2 << 16) | MII_PHYSID1
++} mii_chip_table[] = {
++      { "Intel LXT971A",      0x78e20013 },
++      { "Altima AC104-QF",    0x55410022 },
++      {NULL,0},
++};
++
++
  
  /**************************************************************************
--PHY MANAGEMENT UNIT - Read/write
--***************************************************************************/
--static void p2001_eth_mdio_init()
++ * PHY MANAGEMENT UNIT - Read/write
++ **************************************************************************/
++
++/**
++ *    mdio_read - read MII PHY register
++ *    @dev: the net device to read
++ *    @regadr: the phy register id to read
++ *
++ *    Read MII registers through MDIO and MDC
++ *    using MDIO management frame structure and protocol(defined by ISO/IEC).
++ */
++static int p2001_eth_mdio_read(int phy_id, int location)
  {
--      /* reset ethernet PHYs */
--      printf("Resetting PHYs...\n");
++      int result, boguscnt = 1000;
  
--      /* GPIO24/25: TX_ER2/TX_ER0 */
--      /* GPIO26/27: PHY_RESET/TX_ER1 */
--      P2001_GPIO->PIN_MUX |= 0x0018;
--      // 31-16: 0000 1111 0000 0000
--      P2001_GPIO->GPIO2_En |= 0x0400;
++      do {
++              /* Warten bis Hardware inaktiv (MIU = "0") */
++              while (P2001_MU->MU_CNTL & 0x8000)
++                      barrier();
  
--      P2001_GPIO->GPIO2_Out |= 0x04000000;
--      P2001_GPIO->GPIO2_Out &= ~0x0400;
--      mdelay(500);
--      P2001_GPIO->GPIO2_Out |= 0x0400;
++              /* Schreiben MU_CNTL */
++              P2001_MU->MU_CNTL = location + (phy_id<<5) + (2<<10);
  
--      /* set management unit clock divisor */
--      // max. MDIO CLK = 2.048 MHz (EU.doc)
--      // max. MDIO CLK = 8.000 MHz (LXT971A)
--      // sysclk/(2*(n+1)) = MDIO CLK <= 2.048 MHz
--      // n >= sysclk/4.096 MHz - 1
--#if SYSCLK == 73728000
--      P2001_MU->MU_DIV = 17;  // 73.728 MHZ =17=> 2.020 MHz
--#else
--      //MU->MU_DIV = (SYSCLK/4.096)-1;
--#error "Please define a proper MDIO CLK divisor for that sysclk."
--#endif
--      asm("nop \n nop");
++              /* Warten bis Hardware aktiv (MIU = "1") */
++              while ((P2001_MU->MU_CNTL & 0x8000) == 0)
++                      barrier();
++              //asm("nop \r\n nop");
++
++              /* Warten bis Hardware inaktiv (MIU = "0") */
++              while (P2001_MU->MU_CNTL & 0x8000)
++                      barrier();
++
++              /* Fehler, wenn MDIO Read Error (MRE = "1") */
++      } while ((P2001_MU->MU_CNTL & 0x4000) && (--boguscnt > 0));
++
++      /* Lesen MU_DATA */
++      result = P2001_MU->MU_DATA;
++
++      if (boguscnt == 0)
++              return 0;
++      if ((result & 0xffff) == 0xffff)
++              return 0;
++
++      return result & 0xffff;
  }
  
--static void p2001_eth_mdio_write(unsigned int phyadr, unsigned int regadr, unsigned int data)
--{
--      static unsigned int count;
--      count = 0;
  
++/**
++ *    mdio_write - write MII PHY register
++ *    @dev: the net device to write
++ *    @regadr: the phy register id to write
++ *    @value: the register value to write with
++ *
++ *    Write MII registers with @value through MDIO and MDC
++ *    using MDIO management frame structure and protocol(defined by ISO/IEC)
++ */
++static void p2001_eth_mdio_write(int phy_id, int location, int val)
++{
        /* Warten bis Hardware inaktiv (MIU = "0") */
--      while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
--              count++;
++      while (P2001_MU->MU_CNTL & 0x8000)
++              barrier();
  
        /* Schreiben MU_DATA */
--      MU->MU_DATA = data;
++      P2001_MU->MU_DATA = val;
  
        /* Schreiben MU_CNTL */
--      MU->MU_CNTL = regadr + (phyadr<<5) + (1<<10);
++      P2001_MU->MU_CNTL = location + (phy_id<<5) + (1<<10);
  
        /* Warten bis Hardware aktiv (MIU = "1") */
--      while (((MU->MU_CNTL & 0x8000) == 0) && (count < MDIO_MAXCOUNT))
--              count++;
++      while ((P2001_MU->MU_CNTL & 0x8000) == 0)
++              barrier();
        //asm("nop \r\n nop");
  
        /* Warten bis Hardware inaktiv (MIU = "0") */
--      while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
--              count++;
--
--      mdio_error = (count >= MDIO_MAXCOUNT);
++      while (P2001_MU->MU_CNTL & 0x8000)
++              barrier();
  }
  
--static unsigned int p2001_eth_mdio_read(unsigned int phyadr, unsigned int regadr)
--{
--      static unsigned int count;
--      count = 0;
--
--      do {
--              /* Warten bis Hardware inaktiv (MIU = "0") */
--              while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
--                      count++;
--
--              /* Schreiben MU_CNTL */
--              MU->MU_CNTL = regadr + (phyadr<<5) + (2<<10);
--
--              /* Warten bis Hardware aktiv (MIU = "1") */
--              while (((MU->MU_CNTL & 0x8000) == 0) && (count < MDIO_MAXCOUNT))
--                      count++;
--              //asm("nop \r\n nop");
--
--              /* Warten bis Hardware inaktiv (MIU = "0") */
--              while ((MU->MU_CNTL & 0x8000) && (count < MDIO_MAXCOUNT))
--                      count++;
--
--              /* Fehler, wenn MDIO Read Error (MRE = "1") */
--      } while ((MU->MU_CNTL & 0x4000) && (count < MDIO_MAXCOUNT));
--
--      /* Lesen MU_DATA */
--      mdio_error = (count >= MDIO_MAXCOUNT);
--      return MU->MU_DATA;
--}
  
  
  /**************************************************************************
--POLL - Wait for a frame
--***************************************************************************/
++ * POLL - Wait for a frame
++ **************************************************************************/
++
  /* Function: p2001_eth_poll
   *
   * Description: checks for a received packet and returns it if found.
@@@ -231,9 -231,9 +230,11 @@@ static int p2001_eth_poll(struct nic *n
  }
  
  
++
  /**************************************************************************
--TRANSMIT - Transmit a frame
--***************************************************************************/
++ * TRANSMIT - Transmit a frame
++ **************************************************************************/
++
  /* Function: p2001_eth_transmit
   *
   * Description: transmits a packet and waits for completion or timeout.
@@@ -271,7 -271,7 +272,7 @@@ static void p2001_eth_transmit
        // TMAC_CNTL.ATP does the same
  
  #ifdef DEBUG_NIC
--      printf("p2001_eth_transmit: packet from %! to %! sent\n", txb+ETH_ALEN, txb);
++      printf("p2001_eth_transmit: packet from %! to %! sent (size: %d)\n", txb+ETH_ALEN, txb, s);
  #endif
  
        /* configure descriptor */
  
        /* restart the transmitter */
        EU->TMAC_DMA_EN = 0x01;         /* set run bit */
--      while(EU->TMAC_DMA_EN & 0x01) ; /* wait */
++      while(EU->TMAC_DMA_EN & 0x01) /* wait */
  
  #ifdef DEBUG_NIC
        /* check status */
        status = EU->TMAC_DMA_STAT;
--      if (status & ~(0x40))
++      if (status & ~(0x40))   // not END
                printf("p2001_eth_transmit: dma status=0x%hx\n", status);
  
        printf("TMAC_MIB6..7: %d:%d\n", EU->TMAC_MIB6, EU->TMAC_MIB7);
  }
  
  
++
  /**************************************************************************
--IRQ - Enable, Disable or Force Interrupts
--***************************************************************************/
++ * IRQ - Enable, Disable or Force Interrupts
++ **************************************************************************/
++
  /* Function: p2001_eth_irq
   *
   * Description: Enable, Disable, or Force, interrupts
@@@ -321,9 -321,9 +324,11 @@@ p2001_eth_irq(struct nic *nic __unused
  }
  
  
++
  /**************************************************************************
--INIT - Initialize device
--***************************************************************************/
++ * INIT - Initialize device
++ **************************************************************************/
++
  /* Function: p2001_init
   *
   * Description: resets the ethernet controller chip and various
@@@ -335,6 -335,6 +340,23 @@@ static void p2001_eth_init(
  {
        static int i;
  
++      /* activate MII 3 */
++      if (cur_channel == 3)
++              P2001_GPIO->PIN_MUX |= (1<<8);  // MII_3_en = 1
++
++#ifdef RMII
++      /* RMII init sequence */
++      if (link & LPA_100) {
++              EU->CONF_RMII = (1<<2) | (1<<1);                // softres | 100Mbit
++              EU->CONF_RMII = (1<<2) | (1<<1) | (1<<0);       // softres | 100Mbit | RMII
++              EU->CONF_RMII = (1<<1) | (1<<0);                // 100 Mbit | RMII
++      } else {
++              EU->CONF_RMII = (1<<2);                         // softres
++              EU->CONF_RMII = (1<<2) | (1<<0);                // softres | RMII
++              EU->CONF_RMII = (1<<0);                         // RMII
++      }
++#endif
++
        /* disable transceiver */
  //    EU->TMAC_DMA_EN = 0;            /* clear run bit */
  //    EU->RMAC_DMA_EN = 0;            /* clear run bit */
  //    txd.stat = (1<<31) | (1<<30) | (1<<29);                 // DSC0 OWN|START|END
  //    txd.cntl = cur_channel << 16;                           // DSC1 CHANNEL
  //    txd.cntl |= DMA_BUF_SIZE;                               // DSC1 LEN
--      txd.buf = &txb;                                         // DSC2 BUFFER
++      txd.buf = (char *)&txb;                                 // DSC2 BUFFER
        txd.next = &txd;                                        // DSC3 NEXTDSC @self
        EU->TMAC_DMA_DESC = &txd;
  
        EU->RMAC_DMA_DESC = &rxd[0];
  
        /* set transmitter mode */
--      EU->TMAC_CNTL = (1<<4) |        /* COI: Collision ignore */
--                      //(1<<3) |      /* CSI: Carrier Sense ignore */
--                      (1<<2);         /* ATP: Automatic Transmit Padding */
++      if (link & LPA_DUPLEX)
++              EU->TMAC_CNTL = (1<<4) |        /* COI: Collision ignore */
++                              (1<<3) |        /* CSI: Carrier Sense ignore */
++                              (1<<2);         /* ATP: Automatic Transmit Padding */
++      else
++              EU->TMAC_CNTL = (1<<2);         /* ATP: Automatic Transmit Padding */
  
        /* set receive mode */
        EU->RMAC_CNTL = (1<<3) |        /* BROAD: Broadcast packets */
  }
  
  
++
  /**************************************************************************
--DISABLE - Turn off ethernet interface
--***************************************************************************/
++ * DISABLE - Turn off ethernet interface
++ **************************************************************************/
  static void p2001_eth_disable(struct dev *dev __unused)
  {
        /* put the card in its initial state */
  }
  
  
++
  /**************************************************************************
--LINK - Check for valid link
--***************************************************************************/
++ * LINK - Check for valid link
++ **************************************************************************/
  static int p2001_eth_check_link(unsigned int phy)
  {
        static int status;
--      static unsigned int count;
--      count = 0;
++      static unsigned int i, physid;
++
++      /* print some information about out PHY */
++      physid = (p2001_eth_mdio_read(phy, MII_PHYSID2) << 16) |
++                p2001_eth_mdio_read(phy, MII_PHYSID1);
++      printf("PHY %d, ID 0x%x ", phy, physid);
++      for (i = 0; mii_chip_table[i].physid; i++)
++              if (mii_chip_table[i].physid == physid) {
++                      printf("(%s).\n", mii_chip_table[i].name);
++                      break;
++              }
++      if (!mii_chip_table[i].physid)
++              printf("(unknown).\n");
  
        /* Use 0x3300 for restarting NWay */
        printf("Starting auto-negotiation... ");
--      p2001_eth_mdio_write(phy, Adr_LXT971A_Control, 0x3300);
--      if (mdio_error)
--              goto failed;
++      p2001_eth_mdio_write(phy, MII_BMCR, 0x3300);
  
--      /* Bits 1.5 and 17.7 are set to 1 once the Auto-Negotiation process to completed. */
++      /* Bit 1.5 is set once the Auto-Negotiation process is completed. */
++      i = 0;
        do {
                mdelay(500);
--              status = p2001_eth_mdio_read(phy, Adr_LXT971A_Status1);
--              if (mdio_error || (count++ > 6))        // 6*500ms = 3s timeout
++              status = p2001_eth_mdio_read(phy, MII_BMSR);
++              if (!status || (i++ > 6))       // 6*500ms = 3s timeout
                        goto failed;
--      } while (!(status & 0x20));
--      
--      /* Bits 1.2 and 17.10 are set to 1 once the link is established. */
--      if (p2001_eth_mdio_read(phy, Adr_LXT971A_Status1) & 0x04) {
--              /* Bits 17.14 and 17.9 can be used to determine the link operation conditions (speed and duplex). */
--              printf("Valid link, operating at: %sMb-%s\n",
--                      (p2001_eth_mdio_read(phy, Adr_LXT971A_Status2) & 0x4000) ? "100" : "10",
--                      (p2001_eth_mdio_read(phy, Adr_LXT971A_Status2) & 0x0200) ? "FD" : "HD");
--                      return 1;
++      } while (!(status & BMSR_ANEGCOMPLETE));
++
++      /* Bits 1.2 is set once the link is established. */
++      if ((status = p2001_eth_mdio_read(phy, MII_BMSR)) & BMSR_LSTATUS) {
++              link = p2001_eth_mdio_read(phy, MII_ADVERTISE) &
++                     p2001_eth_mdio_read(phy, MII_LPA);
++              printf("  Valid link, operating at: %sMb-%s\n",
++                      (link & LPA_100) ? "100" : "10",
++                      (link & LPA_DUPLEX) ? "FD" : "HD");
++              return 1;
        }
  
  failed:
--      if (mdio_error)
++      if (!status)
                printf("Failed\n");
        else
                printf("No valid link\n");
  }
  
  
++
++/**************************************************************************
++ * PHYRESET - hardware reset all MII PHYs
++ **************************************************************************/
++
++/**
++ *    p2001_eth_phyreset - hardware reset all MII PHYs
++ */
++static void p2001_eth_phyreset()
++{
++      /* GPIO24/25: TX_ER2/TX_ER0 */
++      /* GPIO26/27: PHY_RESET/TX_ER1 */
++      P2001_GPIO->PIN_MUX |= 0x0018;
++      // 31-16: 0000 1111 0000 0000
++      P2001_GPIO->GPIO2_En |= 0x0400;
++
++      P2001_GPIO->GPIO2_Out |= 0x04000000;
++      P2001_GPIO->GPIO2_Out &= ~0x0400;
++      mdelay(500);
++      P2001_GPIO->GPIO2_Out |= 0x0400;
++
++#ifdef RMII
++      /* RMII_clk_sel = 0xxb  no RMII (default) */
++      /* RMII_clk_sel = 100b  COL_0 */
++      /* RMII_clk_sel = 101b  COL_1 */
++      /* RMII_clk_sel = 110b  COL_2 */
++      /* RMII_clk_sel = 111b  COL_3 */
++      P2001_GPIO->PIN_MUX |= (4 << 13);
++#endif
++}
++
++
++
  /**************************************************************************
--PROBE - Look for an adapter, this routine's visible to the outside
--***************************************************************************/
++ * PROBE - Look for an adapter, this routine's visible to the outside
++ **************************************************************************/
++
  static int p2001_eth_probe(struct dev *dev, unsigned short *probe_addrs __unused)
  {
        struct nic *nic = (struct nic *)dev;
        /* if probe_addrs is 0, then routine can use a hardwired default */
--      static int board_found;
--      static int valid_link;
  
        /* reset phys and configure mdio clk */
--      p2001_eth_mdio_init();
++      printf("Resetting PHYs...\n");
++      p2001_eth_phyreset();
++
++      /* set management unit clock divisor */
++      // max. MDIO CLK = 2.048 MHz (EU.doc)
++      P2001_MU->MU_DIV = (SYSCLK/4096000)-1;  // 2.048 MHz
++      //asm("nop \n nop");
  
        /* find the correct PHY/DMA/MAC combination */
--      MU = P2001_MU;  // MU for all PHYs is only in EU0
        printf("Searching for P2001 NICs...\n");
++      cur_phy = -1;
        for (cur_channel=0; cur_channel<4; cur_channel++) {
--              switch(cur_channel) {
--                      case 0:
--                              EU = P2001_EU0;
--                              cur_phy = 0;
--                              break;
--                      case 1:
--                              EU = P2001_EU1;
--                              cur_phy = 1;
--                              break;
--                      case 2:
--                              EU = P2001_EU2;
--                              cur_phy = 2;
--                              break;
--                      case 3:
--                              EU = P2001_EU3;
--                              cur_phy = 3;
++              EU = P2001_EU(cur_channel);
++
++              /* find next phy */
++              while (++cur_phy < 16) {
++                      //printf("phy detect %d\n", cur_phy);
++                      if (p2001_eth_mdio_read(cur_phy, MII_BMSR) != 0)
                                break;
                }
++              if (cur_phy == 16) {
++                      printf("no more MII PHYs found\n");
++                      break;
++              }
  
                /* first a non destructive test for initial value RMAC_TLEN=1518 */
--              board_found = (EU->RMAC_TLEN == 1518);
--              if (board_found) {
++              if (EU->RMAC_TLEN == 1518) {
                        printf("Checking EU%d...\n", cur_channel);
  
--                      valid_link = p2001_eth_check_link(cur_phy);
--                      if (valid_link) {
++                      if (p2001_eth_check_link(cur_phy)) {
                                /* initialize device */
                                p2001_eth_init(nic);
  
  
                                /* Report the ISA pnp id of the board */
                                dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
--                              dev->devid.vendor_id = htons(0x1234);
                                return 1;
                        }
                }
@@@ -100,10 -100,10 +100,7 @@@ typedef struct {                                 // 0x00130000
  
  typedef union {                                               // 0x00140000U
        struct {        // write
--              volatile unsigned int TX1;              // 0x00000000U
--              volatile unsigned int TX2;              // 0x00000004U
--              volatile unsigned int TX3;              // 0x00000008U
--              volatile unsigned int TX4;              // 0x0000000CU
++              volatile unsigned int TX[4];            // 0x00000000-0x000CU
                volatile unsigned int Baudrate;         // 0x00000010U
                volatile unsigned int reserved1[0x3];
                volatile unsigned int Config;           // 0x00000020U
        } w;            // write
        
        struct {        // read
--              volatile unsigned int RX1;              // 0x00000000U
--              volatile unsigned int RX2;              // 0x00000004U
--              volatile unsigned int RX3;              // 0x00000008U
--              volatile unsigned int RX4;              // 0x0000000CU
++              volatile unsigned int RX[4];            // 0x00000000-0x000CU
                volatile unsigned int reserved1[0x4];
                volatile unsigned int PRE_STATUS;       // 0x00000020U
                volatile unsigned int STATUS;           // 0x00000024U
@@@ -168,11 -168,11 +162,8 @@@ typedef struct {                         // 0x0018_000U _=0,
        volatile unsigned int TMAC_DMA_DATA;    // 0x00000FF8U
        volatile unsigned int TMAC_DMA_ADR;     // 0x00000FFCU
  } *P2001_ETH_regs_ptr;
--#define P2001_EU0 ((volatile P2001_ETH_regs_ptr) 0x00180000)
--#define P2001_EU1 ((volatile P2001_ETH_regs_ptr) 0x00181000)
--#define P2001_EU2 ((volatile P2001_ETH_regs_ptr) 0x00182000)
--#define P2001_EU3 ((volatile P2001_ETH_regs_ptr) 0x00183000)
--#define P2001_MU  P2001_EU0
++#define P2001_EU(x) ((volatile P2001_ETH_regs_ptr) ((unsigned int) 0x00180000UL+(0x1000UL*(x)))) /* x = 0..3 */
++#define P2001_MU  P2001_EU(0)
  
  #endif
  
diff --cc src/arch/armnommu/include/lxt971a.h
index 16314ec,16314ec..0000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,30 -1,30 +1,0 @@@
--/*
-- *  Copyright (C) 2004 Tobias Lorenz
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--/*
-- * Intel LXT971ALE (MII-compatible PHY)
-- */
--
--#define Adr_LXT971A_Control           0       /* Control Register */
--#define Adr_LXT971A_Status1           1       /* MII Status Register #1 */
--#define Adr_LXT971A_PHY_ID1           2       /* PHY Identification Register 1 */
--#define Adr_LXT971A_PHY_ID2           3       /* PHY Identification Register 2 */
--#define Adr_LXT971A_AN_Advertise      4       /* Auto Negotiation Advertisement Register */
--#define Adr_LXT971A_AN_Link_Ability   5       /* Auto Negotiation Link Partner Base Page Ability Register */
--#define Adr_LXT971A_AN_Expansion      6       /* Auto Negotiation Expansion */
--#define Adr_LXT971A_AN_Next_Page_Txmit        7       /* Auto Negotiation Next Page Transmit Register */
--#define Adr_LXT971A_AN_Link_Next_Page 8       /* Auto Negotiation Link Partner Next Page Receive Register */
--#define Adr_LXT971A_Fast_Control      9       /* Not Implemented */
--#define Adr_LXT971A_Fast_Status               10      /* Not Implemented */
--#define Adr_LXT971A_Extended_Status   15      /* Not Implemented */
--#define Adr_LXT971A_Port_Config               16      /* Configuration Register */
--#define Adr_LXT971A_Status2           17      /* Status Register #2 */
--#define Adr_LXT971A_Interrupt_Enable  18      /* Interrupt Enable Register */
--#define Adr_LXT971A_Interrupt_Status  19      /* Interrupt Status Register */
--#define Adr_LXT971A_LED_Config                20      /* LED Configuration Register */
--#define Adr_LXT971A_Transmit_Control  30      /* Transmit Control Register */
@@@ -20,4 -20,4 +20,16 @@@ typedef signed short       int16_t
  typedef signed int         int32_t;
  typedef signed long long   int64_t;
  
++typedef signed char        s8;
++typedef unsigned char      u8;
++
++typedef signed short       s16;
++typedef unsigned short     u16;
++
++typedef signed long        s32;
++typedef unsigned int       u32;
++
++typedef signed long long   s64;
++typedef unsigned long long u64;
++
  #endif /* STDINT_H */
@@@ -13,4 -13,4 +13,16 @@@ typedef signed short       int16_t
  typedef signed int         int32_t;
  typedef signed long long   int64_t;
  
++typedef signed char        s8;
++typedef unsigned char      u8;
++
++typedef signed short       s16;
++typedef unsigned short     u16;
++
++typedef signed long        s32;
++typedef unsigned int       u32;
++
++typedef signed long long   s64;
++typedef unsigned long long u64;
++
  #endif /* STDINT_H */
@@@ -216,7 -216,7 +216,7 @@@ static int elf_freebsd_debug_loader(uns
                                        estate.toread, estate.curaddr);
  #endif
                                /* Save where we are loading this... */
--                              symtab_load = phys_to_virt(estate.curaddr);
++                              symtab_load = estate.curaddr;
                                
                                *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
                                estate.curaddr += sizeof(long);
                                        estate.toread, estate.curaddr);
  #endif
                                /* Save where we are loading this... */
--                              symstr_load = phys_to_virt(estate.curaddr);
++                              symstr_load = estate.curaddr;
                                
                                *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
                                estate.curaddr += sizeof(long);
@@@ -290,7 -290,7 +290,7 @@@ static void elf_freebsd_boot(unsigned l
                /* Assumes size of long is a power of 2... */
                bsdinfo.bi_esymtab = (symstr_load +
                        sizeof(long) +
--                      *((long *)symstr_load) +
++                      *((long *)phys_to_virt(symstr_load)) +
                        sizeof(long) - 1) & ~(sizeof(long) - 1);
                
                /* Where we will build the meta data... */
@@@ -16,4 -16,4 +16,16 @@@ typedef signed long long     int64_t
  
  typedef unsigned long         physaddr_t;
  
++typedef signed char      s8;
++typedef unsigned char      u8;
++
++typedef signed short       s16;
++typedef unsigned short     u16;
++
++typedef signed int         s32;
++typedef unsigned int       u32;
++
++typedef signed long long   s64;
++typedef unsigned long long u64;
++
  #endif /* STDINT_H */
@@@ -13,4 -13,4 +13,16 @@@ typedef signed short       int16_t
  typedef signed int         int32_t;
  typedef signed long        int64_t;
  
++typedef signed char        s8;
++typedef unsigned char      u8;
++
++typedef signed short       s16;
++typedef unsigned short     u16;
++
++typedef signed int         s32;
++typedef unsigned int       u32;
++
++typedef signed long      s64;
++typedef unsigned long      u64;
++
  #endif /* STDINT_H */
@@@ -74,6 -74,6 +74,9 @@@ void print_config ( void ) 
  #ifdef DOWNLOAD_PROTO_TFTP
                "TFTP "
  #endif
++#ifdef  DOWNLOAD_PROTO_FSP
++              "FSP "
++#endif                                
  #ifdef  DOWNLOAD_PROTO_NFS
                "NFS "
  #endif
@@@ -61,10 -61,10 +61,6 @@@ static void t3c515_wait(unsigned int nt
  
  /* TJL definations */
  #define HZ      100
--#define u16 unsigned short
--#define u32 unsigned long
--#define s16 signed short
--#define s32 signed long
  static int if_port;
  static struct corkscrew_private *vp;
  /* Brought directly from 3c515.c by Becker */
  
  #define TX_TIME_OUT       2*TICKS_PER_SEC
  
--typedef unsigned char  u8;
--typedef   signed char  s8;
--typedef unsigned short u16;
--typedef   signed short s16;
--typedef unsigned int   u32;
--typedef   signed int   s32;
--
  /* Register offsets for davicom device */
  enum davicom_offsets {
     CSR0=0,     CSR1=0x08,  CSR2=0x10,  CSR3=0x18,  CSR4=0x20,  CSR5=0x28,
@@@ -413,13 -413,13 +413,6 @@@ static char *adapter_name[] = 
  #define ALIGN8      ((u32)8 - 1)       /* 2 longword (quadword) align */
  #define ALIGN         ALIGN8              /* Keep the LANCE happy... */
  
--typedef       long            s32;
--typedef       unsigned long   u32;
--typedef       short           s16;
--typedef       unsigned short  u16;
--typedef       char            s8;
--typedef       unsigned char   u8;
--
  /*
  ** The DEPCA Rx and Tx ring descriptors. 
  */
  #define dprintf(x)
  #endif
  
--typedef unsigned char u8;
--typedef signed char s8;
--typedef unsigned short u16;
--typedef signed short s16;
--typedef unsigned int u32;
--typedef signed int s32;
--
  /* 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))
@@@ -18,6 -18,6 +18,12 @@@ Be careful with seating the EPROM as th
  has 34 pins, the top row of 2 are not used.
  ***************************************************************************/
  
++/*
++
++ timlegge     2005-05-18      remove the relocation changes cards that 
++                              write directly to the hardware don't need it
++*/
++
  /*
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
@@@ -257,8 -257,8 +263,8 @@@ static unsigned eeprom_reg = EEPROM_REG
  #define eeprom_delay() { udelay(40); }
  #define EE_READ_CMD (6 << 6)
  
--/* do a full reset */
--#define eepro_full_reset(ioaddr)      outb(RESET_CMD, ioaddr); udelay(40);
++/* do a full reset; data sheet asks for 250us delay */
++#define eepro_full_reset(ioaddr)      outb(RESET_CMD, ioaddr); udelay(255);
  
  /* do a nice reset */
  #define eepro_sel_reset(ioaddr)       { \
@@@ -320,13 -320,13 +326,15 @@@ static void eepro_reset(struct nic *nic
        eepro_sw2bank0(nic->ioaddr);    /* Switch back to bank 0 */
        eepro_clear_int(nic->ioaddr);
        /* Initialise RCV */
--      rx_start = (unsigned int)bus_to_virt(RCV_LOWER_LIMIT << 8);
--      outw(RCV_LOWER_LIMIT << 8, nic->ioaddr + RCV_BAR);
++      outw(rx_start = (RCV_LOWER_LIMIT << 8), nic->ioaddr + RCV_BAR);
        outw(((RCV_UPPER_LIMIT << 8) | 0xFE), nic->ioaddr + RCV_STOP);
++      /* Make sure 1st poll won't find a valid packet header */
++      outw((RCV_LOWER_LIMIT << 8), nic->ioaddr + HOST_ADDRESS_REG);
++      outw(0,                      nic->ioaddr + IO_PORT);
        /* Intialise XMT */
        outw((XMT_LOWER_LIMIT << 8), nic->ioaddr + xmt_bar);
        eepro_sel_reset(nic->ioaddr);
--      tx_start = tx_end = (unsigned int)bus_to_virt(XMT_LOWER_LIMIT << 8);
++      tx_start = tx_end = (XMT_LOWER_LIMIT << 8);
        tx_last = 0;
        eepro_en_rx(nic->ioaddr);
  }
@@@ -336,7 -336,7 +344,7 @@@ POLL - Wait for a fram
  ***************************************************************************/
  static int eepro_poll(struct nic *nic, int retrieve)
  {
--      unsigned int    rcv_car = virt_to_bus((void *)rx_start);
++      unsigned int    rcv_car = rx_start;
        unsigned int    rcv_event, rcv_status, rcv_next_frame, rcv_size;
  
        /* return true if there's an ethernet packet ready to read */
  }
  #endif
        nic->packetlen = rcv_size;
--      rcv_car  = virt_to_bus((void *) (rx_start + RCV_HEADER + rcv_size));
--      rx_start = (unsigned int)bus_to_virt(rcv_next_frame << 8);
++      rcv_car  = (rx_start + RCV_HEADER + rcv_size);
++      rx_start = rcv_next_frame;
++/* 
++      hex_dump(rcv_car, nic->packetlen); 
++*/
++
        if (rcv_car == 0)
                rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff);
        outw(rcv_car - 1, nic->ioaddr + RCV_STOP);
@@@ -455,7 -455,7 +467,7 @@@ static void eepro_disable ( struct nic 
        eepro_sw2bank0(nic->ioaddr);    /* Switch to bank 0 */
        /* Flush the Tx and disable Rx */
        outb(STOP_RCV_CMD, nic->ioaddr);
--      tx_start = tx_end = (unsigned int) (bus_to_virt(XMT_LOWER_LIMIT << 8));
++      tx_start = tx_end = (XMT_LOWER_LIMIT << 8);
        tx_last = 0;
        /* Reset the 82595 */
        eepro_full_reset(nic->ioaddr);
  
  static int ioaddr;
  
--typedef unsigned char  u8;
--typedef   signed char  s8;
--typedef unsigned short u16;
--typedef   signed short s16;
--typedef unsigned int   u32;
--typedef   signed int   s32;
--
  enum speedo_offsets {
    SCBStatus = 0, SCBCmd = 2,      /* Rx/Command Unit command and status. */
    SCBPointer = 4,                 /* General purpose pointer. */
  *     (C) 2003 Manfred Spraul
  *             See Linux Driver for full information
  *     
--*     Linux Driver Version 0.22, 19 Jan 2004
++*     Linux Driver Version 0.30, 25 Sep 2004
++*     Linux Kernel 2.6.10
  * 
  * 
  *    REVISION HISTORY:
  *    ================
  *    v1.0     01-31-2004      timlegge        Initial port of Linux driver
  *    v1.1     02-03-2004      timlegge        Large Clean up, first release 
--*    
++*    v1.2     05-14-2005      timlegge        Add Linux 0.22 to .030 features
++*
  *    Indent Options: indent -kr -i8
  ***************************************************************************/
  
  #include "pci.h"
  /* Include timer support functions */
  #include "timer.h"
++#include "mii.h"
  
--#define drv_version "v1.1"
--#define drv_date "02-03-2004"
++#define drv_version "v1.2"
++#define drv_date "05-14-2005"
  
  //#define TFTM_DEBUG
  #ifdef TFTM_DEBUG
  #define dprintf(x)
  #endif
  
--typedef unsigned char u8;
--typedef signed char s8;
--typedef unsigned short u16;
--typedef signed short s16;
--typedef unsigned int u32;
--typedef signed int s32;
++#define ETH_DATA_LEN   1500
  
  /* Condensed operations for readability. */
  #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
  
  static unsigned long BASE;
  /* NIC specific static variables go here */
++#define PCI_DEVICE_ID_NVIDIA_NVENET_1           0x01c3
++#define PCI_DEVICE_ID_NVIDIA_NVENET_2           0x0066
++#define PCI_DEVICE_ID_NVIDIA_NVENET_4           0x0086
++#define PCI_DEVICE_ID_NVIDIA_NVENET_5           0x008c
++#define PCI_DEVICE_ID_NVIDIA_NVENET_3           0x00d6
++#define PCI_DEVICE_ID_NVIDIA_NVENET_7           0x00df
++#define PCI_DEVICE_ID_NVIDIA_NVENET_6           0x00e6
++#define PCI_DEVICE_ID_NVIDIA_NVENET_8           0x0056
++#define PCI_DEVICE_ID_NVIDIA_NVENET_9           0x0057
++#define PCI_DEVICE_ID_NVIDIA_NVENET_10          0x0037
++#define PCI_DEVICE_ID_NVIDIA_NVENET_11          0x0038
  
  
  /*
   * Hardware access:
   */
  
--#define DEV_NEED_LASTPACKET1  0x0001
--#define DEV_IRQMASK_1         0x0002
--#define DEV_IRQMASK_2         0x0004
--#define DEV_NEED_TIMERIRQ     0x0008
++#define DEV_NEED_LASTPACKET1  0x0001  /* set LASTPACKET1 in tx flags */
++#define DEV_IRQMASK_1         0x0002  /* use NVREG_IRQMASK_WANTED_1 for irq mask */
++#define DEV_IRQMASK_2         0x0004  /* use NVREG_IRQMASK_WANTED_2 for irq mask */
++#define DEV_NEED_TIMERIRQ     0x0008  /* set the timer irq flag in the irq mask */
++#define DEV_NEED_LINKTIMER    0x0010  /* poll link settings. Relies on the timer irq */
  
  enum {
        NvRegIrqStatus = 0x000,
  #define NVREG_IRQSTAT_MIIEVENT        0040
  #define NVREG_IRQSTAT_MASK            0x1ff
        NvRegIrqMask = 0x004,
++#define NVREG_IRQ_RX_ERROR            0x0001
  #define NVREG_IRQ_RX                  0x0002
  #define NVREG_IRQ_RX_NOBUF            0x0004
  #define NVREG_IRQ_TX_ERR              0x0008
  #define NVREG_IRQ_TX1                 0x0100
  #define NVREG_IRQMASK_WANTED_1                0x005f
  #define NVREG_IRQMASK_WANTED_2                0x0147
--#define NVREG_IRQ_UNKNOWN             (~(NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))
++#define NVREG_IRQ_UNKNOWN             (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))
  
        NvRegUnknownSetupReg6 = 0x008,
  #define NVREG_UNKSETUP6_VAL           3
  
        NvRegOffloadConfig = 0x90,
  #define NVREG_OFFLOAD_HOMEPHY 0x601
--#define NVREG_OFFLOAD_NORMAL  0x5ee
++#define NVREG_OFFLOAD_NORMAL  RX_NIC_BUFSIZE
        NvRegReceiverControl = 0x094,
  #define NVREG_RCVCTL_START    0x01
        NvRegReceiverStatus = 0x98,
        NvRegRandomSeed = 0x9c,
  #define NVREG_RNDSEED_MASK    0x00ff
  #define NVREG_RNDSEED_FORCE   0x7f00
++#define NVREG_RNDSEED_FORCE2  0x2d00
++#define NVREG_RNDSEED_FORCE3  0x7400
  
        NvRegUnknownSetupReg1 = 0xA0,
  #define NVREG_UNKSETUP1_VAL   0x16070f
        NvRegMulticastMaskA = 0xB8,
        NvRegMulticastMaskB = 0xBC,
  
++      NvRegPhyInterface = 0xC0,
++#define PHY_RGMII             0x10000000
++
        NvRegTxRingPhysAddr = 0x100,
        NvRegRxRingPhysAddr = 0x104,
        NvRegRingSizes = 0x108,
        NvRegUnknownTransmitterReg = 0x10c,
        NvRegLinkSpeed = 0x110,
  #define NVREG_LINKSPEED_FORCE 0x10000
--#define NVREG_LINKSPEED_10    10
++#define NVREG_LINKSPEED_10    1000
  #define NVREG_LINKSPEED_100   100
--#define NVREG_LINKSPEED_1000  1000
++#define NVREG_LINKSPEED_1000  50
        NvRegUnknownSetupReg5 = 0x130,
  #define NVREG_UNKSETUP5_BIT31 (1<<31)
--      NvRegUnknownSetupReg3 = 0x134,
++      NvRegUnknownSetupReg3 = 0x13c,
  #define NVREG_UNKSETUP3_VAL1  0x200010
        NvRegTxRxControl = 0x144,
  #define NVREG_TXRXCTL_KICK    0x0001
  #define NVREG_TXRXCTL_BIT2    0x0004
  #define NVREG_TXRXCTL_IDLE    0x0008
  #define NVREG_TXRXCTL_RESET   0x0010
++#define NVREG_TXRXCTL_RXCHECK 0x0400
        NvRegMIIStatus = 0x180,
  #define NVREG_MIISTAT_ERROR           0x0001
  #define NVREG_MIISTAT_LINKCHANGE      0x0008
        NvRegAdapterControl = 0x188,
  #define NVREG_ADAPTCTL_START  0x02
  #define NVREG_ADAPTCTL_LINKUP 0x04
--#define NVREG_ADAPTCTL_PHYVALID       0x4000
++#define NVREG_ADAPTCTL_PHYVALID       0x40000
  #define NVREG_ADAPTCTL_RUNNING        0x100000
  #define NVREG_ADAPTCTL_PHYSHIFT       24
        NvRegMIISpeed = 0x18c,
  #define NVREG_MIISPEED_BIT8   (1<<8)
  #define NVREG_MIIDELAY        5
        NvRegMIIControl = 0x190,
--#define NVREG_MIICTL_INUSE    0x10000
--#define NVREG_MIICTL_WRITE    0x08000
++#define NVREG_MIICTL_INUSE    0x08000
++#define NVREG_MIICTL_WRITE    0x00400
  #define NVREG_MIICTL_ADDRSHIFT        5
        NvRegMIIData = 0x194,
        NvRegWakeUpFlags = 0x200,
  #define NVREG_WAKEUPFLAGS_ACCEPT_MAGPAT               0x01
  #define NVREG_WAKEUPFLAGS_ACCEPT_WAKEUPPAT    0x02
  #define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE   0x04
++#define NVREG_WAKEUPFLAGS_ENABLE      0x1111
  
        NvRegPatternCRC = 0x204,
        NvRegPatternMask = 0x208,
  #define NVREG_POWERSTATE_D3           0x0003
  };
  
--
--
--#define NV_TX_LASTPACKET      (1<<0)
--#define NV_TX_RETRYERROR      (1<<3)
--#define NV_TX_LASTPACKET1     (1<<8)
--#define NV_TX_DEFERRED                (1<<10)
--#define NV_TX_CARRIERLOST     (1<<11)
--#define NV_TX_LATECOLLISION   (1<<12)
--#define NV_TX_UNDERFLOW               (1<<13)
--#define NV_TX_ERROR           (1<<14)
--#define NV_TX_VALID           (1<<15)
--
--#define NV_RX_DESCRIPTORVALID (1<<0)
--#define NV_RX_MISSEDFRAME     (1<<1)
--#define NV_RX_SUBSTRACT1      (1<<3)
--#define NV_RX_ERROR1          (1<<7)
--#define NV_RX_ERROR2          (1<<8)
--#define NV_RX_ERROR3          (1<<9)
--#define NV_RX_ERROR4          (1<<10)
--#define NV_RX_CRCERR          (1<<11)
--#define NV_RX_OVERFLOW                (1<<12)
--#define NV_RX_FRAMINGERR      (1<<13)
--#define NV_RX_ERROR           (1<<14)
--#define NV_RX_AVAIL           (1<<15)
++#define FLAG_MASK_V1 0xffff0000
++#define FLAG_MASK_V2 0xffffc000
++#define LEN_MASK_V1 (0xffffffff ^ FLAG_MASK_V1)
++#define LEN_MASK_V2 (0xffffffff ^ FLAG_MASK_V2)
++
++#define NV_TX_LASTPACKET      (1<<16)
++#define NV_TX_RETRYERROR      (1<<19)
++#define NV_TX_LASTPACKET1     (1<<24)
++#define NV_TX_DEFERRED                (1<<26)
++#define NV_TX_CARRIERLOST     (1<<27)
++#define NV_TX_LATECOLLISION   (1<<28)
++#define NV_TX_UNDERFLOW               (1<<29)
++#define NV_TX_ERROR           (1<<30)
++#define NV_TX_VALID           (1<<31)
++
++#define NV_TX2_LASTPACKET     (1<<29)
++#define NV_TX2_RETRYERROR     (1<<18)
++#define NV_TX2_LASTPACKET1    (1<<23)
++#define NV_TX2_DEFERRED               (1<<25)
++#define NV_TX2_CARRIERLOST    (1<<26)
++#define NV_TX2_LATECOLLISION  (1<<27)
++#define NV_TX2_UNDERFLOW      (1<<28)
++/* error and valid are the same for both */
++#define NV_TX2_ERROR          (1<<30)
++#define NV_TX2_VALID          (1<<31)
++
++#define NV_RX_DESCRIPTORVALID (1<<16)
++#define NV_RX_MISSEDFRAME     (1<<17)
++#define NV_RX_SUBSTRACT1      (1<<18)
++#define NV_RX_ERROR1          (1<<23)
++#define NV_RX_ERROR2          (1<<24)
++#define NV_RX_ERROR3          (1<<25)
++#define NV_RX_ERROR4          (1<<26)
++#define NV_RX_CRCERR          (1<<27)
++#define NV_RX_OVERFLOW                (1<<28)
++#define NV_RX_FRAMINGERR      (1<<29)
++#define NV_RX_ERROR           (1<<30)
++#define NV_RX_AVAIL           (1<<31)
++
++#define NV_RX2_CHECKSUMMASK   (0x1C000000)
++#define NV_RX2_CHECKSUMOK1    (0x10000000)
++#define NV_RX2_CHECKSUMOK2    (0x14000000)
++#define NV_RX2_CHECKSUMOK3    (0x18000000)
++#define NV_RX2_DESCRIPTORVALID        (1<<29)
++#define NV_RX2_SUBSTRACT1     (1<<25)
++#define NV_RX2_ERROR1         (1<<18)
++#define NV_RX2_ERROR2         (1<<19)
++#define NV_RX2_ERROR3         (1<<20)
++#define NV_RX2_ERROR4         (1<<21)
++#define NV_RX2_CRCERR         (1<<22)
++#define NV_RX2_OVERFLOW               (1<<23)
++#define NV_RX2_FRAMINGERR     (1<<24)
++/* error and avail are the same for both */
++#define NV_RX2_ERROR          (1<<30)
++#define NV_RX2_AVAIL          (1<<31)
  
  /* Miscelaneous hardware related defines: */
  #define NV_PCI_REGSZ          0x270
  #define NV_WAKEUPMASKENTRIES  4
  
  /* General driver defaults */
--#define NV_WATCHDOG_TIMEO     (2*HZ)
--#define DEFAULT_MTU           1500    /* also maximum supported, at least for now */
++#define NV_WATCHDOG_TIMEO     (5*HZ)
  
  #define RX_RING               4
  #define TX_RING               2
--/* limited to 1 packet until we understand NV_TX_LASTPACKET */
--#define TX_LIMIT_STOP 10
--#define TX_LIMIT_START        5
++
++/* 
++ * If your nic mysteriously hangs then try to reduce the limits
++ * to 1/0: It might be required to set NV_TX_LASTPACKET in the
++ * last valid ring entry. But this would be impossible to
++ * implement - probably a disassembly error.
++ */
++#define TX_LIMIT_STOP 63
++#define TX_LIMIT_START        62
  
  /* rx/tx mac addr + type + vlan + align + slack*/
--#define RX_NIC_BUFSIZE                (DEFAULT_MTU + 64)
++#define RX_NIC_BUFSIZE                (ETH_DATA_LEN + 64)
  /* even more slack */
--#define RX_ALLOC_BUFSIZE      (DEFAULT_MTU + 128)
++#define RX_ALLOC_BUFSIZE      (ETH_DATA_LEN + 128)
  
  #define OOM_REFILL    (1+HZ/20)
  #define POLL_WAIT     (1+HZ/100)
--
++#define LINK_TIMEOUT  (3*HZ)
++
++/* 
++ * desc_ver values:
++ * This field has two purposes:
++ * - Newer nics uses a different ring layout. The layout is selected by
++ *   comparing np->desc_ver with DESC_VER_xy.
++ * - It contains bits that are forced on when writing to NvRegTxRxControl.
++ */
++#define DESC_VER_1    0x0
++#define DESC_VER_2    (0x02100|NVREG_TXRXCTL_RXCHECK)
++
++/* PHY defines */
++#define PHY_OUI_MARVELL       0x5043
++#define PHY_OUI_CICADA        0x03f1
++#define PHYID1_OUI_MASK       0x03ff
++#define PHYID1_OUI_SHFT       6
++#define PHYID2_OUI_MASK       0xfc00
++#define PHYID2_OUI_SHFT       10
++#define PHY_INIT1     0x0f000
++#define PHY_INIT2     0x0e00
++#define PHY_INIT3     0x01000
++#define PHY_INIT4     0x0200
++#define PHY_INIT5     0x0004
++#define PHY_INIT6     0x02000
++#define PHY_GIGABIT   0x0100
++
++#define PHY_TIMEOUT   0x1
++#define PHY_ERROR     0x2
++
++#define PHY_100       0x1
++#define PHY_1000      0x2
++#define PHY_HALF      0x100
++
++/* FIXME: MII defines that should be added to <linux/mii.h> */
++#define MII_1000BT_CR 0x09
++#define MII_1000BT_SR 0x0a
++#define ADVERTISE_1000FULL    0x0200
++#define ADVERTISE_1000HALF    0x0100
++#define LPA_1000FULL  0x0800
++#define LPA_1000HALF  0x0400
++
++/* Big endian: should work, but is untested */
  struct ring_desc {
        u32 PacketBuffer;
--      u16 Length;
--      u16 Flags;
++      u32 FlagLen;
  };
  
  
@@@ -310,22 -310,22 +405,25 @@@ static struct forcedeth_private 
        u32 linkspeed;
        int duplex;
        int phyaddr;
++      int wolenabled;
++      unsigned int phy_oui;
++      u16 gigabit;
  
        /* General data: RO fields */
        u8 *ring_addr;
        u32 orig_mac[2];
        u32 irqmask;
++      u32 desc_ver;
        /* rx specific fields.
         * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
         */
        unsigned int cur_rx, refill_rx;
--      unsigned int rx_buf_sz;
  
        /*
         * tx specific fields.
         */
        unsigned int next_tx, nic_tx;
--      u16 tx_flags;
++      u32 tx_flags;
  } npx;
  
  static struct forcedeth_private *np;
@@@ -335,6 -335,6 +433,13 @@@ static inline void pci_push(u8 * base
        /* force out pending posted writes */
        readl(base);
  }
++
++static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v)
++{
++      return le32_to_cpu(prd->FlagLen)
++          & ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
++}
++
  static int reg_delay(int offset, u32 mask,
                     u32 target, int delay, int delaymax, const char *msg)
  {
@@@ -383,18 -383,18 +488,11 @@@ static int mii_rw(struct nic *nic __unu
                  int value)
  {
        u8 *base = (u8 *) BASE;
--      int was_running;
        u32 reg;
        int retval;
  
        writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
--      was_running = 0;
--      reg = readl(base + NvRegAdapterControl);
--      if (reg & NVREG_ADAPTCTL_RUNNING) {
--              was_running = 1;
--              writel(reg & ~NVREG_ADAPTCTL_RUNNING,
--                     base + NvRegAdapterControl);
--      }
++
        reg = readl(base + NvRegMIIControl);
        if (reg & NVREG_MIICTL_INUSE) {
                writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl);
        }
  
        reg =
--          NVREG_MIICTL_INUSE | (addr << NVREG_MIICTL_ADDRSHIFT) | miireg;
++          (addr << NVREG_MIICTL_ADDRSHIFT) | miireg;
        if (value != MII_READ) {
                writel(value, base + NvRegMIIData);
                reg |= NVREG_MIICTL_WRITE;
                         miireg, addr));
                retval = -1;
        } else {
--              /* FIXME: why is that required? */
--              udelay(50);
                retval = readl(base + NvRegMIIData);
                dprintf(("mii_rw read from reg %d at PHY %d: 0x%x.\n",
                         miireg, addr, retval));
        }
--      if (was_running) {
--              reg = readl(base + NvRegAdapterControl);
--              writel(reg | NVREG_ADAPTCTL_RUNNING,
--                     base + NvRegAdapterControl);
--      }
        return retval;
  }
  
++static int phy_reset(struct nic *nic)
++{
++
++      u32 miicontrol;
++      unsigned int tries = 0;
++
++      miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
++      miicontrol |= BMCR_RESET;
++      if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol)) {
++              return -1;
++      }
++
++      /* wait for 500ms */
++      mdelay(500);
++
++      /* must wait till reset is deasserted */
++      while (miicontrol & BMCR_RESET) {
++              mdelay(10);
++              miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
++              /* FIXME: 100 tries seem excessive */
++              if (tries++ > 100)
++                      return -1;
++      }
++      return 0;
++}
++
++static int phy_init(struct nic *nic)
++{
++      u8 *base = (u8 *) BASE;
++      u32 phyinterface, phy_reserved, mii_status, mii_control,
++          mii_control_1000, reg;
++
++      /* set advertise register */
++      reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
++      reg |=
++          (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF |
++           ADVERTISE_100FULL | 0x800 | 0x400);
++      if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg)) {
++              printf("phy write to advertise failed.\n");
++              return PHY_ERROR;
++      }
++
++      /* get phy interface type */
++      phyinterface = readl(base + NvRegPhyInterface);
++
++      /* see if gigabit phy */
++      mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
++
++      if (mii_status & PHY_GIGABIT) {
++              np->gigabit = PHY_GIGABIT;
++              mii_control_1000 =
++                  mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ);
++              mii_control_1000 &= ~ADVERTISE_1000HALF;
++              if (phyinterface & PHY_RGMII)
++                      mii_control_1000 |= ADVERTISE_1000FULL;
++              else
++                      mii_control_1000 &= ~ADVERTISE_1000FULL;
++
++              if (mii_rw
++                  (nic, np->phyaddr, MII_1000BT_CR, mii_control_1000)) {
++                      printf("phy init failed.\n");
++                      return PHY_ERROR;
++              }
++      } else
++              np->gigabit = 0;
++
++      /* reset the phy */
++      if (phy_reset(nic)) {
++              printf("phy reset failed\n");
++              return PHY_ERROR;
++      }
++
++      /* phy vendor specific configuration */
++      if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII)) {
++              phy_reserved =
++                  mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ);
++              phy_reserved &= ~(PHY_INIT1 | PHY_INIT2);
++              phy_reserved |= (PHY_INIT3 | PHY_INIT4);
++              if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved)) {
++                      printf("phy init failed.\n");
++                      return PHY_ERROR;
++              }
++              phy_reserved =
++                  mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ);
++              phy_reserved |= PHY_INIT5;
++              if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved)) {
++                      printf("phy init failed.\n");
++                      return PHY_ERROR;
++              }
++      }
++      if (np->phy_oui == PHY_OUI_CICADA) {
++              phy_reserved =
++                  mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ);
++              phy_reserved |= PHY_INIT6;
++              if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved)) {
++                      printf("phy init failed.\n");
++                      return PHY_ERROR;
++              }
++      }
++
++      /* restart auto negotiation */
++      mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ);
++      mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
++      if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control)) {
++              return PHY_ERROR;
++      }
++
++      return 0;
++}
++
  static void start_rx(struct nic *nic __unused)
  {
        u8 *base = (u8 *) BASE;
@@@ -497,11 -497,11 +698,12 @@@ static void txrx_reset(struct nic *nic 
        u8 *base = (u8 *) BASE;
  
        dprintf(("txrx_reset\n"));
--      writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET,
++      writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver,
               base + NvRegTxRxControl);
++
        pci_push(base);
        udelay(NV_TXRX_RESET_DELAY);
--      writel(NVREG_TXRXCTL_BIT2, base + NvRegTxRxControl);
++      writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
        pci_push(base);
  }
  
@@@ -519,9 -519,9 +721,9 @@@ static int alloc_rx(struct nic *nic __u
                //int nr = refill_rx % RX_RING;
                rx_ring[i].PacketBuffer =
                    virt_to_le32desc(&rxb[i * RX_NIC_BUFSIZE]);
--              rx_ring[i].Length = cpu_to_le16(RX_NIC_BUFSIZE);
                wmb();
--              rx_ring[i].Flags = cpu_to_le16(NV_RX_AVAIL);
++              rx_ring[i].FlagLen =
++                  cpu_to_le32(RX_NIC_BUFSIZE | NV_RX_AVAIL);
                /*      printf("alloc_rx: Packet  %d marked as Available\n",
                   refill_rx); */
                refill_rx++;
  
  static int update_linkspeed(struct nic *nic)
  {
--      int adv, lpa, newdup;
++      int adv, lpa;
        u32 newls;
++      int newdup = np->duplex;
++      u32 mii_status;
++      int retval = 0; 
++      u32 control_1000, status_1000, phyreg;
++      u8 *base = (u8 *) BASE;
++      int i;
++
++      /* BMSR_LSTATUS is latched, read it twice:
++       * we want the current value.
++       */
++      mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
++      mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
++
++#if 1
++      //yhlu
++      for(i=0;i<30;i++) {
++              mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ);
++              if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break;
++              mdelay(100);
++      }
++#endif
++
++      if (!(mii_status & BMSR_LSTATUS)) {
++              printf
++                  ("no link detected by phy - falling back to 10HD.\n");
++              newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
++              newdup = 0;
++              retval = 0;
++              goto set_speed;
++      }
++
++      /* check auto negotiation is complete */
++      if (!(mii_status & BMSR_ANEGCOMPLETE)) {
++              /* still in autonegotiation - configure nic for 10 MBit HD and wait. */
++              newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
++              newdup = 0;
++              retval = 0;
++              printf("autoneg not completed - falling back to 10HD.\n");
++              goto set_speed;
++      }
++
++      retval = 1;
++      if (np->gigabit == PHY_GIGABIT) {
++              control_1000 =
++                  mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ);
++              status_1000 =
++                  mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ);
++
++              if ((control_1000 & ADVERTISE_1000FULL) &&
++                  (status_1000 & LPA_1000FULL)) {
++                      printf
++                          ("update_linkspeed: GBit ethernet detected.\n");
++                      newls =
++                          NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000;
++                      newdup = 1;
++                      goto set_speed;
++              }
++      }
++
        adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ);
        lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ);
        dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n",
                newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
                newdup = 0;
        }
--      if (np->duplex != newdup || np->linkspeed != newls) {
--              np->duplex = newdup;
--              np->linkspeed = newls;
--              return 1;
++
++      set_speed:
++      if (np->duplex == newdup && np->linkspeed == newls)
++              return retval;
++
++      dprintf(("changing link setting from %d/%s to %d/%s.\n",
++             np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex"));
++
++      np->duplex = newdup;
++      np->linkspeed = newls;
++
++      if (np->gigabit == PHY_GIGABIT) {
++              phyreg = readl(base + NvRegRandomSeed);
++              phyreg &= ~(0x3FF00);
++              if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10)
++                      phyreg |= NVREG_RNDSEED_FORCE3;
++              else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
++                      phyreg |= NVREG_RNDSEED_FORCE2;
++              else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
++                      phyreg |= NVREG_RNDSEED_FORCE;
++              writel(phyreg, base + NvRegRandomSeed);
        }
--      return 0;
--}
  
++      phyreg = readl(base + NvRegPhyInterface);
++      phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000);
++      if (np->duplex == 0)
++              phyreg |= PHY_HALF;
++      if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)
++              phyreg |= PHY_100;
++      else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000)
++              phyreg |= PHY_1000;
++      writel(phyreg, base + NvRegPhyInterface);
  
++      writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD),
++             base + NvRegMisc1);
++      pci_push(base);
++      writel(np->linkspeed, base + NvRegLinkSpeed);
++      pci_push(base);
++
++      return retval;
++}
++
++#if 0 /* Not used */
++static void nv_linkchange(struct nic *nic)
++{
++      if (update_linkspeed(nic)) {
++//                if (netif_carrier_ok(nic)) {
++              stop_rx();
++//=                } else {
++              //                      netif_carrier_on(dev);
++              //                    printk(KERN_INFO "%s: link up.\n", dev->name);
++              //          }
++              start_rx(nic);
++      } else {
++              //        if (netif_carrier_ok(dev)) {
++              //              netif_carrier_off(dev);
++              //            printk(KERN_INFO "%s: link down.\n", dev->name);
++              stop_rx();
++              //  }
++      }
++}
++#endif
  
  static int init_ring(struct nic *nic)
  {
        int i;
  
        np->next_tx = np->nic_tx = 0;
--      for (i = 0; i < TX_RING; i++) {
--              tx_ring[i].Flags = 0;
--      }
++      for (i = 0; i < TX_RING; i++)
++              tx_ring[i].FlagLen = 0;
  
        np->cur_rx = 0;
        np->refill_rx = 0;
--      for (i = 0; i < RX_RING; i++) {
--              rx_ring[i].Flags = 0;
--      }
++      for (i = 0; i < RX_RING; i++)
++              rx_ring[i].FlagLen = 0;
        return alloc_rx(nic);
  }
  
@@@ -637,15 -637,15 +949,21 @@@ static int forcedeth_reset(struct nic *
        writel(0, base + NvRegMulticastMaskA);
        writel(0, base + NvRegMulticastMaskB);
        writel(0, base + NvRegPacketFilterFlags);
++
++      writel(0, base + NvRegTransmitterControl);
++      writel(0, base + NvRegReceiverControl);
++
        writel(0, base + NvRegAdapterControl);
++
++      /* 2) initialize descriptor rings */
++      oom = init_ring(nic);
++
        writel(0, base + NvRegLinkSpeed);
        writel(0, base + NvRegUnknownTransmitterReg);
        txrx_reset(nic);
        writel(0, base + NvRegUnknownSetupReg6);
  
--      /* 2) initialize descriptor rings */
        np->in_shutdown = 0;
--      oom = init_ring(nic);
  
        /* 3) set mac address */
        {
                writel(mac[1], base + NvRegMacAddrB);
        }
  
--      /* 4) continue setup */
++      /* 4) give hw rings */
++      writel((u32) virt_to_le32desc(&rx_ring[0]),
++             base + NvRegRxRingPhysAddr);
++      writel((u32) virt_to_le32desc(&tx_ring[0]),
++             base + NvRegTxRingPhysAddr);
++
++      writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) +
++             ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT),
++             base + NvRegRingSizes);
++
++      /* 5) continue setup */
        np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10;
        np->duplex = 0;
++      writel(np->linkspeed, base + NvRegLinkSpeed);
        writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
--      writel(0, base + NvRegTxRxControl);
++      writel(np->desc_ver, base + NvRegTxRxControl);
        pci_push(base);
--      writel(NVREG_TXRXCTL_BIT1, base + NvRegTxRxControl);
--
++      writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl);
        reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31,
                  NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY,
                  NV_SETUP5_DELAYMAX,
                  "open: SetupReg5, Bit 31 remained off\n");
--      writel(0, base + NvRegUnknownSetupReg4);
--
--      /* 5) Find a suitable PHY */
--      writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed);
--      for (i = 1; i < 32; i++) {
--              int id1, id2;
--
--              id1 = mii_rw(nic, i, MII_PHYSID1, MII_READ);
--              if (id1 < 0)
--                      continue;
--              id2 = mii_rw(nic, i, MII_PHYSID2, MII_READ);
--              if (id2 < 0)
--                      continue;
--              dprintf(("open: Found PHY %04x:%04x at address %d.\n",
--                       id1, id2, i));
--              np->phyaddr = i;
--
--              update_linkspeed(nic);
--
--              break;
--      }
--      if (i == 32) {
--              printf("open: failing due to lack of suitable PHY.\n");
--              ret = -1;
--              goto out_drain;
--      }
  
++      writel(0, base + NvRegUnknownSetupReg4);
++//       writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
++      writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
++#if 0
        printf("%d-Mbs Link, %s-Duplex\n",
               np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100,
               np->duplex ? "Full" : "Half");
++#endif
++
        /* 6) continue setup */
--      writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD),
--             base + NvRegMisc1);
++      writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
        writel(readl(base + NvRegTransmitterStatus),
               base + NvRegTransmitterStatus);
        writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
        writel(readl(base + NvRegReceiverStatus),
               base + NvRegReceiverStatus);
  
--      /* FIXME: I cheated and used the calculator to get a random number */
--      i = 75963081;
++      /* Get a random number */
++      i = random();
        writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK),
               base + NvRegRandomSeed);
        writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);
        writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
        writel((np->
                phyaddr << NVREG_ADAPTCTL_PHYSHIFT) |
--             NVREG_ADAPTCTL_PHYVALID, base + NvRegAdapterControl);
++             NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING,
++             base + NvRegAdapterControl);
++      writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed);
        writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);
        writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);
  
--      /* 7) start packet processing */
--      writel((u32) virt_to_le32desc(&rx_ring[0]),
--             base + NvRegRxRingPhysAddr);
--      writel((u32) virt_to_le32desc(&tx_ring[0]),
--             base + NvRegTxRingPhysAddr);
--
--
--      writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) +
--             ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT),
--             base + NvRegRingSizes);
--
        i = readl(base + NvRegPowerState);
--      if ((i & NVREG_POWERSTATE_POWEREDUP) == 0) {
++      if ((i & NVREG_POWERSTATE_POWEREDUP) == 0)
                writel(NVREG_POWERSTATE_POWEREDUP | i,
                       base + NvRegPowerState);
--      }
++
        pci_push(base);
        udelay(10);
        writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID,
               base + NvRegPowerState);
--      writel(NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
  
        writel(0, base + NvRegIrqMask);
        pci_push(base);
--      writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
--      pci_push(base);
        writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
        writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
        pci_push(base);
               base + NvRegPacketFilterFlags);
  
        set_multicast(nic);
++      /* One manual link speed update: Interrupts are enabled, future link
++       * speed changes cause interrupts and are handled by nv_link_irq().
++       */
++      {
++              u32 miistat;
++              miistat = readl(base + NvRegMIIStatus);
++              writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
++              dprintf(("startup: got 0x%hX.\n", miistat));
++      }
++      ret = update_linkspeed(nic);
++
        //start_rx(nic);
        start_tx(nic);
  
--      if (!
--          (mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) &
--           BMSR_ANEGCOMPLETE)) {
++      if (ret) {
++              //Start Connection netif_carrier_on(dev);
++      } else {
                printf("no link during initialization.\n");
        }
  
--      udelay(10000);
--      out_drain:
        return ret;
  }
  
--//extern void hex_dump(const char *data, const unsigned int len);
--
++/* 
++ * extern void hex_dump(const char *data, const unsigned int len);
++*/
  /**************************************************************************
  POLL - Wait for a frame
  ***************************************************************************/
@@@ -793,26 -793,26 +1098,35 @@@ static int forcedeth_poll(struct nic *n
        /* nic->packet should contain data on return */
        /* nic->packetlen should contain length of data */
  
--      struct ring_desc *prd;
        int len;
        int i;
++      u32 Flags;
  
        i = np->cur_rx % RX_RING;
--      prd = &rx_ring[i];
  
--      if ( ! (prd->Flags & cpu_to_le16(NV_RX_DESCRIPTORVALID)) ) {
--        return 0;
++      Flags = le32_to_cpu(rx_ring[i].FlagLen);
++      len = nv_descr_getlength(&rx_ring[i], np->desc_ver);
++
++      if (Flags & NV_RX_AVAIL)
++              return 0;       /* still owned by hardware, */
++
++      if (np->desc_ver == DESC_VER_1) {
++              if (!(Flags & NV_RX_DESCRIPTORVALID))
++                      return 0;
++      } else {
++              if (!(Flags & NV_RX2_DESCRIPTORVALID))
++                      return 0;
        }
  
--      if ( ! retrieve ) return 1;
++      if (!retrieve)
++              return 1;
  
        /* got a valid packet - forward it to the network core */
--      len = cpu_to_le16(prd->Length);
        nic->packetlen = len;
--      //hex_dump(rxb + (i * RX_NIC_BUFSIZE), len);
--      memcpy(nic->packet, rxb +
--             (i * RX_NIC_BUFSIZE), nic->packetlen);
--
++      memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen);
++/*
++ *    hex_dump(rxb + (i * RX_NIC_BUFSIZE), len);
++*/
        wmb();
        np->cur_rx++;
        alloc_rx(nic);
@@@ -831,7 -831,7 +1145,6 @@@ static void forcedeth_transmit(struct n
        /* send the packet to destination */
        u8 *ptxb;
        u16 nstype;
--      //u16 status;
        u8 *base = (u8 *) BASE;
        int nr = np->next_tx % TX_RING;
  
                ptxb[s++] = '\0';
  
        tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb);
--      tx_ring[nr].Length = cpu_to_le16(s - 1);
  
        wmb();
--      tx_ring[nr].Flags = np->tx_flags;
++      tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags);
  
--      writel(NVREG_TXRXCTL_KICK, base + NvRegTxRxControl);
++      writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl);
        pci_push(base);
--      tx_ring[nr].Flags = np->tx_flags;
        np->next_tx++;
  }
  
@@@ -896,16 -896,16 +1207,17 @@@ static void forcedeth_disable ( struct 
  /**************************************************************************
  IRQ - Enable, Disable, or Force interrupts
  ***************************************************************************/
--static void forcedeth_irq(struct nic *nic __unused, irq_action_t action __unused)
++static void forcedeth_irq(struct nic *nic __unused,
++                        irq_action_t action __unused)
  {
--  switch ( action ) {
--  case DISABLE :
--    break;
--  case ENABLE :
--    break;
--  case FORCE :
--    break;
--  }
++      switch (action) {
++      case DISABLE:
++              break;
++      case ENABLE:
++              break;
++      case FORCE:
++              break;
++      }
  }
  
  static struct nic_operations forcedeth_operations = {
  
  };
  
--static struct pci_id forcedeth_nics[] = {
--      PCI_ROM(0x10de, 0x01C3, "nforce", "nForce Ethernet Controller"),
--      PCI_ROM(0x10de, 0x0066, "nforce2", "nForce2 Ethernet Controller"),
--      PCI_ROM(0x10de, 0x00D6, "nforce3", "nForce3 Ethernet Controller"),
--};
--
--PCI_DRIVER ( forcedeth_driver, forcedeth_nics, PCI_NO_CLASS );
--
  /**************************************************************************
  PROBE - Look for an adapter, this routine's visible to the outside
  ***************************************************************************/
@@@ -935,6 -935,6 +1239,7 @@@ static int forcedeth_probe ( struct ni
        unsigned long addr;
        int sz;
        u8 *base;
++      int i;
  
        if (pci->ioaddr == 0)
                return 0;
        BASE = (unsigned long) ioremap(addr, sz);
        if (!BASE)
                return 0;
++
++      /* handle different descriptor versions */
++      if (pci->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_1 ||
++          pci->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_2 ||
++          pci->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_3)
++              np->desc_ver = DESC_VER_1;
++      else
++              np->desc_ver = DESC_VER_2;
++
        //rx_ring[0] = rx_ring;
        //tx_ring[0] = tx_ring; 
  
  #endif
        printf("%s: MAC Address %!, ", pci->name, nic->node_addr);
  
--      np->tx_flags =
--          cpu_to_le16(NV_TX_LASTPACKET | NV_TX_LASTPACKET1 |
--                      NV_TX_VALID);
--      switch (pci->device_id) {
--      case 0x01C3:            // nforce
--              np->irqmask = NVREG_IRQMASK_WANTED_2;
--              np->irqmask |= NVREG_IRQ_TIMER;
--              break;
--      case 0x0066:            // nforce2
--              np->tx_flags |= cpu_to_le16(NV_TX_LASTPACKET1);
--              np->irqmask = NVREG_IRQMASK_WANTED_2;
--              np->irqmask |= NVREG_IRQ_TIMER;
--              break;
--      case 0x00D6:            // nforce3
--              np->tx_flags |= cpu_to_le16(NV_TX_LASTPACKET1);
--              np->irqmask = NVREG_IRQMASK_WANTED_2;
--              np->irqmask |= NVREG_IRQ_TIMER;
--
--      }
++      /* disable WOL */
++      writel(0, base + NvRegWakeUpFlags);
++      np->wolenabled = 0;
++      
++      if (np->desc_ver == DESC_VER_1) {
++              np->tx_flags = NV_TX_LASTPACKET | NV_TX_VALID;
++      } else {
++              np->tx_flags = NV_TX2_LASTPACKET | NV_TX2_VALID;
++      }
++
++      switch (pci->device_id) {
++      case 0x01C3:            // nforce
++              // DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
++              np->irqmask = NVREG_IRQMASK_WANTED_2 | NVREG_IRQ_TIMER;
++              //              np->need_linktimer = 1;
++              //              np->link_timeout = jiffies + LINK_TIMEOUT;
++              break;
++      case 0x0066:
++              /* Fall Through */
++      case 0x00D6:
++              // DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER
++              np->irqmask = NVREG_IRQMASK_WANTED_2;
++              np->irqmask |= NVREG_IRQ_TIMER;
++              //              np->need_linktimer = 1;
++              //              np->link_timeout = jiffies + LINK_TIMEOUT;
++              if (np->desc_ver == DESC_VER_1)
++                      np->tx_flags |= NV_TX_LASTPACKET1;
++              else
++                      np->tx_flags |= NV_TX2_LASTPACKET1;
++              break;
++      case 0x0086:
++              /* Fall Through */
++      case 0x008c:
++              /* Fall Through */
++      case 0x00e6:
++              /* Fall Through */
++      case 0x00df:
++              /* Fall Through */
++      case 0x0056:
++              /* Fall Through */
++      case 0x0057:
++              /* Fall Through */
++      case 0x0037:
++              /* Fall Through */
++      case 0x0038:
++              //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ
++              np->irqmask = NVREG_IRQMASK_WANTED_2;
++              np->irqmask |= NVREG_IRQ_TIMER;
++              //              np->need_linktimer = 1;
++              //              np->link_timeout = jiffies + LINK_TIMEOUT;
++              if (np->desc_ver == DESC_VER_1)
++                      np->tx_flags |= NV_TX_LASTPACKET1;
++              else
++                      np->tx_flags |= NV_TX2_LASTPACKET1;
++              break;
++      default:
++              printf
++                      ("Your card was undefined in this driver.  Review driver_data in Linux driver and send a patch\n");
++      }
++      
++      /* find a suitable phy */
++      for (i = 1; i < 32; i++) {
++              int id1, id2;
++              id1 = mii_rw(nic, i, MII_PHYSID1, MII_READ);
++              if (id1 < 0 || id1 == 0xffff)
++                      continue;
++              id2 = mii_rw(nic, i, MII_PHYSID2, MII_READ);
++              if (id2 < 0 || id2 == 0xffff)
++                      continue;
++              id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
++              id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
++              dprintf
++                      (("%s: open: Found PHY %hX:%hX at address %d.\n",
++                        pci->name, id1, id2, i));
++              np->phyaddr = i;
++              np->phy_oui = id1 | id2;
++              break;
++      }
++      if (i == 32) {
++              /* PHY in isolate mode? No phy attached and user wants to
++               * test loopback? Very odd, but can be correct.
++               */
++              printf
++                      ("%s: open: Could not find a valid PHY.\n", pci->name);
++      }
++      
++      if (i != 32) {
++              /* reset it */
++              phy_init(nic);
++      }
++      
        dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n",
                 pci->name, pci->vendor, pci->dev_id, pci->name));
++      if(!forcedeth_reset(nic)) return 0; // no valid link
  
--      forcedeth_reset(nic);
--//      if (board_found && valid_link)
        /* point to NIC specific routines */
        nic->nic_op     = &forcedeth_operations;
        return 1;
--//      }
--      /* else */
  }
  
++static struct pci_id forcedeth_nics[] = {
++PCI_ROM(0x10de, 0x01C3, "nforce", "nForce NVENET_1 Ethernet Controller"),
++PCI_ROM(0x10de, 0x0066, "nforce2", "nForce NVENET_2 Ethernet Controller"),
++PCI_ROM(0x10de, 0x00D6, "nforce3", "nForce NVENET_3 Ethernet Controller"),
++PCI_ROM(0x10de, 0x0086, "nforce4", "nForce NVENET_4 Ethernet Controller"),
++PCI_ROM(0x10de, 0x008c, "nforce5", "nForce NVENET_5 Ethernet Controller"),
++PCI_ROM(0x10de, 0x00e6, "nforce6", "nForce NVENET_6 Ethernet Controller"),
++PCI_ROM(0x10de, 0x00df, "nforce7", "nForce NVENET_7 Ethernet Controller"),
++PCI_ROM(0x10de, 0x0056, "nforce8", "nForce NVENET_8 Ethernet Controller"),
++PCI_ROM(0x10de, 0x0057, "nforce9", "nForce NVENET_9 Ethernet Controller"),
++PCI_ROM(0x10de, 0x0037, "nforce10", "nForce NVENET_10 Ethernet Controller"),
++PCI_ROM(0x10de, 0x0038, "nforce11", "nForce NVENET_11 Ethernet Controller"),
++};
++
++PCI_DRIVER ( forcedeth_driver, forcedeth_nics, PCI_NO_CLASS );
++
  DRIVER ( "forcedeth", nic_driver, pci_driver, forcedeth_driver,
         forcedeth_probe, forcedeth_disable );
  /* to get the PCI support functions, if this is a PCI NIC */
  #include "pci.h"
  
--typedef unsigned char u8;
--typedef signed char s8;
--typedef unsigned short u16;
--typedef signed short s16;
--typedef unsigned int u32;
--typedef signed int s32;
--
  /* 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))
  
  #define NUM_RX_DESC    4              /* Number of Rx descriptor registers. */
  
--typedef uint8_t    u8;
--typedef int8_t     s8;
--typedef uint16_t   u16;
--typedef int16_t    s16;
--typedef uint32_t   u32;
--typedef int32_t    s32;
--
  /* helpful macroes if on a big_endian machine for changing byte order.
     not strictly needed on Intel */
  #define get_unaligned(ptr) (*(ptr))
  #define dprintf(x)
  #endif
  
--typedef unsigned char u8;
--typedef signed char s8;
--typedef unsigned short u16;
--typedef signed short s16;
--typedef unsigned int u32;
--typedef signed int s32;
--
  #define HZ 100
  
  /* Condensed operations for readability. */
  #define drv_version "v1.3"
  #define drv_date "03-29-2004"
  
--typedef unsigned char u8;
--typedef signed char s8;
--typedef unsigned short u16;
--typedef signed short s16;
--typedef unsigned int u32;
--typedef signed int s32;
--
  static u32 ioaddr;            /* Globally used for the card's io address */
  static struct nic_operations pcnet32_operations;
  static struct pci_driver pcnet32_driver;
  #define drv_version "v1.6"
  #define drv_date "03-27-2004"
  
--typedef unsigned char u8;
--typedef signed char s8;
--typedef unsigned short u16;
--typedef signed short s16;
--typedef unsigned int u32;
--typedef signed int s32;
--
  #define HZ 1000
  
  static u32 ioaddr;
@@@ -363,13 -363,13 +363,6 @@@ enum sis630_revision_id 
  
  #define NUM_RX_DESC     4              /* Number of Rx descriptor registers. */
  
--typedef unsigned char  u8;
--typedef   signed char  s8;
--typedef unsigned short u16;
--typedef   signed short s16;
--typedef unsigned int   u32;
--typedef   signed int   s32;
--
  /* Time in ticks before concluding the transmitter is hung. */
  #define TX_TIMEOUT       (4*TICKS_PER_SEC)
  
  #define drv_version "v1.12"
  #define drv_date "2004-03-21"
  
--typedef unsigned char u8;
--typedef signed char s8;
--typedef unsigned short u16;
--typedef signed short s16;
--typedef unsigned int u32;
--typedef signed int s32;
--
  #define HZ 100
  
  /* Condensed operations for readability. */
@@@ -9,6 -9,6 +9,7 @@@
  /* 11-13-2003 timlegge        Fix Issue with NetGear GA302T 
   * 11-18-2003   ebiederm        Generalize NetGear Fix to what the code was supposed to be.
   * 01-06-2005   Alf (Frederic Olivie) Add Dell bcm 5751 (0x1677) support
++ * 04-15-2005   Martin Vogt Add Fujitsu Siemens Computer (FSC) 0x1734 bcm 5751 0x105d support
   */
  
  #include "etherboot.h"
@@@ -2413,6 -2413,6 +2414,9 @@@ static struct subsys_tbl_ent subsys_id_
        { PCI_VENDOR_ID_DELL, 0x0109, PHY_ID_BCM5411 }, /* MERLOT */
        { PCI_VENDOR_ID_DELL, 0x010a, PHY_ID_BCM5411 }, /* SLIM_MERLOT */
        { PCI_VENDOR_ID_DELL, 0x0179, PHY_ID_BCM5751 }, /* EtherXpress */
++      
++      /* Fujitsu Siemens Computer */
++      { PCI_VENDOR_ID_FSC, 0x105d, PHY_ID_BCM5751 }, /* Futro C200 */ 
  
        /* Compaq boards. */
        { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
@@@ -2156,7 -2156,7 +2156,7 @@@ struct tg3 
        ((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \
         (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
         (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
--       (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5751 || \
++       (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || (X) == PHY_ID_BCM5751 || \
         (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES)
  
        unsigned long                   regs;
  * Indent Style: indent -kr -i8
  ***************************************************************************/
  
--/*
--#include <asm/io.h>
--#include <asm/types.h>
--#include <linux/netdevice.h>
--*/
--
--typedef unsigned char u8;
--typedef signed char s8;
--typedef unsigned short u16;
--typedef signed short s16;
--typedef unsigned int u32;
--typedef signed int s32;
--      /*****************************************************************
--       * TLan Definitions
--       *
--       ****************************************************************/
++/*****************************************************************
++* TLan Definitions
++*
++****************************************************************/
  
  #define FALSE                 0
  #define TRUE                  1
@@@ -48,6 -48,6 +48,8 @@@
  /*********************************************************************/
  
  /*
++  08 Feb 2005  Ramesh Chander chhabaramesh at yahoo.co.in added table entries
++               for SGThomson STE10/100A
    07 Sep 2003  timlegge       Multicast Support Added
    11 Apr 2001  mdc     [patch to etherboot 4.7.24]
       Major rewrite to include Linux tulip driver media detection
@@@ -118,13 -118,13 +120,6 @@@ static int tulip_debug = 2
  
  #define TX_TIME_OUT       2*TICKS_PER_SEC
  
--typedef uint8_t    u8;
--typedef  int8_t    s8;
--typedef uint16_t   u16;
--typedef  int16_t   s16;
--typedef uint32_t   u32;
--typedef  int32_t   s32;
--
  /* helpful macros if on a big_endian machine for changing byte order.
     not strictly needed on Intel */
  #define get_unaligned(ptr) (*(ptr))
@@@ -157,7 -157,7 +152,7 @@@ static const char * const medianame[32
  enum tulip_chips {
      DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
      LC82C168, MX98713, MX98715, MX98725, AX88141, AX88140, PNIC2, COMET,
--    COMPEX9881, I21145, XIRCOM
++    COMPEX9881, I21145, XIRCOM, SGThomson,    /*Ramesh Chander*/
  };
  
  enum pci_id_flags_bits {
@@@ -233,6 -233,6 +228,8 @@@ static const struct pci_id_info pci_id_
        TULIP_IOTYPE, 256, MX98715 },
      { "3Com 3cSOHO100B-TX (ADMtek Centuar)", { 0x930010b7, 0xffffffff, 0, 0, 0, 0 },
        TULIP_IOTYPE, TULIP_SIZE, COMET },
++    { "SG Thomson STE10/100A", { 0x2774104a, 0xffffffff, 0, 0, 0, 0 },
++      TULIP_IOTYPE, 256, COMET },     /*Ramesh Chander*/
      { 0, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 },
  };
  
@@@ -268,6 -268,6 +265,7 @@@ static struct tulip_chip_table 
        | HAS_PWRDWN | HAS_NWAY },
      { "Xircom tulip work-alike", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII 
        | HAS_PWRDWN | HAS_NWAY },
++    { "SGThomson STE10/100A", HAS_MII | MC_HASH_ONLY },       /*Ramesh Chander*/   
      { 0, 0 },
  };
  
@@@ -2068,7 -2068,7 +2066,7 @@@ PCI_ROM(0x125b, 0x1400, "ax88140",     
  PCI_ROM(0x11f6, 0x9881, "rl100tx",     "Compex RL100-TX"),
  PCI_ROM(0x115d, 0x0003, "xircomtulip", "Xircom Tulip"),
  PCI_ROM(0x104a, 0x0981, "tulip-0981",  "Tulip 0x104a 0x0981"),
--PCI_ROM(0x104a, 0x2774, "tulip-2774",  "Tulip 0x104a 0x2774"),
++PCI_ROM(0x104a, 0x2774, "SGThomson-STE10100A", "Tulip 0x104a 0x2774"),        /*Modified by Ramesh Chander*/
  PCI_ROM(0x1113, 0x9511, "tulip-9511",  "Tulip 0x1113 0x9511"),
  PCI_ROM(0x1186, 0x1561, "tulip-1561",  "Tulip 0x1186 0x1561"),
  PCI_ROM(0x1259, 0xa120, "tulip-a120",  "Tulip 0x1259 0xa120"),
  
  static const char *w89c840_version = "driver Version 0.94 - December 12, 2003";
  
--typedef unsigned char  u8;
--typedef   signed char  s8;
--typedef unsigned short u16;
--typedef   signed short s16;
--typedef unsigned int   u32;
--typedef   signed int   s32;
--
  /* Linux support functions */
  #define virt_to_le32desc(addr)  virt_to_bus(addr)
  #define le32desc_to_virt(addr)  bus_to_virt(addr)
  #define PCI_VENDOR_ID_MORETON         0x15aa
  #define PCI_VENDOR_ID_ZOLTRIX         0x15b0
  #define PCI_VENDOR_ID_PDC             0x15e9
++#define PCI_VENDOR_ID_FSC             0x1734
  #define PCI_VENDOR_ID_SYMPHONY                0x1c1c
  #define PCI_VENDOR_ID_TEKRAM          0x1de1
  #define PCI_VENDOR_ID_3DLABS          0x3d3d
@@@ -157,7 -157,7 +157,7 @@@ sub makerom () 
        # If PXE image, just fill the length field and write it out
        if ($opts{'x'}) {
                substr($rom, 2, 1) = chr((length($rom) + 511) / 512);
--              &writerom($ARGV[0], \$rom);
++              writerom($ARGV[0], \$rom);
                return;
        }
        # Size specified with -s overrides value in 3rd byte in image
                        $romsize = ($filesize + 511) & ~511
                }
        } else {
--              $romsize = &getromsize(\$rom);
++              $romsize = getromsize(\$rom);
                # 0 put there by *loader.S means makerom should pick the size
                if ($romsize == 0) {
                        # Shrink romsize down to the smallest power of two that will do
        }
        substr($rom, 2, 1) = chr(($romsize / 512) % 256);
        print "ROM size is $romsize\n" if $opts{'v'};
--      my $identoffset = &addident(\$rom);
--      &pcipnpheaders(\$rom, $identoffset);
--      &undiheaders(\$rom);
++      # set the product string only if we don't have one yet
++      my $pnp_hdr_offset = unpack('v', substr($rom, PNP_PTR_LOC, 2));
++      my $identoffset = substr($rom, $pnp_hdr_offset+PNP_DEVICE_OFF, 2) eq "\0\0" ? addident(\$rom) : undef;
++      pcipnpheaders(\$rom, $identoffset);
++      undiheaders(\$rom);
        # 3c503 requires last two bytes to be 0x80
        substr($rom, MINROMSIZE-2, 2) = "\x80\x80"
                if ($opts{'3'} and $romsize == MINROMSIZE);
--      &checksum(\$rom);
--      &writerom($ARGV[0], \$rom);
++      checksum(\$rom);
++      writerom($ARGV[0], \$rom);
  }
  
  sub modrom () {
        close(R);
        defined($filesize) and $filesize >= 3 or die "Cannot get first 3 bytes of file\n";
        print "$filesize bytes read\n" if $opts{'v'};
--      &pcipnpheaders(\$rom);
--      &undiheaders(\$rom);
--      &checksum(\$rom);
--      &writerom($ARGV[0], \$rom);
++      pcipnpheaders(\$rom, undef);
++      undiheaders(\$rom);
++      checksum(\$rom);
++      writerom($ARGV[0], \$rom);
  }
  
  # Main routine. See how we were called and behave accordingly
  if ($0 =~ m:modrom(\.pl)?$:) {
--      &modrom();
++      modrom();
  } else {
--      &makerom();
++      makerom();
  }
  exit(0);