|
@@ -28,6 +28,9 @@
|
28
|
28
|
#include <stdlib.h>
|
29
|
29
|
#include <gpxe/uaccess.h>
|
30
|
30
|
#include <gpxe/dhcp.h>
|
|
31
|
+#include <gpxe/device.h>
|
|
32
|
+#include <gpxe/netdevice.h>
|
|
33
|
+#include <gpxe/isapnp.h>
|
31
|
34
|
#include <basemem_packet.h>
|
32
|
35
|
#include "pxe.h"
|
33
|
36
|
#include "pxe_call.h"
|
|
@@ -196,41 +199,47 @@ PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE
|
196
|
199
|
* Status: working
|
197
|
200
|
*/
|
198
|
201
|
PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
|
|
202
|
+ unsigned int isapnp_read_port;
|
|
203
|
+ unsigned int isapnp_csn;
|
|
204
|
+ unsigned int pci_busdevfn;
|
|
205
|
+ unsigned int bus_type;
|
|
206
|
+ unsigned int location;
|
|
207
|
+ struct net_device *netdev;
|
|
208
|
+
|
|
209
|
+ DBG ( "PXENV_START_UNDI %04x:%04x:%04x",
|
|
210
|
+ start_undi->AX, start_undi->BX, start_undi->DX );
|
|
211
|
+
|
|
212
|
+ /* Determine bus type and location */
|
|
213
|
+ isapnp_read_port = start_undi->DX;
|
|
214
|
+ isapnp_csn = start_undi->BX;
|
|
215
|
+ pci_busdevfn = start_undi->AX;
|
|
216
|
+
|
|
217
|
+ /* Use a heuristic to decide whether we are PCI or ISAPnP */
|
|
218
|
+ if ( ( isapnp_read_port >= ISAPNP_READ_PORT_MIN ) &&
|
|
219
|
+ ( isapnp_read_port <= ISAPNP_READ_PORT_MAX ) &&
|
|
220
|
+ ( isapnp_csn >= ISAPNP_CSN_MIN ) &&
|
|
221
|
+ ( isapnp_csn <= ISAPNP_CSN_MAX ) ) {
|
|
222
|
+ bus_type = BUS_TYPE_ISAPNP;
|
|
223
|
+ location = isapnp_csn;
|
|
224
|
+ } else {
|
|
225
|
+ bus_type = BUS_TYPE_PCI;
|
|
226
|
+ location = pci_busdevfn;
|
|
227
|
+ }
|
199
|
228
|
|
200
|
|
- DBG ( "PXENV_START_UNDI" );
|
201
|
|
-
|
202
|
|
-#if 0
|
203
|
|
- /* Record PCI bus & devfn passed by caller, so we know which
|
204
|
|
- * NIC they want to use.
|
205
|
|
- *
|
206
|
|
- * If they don't match our already-existing NIC structure, set
|
207
|
|
- * values to ensure that the specified NIC is used at the next
|
208
|
|
- * call to pxe_intialise_nic().
|
209
|
|
- */
|
210
|
|
- bus = ( start_undi->AX >> 8 ) & 0xff;
|
211
|
|
- devfn = start_undi->AX & 0xff;
|
212
|
|
-
|
213
|
|
-#warning "device probing mechanism has completely changed"
|
214
|
|
-#if 0
|
215
|
|
- if ( ( pci->dev.driver == NULL ) ||
|
216
|
|
- ( pci->dev.bus != bus ) || ( pci->dev.devfn != devfn ) ) {
|
217
|
|
- /* This is quite a bit of a hack and relies on
|
218
|
|
- * knowledge of the internal operation of Etherboot's
|
219
|
|
- * probe mechanism.
|
220
|
|
- */
|
221
|
|
- DBG ( " set PCI %hhx:%hhx.%hhx",
|
222
|
|
- bus, PCI_SLOT(devfn), PCI_FUNC(devfn) );
|
223
|
|
- dev->type = BOOT_NIC;
|
224
|
|
- dev->to_probe = PROBE_PCI;
|
225
|
|
- memset ( &dev->state, 0, sizeof(dev->state) );
|
226
|
|
- pci->advance = 1;
|
227
|
|
- pci->dev.use_specified = 1;
|
228
|
|
- pci->dev.bus = bus;
|
229
|
|
- pci->dev.devfn = devfn;
|
|
229
|
+ /* Look for a matching net device */
|
|
230
|
+ netdev = find_netdev_by_location ( bus_type, location );
|
|
231
|
+ if ( ! netdev ) {
|
|
232
|
+ DBG ( " no net device found" );
|
|
233
|
+ start_undi->Status = PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC;
|
|
234
|
+ return PXENV_EXIT_FAILURE;
|
230
|
235
|
}
|
231
|
|
-#endif
|
|
236
|
+ DBG ( " using netdev %s", netdev->name );
|
232
|
237
|
|
233
|
|
-#endif
|
|
238
|
+ /* Save as PXE net device */
|
|
239
|
+ pxe_set_netdev ( netdev );
|
|
240
|
+
|
|
241
|
+ /* Hook INT 1A */
|
|
242
|
+ pxe_hook_int1a();
|
234
|
243
|
|
235
|
244
|
start_undi->Status = PXENV_STATUS_SUCCESS;
|
236
|
245
|
return PXENV_EXIT_SUCCESS;
|