1/* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000, BSDi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 *
| 1/* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000, BSDi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 *
|
28 * $FreeBSD: head/sys/i386/pci/pci_pir.c 97694 2002-06-01 05:14:11Z imp $
| 28 * $FreeBSD: head/sys/i386/pci/pci_pir.c 100435 2002-07-21 05:35:42Z imp $
|
29 * 30 */ 31 32#include <sys/param.h> /* XXX trim includes */ 33#include <sys/systm.h> 34#include <sys/bus.h> 35#include <sys/kernel.h> 36#include <sys/module.h> 37#include <sys/malloc.h> 38#include <vm/vm.h> 39#include <vm/pmap.h> 40#include <machine/md_var.h>
| 29 * 30 */ 31 32#include <sys/param.h> /* XXX trim includes */ 33#include <sys/systm.h> 34#include <sys/bus.h> 35#include <sys/kernel.h> 36#include <sys/module.h> 37#include <sys/malloc.h> 38#include <vm/vm.h> 39#include <vm/pmap.h> 40#include <machine/md_var.h>
|
41#include 42#include
| 41#include <dev/pci/pcivar.h> 42#include <dev/pci/pcireg.h>
|
43#include <isa/isavar.h> 44#include <machine/nexusvar.h> 45#include <machine/pci_cfgreg.h> 46#include <machine/segments.h> 47#include <machine/pc/bios.h> 48 49#ifdef APIC_IO 50#include <machine/smp.h> 51#endif /* APIC_IO */ 52 53#include "pcib_if.h" 54 55#define PRVERB(a) printf a 56 57static int cfgmech; 58static int devmax; 59static int usebios; 60static int enable_pcibios = 0; 61 62TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios); 63 64static int pci_cfgintr_unique(struct PIR_entry *pe, int pin); 65static int pci_cfgintr_linked(struct PIR_entry *pe, int pin); 66static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin); 67static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin); 68 69static int pcibios_cfgread(int bus, int slot, int func, int reg, int bytes); 70static void pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 71static int pcibios_cfgopen(void); 72static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes); 73static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 74static int pcireg_cfgopen(void); 75 76static struct PIR_table *pci_route_table; 77static int pci_route_count; 78 79/* 80 * Some BIOS writers seem to want to ignore the spec and put 81 * 0 in the intline rather than 255 to indicate none. Some use 82 * numbers in the range 128-254 to indicate something strange and 83 * apparently undocumented anywhere. Assume these are completely bogus 84 * and map them to 255, which means "none". 85 */ 86static __inline__ int 87pci_i386_map_intline(int line) 88{
| 43#include <isa/isavar.h> 44#include <machine/nexusvar.h> 45#include <machine/pci_cfgreg.h> 46#include <machine/segments.h> 47#include <machine/pc/bios.h> 48 49#ifdef APIC_IO 50#include <machine/smp.h> 51#endif /* APIC_IO */ 52 53#include "pcib_if.h" 54 55#define PRVERB(a) printf a 56 57static int cfgmech; 58static int devmax; 59static int usebios; 60static int enable_pcibios = 0; 61 62TUNABLE_INT("hw.pci.enable_pcibios", &enable_pcibios); 63 64static int pci_cfgintr_unique(struct PIR_entry *pe, int pin); 65static int pci_cfgintr_linked(struct PIR_entry *pe, int pin); 66static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin); 67static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin); 68 69static int pcibios_cfgread(int bus, int slot, int func, int reg, int bytes); 70static void pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 71static int pcibios_cfgopen(void); 72static int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes); 73static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); 74static int pcireg_cfgopen(void); 75 76static struct PIR_table *pci_route_table; 77static int pci_route_count; 78 79/* 80 * Some BIOS writers seem to want to ignore the spec and put 81 * 0 in the intline rather than 255 to indicate none. Some use 82 * numbers in the range 128-254 to indicate something strange and 83 * apparently undocumented anywhere. Assume these are completely bogus 84 * and map them to 255, which means "none". 85 */ 86static __inline__ int 87pci_i386_map_intline(int line) 88{
|
89 if (line == 0 || line >= 128) 90 return (255); 91 return (line);
| 89 if (line == 0 || line >= 128) 90 return (PCI_INVALID_IRQ); 91 return (line);
|
92} 93 94int 95pci_pcibios_active(void) 96{
| 92} 93 94int 95pci_pcibios_active(void) 96{
|
97 return usebios;
| 97 return (usebios);
|
98} 99 100int 101pci_kill_pcibios(void) 102{
| 98} 99 100int 101pci_kill_pcibios(void) 102{
|
103 usebios = 0; 104 return pcireg_cfgopen() != 0;
| 103 usebios = 0; 104 return (pcireg_cfgopen() != 0);
|
105} 106 107static u_int16_t 108pcibios_get_version(void) 109{
| 105} 106 107static u_int16_t 108pcibios_get_version(void) 109{
|
110 struct bios_regs args;
| 110 struct bios_regs args;
|
111
| 111
|
112 if (PCIbios.entry == 0) { 113 PRVERB(("pcibios: No call entry point\n")); 114 return (0); 115 } 116 args.eax = PCIBIOS_BIOS_PRESENT; 117 if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { 118 PRVERB(("pcibios: BIOS_PRESENT call failed\n")); 119 return (0); 120 } 121 if (args.edx != 0x20494350) { 122 PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n")); 123 return (0); 124 } 125 return (args.ebx & 0xffff);
| 112 if (PCIbios.entry == 0) { 113 PRVERB(("pcibios: No call entry point\n")); 114 return (0); 115 } 116 args.eax = PCIBIOS_BIOS_PRESENT; 117 if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { 118 PRVERB(("pcibios: BIOS_PRESENT call failed\n")); 119 return (0); 120 } 121 if (args.edx != 0x20494350) { 122 PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n")); 123 return (0); 124 } 125 return (args.ebx & 0xffff);
|
126} 127 128/* 129 * Initialise access to PCI configuration space 130 */ 131int 132pci_cfgregopen(void) 133{
| 126} 127 128/* 129 * Initialise access to PCI configuration space 130 */ 131int 132pci_cfgregopen(void) 133{
|
134 static int opened = 0; 135 u_long sigaddr; 136 static struct PIR_table *pt; 137 u_int8_t ck, *cv; 138 int i;
| 134 static int opened = 0; 135 u_long sigaddr; 136 static struct PIR_table *pt; 137 u_int8_t ck, *cv; 138 int i;
|
139
| 139
|
140 if (opened) 141 return(1);
| 140 if (opened) 141 return(1);
|
142
| 142
|
143 if (pcibios_cfgopen() != 0) { 144 usebios = 1; 145 } else if (pcireg_cfgopen() != 0) { 146 usebios = 0; 147 } else { 148 return(0); 149 }
| 143 if (pcibios_cfgopen() != 0) 144 usebios = 1; 145 else if (pcireg_cfgopen() != 0) 146 usebios = 0; 147 else 148 return(0);
|
150
| 149
|
151 /* 152 * Look for the interrupt routing table. 153 * 154 * We use PCI BIOS's PIR table if it's available $PIR is the 155 * standard way to do this. Sadly, some machines are not 156 * standards conforming and have _PIR instead. We shrug and cope 157 * by looking for both. 158 */ 159 if (pcibios_get_version() >= 0x0210 && pt == NULL) { 160 sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0); 161 if (sigaddr == 0) 162 sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0); 163 if (sigaddr != 0) { 164 pt = (struct PIR_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); 165 for (cv = (u_int8_t *)pt, ck = 0, i = 0; 166 i < (pt->pt_header.ph_length); i++) { 167 ck += cv[i]; 168 } 169 if (ck == 0) { 170 pci_route_table = pt; 171 pci_route_count = (pt->pt_header.ph_length - 172 sizeof(struct PIR_header)) / sizeof(struct PIR_entry); 173 printf("Using $PIR table, %d entries at %p\n", 174 pci_route_count, pci_route_table); 175 }
| 150 /* 151 * Look for the interrupt routing table. 152 * 153 * We use PCI BIOS's PIR table if it's available $PIR is the 154 * standard way to do this. Sadly, some machines are not 155 * standards conforming and have _PIR instead. We shrug and cope 156 * by looking for both. 157 */ 158 if (pcibios_get_version() >= 0x0210 && pt == NULL) { 159 sigaddr = bios_sigsearch(0, "$PIR", 4, 16, 0); 160 if (sigaddr == 0) 161 sigaddr = bios_sigsearch(0, "_PIR", 4, 16, 0); 162 if (sigaddr != 0) { 163 pt = (struct PIR_table *)(uintptr_t) 164 BIOS_PADDRTOVADDR(sigaddr); 165 for (cv = (u_int8_t *)pt, ck = 0, i = 0; 166 i < (pt->pt_header.ph_length); i++) { 167 ck += cv[i]; 168 } 169 if (ck == 0) { 170 pci_route_table = pt; 171 pci_route_count = (pt->pt_header.ph_length - 172 sizeof(struct PIR_header)) / 173 sizeof(struct PIR_entry); 174 printf("Using $PIR table, %d entries at %p\n", 175 pci_route_count, pci_route_table); 176 } 177 }
|
176 }
| 178 }
|
177 } 178 opened = 1; 179 return(1);
| 179 opened = 1; 180 return(1);
|
180} 181 182/* 183 * Read configuration space register 184 */ 185static u_int32_t 186pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes) 187{
| 181} 182 183/* 184 * Read configuration space register 185 */ 186static u_int32_t 187pci_do_cfgregread(int bus, int slot, int func, int reg, int bytes) 188{
|
188 return(usebios ? 189 pcibios_cfgread(bus, slot, func, reg, bytes) : 190 pcireg_cfgread(bus, slot, func, reg, bytes));
| 189 return(usebios ? 190 pcibios_cfgread(bus, slot, func, reg, bytes) : 191 pcireg_cfgread(bus, slot, func, reg, bytes));
|
191} 192 193u_int32_t 194pci_cfgregread(int bus, int slot, int func, int reg, int bytes) 195{
| 192} 193 194u_int32_t 195pci_cfgregread(int bus, int slot, int func, int reg, int bytes) 196{
|
196 uint32_t line, pin;
| 197 uint32_t line;
|
197#ifdef APIC_IO
| 198#ifdef APIC_IO
|
198 /* 199 * If we are using the APIC, the contents of the intline register will probably 200 * be wrong (since they are set up for use with the PIC. 201 * Rather than rewrite these registers (maybe that would be smarter) we trap 202 * attempts to read them and translate to our private vector numbers. 203 */ 204 if ((reg == PCIR_INTLINE) && (bytes == 1)) {
| 199 uint32_t pin;
|
205
| 200
|
206 pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1); 207 line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
| 201 /* 202 * If we are using the APIC, the contents of the intline 203 * register will probably be wrong (since they are set up for 204 * use with the PIC. Rather than rewrite these registers 205 * (maybe that would be smarter) we trap attempts to read them 206 * and translate to our private vector numbers. 207 */ 208 if ((reg == PCIR_INTLINE) && (bytes == 1)) {
|
208
| 209
|
209 if (pin != 0) { 210 int airq;
| 210 pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1); 211 line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1);
|
211
| 212
|
212 airq = pci_apic_irq(bus, slot, pin); 213 if (airq >= 0) { 214 /* PCI specific entry found in MP table */ 215 if (airq != line) 216 undirect_pci_irq(line); 217 return(airq); 218 } else { 219 /* 220 * PCI interrupts might be redirected to the 221 * ISA bus according to some MP tables. Use the 222 * same methods as used by the ISA devices 223 * devices to find the proper IOAPIC int pin. 224 */ 225 airq = isa_apic_irq(line); 226 if ((airq >= 0) && (airq != line)) { 227 /* XXX: undirect_pci_irq() ? */ 228 undirect_isa_irq(line); 229 return(airq);
| 213 if (pin != 0) { 214 int airq; 215 216 airq = pci_apic_irq(bus, slot, pin); 217 if (airq >= 0) { 218 /* PCI specific entry found in MP table */ 219 if (airq != line) 220 undirect_pci_irq(line); 221 return(airq); 222 } else { 223 /* 224 * PCI interrupts might be redirected 225 * to the ISA bus according to some MP 226 * tables. Use the same methods as 227 * used by the ISA devices devices to 228 * find the proper IOAPIC int pin. 229 */ 230 airq = isa_apic_irq(line); 231 if ((airq >= 0) && (airq != line)) { 232 /* XXX: undirect_pci_irq() ? */ 233 undirect_isa_irq(line); 234 return(airq); 235 } 236 }
|
230 }
| 237 }
|
231 }
| 238 return(line);
|
232 }
| 239 }
|
233 return(line); 234 }
| |
235#else
| 240#else
|
236 /* 237 * Some BIOS writers seem to want to ignore the spec and put 238 * 0 in the intline rather than 255 to indicate none. The rest of 239 * the code uses 255 as an invalid IRQ. 240 */ 241 if (reg == PCIR_INTLINE && bytes == 1) { 242 line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1); 243 pin = pci_do_cfgregread(bus, slot, func, PCIR_INTPIN, 1); 244 return pci_i386_map_intline(line); 245 }
| 241 /* 242 * Some BIOS writers seem to want to ignore the spec and put 243 * 0 in the intline rather than 255 to indicate none. The rest of 244 * the code uses 255 as an invalid IRQ. 245 */ 246 if (reg == PCIR_INTLINE && bytes == 1) { 247 line = pci_do_cfgregread(bus, slot, func, PCIR_INTLINE, 1); 248 return pci_i386_map_intline(line); 249 }
|
246#endif /* APIC_IO */
| 250#endif /* APIC_IO */
|
247 return(pci_do_cfgregread(bus, slot, func, reg, bytes));
| 251 return(pci_do_cfgregread(bus, slot, func, reg, bytes));
|
248} 249 250/* 251 * Write configuration space register 252 */ 253void 254pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) 255{
| 252} 253 254/* 255 * Write configuration space register 256 */ 257void 258pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes) 259{
|
256 return(usebios ? 257 pcibios_cfgwrite(bus, slot, func, reg, data, bytes) : 258 pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
| 260 return (usebios ? 261 pcibios_cfgwrite(bus, slot, func, reg, data, bytes) : 262 pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
|
259} 260 261/* 262 * Route a PCI interrupt 263 * 264 * XXX we don't do anything "right" with the function number in the PIR table 265 * (because the consumer isn't currently passing it in). We don't care 266 * anyway, due to the way PCI interrupts are assigned. 267 */ 268int 269pci_cfgintr(int bus, int device, int pin) 270{
| 263} 264 265/* 266 * Route a PCI interrupt 267 * 268 * XXX we don't do anything "right" with the function number in the PIR table 269 * (because the consumer isn't currently passing it in). We don't care 270 * anyway, due to the way PCI interrupts are assigned. 271 */ 272int 273pci_cfgintr(int bus, int device, int pin) 274{
|
271 struct PIR_entry *pe; 272 int i, irq; 273 struct bios_regs args; 274 u_int16_t v; 275 int already = 0;
| 275 struct PIR_entry *pe; 276 int i, irq; 277 struct bios_regs args; 278 u_int16_t v; 279 int already = 0;
|
276
| 280
|
277 v = pcibios_get_version(); 278 if (v < 0x0210) { 279 PRVERB(( 280 "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n", 281 (v & 0xff00) >> 8, v & 0xff)); 282 return (255); 283 } 284 if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) || 285 (pin < 1) || (pin > 4)) 286 return(255);
| 281 v = pcibios_get_version(); 282 if (v < 0x0210) { 283 PRVERB(( 284 "pci_cfgintr: BIOS %x.%02x doesn't support interrupt routing\n", 285 (v & 0xff00) >> 8, v & 0xff)); 286 return (PCI_INVALID_IRQ); 287 } 288 if ((bus < 0) || (bus > 255) || (device < 0) || (device > 255) || 289 (pin < 1) || (pin > 4)) 290 return(PCI_INVALID_IRQ);
|
287
| 291
|
288 /* 289 * Scan the entry table for a contender 290 */ 291 for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, pe++) { 292 if ((bus != pe->pe_bus) || (device != pe->pe_device)) 293 continue; 294 295 irq = pci_cfgintr_linked(pe, pin); 296 if (irq == 255) 297 irq = pci_cfgintr_unique(pe, pin); 298 if (irq != 255) 299 already = 1; 300 if (irq == 255) 301 irq = pci_cfgintr_virgin(pe, pin); 302 if (irq == 255) 303 break; 304
| |
305 /*
| 292 /*
|
306 * Ask the BIOS to route the interrupt
| 293 * Scan the entry table for a contender
|
307 */
| 294 */
|
308 args.eax = PCIBIOS_ROUTE_INTERRUPT; 309 args.ebx = (bus << 8) | (device << 3); 310 args.ecx = (irq << 8) | (0xa + pin - 1); /* pin value is 0xa - 0xd */ 311 if (!already && bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { 312 /* 313 * XXX if it fails, we should try to smack the router 314 * hardware directly. 315 * XXX Also, there may be other choices that we can try that 316 * will work. 317 */ 318 PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n")); 319 return(255);
| 295 for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; 296 i++, pe++) { 297 if ((bus != pe->pe_bus) || (device != pe->pe_device)) 298 continue; 299 300 irq = pci_cfgintr_linked(pe, pin); 301 if (irq == PCI_INVALID_IRQ) 302 irq = pci_cfgintr_unique(pe, pin); 303 if (irq != PCI_INVALID_IRQ) 304 already = 1; 305 if (irq == PCI_INVALID_IRQ) 306 irq = pci_cfgintr_virgin(pe, pin); 307 if (irq == PCI_INVALID_IRQ) 308 break; 309 310 /* 311 * Ask the BIOS to route the interrupt 312 */ 313 args.eax = PCIBIOS_ROUTE_INTERRUPT; 314 args.ebx = (bus << 8) | (device << 3); 315 /* pin value is 0xa - 0xd */ 316 args.ecx = (irq << 8) | (0xa + pin - 1); 317 if (!already && 318 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { 319 /* 320 * XXX if it fails, we should try to smack the router 321 * hardware directly. 322 * XXX Also, there may be other choices that we can 323 * try that will work. 324 */ 325 PRVERB(("pci_cfgintr: ROUTE_INTERRUPT failed.\n")); 326 return(PCI_INVALID_IRQ); 327 } 328 printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, 329 device, 'A' + pin - 1, irq); 330 return(irq);
|
320 }
| 331 }
|
321 printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", bus, device, 'A' + pin - 1, irq); 322 return(irq); 323 }
| |
324
| 332
|
325 PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, device, 'A' + pin - 1)); 326 return(255);
| 333 PRVERB(("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, 334 device, 'A' + pin - 1)); 335 return(PCI_INVALID_IRQ);
|
327} 328 329/* 330 * Look to see if the routing table claims this pin is uniquely routed. 331 */ 332static int 333pci_cfgintr_unique(struct PIR_entry *pe, int pin) 334{
| 336} 337 338/* 339 * Look to see if the routing table claims this pin is uniquely routed. 340 */ 341static int 342pci_cfgintr_unique(struct PIR_entry *pe, int pin) 343{
|
335 int irq; 336 uint32_t irqmask;
| 344 int irq; 345 uint32_t irqmask;
|
337
| 346
|
338 irqmask = pe->pe_intpin[pin - 1].irqs; 339 if (irqmask != 0 && powerof2(irqmask)) { 340 irq = ffs(irqmask) - 1; 341 PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq)); 342 return(irq); 343 } 344 return(255);
| 347 irqmask = pe->pe_intpin[pin - 1].irqs; 348 if (irqmask != 0 && powerof2(irqmask)) { 349 irq = ffs(irqmask) - 1; 350 PRVERB(("pci_cfgintr_unique: hard-routed to irq %d\n", irq)); 351 return(irq); 352 } 353 return(PCI_INVALID_IRQ);
|
345} 346 347/* 348 * Look for another device which shares the same link byte and 349 * already has a unique IRQ, or which has had one routed already. 350 */ 351static int 352pci_cfgintr_linked(struct PIR_entry *pe, int pin) 353{
| 354} 355 356/* 357 * Look for another device which shares the same link byte and 358 * already has a unique IRQ, or which has had one routed already. 359 */ 360static int 361pci_cfgintr_linked(struct PIR_entry *pe, int pin) 362{
|
354 struct PIR_entry *oe; 355 struct PIR_intpin *pi; 356 int i, j, irq;
| 363 struct PIR_entry *oe; 364 struct PIR_intpin *pi; 365 int i, j, irq;
|
357
| 366
|
358 /* 359 * Scan table slots. 360 */ 361 for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, oe++) {
| 367 /* 368 * Scan table slots. 369 */ 370 for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; 371 i++, oe++) { 372 /* scan interrupt pins */ 373 for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
|
362
| 374
|
363 /* scan interrupt pins */ 364 for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) {
| 375 /* don't look at the entry we're trying to match */ 376 if ((pe == oe) && (i == (pin - 1))) 377 continue; 378 /* compare link bytes */ 379 if (pi->link != pe->pe_intpin[pin - 1].link) 380 continue; 381 /* link destination mapped to a unique interrupt? */ 382 if (pi->irqs != 0 && powerof2(pi->irqs)) { 383 irq = ffs(pi->irqs) - 1; 384 PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n", 385 pi->link, irq)); 386 return(irq); 387 }
|
365
| 388
|
366 /* don't look at the entry we're trying to match with */ 367 if ((pe == oe) && (i == (pin - 1))) 368 continue; 369 370 /* compare link bytes */ 371 if (pi->link != pe->pe_intpin[pin - 1].link) 372 continue; 373 374 /* link destination mapped to a unique interrupt? */ 375 if (pi->irqs != 0 && powerof2(pi->irqs)) { 376 irq = ffs(pi->irqs) - 1; 377 PRVERB(("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n", 378 pi->link, irq)); 379 return(irq); 380 } 381 382 /* look for the real PCI device that matches this table entry */ 383 if ((irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, j, pin)) != 255) 384 return(irq);
| 389 /* 390 * look for the real PCI device that matches this 391 * table entry 392 */ 393 irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, 394 j, pin); 395 if (irq != PCI_INVALID_IRQ) 396 return(irq); 397 }
|
385 }
| 398 }
|
386 } 387 return(255);
| 399 return(PCI_INVALID_IRQ);
|
388} 389 390/* 391 * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and 392 * see if it has already been assigned an interrupt. 393 */ 394static int 395pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin) 396{
| 400} 401 402/* 403 * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and 404 * see if it has already been assigned an interrupt. 405 */ 406static int 407pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin) 408{
|
397 devclass_t pci_devclass; 398 device_t *pci_devices; 399 int pci_count; 400 device_t *pci_children; 401 int pci_childcount; 402 device_t *busp, *childp; 403 int i, j, irq;
| 409 devclass_t pci_devclass; 410 device_t *pci_devices; 411 int pci_count; 412 device_t *pci_children; 413 int pci_childcount; 414 device_t *busp, *childp; 415 int i, j, irq;
|
404
| 416
|
405 /* 406 * Find all the PCI busses. 407 */ 408 pci_count = 0; 409 if ((pci_devclass = devclass_find("pci")) != NULL) 410 devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
| 417 /* 418 * Find all the PCI busses. 419 */ 420 pci_count = 0; 421 if ((pci_devclass = devclass_find("pci")) != NULL) 422 devclass_get_devices(pci_devclass, &pci_devices, &pci_count);
|
411
| 423
|
412 /* 413 * Scan all the PCI busses/devices looking for this one. 414 */ 415 irq = 255; 416 for (i = 0, busp = pci_devices; (i < pci_count) && (irq == 255); i++, busp++) { 417 pci_childcount = 0; 418 device_get_children(*busp, &pci_children, &pci_childcount);
| 424 /* 425 * Scan all the PCI busses/devices looking for this one. 426 */ 427 irq = PCI_INVALID_IRQ; 428 for (i = 0, busp = pci_devices; (i < pci_count) && (irq == PCI_INVALID_IRQ); 429 i++, busp++) { 430 pci_childcount = 0; 431 device_get_children(*busp, &pci_children, &pci_childcount);
|
419
| 432
|
420 for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) { 421 if ((pci_get_bus(*childp) == bus) && 422 (pci_get_slot(*childp) == device) && 423 (pci_get_intpin(*childp) == matchpin)) { 424 irq = pci_i386_map_intline(pci_get_irq(*childp)); 425 if (irq != 255) 426 PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n", 427 pe->pe_intpin[pin - 1].link, irq, 428 pci_get_bus(*childp), pci_get_slot(*childp), pci_get_function(*childp))); 429 break; 430 }
| 433 for (j = 0, childp = pci_children; j < pci_childcount; j++, 434 childp++) { 435 if ((pci_get_bus(*childp) == bus) && 436 (pci_get_slot(*childp) == device) && 437 (pci_get_intpin(*childp) == matchpin)) { 438 irq = pci_i386_map_intline(pci_get_irq(*childp)); 439 if (irq != PCI_INVALID_IRQ) 440 PRVERB(("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n", 441 pe->pe_intpin[pin - 1].link, irq, 442 pci_get_bus(*childp), 443 pci_get_slot(*childp), 444 pci_get_function(*childp))); 445 break; 446 } 447 } 448 if (pci_children != NULL) 449 free(pci_children, M_TEMP);
|
431 }
| 450 }
|
432 if (pci_children != NULL) 433 free(pci_children, M_TEMP); 434 } 435 if (pci_devices != NULL) 436 free(pci_devices, M_TEMP); 437 return(irq);
| 451 if (pci_devices != NULL) 452 free(pci_devices, M_TEMP); 453 return(irq);
|
438} 439 440/* 441 * Pick a suitable IRQ from those listed as routable to this device. 442 */ 443static int 444pci_cfgintr_virgin(struct PIR_entry *pe, int pin) 445{
| 454} 455 456/* 457 * Pick a suitable IRQ from those listed as routable to this device. 458 */ 459static int 460pci_cfgintr_virgin(struct PIR_entry *pe, int pin) 461{
|
446 int irq, ibit;
| 462 int irq, ibit;
|
447
| 463
|
448 /* first scan the set of PCI-only interrupts and see if any of these are routable */ 449 for (irq = 0; irq < 16; irq++) { 450 ibit = (1 << irq);
| 464 /* 465 * first scan the set of PCI-only interrupts and see if any of these 466 * are routable 467 */ 468 for (irq = 0; irq < 16; irq++) { 469 ibit = (1 << irq);
|
451
| 470
|
452 /* can we use this interrupt? */ 453 if ((pci_route_table->pt_header.ph_pci_irqs & ibit) && 454 (pe->pe_intpin[pin - 1].irqs & ibit)) { 455 PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq)); 456 return(irq);
| 471 /* can we use this interrupt? */ 472 if ((pci_route_table->pt_header.ph_pci_irqs & ibit) && 473 (pe->pe_intpin[pin - 1].irqs & ibit)) { 474 PRVERB(("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq)); 475 return(irq); 476 }
|
457 }
| 477 }
|
458 }
| |
459
| 478
|
460 /* life is tough, so just pick an interrupt */ 461 for (irq = 0; irq < 16; irq++) { 462 ibit = (1 << irq); 463 464 if (pe->pe_intpin[pin - 1].irqs & ibit) { 465 PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq)); 466 return(irq);
| 479 /* life is tough, so just pick an interrupt */ 480 for (irq = 0; irq < 16; irq++) { 481 ibit = (1 << irq); 482 if (pe->pe_intpin[pin - 1].irqs & ibit) { 483 PRVERB(("pci_cfgintr_virgin: using routable interrupt %d\n", irq)); 484 return(irq); 485 }
|
467 }
| 486 }
|
468 } 469 return(255);
| 487 return(PCI_INVALID_IRQ);
|
470} 471 472 473/* 474 * Config space access using BIOS functions 475 */ 476static int 477pcibios_cfgread(int bus, int slot, int func, int reg, int bytes) 478{
| 488} 489 490 491/* 492 * Config space access using BIOS functions 493 */ 494static int 495pcibios_cfgread(int bus, int slot, int func, int reg, int bytes) 496{
|
479 struct bios_regs args; 480 u_int mask;
| 497 struct bios_regs args; 498 u_int mask;
|
481
| 499
|
482 switch(bytes) { 483 case 1: 484 args.eax = PCIBIOS_READ_CONFIG_BYTE; 485 mask = 0xff; 486 break; 487 case 2: 488 args.eax = PCIBIOS_READ_CONFIG_WORD; 489 mask = 0xffff; 490 break; 491 case 4: 492 args.eax = PCIBIOS_READ_CONFIG_DWORD; 493 mask = 0xffffffff; 494 break; 495 default: 496 return(-1); 497 } 498 args.ebx = (bus << 8) | (slot << 3) | func; 499 args.edi = reg; 500 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 501 /* check call results? */ 502 return(args.ecx & mask);
| 500 switch(bytes) { 501 case 1: 502 args.eax = PCIBIOS_READ_CONFIG_BYTE; 503 mask = 0xff; 504 break; 505 case 2: 506 args.eax = PCIBIOS_READ_CONFIG_WORD; 507 mask = 0xffff; 508 break; 509 case 4: 510 args.eax = PCIBIOS_READ_CONFIG_DWORD; 511 mask = 0xffffffff; 512 break; 513 default: 514 return(-1); 515 } 516 args.ebx = (bus << 8) | (slot << 3) | func; 517 args.edi = reg; 518 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 519 /* check call results? */ 520 return(args.ecx & mask);
|
503} 504 505static void 506pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 507{
| 521} 522 523static void 524pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 525{
|
508 struct bios_regs args;
| 526 struct bios_regs args;
|
509
| 527
|
510 switch(bytes) { 511 case 1: 512 args.eax = PCIBIOS_WRITE_CONFIG_BYTE; 513 break; 514 case 2: 515 args.eax = PCIBIOS_WRITE_CONFIG_WORD; 516 break; 517 case 4: 518 args.eax = PCIBIOS_WRITE_CONFIG_DWORD; 519 break; 520 default: 521 return; 522 } 523 args.ebx = (bus << 8) | (slot << 3) | func; 524 args.ecx = data; 525 args.edi = reg; 526 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
| 528 switch(bytes) { 529 case 1: 530 args.eax = PCIBIOS_WRITE_CONFIG_BYTE; 531 break; 532 case 2: 533 args.eax = PCIBIOS_WRITE_CONFIG_WORD; 534 break; 535 case 4: 536 args.eax = PCIBIOS_WRITE_CONFIG_DWORD; 537 break; 538 default: 539 return; 540 } 541 args.ebx = (bus << 8) | (slot << 3) | func; 542 args.ecx = data; 543 args.edi = reg; 544 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
|
527} 528 529/* 530 * Determine whether there is a PCI BIOS present 531 */ 532static int 533pcibios_cfgopen(void) 534{
| 545} 546 547/* 548 * Determine whether there is a PCI BIOS present 549 */ 550static int 551pcibios_cfgopen(void) 552{
|
535 u_int16_t v = 0;
| 553 u_int16_t v = 0;
|
536
| 554
|
537 if (PCIbios.entry != 0 && enable_pcibios) { 538 v = pcibios_get_version(); 539 if (v > 0) 540 printf("pcibios: BIOS version %x.%02x\n", (v & 0xff00) >> 8, 541 v & 0xff); 542 } 543 return (v > 0);
| 555 if (PCIbios.entry != 0 && enable_pcibios) { 556 v = pcibios_get_version(); 557 if (v > 0) 558 printf("pcibios: BIOS version %x.%02x\n", 559 (v & 0xff00) >> 8, v & 0xff); 560 } 561 return (v > 0);
|
544} 545 546/* 547 * Configuration space access using direct register operations 548 */ 549 550/* enable configuration space accesses and return data port address */ 551static int 552pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 553{
| 562} 563 564/* 565 * Configuration space access using direct register operations 566 */ 567 568/* enable configuration space accesses and return data port address */ 569static int 570pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 571{
|
554 int dataport = 0;
| 572 int dataport = 0;
|
555
| 573
|
556 if (bus <= PCI_BUSMAX 557 && slot < devmax 558 && func <= PCI_FUNCMAX 559 && reg <= PCI_REGMAX 560 && bytes != 3 561 && (unsigned) bytes <= 4 562 && (reg & (bytes -1)) == 0) { 563 switch (cfgmech) { 564 case 1: 565 outl(CONF1_ADDR_PORT, (1 << 31) 566 | (bus << 16) | (slot << 11) 567 | (func << 8) | (reg & ~0x03)); 568 dataport = CONF1_DATA_PORT + (reg & 0x03); 569 break; 570 case 2: 571 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 572 outb(CONF2_FORWARD_PORT, bus); 573 dataport = 0xc000 | (slot << 8) | reg; 574 break;
| 574 if (bus <= PCI_BUSMAX 575 && slot < devmax 576 && func <= PCI_FUNCMAX 577 && reg <= PCI_REGMAX 578 && bytes != 3 579 && (unsigned) bytes <= 4 580 && (reg & (bytes -1)) == 0) { 581 switch (cfgmech) { 582 case 1: 583 outl(CONF1_ADDR_PORT, (1 << 31) 584 | (bus << 16) | (slot << 11) 585 | (func << 8) | (reg & ~0x03)); 586 dataport = CONF1_DATA_PORT + (reg & 0x03); 587 break; 588 case 2: 589 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 590 outb(CONF2_FORWARD_PORT, bus); 591 dataport = 0xc000 | (slot << 8) | reg; 592 break; 593 }
|
575 }
| 594 }
|
576 } 577 return (dataport);
| 595 return (dataport);
|
578} 579 580/* disable configuration space accesses */ 581static void 582pci_cfgdisable(void) 583{
| 596} 597 598/* disable configuration space accesses */ 599static void 600pci_cfgdisable(void) 601{
|
584 switch (cfgmech) { 585 case 1: 586 outl(CONF1_ADDR_PORT, 0); 587 break; 588 case 2: 589 outb(CONF2_ENABLE_PORT, 0); 590 outb(CONF2_FORWARD_PORT, 0); 591 break; 592 }
| 602 switch (cfgmech) { 603 case 1: 604 outl(CONF1_ADDR_PORT, 0); 605 break; 606 case 2: 607 outb(CONF2_ENABLE_PORT, 0); 608 outb(CONF2_FORWARD_PORT, 0); 609 break; 610 }
|
593} 594 595static int 596pcireg_cfgread(int bus, int slot, int func, int reg, int bytes) 597{
| 611} 612 613static int 614pcireg_cfgread(int bus, int slot, int func, int reg, int bytes) 615{
|
598 int data = -1; 599 int port;
| 616 int data = -1; 617 int port;
|
600
| 618
|
601 port = pci_cfgenable(bus, slot, func, reg, bytes);
| 619 port = pci_cfgenable(bus, slot, func, reg, bytes);
|
602
| 620
|
603 if (port != 0) { 604 switch (bytes) { 605 case 1: 606 data = inb(port); 607 break; 608 case 2: 609 data = inw(port); 610 break; 611 case 4: 612 data = inl(port); 613 break;
| 621 if (port != 0) { 622 switch (bytes) { 623 case 1: 624 data = inb(port); 625 break; 626 case 2: 627 data = inw(port); 628 break; 629 case 4: 630 data = inl(port); 631 break; 632 } 633 pci_cfgdisable();
|
614 }
| 634 }
|
615 pci_cfgdisable(); 616 } 617 return (data);
| 635 return (data);
|
618} 619 620static void 621pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 622{
| 636} 637 638static void 639pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 640{
|
623 int port;
| 641 int port;
|
624
| 642
|
625 port = pci_cfgenable(bus, slot, func, reg, bytes); 626 if (port != 0) { 627 switch (bytes) { 628 case 1: 629 outb(port, data); 630 break; 631 case 2: 632 outw(port, data); 633 break; 634 case 4: 635 outl(port, data); 636 break;
| 643 port = pci_cfgenable(bus, slot, func, reg, bytes); 644 if (port != 0) { 645 switch (bytes) { 646 case 1: 647 outb(port, data); 648 break; 649 case 2: 650 outw(port, data); 651 break; 652 case 4: 653 outl(port, data); 654 break; 655 } 656 pci_cfgdisable();
|
637 }
| 657 }
|
638 pci_cfgdisable(); 639 }
| |
640} 641 642/* check whether the configuration mechanism has been correctly identified */ 643static int 644pci_cfgcheck(int maxdev) 645{
| 658} 659 660/* check whether the configuration mechanism has been correctly identified */ 661static int 662pci_cfgcheck(int maxdev) 663{
|
646 u_char device;
| 664 u_char device;
|
647
| 665
|
648 if (bootverbose) 649 printf("pci_cfgcheck:\tdevice "); 650 651 for (device = 0; device < maxdev; device++) { 652 unsigned id, class, header;
| |
653 if (bootverbose)
| 666 if (bootverbose)
|
654 printf("%d ", device);
| 667 printf("pci_cfgcheck:\tdevice ");
|
655
| 668
|
656 id = inl(pci_cfgenable(0, device, 0, 0, 4)); 657 if (id == 0 || id == -1) 658 continue;
| 669 for (device = 0; device < maxdev; device++) { 670 unsigned id, class, header; 671 if (bootverbose) 672 printf("%d ", device);
|
659
| 673
|
660 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8; 661 if (bootverbose) 662 printf("[class=%06x] ", class); 663 if (class == 0 || (class & 0xf870ff) != 0) 664 continue;
| 674 id = inl(pci_cfgenable(0, device, 0, 0, 4)); 675 if (id == 0 || id == -1) 676 continue;
|
665
| 677
|
666 header = inb(pci_cfgenable(0, device, 0, 14, 1)); 667 if (bootverbose) 668 printf("[hdr=%02x] ", header); 669 if ((header & 0x7e) != 0) 670 continue;
| 678 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8; 679 if (bootverbose) 680 printf("[class=%06x] ", class); 681 if (class == 0 || (class & 0xf870ff) != 0) 682 continue;
|
671
| 683
|
672 if (bootverbose) 673 printf("is there (id=%08x)\n", id);
| 684 header = inb(pci_cfgenable(0, device, 0, 14, 1)); 685 if (bootverbose) 686 printf("[hdr=%02x] ", header); 687 if ((header & 0x7e) != 0) 688 continue;
|
674
| 689
|
675 pci_cfgdisable(); 676 return (1); 677 } 678 if (bootverbose) 679 printf("-- nothing found\n");
| 690 if (bootverbose) 691 printf("is there (id=%08x)\n", id);
|
680
| 692
|
681 pci_cfgdisable(); 682 return (0);
| 693 pci_cfgdisable(); 694 return (1); 695 } 696 if (bootverbose) 697 printf("-- nothing found\n"); 698 699 pci_cfgdisable(); 700 return (0);
|
683} 684 685static int 686pcireg_cfgopen(void) 687{
| 701} 702 703static int 704pcireg_cfgopen(void) 705{
|
688 unsigned long mode1res,oldval1; 689 unsigned char mode2res,oldval2;
| 706 unsigned long mode1res,oldval1; 707 unsigned char mode2res,oldval2;
|
690
| 708
|
691 oldval1 = inl(CONF1_ADDR_PORT);
| 709 oldval1 = inl(CONF1_ADDR_PORT);
|
692
| 710
|
693 if (bootverbose) { 694 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", 695 oldval1); 696 }
| 711 if (bootverbose) { 712 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", 713 oldval1); 714 }
|
697
| 715
|
698 if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
| 716 if ((oldval1 & CONF1_ENABLE_MSK) == 0) {
|
699
| 717
|
700 cfgmech = 1; 701 devmax = 32;
| 718 cfgmech = 1; 719 devmax = 32;
|
702
| 720
|
703 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 704 outb(CONF1_ADDR_PORT +3, 0); 705 mode1res = inl(CONF1_ADDR_PORT); 706 outl(CONF1_ADDR_PORT, oldval1);
| 721 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 722 outb(CONF1_ADDR_PORT +3, 0); 723 mode1res = inl(CONF1_ADDR_PORT); 724 outl(CONF1_ADDR_PORT, oldval1);
|
707
| 725
|
708 if (bootverbose) 709 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 710 mode1res, CONF1_ENABLE_CHK);
| 726 if (bootverbose) 727 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 728 mode1res, CONF1_ENABLE_CHK);
|
711
| 729
|
712 if (mode1res) { 713 if (pci_cfgcheck(32)) 714 return (cfgmech); 715 }
| 730 if (mode1res) { 731 if (pci_cfgcheck(32)) 732 return (cfgmech); 733 }
|
716
| 734
|
717 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 718 mode1res = inl(CONF1_ADDR_PORT); 719 outl(CONF1_ADDR_PORT, oldval1);
| 735 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 736 mode1res = inl(CONF1_ADDR_PORT); 737 outl(CONF1_ADDR_PORT, oldval1);
|
720
| 738
|
721 if (bootverbose) 722 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 723 mode1res, CONF1_ENABLE_CHK1);
| 739 if (bootverbose) 740 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 741 mode1res, CONF1_ENABLE_CHK1);
|
724
| 742
|
725 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 726 if (pci_cfgcheck(32)) 727 return (cfgmech);
| 743 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 744 if (pci_cfgcheck(32)) 745 return (cfgmech); 746 }
|
728 }
| 747 }
|
729 }
| |
730
| 748
|
731 oldval2 = inb(CONF2_ENABLE_PORT);
| 749 oldval2 = inb(CONF2_ENABLE_PORT);
|
732
| 750
|
733 if (bootverbose) { 734 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 735 oldval2); 736 }
| 751 if (bootverbose) { 752 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 753 oldval2); 754 }
|
737
| 755
|
738 if ((oldval2 & 0xf0) == 0) {
| 756 if ((oldval2 & 0xf0) == 0) {
|
739
| 757
|
740 cfgmech = 2; 741 devmax = 16;
| 758 cfgmech = 2; 759 devmax = 16;
|
742
| 760
|
743 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 744 mode2res = inb(CONF2_ENABLE_PORT); 745 outb(CONF2_ENABLE_PORT, oldval2);
| 761 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 762 mode2res = inb(CONF2_ENABLE_PORT); 763 outb(CONF2_ENABLE_PORT, oldval2);
|
746
| 764
|
747 if (bootverbose) 748 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 749 mode2res, CONF2_ENABLE_CHK);
| 765 if (bootverbose) 766 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 767 mode2res, CONF2_ENABLE_CHK);
|
750
| 768
|
751 if (mode2res == CONF2_ENABLE_RES) { 752 if (bootverbose) 753 printf("pci_open(2a):\tnow trying mechanism 2\n");
| 769 if (mode2res == CONF2_ENABLE_RES) { 770 if (bootverbose) 771 printf("pci_open(2a):\tnow trying mechanism 2\n");
|
754
| 772
|
755 if (pci_cfgcheck(16)) 756 return (cfgmech);
| 773 if (pci_cfgcheck(16)) 774 return (cfgmech); 775 }
|
757 }
| 776 }
|
758 }
| |
759
| 777
|
760 cfgmech = 0; 761 devmax = 0; 762 return (cfgmech);
| 778 cfgmech = 0; 779 devmax = 0; 780 return (cfgmech);
|
763} 764
| 781} 782
|