Imported from Etherboot 5.4 tree
authorMichael Brown <mcb30@etherboot.org>
Thu, 19 May 2005 16:51:32 +0000 (16:51 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 19 May 2005 16:51:32 +0000 (16:51 +0000)
58 files changed:
VERSION
contrib/bin2intelhex/bin2intelhex.c
contrib/initrd/ChangeLog
src/Makefile
src/Makefile.housekeeping
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 [deleted file]
src/arch/armnommu/include/stdint.h
src/arch/e1/include/stdint.h
src/arch/i386/Makefile
src/arch/i386/core/freebsd_loader.c
src/arch/i386/image/nbi.c
src/arch/i386/include/bochs.h
src/arch/i386/include/stdint.h
src/arch/i386/include/virtaddr.h
src/arch/ia64/include/stdint.h
src/config.h
src/core/buffer.c
src/core/config.c
src/core/errno.c [new file with mode: 0644]
src/core/main.c
src/core/pxe_errors.c [new file with mode: 0644]
src/core/vsprintf.c
src/doxygen.cfg [new file with mode: 0644]
src/drivers/bus/isapnp.c
src/drivers/net/3c515.c
src/drivers/net/amd8111e.c [new file with mode: 0644]
src/drivers/net/amd8111e.h [new file with mode: 0644]
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/buffer.h
src/include/compiler.h
src/include/errno.h [new file with mode: 0644]
src/include/etherboot.h
src/include/pci_ids.h
src/include/pxe.h
src/include/tables.h
src/proto/fsp.c [new file with mode: 0644]
src/util/makerom.pl

diff --git a/VERSION b/VERSION
index 85570a8..3328f15 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-5.4.0 2005-04-01
+5.5.0 2005-05-17
index 92c2728..75b88c1 100644 (file)
@@ -24,8 +24,8 @@
 /*
  * $Id$
  * $Log$
- * Revision 1.1.1.1  2005/05/17 16:45:06  mcb30
- * Import from Etherboot 5.4
+ * Revision 1.1  2005/05/17 16:45:06  mcb30
+ * Initial revision
  *
  * Revision 1.9  1997/12/14 05:14:54  install
  * - some documentation....
index 74d3ce1..94f8f6a 100644 (file)
@@ -3,8 +3,8 @@ mkinitrd-net ChangeLog
 Last Modified: Fri Jul 26 23:08:28 2002
 
 $Log$
-Revision 1.1.1.1  2005/05/17 16:45:02  mcb30
-Import from Etherboot 5.4
+Revision 1.1  2005/05/17 16:45:02  mcb30
+Initial revision
 
 Revision 1.1  2002/11/06 06:31:06  ken_yap
 Contributed by Michael Brown.
index fa7b3f3..2393eec 100644 (file)
@@ -79,6 +79,7 @@ MKCONFIG      ?= $(PERL) ./util/mkconfig.pl
 SYMCHECK       ?= $(PERL) ./util/symcheck.pl
 SORTOBJDUMP    ?= $(PERL) ./util/sortobjdump.pl
 NRV2B          ?= ./util/nrv2b
+DOXYGEN                ?= doxygen
 
 # Location to place generated files
 #
@@ -130,7 +131,7 @@ DEBUG_TARGETS       += dbg2.o dbg.o c s
 #
 SRCDIRS                += core
 SRCDIRS                += proto
-SRCDIRS                += image
+#SRCDIRS               += image
 SRCDIRS                += drivers/bus
 SRCDIRS                += drivers/net
 #SRCDIRS               += drivers/disk 
index 1f06d69..2a95032 100644 (file)
@@ -10,8 +10,8 @@ CLEANUP       := $(BIN)/*.* # *.* to avoid catching the "CVS" directory
 # Version number calculations 
 #
 VERSION_MAJOR  = 5
-VERSION_MINOR  = 3
-VERSION_PATCH  = 14
+VERSION_MINOR  = 5
+VERSION_PATCH  = 0
 EXTRAVERSION   =       
 MM_VERSION     = $(VERSION_MAJOR).$(VERSION_MINOR)
 VERSION                = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION)
@@ -422,6 +422,31 @@ $(BIN)/%.rebuild :
        rm -f $(BIN)/$*
        $(MAKE) $(MAKEFLAGS) $(BIN)/$*
 
+# Documentation
+#
+$(BIN)/doxygen.cfg : doxygen.cfg $(MAKEDEPS)
+       $(PERL) -pe 's{\@SRCDIRS\@}{$(SRCDIRS)}; ' \
+               -e  's{\@BIN\@}{$(BIN)}; ' \
+               -e  's{\@ARCH\@}{$(ARCH)}; ' \
+               $< > $@
+
+$(BIN)/doc : $(BIN)/doxygen.cfg
+       $(DOXYGEN) $<
+
+.PHONY : $(BIN)/doc
+
+VERYCLEANUP    += $(BIN)/doc
+
+doc : $(BIN)/doc
+
+docview :
+       @[ -f $(BIN)/doc/html/index.html ] || $(MAKE) $(BIN)/doc
+       @if [ -n "$$BROWSER" ] ; then \
+               ( $$BROWSER $(BIN)/doc/html/index.html & ) ; \
+       else \
+               echo "Documentation index in $(BIN)/doc/html/index.html" ; \
+       fi
+
 # Clean-up
 #
 clean :
index 4c220cd..5794203 100644 (file)
@@ -17,6 +17,12 @@ CFLAGS+= -DRAWADDR=0x40100000
 # 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'"
index 3ae98d4..0fb6e79 100644 (file)
@@ -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 @@ void serial_putc(int ch)
 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;
 }
 
 /*
index 81bc84c..bdf2f0e 100644 (file)
@@ -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 @@ P2001 NIC driver for Etherboot
 #include "isa.h"
 
 #include "hardware.h"
-#include "lxt971a.h"
+#include "mii.h"
 #include "timer.h"
 
 
@@ -31,25 +31,20 @@ static unsigned char MAC_HW_ADDR[6]={MAC_HW_ADDR_DRV};
 #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 +55,107 @@ static void         p2001_eth_init      ();
 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 +230,11 @@ static int p2001_eth_poll(struct nic *nic, int retrieve)
 }
 
 
+
 /**************************************************************************
-TRANSMIT - Transmit a frame
-***************************************************************************/
+ * TRANSMIT - Transmit a frame
+ **************************************************************************/
+
 /* Function: p2001_eth_transmit
  *
  * Description: transmits a packet and waits for completion or timeout.
@@ -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 */
@@ -281,12 +282,12 @@ static void p2001_eth_transmit(
 
        /* 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);
@@ -294,9 +295,11 @@ static void p2001_eth_transmit(
 }
 
 
+
 /**************************************************************************
-IRQ - Enable, Disable or Force Interrupts
-***************************************************************************/
+ * IRQ - Enable, Disable or Force Interrupts
+ **************************************************************************/
+
 /* Function: p2001_eth_irq
  *
  * Description: Enable, Disable, or Force, interrupts
@@ -321,9 +324,11 @@ p2001_eth_irq(struct nic *nic __unused, irq_action_t action __unused)
 }
 
 
+
 /**************************************************************************
-INIT - Initialize device
-***************************************************************************/
+ * INIT - Initialize device
+ **************************************************************************/
+
 /* Function: p2001_init
  *
  * Description: resets the ethernet controller chip and various
@@ -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 */
@@ -353,7 +375,7 @@ static void p2001_eth_init()
 //     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;
 
@@ -371,9 +393,12 @@ static void p2001_eth_init()
        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 */
@@ -384,9 +409,10 @@ static void p2001_eth_init()
 }
 
 
+
 /**************************************************************************
-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 */
@@ -408,40 +434,52 @@ static void p2001_eth_disable(struct dev *dev __unused)
 }
 
 
+
 /**************************************************************************
-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");
@@ -449,49 +487,79 @@ failed:
 }
 
 
+
+/**************************************************************************
+ * 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);
 
@@ -507,7 +575,6 @@ static int p2001_eth_probe(struct dev *dev, unsigned short *probe_addrs __unused
 
                                /* Report the ISA pnp id of the board */
                                dev->devid.vendor_id = htons(GENERIC_ISAPNP_VENDOR);
-                               dev->devid.vendor_id = htons(0x1234);
                                return 1;
                        }
                }
