xref: /netbsd-src/sys/arch/prep/stand/boot/pci.c (revision cde8f271ec30c028c5652673e0e3c4a6298637d1)
1*cde8f271Sriastradh /*	$NetBSD: pci.c,v 1.3 2022/02/16 23:49:27 riastradh Exp $	*/
2158f609aSkiyohara 
3158f609aSkiyohara /*
4158f609aSkiyohara  * Copyright (C) 1995-1997 Gary Thomas (gdt@linuxppc.org)
5158f609aSkiyohara  * All rights reserved.
6158f609aSkiyohara  *
7158f609aSkiyohara  * Adapted from a program by:
8158f609aSkiyohara  *                                      Steve Sellgren
9158f609aSkiyohara  *                                      San Francisco Indigo Company
10158f609aSkiyohara  *                                      sfindigo!sellgren@uunet.uu.net
11158f609aSkiyohara  * Adapted for Moto boxes by:
12158f609aSkiyohara  *                                      Pat Kane & Mark Scott, 1996
13158f609aSkiyohara  * Fixed for IBM/PowerStack II          Pat Kane 1997
14158f609aSkiyohara  *
15158f609aSkiyohara  * Redistribution and use in source and binary forms, with or without
16158f609aSkiyohara  * modification, are permitted provided that the following conditions
17158f609aSkiyohara  * are met:
18158f609aSkiyohara  * 1. Redistributions of source code must retain the above copyright
19158f609aSkiyohara  *    notice, this list of conditions and the following disclaimer.
20158f609aSkiyohara  * 2. Redistributions in binary form must reproduce the above copyright
21158f609aSkiyohara  *    notice, this list of conditions and the following disclaimer in the
22158f609aSkiyohara  *    documentation and/or other materials provided with the distribution.
23158f609aSkiyohara  * 3. All advertising materials mentioning features or use of this software
24158f609aSkiyohara  *    must display the following acknowledgement:
25158f609aSkiyohara  *      This product includes software developed by Gary Thomas.
26158f609aSkiyohara  * 4. The name of the author may not be used to endorse or promote products
27158f609aSkiyohara  *    derived from this software without specific prior written permission.
28158f609aSkiyohara  *
29158f609aSkiyohara  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
30158f609aSkiyohara  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
31158f609aSkiyohara  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32158f609aSkiyohara  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
33158f609aSkiyohara  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
34158f609aSkiyohara  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35158f609aSkiyohara  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36158f609aSkiyohara  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37158f609aSkiyohara  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
38158f609aSkiyohara  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39158f609aSkiyohara  */
40158f609aSkiyohara 
41158f609aSkiyohara #include <lib/libsa/stand.h>
42158f609aSkiyohara #include <sys/bswap.h>
43158f609aSkiyohara #include <dev/pci/pcireg.h>
44158f609aSkiyohara 
45158f609aSkiyohara #include "boot.h"
46158f609aSkiyohara 
47158f609aSkiyohara #define PCI_NSLOTS	8
48158f609aSkiyohara #define PCI_NREGS	10
49158f609aSkiyohara 
50158f609aSkiyohara /*
51158f609aSkiyohara  * should use devfunc number/indirect method to be totally safe on
52158f609aSkiyohara  * all machines, this works for now on 3 slot Moto boxes
53158f609aSkiyohara  */
54158f609aSkiyohara 
55158f609aSkiyohara #define PCI_CONFIG_SPACE_BASE	0x80800000
56158f609aSkiyohara #define PCI_CONFIG_SPACE(d, f)	\
57158f609aSkiyohara 		(u_long *)(PCI_CONFIG_SPACE_BASE | (1 << (d)) | ((f) << 8))
58158f609aSkiyohara 
59158f609aSkiyohara #define DEVID		(PCI_ID_REG >> 2)
60158f609aSkiyohara #define CMD		(PCI_COMMAND_STATUS_REG >> 2)
61158f609aSkiyohara #define CLASS		(PCI_CLASS_REG >> 2)
62158f609aSkiyohara #define BAR_BASE	(PCI_MAPREG_START >> 2)
63158f609aSkiyohara 
64158f609aSkiyohara struct PCI_cinfo {
65158f609aSkiyohara 	u_long *config_addr;
66158f609aSkiyohara 	u_long regs[PCI_NREGS];
67158f609aSkiyohara } PCI_slots[PCI_NSLOTS] = {
68158f609aSkiyohara 	{ (u_long *)0x80808000, {0xDEADBEEF,} },
69158f609aSkiyohara 	{ (u_long *)0x80800800, {0xDEADBEEF,} },
70158f609aSkiyohara 	{ (u_long *)0x80801000, {0xDEADBEEF,} },
71158f609aSkiyohara 	{ (u_long *)0x80802000, {0xDEADBEEF,} },
72158f609aSkiyohara 	{ (u_long *)0x80804000, {0xDEADBEEF,} },
73158f609aSkiyohara 	{ (u_long *)0x80810000, {0xDEADBEEF,} },
74158f609aSkiyohara 	{ (u_long *)0x80820000, {0xDEADBEEF,} },
75158f609aSkiyohara 	{ (u_long *)0x80840000, {0xDEADBEEF,} },
76158f609aSkiyohara };
77158f609aSkiyohara 
78158f609aSkiyohara /*
79158f609aSkiyohara  * The following code modifies the PCI Command register
80158f609aSkiyohara  * to enable memory and I/O accesses.
81158f609aSkiyohara  */
82158f609aSkiyohara void
enablePCI(int slot,int io,int mem,int master)83158f609aSkiyohara enablePCI(int slot, int io, int mem, int master)
84158f609aSkiyohara {
85158f609aSkiyohara 	volatile u_char *ppci;
86158f609aSkiyohara 	u_char enable = 0;
87158f609aSkiyohara 
88158f609aSkiyohara 	if (io)
89158f609aSkiyohara 		enable |= PCI_COMMAND_IO_ENABLE;
90158f609aSkiyohara 	if (mem)
91158f609aSkiyohara 		enable |= PCI_COMMAND_MEM_ENABLE;
92158f609aSkiyohara 	if (master)
93158f609aSkiyohara 		enable |= PCI_COMMAND_MASTER_ENABLE;
94158f609aSkiyohara 
95158f609aSkiyohara 	ppci = (u_char *)&PCI_slots[slot].config_addr[CMD];
96158f609aSkiyohara 	*ppci = enable;
97*cde8f271Sriastradh 	__asm volatile("eieio" ::: "memory");
98158f609aSkiyohara }
99158f609aSkiyohara 
100158f609aSkiyohara int
PCISlotnum(u_int bus,u_int dev,u_int func)101158f609aSkiyohara PCISlotnum(u_int bus, u_int dev, u_int func)
102158f609aSkiyohara {
103158f609aSkiyohara 	u_long *tag;
104158f609aSkiyohara 	int i;
105158f609aSkiyohara 
106158f609aSkiyohara 	if (bus != 0 ||
107158f609aSkiyohara 	    dev < 8 || dev > 18 ||
108158f609aSkiyohara 	    func > 7)
109158f609aSkiyohara 		return -1;
110158f609aSkiyohara 
111158f609aSkiyohara 	tag = PCI_CONFIG_SPACE(dev, func);
112158f609aSkiyohara 	for (i = 0; i < sizeof(PCI_slots) / sizeof(struct PCI_cinfo); i++)
113158f609aSkiyohara 		if (tag == PCI_slots[i].config_addr)
114158f609aSkiyohara 			return i;
115158f609aSkiyohara 	return -1;
116158f609aSkiyohara }
117158f609aSkiyohara 
118158f609aSkiyohara /* return mapped address for I/O or Memory */
119158f609aSkiyohara u_long
PCIAddress(int slotnum,u_int bar,int type)120158f609aSkiyohara PCIAddress(int slotnum, u_int bar, int type)
121158f609aSkiyohara {
122158f609aSkiyohara 	struct PCI_cinfo *pslot;
123158f609aSkiyohara 
124158f609aSkiyohara 	if (bar >= 6)
125158f609aSkiyohara 		return 0xffffffff;
126158f609aSkiyohara 
127158f609aSkiyohara 	pslot = &PCI_slots[slotnum];
128158f609aSkiyohara 
129158f609aSkiyohara 	if (pslot->regs[DEVID] == 0xffffffff ||
130158f609aSkiyohara 	    PCI_MAPREG_TYPE(pslot->regs[BAR_BASE + bar]) != type)
131158f609aSkiyohara 		return 0xffffffff;
132158f609aSkiyohara 
133158f609aSkiyohara 	return PCI_MAPREG_MEM_ADDR(pslot->regs[BAR_BASE + bar]);
134158f609aSkiyohara }
135158f609aSkiyohara 
136158f609aSkiyohara void
unlockVideo(int slot)137158f609aSkiyohara unlockVideo(int slot)
138158f609aSkiyohara {
139158f609aSkiyohara 	volatile u_int8_t *ppci;
140158f609aSkiyohara 
141158f609aSkiyohara 	ppci = (u_int8_t *)PCI_slots[slot].config_addr;
142158f609aSkiyohara 	ppci[4] = 0x0003;	/* enable memory and IO Access */
143158f609aSkiyohara #if 0
144158f609aSkiyohara 	ppci[0x10] = 0x00000;	/* Turn off memory mapping */
145158f609aSkiyohara 	ppci[0x11] = 0x00000;	/* mem base = 0 */
146158f609aSkiyohara 	ppci[0x12] = 0x00000;
147158f609aSkiyohara 	ppci[0x13] = 0x00000;
148158f609aSkiyohara #endif
149*cde8f271Sriastradh 	__asm__ volatile("eieio" ::: "memory");
150158f609aSkiyohara 
151158f609aSkiyohara 	outb(0x3d4, 0x11);
152158f609aSkiyohara 	outb(0x3d5, 0x0e);   /* unlock CR0-CR7 */
153158f609aSkiyohara }
154158f609aSkiyohara 
155158f609aSkiyohara int
scan_PCI(int start)156158f609aSkiyohara scan_PCI(int start)
157158f609aSkiyohara {
158158f609aSkiyohara 	int slot, r;
159158f609aSkiyohara 	struct PCI_cinfo *pslot;
160158f609aSkiyohara 	int VGAslot = -1;
161158f609aSkiyohara 
162158f609aSkiyohara 	for (slot = start + 1; slot < PCI_NSLOTS; slot++) {
163158f609aSkiyohara 		pslot = &PCI_slots[slot];
164158f609aSkiyohara 		for (r = 0; r < PCI_NREGS; r++)
165158f609aSkiyohara 			pslot->regs[r] = bswap32(pslot->config_addr[r]);
166158f609aSkiyohara 		if (pslot->regs[DEVID] != 0xffffffff) {
167158f609aSkiyohara 			/* we have a card */
168158f609aSkiyohara 			if (((pslot->regs[CLASS] & 0xffffff00) ==
169158f609aSkiyohara 				0x03000000) ||
170158f609aSkiyohara 			    ((pslot->regs[CLASS] & 0xffffff00) ==
171158f609aSkiyohara 				0x00010000)) {
172158f609aSkiyohara 				/* it's a VGA card */
173158f609aSkiyohara 				if ((pslot->regs[CMD] & 0x03)) {
174158f609aSkiyohara 					/* fW enabled it */
175158f609aSkiyohara 					VGAslot = slot;
176158f609aSkiyohara 					break;
177158f609aSkiyohara 				}
178158f609aSkiyohara 			}
179158f609aSkiyohara 		}
180158f609aSkiyohara 	}
181158f609aSkiyohara 	return VGAslot;
182158f609aSkiyohara }
183158f609aSkiyohara 
184158f609aSkiyohara int
PCI_vendor(int slotnum)185158f609aSkiyohara PCI_vendor(int slotnum)
186158f609aSkiyohara {
187158f609aSkiyohara 	struct PCI_cinfo *pslot = &PCI_slots[slotnum];
188158f609aSkiyohara 
189158f609aSkiyohara 	return (pslot->regs[DEVID] & 0xffff);
190158f609aSkiyohara }
191