UbixOS V2 2.0

pci.c
Go to the documentation of this file.
1 /*-
2 * Copyright (c) 2002-2018 The UbixOS Project.
3 * All rights reserved.
4 *
5 * This was developed by Christopher W. Olsen for the UbixOS Project.
6 *
7 * Redistribution and use in source and binary forms, with or without modification, are permitted
8 * provided that the following conditions are met:
9 *
10 * 1) Redistributions of source code must retain the above copyright notice, this list of
11 * conditions, the following disclaimer and the list of authors.
12 * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
13 * conditions, the following disclaimer and the list of authors in the documentation and/or
14 * other materials provided with the distribution.
15 * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
16 * endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <pci/pci.h>
30 #include <sys/io.h>
31 #include <lib/kprintf.h>
32
33 const struct {
34 uInt8 baseClass;
35 uInt8 subClass;
36 uInt8 interface;
37 const char* name;
38 } pciClasses[] = { { 0x00, 0x00, 0x00, "Undefined" }, { 0x00, 0x01, 0x00, "VGA" },
39
40 { 0x01, 0x00, 0x00, "SCSI" }, { 0x01, 0x01, 0x00, "IDE" }, { 0x01, 0x01, 0x8A, "IDE" }, { 0x01, 0x02, 0x00, "Floppy" }, { 0x01, 0x03, 0x00, "IPI" }, { 0x01, 0x04, 0x00, "RAID" }, { 0x01, 0x80, 0x00, "Other" },
41
42 { 0x02, 0x00, 0x00, "Ethernet" }, { 0x02, 0x01, 0x00, "Token Ring" }, { 0x02, 0x02, 0x00, "FDDI" }, { 0x02, 0x03, 0x00, "ATM" }, { 0x02, 0x04, 0x00, "ISDN" }, { 0x02, 0x80, 0x00, "Other" },
43
44 { 0x03, 0x00, 0x00, "VGA" }, { 0x03, 0x00, 0x01, "VGA+8514" }, { 0x03, 0x01, 0x00, "XGA" }, { 0x03, 0x02, 0x00, "3D" }, { 0x03, 0x80, 0x00, "VGA Other" },
45
46 { 0x04, 0x00, 0x00, "Video" }, { 0x04, 0x01, 0x00, "Audio" }, { 0x04, 0x02, 0x00, "Telephony" }, { 0x04, 0x80, 0x00, "Other" },
47
48 { 0x05, 0x00, 0x00, "RAM" }, { 0x05, 0x01, 0x00, "Flash" }, { 0x05, 0x80, 0x00, "Other" },
49
50 { 0x06, 0x00, 0x00, "PCI to HOST" }, { 0x06, 0x01, 0x00, "PCI to ISA" }, { 0x06, 0x02, 0x00, "PCI to EISA" }, { 0x06, 0x03, 0x00, "PCI to MCA" }, { 0x06, 0x04, 0x00, "PCI to PCI" }, { 0x06, 0x04, 0x01, "PCI to PCI (Subtractive Decode)" }, { 0x06, 0x05, 0x00, "PCI to PCMCIA" }, { 0x06, 0x06, 0x00, "PCI to NuBUS" }, { 0x06, 0x07, 0x00, "PCI to Cardbus" }, { 0x06, 0x08, 0x00, "PCI to RACEway" }, { 0x06, 0x09, 0x00, "PCI to PCI" }, { 0x06, 0x0A, 0x00, "PCI to InfiBand" }, { 0x06, 0x80, 0x00, "PCI to Other" },
51
52 { 0x07, 0x00, 0x00, "Serial" }, { 0x07, 0x00, 0x01, "Serial - 16450" }, { 0x07, 0x00, 0x02, "Serial - 16550" }, { 0x07, 0x00, 0x03, "Serial - 16650" }, { 0x07, 0x00, 0x04, "Serial - 16750" }, { 0x07, 0x00, 0x05, "Serial - 16850" }, { 0x07, 0x00, 0x06, "Serial - 16950" }, { 0x07, 0x01, 0x00, "Parallel" }, { 0x07, 0x01, 0x01, "Parallel - BiDir" }, { 0x07, 0x01, 0x02, "Parallel - ECP" }, { 0x07, 0x01, 0x03, "Parallel - IEEE1284" }, { 0x07, 0x01, 0xFE, "Parallel - IEEE1284 Target" }, { 0x07, 0x02, 0x00, "Multiport Serial" }, { 0x07, 0x03, 0x00, "Hayes Compatible Modem" }, { 0x07, 0x03, 0x01, "Hayes Compatible Modem, 16450" }, { 0x07, 0x03, 0x02, "Hayes Compatible Modem, 16550" }, { 0x07, 0x03, 0x03, "Hayes Compatible Modem, 16650" }, { 0x07, 0x03, 0x04, "Hayes Compatible Modem, 16750" }, { 0x07, 0x80, 0x00, "Other" },
53
54 { 0x08, 0x00, 0x00, "PIC" }, { 0x08, 0x00, 0x01, "ISA PIC" }, { 0x08, 0x00, 0x02, "EISA PIC" }, { 0x08, 0x00, 0x10, "I/O APIC" }, { 0x08, 0x00, 0x20, "I/O(x) APIC" }, { 0x08, 0x01, 0x00, "DMA" }, { 0x08, 0x01, 0x01, "ISA DMA" }, { 0x08, 0x01, 0x02, "EISA DMA" }, { 0x08, 0x02, 0x00, "Timer" }, { 0x08, 0x02, 0x01, "ISA Timer" }, { 0x08, 0x02, 0x02, "EISA Timer" }, { 0x08, 0x03, 0x00, "RTC" }, { 0x08, 0x03, 0x00, "ISA RTC" }, { 0x08, 0x03, 0x00, "Hot-Plug" }, { 0x08, 0x80, 0x00, "Other" },
55
56 { 0x09, 0x00, 0x00, "Keyboard" }, { 0x09, 0x01, 0x00, "Pen" }, { 0x09, 0x02, 0x00, "Mouse" }, { 0x09, 0x03, 0x00, "Scanner" }, { 0x09, 0x04, 0x00, "Game Port" }, { 0x09, 0x80, 0x00, "Other" },
57
58 { 0x0a, 0x00, 0x00, "Generic" }, { 0x0a, 0x80, 0x00, "Other" },
59
60 { 0x0b, 0x00, 0x00, "386" }, { 0x0b, 0x01, 0x00, "486" }, { 0x0b, 0x02, 0x00, "Pentium" }, { 0x0b, 0x03, 0x00, "PentiumPro" }, { 0x0b, 0x10, 0x00, "DEC Alpha" }, { 0x0b, 0x20, 0x00, "PowerPC" }, { 0x0b, 0x30, 0x00, "MIPS" }, { 0x0b, 0x40, 0x00, "Coprocessor" }, { 0x0b, 0x80, 0x00, "Other" },
61
62 { 0x0c, 0x00, 0x00, "FireWire" }, { 0x0c, 0x00, 0x10, "OHCI FireWire" }, { 0x0c, 0x01, 0x00, "Access.bus" }, { 0x0c, 0x02, 0x00, "SSA" }, { 0x0c, 0x03, 0x00, "USB (UHCI)" }, { 0x0c, 0x03, 0x10, "USB (OHCI)" }, { 0x0c, 0x03, 0x80, "USB" }, { 0x0c, 0x03, 0xFE, "USB Device" }, { 0x0c, 0x04, 0x00, "Fiber" }, { 0x0c, 0x05, 0x00, "SMBus Controller" }, { 0x0c, 0x06, 0x00, "InfiniBand" }, { 0x0c, 0x80, 0x00, "Other" },
63
64 { 0x0d, 0x00, 0x00, "iRDA" }, { 0x0d, 0x01, 0x00, "Consumer IR" }, { 0x0d, 0x10, 0x00, "RF" }, { 0x0d, 0x80, 0x00, "Other" },
65
66 { 0x0e, 0x00, 0x00, "I2O" }, { 0x0e, 0x80, 0x00, "Other" },
67
68 { 0x0f, 0x01, 0x00, "TV" }, { 0x0f, 0x02, 0x00, "Audio" }, { 0x0f, 0x03, 0x00, "Voice" }, { 0x0f, 0x04, 0x00, "Data" }, { 0x0f, 0x80, 0x00, "Other" },
69
70 { 0x10, 0x00, 0x00, "Network" }, { 0x10, 0x10, 0x00, "Entertainment" }, { 0x10, 0x80, 0x00, "Other" },
71
72 { 0x11, 0x00, 0x00, "DPIO Modules" }, { 0x11, 0x01, 0x00, "Performance Counters" }, { 0x11, 0x10, 0x00, "Comm Sync, Time+Frequency Measurement" }, { 0x11, 0x80, 0x00, "Other" },
73
74 };
75
76 uInt32 pciRead(int bus, int dev, int func, int reg, int bytes) {
77 uInt16 base;
78
79 union {
80 struct confadd c;
81 uInt32 n;
82 } u;
83
84 u.n = 0;
85 u.c.enable = 1;
86 u.c.rsvd = 0;
87 u.c.bus = bus;
88 u.c.dev = dev;
89 u.c.func = func;
90 u.c.reg = reg & 0xFC;
91
92 outportDWord(0xCF8, u.n);
93
94 base = 0xCFC + (reg & 0x03);
95
96 switch (bytes) {
97 case 1:
98 return (inportByte(base));
99 case 2:
100 return (inportWord(base));
101 case 4:
102 return (inportDWord(base));
103 default:
104 return 0;
105 }
106 }
107
108 void pciWrite(int bus, int dev, int func, int reg, uInt32 v, int bytes) {
109 uInt16 base;
110
111 union {
112 struct confadd c;
113 uInt32 n;
114 } u;
115
116 u.n = 0;
117 u.c.enable = 1;
118 u.c.rsvd = 0;
119 u.c.bus = bus;
120 u.c.dev = dev;
121 u.c.func = func;
122 u.c.reg = reg & 0xFC;
123
124 base = 0xCFC + (reg & 0x03);
125 outportDWord(0xCF8, u.n);
126 switch (bytes) {
127 case 1:
128 outportByte(base, (uInt8) v);
129 break;
130 case 2:
131 outportWord(base, (uInt16) v);
132 break;
133 case 4:
134 outportDWord(base, v);
135 break;
136 }
137 }
138
139 uint32_t pciProbe(int bus, int dev, int func) {
140 struct pciConfig *cfg = 0x0;
141 uint32_t v;
142 int i;
143
144 cfg = kmalloc(sizeof(struct pciConfig));
145 memset(cfg, 0x0, sizeof(struct pciConfig));
146
147 uint32_t *word = (uint32_t *) cfg;
148
149 for (i = 0; i < 4; i++) {
150 word[i] = pciRead(bus, dev, func, 4 * i, 4);
151
152 /* This is TEMPORARY */
153 if (cfg->vendorID == 0x1022 && i == 1) {
154 kprintf("got it: 0x%X", word[i]);
155 word[i] &= 0xffff0000;
156 word[i] |= 0x5; //0x1 //0x5;
157 pciWrite(bus, dev, func, 4 * i, word[i], 4);
158 kprintf("set it: 0x%X\n", word[i]);
159 }
160 }
161
162 if (cfg->vendorID == 0xffff) {
163 kfree(cfg);
164 return 0x0;
165 }
166
167 if (cfg->vendorID == 0x0) {
168 kfree(cfg);
169 return 0x0;
170 }
171
172 cfg->bus = bus;
173 cfg->dev = dev;
174 cfg->func = func;
175
176 /*
177 if (cfg->vendorID == 0x1022)
178 pciWrite(bus, dev, func, 0x3C, 0x5,1);
179 */
180
181 switch (cfg->headerType & 0x7F) {
182 case 0x0: /* normal device */
183 for (i = 4; i <= 16; i++) {
184 word[i] = pciRead(bus, dev, func, 4 * i, 4);
185 }
186 if (cfg->vendorID == 0x1022) {
187 kprintf("Device Info: /bus/pci/%d/%d/%d\n", bus, dev, func);
188 kprintf(" * Vendor: %X Device: %X Class/SubClass/Interface %X/%X/%X\n", cfg->vendorID, cfg->deviceID, cfg->classCode, cfg->subClass, cfg->progIf);
189 kprintf(" * Status: %X Command: %X BIST/Type/Lat/CLS: %X/%X/%X/%X\n", cfg->status, cfg->command, cfg->bist, cfg->headerType, cfg->latencyTimer, cfg->cacheLineSize);
190 kprintf(" * IRQ: 0x%X.0x%X, BAR[0]: 0x%X\n", cfg->intLine, cfg->intPin, cfg->bar[0]);
191 }
192 break;
193 case 0x1:
194 kprintf(" * PCI <-> PCI Bridge\n");
195 break;
196 case 0x2:
197 kprintf(" * PCI <-> CardBus Bridge\n");
198 break;
199 default:
200 kprintf(" * Unknown Header Type\n");
201 break;
202
203 }
204
205 /*
206 switch (cfg->headerType & 0x7F) {
207 case 0: // normal device
208 for (i = 0; i < 6; i++) {
209 v = pciRead(bus, dev, func, i * 4 + 0x10, 4);
210 if (v) {
211 int v2;
212 pciWrite(bus, dev, func, i * 4 + 0x10, 0xffffffff, 4);
213 v2 = pciRead(bus, dev, func, i * 4 + 0x10, 4) & 0xfffffff0;
214 pciWrite(bus, dev, func, i * 4 + 0x10, v, 4);
215 v2 = 1 + ~v2;
216 if (v & 1) {
217 cfg->base[i] = v & 0xffff;
218 cfg->size[i] = v2 & 0xffff;
219 }
220 else {
221 cfg->base[i] = v;
222 cfg->size[i] = v2;
223 }
224 }
225 else {
226 cfg->base[i] = 0;
227 cfg->size[i] = 0;
228 }
229 }
230 v = pciRead(bus, dev, func, 0x3c, 1);
231 cfg->irq = (v == 0xff ? 0 : v);
232 v = pciRead(bus, dev, func, 0x40, 1);
233 cfg->irqLine = (v == 0xff ? 0 : v);
234 break;
235 case 1:
236
237
238 }
239 */
240
241 return ((uint32_t) cfg);
242 }
243
244 int pci_init() {
245 uint16_t bus, dev, func;
246
247 int i = 0x0;
248
249 struct pciConfig *pcfg;
250
251 for (bus = 0x0; bus < 0x2; bus++) {
252 for (dev = 0; dev < 32; dev++) {
253 for (func = 0; func < 8; func++) {
254 pcfg = (struct pciConfig *) pciProbe(bus, dev, func);
255 if (pcfg != 0x0) {
256 for (i = 0x0; i < countof(pciClasses); i++) {
257 if (pcfg->classCode == pciClasses[i].baseClass && pcfg->subClass == pciClasses[i].subClass && pcfg->progIf == pciClasses[i].interface) {
258 if (pcfg->vendorID == 0x1022) {
259 kprintf("PCI Device: %s @ IRQ: 0x%X.0x%X\n", pciClasses[i].name, pcfg->intPin, pcfg->intLine);
260 }
261 break;
262 }
263 }
264 }
265 }
266 }
267 }
268 return (0x0);
269 }
pciConfig::latencyTimer
uint8_t latencyTimer
Definition: pci.h:47
pciConfig::progIf
uint8_t progIf
Definition: pci.h:42
confadd
Definition: pci.h:89
outportDWord
void outportDWord(unsigned int port, unsigned long value)
outputut one double word to specified port
Definition: io.c:118
interface
uInt8 interface
Definition: pci.c:36
subClass
uInt8 subClass
Definition: pci.c:35
uInt32
unsigned long int uInt32
Definition: objgfx30.h:49
inportDWord
unsigned long inportDWord(unsigned int)
input one double word from specified port
Definition: io.c:133
pciConfig::intPin
uint8_t intPin
Definition: pci.h:66
pciConfig::bus
uint8_t bus
Definition: pci.h:83
uInt16
unsigned short int uInt16
Definition: objgfx30.h:48
outportWord
void outportWord(unsigned int, unsigned short)
outputut one word to specified port
Definition: io.c:103
pciConfig::vendorID
uint16_t vendorID
Definition: pci.h:35
outportByte
void outportByte(unsigned int, unsigned char)
outputut one byte to specified port
Definition: io.c:72
kfree
void kfree(void *baseAddr)
Definition: kmalloc.c:342
pciConfig::deviceID
uint16_t deviceID
Definition: pci.h:36
pciConfig::bist
uint8_t bist
Definition: pci.h:49
confadd::bus
uint8_t bus
Definition: pci.h:93
pciWrite
void pciWrite(int bus, int dev, int func, int reg, uInt32 v, int bytes)
Definition: pci.c:108
confadd::enable
uint8_t enable
Definition: pci.h:95
pciClasses
const struct @29 pciClasses[]
pciConfig::bar
uint32_t bar[6]
Definition: pci.h:51
pci.h
pci_init
int pci_init()
Definition: pci.c:244
inportByte
unsigned char inportByte(unsigned int)
input one byte from specified port
Definition: io.c:38
uint16_t
__uint16_t uint16_t
Definition: types.h:45
countof
#define countof(a)
Definition: pci.h:98
kprintf.h
pciConfig::status
uint16_t status
Definition: pci.h:39
uInt8
unsigned char uInt8
Definition: objgfx30.h:47
confadd::dev
uint8_t dev
Definition: pci.h:92
uint32_t
__uint32_t uint32_t
Definition: types.h:46
pciConfig::headerType
uint8_t headerType
Definition: pci.h:48
pciConfig::command
uint16_t command
Definition: pci.h:38
inportWord
unsigned short inportWord(unsigned int)
input one word from specified port
Definition: io.c:55
name
const char * name
Definition: pci.c:37
pciConfig::classCode
uint8_t classCode
Definition: pci.h:44
pciConfig::subClass
uint8_t subClass
Definition: pci.h:43
confadd::func
uint8_t func
Definition: pci.h:91
kmalloc
void * kmalloc(uInt32 len)
Definition: kmalloc.c:241
io.h
memset
void * memset(void *dst, int c, size_t length)
pciConfig::func
uint8_t func
Definition: pci.h:85
confadd::reg
uint8_t reg
Definition: pci.h:90
baseClass
uInt8 baseClass
Definition: pci.c:34
pciConfig::cacheLineSize
uint8_t cacheLineSize
Definition: pci.h:46
pciConfig::intLine
uint8_t intLine
Definition: pci.h:65
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
pciConfig
Definition: pci.h:34
pciConfig::dev
uint8_t dev
Definition: pci.h:84
pciProbe
uint32_t pciProbe(int bus, int dev, int func)
Definition: pci.c:139
pciRead
uInt32 pciRead(int bus, int dev, int func, int reg, int bytes)
Definition: pci.c:76