iBoot/apps/EmbeddedIOP/function_ceata/iop_ceata.c

194 lines
4.8 KiB
C

/*
* Copyright (C) 2008 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.h>
#include <AssertMacros.h>
#include <platform/memmap.h>
#include <platform.h>
#include <sys/task.h>
#include <qwi.h>
#include <EmbeddedIOPProtocol.h>
#include "iop_ceata.h"
#include "iop_ceata_protocol.h"
#include "ceata.h"
static struct task_event ceata_message_event;
static int ceata_channel;
static bool ceata_message_process(void);
static IOPCEATA_status_t ceata_reset(void);
static IOPCEATA_status_t ceata_identify(IOPCEATA_Identify *identify);
static IOPCEATA_status_t ceata_cmd(CEATA_cmd_t cmd);
static IOPCEATA_status_t ceata_io(CEATA_cmd_t cmd,
UInt32 starting_lba,
UInt32 lba_count,
UInt32 segment_count,
IOPCEATA_dma_segment *segments);
int
iop_ceata_task(void *cfg)
{
struct iop_channel_config *channel = (struct iop_channel_config *)cfg;
dprintf(DEBUG_SPEW, "@@ CEATA task starting\n");
check(kIOPCEATA_COMMAND_SIZE == sizeof(IOPCEATA_Command));
/* establish the host communications channel */
event_init(&ceata_message_event, EVENT_FLAG_AUTO_UNSIGNAL, false);
dprintf(DEBUG_SPEW, "** opening ceata channel\n");
ceata_channel = qwi_instantiate_channel(
"ceata command",
QWI_ROLE_CONSUMER,
channel->ring_size,
mem_static_map_cached(channel->ring_base),
(qwi_channel_hook)event_signal,
(void *)&ceata_message_event);
for (;;) {
dprintf(DEBUG_SPEW, "@@ waiting for message on ceata channel\n");
while (ceata_message_process()) {
// eat all available messages
}
event_wait(&ceata_message_event);
}
return(0);
}
static bool
ceata_message_process(void)
{
uint32_t message;
IOPCEATA_Command* command;
dprintf(DEBUG_SPEW, "@@ handling host message\n");
/* look to see if there's an item waiting for us */
if (qwi_receive_item(ceata_channel, &message) == -1)
return(false);
dprintf(DEBUG_SPEW, "@@ received ceata message\n");
/* find the command structure based on the message */
command = (IOPCEATA_Command*)mem_static_map_cached(message);
/*
* Flush any cached item contents we might have lying around - we are guaranteed
* that the command size is a multiple of our cacheline size.
*/
platform_cache_operation(CACHE_INVALIDATE,
(void *)command,
sizeof(*command));
/*
* TODO: make this part of the API and push this
* architecture-specific command handling down into the s5l8920x
* platform directory.
*/
switch (command->iopceata.opcode) {
case kIOPCEATA_OPCODE_RESET:
dprintf(DEBUG_SPEW, "@@ RESET\n");
command->iopceata.status = ceata_reset();
break;
case kIOPCEATA_OPCODE_IDENTIFY:
dprintf(DEBUG_SPEW, "@@ IDENTIFY\n");
command->iopceata.status = ceata_identify((IOPCEATA_Identify *)command);
break;
case kIOPCEATA_OPCODE_READ:
dprintf(DEBUG_SPEW, "@@ READ\n");
command->iopceata.status = ceata_io(
CEATA_READ_DMA_EXT,
command->read_write.starting_lba,
command->read_write.lba_count,
command->read_write.segment_count,
&command->read_write.data_segments[0]);
break;
case kIOPCEATA_OPCODE_WRITE:
dprintf(DEBUG_SPEW, "@@ WRITE\n");
command->iopceata.status = ceata_io(
CEATA_WRITE_DMA_EXT,
command->read_write.starting_lba,
command->read_write.lba_count,
command->read_write.segment_count,
&command->read_write.data_segments[0]);
break;
case kIOPCEATA_OPCODE_STANDBY:
dprintf(DEBUG_SPEW, "@@ STANDBY\n");
command->iopceata.status = ceata_cmd(CEATA_STANDBY_IMMEDIATE);
break;
case kIOPCEATA_OPCODE_FLUSH:
dprintf(DEBUG_SPEW, "@@ FLUSH\n");
command->iopceata.status = ceata_cmd(CEATA_FLUSH_CACHE_EXT);
break;
default:
dprintf(DEBUG_CRITICAL, "@@ ERROR: unrecognised ceata opcode 0x%x",
command->iopceata.opcode);
command->iopceata.status = kIOPCEATA_STATUS_PARAM_INVALID;
break;
}
dprintf(DEBUG_SPEW, "@@ done processing ceata message with status 0x%08x\n", command->iopceata.status);
platform_cache_operation(CACHE_CLEAN,
(void *)command,
sizeof(IOPCEATA_Command));
qwi_send_item(ceata_channel, message);
dprintf(DEBUG_SPEW, "@@ signaled completion of ceata message to host\n");
return(true);
}
static IOPCEATA_status_t
ceata_reset(void)
{
return(kIOPCEATA_STATUS_UNIMPLEMENTED);
}
static IOPCEATA_status_t
ceata_identify(IOPCEATA_Identify *identify)
{
return(kIOPCEATA_STATUS_UNIMPLEMENTED);
}
static IOPCEATA_status_t
ceata_cmd(CEATA_cmd_t cmd)
{
return(kIOPCEATA_STATUS_UNIMPLEMENTED);
}
static IOPCEATA_status_t
ceata_io(CEATA_cmd_t cmd,
UInt32 starting_lba,
UInt32 lba_count,
UInt32 segment_count,
IOPCEATA_dma_segment *segments)
{
return(kIOPCEATA_STATUS_UNIMPLEMENTED);
}