pci.c revision 1.4.96.1 1 1.4.96.1 uebayasi /* $NetBSD: pci.c,v 1.4.96.1 2010/10/22 07:21:08 uebayasi Exp $ */
2 1.1 sakamoto
3 1.4.96.1 uebayasi /*
4 1.4.96.1 uebayasi * Copyright (C) 1995-1997 Gary Thomas (gdt (at) linuxppc.org)
5 1.1 sakamoto * All rights reserved.
6 1.1 sakamoto *
7 1.4.96.1 uebayasi * Adapted from a program by:
8 1.4.96.1 uebayasi * Steve Sellgren
9 1.4.96.1 uebayasi * San Francisco Indigo Company
10 1.4.96.1 uebayasi * sfindigo!sellgren (at) uunet.uu.net
11 1.4.96.1 uebayasi * Adapted for Moto boxes by:
12 1.4.96.1 uebayasi * Pat Kane & Mark Scott, 1996
13 1.4.96.1 uebayasi * Fixed for IBM/PowerStack II Pat Kane 1997
14 1.1 sakamoto *
15 1.1 sakamoto * Redistribution and use in source and binary forms, with or without
16 1.1 sakamoto * modification, are permitted provided that the following conditions
17 1.1 sakamoto * are met:
18 1.1 sakamoto * 1. Redistributions of source code must retain the above copyright
19 1.1 sakamoto * notice, this list of conditions and the following disclaimer.
20 1.1 sakamoto * 2. Redistributions in binary form must reproduce the above copyright
21 1.1 sakamoto * notice, this list of conditions and the following disclaimer in the
22 1.1 sakamoto * documentation and/or other materials provided with the distribution.
23 1.1 sakamoto * 3. All advertising materials mentioning features or use of this software
24 1.1 sakamoto * must display the following acknowledgement:
25 1.4.96.1 uebayasi * This product includes software developed by Gary Thomas.
26 1.4.96.1 uebayasi * 4. The name of the author may not be used to endorse or promote products
27 1.4.96.1 uebayasi * derived from this software without specific prior written permission.
28 1.1 sakamoto *
29 1.4.96.1 uebayasi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
30 1.4.96.1 uebayasi * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
31 1.4.96.1 uebayasi * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32 1.4.96.1 uebayasi * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
33 1.4.96.1 uebayasi * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
34 1.4.96.1 uebayasi * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 1.4.96.1 uebayasi * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 1.4.96.1 uebayasi * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 1.4.96.1 uebayasi * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
38 1.4.96.1 uebayasi * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 1.1 sakamoto */
40 1.1 sakamoto
41 1.4.96.1 uebayasi #include <lib/libsa/stand.h>
42 1.4.96.1 uebayasi #include <sys/bswap.h>
43 1.1 sakamoto #include <dev/pci/pcireg.h>
44 1.4.96.1 uebayasi #include "boot.h"
45 1.1 sakamoto
46 1.4.96.1 uebayasi #define NSLOTS 5
47 1.4.96.1 uebayasi #define NPCIREGS 10
48 1.1 sakamoto
49 1.4.96.1 uebayasi
50 1.4.96.1 uebayasi /*
51 1.4.96.1 uebayasi * should use devfunc number/indirect method to be totally safe on
52 1.4.96.1 uebayasi * all machines, this works for now on 3 slot Moto boxes
53 1.4.96.1 uebayasi */
54 1.4.96.1 uebayasi
55 1.4.96.1 uebayasi #define PCI_CONFIG_SPACE_BASE 0x80800000
56 1.4.96.1 uebayasi #define PCI_CONFIG_SPACE(d, f) \
57 1.4.96.1 uebayasi (u_long *)(PCI_CONFIG_SPACE_BASE | (1 << (d)) | ((f) << 8))
58 1.4.96.1 uebayasi
59 1.4.96.1 uebayasi struct PCI_ConfigInfo {
60 1.4.96.1 uebayasi u_long *config_addr;
61 1.4.96.1 uebayasi u_long regs[NPCIREGS];
62 1.4.96.1 uebayasi } PCI_slots [NSLOTS] = {
63 1.4.96.1 uebayasi { PCI_CONFIG_SPACE(11, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
64 1.4.96.1 uebayasi { PCI_CONFIG_SPACE(12, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
65 1.4.96.1 uebayasi { PCI_CONFIG_SPACE(13, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
66 1.4.96.1 uebayasi { PCI_CONFIG_SPACE(14, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
67 1.4.96.1 uebayasi { PCI_CONFIG_SPACE(15, 0), { 0xDE, 0xAD, 0xBE, 0xEF } },
68 1.4.96.1 uebayasi };
69 1.4.96.1 uebayasi
70 1.4.96.1 uebayasi
71 1.4.96.1 uebayasi #define DEVID (PCI_ID_REG >> 2)
72 1.4.96.1 uebayasi #define CMD (PCI_COMMAND_STATUS_REG >> 2)
73 1.4.96.1 uebayasi #define CLASS (PCI_CLASS_REG >> 2)
74 1.4.96.1 uebayasi #define BAR_BASE (PCI_MAPREG_START >> 2)
75 1.4.96.1 uebayasi
76 1.4.96.1 uebayasi /*
77 1.4.96.1 uebayasi * The following code modifies the PCI Command register
78 1.4.96.1 uebayasi * to enable memory and I/O accesses.
79 1.4.96.1 uebayasi */
80 1.4.96.1 uebayasi void
81 1.4.96.1 uebayasi enablePCI(int slot, int io, int mem, int master)
82 1.1 sakamoto {
83 1.4.96.1 uebayasi volatile u_char *ppci;
84 1.4.96.1 uebayasi u_char enable = 0;
85 1.4.96.1 uebayasi
86 1.4.96.1 uebayasi if (io)
87 1.4.96.1 uebayasi enable |= PCI_COMMAND_IO_ENABLE;
88 1.4.96.1 uebayasi if (mem)
89 1.4.96.1 uebayasi enable |= PCI_COMMAND_MEM_ENABLE;
90 1.4.96.1 uebayasi if (master)
91 1.4.96.1 uebayasi enable |= PCI_COMMAND_MASTER_ENABLE;
92 1.4.96.1 uebayasi
93 1.4.96.1 uebayasi ppci = (u_char *)&PCI_slots[slot].config_addr[CMD];
94 1.4.96.1 uebayasi *ppci = enable;
95 1.4.96.1 uebayasi __asm volatile("eieio");
96 1.4.96.1 uebayasi }
97 1.4.96.1 uebayasi
98 1.4.96.1 uebayasi void
99 1.4.96.1 uebayasi scanPCI(void)
100 1.4.96.1 uebayasi {
101 1.4.96.1 uebayasi struct PCI_ConfigInfo *pslot;
102 1.4.96.1 uebayasi int slt, r;
103 1.4.96.1 uebayasi
104 1.4.96.1 uebayasi for (slt = 0; slt < NSLOTS; slt++) {
105 1.4.96.1 uebayasi pslot = &PCI_slots[slt];
106 1.4.96.1 uebayasi for (r = 0; r < NPCIREGS; r++)
107 1.4.96.1 uebayasi pslot->regs[r] = bswap32(pslot->config_addr[r]);
108 1.4.96.1 uebayasi }
109 1.4.96.1 uebayasi }
110 1.4.96.1 uebayasi
111 1.4.96.1 uebayasi int
112 1.4.96.1 uebayasi findPCIVga(void)
113 1.4.96.1 uebayasi {
114 1.4.96.1 uebayasi struct PCI_ConfigInfo *pslot;
115 1.4.96.1 uebayasi int theSlot = -1;
116 1.4.96.1 uebayasi int highVgaSlot = -1;
117 1.4.96.1 uebayasi int slt;
118 1.4.96.1 uebayasi
119 1.4.96.1 uebayasi for (slt = 0; slt < NSLOTS; slt++) {
120 1.4.96.1 uebayasi pslot = &PCI_slots[slt];
121 1.4.96.1 uebayasi if (pslot->regs[DEVID] != 0xffffffff) { /* card in slot ? */
122 1.4.96.1 uebayasi if (PCI_CLASS(pslot->regs[CLASS]) ==
123 1.4.96.1 uebayasi PCI_CLASS_DISPLAY) {
124 1.4.96.1 uebayasi highVgaSlot = slt;
125 1.4.96.1 uebayasi if ((pslot->regs[CMD] & 0x03)) { /* did firmware enable it ? */
126 1.4.96.1 uebayasi theSlot = slt;
127 1.4.96.1 uebayasi }
128 1.4.96.1 uebayasi }
129 1.4.96.1 uebayasi }
130 1.4.96.1 uebayasi }
131 1.4.96.1 uebayasi if (theSlot == -1)
132 1.4.96.1 uebayasi theSlot = highVgaSlot;
133 1.1 sakamoto
134 1.4.96.1 uebayasi return theSlot;
135 1.1 sakamoto }
136 1.1 sakamoto
137 1.4.96.1 uebayasi int
138 1.4.96.1 uebayasi PCISlotnum(u_int bus, u_int dev, u_int func)
139 1.1 sakamoto {
140 1.4.96.1 uebayasi u_long *tag;
141 1.4.96.1 uebayasi int i;
142 1.1 sakamoto
143 1.4.96.1 uebayasi if (bus != 0 ||
144 1.4.96.1 uebayasi dev < 11 || dev > 15 ||
145 1.4.96.1 uebayasi func > 7)
146 1.4.96.1 uebayasi return -1;
147 1.4.96.1 uebayasi
148 1.4.96.1 uebayasi tag = PCI_CONFIG_SPACE(dev, func);
149 1.4.96.1 uebayasi for (i = 0; i < sizeof(PCI_slots) / sizeof(struct PCI_ConfigInfo); i++)
150 1.4.96.1 uebayasi if (tag == PCI_slots[i].config_addr)
151 1.4.96.1 uebayasi return i;
152 1.4.96.1 uebayasi return -1;
153 1.1 sakamoto }
154 1.1 sakamoto
155 1.4.96.1 uebayasi /* return Vendor ID of card in the slot */
156 1.4.96.1 uebayasi int
157 1.4.96.1 uebayasi PCIVendor(int slotnum)
158 1.1 sakamoto {
159 1.4.96.1 uebayasi struct PCI_ConfigInfo *pslot;
160 1.1 sakamoto
161 1.4.96.1 uebayasi pslot = &PCI_slots[slotnum];
162 1.1 sakamoto
163 1.4.96.1 uebayasi return pslot->regs[DEVID] & 0xffff;
164 1.4.96.1 uebayasi }
165 1.1 sakamoto
166 1.4.96.1 uebayasi /* return mapped address for I/O or Memory */
167 1.4.96.1 uebayasi u_long
168 1.4.96.1 uebayasi PCIAddress(int slotnum, u_int bar, int type)
169 1.4.96.1 uebayasi {
170 1.4.96.1 uebayasi struct PCI_ConfigInfo *pslot;
171 1.2 sakamoto
172 1.4.96.1 uebayasi if (bar >= 6)
173 1.4.96.1 uebayasi return 0xffffffff;
174 1.1 sakamoto
175 1.4.96.1 uebayasi pslot = &PCI_slots[slotnum];
176 1.1 sakamoto
177 1.4.96.1 uebayasi if (pslot->regs[DEVID] == 0xffffffff ||
178 1.4.96.1 uebayasi PCI_MAPREG_TYPE(pslot->regs[BAR_BASE + bar]) != type)
179 1.4.96.1 uebayasi return 0xffffffff;
180 1.2 sakamoto
181 1.4.96.1 uebayasi return PCI_MAPREG_MEM_ADDR(pslot->regs[BAR_BASE + bar]);
182 1.4.96.1 uebayasi }
183 1.2 sakamoto
184 1.4.96.1 uebayasi #ifdef DEBUG
185 1.4.96.1 uebayasi void
186 1.4.96.1 uebayasi printPCIslots(void)
187 1.4.96.1 uebayasi {
188 1.4.96.1 uebayasi int i;
189 1.4.96.1 uebayasi for (i = 0; i < NSLOTS; i++) {
190 1.4.96.1 uebayasi printf("PCI Slot number: %d", i);
191 1.4.96.1 uebayasi printf(" Vendor ID: 0x%x\n", PCIVendor(i));
192 1.1 sakamoto }
193 1.1 sakamoto }
194 1.4.96.1 uebayasi #endif /* DEBUG */
195