Subversion Repositories Kolibri OS

Rev

Rev 6131 | Details | Compare with Previous | Last modification | View Log | RSS feed

<
Rev Author Line No. Line
6131 serge 1
#include 
2325 Serge 2
 
3
#include 
4
#include 
5
#include 
5354 serge 6
#include 
6131 serge 7
#include 
8
 
5354 serge 9
#include 
2325 Serge 10
 
5354 serge 11
extern int pci_scan_filter(u32 id, u32 busnr, u32 devfn);
2325 Serge 12
 
13
static LIST_HEAD(devices);
14
 
15
/* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
16
#define IORESOURCE_PCI_FIXED            (1<<4)  /* Do not move resource */
17
 
18
#define LEGACY_IO_RESOURCE      (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
19
 
7144 serge 20
#define IORESOURCE_ROM_COPY             (1<<2)  /* ROM is alloc'd copy, resource field overlaid */
21
#define IORESOURCE_ROM_BIOS_COPY        (1<<3)  /* ROM is BIOS copy, resource field overlaid */
22
 
2325 Serge 23
/*
24
 * Translate the low bits of the PCI base
25
 * to the resource type
26
 */
27
static inline unsigned int pci_calc_resource_flags(unsigned int flags)
28
{
29
    if (flags & PCI_BASE_ADDRESS_SPACE_IO)
30
        return IORESOURCE_IO;
31
 
32
    if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
33
        return IORESOURCE_MEM | IORESOURCE_PREFETCH;
34
 
35
    return IORESOURCE_MEM;
36
}
37
 
38
 
5354 serge 39
static u32 pci_size(u32 base, u32 maxbase, u32 mask)
2325 Serge 40
{
5354 serge 41
    u32 size = mask & maxbase;      /* Find the significant bits */
2325 Serge 42
 
43
    if (!size)
44
        return 0;
45
 
46
    /* Get the lowest of them to find the decode size, and
47
       from that the extent.  */
48
    size = (size & ~(size-1)) - 1;
49
 
50
    /* base == maxbase can be valid only if the BAR has
51
       already been programmed with all 1s.  */
52
    if (base == maxbase && ((base | size) & mask) != mask)
53
        return 0;
54
 
55
    return size;
56
}
57
 
5354 serge 58
static u64 pci_size64(u64 base, u64 maxbase, u64 mask)
2325 Serge 59
{
5354 serge 60
    u64 size = mask & maxbase;      /* Find the significant bits */
2325 Serge 61
 
62
    if (!size)
63
        return 0;
64
 
65
    /* Get the lowest of them to find the decode size, and
66
       from that the extent.  */
67
    size = (size & ~(size-1)) - 1;
68
 
69
    /* base == maxbase can be valid only if the BAR has
70
       already been programmed with all 1s.  */
71
    if (base == maxbase && ((base | size) & mask) != mask)
72
        return 0;
73
 
74
    return size;
75
}
76
 
