OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [i386/] [kernel/] [bios32.c] - Blame information for rev 1623

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*
2
 * bios32.c - BIOS32, PCI BIOS functions.
3
 *
4
 * $Id: bios32.c,v 1.1 2005-12-20 09:42:23 jcastillo Exp $
5
 *
6
 * Sponsored by
7
 *      iX Multiuser Multitasking Magazine
8
 *      Hannover, Germany
9
 *      hm@ix.de
10
 *
11
 * Copyright 1993, 1994 Drew Eckhardt
12
 *      Visionary Computing
13
 *      (Unix and Linux consulting and custom programming)
14
 *      Drew@Colorado.EDU
15
 *      +1 (303) 786-7975
16
 *
17
 * For more information, please consult
18
 *
19
 * PCI BIOS Specification Revision
20
 * PCI Local Bus Specification
21
 * PCI System Design Guide
22
 *
23
 * PCI Special Interest Group
24
 * M/S HF3-15A
25
 * 5200 N.E. Elam Young Parkway
26
 * Hillsboro, Oregon 97124-6497
27
 * +1 (503) 696-2000
28
 * +1 (800) 433-5177
29
 *
30
 * Manuals are $25 each or $50 for all three, plus $7 shipping
31
 * within the United States, $35 abroad.
32
 *
33
 *
34
 * CHANGELOG :
35
 * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
36
 *      Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
37
 *
38
 * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
39
 *     Potter, potter@cao-vlsi.ibp.fr
40
 *
41
 * Jan 10, 1995 : Modified to store the information about configured pci
42
 *      devices into a list, which can be accessed via /proc/pci by
43
 *      Curtis Varner, cvarner@cs.ucr.edu
44
 *
45
 * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
46
 *      Alpha version. Intel & UMC chipset support only.
47
 *
48
 * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
49
 *      moved to drivers/pci/pci.c.
50
 *
51
 * Dec 7, 1996  : Added support for direct configuration access of boards
52
 *      with Intel compatible access schemes (tsbogend@alpha.franken.de)
53
 *
54
 * Feb 3, 1997  : Set internal functions to static, save/restore flags
55
 *      avoid dead locks reading broken PCI BIOS, werner@suse.de
56
 *
57
 * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
58
 *      (mj@atrey.karlin.mff.cuni.cz)
59
 *
60
 * May 7,  1997 : Added some missing cli()'s. [mj]
61
 *
62
 * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
63
 *      (paubert@iram.es)
64
 */
65
 
66
#include <linux/config.h>
67
#include <linux/types.h>
68
#include <linux/kernel.h>
69
#include <linux/bios32.h>
70
#include <linux/pci.h>
71
 
72
#include <asm/segment.h>
73
#include <asm/system.h>
74
#include <asm/io.h>
75
 
76
#define PCIBIOS_PCI_FUNCTION_ID         0xb1XX
77
#define PCIBIOS_PCI_BIOS_PRESENT        0xb101
78
#define PCIBIOS_FIND_PCI_DEVICE         0xb102
79
#define PCIBIOS_FIND_PCI_CLASS_CODE     0xb103
80
#define PCIBIOS_GENERATE_SPECIAL_CYCLE  0xb106
81
#define PCIBIOS_READ_CONFIG_BYTE        0xb108
82
#define PCIBIOS_READ_CONFIG_WORD        0xb109
83
#define PCIBIOS_READ_CONFIG_DWORD       0xb10a
84
#define PCIBIOS_WRITE_CONFIG_BYTE       0xb10b
85
#define PCIBIOS_WRITE_CONFIG_WORD       0xb10c
86
#define PCIBIOS_WRITE_CONFIG_DWORD      0xb10d
87
 
88
 
89
/* BIOS32 signature: "_32_" */
90
#define BIOS32_SIGNATURE        (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
91
 
92
/* PCI signature: "PCI " */
93
#define PCI_SIGNATURE           (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
94
 
95
/* PCI service signature: "$PCI" */
96
#define PCI_SERVICE             (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
97
 
