Drop buggy duplicate implementation of intXX handlers and provide enough glue to use all of YABEL. Change-Id: I2db77a56a2a991cb84876456dcbb3a843a0d9754 Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Reviewed-on: https://review.coreboot.org/12117 Reviewed-by: Ronald G. Minnich <rminnich@gmail.com> Tested-by: build bot (Jenkins)
		
			
				
	
	
		
			483 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			483 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /******************************************************************************
 | |
|  * Copyright (c) 2004, 2008 IBM Corporation
 | |
|  * Copyright (c) 2008, 2009 Pattrick Hueper <phueper@hueper.net>
 | |
|  * All rights reserved.
 | |
|  * This program and the accompanying materials
 | |
|  * are made available under the terms of the BSD License
 | |
|  * which accompanies this distribution, and is available at
 | |
|  * http://www.opensource.org/licenses/bsd-license.php
 | |
|  *
 | |
|  * Contributors:
 | |
|  *     IBM Corporation - initial implementation
 | |
|  *****************************************************************************/
 | |
| 
 | |
| 
 | |
| #include <stdtypes.h>
 | |
| 
 | |
| #include <arch/byteorder.h>
 | |
| #include "device.h"
 | |
| #include "compat/rtas.h"
 | |
| #include <string.h>
 | |
| #include "debug.h"
 | |
| 
 | |
| #include <device/device.h>
 | |
| #include <device/pci.h>
 | |
| #include <device/pci_ops.h>
 | |
| #include <device/resource.h>
 | |
| 
 | |
| /* the device we are working with... */
 | |
| biosemu_device_t bios_device;
 | |
| //max. 6 BARs and 1 Exp.ROM plus CfgSpace and 3 legacy ranges, plus 2 "special" memory ranges
 | |
| translate_address_t translate_address_array[13];
 | |
| u8 taa_last_entry;
 | |
| 
 | |
| typedef struct {
 | |
| 	u8 info;
 | |
| 	u8 bus;
 | |
| 	u8 devfn;
 | |
| 	u8 cfg_space_offset;
 | |
| 	u64 address;
 | |
| 	u64 size;
 | |
| } __attribute__ ((__packed__)) assigned_address_t;
 | |
| 
 | |
| #if CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | |
| /* coreboot version */
 | |
| 
 | |
| static void
 | |
| biosemu_dev_get_addr_info(void)
 | |
