/*
 * Copyright (C) 2008 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the 
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <boot/boot.h>

#define STATUS_NOMSG 0
#define STATUS_OKAY  1
#define STATUS_FAIL  2
#define STATUS_PRINT 3

void jtag_hook();

volatile unsigned _jtag_cmd = 0;
volatile unsigned _jtag_msg = 0;
unsigned char _jtag_cmd_buffer[128];
unsigned char _jtag_msg_buffer[128];

volatile unsigned _jtag_arg0 = 0;
volatile unsigned _jtag_arg1 = 0;
volatile unsigned _jtag_arg2 = 0;

static void jtag_msg(unsigned status, const char *msg)
{
    unsigned char *out = _jtag_msg_buffer;
    while((*out++ = *msg++) != 0) ;
    _jtag_msg = status;
    do {
        jtag_hook();
    } while(_jtag_msg != 0);
}

void jtag_okay(const char *msg)
{
    if(msg == 0) msg = "OKAY";
    jtag_msg(STATUS_OKAY, msg);
}

void jtag_fail(const char *msg)
{
    if(msg == 0) msg = "FAIL";
    jtag_msg(STATUS_FAIL, msg);
}

int jtag_cmd_pending()
{
    jtag_hook();
    return (int) _jtag_cmd;
}

void jtag_cmd_loop(void (*do_cmd)(const char *, unsigned, unsigned, unsigned))
{
    unsigned n;
    for(;;) {
        if(jtag_cmd_pending()){
            do_cmd((const char*) _jtag_cmd_buffer, _jtag_arg0, _jtag_arg1, _jtag_arg2);
            for(n = 0; n < 256; n++) _jtag_cmd_buffer[n] = 0;
            _jtag_arg0 = 0;
            _jtag_arg1 = 0;
            _jtag_arg2 = 0;
            _jtag_cmd = 0;
        }
    }
}

static char jtag_putc_buffer[128];
static unsigned jtag_putc_count = 0;

static void jtag_push_buffer(void)
{
    jtag_putc_buffer[jtag_putc_count] = 0;
    jtag_putc_count = 0;
    jtag_msg(STATUS_PRINT, jtag_putc_buffer);
}
    
void jtag_dputc(unsigned c)
{
    if((c < 32) || (c > 127)) {
        if(c == '\n') {
            jtag_push_buffer();
        }
        return;
    }
        
    jtag_putc_buffer[jtag_putc_count++] = c;
    if(jtag_putc_count == 127) {
        jtag_push_buffer();
    }
}

