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