| {
 | |
| #if 0
 | |
| 	int taa_index = 0;
 | |
| 	struct resource *r;
 | |
| 	u8 bus = bios_device.dev->bus->secondary;
 | |
| 	u16 devfn = bios_device.dev->path.pci.devfn;
 | |
| 
 | |
| 	bios_device.bus =  bus;
 | |
| 	bios_device.devfn = devfn;
 | |
| 
 | |
| 	DEBUG_PRINTF("bus: %x, devfn: %x\n", bus, devfn);
 | |
| 	for (r = bios_device.dev->resource_list; r; r = r->next) {
 | |
| 		translate_address_array[taa_index].info = r->flags;
 | |
| 		translate_address_array[taa_index].bus = bus;
 | |
| 		translate_address_array[taa_index].devfn = devfn;
 | |
| 		translate_address_array[taa_index].cfg_space_offset =
 | |
| 		    r->index;
 | |
| 		translate_address_array[taa_index].address = r->base;
 | |
| 		translate_address_array[taa_index].size = r->size;
 | |
| 		/* don't translate addresses... all addresses are 1:1 */
 | |
| 		translate_address_array[taa_index].address_offset = 0;
 | |
| 		taa_index++;
 | |
| 	}
 | |
| 	/* Expansion ROM */
 | |
| 	translate_address_array[taa_index].info = IORESOURCE_MEM | IORESOURCE_READONLY;
 | |
| 	translate_address_array[taa_index].bus = bus;
 | |
| 	translate_address_array[taa_index].devfn = devfn;
 | |
| 	translate_address_array[taa_index].cfg_space_offset = 0x30;
 | |
| 	translate_address_array[taa_index].address = bios_device.img_addr;
 | |
| 	translate_address_array[taa_index].size = 0; /* TODO: do we need the size? */
 | |
| 	/* don't translate addresses... all addresses are 1:1 */
 | |
| 	translate_address_array[taa_index].address_offset = 0;
 | |
| 	taa_index++;
 | |
| 	/* legacy ranges if its a VGA card... */
 | |
| 	if ((bios_device.dev->class & 0xFF0000) == 0x030000) {
 | |
| 		DEBUG_PRINTF("%s: VGA device found, adding legacy resources... \n", __func__);
 | |
| 		/* I/O 0x3B0-0x3BB */
 | |
| 		translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_IO;
 | |
| 		translate_address_array[taa_index].bus = bus;
 | |
| 		translate_address_array[taa_index].devfn = devfn;
 | |
| 		translate_address_array[taa_index].cfg_space_offset = 0;
 | |
| 		translate_address_array[taa_index].address = 0x3b0;
 | |
| 		translate_address_array[taa_index].size = 0xc;
 | |
| 		/* don't translate addresses... all addresses are 1:1 */
 | |
| 		translate_address_array[taa_index].address_offset = 0;
 | |
| 		taa_index++;
 | |
| 		/* I/O 0x3C0-0x3DF */
 | |
| 		translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_IO;
 | |
| 		translate_address_array[taa_index].bus = bus;
 | |
| 		translate_address_array[taa_index].devfn = devfn;
 | |
| 		translate_address_array[taa_index].cfg_space_offset = 0;
 | |
| 		translate_address_array[taa_index].address = 0x3c0;
 | |
| 		translate_address_array[taa_index].size = 0x20;
 | |
| 		/* don't translate addresses... all addresses are 1:1 */
 | |
| 		translate_address_array[taa_index].address_offset = 0;
 | |
| 		taa_index++;
 | |
| 		/* Mem 0xA0000-0xBFFFF */
 | |
| 		translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_MEM;
 | |
| 		translate_address_array[taa_index].bus = bus;
 | |
| 		translate_address_array[taa_index].devfn = devfn;
 | |
| 		translate_address_array[taa_index].cfg_space_offset = 0;
 | |
| 		translate_address_array[taa_index].address = 0xa0000;
 | |
| 		translate_address_array[taa_index].size = 0x20000;
 | |
| 		/* don't translate addresses... all addresses are 1:1 */
 | |
| 		translate_address_array[taa_index].address_offset = 0;
 | |
| 		taa_index++;
 | |
| 	}
 | |
| 	// store last entry index of translate_address_array
 | |
| 	taa_last_entry = taa_index - 1;
 | |
| #if CONFIG_X86EMU_DEBUG
 | |
| 	//dump translate_address_array
 | |
| 	printf("translate_address_array: \n");
 | |
| 	translate_address_t ta;
 | |
| 	int i;
 | |
| 	for (i = 0; i <= taa_last_entry; i++) {
 | |
| 		ta = translate_address_array[i];
 | |
| 		printf
 | |
| 		    ("%d: info: %08lx bus: %02x devfn: %02x cfg_space_offset: %02x\n\taddr: %016llx\n\toffs: %016llx\n\tsize: %016llx\n",
 | |
| 		     i, ta.info, ta.bus, ta.devfn, ta.cfg_space_offset,
 | |
| 		     ta.address, ta.address_offset, ta.size);
 | |
| 	}
 | |
| #endif
 | |
| #endif
 | |
| }
 | |
| #else
 | |
| // use translate_address_dev and get_puid from net-snk's net_support.c
 | |
| void translate_address_dev(u64 *, phandle_t);
 | |
| u64 get_puid(phandle_t node);
 | |
| 
 | |
| 
 | |
| // scan all addresses assigned to the device ("assigned-addresses" and "reg")
 | |
| // store in translate_address_array for faster translation using dev_translate_address
 | |
| void
 | |
| biosemu_dev_get_addr_info(void)
 | |
