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