98
/*
99
 * This is the standard structure used to identify the entry point
100
 * to the BIOS32 Service Directory, as documented in
101
 *      Standard BIOS 32-bit Service Directory Proposal
102
 *      Revision 0.4 May 24, 1993
103
 *      Phoenix Technologies Ltd.
104
 *      Norwood, MA
105
 * and the PCI BIOS specification.
106
 */
107
 
108
union bios32 {
109
        struct {
110
                unsigned long signature;        /* _32_ */
111
                unsigned long entry;            /* 32 bit physical address */
112
                unsigned char revision;         /* Revision level, 0 */
113
                unsigned char length;           /* Length in paragraphs should be 01 */
114
                unsigned char checksum;         /* All bytes must add up to zero */
115
                unsigned char reserved[5];      /* Must be zero */
116
        } fields;
117
        char chars[16];
118
};
119
 
120
#ifdef CONFIG_PCI
121
/*
122
 * Physical address of the service directory.  I don't know if we're
123
 * allowed to have more than one of these or not, so just in case
124
 * we'll make pcibios_present() take a memory start parameter and store
125
 * the array there.
126
 */
127
 
128
static unsigned long bios32_entry = 0;
129
static struct {
130
        unsigned long address;
131
        unsigned short segment;
132
} bios32_indirect = { 0, KERNEL_CS };
133
 
134
 
135
/*
136
 * function table for accessing PCI configuration space
137
 */
138
struct pci_access {
139
    int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);
140
    int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);
141
    int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
142
    int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *);
143
    int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);
144
    int (*write_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char);
145
    int (*write_config_word)(unsigned char, unsigned char, unsigned char, unsigned short);
146
    int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int);
147
};
148
 
149
/*
150
 * pointer to selected PCI access function table
151
 */
152
static struct pci_access *access_pci = NULL;
153
 
154
 
155
 
156
/*
157
 * Returns the entry point for the given service, NULL on error
158
 */
159
 
160
static unsigned long bios32_service(unsigned long service)
161
{
162
        unsigned char return_code;      /* %al */
163
        unsigned long address;          /* %ebx */
164
        unsigned long length;           /* %ecx */
165
        unsigned long entry;            /* %edx */
166
        unsigned long flags;
167
 
168
        save_flags(flags); cli();
169
        __asm__("lcall (%%edi)"
170
                : "=a" (return_code),
171
                  "=b" (address),
172
                  "=c" (length),
173
                  "=d" (entry)
174
                : "0" (service),
175
                  "1" (0),
176
                  "D" (&bios32_indirect));
177
        restore_flags(flags);
178
 
179
        switch (return_code) {
180
                case 0:
181
                        return address + entry;
182
                case 0x80:      /* Not present */
183
                        printk("bios32_service(0x%lx) : not present\n", service);
184
                        return 0;
185
                default: /* Shouldn't happen */
186
                        printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n",
187
                                service, return_code);
188
                        return 0;
189
        }
190
}
191
 
192
static long pcibios_entry = 0;
193
static struct {
194
        unsigned long address;
195
        unsigned short segment;
196
} pci_indirect = { 0, KERNEL_CS };
197
 
198
 
199
static int check_pcibios(void)
200
{
201
        unsigned long signature;
202
        unsigned char present_status;
203
        unsigned char major_revision;
204
        unsigned char minor_revision;
205
        unsigned long flags;
206
        int pack;
207
 
208
        if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
209
                pci_indirect.address = pcibios_entry;
210
 
211
                save_flags(flags); cli();
212
                __asm__("lcall (%%edi)\n\t"
213
                        "jc 1f\n\t"
214
                        "xor %%ah, %%ah\n"
215
                        "1:\tshl $8, %%eax\n\t"
216
                        "movw %%bx, %%ax"
217
                        : "=d" (signature),
218
                          "=a" (pack)
219
                        : "1" (PCIBIOS_PCI_BIOS_PRESENT),
220
                          "D" (&pci_indirect)
221
                        : "bx", "cx");
222
                restore_flags(flags);
223
 
224
                present_status = (pack >> 16) & 0xff;
225
                major_revision = (pack >> 8) & 0xff;
226
                minor_revision = pack & 0xff;
227
                if (present_status || (signature != PCI_SIGNATURE)) {
228
                        printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
229
                                "       but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
230
                                "       and signature of 0x%08lx (%c%c%c%c).  mail drew@Colorado.EDU\n",
231
                                (signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
232
                                present_status, signature,
233
                                (char) (signature >>  0), (char) (signature >>  8),
234
                                (char) (signature >> 16), (char) (signature >> 24));
235
 
236
                        if (signature != PCI_SIGNATURE)
237
                                pcibios_entry = 0;
238
                }
239
                if (pcibios_entry) {
240
                        printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
241
                                major_revision, minor_revision, pcibios_entry);
242
                        return 1;
243
                }
