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

Archive Download this file

Revision: 2117