Browse Source

Separated out UNDI ROM location code into undirom.c, and use struct

undi_rom rather than struct pxe_driver.  (This is part of the naming
consistency fixes).
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
6fc75f659b
2 changed files with 285 additions and 0 deletions
  1. 236
    0
      src/arch/i386/drivers/net/undirom.c
  2. 49
    0
      src/arch/i386/include/undirom.h

+ 236
- 0
src/arch/i386/drivers/net/undirom.c View File

@@ -0,0 +1,236 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <stdlib.h>
21
+#include <string.h>
22
+#include <pxe.h>
23
+#include <realmode.h>
24
+#include <bios.h>
25
+#include <pnpbios.h>
26
+#include <gpxe/pci.h>
27
+#include <undirom.h>
28
+
29
+/** @file
30
+ *
31
+ * UNDI expansion ROMs
32
+ *
33
+ */
34
+
35
+/** List of all UNDI ROMs */
36
+static LIST_HEAD ( undiroms );
37
+
38
+/**
39
+ * Parse PXE ROM ID structure
40
+ *
41
+ * @v undirom		UNDI ROM
42
+ * @v pxeromid		Offset within ROM to PXE ROM ID structure
43
+ * @ret rc		Return status code
44
+ */
45
+static int undirom_parse_pxeromid ( struct undi_rom *undirom,
46
+				   unsigned int pxeromid ) {
47
+	struct undi_rom_id undi_rom_id;
48
+	unsigned int undiloader;
49
+
50
+	DBGC ( undirom, "UNDIROM %p has PXE ROM ID at %04x:%04x\n", undirom,
51
+	       undirom->rom_segment, pxeromid );
52
+
53
+	/* Read PXE ROM ID structure and verify */
54
+	copy_from_real ( &undi_rom_id, undirom->rom_segment, pxeromid,
55
+			 sizeof ( undi_rom_id ) );
56
+	if ( undi_rom_id.Signature != UNDI_ROM_ID_SIGNATURE ) {
57
+		DBGC ( undirom, "UNDIROM %p has bad PXE ROM ID signature "
58
+		       "%08lx\n", undirom, undi_rom_id.Signature );
59
+		return -EINVAL;
60
+	}
61
+
62
+	/* Check for UNDI loader */
63
+	undiloader = undi_rom_id.UNDILoader;
64
+	if ( ! undiloader ) {
65
+		DBGC ( undirom, "UNDIROM %p has no UNDI loader\n", undirom );
66
+		return -EINVAL;
67
+	}
68
+
69
+	/* Fill in UNDI ROM loader fields */
70
+	undirom->loader_entry.segment = undirom->rom_segment;
71
+	undirom->loader_entry.offset = undiloader;
72
+	undirom->code_size = undi_rom_id.CodeSize;
73
+	undirom->data_size = undi_rom_id.DataSize;
74
+
75
+	DBGC ( undirom, "UNDIROM %p has UNDI loader at %04x:%04x "
76
+	       "(code %04x data %04x)\n", undirom,
77
+	       undirom->loader_entry.segment, undirom->loader_entry.offset,
78
+	       undirom->code_size, undirom->data_size );
79
+	return 0;
80
+}
81
+
82
+/**
83
+ * Parse PCI expansion header
84
+ *
85
+ * @v undirom		UNDI ROM
86
+ * @v pcirheader	Offset within ROM to PCI expansion header
87
+ */
88
+static int undirom_parse_pcirheader ( struct undi_rom *undirom,
89
+				     unsigned int pcirheader ) {
90
+	struct pcir_header pcir_header;
91
+
92
+	DBGC ( undirom, "UNDIROM %p has PCI expansion header at %04x:%04x\n",
93
+	       undirom, undirom->rom_segment, pcirheader );
94
+
95
+	/* Read PCI expansion header and verify */
96
+	copy_from_real ( &pcir_header, undirom->rom_segment, pcirheader,
97
+			 sizeof ( pcir_header ) );
98
+	if ( pcir_header.signature != PCIR_SIGNATURE ) {
99
+		DBGC ( undirom, "UNDIROM %p has bad PCI expansion header "
100
+		       "signature %08lx\n", undirom, pcir_header.signature );
101
+		return -EINVAL;
102
+	}
103
+
104
+	/* Fill in UNDI ROM PCI device fields */
105
+	undirom->bus_type = PCI_NIC;
106
+	undirom->bus_id.pci.vendor_id = pcir_header.vendor_id;
107
+	undirom->bus_id.pci.device_id = pcir_header.device_id;
108
+
109
+	DBGC ( undirom, "UNDIROM %p is for PCI devices %04x:%04x\n", undirom,
110
+	       undirom->bus_id.pci.vendor_id, undirom->bus_id.pci.device_id );
111
+	return 0;
112
+	
113
+}
114
+
115
+/**
116
+ * Probe UNDI ROM
117
+ *
118
+ * @v rom_segment	ROM segment address
119
+ * @ret rc		Return status code
120
+ */
121
+static int undirom_probe ( unsigned int rom_segment ) {
122
+	struct undi_rom *undirom = NULL;
123
+	struct undi_rom_header romheader;
124
+	size_t rom_len;
125
+	unsigned int pxeromid;
126
+	unsigned int pcirheader;
127
+	int rc;
128
+
129
+	/* Read expansion ROM header and verify */
130
+	copy_from_real ( &romheader, rom_segment, 0, sizeof ( romheader ) );
131
+	if ( romheader.Signature != ROM_SIGNATURE ) {
132
+		rc = -EINVAL;
133
+		goto err;
134
+	}
135
+	rom_len = ( romheader.ROMLength * 512 );
136
+
137
+	/* Allocate memory for UNDI ROM */
138
+	undirom = malloc ( sizeof ( *undirom ) );
139
+	if ( ! undirom ) {
140
+		DBG ( "Could not allocate UNDI ROM structure\n" );
141
+		rc = -ENOMEM;
142
+		goto err;
143
+	}
144
+	memset ( undirom, 0, sizeof ( *undirom ) );
145
+	DBGC ( undirom, "UNDIROM %p trying expansion ROM at %04x:0000 "
146
+	       "(%zdkB)\n", undirom, rom_segment, ( rom_len / 1024 ) );
147
+	undirom->rom_segment = rom_segment;
148
+
149
+	/* Check for and parse PXE ROM ID */
150
+	pxeromid = romheader.PXEROMID;
151
+	if ( ! pxeromid ) {
152
+		DBGC ( undirom, "UNDIROM %p has no PXE ROM ID\n", undirom );
153
+		rc = -EINVAL;
154
+		goto err;
155
+	}
156
+	if ( pxeromid > rom_len ) {
157
+		DBGC ( undirom, "UNDIROM %p PXE ROM ID outside ROM\n",
158
+		       undirom );
159
+		rc = -EINVAL;
160
+		goto err;
161
+	}
162
+	if ( ( rc = undirom_parse_pxeromid ( undirom, pxeromid ) ) != 0 )
163
+		goto err;
164
+
165
+	/* Parse PCIR header, if present */
166
+	pcirheader = romheader.PCIRHeader;
167
+	if ( pcirheader )
168
+		undirom_parse_pcirheader ( undirom, pcirheader );
169
+
170
+	/* Add to UNDI ROM list and return */
171
+	DBGC ( undirom, "UNDIROM %p registered\n", undirom );
172
+	list_add ( &undirom->list, &undiroms );
173
+	return 0;
174
+
175
+ err:
176
+	free ( undirom );
177
+	return rc;
178
+}
179
+
180
+/**
181
+ * Create UNDI ROMs for all possible expansion ROMs
182
+ *
183
+ * @ret 
184
+ */
185
+static void undirom_probe_all_roms ( void ) {
186
+	static int probed = 0;
187
+	unsigned int rom_segment;
188
+
189
+	/* Perform probe only once */
190
+	if ( probed )
191
+		return;
192
+
193
+	DBG ( "Scanning for PXE expansion ROMs\n" );
194
+
195
+	/* Scan through expansion ROM region at 2kB intervals */
196
+	for ( rom_segment = 0xc000 ; rom_segment < 0x10000 ;
197
+	      rom_segment += 0x80 ) {
198
+		undirom_probe ( rom_segment );
199
+	}
200
+
201
+	probed = 1;
202
+}
203
+
204
+/**
205
+ * Find UNDI ROM for PCI device
206
+ *
207
+ * @v vendor_id		PCI vendor ID
208
+ * @v device_id		PCI device ID
209
+ * @v rombase		ROM base address, or 0 for any
210
+ * @ret undirom		UNDI ROM, or NULL
211
+ */
212
+struct undi_rom * undirom_find_pci ( unsigned int vendor_id,
213
+				     unsigned int device_id,
214
+				     unsigned int rombase ) {
215
+	struct undi_rom *undirom;
216
+
217
+	undirom_probe_all_roms();
218
+
219
+	list_for_each_entry ( undirom, &undiroms, list ) {
220
+		if ( undirom->bus_type != PCI_NIC )
221
+			continue;
222
+		if ( undirom->bus_id.pci.vendor_id != vendor_id )
223
+			continue;
224
+		if ( undirom->bus_id.pci.device_id != device_id )
225
+			continue;
226
+		if ( rombase && ( ( undirom->rom_segment << 4 ) != rombase ) )
227
+			continue;
228
+		DBGC ( undirom, "UNDIROM %p matched PCI %04x:%04x (%08x)\n",
229
+		       undirom, vendor_id, device_id, rombase );
230
+		return undirom;
231
+	}
232
+
233
+	DBG ( "No UNDI ROM matched PCI %04x:%04x (%08x)\n",
234
+	      vendor_id, device_id, rombase );
235
+	return NULL;
236
+}

