193ee2104SAxel Dörfler /* 2bfd4c59bSAxel Dörfler * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de. 393ee2104SAxel Dörfler * Distributed under the terms of the MIT License. 493ee2104SAxel Dörfler */ 593ee2104SAxel Dörfler 693ee2104SAxel Dörfler 70c6f7795SAxel Dörfler #include "device.h" 893ee2104SAxel Dörfler 993ee2104SAxel Dörfler #include <stdlib.h> 1093ee2104SAxel Dörfler #include <string.h> 1193ee2104SAxel Dörfler 126328832fSAxel Dörfler #include <Drivers.h> 136328832fSAxel Dörfler #include <graphic_driver.h> 146328832fSAxel Dörfler #include <image.h> 156328832fSAxel Dörfler #include <KernelExport.h> 166328832fSAxel Dörfler #include <OS.h> 176328832fSAxel Dörfler #include <PCI.h> 186328832fSAxel Dörfler #include <SupportDefs.h> 196328832fSAxel Dörfler 20bb693d77SAxel Dörfler #include <vesa.h> 21bb693d77SAxel Dörfler 226328832fSAxel Dörfler #include "driver.h" 236328832fSAxel Dörfler #include "utility.h" 246328832fSAxel Dörfler #include "vesa_info.h" 256328832fSAxel Dörfler #include "vesa_private.h" 266328832fSAxel Dörfler #include "vga.h" 276328832fSAxel Dörfler 2893ee2104SAxel Dörfler 2993ee2104SAxel Dörfler //#define TRACE_DEVICE 3093ee2104SAxel Dörfler #ifdef TRACE_DEVICE 3193ee2104SAxel Dörfler # define TRACE(x) dprintf x 3293ee2104SAxel Dörfler #else 3393ee2104SAxel Dörfler # define TRACE(x) ; 3493ee2104SAxel Dörfler #endif 3593ee2104SAxel Dörfler 3693ee2104SAxel Dörfler 3793ee2104SAxel Dörfler static status_t 3893ee2104SAxel Dörfler device_open(const char* name, uint32 flags, void** _cookie) 3993ee2104SAxel Dörfler { 4093ee2104SAxel Dörfler int id; 4193ee2104SAxel Dörfler 4293ee2104SAxel Dörfler // find accessed device 4393ee2104SAxel Dörfler char* thisName; 4493ee2104SAxel Dörfler 4593ee2104SAxel Dörfler // search for device name 4693ee2104SAxel Dörfler for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) { 4793ee2104SAxel Dörfler if (!strcmp(name, thisName)) 4893ee2104SAxel Dörfler break; 4993ee2104SAxel Dörfler } 50bfd4c59bSAxel Dörfler if (thisName == NULL) 51bfd4c59bSAxel Dörfler return B_BAD_VALUE; 5293ee2104SAxel Dörfler 5393ee2104SAxel Dörfler vesa_info* info = gDeviceInfo[id]; 5493ee2104SAxel Dörfler 554ea01167SAxel Dörfler mutex_lock(&gLock); 5693ee2104SAxel Dörfler 5793ee2104SAxel Dörfler status_t status = B_OK; 5893ee2104SAxel Dörfler 59*87784cafSAlexander von Gluck IV if (info->open_count == 0) { 6093ee2104SAxel Dörfler // this device has been opened for the first time, so 6193ee2104SAxel Dörfler // we allocate needed resources and initialize the structure 62e5b4782bSAxel Dörfler if (status == B_OK) 6393ee2104SAxel Dörfler status = vesa_init(*info); 64e5b4782bSAxel Dörfler if (status == B_OK) 65e5b4782bSAxel Dörfler info->id = id; 6693ee2104SAxel Dörfler } 6793ee2104SAxel Dörfler 68*87784cafSAlexander von Gluck IV if (status == B_OK) { 69*87784cafSAlexander von Gluck IV info->open_count++; 70*87784cafSAlexander von Gluck IV *_cookie = info; 71*87784cafSAlexander von Gluck IV } 72*87784cafSAlexander von Gluck IV 734ea01167SAxel Dörfler mutex_unlock(&gLock); 7493ee2104SAxel Dörfler return status; 7593ee2104SAxel Dörfler } 7693ee2104SAxel Dörfler 7793ee2104SAxel Dörfler 7893ee2104SAxel Dörfler static status_t 7993ee2104SAxel Dörfler device_close(void* cookie) 8093ee2104SAxel Dörfler { 8193ee2104SAxel Dörfler return B_OK; 8293ee2104SAxel Dörfler } 8393ee2104SAxel Dörfler 8493ee2104SAxel Dörfler 8593ee2104SAxel Dörfler static status_t 8693ee2104SAxel Dörfler device_free(void* cookie) 8793ee2104SAxel Dörfler { 8893ee2104SAxel Dörfler struct vesa_info* info = (vesa_info*)cookie; 8993ee2104SAxel Dörfler 904ea01167SAxel Dörfler mutex_lock(&gLock); 9193ee2104SAxel Dörfler 9293ee2104SAxel Dörfler if (info->open_count-- == 1) { 9393ee2104SAxel Dörfler // release info structure 9493ee2104SAxel Dörfler vesa_uninit(*info); 9593ee2104SAxel Dörfler } 9693ee2104SAxel Dörfler 974ea01167SAxel Dörfler mutex_unlock(&gLock); 9893ee2104SAxel Dörfler return B_OK; 9993ee2104SAxel Dörfler } 10093ee2104SAxel Dörfler 10193ee2104SAxel Dörfler 10293ee2104SAxel Dörfler static status_t 10393ee2104SAxel Dörfler device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength) 10493ee2104SAxel Dörfler { 10593ee2104SAxel Dörfler struct vesa_info* info = (vesa_info*)cookie; 10693ee2104SAxel Dörfler 10793ee2104SAxel Dörfler switch (msg) { 10893ee2104SAxel Dörfler case B_GET_ACCELERANT_SIGNATURE: 10993ee2104SAxel Dörfler dprintf(DEVICE_NAME ": acc: %s\n", VESA_ACCELERANT_NAME); 1106328832fSAxel Dörfler if (user_strlcpy((char*)buffer, VESA_ACCELERANT_NAME, 1116328832fSAxel Dörfler B_FILE_NAME_LENGTH) < B_OK) 1126328832fSAxel Dörfler return B_BAD_ADDRESS; 1136328832fSAxel Dörfler 11493ee2104SAxel Dörfler return B_OK; 11593ee2104SAxel Dörfler 11693ee2104SAxel Dörfler // needed to share data between kernel and accelerant 11793ee2104SAxel Dörfler case VESA_GET_PRIVATE_DATA: 11893ee2104SAxel Dörfler return user_memcpy(buffer, &info->shared_area, sizeof(area_id)); 11993ee2104SAxel Dörfler 12093ee2104SAxel Dörfler // needed for cloning 12193ee2104SAxel Dörfler case VESA_GET_DEVICE_NAME: 1226328832fSAxel Dörfler if (user_strlcpy((char*)buffer, gDeviceNames[info->id], 1236328832fSAxel Dörfler B_PATH_NAME_LENGTH) < B_OK) 12493ee2104SAxel Dörfler return B_BAD_ADDRESS; 1256328832fSAxel Dörfler 12693ee2104SAxel Dörfler return B_OK; 12793ee2104SAxel Dörfler 1289f161845SAxel Dörfler case VESA_SET_DISPLAY_MODE: 1299f161845SAxel Dörfler { 130bfd4c59bSAxel Dörfler if (bufferLength != sizeof(uint32)) 131bfd4c59bSAxel Dörfler return B_BAD_VALUE; 1329f161845SAxel Dörfler 133bfd4c59bSAxel Dörfler uint32 mode; 134bb693d77SAxel Dörfler if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK) 1359f161845SAxel Dörfler return B_BAD_ADDRESS; 1369f161845SAxel Dörfler 1379f161845SAxel Dörfler return vesa_set_display_mode(*info, mode); 1389f161845SAxel Dörfler } 1399f161845SAxel Dörfler 140bfd4c59bSAxel Dörfler case VESA_GET_DPMS_MODE: 141bfd4c59bSAxel Dörfler { 142bfd4c59bSAxel Dörfler if (bufferLength != sizeof(uint32)) 143bfd4c59bSAxel Dörfler return B_BAD_VALUE; 144bfd4c59bSAxel Dörfler 145bfd4c59bSAxel Dörfler uint32 mode; 146bfd4c59bSAxel Dörfler status_t status = vesa_get_dpms_mode(*info, mode); 147bfd4c59bSAxel Dörfler if (status != B_OK) 148bfd4c59bSAxel Dörfler return status; 149bfd4c59bSAxel Dörfler 150bfd4c59bSAxel Dörfler return user_memcpy(buffer, &mode, sizeof(mode)); 151bfd4c59bSAxel Dörfler } 152bfd4c59bSAxel Dörfler 153bfd4c59bSAxel Dörfler case VESA_SET_DPMS_MODE: 154bfd4c59bSAxel Dörfler { 155bfd4c59bSAxel Dörfler if (bufferLength != sizeof(uint32)) 156bfd4c59bSAxel Dörfler return B_BAD_VALUE; 157bfd4c59bSAxel Dörfler 158bfd4c59bSAxel Dörfler uint32 mode; 159bb693d77SAxel Dörfler if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK) 160bfd4c59bSAxel Dörfler return B_BAD_ADDRESS; 161bfd4c59bSAxel Dörfler 162bfd4c59bSAxel Dörfler return vesa_set_dpms_mode(*info, mode); 163bfd4c59bSAxel Dörfler } 164bfd4c59bSAxel Dörfler 165bb693d77SAxel Dörfler case VESA_SET_INDEXED_COLORS: 1660c6f7795SAxel Dörfler { 167b2a75cf5SAxel Dörfler color_space space 168b2a75cf5SAxel Dörfler = (color_space)info->shared_info->current_mode.space; 169b2a75cf5SAxel Dörfler if (space != B_GRAY8 && space != B_CMAP8) 170b2a75cf5SAxel Dörfler return B_ERROR; 171b2a75cf5SAxel Dörfler 172bb693d77SAxel Dörfler vesa_set_indexed_colors_args args; 173bb693d77SAxel Dörfler if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) 1740c6f7795SAxel Dörfler return B_BAD_ADDRESS; 1750c6f7795SAxel Dörfler 176b2a75cf5SAxel Dörfler status_t status = B_NOT_SUPPORTED; 177b2a75cf5SAxel Dörfler if (space != B_GRAY8) { 178b2a75cf5SAxel Dörfler status = vesa_set_indexed_colors(*info, args.first, args.colors, 179b2a75cf5SAxel Dörfler args.count); 180b2a75cf5SAxel Dörfler } 181bb693d77SAxel Dörfler 182b2a75cf5SAxel Dörfler // Try VGA as a fallback 183b2a75cf5SAxel Dörfler if (status != B_OK && (info->vbe_capabilities 184b2a75cf5SAxel Dörfler & CAPABILITY_NOT_VGA_COMPATIBLE) == 0) { 185bb693d77SAxel Dörfler return vga_set_indexed_colors(args.first, args.colors, 186bb693d77SAxel Dörfler args.count); 187bb693d77SAxel Dörfler } 188bb693d77SAxel Dörfler 189b2a75cf5SAxel Dörfler return status; 1900c6f7795SAxel Dörfler } 1910c6f7795SAxel Dörfler 1920c6f7795SAxel Dörfler case VGA_PLANAR_BLIT: 1930c6f7795SAxel Dörfler { 194bb693d77SAxel Dörfler if (info->shared_info->current_mode.space != B_GRAY8 195b2a75cf5SAxel Dörfler || (info->vbe_capabilities 196b2a75cf5SAxel Dörfler & CAPABILITY_NOT_VGA_COMPATIBLE) != 0) 197bb693d77SAxel Dörfler return B_NOT_SUPPORTED; 198bb693d77SAxel Dörfler 1990c6f7795SAxel Dörfler vga_planar_blit_args args; 200bb693d77SAxel Dörfler if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) 2010c6f7795SAxel Dörfler return B_BAD_ADDRESS; 2020c6f7795SAxel Dörfler 2030c6f7795SAxel Dörfler return vga_planar_blit(info->shared_info, args.source, 2040c6f7795SAxel Dörfler args.source_bytes_per_row, args.left, args.top, 2050c6f7795SAxel Dörfler args.right, args.bottom); 2060c6f7795SAxel Dörfler } 2070c6f7795SAxel Dörfler 20893ee2104SAxel Dörfler default: 209bfd4c59bSAxel Dörfler TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", 210bfd4c59bSAxel Dörfler msg, bufferLength)); 211bfd4c59bSAxel Dörfler break; 21293ee2104SAxel Dörfler } 21393ee2104SAxel Dörfler 21493ee2104SAxel Dörfler return B_DEV_INVALID_IOCTL; 21593ee2104SAxel Dörfler } 21693ee2104SAxel Dörfler 21793ee2104SAxel Dörfler 21893ee2104SAxel Dörfler static status_t 21993ee2104SAxel Dörfler device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length) 22093ee2104SAxel Dörfler { 22193ee2104SAxel Dörfler *_length = 0; 22293ee2104SAxel Dörfler return B_NOT_ALLOWED; 22393ee2104SAxel Dörfler } 22493ee2104SAxel Dörfler 22593ee2104SAxel Dörfler 22693ee2104SAxel Dörfler static status_t 227bfd4c59bSAxel Dörfler device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/, 228bfd4c59bSAxel Dörfler size_t* _length) 22993ee2104SAxel Dörfler { 23093ee2104SAxel Dörfler *_length = 0; 23193ee2104SAxel Dörfler return B_NOT_ALLOWED; 23293ee2104SAxel Dörfler } 23393ee2104SAxel Dörfler 234bfd4c59bSAxel Dörfler 235bfd4c59bSAxel Dörfler device_hooks gDeviceHooks = { 236bfd4c59bSAxel Dörfler device_open, 237bfd4c59bSAxel Dörfler device_close, 238bfd4c59bSAxel Dörfler device_free, 239bfd4c59bSAxel Dörfler device_ioctl, 240bfd4c59bSAxel Dörfler device_read, 241bfd4c59bSAxel Dörfler device_write, 242bfd4c59bSAxel Dörfler NULL, 243bfd4c59bSAxel Dörfler NULL, 244bfd4c59bSAxel Dörfler NULL, 245bfd4c59bSAxel Dörfler NULL 246bfd4c59bSAxel Dörfler }; 247