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 %#" 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 strcpy((char*)buffer, INTEL_ACCELERANT_NAME); 190 TRACE("accelerant: %s\n", INTEL_ACCELERANT_NAME); 191 return B_OK; 192 193 // needed to share data between kernel and accelerant 194 case INTEL_GET_PRIVATE_DATA: 195 { 196 intel_get_private_data* data = (intel_get_private_data* )buffer; 197 198 if (data->magic == INTEL_PRIVATE_DATA_MAGIC) { 199 data->shared_info_area = info->shared_area; 200 return B_OK; 201 } 202 break; 203 } 204 205 // needed for cloning 206 case INTEL_GET_DEVICE_NAME: 207 #ifdef __HAIKU__ 208 if (user_strlcpy((char* )buffer, gDeviceNames[info->id], 209 B_PATH_NAME_LENGTH) < B_OK) 210 return B_BAD_ADDRESS; 211 #else 212 strncpy((char* )buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH); 213 ((char* )buffer)[B_PATH_NAME_LENGTH - 1] = '\0'; 214 #endif 215 return B_OK; 216 217 // graphics mem manager 218 case INTEL_ALLOCATE_GRAPHICS_MEMORY: 219 { 220 intel_allocate_graphics_memory allocMemory; 221 #ifdef __HAIKU__ 222 if (user_memcpy(&allocMemory, buffer, 223 sizeof(intel_allocate_graphics_memory)) < B_OK) 224 return B_BAD_ADDRESS; 225 #else 226 memcpy(&allocMemory, buffer, 227 sizeof(intel_allocate_graphics_memory)); 228 #endif 229 230 if (allocMemory.magic != INTEL_PRIVATE_DATA_MAGIC) 231 return B_BAD_VALUE; 232 233 status_t status = intel_allocate_memory(*info, allocMemory.size, 234 allocMemory.alignment, allocMemory.flags, 235 &allocMemory.buffer_base); 236 if (status == B_OK) { 237 // copy result 238 #ifdef __HAIKU__ 239 if (user_memcpy(buffer, &allocMemory, 240 sizeof(intel_allocate_graphics_memory)) < B_OK) 241 return B_BAD_ADDRESS; 242 #else 243 memcpy(buffer, &allocMemory, 244 sizeof(intel_allocate_graphics_memory)); 245 #endif 246 } 247 return status; 248 } 249 250 case INTEL_FREE_GRAPHICS_MEMORY: 251 { 252 intel_free_graphics_memory freeMemory; 253 #ifdef __HAIKU__ 254 if (user_memcpy(&freeMemory, buffer, 255 sizeof(intel_free_graphics_memory)) < B_OK) 256 return B_BAD_ADDRESS; 257 #else 258 memcpy(&freeMemory, buffer, sizeof(intel_free_graphics_memory)); 259 #endif 260 261 if (freeMemory.magic == INTEL_PRIVATE_DATA_MAGIC) 262 return intel_free_memory(*info, freeMemory.buffer_base); 263 break; 264 } 265 266 default: 267 ERROR("ioctl() unknown message %" B_PRIu32 " (length = %" 268 B_PRIuSIZE ")\n", op, bufferLength); 269 break; 270 } 271 272 return B_DEV_INVALID_IOCTL; 273 } 274 275 276 static status_t 277 device_read(void* /*data*/, off_t /*pos*/, void* /*buffer*/, size_t* _length) 278 { 279 *_length = 0; 280 return B_NOT_ALLOWED; 281 } 282 283 284 static status_t 285 device_write(void* /*data*/, off_t /*pos*/, const void* /*buffer*/, 286 size_t* _length) 287 { 288 *_length = 0; 289 return B_NOT_ALLOWED; 290 } 291 292