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