244
        }
245
        return 0;
246
}
247
 
248
 
249
static int pci_bios_find_class (unsigned int class_code, unsigned short index,
250
        unsigned char *bus, unsigned char *device_fn)
251
{
252
        unsigned long bx;
253
        unsigned long ret;
254
        unsigned long flags;
255
 
256
        save_flags(flags); cli();
257
        __asm__ ("lcall (%%edi)\n\t"
258
                "jc 1f\n\t"
259
                "xor %%ah, %%ah\n"
260
                "1:"
261
                : "=b" (bx),
262
                  "=a" (ret)
263
                : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
264
                  "c" (class_code),
265
                  "S" ((int) index),
266
                  "D" (&pci_indirect));
267
        restore_flags(flags);
268
        *bus = (bx >> 8) & 0xff;
269
        *device_fn = bx & 0xff;
270
        return (int) (ret & 0xff00) >> 8;
271
}
272
 
273
 
274
static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
275
        unsigned short index, unsigned char *bus, unsigned char *device_fn)
276
{
277
        unsigned short bx;
278
        unsigned short ret;
279
        unsigned long flags;
280
 
281
        save_flags(flags); cli();
282
        __asm__("lcall (%%edi)\n\t"
283
                "jc 1f\n\t"
284
                "xor %%ah, %%ah\n"
285
                "1:"
286
                : "=b" (bx),
287
                  "=a" (ret)
288
                : "1" (PCIBIOS_FIND_PCI_DEVICE),
289
                  "c" (device_id),
290
                  "d" (vendor),
291
                  "S" ((int) index),
292
                  "D" (&pci_indirect));
293
        restore_flags(flags);
294
        *bus = (bx >> 8) & 0xff;
295
        *device_fn = bx & 0xff;
296
        return (int) (ret & 0xff00) >> 8;
297
}
298
 
299
static int pci_bios_read_config_byte(unsigned char bus,
300
        unsigned char device_fn, unsigned char where, unsigned char *value)
301
{
302
        unsigned long ret;
303
        unsigned long bx = (bus << 8) | device_fn;
304
        unsigned long flags;
305
 
306
        save_flags(flags); cli();
307
        __asm__("lcall (%%esi)\n\t"
308
                "jc 1f\n\t"
309
                "xor %%ah, %%ah\n"
310
                "1:"
311
                : "=c" (*value),
312
                  "=a" (ret)
313
                : "1" (PCIBIOS_READ_CONFIG_BYTE),
314
                  "b" (bx),
315
                  "D" ((long) where),
316
                  "S" (&pci_indirect));
317
        restore_flags(flags);
318
        return (int) (ret & 0xff00) >> 8;
319
}
320
 
321
static int pci_bios_read_config_word (unsigned char bus,
322
        unsigned char device_fn, unsigned char where, unsigned short *value)
323
{
324
        unsigned long ret;
325
        unsigned long bx = (bus << 8) | device_fn;
326
        unsigned long flags;
327
 
328
        save_flags(flags); cli();
329
        __asm__("lcall (%%esi)\n\t"
330
                "jc 1f\n\t"
331
                "xor %%ah, %%ah\n"
332
                "1:"
333
                : "=c" (*value),
334
                  "=a" (ret)
335
                : "1" (PCIBIOS_READ_CONFIG_WORD),
336
                  "b" (bx),
337
                  "D" ((long) where),
338
                  "S" (&pci_indirect));
339
        restore_flags(flags);
340
        return (int) (ret & 0xff00) >> 8;
341
}
342
 