5354 serge 77
static inline int is_64bit_memory(u32 mask)
2325 Serge 78
{
79
    if ((mask & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
80
        (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64))
81
        return 1;
82
    return 0;
83
}
84
 
85
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
86
{
5354 serge 87
    u32  pos, reg, next;
88
    u32  l, sz;
2325 Serge 89
    struct resource *res;
90
 
91
    for(pos=0; pos < howmany; pos = next)
92
    {
5354 serge 93
        u64  l64;
94
        u64  sz64;
95
        u32  raw_sz;
2325 Serge 96
 
97
        next = pos + 1;
98
 
99
        res  = &dev->resource[pos];
100
 
101
        reg = PCI_BASE_ADDRESS_0 + (pos << 2);
102
        l = PciRead32(dev->busnr, dev->devfn, reg);
103
        PciWrite32(dev->busnr, dev->devfn, reg, ~0);
104
        sz = PciRead32(dev->busnr, dev->devfn, reg);
105
        PciWrite32(dev->busnr, dev->devfn, reg, l);
106
 
107
        if (!sz || sz == 0xffffffff)
108
            continue;
109
 
110
        if (l == 0xffffffff)
111
            l = 0;
112
 
113
        raw_sz = sz;
114
        if ((l & PCI_BASE_ADDRESS_SPACE) ==
115
                        PCI_BASE_ADDRESS_SPACE_MEMORY)
116
        {
5354 serge 117
            sz = pci_size(l, sz, (u32)PCI_BASE_ADDRESS_MEM_MASK);
2325 Serge 118
            /*
119
             * For 64bit prefetchable memory sz could be 0, if the
120
             * real size is bigger than 4G, so we need to check
121
             * szhi for that.
122
             */
123
            if (!is_64bit_memory(l) && !sz)
124
                    continue;
125
            res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
126
            res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK;
127
        }
128
        else {
129
            sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
130
            if (!sz)
131
                continue;
132
            res->start = l & PCI_BASE_ADDRESS_IO_MASK;
133
            res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
134
        }
135
        res->end = res->start + (unsigned long) sz;
136
        res->flags |= pci_calc_resource_flags(l);
137
        if (is_64bit_memory(l))
138
        {
5354 serge 139
            u32 szhi, lhi;
2325 Serge 140
 
141
            lhi = PciRead32(dev->busnr, dev->devfn, reg+4);
142
            PciWrite32(dev->busnr, dev->devfn, reg+4, ~0);
143
            szhi = PciRead32(dev->busnr, dev->devfn, reg+4);
144
            PciWrite32(dev->busnr, dev->devfn, reg+4, lhi);
5354 serge 145
            sz64 = ((u64)szhi << 32) | raw_sz;
146
            l64 = ((u64)lhi << 32) | l;
2325 Serge 147
            sz64 = pci_size64(l64, sz64, PCI_BASE_ADDRESS_MEM_MASK);
148
            next++;
149
 
150
#if BITS_PER_LONG == 64
151
            if (!sz64) {
152
                res->start = 0;
153
                res->end = 0;
154
                res->flags = 0;
155
                continue;
156
            }
157
            res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK;
158
            res->end = res->start + sz64;
159
#else
160
            if (sz64 > 0x100000000ULL) {
161
                printk(KERN_ERR "PCI: Unable to handle 64-bit "
162
                                "BAR for device %s\n", pci_name(dev));
163
                res->start = 0;
164
                res->flags = 0;
165
            }
166
            else if (lhi)
167
            {
168
                /* 64-bit wide address, treat as disabled */
169
                PciWrite32(dev->busnr, dev->devfn, reg,
5354 serge 170
                        l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK);
2325 Serge 171
                PciWrite32(dev->busnr, dev->devfn, reg+4, 0);
172
                res->start = 0;
173
                res->end = sz;
174
            }
175
#endif
176
        }
177
    }
178
 
179
    if ( rom )
180
    {
181
        dev->rom_base_reg = rom;
182
        res = &dev->resource[PCI_ROM_RESOURCE];
183
 
184
        l = PciRead32(dev->busnr, dev->devfn, rom);
185
        PciWrite32(dev->busnr, dev->devfn, rom, ~PCI_ROM_ADDRESS_ENABLE);
186
        sz = PciRead32(dev->busnr, dev->devfn, rom);
187
        PciWrite32(dev->busnr, dev->devfn, rom, l);
188
 
189
        if (l == 0xffffffff)
190
            l = 0;
191
 
192
        if (sz && sz != 0xffffffff)
193
        {
5354 serge 194
            sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK);
2325 Serge 195
 
196
            if (sz)
197
            {
198
                res->flags = (l & IORESOURCE_ROM_ENABLE) |
199
                                  IORESOURCE_MEM | IORESOURCE_PREFETCH |
200
                                  IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
201
                res->start = l & PCI_ROM_ADDRESS_MASK;
202
                res->end = res->start + (unsigned long) sz;
203
            }
204
        }
205
    }
206
}
207
 
208
static void pci_read_irq(struct pci_dev *dev)
209
{
5354 serge 210
    u8 irq;
2325 Serge 211
 
212
    irq = PciRead8(dev->busnr, dev->devfn, PCI_INTERRUPT_PIN);
213
    dev->pin = irq;
214
    if (irq)
215
        irq = PciRead8(dev->busnr, dev->devfn, PCI_INTERRUPT_LINE);
216
    dev->irq = irq;
217
};
218
 
219
 
220
int pci_setup_device(struct pci_dev *dev)
221
{
5354 serge 222
    u32  class;
2325 Serge 223
 
224
    class = PciRead32(dev->busnr, dev->devfn, PCI_CLASS_REVISION);
225
    dev->revision = class & 0xff;
226
    class >>= 8;                                /* upper 3 bytes */
227
    dev->class = class;
228
 
229
    /* "Unknown power state" */
230
//    dev->current_state = PCI_UNKNOWN;
231
 
232
    /* Early fixups, before probing the BARs */
233
 //   pci_fixup_device(pci_fixup_early, dev);
234
    class = dev->class >> 8;
235
 
236
    switch (dev->hdr_type)
237
    {
238
        case PCI_HEADER_TYPE_NORMAL:                /* standard header */
239
            if (class == PCI_CLASS_BRIDGE_PCI)
240
                goto bad;