1 /* $NetBSD: pci_machdep.c,v 1.22 2000/06/04 19:14:35 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Leo Weppelman. All rights reserved. 5 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. 6 * Copyright (c) 1994 Charles M. Hannum. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following 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 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Charles M. Hannum. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/time.h> 37 #include <sys/systm.h> 38 #include <sys/errno.h> 39 #include <sys/device.h> 40 #include <sys/malloc.h> 41 42 #include <vm/vm.h> 43 #include <vm/vm_kern.h> 44 45 #include <dev/pci/pcivar.h> 46 #include <dev/pci/pcireg.h> 47 48 #include <machine/cpu.h> 49 #include <machine/iomap.h> 50 #include <machine/mfp.h> 51 #include <machine/bswap.h> 52 #include <machine/bus.h> 53 54 #include <atari/atari/device.h> 55 #include <atari/pci/pci_vga.h> 56 57 /* 58 * Sizes of pci memory and I/O area. 59 */ 60 #define PCI_MEM_END 0x10000000 /* 256 MByte */ 61 #define PCI_IO_END 0x10000000 /* 256 MByte */ 62 63 /* 64 * We preserve some space at the begin of the pci area for 32BIT_1M 65 * devices and standard vga. 66 */ 67 #define PCI_MEM_START 0x00100000 /* 1 MByte */ 68 #define PCI_IO_START 0x00004000 /* 16 kByte (some PCI cards allow only 69 I/O adresses up to 0xffff) */ 70 71 /* 72 * PCI memory and IO should be aligned acording to this masks 73 */ 74 #define PCI_MACHDEP_IO_ALIGN_MASK 0xffffff00 75 #define PCI_MACHDEP_MEM_ALIGN_MASK 0xfffff000 76 77 /* 78 * Convert a PCI 'device' number to a slot number. 79 */ 80 #define DEV2SLOT(dev) (3 - dev) 81 82 /* 83 * Struct to hold the memory and I/O datas of the pci devices 84 */ 85 struct pci_memreg { 86 LIST_ENTRY(pci_memreg) link; 87 int dev; 88 pcitag_t tag; 89 pcireg_t reg, address, mask; 90 u_int32_t size; 91 u_int32_t csr; 92 }; 93 94 typedef LIST_HEAD(pci_memreg_head, pci_memreg) PCI_MEMREG; 95 96 int pcibusprint __P((void *auxp, const char *)); 97 int pcibusmatch __P((struct device *, struct cfdata *, void *)); 98 void pcibusattach __P((struct device *, struct device *, void *)); 99 100 static void enable_pci_devices __P((void)); 101 static void insert_into_list __P((PCI_MEMREG *head, struct pci_memreg *elem)); 102 static int overlap_pci_areas __P((struct pci_memreg *p, 103 struct pci_memreg *self, u_int addr, u_int size, u_int what)); 104 static int pci_config_offset __P((pcitag_t)); 105 106 struct cfattach pcibus_ca = { 107 sizeof(struct device), pcibusmatch, pcibusattach 108 }; 109 110 int 111 pcibusmatch(pdp, cfp, auxp) 112 struct device *pdp; 113 struct cfdata *cfp; 114 void *auxp; 115 { 116 if(atari_realconfig == 0) 117 return (0); 118 if (strcmp((char *)auxp, "pcibus") || cfp->cf_unit != 0) 119 return(0); 120 return(machineid & ATARI_HADES ? 1 : 0); 121 } 122 123 void 124 pcibusattach(pdp, dp, auxp) 125 struct device *pdp, *dp; 126 void *auxp; 127 { 128 struct pcibus_attach_args pba; 129 130 enable_pci_devices(); 131 132 pba.pba_busname = "pci"; 133 pba.pba_pc = NULL; 134 pba.pba_bus = 0; 135 pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; 136 pba.pba_dmat = BUS_PCI_DMA_TAG; 137 pba.pba_iot = leb_alloc_bus_space_tag(NULL); 138 pba.pba_memt = leb_alloc_bus_space_tag(NULL); 139 if ((pba.pba_iot == NULL) || (pba.pba_memt == NULL)) { 140 printf("leb_alloc_bus_space_tag failed!\n"); 141 return; 142 } 143 pba.pba_iot->base = PCI_IO_PHYS; 144 pba.pba_memt->base = PCI_MEM_PHYS; 145 146 MFP2->mf_aer &= ~(0x27); /* PCI interrupts: HIGH -> LOW */ 147 148 printf("\n"); 149 150 config_found(dp, &pba, pcibusprint); 151 } 152 153 int 154 pcibusprint(auxp, name) 155 void *auxp; 156 const char *name; 157 { 158 if(name == NULL) 159 return(UNCONF); 160 return(QUIET); 161 } 162 163 void 164 pci_attach_hook(parent, self, pba) 165 struct device *parent, *self; 166 struct pcibus_attach_args *pba; 167 { 168 } 169 170 /* 171 * Initialize the PCI-bus. The Atari-BIOS does not do this, so.... 172 * We only disable all devices here. Memory and I/O enabling is done 173 * later at pcibusattach. 174 */ 175 void 176 init_pci_bus() 177 { 178 pci_chipset_tag_t pc = NULL; /* XXX */ 179 pcitag_t tag; 180 pcireg_t csr; 181 int device, id, maxndevs; 182 183 tag = 0; 184 id = 0; 185 186 maxndevs = pci_bus_maxdevs(pc, 0); 187 188 for (device = 0; device < maxndevs; device++) { 189 190 tag = pci_make_tag(pc, 0, device, 0); 191 id = pci_conf_read(pc, tag, PCI_ID_REG); 192 if (id == 0 || id == 0xffffffff) 193 continue; 194 195 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 196 csr &= ~(PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE); 197 csr &= ~PCI_COMMAND_MASTER_ENABLE; 198 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); 199 } 200 201 /* 202 * Scan the bus for a VGA-card that we support. If we find 203 * one, try to initialize it to a 'standard' text mode (80x25). 204 */ 205 check_for_vga(); 206 } 207 208 /* 209 * insert a new element in an existing list that the ID's (size in struct 210 * pci_memreg) are sorted. 211 */ 212 static void 213 insert_into_list(head, elem) 214 PCI_MEMREG *head; 215 struct pci_memreg *elem; 216 { 217 struct pci_memreg *p, *q; 218 219 p = LIST_FIRST(head); 220 q = NULL; 221 222 for (; p != NULL && p->size < elem->size; q = p, p = LIST_NEXT(p, link)); 223 224 if (q == NULL) { 225 LIST_INSERT_HEAD(head, elem, link); 226 } else { 227 LIST_INSERT_AFTER(q, elem, link); 228 } 229 } 230 231 /* 232 * Test if a new selected area overlaps with an already (probably preselected) 233 * pci area. 234 */ 235 static int 236 overlap_pci_areas(p, self, addr, size, what) 237 struct pci_memreg *p, *self; 238 u_int addr, size, what; 239 { 240 struct pci_memreg *q; 241 242 if (p == NULL) 243 return 0; 244 245 q = p; 246 while (q != NULL) { 247 if ((q != self) && (q->csr & what)) { 248 if ((addr >= q->address) && (addr < (q->address + q->size))) { 249 #ifdef DEBUG_PCI_MACHDEP 250 printf("\noverlap area dev %d reg 0x%02x with dev %d reg 0x%02x", 251 self->dev, self->reg, q->dev, q->reg); 252 #endif 253 return 1; 254 } 255 if ((q->address >= addr) && (q->address < (addr + size))) { 256 #ifdef DEBUG_PCI_MACHDEP 257 printf("\noverlap area dev %d reg 0x%02x with dev %d reg 0x%02x", 258 self->dev, self->reg, q->dev, q->reg); 259 #endif 260 return 1; 261 } 262 } 263 q = LIST_NEXT(q, link); 264 } 265 return 0; 266 } 267 268 /* 269 * Enable memory and I/O on pci devices. Care about already enabled devices 270 * (probabaly by the console driver). 271 * 272 * The idea behind the following code is: 273 * We build a by sizes sorted list of the requirements of the different 274 * pci devices. After that we choose the start addresses of that areas 275 * in such a way that they are placed as closed as possible together. 276 */ 277 static void 278 enable_pci_devices() 279 { 280 PCI_MEMREG memlist; 281 PCI_MEMREG iolist; 282 struct pci_memreg *p, *q; 283 int dev, reg, id, class; 284 pcitag_t tag; 285 pcireg_t csr, address, mask; 286 pci_chipset_tag_t pc; 287 int sizecnt, membase_1m; 288 289 pc = 0; 290 csr = 0; 291 tag = 0; 292 293 LIST_INIT(&memlist); 294 LIST_INIT(&iolist); 295 296 /* 297 * first step: go through all devices and gather memory and I/O 298 * sizes 299 */ 300 for (dev = 0; dev < pci_bus_maxdevs(pc,0); dev++) { 301 302 tag = pci_make_tag(pc, 0, dev, 0); 303 id = pci_conf_read(pc, tag, PCI_ID_REG); 304 if (id == 0 || id == 0xffffffff) 305 continue; 306 307 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 308 309 /* 310 * special case: if a display card is found and memory is enabled 311 * preserve 128k at 0xa0000 as vga memory. 312 * XXX: if a display card is found without being enabled, leave 313 * it alone! You will usually only create conflicts by enabeling 314 * it. 315 */ 316 class = pci_conf_read(pc, tag, PCI_CLASS_REG); 317 switch (PCI_CLASS(class)) { 318 case PCI_CLASS_PREHISTORIC: 319 case PCI_CLASS_DISPLAY: 320 if (csr & (PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)) { 321 p = (struct pci_memreg *)malloc(sizeof(struct pci_memreg), 322 M_TEMP, M_WAITOK); 323 memset(p, '\0', sizeof(struct pci_memreg)); 324 p->dev = dev; 325 p->csr = csr; 326 p->tag = tag; 327 p->reg = 0; /* there is no register about this */ 328 p->size = 0x20000; /* 128kByte */ 329 p->mask = 0xfffe0000; 330 p->address = 0xa0000; 331 332 insert_into_list(&memlist, p); 333 } 334 else continue; 335 } 336 337 for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) { 338 339 address = pci_conf_read(pc, tag, reg); 340 pci_conf_write(pc, tag, reg, 0xffffffff); 341 mask = pci_conf_read(pc, tag, reg); 342 pci_conf_write(pc, tag, reg, address); 343 if (mask == 0) 344 continue; /* Register unused */ 345 346 p = (struct pci_memreg *)malloc(sizeof(struct pci_memreg), 347 M_TEMP, M_WAITOK); 348 memset(p, '\0', sizeof(struct pci_memreg)); 349 p->dev = dev; 350 p->csr = csr; 351 p->tag = tag; 352 p->reg = reg; 353 p->mask = mask; 354 p->address = 0; 355 356 if (mask & PCI_MAPREG_TYPE_IO) { 357 p->size = PCI_MAPREG_IO_SIZE(mask); 358 359 /* 360 * Align IO if necessary 361 */ 362 if (p->size < PCI_MAPREG_IO_SIZE(PCI_MACHDEP_IO_ALIGN_MASK)) { 363 p->mask = PCI_MACHDEP_IO_ALIGN_MASK; 364 p->size = PCI_MAPREG_IO_SIZE(p->mask); 365 } 366 367 /* 368 * if I/O is already enabled (probably by the console driver) 369 * save the address in order to take care about it later. 370 */ 371 if (csr & PCI_COMMAND_IO_ENABLE) 372 p->address = address; 373 374 insert_into_list(&iolist, p); 375 } else { 376 p->size = PCI_MAPREG_MEM_SIZE(mask); 377 378 /* 379 * Align memory if necessary 380 */ 381 if (p->size < PCI_MAPREG_IO_SIZE(PCI_MACHDEP_MEM_ALIGN_MASK)) { 382 p->mask = PCI_MACHDEP_MEM_ALIGN_MASK; 383 p->size = PCI_MAPREG_MEM_SIZE(p->mask); 384 } 385 386 /* 387 * if memory is already enabled (probably by the console driver) 388 * save the address in order to take care about it later. 389 */ 390 if (csr & PCI_COMMAND_MEM_ENABLE) 391 p->address = address; 392 393 insert_into_list(&memlist, p); 394 395 if (PCI_MAPREG_MEM_TYPE(mask) == PCI_MAPREG_MEM_TYPE_64BIT) 396 reg++; 397 } 398 } 399 400 /* 401 * Both interrupt pin & line are set to the device (== slot) 402 * number. This makes sense on the atari because the 403 * individual slots are hard-wired to a specific MFP-pin. 404 */ 405 csr = (DEV2SLOT(dev) << PCI_INTERRUPT_PIN_SHIFT); 406 csr |= (DEV2SLOT(dev) << PCI_INTERRUPT_LINE_SHIFT); 407 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, csr); 408 } 409 410 /* 411 * second step: calculate the memory and I/O adresses beginning from 412 * PCI_MEM_START and PCI_IO_START. Care about already mapped areas. 413 * 414 * beginn with memory list 415 */ 416 417 address = PCI_MEM_START; 418 sizecnt = 0; 419 membase_1m = 0; 420 p = LIST_FIRST(&memlist); 421 while (p != NULL) { 422 if (!(p->csr & PCI_COMMAND_MEM_ENABLE)) { 423 if (PCI_MAPREG_MEM_TYPE(p->mask) == PCI_MAPREG_MEM_TYPE_32BIT_1M) { 424 if (p->size > membase_1m) 425 membase_1m = p->size; 426 do { 427 p->address = membase_1m; 428 membase_1m += p->size; 429 } while (overlap_pci_areas(LIST_FIRST(&memlist), p, p->address, 430 p->size, PCI_COMMAND_MEM_ENABLE)); 431 if (membase_1m > 0x00100000) { 432 /* 433 * Should we panic here? 434 */ 435 printf("\npcibus0: dev %d reg %d: memory not configured", 436 p->dev, p->reg); 437 p->reg = 0; 438 } 439 } else { 440 441 if (sizecnt && (p->size > sizecnt)) 442 sizecnt = ((p->size + sizecnt) & p->mask) & 443 PCI_MAPREG_MEM_ADDR_MASK; 444 if (sizecnt > address) { 445 address = sizecnt; 446 sizecnt = 0; 447 } 448 449 do { 450 p->address = address + sizecnt; 451 sizecnt += p->size; 452 } while (overlap_pci_areas(LIST_FIRST(&memlist), p, p->address, 453 p->size, PCI_COMMAND_MEM_ENABLE)); 454 455 if ((address + sizecnt) > PCI_MEM_END) { 456 /* 457 * Should we panic here? 458 */ 459 printf("\npcibus0: dev %d reg %d: memory not configured", 460 p->dev, p->reg); 461 p->reg = 0; 462 } 463 } 464 if (p->reg > 0) { 465 pci_conf_write(pc, p->tag, p->reg, p->address); 466 csr = pci_conf_read(pc, p->tag, PCI_COMMAND_STATUS_REG); 467 csr |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; 468 pci_conf_write(pc, p->tag, PCI_COMMAND_STATUS_REG, csr); 469 p->csr = csr; 470 } 471 } 472 p = LIST_NEXT(p, link); 473 } 474 475 /* 476 * now the I/O list 477 */ 478 479 address = PCI_IO_START; 480 sizecnt = 0; 481 p = LIST_FIRST(&iolist); 482 while (p != NULL) { 483 if (!(p->csr & PCI_COMMAND_IO_ENABLE)) { 484 485 if (sizecnt && (p->size > sizecnt)) 486 sizecnt = ((p->size + sizecnt) & p->mask) & 487 PCI_MAPREG_IO_ADDR_MASK; 488 if (sizecnt > address) { 489 address = sizecnt; 490 sizecnt = 0; 491 } 492 493 do { 494 p->address = address + sizecnt; 495 sizecnt += p->size; 496 } while (overlap_pci_areas(LIST_FIRST(&iolist), p, p->address, 497 p->size, PCI_COMMAND_IO_ENABLE)); 498 499 if ((address + sizecnt) > PCI_IO_END) { 500 /* 501 * Should we panic here? 502 */ 503 printf("\npcibus0: dev %d reg %d: io not configured", 504 p->dev, p->reg); 505 } else { 506 pci_conf_write(pc, p->tag, p->reg, p->address); 507 csr = pci_conf_read(pc, p->tag, PCI_COMMAND_STATUS_REG); 508 csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE; 509 pci_conf_write(pc, p->tag, PCI_COMMAND_STATUS_REG, csr); 510 p->csr = csr; 511 } 512 } 513 p = LIST_NEXT(p, link); 514 } 515 516 #ifdef DEBUG_PCI_MACHDEP 517 printf("\nI/O List:\n"); 518 p = LIST_FIRST(&iolist); 519 520 while (p != NULL) { 521 printf("\ndev: %d, reg: 0x%02x, size: 0x%08x, addr: 0x%08x", p->dev, 522 p->reg, p->size, p->address); 523 p = LIST_NEXT(p, link); 524 } 525 printf("\nMemlist:"); 526 p = LIST_FIRST(&memlist); 527 528 while (p != NULL) { 529 printf("\ndev: %d, reg: 0x%02x, size: 0x%08x, addr: 0x%08x", p->dev, 530 p->reg, p->size, p->address); 531 p = LIST_NEXT(p, link); 532 } 533 #endif 534 535 /* 536 * Free the lists 537 */ 538 p = LIST_FIRST(&iolist); 539 while (p != NULL) { 540 q = p; 541 LIST_REMOVE(q, link); 542 free(p, M_WAITOK); 543 p = LIST_FIRST(&iolist); 544 } 545 p = LIST_FIRST(&memlist); 546 while (p != NULL) { 547 q = p; 548 LIST_REMOVE(q, link); 549 free(p, M_WAITOK); 550 p = LIST_FIRST(&memlist); 551 } 552 } 553 554 /* 555 * Atari_init.c maps the config areas NBPG bytes apart.... 556 */ 557 static int pci_config_offset(tag) 558 pcitag_t tag; 559 { 560 int device; 561 562 device = (tag >> 11) & 0x1f; 563 return(device * NBPG); 564 } 565 566 int 567 pci_bus_maxdevs(pc, busno) 568 pci_chipset_tag_t pc; 569 int busno; 570 { 571 return (4); 572 } 573 574 pcitag_t 575 pci_make_tag(pc, bus, device, function) 576 pci_chipset_tag_t pc; 577 int bus, device, function; 578 { 579 return ((bus << 16) | (device << 11) | (function << 8)); 580 } 581 582 pcireg_t 583 pci_conf_read(pc, tag, reg) 584 pci_chipset_tag_t pc; 585 pcitag_t tag; 586 int reg; 587 { 588 u_long data; 589 590 data = *(u_long *)(pci_conf_addr + pci_config_offset(tag) + reg); 591 return (bswap32(data)); 592 } 593 594 void 595 pci_conf_write(pc, tag, reg, data) 596 pci_chipset_tag_t pc; 597 pcitag_t tag; 598 int reg; 599 pcireg_t data; 600 { 601 *((u_long *)(pci_conf_addr + pci_config_offset(tag) + reg)) 602 = bswap32(data); 603 } 604 605 int 606 pci_intr_map(pc, intrtag, pin, line, ihp) 607 pci_chipset_tag_t pc; 608 pcitag_t intrtag; 609 int pin, line; 610 pci_intr_handle_t *ihp; 611 { 612 /* 613 * According to the PCI-spec, 255 means `unknown' or `no connection'. 614 * Interpret this as 'no interrupt assigned'. 615 */ 616 if (line == 255) { 617 *ihp = -1; 618 return 1; 619 } 620 621 /* 622 * Values are pretty useless because the on the Hades all interrupt 623 * lines for a card are tied together and hardwired to the TT-MFP 624 * I/O port. 625 */ 626 *ihp = line; 627 return 0; 628 } 629 630 const char * 631 pci_intr_string(pc, ih) 632 pci_chipset_tag_t pc; 633 pci_intr_handle_t ih; 634 { 635 static char irqstr[8]; /* 4 + 2 + NULL + sanity */ 636 637 if (ih == -1) 638 panic("pci_intr_string: bogus handle 0x%x\n", ih); 639 640 sprintf(irqstr, "irq %d", ih); 641 return (irqstr); 642 643 } 644 645 const struct evcnt * 646 pci_intr_evcnt(pc, ih) 647 pci_chipset_tag_t pc; 648 pci_intr_handle_t ih; 649 { 650 651 /* XXX for now, no evcnt parent reported */ 652 return NULL; 653 } 654 655 /* 656 * The interrupt stuff is rather ugly. On the Hades, all interrupt lines 657 * for a slot are wired together and connected to IO 0,1,2 or 5 (slots: 658 * (0-3) on the TT-MFP. The Pci-config code initializes the irq. number 659 * to the slot position. 660 */ 661 static pci_intr_info_t iinfo[4] = { { -1 }, { -1 }, { -1 }, { -1 } }; 662 663 static int iifun __P((int, int)); 664 665 static int 666 iifun(slot, sr) 667 int slot; 668 int sr; 669 { 670 pci_intr_info_t *iinfo_p; 671 int s; 672 673 iinfo_p = &iinfo[slot]; 674 675 /* 676 * Disable the interrupts 677 */ 678 MFP2->mf_imrb &= ~iinfo_p->imask; 679 680 if ((sr & PSL_IPL) >= (iinfo_p->ipl & PSL_IPL)) { 681 /* 682 * We're running at a too high priority now. 683 */ 684 add_sicallback((si_farg)iifun, (void*)slot, 0); 685 } 686 else { 687 s = splx(iinfo_p->ipl); 688 (void) (iinfo_p->ifunc)(iinfo_p->iarg); 689 splx(s); 690 691 /* 692 * Re-enable interrupts after handling 693 */ 694 MFP2->mf_imrb |= iinfo_p->imask; 695 } 696 return 1; 697 } 698 699 void * 700 pci_intr_establish(pc, ih, level, ih_fun, ih_arg) 701 pci_chipset_tag_t pc; 702 pci_intr_handle_t ih; 703 int level; 704 int (*ih_fun) __P((void *)); 705 void *ih_arg; 706 { 707 pci_intr_info_t *iinfo_p; 708 struct intrhand *ihand; 709 int slot; 710 711 slot = ih; 712 iinfo_p = &iinfo[slot]; 713 714 if (iinfo_p->ipl > 0) 715 panic("pci_intr_establish: interrupt was already established\n"); 716 717 ihand = intr_establish((slot == 3) ? 23 : 16 + slot, USER_VEC, 0, 718 (hw_ifun_t)iifun, (void *)slot); 719 if (ihand != NULL) { 720 iinfo_p->ipl = level; 721 iinfo_p->imask = (slot == 3) ? 0x80 : (0x01 << slot); 722 iinfo_p->ifunc = ih_fun; 723 iinfo_p->iarg = ih_arg; 724 iinfo_p->ihand = ihand; 725 726 /* 727 * Enable (unmask) the interrupt 728 */ 729 MFP2->mf_imrb |= iinfo_p->imask; 730 MFP2->mf_ierb |= iinfo_p->imask; 731 return(iinfo_p); 732 } 733 return NULL; 734 } 735 736 void 737 pci_intr_disestablish(pc, cookie) 738 pci_chipset_tag_t pc; 739 void *cookie; 740 { 741 pci_intr_info_t *iinfo_p = (pci_intr_info_t *)cookie; 742 743 if (iinfo->ipl < 0) 744 panic("pci_intr_disestablish: interrupt was not established\n"); 745 746 MFP2->mf_imrb &= ~iinfo->imask; 747 MFP2->mf_ierb &= ~iinfo->imask; 748 (void) intr_disestablish(iinfo_p->ihand); 749 iinfo_p->ipl = -1; 750 } 751