343
static int pci_bios_read_config_dword (unsigned char bus,
344
        unsigned char device_fn, unsigned char where, unsigned int *value)
345
{
346
        unsigned long ret;
347
        unsigned long bx = (bus << 8) | device_fn;
348
        unsigned long flags;
349
 
350
        save_flags(flags); cli();
351
        __asm__("lcall (%%esi)\n\t"
352
                "jc 1f\n\t"
353
                "xor %%ah, %%ah\n"
354
                "1:"
355
                : "=c" (*value),
356
                  "=a" (ret)
357
                : "1" (PCIBIOS_READ_CONFIG_DWORD),
358
                  "b" (bx),
359
                  "D" ((long) where),
360
                  "S" (&pci_indirect));
361
        restore_flags(flags);
362
        return (int) (ret & 0xff00) >> 8;
363
}
364
 
365
static int pci_bios_write_config_byte (unsigned char bus,
366
        unsigned char device_fn, unsigned char where, unsigned char value)
367
{
368
        unsigned long ret;
369
        unsigned long bx = (bus << 8) | device_fn;
370
        unsigned long flags;
371
 
372
        save_flags(flags); cli();
373
        __asm__("lcall (%%esi)\n\t"
374
                "jc 1f\n\t"
375
                "xor %%ah, %%ah\n"
376
                "1:"
377
                : "=a" (ret)
378
                : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
379
                  "c" (value),
380
                  "b" (bx),
381
                  "D" ((long) where),
382
                  "S" (&pci_indirect));
383
        restore_flags(flags);
384
        return (int) (ret & 0xff00) >> 8;
385
}
386
 
387
static int pci_bios_write_config_word (unsigned char bus,
388
        unsigned char device_fn, unsigned char where, unsigned short value)
389
{
390
        unsigned long ret;
391
        unsigned long bx = (bus << 8) | device_fn;
392
        unsigned long flags;
393
 
394
        save_flags(flags); cli();
395
        __asm__("lcall (%%esi)\n\t"
396
                "jc 1f\n\t"
397
                "xor %%ah, %%ah\n"
398
                "1:"
399
                : "=a" (ret)
400
                : "0" (PCIBIOS_WRITE_CONFIG_WORD),
401
                  "c" (value),
402
                  "b" (bx),
403
                  "D" ((long) where),
404
                  "S" (&pci_indirect));
405
        restore_flags(flags);
406
        return (int) (ret & 0xff00) >> 8;
407
}
408
 
409
static int pci_bios_write_config_dword (unsigned char bus,
410
        unsigned char device_fn, unsigned char where, unsigned int value)
411
{
412
        unsigned long ret;
413
        unsigned long bx = (bus << 8) | device_fn;
414
        unsigned long flags;
415
 
416
        save_flags(flags); cli();
417
        __asm__("lcall (%%esi)\n\t"
418
                "jc 1f\n\t"
419
                "xor %%ah, %%ah\n"
420
                "1:"
421
                : "=a" (ret)
422
                : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
423
                  "c" (value),
424
                  "b" (bx),
425
                  "D" ((long) where),
426
                  "S" (&pci_indirect));
427
        restore_flags(flags);
428
        return (int) (ret & 0xff00) >> 8;
429
}
430
 
431
/*
432
 * function table for BIOS32 access
433
 */
434
static struct pci_access pci_bios_access = {
435
      pci_bios_find_device,
436
      pci_bios_find_class,
437
      pci_bios_read_config_byte,
438
      pci_bios_read_config_word,
439
      pci_bios_read_config_dword,
440
      pci_bios_write_config_byte,
441
      pci_bios_write_config_word,
442
      pci_bios_write_config_dword
443
};
444
 
445
 
446
 
