aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot-sam460ex/board/ACube/bios_emulator/glue_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot-sam460ex/board/ACube/bios_emulator/glue_test.c')
-rw-r--r--roms/u-boot-sam460ex/board/ACube/bios_emulator/glue_test.c619
1 files changed, 619 insertions, 0 deletions
diff --git a/roms/u-boot-sam460ex/board/ACube/bios_emulator/glue_test.c b/roms/u-boot-sam460ex/board/ACube/bios_emulator/glue_test.c
new file mode 100644
index 000000000..86a1b1ef8
--- /dev/null
+++ b/roms/u-boot-sam460ex/board/ACube/bios_emulator/glue_test.c
@@ -0,0 +1,619 @@
+#include <common.h>
+#include <pci.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DEBUG
+
+#ifdef DEBUG
+#define PRINTF(format, args...) printf(format , ## args)
+#else
+#define PRINTF(format, argc...)
+#endif
+
+#ifdef CONFIG_SAM460EX
+extern struct pci_controller *ppc460_hose;
+#endif
+
+static pci_dev_t to_pci(int bus, int devfn)
+{
+ return PCI_BDF(bus, (devfn>>3), devfn&3);
+}
+
+int mypci_find_device(int vendor, int product, int index)
+{
+ return pci_find_device(vendor, product, index);
+}
+
+int mypci_bus(int device)
+{
+ return PCI_BUS(device);
+}
+
+int mypci_devfn(int device)
+{
+ return (PCI_DEV(device)<<3) | PCI_FUNC(device);
+}
+
+
+#define mypci_read_func(type, size) \
+type mypci_read_cfg_##size(int bus, int devfn, int offset) \
+{ \
+ type c; \
+ pci_read_config_##size(to_pci(bus, devfn), offset, &c); \
+ return c; \
+}
+
+#define mypci_write_func(type, size) \
+void mypci_write_cfg_##size(int bus, int devfn, int offset, int value) \
+{ \
+ pci_write_config_##size(to_pci(bus, devfn), offset, value); \
+}
+
+mypci_read_func(u8,byte);
+mypci_read_func(u16,word);
+
+mypci_write_func(u8,byte);
+mypci_write_func(u16,word);
+
+u32 mypci_read_cfg_long(int bus, int devfn, int offset)
+{
+ u32 c;
+ pci_read_config_dword(to_pci(bus, devfn), offset, &c);
+ return c;
+}
+
+void mypci_write_cfg_long(int bus, int devfn, int offset, int value)
+{
+ pci_write_config_dword(to_pci(bus, devfn), offset, value);
+}
+
+unsigned long get_bar_size(pci_dev_t dev, int offset)
+{
+ u32 bar_back, bar_value;
+
+ /* Save old BAR value */
+ pci_read_config_dword(dev, offset, &bar_back);
+
+ /* Write all 1's. */
+ pci_write_config_dword(dev, offset, ~0);
+
+ /* Now read back the relevant bits */
+ pci_read_config_dword(dev, offset, &bar_value);
+
+ /* Restore original value */
+ pci_write_config_dword(dev, offset, bar_back);
+
+ if (bar_value == 0) return 0xFFFFFFFF; /* This BAR is disabled */
+
+ if ((bar_value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
+ {
+ /* This is a memory space BAR. Mask it out so we get the size of it */
+ return ~(bar_value & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ }
+
+ /* Not suitable */
+ return 0xFFFFFFFF;
+}
+
+#ifdef DEBUG
+unsigned long get_real_size(pci_dev_t dev, int offset)
+{
+ u32 bar_back, bar_value;
+
+ /* Save old BAR value */
+ pci_read_config_dword(dev, offset, &bar_back);
+
+ /* Write all 1's. */
+ pci_write_config_dword(dev, offset, ~0);
+
+ /* Now read back the relevant bits */
+ pci_read_config_dword(dev, offset, &bar_value);
+
+ /* Restore original value */
+ pci_write_config_dword(dev, offset, bar_back);
+
+ if (bar_value == 0) return 0;
+
+ if ((bar_value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
+ {
+ /* This is a memory space BAR. Mask it out so we get the size of it */
+ return ~(bar_value & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ }
+
+ if ((bar_value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+ {
+ return ~(bar_value & PCI_BASE_ADDRESS_IO_MASK) + 1;
+ }
+
+ return 0;
+}
+#endif
+
+void enable_compatibility_hole(void)
+{
+ u8 cfg;
+ pci_dev_t art = PCI_BDF(0,0,0);
+
+ pci_read_config_byte(art, 0x54, &cfg);
+ /* cfg |= 0x08; */
+ cfg |= 0x20;
+ pci_write_config_byte(art, 0x54, cfg);
+}
+
+void disable_compatibility_hole(void)
+{
+ u8 cfg;
+ pci_dev_t art = PCI_BDF(0,0,0);
+
+ pci_read_config_byte(art, 0x54, &cfg);
+ /* cfg &= ~0x08; */
+ cfg &= ~0x20;
+ pci_write_config_byte(art, 0x54, cfg);
+}
+
+void map_rom(pci_dev_t dev, u32 address)
+{
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, address|PCI_ROM_ADDRESS_ENABLE);
+}
+
+void unmap_rom(pci_dev_t dev)
+{
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+}
+
+void bat_map(u8 batnum, u32 address, u32 length)
+{
+ return;
+ u32 temp = address;
+ address &= 0xFFFE0000;
+ temp &= 0x0001FFFF;
+ length = (length - 1 ) >> 17;
+ length <<= 2;
+
+ switch (batnum)
+ {
+ case 0:
+ __asm volatile ("mtdbatu 0, %0" : : "r" (address | length | 3));
+ __asm volatile ("mtdbatl 0, %0" : : "r" (address | 0x22));
+ break;
+ case 1:
+ __asm volatile ("mtdbatu 1, %0" : : "r" (address | length | 3));
+ __asm volatile ("mtdbatl 1, %0" : : "r" (address | 0x22));
+ break;
+ case 2:
+ __asm volatile ("mtdbatu 2, %0" : : "r" (address | length | 3));
+ __asm volatile ("mtdbatl 2, %0" : : "r" (address | 0x22));
+ break;
+ case 3:
+ __asm volatile ("mtdbatu 3, %0" : : "r" (address | length | 3));
+ __asm volatile ("mtdbatl 3, %0" : : "r" (address | 0x22));
+ break;
+ }
+}
+
+void clear_bat2(void)
+{
+ return;
+ u32 temp = 0;
+ __asm volatile(
+ "mtdbatu 2, %0\n"
+ "mtdbatl 2, %0\n"
+ "mtibatu 2, %0\n"
+ "mtibatl 2, %0\n"
+ : : "r" (temp));
+}
+
+void find_radeon_values(pci_dev_t dev, u8 * rom_addr)
+{
+ u16 bios_header;
+ u16 pll_info_block;
+ struct radeon_data
+ {
+ unsigned short ReferenceFrequency;
+ unsigned short ReferenceDivider;
+ unsigned long PLLMin;
+ unsigned long PLLMax;
+ } __attribute__((packed));
+ u16 vendor;
+
+ struct radeon_data *rdat;
+
+ DECLARE_GLOBAL_DATA_PTR;
+
+ /* If it's an ATI card, get the values needed by the driver */
+ pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+ if (vendor != 0x1002)
+ return;
+
+ gd->bd->bi_sramstart = malloc(sizeof(struct radeon_data));
+ rdat = (struct radeon_data *) gd->bd->bi_sramstart;
+
+ bios_header = rom_addr[0x48] | (rom_addr[0x49]<<8);
+ bios_header += 0x30;
+ pll_info_block = rom_addr[bios_header] | (rom_addr[bios_header+1]<<8);
+ pll_info_block += 0x0e;
+
+ rdat->ReferenceFrequency = rom_addr[pll_info_block] | (rom_addr[pll_info_block+1]<<8);
+ pll_info_block += 2;
+
+ rdat->ReferenceDivider = rom_addr[pll_info_block] | (rom_addr[pll_info_block+1]<<8);
+ pll_info_block += 2;
+
+ rdat->PLLMin = rom_addr[pll_info_block]
+ | (rom_addr[pll_info_block+1]<<8)
+ | (rom_addr[pll_info_block+2]<<16)
+ | (rom_addr[pll_info_block+3]<<14);
+ pll_info_block += 4;
+
+ rdat->PLLMax = rom_addr[pll_info_block]
+ | (rom_addr[pll_info_block+1]<<8)
+ | (rom_addr[pll_info_block+2]<<16)
+ | (rom_addr[pll_info_block+3]<<14);
+}
+
+
+int find_image(u32 rom_address, u32 rom_size, void **image, u32 *image_size);
+
+#if defined(CONFIG_SAM440EP)
+#include "radeon_bios.h"
+
+void load_compressed_bios(void *copy_address)
+{
+ memcpy(copy_address, radeon_bios, 65536);
+}
+#endif
+
+int attempt_map_rom(pci_dev_t dev, void *copy_address)
+{
+ u32 rom_size = 0;
+ u32 rom_address = 0;
+ u32 bar_size = 0;
+ u32 bar_backup = 0;
+ int i;
+ void *image = 0;
+ u32 image_size = 0;
+ u32 prefetch_idx = 0;
+ u32 lower = 0xFFFFFFFF;
+ u32 upper = 0x00000000;
+ u32 mlower = 0xFFFFFFFF;
+ u32 mupper = 0x00000000;
+ int foundimg = 0;
+ int foundmini = 0;
+ u16 vendor = 0;
+ u32 iobase = 0;
+
+#ifdef CONFIG_SAM460EX
+ struct pci_region *isaio = ppc460_hose->regions+0;
+#else
+ struct pci_region *isaio = gd->ppc440_hose->regions+0;
+#endif
+
+ //extern int pciauto_region_allocate(struct pci_region* res,
+ // unsigned int size, unsigned int *bar);
+
+ /* Get the size of the VGA expansion rom */
+
+#if defined(CONFIG_SAM440EP)
+ if(PCI_BUS(dev) == 0 && PCI_DEV(dev) == 0xc)
+ {
+ foundmini = 1;
+ rom_size = 64*1024;
+ PRINTF("FOUNDMINI\n");
+ }
+ else
+#endif
+ {
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
+ pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
+ if ((rom_size & 0x01) == 0)
+ {
+ PRINTF("No ROM\n");
+ return 0;
+ }
+ else
+ {
+ rom_size &= 0xFFFFF800;
+ rom_size = (~rom_size)+1;
+ }
+ }
+
+ PRINTF("ROM Size is %dK\n", rom_size/1024);
+
+ /*
+ * Try to find a place for the ROM. We always attempt to use
+ * one of the card's bases for this, as this will be in any
+ * bridge's resource range as well as being free of conflicts
+ * with other cards. In a graphics card it is very unlikely
+ * that there won't be any base address that is large enough to
+ * hold the rom.
+ *
+ * FIXME: To work around this, theoretically the largest base
+ * could be used if none is found in the loop below.
+ */
+#ifdef CONFIG_SAM460EX
+ int found_mem64 = 0;
+ u32 tmp, bar_response = 0;
+
+ //pci_write_config_dword (dev, PCI_BASE_ADDRESS_0, 0xffffffff);
+ //pci_read_config_dword (dev, PCI_BASE_ADDRESS_0, &bar_response);
+
+ bar_response = get_bar_size(dev, PCI_BASE_ADDRESS_0);
+
+ if (!bar_response) return 0;
+
+ if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64)
+ {
+ u32 bar_response_upper;
+ u64 bar64;
+
+ bar_response_upper = get_bar_size(dev, PCI_BASE_ADDRESS_0 + 4);
+ bar64 = ((u64)bar_response_upper << 32) | bar_response;
+
+ bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
+ found_mem64 = 1;
+ PRINTF("bar_size = %08x-%08x\n", bar_response_upper, bar_response);
+ rom_address = bar_response;
+ } else
+ {
+ bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
+ PRINTF("bar_size = %08x\n", bar_size);
+
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &rom_address);
+ rom_address &= 0xFFFFFFF0;
+ }
+
+ PRINTF("Rom is being mapped to %p\n", rom_address);
+
+ if (rom_address == 0 || rom_address == 0xFFFFFFF0)
+ {
+ PRINTF("No suitable rom address found\n");
+ return 0;
+ }
+
+ /* Disable the BAR */
+
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar_backup);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0);
+ if (found_mem64)
+ {
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+4, &tmp);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0+4, 0);
+ }
+
+ /* Map ROM */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,rom_address | PCI_ROM_ADDRESS_ENABLE);
+#else
+ for (i = PCI_BASE_ADDRESS_0; i <= PCI_BASE_ADDRESS_5; i += 4)
+ {
+ bar_size = get_bar_size(dev, i);
+ PRINTF("PCI_BASE_ADDRESS_%d is %dK large\n", (i - PCI_BASE_ADDRESS_0)/4, bar_size/1024);
+ if (bar_size != 0xFFFFFFFF && bar_size >= rom_size)
+ {
+ PRINTF("Found a match for rom size\n");
+ pci_read_config_dword(dev, i, &rom_address);
+ rom_address &= 0xFFFFFFF0;
+ if (rom_address != 0 && rom_address != 0xFFFFFFF0) break;
+ }
+ }
+
+ PRINTF("Rom is being mapped to %p\n", rom_address);
+
+ if (rom_address == 0 || rom_address == 0xFFFFFFF0)
+ {
+ PRINTF("No suitable rom address found\n");
+ return 0;
+ }
+
+ /* Disable the BAR */
+ pci_read_config_dword(dev, i, &bar_backup);
+ pci_write_config_dword(dev, i, 0);
+
+ /* Map ROM */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address | PCI_ROM_ADDRESS_ENABLE);
+
+#endif
+
+ /* Copy the rom to a place in the emulator space */
+ PRINTF("Trying to find an X86 BIOS image in ROM\n");
+
+#if defined(CONFIG_SAM440EP)
+ if (foundmini == 1)
+ {
+ load_compressed_bios(copy_address);
+ }
+ else
+#endif
+ {
+ foundimg = find_image(rom_address, rom_size, &image, &image_size);
+
+ PRINTF("find_image return %d\n", foundimg);
+ if (foundimg == 0)
+ {
+ PRINTF("No x86 BIOS image found\n");
+ return 0;
+ }
+
+ PRINTF("Copying %ld bytes from 0x%lx to 0x%lx\n", (long)image_size, (long)image, (long)copy_address);
+
+ memcpy(copy_address, rom_address, rom_size);
+// {
+// unsigned char *from = (unsigned char *)image; /* rom_address; */
+// unsigned char *to = (unsigned char *)copy_address;
+// PRINTF("----- ROM STARTS HERE -----------\n");
+// for (j=0; j<image_size /*rom_size*/; j++)
+// {
+// //PRINTF("%c", *from);
+// *to++ = *from++;
+// }
+// PRINTF("----- ROM ENDS HERE --------------\n");
+// }
+ }
+
+ PRINTF("Copy is done\n");
+
+ /* If it's an ATI card, get the values needed by the driver */
+ pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+ if ( (vendor == 0x1002) || (foundmini == 1) )
+ find_radeon_values(dev, copy_address);
+
+ clear_bat2();
+
+ /* Unmap the ROM and restore the BAR */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+ pci_write_config_dword(dev, i, bar_backup);
+
+ iobase = isaio->bus_lower;
+ PRINTF("GLUE.C IOBASE = %x\n",iobase);
+
+#ifdef DEBUG
+ PRINTF("\n\nCard Summary\n------------\n");
+ {
+ int x=0;
+ for (i = PCI_BASE_ADDRESS_0; i <= PCI_BASE_ADDRESS_5; i += 4)
+ {
+ u32 bar_size = get_real_size(dev, i);
+ u32 bar;
+
+ if (bar_size != 0xFFFFFFFF && bar_size != 0x00000000)
+ {
+ pci_read_config_dword(dev, i, &bar);
+
+ PRINTF("PCI_BASE_ADDRESS_%d: %p-%p",
+ x, bar&0xFFFFFFF0, (bar&0xFFFFFFF0)+bar_size);
+ if ((bar&PCI_BASE_ADDRESS_SPACE))
+ {
+ PRINTF(" (io)\n");
+ }
+ else
+ {
+ PRINTF("(memory");
+ if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ PRINTF(",prefetch)\n");
+ else
+ PRINTF(")\n");
+ }
+ }
+ ++x;
+ }
+ }
+#endif
+
+ return 1;
+}
+
+int find_image(u32 rom_address, u32 rom_size, void **image, u32 *image_size)
+{
+#ifdef DEBUG
+ int i = 0;
+#endif
+ unsigned char *rom = (unsigned char *)rom_address;
+
+ PRINTF("find_image:\n");
+ PRINTF("rom_address = %p\n", rom_address);
+
+ /* if (*rom != 0x55 || *(rom+1) != 0xAA) return 0; // No bios rom this is, yes. */
+#if 1
+ {
+ int j;
+ unsigned int length;
+ unsigned int data_offs = *(rom+0x18) + 256* *(rom+0x19);
+
+ PRINTF("Rom data offset at %p\n", data_offs);
+ PRINTF("Rom header: ");
+ for (j=0; j<0x16; j++)
+ {
+ PRINTF("%02x ", *(rom+j));
+ }
+ PRINTF("\n");
+ PRINTF("Image header: ");
+ for (j=0; j<0x16; j++)
+ {
+ PRINTF("%02x ", *(rom+j+data_offs));
+ }
+ PRINTF("\n");
+ length = *(rom+data_offs+0x10) + 256* *(rom+data_offs+0x11);
+ PRINTF("length: raw=%d, yields %d\n", length, length*512);
+ }
+#endif
+ for (;;)
+ {
+ unsigned int pci_data_offset = *(rom+0x18) + 256 * *(rom+0x19);
+ unsigned int pci_image_length = (*(rom+pci_data_offset+0x10) + 256 * *(rom+pci_data_offset+0x11)) * 512;
+ unsigned char pci_image_type = *(rom+pci_data_offset+0x14);
+ if (*rom != 0x55 || *(rom+1) != 0xAA)
+ {
+ PRINTF("Invalid header this is\n");
+ return 0;
+ }
+ PRINTF("Image %i: Type %d (%s)\n", i++, pci_image_type,
+ pci_image_type==0 ? "x86" :
+ pci_image_type==1 ? "OpenFirmware" :
+ "Unknown");
+ PRINTF("Image size: %d\n", pci_image_length);
+ if (pci_image_type == 0)
+ {
+ *image = rom;
+ *image_size = pci_image_length;
+ return 1;
+ }
+
+ if (*(rom+pci_data_offset+0x15) & 0x80)
+ {
+ PRINTF("LAST image encountered, no image found\n");
+ return 0;
+ }
+
+ rom += pci_image_length;
+ }
+}
+
+void show_bat_mapping(void)
+{
+}
+
+
+void remove_init_data(void)
+{
+ //invalidate_l1_data_cache();
+ dcache_disable();
+ icache_enable();
+ //l1dcache_enable();
+/*
+ char *s;
+
+ // Invalidate and disable data cache
+ invalidate_l1_data_cache();
+ l2cache_invalidate();
+ dcache_disable();
+
+ s = getenv("x86_cache");
+
+ if (!s)
+ {
+ icache_enable();
+ l1dcache_enable();
+ }
+ else if (s)
+ {
+ if (strcmp(s, "dcache")==0)
+ {
+ l1dcache_enable();
+ }
+ else if (strcmp(s, "icache") == 0)
+ {
+ icache_enable();
+ }
+ else if (strcmp(s, "on")== 0 || strcmp(s, "both") == 0)
+ {
+ l1dcache_enable();
+ icache_enable();
+ }
+ }
+
+ l2cache_disable();
+ // show_bat_mapping();
+*/
+}
+