Chameleon

Chameleon Svn Source Tree

Root/branches/slice/old749m/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 "boot.h"
9#include "bootstruct.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...)verbose(x)
19#else
20#define DBG(x...)msglog(x)
21#endif
22
23//static
24pci_dt_t*root_pci_dev;
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));
91if (!new)
92return;
93memset(new, 0, sizeof(pci_dt_t));
94
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->subclass= pci_config_read8(pci_addr, PCI_CLASS_PROG);
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;
114}
115*current = new;
116current = &new->next;
117
118if ((func == 0) && ((header_type & 0x80) == 0))
119{
120break;
121}
122}
123}
124}
125
126void 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{
146root_pci_dev = malloc(sizeof(pci_dt_t));
147
148if (!root_pci_dev)
149return;
150gRootPCIDev = (void*)root_pci_dev;
151bzero(root_pci_dev, sizeof(pci_dt_t));
152enable_pci_devs();
153scan_pci_bus(root_pci_dev, 0);
154#if 1 //DEBUG_PCI
155dump_pci_dt(root_pci_dev->children);
156//pause();
157#endif
158}
159
160static char dev_path[256];
161char *get_pci_dev_path(pci_dt_t *pci_dt)
162{
163pci_dt_t*current;
164pci_dt_t*end;
165chartmp[64];
166
167dev_path[0] = 0;
168end = root_pci_dev;
169
170int uid = getPciRootUID();
171while (end != pci_dt)
172{
173current = pci_dt;
174while (current->parent != end)
175current = current->parent;
176end = current;
177if (current->parent == root_pci_dev)
178{
179sprintf(tmp, "PciRoot(0x%x)/Pci(0x%x,0x%x)", uid,
180current->dev.bits.dev, current->dev.bits.func);
181}
182else
183{
184sprintf(tmp, "/Pci(0x%x,0x%x)",
185current->dev.bits.dev, current->dev.bits.func);
186}
187strcat(dev_path, tmp);
188}
189return dev_path;
190}
191
192#ifndef OPTION_ROM
193void dump_pci_dt(pci_dt_t *pci_dt)
194{
195pci_dt_t*current;
196
197current = pci_dt;
198while (current) {
199msglog("%02x:%02x.%x [%04x%02x] [%04x:%04x] (subsys [%04x:%04x]):: %s\n",
200 current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func,
201 current->class_id, current->subclass, current->vendor_id, current->device_id,
202current->subsys_id.subsys.vendor_id, current->subsys_id.subsys.device_id,
203 get_pci_dev_path(current));
204dump_pci_dt(current->children);
205current = current->next;
206}
207}
208#endif
209

Archive Download this file

Revision: 1174