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 "radeon_hd.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("radeon_hd: " x) 32 #else 33 # define TRACE(x...) ; 34 #endif 35 36 #define ERROR(x...) dprintf("radeon_hd: " x) 37 38 39 /* device hooks prototypes */ 40 41 static status_t device_open(const char *name, uint32 flags, void **_cookie); 42 static status_t device_close(void *data); 43 static status_t device_free(void *data); 44 static status_t device_ioctl(void *data, uint32 opcode, 45 void *buffer, size_t length); 46 static status_t device_read(void *data, off_t offset, 47 void *buffer, size_t *length); 48 static status_t device_write(void *data, off_t offset, 49 const void *buffer, size_t *length); 50 51 52 device_hooks gDeviceHooks = { 53 device_open, 54 device_close, 55 device_free, 56 device_ioctl, 57 device_read, 58 device_write, 59 NULL, 60 NULL, 61 NULL, 62 NULL 63 }; 64 65 66 #ifdef DEBUG_COMMANDS 67 static int 68 getset_register(int argc, char **argv) 69 { 70 if (argc < 2 || argc > 3) { 71 kprintf("usage: %s <register> [set-to-value]\n", argv[0]); 72 return 0; 73 } 74 75 uint32 reg = parse_expression(argv[1]); 76 uint32 value = 0; 77 bool set = argc == 3; 78 if (set) 79 value = parse_expression(argv[2]); 80 81 kprintf("radeon_hd register %#lx\n", reg); 82 83 radeon_info &info = *gDeviceInfo[0]; 84 uint32 oldValue = read32(info.registers + reg); 85 86 kprintf(" %svalue: %#lx (%lu)\n", set ? "old " : "", oldValue, oldValue); 87 88 if (set) { 89 write32(info.registers + reg, value); 90 91 value = read32(info.registers + reg); 92 kprintf(" new value: %#lx (%lu)\n", value, value); 93 } 94 95 return 0; 96 } 97 #endif // DEBUG_COMMANDS 98 99 100 // #pragma mark - Device Hooks 101 102 103 static status_t 104 device_open(const char *name, uint32 /*flags*/, void **_cookie) 105 { 106 TRACE("%s: open(name = %s)\n", __func__, name); 107 int32 id; 108 109 // find accessed device 110 { 111 char *thisName; 112 113 // search for device name 114 for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) { 115 if (!strcmp(name, thisName)) 116 break; 117 } 118 if (!thisName) 119 return B_BAD_VALUE; 120 } 121 122 radeon_info *info = gDeviceInfo[id]; 123 124 mutex_lock(&gLock); 125 126 if (info->open_count == 0) { 127 // this device has been opened for the first time, so 128 // we allocate needed resources and initialize the structure 129 info->init_status = radeon_hd_init(*info); 130 if (info->init_status == B_OK) { 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("%s: close\n", __func__); 148 return B_OK; 149 } 150 151 152 static status_t 153 device_free(void *data) 154 { 155 struct radeon_info *info = (radeon_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 radeon_hd_uninit(*info); 163 } 164 mutex_unlock(&gLock); 165 return B_OK; 166 } 167 168 169 static status_t 170 device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength) 171 { 172 struct radeon_info *info = (radeon_info *)data; 173 174 switch (op) { 175 case B_GET_ACCELERANT_SIGNATURE: 176 strcpy((char *)buffer, RADEON_ACCELERANT_NAME); 177 TRACE("%s: accelerant: %s\n", __func__, RADEON_ACCELERANT_NAME); 178 return B_OK; 179 180 // needed to share data between kernel and accelerant 181 case RADEON_GET_PRIVATE_DATA: 182 { 183 radeon_get_private_data *data = (radeon_get_private_data *)buffer; 184 185 if (data->magic == RADEON_PRIVATE_DATA_MAGIC) { 186 data->shared_info_area = info->shared_area; 187 return B_OK; 188 } 189 break; 190 } 191 192 // needed for cloning 193 case RADEON_GET_DEVICE_NAME: 194 #ifdef __HAIKU__ 195 if (user_strlcpy((char *)buffer, gDeviceNames[info->id], 196 B_PATH_NAME_LENGTH) < B_OK) 197 return B_BAD_ADDRESS; 198 #else 199 strncpy((char *)buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH); 200 ((char *)buffer)[B_PATH_NAME_LENGTH - 1] = '\0'; 201 #endif 202 return B_OK; 203 204 default: 205 TRACE("%s: ioctl() unknown message %ld (length = %ld)\n", 206 __func__, op, bufferLength); 207 break; 208 } 209 210 return B_DEV_INVALID_IOCTL; 211 } 212 213 214 static status_t 215 device_read(void */*data*/, off_t /*pos*/, 216 void */*buffer*/, size_t *_length) 217 { 218 *_length = 0; 219 return B_NOT_ALLOWED; 220 } 221 222 223 static status_t 224 device_write(void */*data*/, off_t /*pos*/, 225 const void */*buffer*/, size_t *_length) 226 { 227 *_length = 0; 228 return B_NOT_ALLOWED; 229 } 230 231