master.c 3.98 KB
#include "cpusim.h"

typedef struct {
    u8      dummy;                  /* for word aliening */
    u8      txsize;                 /* Tx size */
    u8      rxsize;                 /* Rx size */
    u8      cmd;                    /* commmand */
    u8      typeh;
    u8      typel;
    u8      status;
    u8      dummy1;                  /* for word aliening */
} __OSContRequesFormat;

#define CONT_REQUEST		0
#define CONT_READ		1

void
passed(void) {
    message("test master passed\n");
    test_postamble();
}

void
failed(const char* code) {
    message("test master failed (");
    message(code);
    message(")\n");
    test_postamble();
}

static int
si_write(void* addr) {
    /* dma to SI */
    if (IO_READ(SI_STATUS_REG) & (SI_STATUS_DMA_BUSY | SI_STATUS_RD_BUSY))
	return 1;
    writebackDCache(addr, 32);
    IO_WRITE(SI_DRAM_ADDR_REG, K0_TO_PHYS(addr));
    IO_WRITE(SI_PIF_ADDR_WR64B_REG, PIF_RAM_START);
    while(IO_READ(SI_STATUS_REG) & (SI_STATUS_DMA_BUSY | SI_STATUS_RD_BUSY))
	if (IO_READ(SI_STATUS_REG) & SI_STATUS_DMA_ERROR)
	    return 1;
    IO_WRITE(SI_STATUS_REG, 0);
    return 0;
}

static int
si_read(void* addr) {
    /* dma from SI */
    if (IO_READ(SI_STATUS_REG) & (SI_STATUS_DMA_BUSY | SI_STATUS_RD_BUSY))
	return 1;
    IO_WRITE(SI_DRAM_ADDR_REG, K0_TO_PHYS(addr));
    IO_WRITE(SI_PIF_ADDR_RD64B_REG, PIF_RAM_START);
    while(IO_READ(SI_STATUS_REG) & (SI_STATUS_DMA_BUSY | SI_STATUS_RD_BUSY))
	if (IO_READ(SI_STATUS_REG) & SI_STATUS_DMA_ERROR)
	    return 1;
    IO_WRITE(SI_STATUS_REG, 0);
    invalDCache(addr, 32);
    return 0;
}

static int
check_cont(u8* v, u8 cmd, int active) {
    static const u8 request_response[] = {
	0xff, 0x1, 0x3, 0x0, 0x5, 0x0, 0x0, 0x0,
    };
    static const u8 request_timeout_response[] = {
	0xff, 0x1, 0x83, 0x0, 0xff, 0xff, 0xff, 0xff,
    };
    static const u8 read_response[] = {
	0xff, 0x1, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0,
    };
    static const u8 read_timeout_response[] = {
	0xff, 0x1, 0x84, 0x0, 0xff, 0xff, 0xff, 0xff,
    };
    const u8* w;
    int i;

    if (active == 0)
	w = request_timeout_response;
    else if (active == 1)
	w = request_response;
    else if (active == 2)
	w = read_response;
    else if (active == 3)
	w = read_timeout_response;


    for(i = 0; i < 8; i++) {
	if (i == 3 && v[i] != cmd) return 1;
	else if (i != 3 && w[i] != v[i]) return 1;
    }
    return 0;
}

static void
format_cmd(u8* buf, u8 cmd) {
    int i;

    for(i = 0; i < 4; i++) {
	__OSContRequesFormat* r = (__OSContRequesFormat*)(buf+i*sizeof *r);
	r->dummy = 0xff;
	r->txsize = 1;
	r->rxsize = cmd == CONT_READ ? 4 : 3;
	r->cmd = cmd;
	r->typeh = 0xff;
	r->typel = 0xff;
	r->status = 0xff;
	r->dummy1 = 0xff;
    }
}

int
main() {
    u8* buf = (u8*)K0BASE;
    int i;

    test_preamble();

    initICache();
    initDCache();
    init_ddr();

    setcp0reg(C0_SR, SR_CU0|SR_CU1|SR_BEV);
    setcp0reg(C0_CONFIG, CONFIG_BE|CONFIG_NONCOHRNT);

    IO_WRITE(SI_CONFIG_REG, SI_CONFIG_BUT_ENA |
	                    (1 << SI_CONFIG_JC_DIV_SHIFT) | 
	                    (1 << SI_CONFIG_BUT_RATE_SHIFT));
    IO_WRITE(SI_CTRL_REG, 0);

    format_cmd(buf, CONT_REQUEST);
    if (si_write(buf)) failed("0");
    for(i = 0; i < 32; i++) buf[i] = 0;
    if (si_read(buf)) failed("1");
    if (check_cont(buf, CONT_REQUEST, 1)) failed("2");
    if (check_cont(buf+sizeof(__OSContRequesFormat), CONT_REQUEST, 0)) failed("3");
    if (check_cont(buf+2*sizeof(__OSContRequesFormat), CONT_REQUEST, 0)) failed("4");
    if (check_cont(buf+3*sizeof(__OSContRequesFormat), CONT_REQUEST, 0)) failed("5");

    format_cmd(buf, CONT_READ);
    if (si_write(buf)) failed("6");
    for(i = 0; i < 32; i++) buf[i] = 0;
    if (si_read(buf)) failed("7");
    if (check_cont(buf, CONT_READ, 2)) failed("8");
    if (check_cont(buf+sizeof(__OSContRequesFormat), CONT_READ, 3)) failed("9");
    if (check_cont(buf+2*sizeof(__OSContRequesFormat), CONT_READ, 3)) failed("10");
    if (check_cont(buf+3*sizeof(__OSContRequesFormat), CONT_READ, 3)) failed("11");

    passed();
    test_postamble();
    return 0;
}