Home | History | Annotate | Line # | Download | only in dev
pci_machdep.c revision 1.2
      1  1.2  mrg /*	$NetBSD: pci_machdep.c,v 1.2 1999/06/05 05:29:50 mrg Exp $	*/
      2  1.1  mrg 
      3  1.1  mrg /*
      4  1.1  mrg  * Copyright (c) 1999 Matthew R. Green
      5  1.1  mrg  * All rights reserved.
      6  1.1  mrg  *
      7  1.1  mrg  * Redistribution and use in source and binary forms, with or without
      8  1.1  mrg  * modification, are permitted provided that the following conditions
      9  1.1  mrg  * are met:
     10  1.1  mrg  * 1. Redistributions of source code must retain the above copyright
     11  1.1  mrg  *    notice, this list of conditions and the following disclaimer.
     12  1.1  mrg  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  mrg  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  mrg  *    documentation and/or other materials provided with the distribution.
     15  1.1  mrg  * 3. The name of the author may not be used to endorse or promote products
     16  1.1  mrg  *    derived from this software without specific prior written permission.
     17  1.1  mrg  *
     18  1.1  mrg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  1.1  mrg  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  1.1  mrg  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  1.1  mrg  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  1.1  mrg  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     23  1.1  mrg  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  1.1  mrg  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     25  1.1  mrg  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     26  1.1  mrg  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  1.1  mrg  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  1.1  mrg  * SUCH DAMAGE.
     29  1.1  mrg  */
     30  1.1  mrg 
     31  1.1  mrg /*
     32  1.1  mrg  * functions expected by the MI PCI code.
     33  1.1  mrg  */
     34  1.1  mrg 
     35  1.1  mrg #undef DEBUG
     36  1.1  mrg #define DEBUG
     37  1.1  mrg 
     38  1.1  mrg #ifdef DEBUG
     39  1.1  mrg #define SPDB_CONF	0x01
     40  1.1  mrg #define SPDB_INTR	0x04
     41  1.1  mrg #define SPDB_INTMAP	0x08
     42  1.1  mrg #define SPDB_INTFIX	0x10
     43  1.1  mrg int sparc_pci_debug = 0x4;
     44  1.1  mrg #define DPRINTF(l, s)	do { if (sparc_pci_debug & l) printf s; } while (0)
     45  1.1  mrg #else
     46  1.1  mrg #define DPRINTF(l, s)
     47  1.1  mrg #endif
     48  1.1  mrg 
     49  1.1  mrg #include <sys/types.h>
     50  1.1  mrg #include <sys/param.h>
     51  1.1  mrg #include <sys/time.h>
     52  1.1  mrg #include <sys/systm.h>
     53  1.1  mrg #include <sys/errno.h>
     54  1.1  mrg #include <sys/device.h>
     55  1.1  mrg #include <sys/malloc.h>
     56  1.1  mrg 
     57  1.1  mrg #include <vm/vm.h>
     58  1.1  mrg #include <vm/vm_kern.h>
     59  1.1  mrg 
     60  1.1  mrg #define _SPARC_BUS_DMA_PRIVATE
     61  1.1  mrg #include <machine/bus.h>
     62  1.1  mrg #include <machine/autoconf.h>
     63  1.1  mrg 
     64  1.1  mrg #include <dev/pci/pcivar.h>
     65  1.1  mrg #include <dev/pci/pcireg.h>
     66  1.1  mrg 
     67  1.1  mrg #include <sparc64/dev/iommureg.h>
     68  1.1  mrg #include <sparc64/dev/iommuvar.h>
     69  1.1  mrg #include <sparc64/dev/psychoreg.h>
     70  1.1  mrg #include <sparc64/dev/psychovar.h>
     71  1.1  mrg 
     72  1.1  mrg /* this is a base to be copied */
     73  1.1  mrg struct sparc_pci_chipset _sparc_pci_chipset = {
     74  1.1  mrg 	NULL,
     75  1.1  mrg };
     76  1.1  mrg 
     77  1.2  mrg /* commonly used */
     78  1.2  mrg #define TAG2BUS(tag)	((tag) >> 16) & 0xff;
     79  1.2  mrg #define TAG2DEV(tag)	((tag) >> 11) & 0x1f;
     80  1.2  mrg #define TAG2FN(tag)	((tag) >> 8) & 0x7;
     81  1.2  mrg 
     82  1.1  mrg /*
     83  1.1  mrg  * functions provided to the MI code.
     84  1.1  mrg  */
     85  1.1  mrg 
     86  1.1  mrg void
     87  1.1  mrg pci_attach_hook(parent, self, pba)
     88  1.1  mrg 	struct device *parent;
     89  1.1  mrg 	struct device *self;
     90  1.1  mrg 	struct pcibus_attach_args *pba;
     91  1.1  mrg {
     92  1.1  mrg 	pci_chipset_tag_t pc = pba->pba_pc;
     93  1.1  mrg 	struct psycho_pbm *pp = pc->cookie;
     94  1.1  mrg 	struct psycho_registers *pr;
     95  1.1  mrg 	pcitag_t tag;
     96  1.1  mrg 	char *name, *devtype;
     97  1.1  mrg 	u_int32_t hi, mid, lo, intr;
     98  1.2  mrg 	u_int32_t dev, fn, bus;
     99  1.1  mrg 	int node, i, n, *ip, *ap;
    100  1.1  mrg 
    101  1.1  mrg 	DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\npci_attach_hook:"));
    102  1.1  mrg 
    103  1.1  mrg 	/*
    104  1.1  mrg 	 * ok, here we look in the OFW for each PCI device and fix it's
    105  1.1  mrg 	 * "interrupt line" register to be useful.
    106  1.1  mrg 	 */
    107  1.1  mrg 
    108  1.1  mrg 	for (node = firstchild(pc->node); node; node = nextsibling(node)) {
    109  1.1  mrg 		pr = NULL;
    110  1.1  mrg 		ip = ap = NULL;
    111  1.1  mrg 
    112  1.1  mrg 		/*
    113  1.1  mrg 		 * ok, for each child we get the "interrupts" property,
    114  1.1  mrg 		 * which contains a value to match against later.
    115  1.1  mrg 		 * XXX deal with multiple "interrupts" values XXX.
    116  1.1  mrg 		 * then we get the "assigned-addresses" property which
    117  1.1  mrg 		 * contains, in the first entry, the PCI bus, device and
    118  1.1  mrg 		 * function associated with this node, which we use to
    119  1.1  mrg 		 * generate a pcitag_t to use pci_conf_read() and
    120  1.1  mrg 		 * pci_conf_write().  next, we get the 'reg" property
    121  1.1  mrg 		 * which is structured like the following:
    122  1.1  mrg 		 *	u_int32_t	phys_hi;
    123  1.1  mrg 		 *	u_int32_t	phys_mid;
    124  1.1  mrg 		 *	u_int32_t	phys_lo;
    125  1.1  mrg 		 *	u_int32_t	size_hi;
    126  1.1  mrg 		 *	u_int32_t	size_lo;
    127  1.1  mrg 		 * we mask these values with the "interrupt-map-mask"
    128  1.1  mrg 		 * property of our parent and them compare with each
    129  1.1  mrg 		 * entry in the "interrupt-map" property (also of our
    130  1.1  mrg 		 * parent) which is structred like the following:
    131  1.1  mrg 		 *	u_int32_t	phys_hi;
    132  1.1  mrg 		 *	u_int32_t	phys_mid;
    133  1.1  mrg 		 *	u_int32_t	phys_lo;
    134  1.1  mrg 		 *	u_int32_t	intr;
    135  1.1  mrg 		 *	int32_t		child_node;
    136  1.1  mrg 		 *	u_int32_t	child_intr;
    137  1.1  mrg 		 * if there is an exact match with phys_hi, phys_mid,
    138  1.1  mrg 		 * phys_lo and the interrupt, we have a match and we
    139  1.1  mrg 		 * know that this interrupt's value is really the
    140  1.1  mrg 		 * child_intr of the interrupt map entry.  we put this
    141  1.1  mrg 		 * into the PCI interrupt line register so that when
    142  1.1  mrg 		 * the driver for this node wants to attach, we know
    143  1.1  mrg 		 * it's INO already.
    144  1.1  mrg 		 */
    145  1.1  mrg 
    146  1.1  mrg 		name = getpropstring(node, "name");
    147  1.1  mrg 		DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\n\tnode %x name `%s'", node, name));
    148  1.1  mrg 		devtype = getpropstring(node, "device_type");
    149  1.1  mrg 		DPRINTF((SPDB_INTFIX|SPDB_INTMAP), (" devtype `%s':", devtype));
    150  1.1  mrg 
    151  1.1  mrg 		/* ignore PCI bridges, we'll get them later */
    152  1.1  mrg 		if (strcmp(devtype, "pci") == 0)
    153  1.1  mrg 			continue;
    154  1.1  mrg 
    155  1.1  mrg 		/* if there isn't any "interrupts" then we don't care to fix it */
    156  1.1  mrg 		ip = NULL;
    157  1.1  mrg 		if (getprop(node, "interrupts", sizeof(int), &n, (void **)&ip))
    158  1.1  mrg 			continue;
    159  1.1  mrg 		DPRINTF(SPDB_INTFIX, (" got interrupts"));
    160  1.1  mrg 
    161  1.1  mrg 		/* and if there isn't an "assigned-addresses" we can't find b/d/f */
    162  1.1  mrg 		if (getprop(node, "assigned-addresses", sizeof(int), &n,
    163  1.1  mrg 		    (void **)&ap))
    164  1.1  mrg 			goto clean1;
    165  1.1  mrg 		DPRINTF(SPDB_INTFIX, (" got assigned-addresses"));
    166  1.1  mrg 
    167  1.1  mrg 		/* ok, and now the "reg" property, so we know what we're talking about. */
    168  1.1  mrg 		if (getprop(node, "reg", sizeof(*pr), &n,
    169  1.1  mrg 		    (void **)&pr))
    170  1.1  mrg 			goto clean2;
    171  1.1  mrg 		DPRINTF(SPDB_INTFIX, (" got reg"));
    172  1.1  mrg 
    173  1.2  mrg 		bus = TAG2BUS(ap[0]);
    174  1.2  mrg 		dev = TAG2DEV(ap[0]);
    175  1.2  mrg 		fn = TAG2FN(ap[0]);
    176  1.1  mrg 
    177  1.1  mrg 		DPRINTF(SPDB_INTFIX, ("; bus %u dev %u fn %u", bus, dev, fn));
    178  1.1  mrg 
    179  1.1  mrg 		tag = pci_make_tag(pc, bus, dev, fn);
    180  1.1  mrg 
    181  1.1  mrg 		DPRINTF(SPDB_INTFIX, ("; tag %08x\n\t; reg: hi %x mid %x lo %x intr %x", tag, pr->phys_hi, pr->phys_mid, pr->phys_lo, *ip));
    182  1.1  mrg 		DPRINTF(SPDB_INTFIX, ("\n\t; intmapmask: hi %x mid %x lo %x intr %x", pp->pp_intmapmask.phys_hi, pp->pp_intmapmask.phys_mid,
    183  1.1  mrg 										      pp->pp_intmapmask.phys_lo, pp->pp_intmapmask.intr));
    184  1.1  mrg 
    185  1.1  mrg 		hi = pr->phys_hi & pp->pp_intmapmask.phys_hi;
    186  1.1  mrg 		mid = pr->phys_mid & pp->pp_intmapmask.phys_mid;
    187  1.1  mrg 		lo = pr->phys_lo & pp->pp_intmapmask.phys_lo;
    188  1.1  mrg 		intr = *ip & pp->pp_intmapmask.intr;
    189  1.1  mrg 
    190  1.1  mrg 		DPRINTF(SPDB_INTFIX, ("\n\t; after: hi %x mid %x lo %x intr %x", hi, mid, lo, intr));
    191  1.1  mrg 
    192  1.1  mrg 		for (i = 0; i < pp->pp_nintmap; i++) {
    193  1.1  mrg 			DPRINTF(SPDB_INTFIX, ("\n\t\tmatching for: hi %x mid %x lo %x intr %x", pp->pp_intmap[i].phys_hi, pp->pp_intmap[i].phys_mid,
    194  1.1  mrg 												pp->pp_intmap[i].phys_lo, pp->pp_intmap[i].intr));
    195  1.1  mrg 
    196  1.1  mrg 			if (pp->pp_intmap[i].phys_hi != hi ||
    197  1.1  mrg 			    pp->pp_intmap[i].phys_mid != mid ||
    198  1.1  mrg 			    pp->pp_intmap[i].phys_lo != lo ||
    199  1.1  mrg 			    pp->pp_intmap[i].intr != intr)
    200  1.1  mrg 				continue;
    201  1.1  mrg 			DPRINTF(SPDB_INTFIX, ("... BINGO! ..."));
    202  1.1  mrg 
    203  1.1  mrg 			/*
    204  1.1  mrg 			 * OK!  we found match.  pull out the old interrupt
    205  1.1  mrg 			 * register, patch in the new value, and put it back.
    206  1.1  mrg 			 */
    207  1.1  mrg 			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
    208  1.1  mrg 			DPRINTF(SPDB_INTFIX, ("\n\t    ; read %x from intreg", intr));
    209  1.1  mrg 
    210  1.1  mrg 			intr = (intr & ~PCI_INTERRUPT_LINE_MASK) |
    211  1.1  mrg 			       (pp->pp_intmap[i].child_intr & PCI_INTERRUPT_LINE_MASK);
    212  1.1  mrg 			DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\n\t    ; gonna write %x to intreg", intr));
    213  1.1  mrg 
    214  1.1  mrg 			pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
    215  1.1  mrg 			DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\n\t    ; reread %x from intreg", intr));
    216  1.1  mrg 			break;
    217  1.1  mrg 		}
    218  1.1  mrg 
    219  1.1  mrg 		/* clean up */
    220  1.1  mrg 		if (pr)
    221  1.1  mrg 			free(pr, M_DEVBUF);
    222  1.1  mrg clean2:
    223  1.1  mrg 		if (ap)
    224  1.1  mrg 			free(ap, M_DEVBUF);
    225  1.1  mrg clean1:
    226  1.1  mrg 		if (ip)
    227  1.1  mrg 			free(ip, M_DEVBUF);
    228  1.1  mrg 	}
    229  1.1  mrg 	DPRINTF(SPDB_INTFIX, ("\n"));
    230  1.1  mrg }
    231  1.1  mrg 
    232  1.1  mrg int
    233  1.1  mrg pci_bus_maxdevs(pc, busno)
    234  1.1  mrg 	pci_chipset_tag_t pc;
    235  1.1  mrg 	int busno;
    236  1.1  mrg {
    237  1.1  mrg 
    238  1.1  mrg 	return 32;
    239  1.1  mrg }
    240  1.1  mrg 
    241  1.1  mrg pcitag_t
    242  1.1  mrg pci_make_tag(pc, b, d, f)
    243  1.1  mrg 	pci_chipset_tag_t pc;
    244  1.1  mrg 	int b;
    245  1.1  mrg 	int d;
    246  1.1  mrg 	int f;
    247  1.1  mrg {
    248  1.1  mrg 
    249  1.2  mrg 	/* make me a useable offset */
    250  1.1  mrg 	return (b << 16) | (d << 11) | (f << 8);
    251  1.1  mrg }
    252  1.1  mrg 
    253  1.1  mrg static int confaddr_ok __P((struct psycho_softc *, pcitag_t));
    254  1.1  mrg 
    255  1.1  mrg /*
    256  1.1  mrg  * this function is a large hack.  ideally, we should also trap accesses
    257  1.1  mrg  * properly, but we have to avoid letting anything read various parts
    258  1.1  mrg  * of bus 0 dev 0 fn 0 space or the machine may hang.  so, even if we
    259  1.1  mrg  * do properly implement PCI config access trap handling, this function
    260  1.1  mrg  * should remain in place Just In Case.
    261  1.1  mrg  */
    262  1.1  mrg static int
    263  1.1  mrg confaddr_ok(sc, tag)
    264  1.1  mrg 	struct psycho_softc *sc;
    265  1.1  mrg 	pcitag_t tag;
    266  1.1  mrg {
    267  1.1  mrg 	int bus, dev, fn;
    268  1.1  mrg 
    269  1.2  mrg 	bus = TAG2BUS(tag);
    270  1.2  mrg 	dev = TAG2DEV(tag);
    271  1.2  mrg 	fn = TAG2FN(tag);
    272  1.1  mrg 
    273  1.1  mrg 	if (sc->sc_mode == PSYCHO_MODE_SABRE) {
    274  1.1  mrg 		/*
    275  1.1  mrg 		 * bus 0 is only ok for dev 0 fn 0, dev 1 fn 0 and dev fn 1.
    276  1.1  mrg 		 */
    277  1.1  mrg 		if (bus == 0 &&
    278  1.1  mrg 		    ((dev == 0 && fn > 0) ||
    279  1.1  mrg 		     (dev == 1 && fn > 1) ||
    280  1.1  mrg 		     (dev > 1))) {
    281  1.1  mrg 			DPRINTF(SPDB_CONF, (" confaddr_ok: rejecting bus %d dev %d fn %d -", bus, dev, fn));
    282  1.1  mrg 			return (0);
    283  1.1  mrg 		}
    284  1.1  mrg 	} else if (sc->sc_mode == PSYCHO_MODE_PSYCHO_A ||
    285  1.1  mrg 		   sc->sc_mode == PSYCHO_MODE_PSYCHO_B) {
    286  1.1  mrg 		/*
    287  1.1  mrg 		 * make sure we are reading our own bus
    288  1.1  mrg 		 */
    289  1.1  mrg 		/* XXX??? */
    290  1.2  mrg 		panic("confaddr_ok: can't do SUNW,psycho yet");
    291  1.1  mrg 	}
    292  1.1  mrg 	return (1);
    293  1.1  mrg }
    294  1.1  mrg 
    295  1.1  mrg /* assume we are mapped little-endian/side-effect */
    296  1.1  mrg pcireg_t
    297  1.1  mrg pci_conf_read(pc, tag, reg)
    298  1.1  mrg 	pci_chipset_tag_t pc;
    299  1.1  mrg 	pcitag_t tag;
    300  1.1  mrg 	int reg;
    301  1.1  mrg {
    302  1.1  mrg 	struct psycho_pbm *pp = pc->cookie;
    303  1.1  mrg 	struct psycho_softc *sc = pp->pp_sc;
    304  1.2  mrg 	u_int32_t data;
    305  1.1  mrg 	pcireg_t val;
    306  1.1  mrg 
    307  1.1  mrg 	DPRINTF(SPDB_CONF, ("pci_conf_read: tag %lx; reg %x; ", (long)tag, reg));
    308  1.1  mrg 	DPRINTF(SPDB_CONF, ("asi = %x; readaddr = %qx (offset = %x) ...",
    309  1.1  mrg 		    bus_type_asi[sc->sc_configtag->type],
    310  1.1  mrg 		    sc->sc_configaddr + tag + reg, (int)tag + reg));
    311  1.1  mrg 
    312  1.1  mrg 	if (confaddr_ok(sc, tag) == 0) {
    313  1.1  mrg 		val = (pcireg_t)~0;
    314  1.1  mrg 	} else {
    315  1.2  mrg #if 0
    316  1.2  mrg 		membar_sync();
    317  1.2  mrg 		data = probeget(bus_type_asi[sc->sc_configtag->type],
    318  1.2  mrg 			       sc->sc_configaddr + tag + reg, 4);
    319  1.2  mrg 		membar_sync();
    320  1.2  mrg 		if (data == -1)
    321  1.2  mrg 			val = (pcireg_t)~0;
    322  1.2  mrg 		else
    323  1.2  mrg 			val = (pcireg_t)data;
    324  1.2  mrg #else
    325  1.1  mrg 		membar_sync();
    326  1.1  mrg 		val = bus_space_read_4(sc->sc_configtag, sc->sc_configaddr,
    327  1.1  mrg 		    tag + reg);
    328  1.1  mrg 		membar_sync();
    329  1.2  mrg #endif
    330  1.1  mrg 	}
    331  1.1  mrg 	DPRINTF(SPDB_CONF, (" returning %08x\n", (u_int)val));
    332  1.1  mrg 
    333  1.1  mrg 	return (val);
    334  1.1  mrg }
    335  1.1  mrg 
    336  1.1  mrg void
    337  1.1  mrg pci_conf_write(pc, tag, reg, data)
    338  1.1  mrg 	pci_chipset_tag_t pc;
    339  1.1  mrg 	pcitag_t tag;
    340  1.1  mrg 	int reg;
    341  1.1  mrg 	pcireg_t data;
    342  1.1  mrg {
    343  1.1  mrg 	struct psycho_pbm *pp = pc->cookie;
    344  1.1  mrg 	struct psycho_softc *sc = pp->pp_sc;
    345  1.1  mrg 
    346  1.1  mrg 	DPRINTF(SPDB_CONF, ("pci_conf_write: tag %ld; reg %d; data %d; ", (long)tag, reg, (int)data));
    347  1.1  mrg 	DPRINTF(SPDB_CONF, ("asi = %x; readaddr = %qx (offset = %x)\n",
    348  1.1  mrg 		    bus_type_asi[sc->sc_configtag->type],
    349  1.1  mrg 		    sc->sc_configaddr + tag + reg, (int)tag + reg));
    350  1.1  mrg 
    351  1.1  mrg 	if (confaddr_ok(sc, tag) == 0)
    352  1.1  mrg 		panic("pci_conf_write: bad addr");
    353  1.1  mrg 
    354  1.1  mrg 	membar_sync();
    355  1.2  mrg #if 0
    356  1.2  mrg 	probeset(bus_type_asi[sc->sc_configtag->type],
    357  1.2  mrg 		 sc->sc_configaddr + tag + reg, 4, data);
    358  1.2  mrg #else
    359  1.1  mrg 	bus_space_write_4(sc->sc_configtag, sc->sc_configaddr, tag + reg, data);
    360  1.2  mrg #endif
    361  1.1  mrg 	membar_sync();
    362  1.1  mrg }
    363  1.1  mrg 
    364  1.1  mrg /*
    365  1.1  mrg  * interrupt mapping foo.
    366  1.1  mrg  */
    367  1.1  mrg int
    368  1.1  mrg pci_intr_map(pc, tag, pin, line, ihp)
    369  1.1  mrg 	pci_chipset_tag_t pc;
    370  1.1  mrg 	pcitag_t tag;
    371  1.1  mrg 	int pin;
    372  1.1  mrg 	int line;
    373  1.1  mrg 	pci_intr_handle_t *ihp;
    374  1.1  mrg {
    375  1.1  mrg 	struct psycho_pbm *pp = pc->cookie;
    376  1.1  mrg 	int rv;
    377  1.1  mrg 
    378  1.1  mrg 	DPRINTF(SPDB_INTR, ("pci_intr_map: tag %x; pin %d; line %d", (u_int)tag, pin, line));
    379  1.1  mrg 
    380  1.1  mrg 	if (line == 255 || pin == 0) {
    381  1.1  mrg 		*ihp = -1;
    382  1.1  mrg 		rv = 1;
    383  1.1  mrg 		goto out;
    384  1.1  mrg 	}
    385  1.1  mrg 	if (pin > 4)
    386  1.1  mrg 		panic("pci_intr_map: pin > 4");
    387  1.1  mrg 
    388  1.1  mrg 	rv = psycho_intr_map(tag, pin, line, ihp);
    389  1.1  mrg 
    390  1.1  mrg out:
    391  1.1  mrg 	DPRINTF(SPDB_INTR, ("; handle = %d; returning %d\n", (int)*ihp, rv));
    392  1.1  mrg 	return (rv);
    393  1.1  mrg }
    394  1.1  mrg 
    395  1.1  mrg const char *
    396  1.1  mrg pci_intr_string(pc, ih)
    397  1.1  mrg 	pci_chipset_tag_t pc;
    398  1.1  mrg 	pci_intr_handle_t ih;
    399  1.1  mrg {
    400  1.1  mrg 	static char str[16];
    401  1.1  mrg 
    402  1.1  mrg 	DPRINTF(SPDB_INTR, ("pci_intr_string: ih %u", ih));
    403  1.1  mrg 	if (ih < 0 || ih > 0x32) {
    404  1.1  mrg 		printf("\n");	/* i'm *so* beautiful */
    405  1.1  mrg 		panic("pci_intr_string: bogus handle\n");
    406  1.1  mrg 	}
    407  1.1  mrg 	sprintf(str, "vector %u", ih);
    408  1.1  mrg 	DPRINTF(SPDB_INTR, ("; returning %s\n", str));
    409  1.1  mrg 
    410  1.1  mrg 	return (str);
    411  1.1  mrg }
    412  1.1  mrg 
    413  1.1  mrg void *
    414  1.1  mrg pci_intr_establish(pc, ih, level, func, arg)
    415  1.1  mrg 	pci_chipset_tag_t pc;
    416  1.1  mrg 	pci_intr_handle_t ih;
    417  1.1  mrg 	int level;
    418  1.1  mrg 	int (*func) __P((void *));
    419  1.1  mrg 	void *arg;
    420  1.1  mrg {
    421  1.1  mrg 	void *cookie;
    422  1.1  mrg 	struct psycho_pbm *pp = (struct psycho_pbm *)pc->cookie;
    423  1.1  mrg 
    424  1.1  mrg 	DPRINTF(SPDB_INTR, ("pci_intr_establish: ih %lu; level %d", (u_long)ih, level));
    425  1.1  mrg 	cookie = bus_intr_establish(pp->pp_memt, ih, 0, func, arg);
    426  1.1  mrg 
    427  1.1  mrg 	DPRINTF(SPDB_INTR, ("; returning handle %p\n", cookie));
    428  1.1  mrg 	return (cookie);
    429  1.1  mrg }
    430  1.1  mrg 
    431  1.1  mrg void
    432  1.1  mrg pci_intr_disestablish(pc, cookie)
    433  1.1  mrg 	pci_chipset_tag_t pc;
    434  1.1  mrg 	void *cookie;
    435  1.1  mrg {
    436  1.1  mrg 
    437  1.1  mrg 	DPRINTF(SPDB_INTR, ("pci_intr_disestablish: cookie %p\n", cookie));
    438  1.1  mrg 
    439  1.1  mrg 	/* XXX */
    440  1.1  mrg 	panic("can't disestablish PCI interrupts yet");
    441  1.1  mrg }
    442