summaryrefslogtreecommitdiffstats
path: root/sys/i386/pci/pci_cfgreg.c
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>2000-04-16 20:48:33 +0000
committermsmith <msmith@FreeBSD.org>2000-04-16 20:48:33 +0000
commit087c82acdb8383ded1820689980c59ee9fab52c6 (patch)
tree559bc6b745fdd12c5e689a44904bcf714abd567d /sys/i386/pci/pci_cfgreg.c
parent9ae9f06eb1d211d712c6ce5cc3d26ac0336230a4 (diff)
downloadFreeBSD-src-087c82acdb8383ded1820689980c59ee9fab52c6.zip
FreeBSD-src-087c82acdb8383ded1820689980c59ee9fab52c6.tar.gz
Some more i386-only BIOS-friendliness:
- Add support for using the PCI BIOS functions for configuration space accesses, and make this the default. - Make PNPBIOS the default (obsoletes the PNPBIOS config option). - Add two new boot-time tunables to disable each of the above.
Diffstat (limited to 'sys/i386/pci/pci_cfgreg.c')
-rw-r--r--sys/i386/pci/pci_cfgreg.c121
1 files changed, 112 insertions, 9 deletions
diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c
index f09c907..a1b399b 100644
--- a/sys/i386/pci/pci_cfgreg.c
+++ b/sys/i386/pci/pci_cfgreg.c
@@ -36,8 +36,115 @@
#include <pci/pcireg.h>
#include <i386/isa/pcibus.h>
+#include <machine/segments.h>
+#include <machine/pc/bios.h>
+
static int cfgmech;
static int devmax;
+static int usebios;
+
+static int pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes);
+static void pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
+static int pcibios_cfgopen(void);
+static int pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes);
+static void pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
+static int pcireg_cfgopen(void);
+
+/* read configuration space register */
+
+int
+pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
+{
+ return(usebios ?
+ pcibios_cfgread(cfg, reg, bytes) :
+ pcireg_cfgread(cfg, reg, bytes));
+}
+
+/* write configuration space register */
+
+void
+pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ return(usebios ?
+ pcibios_cfgwrite(cfg, reg, data, bytes) :
+ pcireg_cfgwrite(cfg, reg, data, bytes));
+}
+
+/* initialise access to PCI configuration space */
+static int
+pci_cfgopen(void)
+{
+ if (pcibios_cfgopen() != 0) {
+ usebios = 1;
+ } else if (pcireg_cfgopen() != 0) {
+ usebios = 0;
+ } else {
+ return(0);
+ }
+ return(1);
+}
+
+/* config space access using BIOS functions */
+
+static int
+pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
+{
+ struct bios_regs args;
+
+ switch(bytes) {
+ case 1:
+ args.eax = PCIBIOS_READ_CONFIG_BYTE;
+ break;
+ case 2:
+ args.eax = PCIBIOS_READ_CONFIG_WORD;
+ break;
+ case 4:
+ args.eax = PCIBIOS_READ_CONFIG_DWORD;
+ break;
+ default:
+ return(-1);
+ }
+ args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
+ args.edi = reg;
+ bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
+ /* check call results? */
+ return(args.ecx);
+}
+
+static void
+pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+{
+ struct bios_regs args;
+
+ switch(bytes) {
+ case 1:
+ args.eax = PCIBIOS_WRITE_CONFIG_BYTE;
+ break;
+ case 2:
+ args.eax = PCIBIOS_WRITE_CONFIG_WORD;
+ break;
+ case 4:
+ args.eax = PCIBIOS_WRITE_CONFIG_DWORD;
+ break;
+ default:
+ return;
+ }
+ args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
+ args.ecx = data;
+ args.edi = reg;
+ bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
+}
+
+/* determine whether there is a PCI BIOS present */
+
+static int
+pcibios_cfgopen(void)
+{
+ /* check for a found entrypoint */
+ return(PCIbios.entry != 0);
+}
+
+/* configuration space access using direct register operations */
/* enable configuration space accesses and return data port address */
@@ -86,10 +193,8 @@ pci_cfgdisable(void)
}
}
-/* read configuration space register */
-
-int
-pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
+static int
+pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
{
int data = -1;
int port;
@@ -113,10 +218,8 @@ pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
return (data);
}
-/* write configuration space register */
-
-void
-pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
+static void
+pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
{
int port;
@@ -182,7 +285,7 @@ pci_cfgcheck(int maxdev)
}
static int
-pci_cfgopen(void)
+pcireg_cfgopen(void)
{
unsigned long mode1res,oldval1;
unsigned char mode2res,oldval2;
OpenPOWER on IntegriCloud