447
/*
448
 * Given the vendor and device ids, find the n'th instance of that device
449
 * in the system.
450
 */
451
static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
452
                           unsigned short index, unsigned char *bus,
453
                           unsigned char *devfn)
454
{
455
    unsigned int curr = 0;
456
    struct pci_dev *dev;
457
 
458
    for (dev = pci_devices; dev; dev = dev->next) {
459
        if (dev->vendor == vendor && dev->device == device_id) {
460
            if (curr == index) {
461
                *devfn = dev->devfn;
462
                *bus = dev->bus->number;
463
                return PCIBIOS_SUCCESSFUL;
464
            }
465
            ++curr;
466
        }
467
    }
468
    return PCIBIOS_DEVICE_NOT_FOUND;
469
}
470
 
471
 
472
/*
473
 * Given the class, find the n'th instance of that device
474
 * in the system.
475
 */
476
static int pci_direct_find_class (unsigned int class_code, unsigned short index,
477
                          unsigned char *bus, unsigned char *devfn)
478
{
479
    unsigned int curr = 0;
480
    struct pci_dev *dev;
481
 
482
    for (dev = pci_devices; dev; dev = dev->next) {
483
        if (dev->class == class_code) {
484
            if (curr == index) {
485
                *devfn = dev->devfn;
486
                *bus = dev->bus->number;
487
                return PCIBIOS_SUCCESSFUL;
488
            }
489
            ++curr;
490
        }
491
    }
492
    return PCIBIOS_DEVICE_NOT_FOUND;
493
}
494
 
495
/*
496
 * Functions for accessing PCI configuration space with type 1 accesses
497
 */
498
#define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
499
 
500
static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn,
501
                               unsigned char where, unsigned char *value)
502
{
503
    unsigned long flags;
504
 
505
    save_flags(flags); cli();
506
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
507
    *value = inb(0xCFC + (where&3));
508
    restore_flags(flags);
509
    return PCIBIOS_SUCCESSFUL;
510
}
511
 
512
static int pci_conf1_read_config_word (unsigned char bus,
513
    unsigned char device_fn, unsigned char where, unsigned short *value)
514
{
515
    unsigned long flags;
516
 
517
    if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
518
    save_flags(flags); cli();
519
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
520
    *value = inw(0xCFC + (where&2));
521
    restore_flags(flags);
522
    return PCIBIOS_SUCCESSFUL;
523
}
524
 
525
static int pci_conf1_read_config_dword (unsigned char bus, unsigned char device_fn,
526
                                 unsigned char where, unsigned int *value)
527
{
528
    unsigned long flags;
529
 
530
    if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
531
    save_flags(flags); cli();
532
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
533
    *value = inl(0xCFC);
534
    restore_flags(flags);
535
    return PCIBIOS_SUCCESSFUL;
536
}
537
 
538
static int pci_conf1_write_config_byte (unsigned char bus, unsigned char device_fn,
539
                                 unsigned char where, unsigned char value)
540
{
541
    unsigned long flags;
542
 
543
    save_flags(flags); cli();
544
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
545
    outb(value, 0xCFC + (where&3));
546
    restore_flags(flags);
547
    return PCIBIOS_SUCCESSFUL;
548
}
549
 
550
static int pci_conf1_write_config_word (unsigned char bus, unsigned char device_fn,
551
                                 unsigned char where, unsigned short value)
552
{
553
    unsigned long flags;
554
 
555
    if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
556
    save_flags(flags); cli();
557
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
558
    outw(value, 0xCFC + (where&2));
559
    restore_flags(flags);
560
    return PCIBIOS_SUCCESSFUL;
561
}
562
 
563
static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device_fn,
564
                                  unsigned char where, unsigned int value)
565
{
566
    unsigned long flags;
567
 
568
    if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
569
    save_flags(flags); cli();
570
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
571
    outl(value, 0xCFC);
572
    restore_flags(flags);
573
    return PCIBIOS_SUCCESSFUL;
574
}
575
 
576
#undef CONFIG_CMD
577
 
578
/*
579
 * functiontable for type 1
580
 */
