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