| {
 | |
| 	// get bus/dev/fn from assigned-addresses
 | |
| 	int32_t len;
 | |
| 	//max. 6 BARs and 1 Exp.ROM plus CfgSpace and 3 legacy ranges
 | |
| 	assigned_address_t buf[11];
 | |
| 	len =
 | |
| 	    of_getprop(bios_device.phandle, "assigned-addresses", buf,
 | |
| 		       sizeof(buf));
 | |
| 	bios_device.bus = buf[0].bus;
 | |
| 	bios_device.devfn = buf[0].devfn;
 | |
| 	DEBUG_PRINTF("bus: %x, devfn: %x\n", bios_device.bus,
 | |
| 		     bios_device.devfn);
 | |
| 	//store address translations for all assigned-addresses and regs in
 | |
| 	//translate_address_array for faster translation later on...
 | |
| 	int i = 0;
 | |
| 	// index to insert data into translate_address_array
 | |
| 	int taa_index = 0;
 | |
| 	u64 address_offset;
 | |
| 	for (i = 0; i < (len / sizeof(assigned_address_t)); i++, taa_index++) {
 | |
| 		//copy all info stored in assigned-addresses
 | |
| 		translate_address_array[taa_index].info = buf[i].info;
 | |
| 		translate_address_array[taa_index].bus = buf[i].bus;
 | |
| 		translate_address_array[taa_index].devfn = buf[i].devfn;
 | |
| 		translate_address_array[taa_index].cfg_space_offset =
 | |
| 		    buf[i].cfg_space_offset;
 | |
| 		translate_address_array[taa_index].address = buf[i].address;
 | |
| 		translate_address_array[taa_index].size = buf[i].size;
 | |
| 		// translate first address and store it as address_offset
 | |
| 		address_offset = buf[i].address;
 | |
| 		translate_address_dev(&address_offset, bios_device.phandle);
 | |
| 		translate_address_array[taa_index].address_offset =
 | |
| 		    address_offset - buf[i].address;
 | |
| 	}
 | |
| 	//get "reg" property
 | |
| 	len = of_getprop(bios_device.phandle, "reg", buf, sizeof(buf));
 | |
| 	for (i = 0; i < (len / sizeof(assigned_address_t)); i++) {
 | |
| 		if ((buf[i].size == 0) || (buf[i].cfg_space_offset != 0)) {
 | |
| 			// we don't care for ranges with size 0 and
 | |
| 			// BARs and Expansion ROM must be in assigned-addresses... so in reg
 | |
| 			// we only look for those without config space offset set...
 | |
| 			// i.e. the legacy ranges
 | |
| 			continue;
 | |
| 		}
 | |
| 		//copy all info stored in assigned-addresses
 | |
| 		translate_address_array[taa_index].info = buf[i].info;
 | |
| 		translate_address_array[taa_index].bus = buf[i].bus;
 | |
| 		translate_address_array[taa_index].devfn = buf[i].devfn;
 | |
| 		translate_address_array[taa_index].cfg_space_offset =
 | |
| 		    buf[i].cfg_space_offset;
 | |
| 		translate_address_array[taa_index].address = buf[i].address;
 | |
| 		translate_address_array[taa_index].size = buf[i].size;
 | |
| 		// translate first address and store it as address_offset
 | |
| 		address_offset = buf[i].address;
 | |
| 		translate_address_dev(&address_offset, bios_device.phandle);
 | |
| 		translate_address_array[taa_index].address_offset =
 | |
| 		    address_offset - buf[i].address;
 | |
| 		taa_index++;
 | |
| 	}
 | |
| 	// store last entry index of translate_address_array
 | |
| 	taa_last_entry = taa_index - 1;
 | |
| #if CONFIG_X86EMU_DEBUG
 | |
| 	//dump translate_address_array
 | |
| 	printf("translate_address_array: \n");
 | |
| 	translate_address_t ta;
 | |
| 	for (i = 0; i <= taa_last_entry; i++) {
 | |
| 		ta = translate_address_array[i];
 | |
| 		printf
 | |
| 		    ("%d: %02x%02x%02x%02x\n\taddr: %016llx\n\toffs: %016llx\n\tsize: %016llx\n",
 | |
| 		     i, ta.info, ta.bus, ta.devfn, ta.cfg_space_offset,
 | |
| 		     ta.address, ta.address_offset, ta.size);
 | |
| 	}
 | |
| #endif
 | |
| }
 | |
| #endif
 | |
| 
 | |
| // "special memory" is a hack to make some parts of memory fall through to real memory
 | |
| // (ie. no translation). Necessary if option ROMs attempt DMA there, map registers or
 | |
| // do similarly crazy things.
 | |
| void
 | |
| biosemu_add_special_memory(u32 start, u32 size)
 | |
