Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/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 "pci_root.h"
11
12#ifndef DEBUG_PCI
13#define DEBUG_PCI 0
14#endif
15
16#if DEBUG_PCI
17#define DBG(x...)printf(x)
18#else
19#define DBG(x...)
20#endif
21
22pci_dt_t*root_pci_dev;
23
24
25uint8_t pci_config_read8(uint32_t pci_addr, uint8_t reg)
26{
27pci_addr |= reg & ~3;
28outl(PCI_ADDR_REG, pci_addr);
29return inb(PCI_DATA_REG + (reg & 3));
30}
31
32uint16_t pci_config_read16(uint32_t pci_addr, uint8_t reg)
33{
34pci_addr |= reg & ~3;
35outl(PCI_ADDR_REG, pci_addr);
36return inw(PCI_DATA_REG + (reg & 2));
37}
38
39uint32_t pci_config_read32(uint32_t pci_addr, uint8_t reg)
40{
41pci_addr |= reg & ~3;
42outl(PCI_ADDR_REG, pci_addr);
43return inl(PCI_DATA_REG);
44}
45
46void pci_config_write8(uint32_t pci_addr, uint8_t reg, uint8_t data)
47{
48pci_addr |= reg & ~3;
49outl(PCI_ADDR_REG, pci_addr);
50outb(PCI_DATA_REG + (reg & 3), data);
51}
52
53void pci_config_write16(uint32_t pci_addr, uint8_t reg, uint16_t data)
54{
55pci_addr |= reg & ~3;
56outl(PCI_ADDR_REG, pci_addr);
57outw(PCI_DATA_REG + (reg & 2), data);
58}
59
60void pci_config_write32(uint32_t pci_addr, uint8_t reg, uint32_t data)
61{
62pci_addr |= reg & ~3;
63outl(PCI_ADDR_REG, pci_addr);
64outl(PCI_DATA_REG, data);
65}
66
67void scan_pci_bus(pci_dt_t *start, uint8_t bus)
68{
69pci_dt_t*new;
70pci_dt_t**current = &start->children;
71uint32_tid;
72uint32_tpci_addr;
73uint8_tdev = 0;
74uint8_tfunc = 0;
75uint8_tsecondary_bus;
76uint8_theader_type;
77
78for (dev = 0; dev < 32; dev++)
79{
80for (func = 0; func < 8; func++)
81{
82pci_addr = PCIADDR(bus, dev, func);
83id = pci_config_read32(pci_addr, PCI_VENDOR_ID);
84if (!id || id == 0xfffffffful)
85{
86continue;
87}
88
89new = (pci_dt_t*)malloc(sizeof(pci_dt_t));
90if (!new)
91{
92continue;
93}
94
95bzero(new, sizeof(pci_dt_t));
96
97new->dev.addr= pci_addr;
98new->vendor_id= id & 0xffff;
99new->device_id= (id >> 16) & 0xffff;
100new->progif= pci_config_read8(pci_addr, PCI_CLASS_PROG);
101new->revision_id= pci_config_read8(pci_addr, PCI_CLASS_REVISION);
102new->subsys_id.subsys_id= pci_config_read32(pci_addr, PCI_SUBSYSTEM_VENDOR_ID);
103new->class_id= pci_config_read16(pci_addr, PCI_CLASS_DEVICE);
104//new->subclass_id= pci_config_read16(pci_addr, PCI_SUBCLASS_DEVICE);
105new->parent= start;
106
107header_type = pci_config_read8(pci_addr, PCI_HEADER_TYPE);
108switch (header_type & 0x7f)
109{
110case PCI_HEADER_TYPE_BRIDGE:
111case PCI_HEADER_TYPE_CARDBUS:
112secondary_bus = pci_config_read8(pci_addr, PCI_SECONDARY_BUS);
113if (secondary_bus != 0)
114{
115scan_pci_bus(new, secondary_bus);
116}
117break;
118default:
119break;
120}
121
122*current = new;
123current = &new->next;
124
125if ((func == 0) && ((header_type & 0x80) == 0))
126{
127break;
128}
129}
130}
131}
132
133void enable_pci_devs(void)
134{
135uint16_t id;
136uint32_t rcba, *fd;
137
138id = pci_config_read16(PCIADDR(0, 0x00, 0), 0x00);
139/* make sure we're on Intel chipset */
140if (id != 0x8086)
141{
142return;
143}
144
145rcba = pci_config_read32(PCIADDR(0, 0x1f, 0), 0xf0) & ~1; //this is LPC host
146fd = (uint32_t *)(rcba + 0x3418);
147/* set SMBus Disable (SD) to 0 */
148*fd &= ~0x8;
149/* and all devices? */
150//*fd = 0x1;
151}
152
153
154void build_pci_dt(void)
155{
156root_pci_dev = malloc(sizeof(pci_dt_t));
157
158if (!root_pci_dev)
159{
160return;
161}
162
163bzero(root_pci_dev, sizeof(pci_dt_t));
164enable_pci_devs();
165scan_pci_bus(root_pci_dev, 0);
166
167#if DEBUG_PCI
168dump_pci_dt(root_pci_dev->children);
169pause();
170#endif
171}
172
173static char dev_path[256];
174
175char *get_pci_dev_path(pci_dt_t *pci_dt)
176{
177pci_dt_t*current;
178pci_dt_t*end;
179intdev_path_len = 0;
180
181dev_path[0] = 0;
182end = root_pci_dev;
183
184int uid = getPciRootUID();
185while (end != pci_dt)
186{
187current = pci_dt;
188while (current->parent != end)
189current = current->parent;
190end = current;
191if (current->parent == root_pci_dev)
192{
193dev_path_len +=
194snprintf(dev_path + dev_path_len, sizeof(dev_path) - dev_path_len, "PciRoot(0x%x)/Pci(0x%x,0x%x)", uid,
195current->dev.bits.dev, current->dev.bits.func);
196}
197else
198{
199dev_path_len +=
200snprintf(dev_path + dev_path_len, sizeof(dev_path) - dev_path_len, "/Pci(0x%x,0x%x)",
201current->dev.bits.dev, current->dev.bits.func);
202}
203
204}
205return dev_path;
206}
207
208void dump_pci_dt(pci_dt_t *pci_dt)
209{
210pci_dt_t*current;
211
212current = pci_dt;
213while (current) {
214printf("%02x:%02x.%x [%04x%02x] [%04x:%04x] (subsys [%04x:%04x]):: %s\n",
215current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func,
216current->class_id, 0 /* FIXME: what should this be? */,
217current->vendor_id, current->device_id,
218current->subsys_id.subsys.vendor_id, current->subsys_id.subsys.device_id,
219get_pci_dev_path(current));
220dump_pci_dt(current->children);
221current = current->next;
222}
223}
224

Archive Download this file

Revision: 2542