blob: a1961bb800da3a79ca9f8e4a1c151596ba58bcd9 [file] [log] [blame]
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001/******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
3 * Copyright (c) 2008, 2009 Pattrick Hueper <phueper@hueper.net>
Martin Rotha9e1a222016-01-14 14:15:24 -07004 *
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00005 * All rights reserved.
Martin Rotha9e1a222016-01-14 14:15:24 -07006 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000030 *
31 * Contributors:
32 * IBM Corporation - initial implementation
33 *****************************************************************************/
34
35
36#include "device.h"
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000037#include "compat/rtas.h"
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000038#include <string.h>
39#include "debug.h"
40
41#include <device/device.h>
42#include <device/pci.h>
43#include <device/pci_ops.h>
44#include <device/resource.h>
45
46/* the device we are working with... */
47biosemu_device_t bios_device;
Patrick Georgi91443042011-01-13 11:38:46 +000048//max. 6 BARs and 1 Exp.ROM plus CfgSpace and 3 legacy ranges, plus 2 "special" memory ranges
49translate_address_t translate_address_array[13];
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000050u8 taa_last_entry;
51
52typedef struct {
53 u8 info;
54 u8 bus;
55 u8 devfn;
56 u8 cfg_space_offset;
57 u64 address;
58 u64 size;
59} __attribute__ ((__packed__)) assigned_address_t;
60
Stefan Reinauer1d888a92011-04-21 20:24:43 +000061#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000062/* coreboot version */
63
Uwe Hermann01ce6012010-03-05 10:03:50 +000064static void
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000065biosemu_dev_get_addr_info(void)
66{
67 int taa_index = 0;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000068 struct resource *r;
Myles Watsonbd61a812010-08-30 21:52:38 +000069 u8 bus = bios_device.dev->bus->secondary;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000070 u16 devfn = bios_device.dev->path.pci.devfn;
71
72 bios_device.bus = bus;
73 bios_device.devfn = devfn;
74
75 DEBUG_PRINTF("bus: %x, devfn: %x\n", bus, devfn);
Myles Watsonc25cc112010-05-21 14:33:48 +000076 for (r = bios_device.dev->resource_list; r; r = r->next) {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000077 translate_address_array[taa_index].info = r->flags;
78 translate_address_array[taa_index].bus = bus;
79 translate_address_array[taa_index].devfn = devfn;
80 translate_address_array[taa_index].cfg_space_offset =
81 r->index;
82 translate_address_array[taa_index].address = r->base;
83 translate_address_array[taa_index].size = r->size;
Martin Roth63373ed2013-07-08 16:24:19 -060084 /* don't translate addresses... all addresses are 1:1 */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000085 translate_address_array[taa_index].address_offset = 0;
86 taa_index++;
87 }
88 /* Expansion ROM */
89 translate_address_array[taa_index].info = IORESOURCE_MEM | IORESOURCE_READONLY;
90 translate_address_array[taa_index].bus = bus;
91 translate_address_array[taa_index].devfn = devfn;
92 translate_address_array[taa_index].cfg_space_offset = 0x30;
Stefan Reinauer775a7662010-01-19 21:14:24 +000093 translate_address_array[taa_index].address = bios_device.img_addr;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000094 translate_address_array[taa_index].size = 0; /* TODO: do we need the size? */
Martin Roth63373ed2013-07-08 16:24:19 -060095 /* don't translate addresses... all addresses are 1:1 */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000096 translate_address_array[taa_index].address_offset = 0;
97 taa_index++;
98 /* legacy ranges if its a VGA card... */
99 if ((bios_device.dev->class & 0xFF0000) == 0x030000) {
100 DEBUG_PRINTF("%s: VGA device found, adding legacy resources... \n", __func__);
101 /* I/O 0x3B0-0x3BB */
102 translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_IO;
103 translate_address_array[taa_index].bus = bus;
104 translate_address_array[taa_index].devfn = devfn;
105 translate_address_array[taa_index].cfg_space_offset = 0;
106 translate_address_array[taa_index].address = 0x3b0;
107 translate_address_array[taa_index].size = 0xc;
Martin Roth63373ed2013-07-08 16:24:19 -0600108 /* don't translate addresses... all addresses are 1:1 */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000109 translate_address_array[taa_index].address_offset = 0;
110 taa_index++;
111 /* I/O 0x3C0-0x3DF */
112 translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_IO;
113 translate_address_array[taa_index].bus = bus;
114 translate_address_array[taa_index].devfn = devfn;
115 translate_address_array[taa_index].cfg_space_offset = 0;
116 translate_address_array[taa_index].address = 0x3c0;
117 translate_address_array[taa_index].size = 0x20;
Martin Roth63373ed2013-07-08 16:24:19 -0600118 /* don't translate addresses... all addresses are 1:1 */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000119 translate_address_array[taa_index].address_offset = 0;
120 taa_index++;
121 /* Mem 0xA0000-0xBFFFF */
122 translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_MEM;
123 translate_address_array[taa_index].bus = bus;
124 translate_address_array[taa_index].devfn = devfn;
125 translate_address_array[taa_index].cfg_space_offset = 0;
126 translate_address_array[taa_index].address = 0xa0000;
127 translate_address_array[taa_index].size = 0x20000;
Martin Roth63373ed2013-07-08 16:24:19 -0600128 /* don't translate addresses... all addresses are 1:1 */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000129 translate_address_array[taa_index].address_offset = 0;
130 taa_index++;
131 }
132 // store last entry index of translate_address_array
133 taa_last_entry = taa_index - 1;
Stefan Reinauer1d888a92011-04-21 20:24:43 +0000134#if CONFIG_X86EMU_DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000135 //dump translate_address_array
136 printf("translate_address_array: \n");
137 translate_address_t ta;
Stefan Reinauerc56e5ad2010-05-27 15:41:15 +0000138 int i;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000139 for (i = 0; i <= taa_last_entry; i++) {
140 ta = translate_address_array[i];
141 printf
142 ("%d: info: %08lx bus: %02x devfn: %02x cfg_space_offset: %02x\n\taddr: %016llx\n\toffs: %016llx\n\tsize: %016llx\n",
143 i, ta.info, ta.bus, ta.devfn, ta.cfg_space_offset,
144 ta.address, ta.address_offset, ta.size);
145 }
146#endif
147}
148#else
149// use translate_address_dev and get_puid from net-snk's net_support.c
150void translate_address_dev(u64 *, phandle_t);
151u64 get_puid(phandle_t node);
152
153
Martin Roth63373ed2013-07-08 16:24:19 -0600154// scan all addresses assigned to the device ("assigned-addresses" and "reg")
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000155// store in translate_address_array for faster translation using dev_translate_address
156void
157biosemu_dev_get_addr_info(void)
158{
159 // get bus/dev/fn from assigned-addresses
160 int32_t len;
161 //max. 6 BARs and 1 Exp.ROM plus CfgSpace and 3 legacy ranges
162 assigned_address_t buf[11];
163 len =
164 of_getprop(bios_device.phandle, "assigned-addresses", buf,
165 sizeof(buf));
166 bios_device.bus = buf[0].bus;
167 bios_device.devfn = buf[0].devfn;
168 DEBUG_PRINTF("bus: %x, devfn: %x\n", bios_device.bus,
169 bios_device.devfn);
170 //store address translations for all assigned-addresses and regs in
171 //translate_address_array for faster translation later on...
172 int i = 0;
173 // index to insert data into translate_address_array
174 int taa_index = 0;
175 u64 address_offset;
176 for (i = 0; i < (len / sizeof(assigned_address_t)); i++, taa_index++) {
177 //copy all info stored in assigned-addresses
178 translate_address_array[taa_index].info = buf[i].info;
179 translate_address_array[taa_index].bus = buf[i].bus;
180 translate_address_array[taa_index].devfn = buf[i].devfn;
181 translate_address_array[taa_index].cfg_space_offset =
182 buf[i].cfg_space_offset;
183 translate_address_array[taa_index].address = buf[i].address;
184 translate_address_array[taa_index].size = buf[i].size;
185 // translate first address and store it as address_offset
186 address_offset = buf[i].address;
187 translate_address_dev(&address_offset, bios_device.phandle);
188 translate_address_array[taa_index].address_offset =
189 address_offset - buf[i].address;
190 }
191 //get "reg" property
192 len = of_getprop(bios_device.phandle, "reg", buf, sizeof(buf));
193 for (i = 0; i < (len / sizeof(assigned_address_t)); i++) {
194 if ((buf[i].size == 0) || (buf[i].cfg_space_offset != 0)) {
Martin Roth63373ed2013-07-08 16:24:19 -0600195 // we don't care for ranges with size 0 and
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000196 // BARs and Expansion ROM must be in assigned-addresses... so in reg
197 // we only look for those without config space offset set...
198 // i.e. the legacy ranges
199 continue;
200 }
201 //copy all info stored in assigned-addresses
202 translate_address_array[taa_index].info = buf[i].info;
203 translate_address_array[taa_index].bus = buf[i].bus;
204 translate_address_array[taa_index].devfn = buf[i].devfn;
205 translate_address_array[taa_index].cfg_space_offset =
206 buf[i].cfg_space_offset;
207 translate_address_array[taa_index].address = buf[i].address;
208 translate_address_array[taa_index].size = buf[i].size;
209 // translate first address and store it as address_offset
210 address_offset = buf[i].address;
211 translate_address_dev(&address_offset, bios_device.phandle);
212 translate_address_array[taa_index].address_offset =
213 address_offset - buf[i].address;
214 taa_index++;
215 }
216 // store last entry index of translate_address_array
217 taa_last_entry = taa_index - 1;
Stefan Reinauer1d888a92011-04-21 20:24:43 +0000218#if CONFIG_X86EMU_DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000219 //dump translate_address_array
220 printf("translate_address_array: \n");
221 translate_address_t ta;
222 for (i = 0; i <= taa_last_entry; i++) {
223 ta = translate_address_array[i];
224 printf
225 ("%d: %02x%02x%02x%02x\n\taddr: %016llx\n\toffs: %016llx\n\tsize: %016llx\n",
226 i, ta.info, ta.bus, ta.devfn, ta.cfg_space_offset,
227 ta.address, ta.address_offset, ta.size);
228 }
229#endif
230}
231#endif
232
Patrick Georgi91443042011-01-13 11:38:46 +0000233// "special memory" is a hack to make some parts of memory fall through to real memory
234// (ie. no translation). Necessary if option ROMs attempt DMA there, map registers or
Martin Roth63373ed2013-07-08 16:24:19 -0600235// do similarly crazy things.
Patrick Georgi91443042011-01-13 11:38:46 +0000236void
237biosemu_add_special_memory(u32 start, u32 size)
238{
239 int taa_index = ++taa_last_entry;
240 translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_MEM;
241 translate_address_array[taa_index].bus = 0;
242 translate_address_array[taa_index].devfn = 0;
243 translate_address_array[taa_index].cfg_space_offset = 0;
244 translate_address_array[taa_index].address = start;
245 translate_address_array[taa_index].size = size;
Martin Roth63373ed2013-07-08 16:24:19 -0600246 /* don't translate addresses... all addresses are 1:1 */
Patrick Georgi91443042011-01-13 11:38:46 +0000247 translate_address_array[taa_index].address_offset = 0;
248}
249
Stefan Reinauer1d888a92011-04-21 20:24:43 +0000250#if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000251// to simulate accesses to legacy VGA Memory (0xA0000-0xBFFFF)
252// we look for the first prefetchable memory BAR, if no prefetchable BAR found,
253// we use the first memory BAR
254// dev_translate_addr will translate accesses to the legacy VGA Memory into the found vmem BAR
Uwe Hermann01ce6012010-03-05 10:03:50 +0000255static void
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000256biosemu_dev_find_vmem_addr(void)
257{
258 int i = 0;
259 translate_address_t ta;
260 s8 tai_np = -1, tai_p = -1; // translate_address_array index for non-prefetchable and prefetchable memory
261 //search backwards to find first entry
262 for (i = taa_last_entry; i >= 0; i--) {
263 ta = translate_address_array[i];
264 if ((ta.cfg_space_offset >= 0x10)
265 && (ta.cfg_space_offset <= 0x24)) {
266 //only BARs
267 if ((ta.info & 0x03) >= 0x02) {
268 //32/64bit memory
269 tai_np = i;
270 if ((ta.info & 0x40) != 0) {
271 // prefetchable
272 tai_p = i;
273 }
274 }
275 }
276 }
277 if (tai_p != -1) {
278 ta = translate_address_array[tai_p];
279 bios_device.vmem_addr = ta.address;
280 bios_device.vmem_size = ta.size;
281 DEBUG_PRINTF
282 ("%s: Found prefetchable Virtual Legacy Memory BAR: %llx, size: %llx\n",
283 __func__, bios_device.vmem_addr,
284 bios_device.vmem_size);
285 } else if (tai_np != -1) {
286 ta = translate_address_array[tai_np];
287 bios_device.vmem_addr = ta.address;
288 bios_device.vmem_size = ta.size;
289 DEBUG_PRINTF
290 ("%s: Found non-prefetchable Virtual Legacy Memory BAR: %llx, size: %llx",
291 __func__, bios_device.vmem_addr,
292 bios_device.vmem_size);
293 }
294 // disable vmem
295 //bios_device.vmem_size = 0;
296}
297
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000298void
299biosemu_dev_get_puid(void)
300{
301 // get puid
302 bios_device.puid = get_puid(bios_device.phandle);
303 DEBUG_PRINTF("puid: 0x%llx\n", bios_device.puid);
304}
305#endif
306
Uwe Hermann01ce6012010-03-05 10:03:50 +0000307static void
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000308biosemu_dev_get_device_vendor_id(void)
309{
310
311 u32 pci_config_0;
Stefan Reinauer1d888a92011-04-21 20:24:43 +0000312#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000313 pci_config_0 = pci_read_config32(bios_device.dev, 0x0);
314#else
315 pci_config_0 =
316 rtas_pci_config_read(bios_device.puid, 4, bios_device.bus,
317 bios_device.devfn, 0x0);
318#endif
319 bios_device.pci_device_id =
320 (u16) ((pci_config_0 & 0xFFFF0000) >> 16);
321 bios_device.pci_vendor_id = (u16) (pci_config_0 & 0x0000FFFF);
322 DEBUG_PRINTF("PCI Device ID: %04x, PCI Vendor ID: %x\n",
323 bios_device.pci_device_id, bios_device.pci_vendor_id);
324}
325
326/* Check whether the device has a valid Expansion ROM and search the PCI Data
327 * Structure and any Expansion ROM Header (using dev_scan_exp_header()) for
328 * needed information. If the rom_addr parameter is != 0, it is the address of
329 * the Expansion ROM image and will be used, if it is == 0, the Expansion ROM
330 * BAR address will be used.
331 */
332u8
333biosemu_dev_check_exprom(unsigned long rom_base_addr)
334{
335 int i = 0;
336 translate_address_t ta;
337 u16 pci_ds_offset;
338 pci_data_struct_t pci_ds;
339 if (rom_base_addr == 0) {
340 // check for ExpROM Address (Offset 30) in taa
341 for (i = 0; i <= taa_last_entry; i++) {
342 ta = translate_address_array[i];
343 if (ta.cfg_space_offset == 0x30) {
344 //translated address
345 rom_base_addr = ta.address + ta.address_offset;
346 break;
347 }
348 }
349 }
350 /* In the ROM there could be multiple Expansion ROM Images... start
351 * searching them for an x86 image.
352 */
353 do {
354 if (rom_base_addr == 0) {
355 printf("Error: no Expansion ROM address found!\n");
356 return -1;
357 }
358 set_ci();
359 u16 rom_signature = in16le((void *) rom_base_addr);
360 clr_ci();
361 if (rom_signature != 0xaa55) {
362 printf
363 ("Error: invalid Expansion ROM signature: %02x!\n",
364 *((u16 *) rom_base_addr));
365 return -1;
366 }
367 set_ci();
368 // at offset 0x18 is the (16bit little-endian) pointer to the PCI Data Structure
369 pci_ds_offset = in16le((void *) (rom_base_addr + 0x18));
370 //copy the PCI Data Structure
371 memcpy(&pci_ds, (void *) (rom_base_addr + pci_ds_offset),
372 sizeof(pci_ds));
373 clr_ci();
Stefan Reinauer1d888a92011-04-21 20:24:43 +0000374#if CONFIG_X86EMU_DEBUG
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000375 DEBUG_PRINTF("PCI Data Structure @%lx:\n",
376 rom_base_addr + pci_ds_offset);
377 dump((void *) &pci_ds, sizeof(pci_ds));
378#endif
379 if (strncmp((const char *) pci_ds.signature, "PCIR", 4) != 0) {
380 printf("Invalid PCI Data Structure found!\n");
381 break;
382 }
383 //little-endian conversion
384 pci_ds.vendor_id = in16le(&pci_ds.vendor_id);
385 pci_ds.device_id = in16le(&pci_ds.device_id);
386 pci_ds.img_length = in16le(&pci_ds.img_length);
387 pci_ds.pci_ds_length = in16le(&pci_ds.pci_ds_length);
Stefan Reinauerc1efb902011-10-12 14:30:59 -0700388#ifdef DO_THIS_TEST_TWICE
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000389 if (pci_ds.vendor_id != bios_device.pci_vendor_id) {
390 printf
391 ("Image has invalid Vendor ID: %04x, expected: %04x\n",
392 pci_ds.vendor_id, bios_device.pci_vendor_id);
393 break;
394 }
395 if (pci_ds.device_id != bios_device.pci_device_id) {
396 printf
397 ("Image has invalid Device ID: %04x, expected: %04x\n",
398 pci_ds.device_id, bios_device.pci_device_id);
399 break;
400 }
Stefan Reinauerc1efb902011-10-12 14:30:59 -0700401#endif
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000402 DEBUG_PRINTF("Image Length: %d\n", pci_ds.img_length * 512);
403 DEBUG_PRINTF("Image Code Type: %d\n", pci_ds.code_type);
404 if (pci_ds.code_type == 0) {
405 //x86 image
406 //store image address and image length in bios_device struct
407 bios_device.img_addr = rom_base_addr;
408 bios_device.img_size = pci_ds.img_length * 512;
409 // we found the image, exit the loop
410 break;
411 } else {
412 // no x86 image, check next image (if any)
413 rom_base_addr += pci_ds.img_length * 512;
414 }
415 if ((pci_ds.indicator & 0x80) == 0x80) {
416 //last image found, exit the loop
417 DEBUG_PRINTF("Last PCI Expansion ROM Image found.\n");
418 break;
419 }
420 }
421 while (bios_device.img_addr == 0);
422 // in case we did not find a valid x86 Expansion ROM Image
423 if (bios_device.img_addr == 0) {
424 printf("Error: no valid x86 Expansion ROM Image found!\n");
425 return -1;
426 }
427 return 0;
428}
429
430u8
431biosemu_dev_init(struct device * device)
432{
433 u8 rval = 0;
434 //init bios_device struct
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000435 DEBUG_PRINTF("%s\n", __func__);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000436 memset(&bios_device, 0, sizeof(bios_device));
437
Stefan Reinauer1d888a92011-04-21 20:24:43 +0000438#if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000439 bios_device.ihandle = of_open(device_name);
440 if (bios_device.ihandle == 0) {
441 DEBUG_PRINTF("%s is no valid device!\n", device_name);
442 return -1;
443 }
444 bios_device.phandle = of_finddevice(device_name);
445#else
446 bios_device.dev = device;
447#endif
448 biosemu_dev_get_addr_info();
Stefan Reinauer1d888a92011-04-21 20:24:43 +0000449#if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000450 biosemu_dev_find_vmem_addr();
451 biosemu_dev_get_puid();
452#endif
453 biosemu_dev_get_device_vendor_id();
454 return rval;
455}
456
457// translate address function using translate_address_array assembled
458// by dev_get_addr_info... MUCH faster than calling translate_address_dev
459// and accessing client interface for every translation...
460// returns: 0 if addr not found in translate_address_array, 1 if found.
461u8
Patrick Georgi91443042011-01-13 11:38:46 +0000462biosemu_dev_translate_address(int type, unsigned long * addr)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000463{
464 int i = 0;
465 translate_address_t ta;
Stefan Reinauer1d888a92011-04-21 20:24:43 +0000466#if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
Martin Roth63373ed2013-07-08 16:24:19 -0600467 /* we don't need this hack for coreboot... we can access legacy areas */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000468 //check if it is an access to legacy VGA Mem... if it is, map the address
469 //to the vmem BAR and then translate it...
470 // (translation info provided by Ben Herrenschmidt)
471 // NOTE: the translation seems to only work for NVIDIA cards... but it is needed
472 // to make some NVIDIA cards work at all...
473 if ((bios_device.vmem_size > 0)
474 && ((*addr >= 0xA0000) && (*addr < 0xB8000))) {
475 *addr = (*addr - 0xA0000) * 4 + 2 + bios_device.vmem_addr;
476 }
477 if ((bios_device.vmem_size > 0)
478 && ((*addr >= 0xB8000) && (*addr < 0xC0000))) {
479 u8 shift = *addr & 1;
480 *addr &= 0xfffffffe;
481 *addr = (*addr - 0xB8000) * 4 + shift + bios_device.vmem_addr;
482 }
483#endif
484 for (i = 0; i <= taa_last_entry; i++) {
485 ta = translate_address_array[i];
Patrick Georgi91443042011-01-13 11:38:46 +0000486 if ((*addr >= ta.address) && (*addr <= (ta.address + ta.size)) && (ta.info & type)) {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000487 *addr += ta.address_offset;
488 return 1;
489 }
490 }
491 return 0;
492}