/*
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* Clemens Zeidler, haiku@clemens-zeidler.de
* Fredrik Holmqvis, fredrik.holmqvist@gmail.com
* Alexander von Gluck, kallisti5@unixzen.com
*/
#include "radeon_hd.h"
#include "sensors.h"
#include "AreaKeeper.h"
#include "driver.h"
#include "utility.h"
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <boot_item.h>
#include <driver_settings.h>
#include <util/kernel_cpp.h>
#include <vm/vm.h>
#define TRACE_DEVICE
#ifdef TRACE_DEVICE
# define TRACE(x...) dprintf("radeon_hd: " x)
#else
# define TRACE(x) ;
#endif
#define ERROR(x...) dprintf("radeon_hd: " x)
// #pragma mark -
status_t
mapAtomBIOS(radeon_info &info, uint32 romBase, uint32 romSize)
{
TRACE("%s: seeking AtomBIOS @ 0x%" B_PRIX32 " [size: 0x%" B_PRIX32 "]\n",
__func__, romBase, romSize);
uint8* rom;
// attempt to access area specified
area_id testArea = map_physical_memory("radeon hd rom probe",
romBase, romSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA,
(void**)&rom);
if (testArea < 0) {
ERROR("%s: couldn't map potential rom @ 0x%" B_PRIX32
"\n", __func__, romBase);
return B_NO_MEMORY;
}
// check for valid BIOS signature
if (rom[0] != 0x55 || rom[1] != 0xAA) {
uint16 id = rom[0] + (rom[1] << 8);
TRACE("%s: BIOS signature incorrect @ 0x%" B_PRIX32 " (%X)\n",
__func__, romBase, id);
delete_area(testArea);
return B_ERROR;
}
// see if valid AtomBIOS rom
uint16 romHeader = RADEON_BIOS16(rom, 0x48);
bool romValid = !memcmp(&rom[romHeader + 4], "ATOM", 4)
|| !memcmp(&rom[romHeader + 4], "MOTA", 4);
if (romValid == false) {
// FAIL : a PCI VGA bios but not AtomBIOS
uint16 id = rom[0] + (rom[1] << 8);
TRACE("%s: not AtomBIOS rom at 0x%" B_PRIX32 "(%X)\n",
__func__, romBase, id);
delete_area(testArea);
return B_ERROR;
}
info.rom_area = create_area("radeon hd AtomBIOS",
(void**)&info.atom_buffer, B_ANY_KERNEL_ADDRESS,
romSize, B_NO_LOCK,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
if (info.rom_area < 0) {
ERROR("%s: unable to map kernel AtomBIOS space!\n",
__func__);
delete_area(testArea);
return B_NO_MEMORY;
}
memset((void*)info.atom_buffer, 0, romSize);
// Prevent unknown code execution by AtomBIOS parser
memcpy(info.atom_buffer, (void*)rom, romSize);
// Copy AtomBIOS to kernel area
// validate copied rom is valid
romHeader = RADEON_BIOS16(info.atom_buffer, 0x48);
romValid = !memcmp(&info.atom_buffer[romHeader + 4], "ATOM", 4)
|| !memcmp(&info.atom_buffer[romHeader + 4], "MOTA", 4);
if (romValid == true) {
set_area_protection(info.rom_area,
B_KERNEL_READ_AREA | B_USER_CLONEABLE_AREA);
ERROR("%s: AtomBIOS verified and locked\n", __func__);
} else
ERROR("%s: AtomBIOS memcpy failed!\n", __func__);
delete_area(testArea);
return romValid ? B_OK : B_ERROR;
}
static status_t
radeon_hd_getbios(radeon_info &info)
{
TRACE("card(%ld): %s: called\n", info.id, __func__);
uint32 romBase = 0;
uint32 romSize = 0;
uint32 romMethod = 0;
status_t mapResult = B_ERROR;
// first we try to find the AtomBIOS rom via various methods
for (romMethod = 0; romMethod < 3; romMethod++) {
switch(romMethod) {
case 0:
// TODO: *** New ACPI method
ERROR("%s: ACPI ATRM AtomBIOS TODO\n", __func__);
break;
case 1:
// *** Discreet card on IGP, check PCI BAR 0
// On post, the bios puts a copy of the IGP
// AtomBIOS at the start of the video ram
romBase = info.pci->u.h0.base_registers[PCI_BAR_FB];
romSize = 256 * 1024;
if (romBase == 0 || romSize == 0) {
ERROR("%s: No base found at PCI FB BAR\n", __func__);
} else {
mapResult = mapAtomBIOS(info, romBase, romSize);
}
break;
case 2:
{
// *** PCI ROM BAR
// Enable ROM decoding for PCI BAR rom
uint32 pciConfig = get_pci_config(info.pci, PCI_rom_base, 4);
pciConfig |= PCI_rom_enable;
set_pci_config(info.pci, PCI_rom_base, 4, pciConfig);
uint32 flags = get_pci_config(info.pci, PCI_rom_base, 4);
if ((flags & PCI_rom_enable) != 0)
TRACE("%s: PCI ROM decode enabled\n", __func__);
romBase = info.pci->u.h0.rom_base;
romSize = info.pci->u.h0.rom_size;
if (romBase == 0 || romSize == 0) {
ERROR("%s: No base found at PCI ROM BAR\n", __func__);
} else {
mapResult = mapAtomBIOS(info, romBase, romSize);
}
// Disable ROM decoding
pciConfig &= ~PCI_rom_enable;
set_pci_config(info.pci, PCI_rom_base, 4, pciConfig);
break;
}
}
if (mapResult == B_OK) {
ERROR("%s: AtomBIOS found using active method %" B_PRIu32
" at 0x%" B_PRIX32 "\n", __func__, romMethod, romBase);
break;
} else {
ERROR("%s: AtomBIOS not found using active method %" B_PRIu32
" at 0x%" B_PRIX32 "\n", __func__, romMethod, romBase);
}
}
if (mapResult == B_OK) {
info.shared_info->rom_phys = romBase;
info.shared_info->rom_size = romSize;
} else
ERROR("%s: Active AtomBIOS search failed.\n", __func__);
return mapResult;
}
static status_t
radeon_hd_getbios_ni(radeon_info &info)
{
TRACE("card(%ld): %s: called\n", info.id, __func__);
uint32 bus_cntl = read32(info.registers + R600_BUS_CNTL);
uint32 d1vga_control = read32(info.registers + AVIVO_D1VGA_CONTROL);
uint32 d2vga_control = read32(info.registers + AVIVO_D2VGA_CONTROL);
uint32 vga_render_control
= read32(info.registers + AVIVO_VGA_RENDER_CONTROL);
uint32 rom_cntl = read32(info.registers + R600_ROM_CNTL);
// enable the rom
write32(info.registers + R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
// disable VGA mode
write32(info.registers + AVIVO_D1VGA_CONTROL, (d1vga_control
& ~(AVIVO_DVGA_CONTROL_MODE_ENABLE
| AVIVO_DVGA_CONTROL_TIMING_SELECT)));
write32(info.registers + AVIVO_D2VGA_CONTROL, (d2vga_control
& ~(AVIVO_DVGA_CONTROL_MODE_ENABLE
| AVIVO_DVGA_CONTROL_TIMING_SELECT)));
write32(info.registers + AVIVO_VGA_RENDER_CONTROL,
(vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
write32(info.registers + R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE));
// try to grab the bios via PCI ROM bar
// Enable ROM decoding for PCI BAR rom
uint32 pciConfig = get_pci_config(info.pci, PCI_rom_base, 4);
pciConfig |= PCI_rom_enable;
set_pci_config(info.pci, PCI_rom_base, 4, pciConfig);
uint32 flags = get_pci_config(info.pci, PCI_rom_base, 4);
if (flags & PCI_rom_enable)
TRACE("%s: PCI ROM decode enabled\n", __func__);
uint32 romBase = info.pci->u.h0.rom_base;
uint32 romSize = info.pci->u.h0.rom_size;
status_t result = B_OK;
if (romBase == 0 || romSize == 0) {
ERROR("%s: No AtomBIOS location found at PCI ROM BAR\n", __func__);
result = B_ERROR;
} else {
result = mapAtomBIOS(info, romBase, romSize);
}
if (result == B_OK) {
ERROR("%s: AtomBIOS found using disabled method at 0x%" B_PRIX32
" [size: 0x%" B_PRIX32 "]\n", __func__, romBase, romSize);
info.shared_info->rom_phys = romBase;
info.shared_info->rom_size = romSize;
}
// Disable ROM decoding
pciConfig &= ~PCI_rom_enable;
set_pci_config(info.pci, PCI_rom_base, 4, pciConfig);
// restore regs
write32(info.registers + R600_BUS_CNTL, bus_cntl);
write32(info.registers + AVIVO_D1VGA_CONTROL, d1vga_control);
write32(info.registers + AVIVO_D2VGA_CONTROL, d2vga_control);
write32(info.registers + AVIVO_VGA_RENDER_CONTROL, vga_render_control);
write32(info.registers + R600_ROM_CNTL, rom_cntl);
return result;
}
static status_t
radeon_hd_getbios_r700(radeon_info &info)
{
TRACE("card(%ld): %s: called\n", info.id, __func__);
uint32 viph_control = read32(info.registers + RADEON_VIPH_CONTROL);
uint32 bus_cntl = read32(info.registers + R600_BUS_CNTL);
uint32 d1vga_control = read32(info.registers + AVIVO_D1VGA_CONTROL);
uint32 d2vga_control = read32(info.registers + AVIVO_D2VGA_CONTROL);
uint32 vga_render_control
= read32(info.registers + AVIVO_VGA_RENDER_CONTROL);
uint32 rom_cntl = read32(info.registers + R600_ROM_CNTL);
// disable VIP
write32(info.registers + RADEON_VIPH_CONTROL,
(viph_control & ~RADEON_VIPH_EN));
// enable the rom
write32(info.registers + R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
// disable VGA mode
write32(info.registers + AVIVO_D1VGA_CONTROL, (d1vga_control
& ~(AVIVO_DVGA_CONTROL_MODE_ENABLE
| AVIVO_DVGA_CONTROL_TIMING_SELECT)));
write32(info.registers + AVIVO_D2VGA_CONTROL, (d2vga_control
& ~(AVIVO_DVGA_CONTROL_MODE_ENABLE
| AVIVO_DVGA_CONTROL_TIMING_SELECT)));
write32(info.registers + AVIVO_VGA_RENDER_CONTROL,
(vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
write32(info.registers + R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE));
// try to grab the bios via PCI ROM bar
// Enable ROM decoding for PCI BAR rom
uint32 pciConfig = get_pci_config(info.pci, PCI_rom_base, 4);
pciConfig |= PCI_rom_enable;
set_pci_config(info.pci, PCI_rom_base, 4, pciConfig);
uint32 flags = get_pci_config(info.pci, PCI_rom_base, 4);
if (flags & PCI_rom_enable)
TRACE("%s: PCI ROM decode enabled\n", __func__);
uint32 romBase = info.pci->u.h0.rom_base;
uint32 romSize = info.pci->u.h0.rom_size;
status_t result = B_OK;
if (romBase == 0 || romSize == 0) {
ERROR("%s: No AtomBIOS location found at PCI ROM BAR\n", __func__);
result = B_ERROR;
} else {
result = mapAtomBIOS(info, romBase, romSize);
}
if (result == B_OK) {
ERROR("%s: AtomBIOS found using disabled method at 0x%" B_PRIX32
" [size: 0x%" B_PRIX32 "]\n", __func__, romBase, romSize);
info.shared_info->rom_phys = romBase;
info.shared_info->rom_size = romSize;
}
// Disable ROM decoding
pciConfig &= ~PCI_rom_enable;
set_pci_config(info.pci, PCI_rom_base, 4, pciConfig);
// restore regs
write32(info.registers + RADEON_VIPH_CONTROL, viph_control);
write32(info.registers + R600_BUS_CNTL, bus_cntl);
write32(info.registers + AVIVO_D1VGA_CONTROL, d1vga_control);
write32(info.registers + AVIVO_D2VGA_CONTROL, d2vga_control);
write32(info.registers + AVIVO_VGA_RENDER_CONTROL, vga_render_control);
write32(info.registers + R600_ROM_CNTL, rom_cntl);
return result;
}
static status_t
radeon_hd_getbios_r600(radeon_info &info)
{
TRACE("card(%ld): %s: called\n", info.id, __func__);
uint32 viph_control = read32(info.registers + RADEON_VIPH_CONTROL);
uint32 bus_cntl = read32(info.registers + R600_BUS_CNTL);
uint32 d1vga_control = read32(info.registers + AVIVO_D1VGA_CONTROL);
uint32 d2vga_control = read32(info.registers + AVIVO_D2VGA_CONTROL);
uint32 vga_render_control
= read32(info.registers + AVIVO_VGA_RENDER_CONTROL);
uint32 rom_cntl = read32(info.registers + R600_ROM_CNTL);
uint32 general_pwrmgt = read32(info.registers + R600_GENERAL_PWRMGT);
uint32 low_vid_lower_gpio_cntl
= read32(info.registers + R600_LOW_VID_LOWER_GPIO_CNTL);
uint32 medium_vid_lower_gpio_cntl
= read32(info.registers + R600_MEDIUM_VID_LOWER_GPIO_CNTL);
uint32 high_vid_lower_gpio_cntl
= read32(info.registers + R600_HIGH_VID_LOWER_GPIO_CNTL);
uint32 ctxsw_vid_lower_gpio_cntl
= read32(info.registers + R600_CTXSW_VID_LOWER_GPIO_CNTL);
uint32 lower_gpio_enable
= read32(info.registers + R600_LOWER_GPIO_ENABLE);
// disable VIP
write32(info.registers + RADEON_VIPH_CONTROL,
(viph_control & ~RADEON_VIPH_EN));
// enable the rom
write32(info.registers + R600_BUS_CNTL, (bus_cntl & ~R600_BIOS_ROM_DIS));
// disable VGA mode
write32(info.registers + AVIVO_D1VGA_CONTROL, (d1vga_control
& ~(AVIVO_DVGA_CONTROL_MODE_ENABLE
| AVIVO_DVGA_CONTROL_TIMING_SELECT)));
write32(info.registers + AVIVO_D2VGA_CONTROL, (d2vga_control
& ~(AVIVO_DVGA_CONTROL_MODE_ENABLE
| AVIVO_DVGA_CONTROL_TIMING_SELECT)));
write32(info.registers + AVIVO_VGA_RENDER_CONTROL,
(vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
write32(info.registers + R600_ROM_CNTL,
((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK)
| (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | R600_SCK_OVERWRITE));
write32(info.registers + R600_GENERAL_PWRMGT,
(general_pwrmgt & ~R600_OPEN_DRAIN_PADS));
write32(info.registers + R600_LOW_VID_LOWER_GPIO_CNTL,
(low_vid_lower_gpio_cntl & ~0x400));
write32(info.registers + R600_MEDIUM_VID_LOWER_GPIO_CNTL,
(medium_vid_lower_gpio_cntl & ~0x400));
write32(info.registers + R600_HIGH_VID_LOWER_GPIO_CNTL,
(high_vid_lower_gpio_cntl & ~0x400));
write32(info.registers + R600_CTXSW_VID_LOWER_GPIO_CNTL,
(ctxsw_vid_lower_gpio_cntl & ~0x400));
write32(info.registers + R600_LOWER_GPIO_ENABLE,
(lower_gpio_enable | 0x400));
// try to grab the bios via PCI ROM bar
// Enable ROM decoding for PCI BAR rom
uint32 pciConfig = get_pci_config(info.pci, PCI_rom_base, 4);
pciConfig |= PCI_rom_enable;
set_pci_config(info.pci, PCI_rom_base, 4, pciConfig);
uint32 flags = get_pci_config(info.pci, PCI_rom_base, 4);
if (flags & PCI_rom_enable)
TRACE("%s: PCI ROM decode enabled\n", __func__);
uint32 romBase = info.pci->u.h0.rom_base;
uint32 romSize = info.pci->u.h0.rom_size;
status_t result = B_OK;
if (romBase == 0 || romSize == 0) {
ERROR("%s: No AtomBIOS location found at PCI ROM BAR\n", __func__);
result = B_ERROR;
} else {
result = mapAtomBIOS(info, romBase, romSize);
}
if (result == B_OK) {
ERROR("%s: AtomBIOS found using disabled method at 0x%" B_PRIX32
" [size: 0x%" B_PRIX32 "]\n", __func__, romBase, romSize);
info.shared_info->rom_phys = romBase;
info.shared_info->rom_size = romSize;
}
// Disable ROM decoding
pciConfig &= ~PCI_rom_enable;
set_pci_config(info.pci, PCI_rom_base, 4, pciConfig);
// restore regs
write32(info.registers + RADEON_VIPH_CONTROL, viph_control);
write32(info.registers + R600_BUS_CNTL, bus_cntl);
write32(info.registers + AVIVO_D1VGA_CONTROL, d1vga_control);
write32(info.registers + AVIVO_D2VGA_CONTROL, d2vga_control);
write32(info.registers + AVIVO_VGA_RENDER_CONTROL, vga_render_control);
write32(info.registers + R600_ROM_CNTL, rom_cntl);
write32(info.registers + R600_GENERAL_PWRMGT, general_pwrmgt);
write32(info.registers + R600_LOW_VID_LOWER_GPIO_CNTL,
low_vid_lower_gpio_cntl);
write32(info.registers + R600_MEDIUM_VID_LOWER_GPIO_CNTL,
medium_vid_lower_gpio_cntl);
write32(info.registers + R600_HIGH_VID_LOWER_GPIO_CNTL,
high_vid_lower_gpio_cntl);
write32(info.registers + R600_CTXSW_VID_LOWER_GPIO_CNTL,
ctxsw_vid_lower_gpio_cntl);
write32(info.registers + R600_LOWER_GPIO_ENABLE, lower_gpio_enable);
return result;
}
static status_t
radeon_hd_getbios_avivo(radeon_info &info)
{
TRACE("card(%ld): %s: called\n", info.id, __func__);
uint32 sepromControl = read32(info.registers + RADEON_SEPROM_CNTL1);
uint32 viphControl = read32(info.registers + RADEON_VIPH_CONTROL);
uint32 busControl = read32(info.registers + RV370_BUS_CNTL);
uint32 d1vgaControl = read32(info.registers + AVIVO_D1VGA_CONTROL);
uint32 d2vgaControl = read32(info.registers + AVIVO_D2VGA_CONTROL);
uint32 vgaRenderControl
= read32(info.registers + AVIVO_VGA_RENDER_CONTROL);
uint32 gpioPadA = read32(info.registers + RADEON_GPIOPAD_A);
uint32 gpioPadEN = read32(info.registers + RADEON_GPIOPAD_EN);
uint32 gpioPadMask = read32(info.registers + RADEON_GPIOPAD_MASK);
write32(info.registers + RADEON_SEPROM_CNTL1,
((sepromControl & ~RADEON_SCK_PRESCALE_MASK)
| (0xc << RADEON_SCK_PRESCALE_SHIFT)));
write32(info.registers + RADEON_GPIOPAD_A, 0);
write32(info.registers + RADEON_GPIOPAD_EN, 0);
write32(info.registers + RADEON_GPIOPAD_MASK, 0);
// disable VIP
write32(info.registers + RADEON_VIPH_CONTROL,
(viphControl & ~RADEON_VIPH_EN));
// enable the ROM
write32(info.registers + RV370_BUS_CNTL,
(busControl & ~RV370_BUS_BIOS_DIS_ROM));
// disable VGA
write32(info.registers + AVIVO_D1VGA_CONTROL,
(d1vgaControl & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE
| AVIVO_DVGA_CONTROL_TIMING_SELECT)));
write32(info.registers + AVIVO_D2VGA_CONTROL,
(d2vgaControl & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE
| AVIVO_DVGA_CONTROL_TIMING_SELECT)));
write32(info.registers + AVIVO_VGA_RENDER_CONTROL,
(vgaRenderControl & ~AVIVO_VGA_VSTATUS_CNTL_MASK));
uint32 romBase = info.pci->u.h0.rom_base;
uint32 romSize = info.pci->u.h0.rom_size;
status_t result = B_OK;
if (romBase == 0 || romSize == 0) {
ERROR("%s: No AtomBIOS location found at PCI ROM BAR\n", __func__);
result = B_ERROR;
} else {
result = mapAtomBIOS(info, romBase, romSize);
}
if (result == B_OK) {
ERROR("%s: AtomBIOS found using disabled method at 0x%" B_PRIX32
" [size: 0x%" B_PRIX32 "]\n", __func__, romBase, romSize);
info.shared_info->rom_phys = romBase;
info.shared_info->rom_size = romSize;
}
// restore registers
write32(info.registers + RADEON_SEPROM_CNTL1, sepromControl);
write32(info.registers + RADEON_VIPH_CONTROL, viphControl);
write32(info.registers + RV370_BUS_CNTL, busControl);
write32(info.registers + AVIVO_D1VGA_CONTROL, d1vgaControl);
write32(info.registers + AVIVO_D2VGA_CONTROL, d2vgaControl);
write32(info.registers + AVIVO_VGA_RENDER_CONTROL, vgaRenderControl);
write32(info.registers + RADEON_GPIOPAD_A, gpioPadA);
write32(info.registers + RADEON_GPIOPAD_EN, gpioPadEN);
write32(info.registers + RADEON_GPIOPAD_MASK, gpioPadMask);
return result;
}
static uint32
radeon_hd_pci_bar_mmio(uint16 chipsetID)
{
if (chipsetID < RADEON_BONAIRE)
return 2;
else
return 5;
}
status_t
radeon_hd_init(radeon_info &info)
{
TRACE("card(%ld): %s: called\n", info.id, __func__);
ERROR("%s: card(%ld): "
"Radeon %s 1002:%" B_PRIX32 "\n", __func__, info.id,
radeon_chip_name[info.chipsetID], info.pciID);
// *** Map shared info
AreaKeeper sharedCreator;
info.shared_area = sharedCreator.Create("radeon hd shared info",
(void**)&info.shared_info, B_ANY_KERNEL_ADDRESS,
ROUND_TO_PAGE_SIZE(sizeof(radeon_shared_info)), B_FULL_LOCK,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
if (info.shared_area < B_OK) {
ERROR("%s: card (%ld): couldn't map shared area!\n",
__func__, info.id);
return info.shared_area;
}
memset((void*)info.shared_info, 0, sizeof(radeon_shared_info));
sharedCreator.Detach();
// *** Map Memory mapped IO
AreaKeeper mmioMapper;
const uint32 pciBarMmio = radeon_hd_pci_bar_mmio(info.chipsetID);
info.registers_area = mmioMapper.Map("radeon hd mmio",
info.pci->u.h0.base_registers[pciBarMmio],
info.pci->u.h0.base_register_sizes[pciBarMmio],
B_ANY_KERNEL_ADDRESS,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA,
(void**)&info.registers);
if (mmioMapper.InitCheck() < B_OK) {
ERROR("%s: card (%ld): couldn't map memory I/O!\n",
__func__, info.id);
return info.registers_area;
}
mmioMapper.Detach();
// *** Populate frame buffer information
if (info.chipsetID >= RADEON_CEDAR) {
if ((info.chipsetFlags & CHIP_APU) != 0
|| (info.chipsetFlags & CHIP_IGP) != 0) {
// Evergreen+ fusion in bytes
info.shared_info->graphics_memory_size
= read32(info.registers + CONFIG_MEMSIZE) / 1024;
} else {
// Evergreen+ has memory stored in MB
info.shared_info->graphics_memory_size
= read32(info.registers + CONFIG_MEMSIZE) * 1024;
}
} else if (info.chipsetID >= RADEON_R600) {
// R600-R700 has memory stored in bytes
info.shared_info->graphics_memory_size
= read32(info.registers + CONFIG_MEMSIZE) / 1024;
} else {
// R420 - R600 cards
// older cards use RADEON_CONFIG_MEMSIZE vs CONFIG_MEMSIZE
if ((info.chipsetFlags & CHIP_IGP) != 0) {
// NB_TOM holds amount of ram stolen for GPU
uint32 tom = read32(info.registers + RADEON_NB_TOM);
info.shared_info->graphics_memory_size
= (((tom >> 16) - (tom & 0xffff) + 1) << 16);
write32(info.registers + RADEON_CONFIG_MEMSIZE,
info.shared_info->graphics_memory_size);
} else {
info.shared_info->graphics_memory_size
= read32(info.registers + RADEON_CONFIG_MEMSIZE);
if (info.shared_info->graphics_memory_size == 0) {
// known bug if video memory == 8MB
info.shared_info->graphics_memory_size = 8192;
write32(info.registers + RADEON_CONFIG_MEMSIZE,
info.shared_info->graphics_memory_size * 1024);
}
}
}
uint32 barSize = info.pci->u.h0.base_register_sizes[PCI_BAR_FB] / 1024;
// if graphics memory is larger then PCI bar, just map bar
if (info.shared_info->graphics_memory_size == 0) {
// we can recover as we have PCI FB bar, but this should be fixed
ERROR("%s: Error: found 0MB video ram, using PCI bar size...\n",
__func__);
info.shared_info->frame_buffer_size = barSize;
} else if (info.shared_info->graphics_memory_size > barSize) {
TRACE("%s: shrinking frame buffer to PCI bar...\n",
__func__);
info.shared_info->frame_buffer_size = barSize;
} else {
info.shared_info->frame_buffer_size
= info.shared_info->graphics_memory_size;
}
TRACE("%s: mapping a frame buffer of %" B_PRIu32 "MB out of %" B_PRIu32
"MB video ram\n", __func__, info.shared_info->frame_buffer_size / 1024,
info.shared_info->graphics_memory_size / 1024);
// *** Framebuffer mapping
AreaKeeper frambufferMapper;
info.framebuffer_area = frambufferMapper.Map("radeon hd frame buffer",
info.pci->u.h0.base_registers[PCI_BAR_FB],
info.shared_info->frame_buffer_size * 1024,
B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA,
(void**)&info.shared_info->frame_buffer);
if (frambufferMapper.InitCheck() < B_OK) {
ERROR("%s: card(%ld): couldn't map frame buffer!\n",
__func__, info.id);
return info.framebuffer_area;
}
// Turn on write combining for the frame buffer area
vm_set_area_memory_type(info.framebuffer_area,
info.pci->u.h0.base_registers[PCI_BAR_FB], B_MTR_WC);
frambufferMapper.Detach();
info.shared_info->frame_buffer_area = info.framebuffer_area;
info.shared_info->frame_buffer_phys
= info.pci->u.h0.base_registers[PCI_BAR_FB];
// Pass common information to accelerant
info.shared_info->deviceIndex = info.id;
info.shared_info->pciID = info.pciID;
info.shared_info->pciRev = info.pci->revision;
info.shared_info->chipsetID = info.chipsetID;
info.shared_info->chipsetFlags = info.chipsetFlags;
info.shared_info->dceMajor = info.dceMajor;
info.shared_info->dceMinor = info.dceMinor;
info.shared_info->registers_area = info.registers_area;
strlcpy(info.shared_info->deviceName,
info.deviceName, MAX_NAME_LENGTH);
strlcpy(info.shared_info->chipsetName,
radeon_chip_name[info.chipsetID], MAX_NAME_LENGTH);
// *** AtomBIOS mapping
// First we try an active bios read
status_t biosStatus = radeon_hd_getbios(info);
if (biosStatus != B_OK) {
// If the active read fails, we try a disabled read
if (info.chipsetID >= RADEON_CAICOS)
biosStatus = radeon_hd_getbios_ni(info);
else if (info.chipsetID >= RADEON_RV770)
biosStatus = radeon_hd_getbios_r700(info);
else if (info.chipsetID >= RADEON_R600)
biosStatus = radeon_hd_getbios_r600(info);
else if (info.chipsetID >= RADEON_RS600)
biosStatus = radeon_hd_getbios_avivo(info);
// else legacy_read_disabled_bios
}
if (biosStatus != B_OK) {
// *** very last resort, shadow bios VGA rom
ERROR("%s: Can't find an AtomBIOS rom! Trying shadow rom...\n",
__func__);
// This works as long as the primary card is what this driver
// is loaded for. Multiple cards may pose the risk of loading
// the wrong AtomBIOS for the wrong card.
uint32 romBase = 0xC0000;
uint32 romSize = 128 * 1024;
// what happens when AtomBIOS goes over 128Kb?
// A Radeon HD 6990 has a 128Kb AtomBIOS
if (mapAtomBIOS(info, romBase, romSize) == B_OK) {
ERROR("%s: Found AtomBIOS at VGA shadow rom\n", __func__);
// Whew!
info.shared_info->rom_phys = romBase;
info.shared_info->rom_size = romSize;
biosStatus = B_OK;
}
}
// Check if a valid AtomBIOS image was found.
if (biosStatus != B_OK) {
ERROR("%s: card (%ld): couldn't find AtomBIOS rom!\n",
__func__, info.id);
ERROR("%s: card (%ld): exiting. Please open a bug ticket"
" at haiku-os.org with your /var/log/syslog\n",
__func__, info.id);
// Fallback to VESA (more likely crash app_server)
return B_ERROR;
}
info.shared_info->has_rom = (biosStatus == B_OK) ? true : false;
info.shared_info->rom_area = (biosStatus == B_OK) ? info.rom_area : -1;
// *** Pull active monitor VESA EDID from boot loader
edid1_info* edidInfo
= (edid1_info*)get_boot_item(EDID_BOOT_INFO, NULL);
if (edidInfo != NULL) {
TRACE("card(%ld): %s found VESA EDID information.\n", info.id,
__func__);
info.shared_info->has_edid = true;
memcpy(&info.shared_info->edid_info, edidInfo, sizeof(edid1_info));
} else {
TRACE("card(%ld): %s didn't find VESA EDID modes.\n", info.id,
__func__);
info.shared_info->has_edid = false;
}
TRACE("card(%ld): %s completed successfully!\n", info.id, __func__);
TRACE("card(%ld): GPU thermal status: %" B_PRId32 "C\n", info.id,
radeon_thermal_query(info) / 1000);
return B_OK;
}
void
radeon_hd_uninit(radeon_info &info)
{
TRACE("card(%ld): %s called\n", info.id, __func__);
delete_area(info.shared_area);
delete_area(info.registers_area);
delete_area(info.framebuffer_area);
delete_area(info.rom_area);
}
↑ V576 Incorrect format. Consider checking the third actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the third actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the third actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the third actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the third actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the third actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V547 Expression 'biosStatus == ((int) 0)' is always true.
↑ V547 Expression 'biosStatus == ((int) 0)' is always true.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'dprintf' function. The memsize type argument is expected.