Chameleon

Chameleon Svn Source Tree

Root/branches/rekursor/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
11uint32_t pci_config_read(uint32_t pci_addr, uint8_t reg, uint8_t bytes)
12{
13uint32_t data = -1;
14
15pci_addr |= reg & ~3;
16outl(PCI_ADDR_REG, pci_addr);
17
18switch (bytes)
19{
20case 1:
21data = inb(PCI_DATA_REG + (reg & 3));
22break;
23case 2:
24data = inw(PCI_DATA_REG + (reg & 2));
25break;
26case 4:
27data = inl(PCI_DATA_REG);
28break;
29}
30
31return data;
32}
33
34void pci_config_write(uint32_t pci_addr, uint8_t reg, uint32_t data, uint8_t bytes)
35{
36pci_addr |= reg & ~3;
37outl(PCI_ADDR_REG, pci_addr);
38
39switch (bytes)
40{
41case 1:
42outb(PCI_DATA_REG + (reg & 3), data);
43break;
44case 2:
45outw(PCI_DATA_REG + (reg & 2), data);
46break;
47case 4:
48outl(PCI_DATA_REG, data);
49break;
50}
51}
52
53pci_dt_t *root_pci_dev;
54
55void scan_pci_bus(pci_dt_t *start, uint8_t bus)
56{
57uint8_t dev, func, secondary_bus, header_type;
58uint32_t id, pci_addr;
59pci_dt_t *new;
60pci_dt_t **current = &start->children;
61
62for (dev = 0; dev < 32; dev++)
63for (func = 0; func < 8; func++)
64{
65pci_addr = PCIADDR(bus, dev, func);
66id = pci_config_read32(pci_addr, PCI_VENDOR_ID);
67if (!id || id == 0xffffffff)
68continue;
69
70new = (pci_dt_t*)MALLOC(sizeof(pci_dt_t));
71if (!new)
72return;
73memset(new, 0, sizeof(pci_dt_t));
74
75new->dev.addr= pci_addr;
76new->vendor_id= id & 0xffff;
77new->device_id= (id >> 16) & 0xffff;
78new->class_id= pci_config_read16(pci_addr, PCI_CLASS_DEVICE);
79new->parent= start;
80
81header_type = pci_config_read8(pci_addr, PCI_HEADER_TYPE);
82switch (header_type & 0x7f)
83{
84case PCI_HEADER_TYPE_BRIDGE:
85case PCI_HEADER_TYPE_CARDBUS:
86secondary_bus = pci_config_read8(pci_addr, PCI_SECONDARY_BUS);
87if (secondary_bus != 0)
88scan_pci_bus(new, secondary_bus);
89break;
90}
91
92*current = new;
93current = &new->next;
94
95if ((func == 0) && ((header_type & 0x80) == 0))
96break;
97}
98}
99
100void enable_pci_devs(void)
101{
102uint16_t id;
103uint32_t rcba, *fd;
104
105id = pci_config_read16(PCIADDR(0, 0x00, 0), 0x00);
106/* make sure we're on Intel chipset */
107if (id != 0x8086)
108return;
109rcba = pci_config_read32(PCIADDR(0, 0x1f, 0), 0xf0) & ~1;
110fd = (uint32_t *)(rcba + 0x3418);
111/* set SMBus Disable (SD) to 0 */
112*fd &= ~0x8;
113/* and all devices? */
114//*fd = 0x1;
115}
116
117void build_pci_dt(void)
118{
119root_pci_dev = MALLOC(sizeof(pci_dt_t));
120
121if (!root_pci_dev)
122return;
123
124bzero(root_pci_dev, sizeof(pci_dt_t));
125enable_pci_devs();
126scan_pci_bus(root_pci_dev, 0);
127}
128
129char dev_path[80];
130
131char *get_pci_dev_path(pci_dt_t *pci_dt)
132{
133pci_dt_t *current, *end;
134char tmp[30];
135int uid = 0;
136
137dev_path[0] = 0;
138end = root_pci_dev;
139
140uid = getPciRootUID();
141
142while (end != pci_dt)
143{
144current = pci_dt;
145while (current->parent != end)
146current = current->parent;
147end = current;
148if (current->parent == root_pci_dev)
149{
150sprintf(tmp, "PciRoot(0x%x)/Pci(0x%x,0x%x)", uid,
151current->dev.bits.dev, current->dev.bits.func);
152} else {
153sprintf(tmp, "/Pci(0x%x,0x%x)",
154current->dev.bits.dev, current->dev.bits.func);
155}
156strcat(dev_path, tmp);
157}
158
159return dev_path;
160}
161
162void dump_pci_dt(pci_dt_t *pci_dt)
163{
164pci_dt_t *current = pci_dt;
165
166while (current)
167{
168printf("%02x:%02x.%x [%04x] [%04x:%04x] :: %s\n",
169current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func,
170current->class_id, current->vendor_id, current->device_id,
171get_pci_dev_path(current));
172dump_pci_dt(current->children);
173current = current->next;
174}
175}
176
177
178void lspci(const char *booterParam)
179{
180if(bootArgs->Video.v_display == VGA_TEXT_MODE)
181{
182setActiveDisplayPage(1);
183clearScreenRows(0, 24);
184setCursorPosition(0, 0, 1);
185}
186
187dump_pci_dt(root_pci_dev->children);
188
189printf("(Press a key to continue...)");
190getc();
191
192if(bootArgs->Video.v_display == VGA_TEXT_MODE)
193setActiveDisplayPage(0);
194}
195
196int check_vga_nvidia(pci_dt_t *pci_dt)
197{
198pci_dt_t *current = pci_dt;
199while (current)
200{
201if(current->vendor_id == PCI_CLASS_DISPLAY_VGA)
202if(current->class_id == PCI_VENDOR_ID_NVIDIA)
203return 1;
204
205check_vga_nvidia(current->children);
206current = current->next;
207}
208return 0;
209}
210
211

Archive Download this file

Revision: 4