aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown <mcb30@etherboot.org>2007-07-03 18:17:14 +0100
committerMichael Brown <mcb30@etherboot.org>2007-07-03 18:17:14 +0100
commit0924cf678e67020de2e928dbbe773e45be1c8551 (patch)
treeb87e818d32b7a35c73dcf4c9c30b43db09ef03bf
parent30a442aef8ef1431be21e53e2265bfeb85403b60 (diff)
downloadipxe-0924cf678e67020de2e928dbbe773e45be1c8551.tar.gz
Implemented (untested) PXENV_START_UNDI.
-rw-r--r--src/drivers/bus/isapnp.c2
-rw-r--r--src/include/gpxe/isapnp.h7
-rw-r--r--src/include/gpxe/netdevice.h11
-rw-r--r--src/interface/pxe/pxe_preboot.c73
-rw-r--r--src/net/netdevice.c10
5 files changed, 60 insertions, 43 deletions
diff --git a/src/drivers/bus/isapnp.c b/src/drivers/bus/isapnp.c
index 79268d440..b34108c77 100644
--- a/src/drivers/bus/isapnp.c
+++ b/src/drivers/bus/isapnp.c
@@ -529,7 +529,7 @@ static int isapnp_try_isolate ( void ) {
*
*/
static void isapnp_isolate ( void ) {
- for ( isapnp_read_port = ISAPNP_READ_PORT_MIN ;
+ for ( isapnp_read_port = ISAPNP_READ_PORT_START ;
isapnp_read_port <= ISAPNP_READ_PORT_MAX ;
isapnp_read_port += ISAPNP_READ_PORT_STEP ) {
/* Avoid problematic locations such as the NE2000
diff --git a/src/include/gpxe/isapnp.h b/src/include/gpxe/isapnp.h
index 72ce0a6fe..07797a993 100644
--- a/src/include/gpxe/isapnp.h
+++ b/src/include/gpxe/isapnp.h
@@ -49,7 +49,8 @@
/* Port addresses */
#define ISAPNP_ADDRESS 0x279
#define ISAPNP_WRITE_DATA 0xa79
-#define ISAPNP_READ_PORT_MIN 0x213 /* ISAPnP spec says 0x203, but
+#define ISAPNP_READ_PORT_MIN 0x203
+#define ISAPNP_READ_PORT_START 0x213 /* ISAPnP spec says 0x203, but
* Linux ISAPnP starts at
* 0x213 with no explanatory
* comment. 0x203 probably
@@ -63,6 +64,10 @@
* any value less than 16.
*/
+/* Card select numbers */
+#define ISAPNP_CSN_MIN 0x01
+#define ISAPNP_CSN_MAX 0x0f
+
/* Registers */
#define ISAPNP_READPORT 0x00
#define ISAPNP_SERIALISOLATION 0x01
diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h
index c0df7c967..0bc5311ca 100644
--- a/src/include/gpxe/netdevice.h
+++ b/src/include/gpxe/netdevice.h
@@ -289,8 +289,9 @@ netdev_put ( struct net_device *netdev ) {
}
extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
-void netdev_tx_complete ( struct net_device *netdev, struct io_buffer *iobuf );
-void netdev_tx_complete_next ( struct net_device *netdev );
+extern void netdev_tx_complete ( struct net_device *netdev,
+ struct io_buffer *iobuf );
+extern void netdev_tx_complete_next ( struct net_device *netdev );
extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf );
extern int netdev_poll ( struct net_device *netdev, unsigned int rx_quota );
extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev );
@@ -299,9 +300,9 @@ extern int register_netdev ( struct net_device *netdev );
extern int netdev_open ( struct net_device *netdev );
extern void netdev_close ( struct net_device *netdev );
extern void unregister_netdev ( struct net_device *netdev );
-struct net_device * find_netdev ( const char *name );
-struct net_device * find_pci_netdev ( unsigned int busdevfn );
-
+extern struct net_device * find_netdev ( const char *name );
+extern struct net_device * find_netdev_by_location ( unsigned int bus_type,
+ unsigned int location );
extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
struct net_protocol *net_protocol, const void *ll_dest );
extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
diff --git a/src/interface/pxe/pxe_preboot.c b/src/interface/pxe/pxe_preboot.c
index 15752b231..a74e58af9 100644
--- a/src/interface/pxe/pxe_preboot.c
+++ b/src/interface/pxe/pxe_preboot.c
@@ -28,6 +28,9 @@
#include <stdlib.h>
#include <gpxe/uaccess.h>
#include <gpxe/dhcp.h>
+#include <gpxe/device.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/isapnp.h>
#include <basemem_packet.h>
#include "pxe.h"
#include "pxe_call.h"
@@ -196,41 +199,47 @@ PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE
* Status: working
*/
PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
+ unsigned int isapnp_read_port;
+ unsigned int isapnp_csn;
+ unsigned int pci_busdevfn;
+ unsigned int bus_type;
+ unsigned int location;
+ struct net_device *netdev;
+
+ DBG ( "PXENV_START_UNDI %04x:%04x:%04x",
+ start_undi->AX, start_undi->BX, start_undi->DX );
+
+ /* Determine bus type and location */
+ isapnp_read_port = start_undi->DX;
+ isapnp_csn = start_undi->BX;
+ pci_busdevfn = start_undi->AX;
+
+ /* Use a heuristic to decide whether we are PCI or ISAPnP */
+ if ( ( isapnp_read_port >= ISAPNP_READ_PORT_MIN ) &&
+ ( isapnp_read_port <= ISAPNP_READ_PORT_MAX ) &&
+ ( isapnp_csn >= ISAPNP_CSN_MIN ) &&
+ ( isapnp_csn <= ISAPNP_CSN_MAX ) ) {
+ bus_type = BUS_TYPE_ISAPNP;
+ location = isapnp_csn;
+ } else {
+ bus_type = BUS_TYPE_PCI;
+ location = pci_busdevfn;
+ }
- DBG ( "PXENV_START_UNDI" );
-
-#if 0
- /* Record PCI bus & devfn passed by caller, so we know which
- * NIC they want to use.
- *
- * If they don't match our already-existing NIC structure, set
- * values to ensure that the specified NIC is used at the next
- * call to pxe_intialise_nic().
- */
- bus = ( start_undi->AX >> 8 ) & 0xff;
- devfn = start_undi->AX & 0xff;
-
-#warning "device probing mechanism has completely changed"
-#if 0
- if ( ( pci->dev.driver == NULL ) ||
- ( pci->dev.bus != bus ) || ( pci->dev.devfn != devfn ) ) {
- /* This is quite a bit of a hack and relies on
- * knowledge of the internal operation of Etherboot's
- * probe mechanism.
- */
- DBG ( " set PCI %hhx:%hhx.%hhx",
- bus, PCI_SLOT(devfn), PCI_FUNC(devfn) );
- dev->type = BOOT_NIC;
- dev->to_probe = PROBE_PCI;
- memset ( &dev->state, 0, sizeof(dev->state) );
- pci->advance = 1;
- pci->dev.use_specified = 1;
- pci->dev.bus = bus;
- pci->dev.devfn = devfn;
+ /* Look for a matching net device */
+ netdev = find_netdev_by_location ( bus_type, location );
+ if ( ! netdev ) {
+ DBG ( " no net device found" );
+ start_undi->Status = PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC;
+ return PXENV_EXIT_FAILURE;
}
-#endif
+ DBG ( " using netdev %s", netdev->name );
-#endif
+ /* Save as PXE net device */
+ pxe_set_netdev ( netdev );
+
+ /* Hook INT 1A */
+ pxe_hook_int1a();
start_undi->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 8a0991079..971830d97 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -356,15 +356,17 @@ struct net_device * find_netdev ( const char *name ) {
/**
* Get network device by PCI bus:dev.fn address
*
- * @v busdevfn PCI bus:dev.fn address
+ * @v bus_type Bus type
+ * @v location Bus location
* @ret netdev Network device, or NULL
*/
-struct net_device * find_pci_netdev ( unsigned int busdevfn ) {
+struct net_device * find_netdev_by_location ( unsigned int bus_type,
+ unsigned int location ) {
struct net_device *netdev;
list_for_each_entry ( netdev, &net_devices, list ) {
- if ( ( netdev->dev->desc.bus_type == BUS_TYPE_PCI ) &&
- ( netdev->dev->desc.location == busdevfn ) )
+ if ( ( netdev->dev->desc.bus_type == bus_type ) &&
+ ( netdev->dev->desc.location == location ) )
return netdev;
}