From 087c82acdb8383ded1820689980c59ee9fab52c6 Mon Sep 17 00:00:00 2001 From: msmith Date: Sun, 16 Apr 2000 20:48:33 +0000 Subject: 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. --- sys/i386/conf/LINT | 2 - sys/i386/conf/NOTES | 2 - sys/i386/i386/bios.c | 30 ++++++----- sys/i386/include/pc/bios.h | 11 +++++ sys/i386/isa/pcibus.c | 121 +++++++++++++++++++++++++++++++++++++++++---- sys/i386/pci/pci_bus.c | 121 +++++++++++++++++++++++++++++++++++++++++---- sys/i386/pci/pci_cfgreg.c | 121 +++++++++++++++++++++++++++++++++++++++++---- sys/i386/pci/pci_pir.c | 121 +++++++++++++++++++++++++++++++++++++++++---- 8 files changed, 476 insertions(+), 53 deletions(-) (limited to 'sys/i386') diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index d6f57bb..e78cbb8 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -1349,7 +1349,6 @@ options NATM #native ATM #device uart0 at isa? port 0x330 irq 5 # The newpcm driver (use INSTEAD of snd0 and all VOXWARE drivers!). -# Note that motherboard sound devices may require options PNPBIOS. # # Supported cards include: # Creative SoundBlaster ISA PnP/non-PnP @@ -2336,7 +2335,6 @@ options NMBCLUSTERS=1024 #options OLTR_NO_HAWKEYE_MAC #options OLTR_NO_TMS_MAC options PANIC_REBOOT_WAIT_TIME=16 -options PNPBIOS options PSM_DEBUG=1 options SCSI_NCR_DEBUG options SCSI_NCR_MAX_SYNC=10000 diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index d6f57bb..e78cbb8 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -1349,7 +1349,6 @@ options NATM #native ATM #device uart0 at isa? port 0x330 irq 5 # The newpcm driver (use INSTEAD of snd0 and all VOXWARE drivers!). -# Note that motherboard sound devices may require options PNPBIOS. # # Supported cards include: # Creative SoundBlaster ISA PnP/non-PnP @@ -2336,7 +2335,6 @@ options NMBCLUSTERS=1024 #options OLTR_NO_HAWKEYE_MAC #options OLTR_NO_TMS_MAC options PANIC_REBOOT_WAIT_TIME=16 -options PNPBIOS options PSM_DEBUG=1 options SCSI_NCR_DEBUG options SCSI_NCR_MAX_SYNC=10000 diff --git a/sys/i386/i386/bios.c b/sys/i386/i386/bios.c index f70959c..5b47fd7 100644 --- a/sys/i386/i386/bios.c +++ b/sys/i386/i386/bios.c @@ -31,8 +31,6 @@ * Code for dealing with the BIOS in x86 PC systems. */ -#include "opt_pnp.h" - #include "isa.h" #include @@ -79,9 +77,10 @@ bios32_init(void *junk) struct PnPBIOS_table *pt; u_int8_t ck, *cv; int i; + char *p; /* - * BIOS32 Service Directory + * BIOS32 Service Directory, PCI BIOS */ /* look for the signature */ @@ -100,10 +99,15 @@ bios32_init(void *junk) printf("bios32: Entry = 0x%x (%x) Rev = %d Len = %d\n", sdh->entry, bios32_SDCI, sdh->revision, sdh->len); } - /* See if there's a PCI BIOS entrypoint here */ - PCIbios.ident.id = 0x49435024; /* PCI systems should have this */ - if (!bios32_SDlookup(&PCIbios) && bootverbose) - printf("pcibios: PCI BIOS entry at 0x%x\n", PCIbios.entry); + + /* Allow user override of PCI BIOS search */ + if (((p = getenv("machdep.bios.pci")) == NULL) || strcmp(p, "disable")) { + + /* See if there's a PCI BIOS entrypoint here */ + PCIbios.ident.id = 0x49435024; /* PCI systems should have this */ + if (!bios32_SDlookup(&PCIbios) && bootverbose) + printf("pcibios: PCI BIOS entry at 0x%x+0x%x\n", PCIbios.base, PCIbios.entry); + } } else { printf("bios32: Bad BIOS32 Service Directory\n"); } @@ -111,8 +115,11 @@ bios32_init(void *junk) /* * PnP BIOS + * + * Allow user override of PnP BIOS search */ - if ((sigaddr = bios_sigsearch(0, "$PnP", 4, 16, 0)) != 0) { + if ((((p = getenv("machdep.bios.pnp")) == NULL) || strcmp(p, "disable")) && + ((sigaddr = bios_sigsearch(0, "$PnP", 4, 16, 0)) != 0)) { /* get a virtual pointer to the structure */ pt = (struct PnPBIOS_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); @@ -166,6 +173,7 @@ bios32_SDlookup(struct bios32_SDentry *ent) ent->base = args.ebx; ent->len = args.ecx; ent->entry = args.edx; + ent->ventry = BIOS_PADDRTOVADDR(ent->base + ent->entry); return (0); /* all OK */ } return (1); /* failed */ @@ -454,8 +462,6 @@ bios16(struct bios_args *args, char *fmt, ...) return (i); } -#ifdef PNPBIOS /* remove conditional later */ - /* * PnP BIOS interface; enumerate devices only known to the system * BIOS and save information about them for later use. @@ -518,7 +524,7 @@ pnpbios_identify(driver_t *driver, device_t parent) /* no PnP BIOS information */ if (pt == NULL) return; - + bzero(&args, sizeof(args)); args.seg.code16.base = BIOS_PADDRTOVADDR(pt->pmentrybase); args.seg.code16.limit = 0xffff; /* XXX ? */ @@ -623,5 +629,3 @@ static driver_t pnpbios_driver = { static devclass_t pnpbios_devclass; DRIVER_MODULE(pnpbios, isa, pnpbios_driver, pnpbios_devclass, 0, 0); - -#endif /* PNPBIOS */ diff --git a/sys/i386/include/pc/bios.h b/sys/i386/include/pc/bios.h index 3a31786..1d8b893 100644 --- a/sys/i386/include/pc/bios.h +++ b/sys/i386/include/pc/bios.h @@ -54,6 +54,7 @@ struct bios32_SDentry u_int32_t base; /* base of service */ u_int32_t len; /* service length */ u_int32_t entry; /* entrypoint offset from base */ + vm_offset_t ventry; /* entrypoint in kernel virtual segment */ }; extern int bios32_SDlookup(struct bios32_SDentry *ent); @@ -203,6 +204,16 @@ struct bios_args { #define PNP_GET_BOOTFIRST "sp", 0x65 #define PNP_SET_BOOTFIRST "sp", 0x66 +/* + * PCI BIOS functions + */ +#define PCIBIOS_READ_CONFIG_BYTE 0xb108 +#define PCIBIOS_READ_CONFIG_WORD 0xb109 +#define PCIBIOS_READ_CONFIG_DWORD 0xb10a +#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b +#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c +#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d + extern int bios16(struct bios_args *, char *, ...); extern int bios16_call(struct bios_regs *, char *); extern int bios32(struct bios_regs *, u_int, u_short); diff --git a/sys/i386/isa/pcibus.c b/sys/i386/isa/pcibus.c index f09c907..a1b399b 100644 --- a/sys/i386/isa/pcibus.c +++ b/sys/i386/isa/pcibus.c @@ -36,8 +36,115 @@ #include #include +#include +#include + 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; diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c index f09c907..a1b399b 100644 --- a/sys/i386/pci/pci_bus.c +++ b/sys/i386/pci/pci_bus.c @@ -36,8 +36,115 @@ #include #include +#include +#include + 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; 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 #include +#include +#include + 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; diff --git a/sys/i386/pci/pci_pir.c b/sys/i386/pci/pci_pir.c index f09c907..a1b399b 100644 --- a/sys/i386/pci/pci_pir.c +++ b/sys/i386/pci/pci_pir.c @@ -36,8 +36,115 @@ #include #include +#include +#include + 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; -- cgit v1.1