pci_bus.c (66416) | pci_bus.c (66529) |
---|---|
1/* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * | 1/* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/sys/i386/pci/pci_bus.c 66416 2000-09-28 00:37:32Z peter $ | 26 * $FreeBSD: head/sys/i386/pci/pci_bus.c 66529 2000-10-02 07:11:13Z msmith $ |
27 * 28 */ 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/malloc.h> 36 37#include <pci/pcivar.h> 38#include <pci/pcireg.h> | 27 * 28 */ 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/malloc.h> 36 37#include <pci/pcivar.h> 38#include <pci/pcireg.h> |
39#include <i386/isa/pcibus.h> | |
40#include <isa/isavar.h> 41#include <machine/nexusvar.h> | 39#include <isa/isavar.h> 40#include <machine/nexusvar.h> |
42 | 41#include <machine/pci_cfgreg.h> |
43#include <machine/segments.h> 44#include <machine/pc/bios.h> 45 46#include "pcib_if.h" 47 | 42#include <machine/segments.h> 43#include <machine/pc/bios.h> 44 45#include "pcib_if.h" 46 |
48static int cfgmech; 49static int devmax; 50static int usebios; 51 52static int pcibios_cfgread(int bus, int slot, int func, int reg, 53 int bytes); 54static void pcibios_cfgwrite(int bus, int slot, int func, int reg, 55 int data, int bytes); 56static int pcibios_cfgopen(void); 57static int pcireg_cfgread(int bus, int slot, int func, int reg, 58 int bytes); 59static void pcireg_cfgwrite(int bus, int slot, int func, int reg, 60 int data, int bytes); 61static int pcireg_cfgopen(void); 62 63/* read configuration space register */ 64 | |
65static int 66nexus_pcib_maxslots(device_t dev) 67{ 68 return 31; 69} 70 | 47static int 48nexus_pcib_maxslots(device_t dev) 49{ 50 return 31; 51} 52 |
53/* read configuration space register */ 54 |
|
71static u_int32_t 72nexus_pcib_read_config(device_t dev, int bus, int slot, int func, 73 int reg, int bytes) 74{ | 55static u_int32_t 56nexus_pcib_read_config(device_t dev, int bus, int slot, int func, 57 int reg, int bytes) 58{ |
75 return(usebios ? 76 pcibios_cfgread(bus, slot, func, reg, bytes) : 77 pcireg_cfgread(bus, slot, func, reg, bytes)); | 59 return(pci_cfgregread(bus, slot, func, reg, bytes)); |
78} 79 80/* write configuration space register */ 81 82static void 83nexus_pcib_write_config(device_t dev, int bus, int slot, int func, 84 int reg, u_int32_t data, int bytes) 85{ | 60} 61 62/* write configuration space register */ 63 64static void 65nexus_pcib_write_config(device_t dev, int bus, int slot, int func, 66 int reg, u_int32_t data, int bytes) 67{ |
86 return(usebios ? 87 pcibios_cfgwrite(bus, slot, func, reg, data, bytes) : 88 pcireg_cfgwrite(bus, slot, func, reg, data, bytes)); | 68 pci_cfgregwrite(bus, slot, func, reg, data, bytes); |
89} 90 | 69} 70 |
91/* initialise access to PCI configuration space */ 92static int 93pci_cfgopen(void) 94{ 95 if (pcibios_cfgopen() != 0) { 96 usebios = 1; 97 } else if (pcireg_cfgopen() != 0) { 98 usebios = 0; 99 } else { 100 return(0); 101 } 102 return(1); 103} 104 105/* config space access using BIOS functions */ 106 107static int 108pcibios_cfgread(int bus, int slot, int func, int reg, int bytes) 109{ 110 struct bios_regs args; 111 u_int mask; 112 113 switch(bytes) { 114 case 1: 115 args.eax = PCIBIOS_READ_CONFIG_BYTE; 116 mask = 0xff; 117 break; 118 case 2: 119 args.eax = PCIBIOS_READ_CONFIG_WORD; 120 mask = 0xffff; 121 break; 122 case 4: 123 args.eax = PCIBIOS_READ_CONFIG_DWORD; 124 mask = 0xffffffff; 125 break; 126 default: 127 return(-1); 128 } 129 args.ebx = (bus << 8) | (slot << 3) | func; 130 args.edi = reg; 131 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 132 /* check call results? */ 133 return(args.ecx & mask); 134} 135 136static void 137pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 138{ 139 struct bios_regs args; 140 141 switch(bytes) { 142 case 1: 143 args.eax = PCIBIOS_WRITE_CONFIG_BYTE; 144 break; 145 case 2: 146 args.eax = PCIBIOS_WRITE_CONFIG_WORD; 147 break; 148 case 4: 149 args.eax = PCIBIOS_WRITE_CONFIG_DWORD; 150 break; 151 default: 152 return; 153 } 154 args.ebx = (bus << 8) | (slot << 3) | func; 155 args.ecx = data; 156 args.edi = reg; 157 bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); 158} 159 160/* determine whether there is a PCI BIOS present */ 161 162static int 163pcibios_cfgopen(void) 164{ 165 /* check for a found entrypoint */ 166 return(PCIbios.entry != 0); 167} 168 169/* configuration space access using direct register operations */ 170 171/* enable configuration space accesses and return data port address */ 172 173static int 174pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) 175{ 176 int dataport = 0; 177 178 if (bus <= PCI_BUSMAX 179 && slot < devmax 180 && func <= PCI_FUNCMAX 181 && reg <= PCI_REGMAX 182 && bytes != 3 183 && (unsigned) bytes <= 4 184 && (reg & (bytes -1)) == 0) { 185 switch (cfgmech) { 186 case 1: 187 outl(CONF1_ADDR_PORT, (1 << 31) 188 | (bus << 16) | (slot << 11) 189 | (func << 8) | (reg & ~0x03)); 190 dataport = CONF1_DATA_PORT + (reg & 0x03); 191 break; 192 case 2: 193 outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); 194 outb(CONF2_FORWARD_PORT, bus); 195 dataport = 0xc000 | (slot << 8) | reg; 196 break; 197 } 198 } 199 return (dataport); 200} 201 202/* disable configuration space accesses */ 203 204static void 205pci_cfgdisable(void) 206{ 207 switch (cfgmech) { 208 case 1: 209 outl(CONF1_ADDR_PORT, 0); 210 break; 211 case 2: 212 outb(CONF2_ENABLE_PORT, 0); 213 outb(CONF2_FORWARD_PORT, 0); 214 break; 215 } 216} 217 218static int 219pcireg_cfgread(int bus, int slot, int func, int reg, int bytes) 220{ 221 int data = -1; 222 int port; 223 224 port = pci_cfgenable(bus, slot, func, reg, bytes); 225 226 if (port != 0) { 227 switch (bytes) { 228 case 1: 229 data = inb(port); 230 break; 231 case 2: 232 data = inw(port); 233 break; 234 case 4: 235 data = inl(port); 236 break; 237 } 238 pci_cfgdisable(); 239 } 240 return (data); 241} 242 243static void 244pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) 245{ 246 int port; 247 248 port = pci_cfgenable(bus, slot, func, reg, bytes); 249 if (port != 0) { 250 switch (bytes) { 251 case 1: 252 outb(port, data); 253 break; 254 case 2: 255 outw(port, data); 256 break; 257 case 4: 258 outl(port, data); 259 break; 260 } 261 pci_cfgdisable(); 262 } 263} 264 265/* check whether the configuration mechanism has been correct identified */ 266 267static int 268pci_cfgcheck(int maxdev) 269{ 270 u_char device; 271 272 if (bootverbose) 273 printf("pci_cfgcheck:\tdevice "); 274 275 for (device = 0; device < maxdev; device++) { 276 unsigned id, class, header; 277 if (bootverbose) 278 printf("%d ", device); 279 280 id = inl(pci_cfgenable(0, device, 0, 0, 4)); 281 if (id == 0 || id == -1) 282 continue; 283 284 class = inl(pci_cfgenable(0, device, 0, 8, 4)) >> 8; 285 if (bootverbose) 286 printf("[class=%06x] ", class); 287 if (class == 0 || (class & 0xf870ff) != 0) 288 continue; 289 290 header = inb(pci_cfgenable(0, device, 0, 14, 1)); 291 if (bootverbose) 292 printf("[hdr=%02x] ", header); 293 if ((header & 0x7e) != 0) 294 continue; 295 296 if (bootverbose) 297 printf("is there (id=%08x)\n", id); 298 299 pci_cfgdisable(); 300 return (1); 301 } 302 if (bootverbose) 303 printf("-- nothing found\n"); 304 305 pci_cfgdisable(); 306 return (0); 307} 308 309static int 310pcireg_cfgopen(void) 311{ 312 unsigned long mode1res,oldval1; 313 unsigned char mode2res,oldval2; 314 315 oldval1 = inl(CONF1_ADDR_PORT); 316 317 if (bootverbose) { 318 printf("pci_open(1):\tmode 1 addr port (0x0cf8) is 0x%08lx\n", 319 oldval1); 320 } 321 322 if ((oldval1 & CONF1_ENABLE_MSK) == 0) { 323 324 cfgmech = 1; 325 devmax = 32; 326 327 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK); 328 outb(CONF1_ADDR_PORT +3, 0); 329 mode1res = inl(CONF1_ADDR_PORT); 330 outl(CONF1_ADDR_PORT, oldval1); 331 332 if (bootverbose) 333 printf("pci_open(1a):\tmode1res=0x%08lx (0x%08lx)\n", 334 mode1res, CONF1_ENABLE_CHK); 335 336 if (mode1res) { 337 if (pci_cfgcheck(32)) 338 return (cfgmech); 339 } 340 341 outl(CONF1_ADDR_PORT, CONF1_ENABLE_CHK1); 342 mode1res = inl(CONF1_ADDR_PORT); 343 outl(CONF1_ADDR_PORT, oldval1); 344 345 if (bootverbose) 346 printf("pci_open(1b):\tmode1res=0x%08lx (0x%08lx)\n", 347 mode1res, CONF1_ENABLE_CHK1); 348 349 if ((mode1res & CONF1_ENABLE_MSK1) == CONF1_ENABLE_RES1) { 350 if (pci_cfgcheck(32)) 351 return (cfgmech); 352 } 353 } 354 355 oldval2 = inb(CONF2_ENABLE_PORT); 356 357 if (bootverbose) { 358 printf("pci_open(2):\tmode 2 enable port (0x0cf8) is 0x%02x\n", 359 oldval2); 360 } 361 362 if ((oldval2 & 0xf0) == 0) { 363 364 cfgmech = 2; 365 devmax = 16; 366 367 outb(CONF2_ENABLE_PORT, CONF2_ENABLE_CHK); 368 mode2res = inb(CONF2_ENABLE_PORT); 369 outb(CONF2_ENABLE_PORT, oldval2); 370 371 if (bootverbose) 372 printf("pci_open(2a):\tmode2res=0x%02x (0x%02x)\n", 373 mode2res, CONF2_ENABLE_CHK); 374 375 if (mode2res == CONF2_ENABLE_RES) { 376 if (bootverbose) 377 printf("pci_open(2a):\tnow trying mechanism 2\n"); 378 379 if (pci_cfgcheck(16)) 380 return (cfgmech); 381 } 382 } 383 384 cfgmech = 0; 385 devmax = 0; 386 return (cfgmech); 387} 388 | |
389static devclass_t pcib_devclass; 390 391static const char * 392nexus_pcib_is_host_bridge(int bus, int slot, int func, 393 u_int32_t id, u_int8_t class, u_int8_t subclass, 394 u_int8_t *busnum) 395{ 396 const char *s = NULL; --- 174 unchanged lines hidden (view full) --- 571{ 572 int bus, slot, func; 573 u_int8_t hdrtype; 574 int found = 0; 575 int pcifunchigh; 576 int found824xx = 0; 577 device_t child; 578 | 71static devclass_t pcib_devclass; 72 73static const char * 74nexus_pcib_is_host_bridge(int bus, int slot, int func, 75 u_int32_t id, u_int8_t class, u_int8_t subclass, 76 u_int8_t *busnum) 77{ 78 const char *s = NULL; --- 174 unchanged lines hidden (view full) --- 253{ 254 int bus, slot, func; 255 u_int8_t hdrtype; 256 int found = 0; 257 int pcifunchigh; 258 int found824xx = 0; 259 device_t child; 260 |
579 if (pci_cfgopen() == 0) | 261 if (pci_cfgregopen() == 0) |
580 return; 581 bus = 0; 582 retry: 583 for (slot = 0; slot <= PCI_SLOTMAX; slot++) { 584 func = 0; 585 hdrtype = nexus_pcib_read_config(0, bus, slot, func, 586 PCIR_HEADERTYPE, 1); 587 if (hdrtype & PCIM_MFDEV) --- 60 unchanged lines hidden (view full) --- 648 if (found824xx && bus == 0) { 649 bus++; 650 goto retry; 651 } 652 653 /* 654 * Make sure we add at least one bridge since some old 655 * hardware doesn't actually have a host-pci bridge device. | 262 return; 263 bus = 0; 264 retry: 265 for (slot = 0; slot <= PCI_SLOTMAX; slot++) { 266 func = 0; 267 hdrtype = nexus_pcib_read_config(0, bus, slot, func, 268 PCIR_HEADERTYPE, 1); 269 if (hdrtype & PCIM_MFDEV) --- 60 unchanged lines hidden (view full) --- 330 if (found824xx && bus == 0) { 331 bus++; 332 goto retry; 333 } 334 335 /* 336 * Make sure we add at least one bridge since some old 337 * hardware doesn't actually have a host-pci bridge device. |
656 * Note that pci_cfgopen() thinks we have PCI devices.. | 338 * Note that pci_cfgregopen() thinks we have PCI devices.. |
657 */ 658 if (!found) { 659 if (bootverbose) 660 printf( 661 "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n"); 662 child = BUS_ADD_CHILD(parent, 100, "pcib", 0); 663 nexus_set_pcibus(child, 0); 664 } 665} 666 667static int 668nexus_pcib_probe(device_t dev) 669{ 670 | 339 */ 340 if (!found) { 341 if (bootverbose) 342 printf( 343 "nexus_pcib_identify: no bridge found, adding pcib0 anyway\n"); 344 child = BUS_ADD_CHILD(parent, 100, "pcib", 0); 345 nexus_set_pcibus(child, 0); 346 } 347} 348 349static int 350nexus_pcib_probe(device_t dev) 351{ 352 |
671 if (pci_cfgopen() != 0) | 353 if (pci_cfgregopen() != 0) |
672 return 0; 673 674 return ENXIO; 675} 676 677static int 678nexus_pcib_attach(device_t dev) 679{ --- 165 unchanged lines hidden --- | 354 return 0; 355 356 return ENXIO; 357} 358 359static int 360nexus_pcib_attach(device_t dev) 361{ --- 165 unchanged lines hidden --- |