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
11#ifndef DEBUG_PCI
12#define DEBUG_PCI 0
13#endif
14
15#if DEBUG_PCI
16#define DBG(x...)printf(x)
17#else
18#define DBG(x...)
19#endif
20
21pci_dt_t*root_pci_dev;
22
23
24uint8_t pci_config_read8(uint32_t pci_addr, uint8_t reg)
25{
26pci_addr |= reg & ~3;
27outl(PCI_ADDR_REG, pci_addr);
28return inb(PCI_DATA_REG + (reg & 3));
29}
30
31uint16_t pci_config_read16(uint32_t pci_addr, uint8_t reg)
32{
33pci_addr |= reg & ~3;
34outl(PCI_ADDR_REG, pci_addr);
35return inw(PCI_DATA_REG + (reg & 2));
36}
37
38uint32_t pci_config_read32(uint32_t pci_addr, uint8_t reg)
39{
40pci_addr |= reg & ~3;
41outl(PCI_ADDR_REG, pci_addr);
42return inl(PCI_DATA_REG);
43}
44
45void pci_config_write8(uint32_t pci_addr, uint8_t reg, uint8_t data)
46{
47pci_addr |= reg & ~3;
48outl(PCI_ADDR_REG, pci_addr);
49outb(PCI_DATA_REG + (reg & 3), data);
50}
51
52void pci_config_write16(uint32_t pci_addr, uint8_t reg, uint16_t data)
53{
54pci_addr |= reg & ~3;
55outl(PCI_ADDR_REG, pci_addr);
56outw(PCI_DATA_REG + (reg & 2), data);
57}
58
59void pci_config_write32(uint32_t pci_addr, uint8_t reg, uint32_t data)
60{
61pci_addr |= reg & ~3;
62outl(PCI_ADDR_REG, pci_addr);
63outl(PCI_DATA_REG, data);
64}
65
66void scan_pci_bus(pci_dt_t *start, uint8_t bus)
67{
68pci_dt_t*new;
69pci_dt_t**current = &start->children;
70uint32_tid;
71uint32_tpci_addr;
72uint8_tdev;
73uint8_tfunc;
74uint8_tsecondary_bus;
75uint8_theader_type;
76
77for (dev = 0; dev < 32; dev++) {
78for (func = 0; func < 8; func++) {
79pci_addr = PCIADDR(bus, dev, func);
80id = pci_config_read32(pci_addr, PCI_VENDOR_ID);
81if (!id || id == 0xffffffff) {
82continue;
83}
84new = (pci_dt_t*)MALLOC(sizeof(pci_dt_t));
85bzero(new, sizeof(pci_dt_t));
86new->dev.addr= pci_addr;
87new->vendor_id= id & 0xffff;
88new->device_id= (id >> 16) & 0xffff;
89new->class_id= pci_config_read16(pci_addr, PCI_CLASS_DEVICE);
90new->parent= start;
91
92header_type = pci_config_read8(pci_addr, PCI_HEADER_TYPE);
93switch (header_type & 0x7f) {
94case PCI_HEADER_TYPE_BRIDGE:
95case PCI_HEADER_TYPE_CARDBUS:
96secondary_bus = pci_config_read8(pci_addr, PCI_SECONDARY_BUS);
97if (secondary_bus != 0) {
98scan_pci_bus(new, secondary_bus);
99}
100break;
101}
102*current = new;
103current = &new->next;
104
105if ((func == 0) && ((header_type & 0x80) == 0)) {
106break;
107}
108}
109}
110}
111
112void build_pci_dt(void)
113{
114root_pci_dev = MALLOC(sizeof(pci_dt_t));
115bzero(root_pci_dev, sizeof(pci_dt_t));
116scan_pci_bus(root_pci_dev, 0);
117#if DEBUG_PCI
118dump_pci_dt(root_pci_dev->children);
119printf("(Press a key to continue...)\n");
120getc();
121#endif
122}
123
124static char dev_path[256];
125char *get_pci_dev_path(pci_dt_t *pci_dt)
126{
127pci_dt_t*current;
128pci_dt_t*end;
129chartmp[64];
130
131dev_path[0] = 0;
132end = root_pci_dev;
133while (end != pci_dt) {
134current = pci_dt;
135while (current->parent != end) {
136current = current->parent;
137}
138end = current;
139sprintf(tmp, "%s/Pci(0x%x,0x%x)",
140(current->parent == root_pci_dev) ? "PciRoot(0x0)" : "",
141current->dev.bits.dev, current->dev.bits.func);
142strcat(dev_path, tmp);
143}
144return dev_path;
145}
146
147void dump_pci_dt(pci_dt_t *pci_dt)
148{
149pci_dt_t*current;
150
151current = pci_dt;
152while (current) {
153printf("%02x:%02x.%x [%04x] [%04x:%04x] :: %s\n",
154current->dev.bits.bus, current->dev.bits.dev, current->dev.bits.func,
155current->class_id, current->vendor_id, current->device_id,
156get_pci_dev_path(current));
157dump_pci_dt(current->children);
158current = current->next;
159}
160}
161

Archive Download this file

Revision: 5