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 41static status_t device_open(const char* name, uint32 flags, void** _cookie); 42static status_t device_close(void* data); 43static status_t device_free(void* data); 44static status_t device_ioctl(void* data, uint32 opcode, 45 void* buffer, size_t length); 46static status_t device_read(void* data, off_t offset, 47 void* buffer, size_t* length); 48static status_t device_write(void* data, off_t offset, 49 const void* buffer, size_t* length); 50 51 52device_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 67static int 68getset_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 103static status_t 104device_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 144static status_t 145device_close(void* /*data*/) 146{ 147 TRACE("%s: close\n", __func__); 148 return B_OK; 149} 150 151 152static status_t 153device_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 169static status_t 170device_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 214static status_t 215device_read(void* /*data*/, off_t /*pos*/, 216 void* /*buffer*/, size_t *_length) 217{ 218 *_length = 0; 219 return B_NOT_ALLOWED; 220} 221 222 223static status_t 224device_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