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