581
static struct pci_access pci_direct_conf1 = {
582
      pci_direct_find_device,
583
      pci_direct_find_class,
584
      pci_conf1_read_config_byte,
585
      pci_conf1_read_config_word,
586
      pci_conf1_read_config_dword,
587
      pci_conf1_write_config_byte,
588
      pci_conf1_write_config_word,
589
      pci_conf1_write_config_dword
590
};
591
 
592
/*
593
 * Functions for accessing PCI configuration space with type 2 accesses
594
 */
595
#define IOADDR(devfn, where)   ((0xC000 | ((devfn & 0x78) << 5)) + where)
596
#define FUNC(devfn)            (((devfn & 7) << 1) | 0xf0)
597
 
598
static int pci_conf2_read_config_byte(unsigned char bus, unsigned char device_fn,
599
                               unsigned char where, unsigned char *value)
600
{
601
    unsigned long flags;
602
 
603
    if (device_fn & 0x80)
604
        return PCIBIOS_DEVICE_NOT_FOUND;
605
    save_flags(flags); cli();
606
    outb (FUNC(device_fn), 0xCF8);
607
    outb (bus, 0xCFA);
608
    *value = inb(IOADDR(device_fn,where));
609
    outb (0, 0xCF8);
610
    restore_flags(flags);
611
    return PCIBIOS_SUCCESSFUL;
612
}
613
 
614
static int pci_conf2_read_config_word (unsigned char bus, unsigned char device_fn,
615
                                unsigned char where, unsigned short *value)
616
{
617
    unsigned long flags;
618
 
619
    if (device_fn & 0x80)
620
        return PCIBIOS_DEVICE_NOT_FOUND;
621
    save_flags(flags); cli();
622
    outb (FUNC(device_fn), 0xCF8);
623
    outb (bus, 0xCFA);
624
    *value = inw(IOADDR(device_fn,where));
625
    outb (0, 0xCF8);
626
    restore_flags(flags);
627
    return PCIBIOS_SUCCESSFUL;
628
}
629
 
630
static int pci_conf2_read_config_dword (unsigned char bus, unsigned char device_fn,
631
                                 unsigned char where, unsigned int *value)
632
{
633
    unsigned long flags;
634
 
635
    if (device_fn & 0x80)
636
        return PCIBIOS_DEVICE_NOT_FOUND;
637
    save_flags(flags); cli();
638
    outb (FUNC(device_fn), 0xCF8);
639
    outb (bus, 0xCFA);
640
    *value = inl (IOADDR(device_fn,where));
641
    outb (0, 0xCF8);
642
    restore_flags(flags);
643
    return PCIBIOS_SUCCESSFUL;
644
}
645
 
646
static int pci_conf2_write_config_byte (unsigned char bus, unsigned char device_fn,
647
                                 unsigned char where, unsigned char value)
648
{
649
    unsigned long flags;
650
 
651
    save_flags(flags); cli();
652
    outb (FUNC(device_fn), 0xCF8);
653
    outb (bus, 0xCFA);
654
    outb (value, IOADDR(device_fn,where));
655
    outb (0, 0xCF8);
656
    restore_flags(flags);
657
    return PCIBIOS_SUCCESSFUL;
658
}
659
 
660
static int pci_conf2_write_config_word (unsigned char bus, unsigned char device_fn,
661
                                 unsigned char where, unsigned short value)
662
{
663
    unsigned long flags;
664
 
665
    save_flags(flags); cli();
666
    outb (FUNC(device_fn), 0xCF8);
667
    outb (bus, 0xCFA);
668
    outw (value, IOADDR(device_fn,where));
669
    outb (0, 0xCF8);
670
    restore_flags(flags);
671
    return PCIBIOS_SUCCESSFUL;
672
}
673
 
674
static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device_fn,
675
                                  unsigned char where, unsigned int value)
