root/usr/src/grub/grub-0.97/netboot/undi.h
/**************************************************************************
Etherboot -  BOOTP/TFTP Bootstrap Program
UNDI NIC driver for Etherboot - header file

This file Copyright (C) 2003 Michael Brown <mbrown@fensystems.co.uk>
of Fen Systems Ltd. (http://www.fensystems.co.uk/).  All rights
reserved.

$Id: undi.h,v 1.5 2003/10/24 10:05:06 mcb30 Exp $
***************************************************************************/

/*
 * 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
 * your option) any later version.
 */

/* Include pxe.h from FreeBSD.
 * pxe.h defines PACKED, which etherboot.h has already defined.
 */

#undef PACKED
#include "pxe.h"
#include "pic8259.h"

/* __undi_call is the assembler wrapper to the real-mode UNDI calls.
 * Pass it the real-mode segment:offset address of an undi_call_info_t
 * structure.  The parameters are only uint16_t, but GCC will push
 * them on the stack as uint32_t anyway for the sake of alignment.  We
 * specify them here as uint32_t to remove ambiguity.
 */

typedef struct undi_call_info {
        SEGOFF16_t      routine;
        uint16_t        stack[3];
} undi_call_info_t;

typedef uint16_t PXENV_EXIT_t;
#define PXENV_EXIT_SUCCESS 0x0000
#define PXENV_EXIT_FAILURE 0x0001
PXENV_EXIT_t __undi_call ( uint32_t, uint32_t );

/* The UNDI loader parameter structure is not defined in pxe.h
 */

typedef struct undi_loader {
        PXENV_STATUS_t  status;
        uint16_t        ax;
        uint16_t        bx;
        uint16_t        dx;
        uint16_t        di;
        uint16_t        es;
        uint16_t        undi_ds;
        uint16_t        undi_cs;
        uint16_t        pxe_off;
        uint16_t        pxenv_off;
} undi_loader_t;

/* A union that can function as the parameter block for any UNDI API call.
 */

typedef union pxenv_structure {
        PXENV_STATUS_t                  Status; /* Make it easy to read status
                                                   for any operation */
        undi_loader_t                   loader;
        t_PXENV_START_UNDI              start_undi;
        t_PXENV_UNDI_STARTUP            undi_startup;
        t_PXENV_UNDI_CLEANUP            undi_cleanup;
        t_PXENV_UNDI_INITIALIZE         undi_initialize;
        t_PXENV_UNDI_SHUTDOWN           undi_shutdown;
        t_PXENV_UNDI_OPEN               undi_open;
        t_PXENV_UNDI_CLOSE              undi_close;
        t_PXENV_UNDI_TRANSMIT           undi_transmit;
        t_PXENV_UNDI_SET_STATION_ADDRESS undi_set_station_address;
        t_PXENV_UNDI_GET_INFORMATION    undi_get_information;
        t_PXENV_UNDI_GET_IFACE_INFO     undi_get_iface_info;
        t_PXENV_UNDI_ISR                undi_isr;
        t_PXENV_STOP_UNDI               stop_undi;
        t_PXENV_UNLOAD_STACK            unload_stack;
        t_PXENV_GET_CACHED_INFO         get_cached_info;
        t_PXENV_UDP_OPEN                udp_open;
        t_PXENV_UDP_CLOSE               udp_close;
        t_PXENV_UDP_READ                udp_read;
        t_PXENV_UDP_WRITE               udp_write;
        t_PXENV_TFTP_OPEN               tftp_open;
        t_PXENV_TFTP_CLOSE              tftp_close;
        t_PXENV_TFTP_READ               tftp_read;
        t_PXENV_TFTP_GET_FSIZE          tftp_get_fsize;
} pxenv_structure_t;

/* UNDI status codes
 */

#define PXENV_STATUS_SUCCESS                    0x0000
#define PXENV_STATUS_FAILURE                    0x0001
#define PXENV_STATUS_KEEP_UNDI                  0x0004
#define PXENV_STATUS_KEEP_ALL                   0x0005
#define PXENV_STATUS_UNDI_MEDIATEST_FAILED      0x0061

/* BIOS PnP parameter block.  We scan for this so that we can pass it
 * to the UNDI driver.
 */

#define PNP_BIOS_SIGNATURE ( ('$'<<0) + ('P'<<8) + ('n'<<16) + ('P'<<24) )
typedef struct pnp_bios {
        uint32_t        signature;
        uint8_t         version;
        uint8_t         length;
        uint16_t        control;
        uint8_t         checksum;
        uint8_t         dontcare[24];
} PACKED pnp_bios_t;

/* Structures within the PXE ROM.
 */

