aboutsummaryrefslogtreecommitdiffstats
path: root/gpxe/src/drivers/bus
diff options
context:
space:
mode:
Diffstat (limited to 'gpxe/src/drivers/bus')
-rw-r--r--gpxe/src/drivers/bus/eisa.c7
-rw-r--r--gpxe/src/drivers/bus/isa.c9
-rw-r--r--gpxe/src/drivers/bus/isapnp.c9
-rw-r--r--gpxe/src/drivers/bus/mca.c9
-rw-r--r--gpxe/src/drivers/bus/pci.c9
-rw-r--r--gpxe/src/drivers/bus/pcibackup.c90
-rw-r--r--gpxe/src/drivers/bus/pciextra.c7
7 files changed, 111 insertions, 29 deletions
diff --git a/gpxe/src/drivers/bus/eisa.c b/gpxe/src/drivers/bus/eisa.c
index d9e42359..b533364b 100644
--- a/gpxe/src/drivers/bus/eisa.c
+++ b/gpxe/src/drivers/bus/eisa.c
@@ -7,10 +7,7 @@
#include <unistd.h>
#include <gpxe/eisa.h>
-static struct eisa_driver eisa_drivers[0]
- __table_start ( struct eisa_driver, eisa_drivers );
-static struct eisa_driver eisa_drivers_end[0]
- __table_end ( struct eisa_driver, eisa_drivers );
+FILE_LICENCE ( GPL2_OR_LATER );
static void eisabus_remove ( struct root_device *rootdev );
@@ -57,7 +54,7 @@ static int eisa_probe ( struct eisa_device *eisa ) {
eisa->slot, eisa->vendor_id, eisa->prod_id,
isa_id_string ( eisa->vendor_id, eisa->prod_id ), eisa->ioaddr );
- for ( driver = eisa_drivers; driver < eisa_drivers_end; driver++ ) {
+ for_each_table_entry ( driver, EISA_DRIVERS ) {
for ( i = 0 ; i < driver->id_count ; i++ ) {
id = &driver->ids[i];
if ( id->vendor_id != eisa->vendor_id )
diff --git a/gpxe/src/drivers/bus/isa.c b/gpxe/src/drivers/bus/isa.c
index fa5def54..f458826d 100644
--- a/gpxe/src/drivers/bus/isa.c
+++ b/gpxe/src/drivers/bus/isa.c
@@ -6,6 +6,8 @@
#include <gpxe/io.h>
#include <gpxe/isa.h>
+FILE_LICENCE ( GPL2_OR_LATER );
+
/*
* isa.c implements a "classical" port-scanning method of ISA device
* detection. The driver must provide a list of probe addresses
@@ -48,11 +50,6 @@ static isa_probe_addr_t isa_extra_probe_addrs[] = {
isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \
(driver)->probe_addrs[(ioidx)] )
-static struct isa_driver isa_drivers[0]
- __table_start ( struct isa_driver, isa_drivers );
-static struct isa_driver isa_drivers_end[0]
- __table_end ( struct isa_driver, isa_drivers );
-
static void isabus_remove ( struct root_device *rootdev );
/**
@@ -100,7 +97,7 @@ static int isabus_probe ( struct root_device *rootdev ) {
int ioidx;
int rc;
- for ( driver = isa_drivers ; driver < isa_drivers_end ; driver++ ) {
+ for_each_table_entry ( driver, ISA_DRIVERS ) {
for ( ioidx = ISA_IOIDX_MIN ( driver ) ;
ioidx <= ISA_IOIDX_MAX ( driver ) ; ioidx++ ) {
/* Allocate struct isa_device */
diff --git a/gpxe/src/drivers/bus/isapnp.c b/gpxe/src/drivers/bus/isapnp.c
index 8f812df8..ccf6209f 100644
--- a/gpxe/src/drivers/bus/isapnp.c
+++ b/gpxe/src/drivers/bus/isapnp.c
@@ -55,6 +55,8 @@
*
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -72,11 +74,6 @@
*/
uint16_t isapnp_read_port;
-static struct isapnp_driver isapnp_drivers[0]
- __table_start ( struct isapnp_driver, isapnp_drivers );
-static struct isapnp_driver isapnp_drivers_end[0]
- __table_end ( struct isapnp_driver, isapnp_drivers );
-
static void isapnpbus_remove ( struct root_device *rootdev );
/*
@@ -594,7 +591,7 @@ static int isapnp_probe ( struct isapnp_device *isapnp ) {
isa_id_string ( isapnp->vendor_id, isapnp->prod_id ),
isapnp->ioaddr, isapnp->irqno );
- for ( driver = isapnp_drivers; driver < isapnp_drivers_end; driver++ ){
+ for_each_table_entry ( driver, ISAPNP_DRIVERS ) {
for ( i = 0 ; i < driver->id_count ; i++ ) {
id = &driver->ids[i];
if ( id->vendor_id != isapnp->vendor_id )
diff --git a/gpxe/src/drivers/bus/mca.c b/gpxe/src/drivers/bus/mca.c
index e9233813..2815603e 100644
--- a/gpxe/src/drivers/bus/mca.c
+++ b/gpxe/src/drivers/bus/mca.c
@@ -5,6 +5,8 @@
*
*/
+FILE_LICENCE ( BSD2 );
+
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
@@ -13,11 +15,6 @@
#include <gpxe/io.h>
#include <gpxe/mca.h>
-static struct mca_driver mca_drivers[0]
- __table_start ( struct mca_driver, mca_drivers );
-static struct mca_driver mca_drivers_end[0]
- __table_end ( struct mca_driver, mca_drivers );
-
static void mcabus_remove ( struct root_device *rootdev );
/**
@@ -41,7 +38,7 @@ static int mca_probe ( struct mca_device *mca ) {
mca->pos[0], mca->pos[1], mca->pos[2], mca->pos[3],
mca->pos[4], mca->pos[5], mca->pos[6], mca->pos[7] );
- for ( driver = mca_drivers; driver < mca_drivers_end; driver++ ){
+ for_each_table_entry ( driver, MCA_DRIVERS ) {
for ( i = 0 ; i < driver->id_count ; i++ ) {
id = &driver->ids[i];
if ( id->id != MCA_ID ( mca ) )
diff --git a/gpxe/src/drivers/bus/pci.c b/gpxe/src/drivers/bus/pci.c
index 2dc9d43a..8899e6e1 100644
--- a/gpxe/src/drivers/bus/pci.c
+++ b/gpxe/src/drivers/bus/pci.c
@@ -19,6 +19,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
@@ -34,11 +36,6 @@
*
*/
-static struct pci_driver pci_drivers[0]
- __table_start ( struct pci_driver, pci_drivers );
-static struct pci_driver pci_drivers_end[0]
- __table_end ( struct pci_driver, pci_drivers );
-
static void pcibus_remove ( struct root_device *rootdev );
/**
@@ -188,7 +185,7 @@ static int pci_probe ( struct pci_device *pci ) {
PCI_FUNC ( pci->devfn ), pci->vendor, pci->device,
pci->membase, pci->ioaddr, pci->irq );
- for ( driver = pci_drivers ; driver < pci_drivers_end ; driver++ ) {
+ for_each_table_entry ( driver, PCI_DRIVERS ) {
for ( i = 0 ; i < driver->id_count ; i++ ) {
id = &driver->ids[i];
if ( ( id->vendor != PCI_ANY_ID ) &&
diff --git a/gpxe/src/drivers/bus/pcibackup.c b/gpxe/src/drivers/bus/pcibackup.c
new file mode 100644
index 00000000..8f9994ec
--- /dev/null
+++ b/gpxe/src/drivers/bus/pcibackup.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * 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 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <gpxe/pci.h>
+#include <gpxe/pcibackup.h>
+
+/** @file
+ *
+ * PCI configuration space backup and restoration
+ *
+ */
+
+/**
+ * Check PCI configuration space offset against exclusion list
+ *
+ * @v pci PCI device
+ * @v offset Offset within PCI configuration space
+ * @v exclude PCI configuration space backup exclusion list, or NULL
+ */
+static int
+pci_backup_excluded ( struct pci_device *pci, unsigned int offset,
+ const uint8_t *exclude ) {
+
+ if ( ! exclude )
+ return 0;
+ for ( ; *exclude != PCI_CONFIG_BACKUP_EXCLUDE_END ; exclude++ ) {
+ if ( offset == *exclude ) {
+ DBGC ( pci, "PCI %p skipping configuration offset "
+ "%02x\n", pci, offset );
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Back up PCI configuration space
+ *
+ * @v pci PCI device
+ * @v backup PCI configuration space backup
+ * @v exclude PCI configuration space backup exclusion list, or NULL
+ */
+void pci_backup ( struct pci_device *pci, struct pci_config_backup *backup,
+ const uint8_t *exclude ) {
+ unsigned int offset;
+ uint32_t *dword;
+
+ for ( offset = 0, dword = backup->dwords ; offset < 0x100 ;
+ offset += sizeof ( *dword ) , dword++ ) {
+ if ( ! pci_backup_excluded ( pci, offset, exclude ) )
+ pci_read_config_dword ( pci, offset, dword );
+ }
+}
+
+/**
+ * Restore PCI configuration space
+ *
+ * @v pci PCI device
+ * @v backup PCI configuration space backup
+ * @v exclude PCI configuration space backup exclusion list, or NULL
+ */
+void pci_restore ( struct pci_device *pci, struct pci_config_backup *backup,
+ const uint8_t *exclude ) {
+ unsigned int offset;
+ uint32_t *dword;
+
+ for ( offset = 0, dword = backup->dwords ; offset < 0x100 ;
+ offset += sizeof ( *dword ) , dword++ ) {
+ if ( ! pci_backup_excluded ( pci, offset, exclude ) )
+ pci_write_config_dword ( pci, offset, *dword );
+ }
+}
diff --git a/gpxe/src/drivers/bus/pciextra.c b/gpxe/src/drivers/bus/pciextra.c
index 4603bcb9..74c40990 100644
--- a/gpxe/src/drivers/bus/pciextra.c
+++ b/gpxe/src/drivers/bus/pciextra.c
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER );
+
#include <stdint.h>
#include <gpxe/pci.h>
@@ -58,8 +60,11 @@ int pci_find_capability ( struct pci_device *pci, int cap ) {
* function.
*/
unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) {
+ uint16_t cmd;
uint32_t start, size;
+ /* Save the original command register */
+ pci_read_config_word ( pci, PCI_COMMAND, &cmd );
/* Save the original bar */
pci_read_config_dword ( pci, reg, &start );
/* Compute which bits can be set */
@@ -68,6 +73,8 @@ unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) {
/* Restore the original size */
pci_write_config_dword ( pci, reg, start );
/* Find the significant bits */
+ /* Restore the original command register. This reenables decoding. */
+ pci_write_config_word ( pci, PCI_COMMAND, cmd );
if ( start & PCI_BASE_ADDRESS_SPACE_IO ) {
size &= PCI_BASE_ADDRESS_IO_MASK;
} else {