source: mainline/uspace/srv/dd/pci.c@ cf8cc36

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cf8cc36 was fcbd1be, checked in by Lenka Trochtova <trochtova.lenka@…>, 16 years ago

the name of the hierarchical driver was changed II

  • Property mode set to 100644
File size: 4.0 KB
Line 
1#include <futex.h>
2#include <assert.h>
3
4#include "pci.h"
5#include "pci_bus.h"
6#include "pci_regs.h"
7#include "pci_conf.h"
8
9#define NAME "PCI"
10
11LIST_INITIALIZE(devices_list);
12LIST_INITIALIZE(buses_list);
13LIST_INITIALIZE(drivers_list);
14
15static atomic_t pci_bus_futex = FUTEX_INITIALIZER;
16
17static int pci_match(pci_drv_t *drv, pci_dev_t *dev);
18static int pci_pass_dev(pci_drv_t *drv, pci_dev_t *dev);
19static void pci_lookup_driver(pci_dev_t *dev);
20static void pci_lookup_devices(pci_drv_t *drv);
21
22
23void pci_bus_scan(pci_bus_t *bus)
24{
25 pci_dev_t *dev = pci_alloc_dev();
26 pci_bus_t *child_bus = NULL;
27 int dnum, fnum, bus_num;
28 bool multi;
29 uint8_t header_type;
30
31 for (dnum = 0; dnum < 32; dnum++) {
32 multi = true;
33 for (fnum = 0; multi && fnum < 8; fnum++) {
34 pci_init_dev(dev, bus, dnum, fnum);
35 dev->vendor_id = pci_conf_read_16(dev, PCI_VENDOR_ID);
36 dev->device_id = pci_conf_read_16(dev, PCI_DEVICE_ID);
37 if (dev->vendor_id == 0xFFFF) { // device is not present, go on scanning the bus
38 if (fnum == 0) {
39 break;
40 } else {
41 continue;
42 }
43 }
44 header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE);
45 if (fnum == 0) {
46 multi = header_type >> 7; // is the device multifunction?
47 }
48 header_type = header_type & 0x7F; // clear the multifunction bit
49
50 printf(NAME ": adding new device %3d : %2d : %2d", dev->bus->num, dnum, fnum);
51 printf(" - vendor = 0x%04X, device = 0x%04X.\n", dev->vendor_id, dev->device_id);
52 pci_device_register(dev);
53
54 if (header_type == PCI_HEADER_TYPE_BRIDGE || header_type == PCI_HEADER_TYPE_CARDBUS ) {
55 bus_num = pci_conf_read_8(dev, PCI_BRIDGE_SEC_BUS_NUM);
56 printf(NAME ": device is pci-to-pci bridge, secondary bus number = %d.\n", bus_num);
57 if(bus_num > bus->num) {
58 child_bus = pci_alloc_bus();
59 pci_init_bus(child_bus, bus, bus_num);
60 pci_bus_register(child_bus);
61 pci_bus_scan(child_bus);
62 }
63 }
64
65 dev = pci_alloc_dev(); // alloc new aux. dev. structure
66 }
67 }
68
69 if (dev->vendor_id == 0xFFFF) {
70 pci_free_dev(dev); // free the auxiliary device structure
71 }
72}
73
74/*
75 * Usage: pci_bus_futex must be down.
76 */
77static int pci_pass_dev(pci_drv_t *drv, pci_dev_t *dev)
78{
79 assert(dev->driver == NULL);
80 assert(drv->name != NULL);
81
82 printf(NAME ": passing device to driver '%s'.\n", drv->name);
83 if (drv->ops->add_device != NULL && drv->ops->add_device(dev)) {
84 dev->driver = drv;
85 return 1;
86 }
87
88 return 0;
89}
90
91/*
92 * Usage: pci_bus_futex must be down.
93 */
94static void pci_lookup_driver(pci_dev_t *dev)
95{
96 link_t *item = drivers_list.next;
97 pci_drv_t *drv = NULL;
98
99 while (item != &drivers_list) {
100 drv = list_get_instance(item, pci_drv_t, link);
101 if (pci_match(drv, dev) && pci_pass_dev(drv, dev)) {
102 return;
103 }
104 item = item->next;
105 }
106}
107
108/*
109 * Usage: pci_bus_futex must be down.
110 */
111static void pci_lookup_devices(pci_drv_t *drv)
112{
113 link_t *item = devices_list.next;
114 pci_dev_t *dev = NULL;
115
116 printf(NAME ": looking up devices for a newly added driver '%s'.\n", drv->name);
117
118 while (item != &devices_list) {
119 dev = list_get_instance(item, pci_dev_t, link);
120 if (dev->driver == NULL && pci_match(drv, dev)) {
121 pci_pass_dev(drv, dev);
122 }
123 item = item->next;
124 }
125}
126
127static int pci_match(pci_drv_t *drv, pci_dev_t *dev)
128{
129 return drv->vendor_id == dev->vendor_id && drv->device_id == dev->device_id;
130}
131
132void pci_bus_register(pci_bus_t *bus)
133{
134 futex_down(&pci_bus_futex);
135
136 // add the device to the list of pci devices
137 list_append(&(bus->link), &buses_list);
138
139 futex_up(&pci_bus_futex);
140}
141
142void pci_device_register(pci_dev_t *dev)
143{
144 futex_down(&pci_bus_futex);
145
146 // add the device to the list of pci devices
147 list_append(&(dev->link), &devices_list);
148
149 // try to find suitable driver for the device and pass the device to it
150 pci_lookup_driver(dev);
151
152 futex_up(&pci_bus_futex);
153}
154
155void pci_driver_register(pci_drv_t *drv)
156{
157 assert(drv->name != NULL);
158
159 futex_down(&pci_bus_futex);
160 printf(NAME ": registering new driver '%s'.\n", drv->name);
161 list_append(&(drv->link), &drivers_list);
162
163 // try to find compatible devices
164 pci_lookup_devices(drv);
165
166 futex_up(&pci_bus_futex);
167}
168
Note: See TracBrowser for help on using the repository browser.