| /************************************************************************** |
| 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 |