UbixOS  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 {
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