The Pedigree Project 0.1
cdi.cc
1/*
2 * Copyright (c) 2007 Kevin Wolf
3 *
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9 */
10
11#include <cdi-osdep.h>
12#include <cdi.h>
13#include <cdi/lists.h>
14#include <cdi/pci.h>
15#include <stdbool.h>
16#include <stddef.h>
17#include "modules/Module.h"
18#include "pedigree/kernel/Log.h"
19#include "pedigree/kernel/compiler.h"
20#include "pedigree/kernel/machine/Device.h"
21#include "pedigree/kernel/machine/Pci.h"
22#include "pedigree/kernel/processor/types.h"
23#include "pedigree/kernel/utilities/StaticString.h"
24#include "pedigree/kernel/utilities/String.h"
25#include "pedigree/kernel/utilities/Vector.h"
26#include "pedigree/kernel/utilities/new"
27
28static cdi_list_t drivers = NULL;
29static cdi_list_t devices = NULL;
30
31static void cdi_destroy(void);
32
33void cdi_run_drivers(void);
34
35static Device *handleDevice(Device *p)
36{
37 struct cdi_pci_device *dev = new struct cdi_pci_device;
38 dev->bus_data.bus_type = CDI_PCI;
39
40 // Enable bus mastering and standard I/O as needed.
41#if X86_COMMON
42 uint32_t nPciCmdSts = PciBus::instance().readConfigSpace(p, 1);
43 PciBus::instance().writeConfigSpace(p, 1, nPciCmdSts | 0x7);
44#endif
45
46 dev->bus = p->getPciBusPosition();
47 dev->dev = p->getPciDevicePosition();
48 dev->function = p->getPciFunctionNumber();
49
50 dev->vendor_id = p->getPciVendorId();
51 dev->device_id = p->getPciDeviceId();
52
53 dev->class_id = p->getPciClassCode();
54 dev->subclass_id = p->getPciSubclassCode();
55 dev->interface_id = p->getPciProgInterface();
56
57 dev->rev_id = 0;
58
59 dev->irq = p->getInterruptNumber();
60
61 dev->resources = cdi_list_create();
62 for(size_t j = 0; j < p->addresses().count(); j++)
63 {
64 Device::Address *addr = p->addresses()[j];
65 struct cdi_pci_resource *res = new struct cdi_pci_resource;
66 if(addr->m_IsIoSpace)
67 res->type = CDI_PCI_IOPORTS;
68 else
69 res->type = CDI_PCI_MEMORY;
70 res->start = addr->m_Address;
71 res->length = addr->m_Size;
72 res->index = j;
73 res->address = reinterpret_cast<void*>(res->start);
74
75 cdi_list_push(dev->resources, res);
76 }
77
78 dev->meta.backdev = reinterpret_cast<void *>(p);
79
80 cdi_list_push(devices, dev);
81
82 return p;
83}
84
90void cdi_init(void)
91{
92 drivers = cdi_list_create();
93 devices = cdi_list_create();
94
95 // Iterate the device tree and add cdi_bus_data structs to the device list
96 // for each found device.
97 Device::foreach(handleDevice);
98}
99
100static bool cdi_module_init()
101{
102 cdi_init();
103 return true;
104}
105
106EXPORTED_PUBLIC bool cdi_pedigree_walk_dev_list_init(struct cdi_driver *dev)
107{
108 bool bFound = false;
109
110 struct cdi_driver* driver = dev;
111 struct cdi_bus_data* device;
112 int i;
113 for (i = 0; (device = reinterpret_cast<struct cdi_bus_data*>(cdi_list_get(devices, i))); i++) {
114 if (driver->init_device) {
115 struct cdi_device *p = driver->init_device(device);
116 if(p)
117 {
118 p->driver = driver;
119 bFound = true;
120 }
121 }
122 }
123
124 return bFound;
125}
126
127EXPORTED_PUBLIC void cdi_pedigree_walk_dev_list_destroy(struct cdi_driver *dev)
128{
129 struct cdi_driver* driver = dev;
130 struct cdi_device* device;
131 int i;
132 for (i = 0; (device = reinterpret_cast<struct cdi_device*>(cdi_list_get(devices, i))); i++) {
133 if (driver->remove_device) {
134 driver->remove_device(device);
135 }
136 }
137}
138
142static void cdi_destroy(void)
143{
144 auto removeNetworkWrappers = [] (Device *device) {
145 if (device->getType() == Device::Network &&
146 device->getSpecificType().compare("CDI NIC")) {
147 return static_cast<Device *>(nullptr);
148 }
149 return device;
150 };
151 auto callback = pedigree_std::make_callable(removeNetworkWrappers);
152 Device::foreach(callback, 0);
153}
154
160void cdi_run_drivers(void)
161{
162 // Geraete initialisieren
163 struct cdi_driver* driver;
164 int i;
165 for (i = 0; (driver = reinterpret_cast<struct cdi_driver*>(cdi_list_get(drivers, i))); i++) {
166 cdi_pedigree_walk_dev_list_init(driver);
167 }
168}
169
173void cdi_driver_init(struct cdi_driver* driver)
174{
175 driver->devices = cdi_list_create();
176}
177
181void cdi_driver_destroy(struct cdi_driver* driver)
182{
183 cdi_list_destroy(driver->devices);
184}
185
191void cdi_driver_register(struct cdi_driver* driver)
192{
193 cdi_list_push(drivers, driver);
194}
195
196int cdi_provide_device(struct cdi_bus_data *device)
197{
198 // What type is the device?
199 switch(device->bus_type)
200 {
201 case CDI_PCI:
202 {
203 // Grab the cdi_pci_device for this device
204 struct cdi_pci_device *pci = reinterpret_cast<struct cdi_pci_device *>(device);
205
206 // Don't re-create existing devices
207 if(pci->meta.backdev)
208 return -1;
209
210 // Create a new device object to add to the tree
211 Device *pDevice = new Device();
212
213 // PCI data
214 pDevice->setPciPosition(pci->bus, pci->dev, pci->function);
215 pDevice->setPciIdentifiers(pci->class_id, pci->subclass_id, pci->vendor_id, pci->device_id, pci->interface_id);
216 pDevice->setInterruptNumber(pci->irq);
217
218 // PCI BARs
219 struct cdi_pci_resource *pResource = 0;
220 for(int i = 0; (pResource = reinterpret_cast<struct cdi_pci_resource *>(cdi_list_get(pci->resources, i))); i++)
221 {
222 TinyStaticString barName("BAR");
223 barName.append(i, 10);
224
225 Device::Address *pAddress = new Device::Address(String(barName), pResource->start, pResource->length, pResource->type == CDI_PCI_IOPORTS);
226
227 pDevice->addresses().pushBack(pAddress);
228 }
229
230 // Link into the tree
231 Device::addToRoot(pDevice);
232
233 return 0;
234 }
235
236 default:
237 WARNING("CDI: Unimplemented device type for cdi_provide_device(): " << static_cast<int>(device->bus_type));
238 break;
239 };
240
241 return -1;
242}
243
244MODULE_INFO("cdi", &cdi_module_init, &cdi_destroy, "dma", "network-stack", "vfs");
uint16_t getPciDeviceId()
Definition Device.h:223
uint16_t getPciVendorId()
Definition Device.h:219
static void addToRoot(Device *device)
Definition Device.cc:102
uint32_t getPciFunctionNumber()
Definition Device.h:239
uint32_t getPciDevicePosition()
Definition Device.h:235
static void foreach(Callback callback, Device *root=0)
Definition Device.cc:95
virtual Vector< Address * > & addresses()
Definition Device.h:249
void setPciIdentifiers(uint8_t classCode, uint8_t subclassCode, uint16_t vendorId, uint16_t deviceId, uint8_t progIf)
Definition Device.h:194
@ Network
A communication device.
Definition Device.h:75
virtual void setInterruptNumber(uintptr_t n)
Definition Device.h:259
uint8_t getPciClassCode()
Definition Device.h:211
uint8_t getPciSubclassCode()
Definition Device.h:215
uint8_t getPciProgInterface()
Definition Device.h:227
virtual uintptr_t getInterruptNumber()
Definition Device.h:254
uint32_t getPciBusPosition()
Definition Device.h:231
void setPciPosition(uint32_t bus, uint32_t device, uint32_t func)
Definition Device.h:187
uint32_t readConfigSpace(Device *pDev, uint8_t offset)
Definition Pci.cc:83
void writeConfigSpace(Device *pDev, uint8_t offset, uint32_t data)
Definition Pci.cc:94