Home | History | Annotate | Line # | Download | only in pci
bandit.c revision 1.8.2.2
      1 /*	$NetBSD: bandit.c,v 1.8.2.2 1999/05/06 19:38:49 perry Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the NetBSD
     22  *	Foundation, Inc. and its contributors.
     23  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  *    contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  * POSSIBILITY OF SUCH DAMAGE.
     38  */
     39 
     40 /*
     41  * Copyright 1991-1998 by Open Software Foundation, Inc.
     42  *              All Rights Reserved
     43  *
     44  * Permission to use, copy, modify, and distribute this software and
     45  * its documentation for any purpose and without fee is hereby granted,
     46  * provided that the above copyright notice appears in all copies and
     47  * that both the copyright notice and this permission notice appear in
     48  * supporting documentation.
     49  *
     50  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
     51  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     52  * FOR A PARTICULAR PURPOSE.
     53  *
     54  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
     55  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
     56  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
     57  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     58  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     59  */
     60 /*
     61  * Copyright 1991-1998 by Apple Computer, Inc.
     62  *              All Rights Reserved
     63  *
     64  * Permission to use, copy, modify, and distribute this software and
     65  * its documentation for any purpose and without fee is hereby granted,
     66  * provided that the above copyright notice appears in all copies and
     67  * that both the copyright notice and this permission notice appear in
     68  * supporting documentation.
     69  *
     70  * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
     71  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     72  * FOR A PARTICULAR PURPOSE.
     73  *
     74  * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
     75  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
     76  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
     77  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     78  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     79  */
     80 
     81 #include <sys/param.h>
     82 #include <sys/device.h>
     83 #include <sys/systm.h>
     84 
     85 #include <dev/pci/pcireg.h>
     86 #include <dev/pci/pcivar.h>
     87 #include <dev/ofw/openfirm.h>
     88 #include <dev/ofw/ofw_pci.h>
     89 
     90 #include <machine/bus.h>
     91 
     92 #define	PCI_BANDIT		11
     93 
     94 #define	PCI_REG_BANDIT_CFG	0x40
     95 #define	PCI_REG_ADDR_MASK	0x48
     96 #define	PCI_REG_MODE_SELECT	0x50
     97 #define	PCI_REG_ARBUS_HOLDOFF	0x58
     98 
     99 #define	PCI_MS_BYTESWAP		0x001	/* Enable Big Endian mode. (R/W)*/
    100 #define	PCI_MS_PASSATOMIC	0x002	/* PCI Bus to ARBus Lock are always allowed (R)*/
    101 #define	PCI_MS_NUMBER_MASK	0x00C	/* PCI Bus Number (R) */
    102 #define	PCI_MS_IS_SYNC		0x010	/* Is Synchronous (1) or Async (0) ? (R)*/
    103 #define	PCI_MS_VGA_SPACE	0x020	/* Map VGA I/O space  (R/W) */
    104 #define	PCI_MS_IO_COHERENT	0x040	/* I/O Coherent (R/W) */
    105 #define	PCI_MS_INT_ENABLE	0x080	/* Allow TEA or PCI Abort INT to pass to Grand Central (R/W) */
    106 
    107 #define	BANDIT_SPECIAL_CYCLE	0xe00000	/* Special Cycle offset */
    108 
    109 static void bandit_init __P((pci_chipset_tag_t));
    110 static void scan_pci_devs __P((int));
    111 static void config_slot __P((int, pci_chipset_tag_t, int));
    112 
    113 void
    114 pci_init(canmap)
    115 	int canmap;
    116 {
    117 
    118 	scan_pci_devs(canmap);
    119 }
    120 
    121 static void
    122 bandit_init(pc)
    123 	pci_chipset_tag_t pc;
    124 {
    125 	u_int status;
    126 	pcitag_t tag;
    127 
    128 	tag = pci_make_tag(pc, 0, PCI_BANDIT, 0);
    129 	if ((pci_conf_read(pc, tag, PCI_ID_REG) & 0xffff) == 0xffff)
    130 		return;
    131 
    132 	status = pci_conf_read(pc, tag, PCI_REG_MODE_SELECT);
    133 
    134 	if ((status & PCI_MS_IO_COHERENT) == 0) {
    135 		status |= PCI_MS_IO_COHERENT;
    136 		pci_conf_write(pc, tag, PCI_REG_MODE_SELECT, status);
    137 	}
    138 }
    139 
    140 
    141 static void
    142 scan_pci_devs(canmap)
    143 	int canmap;
    144 {
    145 	int reglen, node, child, n, is_bandit, is_mpc106;
    146 	char name[64];
    147 	u_int32_t *p, reg[36];
    148 
    149 	bzero(pci_bridges, sizeof(pci_bridges));
    150 
    151 	node = OF_peer(0);
    152 	node = OF_child(node);
    153 
    154 	for (n = 0; node != 0; node = OF_peer(node)) {
    155 		if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
    156 			continue;
    157 
    158 		is_bandit = (strcmp(name, "bandit") == 0 ||
    159 			     strcmp(name, "chaos") == 0) ? 1 : 0;
    160 
    161 		/* XXX for now */
    162 		is_mpc106 = (strcmp(name, "pci") == 0) ? 1 : 0;
    163 
    164 		if (is_bandit == 0 && is_mpc106 == 0)
    165 			continue;
    166 
    167 		/*
    168 		 * Get the "ranges" property.  We're expecting 6 32-bit
    169 		 * values for each address space:
    170 		 *
    171 		 *	phys.hi phys.mid phys.lo host size.hi size.lo
    172 		 *
    173 		 * Note that the MPC106 maps PCI memory space into
    174 		 * two regions, one of which has a 24-bit addressing
    175 		 * mode.  We don't know the order of the "ranges"
    176 		 * property, but both Address Map modes of the MPC106
    177 		 * map the 32-bit memory range at a lower host address
    178 		 * than the 24-bit range.  We always pick the lower
    179 		 * of the memory ranges for this reason.
    180 		 */
    181 
    182 		pci_bridges[n].memt = (bus_space_tag_t) 0xffffffff;
    183 
    184 		reglen = OF_getproplen(node, "ranges");
    185 		if (reglen > sizeof(reg) || reglen <= 0 ||
    186 		    reglen % (6 * sizeof(u_int32_t)) != 0)
    187 			continue;	/* eek */
    188 
    189 		reglen = OF_getprop(node, "ranges", reg, sizeof(reg));
    190 
    191 		for (p = reg; reglen > 0;
    192 		     reglen -= (6 * sizeof(u_int32_t)), p += 6) {
    193 			switch (p[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
    194 			case OFW_PCI_PHYS_HI_SPACE_IO:
    195 				pci_bridges[n].iot =
    196 				    (bus_space_tag_t) p[3];
    197 				break;
    198 
    199 			case OFW_PCI_PHYS_HI_SPACE_MEM32:
    200 #if 0	/* XXX XXX XXX */
    201 				if (pci_bridges[n].memt >
    202 				    (bus_space_tag_t)p[3])
    203 					pci_bridges[n].memt =
    204 					    (bus_space_tag_t) p[3];
    205 #else
    206 				/*
    207 				 * XXX The Power Mac firmware seems to
    208 				 * XXX include the PCI memory space base
    209 				 * XXX in the device's BARs.  We can remove
    210 				 * XXX this kludge from here once we
    211 				 * XXX fix the bus_space(9) implelentation.
    212 				 */
    213 				pci_bridges[n].memt = (bus_space_tag_t) 0;
    214 #endif
    215 				break;
    216 
    217 			/* XXX What about OFW_PCI_PHYS_HI_SPACE_MEM64? */
    218 			}
    219 		}
    220 
    221 		/*
    222 		 * The "bus-range" property tells us our PCI bus number.
    223 		 */
    224 		if (OF_getprop(node, "bus-range", reg, sizeof(reg)) != 8)
    225 			continue;
    226 
    227 		pci_bridges[n].bus = reg[0];
    228 		pci_bridges[n].present = 1;
    229 
    230 		/*
    231 		 * Map the PCI configuration space access registers,
    232 		 * and perform any PCI-Host bridge initialization.
    233 		 */
    234 		if (is_bandit) {
    235 			/* XXX magic numbers */
    236 			pci_bridges[n].pc = n;
    237 			if (canmap) {
    238 				if (OF_getprop(node, "reg", reg,
    239 				    sizeof(reg)) != 8)
    240 					continue;
    241 				pci_bridges[n].addr =
    242 				    mapiodev(reg[0] + 0x800000, 4);
    243 				pci_bridges[n].data =
    244 				    mapiodev(reg[0] + 0xc00000, 4);
    245 				bandit_init(n);
    246 			}
    247 		} else if (is_mpc106) {
    248 			/* XXX magic numbers */
    249 			pci_bridges[n].pc = PCI_CHIPSET_MPC106; /* for now */
    250 			if (canmap) {
    251 				pci_bridges[n].addr = mapiodev(0xfec00000, 4);
    252 				pci_bridges[n].data = mapiodev(0xfee00000, 4);
    253 			}
    254 		}
    255 
    256 		if (canmap) {
    257 			/*
    258 			 * Configure all of the PCI devices attached to this
    259 			 * PCI-Host bridge.
    260 			 */
    261 			child = OF_child(node);
    262 			while (child) {
    263 				config_slot(child, pci_bridges[n].pc, -1);
    264 				child = OF_peer(child);
    265 			}
    266 		}
    267 
    268 		/* Bridge found, increment bridge instance. */
    269 		n++;
    270 	}
    271 }
    272 
    273 static void
    274 config_slot(node, pc, irq)
    275 	int node;
    276 	pci_chipset_tag_t pc;
    277 	int irq;
    278 {
    279 	pcitag_t tag;
    280 	pcireg_t csr, intr;
    281 	int i, sz;
    282 	int bus, dev, func;
    283 	u_int32_t reg[40], *rp;
    284 	char name[16];
    285 	struct {
    286 		u_int32_t device;
    287 		u_int32_t junk[3];
    288 		u_int32_t intrnode;
    289 		u_int32_t interrupt;
    290 	} imap[16];
    291 
    292 	bzero(name, sizeof(name));
    293 	OF_getprop(node, "name", name, sizeof(name));
    294 	if (strcmp(name, "pci-bridge") == 0) {
    295 		if (irq == -1)
    296 			OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq));
    297 
    298 		node = OF_child(node);
    299 		while (node) {
    300 			config_slot(node, pc, irq);
    301 			node = OF_peer(node);
    302 		}
    303 		return;
    304 	}
    305 
    306 	sz = OF_getprop(node, "assigned-addresses", reg, sizeof(reg));
    307 	if (sz < 4)
    308 		return;
    309 
    310 	rp = reg;
    311 	bus = (rp[0] & OFW_PCI_PHYS_HI_BUSMASK) >>
    312 	    OFW_PCI_PHYS_HI_BUSSHIFT;
    313 	dev = (rp[0] & OFW_PCI_PHYS_HI_DEVICEMASK) >>
    314 	    OFW_PCI_PHYS_HI_DEVICESHIFT;
    315 	func = (rp[0] & OFW_PCI_PHYS_HI_FUNCTIONMASK) >>
    316 	    OFW_PCI_PHYS_HI_FUNCTIONSHIFT;
    317 
    318 	tag = pci_make_tag(pc, bus, dev, func);
    319 	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
    320 
    321 	/*
    322 	 * Make sure the IO and MEM enable bits are set in the CSR.
    323 	 */
    324 	csr &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
    325 	for (; sz > 0; sz -= 5 * sizeof(u_int32_t), rp += 5) {
    326 		switch (rp[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
    327 		case OFW_PCI_PHYS_HI_SPACE_IO:
    328 			csr |= PCI_COMMAND_IO_ENABLE;
    329 			break;
    330 
    331 		case OFW_PCI_PHYS_HI_SPACE_MEM32:
    332 			csr |= PCI_COMMAND_MEM_ENABLE;
    333 			break;
    334 		}
    335 	}
    336 
    337 	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
    338 
    339 	/*
    340 	 * Make sure the line register is programmed with the interrupt
    341 	 * mapping.
    342 	 */
    343 	if (irq == -1 &&
    344 	    OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq)) == -1 &&
    345 	    OF_getprop(node, "interrupts", &irq, sizeof(irq)) == -1)
    346 		return;
    347 
    348 	if (irq == 1) {		/* XXX */
    349 		sz = OF_getprop(OF_parent(node), "interrupt-map",
    350 		    imap, sizeof(imap));
    351 		if (sz != -1) {
    352 			for (i = 0; i < sz / sizeof(*imap); i++) {
    353 				/* XXX should use interrupt-map-mask */
    354 				if (((imap[i].device &
    355 				      OFW_PCI_PHYS_HI_DEVICEMASK) >>
    356 				     OFW_PCI_PHYS_HI_DEVICESHIFT) == dev) {
    357 					irq = imap[i].interrupt;
    358 					break;
    359 				}
    360 			}
    361 		}
    362 	}
    363 
    364 	intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
    365 	intr = (intr & ~PCI_INTERRUPT_LINE_MASK) |
    366 	    (irq & PCI_INTERRUPT_LINE_MASK);
    367 	pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
    368 }
    369