+ 49
- 0
src/arch/i386/include/undirom.h View File

@@ -0,0 +1,49 @@
1
+#ifndef _UNDIROM_H
2
+#define _UNDIROM_H
3
+
4
+/** @file
5
+ *
6
+ * UNDI expansion ROMs
7
+ *
8
+ */
9
+
10
+/** An UNDI PCI device ID */
11
+struct undi_pci_device_id {
12
+	/** PCI vendor ID */
13
+	unsigned int vendor_id;
14
+	/** PCI device ID */
15
+	unsigned int device_id;
16
+};
17
+
18
+/** An UNDI device ID */
19
+union undi_device_id {
20
+	/** PCI device ID */
21
+	struct undi_pci_device_id pci;
22
+};
23
+
24
+/** An UNDI ROM */
25
+struct undi_rom {
26
+	/** List of UNDI ROMs */
27
+	struct list_head list;
28
+	/** ROM segment address */
29
+	unsigned int rom_segment;
30
+	/** UNDI loader entry point */
31
+	SEGOFF16_t loader_entry;
32
+	/** Code segment size */
33
+	size_t code_size;
34
+	/** Data segment size */
35
+	size_t data_size;
36
+	/** Bus type
37
+	 *
38
+	 * Values are as used by @c PXENV_UNDI_GET_NIC_TYPE
39
+	 */
40
+	unsigned int bus_type;
41
+	/** Device ID */
42
+	union undi_device_id bus_id;
43
+};
44
+
45
+extern struct undi_rom * undirom_find_pci ( unsigned int vendor_id,
46
+					    unsigned int device_id,
47
+					    unsigned int rombase );
48
+
49
+#endif /* _UNDIROM_H */

Loading…
Cancel
Save