#define ROM_SIGNATURE 0xaa55
typedef struct rom {
        uint16_t        signature;
        uint8_t         unused[0x14];
        uint16_t        undi_rom_id_off;
        uint16_t        pcir_off;
        uint16_t        pnp_off;
} PACKED rom_t; 

#define PCIR_SIGNATURE ( ('P'<<0) + ('C'<<8) + ('I'<<16) + ('R'<<24) )
typedef struct pcir_header {
        uint32_t        signature;
        uint16_t        vendor_id;
        uint16_t        device_id;
} PACKED pcir_header_t;

#define PNP_SIGNATURE ( ('$'<<0) + ('P'<<8) + ('n'<<16) + ('P'<<24) )
typedef struct pnp_header {
        uint32_t        signature;
        uint8_t         struct_revision;
        uint8_t         length;
        uint16_t        next;
        uint8_t         reserved;
        uint8_t         checksum;
        uint16_t        id[2];
        uint16_t        manuf_str_off;
        uint16_t        product_str_off;
        uint8_t         base_type;
        uint8_t         sub_type;
        uint8_t         interface_type;
        uint8_t         indicator;
        uint16_t        boot_connect_off;
        uint16_t        disconnect_off;
        uint16_t        initialise_off;
        uint16_t        reserved2;
        uint16_t        info;
} PACKED pnp_header_t;

#define UNDI_SIGNATURE ( ('U'<<0) + ('N'<<8) + ('D'<<16) + ('I'<<24) )
typedef struct undi_rom_id {
        uint32_t        signature;
        uint8_t         struct_length;
        uint8_t         struct_cksum;
        uint8_t         struct_rev;
        uint8_t         undi_rev[3];
        uint16_t        undi_loader_off;
        uint16_t        stack_size;
        uint16_t        data_size;
        uint16_t        code_size;
} PACKED undi_rom_id_t;

/* Storage buffers that we need in base memory.  We collect these into
 * a single structure to make allocation simpler.
 */

typedef struct undi_base_mem_xmit_data {
        MAC_ADDR                destaddr;
        t_PXENV_UNDI_TBD        tbd;
} undi_base_mem_xmit_data_t;

typedef struct undi_base_mem_data {
        undi_call_info_t        undi_call_info;
        pxenv_structure_t       pxs;
        undi_base_mem_xmit_data_t xmit_data;
        char                    xmit_buffer[ETH_FRAME_LEN];
        char                    irq_handler[0]; /* Must be last in structure */
} undi_base_mem_data_t;

/* Macros and data structures used when freeing bits of base memory
 * used by the UNDI driver.
 */

#define FIRING_SQUAD_TARGET_SIZE 8
#define FIRING_SQUAD_TARGET_INDEX(x) ( (x) / FIRING_SQUAD_TARGET_SIZE )
#define FIRING_SQUAD_TARGET_BIT(x) ( (x) % FIRING_SQUAD_TARGET_SIZE )
typedef struct firing_squad_lineup {
        uint8_t targets[ 640 / FIRING_SQUAD_TARGET_SIZE ];
} firing_squad_lineup_t;
typedef enum firing_squad_shoot {
        DONTSHOOT = 0,
        SHOOT = 1
} firing_squad_shoot_t;

/* Driver private data structure.
 */

typedef struct undi {
        /* Pointers to various data structures */
        pnp_bios_t              *pnp_bios;
        rom_t                   *rom;
        undi_rom_id_t           *undi_rom_id;
        pxe_t                   *pxe;
        undi_call_info_t        *undi_call_info;
        pxenv_structure_t       *pxs;
        undi_base_mem_xmit_data_t *xmit_data;
        /* Pointers and sizes to keep track of allocated base memory */
        undi_base_mem_data_t    *base_mem_data;
        void                    *driver_code;
        size_t                  driver_code_size;
        void                    *driver_data;
        size_t                  driver_data_size;
        char                    *xmit_buffer;
        /* Flags.  We keep our own instead of trusting the UNDI driver
         * to have implemented PXENV_UNDI_GET_STATE correctly.  Plus
         * there's the small issue of PXENV_UNDI_GET_STATE being the
         * same API call as PXENV_STOP_UNDI...
         */
        uint8_t prestarted;     /* pxenv_start_undi() has been called */
        uint8_t started;        /* pxenv_undi_startup() has been called */
        uint8_t initialized;    /* pxenv_undi_initialize() has been called */
        uint8_t opened;         /* pxenv_undi_open() has been called */
        /* Parameters that we need to store for future reference
         */
        struct pci_device       pci;
        irq_t                   irq;
} undi_t;

/* Constants
 */

#define HUNT_FOR_PIXIES 0
#define HUNT_FOR_UNDI_ROMS 1