| {
 | |
| #if 0
 | |
| 	int taa_index = ++taa_last_entry;
 | |
| 	translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_MEM;
 | |
| 	translate_address_array[taa_index].bus = 0;
 | |
| 	translate_address_array[taa_index].devfn = 0;
 | |
| 	translate_address_array[taa_index].cfg_space_offset = 0;
 | |
| 	translate_address_array[taa_index].address = start;
 | |
| 	translate_address_array[taa_index].size = size;
 | |
| 	/* don't translate addresses... all addresses are 1:1 */
 | |
| 	translate_address_array[taa_index].address_offset = 0;
 | |
| #endif
 | |
| 	printf("TODO: Add special memory handler for %x[%x]\n", start, size);
 | |
| }
 | |
| 
 | |
| #if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | |
| // to simulate accesses to legacy VGA Memory (0xA0000-0xBFFFF)
 | |
| // we look for the first prefetchable memory BAR, if no prefetchable BAR found,
 | |
| // we use the first memory BAR
 | |
| // dev_translate_addr will translate accesses to the legacy VGA Memory into the found vmem BAR
 | |
| static void
 | |
| biosemu_dev_find_vmem_addr(void)
 | |
| {
 | |
| 	int i = 0;
 | |
| 	translate_address_t ta;
 | |
| 	s8 tai_np = -1, tai_p = -1;	// translate_address_array index for non-prefetchable and prefetchable memory
 | |
| 	//search backwards to find first entry
 | |
| 	for (i = taa_last_entry; i >= 0; i--) {
 | |
| 		ta = translate_address_array[i];
 | |
| 		if ((ta.cfg_space_offset >= 0x10)
 | |
| 		    && (ta.cfg_space_offset <= 0x24)) {
 | |
| 			//only BARs
 | |
| 			if ((ta.info & 0x03) >= 0x02) {
 | |
| 				//32/64bit memory
 | |
| 				tai_np = i;
 | |
| 				if ((ta.info & 0x40) != 0) {
 | |
| 					// prefetchable
 | |
| 					tai_p = i;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	if (tai_p != -1) {
 | |
| 		ta = translate_address_array[tai_p];
 | |
| 		bios_device.vmem_addr = ta.address;
 | |
| 		bios_device.vmem_size = ta.size;
 | |
| 		DEBUG_PRINTF
 | |
| 		    ("%s: Found prefetchable Virtual Legacy Memory BAR: %llx, size: %llx\n",
 | |
| 		     __func__, bios_device.vmem_addr,
 | |
| 		     bios_device.vmem_size);
 | |
| 	} else if (tai_np != -1) {
 | |
| 		ta = translate_address_array[tai_np];
 | |
| 		bios_device.vmem_addr = ta.address;
 | |
| 		bios_device.vmem_size = ta.size;
 | |
| 		DEBUG_PRINTF
 | |
| 		    ("%s: Found non-prefetchable Virtual Legacy Memory BAR: %llx, size: %llx",
 | |
| 		     __func__, bios_device.vmem_addr,
 | |
| 		     bios_device.vmem_size);
 | |
| 	}
 | |
| 	// disable vmem
 | |
| 	//bios_device.vmem_size = 0;
 | |
| }
 | |
| 
 | |
| void
 | |
| biosemu_dev_get_puid(void)
 | |
| {
 | |
| 	// get puid
 | |
| 	bios_device.puid = get_puid(bios_device.phandle);
 | |
| 	DEBUG_PRINTF("puid: 0x%llx\n", bios_device.puid);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static void
 | |
| biosemu_dev_get_device_vendor_id(void)
 | |
| {
 | |
| 
 | |
| 	u32 pci_config_0;
 | |
| #if CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | |
| 	pci_config_0 = pci_read_config32(bios_device.dev, 0x0);
 | |
| #else
 | |
| 	pci_config_0 =
 | |
| 	    rtas_pci_config_read(bios_device.puid, 4, bios_device.bus,
 | |
| 				 bios_device.devfn, 0x0);
 | |
| #endif
 | |
| 	bios_device.pci_device_id =
 | |
| 	    (u16) ((pci_config_0 & 0xFFFF0000) >> 16);
 | |
| 	bios_device.pci_vendor_id = (u16) (pci_config_0 & 0x0000FFFF);
 | |
| 	DEBUG_PRINTF("PCI Device ID: %04x, PCI Vendor ID: %x\n",
 | |
| 		     bios_device.pci_device_id, bios_device.pci_vendor_id);
 | |
| }
 | |
| 
 | |
| /* Check whether the device has a valid Expansion ROM and search the PCI Data
 | |
|  * Structure and any Expansion ROM Header (using dev_scan_exp_header()) for
 | |
|  * needed information.  If the rom_addr parameter is != 0, it is the address of
 | |
|  * the Expansion ROM image and will be used, if it is == 0, the Expansion ROM
 | |
|  * BAR address will be used.
 | |
|  */
 | |
| u8
 | |
| biosemu_dev_check_exprom(unsigned long rom_base_addr)
 | |
| {
 | |
| #if 0
 | |
| 	int i = 0;
 | |
| 	translate_address_t ta;
 | |
| 	u16 pci_ds_offset;
 | |
| 	pci_data_struct_t pci_ds;
 | |
| 	if (rom_base_addr == 0) {
 | |
| 		// check for ExpROM Address (Offset 30) in taa
 | |
| 		for (i = 0; i <= taa_last_entry; i++) {
 | |
| 			ta = translate_address_array[i];
 | |
| 			if (ta.cfg_space_offset == 0x30) {
 | |
| 				//translated address
 | |
| 				rom_base_addr = ta.address + ta.address_offset;
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	/* In the ROM there could be multiple Expansion ROM Images... start
 | |
| 	 * searching them for an x86 image.
 | |
| 	 */
 | |
| 	do {
 | |
| 		if (rom_base_addr == 0) {
 | |
| 			printf("Error: no Expansion ROM address found!\n");
 | |
| 			return -1;
 | |
| 		}
 | |
| 		set_ci();
 | |
| 		u16 rom_signature = in16le((void *) rom_base_addr);
 | |
| 		clr_ci();
 | |
| 		if (rom_signature != 0xaa55) {
 | |
| 			printf
 | |
| 			    ("Error: invalid Expansion ROM signature: %02x!\n",
 | |
| 			     *((u16 *) rom_base_addr));
 | |
| 			return -1;
 | |
| 		}
 | |
| 		set_ci();
 | |
| 		// at offset 0x18 is the (16bit little-endian) pointer to the PCI Data Structure
 | |
| 		pci_ds_offset = in16le((void *) (rom_base_addr + 0x18));
 | |
| 		//copy the PCI Data Structure
 | |
| 		memcpy(&pci_ds, (void *) (rom_base_addr + pci_ds_offset),
 | |
| 		       sizeof(pci_ds));
 | |
| 		clr_ci();
 | |
| #if CONFIG_X86EMU_DEBUG
 | |
| 		DEBUG_PRINTF("PCI Data Structure @%lx:\n",
 | |
| 			     rom_base_addr + pci_ds_offset);
 | |
| 		dump((void *) &pci_ds, sizeof(pci_ds));
 | |
| #endif
 | |
| 		if (strncmp((const char *) pci_ds.signature, "PCIR", 4) != 0) {
 | |
| 			printf("Invalid PCI Data Structure found!\n");
 | |
| 			break;
 | |
| 		}
 | |
| 		//little-endian conversion
 | |
| 		pci_ds.vendor_id = in16le(&pci_ds.vendor_id);
 | |
| 		pci_ds.device_id = in16le(&pci_ds.device_id);
 | |
| 		pci_ds.img_length = in16le(&pci_ds.img_length);
 | |
| 		pci_ds.pci_ds_length = in16le(&pci_ds.pci_ds_length);
 | |
| #ifdef DO_THIS_TEST_TWICE
 | |
| 		if (pci_ds.vendor_id != bios_device.pci_vendor_id) {
 | |
| 			printf
 | |
| 			    ("Image has invalid Vendor ID: %04x, expected: %04x\n",
 | |
| 			     pci_ds.vendor_id, bios_device.pci_vendor_id);
 | |
| 			break;
 | |
| 		}
 | |
| 		if (pci_ds.device_id != bios_device.pci_device_id) {
 | |
| 			printf
 | |
| 			    ("Image has invalid Device ID: %04x, expected: %04x\n",
 | |
| 			     pci_ds.device_id, bios_device.pci_device_id);
 | |
| 			break;
 | |
| 		}
 | |
| #endif
 | |
| 		DEBUG_PRINTF("Image Length: %d\n", pci_ds.img_length * 512);
 | |
| 		DEBUG_PRINTF("Image Code Type: %d\n", pci_ds.code_type);
 | |
| 		if (pci_ds.code_type == 0) {
 | |
| 			//x86 image
 | |
| 			//store image address and image length in bios_device struct
 | |
| 			bios_device.img_addr = rom_base_addr;
 | |
| 			bios_device.img_size = pci_ds.img_length * 512;
 | |
| 			// we found the image, exit the loop
 | |
| 			break;
 | |
| 		} else {
 | |
| 			// no x86 image, check next image (if any)
 | |
| 			rom_base_addr += pci_ds.img_length * 512;
 | |
| 		}
 | |
| 		if ((pci_ds.indicator & 0x80) == 0x80) {
 | |
| 			//last image found, exit the loop
 | |
| 			DEBUG_PRINTF("Last PCI Expansion ROM Image found.\n");
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 	while (bios_device.img_addr == 0);
 | |
| 	// in case we did not find a valid x86 Expansion ROM Image
 | |
| 	if (bios_device.img_addr == 0) {
 | |
| 		printf("Error: no valid x86 Expansion ROM Image found!\n");
 | |
| 		return -1;
 | |
| 	}
 | |
| #endif
 | |
| 	return 0;
 | |
| 
 | |
| }
 | |
| 
 | |
| u8
 | |
| biosemu_dev_init(struct device * device)
 | |
| {
 | |
| 	u8 rval = 0;
 | |
| 	//init bios_device struct
 | |
| 	DEBUG_PRINTF("%s\n", __func__);
 | |
| 	memset(&bios_device, 0, sizeof(bios_device));
 | |
| 
 | |
| #if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | |
| 	bios_device.ihandle = of_open(device_name);
 | |
| 	if (bios_device.ihandle == 0) {
 | |
| 		DEBUG_PRINTF("%s is no valid device!\n", device_name);
 | |
| 		return -1;
 | |
| 	}
 | |
| 	bios_device.phandle = of_finddevice(device_name);
 | |
| #else
 | |
| 	bios_device.dev = device;
 | |
| #endif
 | |
| 	biosemu_dev_get_addr_info();
 | |
| #if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | |
| 	biosemu_dev_find_vmem_addr();
 | |
| 	biosemu_dev_get_puid();
 | |
| #endif
 | |
| 	biosemu_dev_get_device_vendor_id();
 | |
| 	return rval;
 | |
| }
 | |
| 
 | |
| // translate address function using translate_address_array assembled
 | |
| // by dev_get_addr_info... MUCH faster than calling translate_address_dev
 | |
| // and accessing client interface for every translation...
 | |
| // returns: 0 if addr not found in translate_address_array, 1 if found.
 | |
| u8
 | |
| biosemu_dev_translate_address(int type, unsigned long * addr)
 | |
| {
 | |
| 	int i = 0;
 | |
| 	translate_address_t ta;
 | |
| #if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
 | |
| 	/* we don't need this hack for coreboot... we can access legacy areas */
 | |
| 	//check if it is an access to legacy VGA Mem... if it is, map the address
 | |
| 	//to the vmem BAR and then translate it...
 | |
| 	// (translation info provided by Ben Herrenschmidt)
 | |
| 	// NOTE: the translation seems to only work for NVIDIA cards... but it is needed
 | |
| 	// to make some NVIDIA cards work at all...
 | |
| 	if ((bios_device.vmem_size > 0)
 | |
| 	    && ((*addr >= 0xA0000) && (*addr < 0xB8000))) {
 | |
| 		*addr = (*addr - 0xA0000) * 4 + 2 + bios_device.vmem_addr;
 | |
| 	}
 | |
| 	if ((bios_device.vmem_size > 0)
 | |
| 	    && ((*addr >= 0xB8000) && (*addr < 0xC0000))) {
 | |
| 		u8 shift = *addr & 1;
 | |
| 		*addr &= 0xfffffffe;
 | |
| 		*addr = (*addr - 0xB8000) * 4 + shift + bios_device.vmem_addr;
 | |
| 	}
 | |
| #endif
 | |
| 	for (i = 0; i <= taa_last_entry; i++) {
 | |
| 		ta = translate_address_array[i];
 | |
| 		if ((*addr >= ta.address) && (*addr <= (ta.address + ta.size)) && (ta.info & type)) {
 | |
| 			*addr += ta.address_offset;
 | |
| 			return 1;
 | |
| 		}
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 |