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 
28 static cdi_list_t drivers = NULL;
29 static cdi_list_t devices = NULL;
30 
31 static void cdi_destroy(void);
32 
33 void cdi_run_drivers(void);
34 
35 static 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 #ifdef 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 
90 void 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 
100 static bool cdi_module_init()
101 {
102  cdi_init();
103  return true;
104 }
105 
106 EXPORTED_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 
127 EXPORTED_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 
142 static void cdi_destroy(void)
143 {
144  // Drivers are already destroyed by the module exit function
145 }
146 
152 void cdi_run_drivers(void)
153 {
154  // Geraete initialisieren
155  struct cdi_driver* driver;
156  int i;
157  for (i = 0; (driver = reinterpret_cast<struct cdi_driver*>(cdi_list_get(drivers, i))); i++) {
158  cdi_pedigree_walk_dev_list_init(driver);
159  }
160 }
161 
165 void cdi_driver_init(struct cdi_driver* driver)
166 {
167  driver->devices = cdi_list_create();
168 }
169 
173 void cdi_driver_destroy(struct cdi_driver* driver)
174 {
175  cdi_list_destroy(driver->devices);
176 }
177 
183 void cdi_driver_register(struct cdi_driver* driver)
184 {
185  cdi_list_push(drivers, driver);
186 }
187 
188 int cdi_provide_device(struct cdi_bus_data *device)
189 {
190  // What type is the device?
191  switch(device->bus_type)
192  {
193  case CDI_PCI:
194  {
195  // Grab the cdi_pci_device for this device
196  struct cdi_pci_device *pci = reinterpret_cast<struct cdi_pci_device *>(device);
197 
198  // Don't re-create existing devices
199  if(pci->meta.backdev)
200  return -1;
201 
202  // Create a new device object to add to the tree
203  Device *pDevice = new Device();
204 
205  // PCI data
206  pDevice->setPciPosition(pci->bus, pci->dev, pci->function);
207  pDevice->setPciIdentifiers(pci->class_id, pci->subclass_id, pci->vendor_id, pci->device_id, pci->interface_id);
208  pDevice->setInterruptNumber(pci->irq);
209 
210  // PCI BARs
211  struct cdi_pci_resource *pResource = 0;
212  for(int i = 0; (pResource = reinterpret_cast<struct cdi_pci_resource *>(cdi_list_get(pci->resources, i))); i++)
213  {
214  TinyStaticString barName("BAR");
215  barName.append(i, 10);
216 
217  Device::Address *pAddress = new Device::Address(String(barName), pResource->start, pResource->length, pResource->type == CDI_PCI_IOPORTS);
218 
219  pDevice->addresses().pushBack(pAddress);
220  }
221 
222  // Link into the tree
223  Device::addToRoot(pDevice);
224 
225  return 0;
226  }
227 
228  default:
229  WARNING("CDI: Unimplemented device type for cdi_provide_device(): " << static_cast<int>(device->bus_type));
230  break;
231  };
232 
233  return -1;
234 }
235 
236 MODULE_INFO("cdi", &cdi_module_init, &cdi_destroy, "dma", "network-stack", "vfs");
uintptr_t m_Address
Definition: Device.h:89
uint8_t getPciSubclassCode()
Definition: Device.h:214
uint32_t getPciDevicePosition()
Definition: Device.h:239
size_t m_Size
Definition: Device.h:91
virtual void setInterruptNumber(uintptr_t n)
Definition: Device.h:268
virtual Vector< Address * > & addresses()
Definition: Device.h:256
static void addToRoot(Device *device)
Definition: Device.cc:102
Definition: String.h:49
uint32_t getPciBusPosition()
Definition: Device.h:234
virtual uintptr_t getInterruptNumber()
Definition: Device.h:262
Definition: Device.h:43
#define WARNING(text)
Definition: Log.h:78
bool m_IsIoSpace
Definition: Device.h:94
uint32_t getPciFunctionNumber()
Definition: Device.h:244
uint32_t readConfigSpace(Device *pDev, uint8_t offset)
Definition: Pci.cc:75
uint8_t getPciProgInterface()
Definition: Device.h:229
void setPciPosition(uint32_t bus, uint32_t device, uint32_t func)
Definition: Device.h:180
uint16_t getPciDeviceId()
Definition: Device.h:224
static void foreach(Callback callback, Device *root=0)
Definition: Device.cc:94
void setPciIdentifiers(uint8_t classCode, uint8_t subclassCode, uint16_t vendorId, uint16_t deviceId, uint8_t progIf)
Definition: Device.h:188
uint8_t getPciClassCode()
Definition: Device.h:209
void writeConfigSpace(Device *pDev, uint8_t offset, uint32_t data)
Definition: Pci.cc:104
uint16_t getPciVendorId()
Definition: Device.h:219