extern "C" status_t init_hardware(void) { TRACE((DEVICE_NAME ": init_hardware()\n")); return get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL) != NULL ? B_OK : B_ERROR; }
static status_t InitDevice(DeviceInfo& di) { // Perform initialization and mapping of the device, and return B_OK if // sucessful; else, return error code. // Get the table of VESA modes that the chip supports. Note that we will // need this table only for chips that are currently connected to a laptop // display or a monitor connected via a DVI interface. size_t vesaModeTableSize = 0; VesaMode* vesaModes = (VesaMode*)get_boot_item(VESA_MODES_BOOT_INFO, &vesaModeTableSize); size_t sharedSize = (sizeof(SharedInfo) + 7) & ~7; // Create the area for shared info with NO user-space read or write // permissions, to prevent accidental damage. di.sharedArea = create_area("ATI shared info", (void**) &(di.sharedInfo), B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(sharedSize + vesaModeTableSize), B_FULL_LOCK, 0); if (di.sharedArea < 0) return di.sharedArea; // return error code SharedInfo& si = *(di.sharedInfo); memset(&si, 0, sharedSize); if (vesaModes != NULL) { si.vesaModeTableOffset = sharedSize; si.vesaModeCount = vesaModeTableSize / sizeof(VesaMode); memcpy((uint8*)&si + si.vesaModeTableOffset, vesaModes, vesaModeTableSize); } pci_info& pciInfo = di.pciInfo; si.vendorID = pciInfo.vendor_id; si.deviceID = pciInfo.device_id; si.revision = pciInfo.revision; si.chipType = di.pChipInfo->chipType; strcpy(si.chipName, di.pChipInfo->chipName); TRACE("Chip revision: 0x%x\n", si.revision); // 264GT has two chip versions. If version is non-zero, chip is 264GTB. if (si.chipType == MACH64_264GT && si.revision & 0x7) si.chipType = MACH64_264GTB; // 264VT has two chip versions. If version is non-zero, chip is 264VTB. if (si.chipType == MACH64_264VT && si.revision & 0x7) si.chipType = MACH64_264VTB; status_t status = MapDevice(di); // If device mapped without any error, get the bios parameters from the // chip's BIOS ROM. if (status >= 0) { if (MACH64_FAMILY(si.chipType)) { uint8 clockType; Mach64_GetBiosParameters(di, clockType); // All chips supported by this driver should have an internal clock. // If the clock is not an internal clock, the video chip is not // supported. if (clockType != M64_CLOCK_INTERNAL) { TRACE("Video chip clock type %d not supported\n", clockType); status = B_UNSUPPORTED; } } else if (RAGE128_FAMILY(si.chipType)) Rage128_GetBiosParameters(di); } if (status < 0) { delete_area(di.sharedArea); di.sharedArea = -1; di.sharedInfo = NULL; return status; // return error code } InitInterruptHandler(di); TRACE("Interrupt assigned: %s\n", si.bInterruptAssigned ? "yes" : "no"); return B_OK; }
status_t intel_extreme_init(intel_info &info) { CALLED(); info.aperture = gGART->map_aperture(info.pci->bus, info.pci->device, info.pci->function, 0, &info.aperture_base); if (info.aperture < B_OK) { ERROR("error: could not map GART aperture! (%s)\n", strerror(info.aperture)); return info.aperture; } AreaKeeper sharedCreator; info.shared_area = sharedCreator.Create("intel extreme shared info", (void**)&info.shared_info, B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(sizeof(intel_shared_info)) + 3 * B_PAGE_SIZE, B_FULL_LOCK, 0); if (info.shared_area < B_OK) { ERROR("error: could not create shared area!\n"); gGART->unmap_aperture(info.aperture); return info.shared_area; } memset((void*)info.shared_info, 0, sizeof(intel_shared_info)); int fbIndex = 0; int mmioIndex = 1; if (info.device_type.InFamily(INTEL_TYPE_9xx)) { // For some reason Intel saw the need to change the order of the // mappings with the introduction of the i9xx family mmioIndex = 0; fbIndex = 2; } // evaluate driver settings, if any bool hardwareCursor; read_settings(hardwareCursor); // memory mapped I/O // TODO: registers are mapped twice (by us and intel_gart), maybe we // can share it between the drivers AreaKeeper mmioMapper; info.registers_area = mmioMapper.Map("intel extreme mmio", info.pci->u.h0.base_registers[mmioIndex], info.pci->u.h0.base_register_sizes[mmioIndex], B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.registers); if (mmioMapper.InitCheck() < B_OK) { ERROR("error: could not map memory I/O!\n"); gGART->unmap_aperture(info.aperture); return info.registers_area; } uint32* blocks = info.shared_info->register_blocks; blocks[REGISTER_BLOCK(REGS_FLAT)] = 0; // setup the register blocks for the different architectures if (info.device_type.HasPlatformControlHub()) { // PCH based platforms (IronLake and up) blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)] = PCH_NORTH_SHARED_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] = PCH_NORTH_PIPE_AND_PORT_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] = PCH_NORTH_PLANE_CONTROL_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)] = PCH_SOUTH_SHARED_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)] = PCH_SOUTH_TRANSCODER_AND_PORT_REGISTER_BASE; } else { // (G)MCH/ICH based platforms blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)] = MCH_SHARED_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] = MCH_PIPE_AND_PORT_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] = MCH_PLANE_CONTROL_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)] = ICH_SHARED_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)] = ICH_PORT_REGISTER_BASE; } // make sure bus master, memory-mapped I/O, and frame buffer is enabled set_pci_config(info.pci, PCI_command, 2, get_pci_config(info.pci, PCI_command, 2) | PCI_command_io | PCI_command_memory | PCI_command_master); // reserve ring buffer memory (currently, this memory is placed in // the graphics memory), but this could bring us problems with // write combining... ring_buffer &primary = info.shared_info->primary_ring_buffer; if (intel_allocate_memory(info, 16 * B_PAGE_SIZE, 0, 0, (addr_t*)&primary.base) == B_OK) { primary.register_base = INTEL_PRIMARY_RING_BUFFER; primary.size = 16 * B_PAGE_SIZE; primary.offset = (addr_t)primary.base - info.aperture_base; } // Enable clock gating intel_en_gating(info); // Enable automatic gpu downclocking if we can to save power intel_en_downclock(info); // no errors, so keep areas and mappings sharedCreator.Detach(); mmioMapper.Detach(); aperture_info apertureInfo; gGART->get_aperture_info(info.aperture, &apertureInfo); info.shared_info->registers_area = info.registers_area; info.shared_info->graphics_memory = (uint8*)info.aperture_base; info.shared_info->physical_graphics_memory = apertureInfo.physical_base; info.shared_info->graphics_memory_size = apertureInfo.size; info.shared_info->frame_buffer = 0; info.shared_info->dpms_mode = B_DPMS_ON; info.shared_info->got_vbt = get_lvds_mode_from_bios( &info.shared_info->current_mode); /* at least 855gm can't drive more than one head at time */ if (info.device_type.InFamily(INTEL_TYPE_8xx)) info.shared_info->single_head_locked = 1; if (info.device_type.InFamily(INTEL_TYPE_9xx)) { info.shared_info->pll_info.reference_frequency = 96000; // 96 kHz info.shared_info->pll_info.max_frequency = 400000; // 400 MHz RAM DAC speed info.shared_info->pll_info.min_frequency = 20000; // 20 MHz } else { info.shared_info->pll_info.reference_frequency = 48000; // 48 kHz info.shared_info->pll_info.max_frequency = 350000; // 350 MHz RAM DAC speed info.shared_info->pll_info.min_frequency = 25000; // 25 MHz } info.shared_info->pll_info.divisor_register = INTEL_DISPLAY_A_PLL_DIVISOR_0; info.shared_info->device_type = info.device_type; #ifdef __HAIKU__ strlcpy(info.shared_info->device_identifier, info.device_identifier, sizeof(info.shared_info->device_identifier)); #else strcpy(info.shared_info->device_identifier, info.device_identifier); #endif // setup overlay registers status_t status = intel_allocate_memory(info, B_PAGE_SIZE, 0, intel_uses_physical_overlay(*info.shared_info) ? B_APERTURE_NEED_PHYSICAL : 0, (addr_t*)&info.overlay_registers, &info.shared_info->physical_overlay_registers); if (status == B_OK) { info.shared_info->overlay_offset = (addr_t)info.overlay_registers - info.aperture_base; init_overlay_registers(info.overlay_registers); } else { ERROR("error: could not allocate overlay memory! %s\n", strerror(status)); } // Allocate hardware status page and the cursor memory if (intel_allocate_memory(info, B_PAGE_SIZE, 0, B_APERTURE_NEED_PHYSICAL, (addr_t*)info.shared_info->status_page, &info.shared_info->physical_status_page) == B_OK) { // TODO: set status page } if (hardwareCursor) { intel_allocate_memory(info, B_PAGE_SIZE, 0, B_APERTURE_NEED_PHYSICAL, (addr_t*)&info.shared_info->cursor_memory, &info.shared_info->physical_cursor_memory); } edid1_info* edidInfo = (edid1_info*)get_boot_item(VESA_EDID_BOOT_INFO, NULL); if (edidInfo != NULL) { info.shared_info->has_vesa_edid_info = true; memcpy(&info.shared_info->vesa_edid_info, edidInfo, sizeof(edid1_info)); } init_interrupt_handler(info); TRACE("%s: completed successfully!\n", __func__); return B_OK; }
status_t vesa_init(vesa_info& info) { frame_buffer_boot_info* bufferInfo = (frame_buffer_boot_info*)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL); if (bufferInfo == NULL) return B_ERROR; info.vbe_capabilities = bufferInfo->vesa_capabilities; info.complete_frame_buffer_mapped = false; // Find out which PCI device we belong to, so that we know its frame buffer // size find_graphics_card(bufferInfo->physical_frame_buffer, info.physical_frame_buffer, info.physical_frame_buffer_size); size_t modesSize = 0; vesa_mode* modes = (vesa_mode*)get_boot_item(VESA_MODES_BOOT_INFO, &modesSize); info.modes = modes; size_t sharedSize = (sizeof(vesa_shared_info) + 7) & ~7; info.shared_area = create_area("vesa shared info", (void**)&info.shared_info, B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(sharedSize + modesSize), B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA); if (info.shared_area < 0) return info.shared_area; vesa_shared_info& sharedInfo = *info.shared_info; memset(&sharedInfo, 0, sizeof(vesa_shared_info)); if (modes != NULL) { sharedInfo.vesa_mode_offset = sharedSize; sharedInfo.vesa_mode_count = modesSize / sizeof(vesa_mode); memcpy((uint8*)&sharedInfo + sharedSize, modes, modesSize); } sharedInfo.frame_buffer_area = bufferInfo->area; remap_frame_buffer(info, bufferInfo->physical_frame_buffer, bufferInfo->width, bufferInfo->height, bufferInfo->depth, bufferInfo->bytes_per_row, true); // Does not matter if this fails - the frame buffer was already mapped // before. sharedInfo.current_mode.virtual_width = bufferInfo->width; sharedInfo.current_mode.virtual_height = bufferInfo->height; sharedInfo.current_mode.space = get_color_space_for_depth( bufferInfo->depth); edid1_info* edidInfo = (edid1_info*)get_boot_item(VESA_EDID_BOOT_INFO, NULL); if (edidInfo != NULL) { sharedInfo.has_edid = true; memcpy(&sharedInfo.edid_info, edidInfo, sizeof(edid1_info)); } vbe_get_dpms_capabilities(info.vbe_dpms_capabilities, sharedInfo.dpms_capabilities); if (bufferInfo->depth <= 8) vbe_set_bits_per_gun(info, 8); dprintf(DEVICE_NAME ": vesa_init() completed successfully!\n"); return B_OK; }