summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile3
-rw-r--r--src/Makefile.housekeeping29
-rw-r--r--src/arch/armnommu/Config6
-rw-r--r--src/arch/armnommu/core/serial.c4
-rw-r--r--src/arch/armnommu/drivers/net/p2001_eth.c365
-rw-r--r--src/arch/armnommu/include/hardware.h17
-rw-r--r--src/arch/armnommu/include/lxt971a.h30
-rw-r--r--src/arch/armnommu/include/stdint.h12
-rw-r--r--src/arch/e1/include/stdint.h12
-rw-r--r--src/arch/i386/Makefile2
-rw-r--r--src/arch/i386/core/freebsd_loader.c6
-rw-r--r--src/arch/i386/image/nbi.c164
-rw-r--r--src/arch/i386/include/bochs.h15
-rw-r--r--src/arch/i386/include/stdint.h12
-rw-r--r--src/arch/i386/include/virtaddr.h3
-rw-r--r--src/arch/ia64/include/stdint.h12
-rw-r--r--src/config.h21
-rw-r--r--src/core/buffer.c164
-rw-r--r--src/core/config.c3
-rw-r--r--src/core/errno.c61
-rw-r--r--src/core/main.c11
-rw-r--r--src/core/pxe_errors.c102
-rw-r--r--src/core/vsprintf.c114
-rw-r--r--src/doxygen.cfg204
-rw-r--r--src/drivers/bus/isapnp.c254
-rw-r--r--src/drivers/net/3c515.c4
-rw-r--r--src/drivers/net/davicom.c7
-rw-r--r--src/drivers/net/depca.c7
-rw-r--r--src/drivers/net/dmfe.c7
-rw-r--r--src/drivers/net/eepro.c30
-rw-r--r--src/drivers/net/eepro100.c7
-rw-r--r--src/drivers/net/forcedeth.c811
-rw-r--r--src/drivers/net/mtd80x.c7
-rw-r--r--src/drivers/net/natsemi.c7
-rwxr-xr-xsrc/drivers/net/ns83820.c7
-rw-r--r--src/drivers/net/pcnet32.c7
-rw-r--r--src/drivers/net/r8169.c7
-rw-r--r--src/drivers/net/sis900.h7
-rw-r--r--src/drivers/net/sundance.c7
-rw-r--r--src/drivers/net/tg3.c4
-rw-r--r--src/drivers/net/tg3.h2
-rw-r--r--src/drivers/net/tlan.h20
-rw-r--r--src/drivers/net/tulip.c16
-rw-r--r--src/drivers/net/w89c840.c7
-rw-r--r--src/include/buffer.h40
-rw-r--r--src/include/compiler.h12
-rw-r--r--src/include/errno.h141
-rw-r--r--src/include/etherboot.h40
-rw-r--r--src/include/pci_ids.h1
-rw-r--r--src/include/pxe.h145
-rw-r--r--src/include/tables.h212
-rwxr-xr-xsrc/util/makerom.pl28
52 files changed, 2323 insertions, 893 deletions
diff --git a/src/Makefile b/src/Makefile
index fa7b3f3f9..2393eecb1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -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
diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping
index 1f06d698b..2a9503263 100644
--- a/src/Makefile.housekeeping
+++ b/src/Makefile.housekeeping
@@ -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 :
diff --git a/src/arch/armnommu/Config b/src/arch/armnommu/Config
index 4c220cd50..579420388 100644
--- a/src/arch/armnommu/Config
+++ b/src/arch/armnommu/Config
@@ -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'"
diff --git a/src/arch/armnommu/core/serial.c b/src/arch/armnommu/core/serial.c
index 3ae98d47a..0fb6e79b9 100644
--- a/src/arch/armnommu/core/serial.c
+++ b/src/arch/armnommu/core/serial.c
@@ -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;
}
/*
diff --git a/src/arch/armnommu/drivers/net/p2001_eth.c b/src/arch/armnommu/drivers/net/p2001_eth.c
index 81bc84c3c..bdf2f0e96 100644
--- a/src/arch/armnommu/drivers/net/p2001_eth.c
+++ b/src/arch/armnommu/drivers/net/p2001_eth.c
@@ -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;
}
}
diff --git a/src/arch/armnommu/include/hardware.h b/src/arch/armnommu/include/hardware.h
index 203b78b73..49264d63b 100644
--- a/src/arch/armnommu/include/hardware.h
+++ b/src/arch/armnommu/include/hardware.h
@@ -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
index 16314ec25..000000000
--- a/src/arch/armnommu/include/lxt971a.h
+++ /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 */
diff --git a/src/arch/armnommu/include/stdint.h b/src/arch/armnommu/include/stdint.h
index 3f5dc3f96..1cb008515 100644
--- a/src/arch/armnommu/include/stdint.h
+++ b/src/arch/armnommu/include/stdint.h
@@ -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 */
diff --git a/src/arch/e1/include/stdint.h b/src/arch/e1/include/stdint.h
index 8a7ad978a..505cc3751 100644
--- a/src/arch/e1/include/stdint.h
+++ b/src/arch/e1/include/stdint.h
@@ -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 */
diff --git a/src/arch/i386/Makefile b/src/arch/i386/Makefile
index 9f207ea0a..0c258ae81 100644
--- a/src/arch/i386/Makefile
+++ b/src/arch/i386/Makefile
@@ -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
diff --git a/src/arch/i386/core/freebsd_loader.c b/src/arch/i386/core/freebsd_loader.c
index 4e820e8e9..464f6d939 100644
--- a/src/arch/i386/core/freebsd_loader.c
+++ b/src/arch/i386/core/freebsd_loader.c
@@ -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... */
diff --git a/src/arch/i386/image/nbi.c b/src/arch/i386/image/nbi.c
index f361aa945..f5d9e3826 100644
--- a/src/arch/i386/image/nbi.c
+++ b/src/arch/i386/image/nbi.c
@@ -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,
diff --git a/src/arch/i386/include/bochs.h b/src/arch/i386/include/bochs.h
index 73f43c364..9d090fc12 100644
--- a/src/arch/i386/include/bochs.h
+++ b/src/arch/i386/include/bochs.h
@@ -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" );
}
diff --git a/src/arch/i386/include/stdint.h b/src/arch/i386/include/stdint.h
index b9ade4e00..c801cf6f4 100644
--- a/src/arch/i386/include/stdint.h
+++ b/src/arch/i386/include/stdint.h
@@ -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 */
diff --git a/src/arch/i386/include/virtaddr.h b/src/arch/i386/include/virtaddr.h
index d48b6c6cd..4d248b0ac 100644
--- a/src/arch/i386/include/virtaddr.h
+++ b/src/arch/i386/include/virtaddr.h
@@ -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 );
}
diff --git a/src/arch/ia64/include/stdint.h b/src/arch/ia64/include/stdint.h
index 2f9c592c3..8d8270be8 100644
--- a/src/arch/ia64/include/stdint.h
+++ b/src/arch/ia64/include/stdint.h
@@ -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 */
diff --git a/src/config.h b/src/config.h
index d41a403fc..ec4b18019 100644
--- a/src/config.h
+++ b/src/config.h
@@ -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 */
@@ -91,6 +92,26 @@
/* @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
*
* You probably don't need to touch these.
diff --git a/src/core/buffer.c b/src/core/buffer.c
index b300d4ece..6e05b0882 100644
--- a/src/core/buffer.c
+++ b/src/core/buffer.c
@@ -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
@@ -14,22 +18,94 @@
* 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;
}
diff --git a/src/core/config.c b/src/core/config.c
index f8683063f..7756c634e 100644
--- a/src/core/config.c
+++ b/src/core/config.c
@@ -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
index 000000000..83c8564bc
--- /dev/null
+++ b/src/core/errno.c
@@ -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;
+}
diff --git a/src/core/main.c b/src/core/main.c
index 3a112eee7..e0cac2226 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -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
index 000000000..581393e81
--- /dev/null
+++ b/src/core/pxe_errors.c
@@ -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" },
+};
diff --git a/src/core/vsprintf.c b/src/core/vsprintf.c
index 414b4509a..c0bc759a4 100644
--- a/src/core/vsprintf.c
+++ b/src/core/vsprintf.c
@@ -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))
@@ -9,29 +10,61 @@
#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
index 000000000..3ce15c491
--- /dev/null
+++ b/src/doxygen.cfg
@@ -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 =
diff --git a/src/drivers/bus/isapnp.c b/src/drivers/bus/isapnp.c
index 6b7c79e45..4888c6115 100644
--- a/src/drivers/bus/isapnp.c
+++ b/src/drivers/bus/isapnp.c
@@ -33,16 +33,18 @@
*
***************************************************************************/
-#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
@@ -50,18 +52,30 @@
* 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 ) {
diff --git a/src/drivers/net/3c515.c b/src/drivers/net/3c515.c
index 7fcc9f0fe..c87495006 100644
--- a/src/drivers/net/3c515.c
+++ b/src/drivers/net/3c515.c
@@ -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/davicom.c b/src/drivers/net/davicom.c
index fdbf98342..d087e29e7 100644
--- a/src/drivers/net/davicom.c
+++ b/src/drivers/net/davicom.c
@@ -50,13 +50,6 @@
#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,
diff --git a/src/drivers/net/depca.c b/src/drivers/net/depca.c
index 3707da64e..cc904c71e 100644
--- a/src/drivers/net/depca.c
+++ b/src/drivers/net/depca.c
@@ -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.
*/
diff --git a/src/drivers/net/dmfe.c b/src/drivers/net/dmfe.c
index 4061ebfc9..e1ff44ec5 100644
--- a/src/drivers/net/dmfe.c
+++ b/src/drivers/net/dmfe.c
@@ -51,13 +51,6 @@
#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))
diff --git a/src/drivers/net/eepro.c b/src/drivers/net/eepro.c
index 6c2318bdd..65c6c8f59 100644
--- a/src/drivers/net/eepro.c
+++ b/src/drivers/net/eepro.c
@@ -19,6 +19,12 @@ 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
* published by the Free Software Foundation; either version 2, or (at
@@ -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);
diff --git a/src/drivers/net/eepro100.c b/src/drivers/net/eepro100.c
index 590b37c8d..d97b1b187 100644
--- a/src/drivers/net/eepro100.c
+++ b/src/drivers/net/eepro100.c
@@ -110,13 +110,6 @@
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. */
diff --git a/src/drivers/net/forcedeth.c b/src/drivers/net/forcedeth.c
index 3297effd1..637738362 100644
--- a/src/drivers/net/forcedeth.c
+++ b/src/drivers/net/forcedeth.c
@@ -30,14 +30,16 @@
* (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
***************************************************************************/
@@ -49,9 +51,10 @@
#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
@@ -60,12 +63,7 @@
#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 );
diff --git a/src/drivers/net/mtd80x.c b/src/drivers/net/mtd80x.c
index 3d974abc3..c7754a94f 100644
--- a/src/drivers/net/mtd80x.c
+++ b/src/drivers/net/mtd80x.c
@@ -30,13 +30,6 @@
/* 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))
diff --git a/src/drivers/net/natsemi.c b/src/drivers/net/natsemi.c
index 003b97983..774b5e310 100644
--- a/src/drivers/net/natsemi.c
+++ b/src/drivers/net/natsemi.c
@@ -71,13 +71,6 @@
#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))
diff --git a/src/drivers/net/ns83820.c b/src/drivers/net/ns83820.c
index d4fafb686..df9eec5a2 100755
--- a/src/drivers/net/ns83820.c
+++ b/src/drivers/net/ns83820.c
@@ -53,13 +53,6 @@
#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. */
diff --git a/src/drivers/net/pcnet32.c b/src/drivers/net/pcnet32.c
index 5a0bb14cd..4255269bb 100644
--- a/src/drivers/net/pcnet32.c
+++ b/src/drivers/net/pcnet32.c
@@ -54,13 +54,6 @@
#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;
diff --git a/src/drivers/net/r8169.c b/src/drivers/net/r8169.c
index ad3b62bd6..427fad0f8 100644
--- a/src/drivers/net/r8169.c
+++ b/src/drivers/net/r8169.c
@@ -52,13 +52,6 @@
#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;
diff --git a/src/drivers/net/sis900.h b/src/drivers/net/sis900.h
index 89aa3aa5a..e88e111d4 100644
--- a/src/drivers/net/sis900.h
+++ b/src/drivers/net/sis900.h
@@ -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)
diff --git a/src/drivers/net/sundance.c b/src/drivers/net/sundance.c
index 05621d4f2..701f922a4 100644
--- a/src/drivers/net/sundance.c
+++ b/src/drivers/net/sundance.c
@@ -52,13 +52,6 @@
#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. */
diff --git a/src/drivers/net/tg3.c b/src/drivers/net/tg3.c
index 2d881f08a..ace2dfec6 100644
--- a/src/drivers/net/tg3.c
+++ b/src/drivers/net/tg3.c
@@ -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 */
diff --git a/src/drivers/net/tg3.h b/src/drivers/net/tg3.h
index 6e05b9cc0..fd038f587 100644
--- a/src/drivers/net/tg3.h
+++ b/src/drivers/net/tg3.h
@@ -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;
diff --git a/src/drivers/net/tlan.h b/src/drivers/net/tlan.h
index e0379a7bc..de57d5984 100644
--- a/src/drivers/net/tlan.h
+++ b/src/drivers/net/tlan.h
@@ -34,22 +34,10 @@
* 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
diff --git a/src/drivers/net/tulip.c b/src/drivers/net/tulip.c
index 28e38d952..279e0dbc3 100644
--- a/src/drivers/net/tulip.c
+++ b/src/drivers/net/tulip.c
@@ -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"),
diff --git a/src/drivers/net/w89c840.c b/src/drivers/net/w89c840.c
index 1ed3503c8..c3f03f9f6 100644
--- a/src/drivers/net/w89c840.c
+++ b/src/drivers/net/w89c840.c
@@ -84,13 +84,6 @@
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)
diff --git a/src/include/buffer.h b/src/include/buffer.h
index 0085c7d16..ee06371d2 100644
--- a/src/include/buffer.h
+++ b/src/include/buffer.h
@@ -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 );
diff --git a/src/include/compiler.h b/src/include/compiler.h
index 4a7c48a1c..d02078b06 100644
--- a/src/include/compiler.h
+++ b/src/include/compiler.h
@@ -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
index 000000000..e122d9c39
--- /dev/null
+++ b/src/include/errno.h
@@ -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 */
diff --git a/src/include/etherboot.h b/src/include/etherboot.h
index e61a711ff..9d364282f 100644
--- a/src/include/etherboot.h
+++ b/src/include/etherboot.h
@@ -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:
diff --git a/src/include/pci_ids.h b/src/include/pci_ids.h
index bcf4c3cd8..a853d4dcb 100644
--- a/src/include/pci_ids.h
+++ b/src/include/pci_ids.h
@@ -319,6 +319,7 @@
#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
diff --git a/src/include/pxe.h b/src/include/pxe.h
index 48f555094..26ecf3a63 100644
--- a/src/include/pxe.h
+++ b/src/include/pxe.h
@@ -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.
*****************************************************************************
diff --git a/src/include/tables.h b/src/include/tables.h
index 26ad61db7..9d74df6bd 100644
--- a/src/include/tables.h
+++ b/src/include/tables.h
@@ -1,44 +1,166 @@
#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.
*
*/
@@ -49,10 +171,54 @@
#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/util/makerom.pl b/src/util/makerom.pl
index 695468c26..9d751e190 100755
--- a/src/util/makerom.pl
+++ b/src/util/makerom.pl
@@ -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);