Home | History | Annotate | Line # | Download | only in pci
pci_machdep.c revision 1.14
      1 /*	$NetBSD: pci_machdep.c,v 1.14 1998/12/20 14:24:52 thomas 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/bus.h>
     52 
     53 #include <atari/atari/device.h>
     54 
     55 /*
     56  * Sizes of pci memory and I/O area.
     57  */
     58 #define PCI_MEM_END     0x10000000      /* 256 MByte */
     59 #define PCI_IO_END      0x10000000      /* 256 MByte */
     60 
     61 /*
     62  * We preserve some space at the begin of the pci area for 32BIT_1M
     63  * devices and standard vga.
     64  */
     65 #define PCI_MEM_START   0x00100000      /*   1 MByte */
     66 #define PCI_IO_START    0x00010000      /*  64 kByte */
     67 
     68 /*
     69  * Struct to hold the memory and I/O datas of the pci devices
     70  */
     71 struct pci_memreg {
     72     LIST_ENTRY(pci_memreg) link;
     73     int dev;
     74     pcitag_t tag;
     75     pcireg_t reg, address, mask;
     76     u_int32_t size;
     77     u_int32_t csr;
     78 };
     79 
     80 typedef LIST_HEAD(pci_memreg_head, pci_memreg) PCI_MEMREG;
     81 
     82 int	pcibusprint __P((void *auxp, const char *));
     83 int	pcibusmatch __P((struct device *, struct cfdata *, void *));
     84 void	pcibusattach __P((struct device *, struct device *, void *));
     85 
     86 static void enable_pci_devices __P((void));
     87 static void insert_into_list __P((PCI_MEMREG *head, struct pci_memreg *elem));
     88 static int overlap_pci_areas __P((struct pci_memreg *p,
     89 	struct pci_memreg *self, u_int addr, u_int size, u_int what));
     90 static int pci_config_offset __P((pcitag_t));
     91 
     92 struct cfattach pcibus_ca = {
     93 	sizeof(struct device), pcibusmatch, pcibusattach
     94 };
     95 
     96 int
     97 pcibusmatch(pdp, cfp, auxp)
     98 struct device	*pdp;
     99 struct cfdata	*cfp;
    100 void		*auxp;
    101 {
    102 	if(atari_realconfig == 0)
    103 		return (0);
    104 	if (strcmp((char *)auxp, "pcibus") || cfp->cf_unit != 0)
    105 		return(0);
    106 	return(machineid & ATARI_HADES ? 1 : 0);
    107 }
    108 
    109 void
    110 pcibusattach(pdp, dp, auxp)
    111 struct device	*pdp, *dp;
    112 void		*auxp;
    113 {
    114 	struct pcibus_attach_args	pba;
    115 	bus_space_tag_t			leb_alloc_bus_space_tag __P((void));
    116 
    117 
    118 	enable_pci_devices();
    119 
    120 	pba.pba_busname = "pci";
    121 	pba.pba_pc      = NULL;
    122 	pba.pba_bus     = 0;
    123 	pba.pba_flags	= PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
    124 	pba.pba_dmat	= BUS_PCI_DMA_TAG;
    125 	pba.pba_iot     = leb_alloc_bus_space_tag();
    126 	pba.pba_memt    = leb_alloc_bus_space_tag();
    127 	if ((pba.pba_iot == NULL) || (pba.pba_memt == NULL)) {
    128 		printf("leb_alloc_bus_space_tag failed!\n");
    129 		return;
    130 	}
    131 	pba.pba_iot->base  = PCI_IO_PHYS;
    132 	pba.pba_memt->base = PCI_MEM_PHYS;
    133 
    134 	MFP2->mf_aer &= ~(0x27); /* PCI interrupts: HIGH -> LOW */
    135 
    136 	printf("\n");
    137 
    138 	config_found(dp, &pba, pcibusprint);
    139 }
    140 
    141 int
    142 pcibusprint(auxp, name)
    143 void		*auxp;
    144 const char	*name;
    145 {
    146 	if(name == NULL)
    147 		return(UNCONF);
    148 	return(QUIET);
    149 }
    150 
    151 void
    152 pci_attach_hook(parent, self, pba)
    153 	struct device *parent, *self;
    154 	struct pcibus_attach_args *pba;
    155 {
    156 }
    157 
    158 /*
    159  * Initialize the PCI-bus. The Atari-BIOS does not do this, so....
    160  * We only disable all devices here. Memory and I/O enabling is done
    161  * later at pcibusattach.
    162  */
    163 void
    164 init_pci_bus()
    165 {
    166 	pci_chipset_tag_t	pc = NULL; /* XXX */
    167 	pcitag_t		tag;
    168 	pcireg_t		csr;
    169 	int			device, id, maxndevs;
    170 
    171 	tag   = 0;
    172 	id    = 0;
    173 
    174 	maxndevs = pci_bus_maxdevs(pc, 0);
    175 
    176 	for (device = 0; device < maxndevs; device++) {
    177 
    178 		tag = pci_make_tag(pc, 0, device, 0);
    179 		id  = pci_conf_read(pc, tag, PCI_ID_REG);
    180 		if (id == 0 || id == 0xffffffff)
    181 			continue;
    182 
    183 		csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
    184 		csr &= ~(PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE);
    185 		csr &= ~PCI_COMMAND_MASTER_ENABLE;
    186 		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
    187 	}
    188 }
    189 
    190 /*
    191  * insert a new element in an existing list that the ID's (size in struct
    192  * pci_memreg) are sorted.
    193  */
    194 static void
    195 insert_into_list(head, elem)
    196     PCI_MEMREG *head;
    197     struct pci_memreg *elem;
    198 {
    199     struct pci_memreg *p, *q;
    200 
    201     p = LIST_FIRST(head);
    202     q = NULL;
    203 
    204     for (; p != NULL && p->size < elem->size; q = p, p = LIST_NEXT(p, link));
    205 
    206     if (q == NULL) {
    207 	LIST_INSERT_HEAD(head, elem, link);
    208     } else {
    209 	LIST_INSERT_AFTER(q, elem, link);
    210     }
    211 }
    212 
    213 /*
    214  * Test if a new selected area overlaps with an already (probably preselected)
    215  * pci area.
    216  */
    217 static int
    218 overlap_pci_areas(p, self, addr, size, what)
    219     struct pci_memreg *p, *self;
    220     u_int addr, size, what;
    221 {
    222     struct pci_memreg *q;
    223 
    224     if (p == NULL)
    225 	return 0;
    226 
    227     q = p;
    228     while (q != NULL) {
    229 	if ((q != self) && (q->csr & what)) {
    230 	    if ((addr >= q->address) && (addr < (q->address + q->size))) {
    231 #ifdef DEBUG_PCI_MACHDEP
    232 		printf("\noverlap area dev %d reg 0x%02x with dev %d reg 0x%02x",
    233 			self->dev, self->reg, q->dev, q->reg);
    234 #endif
    235 		return 1;
    236 	    }
    237 	    if ((q->address >= addr) && (q->address < (addr + size))) {
    238 #ifdef DEBUG_PCI_MACHDEP
    239 		printf("\noverlap area dev %d reg 0x%02x with dev %d reg 0x%02x",
    240 			self->dev, self->reg, q->dev, q->reg);
    241 #endif
    242 		return 1;
    243 	    }
    244 	}
    245 	q = LIST_NEXT(q, link);
    246     }
    247     return 0;
    248 }
    249 
    250 /*
    251  * Enable memory and I/O on pci devices. Care about already enabled devices
    252  * (probabaly by the console driver).
    253  *
    254  * The idea behind the following code is:
    255  * We build a by sizes sorted list of the requirements of the different
    256  * pci devices. After that we choose the start addresses of that areas
    257  * in such a way that they are placed as closed as possible together.
    258  */
    259 static void
    260 enable_pci_devices()
    261 {
    262     PCI_MEMREG memlist;
    263     PCI_MEMREG iolist;
    264     struct pci_memreg *p, *q;
    265     int dev, reg, id, class;
    266     pcitag_t tag;
    267     pcireg_t csr, address, mask;
    268     pci_chipset_tag_t pc;
    269     int sizecnt, membase_1m;
    270 
    271     pc = 0;
    272     csr = 0;
    273     tag = 0;
    274 
    275     LIST_INIT(&memlist);
    276     LIST_INIT(&iolist);
    277 
    278     /*
    279      * first step: go through all devices and gather memory and I/O
    280      * sizes
    281      */
    282     for (dev = 0; dev < pci_bus_maxdevs(pc,0); dev++) {
    283 
    284 	tag = pci_make_tag(pc, 0, dev, 0);
    285 	id  = pci_conf_read(pc, tag, PCI_ID_REG);
    286 	if (id == 0 || id == 0xffffffff)
    287 	    continue;
    288 
    289 	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
    290 
    291 	/*
    292 	 * special case: if a display card is found and memory is enabled
    293 	 * preserve 128k at 0xa0000 as vga memory.
    294 	 */
    295 	class = pci_conf_read(pc, tag, PCI_CLASS_REG);
    296 	switch (PCI_CLASS(class)) {
    297 	    case PCI_CLASS_PREHISTORIC:
    298 	    case PCI_CLASS_DISPLAY:
    299 		if (csr & (PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)) {
    300 		    p = (struct pci_memreg *)malloc(sizeof(struct pci_memreg),
    301 				M_TEMP, M_WAITOK);
    302 		    memset(p, '\0', sizeof(struct pci_memreg));
    303 		    p->dev = dev;
    304 		    p->csr = csr;
    305 		    p->tag = tag;
    306 		    p->reg = 0;     /* there is no register about this */
    307 		    p->size = 0x20000;  /* 128kByte */
    308 		    p->mask = 0xfffe0000;
    309 		    p->address = 0xa0000;
    310 
    311 		    insert_into_list(&memlist, p);
    312 		}
    313 	}
    314 
    315 	for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {
    316 
    317 	    address = pci_conf_read(pc, tag, reg);
    318 	    pci_conf_write(pc, tag, reg, 0xffffffff);
    319 	    mask    = pci_conf_read(pc, tag, reg);
    320 	    pci_conf_write(pc, tag, reg, address);
    321 	    if (mask == 0)
    322 		continue; /* Register unused */
    323 
    324 	    p = (struct pci_memreg *)malloc(sizeof(struct pci_memreg),
    325 			M_TEMP, M_WAITOK);
    326 	    memset(p, '\0', sizeof(struct pci_memreg));
    327 	    p->dev = dev;
    328 	    p->csr = csr;
    329 	    p->tag = tag;
    330 	    p->reg = reg;
    331 	    p->mask = mask;
    332 	    p->address = 0;
    333 
    334 	    if (mask & PCI_MAPREG_TYPE_IO) {
    335 		p->size = PCI_MAPREG_IO_SIZE(mask);
    336 
    337 		/*
    338 		 * if I/O is already enabled (probably by the console driver)
    339 		 * save the address in order to take care about it later.
    340 		 */
    341 		if (csr & PCI_COMMAND_IO_ENABLE)
    342 		    p->address = address;
    343 
    344 		insert_into_list(&iolist, p);
    345 	    } else {
    346 		p->size = PCI_MAPREG_MEM_SIZE(mask);
    347 
    348 		/*
    349 		 * if memory is already enabled (probably by the console driver)
    350 		 * save the address in order to take care about it later.
    351 		 */
    352 		if (csr & PCI_COMMAND_MEM_ENABLE)
    353 		    p->address = address;
    354 
    355 		insert_into_list(&memlist, p);
    356 
    357 		if (PCI_MAPREG_MEM_TYPE(mask) == PCI_MAPREG_MEM_TYPE_64BIT)
    358 		    reg++;
    359 	    }
    360 	}
    361 
    362 	/*
    363 	 * Both interrupt pin & line are set to the device (== slot)
    364 	 * number. This makes sense on the atari because the
    365 	 * individual slots are hard-wired to a specific MFP-pin.
    366 	 */
    367 	csr  = (dev << PCI_INTERRUPT_PIN_SHIFT);
    368 	csr |= (dev << PCI_INTERRUPT_LINE_SHIFT);
    369 	pci_conf_write(pc, tag, PCI_INTERRUPT_REG, csr);
    370     }
    371 
    372     /*
    373      * second step: calculate the memory and I/O adresses beginning from
    374      * PCI_MEM_START and PCI_IO_START. Care about already mapped areas.
    375      *
    376      * beginn with memory list
    377      */
    378 
    379     address = PCI_MEM_START;
    380     sizecnt = 0;
    381     membase_1m = 0;
    382     p = LIST_FIRST(&memlist);
    383     while (p != NULL) {
    384 	if (!(p->csr & PCI_COMMAND_MEM_ENABLE)) {
    385 	    if (PCI_MAPREG_MEM_TYPE(p->mask) == PCI_MAPREG_MEM_TYPE_32BIT_1M) {
    386 		if (p->size > membase_1m)
    387 		    membase_1m = p->size;
    388 		do {
    389 		    p->address = membase_1m;
    390 		    membase_1m += p->size;
    391 		} while (overlap_pci_areas(LIST_FIRST(&memlist), p, p->address,
    392 					   p->size, PCI_COMMAND_MEM_ENABLE));
    393 		if (membase_1m > 0x00100000) {
    394 		    /*
    395 		     * Should we panic here?
    396 		     */
    397 		    printf("\npcibus0: dev %d reg %d: memory not configured",
    398 			    p->dev, p->reg);
    399 		    p->reg = 0;
    400 		}
    401 	    } else {
    402 
    403 		if (sizecnt && (p->size > sizecnt))
    404 		    sizecnt = ((p->size + sizecnt) & p->mask) &
    405 			      PCI_MAPREG_MEM_ADDR_MASK;
    406 		if (sizecnt > address) {
    407 		    address = sizecnt;
    408 		    sizecnt = 0;
    409 		}
    410 
    411 		do {
    412 		    p->address = address + sizecnt;
    413 		    sizecnt += p->size;
    414 		} while (overlap_pci_areas(LIST_FIRST(&memlist), p, p->address,
    415 					   p->size, PCI_COMMAND_MEM_ENABLE));
    416 
    417 		if ((address + sizecnt) > PCI_MEM_END) {
    418 		    /*
    419 		     * Should we panic here?
    420 		     */
    421 		    printf("\npcibus0: dev %d reg %d: memory not configured",
    422 			    p->dev, p->reg);
    423 		    p->reg = 0;
    424 		}
    425 	    }
    426 	    if (p->reg > 0) {
    427 		pci_conf_write(pc, p->tag, p->reg, p->address);
    428 		csr = pci_conf_read(pc, p->tag, PCI_COMMAND_STATUS_REG);
    429 		csr |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
    430 		pci_conf_write(pc, p->tag, PCI_COMMAND_STATUS_REG, csr);
    431 	    }
    432 	}
    433 	p = LIST_NEXT(p, link);
    434     }
    435 
    436     /*
    437      * now the I/O list
    438      */
    439 
    440     address = PCI_IO_START;
    441     sizecnt = 0;
    442     p = LIST_FIRST(&iolist);
    443     while (p != NULL) {
    444 	if (!(p->csr & PCI_COMMAND_IO_ENABLE)) {
    445 
    446 	    if (sizecnt && (p->size > sizecnt))
    447 		sizecnt = ((p->size + sizecnt) & p->mask) &
    448 			  PCI_MAPREG_IO_ADDR_MASK;
    449 	    if (sizecnt > address) {
    450 		address = sizecnt;
    451 		sizecnt = 0;
    452 	    }
    453 
    454 	    do {
    455 		p->address = address + sizecnt;
    456 		sizecnt += p->size;
    457 	    } while (overlap_pci_areas(LIST_FIRST(&iolist), p, p->address,
    458 				       p->size, PCI_COMMAND_IO_ENABLE));
    459 
    460 	    if ((address + sizecnt) > PCI_IO_END) {
    461 		/*
    462 		 * Should we panic here?
    463 		 */
    464 		printf("\npcibus0: dev %d reg %d: io not configured",
    465 			p->dev, p->reg);
    466 	    } else {
    467 		pci_conf_write(pc, p->tag, p->reg, p->address);
    468 		csr = pci_conf_read(pc, p->tag, PCI_COMMAND_STATUS_REG);
    469 		csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE;
    470 		pci_conf_write(pc, p->tag, PCI_COMMAND_STATUS_REG, csr);
    471 	    }
    472 	}
    473 	p = LIST_NEXT(p, link);
    474     }
    475 
    476 #ifdef DEBUG_PCI_MACHDEP
    477     printf("\nI/O List:\n");
    478     p = LIST_FIRST(&iolist);
    479 
    480     while (p != NULL) {
    481 	printf("\ndev: %d, reg: 0x%02x, size: 0x%08x, addr: 0x%08x", p->dev,
    482 			p->reg, p->size, p->address);
    483 	p = LIST_NEXT(p, link);
    484     }
    485     printf("\nMemlist:");
    486     p = LIST_FIRST(&memlist);
    487 
    488     while (p != NULL) {
    489 	printf("\ndev: %d, reg: 0x%02x, size: 0x%08x, addr: 0x%08x", p->dev,
    490 			p->reg, p->size, p->address);
    491 	p = LIST_NEXT(p, link);
    492     }
    493 #endif
    494 
    495     /*
    496      * Free the lists
    497      */
    498     p = LIST_FIRST(&iolist);
    499     while (p != NULL) {
    500 	q = p;
    501 	LIST_REMOVE(q, link);
    502 	free(p, M_WAITOK);
    503 	p = LIST_FIRST(&iolist);
    504     }
    505     p = LIST_FIRST(&memlist);
    506     while (p != NULL) {
    507 	q = p;
    508 	LIST_REMOVE(q, link);
    509 	free(p, M_WAITOK);
    510 	p = LIST_FIRST(&memlist);
    511     }
    512 }
    513 
    514 /*
    515  * Atari_init.c maps the config areas NBPG bytes apart....
    516  */
    517 static int pci_config_offset(tag)
    518 pcitag_t	tag;
    519 {
    520 	int	device;
    521 
    522 	device = (tag >> 11) & 0x1f;
    523 	return(device * NBPG);
    524 }
    525 
    526 int
    527 pci_bus_maxdevs(pc, busno)
    528 	pci_chipset_tag_t pc;
    529 	int busno;
    530 {
    531 	return (4);
    532 }
    533 
    534 pcitag_t
    535 pci_make_tag(pc, bus, device, function)
    536 	pci_chipset_tag_t pc;
    537 	int bus, device, function;
    538 {
    539 	return ((bus << 16) | (device << 11) | (function << 8));
    540 }
    541 
    542 pcireg_t
    543 pci_conf_read(pc, tag, reg)
    544 	pci_chipset_tag_t pc;
    545 	pcitag_t tag;
    546 	int reg;
    547 {
    548 	u_long	data;
    549 
    550 	data = *(u_long *)(pci_conf_addr + pci_config_offset(tag) + reg);
    551 	return (bswap32(data));
    552 }
    553 
    554 void
    555 pci_conf_write(pc, tag, reg, data)
    556 	pci_chipset_tag_t pc;
    557 	pcitag_t tag;
    558 	int reg;
    559 	pcireg_t data;
    560 {
    561 	*((u_long *)(pci_conf_addr + pci_config_offset(tag) + reg))
    562 		= bswap32(data);
    563 }
    564 
    565 int
    566 pci_intr_map(pc, intrtag, pin, line, ihp)
    567 	pci_chipset_tag_t pc;
    568 	pcitag_t intrtag;
    569 	int pin, line;
    570 	pci_intr_handle_t *ihp;
    571 {
    572 	/*
    573 	 * According to the PCI-spec, 255 means `unknown' or `no connection'.
    574 	 * Interpret this as 'no interrupt assigned'.
    575 	 */
    576 	if (line == 255) {
    577 		*ihp = -1;
    578 		return 1;
    579 	}
    580 
    581 	/*
    582 	 * Values are pretty useless because the on the Hades all interrupt
    583 	 * lines for a card are tied together and hardwired to the TT-MFP
    584 	 * I/O port.
    585 	 */
    586 	*ihp = line;
    587 	return 0;
    588 }
    589 
    590 const char *
    591 pci_intr_string(pc, ih)
    592 	pci_chipset_tag_t pc;
    593 	pci_intr_handle_t ih;
    594 {
    595 	static char irqstr[8];		/* 4 + 2 + NULL + sanity */
    596 
    597 	if (ih == -1)
    598 		panic("pci_intr_string: bogus handle 0x%x\n", ih);
    599 
    600 	sprintf(irqstr, "irq %d", ih);
    601 	return (irqstr);
    602 
    603 }
    604 
    605 /*
    606  * The interrupt stuff is rather ugly. On the Hades, all interrupt lines
    607  * for a slot are wired together and connected to IO 0,1,2 or 5 (slots:
    608  * (0-3) on the TT-MFP. The Pci-config code initializes the irq. number
    609  * to the slot position.
    610  */
    611 static pci_intr_info_t iinfo[4] = { { -1 }, { -1 }, { -1 }, { -1 } };
    612 
    613 static int	iifun __P((int, int));
    614 
    615 static int
    616 iifun(slot, sr)
    617 int	slot;
    618 int	sr;
    619 {
    620 	pci_intr_info_t *iinfo_p;
    621 	int		s;
    622 
    623 	iinfo_p = &iinfo[slot];
    624 
    625 	/*
    626 	 * Disable the interrupts
    627 	 */
    628 	MFP2->mf_imrb  &= ~iinfo_p->imask;
    629 
    630 	if ((sr & PSL_IPL) >= (iinfo_p->ipl & PSL_IPL)) {
    631 		/*
    632 		 * We're running at a too high priority now.
    633 		 */
    634 		add_sicallback((si_farg)iifun, (void*)slot, 0);
    635 	}
    636 	else {
    637 		s = splx(iinfo_p->ipl);
    638 		(void) (iinfo_p->ifunc)(iinfo_p->iarg);
    639 		splx(s);
    640 
    641 		/*
    642 		 * Re-enable interrupts after handling
    643 		 */
    644 		MFP2->mf_imrb |= iinfo_p->imask;
    645 	}
    646 	return 1;
    647 }
    648 
    649 void *
    650 pci_intr_establish(pc, ih, level, ih_fun, ih_arg)
    651 	pci_chipset_tag_t	pc;
    652 	pci_intr_handle_t	ih;
    653 	int			level;
    654 	int			(*ih_fun) __P((void *));
    655 	void			*ih_arg;
    656 {
    657 	pci_intr_info_t *iinfo_p;
    658 	struct intrhand	*ihand;
    659 	int		slot;
    660 
    661 	slot    = ih;
    662 	iinfo_p = &iinfo[slot];
    663 
    664 	if (iinfo_p->ipl > 0)
    665 	    panic("pci_intr_establish: interrupt was already established\n");
    666 
    667 	ihand = intr_establish((slot == 3) ? 23 : 16 + slot, USER_VEC, 0,
    668 				(hw_ifun_t)iifun, (void *)slot);
    669 	if (ihand != NULL) {
    670 		iinfo_p->ipl   = level;
    671 		iinfo_p->imask = (slot == 3) ? 0x80 : (0x01 << slot);
    672 		iinfo_p->ifunc = ih_fun;
    673 		iinfo_p->iarg  = ih_arg;
    674 		iinfo_p->ihand = ihand;
    675 
    676 		/*
    677 		 * Enable (unmask) the interrupt
    678 		 */
    679 		MFP2->mf_imrb |= iinfo_p->imask;
    680 		MFP2->mf_ierb |= iinfo_p->imask;
    681 		return(iinfo_p);
    682 	}
    683 	return NULL;
    684 }
    685 
    686 void
    687 pci_intr_disestablish(pc, cookie)
    688 	pci_chipset_tag_t pc;
    689 	void *cookie;
    690 {
    691 	pci_intr_info_t *iinfo_p = (pci_intr_info_t *)cookie;
    692 
    693 	if (iinfo->ipl < 0)
    694 	    panic("pci_intr_disestablish: interrupt was not established\n");
    695 
    696 	MFP2->mf_imrb &= ~iinfo->imask;
    697 	MFP2->mf_ierb &= ~iinfo->imask;
    698 	(void) intr_disestablish(iinfo_p->ihand);
    699 	iinfo_p->ipl = -1;
    700 }
    701