1 /* 2 * Copyright 2006, 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 TRACE_DEVICE 28 #ifdef TRACE_DEVICE 29 # define TRACE(x) dprintf x 30 #else 31 # define TRACE(x) ; 32 #endif 33 34 35 /* device hooks prototypes */ 36 37 static status_t device_open(const char *name, uint32 flags, void **_cookie); 38 static status_t device_close(void *data); 39 static status_t device_free(void *data); 40 static status_t device_ioctl(void *data, uint32 opcode, void *buffer, size_t length); 41 static status_t device_read(void *data, off_t offset, void *buffer, size_t *length); 42 static status_t device_write(void *data, off_t offset, const void *buffer, size_t *length); 43 44 45 device_hooks gDeviceHooks = { 46 device_open, 47 device_close, 48 device_free, 49 device_ioctl, 50 device_read, 51 device_write, 52 NULL, 53 NULL, 54 NULL, 55 NULL 56 }; 57 58 59 static status_t 60 checkDeviceInfo(struct intel_info *info) 61 { 62 if (!info || info->cookie_magic != INTEL_COOKIE_MAGIC) 63 return B_BAD_VALUE; 64 65 return B_OK; 66 } 67 68 69 // #pragma mark - Device Hooks 70 71 72 static status_t 73 device_open(const char *name, uint32 /*flags*/, void **_cookie) 74 { 75 TRACE((DEVICE_NAME ": open(name = %s)\n", name)); 76 int32 id; 77 78 // find accessed device 79 { 80 char *thisName; 81 82 // search for device name 83 for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) { 84 if (!strcmp(name, thisName)) 85 break; 86 } 87 if (!thisName) 88 return B_BAD_VALUE; 89 } 90 intel_info *info = gDeviceInfo[id]; 91 *_cookie = info; 92 93 acquire_lock(&gLock); 94 95 status_t status = B_OK; 96 97 if (info->open_count++ == 0) { 98 // this device has been opened for the first time, so 99 // we allocate needed resources and initialize the structure 100 status = intel_extreme_init(*info); 101 } 102 103 release_lock(&gLock); 104 105 return status; 106 } 107 108 109 static status_t 110 device_close(void *data) 111 { 112 TRACE((DEVICE_NAME ": close\n")); 113 struct intel_info *info; 114 115 if (checkDeviceInfo(info = (intel_info *)data) != B_OK) 116 return B_BAD_VALUE; 117 118 info->cookie_magic = INTEL_FREE_COOKIE_MAGIC; 119 120 return B_OK; 121 } 122 123 124 static status_t 125 device_free(void *data) 126 { 127 struct intel_info *info = (intel_info *)data; 128 status_t retval = B_NO_ERROR; 129 130 if (info == NULL || info->cookie_magic != INTEL_FREE_COOKIE_MAGIC) 131 retval = B_BAD_VALUE; 132 133 acquire_lock(&gLock); 134 135 if (info->open_count-- == 1) { 136 // release info structure 137 info->cookie_magic = 0; 138 intel_extreme_uninit(*info); 139 } 140 141 release_lock(&gLock); 142 143 return retval; 144 } 145 146 147 static status_t 148 device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength) 149 { 150 struct intel_info *info; 151 152 if (checkDeviceInfo(info = (intel_info *)data) != B_OK) 153 return B_BAD_VALUE; 154 155 switch (op) { 156 case B_GET_ACCELERANT_SIGNATURE: 157 strcpy((char *)buffer, INTEL_ACCELERANT_NAME); 158 TRACE((DEVICE_NAME ": accelerant: %s\n", INTEL_ACCELERANT_NAME)); 159 return B_OK; 160 161 // needed to share data between kernel and accelerant 162 case INTEL_GET_PRIVATE_DATA: 163 { 164 intel_get_private_data *data = (intel_get_private_data *)buffer; 165 166 if (data->magic == INTEL_PRIVATE_DATA_MAGIC) { 167 data->shared_info_area = info->shared_area; 168 return B_OK; 169 } 170 break; 171 } 172 173 // needed for cloning 174 case INTEL_GET_DEVICE_NAME: 175 #ifdef __HAIKU__ 176 if (user_strlcpy((char *)buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH) < B_OK) 177 return B_BAD_ADDRESS; 178 #else 179 strncpy((char *)buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH); 180 ((char *)buffer)[B_PATH_NAME_LENGTH - 1] = '\0'; 181 #endif 182 return B_OK; 183 184 // graphics mem manager 185 case INTEL_ALLOCATE_GRAPHICS_MEMORY: 186 { 187 intel_allocate_graphics_memory allocMemory; 188 #ifdef __HAIKU__ 189 if (user_memcpy(&allocMemory, buffer, sizeof(intel_allocate_graphics_memory)) < B_OK) 190 return B_BAD_ADDRESS; 191 #else 192 memcpy(&allocMemory, buffer, sizeof(intel_allocate_graphics_memory)); 193 #endif 194 195 if (allocMemory.magic != INTEL_PRIVATE_DATA_MAGIC) 196 return B_BAD_VALUE; 197 198 status_t status = mem_alloc(info->memory_manager, allocMemory.size, info, 199 &allocMemory.handle, &allocMemory.buffer_offset); 200 if (status == B_OK) { 201 // copy result 202 #ifdef __HAIKU__ 203 if (user_memcpy(buffer, &allocMemory, sizeof(intel_allocate_graphics_memory)) < B_OK) 204 return B_BAD_ADDRESS; 205 #else 206 memcpy(buffer, &allocMemory, sizeof(intel_allocate_graphics_memory)); 207 #endif 208 } 209 return status; 210 } 211 212 case INTEL_FREE_GRAPHICS_MEMORY: 213 { 214 intel_free_graphics_memory freeMemory; 215 #ifdef __HAIKU__ 216 if (user_memcpy(&freeMemory, buffer, sizeof(intel_free_graphics_memory)) < B_OK) 217 return B_BAD_ADDRESS; 218 #else 219 memcpy(&freeMemory, buffer, sizeof(intel_free_graphics_memory)); 220 #endif 221 222 if (freeMemory.magic == INTEL_PRIVATE_DATA_MAGIC) 223 return mem_free(info->memory_manager, freeMemory.handle, info); 224 break; 225 } 226 227 default: 228 TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %ld)\n", 229 op, bufferLength)); 230 break; 231 } 232 233 return B_DEV_INVALID_IOCTL; 234 } 235 236 237 static status_t 238 device_read(void */*data*/, off_t /*pos*/, void */*buffer*/, size_t *_length) 239 { 240 *_length = 0; 241 return B_NOT_ALLOWED; 242 } 243 244 245 static status_t 246 device_write(void */*data*/, off_t /*pos*/, const void */*buffer*/, size_t *_length) 247 { 248 *_length = 0; 249 return B_NOT_ALLOWED; 250 } 251 252