1ac19f918SStefan Eßer /* 25bec6157SStefan Eßer * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 312a02d6eSMike Smith * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 412a02d6eSMike Smith * Copyright (c) 2000, BSDi 55bec6157SStefan Eßer * All rights reserved. 65bec6157SStefan Eßer * 75bec6157SStefan Eßer * Redistribution and use in source and binary forms, with or without 85bec6157SStefan Eßer * modification, are permitted provided that the following conditions 95bec6157SStefan Eßer * are met: 105bec6157SStefan Eßer * 1. Redistributions of source code must retain the above copyright 115bec6157SStefan Eßer * notice unmodified, this list of conditions, and the following 125bec6157SStefan Eßer * disclaimer. 135bec6157SStefan Eßer * 2. Redistributions in binary form must reproduce the above copyright 145bec6157SStefan Eßer * notice, this list of conditions and the following disclaimer in the 155bec6157SStefan Eßer * documentation and/or other materials provided with the distribution. 165bec6157SStefan Eßer * 175bec6157SStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 185bec6157SStefan Eßer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 195bec6157SStefan Eßer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 205bec6157SStefan Eßer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 215bec6157SStefan Eßer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 225bec6157SStefan Eßer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235bec6157SStefan Eßer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245bec6157SStefan Eßer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255bec6157SStefan Eßer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 265bec6157SStefan Eßer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275bec6157SStefan Eßer * 28c3aac50fSPeter Wemm * $FreeBSD$ 295bec6157SStefan Eßer * 30ac19f918SStefan Eßer */ 31ac19f918SStefan Eßer 3212a02d6eSMike Smith #include <sys/param.h> /* XXX trim includes */ 335bec6157SStefan Eßer #include <sys/systm.h> 348dc26439SPeter Wemm #include <sys/bus.h> 358dc26439SPeter Wemm #include <sys/kernel.h> 362a50a6d7SMike Smith #include <sys/module.h> 37280b4748SPeter Wemm #include <sys/malloc.h> 3854c9005fSWarner Losh #include <vm/vm.h> 3954c9005fSWarner Losh #include <vm/pmap.h> 4054c9005fSWarner Losh #include <machine/md_var.h> 415bec6157SStefan Eßer #include <pci/pcivar.h> 4285001303SMike Smith #include <pci/pcireg.h> 432a50a6d7SMike Smith #include <isa/isavar.h> 44b6c84078SPeter Wemm #include <machine/nexusvar.h> 4512a02d6eSMike Smith #include <machine/pci_cfgreg.h> 46300451c4SMike Smith #include <machine/segments.h> 47300451c4SMike Smith #include <machine/pc/bios.h> 48300451c4SMike Smith 4921c3015aSDoug Rabson #include "pcib_if.h" 5021c3015aSDoug Rabson 515bec6157SStefan Eßer static int cfgmech; 525bec6157SStefan Eßer static int devmax; 53300451c4SMike Smith static int usebios; 54300451c4SMike Smith 5512a02d6eSMike Smith static int pcibios_cfgread(int bus, int slot, int func, int reg, int bytes); 5612a02d6eSMike Smith static void pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 57300451c4SMike Smith static int pcibios_cfgopen(void); 5812a02d6eSMike Smith static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes); 5912a02d6eSMike Smith static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 60300451c4SMike Smith static int pcireg_cfgopen(void); 61300451c4SMike Smith 6254c9005fSWarner Losh static struct PIR_entry *pci_route_table; 6354c9005fSWarner Losh static int pci_route_count; 6454c9005fSWarner Losh 6512a02d6eSMike Smith /* 6612a02d6eSMike Smith * Initialise access to PCI configuration space 6712a02d6eSMike Smith */ 6812a02d6eSMike Smith int 6912a02d6eSMike Smith pci_cfgregopen(void) 7021c3015aSDoug Rabson { 7112a02d6eSMike Smith static int opened = 0; 7254c9005fSWarner Losh u_long sigaddr; 7354c9005fSWarner Losh static struct PIR_table *pt; 7454c9005fSWarner Losh u_int8_t ck, *cv; 7554c9005fSWarner Losh int i; 7621c3015aSDoug Rabson 7712a02d6eSMike Smith if (opened) 7812a02d6eSMike Smith return(1); 79300451c4SMike Smith 80300451c4SMike Smith if (pcibios_cfgopen() != 0) { 81300451c4SMike Smith usebios = 1; 82300451c4SMike Smith } else if (pcireg_cfgopen() != 0) { 83300451c4SMike Smith usebios = 0; 84300451c4SMike Smith } else { 85300451c4SMike Smith return(0); 86300451c4SMike Smith } 8754c9005fSWarner Losh 8854c9005fSWarner Losh /* 8954c9005fSWarner Losh * Look for the interrupt routing table. 9054c9005fSWarner Losh */ 9154c9005fSWarner Losh /* XXX use PCI BIOS if it's available */ 9254c9005fSWarner Losh 9354c9005fSWarner Losh if ((pt == NULL) && ((sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0)) != 0)) { 9454c9005fSWarner Losh pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); 9554c9005fSWarner Losh for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < (pt->pt_header.ph_length); i++) { 9654c9005fSWarner Losh ck += cv[i]; 9754c9005fSWarner Losh } 9854c9005fSWarner Losh if (ck == 0) { 9954c9005fSWarner Losh pci_route_table = &pt->pt_entry[0]; 10054c9005fSWarner Losh pci_route_count = (pt->pt_header.ph_length - sizeof(struct PIR_header)) / sizeof(struct PIR_entry); 10154c9005fSWarner Losh printf("Using $PIR table, %d entries at %p\n", pci_route_count, pci_route_table); 10254c9005fSWarner Losh } 10354c9005fSWarner Losh } 10454c9005fSWarner Losh 10512a02d6eSMike Smith opened = 1; 106300451c4SMike Smith return(1); 107300451c4SMike Smith } 108300451c4SMike Smith 10912a02d6eSMike Smith /* 11012a02d6eSMike Smith * Read configuration space register 11112a02d6eSMike Smith */ 11212a02d6eSMike Smith u_int32_t 11312a02d6eSMike Smith pci_cfgregread(int bus, int slot, int func, int reg, int bytes) 11412a02d6eSMike Smith { 11512a02d6eSMike Smith return(usebios ? 11612a02d6eSMike Smith pcibios_cfgread(bus, slot, func, reg, bytes) : 11712a02d6eSMike Smith pcireg_cfgread(bus, slot, func, reg, bytes)); 11812a02d6eSMike Smith } 119300451c4SMike Smith 12012a02d6eSMike Smith /* 12112a02d6eSMike Smith * Write configuration space register 12212a02d6eSMike Smith */ 12312a02d6eSMike Smith void 12412a02d6eSMike Smith pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) 12512a02d6eSMike Smith { 12612a02d6eSMike Smith return(usebios ? 12712a02d6eSMike Smith pcibios_cfgwrite(bus, slot, func, reg, data, bytes) : 12812a02d6eSMike Smith pcireg_cfgwrite(bus, slot, func, reg, data, bytes)); 12912a02d6eSMike Smith } 13012a02d6eSMike Smith 13112a02d6eSMike Smith /* 13254c9005fSWarner Losh * Route a PCI interrupt 13354c9005fSWarner Losh * 13454c9005fSWarner Losh * XXX this needs to learn to actually route uninitialised interrupts as well 13554c9005fSWarner Losh * as just returning interrupts for stuff that's already initialised. 13654c9005fSWarner Losh */ 13754c9005fSWarner Losh int 13854c9005fSWarner Losh pci_cfgintr(int bus, int device, int pin) 13954c9005fSWarner Losh { 14054c9005fSWarner Losh struct PIR_entry *pe; 14154c9005fSWarner Losh int i; 14254c9005fSWarner Losh 14354c9005fSWarner Losh if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) || (pin < 1) || (pin > 4)) { 14454c9005fSWarner Losh printf("bus %d pin %d device %d, returning 255\n", bus, pin, device); 14554c9005fSWarner Losh return(255); 14654c9005fSWarner Losh } 14754c9005fSWarner Losh 14854c9005fSWarner Losh /* 14954c9005fSWarner Losh * Scan the entry table for a contender 15054c9005fSWarner Losh */ 15154c9005fSWarner Losh printf("bus %d device %d\n", bus, device); 15254c9005fSWarner Losh for (i = 0, pe = pci_route_table; i < pci_route_count; i++, pe++) { 15354c9005fSWarner Losh printf("pe_bus %d pe_device %d\n", pe->pe_bus, pe->pe_device); 15454c9005fSWarner Losh if ((bus != pe->pe_bus) || (device != pe->pe_device)) 15554c9005fSWarner Losh continue; 15654c9005fSWarner Losh if (!powerof2(pe->pe_intpin[pin - 1].irqs)) { 15754c9005fSWarner Losh printf("pci_cfgintr: %d:%d:%c is not routed to a unique interrupt\n", bus, device, 'A' + pin - 1); 15854c9005fSWarner Losh break; 15954c9005fSWarner Losh } 16054c9005fSWarner Losh printf("pci_cfgintr: %d:%d:%c routed to irq %d\n", bus, device, 'A' + pin - 1, ffs(pe->pe_intpin[pin - 1].irqs)); 16154c9005fSWarner Losh return(ffs(pe->pe_intpin[pin - 1].irqs)); 16254c9005fSWarner Losh } 16354c9005fSWarner Losh return(255); 16454c9005fSWarner Losh } 16554c9005fSWarner Losh 16654c9005fSWarner Losh 16754c9005fSWarner Losh /* 16812a02d6eSMike Smith * Config space access using BIOS functions 16912a02d6eSMike Smith */ 170300451c4SMike Smith static int 17121c3015aSDoug Rabson pcibios_cfgread(int bus, int slot, int func, int reg, int bytes) 172300451c4SMike Smith { 173300451c4SMike Smith struct bios_regs args; 174ac9b3dacSMike Smith u_int mask; 175300451c4SMike Smith 176300451c4SMike Smith switch(bytes) { 177300451c4SMike Smith case 1: 178300451c4SMike Smith args.eax = PCIBIOS_READ_CONFIG_BYTE; 179ac9b3dacSMike Smith mask = 0xff; 180300451c4SMike Smith break; 181300451c4SMike Smith case 2: 182300451c4SMike Smith args.eax = PCIBIOS_READ_CONFIG_WORD; 183ac9b3dacSMike Smith mask = 0xffff; 184300451c4SMike Smith break; 185300451c4SMike Smith case 4: 186300451c4SMike Smith args.eax = PCIBIOS_READ_CONFIG_DWORD; 187ac9b3dacSMike Smith mask = 0xffffffff; 188300451c4SMike Smith break; 189300451c4SMike Smith default: 190300451c4SMike Smith return(-1); 191300451c4SMike Smith } 19221c3015aSDoug Rabson args.ebx = (bus << 8) | (slot << 3) | func; 193300451c4SMike Smith args.edi = reg; 194300451c4SMike Smith bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 195300451c4SMike Smith /* check call results? */ 196ac9b3dacSMike Smith return(args.ecx & mask); 197300451c4SMike Smith } 198300451c4SMike Smith 199300451c4SMike Smith static void 20021c3015aSDoug Rabson pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 201300451c4SMike Smith { 202300451c4SMike Smith struct bios_regs args; 203300451c4SMike Smith 204300451c4SMike Smith switch(bytes) { 205300451c4SMike Smith case 1: 206300451c4SMike Smith args.eax = PCIBIOS_WRITE_CONFIG_BYTE; 207300451c4SMike Smith break; 208300451c4SMike Smith case 2: 209300451c4SMike Smith args.eax = PCIBIOS_WRITE_CONFIG_WORD; 210300451c4SMike Smith break; 211300451c4SMike Smith case 4: 212300451c4SMike Smith args.eax = PCIBIOS_WRITE_CONFIG_DWORD; 213300451c4SMike Smith break; 214300451c4SMike Smith default: 215300451c4SMike Smith return; 216300451c4SMike Smith } 21721c3015aSDoug Rabson args.ebx = (bus << 8) | (slot << 3) | func; 218300451c4SMike Smith args.ecx = data; 219300451c4SMike Smith args.edi = reg; 220300451c4SMike Smith bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 221300451c4SMike Smith } 222300451c4SMike Smith 22312a02d6eSMike Smith /* 22412a02d6eSMike Smith * Determine whether there is a PCI BIOS present 22512a02d6eSMike Smith */ 226300451c4SMike Smith static int 227300451c4SMike Smith pcibios_cfgopen(void) 228300451c4SMike Smith { 229300451c4SMike Smith /* check for a found entrypoint */ 230300451c4SMike Smith return(PCIbios.entry != 0); 231300451c4SMike Smith } 232300451c4SMike Smith 23312a02d6eSMike Smith /* 23412a02d6eSMike Smith * Configuration space access using direct register operations 23512a02d6eSMike Smith */ 236ac19f918SStefan Eßer 2375bec6157SStefan Eßer /* enable configuration space accesses and return data port address */ 238a3adc4f8SStefan Eßer static int 2395bec6157SStefan Eßer pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 2405bec6157SStefan Eßer { 2415bec6157SStefan Eßer int dataport = 0; 2425bec6157SStefan Eßer 2435bec6157SStefan Eßer if (bus <= PCI_BUSMAX 2445bec6157SStefan Eßer && slot < devmax 2455bec6157SStefan Eßer && func <= PCI_FUNCMAX 2465bec6157SStefan Eßer && reg <= PCI_REGMAX 2475bec6157SStefan Eßer && bytes != 3 2485bec6157SStefan Eßer && (unsigned) bytes <= 4 2495bec6157SStefan Eßer && (reg & (bytes -1)) == 0) { 2505bec6157SStefan Eßer switch (cfgmech) { 2515bec6157SStefan Eßer case 1: 252b3daa02eSStefan Eßer outl(CONF1_ADDR_PORT, (1 << 31) 253b3daa02eSStefan Eßer | (bus << 16) | (slot << 11) 254b3daa02eSStefan Eßer | (func << 8) | (reg & ~0x03)); 255b3daa02eSStefan Eßer dataport = CONF1_DATA_PORT + (reg & 0x03); 2565bec6157SStefan Eßer break; 2575bec6157SStefan Eßer case 2: 2585bec6157SStefan Eßer outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 2595bec6157SStefan Eßer outb(CONF2_FORWARD_PORT, bus); 2605bec6157SStefan Eßer dataport = 0xc000 | (slot << 8) | reg; 2615bec6157SStefan Eßer break; 2625bec6157SStefan Eßer } 2635bec6157SStefan Eßer } 2645bec6157SStefan Eßer return (dataport); 2655bec6157SStefan Eßer } 2665bec6157SStefan Eßer 2675bec6157SStefan Eßer /* disable configuration space accesses */ 2685bec6157SStefan Eßer static void 2695bec6157SStefan Eßer pci_cfgdisable(void) 2705bec6157SStefan Eßer { 2715bec6157SStefan Eßer switch (cfgmech) { 2725bec6157SStefan Eßer case 1: 2735bec6157SStefan Eßer outl(CONF1_ADDR_PORT, 0); 2745bec6157SStefan Eßer break; 2755bec6157SStefan Eßer case 2: 2765bec6157SStefan Eßer outb(CONF2_ENABLE_PORT, 0); 2775bec6157SStefan Eßer outb(CONF2_FORWARD_PORT, 0); 2785bec6157SStefan Eßer break; 2795bec6157SStefan Eßer } 2805bec6157SStefan Eßer } 2815bec6157SStefan Eßer 282300451c4SMike Smith static int 28321c3015aSDoug Rabson pcireg_cfgread(int bus, int slot, int func, int reg, int bytes) 2845bec6157SStefan Eßer { 2855bec6157SStefan Eßer int data = -1; 2865bec6157SStefan Eßer int port; 2875bec6157SStefan Eßer 28821c3015aSDoug Rabson port = pci_cfgenable(bus, slot, func, reg, bytes); 2895bec6157SStefan Eßer 2905bec6157SStefan Eßer if (port != 0) { 2915bec6157SStefan Eßer switch (bytes) { 2925bec6157SStefan Eßer case 1: 2935bec6157SStefan Eßer data = inb(port); 2945bec6157SStefan Eßer break; 2955bec6157SStefan Eßer case 2: 2965bec6157SStefan Eßer data = inw(port); 2975bec6157SStefan Eßer break; 2985bec6157SStefan Eßer case 4: 2995bec6157SStefan Eßer data = inl(port); 3005bec6157SStefan Eßer break; 3015bec6157SStefan Eßer } 3025bec6157SStefan Eßer pci_cfgdisable(); 3035bec6157SStefan Eßer } 3045bec6157SStefan Eßer return (data); 3055bec6157SStefan Eßer } 3065bec6157SStefan Eßer 307300451c4SMike Smith static void 30821c3015aSDoug Rabson pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 3095bec6157SStefan Eßer { 3105bec6157SStefan Eßer int port; 3115bec6157SStefan Eßer 31221c3015aSDoug Rabson port = pci_cfgenable(bus, slot, func, reg, bytes); 3135bec6157SStefan Eßer if (port != 0) { 3145bec6157SStefan Eßer switch (bytes) { 3155bec6157SStefan Eßer case 1: 3165bec6157SStefan Eßer outb(port, data); 3175bec6157SStefan Eßer break; 3185bec6157SStefan Eßer case 2: 3195bec6157SStefan Eßer outw(port, data); 3205bec6157SStefan Eßer break; 3215bec6157SStefan Eßer case 4: 3225bec6157SStefan Eßer outl(port, data); 3235bec6157SStefan Eßer break; 3245bec6157SStefan Eßer } 3255bec6157SStefan Eßer pci_cfgdisable(); 3265bec6157SStefan Eßer } 3275bec6157SStefan Eßer } 3285bec6157SStefan Eßer 32912a02d6eSMike Smith /* check whether the configuration mechanism has been correctly identified */ 3305bec6157SStefan Eßer static int 3315bec6157SStefan Eßer pci_cfgcheck(int maxdev) 332a3adc4f8SStefan Eßer { 333a3adc4f8SStefan Eßer u_char device; 334a3adc4f8SStefan Eßer 3355bec6157SStefan Eßer if (bootverbose) 3365bec6157SStefan Eßer printf("pci_cfgcheck:\tdevice "); 33777b57314SStefan Eßer 3385bec6157SStefan Eßer for (device = 0; device < maxdev; device++) { 3395bec6157SStefan Eßer unsigned id, class, header; 340c7483249SStefan Eßer if (bootverbose) 341c7483249SStefan Eßer printf("%d ", device); 3425bec6157SStefan Eßer 3435bec6157SStefan Eßer id = inl(pci_cfgenable(0, device, 0, 0, 4)); 3445bec6157SStefan Eßer if (id == 0 || id == -1) 34581cf5d7aSStefan Eßer continue; 34681cf5d7aSStefan Eßer 3475bec6157SStefan Eßer class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8; 34881cf5d7aSStefan Eßer if (bootverbose) 3495bec6157SStefan Eßer printf("[class=%06x] ", class); 3508277ac25SStefan Eßer if (class == 0 || (class & 0xf870ff) != 0) 35181cf5d7aSStefan Eßer continue; 35281cf5d7aSStefan Eßer 3535bec6157SStefan Eßer header = inb(pci_cfgenable(0, device, 0, 14, 1)); 35481cf5d7aSStefan Eßer if (bootverbose) 3555bec6157SStefan Eßer printf("[hdr=%02x] ", header); 3565bec6157SStefan Eßer if ((header & 0x7e) != 0) 35781cf5d7aSStefan Eßer continue; 35881cf5d7aSStefan Eßer 3595bec6157SStefan Eßer if (bootverbose) 3605bec6157SStefan Eßer printf("is there (id=%08x)\n", id); 3615bec6157SStefan Eßer 3625bec6157SStefan Eßer pci_cfgdisable(); 3635bec6157SStefan Eßer return (1); 364a3adc4f8SStefan Eßer } 365c7483249SStefan Eßer if (bootverbose) 366c7483249SStefan Eßer printf("-- nothing found\n"); 3675bec6157SStefan Eßer 3685bec6157SStefan Eßer pci_cfgdisable(); 3695bec6157SStefan Eßer return (0); 370a3adc4f8SStefan Eßer } 371d7ea35fcSStefan Eßer 3728dc26439SPeter Wemm static int 373300451c4SMike Smith pcireg_cfgopen(void) 374ac19f918SStefan Eßer { 375287911bdSStefan Eßer unsigned long mode1res,oldval1; 376287911bdSStefan Eßer unsigned char mode2res,oldval2; 3770847c06dSStefan Eßer 378287911bdSStefan Eßer oldval1 = inl(CONF1_ADDR_PORT); 379a3adc4f8SStefan Eßer 38077b57314SStefan Eßer if (bootverbose) { 3815bec6157SStefan Eßer printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", 3825bec6157SStefan Eßer oldval1); 383a3adc4f8SStefan Eßer } 384a3adc4f8SStefan Eßer 3850e2f699bSStefan Eßer if ((oldval1 & CONF1_ENABLE_MSK) == 0) { 386287911bdSStefan Eßer 3875bec6157SStefan Eßer cfgmech = 1; 3885bec6157SStefan Eßer devmax = 32; 38977b57314SStefan Eßer 39077b57314SStefan Eßer outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 39177b57314SStefan Eßer outb(CONF1_ADDR_PORT +3, 0); 39277b57314SStefan Eßer mode1res = inl(CONF1_ADDR_PORT); 393287911bdSStefan Eßer outl(CONF1_ADDR_PORT, oldval1); 39477b57314SStefan Eßer 39577b57314SStefan Eßer if (bootverbose) 3965bec6157SStefan Eßer printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 39777b57314SStefan Eßer mode1res, CONF1_ENABLE_CHK); 39877b57314SStefan Eßer 39977b57314SStefan Eßer if (mode1res) { 4005bec6157SStefan Eßer if (pci_cfgcheck(32)) 4015bec6157SStefan Eßer return (cfgmech); 4025bec6157SStefan Eßer } 40377b57314SStefan Eßer 40477b57314SStefan Eßer outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 40577b57314SStefan Eßer mode1res = inl(CONF1_ADDR_PORT); 406287911bdSStefan Eßer outl(CONF1_ADDR_PORT, oldval1); 40777b57314SStefan Eßer 40877b57314SStefan Eßer if (bootverbose) 4095bec6157SStefan Eßer printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 41077b57314SStefan Eßer mode1res, CONF1_ENABLE_CHK1); 41177b57314SStefan Eßer 412c7483249SStefan Eßer if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 4135bec6157SStefan Eßer if (pci_cfgcheck(32)) 4145bec6157SStefan Eßer return (cfgmech); 415287911bdSStefan Eßer } 4165bec6157SStefan Eßer } 41777b57314SStefan Eßer 418287911bdSStefan Eßer oldval2 = inb(CONF2_ENABLE_PORT); 419287911bdSStefan Eßer 420287911bdSStefan Eßer if (bootverbose) { 4215bec6157SStefan Eßer printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 4225bec6157SStefan Eßer oldval2); 423287911bdSStefan Eßer } 424287911bdSStefan Eßer 425287911bdSStefan Eßer if ((oldval2 & 0xf0) == 0) { 426c7483249SStefan Eßer 4275bec6157SStefan Eßer cfgmech = 2; 4285bec6157SStefan Eßer devmax = 16; 42977b57314SStefan Eßer 430287911bdSStefan Eßer outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 431287911bdSStefan Eßer mode2res = inb(CONF2_ENABLE_PORT); 432287911bdSStefan Eßer outb(CONF2_ENABLE_PORT, oldval2); 433287911bdSStefan Eßer 434287911bdSStefan Eßer if (bootverbose) 4355bec6157SStefan Eßer printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 436287911bdSStefan Eßer mode2res, CONF2_ENABLE_CHK); 437287911bdSStefan Eßer 438287911bdSStefan Eßer if (mode2res == CONF2_ENABLE_RES) { 439287911bdSStefan Eßer if (bootverbose) 4405bec6157SStefan Eßer printf("pci_open(2a):\tnow trying mechanism 2\n"); 441287911bdSStefan Eßer 4425bec6157SStefan Eßer if (pci_cfgcheck(16)) 4435bec6157SStefan Eßer return (cfgmech); 444287911bdSStefan Eßer } 445287911bdSStefan Eßer } 44677b57314SStefan Eßer 4475bec6157SStefan Eßer cfgmech = 0; 4485bec6157SStefan Eßer devmax = 0; 4495bec6157SStefan Eßer return (cfgmech); 450ac19f918SStefan Eßer } 4518dc26439SPeter Wemm 452