Rev 184 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | #include <ll/i386/hw-instr.h> |
2 | #include <ll/i386/hw-data.h> |
||
3 | #include <ll/i386/hw-arch.h> |
||
4 | #include <ll/i386/hw-io.h> |
||
5 | #include <ll/i386/cons.h> |
||
6 | #include <ll/stdlib.h> |
||
7 | #include <drivers/llpci.h> |
||
8 | #include <drivers/pci.h> |
||
9 | #include <drivers/linuxpci.h> |
||
10 | |||
16 | pj | 11 | #include <kernel/log.h> |
12 | |||
2 | pj | 13 | static int ndev = 0; |
14 | static struct pci_des pci_devs[N_MAX_DEVS]; |
||
15 | |||
184 | giacomo | 16 | static int initialized = 0; |
17 | |||
2 | pj | 18 | /* scan the bus to find all the connected devices */ |
19 | int scan_bus(struct pci_des *p_des) |
||
20 | { |
||
21 | int ndev; |
||
22 | DWORD tmp; |
||
23 | BYTE hdr; |
||
24 | int j, ok; |
||
25 | BYTE bus, b; |
||
26 | WORD dev; |
||
27 | int present; |
||
28 | |||
29 | if (pcibios_present() == 0) return -1; |
||
30 | ndev = 0; |
||
31 | |||
49 | pj | 32 | for (bus = 0; bus <= 1; bus++) { |
2 | pj | 33 | for (dev = 0; dev <= 0xFF; dev++) { |
34 | present = 0; |
||
35 | if ((dev & 0x07) == 0) { |
||
36 | present = pcibios_read_config_byte(bus, dev, 0x0e, &hdr); |
||
37 | } |
||
38 | if (hdr & 0x80) { |
||
39 | present = 1; |
||
40 | } |
||
41 | if (present) { |
||
42 | ok = pcibios_read_config_dword(bus, dev, 0, &tmp); |
||
43 | if ( ok && (((tmp & 0xFFFF) != 0xFFFF) && ((tmp >> 16) != 0xFFFF))) { |
||
44 | p_des[ndev].bus = bus; |
||
45 | p_des[ndev].dev = dev; |
||
46 | for (j = 0; j <= 255; j++) { |
||
47 | pcibios_read_config_byte(bus, dev, j, &b); |
||
48 | p_des[ndev].mem[j] = b; |
||
49 | } |
||
50 | ndev++; |
||
51 | } |
||
52 | } |
||
53 | } |
||
54 | } |
||
55 | return ndev; |
||
56 | } |
||
57 | |||
58 | struct pci_regs *pci_device(WORD vendor, WORD device, WORD index, BYTE *bus, BYTE *dev) |
||
59 | { |
||
60 | int i, curr; |
||
61 | struct pci_regs *regs; |
||
62 | |||
63 | curr = 0; |
||
64 | for (i = 0; i < ndev; i++) { |
||
65 | regs = (struct pci_regs *)pci_devs[i].mem; |
||
66 | if ((regs->VendorId == vendor) && (regs->DeviceId == device)) { |
||
67 | if (curr == index) { |
||
68 | *dev = pci_devs[i].dev; |
||
69 | *bus = pci_devs[i].bus; |
||
70 | return regs; |
||
71 | } |
||
72 | ++curr; |
||
73 | } |
||
74 | } |
||
75 | return NULL; |
||
76 | } |
||
77 | |||
78 | struct pci_regs *pci_class(DWORD class_code, WORD index, BYTE *bus, BYTE *dev) |
||
79 | { |
||
80 | int i, curr; |
||
81 | struct pci_regs *regs; |
||
82 | |||
83 | curr = 0; |
||
84 | for (i = 0; i < ndev; i++) { |
||
85 | regs = (struct pci_regs *)pci_devs[i].mem; |
||
86 | if ((regs->ClassCode << 8) == class_code) { |
||
87 | if (curr == index) { |
||
88 | *dev = pci_devs[i].dev; |
||
89 | *bus = pci_devs[i].bus; |
||
90 | return regs; |
||
91 | } |
||
92 | ++curr; |
||
93 | } |
||
94 | } |
||
95 | return NULL; |
||
96 | } |
||
97 | |||
98 | int pcibios_find_device(WORD vendor, WORD device, WORD index, BYTE *bus, BYTE *dev) |
||
99 | { |
||
100 | |||
101 | if (pci_device(vendor, device, index, bus, dev) != NULL) { |
||
102 | return PCIBIOS_SUCCESSFUL; |
||
103 | } else { |
||
104 | return PCIBIOS_DEVICE_NOT_FOUND; |
||
105 | } |
||
106 | } |
||
107 | int pcibios_find_class(DWORD class_code, WORD index, BYTE *bus, BYTE *dev) |
||
108 | { |
||
109 | |||
110 | if (pci_class(class_code, index, bus, dev) != NULL) { |
||
16 | pj | 111 | #ifdef DEBUG_PCI |
112 | printk(KERN_DEBUG "PCIBIOS_FIND_CLASS:" |
||
113 | "found at bus %d, dev %d\n", *bus, *dev); |
||
114 | #endif |
||
2 | pj | 115 | return PCIBIOS_SUCCESSFUL; |
116 | } else { |
||
117 | return PCIBIOS_DEVICE_NOT_FOUND; |
||
118 | } |
||
119 | } |
||
120 | |||
121 | |||
122 | /* shows the detected devices */ |
||
123 | void pci_show(void) |
||
124 | { |
||
125 | int i; |
||
126 | struct pci_regs *r; |
||
127 | |||
16 | pj | 128 | printk(KERN_INFO "DevLib PCI support\n\n"); |
129 | printk(KERN_INFO "PCI config type %d\n", pcibios_present()); |
||
130 | printk(KERN_INFO "%d PCI devices found:\n\n", ndev); |
||
2 | pj | 131 | for(i = 0; i < ndev; i++) { |
132 | r = (struct pci_regs *) pci_devs[i].mem; |
||
16 | pj | 133 | printk(KERN_INFO "%d: bus %d dev %d\n", |
134 | i, pci_devs[i].bus, pci_devs[i].dev); |
||
198 | pj | 135 | printk(KERN_INFO "Vendor: %s Class: %s\n", pci_strvendor(r->VendorId), |
136 | pci_strclass(r->ClassCode << 8)); |
||
2 | pj | 137 | } |
138 | } |
||
139 | |||
140 | /*Linux-->unsigned long pci_init(unsigned long mem_start, unsigned long mem_end) */ |
||
141 | /* H-PCI --> void pci_init(void) */ |
||
142 | /* (mem_start/mem_end have no sense) */ |
||
143 | |||
144 | int pci_init(void) |
||
145 | { |
||
184 | giacomo | 146 | if (initialized == 1) return 1; |
147 | |||
2 | pj | 148 | if (pcibios_init() == -1) { |
149 | return -1; |
||
150 | } |
||
184 | giacomo | 151 | |
2 | pj | 152 | ndev = scan_bus(pci_devs); |
184 | giacomo | 153 | |
154 | initialized = 1; |
||
155 | |||
2 | pj | 156 | return 1; |
184 | giacomo | 157 | |
2 | pj | 158 | } |