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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [x86_64/] [kernel/] [aperture.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Firmware replacement code.
3
 *
4
 * Work around broken BIOSes that don't set an aperture or only set the
5
 * aperture in the AGP bridge.
6
 * If all fails map the aperture over some low memory.  This is cheaper than
7
 * doing bounce buffering. The memory is lost. This is done at early boot
8
 * because only the bootmem allocator can allocate 32+MB.
9
 *
10
 * Copyright 2002 Andi Kleen, SuSE Labs.
11
 * $Id: aperture.c,v 1.1.1.1 2004-04-15 01:36:44 phoenix Exp $
12
 */
13
#include <linux/config.h>
14
#include <linux/kernel.h>
15
#include <linux/types.h>
16
#include <linux/init.h>
17
#include <linux/bootmem.h>
18
#include <linux/mmzone.h>
19
#include <linux/pci_ids.h>
20
#include <linux/pci.h>
21
#include <linux/bitops.h>
22
#include <asm/e820.h>
23
#include <asm/io.h>
24
#include <asm/proto.h>
25
#include <asm/pci-direct.h>
26
 
27
int fallback_aper_order __initdata = 1; /* 64MB */
28
int fallback_aper_force __initdata = 0;
29
 
30
int iommu_aperture;
31
 
32
extern int no_iommu, force_mmu;
33
 
34
/* This code runs before the PCI subsystem is initialized, so just
35
   access the northbridge directly. */
36
 
37
#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
38
 
39
static u32 __init allocate_aperture(void)
40
{
41
#ifdef CONFIG_DISCONTIGMEM
42
        pg_data_t *nd0 = NODE_DATA(0);
43
#else
44
        pg_data_t *nd0 = &contig_page_data;
45
#endif  
46
        u32 aper_size;
47
        void *p;
48
 
49
        if (fallback_aper_order > 7)
50
                fallback_aper_order = 7;
51
        aper_size = (32 * 1024 * 1024) << fallback_aper_order;
52
 
53
        /*
54
         * Aperture has to be naturally aligned. This means an 2GB aperture won't
55
         * have much chances to find a place in the lower 4GB of memory. Unfortunately
56
         * we cannot move it up because that would make the IOMMU useless.
57
         */
58
        p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0);
59
        if (!p || __pa(p)+aper_size > 0xffffffff) {
60
                printk("Cannot allocate aperture memory hole (%p,%uK)\n",
61
                       p, aper_size>>10);
62
                if (p)
63
                        free_bootmem_generic((unsigned long)p, aper_size);
64
                return 0;
65
        }
66
        printk("Mapping aperture over %d KB of RAM @ %lx\n",
67
               aper_size >> 10, __pa(p));
68
        return (u32)__pa(p);
69
}
70
 
71
static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size)
72
{
73
        if (!aper_base)
74
                return 0;
75
        if (aper_size < 64*1024*1024) {
76
                printk("Aperture from %s too small (%d MB)\n", name, aper_size>>20);
77
                return 0;
78
        }
79
        if (aper_base + aper_size >= 0xffffffff) {
80
                printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
81
                return 0;
82
        }
83
        if (e820_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
84
                printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
85
                return 0;
86
        }
87
        return 1;
88
}
89
 
90
/* Find a PCI capability */
91
static __u32 __init find_cap(int num, int slot, int func, int cap)
92
{
93
        if (!(read_pci_config_16(num,slot,func,PCI_STATUS) & PCI_STATUS_CAP_LIST))
94
                return 0;
95
        u8 pos = read_pci_config_byte(num,slot,func,PCI_CAPABILITY_LIST);
96
        int bytes;
97
        for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
98
                pos &= ~3;
99
                u8 id = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_ID);
100
                if (id == 0xff)
101
                        break;
102
                if (id == cap)
103
                        return pos;
104
                pos = read_pci_config_byte(num,slot,func,pos+PCI_CAP_LIST_NEXT);
105
        }
106
        return 0;
107
}
108
 
109
/* Read a standard AGPv3 bridge header */
110
static __u32 __init read_agp(int num, int slot, int func, int cap, u32 *order)
111
{
112
        printk("AGP bridge at %02x:%02x:%02x\n", num, slot, func);
113
        u32 apsizereg = read_pci_config_16(num,slot,func, cap + 0x14);
114
 
115
        if (apsizereg == 0xffffffff) {
116
                printk("APSIZE in AGP bridge unreadable\n");
117
                return 0;
118
        }
119
 
120
        u32 apsize = apsizereg & 0xfff;
121
        /* Some BIOS use weird encodings not in the AGPv3 table. */
122
        if (apsize & 0xff)
123
                apsize |= 0xf00;
124
        int nbits = hweight16(apsize);
125
        *order = 7 - nbits;
126
        if ((int)*order < 0) /* < 32MB */
127
                *order = 0;
128
 
129
        u32 aper_low = read_pci_config(num,slot,func, 0x10);
130
        u32 aper_hi = read_pci_config(num,slot,func,0x14);
131
        u64 aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
132
 
133
        printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n",
134
               aper, 32 << *order, apsizereg);
135
 