676
{
677
    unsigned long flags;
678
 
679
    save_flags(flags); cli();
680
    outb (FUNC(device_fn), 0xCF8);
681
    outb (bus, 0xCFA);
682
    outl (value, IOADDR(device_fn,where));
683
    outb (0, 0xCF8);
684
    restore_flags(flags);
685
    return PCIBIOS_SUCCESSFUL;
686
}
687
 
688
#undef IOADDR
689
#undef FUNC
690
 
691
/*
692
 * functiontable for type 2
693
 */
694
static struct pci_access pci_direct_conf2 = {
695
      pci_direct_find_device,
696
      pci_direct_find_class,
697
      pci_conf2_read_config_byte,
698
      pci_conf2_read_config_word,
699
      pci_conf2_read_config_dword,
700
      pci_conf2_write_config_byte,
701
      pci_conf2_write_config_word,
702
      pci_conf2_write_config_dword
703
};
704
 
705
 
706
static struct pci_access *check_direct_pci(void)
707
{
708
    unsigned int tmp;
709
    unsigned long flags;
710
 
711
    save_flags(flags); cli();
712
 
713
    /*
714
     * check if configuration type 1 works
715
     */
716
    outb (0x01, 0xCFB);
717
    tmp = inl (0xCF8);
718
    outl (0x80000000, 0xCF8);
719
    if (inl (0xCF8) == 0x80000000) {
720
        outl (tmp, 0xCF8);
721
        restore_flags(flags);
722
        printk("pcibios_init: Using configuration type 1\n");
723
        return &pci_direct_conf1;
724
    }
725
    outl (tmp, 0xCF8);
726
 
727
    /*
728
     * check if configuration type 2 works
729
     */
730
    outb (0x00, 0xCFB);
731
    outb (0x00, 0xCF8);
732
    outb (0x00, 0xCFA);
733
    if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) {
734
        restore_flags(flags);
735
        printk("pcibios_init: Using configuration type 2\n");
736
        return &pci_direct_conf2;
737
    }
738
    restore_flags(flags);
739
    printk("pcibios_init: Not supported chipset for direct PCI access !\n");
740
    return NULL;
741
}
742
 
743
 
744
/*
745
 * access defined pcibios functions via
746
 * the function table
747
 */
748
 
749
int pcibios_present(void)
750
{
751
        return access_pci ? 1 : 0;
752
}
753
 
754
int pcibios_find_class (unsigned int class_code, unsigned short index,
755
        unsigned char *bus, unsigned char *device_fn)
756
{
757
   if (access_pci && access_pci->find_class)
758
      return access_pci->find_class(class_code, index, bus, device_fn);
759
 
760
    return PCIBIOS_FUNC_NOT_SUPPORTED;
761
}
762
 
763
int pcibios_find_device (unsigned short vendor, unsigned short device_id,
764
        unsigned short index, unsigned char *bus, unsigned char *device_fn)
765
{
766
    if (access_pci && access_pci->find_device)
767
      return access_pci->find_device(vendor, device_id, index, bus, device_fn);
768
 
769
    return PCIBIOS_FUNC_NOT_SUPPORTED;
770
}
771
 
772
int pcibios_read_config_byte (unsigned char bus,
773
        unsigned char device_fn, unsigned char where, unsigned char *value)
774
{
775
    if (access_pci && access_pci->read_config_byte)
776
      return access_pci->read_config_byte(bus, device_fn, where, value);
777
 
778
    return PCIBIOS_FUNC_NOT_SUPPORTED;
779
}
780
 
781
int pcibios_read_config_word (unsigned char bus,
782
        unsigned char device_fn, unsigned char where, unsigned short *value)
783
{
784
    if (access_pci && access_pci->read_config_word)
785
      return access_pci->read_config_word(bus, device_fn, where, value);
786
 
787
    return PCIBIOS_FUNC_NOT_SUPPORTED;
788
}
789
 
790
int pcibios_read_config_dword (unsigned char bus,
791
        unsigned char device_fn, unsigned char where, unsigned int *value)
792
{
793
    if (access_pci && access_pci->read_config_dword)
794
      return access_pci->read_config_dword(bus, device_fn, where, value);
795
 
796
    return PCIBIOS_FUNC_NOT_SUPPORTED;
797
}
798
 
