xref: /freebsd/sys/i386/pci/pci_cfgreg.c (revision 54c9005fafc15c0907493c9c3a33a7ff885f236d)
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