136
        if (!aperture_valid("AGP bridge", aper, (32*1024*1024) << *order))
137
            return 0;
138
        return (u32)aper;
139
}
140
 
141
/* Look for an AGP bridge. Windows only expects the aperture in the
142
   AGP bridge and some BIOS forget to initialize the Northbridge too.
143
   Work around this here.
144
 
145
   Do an PCI bus scan by hand because we're running before the PCI
146
   subsystem.
147
 
148
   All K8 AGP bridges are AGPv3 compliant, so we can do this scan
149
   generically. It's probably overkill to always scan all slots because
150
   the AGP bridges should be always an own bus on the HT hierarchy,
151
   but do it here for future safety. */
152
static __u32 __init search_agp_bridge(u32 *order, int *valid_agp)
153
{
154
        int num, slot, func;
155
 
156
        /* Poor man's PCI discovery */
157
        for (num = 0; num < 32; num++) {
158
                for (slot = 0; slot < 32; slot++) {
159
                        for (func = 0; func < 8; func++) {
160
                                u32 class, cap;
161
                                class = read_pci_config(num,slot,func,
162
                                                        PCI_CLASS_REVISION);
163
                                if (class == 0xffffffff)
164
                                        break;
165
 
166
                                switch (class >> 16) {
167
                                case PCI_CLASS_BRIDGE_HOST:
168
                                case PCI_CLASS_BRIDGE_OTHER: /* needed? */
169
                                        /* AGP bridge? */
170
                                        cap = find_cap(num,slot,func,PCI_CAP_ID_AGP);
171
                                        if (!cap)
172
                                                break;
173
                                        *valid_agp = 1;
174
                                        return read_agp(num,slot,func,cap,order);
175
                                }
176
 
177
                                /* No multi-function device? */
178
                                u8 type = read_pci_config_byte(num,slot,func,
179
                                                               PCI_HEADER_TYPE);
180
                                if (!(type & 0x80))
181
                                        break;
182
                        }
183
                }
184
        }
185
        printk("No AGP bridge found\n");
186
        return 0;
187
}
188
 
189
void __init iommu_hole_init(void)
190
{
191
        int fix, num;
192
        u32 aper_size, aper_alloc = 0, aper_order;
193
        u64 aper_base;
194
        int valid_agp = 0;
195
 
196
        printk("Checking aperture...\n");
197
 
198
        fix = 0;
199
        for (num = 24; num < 32; num++) {
200
                if (read_pci_config(0, num, 3, 0x00) != NB_ID_3)
201
                        continue;
202
 
203
                iommu_aperture = 1;
204
 
205
                aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7;
206
                aper_size = (32 * 1024 * 1024) << aper_order;
207
                aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff;
208
                aper_base <<= 25;
209
 
210
                printk("CPU %d: aperture @ %Lx size %u MB\n", num-24,
211
                       aper_base, aper_size>>20);
212
 
213
                char name[30];
214
                sprintf(name, "northbridge cpu %d", num-24);
215
 
216
                if (!aperture_valid(name, aper_base, aper_size)) {
217
                        fix = 1;
218
                        break;
219
                }
220
        }
221
 
222
        if (!fix && !fallback_aper_force)
223
                return;
224
 
225
        if (!fallback_aper_force)
226
                aper_alloc = search_agp_bridge(&aper_order, &valid_agp);
227
 
228
        if (aper_alloc) {
229
                /* Got the aperture from the AGP bridge */
230
        } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
231
                   force_mmu ||
232
                   valid_agp ||
233
                   fallback_aper_force) {
234
                /* When there is a AGP bridge in the system assume the
235
                   user wants to use the AGP driver too and needs an
236
                   aperture.  However this case (AGP but no good
237
                   aperture) should only happen with a more broken than
238
                   usual BIOS, because it would even break Windows. */
239
 
240
        printk("Your BIOS doesn't leave a aperture memory hole\n");
241
        printk("Please enable the IOMMU option in the BIOS setup\n");
242
                printk("This costs you %d MB of RAM\n", 32 << fallback_aper_order);
243
 
244
                aper_order = fallback_aper_order;
245
        aper_alloc = allocate_aperture();
246
                if (!aper_alloc) {
247
                        /* Could disable AGP and IOMMU here, but it's probably
248
                           not worth it. But the later users cannot deal with
249
                           bad apertures and turning on the aperture over memory
250
                           causes very strange problems, so it's better to
251
                           panic early. */
252
                        panic("Not enough memory for aperture");
253
                }
254
        } else {
255
                return;
256
        }
257
 
258
        /* Fix up the north bridges */
259
        for (num = 24; num < 32; num++) {
260
                if (read_pci_config(0, num, 3, 0x00) != NB_ID_3)
261
                        continue;
262
 
263
                /* Don't enable translation yet. That is done later.
264
                   Assume this BIOS didn't initialise the GART so
265
                   just overwrite all previous bits */
266
                write_pci_config(0, num, 3, 0x90, aper_order<<1);
267
                write_pci_config(0, num, 3, 0x94, aper_alloc>>25);
268
        }
269
}

powered by: WebSVN 2.1.0

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