diff options
Diffstat (limited to 'src')
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); |
