1 /* 2 * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2016, Jessica Hamilton, jessica.l.hamilton@gmail.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "device.h" 9 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include <Drivers.h> 14 #include <graphic_driver.h> 15 #include <image.h> 16 #include <KernelExport.h> 17 #include <OS.h> 18 #include <PCI.h> 19 #include <SupportDefs.h> 20 21 #include <vesa.h> 22 23 #include "driver.h" 24 #include "utility.h" 25 #include "vesa_info.h" 26 #include "framebuffer_private.h" 27 28 29 //#define TRACE_DEVICE 30 #ifdef TRACE_DEVICE 31 # define TRACE(x) dprintf x 32 #else 33 # define TRACE(x) ; 34 #endif 35 36 37 static status_t 38 device_open(const char* name, uint32 flags, void** _cookie) 39 { 40 int id; 41 42 // find accessed device 43 char* thisName; 44 45 // search for device name 46 for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) { 47 if (!strcmp(name, thisName)) 48 break; 49 } 50 if (thisName == NULL) 51 return B_BAD_VALUE; 52 53 framebuffer_info* info = gDeviceInfo[id]; 54 55 mutex_lock(&gLock); 56 57 status_t status = B_OK; 58 59 if (info->open_count == 0) { 60 // this device has been opened for the first time, so 61 // we allocate needed resources and initialize the structure 62 if (status == B_OK) 63 status = framebuffer_init(*info); 64 if (status == B_OK) 65 info->id = id; 66 } 67 68 if (status == B_OK) { 69 info->open_count++; 70 *_cookie = info; 71 } 72 73 mutex_unlock(&gLock); 74 return status; 75 } 76 77 78 static status_t 79 device_close(void* cookie) 80 { 81 return B_OK; 82 } 83 84 85 static status_t 86 device_free(void* cookie) 87 { 88 struct framebuffer_info* info = (framebuffer_info*)cookie; 89 90 mutex_lock(&gLock); 91 92 if (info->open_count-- == 1) { 93 // release info structure 94 framebuffer_uninit(*info); 95 } 96 97 mutex_unlock(&gLock); 98 return B_OK; 99 } 100 101 102 static status_t 103 device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength) 104 { 105 struct framebuffer_info* info = (framebuffer_info*)cookie; 106 107 switch (msg) { 108 case B_GET_ACCELERANT_SIGNATURE: 109 dprintf(DEVICE_NAME ": acc: %s\n", ACCELERANT_NAME); 110 if (user_strlcpy((char*)buffer, ACCELERANT_NAME, 111 B_FILE_NAME_LENGTH) < B_OK) 112 return B_BAD_ADDRESS; 113 114 return B_OK; 115 116 // needed to share data between kernel and accelerant 117 case VESA_GET_PRIVATE_DATA: 118 return user_memcpy(buffer, &info->shared_area, sizeof(area_id)); 119 120 // needed for cloning 121 case VESA_GET_DEVICE_NAME: 122 if (user_strlcpy((char*)buffer, gDeviceNames[info->id], 123 B_PATH_NAME_LENGTH) < B_OK) 124 return B_BAD_ADDRESS; 125 126 return B_OK; 127 128 default: 129 TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", 130 msg, bufferLength)); 131 break; 132 } 133 134 return B_DEV_INVALID_IOCTL; 135 } 136 137 138 static status_t 139 device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length) 140 { 141 *_length = 0; 142 return B_NOT_ALLOWED; 143 } 144 145 146 static status_t 147 device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/, 148 size_t* _length) 149 { 150 *_length = 0; 151 return B_NOT_ALLOWED; 152 } 153 154 155 device_hooks gDeviceHooks = { 156 device_open, 157 device_close, 158 device_free, 159 device_ioctl, 160 device_read, 161 device_write, 162 NULL, 163 NULL, 164 NULL, 165 NULL 166 }; 167