exchange epic100.c with the special boot code

All Etherboot drivers have the option to boot (in case of an error or user intervention) from harddisk. To make harddisk booting the default starting method and remove the network card specific code, we have to patch one of the Etherboot drivers. I choosed the epic100 driver because of its size ;)

Here you can see how its done:

#ifdef ALLMULTI
#error multicast support is not yet implemented
#endif
/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Etherboot */

#define LINUX_OUT_MACROS

#include "etherboot.h"
#include "nic.h"
#include "cards.h"
#include "timer.h"
#include "epic100.h"

#undef  virt_to_bus
#define virt_to_bus(x)  ((unsigned long)x)

#define TX_RING_SIZE    2       /* use at least 2 buffers for TX */
#define RX_RING_SIZE    2

#define PKT_BUF_SZ      1536    /* Size of each temporary Tx/Rx buffer.*/

/*
#define DEBUG_RX
#define DEBUG_TX
#define DEBUG_EEPROM
*/

#define EPIC_DEBUG 0    /* debug level */

/* The EPIC100 Rx and Tx buffer descriptors. */
struct epic_rx_desc {
    unsigned short status;
    unsigned short rxlength;
    unsigned long  bufaddr;
    unsigned short buflength;
    unsigned short control;
    unsigned long  next;
};

/* description of the tx descriptors control bits commonly used */
#define TD_STDFLAGS     TD_LASTDESC

struct epic_tx_desc {
    unsigned short status;
    unsigned short txlength;
    unsigned long  bufaddr;
    unsigned short buflength;
    unsigned short control;
    unsigned long  next;
};

#define delay(nanosec)   do { int _i = 3; while (--_i > 0) \
                                     { __SLOW_DOWN_IO; }} while (0)

static void     epic100_open(void);
static void     epic100_init_ring(void);
static void     epic100_disable(struct nic *nic);
static int      epic100_poll(struct nic *nic);
static void     epic100_transmit(struct nic *nic, const char *destaddr,
                                 unsigned int type, unsigned int len, const char *data);
static int      read_eeprom(int location);
static int      mii_read(int phy_id, int location);

static int      ioaddr;

static int      command;
static int      intstat;
static int      intmask;
static int      genctl ;
static int      eectl  ;
static int      test   ;
static int      mmctl  ;
static int      mmdata ;
static int      lan0   ;
static int      rxcon  ;
static int      txcon  ;
static int      prcdar ;
static int      ptcdar ;
static int      eththr ;

static unsigned int     cur_rx, cur_tx;         /* The next free ring entry */
#ifdef  DEBUG_EEPROM
static unsigned short   eeprom[64];
#endif
static signed char      phys[4];                /* MII device addresses. */
static struct epic_rx_desc      rx_ring[RX_RING_SIZE];
static struct epic_tx_desc      tx_ring[TX_RING_SIZE];
#ifdef  USE_LOWMEM_BUFFER
#define rx_packet ((char *)0x10000 - PKT_BUF_SZ * RX_RING_SIZE)
#define tx_packet ((char *)0x10000 - PKT_BUF_SZ * RX_RING_SIZE - PKT_BUF_SZ * TX_RING_SIZE)
#else
static char             rx_packet[PKT_BUF_SZ * RX_RING_SIZE];
static char             tx_packet[PKT_BUF_SZ * TX_RING_SIZE];
#endif

/***********************************************************************/
/*                    Externally visible functions                     */
/***********************************************************************/

    static void
epic100_reset(struct nic *nic)
{
    /* Soft reset the chip. */
    outl(GC_SOFT_RESET, genctl);
}

    struct nic*
epic100_probe(struct nic *nic, unsigned short *probeaddrs)
{
 return 0;
}

    static void
epic100_open(void)
{
}

/* Initialize the Rx and Tx rings. */
    static void
epic100_init_ring(void)
{
}

/* function: epic100_transmit
 * This transmits a packet.
 *
 * Arguments: char d[6]:          destination ethernet address.
 *            unsigned short t:   ethernet protocol type.
 *            unsigned short s:   size of the data-part of the packet.
 *            char *p:            the data for the packet.
 * returns:   void.
 */
    static void
epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
                 unsigned int len, const char *data)
{
}

/* function: epic100_poll / eth_poll
 * This receives a packet from the network.
 *
 * Arguments: none
 *
 * returns:   1 if a packet was received.
 *            0 if no pacet was received.
 * side effects:
 *            returns the packet in the array nic->packet.
 *            returns the length of the packet in nic->packetlen.
 */

    static int
epic100_poll(struct nic *nic)
{
    return 0;
}


    static void
epic100_disable(struct nic *nic)
{
}


#ifdef  DEBUG_EEPROM
/* Serial EEPROM section. */

/*  EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK    0x04    /* EEPROM shift clock. */
#define EE_CS           0x02    /* EEPROM chip select. */
#define EE_DATA_WRITE   0x08    /* EEPROM chip data in. */
#define EE_WRITE_0      0x01
#define EE_WRITE_1      0x09
#define EE_DATA_READ    0x10    /* EEPROM chip data out. */
#define EE_ENB          (0x0001 | EE_CS)

/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD    (5 << 6)
#define EE_READ_CMD     (6 << 6)
#define EE_ERASE_CMD    (7 << 6)

#define eeprom_delay(n) delay(n)

    static int
read_eeprom(int location)
{
 return 0;
}
#endif


#define MII_READOP      1
#define MII_WRITEOP     2

    static int
mii_read(int phy_id, int location)
{
 return 0;
}

Exchange the code from the epic100.c file (in the src directory) with the code above. Now you have tho change the default boot type. Exchange in etherboot.h

#ifndef	ANS_DEFAULT	/* in case left out in Makefile */
#define	ANS_DEFAULT	ANS_NETWORK
#endif
with
#define	ANS_DEFAULT ANS_LOCAL
and
#define TIMEOUT			(10*TICKS_PER_SEC)
with
#define TIMEOUT			(1*TICKS_PER_SEC)

Now execute the following commands:

make clean
make



dodger 2018-05-08