Home | History | Annotate | Line # | Download | only in pci
bandit.c revision 1.10
      1 /*	$NetBSD: bandit.c,v 1.10 1999/05/05 08:43:53 tsubai 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((void));
    111 static void config_slot __P((int, pci_chipset_tag_t, int));
    112 
    113 void
    114 pci_init()
    115 {
    116 
    117 	scan_pci_devs();
    118 }
    119 
    120 static void
    121 bandit_init(pc)
    122 	pci_chipset_tag_t pc;
    123 {
    124 	u_int status;
    125 	pcitag_t tag;
    126 
    127 	tag = pci_make_tag(pc, 0, PCI_BANDIT, 0);
    128 	if ((pci_conf_read(pc, tag, PCI_ID_REG) & 0xffff) == 0xffff)
    129 		return;
    130 
    131 	status = pci_conf_read(pc, tag, PCI_REG_MODE_SELECT);
    132 
    133 	if ((status & PCI_MS_IO_COHERENT) == 0) {
    134 		status |= PCI_MS_IO_COHERENT;
    135 		pci_conf_write(pc, tag, PCI_REG_MODE_SELECT, status);
    136 	}
    137 }
    138 
    139 
    140 static void
    141 scan_pci_devs()
    142 {
    143 	int reglen, node, child, n, is_bandit, is_mpc106;
    144 	char name[64];
    145 	u_int32_t *p, reg[36];
    146 
    147 	bzero(pci_bridges, sizeof(pci_bridges));
    148 
    149 	node = OF_peer(0);
    150 	node = OF_child(node);
    151 
    152 	for (n = 0; node != 0; node = OF_peer(node)) {
    153 		if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
    154 			continue;
    155 
    156 		is_bandit = (strcmp(name, "bandit") == 0 ||
    157 			     strcmp(name, "chaos") == 0) ? 1 : 0;
    158 
    159 		/* XXX for now */
    160 		is_mpc106 = (strcmp(name, "pci") == 0) ? 1 : 0;
    161 
    162 		if (is_bandit == 0 && is_mpc106 == 0)
    163 			continue;
    164 
    165 		/*
    166 		 * Get the "ranges" property.  We're expecting 6 32-bit
    167 		 * values for each address space:
    168 		 *
    169 		 *	phys.hi phys.mid phys.lo host size.hi size.lo
    170 		 *
    171 		 * Note that the MPC106 maps PCI memory space into
    172 		 * two regions, one of which has a 24-bit addressing
    173 		 * mode.  We don't know the order of the "ranges"
    174 		 * property, but both Address Map modes of the MPC106
    175 		 * map the 32-bit memory range at a lower host address
    176 		 * than the 24-bit range.  We always pick the lower
    177 		 * of the memory ranges for this reason.
    178 		 */
    179 
    180 		pci_bridges[n].memt = (bus_space_tag_t) 0xffffffff;
    181 
    182 		reglen = OF_getproplen(node, "ranges");
    183 		if (reglen > sizeof(reg) || reglen <= 0 ||
    184 		    reglen % (6 * sizeof(u_int32_t)) != 0)
    185 			continue;	/* eek */
    186 
    187 		reglen = OF_getprop(node, "ranges", reg, sizeof(reg));
    188 
    189 		for (p = reg; reglen > 0;
    190 		     reglen -= (6 * sizeof(u_int32_t)), p += 6) {
    191 			switch (p[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
    192 			case OFW_PCI_PHYS_HI_SPACE_IO:
    193 				pci_bridges[n].iot =
    194 				    (bus_space_tag_t) p[3];
    195 				break;
    196 
    197 			case OFW_PCI_PHYS_HI_SPACE_MEM32:
    198 #if 0	/* XXX XXX XXX */
    199 				if (pci_bridges[n].memt >
    200 				    (bus_space_tag_t)p[3])
    201 					pci_bridges[n].memt =
    202 					    (bus_space_tag_t) p[3];
    203 #else
    204 				/*
    205 				 * XXX The Power Mac firmware seems to
    206 				 * XXX include the PCI memory space base
    207 				 * XXX in the device's BARs.  We can remove
    208 				 * XXX this kludge from here once we
    209 				 * XXX fix the bus_space(9) implelentation.
    210 				 */
    211 				pci_bridges[n].memt = (bus_space_tag_t) 0;
    212 #endif
    213 				break;
    214 
    215 			/* XXX What about OFW_PCI_PHYS_HI_SPACE_MEM64? */
    216 			}
    217 		}
    218 
    219 		/*
    220 		 * The "bus-range" property tells us our PCI bus number.
    221 		 */
    222 		if (OF_getprop(node, "bus-range", reg, sizeof(reg)) != 8)
    223 			continue;
    224 
    225 		pci_bridges[n].bus = reg[0];
    226 
    227 		/*
    228 		 * Map the PCI configuration space access registers,
    229 		 * and perform any PCI-Host bridge initialization.
    230 		 */
    231 		if (is_bandit) {
    232 			/* XXX magic numbers */
    233 			if (OF_getprop(node, "reg", reg, sizeof(reg)) != 8)
    234 				continue;
    235 			pci_bridges[n].addr = mapiodev(reg[0] + 0x800000, 4);
    236 			pci_bridges[n].data = mapiodev(reg[0] + 0xc00000, 4);
    237 			pci_bridges[n].pc = n;
    238 			bandit_init(n);
    239 		} else if (is_mpc106) {
    240 			/* XXX magic numbers */
    241 			pci_bridges[n].addr = mapiodev(0xfec00000, 4);
    242 			pci_bridges[n].data = mapiodev(0xfee00000, 4);
    243 			pci_bridges[n].pc = PCI_CHIPSET_MPC106; /* for now */
    244 		}
    245 
    246 		/*
    247 		 * Configure all of the PCI devices attached to this
    248 		 * PCI-Host bridge.
    249 		 */
    250 		child = OF_child(node);
    251 		while (child) {
    252 			config_slot(child, pci_bridges[n].pc, -1);
    253 			child = OF_peer(child);
    254 		}
    255 
    256 		/* Bridge found, increment bridge instance. */
    257 		n++;
    258 	}
    259 }
    260 
    261 static void
    262 config_slot(node, pc, irq)
    263 	int node;
    264 	pci_chipset_tag_t pc;
    265 	int irq;
    266 {
    267 	pcitag_t tag;
    268 	pcireg_t csr, intr;
    269 	int i, sz;
    270 	int bus, dev, func;
    271 	u_int32_t reg[40], *rp;
    272 	char name[16];
    273 	struct {
    274 		u_int32_t device;
    275 		u_int32_t junk[3];
    276 		u_int32_t intrnode;
    277 		u_int32_t interrupt;
    278 	} imap[16];
    279 
    280 	bzero(name, sizeof(name));
    281 	OF_getprop(node, "name", name, sizeof(name));
    282 	if (strcmp(name, "pci-bridge") == 0) {
    283 		if (irq == -1)
    284 			OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq));
    285 
    286 		node = OF_child(node);
    287 		while (node) {
    288 			config_slot(node, pc, irq);
    289 			node = OF_peer(node);
    290 		}
    291 		return;
    292 	}
    293 
    294 	sz = OF_getprop(node, "assigned-addresses", reg, sizeof(reg));
    295 	if (sz < 4)
    296 		return;
    297 
    298 	rp = reg;
    299 	bus = (rp[0] & OFW_PCI_PHYS_HI_BUSMASK) >>
    300 	    OFW_PCI_PHYS_HI_BUSSHIFT;
    301 	dev = (rp[0] & OFW_PCI_PHYS_HI_DEVICEMASK) >>
    302 	    OFW_PCI_PHYS_HI_DEVICESHIFT;
    303 	func = (rp[0] & OFW_PCI_PHYS_HI_FUNCTIONMASK) >>
    304 	    OFW_PCI_PHYS_HI_FUNCTIONSHIFT;
    305 
    306 	tag = pci_make_tag(pc, bus, dev, func);
    307 	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
    308 
    309 	/*
    310 	 * Make sure the IO and MEM enable bits are set in the CSR.
    311 	 */
    312 	csr &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
    313 	for (; sz > 0; sz -= 5 * sizeof(u_int32_t), rp += 5) {
    314 		switch (rp[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
    315 		case OFW_PCI_PHYS_HI_SPACE_IO:
    316 			csr |= PCI_COMMAND_IO_ENABLE;
    317 			break;
    318 
    319 		case OFW_PCI_PHYS_HI_SPACE_MEM32:
    320 			csr |= PCI_COMMAND_MEM_ENABLE;
    321 			break;
    322 		}
    323 	}
    324 
    325 	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
    326 
    327 	/*
    328 	 * Make sure the line register is programmed with the interrupt
    329 	 * mapping.
    330 	 */
    331 	if (irq == -1 &&
    332 	    OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq)) == -1 &&
    333 	    OF_getprop(node, "interrupts", &irq, sizeof(irq)) == -1)
    334 		return;
    335 
    336 	if (irq == 1) {		/* XXX */
    337 		sz = OF_getprop(OF_parent(node), "interrupt-map",
    338 		    imap, sizeof(imap));
    339 		if (sz != -1) {
    340 			for (i = 0; i < sz / sizeof(*imap); i++) {
    341 				/* XXX should use interrupt-map-mask */
    342 				if (((imap[i].device &
    343 				      OFW_PCI_PHYS_HI_DEVICEMASK) >>
    344 				     OFW_PCI_PHYS_HI_DEVICESHIFT) == dev) {
    345 					irq = imap[i].interrupt;
    346 					break;
    347 				}
    348 			}
    349 		}
    350 	}
    351 
    352 	intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
    353 	intr = (intr & ~PCI_INTERRUPT_LINE_MASK) |
    354 	    (irq & PCI_INTERRUPT_LINE_MASK);
    355 	pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
    356 }
    357