1 /* $OpenBSD: pci_machdep.c,v 1.18 2001/01/27 04:59:40 mickey Exp $ */ 2 /* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */ 3 4 /*- 5 * Copyright (c) 1997 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10 * NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 /* 42 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 43 * Copyright (c) 1994 Charles Hannum. All rights reserved. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by Charles Hannum. 56 * 4. The name of the author may not be used to endorse or promote products 57 * derived from this software without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 60 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 61 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 62 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 63 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 64 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 65 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 66 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 67 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 68 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 */ 70 71 /* 72 * Machine-specific functions for PCI autoconfiguration. 73 * 74 * On PCs, there are two methods of generating PCI configuration cycles. 75 * We try to detect the appropriate mechanism for this machine and set 76 * up a few function pointers to access the correct method directly. 77 * 78 * The configuration method can be hard-coded in the config file by 79 * using `options PCI_CONF_MODE=N', where `N' is the configuration mode 80 * as defined section 3.6.4.1, `Generating Configuration Cycles'. 81 */ 82 83 #include <sys/types.h> 84 #include <sys/param.h> 85 #include <sys/time.h> 86 #include <sys/systm.h> 87 #include <sys/errno.h> 88 #include <sys/device.h> 89 90 #include <vm/vm.h> 91 #include <vm/vm_kern.h> 92 93 #define _I386_BUS_DMA_PRIVATE 94 #include <machine/bus.h> 95 #include <machine/pio.h> 96 97 #include "bios.h" 98 #if NBIOS > 0 99 #include <machine/biosvar.h> 100 extern bios_pciinfo_t *bios_pciinfo; 101 #endif 102 103 #include <i386/isa/icu.h> 104 #include <dev/isa/isavar.h> 105 #include <dev/pci/pcivar.h> 106 #include <dev/pci/pcireg.h> 107 108 #include "pcibios.h" 109 #if NPCIBIOS > 0 110 #include <i386/pci/pcibiosvar.h> 111 #endif 112 113 int pci_mode = -1; 114 115 #define PCI_MODE1_ENABLE 0x80000000UL 116 #define PCI_MODE1_ADDRESS_REG 0x0cf8 117 #define PCI_MODE1_DATA_REG 0x0cfc 118 119 #define PCI_MODE2_ENABLE_REG 0x0cf8 120 #define PCI_MODE2_FORWARD_REG 0x0cfa 121 122 /* 123 * PCI doesn't have any special needs; just use the generic versions 124 * of these functions. 125 */ 126 struct i386_bus_dma_tag pci_bus_dma_tag = { 127 NULL, /* _cookie */ 128 _bus_dmamap_create, 129 _bus_dmamap_destroy, 130 _bus_dmamap_load, 131 _bus_dmamap_load_mbuf, 132 _bus_dmamap_load_uio, 133 _bus_dmamap_load_raw, 134 _bus_dmamap_unload, 135 NULL, /* _dmamap_sync */ 136 _bus_dmamem_alloc, 137 _bus_dmamem_free, 138 _bus_dmamem_map, 139 _bus_dmamem_unmap, 140 _bus_dmamem_mmap, 141 }; 142 143 void 144 pci_attach_hook(parent, self, pba) 145 struct device *parent, *self; 146 struct pcibus_attach_args *pba; 147 { 148 149 #if NBIOS > 0 150 if (pba->pba_bus == 0) 151 printf(": configuration mode %d (%s)", 152 pci_mode, (bios_pciinfo?"bios":"no bios")); 153 #else 154 if (pba->pba_bus == 0) 155 printf(": configuration mode %d", pci_mode); 156 #endif 157 } 158 159 int 160 pci_bus_maxdevs(pc, busno) 161 pci_chipset_tag_t pc; 162 int busno; 163 { 164 165 /* 166 * Bus number is irrelevant. If Configuration Mechanism 2 is in 167 * use, can only have devices 0-15 on any bus. If Configuration 168 * Mechanism 1 is in use, can have devices 0-32 (i.e. the `normal' 169 * range). 170 */ 171 if (pci_mode == 2) 172 return (16); 173 else 174 return (32); 175 } 176 177 pcitag_t 178 pci_make_tag(pc, bus, device, function) 179 pci_chipset_tag_t pc; 180 int bus, device, function; 181 { 182 pcitag_t tag; 183 184 #ifndef PCI_CONF_MODE 185 switch (pci_mode) { 186 case 1: 187 goto mode1; 188 case 2: 189 goto mode2; 190 default: 191 panic("pci_make_tag: mode not configured"); 192 } 193 #endif 194 195 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1) 196 #ifndef PCI_CONF_MODE 197 mode1: 198 #endif 199 if (bus >= 256 || device >= 32 || function >= 8) 200 panic("pci_make_tag: bad request"); 201 202 tag.mode1 = PCI_MODE1_ENABLE | 203 (bus << 16) | (device << 11) | (function << 8); 204 return tag; 205 #endif 206 207 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2) 208 #ifndef PCI_CONF_MODE 209 mode2: 210 #endif 211 if (bus >= 256 || device >= 16 || function >= 8) 212 panic("pci_make_tag: bad request"); 213 214 tag.mode2.port = 0xc000 | (device << 8); 215 tag.mode2.enable = 0xf0 | (function << 1); 216 tag.mode2.forward = bus; 217 return tag; 218 #endif 219 } 220 221 void 222 pci_decompose_tag(pc, tag, bp, dp, fp) 223 pci_chipset_tag_t pc; 224 pcitag_t tag; 225 int *bp, *dp, *fp; 226 { 227 228 #ifndef PCI_CONF_MODE 229 switch (pci_mode) { 230 case 1: 231 goto mode1; 232 case 2: 233 goto mode2; 234 default: 235 panic("pci_decompose_tag: mode not configured"); 236 } 237 #endif 238 239 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1) 240 #ifndef PCI_CONF_MODE 241 mode1: 242 #endif 243 if (bp != NULL) 244 *bp = (tag.mode1 >> 16) & 0xff; 245 if (dp != NULL) 246 *dp = (tag.mode1 >> 11) & 0x1f; 247 if (fp != NULL) 248 *fp = (tag.mode1 >> 8) & 0x7; 249 return; 250 #endif 251 252 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2) 253 #ifndef PCI_CONF_MODE 254 mode2: 255 #endif 256 if (bp != NULL) 257 *bp = tag.mode2.forward & 0xff; 258 if (dp != NULL) 259 *dp = (tag.mode2.port >> 8) & 0xf; 260 if (fp != NULL) 261 *fp = (tag.mode2.enable >> 1) & 0x7; 262 #endif 263 } 264 265 pcireg_t 266 pci_conf_read(pc, tag, reg) 267 pci_chipset_tag_t pc; 268 pcitag_t tag; 269 int reg; 270 { 271 pcireg_t data; 272 273 #ifndef PCI_CONF_MODE 274 switch (pci_mode) { 275 case 1: 276 goto mode1; 277 case 2: 278 goto mode2; 279 default: 280 panic("pci_conf_read: mode not configured"); 281 } 282 #endif 283 284 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1) 285 #ifndef PCI_CONF_MODE 286 mode1: 287 #endif 288 outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg); 289 data = inl(PCI_MODE1_DATA_REG); 290 outl(PCI_MODE1_ADDRESS_REG, 0); 291 return data; 292 #endif 293 294 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2) 295 #ifndef PCI_CONF_MODE 296 mode2: 297 #endif 298 outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable); 299 outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward); 300 data = inl(tag.mode2.port | reg); 301 outb(PCI_MODE2_ENABLE_REG, 0); 302 return data; 303 #endif 304 } 305 306 void 307 pci_conf_write(pc, tag, reg, data) 308 pci_chipset_tag_t pc; 309 pcitag_t tag; 310 int reg; 311 pcireg_t data; 312 { 313 314 #ifndef PCI_CONF_MODE 315 switch (pci_mode) { 316 case 1: 317 goto mode1; 318 case 2: 319 goto mode2; 320 default: 321 panic("pci_conf_write: mode not configured"); 322 } 323 #endif 324 325 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1) 326 #ifndef PCI_CONF_MODE 327 mode1: 328 #endif 329 outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg); 330 outl(PCI_MODE1_DATA_REG, data); 331 outl(PCI_MODE1_ADDRESS_REG, 0); 332 return; 333 #endif 334 335 #if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2) 336 #ifndef PCI_CONF_MODE 337 mode2: 338 #endif 339 outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable); 340 outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward); 341 outl(tag.mode2.port | reg, data); 342 outb(PCI_MODE2_ENABLE_REG, 0); 343 #endif 344 } 345 346 int 347 pci_mode_detect() 348 { 349 350 #ifdef PCI_CONF_MODE 351 #if (PCI_CONF_MODE == 1) || (PCI_CONF_MODE == 2) 352 return (pci_mode = PCI_CONF_MODE); 353 #else 354 #error Invalid PCI configuration mode. 355 #endif 356 #else 357 if (pci_mode != -1) 358 return pci_mode; 359 360 #if NBIOS > 0 361 /* 362 * If we have PCI info passed from the BIOS, use the mode given there 363 * for all of this code. If not, pass on through to the previous tests 364 * to try and devine the correct mode. 365 */ 366 if (bios_pciinfo != NULL) { 367 if (bios_pciinfo->pci_chars & 0x2) 368 return (pci_mode = 2); 369 370 if (bios_pciinfo->pci_chars & 0x1) 371 return (pci_mode = 1); 372 373 /* We should never get here, but if we do, fall through... */ 374 } 375 #endif 376 377 /* 378 * We try to divine which configuration mode the host bridge wants. We 379 * try mode 2 first, because our probe for mode 1 is likely to succeed 380 * for mode 2 also. 381 * 382 * This should really be done using the PCI BIOS. If we get here, the 383 * PCI BIOS does not exist, or the boot blocks did not provide the 384 * information. 385 */ 386 outb(PCI_MODE2_ENABLE_REG, 0); 387 outb(PCI_MODE2_FORWARD_REG, 0); 388 if (inb(PCI_MODE2_ENABLE_REG) != 0 || 389 inb(PCI_MODE2_FORWARD_REG) != 0) 390 goto not2; 391 return (pci_mode = 2); 392 393 not2: 394 outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE); 395 if (inl(PCI_MODE1_ADDRESS_REG) != PCI_MODE1_ENABLE) 396 goto not1; 397 outl(PCI_MODE1_ADDRESS_REG, 0); 398 if (inl(PCI_MODE1_ADDRESS_REG) != 0) 399 goto not1; 400 return (pci_mode = 1); 401 402 not1: 403 return (pci_mode = 0); 404 #endif 405 } 406 407 int 408 pci_intr_map(pc, intrtag, pin, line, ihp) 409 pci_chipset_tag_t pc; 410 pcitag_t intrtag; 411 int pin, line; 412 pci_intr_handle_t *ihp; 413 { 414 if (pin == 0) { 415 /* No IRQ used. */ 416 goto bad; 417 } 418 419 if (pin > 4) { 420 printf("pci_intr_map: bad interrupt pin %d\n", pin); 421 goto bad; 422 } 423 424 ihp->line = line; 425 ihp->pin = pin; 426 #if NPCIBIOS > 0 427 pci_intr_header_fixup(pc, intrtag, ihp); 428 line = ihp->line; 429 #endif 430 431 /* 432 * Section 6.2.4, `Miscellaneous Functions', says that 255 means 433 * `unknown' or `no connection' on a PC. We assume that a device with 434 * `no connection' either doesn't have an interrupt (in which case the 435 * pin number should be 0, and would have been noticed above), or 436 * wasn't configured by the BIOS (in which case we punt, since there's 437 * no real way we can know how the interrupt lines are mapped in the 438 * hardware). 439 * 440 * XXX 441 * Since IRQ 0 is only used by the clock, and we can't actually be sure 442 * that the BIOS did its job, we also recognize that as meaning that 443 * the BIOS has not configured the device. 444 */ 445 if (line == 0 || line == 255) { 446 printf("pci_intr_map: no mapping for pin %c\n", '@' + pin); 447 goto bad; 448 } else { 449 if (line >= ICU_LEN) { 450 printf("pci_intr_map: bad interrupt line %d\n", line); 451 goto bad; 452 } 453 if (line == 2) { 454 printf("pci_intr_map: changed line 2 to line 9\n"); 455 line = 9; 456 } 457 } 458 459 return 0; 460 461 bad: 462 ihp->line = -1; 463 return 1; 464 } 465 466 const char * 467 pci_intr_string(pc, ih) 468 pci_chipset_tag_t pc; 469 pci_intr_handle_t ih; 470 { 471 static char irqstr[8]; /* 4 + 2 + NULL + sanity */ 472 473 if (ih.line == 0 || ih.line >= ICU_LEN || ih.line == 2) 474 panic("pci_intr_string: bogus handle 0x%x", ih.line); 475 476 sprintf(irqstr, "irq %d", ih.line); 477 return (irqstr); 478 479 } 480 481 void * 482 pci_intr_establish(pc, ih, level, func, arg, what) 483 pci_chipset_tag_t pc; 484 pci_intr_handle_t ih; 485 int level, (*func) __P((void *)); 486 void *arg; 487 char *what; 488 { 489 void *ret; 490 491 if (ih.line == 0 || ih.line >= ICU_LEN || ih.line == 2) 492 panic("pci_intr_establish: bogus handle 0x%x", ih.line); 493 494 ret = isa_intr_establish(NULL, ih.line, 495 IST_LEVEL, level, func, arg, what); 496 #if NPCIBIOS > 0 497 if (ret) 498 pci_intr_route_link(pc, &ih); 499 #endif 500 return ret; 501 } 502 503 void 504 pci_intr_disestablish(pc, cookie) 505 pci_chipset_tag_t pc; 506 void *cookie; 507 { 508 /* XXX oh, unroute the pci int link? */ 509 return isa_intr_disestablish(NULL, cookie); 510 } 511