summaryrefslogtreecommitdiff
path: root/usr/src/grub/grub-0.97/netboot/undi.h
blob: 511de98b8aae1ae9a680e11af0df5984bc3421ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/**************************************************************************
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