7 extern struct cdi_driver
*__start_cdi_drivers
, *__stop_cdi_drivers
;
9 uint8_t pci_in8(int bus
, int device
, int function
, int offset
);
10 uint16_t pci_in16(int bus
, int device
, int function
, int offset
);
11 uint32_t pci_in32(int bus
, int device
, int function
, int offset
);
13 void pci_out8(int bus
, int device
, int function
, int offset
, uint8_t value
);
14 void pci_out16(int bus
, int device
, int function
, int offset
, uint16_t value
);
15 void pci_out32(int bus
, int device
, int function
, int offset
, uint32_t value
);
17 extern void register_cdi_audio_device(struct cdi_audio_device
*dev
);
19 void cdi_driver_init(struct cdi_driver
*driver
)
21 driver
->devices
= cdi_list_create();
24 void cdi_driver_destroy(struct cdi_driver
*driver
)
26 struct cdi_device
*dev
;
28 while ((dev
= cdi_list_pop(driver
->devices
))) {
29 if (driver
->remove_device
) {
30 driver
->remove_device(dev
);
35 cdi_list_destroy(driver
->devices
);
42 static void add_pci_function(int bus
, int device
, int function
)
44 struct cdi_pci_device dev
= {
45 .bus_data
.bus_type
= CDI_PCI
,
49 .vendor_id
= pci_in16(bus
, device
, function
, 0x00),
50 .device_id
= pci_in16(bus
, device
, function
, 0x02),
51 .class_id
= pci_in8(bus
, device
, function
, 0x0b),
52 .subclass_id
= pci_in8(bus
, device
, function
, 0x0a),
53 .interface_id
= pci_in8(bus
, device
, function
, 0x09),
54 .rev_id
= pci_in8(bus
, device
, function
, 0x08),
55 .irq
= pci_in8(bus
, device
, function
, 0x3c),
56 .resources
= cdi_list_create()
59 for (int i
= 0; i
< 6; i
++) {
60 uint32_t bar
= pci_in32(bus
, device
, function
, 0x10 + i
* 4);
65 struct cdi_pci_resource
*res
= malloc(sizeof(*res
));
68 res
->type
= CDI_PCI_IOPORTS
;
69 res
->start
= bar
& ~0x3;
73 pci_out32(bus
, device
, function
, 0x10 + i
* 4, 0xfffffffc);
74 res
->length
= ~(pci_in32(bus
, device
, function
, 0x10 + i
* 4) & 0xfffffffc) + 0x1;
75 pci_out32(bus
, device
, function
, 0x10 + i
* 4, bar
& ~0x2);
76 } else if (((bar
>> 1) & 0x3) <= 0x1) {
77 res
->type
= CDI_PCI_MEMORY
;
78 res
->start
= bar
& ~0xf;
82 pci_out32(bus
, device
, function
, 0x10 + i
* 4, 0xfffffff0);
83 res
->length
= ~(pci_in32(bus
, device
, function
, 0x10 + i
* 4) & 0xfffffff0) + 0x1;
84 pci_out32(bus
, device
, function
, 0x10 + i
* 4, bar
);
92 cdi_list_push(dev
.resources
, res
);
95 struct cdi_driver
**drvp
= &__start_cdi_drivers
;
96 while (drvp
< &__stop_cdi_drivers
) {
97 struct cdi_driver
*drv
= *drvp
;
99 if (drv
->bus
== CDI_PCI
&& drv
->init_device
) {
100 struct cdi_device
*cdi_dev
= drv
->init_device(&dev
.bus_data
);
102 cdi_dev
->driver
= drv
;
103 cdi_list_push(drv
->devices
, cdi_dev
);
105 if (drv
->type
== CDI_AUDIO
) {
106 register_cdi_audio_device((struct cdi_audio_device
*)cdi_dev
);
117 static void enumerate_pci_bus(int bus
)
119 for (int dev
= 0; dev
< 32; dev
++) {
120 for (int fnc
= 0; fnc
< 8; fnc
++) {
121 if (pci_in16(bus
, dev
, fnc
, 0x00) == 0xffff) {
129 switch (pci_in8(bus
, dev
, fnc
, 0x0e) & 0x7f) {
131 add_pci_function(bus
, dev
, fnc
);
135 enumerate_pci_bus(pci_in8(bus
, dev
, fnc
, 0x19));
138 if (!fnc
&& !(pci_in8(bus
, dev
, fnc
, 0x0e) & 0x80)) {
145 void load_cdi_drivers(void)
147 struct cdi_driver
**drvp
= &__start_cdi_drivers
;
148 while (drvp
< &__stop_cdi_drivers
) {
149 struct cdi_driver
*drv
= *drvp
;
151 if (drv
->init
!= NULL
) {
155 if (drv
->type
== CDI_AUDIO
) {
156 for (size_t i
= 0; i
< cdi_list_size(drv
->devices
); i
++) {
157 register_cdi_audio_device((struct cdi_audio_device
*)cdi_list_get(drv
->devices
, i
));
164 enumerate_pci_bus(0);