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