* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel DΓΆrfler, axeld@pinc-software.de
*/
#include "driver.h"
#include "device.h"
#include "radeon_hd.h"
#include "utility.h"
#include <OS.h>
#include <KernelExport.h>
#include <Drivers.h>
#include <PCI.h>
#include <SupportDefs.h>
#include <graphic_driver.h>
#include <image.h>
#include <stdlib.h>
#include <string.h>
#define TRACE_DEVICE
#ifdef TRACE_DEVICE
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
static status_t device_open(const char *name, uint32 flags, void **_cookie);
static status_t device_close(void *data);
static status_t device_free(void *data);
static status_t device_ioctl(void *data, uint32 opcode,
void *buffer, size_t length);
static status_t device_read(void *data, off_t offset,
void *buffer, size_t *length);
static status_t device_write(void *data, off_t offset,
const void *buffer, size_t *length);
device_hooks gDeviceHooks = {
device_open,
device_close,
device_free,
device_ioctl,
device_read,
device_write,
NULL,
NULL,
NULL,
NULL
};
#ifdef DEBUG_COMMANDS
static int
getset_register(int argc, char **argv)
{
if (argc < 2 || argc > 3) {
kprintf("usage: %s <register> [set-to-value]\n", argv[0]);
return 0;
}
uint32 reg = parse_expression(argv[1]);
uint32 value = 0;
bool set = argc == 3;
if (set)
value = parse_expression(argv[2]);
kprintf("radeon_hd register %#lx\n", reg);
radeon_info &info = *gDeviceInfo[0];
uint32 oldValue = read32(info.registers + reg);
kprintf(" %svalue: %#lx (%lu)\n", set ? "old " : "", oldValue, oldValue);
if (set) {
write32(info.registers + reg, value);
value = read32(info.registers + reg);
kprintf(" new value: %#lx (%lu)\n", value, value);
}
return 0;
}
#endif
static status_t
device_open(const char *name, uint32 , void **_cookie)
{
TRACE((DEVICE_NAME ": open(name = %s)\n", name));
int32 id;
{
char *thisName;
for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
if (!strcmp(name, thisName))
break;
}
if (!thisName)
return B_BAD_VALUE;
}
radeon_info *info = gDeviceInfo[id];
mutex_lock(&gLock);
if (info->open_count == 0) {
info->init_status = radeon_hd_init(*info);
if (info->init_status == B_OK) {
info->open_count++;
}
}
mutex_unlock(&gLock);
if (info->init_status == B_OK)
*_cookie = info;
return info->init_status;
}
static status_t
device_close(void *)
{
TRACE((DEVICE_NAME ": close\n"));
return B_OK;
}
static status_t
device_free(void *data)
{
struct radeon_info *info = (radeon_info *)data;
mutex_lock(&gLock);
if (info->open_count-- == 1) {
info->init_status = B_NO_INIT;
radeon_hd_uninit(*info);
}
mutex_unlock(&gLock);
return B_OK;
}
static status_t
device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength)
{
struct radeon_info *info = (radeon_info *)data;
switch (op) {
case B_GET_ACCELERANT_SIGNATURE:
strcpy((char *)buffer, RADEON_ACCELERANT_NAME);
TRACE((DEVICE_NAME ": accelerant: %s\n", RADEON_ACCELERANT_NAME));
return B_OK;
case RADEON_GET_PRIVATE_DATA:
{
radeon_get_private_data *data = (radeon_get_private_data *)buffer;
if (data->magic == RADEON_PRIVATE_DATA_MAGIC) {
data->shared_info_area = info->shared_area;
return B_OK;
}
break;
}
case RADEON_GET_DEVICE_NAME:
#ifdef __HAIKU__
if (user_strlcpy((char *)buffer, gDeviceNames[info->id],
B_PATH_NAME_LENGTH) < B_OK)
return B_BAD_ADDRESS;
#else
strncpy((char *)buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH);
((char *)buffer)[B_PATH_NAME_LENGTH - 1] = '\0';
#endif
return B_OK;
default:
TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %ld)\n",
op, bufferLength));
break;
}
return B_DEV_INVALID_IOCTL;
}
static status_t
device_read(void *, off_t ,
void *, size_t *_length)
{
*_length = 0;
return B_NOT_ALLOWED;
}
static status_t
device_write(void *, off_t ,
const void *, size_t *_length)
{
*_length = 0;
return B_NOT_ALLOWED;
}