Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/pci.c

1/*
2 *
3 * Copyright 2008 by Islam M. Ahmed Zaid. All rights reserved.
4 *
5 */
6
7#include "libsaio.h"
8#include "bootstruct.h"
9#include "pci.h"
10#include "modules.h"
11#include "device_inject.h"
12
13#ifndef DEBUG_PCI
14#define DEBUG_PCI 0
15#endif
16
17#if DEBUG_PCI
18#define DBG(x...)printf(x)
19#else
20#define DBG(x...)
21#endif
22
23pci_dt_t*root_pci_dev;
24static char* dev_path;// TODO: Figure out what is going on here...
25
26
27uint8_t pci_config_read8(uint32_t pci_addr, uint8_t reg)
28{
29pci_addr |= reg & ~3;
30outl(PCI_ADDR_REG, pci_addr);
31return inb(PCI_DATA_REG + (reg & 3));
32}
33
34uint16_t pci_config_read16(uint32_t pci_addr, uint8_t reg)
35{
36pci_addr |= reg & ~3;
37outl(PCI_ADDR_REG, pci_addr);
38return inw(PCI_DATA_REG + (reg & 2));
39}
40
41uint32_t pci_config_read32(uint32_t pci_addr, uint8_t reg)
42{
43pci_addr |= reg & ~3;
44outl(PCI_ADDR_REG, pci_addr);
45return inl(PCI_DATA_REG);
46}
47
48void pci_config_write8(uint32_t pci_addr, uint8_t reg, uint8_t data)
49{
50pci_addr |= reg & ~3;
51outl(PCI_ADDR_REG, pci_addr);
52outb(PCI_DATA_REG + (reg & 3), data);
53}
54
55void pci_config_write16(uint32_t pci_addr, uint8_t reg, uint16_t data)
56{
57pci_addr |= reg & ~3;
58outl(PCI_ADDR_REG, pci_addr);
59outw(PCI_DATA_REG + (reg & 2), data);
60}
61
62void pci_config_write32(uint32_t pci_addr, uint8_t reg, uint32_t data)
63{
64pci_addr |= reg & ~3;
65outl(PCI_ADDR_REG, pci_addr);
66outl(PCI_DATA_REG, data);
67}
68
69void scan_pci_bus(pci_dt_t *start, uint8_t bus)
70{
71pci_dt_t*new;
72pci_dt_t**current = &start->children;
73uint32_tid;
74uint32_tpci_addr;
75uint8_tdev;
76uint8_tfunc;
77uint8_tsecondary_bus;
78uint8_theader_type;
79
80for (dev = 0; dev < 32; dev++)
81{
82for (func = 0; func < 8; func++)
83{
84pci_addr = PCIADDR(bus, dev, func);
85id = pci_config_read32(pci_addr, PCI_VENDOR_ID);
86if (!id || id == 0xffffffff)
87{
88continue;
89}
90new = (pci_dt_t*)malloc(sizeof(pci_dt_t));
91 if (!new) {
92 continue;
93 }
94bzero(new, sizeof(pci_dt_t));
95new->dev.addr= pci_addr;
96new->vendor_id= id & 0xffff;
97new->device_id= (id >> 16) & 0xffff;
98new->subsys_id.subsys_id= pci_config_read32(pci_addr, PCI_SUBSYSTEM_VENDOR_ID);
99new->class_id= pci_config_read16(pci_addr, PCI_CLASS_DEVICE);
100new->parent= start;
101
102header_type = pci_config_read8(pci_addr, PCI_HEADER_TYPE);
103switch (header_type & 0x7f)
104{
105case PCI_HEADER_TYPE_BRIDGE:
106case PCI_HEADER_TYPE_CARDBUS:
107secondary_bus = pci_config_read8(pci_addr, PCI_SECONDARY_BUS);
108if (secondary_bus != 0)
109{
110scan_pci_bus(new, secondary_bus);
111}
112break;
113default:
114break;
115}
116*current = new;
117current = &new->next;
118
119if ((func == 0) && ((header_type & 0x80) == 0))
120{
121break;
122}
123}
124}
125}
126
127void enable_pci_devs(void)
128{
129uint16_t id;
130uint32_t rcba, *fd;
131
132id = pci_config_read16(PCIADDR(0, 0x00, 0), 0x00);
133/* make sure we're on Intel chipset */
134if (id != 0x8086)
135return;
136rcba = pci_config_read32(PCIADDR(0, 0x1f, 0), 0xf0) & ~1;
137fd = (uint32_t *)(rcba + 0x3418);
138/* set SMBus Disable (SD) to 0 */
139*fd &= ~0x8;
140/* and all devices? */
141//*fd = 0x1;
142}
143
144
145void build_pci_dt(void)
146{
147dev_path = malloc(sizeof(char) * 256);// TODO: remove
148
149root_pci_dev = malloc(sizeof(pci_dt_t));
150
151 if (!dev_path || !root_pci_dev) {
152 stop("Couldn't allocate memory for the pci root device\n");
153 return ;
154 }
155bzero(root_pci_dev, sizeof(pci_dt_t));
156enable_pci_devs();
157scan_pci_bus(root_pci_dev, 0);
158#if DEBUG_PCI
159#ifndef OPTION_ROM
160dump_pci_dt(root_pci_dev->children);
161pause();
162#endif
163#endif
164}
165
166#if 0
167char *get_pci_dev_path(pci_dt_t *pci_dt)
168{
169char* buffer = malloc(sizeof(char) * 256);
170
171 if (!buffer) {
172 return NULL;
173 }
174
175pci_dt_t*current;
176pci_dt_t*end;
177chartmp[64];
178
179buffer[0] = 0;
180end = root_pci_dev;
181
182int uid = getPciRootUID();
183while (end != pci_dt)
184{
185current = pci_dt;
186while (current->parent != end)
187current = current->parent;
188end = current;
189if (current->parent == root_pci_dev)
190{
191snprintf(tmp, sizeof(tmp),"PciRoot(0x%x)/Pci(0x%x,0x%x)", uid,
192current->dev.bits.dev, current->dev.bits.func);
193}
194else
195{
196snprintf(tmp, sizeof(tmp) ,"/Pci(0x%x,0x%x)",
197current->dev.bits.dev, current->dev.bits.func);
198}
199snprintf(buffer, sizeof(char) * 256,"%s%s", buffer, tmp);
200}
201return buffer;
202}
203#endif
204
205void setup_pci_devs(pci_dt_t *pci_dt)
206{
207pci_dt_t *current = pci_dt;
208
209while (current)
210{
211execute_hook("PCIDevice", (void*)current, NULL, NULL, NULL, NULL, NULL);
212
213setup_pci_devs(current->children);
214current = current->next;
215}
216}
217
218#ifndef OPTION_ROM
219void dump_pci_dt(pci_dt_t *pci_dt)
220{
221pci_dt_t*current;
222
223current = pci_dt;
224while (current)
225{
226printf("%02x:%02x.%x [%04x] [%04x:%04x] \n",
227 current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func,
228 current->class_id, current->vendor_id, current->device_id);
229dump_pci_dt(current->children);
230current = current->next;
231}
232}
233#endif
234
235static int rootuid = 10; //value means function wasnt ran yet
236
237/*
238 * getPciRootUID: Copyright 2009 netkas
239 */
240int getPciRootUID(void)
241{
242const char *val;
243int len;
244
245if (rootuid < 10) return rootuid;
246rootuid = 0;/* default uid = 0 */
247
248if (getValueForKey(kPCIRootUID, &val, &len, DEFAULT_BOOT_CONFIG))
249{
250if (isdigit(val[0])) rootuid = val[0] - '0';
251
252if ( (rootuid >= 0) && (rootuid < 10) )
253goto out;
254else
255rootuid = 0;
256}
257
258/* PCEFI compatibility */
259if (getValueForKey("-pci0", &val, &len, DEFAULT_BOOT_CONFIG))
260{
261rootuid = 0;
262}
263else if (getValueForKey("-pci1", &val, &len, DEFAULT_BOOT_CONFIG))
264{
265rootuid = 1;
266}
267out:
268verbose("Using PCI-Root-UID value: %d\n", rootuid);
269return rootuid;
270}

Archive Download this file

Revision: 2057