/* * (C) Copyright 2009-2011 * Max Tretene, ACube Systems Srl. mtretene@acube-systems.com. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include #include "../common/vesa.h" DECLARE_GLOBAL_DATA_PTR; #undef DEBUG #ifdef DEBUG #define PRINTF(fmt,args...) printf (fmt ,##args) #else #define PRINTF(fmt,args...) #endif extern int execute_bios(pci_dev_t gr_dev, void *); u32 fb_base_phys = 0; u32 mmio_base_phys = 0; u32 io_base_phys = 0; int onbus = -1; struct FrameBufferInfo *fbi = NULL; pci_dev_t pci_find_radeon(struct pci_controller *ppc460_hose) { struct pci_controller * hose; u16 vendor; u8 header_type; pci_dev_t bdf; int bus, found_multi = 0; static struct pci_device_id id; id.vendor = PCI_VENDOR_ID_ATI; for (hose = ppc460_hose; hose; hose = hose->next) { for (bus = 0; bus <= hose->last_busno; bus++) { PRINTF("pci_find_radeon %d\n",bus); for (bdf = PCI_BDF(bus,0,0); bdf < PCI_BDF(bus+1,0,0); bdf += PCI_BDF(0,0,1)) { if (!PCI_FUNC(bdf)) { pci_read_config_byte(bdf, PCI_HEADER_TYPE, &header_type); found_multi = header_type & 0x80; } else { if (!found_multi) continue; } pci_read_config_word(bdf, PCI_VENDOR_ID, &vendor); if (vendor == id.vendor) { onbus = bus; return bdf; } } } } return (-1); } int init_radeon(struct pci_controller *hose) { int jj; unsigned char agp_control; unsigned short cmd, devcmd; pci_dev_t dev = ~0; pci_dev_t bridge = ~0; puts("VGA: "); dev = pci_find_radeon(hose); if (dev != -1) { PRINTF("RADEON found on %02x:%02x:%02x\n", PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev)); // ---------------------------------------------------------- PRINTF("Shutting down graphics card at %x.%x.%x\n", PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev)); // Graphics card... pci_read_config_word(dev, PCI_COMMAND, &cmd); devcmd = cmd; cmd &= ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY); pci_write_config_word(dev, PCI_COMMAND, cmd); PRINTF(" CMD register now %X\n", cmd); // ---------------------------------------------------------- //bridge = pci_find_bridge_for_bus(hose, PCI_BUS(dev)); bridge = PCI_BDF(0,0,0); PRINTF("Behind bridge (%d) at %02x:%02x:%02x\n", bridge, PCI_BUS(bridge), PCI_DEV(bridge), PCI_FUNC(bridge)); pci_read_config_byte(bridge, 0x3E, &agp_control); agp_control |= 0x18; pci_write_config_byte(bridge, 0x3E, agp_control); // ---------------------------------------------------------- PRINTF("Re-enabling %x.%x.%x\n", PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev)); pci_write_config_word(dev, PCI_COMMAND, devcmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY); // ---------------------------------------------------------- #ifdef DEBUG2 PRINTF("\nCard Summary\n------------\n"); { int bar, found_mem64; unsigned int bar_response; unsigned int io, mem; pci_addr_t bar_value; pci_size_t bar_size; for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_5; bar += 4) { pci_write_config_dword (dev, bar, 0xffffffff); pci_read_config_dword (dev, bar, &bar_response); if (!bar_response) continue; found_mem64 = 0; io = 0; mem = 0; /* Check the BAR type and set our address mask */ if (bar_response & PCI_BASE_ADDRESS_SPACE) { bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1; /* round up region base address to a multiple of size */ io = 1; //((io - 1) | (bar_size - 1)) + 1; //bar_value = io; /* compute new region base address */ //io = io + bar_size; } else { if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) { u32 bar_response_upper; u64 bar64; pci_write_config_dword(dev, bar+4, 0xffffffff); pci_read_config_dword(dev, bar+4, &bar_response_upper); bar64 = ((u64)bar_response_upper << 32) | bar_response; bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; found_mem64 = 1; } else { bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); } /* round up region base address to multiple of size */ mem = 1; //((mem - 1) | (bar_size - 1)) + 1; //bar_value = mem; /* compute new region base address */ //mem = mem + bar_size; } u32 low, high; low = bar_size & 0xffffffff; if (found_mem64) high = (bar_size >> 32) & 0xffffffff; else high = 0; PRINTF("bar_size = %08x%08x, io = %x, mem = %x mem64 = %x\n", high, low, io, mem, found_mem64); if (found_mem64) bar += 4; } } #endif pci_read_config_dword(dev, PCI_BASE_ADDRESS_2, &mmio_base_phys); mmio_base_phys &= ~0x0F; PRINTF("mmio_base_phys = %08x\n",mmio_base_phys); /* here we assume that a Radeon is on bus 0 (PCI) */ /* and a RadeonHD is on bus 1 or higher (PCI or PCI-E) */ if (onbus == 0) pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, &io_base_phys); else pci_read_config_dword(dev, PCI_BASE_ADDRESS_4, &io_base_phys); io_base_phys &= ~0x0F; PRINTF("io_base = %08x\n",io_base_phys); pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &fb_base_phys); fb_base_phys &= ~0x0F; PRINTF("fb_base = %08x\n",fb_base_phys); PRINTF("executing bios onbus=%d\n",onbus); if (execute_bios(dev, TEXT_BASE)) { puts("1\n"); u32 *tmp = fb_base_phys; jj = (640 * 480) / 4; while (jj--) *tmp++ = 0; puts("VESA: "); // 257 = 640 x 480 - 8 bit // 259 = 800 x 600 - 8 bit fbi = set_vesa_mode(257); if (fbi) { puts("OK\n"); // fixme: there is a problem with some radeon cards // the fbi structure isn't filled with the required // information, here we fill it in such case PRINTF("%08x %d %d %d %d\n",fbi->BaseAddress, fbi->XSize, fbi->YSize, fbi->BitsPerPixel, fbi->Modulo); if (fbi->BaseAddress != fb_base_phys) { fbi->BaseAddress = fb_base_phys; fbi->XSize = 640; fbi->YSize = 480; fbi->BitsPerPixel = 8; fbi->Modulo = 640; PRINTF("%08x %d %d %d %d\n",fbi->BaseAddress, fbi->XSize, fbi->YSize, fbi->BitsPerPixel, fbi->Modulo); } drv_video_init(); } else puts("ERROR\n"); return 1; } else puts("ERROR EXECUTING BIOS\n"); } else puts("NO CARDS\n"); return 0; }