This source file includes following definitions.
- bios32_init
- bios32_service
- pcibios_init
- pcibios_present
- pcibios_find_class_code
- pcibios_find_device
- pcibios_read_config_byte
- pcibios_read_config_word
- pcibios_read_config_dword
- pcibios_write_config_byte
- pcibios_write_config_word
- pcibios_write_config_dword
- NCR53c810_test
- pcibios_strerror
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <linux/kernel.h>
38 #include <linux/segment.h>
39 #include <linux/bios32.h>
40 #include <linux/pci.h>
41
42 #define PCIBIOS_PCI_FUNCTION_ID 0xb1
43 #define PCIBIOS_PCI_BIOS_PRESENT 0x01
44 #define PCIBIOS_FIND_PCI_DEVICE 0x02
45 #define PCIBIOS_FIND_PCI_CLASS_CODE 0x03
46 #define PCIBIOS_GENERATE_SPECIAL_CYCLE 0x06
47 #define PCIBIOS_READ_CONFIG_BYTE 0x08
48 #define PCIBIOS_READ_CONFIG_WORD 0x09
49 #define PCIBIOS_READ_CONFIG_DWORD 0x0a
50 #define PCIBIOS_WRITE_CONFIG_BYTE 0x0b
51 #define PCIBIOS_WRITE_CONFIG_WORD 0x0c
52 #define PCIBIOS_WRITE_CONFIG_DWORD 0x0d
53
54
55 union signature {
56 char chars[4];
57 unsigned long scalar;
58 };
59
60
61
62
63
64
65
66
67
68
69
70 static union signature bios32_signature = {"_32_",};
71
72 union bios32 {
73 struct {
74 union signature signature;
75 long entry;
76 unsigned char revision;
77 unsigned char length;
78 unsigned char checksum;
79 unsigned char reserved[5];
80 } fields;
81 char chars[16];
82 };
83
84
85
86
87
88
89
90
91 static long bios32_entry = 0;
92 static unsigned char bios32_indirect[6];
93
94 static long pcibios_init (long, long);
95
96 long bios32_init (long memory_start, long memory_end) {
97 union bios32 *check;
98 unsigned char sum;
99 int i, length;
100
101
102
103
104
105
106
107 for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0;
108 ++check) {
109 if (check->fields.signature.scalar == bios32_signature.scalar) {
110 for (i = sum = 0, length = check->fields.length * 16;
111 i < check->fields.length * 16; ++i)
112 sum += check->chars[i];
113 if (sum != 0)
114 continue;
115 if (check->fields.revision != 0) {
116 printk ("bios32_init : unsupported revision %d at 0x%x, mail drew@colorado.edu\n",
117 check->fields.revision, (unsigned) check);
118 continue;
119 }
120 printk ("bios32_init : BIOS32 Service Directory structure at 0x%x\n",
121 (unsigned) check);
122 if (!bios32_entry) {
123 *((long *) bios32_indirect) = bios32_entry = check->fields.entry;
124 *((short *) (bios32_indirect + 4)) = KERNEL_CS;
125 printk ("bios32_init : BIOS32 Service Directory entry at 0x%x\n",
126 (unsigned) bios32_entry);
127 } else
128 printk ("bios32_init : multiple entries, mail drew@colorado.edu\n");
129 }
130 }
131 if (bios32_entry) {
132 memory_start = pcibios_init (memory_start, memory_end);
133 }
134 return memory_start;
135 }
136
137
138
139
140
141 static long bios32_service (long service) {
142 unsigned char return_code;
143 long address;
144 long length;
145 long entry;
146
147 __asm__ ("
148 movl $0, %%ebx
149 lcall (%%edi)
150 "
151 : "=al" (return_code), "=ebx" (address), "=ecx" (length), "=edx" (entry)
152 : "eax" (service), "D" (bios32_indirect)
153 : "ebx"
154 );
155
156 switch (return_code) {
157 case 0:
158 return address + entry;
159 case 0x80:
160 printk ("bios32_service(%ld) : not present\n", service);
161 return 0;
162 default:
163 printk ("bios32_service(%ld) : returned 0x%x, mail drew@colorado.edu\n",
164 service, (int) return_code );
165 return 0;
166 }
167
168 }
169
170 static union signature pci_signature = {"PCI ",};
171 static union signature pci_service = {"$PCI",};
172 static long pcibios_entry = 0;
173 static unsigned char pci_indirect[6];
174
175 void NCR53c810_test(void);
176
177 static long pcibios_init (long memory_start, long memory_end) {
178 union signature signature;
179 unsigned char present_status;
180 unsigned char major_revision;
181 unsigned char minor_revision;
182 int pack;
183
184 if ((pcibios_entry = bios32_service (pci_service.scalar))) {
185 *((long *) pci_indirect) = pcibios_entry;
186 *((short *) (pci_indirect + 4)) = KERNEL_CS;
187 __asm__ ("
188 movw $0xb101, %%eax
189 lcall (%%edi)
190 jc 1f
191 xor %%ah, %%ah
192 1:
193 shl $8, %%eax;
194 movw %%bx, %%ax;
195 "
196 : "=edx" (signature.scalar), "=eax" (pack)
197 : "D" (pci_indirect)
198 : "cx"
199 );
200
201 present_status = (pack >> 16) & 0xff;
202 major_revision = (pack >> 8) & 0xff;
203 minor_revision = pack & 0xff;
204 if (present_status || (signature.scalar != pci_signature.scalar)) {
205 printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
206 " but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
207 " and signature of 0x%08lx (%c%c%c%c). mail drew@Colorado.EDU\n",
208 (signature.scalar == pci_signature.scalar) ? "WARNING" : "ERROR",
209 (int) present_status, signature.scalar , signature.chars[0],
210 signature.chars[1], signature.chars[2], signature.chars[3]);
211
212 if (signature.scalar != pci_signature.scalar)
213 pcibios_entry = 0;
214 }
215 if (pcibios_entry) {
216 printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
217 (int) major_revision, (int) minor_revision, pcibios_entry);
218 }
219 }
220
221 #if 0
222 NCR53c810_test();
223 #endif
224 return memory_start;
225 }
226
227 int pcibios_present (void) {
228 return pcibios_entry ? 1 : 0;
229 }
230
231 int pcibios_find_class_code (unsigned long class_code, unsigned short index,
232 unsigned char *bus, unsigned char *device_fn) {
233 unsigned short bx;
234 unsigned short ret;
235 __asm__ ("
236 movw $0xb103, %%ax
237 lcall (%%edi)
238 jc 1f
239 xor %%ah, %%ah
240 1:
241 "
242 : "=bx" (bx), "=ax" (ret)
243 : "cx" (class_code), "S" ((int) index), "D" (pci_indirect)
244 );
245 *bus = (bx >> 8) & 0xff;
246 *device_fn = bx & 0xff;
247 return (int) (ret & 0xff00) >> 8;
248 }
249
250
251 int pcibios_find_device (unsigned short vendor, unsigned short device_id,
252 unsigned short index, unsigned char *bus, unsigned char *device_fn) {
253 unsigned short bx;
254 unsigned short ret;
255 __asm__ ("
256 movw $0xb102, %%ax
257 lcall (%%edi)
258 jc 1f
259 xor %%ah, %%ah
260 1:
261 "
262 : "=bx" (bx), "=ax" (ret)
263 : "cx" (device_id), "dx" (vendor), "S" ((int) index), "D" (pci_indirect)
264 );
265 *bus = (bx >> 8) & 0xff;
266 *device_fn = bx & 0xff;
267 return (int) (ret & 0xff00) >> 8;
268 }
269
270 int pcibios_read_config_byte (unsigned char bus,
271 unsigned char device_fn, unsigned char where, unsigned char *value) {
272 unsigned long ret;
273 unsigned short bx = (bus << 8) | device_fn;
274 __asm__ ("
275 movw $0xb108, %%ax
276 lcall (%%esi)
277 jc 1f
278 xor %%ah, %%ah
279 1:
280 "
281 : "=cl" (*value), "=eax" (ret)
282 : "bx" (bx), "D" ((long) where), "S" (pci_indirect)
283 );
284 return (int) (ret & 0xff00) >> 8;
285 }
286
287 int pcibios_read_config_word (unsigned char bus,
288 unsigned char device_fn, unsigned char where, unsigned short *value) {
289 unsigned short ret;
290 unsigned short bx = (bus << 8) | device_fn;
291 __asm__ ("
292 movw $0xb109, %%ax
293 lcall (%%esi)
294 jc 1f
295 xor %%ah, %%ah
296 1:
297 "
298 : "=cx" (*value), "=ax" (ret)
299 : "bx" (bx), "D" ((long) where), "S" (pci_indirect)
300 );
301 return (int) (ret & 0xff00) >> 8;
302 }
303
304 int pcibios_read_config_dword (unsigned char bus,
305 unsigned char device_fn, unsigned char where, unsigned long *value) {
306 unsigned short ret;
307 unsigned short bx = (bus << 8) | device_fn;
308 __asm__ ("
309 movw $0xb10a, %%ax
310 lcall (%%esi)
311 jc 1f
312 xor %%ah, %%ah
313 1:
314 "
315 : "=ecx" (*value), "=ax" (ret)
316 : "bx" (bx), "D" ((long) where), "S" (pci_indirect)
317 );
318 return (int) (ret & 0xff00) >> 8;
319 }
320
321 int pcibios_write_config_byte (unsigned char bus,
322 unsigned char device_fn, unsigned char where, unsigned char value) {
323 unsigned short ret;
324 unsigned short bx = (bus << 8) | device_fn;
325 __asm__ ("
326 movw $0xb108, %%ax
327 lcall (%%esi)
328 jc 1f
329 xor %%ah, %%ah
330 1:
331 "
332 : "=ax" (ret)
333 : "cl" (value), "bx" (bx), "D" ((long) where), "S" (pci_indirect)
334 );
335 return (int) (ret & 0xff00) >> 8;
336 }
337
338 int pcibios_write_config_word (unsigned char bus,
339 unsigned char device_fn, unsigned char where, unsigned short value) {
340 unsigned short ret;
341 unsigned short bx = (bus << 8) | device_fn;
342 __asm__ ("
343 movw $0xb109, %%ax
344 lcall (%%esi)
345 jc 1f
346 xor %%ah, %%ah
347 1:
348 "
349 : "=ax" (ret)
350 : "cx" (value), "bx" (bx), "D" ((long) where), "S" (pci_indirect)
351 );
352 return (int) (ret & 0xff00) >> 8;
353 }
354
355 int pcibios_write_config_dword (unsigned char bus,
356 unsigned char device_fn, unsigned char where, unsigned long value) {
357 unsigned short ret;
358 unsigned short bx = (bus << 8) | device_fn;
359 __asm__ ("
360 movw $0xb10a, %%ax
361 lcall (%%esi)
362 jc 1f
363 xor %%ah, %%ah
364 1:
365 "
366 : "=ax" (ret)
367 : "ecx" (value), "bx" (bx), "D" ((long) where), "S" (pci_indirect)
368 );
369 return (int) (ret & 0xff00) >> 8;
370 }
371
372 void NCR53c810_test(void) {
373 unsigned char bus, device_fn;
374 unsigned short index;
375 int ret;
376 unsigned char row, col;
377 unsigned long val;
378
379 for (index = 0; index < 4; ++index) {
380 ret = pcibios_find_device ((unsigned short) PCI_VENDOR_ID_NCR, (unsigned short)
381 PCI_DEVICE_ID_NCR_53C810, index, &bus, &device_fn);
382 if (ret)
383 break;
384 printk ("ncr53c810 : at PCI bus %d, device %d, function %d.",
385 (int) bus, (int) ((device_fn & 0xf8) >> 3), (int) (device_fn & 7));
386 for (row = 0; row < 0x3c; row += 0x10) {
387 printk ("\n reg 0x%02x ", row);
388 for (col = 0; col < 0x10; col += 4) {
389 if (!(ret = pcibios_read_config_dword (bus, device_fn, row+col, &val)))
390 printk ("0x%08lx ", val);
391 else
392 printk ("error 0x%02x ", ret);
393 }
394 }
395 printk ("\n");
396 }
397 }
398
399 char *pcibios_strerror (int error) {
400 char buf[80];
401 switch (error) {
402 case PCIBIOS_SUCCESFUL:
403 return "SUCCESFUL";
404 case PCIBIOS_FUNC_NOT_SUPPORTED:
405 return "FUNC_NOT_SUPPORTED";
406 case PCIBIOS_BAD_VENDOR_ID:
407 return "BAD_VENDOR_ID";
408 case PCIBIOS_DEVICE_NOT_FOUND:
409 return "DEVICE_NOT_FOUND";
410 case PCIBIOS_BAD_REGISTER_NUMBER:
411 return "BAD_REGISTER_NUMBER";
412 default:
413 sprintf (buf, "UNKNOWN RETURN 0x%x", error);
414 return buf;
415 }
416 }