More stuff that I thought I already checked in (did cvs burp ?)
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8436 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5f6e3f515c
commit
ed03de4ccf
13
src/add-ons/kernel/drivers/graphics/common/Jamfile
Normal file
13
src/add-ons/kernel/drivers/graphics/common/Jamfile
Normal file
@ -0,0 +1,13 @@
|
||||
SubDir OBOS_TOP src add-ons kernel drivers graphics common ;
|
||||
|
||||
SubDirCcFlags -DENABLE_LOGGING -DLOG_INCLUDE_STARTUP ;
|
||||
|
||||
UsePrivateHeaders graphics ;
|
||||
UsePrivateHeaders [ FDirName graphics radeon ] ;
|
||||
UsePrivateHeaders [ FDirName graphics common ] ;
|
||||
|
||||
StaticLibrary graphicscommon :
|
||||
log_coll.c
|
||||
log_dump.c
|
||||
memmgr.c
|
||||
;
|
129
src/add-ons/kernel/drivers/graphics/common/log_coll.c
Normal file
129
src/add-ons/kernel/drivers/graphics/common/log_coll.c
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon driver
|
||||
|
||||
Both kernel and user space part.
|
||||
(init and clean-up must be done in
|
||||
kernel space).
|
||||
*/
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <perfmon_kernel.h>
|
||||
#include "log_coll.h"
|
||||
#include <OS.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct log_info_t {
|
||||
char *log_buffer;
|
||||
uint32 log_buffer_len;
|
||||
uint32 log_buffer_pos;
|
||||
area_id area;
|
||||
} log_info;
|
||||
|
||||
#ifdef ENABLE_LOGGING
|
||||
|
||||
|
||||
// write one log entry
|
||||
void log( log_info *li, uint16 what, const uint8 num_args, ... )
|
||||
{
|
||||
uint32 pos;
|
||||
va_list vl;
|
||||
log_entry *entry;
|
||||
uint32 i;
|
||||
uint32 entry_size;
|
||||
|
||||
entry_size = sizeof( log_entry ) + (num_args - 1) * sizeof( uint32 );
|
||||
pos = atomic_add( &li->log_buffer_pos, entry_size );
|
||||
|
||||
if( li->log_buffer_pos > li->log_buffer_len ) {
|
||||
atomic_add( &li->log_buffer_pos, -entry_size );
|
||||
return;
|
||||
}
|
||||
|
||||
entry = (log_entry *)&li->log_buffer[pos];
|
||||
|
||||
entry->tsc = read_tsc();
|
||||
entry->what = what;
|
||||
entry->num_args = num_args;
|
||||
|
||||
va_start( vl, num_args );
|
||||
for( i = 0; i < num_args; ++i ) {
|
||||
entry->args[i] = va_arg( vl, uint32 );
|
||||
}
|
||||
va_end( vl );
|
||||
}
|
||||
|
||||
#ifdef LOG_INCLUDE_STARTUP
|
||||
|
||||
// create log buffer
|
||||
log_info *log_init( uint32 size )
|
||||
{
|
||||
log_info *li;
|
||||
area_id area;
|
||||
|
||||
// buffer must be accessible from user mem
|
||||
// to allow logging from there as well;
|
||||
// you cannot clone this area as there are
|
||||
// pointers which would break (it wouldn't be
|
||||
// hard to get rid of them, but I don't care
|
||||
// and keep it as simple as possible)
|
||||
area = create_area( "fast_logger",
|
||||
(void **)&li, B_ANY_KERNEL_ADDRESS,
|
||||
(sizeof( log_info ) + size + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1),
|
||||
B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA );
|
||||
|
||||
if( area < 0 )
|
||||
panic( "Radeon Fast logger: cannot allocate %ld byte for logging data\n", size );
|
||||
|
||||
li->area = area;
|
||||
li->log_buffer = (char *)li + sizeof( log_info );
|
||||
li->log_buffer_len = size;
|
||||
li->log_buffer_pos = 0;
|
||||
|
||||
return li;
|
||||
}
|
||||
|
||||
// clean-up logging
|
||||
void log_exit( log_info *li )
|
||||
{
|
||||
li->log_buffer_pos = 0;
|
||||
//free( li->log_buffer );
|
||||
delete_area( li->area );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LOG_INCLUDE_STARTUP
|
||||
|
||||
// get *current* size of logging data
|
||||
uint32 log_getsize( log_info *li )
|
||||
{
|
||||
if( li == NULL )
|
||||
return 0;
|
||||
|
||||
dprintf( "RADEON -- log_getsize: log_pos %ld\n", li->log_buffer_pos );
|
||||
return li->log_buffer_pos;
|
||||
}
|
||||
|
||||
// get up to max_size bytes of logging data
|
||||
void log_getcopy( log_info *li, void *dest, uint32 max_size )
|
||||
{
|
||||
if( li == NULL )
|
||||
return;
|
||||
|
||||
dprintf( "RADEON -- log_getcopy: max_size %ld, log_pos %ld\n",
|
||||
max_size, li->log_buffer_pos );
|
||||
memcpy( dest, li->log_buffer, min( li->log_buffer_pos, max_size ));
|
||||
|
||||
li->log_buffer_pos = 0;
|
||||
}
|
||||
|
||||
#endif
|
73
src/add-ons/kernel/drivers/graphics/common/log_dump.c
Normal file
73
src/add-ons/kernel/drivers/graphics/common/log_dump.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon driver
|
||||
|
||||
Fast logger - functions to create dump
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <OS.h>
|
||||
|
||||
#include "log_coll.h"
|
||||
#include "log_dump.h"
|
||||
#include "log_enum.h"
|
||||
#include "log_names.h"
|
||||
|
||||
system_info sysinfo;
|
||||
|
||||
// dump one entry
|
||||
void log_printentry( FILE *logfile, log_entry *entry )
|
||||
{
|
||||
uint64 time;
|
||||
uint32 min, sec, mill, mic;
|
||||
|
||||
time = entry->tsc / (sysinfo.cpu_clock_speed / 1000000);
|
||||
mic = time % 1000;
|
||||
time /= 1000;
|
||||
mill = time % 1000;
|
||||
time /= 1000;
|
||||
sec = time % 60;
|
||||
time /= 60;
|
||||
min = time;
|
||||
|
||||
fprintf( logfile, "%03ld:%02ld:%03ld.%03ld ", min, sec, mill, mic );
|
||||
if( entry->what < sizeof( log_names ) / sizeof( log_names[0] ) )
|
||||
fprintf( logfile, log_names[entry->what] );
|
||||
else
|
||||
fprintf( logfile, "unknown %ld", (uint32)entry->what );
|
||||
|
||||
if( entry->num_args > 0 ) {
|
||||
uint32 i;
|
||||
|
||||
fprintf( logfile, " (" );
|
||||
for( i = 0; i < entry->num_args; ++i ) {
|
||||
if( i > 0 )
|
||||
fprintf( logfile, ", " );
|
||||
|
||||
fprintf( logfile, "0x%08lx", entry->args[i] );
|
||||
}
|
||||
fprintf( logfile, ")" );
|
||||
}
|
||||
|
||||
fprintf( logfile, "\n" );
|
||||
}
|
||||
|
||||
|
||||
// dump entire log
|
||||
void log_printall( FILE *logfile, char *buffer, uint32 buffer_len )
|
||||
{
|
||||
uint32 pos;
|
||||
|
||||
get_system_info( &sysinfo );
|
||||
|
||||
for( pos = 0; pos < buffer_len; ) {
|
||||
log_entry *entry;
|
||||
|
||||
entry = (log_entry *)(buffer + pos);
|
||||
log_printentry( logfile, entry/*, &tsc*/ );
|
||||
pos += sizeof( log_entry ) + (entry->num_args - 1) * sizeof( uint32 );
|
||||
}
|
||||
}
|
273
src/add-ons/kernel/drivers/graphics/common/memmgr.c
Normal file
273
src/add-ons/kernel/drivers/graphics/common/memmgr.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
Copyright (c) 2002, Thomas Kurschel
|
||||
|
||||
|
||||
Part of Radeon kernel driver
|
||||
|
||||
Memory manager used for graphics mem
|
||||
|
||||
|
||||
It has the following features
|
||||
- doesn't access memory to be managed
|
||||
- memory block's owner is identified by tag,
|
||||
tag is verified during free, and all memory
|
||||
belonging to one tag can be freed at once
|
||||
- multi-threading save
|
||||
*/
|
||||
|
||||
#include "memmgr.h"
|
||||
#include <malloc.h>
|
||||
#include "KernelExport.h"
|
||||
|
||||
#define debug_level_flow 4
|
||||
#define debug_level_info 4
|
||||
#define debug_level_error 4
|
||||
|
||||
#define DEBUG_MSG_PREFIX "Graphics Driver - "
|
||||
#include "debug_ext.h"
|
||||
|
||||
|
||||
#if 0
|
||||
#ifndef _KERNEL_MODE
|
||||
void _kdprintf_(const char *format, ...);
|
||||
//bool set_dprintf_enabled(bool); /* returns old enable flag */
|
||||
|
||||
#define dprintf _kdprintf_
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// init manager
|
||||
// start - start of address space
|
||||
// len - len of address space
|
||||
// block_size - granularity
|
||||
// heap_entries - maximum number of blocks
|
||||
mem_info *mem_init( uint32 start, uint32 len, uint32 block_size, uint32 heap_entries )
|
||||
{
|
||||
mem_block *first;
|
||||
mem_info *mem;
|
||||
uint i;
|
||||
|
||||
SHOW_FLOW( 2, "start=%lx, len=%lx, block_size=%lx, heap_entries=%ld",
|
||||
start, len, block_size, heap_entries );
|
||||
|
||||
mem = malloc( sizeof( *mem ));
|
||||
if( mem == NULL )
|
||||
goto err;
|
||||
|
||||
mem->block_size = block_size;
|
||||
mem->heap_entries = heap_entries;
|
||||
mem->lock = create_sem( 1, "mem_lock" );
|
||||
|
||||
if( mem->lock < 0 )
|
||||
goto err2;
|
||||
|
||||
mem->heap = malloc( heap_entries * sizeof( mem_block ));
|
||||
if( mem->heap == NULL )
|
||||
goto err3;
|
||||
|
||||
for( i = 1; i < heap_entries; ++i )
|
||||
mem->heap[i].next = &mem->heap[i+1];
|
||||
|
||||
mem->heap[heap_entries - 1].next = NULL;
|
||||
mem->unused = &mem->heap[1];
|
||||
|
||||
first = &mem->heap[0];
|
||||
mem->first = first;
|
||||
|
||||
first->base = start;
|
||||
first->size = len;
|
||||
first->prev = first->next = NULL;
|
||||
first->alloced = false;
|
||||
|
||||
return mem;
|
||||
|
||||
err3:
|
||||
delete_sem( mem->lock );
|
||||
err2:
|
||||
free( mem );
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// destroy heap
|
||||
void mem_destroy( mem_info *mem )
|
||||
{
|
||||
SHOW_FLOW0( 2, "" );
|
||||
|
||||
free( mem->heap );
|
||||
delete_sem( mem->lock );
|
||||
free( mem );
|
||||
}
|
||||
|
||||
|
||||
// allocate memory block
|
||||
// in:
|
||||
// mem - heap handle
|
||||
// size - size in bytes
|
||||
// tag - owner tag
|
||||
// out:
|
||||
// block_id - block id
|
||||
// offset - start address of block
|
||||
status_t mem_alloc( mem_info *mem, uint32 size, void *tag, uint32 *block_id, uint32 *offset )
|
||||
{
|
||||
mem_block *cur, *new_entry;
|
||||
|
||||
SHOW_FLOW( 2, "size=%ld, tag=%p", size, tag );
|
||||
|
||||
acquire_sem( mem->lock );
|
||||
|
||||
// we assume block_size is power of two
|
||||
size = (size + mem->block_size - 1) & ~(mem->block_size - 1);
|
||||
|
||||
// simple first fit
|
||||
for( cur = mem->first; cur; cur = cur->next ) {
|
||||
if( !cur->alloced && cur->size >= size )
|
||||
break;
|
||||
}
|
||||
|
||||
if( cur == NULL ) {
|
||||
SHOW_FLOW0( 2, "out of memory" );
|
||||
goto err;
|
||||
}
|
||||
|
||||
if( size != cur->size ) {
|
||||
new_entry = mem->unused;
|
||||
|
||||
if( new_entry == NULL ) {
|
||||
SHOW_FLOW0( 2, "out of blocks" );
|
||||
goto err;
|
||||
}
|
||||
|
||||
mem->unused = new_entry->next;
|
||||
|
||||
new_entry->next = cur->next;
|
||||
new_entry->prev = cur;
|
||||
new_entry->alloced = false;
|
||||
new_entry->base = cur->base + size;
|
||||
new_entry->size = cur->size - size;
|
||||
|
||||
if( cur->next )
|
||||
cur->next->prev = new_entry;
|
||||
|
||||
cur->next = new_entry;
|
||||
cur->size = size;
|
||||
}
|
||||
|
||||
cur->alloced = true;
|
||||
cur->tag = tag;
|
||||
|
||||
*block_id = cur - mem->heap + 1;
|
||||
*offset = cur->base;
|
||||
|
||||
release_sem( mem->lock );
|
||||
|
||||
SHOW_FLOW( 2, "block_id=%ld, offset=%lx", *block_id, *offset );
|
||||
|
||||
return B_OK;
|
||||
|
||||
err:
|
||||
release_sem( mem->lock );
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
// merge "block" with successor
|
||||
static void merge( mem_info *mem, mem_block *block )
|
||||
{
|
||||
mem_block *next;
|
||||
|
||||
next = block->next;
|
||||
|
||||
block->size += next->size;
|
||||
|
||||
if( next->next )
|
||||
next->next->prev = block;
|
||||
|
||||
block->next = next->next;
|
||||
|
||||
next->next = mem->unused;
|
||||
mem->unused = next;
|
||||
}
|
||||
|
||||
|
||||
// internal: free memory block including merge
|
||||
static mem_block *freeblock( mem_info *mem, mem_block *block )
|
||||
{
|
||||
mem_block *prev, *next;
|
||||
|
||||
block->alloced = false;
|
||||
|
||||
prev = block->prev;
|
||||
|
||||
if( prev && !prev->alloced ) {
|
||||
block = prev;
|
||||
merge( mem, prev );
|
||||
}
|
||||
|
||||
next = block->next;
|
||||
|
||||
if( next && !next->alloced )
|
||||
merge( mem, block );
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
// free memory
|
||||
// mem - heap handle
|
||||
// block_id - block id
|
||||
// tag - owner tag (must match tag passed to mem_alloc)
|
||||
status_t mem_free( mem_info *mem, uint32 block_id, void *tag )
|
||||
{
|
||||
mem_block *block;
|
||||
|
||||
SHOW_FLOW( 2, "block_id=%ld, tag=%p", block_id, tag );
|
||||
|
||||
acquire_sem( mem->lock );
|
||||
|
||||
--block_id;
|
||||
|
||||
if( block_id >= mem->heap_entries ) {
|
||||
SHOW_ERROR0( 2, "invalid id" );
|
||||
goto err;
|
||||
}
|
||||
|
||||
block = &mem->heap[block_id];
|
||||
if( !block->alloced || block->tag != tag ) {
|
||||
SHOW_ERROR0( 2, "not owner" );
|
||||
goto err;
|
||||
}
|
||||
|
||||
freeblock( mem, block );
|
||||
|
||||
release_sem( mem->lock );
|
||||
|
||||
SHOW_FLOW0( 2, "success" );
|
||||
return B_OK;
|
||||
|
||||
err:
|
||||
release_sem( mem->lock );
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
// free all memory belonging to owner "tag"
|
||||
void mem_freetag( mem_info *mem, void *tag )
|
||||
{
|
||||
mem_block *cur;
|
||||
|
||||
SHOW_FLOW( 2, "tag=%p", tag );
|
||||
|
||||
acquire_sem( mem->lock );
|
||||
|
||||
for( cur = mem->first; cur; cur = cur->next ) {
|
||||
if( cur->alloced && cur->tag == tag )
|
||||
cur = freeblock( mem, cur );
|
||||
}
|
||||
|
||||
release_sem( mem->lock );
|
||||
|
||||
SHOW_FLOW0( 2, "done" );
|
||||
}
|
Loading…
Reference in New Issue
Block a user