3 #include "manes/error.h"
4 #define pci_register_number(bus, dev, func, dword, ioconf) \
5 ((ioconf) << 31 | (bus) << 16 | (dev) << 11 | (func) << 8 | (dword) << 2)
8 static const int max_pci_buses
= 256;
9 static const int max_pci_devs
= 32;
10 static const int max_pci_funcs
= 8;
16 u32
arch::get_pci_conf(u32 bus
, u32 dev
, u32 func
, u32 dword
) {
17 outl(0xcf8, pci_register_number(bus
, dev
, func
, dword
, 1));
21 void arch::set_pci_conf(u32 bus
, u32 dev
, u32 func
, u32 dword
, u32 value
) {
22 outl(0xcf8, pci_register_number(bus
, dev
, func
, dword
, 1));
26 bool pci_dev_exist(u32 bus
, u32 dev
, u32 func
) {
27 return (get_pci_conf(bus
, dev
, func
, 0) & 0xffff) != 0xffff;
30 const u16 vendors
[] = {
36 const char *company
[] = {
37 "Realtek Semiconductor",
43 u32
arch::get_pci_name(pci_address p
) {
44 return get_pci_conf(p
.bus
, p
.device
, p
.function
, 0);
47 u32
arch::get_pci_type(pci_address p
) {
48 return get_pci_conf(p
.bus
, p
.device
, p
.function
, 2) >> 16;
51 u32
arch::get_pci_fulltype(pci_address p
) {
52 return get_pci_conf(p
.bus
, p
.device
, p
.function
, 2) >> 8;
56 #define PCI_ETHERNET 0x0200
57 #define PCI_USBHOST 0x0c03
59 static u32 start_io
= 0xa00;
60 u32
allocate_pci_io(u32 bar
) {
63 asm ("bsf %%eax, %%eax" : "=a" (size
) : "a" (bar
));
65 u32 allocated
= start_io
;
66 allocated
= (allocated
/ size
+ 1) * size
;
67 start_io
+= allocated
- start_io
;
68 return allocated
& bar
;
71 static u32 free_irqs
[] = { 5, 9, 10, 11 };
72 static int last_irq
= 0;
73 u32
allocate_pci_irq() {
75 return free_irqs
[last_irq
% 4];
78 const char *get_company(pci_address p
) {
79 int vendor
= get_pci_conf(p
.bus
, p
.device
, p
.function
, 0) & 0xffff;
81 for (i
= 0; vendors
[i
] != 0xffff; i
++)
82 if (vendors
[i
] == vendor
)
88 pci_address
get_address(u32 bus
, u32 dev
, u32 func
) {
89 assert("pci: attempt to get address of not existing device", !pci_dev_exist(bus
, dev
, func
));
94 paddr
.function
= func
;
97 //set_pci_conf(bus, dev, func, 15, (get_pci_conf(bus, dev, func, 15) & ~0xff) | allocate_pci_irq());
98 paddr
.irq
= get_pci_conf(bus
, dev
, func
, 15) & 0xff;
100 set_pci_conf(bus
, dev
, func
, 1, get_pci_conf(bus
, dev
, func
, 1) | 3);
102 /* Set IO address space */
103 for (int i
= 0; i
< 5; i
++) {
104 set_pci_conf(bus
, dev
, func
, 4 + i
, 0xffffffff);
105 u32 bar
= get_pci_conf(bus
, dev
, func
, 4 + i
);
106 if ((bar
& 1) == 1) {
107 int ioaddr
= allocate_pci_io(bar
);
108 set_pci_conf(bus
, dev
, func
, i
+4, ioaddr
);
109 paddr
.ioport
= ioaddr
;
116 pci_address
get_device_type(u32 type
) {
117 for (int i
= 0; i
< max_pci_buses
; i
++) {
118 for (int j
= 0; j
< max_pci_devs
; j
++) {
119 for (int k
= 0; k
< max_pci_funcs
; k
++) {
120 if (pci_dev_exist(i
,j
,k
)) {
121 if ((get_pci_conf(i
,j
,k
,2) >> 16) == type
) {
122 return get_address(i
,j
,k
);
128 return get_address(0,0,0);
131 pci_address
get_usb_host() {
132 pci_address p
= get_device_type(PCI_USBHOST
);
134 debug("pci: no usb host found");
138 pci_address
get_eth_device() {
139 pci_address p
= get_device_type(PCI_ETHERNET
);
141 debug("pci: no ethernet card found");
145 int arch::scan_pci_bus() {
147 for (int i
= 0; i
< max_pci_buses
; i
++) {
148 for (int j
= 0; j
< max_pci_devs
; j
++) {
149 for (int k
= 0; k
< max_pci_funcs
; k
++) {
150 if (pci_dev_exist(i
,j
,k
))