1 /* 2 * Copyright 2006-2009, 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 %#lx\n", reg); 83 84 intel_info &info = *gDeviceInfo[0]; 85 uint32 oldValue = read32(info, reg); 86 87 kprintf(" %svalue: %#lx (%lu)\n", set ? "old " : "", oldValue, oldValue); 88 89 if (set) { 90 write32(info, reg, value); 91 92 value = read32(info, reg); 93 kprintf(" new value: %#lx (%lu)\n", value, value); 94 } 95 96 return 0; 97 } 98 #endif // DEBUG_COMMANDS 99 100 101 // #pragma mark - Device Hooks 102 103 104 static status_t 105 device_open(const char* name, uint32 /*flags*/, void** _cookie) 106 { 107 CALLED(); 108 int32 id; 109 110 // find accessed device 111 { 112 char* thisName; 113 114 // search for device name 115 for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) { 116 if (!strcmp(name, thisName)) 117 break; 118 } 119 if (!thisName) 120 return B_BAD_VALUE; 121 } 122 123 intel_info* info = gDeviceInfo[id]; 124 125 mutex_lock(&gLock); 126 127 if (info->open_count == 0) { 128 // This device hasn't been initialized yet, so we 129 // allocate needed resources and initialize the structure 130 info->init_status = intel_extreme_init(*info); 131 if (info->init_status == B_OK) { 132 #ifdef DEBUG_COMMANDS 133 add_debugger_command("ie_reg", getset_register, 134 "dumps or sets the specified intel_extreme register"); 135 #endif 136 } 137 } 138 139 if (info->init_status == B_OK) { 140 info->open_count++; 141 *_cookie = info; 142 } else 143 ERROR("%s: initialization failed!\n", __func__); 144 145 mutex_unlock(&gLock); 146 147 return info->init_status; 148 } 149 150 151 static status_t 152 device_close(void* /*data*/) 153 { 154 CALLED(); 155 return B_OK; 156 } 157 158 159 static status_t 160 device_free(void* data) 161 { 162 struct intel_info* info = (intel_info*)data; 163 164 mutex_lock(&gLock); 165 166 if (info->open_count-- == 1) { 167 // release info structure 168 info->init_status = B_NO_INIT; 169 intel_extreme_uninit(*info); 170 171 #ifdef DEBUG_COMMANDS 172 remove_debugger_command("ie_reg", getset_register); 173 #endif 174 } 175 176 mutex_unlock(&gLock); 177 return B_OK; 178 } 179 180 181 static status_t 182 device_ioctl(void* data, uint32 op, void* buffer, size_t bufferLength) 183 { 184 struct intel_info* info = (intel_info*)data; 185 186 switch (op) { 187 case B_GET_ACCELERANT_SIGNATURE: 188 strcpy((char*)buffer, INTEL_ACCELERANT_NAME); 189 TRACE("accelerant: %s\n", INTEL_ACCELERANT_NAME); 190 return B_OK; 191 192 // needed to share data between kernel and accelerant 193 case INTEL_GET_PRIVATE_DATA: 194 { 195 intel_get_private_data* data = (intel_get_private_data* )buffer; 196 197 if (data->magic == INTEL_PRIVATE_DATA_MAGIC) { 198 data->shared_info_area = info->shared_area; 199 return B_OK; 200 } 201 break; 202 } 203 204 // needed for cloning 205 case INTEL_GET_DEVICE_NAME: 206 #ifdef __HAIKU__ 207 if (user_strlcpy((char* )buffer, gDeviceNames[info->id], 208 B_PATH_NAME_LENGTH) < B_OK) 209 return B_BAD_ADDRESS; 210 #else 211 strncpy((char* )buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH); 212 ((char* )buffer)[B_PATH_NAME_LENGTH - 1] = '\0'; 213 #endif 214 return B_OK; 215 216 // graphics mem manager 217 case INTEL_ALLOCATE_GRAPHICS_MEMORY: 218 { 219 intel_allocate_graphics_memory allocMemory; 220 #ifdef __HAIKU__ 221 if (user_memcpy(&allocMemory, buffer, 222 sizeof(intel_allocate_graphics_memory)) < B_OK) 223 return B_BAD_ADDRESS; 224 #else 225 memcpy(&allocMemory, buffer, 226 sizeof(intel_allocate_graphics_memory)); 227 #endif 228 229 if (allocMemory.magic != INTEL_PRIVATE_DATA_MAGIC) 230 return B_BAD_VALUE; 231 232 status_t status = intel_allocate_memory(*info, allocMemory.size, 233 allocMemory.alignment, allocMemory.flags, 234 &allocMemory.buffer_base); 235 if (status == B_OK) { 236 // copy result 237 #ifdef __HAIKU__ 238 if (user_memcpy(buffer, &allocMemory, 239 sizeof(intel_allocate_graphics_memory)) < B_OK) 240 return B_BAD_ADDRESS; 241 #else 242 memcpy(buffer, &allocMemory, 243 sizeof(intel_allocate_graphics_memory)); 244 #endif 245 } 246 return status; 247 } 248 249 case INTEL_FREE_GRAPHICS_MEMORY: 250 { 251 intel_free_graphics_memory freeMemory; 252 #ifdef __HAIKU__ 253 if (user_memcpy(&freeMemory, buffer, 254 sizeof(intel_free_graphics_memory)) < B_OK) 255 return B_BAD_ADDRESS; 256 #else 257 memcpy(&freeMemory, buffer, sizeof(intel_free_graphics_memory)); 258 #endif 259 260 if (freeMemory.magic == INTEL_PRIVATE_DATA_MAGIC) 261 return intel_free_memory(*info, freeMemory.buffer_base); 262 break; 263 } 264 265 default: 266 ERROR("ioctl() unknown message %ld (length = %ld)\n", op, 267 bufferLength); 268 break; 269 } 270 271 return B_DEV_INVALID_IOCTL; 272 } 273 274 275 static status_t 276 device_read(void* /*data*/, off_t /*pos*/, void* /*buffer*/, size_t* _length) 277 { 278 *_length = 0; 279 return B_NOT_ALLOWED; 280 } 281 282 283 static status_t 284 device_write(void* /*data*/, off_t /*pos*/, const void* /*buffer*/, 285 size_t* _length) 286 { 287 *_length = 0; 288 return B_NOT_ALLOWED; 289 } 290 291