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