1 /* 2 * Copyright 2006-2018, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "driver.h" 11 #include "device.h" 12 #include "intel_extreme.h" 13 #include "utility.h" 14 15 #include <OS.h> 16 #include <KernelExport.h> 17 #include <Drivers.h> 18 #include <PCI.h> 19 #include <SupportDefs.h> 20 #include <graphic_driver.h> 21 #include <image.h> 22 23 #include <stdlib.h> 24 #include <string.h> 25 26 27 #define DEBUG_COMMANDS 28 29 #define TRACE_DEVICE 30 #ifdef TRACE_DEVICE 31 # define TRACE(x...) dprintf("intel_extreme: " x) 32 #else 33 # define TRACE(x) ; 34 #endif 35 36 #define ERROR(x...) dprintf("intel_extreme: " x) 37 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 38 39 40 /* device hooks prototypes */ 41 42 static status_t device_open(const char* name, uint32 flags, void** _cookie); 43 static status_t device_close(void* data); 44 static status_t device_free(void* data); 45 static status_t device_ioctl(void* data, uint32 opcode, void* buffer, 46 size_t length); 47 static status_t device_read(void* data, off_t offset, void* buffer, 48 size_t* length); 49 static status_t device_write(void* data, off_t offset, const void* buffer, 50 size_t* length); 51 52 53 device_hooks gDeviceHooks = { 54 device_open, 55 device_close, 56 device_free, 57 device_ioctl, 58 device_read, 59 device_write, 60 NULL, 61 NULL, 62 NULL, 63 NULL 64 }; 65 66 67 #ifdef DEBUG_COMMANDS 68 static int 69 getset_register(int argc, char** argv) 70 { 71 if (argc < 2 || argc > 3) { 72 kprintf("usage: %s <register> [set-to-value]\n", argv[0]); 73 return 0; 74 } 75 76 uint32 reg = parse_expression(argv[1]); 77 uint32 value = 0; 78 bool set = argc == 3; 79 if (set) 80 value = parse_expression(argv[2]); 81 82 kprintf("intel_extreme register %#" B_PRIx32 "\n", reg); 83 84 intel_info &info = *gDeviceInfo[0]; 85 uint32 oldValue = read32(info, reg); 86 87 kprintf(" %svalue: %#" B_PRIx32 " (%" B_PRIu32 ")\n", set ? "old " : "", 88 oldValue, oldValue); 89 90 if (set) { 91 write32(info, reg, value); 92 93 value = read32(info, reg); 94 kprintf(" new value: %#" B_PRIx32 " (%" B_PRIu32 ")\n", value, value); 95 } 96 97 return 0; 98 } 99 #endif // DEBUG_COMMANDS 100 101 102 // #pragma mark - Device Hooks 103 104 105 static status_t 106 device_open(const char* name, uint32 /*flags*/, void** _cookie) 107 { 108 CALLED(); 109 int32 id; 110 111 // find accessed device 112 { 113 char* thisName; 114 115 // search for device name 116 for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) { 117 if (!strcmp(name, thisName)) 118 break; 119 } 120 if (!thisName) 121 return B_BAD_VALUE; 122 } 123 124 intel_info* info = gDeviceInfo[id]; 125 126 mutex_lock(&gLock); 127 128 if (info->open_count == 0) { 129 // This device hasn't been initialized yet, so we 130 // allocate needed resources and initialize the structure 131 info->init_status = intel_extreme_init(*info); 132 if (info->init_status == B_OK) { 133 #ifdef DEBUG_COMMANDS 134 add_debugger_command("ie_reg", getset_register, 135 "dumps or sets the specified intel_extreme register"); 136 #endif 137 } 138 } 139 140 if (info->init_status == B_OK) { 141 info->open_count++; 142 *_cookie = info; 143 } else 144 ERROR("%s: initialization failed!\n", __func__); 145 146 mutex_unlock(&gLock); 147 148 return info->init_status; 149 } 150 151 152 static status_t 153 device_close(void* /*data*/) 154 { 155 CALLED(); 156 return B_OK; 157 } 158 159 160 static status_t 161 device_free(void* data) 162 { 163 struct intel_info* info = (intel_info*)data; 164 165 mutex_lock(&gLock); 166 167 if (info->open_count-- == 1) { 168 // release info structure 169 info->init_status = B_NO_INIT; 170 intel_extreme_uninit(*info); 171 172 #ifdef DEBUG_COMMANDS 173 remove_debugger_command("ie_reg", getset_register); 174 #endif 175 } 176 177 mutex_unlock(&gLock); 178 return B_OK; 179 } 180 181 182 static status_t 183 device_ioctl(void* data, uint32 op, void* buffer, size_t bufferLength) 184 { 185 struct intel_info* info = (intel_info*)data; 186 187 switch (op) { 188 case B_GET_ACCELERANT_SIGNATURE: 189 TRACE("accelerant: %s\n", INTEL_ACCELERANT_NAME); 190 if (user_strlcpy((char*)buffer, INTEL_ACCELERANT_NAME, 191 bufferLength) < B_OK) 192 return B_BAD_ADDRESS; 193 return B_OK; 194 195 // needed to share data between kernel and accelerant 196 case INTEL_GET_PRIVATE_DATA: 197 { 198 intel_get_private_data data; 199 if (user_memcpy(&data, buffer, sizeof(intel_get_private_data)) < B_OK) 200 return B_BAD_ADDRESS; 201 202 if (data.magic == INTEL_PRIVATE_DATA_MAGIC) { 203 data.shared_info_area = info->shared_area; 204 return user_memcpy(buffer, &data, 205 sizeof(intel_get_private_data)); 206 } 207 break; 208 } 209 210 // needed for cloning 211 case INTEL_GET_DEVICE_NAME: 212 if (user_strlcpy((char* )buffer, gDeviceNames[info->id], 213 bufferLength) < B_OK) 214 return B_BAD_ADDRESS; 215 return B_OK; 216 217 // graphics mem manager 218 case INTEL_ALLOCATE_GRAPHICS_MEMORY: 219 { 220 intel_allocate_graphics_memory allocMemory; 221 if (user_memcpy(&allocMemory, buffer, 222 sizeof(intel_allocate_graphics_memory)) < B_OK) 223 return B_BAD_ADDRESS; 224 225 if (allocMemory.magic != INTEL_PRIVATE_DATA_MAGIC) 226 return B_BAD_VALUE; 227 228 status_t status = intel_allocate_memory(*info, allocMemory.size, 229 allocMemory.alignment, allocMemory.flags, 230 &allocMemory.buffer_base); 231 if (status == B_OK) { 232 // copy result 233 if (user_memcpy(buffer, &allocMemory, 234 sizeof(intel_allocate_graphics_memory)) < B_OK) 235 return B_BAD_ADDRESS; 236 } 237 return status; 238 } 239 240 case INTEL_FREE_GRAPHICS_MEMORY: 241 { 242 intel_free_graphics_memory freeMemory; 243 if (user_memcpy(&freeMemory, buffer, 244 sizeof(intel_free_graphics_memory)) < B_OK) 245 return B_BAD_ADDRESS; 246 247 if (freeMemory.magic == INTEL_PRIVATE_DATA_MAGIC) 248 return intel_free_memory(*info, freeMemory.buffer_base); 249 break; 250 } 251 252 default: 253 ERROR("ioctl() unknown message %" B_PRIu32 " (length = %" 254 B_PRIuSIZE ")\n", op, bufferLength); 255 break; 256 } 257 258 return B_DEV_INVALID_IOCTL; 259 } 260 261 262 static status_t 263 device_read(void* /*data*/, off_t /*pos*/, void* /*buffer*/, size_t* _length) 264 { 265 *_length = 0; 266 return B_NOT_ALLOWED; 267 } 268 269 270 static status_t 271 device_write(void* /*data*/, off_t /*pos*/, const void* /*buffer*/, 272 size_t* _length) 273 { 274 *_length = 0; 275 return B_NOT_ALLOWED; 276 } 277 278