minor changes in ne2k_pci and pci drivers
[quarnos.git] / arch / x86 / pci.cpp
blobfdb95f4b457bdd83a4708817a0341cb79a2aed09
1 #include "lowlevel.h"
2 #include "pci.h"
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)
7 namespace arch {
8 static const int max_pci_buses = 256;
9 static const int max_pci_devs = 32;
10 static const int max_pci_funcs = 8;
11 int scan_pci_bus();
14 using namespace arch;
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));
18 return inl(0xcfc);
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));
23 outl(0xcfc, value);
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[] = {
31 0x10ec, /* Realtek */
32 0x8086, /* Intel */
33 0xffff
36 const char *company[] = {
37 "Realtek Semiconductor",
38 "Intel Corporation",
39 "unknown"
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) {
61 bar = bar & ~1;
62 int size;
63 asm ("bsf %%eax, %%eax" : "=a" (size) : "a" (bar));
64 size = 1 << size;
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() {
74 last_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;
80 int i;
81 for (i = 0; vendors[i] != 0xffff; i++)
82 if (vendors[i] == vendor)
83 return company[i];
85 return company[i];
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));
91 pci_address paddr;
92 paddr.bus = bus;
93 paddr.device = dev;
94 paddr.function = func;
96 /* Get IRQ line */
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;
113 return paddr;
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);
133 if (p.bus == -1)
134 debug("pci: no usb host found");
135 return p;
138 pci_address get_eth_device() {
139 pci_address p = get_device_type(PCI_ETHERNET);
140 if (p.bus == -1)
141 debug("pci: no ethernet card found");
142 return p;
145 int arch::scan_pci_bus() {
146 int devices = 0;
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))
151 devices++;
155 return devices;