799
int pcibios_write_config_byte (unsigned char bus,
800
        unsigned char device_fn, unsigned char where, unsigned char value)
801
{
802
    if (access_pci && access_pci->write_config_byte)
803
      return access_pci->write_config_byte(bus, device_fn, where, value);
804
 
805
    return PCIBIOS_FUNC_NOT_SUPPORTED;
806
}
807
 
808
int pcibios_write_config_word (unsigned char bus,
809
        unsigned char device_fn, unsigned char where, unsigned short value)
810
{
811
    if (access_pci && access_pci->write_config_word)
812
      return access_pci->write_config_word(bus, device_fn, where, value);
813
 
814
    return PCIBIOS_FUNC_NOT_SUPPORTED;
815
}
816
 
817
int pcibios_write_config_dword (unsigned char bus,
818
        unsigned char device_fn, unsigned char where, unsigned int value)
819
{
820
    if (access_pci && access_pci->write_config_dword)
821
      return access_pci->write_config_dword(bus, device_fn, where, value);
822
 
823
    return PCIBIOS_FUNC_NOT_SUPPORTED;
824
}
825
 
826
const char *pcibios_strerror (int error)
827
{
828
        static char buf[80];
829
 
830
        switch (error) {
831
                case PCIBIOS_SUCCESSFUL:
832
                        return "SUCCESSFUL";
833
 
834
                case PCIBIOS_FUNC_NOT_SUPPORTED:
835
                        return "FUNC_NOT_SUPPORTED";
836
 
837
                case PCIBIOS_BAD_VENDOR_ID:
838
                        return "SUCCESSFUL";
839
 
840
                case PCIBIOS_DEVICE_NOT_FOUND:
841
                        return "DEVICE_NOT_FOUND";
842
 
843
                case PCIBIOS_BAD_REGISTER_NUMBER:
844
                        return "BAD_REGISTER_NUMBER";
845
 
846
                case PCIBIOS_SET_FAILED:
847
                        return "SET_FAILED";
848
 
849
                case PCIBIOS_BUFFER_TOO_SMALL:
850
                        return "BUFFER_TOO_SMALL";
851
 
852
                default:
853
                        sprintf (buf, "UNKNOWN RETURN 0x%x", error);
854
                        return buf;
855
        }
856
}
857
 
858
 
859
unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
860
{
861
    return mem_start;
862
}
863
 
864
#endif
865
 
866
unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
867
{
868
#ifdef CONFIG_PCI
869
        union bios32 *check;
870
        unsigned char sum;
871
        int i, length;
872
 
873
        /*
874
         * Follow the standard procedure for locating the BIOS32 Service
875
         * directory by scanning the permissible address range from
876
         * 0xe0000 through 0xfffff for a valid BIOS32 structure.
877
         *
878
         */
879
 
880
        for (check = (union bios32 *) 0xe0000;
881
             check <= (union bios32 *) 0xffff0;
882
             ++check) {
883
                if (check->fields.signature != BIOS32_SIGNATURE)
884
                        continue;
885
                length = check->fields.length * 16;
886
                if (!length)
887
                        continue;
888
                sum = 0;
889
                for (i = 0; i < length ; ++i)
890
                        sum += check->chars[i];
891
                if (sum != 0)
892
                        continue;
893
                if (check->fields.revision != 0) {
894
                        printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n",
895
                                check->fields.revision, check);
896
                        continue;
897
                }
898
                printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
899
                if (!bios32_entry) {
900
                        if (check->fields.entry >= 0x100000) {
901
                                printk("pcibios_init: entry in high memory, trying direct PCI access\n");
902
                                access_pci = check_direct_pci();
903
                        } else {
904
                                bios32_entry = check->fields.entry;
905
                                printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
906
                                bios32_indirect.address = bios32_entry;
907
                        }
908
                }
909
        }
910
        if (bios32_entry && check_pcibios())
911
                access_pci = &pci_bios_access;
912
#endif
913
        return memory_start;
914
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.