iBoot/apps/EmbeddedIOP/function_audiodsp/debug_tap.c

135 lines
3.8 KiB
C

/*
* Copyright (C) 2010-2011 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include "debug_tap.h"
#include "timestamper.h"
#include <debug.h>
#include <AssertMacros.h>
#include <platform.h>
#include <platform/timer.h>
#include <sys/task.h>
#include "iop_au_interface.h"
typedef struct
{
uint8_t *IOBufferBegin;
uint8_t *IOBufferEnd;
uint8_t *IOBuffer;
} internal_debug_tap_t;
debug_tap_t create_debug_tap(uint8_t *inIOBegin, uint8_t *inIOEnd, uint8_t *inIO)
{
internal_debug_tap_t *This = (internal_debug_tap_t*)malloc(sizeof(debug_tap_t));
if (This)
{
This->IOBufferBegin = inIOBegin;
This->IOBufferEnd = inIOEnd;
This->IOBuffer = inIO;
}
return This;
}
void destroy_debug_tap(debug_tap_t tap)
{
free(tap);
}
static void clean_cache(void *addr, size_t size)
{
// the onus is on the caller to make sure the cache is aligned
void* lineBase = (void*)((uint32_t)addr & ~(CPU_CACHELINE_SIZE-1));
size_t sizeToDo = ((((uint32_t)addr & (CPU_CACHELINE_SIZE-1)) + size)/CPU_CACHELINE_SIZE + 1) * CPU_CACHELINE_SIZE;
platform_cache_operation(CACHE_CLEAN, lineBase, sizeToDo);
}
static void invalidate_cache(void *addr, size_t size)
{
void* lineBase = (void*)((uint32_t)addr & ~(CPU_CACHELINE_SIZE-1));
size_t sizeToDo = ((((uint32_t)addr & (CPU_CACHELINE_SIZE-1)) + size)/CPU_CACHELINE_SIZE + 1) * CPU_CACHELINE_SIZE;
platform_cache_operation(CACHE_INVALIDATE, lineBase, sizeToDo);
}
static size_t min(size_t a, size_t b) { return (a < b) ? a : b; }
size_t send_to_tap(debug_tap_t tap, const uint8_t* src, uint32_t sizeInBytes)
{
internal_debug_tap_t *This = (internal_debug_tap_t*)tap;
size_t result = 0;
// don't transfer anything to user if sizeInBytes is larger than IOBuffer:
if (sizeInBytes > (uint32_t)(This->IOBufferEnd - This->IOBufferBegin))
return result;
// make sure we don't overflow the IOBuffer
size_t dataToSend = min(This->IOBufferEnd - This->IOBuffer, sizeInBytes);
memcpy(This->IOBuffer, src, dataToSend);
clean_cache(This->IOBuffer, dataToSend);
This->IOBuffer += dataToSend;
src += dataToSend;
if (This->IOBuffer >= This->IOBufferEnd)
{
// if we've wrapped around, send the size of the IOBuffer to the caller
This->IOBuffer = This->IOBufferBegin;
result = This->IOBufferEnd - This->IOBufferBegin;
}
// now that we've sent the data, how much is left
dataToSend = sizeInBytes - dataToSend;
// if there is anything left, send it
if (dataToSend)
{
memcpy(This->IOBuffer, src, dataToSend);
clean_cache(This->IOBuffer, sizeInBytes);
This->IOBuffer += dataToSend;
}
return result;
}
size_t get_from_tap(debug_tap_t tap, uint8_t* dst, uint32_t sizeInBytes)
{
internal_debug_tap_t *This = (internal_debug_tap_t*)tap;
size_t result = 0;
// don't transfer anything to user if sizeInBytes is larger than IOBuffer:
if (sizeInBytes > (uint32_t)(This->IOBufferEnd - This->IOBufferBegin))
return result;
// make sure we don't overflow the IOBuffer
size_t dataToGet = min(This->IOBufferEnd - This->IOBuffer, sizeInBytes);
invalidate_cache(This->IOBuffer, dataToGet);
memcpy(dst, This->IOBuffer, dataToGet);
This->IOBuffer += dataToGet;
dst += dataToGet;
if (This->IOBuffer >= This->IOBufferEnd)
{
// if we've wrapped around, send the size of the IOBuffer to the caller
This->IOBuffer = This->IOBufferBegin;
result = This->IOBufferEnd - This->IOBufferBegin;
}
// now that we've got the data, how much is left
dataToGet = sizeInBytes - dataToGet;
// if there is anything left, get it
if (dataToGet)
{
invalidate_cache(This->IOBuffer, dataToGet);
memcpy(dst, This->IOBuffer, dataToGet);
This->IOBuffer += dataToGet;
}
return result;
}