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

Archive Download this file

Revision: 2118