nkeynes@248: /** nkeynes@561: * $Id$ nkeynes@248: * nkeynes@248: * IDE interface test cases. Covers all (known) IDE registers in the nkeynes@248: * 5F7000 - 5F74FF range including DMA, but does not cover any GD-Rom nkeynes@248: * device behaviour (ie packet comands). nkeynes@248: * nkeynes@248: * These tests should be run with the drive empty. nkeynes@248: * nkeynes@248: * Copyright (c) 2006 Nathan Keynes. nkeynes@248: * nkeynes@248: * This program is free software; you can redistribute it and/or modify nkeynes@248: * it under the terms of the GNU General Public License as published by nkeynes@248: * the Free Software Foundation; either version 2 of the License, or nkeynes@248: * (at your option) any later version. nkeynes@248: * nkeynes@248: * This program is distributed in the hope that it will be useful, nkeynes@248: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@248: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@248: * GNU General Public License for more details. nkeynes@248: */ nkeynes@248: nkeynes@248: #include nkeynes@248: #include nkeynes@263: #include "testdata.h" nkeynes@248: #include "lib.h" nkeynes@185: #include "ide.h" nkeynes@248: #include "asic.h" nkeynes@248: nkeynes@248: unsigned int test_count = 0, test_failures = 0; nkeynes@248: nkeynes@248: #define IDE_BASE 0xA05F7000 nkeynes@248: nkeynes@248: #define IDE_ALTSTATUS IDE_BASE+0x018 nkeynes@248: #define IDE_UNKNOWN IDE_BASE+0x01C nkeynes@248: #define IDE_DATA IDE_BASE+0x080 /* 16 bits */ nkeynes@248: #define IDE_FEATURE IDE_BASE+0x084 nkeynes@248: #define IDE_COUNT IDE_BASE+0x088 nkeynes@248: #define IDE_LBA0 IDE_BASE+0x08C nkeynes@248: #define IDE_LBA1 IDE_BASE+0x090 nkeynes@248: #define IDE_LBA2 IDE_BASE+0x094 nkeynes@248: #define IDE_DEVICE IDE_BASE+0x098 nkeynes@248: #define IDE_COMMAND IDE_BASE+0x09C nkeynes@248: #define IDE_ACTIVATE IDE_BASE+0x4E4 nkeynes@248: nkeynes@252: #define IDE_DISC IDE_LBA0 nkeynes@248: #define IDE_DEVCONTROL IDE_ALTSTATUS nkeynes@248: #define IDE_ERROR IDE_FEATURE nkeynes@248: #define IDE_STATUS IDE_COMMAND nkeynes@248: nkeynes@248: #define IDE_DMA_ADDR IDE_BASE+0x404 nkeynes@248: #define IDE_DMA_SIZE IDE_BASE+0x408 nkeynes@248: #define IDE_DMA_DIR IDE_BASE+0x40C nkeynes@248: #define IDE_DMA_CTL1 IDE_BASE+0x414 nkeynes@248: #define IDE_DMA_CTL2 IDE_BASE+0x418 nkeynes@248: #define IDE_DMA_MAGIC IDE_BASE+0x4B8 nkeynes@248: #define IDE_DMA_STATUS IDE_BASE+0x4F8 nkeynes@248: nkeynes@248: #define CHECK_REG_EQUALS( a, b, c ) if( b != c ) { fprintf(stderr, "Assertion failed at %s:%d %s(): expected %08X from register %08X, but was %08X\n", __FILE__, __LINE__, __func__, b, a, c ); return -1; } nkeynes@248: nkeynes@248: /* Wait for the standard timeout for an INTRQ. If none is received, print an nkeynes@248: * error and return -1 nkeynes@248: */ nkeynes@248: #define EXPECT_INTRQ() if( ide_wait_irq() != 0 ) { fprintf(stderr, "Timeout at %s:%d %s(): waiting for INTRQ\n", __FILE__, __LINE__, __func__ ); return -1; } nkeynes@248: nkeynes@248: /* Check if the INTRQ line is currently cleared (ie inactive) */ nkeynes@248: #define CHECK_INTRQ_CLEAR() if ( (long_read( ASIC_STATUS1 ) & 1) != 0 ) { fprintf(stderr, "Assertion failed at %s:%d %s(): expected INTRQ to be cleared, but was raised.\n", __FILE__, __LINE__, __func__ ); return -1; } nkeynes@248: nkeynes@248: #define EXPECT_READY() if( ide_wait_ready() != 0 ) { fprintf(stderr, "Timeout at %s:%d %s(): waiting for BSY flag to clear\n", __FILE__, __LINE__, __func__ ); return -1; } nkeynes@248: nkeynes@248: int check_regs( uint32_t *regs,const char *file, int line, const char *fn ) nkeynes@185: { nkeynes@248: int i; nkeynes@248: int rv = 0; nkeynes@248: for( i=0; regs[i] != 0; i+=2 ) { nkeynes@248: uint32_t addr = regs[i]; nkeynes@248: uint32_t val = regs[i+1]; nkeynes@248: uint32_t actual; nkeynes@248: if( addr == IDE_DATA ) { nkeynes@248: actual = (uint32_t)word_read(addr); nkeynes@248: if( val != actual ) { nkeynes@248: fprintf(stderr, "Assertion failed at %s:%d %s(): expected %04X from register %08X, but was %04X\n", file, line, fn, val, addr, actual ); nkeynes@248: rv = -1; nkeynes@248: } nkeynes@248: } else if( addr <= IDE_COMMAND ) { nkeynes@248: actual = (uint32_t)byte_read(addr); nkeynes@248: if( val != actual ) { nkeynes@248: fprintf(stderr, "Assertion failed at %s:%d %s(): expected %02X from register %08X, but was %02X\n", file, line, fn, val, addr, actual ); nkeynes@248: rv = -1; nkeynes@248: } nkeynes@248: } else { nkeynes@248: actual = long_read(addr); nkeynes@248: if( val != actual ) { nkeynes@248: fprintf(stderr, "Assertion failed at %s:%d %s(): expected %08X from register %08X, but was %08X\n", file, line, fn, val, addr, actual ); nkeynes@248: rv = -1; nkeynes@248: } nkeynes@185: } nkeynes@185: } nkeynes@248: return rv; nkeynes@185: } nkeynes@185: nkeynes@248: #define CHECK_REGS( r ) if( check_regs(r, __FILE__, __LINE__, __func__) != 0 ) { return -1; } nkeynes@248: nkeynes@251: nkeynes@251: uint32_t post_packet_ready_regs[] = nkeynes@251: { IDE_ALTSTATUS, 0x58, nkeynes@251: IDE_COUNT, 0x01, nkeynes@251: IDE_LBA1, 8, nkeynes@251: IDE_LBA2, 0, nkeynes@251: IDE_DEVICE, 0, nkeynes@251: IDE_STATUS, 0x58, 0, 0 }; nkeynes@251: nkeynes@251: uint32_t post_packet_cmd_regs[] = nkeynes@251: { IDE_ALTSTATUS, 0xD0, nkeynes@251: IDE_ERROR, 0x00, nkeynes@251: IDE_COUNT, 0x01, nkeynes@251: IDE_LBA1, 8, nkeynes@251: IDE_LBA2, 0, nkeynes@251: IDE_DEVICE, 0, nkeynes@251: IDE_STATUS, 0xD0, 0, 0 }; nkeynes@251: nkeynes@251: uint32_t packet_cmd_error6_regs[] = nkeynes@251: { IDE_ALTSTATUS, 0x51, nkeynes@251: IDE_ERROR, 0x60, nkeynes@251: IDE_COUNT, 0x03, nkeynes@251: IDE_LBA1, 8, nkeynes@251: IDE_LBA2, 0, nkeynes@251: IDE_DEVICE, 0, nkeynes@251: IDE_STATUS, 0x51, 0, 0 }; nkeynes@251: nkeynes@251: uint32_t packet_data_ready_regs[] = nkeynes@251: { IDE_ALTSTATUS, 0x58, nkeynes@251: IDE_ERROR, 0x00, nkeynes@251: IDE_COUNT, 0x02, nkeynes@251: IDE_LBA1, 0x0C, nkeynes@251: IDE_LBA2, 0, nkeynes@251: IDE_DEVICE, 0, nkeynes@251: IDE_STATUS, 0x58, 0, 0 }; nkeynes@251: nkeynes@251: nkeynes@251: uint32_t post_packet_data_regs[] = nkeynes@251: { IDE_ALTSTATUS, 0xD0, nkeynes@251: IDE_ERROR, 0x00, nkeynes@251: IDE_COUNT, 0x02, nkeynes@251: IDE_LBA1, 0x0C, nkeynes@251: IDE_LBA2, 0, nkeynes@251: IDE_DEVICE, 0, nkeynes@251: IDE_STATUS, 0xD0, 0, 0 }; nkeynes@251: nkeynes@251: uint32_t packet_complete_regs[] = nkeynes@251: { IDE_ALTSTATUS, 0x50, nkeynes@251: IDE_ERROR, 0x00, nkeynes@251: IDE_COUNT, 0x03, nkeynes@251: IDE_LBA1, 0x0C, nkeynes@251: IDE_LBA2, 0, nkeynes@251: IDE_DEVICE, 0, nkeynes@251: IDE_STATUS, 0x50, 0, 0 }; nkeynes@251: nkeynes@252: int send_packet_command( const char *cmd ) nkeynes@251: { nkeynes@251: unsigned short *spkt = (unsigned short *)cmd; nkeynes@251: int i; nkeynes@251: nkeynes@251: EXPECT_READY(); nkeynes@251: byte_write( IDE_FEATURE, 0 ); nkeynes@251: byte_write( IDE_COUNT, 0 ); nkeynes@251: byte_write( IDE_LBA0, 0 ); nkeynes@251: byte_write( IDE_LBA1, 8 ); nkeynes@251: byte_write( IDE_LBA2, 0 ); nkeynes@251: byte_write( IDE_DEVICE, 0 ); nkeynes@251: byte_write( IDE_COMMAND, 0xA0 ); nkeynes@251: byte_read(IDE_ALTSTATUS); /* delay 1 PIO cycle */ nkeynes@251: EXPECT_READY(); /* Wait until device is ready to accept command (usually immediate) */ nkeynes@251: CHECK_INTRQ_CLEAR(); nkeynes@251: CHECK_REGS( post_packet_ready_regs ); nkeynes@251: nkeynes@251: /* Write the command */ nkeynes@251: for( i=0; i<6; i++ ) { nkeynes@251: word_write( IDE_DATA, spkt[i] ); nkeynes@251: } nkeynes@251: nkeynes@251: byte_read(IDE_ALTSTATUS); nkeynes@251: nkeynes@251: // CHECK_REGS( post_packet_cmd_regs ); nkeynes@251: EXPECT_INTRQ(); nkeynes@251: EXPECT_READY(); nkeynes@251: return 0; nkeynes@251: } nkeynes@251: nkeynes@252: int read_pio( char *buf, int expected_length ) { nkeynes@252: uint32_t ready_regs[] = { nkeynes@252: IDE_ALTSTATUS, 0x58, nkeynes@252: IDE_ERROR, 0x00, nkeynes@252: IDE_COUNT, 0x02, nkeynes@252: IDE_LBA1, expected_length & 0xFF, nkeynes@252: IDE_LBA2, (expected_length >> 8), nkeynes@252: IDE_DEVICE, 0, nkeynes@252: IDE_STATUS, 0x58, nkeynes@252: 0, 0 }; nkeynes@252: nkeynes@252: int i; nkeynes@252: unsigned short *bufptr = (unsigned short *)buf; nkeynes@252: unsigned int length = 0, avail; nkeynes@252: int status; nkeynes@252: nkeynes@252: CHECK_REGS( ready_regs ); nkeynes@252: for( i=0; i