1 /* $NetBSD: pci_machdep.c,v 1.21 2003/07/15 02:43:33 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 5 * Copyright (c) 1994 Charles M. Hannum. 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, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Charles M. Hannum. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Machine-specific functions for PCI autoconfiguration. 35 * 36 * On PCs, there are two methods of generating PCI configuration cycles. 37 * We try to detect the appropriate mechanism for this machine and set 38 * up a few function pointers to access the correct method directly. 39 * 40 * The configuration method can be hard-coded in the config file by 41 * using `options PCI_CONF_MODE=N', where `N' is the configuration mode 42 * as defined section 3.6.4.1, `Generating Configuration Cycles'. 43 */ 44 45 #include <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.21 2003/07/15 02:43:33 lukem Exp $"); 47 48 #include <sys/types.h> 49 #include <sys/param.h> 50 #include <sys/time.h> 51 #include <sys/systm.h> 52 #include <sys/errno.h> 53 #include <sys/device.h> 54 55 #include <uvm/uvm_extern.h> 56 57 #define _MACPPC_BUS_DMA_PRIVATE 58 #include <machine/bus.h> 59 60 #include <machine/bus.h> 61 #include <machine/pio.h> 62 #include <machine/intr.h> 63 64 #include <dev/pci/pcivar.h> 65 #include <dev/pci/pcireg.h> 66 67 #include <dev/ofw/openfirm.h> 68 #include <dev/ofw/ofw_pci.h> 69 70 static void fixpci __P((int, pci_chipset_tag_t)); 71 static int find_node_intr __P((int, u_int32_t *, u_int32_t *)); 72 73 /* 74 * PCI doesn't have any special needs; just use the generic versions 75 * of these functions. 76 */ 77 struct macppc_bus_dma_tag pci_bus_dma_tag = { 78 0, /* _bounce_thresh */ 79 _bus_dmamap_create, 80 _bus_dmamap_destroy, 81 _bus_dmamap_load, 82 _bus_dmamap_load_mbuf, 83 _bus_dmamap_load_uio, 84 _bus_dmamap_load_raw, 85 _bus_dmamap_unload, 86 NULL, /* _dmamap_sync */ 87 _bus_dmamem_alloc, 88 _bus_dmamem_free, 89 _bus_dmamem_map, 90 _bus_dmamem_unmap, 91 _bus_dmamem_mmap, 92 }; 93 94 void 95 pci_attach_hook(parent, self, pba) 96 struct device *parent, *self; 97 struct pcibus_attach_args *pba; 98 { 99 pci_chipset_tag_t pc = pba->pba_pc; 100 int bus = pba->pba_bus; 101 int node, nn, sz; 102 int32_t busrange[2]; 103 104 for (node = pc->node; node; node = nn) { 105 sz = OF_getprop(node, "bus-range", busrange, 8); 106 if (sz == 8 && busrange[0] == bus) { 107 fixpci(node, pc); 108 return; 109 } 110 if ((nn = OF_child(node)) != 0) 111 continue; 112 while ((nn = OF_peer(node)) == 0) { 113 node = OF_parent(node); 114 if (node == pc->node) 115 return; /* not found */ 116 } 117 } 118 } 119 120 int 121 pci_bus_maxdevs(pc, busno) 122 pci_chipset_tag_t pc; 123 int busno; 124 { 125 126 /* 127 * Bus number is irrelevant. Configuration Mechanism 1 is in 128 * use, can have devices 0-32 (i.e. the `normal' range). 129 */ 130 return 32; 131 } 132 133 pcitag_t 134 pci_make_tag(pc, bus, device, function) 135 pci_chipset_tag_t pc; 136 int bus, device, function; 137 { 138 pcitag_t tag; 139 140 if (bus >= 256 || device >= 32 || function >= 8) 141 panic("pci_make_tag: bad request"); 142 143 /* XXX magic number */ 144 tag = 0x80000000 | (bus << 16) | (device << 11) | (function << 8); 145 146 return tag; 147 } 148 149 void 150 pci_decompose_tag(pc, tag, bp, dp, fp) 151 pci_chipset_tag_t pc; 152 pcitag_t tag; 153 int *bp, *dp, *fp; 154 { 155 156 if (bp != NULL) 157 *bp = (tag >> 16) & 0xff; 158 if (dp != NULL) 159 *dp = (tag >> 11) & 0x1f; 160 if (fp != NULL) 161 *fp = (tag >> 8) & 0x07; 162 } 163 164 pcireg_t 165 pci_conf_read(pc, tag, reg) 166 pci_chipset_tag_t pc; 167 pcitag_t tag; 168 int reg; 169 { 170 171 return (*pc->conf_read)(pc, tag, reg); 172 } 173 174 void 175 pci_conf_write(pc, tag, reg, data) 176 pci_chipset_tag_t pc; 177 pcitag_t tag; 178 int reg; 179 pcireg_t data; 180 { 181 182 (*pc->conf_write)(pc, tag, reg, data); 183 } 184 185 int 186 pci_intr_map(pa, ihp) 187 struct pci_attach_args *pa; 188 pci_intr_handle_t *ihp; 189 { 190 int pin = pa->pa_intrpin; 191 int line = pa->pa_intrline; 192 193 if (pin == 0) { 194 /* No IRQ used. */ 195 goto bad; 196 } 197 198 if (pin > 4) { 199 printf("pci_intr_map: bad interrupt pin %d\n", pin); 200 goto bad; 201 } 202 203 /* 204 * Section 6.2.4, `Miscellaneous Functions', says that 255 means 205 * `unknown' or `no connection' on a PC. We assume that a device with 206 * `no connection' either doesn't have an interrupt (in which case the 207 * pin number should be 0, and would have been noticed above), or 208 * wasn't configured by the BIOS (in which case we punt, since there's 209 * no real way we can know how the interrupt lines are mapped in the 210 * hardware). 211 * 212 * XXX 213 * Since IRQ 0 is only used by the clock, and we can't actually be sure 214 * that the BIOS did its job, we also recognize that as meaning that 215 * the BIOS has not configured the device. 216 */ 217 if (line == 0 || line == 255) { 218 printf("pci_intr_map: no mapping for pin %c\n", '@' + pin); 219 goto bad; 220 } else { 221 if (line >= ICU_LEN) { 222 printf("pci_intr_map: bad interrupt line %d\n", line); 223 goto bad; 224 } 225 } 226 227 *ihp = line; 228 return 0; 229 230 bad: 231 *ihp = -1; 232 return 1; 233 } 234 235 const char * 236 pci_intr_string(pc, ih) 237 pci_chipset_tag_t pc; 238 pci_intr_handle_t ih; 239 { 240 static char irqstr[8]; /* 4 + 2 + NULL + sanity */ 241 242 if (ih == 0 || ih >= ICU_LEN) 243 panic("pci_intr_string: bogus handle 0x%x", ih); 244 245 sprintf(irqstr, "irq %d", ih); 246 return (irqstr); 247 248 } 249 250 const struct evcnt * 251 pci_intr_evcnt(pc, ih) 252 pci_chipset_tag_t pc; 253 pci_intr_handle_t ih; 254 { 255 256 /* XXX for now, no evcnt parent reported */ 257 return NULL; 258 } 259 260 void * 261 pci_intr_establish(pc, ih, level, func, arg) 262 pci_chipset_tag_t pc; 263 pci_intr_handle_t ih; 264 int level, (*func) __P((void *)); 265 void *arg; 266 { 267 268 if (ih == 0 || ih >= ICU_LEN) 269 panic("pci_intr_establish: bogus handle 0x%x", ih); 270 271 return intr_establish(ih, IST_LEVEL, level, func, arg); 272 } 273 274 void 275 pci_intr_disestablish(pc, cookie) 276 pci_chipset_tag_t pc; 277 void *cookie; 278 { 279 280 intr_disestablish(cookie); 281 } 282 283 #define pcibus(x) \ 284 (((x) & OFW_PCI_PHYS_HI_BUSMASK) >> OFW_PCI_PHYS_HI_BUSSHIFT) 285 #define pcidev(x) \ 286 (((x) & OFW_PCI_PHYS_HI_DEVICEMASK) >> OFW_PCI_PHYS_HI_DEVICESHIFT) 287 #define pcifunc(x) \ 288 (((x) & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> OFW_PCI_PHYS_HI_FUNCTIONSHIFT) 289 290 void 291 fixpci(parent, pc) 292 int parent; 293 pci_chipset_tag_t pc; 294 { 295 int node; 296 pcitag_t tag; 297 pcireg_t csr, intr; 298 int len, i; 299 int32_t irqs[4]; 300 struct { 301 u_int32_t phys_hi, phys_mid, phys_lo; 302 u_int32_t size_hi, size_lo; 303 } addr[8]; 304 305 for (node = OF_child(parent); node; node = OF_peer(node)) { 306 len = OF_getprop(node, "assigned-addresses", addr, 307 sizeof(addr)); 308 if (len < (int)sizeof(addr[0])) 309 continue; 310 311 tag = pci_make_tag(pc, pcibus(addr[0].phys_hi), 312 pcidev(addr[0].phys_hi), 313 pcifunc(addr[0].phys_hi)); 314 315 /* 316 * Make sure the IO and MEM enable bits are set in the CSR. 317 */ 318 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 319 csr &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE); 320 321 for (i = 0; i < len / sizeof(addr[0]); i++) { 322 switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) { 323 case OFW_PCI_PHYS_HI_SPACE_IO: 324 csr |= PCI_COMMAND_IO_ENABLE; 325 break; 326 327 case OFW_PCI_PHYS_HI_SPACE_MEM32: 328 case OFW_PCI_PHYS_HI_SPACE_MEM64: 329 csr |= PCI_COMMAND_MEM_ENABLE; 330 break; 331 } 332 } 333 334 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); 335 336 /* 337 * Make sure the line register is programmed with the 338 * interrupt mapping. 339 */ 340 if (find_node_intr(node, &addr[0].phys_hi, irqs) == -1) 341 continue; 342 343 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 344 intr &= ~PCI_INTERRUPT_LINE_MASK; 345 intr |= irqs[0] & PCI_INTERRUPT_LINE_MASK; 346 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr); 347 } 348 } 349 350 /* 351 * Find PCI IRQ of the node from OF tree. 352 */ 353 int 354 find_node_intr(node, addr, intr) 355 int node; 356 u_int32_t *addr, *intr; 357 { 358 int parent, len, mlen, iparent; 359 int match, i; 360 u_int32_t map[160], *mp; 361 u_int32_t imask[8], maskedaddr[8]; 362 u_int32_t icells; 363 char name[32]; 364 365 len = OF_getprop(node, "AAPL,interrupts", intr, 4) ; 366 if (len == 4) 367 return len; 368 369 parent = OF_parent(node); 370 len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); 371 mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask)); 372 373 if (len == -1 || mlen == -1) 374 goto nomap; 375 376 #ifdef DIAGNOSTIC 377 if (mlen == sizeof(imask)) { 378 printf("interrupt-map too long\n"); 379 return -1; 380 } 381 #endif 382 383 /* mask addr by "interrupt-map-mask" */ 384 memcpy(maskedaddr, addr, mlen); 385 for (i = 0; i < mlen / 4; i++) 386 maskedaddr[i] &= imask[i]; 387 388 mp = map; 389 while (len > mlen) { 390 match = memcmp(maskedaddr, mp, mlen); 391 mp += mlen / 4; 392 len -= mlen; 393 394 /* 395 * We must read "#interrupt-cells" for each time because 396 * interrupt-parent may be different. 397 */ 398 iparent = *mp++; 399 len -= 4; 400 if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4) 401 goto nomap; 402 403 /* Found. */ 404 if (match == 0) { 405 memcpy(intr, mp, icells * 4); 406 return icells * 4; 407 } 408 409 mp += icells; 410 len -= icells * 4; 411 } 412 413 nomap: 414 /* 415 * If the node has no interrupt property and the parent is a 416 * pci-bridge, use parent's interrupt. This occurs on a PCI 417 * slot. (e.g. AHA-3940) 418 */ 419 memset(name, 0, sizeof(name)); 420 OF_getprop(parent, "name", name, sizeof(name)); 421 if (strcmp(name, "pci-bridge") == 0) { 422 len = OF_getprop(parent, "AAPL,interrupts", intr, 4) ; 423 if (len == 4) 424 return len; 425 /* 426 * XXX I don't know what is the correct local address. 427 * XXX Use the first entry for now. 428 */ 429 len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); 430 if (len >= 36) { 431 addr = &map[5]; 432 return find_node_intr(parent, addr, intr); 433 } 434 } 435 436 /* XXX This may be wrong... */ 437 len = OF_getprop(node, "interrupts", intr, 4) ; 438 if (len == 4) 439 return len; 440 441 return -1; 442 } 443