/* * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ #include "accelerant_protos.h" #include "accelerant.h" #include #include #include #include #include #include //#define TRACE_ACCELERANT #ifdef TRACE_ACCELERANT extern "C" void _sPrintf(const char *format, ...); # define TRACE(x) _sPrintf x #else # define TRACE(x) ; #endif struct accelerant_info *gInfo; // #pragma mark - /*! This is the common accelerant_info initializer. It is called by both, the first accelerant and all clones. */ static status_t init_common(int device, bool isClone) { // initialize global accelerant info structure gInfo = (accelerant_info *)malloc(sizeof(accelerant_info)); MemoryDeleter infoDeleter(gInfo); if (gInfo == NULL) return B_NO_MEMORY; memset(gInfo, 0, sizeof(accelerant_info)); gInfo->is_clone = isClone; gInfo->device = device; gInfo->current_mode = UINT16_MAX; // get basic info from driver area_id sharedArea; if (ioctl(device, VESA_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) != 0) return B_ERROR; AreaDeleter sharedDeleter(clone_area("vesa shared info", (void **)&gInfo->shared_info, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, sharedArea)); status_t status = gInfo->shared_info_area = sharedDeleter.Get(); if (status < B_OK) return status; gInfo->vesa_modes = (vesa_mode *)((uint8 *)gInfo->shared_info + gInfo->shared_info->vesa_mode_offset); infoDeleter.Detach(); sharedDeleter.Detach(); return B_OK; } /*! Cleans up everything done by a successful init_common(). */ static void uninit_common(void) { delete_area(gInfo->shared_info_area); gInfo->shared_info_area = -1; gInfo->shared_info = NULL; // close the file handle ONLY if we're the clone // (this is what Be tells us ;) if (gInfo->is_clone) close(gInfo->device); free(gInfo); } // #pragma mark - public accelerant functions /*! Init primary accelerant */ status_t vesa_init_accelerant(int device) { TRACE(("vesa_init_accelerant()\n")); status_t status = init_common(device, false); if (status != B_OK) return status; status = create_mode_list(); if (status != B_OK) { uninit_common(); return status; } // Initialize current mode completely from the mode list vesa_propose_display_mode(&gInfo->shared_info->current_mode, NULL, NULL); return B_OK; } ssize_t vesa_accelerant_clone_info_size(void) { // clone info is device name, so return its maximum size return B_PATH_NAME_LENGTH; } void vesa_get_accelerant_clone_info(void *info) { ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH); } status_t vesa_clone_accelerant(void *info) { TRACE(("vesa_clone_accelerant()\n")); // create full device name char path[MAXPATHLEN]; strcpy(path, "/dev/"); strcat(path, (const char *)info); int fd = open(path, B_READ_WRITE); if (fd < 0) return errno; status_t status = init_common(fd, true); if (status != B_OK) goto err1; // get read-only clone of supported display modes status = gInfo->mode_list_area = clone_area( "vesa cloned modes", (void **)&gInfo->mode_list, B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area); if (status < B_OK) goto err2; return B_OK; err2: uninit_common(); err1: close(fd); return status; } /*! This function is called for both, the primary accelerant and all of its clones. */ void vesa_uninit_accelerant(void) { TRACE(("vesa_uninit_accelerant()\n")); // delete accelerant instance data delete_area(gInfo->mode_list_area); gInfo->mode_list = NULL; uninit_common(); } status_t vesa_get_accelerant_device_info(accelerant_device_info *info) { info->version = B_ACCELERANT_VERSION; strcpy(info->name, "VESA driver"); if (gInfo->shared_info->name[0] != '\0') { strlcpy(info->chipset, gInfo->shared_info->name, 32); } else { switch (gInfo->shared_info->bios_type) { case kIntelBiosType: strcpy(info->chipset, "Intel"); break; case kNVidiaBiosType: strcpy(info->chipset, "nVidia"); break; case kAtomBiosType1: case kAtomBiosType2: strcpy(info->chipset, "AMD/ATI Atombios"); break; default: strcpy(info->chipset, "Generic VESA"); break; } } strcpy(info->serial_no, "None"); info->memory = gInfo->shared_info->vram_size; #if 0 info->dac_speed = ??? #endif return B_OK; } sem_id vesa_accelerant_retrace_semaphore() { return -1; }