Chameleon

Chameleon Svn Source Tree

Root/branches/slice/trunkM/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 "boot.h"
10#include "pci.h"
11#include "pci_root.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;
24
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
68void 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++) {
80for (func = 0; func < 8; func++) {
81pci_addr = PCIADDR(bus, dev, func);
82id = pci_config_read32(pci_addr, PCI_VENDOR_ID);
83if (!id || id == 0xffffffff) {
84continue;
85}
86new = (pci_dt_t*)malloc(sizeof(pci_dt_t));
87if (!new)
88return;
89memset(new, 0, sizeof(pci_dt_t));
90
91new->dev.addr= pci_addr;
92new->vendor_id= id & 0xffff;
93new->device_id= (id >> 16) & 0xffff;
94new->subsys_id.subsys_id= pci_config_read32(pci_addr, PCI_SUBSYSTEM_VENDOR_ID);
95new->subclass= pci_config_read8(pci_addr, PCI_CLASS_PROG);
96new->class_id= pci_config_read16(pci_addr, PCI_CLASS_DEVICE);
97new->parent= start;
98
99header_type = pci_config_read8(pci_addr, PCI_HEADER_TYPE);
100switch (header_type & 0x7f)
101{
102case PCI_HEADER_TYPE_BRIDGE:
103case PCI_HEADER_TYPE_CARDBUS:
104secondary_bus = pci_config_read8(pci_addr, PCI_SECONDARY_BUS);
105if (secondary_bus != 0) {
106scan_pci_bus(new, secondary_bus);
107}
108break;
109}
110*current = new;
111current = &new->next;
112
113if ((func == 0) && ((header_type & 0x80) == 0))
114{
115break;
116}
117}
118}
119}
120
121void enable_pci_devs(void)
122{
123uint16_t id;
124uint32_t rcba, *fd;
125
126id = pci_config_read16(PCIADDR(0, 0x00, 0), 0x00);
127/* make sure we're on Intel chipset */
128if (id != 0x8086)
129return;
130rcba = pci_config_read32(PCIADDR(0, 0x1f, 0), 0xf0) & ~1;
131fd = (uint32_t *)(rcba + 0x3418);
132/* set SMBus Disable (SD) to 0 */
133*fd &= ~0x8;
134/* and all devices? */
135//*fd = 0x1;
136}
137
138
139void build_pci_dt(void)
140{
141root_pci_dev = malloc(sizeof(pci_dt_t));
142
143if (!root_pci_dev)
144return;
145gRootPCIDev = (void*)root_pci_dev;
146bzero(root_pci_dev, sizeof(pci_dt_t));
147enable_pci_devs();
148scan_pci_bus(root_pci_dev, 0);
149#if 1 //DEBUG_PCI
150dump_pci_dt(root_pci_dev->children);
151//pause();
152#endif
153}
154
155static char dev_path[256];
156char *get_pci_dev_path(pci_dt_t *pci_dt)
157{
158pci_dt_t*current;
159pci_dt_t*end;
160chartmp[64];
161
162dev_path[0] = 0;
163end = root_pci_dev;
164
165int uid = getPciRootUID();
166while (end != pci_dt)
167{
168current = pci_dt;
169while (current->parent != end)
170current = current->parent;
171end = current;
172if (current->parent == root_pci_dev)
173{
174sprintf(tmp, "PciRoot(0x%x)/Pci(0x%x,0x%x)", uid,
175current->dev.bits.dev, current->dev.bits.func);
176} else {
177sprintf(tmp, "/Pci(0x%x,0x%x)",
178current->dev.bits.dev, current->dev.bits.func);
179}
180strcat(dev_path, tmp);
181}
182return dev_path;
183}
184
185void dump_pci_dt(pci_dt_t *pci_dt)
186{
187pci_dt_t*current;
188
189current = pci_dt;
190while (current) {
191msglog("%02x:%02x.%x [%04x%02x] [%04x:%04x] (subsys [%04x:%04x]):: %s\n",
192current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func,
193 current->class_id, current->subclass, current->vendor_id, current->device_id,
194current->subsys_id.subsys.vendor_id, current->subsys_id.subsys.device_id,
195get_pci_dev_path(current));
196dump_pci_dt(current->children);
197current = current->next;
198}
199}
200

Archive Download this file

Revision: 1171