source: rtems/c/src/lib/libbsp/sparc/leon2/pci/pci.c @ 8bbf69e

4.115
Last change on this file since 8bbf69e was 8bbf69e, checked in by Joel Sherrill <joel.sherrill@…>, on 05/16/12 at 21:04:10

pci.h cleanup - Consolidate common defines to cpukit pci.h

+ libbsp/sparc/shared/include/pci.h was largely a copy of

an older version of the cpukit pci.h. Removed much of the
contents and included <rtems/pci.h>.

+ sparc/*/pci*.c - Move to <rtems/pci.h> required updating

to use uint32_t for dword accesses.

+ Rename PCI_MULTI_FUNCTION to PCI_HEADER_TYPE_MULTI_FUNCTION
+ Define PCI_HEADER_TYPE_MULTI_FUNCTION in cpukit pci.h and remove

PCI_MULTI_FUNCTION definitions in C files.

+ Move PCI_INVALID_VENDORDEVICEID definitions from various C files

to cpukit pci.h

  • Property mode set to 100644
File size: 19.2 KB
RevLine 
[931e9cc0]1/*
2 * pci.c :  this file contains basic PCI Io functions.
3 *
4 *  Copyright (C) 1999 valette@crf.canon.fr
5 *
6 *  This code is heavily inspired by the public specification of STREAM V2
7 *  that can be found at :
8 *
9 *      <http://www.chorus.com/Documentation/index.html> by following
10 *  the STREAM API Specification Document link.
11 *
12 *  The license and distribution terms for this file may be
[801a7ba6]13 *  found in the file LICENSE in this distribution or at
[931e9cc0]14 *  http://www.rtems.com/license/LICENSE.
15 *
16 *  Till Straumann, <strauman@slac.stanford.edu>, 1/2002
17 *   - separated bridge detection code out of this file
18 *
[44b06ca]19 *  Adapted to LEON2 AT697 PCI
[931e9cc0]20 *  Copyright (C) 2006 Gaisler Research
21 *
22 */
23
24#include <pci.h>
25#include <rtems/bspIo.h>
26#include <stdlib.h>
27
28/* Define PCI_INFO to get a listing of configured devices at boot time */
[44b06ca]29#define PCI_INFO 1
[931e9cc0]30
31/* #define DEBUG 1 */
32
33#ifdef DEBUG
34#define DBG(x...) printk(x)
35#else
[44b06ca]36#define DBG(x...)
[931e9cc0]37#endif
38
39/* allow for overriding these definitions */
40#ifndef PCI_CONFIG_ADDR
41#define PCI_CONFIG_ADDR                 0xcf8
42#endif
43#ifndef PCI_CONFIG_DATA
44#define PCI_CONFIG_DATA                 0xcfc
45#endif
46
47/* define a shortcut */
48#define pci     BSP_pci_configuration
49
50/*
51 * Bit encode for PCI_CONFIG_HEADER_TYPE register
52 */
[44b06ca]53unsigned char ucMaxPCIBus;
[931e9cc0]54
55typedef struct {
56    volatile unsigned int pciid1;        /* 0x80000100 - PCI Device identification register 1         */
57    volatile unsigned int pcisc;         /* 0x80000104 - PCI Status & Command                         */
58    volatile unsigned int pciid2;        /* 0x80000108 - PCI Device identification register 2         */
59    volatile unsigned int pcibhlc;       /* 0x8000010c - BIST, Header type, Cache line size register  */
60    volatile unsigned int mbar1;         /* 0x80000110 - Memory Base Address Register 1               */
61    volatile unsigned int mbar2;         /* 0x80000114 - Memory Base Address Register 2               */
62    volatile unsigned int iobar3;        /* 0x80000118 - IO Base Address Register 3                   */
[44b06ca]63    volatile unsigned int dummy1[4];     /* 0x8000011c - 0x80000128                                   */
[931e9cc0]64    volatile unsigned int pcisid;        /* 0x8000012c - Subsystem identification register            */
65    volatile unsigned int dummy2;        /* 0x80000130                                                */
66    volatile unsigned int pcicp;         /* 0x80000134 - PCI capabilities pointer register            */
67    volatile unsigned int dummy3;        /* 0x80000138                                                */
68    volatile unsigned int pcili;         /* 0x8000013c - PCI latency interrupt register               */
69    volatile unsigned int pcirt;         /* 0x80000140 - PCI retry, trdy config                       */
70    volatile unsigned int pcicw;         /* 0x80000144 - PCI configuration write register             */
71    volatile unsigned int pcisa;         /* 0x80000148 - PCI Initiator Start Address                  */
72    volatile unsigned int pciiw;         /* 0x8000014c - PCI Initiator Write Register                 */
73    volatile unsigned int pcidma;        /* 0x80000150 - PCI DMA configuration register               */
74    volatile unsigned int pciis;         /* 0x80000154 - PCI Initiator Status Register                */
75    volatile unsigned int pciic;         /* 0x80000158 - PCI Initiator Configuration                  */
[44b06ca]76    volatile unsigned int pcitpa;        /* 0x8000015c - PCI Target Page Address Register             */
[931e9cc0]77    volatile unsigned int pcitsc;        /* 0x80000160 - PCI Target Status-Command Register           */
78    volatile unsigned int pciite;        /* 0x80000164 - PCI Interrupt Enable Register                */
79    volatile unsigned int pciitp;        /* 0x80000168 - PCI Interrupt Pending Register               */
80    volatile unsigned int pciitf;        /* 0x8000016c - PCI Interrupt Force Register                 */
[44b06ca]81    volatile unsigned int pcid;          /* 0x80000170 - PCI Data Register                            */
[931e9cc0]82    volatile unsigned int pcibe;         /* 0x80000174 - PCI Burst End Register                       */
83    volatile unsigned int pcidmaa;       /* 0x80000178 - PCI DMA Address Register                     */
84} AT697_PCI_Map;
85
86AT697_PCI_Map *pcic = (AT697_PCI_Map *) 0x80000100;
87
88#define PCI_MEM_START 0xa0000000
89#define PCI_MEM_END   0xf0000000
90#define PCI_MEM_SIZE  (PCI_MEM_START - PCI_MEM_END)
91
92
93struct pci_res {
94    unsigned int size;
95    unsigned char bar;
96    unsigned char devfn;
97};
98
99/*  The configuration access functions uses the DMA functionality of the
100 *  AT697 pci controller to be able access all slots
101 */
[44b06ca]102
[38386473]103static int
104BSP_pci_read_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int *val) {
[931e9cc0]105
106    volatile unsigned int data;
107
108    if (offset & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
109
[44b06ca]110    pcic->pciitp = 0xff; /* clear interrupts */
[931e9cc0]111
112    pcic->pcisa = (  1<<(11+slot) ) | ((function & 7)<<8) |  (offset&0x3f);
113    pcic->pcidma = 0xa01;
114    pcic->pcidmaa = (unsigned int) &data;
115
116    while (pcic->pciitp == 0)
117        ;
[44b06ca]118
119    pcic->pciitp = 0xff; /* clear interrupts */
[931e9cc0]120
121    if (pcic->pcisc & 0x20000000)  { /* Master Abort */
122        pcic->pcisc |= 0x20000000;
123        *val = 0xffffffff;
124    }
125    else
126        *val = data;
127
[44b06ca]128    DBG("pci_read - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n", bus, slot, function, offset,  (1<<(11+slot) ) | ((function & 7)<<8) |  (offset&0x3f), *val);
[931e9cc0]129
130    return PCIBIOS_SUCCESSFUL;
131}
132
133
[44b06ca]134static int
[38386473]135BSP_pci_read_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short *val) {
[931e9cc0]136    unsigned int v;
137
138    if (offset & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
139
140    pci_read_config_dword(bus, slot, function, offset&~3, &v);
141    *val = 0xffff & (v >> (8*(offset & 3)));
142
143    return PCIBIOS_SUCCESSFUL;
144}
145
146
[44b06ca]147static int
[38386473]148BSP_pci_read_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char *val) {
[931e9cc0]149    unsigned int v;
150
151    pci_read_config_dword(bus, slot, function, offset&~3, &v);
152
153    *val = 0xff & (v >> (8*(offset & 3)));
154
155    return PCIBIOS_SUCCESSFUL;
156}
157
158
[38386473]159static int
160BSP_pci_write_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int val) {
[931e9cc0]161
162    if (offset & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
163
164    pcic->pciitp = 0xff; /* clear interrupts */
[44b06ca]165
[931e9cc0]166    pcic->pcisa = (  1<<(11+slot) ) | ((function & 7)<<8) |  (offset&0x3f);
167    pcic->pcidma = 0xb01;
168    pcic->pcidmaa = (unsigned int) &val;
169
170    while (pcic->pciitp == 0)
171        ;
172
173    if (pcic->pcisc & 0x20000000)  { /* Master Abort */
174        pcic->pcisc |= 0x20000000;
175    }
176
177    pcic->pciitp = 0xff; /* clear interrupts */
178
179/*    DBG("pci write - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n", bus, slot, function, offset, (1<<(11+slot) ) | ((function & 7)<<8) |  (offset&0x3f), val); */
180
181    return PCIBIOS_SUCCESSFUL;
182}
183
184
[44b06ca]185static int
[38386473]186BSP_pci_write_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short val) {
[931e9cc0]187    unsigned int v;
188
189    if (offset & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
190
191    pci_read_config_dword(bus, slot, function, offset&~3, &v);
192
193    v = (v & ~(0xffff << (8*(offset&3)))) | ((0xffff&val) << (8*(offset&3)));
194
195    return pci_write_config_dword(bus, slot, function, offset&~3, v);
196}
197
198
[44b06ca]199static int
[38386473]200BSP_pci_write_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char val) {
[931e9cc0]201    unsigned int v;
202
203    pci_read_config_dword(bus, slot, function, offset&~3, &v);
204
205    v = (v & ~(0xff << (8*(offset&3)))) | ((0xff&val) << (8*(offset&3)));
[44b06ca]206
[931e9cc0]207    return pci_write_config_dword(bus, slot, function, offset&~3, v);
208}
209
210
211
212const pci_config_access_functions pci_access_functions = {
[38386473]213    BSP_pci_read_config_byte,
214    BSP_pci_read_config_word,
215    BSP_pci_read_config_dword,
216    BSP_pci_write_config_byte,
217    BSP_pci_write_config_word,
218    BSP_pci_write_config_dword
[931e9cc0]219};
220
[df0243f]221rtems_pci_config_t BSP_pci_configuration = {
222    (volatile unsigned char*)PCI_CONFIG_ADDR,
223    (volatile unsigned char*)PCI_CONFIG_DATA,
224    &pci_access_functions
225};
[931e9cc0]226
227
228void init_at697_pci(void) {
229
230    /* Reset */
231    pcic->pciic = 0xffffffff;
232
233    /* Map system RAM at pci address 0x40000000 and system SDRAM to pci address 0x60000000  */
234    pcic->mbar1  = 0x40000000;
235    pcic->mbar2  = 0x60000000;
236    pcic->pcitpa = 0x40006000;
237
238    /* Enable PCI master and target memory command response  */
239    pcic->pcisc |= 0x40 | 0x6;
240
241    /* Set latency timer to 64 */
242    pcic->pcibhlc = 0x00004000;
243
244    /* Set Inititator configuration so that AHB slave accesses generate memory read/write commands */
245    pcic->pciic = 0x41;
246
247    pcic->pciite = 0xff;
248
249}
250
251/* May not pass a 1k boundary */
252int dma_from_pci_1k(unsigned int addr, unsigned int paddr, unsigned char len) {
253
254    int retval = 0;
255
256    if (addr & 3) {
257        return -1;
258    }
259
[44b06ca]260    pcic->pciitp = 0xff; /* clear interrupts */
[931e9cc0]261
262    pcic->pcisa = paddr;
263    pcic->pcidma = 0xc00 | len;
264    pcic->pcidmaa = addr;
265
266    while (pcic->pciitp == 0)
267        ;
268
[44b06ca]269    if (pcic->pciitp & 0x7F) {
[931e9cc0]270        retval = -1;
271    }
272
[44b06ca]273    pcic->pciitp = 0xff; /* clear interrupts */
[931e9cc0]274
275    if (pcic->pcisc & 0x20000000)  { /* Master Abort */
276        pcic->pcisc |= 0x20000000;
277        retval = -1;
278    }
[44b06ca]279
[931e9cc0]280    return retval;
281}
282
283/* May not pass a 1k boundary */
284int dma_to_pci_1k(unsigned int addr, unsigned int paddr, unsigned char len) {
285
286    int retval = 0;
287
288    if (addr & 3) return -1;
289
[44b06ca]290    pcic->pciitp = 0xff; /* clear interrupts */
[931e9cc0]291
292    pcic->pcisa = paddr;
293    pcic->pcidma = 0x700 | len;
294    pcic->pcidmaa = addr;
295
296    while (pcic->pciitp == 0)
297        ;
[44b06ca]298
[931e9cc0]299    if (pcic->pciitp & 0x7F) retval = -1;
300
[44b06ca]301    pcic->pciitp = 0xff; /* clear interrupts */
[931e9cc0]302
303    if (pcic->pcisc & 0x20000000)  { /* Master Abort */
304        pcic->pcisc |= 0x20000000;
305        retval =  -1;
306    }
307
308    return retval;
309}
310
311/* Transfer len number of words from addr to paddr */
312int dma_to_pci(unsigned int addr, unsigned int paddr, unsigned int len) {
[44b06ca]313
[931e9cc0]314    int tmp_len;
315
316    /* Align to 1k boundary */
317    tmp_len = ((addr + 1024)  & 0xfffffc00) - addr;
318
319    tmp_len = (tmp_len/4 < len) ? tmp_len : (len*4);
320
321    if (dma_to_pci_1k(addr, paddr, tmp_len/4) < 0)
322        return -1;
323
324    addr += tmp_len;
325    paddr += tmp_len;
326    len -= tmp_len/4;
[44b06ca]327
[931e9cc0]328    /* Transfer all 1k blocks */
329    while (len >= 128) {
330
[44b06ca]331        if (dma_to_pci_1k(addr, paddr, 128) < 0)
[931e9cc0]332            return -1;
333
334        addr += 512;
335        paddr += 512;
336        len -= 128;
337
338    }
339
340    /* Transfer last words */
341    if (len) return dma_to_pci_1k(addr, paddr, len);
342
343    return 0;
344}
345
346/* Transfer len number of words from paddr to addr */
347int dma_from_pci(unsigned int addr, unsigned int paddr, unsigned int len) {
348
349    int tmp_len;
350
351    /* Align to 1k boundary */
352    tmp_len = ((addr + 1024)  & 0xfffffc00) - addr;
353
354    tmp_len = (tmp_len/4 < len) ? tmp_len : (len*4);
355
356    if (dma_from_pci_1k(addr, paddr, tmp_len/4) < 0)
357        return -1;
358
359    addr += tmp_len;
360    paddr += tmp_len;
361    len -= tmp_len/4;
[44b06ca]362
[931e9cc0]363    /* Transfer all 1k blocks */
364    while (len >= 128) {
365
366        if (dma_from_pci_1k(addr, paddr, 128) < 0)
367            return -1;
368        addr += 512;
369        paddr += 512;
370        len -= 128;
371
372    }
373
374    /* Transfer last words */
375    if (len) return dma_from_pci_1k(addr, paddr, len);
376
377    return 0;
378}
379
380void pci_mem_enable(unsigned char bus, unsigned char slot, unsigned char function) {
381    unsigned int data;
382
383    pci_read_config_dword(0, slot, function, PCI_COMMAND, &data);
[44b06ca]384    pci_write_config_dword(0, slot, function, PCI_COMMAND, data | PCI_COMMAND_MEMORY);
[931e9cc0]385
386}
387
388void pci_master_enable(unsigned char bus, unsigned char slot, unsigned char function) {
389    unsigned int data;
390
391    pci_read_config_dword(0, slot, function, PCI_COMMAND, &data);
[44b06ca]392    pci_write_config_dword(0, slot, function, PCI_COMMAND, data | PCI_COMMAND_MASTER);
[931e9cc0]393
394}
395
396static inline void swap_res(struct pci_res **p1, struct pci_res **p2) {
397
398    struct pci_res *tmp = *p1;
399    *p1 = *p2;
400    *p2 = tmp;
401
402}
403
404/* pci_allocate_resources
405 *
406 * This function scans the bus and assigns PCI addresses to all devices. It handles both
407 * single function and multi function devices. All allocated devices are enabled and
408 * latency timers are set to 40.
409 *
410 * NOTE that it only allocates PCI memory space devices. IO spaces are not enabled.
[44b06ca]411 * Also, it does not handle pci-pci bridges. They are left disabled.
[931e9cc0]412 *
413 *
414*/
415void pci_allocate_resources(void) {
416
417    unsigned int slot, numfuncs, func, id, pos, size, tmp, i, swapped, addr, dev, fn;
418    unsigned char header;
419    struct pci_res **res;
420
421    res = (struct pci_res **) malloc(sizeof(struct pci_res *)*32*8*6);
422
423    for (i = 0; i < 32*8*6; i++) {
[44b06ca]424        res[i] = (struct pci_res *) malloc(sizeof(struct pci_res));
[931e9cc0]425        res[i]->size = 0;
426        res[i]->devfn = i;
427    }
428
429    for(slot = 0; slot< PCI_MAX_DEVICES; slot++) {
430
431        pci_read_config_dword(0, slot, 0, PCI_VENDOR_ID, &id);
432
433        if(id == PCI_INVALID_VENDORDEVICEID || id == 0) {
434            /*
435             * This slot is empty
436             */
437            continue;
438        }
439
440        pci_read_config_byte(0, slot, 0, PCI_HEADER_TYPE, &header);
[44b06ca]441
[8bbf69e]442        if(header & PCI_HEADER_TYPE_MULTI_FUNCTION)     {
[931e9cc0]443            numfuncs = PCI_MAX_FUNCTIONS;
444        }
445        else {
446            numfuncs = 1;
447        }
448
449        for(func = 0; func < numfuncs; func++) {
450
451            pci_read_config_dword(0, slot, func, PCI_VENDOR_ID, &id);
452            if(id == PCI_INVALID_VENDORDEVICEID || id == 0) {
453                continue;
454            }
455
456            pci_read_config_dword(0, slot, func, PCI_CLASS_REVISION, &tmp);
457            tmp >>= 16;
458            if (tmp == PCI_CLASS_BRIDGE_PCI) {
459                continue;
460            }
[44b06ca]461
[931e9cc0]462            for (pos = 0; pos < 6; pos++) {
463                pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + (pos<<2), 0xffffffff);
464                pci_read_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + (pos<<2), &size);
465
466                if (size == 0 || size == 0xffffffff || (size & 0xff) != 0) {
467                    pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + (pos<<2), 0);
468                    continue;
469                }
470
471                else {
472                    res[slot*8*6+func*6+pos]->size  = ~size+1;
473                    res[slot*8*6+func*6+pos]->devfn = slot*8 + func;
474                    res[slot*8*6+func*6+pos]->bar   = pos;
475
476                    DBG("Slot: %d, function: %d, bar%d size: %x\n", slot, func, pos, ~size+1);
477                }
478            }
479        }
480    }
481
482
[44b06ca]483    /* Sort the resources in descending order */
[931e9cc0]484
485    swapped = 1;
486    while (swapped == 1) {
487        swapped = 0;
488        for (i = 0; i < 32*8*6-1; i++) {
489            if (res[i]->size < res[i+1]->size) {
490                swap_res(&res[i], &res[i+1]);
491                swapped = 1;
492            }
493        }
494        i++;
495    }
496
497    /* Assign the BARs */
498
499    addr = PCI_MEM_START;
500    for (i = 0; i < 32*8*6; i++) {
501
502        if (res[i]->size == 0) {
503            goto done;
504        }
505        if ( (addr + res[i]->size) > PCI_MEM_END) {
506            printk("Out of PCI memory space, all devices not configured.\n");
507            goto done;
508        }
[44b06ca]509
[931e9cc0]510        dev = res[i]->devfn >> 3;
511        fn  = res[i]->devfn & 7;
[44b06ca]512
[931e9cc0]513        DBG("Assigning PCI addr %x to device %d, function %d, bar %d\n", addr, dev, fn, res[i]->bar);
514        pci_write_config_dword(0, dev, fn, PCI_BASE_ADDRESS_0+res[i]->bar*4, addr);
515        addr += res[i]->size;
516
517        /* Set latency timer to 64 */
[44b06ca]518        pci_read_config_dword(0, dev, fn, 0xC, &tmp);
[931e9cc0]519        pci_write_config_dword(0, dev, fn, 0xC, tmp|0x4000);
520
[44b06ca]521        pci_mem_enable(0, dev, fn);
522
523    }
[931e9cc0]524
525
526
527done:
528
529#ifdef PCI_INFO
530    printk("\nPCI devices found and configured:\n");
531    for (slot = 0; slot < PCI_MAX_DEVICES; slot++) {
[44b06ca]532
533        pci_read_config_byte(0, slot, 0, PCI_HEADER_TYPE, &header);
534
[8bbf69e]535        if(header & PCI_HEADER_TYPE_MULTI_FUNCTION)     {
[931e9cc0]536            numfuncs = PCI_MAX_FUNCTIONS;
537        }
538        else {
539            numfuncs = 1;
540        }
541
542        for (func = 0; func < numfuncs; func++) {
[44b06ca]543
[931e9cc0]544            pci_read_config_dword(0, slot, func, PCI_COMMAND, &tmp);
545
[44b06ca]546            if (tmp & PCI_COMMAND_MEMORY) {
547
[931e9cc0]548                pci_read_config_dword(0, slot, func, PCI_VENDOR_ID,  &id);
549
550                if (id == PCI_INVALID_VENDORDEVICEID || id == 0) continue;
[44b06ca]551
[931e9cc0]552                printk("\nSlot %d function: %d\nVendor id: 0x%x, device id: 0x%x\n", slot, func, id & 0xffff, id>>16);
553
554                for (pos = 0; pos < 6; pos++) {
555                    pci_read_config_dword(0, slot, func, PCI_BASE_ADDRESS_0 + pos*4, &tmp);
556
557                    if (tmp != 0 && tmp != 0xffffffff && (tmp & 0xff) == 0) {
558
559                        printk("\tBAR %d: %x\n", pos, tmp);
560                    }
[44b06ca]561
[931e9cc0]562                }
563                printk("\n");
564
[44b06ca]565            }
[931e9cc0]566
567        }
568     }
569    printk("\n");
570#endif
[44b06ca]571
[931e9cc0]572    for (i = 0; i < 1536; i++) {
573        free(res[i]);
574    }
575    free(res);
576}
577
578
579
580
581
582
583
584/*
585 * This routine determines the maximum bus number in the system
586 */
[49c8f45]587int init_pci(void)
[931e9cc0]588{
589    unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs;
590    unsigned char ucHeader;
591    unsigned char ucMaxSubordinate;
[44b06ca]592    unsigned int  ulClass, ulDeviceID;
[931e9cc0]593
594    init_at697_pci();
595    pci_allocate_resources();
596
597/*
598 * Scan PCI bus 0 looking for PCI-PCI bridges
599 */
600    for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
601        (void)pci_read_config_dword(0,
602                                    ucSlotNumber,
603                                    0,
604                                    PCI_VENDOR_ID,
605                                    &ulDeviceID);
606        if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
607/*
608 * This slot is empty
609 */
610            continue;
611        }
612        (void)pci_read_config_byte(0,
613                                   ucSlotNumber,
614                                   0,
615                                   PCI_HEADER_TYPE,
616                                   &ucHeader);
[8bbf69e]617        if(ucHeader&PCI_HEADER_TYPE_MULTI_FUNCTION)     {
[931e9cc0]618            ucNumFuncs=PCI_MAX_FUNCTIONS;
619        }
620        else {
621            ucNumFuncs=1;
622        }
623        for(ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++) {
624            (void)pci_read_config_dword(0,
625                                        ucSlotNumber,
626                                        ucFnNumber,
627                                        PCI_VENDOR_ID,
628                                        &ulDeviceID);
629            if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
630/*
631 * This slot/function is empty
632 */
633                continue;
634            }
635
636/*
637 * This slot/function has a device fitted.
638 */
639            (void)pci_read_config_dword(0,
640                                        ucSlotNumber,
641                                        ucFnNumber,
642                                        PCI_CLASS_REVISION,
643                                        &ulClass);
644            ulClass >>= 16;
645            if (ulClass == PCI_CLASS_BRIDGE_PCI) {
646/*
647 * We have found a PCI-PCI bridge
648 */
649                (void)pci_read_config_byte(0,
650                                           ucSlotNumber,
651                                           ucFnNumber,
652                                           PCI_SUBORDINATE_BUS,
653                                           &ucMaxSubordinate);
654                if(ucMaxSubordinate>ucMaxPCIBus) {
655                    ucMaxPCIBus=ucMaxSubordinate;
656                }
657            }
658        }
659    }
660    return 0;
661}
662
663/*
664 * Return the number of PCI busses in the system
665 */
[49c8f45]666unsigned char BusCountPCI(void)
[931e9cc0]667{
668    return(ucMaxPCIBus+1);
669}
Note: See TracBrowser for help on using the repository browser.