index 203b78b..49264d6 100644 (file)
@@ -100,10 +100,7 @@ typedef struct {                                   // 0x00130000U
 
 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
@@ -113,10 +110,7 @@ typedef union {                                            // 0x00140000U
        } 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 +162,8 @@ typedef struct {                           // 0x0018_000U _=0,1,2,3
        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 --git a/src/arch/armnommu/include/lxt971a.h b/src/arch/armnommu/include/lxt971a.h
deleted file mode 100644 (file)
index 16314ec..0000000
+++ /dev/null
@@ -1,30 +0,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 */
index 3f5dc3f..1cb0085 100644 (file)
@@ -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 */
index 8a7ad97..505cc37 100644 (file)
@@ -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 */
index 9f207ea..0c258ae 100644 (file)
@@ -1,7 +1,7 @@
 # i386-specific directories containing source files
 #
 SRCDIRS                += arch/i386/core arch/i386/transitions arch/i386/prefix
-SRCDIRS                += arch/i386/firmware/pcbios arch/i386/firmware/linuxbios
+SRCDIRS                += arch/i386/firmware/pcbios
 SRCDIRS                += arch/i386/image
 SRCDIRS                += arch/i386/drivers/bus
 SRCDIRS                += arch/i386/drivers/net
index 4e820e8..464f6d9 100644 (file)
@@ -216,7 +216,7 @@ static int elf_freebsd_debug_loader(unsigned int offset)
                                        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);
@@ -244,7 +244,7 @@ static int elf_freebsd_debug_loader(unsigned int offset)
                                        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 @@ static void elf_freebsd_boot(unsigned long entry)
                /* 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... */
index f361aa9..f5d9e38 100644 (file)
@@ -4,22 +4,44 @@
 #include "gateA20.h"
 #include "osloader.h"
 #include "etherboot.h"
+#include "errno.h"
 
-/* An NBI image header */
+/** @file
+ *
+ * NBI image format.
+ *
+ * The Net Boot Image format is defined by the "Draft Net Boot Image
+ * Proposal 0.3" by Jamie Honan, Gero Kuhlmann and Ken Yap.  It is now
+ * considered to be a legacy format, but it still included because a
+ * large amount of software (e.g. nymph, LTSP) makes use of NBI files.
+ *
+ * Etherboot does not implement the INT 78 callback interface
+ * described by the NBI specification.  For a callback interface on
+ * x86 architecture, use PXE.
+ *
+ */
+
+/**
+ * An NBI image header
+ *
+ * Note that the length field uses a peculiar encoding; use the
+ * NBI_LENGTH() macro to decode the actual header length.
+ *
+ */
 struct imgheader {
-       unsigned long magic;
+       unsigned long magic;            /**< Magic number (NBI_MAGIC) */
        union {
-               unsigned char length;
-               unsigned long flags;
+               unsigned char length;   /**< Nibble-coded header length */
+               unsigned long flags;    /**< Image flags */
        };
-       segoff_t location;
+       segoff_t location;              /**< 16-bit seg:off header location */
        union {
-               segoff_t segoff;
-               unsigned long linear;
+               segoff_t segoff;        /**< 16-bit seg:off entry point */
+               unsigned long linear;   /**< 32-bit entry point */
        } execaddr;
 } __attribute__ (( packed ));
 
-/* NBI magic number */
+/** NBI magic number */
 #define NBI_MAGIC 0x1B031336UL
 
 /* Interpretation of the "length" fields */
@@ -31,18 +53,24 @@ struct imgheader {
 #define        NBI_PROGRAM_RETURNS(flags)      ( (flags) & ( 1 << 8 ) )
 #define        NBI_LINEAR_EXEC_ADDR(flags)     ( (flags) & ( 1 << 31 ) )
 
-/* NBI header length */
+/** NBI header length */
 #define NBI_HEADER_LENGTH      512
 
-/* An NBI segment header */
+/**
+ * An NBI segment header
+ *
+ * Note that the length field uses a peculiar encoding; use the
+ * NBI_LENGTH() macro to decode the actual header length.
+ *
+ */
 struct segheader {
-       unsigned char length;
-       unsigned char vendortag;
+       unsigned char length;           /**< Nibble-coded header length */
+       unsigned char vendortag;        /**< Vendor-defined private tag */
        unsigned char reserved;
-       unsigned char flags;
-       unsigned long loadaddr;
-       unsigned long imglength;
-       unsigned long memlength;
+       unsigned char flags;            /**< Segment flags */
+       unsigned long loadaddr;         /**< Load address */
+       unsigned long imglength;        /**< Segment length in NBI file */
+       unsigned long memlength;        /**< Segment length in memory */
 };
 
 /* Interpretation of the "flags" fields */
@@ -53,28 +81,41 @@ struct segheader {
 #define NBI_LOADADDR_BEFORE            0x03
 #define NBI_LAST_SEGHEADER(flags)      ( (flags) & ( 1 << 2 ) )
 
-/* Info passed to NBI image */
+/** Info passed to NBI image */
 static struct ebinfo loaderinfo = {
        VERSION_MAJOR, VERSION_MINOR,
        0
 };
 
-/*
+/**
  * Determine whether or not this is a valid NBI image
  *
+ * @v start            Address of the image
+ * @v len              Length of the image
+ * @v context          NBI image context
+ * @ret        True            Image is a valid NBI image
+ * @ret        False           Image is not a valid NBI image
+ * @err        EBADIMG         Image is not a valid NBI image
+ * 
+ * "context" is filled in with a context pointer suitable for passing to
+ * nbi_load() and nbi_boot().
+ *
  */
 static int nbi_probe ( physaddr_t start, off_t len, void **context ) {
        static struct imgheader imgheader;
 
        if ( (unsigned)len < sizeof ( imgheader ) ) {
                DBG ( "NBI image too small\n" );
+               errno = EBADIMG;
                return 0;
        }
 
        copy_from_phys ( &imgheader, start, sizeof ( imgheader ) );
 
-       if ( imgheader.magic != NBI_MAGIC )
+       if ( imgheader.magic != NBI_MAGIC ) {
+               errno = EBADIMG;
                return 0;
+       }
 
        /* Record image context */
        DBG ( "NBI found valid image\n" );
@@ -82,9 +123,17 @@ static int nbi_probe ( physaddr_t start, off_t len, void **context ) {
        return 1;
 }
 
-/*
+/**
  * Prepare a segment for an NBI image
  *
+ * @v dest             Address of segment
+ * @v imglen           Length of initialised-data portion of the segment
+ * @v memlen           Total length of the segment
+ * @v src              Source for initialised data
+ * @ret True           Segment can be used
+ * @ret False          Segment cannot be used
+ * @err other          As returned by prep_segment()
+ *
  */
 static int nbi_prepare_segment ( physaddr_t dest, off_t imglen, off_t memlen,
                                 physaddr_t src __unused ) {
@@ -93,9 +142,15 @@ static int nbi_prepare_segment ( physaddr_t dest, off_t imglen, off_t memlen,
        return prep_segment ( dest, dest + imglen, dest + memlen );
 }
 
-/*
+/**
  * Load a segment for an NBI image
  *
+ * @v dest             Address of segment
+ * @v imglen           Length of initialised-data portion of the segment
+ * @v memlen           Total length of the segment
+ * @v src              Source for initialised data
+ * @ret True           Always
+ *
  */
 static int nbi_load_segment ( physaddr_t dest, off_t imglen,
                              off_t memlen __unused, physaddr_t src ) {
@@ -104,9 +159,18 @@ static int nbi_load_segment ( physaddr_t dest, off_t imglen,
        return 1;
 }
 
-/*
+/**
  * Process segments of an NBI image
  *
+ * @v start            Address of the image
+ * @v len              Length of the image
+ * @v imgheader                Image header information
+ * @v process          Function to call for each segment
+ * @ret True           All segments were processed successfully
+ * @ret False          An error occurred processing a segment
+ * @err EBADIMG                Image is not a valid NBI image
+ * @err other          As returned by the "process" function
+ *
  */
 static int nbi_process_segments ( physaddr_t start, off_t len,
                                  struct imgheader *imgheader,
@@ -136,6 +200,7 @@ static int nbi_process_segments ( physaddr_t start, off_t len,
                if ( sh.length == 0 ) {
                        /* Avoid infinite loop? */
                        DBG ( "NBI invalid segheader length 0\n" );
+                       errno = EBADIMG;
                        return 0;
                }
                
@@ -159,8 +224,8 @@ static int nbi_process_segments ( physaddr_t start, off_t len,
                                - sh.loadaddr;
                        break;
                default:
-                       DBG ( "NBI can't count up to three\n" );
-                       return 0;
+                       /* Cannot be reached */
+                       DBG ( "NBI can't count up to three!\n" );
                }
 
                /* Process this segment */
@@ -175,6 +240,7 @@ static int nbi_process_segments ( physaddr_t start, off_t len,
                sh_off += NBI_LENGTH ( sh.length );
                if ( sh_off >= NBI_HEADER_LENGTH ) {
                        DBG ( "NBI header overflow\n" );
+                       errno = EBADIMG;
                        return 0;
                }
 
@@ -183,22 +249,35 @@ static int nbi_process_segments ( physaddr_t start, off_t len,
        if ( offset != len ) {
                DBG ( "NBI length mismatch (file %d, metadata %d)\n",
                      len, offset );
+               errno = EBADIMG;
                return 0;
        }
 
        return 1;
 }
 
-/*
+/**
  * Load an NBI image into memory
  *
+ * @v start            Address of image
+ * @v len              Length of image
+ * @v context          NBI context (as returned by nbi_probe())
+ * @ret True           Image loaded into memory
+ * @ret False          Image not loaded into memory
+ * @err EBADIMG                Image is not a valid NBI image
+ * @err other          As returned by nbi_process_segments()
+ * @err other          As returned by nbi_prepare_segment()
+ * @err other          As returned by nbi_load_segment()
+ *
  */
 static int nbi_load ( physaddr_t start, off_t len, void *context ) {
        struct imgheader *imgheader = context;
 
        /* If we don't have enough data give up */
-       if ( len < NBI_HEADER_LENGTH )
+       if ( len < NBI_HEADER_LENGTH ) {
+               errno = EBADIMG;
                return 0;
+       }
        
        DBG ( "NBI placing header at %hx:%hx\n",
              imgheader->location.segment, imgheader->location.offset );
@@ -220,9 +299,14 @@ static int nbi_load ( physaddr_t start, off_t len, void *context ) {
        return 1;
 }
 
-/*
+/**
  * Boot a 16-bit NBI image
  *
+ * @v imgheader                Image header information
+ * @ret Never          NBI program booted successfully
+ * @ret False          NBI program returned
+ * @err EIMGRET                NBI program returned
+ *
  */
 static int nbi_boot16 ( struct imgheader *imgheader ) {
        uint16_t basemem_bootp;
@@ -256,12 +340,23 @@ static int nbi_boot16 ( struct imgheader *imgheader ) {
                    CLOBBER ( "eax", "ecx", "edx", "ebp" ) );
        BASEMEM_PARAMETER_DONE ( bootp_data );
        
+       errno = EIMGRET;
        return 0;
 }
 
-/*
+/**
  * Boot a 32-bit NBI image
  *
+ * @v imgheader                Image header information
+ * @ret False          NBI program should not have returned
+ * @ret other          As returned by NBI program
+ * @err EIMGRET                NBI program should not have returned
+ *
+ * To distinguish between the case of an NBI program returning false,
+ * and an NBI program that should not have returned, check errno.
+ * errno will be set to EIMGRET only if the NBI program should not
+ * have returned.
+ *
  */
 static int nbi_boot32 ( struct imgheader *imgheader ) {
        int rc = 0;
@@ -270,6 +365,7 @@ static int nbi_boot32 ( struct imgheader *imgheader ) {
              imgheader->execaddr.linear );
 
        /* no gateA20_unset for PM call */
+       errno = ENOERR;
        rc = xstart32 ( imgheader->execaddr.linear,
                        virt_to_phys ( &loaderinfo ),
                        ( ( imgheader->location.segment << 4 ) +
@@ -278,15 +374,24 @@ static int nbi_boot32 ( struct imgheader *imgheader ) {
        printf ( "Secondary program returned %d\n", rc );
        if ( ! NBI_PROGRAM_RETURNS ( imgheader->flags ) ) {
                /* We shouldn't have returned */
+               errno = EIMGRET;
                rc = 0;
        }
 
        return rc;
 }
 
-/*
+/**
  * Boot a loaded NBI image
  *
+ * @v context          NBI context (as returned by nbi_probe())
+ * @ret Never          NBI program booted successfully
+ * @ret False          NBI program should not have returned
+ * @ret other          As returned by NBI program
+ * @err EIMGRET                NBI program should not have returned
+ *
+ * See also nbi_boot16() and nbi_boot32().
+ *
  */
 static int nbi_boot ( void *context ) {
        struct imgheader *imgheader = context;
@@ -298,6 +403,7 @@ static int nbi_boot ( void *context ) {
        }
 }
 
+/** Declaration of the NBI image format */
 static struct image nbi_image __image = {
        .name   = "NBI",
        .probe  = nbi_probe,
index 73f43c3..9d090fc 100644 (file)
@@ -1,9 +1,16 @@
 #ifndef BOCHS_H
 #define BOCHS_H
 
-/*
- * This file defines "bochsbp", the magic breakpoint instruction that
- * is incredibly useful when debugging under bochs.
+/** @file
+ *
+ * bochs breakpoints
+ *
+ * This file defines @c bochsbp, the magic breakpoint instruction that
+ * is incredibly useful when debugging under bochs.  This file should
+ * never be included in production code.
+ *
+ * Use the pseudo-instruction @c bochsbp in assembly code, or the
+ * bochsbp() function in C code.
  *
  */
 
@@ -15,7 +22,7 @@
 
 #else /* ASSEMBLY */
 
-/* Breakpoint for when debugging under bochs */
+/** Breakpoint for when debugging under bochs */
 static inline void bochsbp ( void ) {
        __asm__ __volatile__ ( "xchgw %bx, %bx" );
 }
index b9ade4e..c801cf6 100644 (file)
@@ -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 */
index d48b6c6..4d248b0 100644 (file)
@@ -46,7 +46,8 @@ static inline void * phys_to_virt ( unsigned long phys_addr ) {
        return ( void * ) ( phys_addr - virt_offset );
 }
 
-static inline void copy_to_phys ( physaddr_t dest, void *src, size_t len ) {
+static inline void copy_to_phys ( physaddr_t dest, const void *src,
+                                 size_t len ) {
        memcpy ( phys_to_virt ( dest ), src, len );
 }
 
index 2f9c592..8d8270b 100644 (file)
@@ -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 */
index d41a403..ec4b180 100644 (file)
@@ -75,6 +75,7 @@
 #undef DOWNLOAD_PROTO_HTTP     /* Hypertext Transfer Protocol */
 #undef DOWNLOAD_PROTO_TFTM     /* Multicast Trivial File Transfer Protocol */
 #undef DOWNLOAD_PROTO_SLAM     /* Scalable Local Area Multicast */
+#undef DOWNLOAD_PROTO_FSP      /* FSP? */
 
 /* @END general.h */
 
 
 /* @END general.h */
 
+/* @BEGIN general.h
+ *
+ * Image types
+ *
+ * Etherboot supports various image formats.  Select whichever ones
+ * you want to use.
+ *
+ */
+#define TAGGED_IMAGE           /* NBI image support */
+#undef ELF64_IMAGE             /* ELF64 image support */
+#undef ELF_IMAGE               /* ELF image support */
+#undef COFF_IMAGE              /* COFF image support */
+#undef IMAGE_FREEBSD           /* FreeBSD kernel image support */
+#undef IMAGE_MULTIBOOT         /* MultiBoot image support */
+#undef AOUT_IMAGE              /* a.out image support */
+#undef WINCE_IMAGE             /* WinCE image support */
+#undef PXE_IMAGE               /* PXE image support */
+
+/* @END general.h */ 
+
 /* @BEGIN general.h
  *
  * Obscure configuration options
index b300d4e..6e05b08 100644 (file)
@@ -1,6 +1,10 @@
-/*
- * Routines for filling a buffer with data received piecemeal, where
- * the size of the data is not necessarily known in advance.
+/** @file
+ *
+ * Buffers for loading files.
+ *
+ * This file provides routines for filling a buffer with data received
+ * piecemeal, where the size of the data is not necessarily known in
+ * advance.
  *
  * Some protocols do not provide a mechanism for us to know the size
  * of the file before we happen to receive a particular block
  * which assemble a file into a single contiguous block.  The whole
  * block is then passed to the image loader.
  *
+ * Example usage:
+ *
+ * @code
+ *
+ *   struct buffer my_buffer;
+ *   void *data;
+ *   off_t offset;
+ *   size_t len;
+ *   
+ *   // We have an area of memory [buf_start,buf_end) into which we want
+ *   // to load a file, where buf_start and buf_end are physical addresses.
+ *   buffer->start = buf_start;
+ *   buffer->end = buf_end;
+ *   init_buffer ( &buffer );
+ *   ...
+ *   while ( get_file_block ( ... ) ) {
+ *     // Downloaded block is stored in [data,data+len), and represents 
+ *     // the portion of the file at offsets [offset,offset+len)
+ *     if ( ! fill_buffer ( &buffer, data, offset, len ) ) {
+ *       // An error occurred
+ *       return 0;
+ *     }
+ *     ...
+ *   }
+ *   ...
+ *   // The whole file is now present at [buf_start,buf_start+filesize),
+ *   // where buf_start is a physical address.  The struct buffer can simply
+ *   // be discarded; there is no done_buffer() call.
+ *
+ * @endcode
+ *
+ * For a description of the internal operation, see \ref buffer_int.
+ *
+ */
+
+/** @page buffer_int Buffer internals
+ *
+ * A buffer consists of a single, contiguous area of memory, some of
+ * which is "filled" and the remainder of which is "free".  The
+ * "filled" and "free" spaces are not necessarily contiguous.
+ *
+ * When a buffer is initialised via init_buffer(), it consists of a
+ * single free space.  As data is added to the buffer via
+ * fill_buffer(), this free space decreases and can become fragmented.
+ *
+ * Each free block within a buffer starts with a "tail byte".  If the
+ * tail byte is non-zero, this indicates that the free block is the
+ * tail of the buffer, i.e. occupies all the remaining space up to the
+ * end of the buffer.  When the tail byte is non-zero, it indicates
+ * that a descriptor (a @c struct @c buffer_free_block) follows the
+ * tail byte.  The descriptor describes the size of the free block and
+ * the address of the next free block.
+ *
+ * We cannot simply always start a free block with a descriptor,
+ * because it is conceivable that we will, at some point, encounter a
+ * situation in which the final free block of a buffer is too small to
+ * contain a descriptor.  Consider a protocol with a blocksize of 512
+ * downloading a 1025-byte file into a 1025-byte buffer.  Suppose that
+ * the first two blocks are received; we have now filled 1024 of the
+ * 1025 bytes in the buffer, and our only free block consists of the
+ * 1025th byte.  Using a "tail byte" solves this problem.
  *
+ * 
  * Note that the rather convoluted way of manipulating the buffer
  * descriptors (using copy_{to,from}_phys rather than straightforward
  * pointers) is needed to cope with operation as a PXE stack, when we
  * may be running in real mode or 16-bit protected mode, and therefore
- * cannot directly access arbitrary areas of memory.
+ * cannot directly access arbitrary areas of memory using simple
+ * pointers.
  *
  */
 
 #include "stddef.h"
 #include "string.h"
 #include "io.h"
+#include "errno.h"
 #include "buffer.h"
 
-/*
- * Initialise a buffer
+/**
+ * Initialise a buffer.
+ *
+ * @v buffer           The buffer to be initialised
+ * @ret None
+ * @err None
+ *
+ * Set @c buffer->start and @c buffer->end before calling init_buffer().
+ * init_buffer() will initialise the buffer to the state of being
+ * empty.
  *
  */
 void init_buffer ( struct buffer *buffer ) {
@@ -42,8 +118,27 @@ void init_buffer ( struct buffer *buffer ) {
        DBG ( "BUFFER [%x,%x) initialised\n", buffer->start, buffer->end );
 }
 
-/*
- * Split a free block
+/**
+ * Split a free block.
+ *
+ * @v desc             A descriptor for the free block
+ * @v block            Start address of the block
+ * @v split            Address at which to split the block
+ * @ret None
+ * @err None
+ *
+ * Split a free block into two separate free blocks.  If the split
+ * point lies outside the block, no action is taken; this is not an
+ * error.
+ *
+ * @b NOTE: It is the reponsibility of the caller to ensure that there
+ * is enough room in each of the two portions for a free block
+ * descriptor (a @c struct @c buffer_free_block, except in the case of
+ * a tail block which requires only a one byte descriptor).  If the
+ * caller fails to do this, data corruption will occur.
+ *
+ * In practice, this means that the granularity at which blocks are
+ * split must be at least @c sizeof(struct @c buffer_free_block).
  *
  */
 static void split_free_block ( struct buffer_free_block *desc,
@@ -71,8 +166,16 @@ static void split_free_block ( struct buffer_free_block *desc,
        copy_to_phys ( block, desc, sizeof ( *desc ) );
 }
 
-/*
- * Mark a free block as used
+/**
+ * Mark a free block as used.
+ *
+ * @v buffer           The buffer containing the block
+ * @v desc             A descriptor for the free block
+ * @v prev_block       Address of the previous block
+ * @ret None
+ * @err None
+ *
+ * Marks a free block as used, i.e. removes it from the free list.
  *
  */
 static inline void unfree_block ( struct buffer *buffer,
@@ -99,15 +202,41 @@ static inline void unfree_block ( struct buffer *buffer,
        copy_to_phys ( prev_block, &prev_desc, sizeof ( prev_desc ) );
 }
 
-/*
- * Write data into a buffer
+/**
+ * Write data into a buffer.
+ *
+ * @v buffer           The buffer into which to write the data
+ * @v data             The data to be written
+ * @v offset           Offset within the buffer at which to write the data
+ * @v len              Length of data to be written
+ * @ret True           Data was successfully written
+ * @ret False          Data was not written
+ * @err ENOMEM         Buffer is too small to contain the data
+ *
+ * Writes a block of data into the buffer.  The block need not be
+ * aligned to any particular boundary, or be of any particular size,
+ * and it may overlap blocks already in the buffer (i.e. duplicate
+ * calls to fill_buffer() are explicitly permitted).
+ *
+ * @c buffer->fill will be updated to indicate the fill level of the
+ * buffer, i.e. the offset to the first gap within the buffer.  If the
+ * filesize is known (e.g. as with the SLAM protocol), you can test
+ * for end-of-file by checking for @c buffer->fill==filesize.  If the
+ * filesize is not known, but there is a well-defined end-of-file test
+ * (e.g. as with the TFTP protocol), you can read @c buffer->fill to
+ * determine the final filesize.  If blocks are known to be delivered
+ * in a strictly sequential order with no packet loss or duplication,
+ * then you can pass in @c offset==buffer->fill.
+ *
+ * @b NOTE: It is the caller's responsibility to ensure that the
+ * boundaries between data blocks are more than @c sizeof(struct @c
+ * buffer_free_block) apart.  If this condition is not satisfied, data
+ * corruption will occur.  (See split_free_block() for details.)
  *
- * It is the caller's responsibility to ensure that the boundaries
- * between data blocks are more than sizeof(struct buffer_free_block)
- * apart.  If this condition is not satisfied, data corruption will
- * occur.
+ * In practice this is not a problem.  Callers of fill_buffer() will
+ * be download protocols such as TFTP, and very few protocols have a
+ * block size smaller than @c sizeof(struct @c buffer_free_block).
  *
- * Returns 1 for success, 0 for failure (e.g. buffer too small).
  */
 int fill_buffer ( struct buffer *buffer, const void *data,
                  off_t offset, size_t len ) {
@@ -125,6 +254,7 @@ int fill_buffer ( struct buffer *buffer, const void *data,
        if ( data_end > buffer->end ) {
                DBG ( "BUFFER [%x,%x) too small for data!\n",
                      buffer->start, buffer->end );
+               errno = ENOMEM;
                return 0;
        }
 
index f868306..7756c63 100644 (file)
@@ -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
diff --git a/src/core/errno.c b/src/core/errno.c
new file mode 100644 (file)
index 0000000..83c8564
--- /dev/null
@@ -0,0 +1,61 @@
+#include "etherboot.h"
+#include "errno.h"
+#include "vsprintf.h"
+
+/** @file
+ *
+ * Error codes and descriptions.
+ *
+ * This file provides the global variable #errno and the function
+ * strerror().  These function much like their standard C library
+ * equivalents.
+ *
+ * The error numbers used by Etherboot are a superset of those defined
+ * by the PXE specification version 2.1.  See errno.h for a listing of
+ * the error values.
+ *
+ * To save space in ROM images, error string tables are optional.  Use
+ * the ERRORMSG_XXX options in config.h to select which error string
+ * tables you want to include.  If an error string table is omitted,
+ * strerror() will simply return the text "Error 0x<errno>".
+ *
+ */
+
+/**
+ * Global "last error" number.
+ *
+ * This is valid only when a function has just returned indicating a
+ * failure.
+ *
+ */
+int errno;
+
+static struct errortab errortab_start[0] __table_start(errortab);
+static struct errortab errortab_end[0] __table_end(errortab);
+
+/**
+ * Retrieve string representation of error number.
+ *
+ * @v errno            Error number
+ * @ret strerror       Pointer to error text
+ *
+ * If the error is not found in the linked-in error tables, generates
+ * a generic "Error 0x<errno>" message.
+ *
+ * The pointer returned by strerror() is valid only until the next
+ * call to strerror().
+ *
+ */
+const char * strerror ( int errno ) {
+       static char *generic_message = "Error 0x0000";
+       struct errortab *errortab;
+
+       for ( errortab = errortab_start ; errortab < errortab_end ;
+             errortab++ ) {
+               if ( errortab->errno == errno )
+                       return errortab->text;
+       }
+
+       sprintf ( generic_message + 8, "%hx", errno );
+       return generic_message;
+}
index 3a112ee..e0cac22 100644 (file)
@@ -31,6 +31,9 @@ Literature dealing with the network protocols:
 #include <lib.h>
 #endif
 
+/* Linker symbols */
+extern char _bss[], _ebss[];
+
 jmp_buf        restart_etherboot;
 int    url_port;               
 
@@ -199,7 +202,7 @@ int main ( void ) {
                /* Probe boot device */
                if ( ! probe ( &dev ) ) {
                        /* Device found on bus, but probe failed */
-                       printf ( "...probe failed\n" );
+                       printf ( "...probe failed: %m\n" );
                        continue;
                }
 
@@ -212,14 +215,14 @@ int main ( void ) {
                /* Configure boot device */
                if ( ! configure ( &dev ) ) {
                        /* Configuration (e.g. DHCP) failed */
-                       printf ( "...configuration failed\n" );
+                       printf ( "...configuration failed: %m\n" );
                        continue;
                }
 
                /* Load boot file from the device */
                if ( ! autoload ( &dev, &image, &image_context ) ) {
                        /* Load (e.g. TFTP) failed */
-                       printf ( "...load failed\n" );
+                       printf ( "...load failed: %m\n" );
                        continue;
                }
 
@@ -233,7 +236,7 @@ int main ( void ) {
                /* Boot the image */
                if ( ! image->boot ( image_context ) ) {
                        /* Boot failed */
-                       printf ( "...boot failed\n" );
+                       printf ( "...boot failed: %m\n" );
                        continue;
                }
                
diff --git a/src/core/pxe_errors.c b/src/core/pxe_errors.c
new file mode 100644 (file)
index 0000000..581393e
--- /dev/null
@@ -0,0 +1,102 @@
+#include "errno.h"
+
+/*
+ * This table was generated from the relevant section of errno.h using
+ *
+ * perl -ne 'if ( /(PXENV_STATUS_(\S+))/ ) {
+ *     $code = $1; $msg = $2;
+ *     $msg =~ s/_/ /g; $msg = ucfirst lc $msg;
+ *     $msg =~ s/(tftp|udp|arp|undi|bis|binl|pxenv|pxe|dhcp)/uc $1/ieg;
+ *     print "\t{ $code, \"$msg\" },\n";
+ *     }'
+ *
+ * followed by a little manual tweaking.
+ *
+ */
+static struct errortab pxe_errortab[] __errortab = {
+       { PXENV_STATUS_SUCCESS, "Success" },
+       { PXENV_STATUS_FAILURE, "Failure" },
+       { PXENV_STATUS_BAD_FUNC, "Bad function" },
+       { PXENV_STATUS_UNSUPPORTED, "Unsupported function" },
+       { PXENV_STATUS_KEEP_UNDI, "Keep UNDI" },
+       { PXENV_STATUS_KEEP_ALL, "Keep all" },
+       { PXENV_STATUS_OUT_OF_RESOURCES, "Out of resources" },
+       { PXENV_STATUS_ARP_TIMEOUT, "ARP timeout" },
+       { PXENV_STATUS_UDP_CLOSED, "UDP closed" },
+       { PXENV_STATUS_UDP_OPEN, "UDP open" },
+       { PXENV_STATUS_TFTP_CLOSED, "TFTP closed" },
+       { PXENV_STATUS_TFTP_OPEN, "TFTP open" },
+       { PXENV_STATUS_MCOPY_PROBLEM, "Memory copy problem" },
+       { PXENV_STATUS_BIS_INTEGRITY_FAILURE, "BIS integrity failure" },
+       { PXENV_STATUS_BIS_VALIDATE_FAILURE, "BIS validation failure" },
+       { PXENV_STATUS_BIS_INIT_FAILURE, "BIS init failure" },
+       { PXENV_STATUS_BIS_SHUTDOWN_FAILURE, "BIS shutdown failure" },
+       { PXENV_STATUS_BIS_GBOA_FAILURE, "BIS GBOA failure" },
+       { PXENV_STATUS_BIS_FREE_FAILURE, "BIS free failure" },
+       { PXENV_STATUS_BIS_GSI_FAILURE, "BIS GSI failure" },
+       { PXENV_STATUS_BIS_BAD_CKSUM, "BIS bad checksum" },
+       { PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS, "TFTP cannot ARP address" },
+       { PXENV_STATUS_TFTP_OPEN_TIMEOUT, "TFTP open timeout" },
+       { PXENV_STATUS_TFTP_UNKNOWN_OPCODE, "TFTP unknown opcode" },
+       { PXENV_STATUS_TFTP_READ_TIMEOUT, "TFTP read timeout" },
+       { PXENV_STATUS_TFTP_ERROR_OPCODE, "TFTP error opcode" },
+       { PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION,
+         "TFTP cannot open connection" },
+       { PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION,
+         "TFTP cannot read from connection" },
+       { PXENV_STATUS_TFTP_TOO_MANY_PACKAGES, "TFTP too many packages" },
+       { PXENV_STATUS_TFTP_FILE_NOT_FOUND, "TFTP file not found" },
+       { PXENV_STATUS_TFTP_ACCESS_VIOLATION, "TFTP access violation" },
+       { PXENV_STATUS_TFTP_NO_MCAST_ADDRESS, "TFTP no mcast address" },
+       { PXENV_STATUS_TFTP_NO_FILESIZE, "TFTP no filesize" },
+       { PXENV_STATUS_TFTP_INVALID_PACKET_SIZE, "TFTP invalid packet size" },
+       { PXENV_STATUS_DHCP_TIMEOUT, "DHCP timeout" },
+       { PXENV_STATUS_DHCP_NO_IP_ADDRESS, "DHCP no ip address" },
+       { PXENV_STATUS_DHCP_NO_BOOTFILE_NAME, "DHCP no bootfile name" },
+       { PXENV_STATUS_DHCP_BAD_IP_ADDRESS, "DHCP bad ip address" },
+       { PXENV_STATUS_UNDI_INVALID_FUNCTION, "UNDI invalid function" },
+       { PXENV_STATUS_UNDI_MEDIATEST_FAILED, "UNDI mediatest failed" },
+       { PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST,
+         "UNDI cannot initialise NIC for multicast" },
+       { PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC,
+         "UNDI cannot initialise NIC" },
+       { PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY,
+         "UNDI cannot initialise PHY" },
+       { PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA,
+         "UNDI cannot read config data" },
+       { PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA,
+         "UNDI cannot read init data" },
+       { PXENV_STATUS_UNDI_BAD_MAC_ADDRESS, "UNDI bad MAC address" },
+       { PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM, "UNDI bad EEPROM checksum" },
+       { PXENV_STATUS_UNDI_ERROR_SETTING_ISR, "UNDI error setting ISR" },
+       { PXENV_STATUS_UNDI_INVALID_STATE, "UNDI invalid state" },
+       { PXENV_STATUS_UNDI_TRANSMIT_ERROR, "UNDI transmit error" },
+       { PXENV_STATUS_UNDI_INVALID_PARAMETER, "UNDI invalid parameter" },
+       { PXENV_STATUS_BSTRAP_PROMPT_MENU, "Bootstrap prompt menu" },
+       { PXENV_STATUS_BSTRAP_MCAST_ADDR, "Bootstrap mcast addr" },
+       { PXENV_STATUS_BSTRAP_MISSING_LIST, "Bootstrap missing list" },
+       { PXENV_STATUS_BSTRAP_NO_RESPONSE, "Bootstrap no response" },
+       { PXENV_STATUS_BSTRAP_FILE_TOO_BIG, "Bootstrap file too big" },
+       { PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE,
+         "BINL canceled by keystroke" },
+       { PXENV_STATUS_BINL_NO_PXE_SERVER, "BINL no PXE server" },
+       { PXENV_STATUS_NOT_AVAILABLE_IN_PMODE,
+         "Not available in protected mode" },
+       { PXENV_STATUS_NOT_AVAILABLE_IN_RMODE, "Not available in real mode" },
+       { PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED,
+         "BUSD device not supported" },
+       { PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY,
+         "Loader no free base memory" },
+       { PXENV_STATUS_LOADER_NO_BC_ROMID, "Loader no Base Code ROM ID" },
+       { PXENV_STATUS_LOADER_BAD_BC_ROMID, "Loader bad Base Code ROM ID" },
+       { PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE,
+         "Loader bad Base Code runtime image" },
+       { PXENV_STATUS_LOADER_NO_UNDI_ROMID, "Loader no UNDI ROM ID" },
+       { PXENV_STATUS_LOADER_BAD_UNDI_ROMID, "Loader bad UNDI ROM ID" },
+       { PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE,
+         "Loader bad UNDI driver image" },
+       { PXENV_STATUS_LOADER_NO_PXE_STRUCT, "Loader no !PXE struct" },
+       { PXENV_STATUS_LOADER_NO_PXENV_STRUCT, "Loader no PXENV+ struct" },
+       { PXENV_STATUS_LOADER_UNDI_START, "Loader UNDI start" },
+       { PXENV_STATUS_LOADER_BC_START, "Loader Base Code start" },
+};
index 414b450..c0bc759 100644 (file)
@@ -2,6 +2,7 @@
 #include "if_ether.h" /* for ETH_ALEN */
 #include "limits.h" /* for CHAR_BIT */
 #include "console.h"
+#include "errno.h"
 #include "vsprintf.h"
 
 #define LONG_SHIFT  ((int)((sizeof(unsigned long)*CHAR_BIT) - 4))
 #define SHRT_SHIFT  ((int)((sizeof(unsigned short)*CHAR_BIT) - 4))
 #define CHAR_SHIFT  ((int)((sizeof(unsigned char)*CHAR_BIT) - 4))
 
-/**************************************************************************
-PRINTF and friends
+/** @file
+ *
+ * printf and friends.
+ *
+ * Etherboot's printf() functions understand the following format
+ * specifiers:
+ *
+ *     - Hexadecimal integers
+ *             - @c %[#]x      - 4 bytes int (8 hex digits, lower case)
+ *             - @c %[#]X      - 4 bytes int (8 hex digits, upper case)
+ *             - @c %[#]lx     - 8 bytes long (16 hex digits, lower case)
+ *             - @c %[#]lX     - 8 bytes long (16 hex digits, upper case)
+ *             - @c %[#]hx     - 2 bytes int (4 hex digits, lower case)
+ *             - @c %[#]hX     - 2 bytes int (4 hex digits, upper case)
+ *             - @c %[#]hhx    - 1 byte int (2 hex digits, lower case)
+ *             - @c %[#]hhX    - 1 byte int (2 hex digits, upper case)
+ *             .
+ *             If the optional # prefix is specified, the output will
+ *             be prefixed with 0x (or 0X).
+ *
+ *     - Other integers
+ *             - @c %d         - decimal int
+ *     .
+ *     Note that any width specification (e.g. the @c 02 in @c %02x)
+ *     will be accepted but ignored.
+ *
+ *     - Strings and characters
+ *             - @c %c         - char
+ *             - @c %s         - string
+ *             - @c %m         - error message text (i.e. strerror(errno))
+ *
+ *     - Etherboot-specific specifiers
+ *             - @c %@         - IP in ddd.ddd.ddd.ddd notation
+ *             - @c %!         - MAC address in xx:xx:xx:xx:xx:xx notation
+ *
+ */
 
-       Formats:
-               %[#]x   - 4 bytes int (8 hex digits, lower case)
-               %[#]X   - 4 bytes int (8 hex digits, upper case)
-               %[#]lx  - 8 bytes long (16 hex digits, lower case)
-               %[#]lX  - 8 bytes long (16 hex digits, upper case)
-               %[#]hx  - 2 bytes int (4 hex digits, lower case)
-               %[#]hX  - 2 bytes int (4 hex digits, upper case)
-               %[#]hhx - 1 byte int (2 hex digits, lower case)
-               %[#]hhX - 1 byte int (2 hex digits, upper case)
-                       - optional # prefixes 0x or 0X
-               %d      - decimal int
-               %c      - char
-               %s      - string
-               %@      - Internet address in ddd.ddd.ddd.ddd notation
-               %!      - Ethernet address in xx:xx:xx:xx:xx:xx notation
-       Note: width specification ignored
-**************************************************************************/
+/**
+ * Write a formatted string to a buffer.
+ *
+ * @v buf              Buffer into which to write the string, or NULL
+ * @v fmt              Format string
+ * @v args             Arguments corresponding to the format string
+ * @ret len            Length of string written to buffer (if buf != NULL)
+ * @ret        0               (if buf == NULL)
+ * @err None
+ *
+ * If @c buf==NULL, then the string will be written to the console
+ * directly using putchar().
+ *
+ */
 static int vsprintf(char *buf, const char *fmt, va_list args)
 {
-       char *p, *s;
+       const char *p;
+       char *s;
        s = buf;
        for ( ; *fmt != '\0'; ++fmt) {
                if (*fmt != '%') {
@@ -49,8 +82,10 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
                if (*fmt == 's') {
                        for(p = va_arg(args, char *); *p != '\0'; p++) 
                                buf ? *s++ = *p : putchar(*p);
-               }
-               else {  /* Length of item is bounded */
+               } else if (*fmt == 'm') {
+                       for(p = strerror(errno); *p != '\0'; p++)
+                               buf ? *s++ = *p : putchar(*p);
+               } else {        /* Length of item is bounded */
                        char tmp[40], *q = tmp;
                        int alt = 0;
                        int shift = INT_SHIFT;
@@ -93,7 +128,7 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
                                        *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
                        }
                        else if (*fmt == 'd') {
-                               char *r;
+                               char *r, *t;
                                long i;
                                if (shift > INT_SHIFT) {
                                        i = va_arg(args, long);
@@ -104,17 +139,17 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
                                        *q++ = '-';
                                        i = -i;
                                }
-                               p = q;          /* save beginning of digits */
+                               t = q;          /* save beginning of digits */
                                do {
                                        *q++ = '0' + (i % 10);
                                        i /= 10;
                                } while (i);
                                /* reverse digits, stop in middle */
                                r = q;          /* don't alter q */
-                               while (--r > p) {
+                               while (--r > t) {
                                        i = *r;
-                                       *r = *p;
-                                       *p++ = i;
+                                       *r = *t;
+                                       *t++ = i;
                                }
                        }
                        else if (*fmt == '@') {
@@ -129,7 +164,7 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
                                --q;
                        }
                        else if (*fmt == '!') {
-                               char *r;
+                               const char *r;
                                p = va_arg(args, char *);
                                for (r = p + ETH_ALEN; p < r; ++p)
                                        q += sprintf(q, "%hhX:", *p);
@@ -149,6 +184,20 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
        return (s - buf);
 }
 
+/**
+ * Write a formatted string to a buffer.
+ *
+ * @v buf              Buffer into which to write the string, or NULL
+ * @v fmt              Format string
+ * @v ...              Arguments corresponding to the format string
+ * @ret len            Length of string written to buffer (if buf != NULL)
+ * @ret        0               (if buf == NULL)
+ * @err None
+ *
+ * If @c buf==NULL, then the string will be written to the console
+ * directly using putchar().
+ *
+ */
 int sprintf(char *buf, const char *fmt, ...)
 {
        va_list args;
@@ -159,6 +208,15 @@ int sprintf(char *buf, const char *fmt, ...)
        return i;
 }
 
+/**
+ * Write a formatted string to the console.
+ *
+ * @v fmt              Format string
+ * @v ...              Arguments corresponding to the format string
+ * @ret        None
+ * @err None
+ *
+ */
 void printf(const char *fmt, ...)
 {
        va_list args;
diff --git a/src/doxygen.cfg b/src/doxygen.cfg
new file mode 100644 (file)
index 0000000..3ce15c4
--- /dev/null
@@ -0,0 +1,204 @@
+# Doxyfile 1.2.17
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = Etherboot
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = @BIN@/doc
+OUTPUT_LANGUAGE        = English
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = YES
+EXTRACT_STATIC         = YES
+EXTRACT_LOCAL_CLASSES  = YES
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = YES
+STRIP_CODE_COMMENTS    = NO
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = YES
+SHOW_INCLUDE_FILES     = YES
+JAVADOC_AUTOBRIEF      = YES
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = YES
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = NO
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ALIASES                = v=@param \
+                         ret=@retval \
+                         err=@exception
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+SHOW_USED_FILES        = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = 
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = @SRCDIRS@ \
+                         include \
+                         arch/@ARCH@/include
+FILE_PATTERNS          = 
+RECURSIVE              = NO
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = YES
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = 
+HTML_FILE_EXTENSION    = 
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = YES
+LATEX_OUTPUT           = 
+LATEX_CMD_NAME         = 
+MAKEINDEX_CMD_NAME     = 
+COMPACT_LATEX          = YES
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = 
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = YES
+MAN_OUTPUT             = 
+MAN_EXTENSION          = 
+MAN_LINKS              = YES
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_SCHEMA             = 
+XML_DTD                = 
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = YES
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = include \
+                         arch/@ARCH@/include
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = DOXYGEN=1
+EXPAND_AS_DEFINED      = __attribute__ \
+                         PACKED \
+                         __unused \
+                         __used \
+                         __aligned \
+                         __table \
+                         __table_start \
+                         __table_end
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = 
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+GRAPHICAL_HIERARCHY    = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
+CGI_NAME               = 
+CGI_URL                = 
+DOC_URL                = 
+DOC_ABSPATH            = 
+BIN_ABSPATH            = 
+EXT_DOC_PATHS          = 
index 6b7c79e..4888c61 100644 (file)
 *
 ***************************************************************************/
 
-#include "string.h"
-#include "timer.h"
-#include "io.h"
-#include "console.h"
-#include "isapnp.h"
-
-/*
- * We can have only one ISAPnP bus in a system.  Once the read port is
- * known and all cards have been allocated CSNs, there's nothing to be
- * gained by re-scanning for cards.
+/** @file
+ *
+ * ISAPnP bus support
+ *
+ * Etherboot orignally gained ISAPnP support in a very limited way for
+ * the 3c515 NIC.  The current implementation is almost a complete
+ * rewrite based on the ISAPnP specification, with passing reference
+ * to the Linux ISAPnP code.
+ *
+ * There can be only one ISAPnP bus in a system.  Once the read port
+ * is known and all cards have been allocated CSNs, there's nothing to
+ * be gained by re-scanning for cards.
  *
  * However, we shouldn't make scanning the ISAPnP bus an INIT_FN(),
  * because even ISAPnP probing can still screw up other devices on the
  * an ISAPnP device.
  *
  * External code (e.g. the ISAPnP ROM prefix) may already know the
- * read port address, in which case it can initialise this value.
- * Note that setting the read port address will prevent further
- * isolation from taking place; you should set the read port address
- * only if you know that devices have already been allocated CSNs.
+ * read port address, in which case it can store it in @c
+ * isapnp_read_port.  Note that setting the read port address in this
+ * way will prevent further isolation from taking place; you should
+ * set the read port address only if you know that devices have
+ * already been allocated CSNs.
+ *
+ */
+
+#include "string.h"
+#include "timer.h"
+#include "io.h"
+#include "console.h"
+#include "isapnp.h"
+
+/**
+ * ISAPnP Read Port address.
  *
  */
 uint16_t isapnp_read_port;
 
-/*
+/**
  * Highest assigned CSN.
  *
- * Note that *we* do not necessarily assign CSNs; it could be done by
+ * Note that @b we do not necessarily assign CSNs; it could be done by
  * the PnP BIOS instead.  We therefore set this only when we first try
  * to Wake[CSN] a device and find that there's nothing there.  Page 16
  * (PDF page 22) of the ISAPnP spec states that "Valid Card Select
@@ -116,22 +130,56 @@ static inline uint16_t isapnp_read_word ( uint8_t address ) {
                 + isapnp_read_byte ( address + 1 ) );
 }
 
+/** Inform cards of a new read port address */
 static inline void isapnp_set_read_port ( void ) {
        isapnp_write_byte ( ISAPNP_READPORT, isapnp_read_port >> 2 );
 }
 
+/**
+ * Enter the Isolation state.
+ *
+ * Only cards currently in the Sleep state will respond to this
+ * command.
+ *
+ */
 static inline void isapnp_serialisolation ( void ) {
        isapnp_write_address ( ISAPNP_SERIALISOLATION );
 }
 
+/**
+ * Enter the Wait for Key state.
+ *
+ * All cards will respond to this command, regardless of their current
+ * state.
+ *
+ */
 static inline void isapnp_wait_for_key ( void ) {
        isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY );
 }
 
+/**
+ * Reset (i.e. remove) Card Select Number.
+ *
+ * Only cards currently in the Sleep state will respond to this
+ * command.
+ *
+ */
 static inline void isapnp_reset_csn ( void ) {
        isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN );
 }
 
+/**
+ * Place a specified card into the Config state.
+ *
+ * @v csn              Card Select Number
+ * @ret None
+ * @err None
+ *
+ * Only cards currently in the Sleep, Isolation, or Config states will
+ * respond to this command.  The card that has the specified CSN will
+ * enter the Config state, all other cards will enter the Sleep state.
+ *
+ */
 static inline void isapnp_wake ( uint8_t csn ) {
        isapnp_write_byte ( ISAPNP_WAKE, csn );
 }
@@ -144,6 +192,19 @@ static inline uint8_t isapnp_read_status ( void ) {
        return isapnp_read_byte ( ISAPNP_STATUS );
 }
 
+/**
+ * Assign a Card Select Number to a card, and enter the Config state.
+ *
+ * @v csn              Card Select Number
+ * @ret None
+ * @err None
+ *
+ * Only cards in the Isolation state will respond to this command.
+ * The isolation protocol is designed so that only one card will
+ * remain in the Isolation state by the time the isolation protocol
+ * completes.
+ *
+ */
 static inline void isapnp_write_csn ( uint8_t csn ) {
        isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn );
 }
@@ -174,12 +235,20 @@ static void isapnp_delay ( void ) {
        udelay ( 1000 );
 }
 
-/*
- * The linear feedback shift register as described in Appendix B of
- * the PnP ISA spec.  The hardware implementation uses eight D-type
- * latches and two XOR gates.  I think this is probably the smallest
- * possible implementation in software.  Six instructions when input_bit
- * is a constant 0 (for isapnp_send_key).  :)
+/**
+ * Linear feedback shift register.
+ *
+ * @v lfsr             Current value of the LFSR
+ * @v input_bit                Current input bit to the LFSR
+ * @ret lfsr           Next value of the LFSR
+ * @err None
+ *
+ * This routine implements the linear feedback shift register as
+ * described in Appendix B of the PnP ISA spec.  The hardware
+ * implementation uses eight D-type latches and two XOR gates.  I
+ * think this is probably the smallest possible implementation in
+ * software.  Six instructions when input_bit is a constant 0 (for
+ * isapnp_send_key).  :)
  *
  */
 static inline uint8_t isapnp_lfsr_next ( uint8_t lfsr, int input_bit ) {
@@ -190,8 +259,11 @@ static inline uint8_t isapnp_lfsr_next ( uint8_t lfsr, int input_bit ) {
        return lfsr_next;
 }
 
-/*
- * Send the ISAPnP initiation key
+/**
+ * Send the ISAPnP initiation key.
+ *
+ * Sending the key causes all ISAPnP cards that are currently in the
+ * Wait for Key state to transition into the Sleep state.
  *
  */
 static void isapnp_send_key ( void ) {
@@ -209,8 +281,12 @@ static void isapnp_send_key ( void ) {
        }
 }
 
-/*
- *  Compute ISAPnP identifier checksum
+/**
+ * Compute ISAPnP identifier checksum
+ *
+ * @v identifier               ISAPnP identifier
+ * @ret checksum               Expected checksum value
+ * @err None
  *
  */
 static uint8_t isapnp_checksum ( struct isapnp_identifier *identifier ) {
@@ -248,9 +324,16 @@ static inline uint8_t isapnp_peek_byte ( void ) {
        return 0xff;
 }
 
-/*
- * Read n bytes of resource data from the current location.  If buf is
- * NULL, discard data.
+/**
+ * Read resource data.
+ *
+ * @v buf              Buffer in which to store data, or NULL
+ * @v bytes            Number of bytes to read
+ * @ret None
+ * @err None
+ *
+ * Resource data is read from the current location.  If @c buf is NULL,
+ * the data is discarded.
  *
  */
 static void isapnp_peek ( uint8_t *buf, size_t bytes ) {
@@ -265,12 +348,19 @@ static void isapnp_peek ( uint8_t *buf, size_t bytes ) {
        }
 }
 
-/*
- * Scan through the resource data until we find a particular tag, and
- * read its contents into a buffer.
+/**
+ * Find a tag within the resource data.
  *
- * It is the caller's responsibility to ensure that buf is large
- * enough to contain a tag of the requested size.
+ * @v wanted_tag       The tag that we're looking for
+ * @v buf              Buffer in which to store the tag's contents
+ * @ret True           Tag was found
+ * @ret False          Tag was not found
+ * @err None
+ *
+ * Scan through the resource data until we find a particular tag, and
+ * read its contents into a buffer.  It is the caller's responsibility
+ * to ensure that @c buf is large enough to contain a tag of the
+ * requested size.
  *
  */
 static int isapnp_find_tag ( uint8_t wanted_tag, uint8_t *buf ) {
@@ -300,10 +390,13 @@ static int isapnp_find_tag ( uint8_t wanted_tag, uint8_t *buf ) {
        return 0;
 }
 
-/*
- * Try isolating ISAPnP cards at the current read port.  Return the
- * number of ISAPnP cards found.  <0 indicates "try a new read port",
- * 0 indicates "definitely no cards".
+/**
+ * Try isolating ISAPnP cards at the current read port.
+ *
+ * @ret \>0            Number of ISAPnP cards found
+ * @ret 0              There are no ISAPnP cards in the system
+ * @ret \<0            A conflict was detected; try a new read port
+ * @err None
  *
  * The state diagram on page 18 (PDF page 24) of the PnP ISA spec
  * gives the best overview of what happens here.
@@ -429,8 +522,8 @@ static int isapnp_try_isolate ( void ) {
        return csn;
 }
 
-/*
- * Isolate all ISAPnP cards, locating a valid read port in the process.
+/**
+ * Find a valid read port and isolate all ISAPnP cards.
  *
  */
 static void isapnp_isolate ( void ) {
@@ -450,10 +543,17 @@ static void isapnp_isolate ( void ) {
        }
 }
 
-/*
- * Increment a bus_loc structure to the next possible ISAPnP location.
- * Leave the structure zeroed and return 0 if there are no more valid
- * locations.
+/**
+ * Increment a @c bus_loc structure to the next possible ISAPnP
+ * location.
+ *
+ * @v bus_loc          Bus location
+ * @ret True           @c bus_loc contains a valid ISAPnP location
+ * @ret False          There are no more valid ISAPnP locations
+ * @err None
+ *
+ * If there are no more valid locations, the @c bus_loc structure will
+ * be zeroed.
  *
  */
 static int isapnp_next_location ( struct bus_loc *bus_loc ) {
@@ -471,10 +571,14 @@ static int isapnp_next_location ( struct bus_loc *bus_loc ) {
        return ( ++isapnp_loc->logdev ? 1 : ++isapnp_loc->csn );
 }
 
-/*
- * Fill in parameters for an ISAPnP device based on CSN
+/**
+ * Fill in parameters for an ISAPnP device based on CSN.
  *
- * Return 1 if device present, 0 otherwise
+ * @v bus_dev          Bus device to be filled in
+ * @v bus_loc          Bus location as filled in by isapnp_next_location()
+ * @ret True           A device is present at this location
+ * @ret False          No device is present at this location
+ * @err None
  *
  */
 static int isapnp_fill_device ( struct bus_dev *bus_dev,
@@ -566,9 +670,15 @@ static int isapnp_fill_device ( struct bus_dev *bus_dev,
        return 1;
 }
 
-/*
+/**
  * Test whether or not a driver is capable of driving the device.
  *
+ * @v bus_dev          Bus device as filled in by isapnp_fill_device()
+ * @v device_driver    Device driver
+ * @ret True           Driver is capable of driving this device
+ * @ret False          Driver is not capable of driving this device
+ * @err None
+ *
  */
 static int isapnp_check_driver ( struct bus_dev *bus_dev,
                                 struct device_driver *device_driver ) {
@@ -598,8 +708,15 @@ static int isapnp_check_driver ( struct bus_dev *bus_dev,
        return 0;
 }
 
-/*
- * Describe an ISAPnP device
+/**
+ * Describe an ISAPnP device.
+ *
+ * @v bus_dev          Bus device as filled in by isapnp_fill_device()
+ * @ret string         Printable string describing the device
+ * @err None
+ *
+ * The string returned by isapnp_describe_device() is valid only until
+ * the next call to isapnp_describe_device().
  *
  */
 static char * isapnp_describe_device ( struct bus_dev *bus_dev ) {
@@ -611,8 +728,15 @@ static char * isapnp_describe_device ( struct bus_dev *bus_dev ) {
        return isapnp_description;
 }
 
-/*
- * Name an ISAPnP device
+/**
+ * Name an ISAPnP device.
+ *
+ * @v bus_dev          Bus device as filled in by isapnp_fill_device()
+ * @ret string         Printable string naming the device
+ * @err None
+ *
+ * The string returned by isapnp_name_device() is valid only until the
+ * next call to isapnp_name_device().
  *
  */
 static const char * isapnp_name_device ( struct bus_dev *bus_dev ) {
@@ -634,12 +758,17 @@ struct bus_driver isapnp_driver __bus_driver = {
        .name_device            = isapnp_name_device,
 };
 
-/*
- * Activate or deactivate an ISAPnP device
+/**
+ * Activate or deactivate an ISAPnP device.
+ *
+ * @v isapnp           ISAPnP device
+ * @v activation       True to enable, False to disable the device
+ * @ret None
+ * @err None
  *
  * This routine simply activates the device in its current
- * configuration.  It does not attempt any kind of resource
- * arbitration.
+ * configuration, or deactivates the device.  It does not attempt any
+ * kind of resource arbitration.
  *
  */
 void isapnp_device_activation ( struct isapnp_device *isapnp,
@@ -662,8 +791,17 @@ void isapnp_device_activation ( struct isapnp_device *isapnp,
              isapnp->csn, isapnp->logdev );
 }
 
-/*
- * Fill in a nic structure
+/**
+ * Fill in a nic structure.
+ *
+ * @v nic              NIC structure to be filled in
+ * @v isapnp           ISAPnP device
+ * @ret None
+ * @err None
+ *
+ * This fills in generic NIC parameters (e.g. I/O address and IRQ
+ * number) that can be determined directly from the ISAPnP device,
+ * without any driver-specific knowledge.
  *
  */
 void isapnp_fill_nic ( struct nic *nic, struct isapnp_device *isapnp ) {
index 7fcc9f0..c874950 100644 (file)
@@ -61,10 +61,6 @@ static void t3c515_wait(unsigned int nticks)
 
 /* 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 */
diff --git a/src/drivers/net/amd8111e.c b/src/drivers/net/amd8111e.c
new file mode 100644 (file)
index 0000000..611cbc8
--- /dev/null
@@ -0,0 +1,681 @@
+/* Advanced  Micro Devices Inc. AMD8111E Linux Network Driver 
+ * Copyright (C) 2004 Advanced Micro Devices 
+ * Copyright (C) 2005 Liu Tao <liutao1980@gmail.com> [etherboot port]
+ * 
+ * Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
+ * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)[ tg3.c]
+ * Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ]
+ * Derived from the lance driver written 1993,1994,1995 by Donald Becker.
+ * Copyright 1993 United States Government as represented by the
+ *     Director, National Security Agency.[ pcnet32.c ]
+ * Carsten Langgaard, carstenl@mips.com [ pcnet32.c ]
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
+ * USA
+ */
+
+#include "etherboot.h"
+#include "nic.h"
+#include "mii.h"
+#include "pci.h"
+#include "timer.h"
+#include "string.h"
+#include "stdint.h"
+#include "amd8111e.h"
+
+
+/* driver definitions */
+#define NUM_TX_SLOTS   2
+#define NUM_RX_SLOTS   4
+#define TX_SLOTS_MASK  1
+#define RX_SLOTS_MASK  3
+
+#define TX_BUF_LEN     1536
+#define RX_BUF_LEN     1536
+
+#define TX_PKT_LEN_MAX (ETH_FRAME_LEN - ETH_HLEN)
+#define RX_PKT_LEN_MIN 60
+#define RX_PKT_LEN_MAX ETH_FRAME_LEN
+
+#define TX_TIMEOUT     3000
+#define TX_PROCESS_TIME        10
+#define TX_RETRY       (TX_TIMEOUT / TX_PROCESS_TIME)
+
+#define PHY_RW_RETRY   10
+
+
+struct amd8111e_tx_desc {
+       u16 buf_len;
+       u16 tx_flags;
+       u16 tag_ctrl_info;
+       u16 tag_ctrl_cmd;
+       u32 buf_phy_addr;
+       u32 reserved;
+}; 
+
+struct amd8111e_rx_desc {
+       u32 reserved;
+       u16 msg_len;
+       u16 tag_ctrl_info; 
+       u16 buf_len;
+       u16 rx_flags;
+       u32 buf_phy_addr;
+};
+
+struct eth_frame {
+       u8 dst_addr[ETH_ALEN];
+       u8 src_addr[ETH_ALEN];
+       u16 type;
+       u8 data[ETH_FRAME_LEN - ETH_HLEN];
+} __attribute__((packed));
+
+struct amd8111e_priv {
+       struct amd8111e_tx_desc tx_ring[NUM_TX_SLOTS];
+       struct amd8111e_rx_desc rx_ring[NUM_RX_SLOTS];
+       unsigned char tx_buf[NUM_TX_SLOTS][TX_BUF_LEN];
+       unsigned char rx_buf[NUM_RX_SLOTS][RX_BUF_LEN];
+       unsigned long tx_idx, rx_idx;
+       int tx_consistent;
+
+       char opened;
+       char link;
+       char speed;
+       char duplex;
+       int ext_phy_addr;
+       u32 ext_phy_id;
+
+       struct pci_device *pdev;
+       struct nic *nic;
+       void *mmio;
+};
+
+static struct amd8111e_priv amd8111e;
+
+
+/********************************************************
+ *             locale functions                        *
+ ********************************************************/
+static void amd8111e_init_hw_default(struct amd8111e_priv *lp);
+static int amd8111e_start(struct amd8111e_priv *lp);
+static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val);
+#if 0
+static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val);
+#endif
+static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp);
+static void amd8111e_disable_interrupt(struct amd8111e_priv *lp);
+static void amd8111e_enable_interrupt(struct amd8111e_priv *lp);
+static void amd8111e_force_interrupt(struct amd8111e_priv *lp);
+static int amd8111e_get_mac_address(struct amd8111e_priv *lp);
+static int amd8111e_init_rx_ring(struct amd8111e_priv *lp);
+static int amd8111e_init_tx_ring(struct amd8111e_priv *lp);
+static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index);
+static void amd8111e_wait_link(struct amd8111e_priv *lp);
+static void amd8111e_poll_link(struct amd8111e_priv *lp);
+static void amd8111e_restart(struct amd8111e_priv *lp);
+
+
+/* 
+ * This function clears necessary the device registers. 
+ */    
+static void amd8111e_init_hw_default(struct amd8111e_priv *lp)
+{
+       unsigned int reg_val;
+       unsigned int logic_filter[2] = {0,};
+       void *mmio = lp->mmio;
+
+        /* stop the chip */
+       writel(RUN, mmio + CMD0);
+
+       /* Clear RCV_RING_BASE_ADDR */
+       writel(0, mmio + RCV_RING_BASE_ADDR0);
+
+       /* Clear XMT_RING_BASE_ADDR */
+       writel(0, mmio + XMT_RING_BASE_ADDR0);
+       writel(0, mmio + XMT_RING_BASE_ADDR1);
+       writel(0, mmio + XMT_RING_BASE_ADDR2);
+       writel(0, mmio + XMT_RING_BASE_ADDR3);
+
+       /* Clear CMD0  */
+       writel(CMD0_CLEAR, mmio + CMD0);
+       
+       /* Clear CMD2 */
+       writel(CMD2_CLEAR, mmio + CMD2);
+
+       /* Clear CMD7 */
+       writel(CMD7_CLEAR, mmio + CMD7);
+
+       /* Clear DLY_INT_A and DLY_INT_B */
+       writel(0x0, mmio + DLY_INT_A);
+       writel(0x0, mmio + DLY_INT_B);
+
+       /* Clear FLOW_CONTROL */
+       writel(0x0, mmio + FLOW_CONTROL);
+
+       /* Clear INT0  write 1 to clear register */
+       reg_val = readl(mmio + INT0);
+       writel(reg_val, mmio + INT0);
+
+       /* Clear STVAL */
+       writel(0x0, mmio + STVAL);
+
+       /* Clear INTEN0 */
+       writel(INTEN0_CLEAR, mmio + INTEN0);
+
+       /* Clear LADRF */
+       writel(0x0, mmio + LADRF);
+
+       /* Set SRAM_SIZE & SRAM_BOUNDARY registers  */
+       writel(0x80010, mmio + SRAM_SIZE);
+
+       /* Clear RCV_RING0_LEN */
+       writel(0x0, mmio +  RCV_RING_LEN0);
+
+       /* Clear XMT_RING0/1/2/3_LEN */
+       writel(0x0, mmio +  XMT_RING_LEN0);
+       writel(0x0, mmio +  XMT_RING_LEN1);
+       writel(0x0, mmio +  XMT_RING_LEN2);
+       writel(0x0, mmio +  XMT_RING_LEN3);
+
+       /* Clear XMT_RING_LIMIT */
+       writel(0x0, mmio + XMT_RING_LIMIT);
+
+       /* Clear MIB */
+       writew(MIB_CLEAR, mmio + MIB_ADDR);
+
+       /* Clear LARF */
+       amd8111e_writeq(*(u64*)logic_filter, mmio + LADRF);
+
+       /* SRAM_SIZE register */
+       reg_val = readl(mmio + SRAM_SIZE);
+       
+       /* Set default value to CTRL1 Register */
+       writel(CTRL1_DEFAULT, mmio + CTRL1);
+
+       /* To avoid PCI posting bug */
+       readl(mmio + CMD2);
+}
+
+/* 
+ * This function initializes the device registers  and starts the device.  
+ */
+static int amd8111e_start(struct amd8111e_priv *lp)
+{
+       struct nic *nic = lp->nic;
+       void *mmio = lp->mmio;
+       int i, reg_val;
+
+       /* stop the chip */
+       writel(RUN, mmio + CMD0);
+
+       /* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
+       writew(0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0);
+
+       /* enable the port manager and set auto negotiation always */
+       writel(VAL1 | EN_PMGR, mmio + CMD3 );
+       writel(XPHYANE | XPHYRST, mmio + CTRL2); 
+
+       /* set control registers */
+       reg_val = readl(mmio + CTRL1);
+       reg_val &= ~XMTSP_MASK;
+       writel(reg_val | XMTSP_128 | CACHE_ALIGN, mmio + CTRL1);
+
+       /* initialize tx and rx ring base addresses */
+       amd8111e_init_tx_ring(lp);
+       amd8111e_init_rx_ring(lp);
+       writel(virt_to_bus(lp->tx_ring), mmio + XMT_RING_BASE_ADDR0);
+       writel(virt_to_bus(lp->rx_ring), mmio + RCV_RING_BASE_ADDR0);
+       writew(NUM_TX_SLOTS, mmio + XMT_RING_LEN0);
+       writew(NUM_RX_SLOTS, mmio + RCV_RING_LEN0);
+       
+       /* set default IPG to 96 */
+       writew(DEFAULT_IPG, mmio + IPG);
+       writew(DEFAULT_IPG - IFS1_DELTA, mmio + IFS1); 
+
+       /* AutoPAD transmit, Retransmit on Underflow */
+       writel(VAL0 | APAD_XMT | REX_RTRY | REX_UFLO, mmio + CMD2);
+       
+       /* JUMBO disabled */
+       writel(JUMBO, mmio + CMD3);
+
+       /* Setting the MAC address to the device */
+       for(i = 0; i < ETH_ALEN; i++)
+               writeb(nic->node_addr[i], mmio + PADR + i); 
+
+       /* set RUN bit to start the chip, interrupt not enabled */
+       writel(VAL2 | RDMD0 | VAL0 | RUN, mmio + CMD0);
+       
+       /* To avoid PCI posting bug */
+       readl(mmio + CMD0);
+       return 0;
+}
+
+/* 
+This function will read the PHY registers.
+*/
+static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val)
+{
+       void *mmio = lp->mmio;
+       unsigned int reg_val;
+       unsigned int retry = PHY_RW_RETRY;
+
+       reg_val = readl(mmio + PHY_ACCESS);
+       while (reg_val & PHY_CMD_ACTIVE)
+               reg_val = readl(mmio + PHY_ACCESS);
+
+       writel(PHY_RD_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16),
+               mmio + PHY_ACCESS);
+       do {
+               reg_val = readl(mmio + PHY_ACCESS);
+               udelay(30);  /* It takes 30 us to read/write data */
+       } while (--retry && (reg_val & PHY_CMD_ACTIVE));
+
+       if (reg_val & PHY_RD_ERR) {
+               *val = 0;
+               return -1;
+       }
+       
+       *val = reg_val & 0xffff;
+       return 0;
+}
+
+/* 
+This function will write into PHY registers. 
+*/
+#if 0
+static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val)
+{
+       void *mmio = lp->mmio;
+       unsigned int reg_val;
+       unsigned int retry = PHY_RW_RETRY;
+
+       reg_val = readl(mmio + PHY_ACCESS);
+       while (reg_val & PHY_CMD_ACTIVE)
+               reg_val = readl(mmio + PHY_ACCESS);
+
+       writel(PHY_WR_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16) | val,
+               mmio + PHY_ACCESS);
+       do {
+               reg_val = readl(mmio + PHY_ACCESS);
+               udelay(30);  /* It takes 30 us to read/write the data */
+       } while (--retry && (reg_val & PHY_CMD_ACTIVE));
+       
+       if(reg_val & PHY_RD_ERR)
+               return -1;
+
+       return 0;
+}
+#endif
+
+static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp)
+{
+       int i;
+
+       lp->ext_phy_id = 0;
+       lp->ext_phy_addr = 1;
+       
+       for (i = 0x1e; i >= 0; i--) {
+               u32 id1, id2;
+
+               if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1))
+                       continue;
+               if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2))
+                       continue;
+               lp->ext_phy_id = (id1 << 16) | id2;
+               lp->ext_phy_addr = i;
+               break;
+       }
+
+       if (lp->ext_phy_id)
+               printf("Found MII PHY ID 0x%08x at address 0x%02x\n",
+                       lp->ext_phy_id, lp->ext_phy_addr);
+       else
+               printf("Couldn't detect MII PHY, assuming address 0x01\n");
+}
+
+static void amd8111e_disable_interrupt(struct amd8111e_priv *lp)
+{
+       void *mmio = lp->mmio;
+       unsigned int int0;
+
+       writel(INTREN, mmio + CMD0);
+       writel(INTEN0_CLEAR, mmio + INTEN0);
+       int0 = readl(mmio + INT0);
+       writel(int0, mmio + INT0);
+       readl(mmio + INT0);
+}
+
+static void amd8111e_enable_interrupt(struct amd8111e_priv *lp)
+{
+       void *mmio = lp->mmio;
+
+       writel(VAL3 | LCINTEN | VAL1 | TINTEN0 | VAL0 | RINTEN0, mmio + INTEN0);
+       writel(VAL0 | INTREN, mmio + CMD0);
+       readl(mmio + CMD0);
+}
+
+static void amd8111e_force_interrupt(struct amd8111e_priv *lp)
+{
+       void *mmio = lp->mmio;
+
+       writel(VAL0 | UINTCMD, mmio + CMD0);
+       readl(mmio + CMD0);
+}
+
+static int amd8111e_get_mac_address(struct amd8111e_priv *lp)
+{
+       struct nic *nic = lp->nic;
+       void *mmio = lp->mmio;
+       int i;
+
+       /* BIOS should have set mac address to PADR register,
+        * so we read PADR to get it.
+        */
+       for (i = 0; i < ETH_ALEN; i++)
+               nic->node_addr[i] = readb(mmio + PADR + i);
+       printf("Ethernet addr: %!\n", nic->node_addr);
+
+       return 0;
+}
+
+static int amd8111e_init_rx_ring(struct amd8111e_priv *lp)
+{
+       int i;
+
+       lp->rx_idx = 0;
+       
+        /* Initilaizing receive descriptors */
+       for (i = 0; i < NUM_RX_SLOTS; i++) {
+               lp->rx_ring[i].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[i]));
+               lp->rx_ring[i].buf_len = cpu_to_le16(RX_BUF_LEN);
+               wmb();
+               lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
+       }
+
+       return 0;
+}
+
+static int amd8111e_init_tx_ring(struct amd8111e_priv *lp)
+{
+       int i;
+
+       lp->tx_idx = 0;
+       lp->tx_consistent = 1;
+       
+       /* Initializing transmit descriptors */
+       for (i = 0; i < NUM_TX_SLOTS; i++) {
+               lp->tx_ring[i].tx_flags = 0;
+               lp->tx_ring[i].buf_phy_addr = 0;
+               lp->tx_ring[i].buf_len = 0;
+       }
+
+       return 0;
+}
+
+static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index)
+{
+       volatile u16 status;
+       int retry = TX_RETRY;
+
+       status = le16_to_cpu(lp->tx_ring[index].tx_flags);
+       while (--retry && (status & OWN_BIT)) {
+               mdelay(TX_PROCESS_TIME);
+               status = le16_to_cpu(lp->tx_ring[index].tx_flags);
+       }
+       if (status & OWN_BIT) {
+               printf("Error: tx slot %d timeout, stat = 0x%x\n", index, status);
+               amd8111e_restart(lp);
+               return -1;
+       }
+
+       return 0;
+}
+
+static void amd8111e_wait_link(struct amd8111e_priv *lp)
+{
+       unsigned int status;
+       u32 reg_val;
+
+       do {
+               /* read phy to update STAT0 register */
+               amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, &reg_val);
+               amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, &reg_val);
+               amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, &reg_val);
+               amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, &reg_val);
+               status = readl(lp->mmio + STAT0);
+       } while (!(status & AUTONEG_COMPLETE) || !(status & LINK_STATS));
+}
+
+static void amd8111e_poll_link(struct amd8111e_priv *lp)
+{
+       unsigned int status, speed;
+       u32 reg_val;
+
+       if (!lp->link) {
+               /* read phy to update STAT0 register */
+               amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, &reg_val);
+               amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, &reg_val);
+               amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, &reg_val);
+               amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, &reg_val);
+               status = readl(lp->mmio + STAT0);
+
+               if (status & LINK_STATS) {
+                       lp->link = 1;
+                       speed = (status & SPEED_MASK) >> 7;
+                       if (speed == PHY_SPEED_100)
+                               lp->speed = 1;
+                       else
+                               lp->speed = 0;
+                       if (status & FULL_DPLX)
+                               lp->duplex = 1;
+                       else
+                               lp->duplex = 0;
+
+                       printf("Link is up: %s Mbps %s duplex\n",
+                               lp->speed ? "100" : "10", lp->duplex ? "full" : "half");
+               }
+       } else {
+               status = readl(lp->mmio + STAT0);
+               if (!(status & LINK_STATS)) {
+                       lp->link = 0;
+                       printf("Link is down\n");
+               }
+       }
+}
+
+static void amd8111e_restart(struct amd8111e_priv *lp)
+{
+       printf("\nStarting nic...\n");
+       amd8111e_disable_interrupt(lp);
+       amd8111e_init_hw_default(lp);
+       amd8111e_probe_ext_phy(lp);
+       amd8111e_get_mac_address(lp);
+       amd8111e_start(lp);
+
+       printf("Waiting link up...\n");
+       lp->link = 0;
+       amd8111e_wait_link(lp);
+       amd8111e_poll_link(lp);
+}
+
+
+/********************************************************
+ *             Interface Functions                     *
+ ********************************************************/
+
+static void amd8111e_transmit(struct nic *nic, const char *dst_addr,
+               unsigned int type, unsigned int size, const char *packet)
+{
+       struct amd8111e_priv *lp = nic->priv_data;
+       struct eth_frame *frame;
+       unsigned int index;
+
+       /* check packet size */
+       if (size > TX_PKT_LEN_MAX) {
+               printf("amd8111e_transmit(): too large packet, drop\n");
+               return;
+       }
+
+       /* get tx slot */
+       index = lp->tx_idx;
+       if (amd8111e_wait_tx_ring(lp, index))
+               return;
+
+       /* fill frame */
+       frame = (struct eth_frame *)lp->tx_buf[index];
+       memset(frame->data, 0, TX_PKT_LEN_MAX);
+       memcpy(frame->dst_addr, dst_addr, ETH_ALEN);
+       memcpy(frame->src_addr, nic->node_addr, ETH_ALEN);
+       frame->type = htons(type);
+       memcpy(frame->data, packet, size);
+
+       /* start xmit */
+       lp->tx_ring[index].buf_len = cpu_to_le16(ETH_HLEN + size);
+       lp->tx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(frame));
+       wmb();
+       lp->tx_ring[index].tx_flags = 
+               cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT | ADD_FCS_BIT | LTINT_BIT);
+       writel(VAL1 | TDMD0, lp->mmio + CMD0);
+       readl(lp->mmio + CMD0);
+
+       /* update slot pointer */
+       lp->tx_idx = (lp->tx_idx + 1) & TX_SLOTS_MASK;
+}
+
+static int amd8111e_poll(struct nic *nic, int retrieve)
+{
+       /* return true if there's an ethernet packet ready to read */
+       /* nic->packet should contain data on return */
+       /* nic->packetlen should contain length of data */
+
+       struct amd8111e_priv *lp = nic->priv_data;
+       u16 status, pkt_len;
+       unsigned int index, pkt_ok;
+
+       amd8111e_poll_link(lp);
+
+       index = lp->rx_idx;
+       status = le16_to_cpu(lp->rx_ring[index].rx_flags);
+       pkt_len = le16_to_cpu(lp->rx_ring[index].msg_len) - 4;  /* remove 4bytes FCS */
+       
+       if (status & OWN_BIT)
+               return 0;
+
+       if (status & ERR_BIT)
+               pkt_ok = 0;
+       else if (!(status & STP_BIT))
+               pkt_ok = 0;
+       else if (!(status & ENP_BIT))
+               pkt_ok = 0;
+       else if (pkt_len < RX_PKT_LEN_MIN)
+               pkt_ok = 0;
+       else if (pkt_len > RX_PKT_LEN_MAX)
+               pkt_ok = 0;
+       else
+               pkt_ok = 1;
+
+       if (pkt_ok) {
+               if (!retrieve)
+                       return 1;
+               nic->packetlen = pkt_len;
+               memcpy(nic->packet, lp->rx_buf[index], nic->packetlen);
+       }
+
+       lp->rx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[index]));
+       lp->rx_ring[index].buf_len = cpu_to_le16(RX_BUF_LEN);
+       wmb();
+       lp->rx_ring[index].rx_flags = cpu_to_le16(OWN_BIT);
+       writel(VAL2 | RDMD0, lp->mmio + CMD0);
+       readl(lp->mmio + CMD0);
+
+       lp->rx_idx = (lp->rx_idx + 1) & RX_SLOTS_MASK;
+       return pkt_ok;
+}
+
+static void amd8111e_disable(struct nic *nic)
+{
+       struct amd8111e_priv *lp = nic->priv_data;
+
+       /* disable interrupt */
+       amd8111e_disable_interrupt(lp);
+
+       /* stop chip */
+       amd8111e_init_hw_default(lp);
+
+       /* unmap mmio */
+       iounmap(lp->mmio);
+
+       /* update status */
+       lp->opened = 0;
+}
+
+static void amd8111e_irq(struct nic *nic, irq_action_t action)
+{
+       struct amd8111e_priv *lp = nic->priv_data;
+               
+       switch (action) {
+       case DISABLE:
+               amd8111e_disable_interrupt(lp);
+               break;
+       case ENABLE:
+               amd8111e_enable_interrupt(lp);
+               break;
+       case FORCE:
+               amd8111e_force_interrupt(lp);
+               break;
+       }
+}
+
+static struct nic_operations amd8111e_operations = {
+       .connect        = dummy_connect,
+       .poll           = amd8111e_poll,
+       .transmit       = amd8111e_transmit,
+       .irq            = amd8111e_irq,
+};
+
+static int amd8111e_probe(struct nic *nic, struct pci_device *pdev)
+{
+       struct amd8111e_priv *lp = &amd8111e;
+       unsigned long mmio_start, mmio_len;
+
+       pci_fill_nic ( nic, pdev );
+       
+       mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
+       mmio_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
+
+       memset(lp, 0, sizeof(*lp));
+       lp->pdev = pdev;
+       lp->nic = nic;
+       lp->mmio = ioremap(mmio_start, mmio_len);
+       lp->opened = 1;
+       adjust_pci_device(pdev);
+
+       nic->priv_data = lp;
+
+       amd8111e_restart(lp);
+
+       nic->nic_op     = &amd8111e_operations;
+       return 1;
+}
+
+static struct pci_id amd8111e_nics[] = {
+       PCI_ROM(0x1022, 0x7462, "amd8111e",     "AMD8111E"),
+};
+
+PCI_DRIVER ( amd8111e_driver, amd8111e_nics, PCI_NO_CLASS );
+
+DRIVER ( "AMD8111E", nic_driver, pci_driver, amd8111e_driver,
+        amd8111e_probe, amd8111e_disable );
diff --git a/src/drivers/net/amd8111e.h b/src/drivers/net/amd8111e.h
new file mode 100644 (file)
index 0000000..82b8f7a
--- /dev/null
@@ -0,0 +1,629 @@
+/*
+ * Advanced  Micro Devices Inc. AMD8111E Linux Network Driver 
+ * Copyright (C) 2003 Advanced Micro Devices 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
+ * USA
+
+Module Name:
+
+    amd8111e.h
+
+Abstract:
+       
+        AMD8111 based 10/100 Ethernet Controller driver definitions. 
+
+Environment:
+    
+       Kernel Mode
+
+Revision History:
+       3.0.0
+          Initial Revision.
+       3.0.1
+*/
+
+#ifndef _AMD811E_H
+#define _AMD811E_H
+
+/* Command style register access
+
+Registers CMD0, CMD2, CMD3,CMD7 and INTEN0 uses a write access technique called command style access. It allows the write to selected bits of this register without altering the bits that are not selected. Command style registers are divided into 4 bytes that can be written independently. Higher order bit of each byte is the  value bit that specifies the value that will be written into the selected bits of register. 
+
+eg., if the value 10011010b is written into the least significant byte of a command style register, bits 1,3 and 4 of the register will be set to 1, and the other bits will not be altered. If the value 00011010b is written into the same byte, bits 1,3 and 4 will be cleared to 0 and the other bits will not be altered.
+
+*/
+
+/*  Offset for Memory Mapped Registers. */
+/* 32 bit registers */
+
+#define  ASF_STAT              0x00    /* ASF status register */
+#define CHIPID                 0x04    /* Chip ID regsiter */
+#define        MIB_DATA                0x10    /* MIB data register */
+#define MIB_ADDR               0x14    /* MIB address register */
+#define STAT0                  0x30    /* Status0 register */
+#define INT0                   0x38    /* Interrupt0 register */
+#define INTEN0                 0x40    /* Interrupt0  enable register*/
+#define CMD0                   0x48    /* Command0 register */
+#define CMD2                   0x50    /* Command2 register */
+#define CMD3                   0x54    /* Command3 resiter */
+#define CMD7                   0x64    /* Command7 register */
+
+#define CTRL1                  0x6C    /* Control1 register */
+#define CTRL2                  0x70    /* Control2 register */
+
+#define XMT_RING_LIMIT         0x7C    /* Transmit ring limit register */
+
+#define AUTOPOLL0              0x88    /* Auto-poll0 register */
+#define AUTOPOLL1              0x8A    /* Auto-poll1 register */
+#define AUTOPOLL2              0x8C    /* Auto-poll2 register */
+#define AUTOPOLL3              0x8E    /* Auto-poll3 register */
+#define AUTOPOLL4              0x90    /* Auto-poll4 register */
+#define        AUTOPOLL5               0x92    /* Auto-poll5 register */
+
+#define AP_VALUE               0x98    /* Auto-poll value register */
+#define DLY_INT_A              0xA8    /* Group A delayed interrupt register */
+#define DLY_INT_B              0xAC    /* Group B delayed interrupt register */
+
+#define FLOW_CONTROL           0xC8    /* Flow control register */
+#define PHY_ACCESS             0xD0    /* PHY access register */
+
+#define STVAL                  0xD8    /* Software timer value register */
+
+#define XMT_RING_BASE_ADDR0    0x100   /* Transmit ring0 base addr register */
+#define XMT_RING_BASE_ADDR1    0x108   /* Transmit ring1 base addr register */
+#define XMT_RING_BASE_ADDR2    0x110   /* Transmit ring2 base addr register */
+#define XMT_RING_BASE_ADDR3    0x118   /* Transmit ring2 base addr register */
+
+#define RCV_RING_BASE_ADDR0    0x120   /* Transmit ring0 base addr register */
+
+#define PMAT0                  0x190   /* OnNow pattern register0 */
+#define PMAT1                  0x194   /* OnNow pattern register1 */
+
+/* 16bit registers */
+
+#define XMT_RING_LEN0          0x140   /* Transmit Ring0 length register */
+#define XMT_RING_LEN1          0x144   /* Transmit Ring1 length register */
+#define XMT_RING_LEN2          0x148   /* Transmit Ring2 length register */
+#define XMT_RING_LEN3          0x14C   /* Transmit Ring3 length register */
+
+#define RCV_RING_LEN0          0x150   /* Receive Ring0 length register */
+
+#define SRAM_SIZE              0x178   /* SRAM size register */
+#define SRAM_BOUNDARY          0x17A   /* SRAM boundary register */
+
+/* 48bit register */
+
+#define PADR                   0x160   /* Physical address register */
+
+#define IFS1                   0x18C   /* Inter-frame spacing Part1 register */
+#define IFS                    0x18D   /* Inter-frame spacing register */
+#define IPG                    0x18E   /* Inter-frame gap register */
+/* 64bit register */
+
+#define LADRF                  0x168   /* Logical address filter register */
+
+
+/* Register Bit Definitions */
+typedef enum {
+
+       ASF_INIT_DONE           = (1 << 1),
+       ASF_INIT_PRESENT        = (1 << 0),
+
+}STAT_ASF_BITS; 
+   
+typedef enum {
+
+       MIB_CMD_ACTIVE          = (1 << 15 ),
+       MIB_RD_CMD              = (1 << 13 ),
+       MIB_CLEAR               = (1 << 12 ),
+       MIB_ADDRESS             = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)|
+                                       (1 << 4) | (1 << 5),
+}MIB_ADDR_BITS;
+
+
+typedef enum {
+       
+       PMAT_DET                = (1 << 12),
+       MP_DET                  = (1 << 11),
+       LC_DET                  = (1 << 10),
+       SPEED_MASK              = (1 << 9)|(1 << 8)|(1 << 7),
+       FULL_DPLX               = (1 << 6),
+       LINK_STATS              = (1 << 5),
+       AUTONEG_COMPLETE        = (1 << 4),
+       MIIPD                   = (1 << 3),
+       RX_SUSPENDED            = (1 << 2),
+       TX_SUSPENDED            = (1 << 1),
+       RUNNING                 = (1 << 0),
+
+}STAT0_BITS;
+
+#define PHY_SPEED_10           0x2
+#define PHY_SPEED_100          0x3
+
+/* INT0                                0x38, 32bit register */
+typedef enum {
+
+       INTR                    = (1 << 31),
+       PCSINT                  = (1 << 28), 
+       LCINT                   = (1 << 27),
+       APINT5                  = (1 << 26),
+       APINT4                  = (1 << 25),
+       APINT3                  = (1 << 24),
+       TINT_SUM                = (1 << 23),
+       APINT2                  = (1 << 22),
+       APINT1                  = (1 << 21),
+       APINT0                  = (1 << 20),
+       MIIPDTINT               = (1 << 19),
+       MCCINT                  = (1 << 17),
+       MREINT                  = (1 << 16),
+       RINT_SUM                = (1 << 15),
+       SPNDINT                 = (1 << 14),
+       MPINT                   = (1 << 13),
+       SINT                    = (1 << 12),
+       TINT3                   = (1 << 11),
+       TINT2                   = (1 << 10),
+       TINT1                   = (1 << 9),
+       TINT0                   = (1 << 8),
+       UINT                    = (1 << 7),
+       STINT                   = (1 << 4),
+       RINT0                   = (1 << 0),
+
+}INT0_BITS;
+
+typedef enum {
+
+       VAL3                    = (1 << 31),   /* VAL bit for byte 3 */
+       VAL2                    = (1 << 23),   /* VAL bit for byte 2 */
+       VAL1                    = (1 << 15),   /* VAL bit for byte 1 */
+       VAL0                    = (1 << 7),    /* VAL bit for byte 0 */
+
+}VAL_BITS;
+
+typedef enum {
+
+       /* VAL3 */
+       LCINTEN                 = (1 << 27),
+       APINT5EN                = (1 << 26),
+       APINT4EN                = (1 << 25),
+       APINT3EN                = (1 << 24),
+       /* VAL2 */
+       APINT2EN                = (1 << 22),
+       APINT1EN                = (1 << 21),
+       APINT0EN                = (1 << 20),
+       MIIPDTINTEN             = (1 << 19),
+       MCCIINTEN               = (1 << 18),
+       MCCINTEN                = (1 << 17),
+       MREINTEN                = (1 << 16),
+       /* VAL1 */
+       SPNDINTEN               = (1 << 14),
+       MPINTEN                 = (1 << 13),
+       TINTEN3                 = (1 << 11),
+       SINTEN                  = (1 << 12),
+       TINTEN2                 = (1 << 10),
+       TINTEN1                 = (1 << 9),
+       TINTEN0                 = (1 << 8),
+       /* VAL0 */
+       STINTEN                 = (1 << 4),
+       RINTEN0                 = (1 << 0),
+
+       INTEN0_CLEAR            = 0x1F7F7F1F, /* Command style register */
+
+}INTEN0_BITS;          
+
+typedef enum {
+       /* VAL2 */
+       RDMD0                   = (1 << 16),
+       /* VAL1 */
+       TDMD3                   = (1 << 11),
+       TDMD2                   = (1 << 10),
+       TDMD1                   = (1 << 9),
+       TDMD0                   = (1 << 8),
+       /* VAL0 */
+       UINTCMD                 = (1 << 6),
+       RX_FAST_SPND            = (1 << 5),
+       TX_FAST_SPND            = (1 << 4),
+       RX_SPND                 = (1 << 3),
+       TX_SPND                 = (1 << 2),
+       INTREN                  = (1 << 1),
+       RUN                     = (1 << 0),
+
+       CMD0_CLEAR              = 0x000F0F7F,   /* Command style register */    
+
+}CMD0_BITS;
+
+typedef enum {
+
+       /* VAL3 */
+       CONDUIT_MODE            = (1 << 29),
+       /* VAL2 */
+       RPA                     = (1 << 19),
+       DRCVPA                  = (1 << 18),
+       DRCVBC                  = (1 << 17),
+       PROM                    = (1 << 16),
+       /* VAL1 */
+       ASTRP_RCV               = (1 << 13),
+       RCV_DROP0               = (1 << 12),
+       EMBA                    = (1 << 11),
+       DXMT2PD                 = (1 << 10),
+       LTINTEN                 = (1 << 9),
+       DXMTFCS                 = (1 << 8),
+       /* VAL0 */
+       APAD_XMT                = (1 << 6),
+       DRTY                    = (1 << 5),
+       INLOOP                  = (1 << 4),
+       EXLOOP                  = (1 << 3),
+       REX_RTRY                = (1 << 2),
+       REX_UFLO                = (1 << 1),
+       REX_LCOL                = (1 << 0),
+
+       CMD2_CLEAR              = 0x3F7F3F7F,   /* Command style register */
+
+}CMD2_BITS;
+
+typedef enum {
+
+       /* VAL3 */
+       ASF_INIT_DONE_ALIAS     = (1 << 29),
+       /* VAL2 */
+       JUMBO                   = (1 << 21),
+       VSIZE                   = (1 << 20),    
+       VLONLY                  = (1 << 19),
+       VL_TAG_DEL              = (1 << 18),    
+       /* VAL1 */
+       EN_PMGR                 = (1 << 14),                    
+       INTLEVEL                = (1 << 13),
+       FORCE_FULL_DUPLEX       = (1 << 12),    
+       FORCE_LINK_STATUS       = (1 << 11),    
+       APEP                    = (1 << 10),    
+       MPPLBA                  = (1 << 9),     
+       /* VAL0 */
+       RESET_PHY_PULSE         = (1 << 2),     
+       RESET_PHY               = (1 << 1),     
+       PHY_RST_POL             = (1 << 0),     
+
+}CMD3_BITS;
+
+
+typedef enum {
+
+       /* VAL0 */
+       PMAT_SAVE_MATCH         = (1 << 4),
+       PMAT_MODE               = (1 << 3),
+       MPEN_SW                 = (1 << 1),
+       LCMODE_SW               = (1 << 0),
+
+       CMD7_CLEAR              = 0x0000001B    /* Command style register */
+
+}CMD7_BITS;
+
+
+typedef enum {
+
+       RESET_PHY_WIDTH         = (0xF << 16) | (0xF<< 20), /* 0x00FF0000 */
+       XMTSP_MASK              = (1 << 9) | (1 << 8),  /* 9:8 */
+       XMTSP_128               = (1 << 9),     /* 9 */ 
+       XMTSP_64                = (1 << 8),
+       CACHE_ALIGN             = (1 << 4),
+       BURST_LIMIT_MASK        = (0xF << 0 ),
+       CTRL1_DEFAULT           = 0x00010111,
+
+}CTRL1_BITS;
+
+typedef enum {
+
+       FMDC_MASK               = (1 << 9)|(1 << 8),    /* 9:8 */
+       XPHYRST                 = (1 << 7),
+       XPHYANE                 = (1 << 6),
+       XPHYFD                  = (1 << 5),
+       XPHYSP                  = (1 << 4) | (1 << 3),  /* 4:3 */
+       APDW_MASK               = (1 << 2) | (1 << 1) | (1 << 0), /* 2:0 */
+
+}CTRL2_BITS;
+
+/* XMT_RING_LIMIT              0x7C, 32bit register */
+typedef enum {
+
+       XMT_RING2_LIMIT         = (0xFF << 16), /* 23:16 */
+       XMT_RING1_LIMIT         = (0xFF << 8),  /* 15:8 */
+       XMT_RING0_LIMIT         = (0xFF << 0),  /* 7:0 */
+
+}XMT_RING_LIMIT_BITS;
+
+typedef enum {
+
+       AP_REG0_EN              = (1 << 15),
+       AP_REG0_ADDR_MASK       = (0xF << 8) |(1 << 12),/* 12:8 */
+       AP_PHY0_ADDR_MASK       = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL0_BITS;
+
+/* AUTOPOLL1                   0x8A, 16bit register */
+typedef enum {
+
+       AP_REG1_EN              = (1 << 15),
+       AP_REG1_ADDR_MASK       = (0xF << 8) |(1 << 12),/* 12:8 */
+       AP_PRE_SUP1             = (1 << 6),
+       AP_PHY1_DFLT            = (1 << 5),
+       AP_PHY1_ADDR_MASK       = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL1_BITS;
+
+
+typedef enum {
+
+       AP_REG2_EN              = (1 << 15),
+       AP_REG2_ADDR_MASK       = (0xF << 8) |(1 << 12),/* 12:8 */
+       AP_PRE_SUP2             = (1 << 6),
+       AP_PHY2_DFLT            = (1 << 5),
+       AP_PHY2_ADDR_MASK       = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL2_BITS;
+
+typedef enum {
+
+       AP_REG3_EN              = (1 << 15),
+       AP_REG3_ADDR_MASK       = (0xF << 8) |(1 << 12),/* 12:8 */
+       AP_PRE_SUP3             = (1 << 6),
+       AP_PHY3_DFLT            = (1 << 5),
+       AP_PHY3_ADDR_MASK       = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL3_BITS;
+
+
+typedef enum {
+
+       AP_REG4_EN              = (1 << 15),
+       AP_REG4_ADDR_MASK       = (0xF << 8) |(1 << 12),/* 12:8 */
+       AP_PRE_SUP4             = (1 << 6),
+       AP_PHY4_DFLT            = (1 << 5),
+       AP_PHY4_ADDR_MASK       = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL4_BITS;
+
+
+typedef enum {
+
+       AP_REG5_EN              = (1 << 15),
+       AP_REG5_ADDR_MASK       = (0xF << 8) |(1 << 12),/* 12:8 */
+       AP_PRE_SUP5             = (1 << 6),
+       AP_PHY5_DFLT            = (1 << 5),
+       AP_PHY5_ADDR_MASK       = (0xF << 0) |(1 << 4),/* 4:0 */
+
+}AUTOPOLL5_BITS;
+
+
+
+
+/* AP_VALUE                    0x98, 32bit ragister */
+typedef enum {
+
+       AP_VAL_ACTIVE           = (1 << 31),
+       AP_VAL_RD_CMD           = ( 1 << 29),
+       AP_ADDR                 = (1 << 18)|(1 << 17)|(1 << 16), /* 18:16 */
+       AP_VAL                  = (0xF << 0) | (0xF << 4) |( 0xF << 8) |
+                                 (0xF << 12),  /* 15:0 */
+
+}AP_VALUE_BITS;
+
+typedef enum {
+
+       DLY_INT_A_R3            = (1 << 31),
+       DLY_INT_A_R2            = (1 << 30),
+       DLY_INT_A_R1            = (1 << 29),
+       DLY_INT_A_R0            = (1 << 28),
+       DLY_INT_A_T3            = (1 << 27),
+       DLY_INT_A_T2            = (1 << 26),
+       DLY_INT_A_T1            = (1 << 25),
+       DLY_INT_A_T0            = ( 1 << 24),
+       EVENT_COUNT_A           = (0xF << 16) | (0x1 << 20),/* 20:16 */
+       MAX_DELAY_TIME_A        = (0xF << 0) | (0xF << 4) | (1 << 8)|
+                                 (1 << 9) | (1 << 10), /* 10:0 */
+
+}DLY_INT_A_BITS;
+
+typedef enum {
+
+       DLY_INT_B_R3            = (1 << 31),
+       DLY_INT_B_R2            = (1 << 30),
+       DLY_INT_B_R1            = (1 << 29),
+       DLY_INT_B_R0            = (1 << 28),
+       DLY_INT_B_T3            = (1 << 27),
+       DLY_INT_B_T2            = (1 << 26),
+       DLY_INT_B_T1            = (1 << 25),
+       DLY_INT_B_T0            = ( 1 << 24),
+       EVENT_COUNT_B           = (0xF << 16) | (0x1 << 20),/* 20:16 */
+       MAX_DELAY_TIME_B        = (0xF << 0) | (0xF << 4) | (1 << 8)| 
+                                 (1 << 9) | (1 << 10), /* 10:0 */
+}DLY_INT_B_BITS;
+
+
+/* FLOW_CONTROL                0xC8, 32bit register */
+typedef enum {
+
+       PAUSE_LEN_CHG           = (1 << 30),
+       FTPE                    = (1 << 22),
+       FRPE                    = (1 << 21),
+       NAPA                    = (1 << 20),
+       NPA                     = (1 << 19),
+       FIXP                    = ( 1 << 18),
+       FCCMD                   = ( 1 << 16),
+       PAUSE_LEN               = (0xF << 0) | (0xF << 4) |( 0xF << 8) |                                          (0xF << 12),  /* 15:0 */
+
+}FLOW_CONTROL_BITS;
+
+/* PHY_ ACCESS                 0xD0, 32bit register */
+typedef enum {
+
+       PHY_CMD_ACTIVE          = (1 << 31),
+       PHY_WR_CMD              = (1 << 30),
+       PHY_RD_CMD              = (1 << 29),
+       PHY_RD_ERR              = (1 << 28),
+       PHY_PRE_SUP             = (1 << 27),
+       PHY_ADDR                = (1 << 21) | (1 << 22) | (1 << 23)|
+                                       (1 << 24) |(1 << 25),/* 25:21 */
+       PHY_REG_ADDR            = (1 << 16) | (1 << 17) | (1 << 18)|                                                    (1 << 19) | (1 << 20),/* 20:16 */
+       PHY_DATA                = (0xF << 0)|(0xF << 4) |(0xF << 8)|
+                                       (0xF << 12),/* 15:0 */
+
+}PHY_ACCESS_BITS;
+
+
+/* PMAT0                       0x190,   32bit register */
+typedef enum {
+       PMR_ACTIVE              = (1 << 31),
+       PMR_WR_CMD              = (1 << 30),
+       PMR_RD_CMD              = (1 << 29),
+       PMR_BANK                = (1 <<28),
+       PMR_ADDR                = (0xF << 16)|(1 << 20)|(1 << 21)|
+                                       (1 << 22),/* 22:16 */
+       PMR_B4                  = (0xF << 0) | (0xF << 4),/* 15:0 */
+}PMAT0_BITS;
+
+
+/* PMAT1                       0x194,   32bit register */
+typedef enum {
+       PMR_B3                  = (0xF << 24) | (0xF <<28),/* 31:24 */
+       PMR_B2                  = (0xF << 16) |(0xF << 20),/* 23:16 */
+       PMR_B1                  = (0xF << 8) | (0xF <<12), /* 15:8 */
+       PMR_B0                  = (0xF << 0)|(0xF << 4),/* 7:0 */
+}PMAT1_BITS;
+
+/************************************************************************/
+/*                                                                      */
+/*                      MIB counter definitions                         */
+/*                                                                      */
+/************************************************************************/
+
+#define rcv_miss_pkts                          0x00
+#define rcv_octets                             0x01
+#define rcv_broadcast_pkts                     0x02
+#define rcv_multicast_pkts                     0x03
+#define rcv_undersize_pkts                     0x04
+#define rcv_oversize_pkts                      0x05
+#define rcv_fragments                          0x06
+#define rcv_jabbers                            0x07
+#define rcv_unicast_pkts                       0x08
+#define rcv_alignment_errors                   0x09
+#define rcv_fcs_errors                         0x0A
+#define rcv_good_octets                                0x0B
+#define rcv_mac_ctrl                           0x0C
+#define rcv_flow_ctrl                          0x0D
+#define rcv_pkts_64_octets                     0x0E
+#define rcv_pkts_65to127_octets                        0x0F
+#define rcv_pkts_128to255_octets               0x10
+#define rcv_pkts_256to511_octets               0x11
+#define rcv_pkts_512to1023_octets              0x12
+#define rcv_pkts_1024to1518_octets             0x13
+#define rcv_unsupported_opcode                 0x14
+#define rcv_symbol_errors                      0x15
+#define rcv_drop_pkts_ring1                    0x16
+#define rcv_drop_pkts_ring2                    0x17
+#define rcv_drop_pkts_ring3                    0x18
+#define rcv_drop_pkts_ring4                    0x19
+#define rcv_jumbo_pkts                         0x1A
+
+#define xmt_underrun_pkts                      0x20
+#define xmt_octets                             0x21
+#define xmt_packets                            0x22
+#define xmt_broadcast_pkts                     0x23
+#define xmt_multicast_pkts                     0x24
+#define xmt_collisions                         0x25
+#define xmt_unicast_pkts                       0x26
+#define xmt_one_collision                      0x27
+#define xmt_multiple_collision                 0x28
+#define xmt_deferred_transmit                  0x29
+#define xmt_late_collision                     0x2A
+#define xmt_excessive_defer                    0x2B
+#define xmt_loss_carrier                       0x2C
+#define xmt_excessive_collision                        0x2D
+#define xmt_back_pressure                      0x2E
+#define xmt_flow_ctrl                          0x2F
+#define xmt_pkts_64_octets                     0x30
+#define xmt_pkts_65to127_octets                        0x31
+#define xmt_pkts_128to255_octets               0x32
+#define xmt_pkts_256to511_octets               0x33
+#define xmt_pkts_512to1023_octets              0x34
+#define xmt_pkts_1024to1518_octet              0x35
+#define xmt_oversize_pkts                      0x36
+#define xmt_jumbo_pkts                         0x37
+
+/* ipg parameters */
+#define DEFAULT_IPG                    0x60
+#define IFS1_DELTA                     36
+#define        IPG_CONVERGE_JIFFIES (HZ/2)
+#define        IPG_STABLE_TIME 5
+#define        MIN_IPG 96
+#define        MAX_IPG 255
+#define IPG_STEP       16
+#define CSTATE  1 
+#define SSTATE  2 
+
+/* amd8111e decriptor flag definitions */
+typedef enum {
+
+       OWN_BIT         =       (1 << 15),
+       ADD_FCS_BIT     =       (1 << 13),
+       LTINT_BIT       =       (1 << 12),
+       STP_BIT         =       (1 << 9),
+       ENP_BIT         =       (1 << 8),
+       KILL_BIT        =       (1 << 6),
+       TCC_VLAN_INSERT =       (1 << 1),
+       TCC_VLAN_REPLACE =      (1 << 1) |( 1<< 0),
+
+}TX_FLAG_BITS;
+
+typedef enum {
+       ERR_BIT         =       (1 << 14),
+       FRAM_BIT        =       (1 << 13),
+       OFLO_BIT        =       (1 << 12),
+       CRC_BIT         =       (1 << 11),
+       PAM_BIT         =       (1 << 6),
+       LAFM_BIT        =       (1 << 5),
+       BAM_BIT         =       (1 << 4),
+       TT_VLAN_TAGGED  =       (1 << 3) |(1 << 2),/* 0x000 */
+       TT_PRTY_TAGGED  =       (1 << 3),/* 0x0008 */
+
+}RX_FLAG_BITS;
+
+#define RESET_RX_FLAGS         0x0000
+#define TT_MASK                        0x000c
+#define TCC_MASK               0x0003
+
+/* driver ioctl parameters */
+#define AMD8111E_REG_DUMP_LEN   13*sizeof(u32) 
+
+/* crc generator constants */
+#define CRC32 0xedb88320
+#define INITCRC 0xFFFFFFFF
+
+/* kernel provided writeq does not write 64 bits into the amd8111e device register instead writes only higher 32bits data into lower 32bits of the register.
+BUG? */
+#define  amd8111e_writeq(_UlData,_memMap)   \
+               writel(*(u32*)(&_UlData), _memMap);     \
+               writel(*(u32*)((u8*)(&_UlData)+4), _memMap+4)   
+
+/* maps the external speed options to internal value */
+typedef enum {
+       SPEED_AUTONEG,
+       SPEED10_HALF,
+       SPEED10_FULL,
+       SPEED100_HALF,
+       SPEED100_FULL,
+}EXT_PHY_OPTION;
+
+
+#endif /* _AMD8111E_H */
+
index fdbf983..d087e29 100644 (file)
 
 #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,
index 3707da6..cc904c7 100644 (file)
@@ -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. 
 */
index 4061ebf..e1ff44e 100644 (file)
 #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))
index 6c2318b..65c6c8f 100644 (file)
@@ -18,6 +18,12 @@ Be careful with seating the EPROM as the socket on my board actually
 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 +263,8 @@ static unsigned eeprom_reg = EEPROM_REG_PRO;
 #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 +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 +344,7 @@ POLL - Wait for a frame
 ***************************************************************************/
 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 */
@@ -380,8 +388,12 @@ static int eepro_poll(struct nic *nic, int retrieve)
 }
 #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 +467,7 @@ static void eepro_disable ( struct nic *nic, struct isa_device *isa __unused ) {
        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);
index 590b37c..d97b1b1 100644 (file)
 
 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. */
index 3297eff..6377383 100644 (file)
 *      (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))
@@ -73,22 +71,35 @@ typedef signed int s32;
 
 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
@@ -98,7 +109,7 @@ enum {
 #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
@@ -125,7 +136,7 @@ enum {
 
        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,
@@ -134,6 +145,8 @@ enum {
        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
@@ -147,6 +160,9 @@ enum {
        NvRegMulticastMaskA = 0xB8,
        NvRegMulticastMaskB = 0xBC,
 
+       NvRegPhyInterface = 0xC0,
+#define PHY_RGMII              0x10000000
+
        NvRegTxRingPhysAddr = 0x100,
        NvRegRxRingPhysAddr = 0x104,
        NvRegRingSizes = 0x108,
@@ -155,12 +171,12 @@ enum {
        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
@@ -168,6 +184,7 @@ enum {
 #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
@@ -179,15 +196,15 @@ enum {
        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,
@@ -201,6 +218,7 @@ enum {
 #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,
@@ -218,30 +236,61 @@ enum {
 #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
@@ -266,27 +315,73 @@ enum {
 #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 +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 +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 +488,11 @@ static int mii_rw(struct nic *nic __unused, int addr, int miireg,
                  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);
@@ -402,7 +500,7 @@ static int mii_rw(struct nic *nic __unused, int addr, int miireg,
        }
 
        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;
@@ -424,20 +522,123 @@ static int mii_rw(struct nic *nic __unused, int addr, int miireg,
                         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 +698,12 @@ static void txrx_reset(struct nic *nic __unused)
        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 +721,9 @@ static int alloc_rx(struct nic *nic __unused)
                //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++;
@@ -534,8 +736,67 @@ static int alloc_rx(struct nic *nic __unused)
 
 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",
@@ -560,30 +821,81 @@ static int update_linkspeed(struct nic *nic)
                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 +949,21 @@ static int forcedeth_reset(struct nic *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 */
        {
@@ -661,51 +979,40 @@ static int forcedeth_reset(struct nic *nic)
                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);
@@ -714,8 +1021,8 @@ static int forcedeth_reset(struct nic *nic)
        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);
@@ -724,36 +1031,24 @@ static int forcedeth_reset(struct nic *nic)
        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);
@@ -768,22 +1063,32 @@ static int forcedeth_reset(struct nic *nic)
               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 +1098,35 @@ static int forcedeth_poll(struct nic *nic, int retrieve)
        /* 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 +1145,6 @@ static void forcedeth_transmit(struct nic *nic, const char *d,     /* Destination */
        /* send the packet to destination */
        u8 *ptxb;
        u16 nstype;
-       //u16 status;
        u8 *base = (u8 *) BASE;
        int nr = np->next_tx % TX_RING;
 
@@ -851,14 +1164,12 @@ static void forcedeth_transmit(struct nic *nic, const char *d,   /* Destination */
                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 +1207,17 @@ static void forcedeth_disable ( struct nic *nic __unused ) {
 /**************************************************************************
 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 = {
@@ -916,14 +1228,6 @@ 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 +1239,7 @@ static int forcedeth_probe ( struct nic *nic, struct pci_device *pci ) {
        unsigned long addr;
        int sz;
        u8 *base;
+       int i;
 
        if (pci->ioaddr == 0)
                return 0;
@@ -956,6 +1261,15 @@ static int forcedeth_probe ( struct nic *nic, struct pci_device *pci ) {
        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; 
 
@@ -992,36 +1306,121 @@ static int forcedeth_probe ( struct nic *nic, struct pci_device *pci ) {
 #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 );
index 3d974ab..c7754a9 100644 (file)
 /* 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))
index 003b979..774b5e3 100644 (file)
 
 #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))
index d4fafb6..df9eec5 100755 (executable)
 #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. */
index 5a0bb14..4255269 100644 (file)
 #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;
index ad3b62b..427fad0 100644 (file)
 #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;
index 89aa3aa..e88e111 100644 (file)
@@ -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)
 
index 05621d4..701f922 100644 (file)
 #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. */
index 2d881f0..ace2dfe 100644 (file)
@@ -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 +2414,9 @@ static struct subsys_tbl_ent subsys_id_to_phy_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 */
index 6e05b9c..fd038f5 100644 (file)
@@ -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;
index e0379a7..de57d59 100644 (file)
 * 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
index 28e38d9..279e0db 100644 (file)
@@ -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 +120,6 @@ static int tulip_debug = 2;             /* 1 normal messages, 0 quiet .. 7 verbo
 
 #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 +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 +228,8 @@ static const struct pci_id_info pci_id_tbl[] = {
       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 +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 +2066,7 @@ PCI_ROM(0x125b, 0x1400, "ax88140",     "ASIX 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"),
index 1ed3503..c3f03f9 100644 (file)
 
 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)
index 0085c7d..ee06371 100644 (file)
@@ -3,39 +3,35 @@
 
 #include "stdint.h"
 
-/*
- * "start" and "end" denote the real boundaries of the buffer.  "fill"
- * denotes the offset to the first free block in the buffer.  (If the
- * buffer is full, "fill" will equal ( end - start ) ).
+/* @file */
+
+/**
+ * A buffer
+ *
+ * @c start and @c end denote the real boundaries of the buffer, and
+ * are physical addresses.  @c fill denotes the offset to the first
+ * free block in the buffer.  (If the buffer is full, @c fill will
+ * equal @c end-start.)
  *
  */
 struct buffer {
-       physaddr_t      start;
-       physaddr_t      end;
-       off_t           fill;
+       physaddr_t      start;          /**< Start of buffer in memory */
+       physaddr_t      end;            /**< End of buffer in memory */
+       off_t           fill;           /**< Offset to first gap in buffer */
 };
 
-/*
- * Free blocks in the buffer start with a "tail byte".  If non-zero,
- * this byte indicates that the free block is the tail of the buffer,
- * i.e. occupies all the remaining space up to the end of the buffer.
- * When the tail byte is non-zero, it indicates that the remainder of
- * the descriptor (the struct buffer_free_block) follows the tail
- * byte.
+/**
+ * A free block descriptor.
  *
- * This scheme is necessary because we may end up with a tail that is
- * smaller than a struct buffer_free_block.
+ * See \ref buffer_int for a full description of the fields.
  *
  */
 struct buffer_free_block {
-       char            tail;
-       physaddr_t      next_free;
-       physaddr_t      end;
+       char            tail;           /**< Tail byte marker */
+       physaddr_t      next_free;      /**< Address of next free block */
+       physaddr_t      end;            /**< End of this block */
 } __attribute__ (( packed ));
 
-/* This must be provided by the architecture-dependent load_buffer.c */
-extern struct buffer load_buffer;
-
 /* Functions in buffer.c */
 
 extern void init_buffer ( struct buffer *buffer );
index 4a7c48a..d02078b 100644 (file)
@@ -1,7 +1,17 @@
 #ifndef COMPILER_H
 #define COMPILER_H
 
-/* We export the symbol obj_OBJECT (OBJECT is defined on command-line)
+/*
+ * Doxygen can't cope with some of the more esoteric areas of C, so we
+ * make its life simpler.
+ *
+ */
+#ifdef DOXYGEN
+#define __attribute__(x)
+#endif
+
+/*
+ * We export the symbol obj_OBJECT (OBJECT is defined on command-line)
  * as a global symbol, so that the linker can drag in selected object
  * files from the library using -u obj_OBJECT.
  *
diff --git a/src/include/errno.h b/src/include/errno.h
new file mode 100644 (file)
index 0000000..e122d9c
--- /dev/null
@@ -0,0 +1,141 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+
+/** @file
+ *
+ * Error codes
+ *
+ */
+
+/* PXE error codes are determined by the PXE specification */
+
+/* Generic errors */
+#define        PXENV_STATUS_SUCCESS                            0x00
+#define        PXENV_STATUS_FAILURE                            0x01
+#define        PXENV_STATUS_BAD_FUNC                           0x02
+#define        PXENV_STATUS_UNSUPPORTED                        0x03
+#define        PXENV_STATUS_KEEP_UNDI                          0x04
+#define        PXENV_STATUS_KEEP_ALL                           0x05
+#define        PXENV_STATUS_OUT_OF_RESOURCES                   0x06
+
+/* ARP errors (0x10 to 0x1f) */
+#define        PXENV_STATUS_ARP_TIMEOUT                        0x11
+
+/* Base-Code state errors */
+#define        PXENV_STATUS_UDP_CLOSED                         0x18
+#define        PXENV_STATUS_UDP_OPEN                           0x19
+#define        PXENV_STATUS_TFTP_CLOSED                        0x1a
+#define        PXENV_STATUS_TFTP_OPEN                          0x1b
+
+/* BIOS/system errors (0x20 to 0x2f) */
+#define        PXENV_STATUS_MCOPY_PROBLEM                      0x20
+#define        PXENV_STATUS_BIS_INTEGRITY_FAILURE              0x21
+#define        PXENV_STATUS_BIS_VALIDATE_FAILURE               0x22
+#define        PXENV_STATUS_BIS_INIT_FAILURE                   0x23
+#define        PXENV_STATUS_BIS_SHUTDOWN_FAILURE               0x24
+#define        PXENV_STATUS_BIS_GBOA_FAILURE                   0x25
+#define        PXENV_STATUS_BIS_FREE_FAILURE                   0x26
+#define        PXENV_STATUS_BIS_GSI_FAILURE                    0x27
+#define        PXENV_STATUS_BIS_BAD_CKSUM                      0x28
+
+/* TFTP/MTFTP errors (0x30 to 0x3f) */
+#define        PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS            0x30
+#define        PXENV_STATUS_TFTP_OPEN_TIMEOUT                  0x32
+#define        PXENV_STATUS_TFTP_UNKNOWN_OPCODE                0x33
+#define        PXENV_STATUS_TFTP_READ_TIMEOUT                  0x35
+#define        PXENV_STATUS_TFTP_ERROR_OPCODE                  0x36
+#define        PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION        0x38
+#define        PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION   0x39
+#define        PXENV_STATUS_TFTP_TOO_MANY_PACKAGES             0x3a
+#define        PXENV_STATUS_TFTP_FILE_NOT_FOUND                0x3b
+#define        PXENV_STATUS_TFTP_ACCESS_VIOLATION              0x3c
+#define        PXENV_STATUS_TFTP_NO_MCAST_ADDRESS              0x3d
+#define        PXENV_STATUS_TFTP_NO_FILESIZE                   0x3e
+#define        PXENV_STATUS_TFTP_INVALID_PACKET_SIZE           0x3f
+
+/* Reserved errors 0x40 to 0x4f) */
+
+/* DHCP/BOOTP errors (0x50 to 0x5f) */
+#define        PXENV_STATUS_DHCP_TIMEOUT                       0x51
+#define        PXENV_STATUS_DHCP_NO_IP_ADDRESS                 0x52
+#define        PXENV_STATUS_DHCP_NO_BOOTFILE_NAME              0x53
+#define        PXENV_STATUS_DHCP_BAD_IP_ADDRESS                0x54
+
+/* Driver errors (0x60 to 0x6f) */
+#define        PXENV_STATUS_UNDI_INVALID_FUNCTION              0x60
+#define        PXENV_STATUS_UNDI_MEDIATEST_FAILED              0x61
+#define        PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST     0x62
+#define        PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC         0x63
+#define        PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY         0x64
+#define        PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA       0x65
+#define        PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA         0x66
+#define        PXENV_STATUS_UNDI_BAD_MAC_ADDRESS               0x67
+#define        PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM           0x68
+#define        PXENV_STATUS_UNDI_ERROR_SETTING_ISR             0x69
+#define        PXENV_STATUS_UNDI_INVALID_STATE                 0x6a
+#define        PXENV_STATUS_UNDI_TRANSMIT_ERROR                0x6b
+#define        PXENV_STATUS_UNDI_INVALID_PARAMETER             0x6c
+
+/* ROM and NBP bootstrap errors (0x70 to 0x7f) */
+#define        PXENV_STATUS_BSTRAP_PROMPT_MENU                 0x74
+#define        PXENV_STATUS_BSTRAP_MCAST_ADDR                  0x76
+#define        PXENV_STATUS_BSTRAP_MISSING_LIST                0x77
+#define        PXENV_STATUS_BSTRAP_NO_RESPONSE                 0x78
+#define        PXENV_STATUS_BSTRAP_FILE_TOO_BIG                0x79
+
+/* Environment NBP errors (0x80 to 0x8f) */
+
+/* Reserved errors (0x90 to 0x9f) */
+
+/* Miscellaneous errors (0xa0 to 0xaf) */
+#define        PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE         0xa0
+#define        PXENV_STATUS_BINL_NO_PXE_SERVER                 0xa1
+#define        PXENV_STATUS_NOT_AVAILABLE_IN_PMODE             0xa2
+#define        PXENV_STATUS_NOT_AVAILABLE_IN_RMODE             0xa3
+
+/* BUSD errors (0xb0 to 0xbf) */
+#define        PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED          0xb0
+
+/* Loader errors (0xc0 to 0xcf) */
+#define        PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY         0xc0
+#define        PXENV_STATUS_LOADER_NO_BC_ROMID                 0xc1
+#define        PXENV_STATUS_LOADER_BAD_BC_ROMID                0xc2
+#define        PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE        0xc3
+#define        PXENV_STATUS_LOADER_NO_UNDI_ROMID               0xc4
+#define        PXENV_STATUS_LOADER_BAD_UNDI_ROMID              0xc5
+#define        PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE       0xc6
+#define        PXENV_STATUS_LOADER_NO_PXE_STRUCT               0xc8
+#define        PXENV_STATUS_LOADER_NO_PXENV_STRUCT             0xc9
+#define        PXENV_STATUS_LOADER_UNDI_START                  0xca
+#define        PXENV_STATUS_LOADER_BC_START                    0xcb
+
+/*
+ * The range 0xd0 to 0xff is defined as "Vendor errors" by the PXE
+ * spec.  We place all our Etherboot-specific errors in this range.
+ * We also define some generic errors as aliases to the PXE errors.
+ *
+ */
+
+#define ENOERR         0x00
+#define ENOMEM         PXENV_STATUS_OUT_OF_RESOURCES
+#define        EBADIMG         0xd0
+#define EIMGRET                0xd1
+#define ETIMEDOUT      0xd2
+#define EINVAL         0xd3
+
+/* Data structures and declarations */
+
+#include "tables.h"
+
+extern int errno;
+
+extern const char * strerror ( int errno );
+
+struct errortab {
+       int errno;
+       const char *text;
+};
+
+#define __errortab __table(errortab,01)
+
+#endif /* ERRNO_H */
index e61a711..9d36428 100644 (file)
@@ -1,6 +1,26 @@
 #ifndef ETHERBOOT_H
 #define ETHERBOOT_H
 
+/*
+ * Standard includes that we always want
+ *
+ */
+
+#include "compiler.h"
+#include "stddef.h"
+#include "stdint.h"
+
+
+/*
+ * IMPORTANT!!!!!!!!!!!!!!
+ *
+ * Everything below this point is cruft left over from older versions
+ * of Etherboot.  Do not add *anything* below this point.  Things are
+ * gradually being moved to individual header files.
+ *
+ */
+
+
 #include <stdarg.h>
 #include "osdep.h"
 
@@ -205,9 +225,6 @@ extern long rfc2131_sleep_interval P((long base, int exp));
 extern long rfc1112_sleep_interval P((long base, int exp));
 extern void cleanup P((void));
 
-/* config.c */
-extern void print_config(void);
-
 /* osloader.c */
 /* Be careful with sector_t it is an unsigned long long on x86 */
 typedef uint64_t sector_t;
@@ -271,15 +288,6 @@ extern int elf_start(unsigned long machine, unsigned long entry, unsigned long p
 extern unsigned long currticks P((void));
 extern void exit P((int status));
 
-/* serial.c */
-extern int serial_getc P((void));
-extern void serial_putc P((int));
-extern int serial_ischar P((void));
-extern int serial_init P((void));
-extern void serial_fini P((void));
-
-/* floppy.c */
-extern int bootdisk P((int dev,int part));
 
 /***************************************************************************
 External variables
@@ -309,14 +317,6 @@ extern int freebsd_howto;
 extern char freebsd_kernel_env[FREEBSD_KERNEL_ENV_SIZE];
 #endif
 
-/* bootmenu.c */
-
-/* osloader.c */
-
-/* created by linker */
-extern char _virt_start[], _text[], _etext[], _text16[], _etext16[];
-extern char _data[], _edata[], _bss[], _ebss[], _end[];
-
 
 /*
  * Local variables:
index bcf4c3c..a853d4d 100644 (file)
 #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
index 48f5550..26ecf3a 100644 (file)
@@ -56,6 +56,8 @@
 #include <pxe_types.h>
 #endif
 
+#include "errno.h"
+
 /* Defaults in case pxe_types.h did not define a type.  These are
  * placeholder structures just to make the code compile.
  */
@@ -673,149 +675,6 @@ typedef struct {
 
 
 
-/*
- **************************************************************************
- *
- * Status codes returned in the status word of the PXENV API parameter
- * structure. Some of these codes are also used to return status
- * information from a boot image loader back to the bootrom.
- */
-
-/* Generic API errors that are reported by the loader */
-#define PXENV_STATUS_SUCCESS           0x00
-#define PXENV_STATUS_FAILURE           0x01    /* general failure */
-#define PXENV_STATUS_BAD_FUNC          0x02    /* invalid function number */
-#define PXENV_STATUS_UNSUPPORTED       0x03    /* not yet supported */
-#define PXENV_STATUS_KEEP_UNDI         0x04    /* keep UNDI in memory */
-#define PXENV_STATUS_KEEP_ALL          0x05    /* keep everything in memory */
-#define PXENV_STATUS_OUT_OF_RESOURCES  0x06    /* also keep everything */
-
-/* ARP/UDP errors (0x10 to 0x1F) */
-#define PXENV_STATUS_ARP_CANCELED      0x10    /* ARP canceled by keystroke */
-#define PXENV_STATUS_ARP_TIMEOUT       0x11    /* ARP timeout */
-#define PXENV_STATUS_UDP_CLOSED                0x18    /* UDP closed */
-#define PXENV_STATUS_UDP_OPEN          0x19    /* UDP already open */
-#define PXENV_STATUS_TFTP_CLOSED       0x1A    /* TFTP closed */
-#define PXENV_STATUS_TFTP_OPEN         0x1B    /* TFTP already opened */
-
-/* BIOS/system errors (0x20 to 0x2F) */
-#define PXENV_STATUS_MCOPY_PROBLEM     0x20    /* can't copy into memory */
-
-/* TFP errors (0x30 to 0x3F) */
-#define PXENV_STATUS_TFTP_CANNOT_ARP   0x30    /* TFTP ARP problem */
-#define PXENV_STATUS_TFTP_OPEN_CANCELED        0x31    /* TFTP open canceled by key */
-#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x32    /* timeout during TFTP open */
-#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x33  /* unknown TFTP opcode */
-#define PXENV_STATUS_TFTP_READ_CANCELED        0x34    /* TFTP read canceled by key */
-#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x35    /* timeout during TFTP read */
-#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x36    /* bad TFTP opcode */
-#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION \
-                                       0x38    /* error during TFTP open */
-#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION \
-                                       0x39    /* error during TFTP read */
-#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES \
-                                       0x3A    /* too many packages */
-#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x3B  /* file not found */
-#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x3C        /* access violation */
-#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x3D        /* no multicast address */
-#define PXENV_STATUS_TFTP_NO_FILESIZE  0x3E    /* unable to get file size */
-#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE \
-                                       0x3F    /* invalid packet size */
-
-/* BOOTP errors (0x40 to 0x4F) */
-#define PXENV_STATUS_BOOTP_CANCELED    0x40    /* BOOTP canceled by key */
-#define PXENV_STATUS_BOOTP_TIMEOUT     0x41    /* timeout during BOOTP */
-#define PXENV_STATUS_BOOTP_NO_FILE     0x42    /* missing bootfile name */
-
-/* DHCP errors (0x50 to 0x5F) */
-#define PXENV_STATUS_DHCP_CANCELED     0x50    /* DHCP canceled by key */
-#define PXENV_STATUS_DHCP_TIMEOUT      0x51    /* timeout during DHCP */
-#define PXENV_STATUS_DHCP_NO_IP_ADDRESS        0x52    /* missing IP address */
-#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x53        /* missing bootfile name */
-#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x54  /* invalid IP address */
-
-/* Driver errors (0x60 to 0x6F) */
-#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x60        /* invalid UNDI function */
-#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x61        /* media test failed */
-#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST \
-                                       0x62    /* cannot init for multicast */
-#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC \
-                                       0x63    /* cannot init NIC */
-#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY \
-                                       0x64    /* cannot init hardware */
-#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA \
-                                       0x65    /* cannot read config data */
-#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA        \
-                                       0x66    /* cannot read init data */
-#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x67 /* invalid hardware address */
-#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM \
-                                       0x68    /* invalid EEPROM checksum */
-#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x69
-#define PXENV_STATUS_UNDI_INVALID_STATE        0x6a    /* invalid UNDI state */
-#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x6b  /* transmit error */
-#define PXENV_STATUS_UNDI_INVALID_PARAMETER \
-                                       0x6c    /* almost anything */
-
-/* Bootstrap (.1) errors (0x70 to 0x7F) */
-#define PXENV_STATUS_BSTRAP_PROMPT_MENU        0x74    /* invalid bootstrap menu */
-#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x76    /* missing multicast address */
-#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x77  /* missing file list */
-#define PXENV_STATUS_BSTRAP_NO_RESPONSE        0x78    /* no response from server */
-#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x79  /* next file too big */
-
-/* Environment (.2) errors (0x80 to 0x8F) */
-
-/* MTFTP errors (0x90 to 0x9F) */
-#define PXENV_STATUS_MTFTP_OPEN_CANCEL 0x91    /* MTFTP open canceled by key */
-#define PXENV_STATUS_MTFTP_OPEN_TIMEOUT        0x92    /* timeout during MTFTP open */
-#define PXENV_STATUS_MTFTP_UNKNOWN_OP  0x93    /* unknown TFTP opcode */
-#define PXENV_STATUS_MTFTP_READ_CANCEL 0x94    /* MTFTP read canceled by key */
-#define PXENV_STATUS_MTFTP_READ_TIMEOUT        0x95    /* timeout during MTFTP read */
-#define PXENV_STATUS_MTFTP_ERROR_OP    0x96    /* bad TFTP opcode */
-#define PXENV_STATUS_MTFTP_CANNOT_OPEN 0x98    /* error during MTFTP open */
-#define PXENV_STATUS_MTFTP_CANNOT_READ 0x99    /* error during MTFTP read */
-#define PXENV_STATUS_MTFTP_TOO_MANY    0x9A    /* too many packages */
-#define PXENV_STATUS_MTFTP_PACK_SIZE   0x9B    /* invalid package size */
-
-/* Misc. errors (0xA0 to 0xAF) */
-#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE        \
-                                       0xA0    /* BINL canceled by key */
-#define PXENV_STATUS_BINL_NO_PXE_SERVER        0xA1    /* no BINL server found */
-#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE \
-                                       0xA2    /* not avail. in prot mode */
-#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE \
-                                       0xA3    /* not avail. in real mode */
-
-/* BUSD errors (0xB0 to 0xBF) */
-#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED \
-                                       0xB0    /* BUSD services not enabled */
-#define PXENV_STATUS_BUSD_DEV_ENABLE   0xB1    /* BUSD device not enabled */
-
-/* Loader errors (0xC0 to 0xCF) */
-#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY \
-                                       0xC0    /* no free base memory */
-#define PXENV_STATUS_LOADER_NO_BC_ROMID        0xC1    /* no base code rom ID */
-#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0xC2  /* bad base code rom ID */
-#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE \
-                                       0xC3    /* bad base code image */
-#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0xC4 /* no UNDI rom ID */
-#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0xC5        /* bad UNDI rom ID */
-#define PXENV_STATUS_LOADER_UNDI_DRIVER_IMAGE \
-                                       0xC6    /* bad UNDI runtime image */
-#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0xC8 /* missing !PXE struct */
-#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT \
-                                       0xC9    /* missing PXENV+ struct */
-#define PXENV_STATUS_LOADER_UNDI_START 0xCA    /* UNDI not started */
-#define PXENV_STATUS_LOADER_BC_START   0xCB    /* base code not started */
-
-/* Reserved errors (0xD0 to 0xFF) */
-#define PXENV_STATUS_IMAGE_INVALID     0xD0    /* invalid boot image */
-#define PXENV_STATUS_STOP_BASE         0xD1    /* error stopping base code */
-#define PXENV_STATUS_UNLOAD_BASE       0xD2    /* error unloading base code */
-#define PXENV_STATUS_STOP_UNDI         0xD3    /* error stopping UNDI */
-#define PXENV_STATUS_CLEANUP_UNDI      0xD4    /* error cleaning up UNDI */
-
-
 /*****************************************************************************
  * The remainder of this file is original to Etherboot.
  *****************************************************************************
index 26ad61d..9d74df6 100644 (file)
 #ifndef TABLES_H
 #define TABLES_H
 
-/*
- * Macros for dealing with linker-generated tables of fixed-size
- * symbols.  We make fairly extensive use of these in order to avoid
- * ifdef spaghetti and/or linker symbol pollution.  For example,
- * instead of having code such as
+/** @page ifdef_harmful #ifdef considered harmful
+ *
+ * Overuse of @c #ifdef has long been a problem in Etherboot.
+ * Etherboot provides a rich array of features, but all these features
+ * take up valuable space in a ROM image.  The traditional solution to
+ * this problem has been for each feature to have its own @c #ifdef
+ * option, allowing the feature to be compiled in only if desired.
+ *
+ * The problem with this is that it becomes impossible to compile, let
+ * alone test, all possible versions of Etherboot.  Code that is not
+ * typically used tends to suffer from bit-rot over time.  It becomes
+ * extremely difficult to predict which combinations of compile-time
+ * options will result in code that can even compile and link
+ * correctly.
+ *
+ * To solve this problem, we have adopted a new approach from
+ * Etherboot 5.5 onwards.  @c #ifdef is now "considered harmful", and
+ * its use should be minimised.  Separate features should be
+ * implemented in separate @c .c files, and should \b always be
+ * compiled (i.e. they should \b not be guarded with a @c #ifdef @c
+ * MY_PET_FEATURE statement).  By making (almost) all code always
+ * compile, we avoid the problem of bit-rot in rarely-used code.
+ *
+ * The file config.h, in combination with the @c make command line,
+ * specifies the objects that will be included in any particular build
+ * of Etherboot.  For example, suppose that config.h includes the line
+ *
+ * @code
+ *
+ *   #define CONSOLE_SERIAL
+ *   #define DOWNLOAD_PROTO_TFTP
+ *
+ * @endcode
+ *
+ * When a particular Etherboot image (e.g. @c bin/rtl8139.zdsk) is
+ * built, the options specified in config.h are used to drag in the
+ * relevant objects at link-time.  For the above example, serial.o and
+ * tftp.o would be linked in.
+ *
+ * There remains one problem to solve: how do these objects get used?
+ * Traditionally, we had code such as
+ *
+ * @code
+ *
+ *    #ifdef CONSOLE_SERIAL
+ *      serial_init();
+ *    #endif
+ *
+ * @endcode
+ *
+ * in main.c, but this reintroduces @c #ifdef and so is a Bad Idea.
+ * We cannot simply remove the @c #ifdef and make it
+ *
+ * @code
  *
- * #ifdef CONSOLE_SERIAL
  *   serial_init();
- * #endif
+ *
+ * @endcode
+ *
+ * because then serial.o would end up always being linked in.
+ *
+ * The solution is to use @link tables.h linker tables @endlink.
+ *
+ */
+
+/** @file
+ *
+ * Linker tables
+ *
+ * Read @ref ifdef_harmful first for some background on the motivation
+ * for using linker tables.
+ *
+ * This file provides macros for dealing with linker-generated tables
+ * of fixed-size symbols.  We make fairly extensive use of these in
+ * order to avoid @c #ifdef spaghetti and/or linker symbol pollution.
+ * For example, instead of having code such as
+ *
+ * @code
+ *
+ *    #ifdef CONSOLE_SERIAL
+ *      serial_init();
+ *    #endif
+ *
+ * @endcode
  *
  * we make serial.c generate an entry in the initialisation function
  * table, and then have a function call_init_fns() that simply calls
  * all functions present in this table.  If and only if serial.o gets
  * linked in, then its initialisation function will be called.  We
  * avoid linker symbol pollution (i.e. always dragging in serial.o
- * just because of a call to serial_init()) and we also avoid ifdef
- * spaghetti (having to conditionalise every reference to functions in
- * serial.c).
+ * just because of a call to serial_init()) and we also avoid @c
+ * #ifdef spaghetti (having to conditionalise every reference to
+ * functions in serial.c).
  *
  * The linker script takes care of assembling the tables for us.  All
- * our table sections have names of the format ".tbl.NAME.NN" where
- * NAME designates the data structure stored in the table
- * (e.g. "init_fn") and NN is a two-digit decimal number used to
- * impose an ordering upon the tables if required.  NN=00 is reserved
- * for the symbol indicating "table start", and NN=99 is reserved for
- * the symbol indicating "table end".
+ * our table sections have names of the format @c .tbl.NAME.NN where
+ * @c NAME designates the data structure stored in the table (e.g. @c
+ * init_fn) and @c NN is a two-digit decimal number used to impose an
+ * ordering upon the tables if required.  @c NN=00 is reserved for the
+ * symbol indicating "table start", and @c NN=99 is reserved for the
+ * symbol indicating "table end".
+ *
+ * As an example, suppose that we want to create a "frobnicator"
+ * feature framework, and allow for several independent modules to
+ * provide frobnicating services.  Then we would create a frob.h
+ * header file containing e.g.
+ *
+ * @code
+ *
+ *   struct frobnicator {
+ *      const char *name;              // Name of the frobnicator
+ *     void ( *frob ) ( void );        // The frobnicating function itself
+ *   };
+ *
+ *   #define __frobnicator __table ( frobnicators, 01 )
+ *
+ * @endcode
  *
- * To define an entry in the "xxx" table:
+ * Any module providing frobnicating services would look something
+ * like
  *
- *  static struct xxx my_xxx __table(xxx,01) = { ... };
+ * @code
  *
- * To access start and end markers for the "xxx" table:
+ *   #include "frob.h"
  *
- *  static struct xxx xxx_start[0] __table_start(xxx);
- *  static struct xxx xxx_end[0] __table_end(xxx);
+ *   static void my_frob ( void ) {
+ *     // Do my frobnicating
+ *     ...
+ *   }
  *
- * See init.h and init.c for an example of how these macros are used
- * in practice.
+ *   static struct frob my_frobnicator __frobnicator = {
+ *     .name = "my_frob",
+ *     .frob = my_frob,
+ *   };
+ *
+ * @endcode
+ *
+ * The central frobnicator code (frob.c) would use the frobnicating
+ * modules as follows
+ *
+ * @code
+ *
+ *   #include "frob.h"
+ *
+ *   static struct frob frob_start[0] __table_start ( frobnicators );
+ *   static struct frob frob_end[0] __table_end ( frobnicators );
+ *
+ *   // Call all linked-in frobnicators
+ *   void frob_all ( void ) {
+ *     struct frob *frob;
+ *
+ *      for ( frob = frob_start ; frob < frob_end ; frob++ ) {
+ *         printf ( "Calling frobnicator \"%s\"\n", frob->name );
+ *        frob->frob ();
+ *     }
+ *   }
+ *
+ * @endcode
+ *
+ * See init.h and init.c for a real-life example.
  *
  */
 
 #define __table_section_start(table) __table_section(table,00)
 #define __table_section_end(table) __table_section(table,99)
 
+
+/**
+ * Linker table entry.
+ *
+ * Declares a data structure to be part of a linker table.  Use as
+ * e.g.
+ *
+ * @code
+ *
+ *   static struct my_foo __table ( foo, 01 ) = {
+ *      ...
+ *   };
+ *
+ * @endcode
+ *
+ */
 #define __table(table,idx) \
        __attribute__ (( unused, __table_section(table,idx) ))
+
+/**
+ * Linker table start marker.
+ *
+ * Declares a data structure (usually an empty data structure) to be
+ * the start of a linker table.  Use as e.g.
+ *
+ * @code
+ *
+ *   static struct foo_start[0] __table_start ( foo );
+ *
+ * @endcode
+ *
+ */
 #define __table_start(table) \
        __attribute__ (( unused, __table_section_start(table) ))
+
+/**
+ * Linker table end marker.
+ *
+ * Declares a data structure (usually an empty data structure) to be
+ * the end of a linker table.  Use as e.g.
+ *
+ * @code
+ *
+ *   static struct foo_end[0] __table_end ( foo );
+ *
+ * @endcode
+ *
+ */
 #define __table_end(table) \
        __attribute__ (( unused, __table_section_end(table) ))
 
diff --git a/src/proto/fsp.c b/src/proto/fsp.c
new file mode 100644 (file)
index 0000000..6aba937
--- /dev/null
@@ -0,0 +1,245 @@
+    /*********************************************************************\
+    * Copyright (c) 2005 by Radim Kolar (hsn-sendmail.cz)                 *
+    *                                                                     *
+    * You may copy or modify this file in any manner you wish, provided   *
+    * that this notice is always included, and that you hold the author   *
+    * harmless for any loss or damage resulting from the installation or  *
+    * use of this software.                                               *
+    *                                                                     *
+    * This file provides support for FSP v2 protocol written from scratch *
+    * by Radim Kolar,   FSP project leader.                               *
+    *                                                                     *
+    * ABOUT FSP                                                           *
+    * FSP is a lightweight file transfer protocol and is being used for   *
+    * booting, Internet firmware updates, embedded devices and in         *
+    * wireless applications. FSP is very easy to implement; contact Radim *
+    * Kolar if you need hand optimized assembler FSP stacks for various   *
+    * microcontrollers, CPUs or consultations.                            *
+    * http://fsp.sourceforge.net/                                         *
+    *                                                                     *
+    * REVISION HISTORY                                                    *
+    * 1.0 2005-03-17 rkolar   Initial coding                              *
+    * 1.1 2005-03-24 rkolar   We really need to send CC_BYE to the server *
+    *                         at end of transfer, because next stage boot *
+    *                         loader is unable to contact FSP server      *
+    *                         until session timeouts.                     *
+    * 1.2 2005-03-26 rkolar   We need to query filesize in advance,       *
+    *                         because NBI loader do not reads file until  *
+    *                         eof is reached.
+    * REMARKS                                                             *
+    * there is no support for selecting port number of fsp server, maybe  *
+    *   we should parse fsp:// URLs in boot image filename.               *
+    * this implementation has filename limit 255 chars.                   *
+    \*********************************************************************/
+
+#ifdef DOWNLOAD_PROTO_FSP
+#include "etherboot.h"
+#include "nic.h"
+
+#define FSP_PORT 21
+
+/* FSP commands */
+#define CC_GET_FILE    0x42
+#define CC_BYE         0x4A
+#define CC_ERR         0x40
+#define CC_STAT                0x4D
+
+/* etherboot limits */
+#define FSP_MAXFILENAME 255
+
+struct fsp_info {
+       in_addr server_ip;
+       uint16_t server_port;
+       uint16_t local_port;
+       const char *filename;
+       int (*fnc)(unsigned char *, unsigned int, unsigned int, int);
+};
+
+struct fsp_header {
+       uint8_t cmd;
+       uint8_t sum;
+       uint16_t key;
+       uint16_t seq;
+       uint16_t len;
+       uint32_t pos;
+} PACKED;
+
+#define FSP_MAXPAYLOAD (ETH_MAX_MTU - \
+  (sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct fsp_header)))
+
+static struct fsp_request {
+       struct iphdr ip;
+       struct udphdr udp;
+       struct fsp_header fsp;
+       unsigned char data[FSP_MAXFILENAME + 1 + 2];
+} request;
+
+struct fsp_reply {
+       struct iphdr ip;
+       struct udphdr udp;
+       struct fsp_header fsp;
+       unsigned char data[FSP_MAXPAYLOAD];
+} PACKED;
+
+
+static int await_fsp(int ival, void *ptr, unsigned short ptype __unused,
+                      struct iphdr *ip, struct udphdr *udp)
+{
+       if(!udp)
+           return 0;
+       if (ip->dest.s_addr != arptable[ARP_CLIENT].ipaddr.s_addr) 
+           return 0;
+        if (ntohs(udp->dest) != ival)
+            return 0;
+       if (ntohs(udp->len) < 12+sizeof(struct udphdr))
+           return 0;
+       return 1;
+}
+
+static int proto_fsp(struct fsp_info *info)
+{
+    uint32_t filepos;
+    uint32_t filelength=0;
+    int i,retry;
+    uint16_t reqlen;
+    struct fsp_reply *reply;
+    int block=1;
+    
+    /* prepare FSP request packet */
+    filepos=0;
+    i=strlen(info->filename);
+    if(i>FSP_MAXFILENAME)
+    {
+       printf("Boot filename is too long.\n");
+       return 0;
+    }
+    strcpy(request.data,info->filename);
+    *(uint16_t *)(request.data+i+1)=htons(FSP_MAXPAYLOAD);
+    request.fsp.len=htons(i+1);
+    reqlen=i+3+12;
+
+    rx_qdrain();
+    retry=0;
+
+    /* main loop */
+    for(;;) {
+       int  sum;
+       long timeout;
+
+        /* query filelength if not known */
+       if(filelength == 0)
+           request.fsp.cmd=CC_STAT;
+               
+       /* prepare request packet */
+       request.fsp.pos=htonl(filepos);
+       request.fsp.seq=random();
+       request.fsp.sum=0;
+       for(i=0,sum=reqlen;i<reqlen;i++)
+       {
+           sum += ((uint8_t *)&request.fsp)[i];
+        }
+       request.fsp.sum= sum + (sum >> 8);
+       /* send request */
+        if (!udp_transmit(info->server_ip.s_addr, info->local_port,
+                        info->server_port, sizeof(request.ip) +
+                        sizeof(request.udp) + reqlen, &request))
+                           return (0);
+       /* wait for retry */                
+#ifdef  CONGESTED
+        timeout =
+            rfc2131_sleep_interval(filepos ? TFTP_REXMT : TIMEOUT, retry);
+#else
+       timeout = rfc2131_sleep_interval(TIMEOUT, retry);
+#endif
+       retry++;
+        if (!await_reply(await_fsp, info->local_port, NULL, timeout))
+           continue;
+       reply=(struct fsp_reply *) &nic.packet[ETH_HLEN];    
+       /* check received packet */
+       if (reply->fsp.seq != request.fsp.seq)
+           continue;
+       reply->udp.len=ntohs(reply->udp.len)-sizeof(struct udphdr);
+       if(reply->udp.len < ntohs(reply->fsp.len) + 12 )
+           continue;
+        sum=-reply->fsp.sum;
+       for(i=0;i<reply->udp.len;i++)
+       {
+           sum += ((uint8_t *)&(reply->fsp))[i];
+        }
+        sum = (sum + (sum >> 8)) & 0xff;
+       if(sum != reply->fsp.sum)
+       {
+           printf("FSP checksum failed. computed %d, but packet has %d.\n",sum,reply->fsp.sum);
+           continue;
+       }
+       if(reply->fsp.cmd == CC_ERR)
+       {
+           printf("\nFSP error: %s",info->filename);
+           if(reply->fsp.len)
+               printf(" [%s]",reply->data);
+           printf("\n");
+           return 0;
+       }
+       if(reply->fsp.cmd == CC_BYE && filelength == 1)
+       {
+           info->fnc(request.data,block,1,1);
+           return 1;
+       }
+       if(reply->fsp.cmd == CC_STAT)
+       {
+           if(reply->data[8] == 0)
+           {
+               /* file not found, etc. */
+               filelength=0xffffffff;
+           } else
+           {
+               filelength= ntohl(*((uint32_t *)&reply->data[4]));
+           }
+           request.fsp.cmd = CC_GET_FILE;
+           request.fsp.key = reply->fsp.key;
+           retry=0;
+           continue;
+       }
+
+       if(reply->fsp.cmd == CC_GET_FILE)
+       {
+           if(ntohl(reply->fsp.pos) != filepos)
+               continue;
+           request.fsp.key = reply->fsp.key;
+           retry=0;
+           i=ntohs(reply->fsp.len);
+           if(i == 1)
+           {
+               request.fsp.cmd=CC_BYE;
+               request.data[0]=reply->data[0];
+               continue;
+           }
+           /* let last byte alone */
+            if(i >= filelength)
+               i = filelength - 1;
+           if(!info->fnc(reply->data,block++,i,0))
+               return 0;
+           filepos += i;
+           filelength -= i;
+       }
+    }
+
+    return 0;
+}
+
+int url_fsp(const char *name, int (*fnc)(unsigned char *, unsigned int, unsigned int, int))
+{
+       struct fsp_info info;
+       /* Set the defaults */
+       info.server_ip.s_addr    = arptable[ARP_SERVER].ipaddr.s_addr;
+       info.server_port         = FSP_PORT;
+       info.local_port          = 1024 + random() & 0xfbff;
+       info.fnc                 = fnc;
+       
+       /* Now parse the url */
+       /* printf("fsp-URI: [%s]\n", name); */
+        /* quick hack for now */
+       info.filename=name;
+       return proto_fsp(&info);
+}
+#endif
index 695468c..9d751e1 100755 (executable)
@@ -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
@@ -168,7 +168,7 @@ sub makerom () {
                        $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
@@ -190,14 +190,16 @@ sub makerom () {
        }
        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 () {
@@ -211,16 +213,16 @@ 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);