/************************************************************************** Etherboot - BOOTP/TFTP Bootstrap Program UNDI NIC driver for Etherboot - header file This file Copyright (C) 2003 Michael Brown 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