Search
lxdream.org :: lxdream/test/testide.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename test/testide.c
changeset 248:f8022f2ef2a2
prev185:6755a04c447f
next251:3c5953d944e0
author nkeynes
date Tue Dec 19 11:53:39 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change IDE system test work-in-progress
file annotate diff log raw
1.1 --- a/test/testide.c Tue Jul 11 01:35:27 2006 +0000
1.2 +++ b/test/testide.c Tue Dec 19 11:53:39 2006 +0000
1.3 @@ -1,90 +1,377 @@
1.4 -#include <assert.h>
1.5 -#include <ctype.h>
1.6 +/**
1.7 + * $Id: testide.c,v 1.2 2006-12-19 11:53:39 nkeynes Exp $
1.8 + *
1.9 + * IDE interface test cases. Covers all (known) IDE registers in the
1.10 + * 5F7000 - 5F74FF range including DMA, but does not cover any GD-Rom
1.11 + * device behaviour (ie packet comands).
1.12 + *
1.13 + * These tests should be run with the drive empty.
1.14 + *
1.15 + * Copyright (c) 2006 Nathan Keynes.
1.16 + *
1.17 + * This program is free software; you can redistribute it and/or modify
1.18 + * it under the terms of the GNU General Public License as published by
1.19 + * the Free Software Foundation; either version 2 of the License, or
1.20 + * (at your option) any later version.
1.21 + *
1.22 + * This program is distributed in the hope that it will be useful,
1.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.25 + * GNU General Public License for more details.
1.26 + */
1.27 +
1.28 +#include <stdlib.h>
1.29 +#include <stdio.h>
1.30 +#include "lib.h"
1.31 #include "ide.h"
1.32 -void debug_dump_buffer(char *buf, int length)
1.33 +#include "asic.h"
1.34 +
1.35 +unsigned int test_count = 0, test_failures = 0;
1.36 +
1.37 +#define IDE_BASE 0xA05F7000
1.38 +
1.39 +#define IDE_ALTSTATUS IDE_BASE+0x018
1.40 +#define IDE_UNKNOWN IDE_BASE+0x01C
1.41 +#define IDE_DATA IDE_BASE+0x080 /* 16 bits */
1.42 +#define IDE_FEATURE IDE_BASE+0x084
1.43 +#define IDE_COUNT IDE_BASE+0x088
1.44 +#define IDE_LBA0 IDE_BASE+0x08C
1.45 +#define IDE_LBA1 IDE_BASE+0x090
1.46 +#define IDE_LBA2 IDE_BASE+0x094
1.47 +#define IDE_DEVICE IDE_BASE+0x098
1.48 +#define IDE_COMMAND IDE_BASE+0x09C
1.49 +#define IDE_ACTIVATE IDE_BASE+0x4E4
1.50 +
1.51 +#define IDE_DEVCONTROL IDE_ALTSTATUS
1.52 +#define IDE_ERROR IDE_FEATURE
1.53 +#define IDE_STATUS IDE_COMMAND
1.54 +
1.55 +#define IDE_DMA_ADDR IDE_BASE+0x404
1.56 +#define IDE_DMA_SIZE IDE_BASE+0x408
1.57 +#define IDE_DMA_DIR IDE_BASE+0x40C
1.58 +#define IDE_DMA_CTL1 IDE_BASE+0x414
1.59 +#define IDE_DMA_CTL2 IDE_BASE+0x418
1.60 +#define IDE_DMA_MAGIC IDE_BASE+0x4B8
1.61 +#define IDE_DMA_STATUS IDE_BASE+0x4F8
1.62 +
1.63 +#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; }
1.64 +
1.65 +/* Wait for the standard timeout for an INTRQ. If none is received, print an
1.66 + * error and return -1
1.67 + */
1.68 +#define EXPECT_INTRQ() if( ide_wait_irq() != 0 ) { fprintf(stderr, "Timeout at %s:%d %s(): waiting for INTRQ\n", __FILE__, __LINE__, __func__ ); return -1; }
1.69 +
1.70 +/* Check if the INTRQ line is currently cleared (ie inactive) */
1.71 +#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; }
1.72 +
1.73 +#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; }
1.74 +
1.75 +int check_regs( uint32_t *regs,const char *file, int line, const char *fn )
1.76 {
1.77 - int i,j;
1.78 - for( i=0; i<length; i+=16 ) {
1.79 - printf( "%08X: ", i );
1.80 - for( j=0; j<16 && i+j < length; j+=4 ) {
1.81 - unsigned int val = *((volatile unsigned int *)(buf+i+j));
1.82 - printf( "%02X %02X %02X %02X ", val&0xFF, (val>>8)&0xFF, (val>>16)&0xFF, (val>>24)&0xFF );
1.83 - }
1.84 - for( j=0; j<16 && i+j < length; j++ ) {
1.85 - printf( "%c", isprint(buf[i+j]) ? buf[i+j] : '.' );
1.86 + int i;
1.87 + int rv = 0;
1.88 + for( i=0; regs[i] != 0; i+=2 ) {
1.89 + uint32_t addr = regs[i];
1.90 + uint32_t val = regs[i+1];
1.91 + uint32_t actual;
1.92 + if( addr == IDE_DATA ) {
1.93 + actual = (uint32_t)word_read(addr);
1.94 + if( val != actual ) {
1.95 + fprintf(stderr, "Assertion failed at %s:%d %s(): expected %04X from register %08X, but was %04X\n", file, line, fn, val, addr, actual );
1.96 + rv = -1;
1.97 + }
1.98 + } else if( addr <= IDE_COMMAND ) {
1.99 + actual = (uint32_t)byte_read(addr);
1.100 + if( val != actual ) {
1.101 + fprintf(stderr, "Assertion failed at %s:%d %s(): expected %02X from register %08X, but was %02X\n", file, line, fn, val, addr, actual );
1.102 + rv = -1;
1.103 + }
1.104 + } else {
1.105 + actual = long_read(addr);
1.106 + if( val != actual ) {
1.107 + fprintf(stderr, "Assertion failed at %s:%d %s(): expected %08X from register %08X, but was %08X\n", file, line, fn, val, addr, actual );
1.108 + rv = -1;
1.109 + }
1.110 }
1.111 - printf("\n");
1.112 }
1.113 + return rv;
1.114 }
1.115
1.116 -void debug_dump_int_buffer(volatile char *buf, int length)
1.117 +#define CHECK_REGS( r ) if( check_regs(r, __FILE__, __LINE__, __func__) != 0 ) { return -1; }
1.118 +
1.119 +uint32_t abort_regs[] = {
1.120 + IDE_ALTSTATUS, 0x51,
1.121 + IDE_ERROR, 0x04,
1.122 + IDE_COUNT, 0x02,
1.123 + IDE_LBA0, 0x06,
1.124 + IDE_LBA1, 0x00,
1.125 + IDE_LBA2, 0x50,
1.126 + IDE_DEVICE, 0,
1.127 + IDE_DATA, 0x0000,
1.128 + IDE_STATUS, 0x51,
1.129 + 0, 0 };
1.130 +
1.131 +uint32_t post_reset_regs[] = {
1.132 + IDE_ALTSTATUS, 0x00,
1.133 + IDE_ERROR, 0x01,
1.134 + IDE_COUNT, 0x01,
1.135 + IDE_LBA0, 0x01,
1.136 + IDE_LBA1, 0x14,
1.137 + IDE_LBA2, 0xEB,
1.138 + IDE_DEVICE, 0,
1.139 + IDE_DATA, 0xFFFF,
1.140 + IDE_STATUS, 0x00,
1.141 + 0, 0 };
1.142 +
1.143 +uint32_t post_set_feature_regs[] = {
1.144 + IDE_ALTSTATUS, 0x50,
1.145 + IDE_ERROR, 0x00,
1.146 + IDE_COUNT, 0x0B,
1.147 + IDE_LBA0, 0x01,
1.148 + IDE_LBA1, 0x00,
1.149 + IDE_LBA2, 0x00,
1.150 + IDE_DEVICE, 0,
1.151 + IDE_DATA, 0xFFFF,
1.152 + IDE_STATUS, 0x50,
1.153 + 0, 0 };
1.154 +
1.155 +uint32_t post_set_feature2_regs[] = {
1.156 + IDE_ALTSTATUS, 0x50,
1.157 + IDE_ERROR, 0x00,
1.158 + IDE_COUNT, 0x22,
1.159 + IDE_LBA0, 0x01,
1.160 + IDE_LBA1, 0x00,
1.161 + IDE_LBA2, 0x00,
1.162 + IDE_DEVICE, 0,
1.163 + IDE_DATA, 0xFFFF,
1.164 + IDE_STATUS, 0x50,
1.165 + 0, 0 };
1.166 +
1.167 +/**
1.168 + * Test enable/disable of the IDE interface via port
1.169 + * 0x4E4.
1.170 + */
1.171 +int test_enable()
1.172 {
1.173 - int i,j;
1.174 - for( i=0; i<length; i+=16 ) {
1.175 - printf( "%08X:", i );
1.176 - for( j=0; j<16 && i+j < length; j+=4 ) {
1.177 - printf( " %08X", *((volatile unsigned int *)(buf+i+j)) );
1.178 - }
1.179 - printf( "\n" );
1.180 - }
1.181 -}
1.182 + int i;
1.183 + int failed = 0;
1.184 + /* ensure deactivated */
1.185 + long_write( IDE_ACTIVATE, 0x00042FE );
1.186
1.187 -
1.188 -char buf[2048*7 + 32];
1.189 -
1.190 -int test_ide_read_bootstrap()
1.191 -{
1.192 - struct gdrom_session session;
1.193 - int length;
1.194 - char *p;
1.195 -
1.196 - ide_init();
1.197 -
1.198 - if( ide_test_ready() != 0 ) {
1.199 - printf( "ERROR - Test ready failed\n" );
1.200 - return -1;
1.201 + /* test registers to ensure all return 0xFF (need to wait a few cycles?) */
1.202 + for( i= IDE_BASE; i< IDE_BASE+0x400; i+= 4 ) {
1.203 + CHECK_REG_EQUALS( i, 0xFFFFFFFF, long_read( i ) );
1.204 }
1.205
1.206 - if( ide_spinup() != 0 ) {
1.207 - printf( "ERROR - Spinup failed\n" );
1.208 - return -1;
1.209 + /* enable interface */
1.210 + ide_activate();
1.211 +
1.212 + /* test registers have default settings */
1.213 + // CHECK_REGS( post_reset_regs );
1.214 +
1.215 +
1.216 + /* disable interface and re-test */
1.217 + long_write( IDE_ACTIVATE, 0x00042FE );
1.218 +
1.219 + /* Test registers all 0xFF */
1.220 + for( i= IDE_BASE; i< IDE_BASE+0x400; i+= 4 ) {
1.221 + CHECK_REG_EQUALS( i, 0xFFFFFFFF, long_read( i ) );
1.222 }
1.223
1.224 - /*
1.225 - length = ide_unknown71( buf, sizeof(buf) );
1.226 - if( length == -1 ) {
1.227 - printf( "ERROR - 0x71 failed\n" );
1.228 - ide_print_sense_error();
1.229 - return -1;
1.230 - }
1.231 - debug_dump_buffer(buf,length);
1.232 - */
1.233 - if( ide_get_session( 0, &session ) == -1 ) {
1.234 - printf( "ERROR - Get session(0) failed\n" );
1.235 - return -1;
1.236 - }
1.237 - if( ide_get_session( session.track, &session ) == -1 ) {
1.238 - printf( "ERROR - Get session(%d) failed\n", session.track );
1.239 - return -1;
1.240 - }
1.241 -
1.242 - p = (char *)((((unsigned int)buf) & 0xFFFFFFE0) + 0x20);
1.243 - printf( "--- DMA buffer: %08X\n", p );
1.244 - length = ide_read_sector_dma( session.lba, 2, 0x28, p, 2048*2 );
1.245 - if( length != 2048*2 ) {
1.246 - printf( "ERROR - Got incorrect read length, expected %d but was %d\n", 2048, length );
1.247 - return -1;
1.248 - }
1.249 - debug_dump_buffer( p, 2048*2 );
1.250 -
1.251 + /* Finally leave the interface in an enabled state */
1.252 + ide_activate();
1.253 return 0;
1.254 }
1.255
1.256 +/**
1.257 + * Test the reset command
1.258 + */
1.259 +int test_reset()
1.260 +{
1.261 + byte_write( IDE_COMMAND, 0x08 );
1.262 + EXPECT_READY();
1.263 + CHECK_INTRQ_CLEAR();
1.264 + CHECK_REGS( post_reset_regs );
1.265 +
1.266 + /** Set Default PIO mode */
1.267 + byte_write( IDE_FEATURE, 0x03 );
1.268 + byte_write( IDE_COUNT, 0x0B );
1.269 + byte_write( IDE_COMMAND, 0xEF );
1.270 + EXPECT_READY();
1.271 + CHECK_INTRQ_CLEAR();
1.272 + CHECK_REGS( post_set_feature_regs );
1.273 +
1.274 + /** Set Multi-word DMA mode 2 */
1.275 + long_write( 0xA05F7490, 0x222 );
1.276 + long_write( 0xA05F7494, 0x222 );
1.277 + byte_write( IDE_FEATURE, 0x03 );
1.278 + byte_write( IDE_COUNT, 0x22 );
1.279 + byte_write( IDE_COMMAND, 0xEF );
1.280 + EXPECT_READY();
1.281 + CHECK_INTRQ_CLEAR();
1.282 + CHECK_REGS( post_set_feature2_regs );
1.283
1.284 -int main( int argc, char *argv[] )
1.285 + return 0;
1.286 +}
1.287 +
1.288 +uint32_t post_packet_ready_regs[] =
1.289 + { IDE_ALTSTATUS, 0x58,
1.290 + IDE_ERROR, 0x00,
1.291 + IDE_COUNT, 0x01,
1.292 + IDE_LBA0, 0x00,
1.293 + IDE_LBA1, 8,
1.294 + IDE_LBA2, 0,
1.295 + IDE_DEVICE, 0,
1.296 + IDE_STATUS, 0x58, 0, 0 };
1.297 +
1.298 +uint32_t post_packet_cmd_regs[] =
1.299 + { IDE_ALTSTATUS, 0xD0,
1.300 + IDE_ERROR, 0x00,
1.301 + IDE_COUNT, 0x01,
1.302 + IDE_LBA1, 8,
1.303 + IDE_LBA2, 0,
1.304 + IDE_DEVICE, 0,
1.305 + IDE_STATUS, 0xD0, 0, 0 };
1.306 +
1.307 +uint32_t packet_cmd_error6_regs[] =
1.308 + { IDE_ALTSTATUS, 0x51,
1.309 + IDE_ERROR, 0x60,
1.310 + IDE_COUNT, 0x03,
1.311 + IDE_LBA1, 8,
1.312 + IDE_LBA2, 0,
1.313 + IDE_DEVICE, 0,
1.314 + IDE_STATUS, 0x51, 0, 0 };
1.315 +
1.316 +uint32_t packet_data_ready_regs[] =
1.317 + { IDE_ALTSTATUS, 0x58,
1.318 + IDE_ERROR, 0x00,
1.319 + IDE_COUNT, 0x02,
1.320 + IDE_LBA0, 0x00,
1.321 + IDE_LBA1, 0x0C,
1.322 + IDE_LBA2, 0,
1.323 + IDE_DEVICE, 0,
1.324 + IDE_STATUS, 0x58, 0, 0 };
1.325 +
1.326 +
1.327 +uint32_t post_packet_data_regs[] =
1.328 + { IDE_ALTSTATUS, 0xD0,
1.329 + IDE_ERROR, 0x00,
1.330 + IDE_COUNT, 0x02,
1.331 + IDE_LBA0, 0x00,
1.332 + IDE_LBA1, 0x0C,
1.333 + IDE_LBA2, 0,
1.334 + IDE_DEVICE, 0,
1.335 + IDE_STATUS, 0xD0, 0, 0 };
1.336 +
1.337 +uint32_t packet_complete_regs[] =
1.338 + { IDE_ALTSTATUS, 0x50,
1.339 + IDE_ERROR, 0x00,
1.340 + IDE_COUNT, 0x03,
1.341 + IDE_LBA1, 0x0C,
1.342 + IDE_LBA2, 0,
1.343 + IDE_DEVICE, 0,
1.344 + IDE_STATUS, 0x50, 0, 0 };
1.345 +
1.346 +char expect_ident[] = { 0x00, 0xb4, 0x19, 0x00,
1.347 + 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20 };
1.348 +/**
1.349 + * Test the PACKET command (using the Inquiry command)
1.350 + */
1.351 +int test_packet()
1.352 {
1.353 - ide_dump_registers();
1.354 - ide_spinup();
1.355 - ide_read_something();
1.356 -// test_ide_read_bootstrap();
1.357 + int i;
1.358 + char cmd[12] = { 0x11, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0 };
1.359 + // char cmd[12] = { 0x00,0,0,0, 0,0,0,0, 0,0,0,0 };
1.360 + unsigned short *spkt = (unsigned short *)cmd;
1.361 + char result[12];
1.362 +
1.363 + ide_print_sense_error();
1.364 + EXPECT_READY();
1.365 + byte_write( IDE_FEATURE, 0 );
1.366 + byte_write( IDE_COUNT, 0 );
1.367 + byte_write( IDE_LBA0, 0 );
1.368 + byte_write( IDE_LBA1, 8 );
1.369 + byte_write( IDE_LBA2, 0 );
1.370 + byte_write( IDE_DEVICE, 0 );
1.371 + byte_write( IDE_COMMAND, 0xA0 );
1.372 + byte_read(IDE_ALTSTATUS); /* delay 1 PIO cycle */
1.373 + EXPECT_READY(); /* Wait until device is ready to accept command (usually immediate) */
1.374 + CHECK_INTRQ_CLEAR();
1.375 + CHECK_REGS( post_packet_ready_regs );
1.376 +
1.377 + /* Write the command */
1.378 + for( i=0; i<6; i++ ) {
1.379 + word_write( IDE_DATA, spkt[i] );
1.380 + }
1.381 +
1.382 + byte_read(IDE_ALTSTATUS);
1.383 +
1.384 + CHECK_REGS( post_packet_cmd_regs );
1.385 + EXPECT_INTRQ();
1.386 + EXPECT_READY();
1.387 + CHECK_REGS( packet_data_ready_regs );
1.388 +
1.389 + spkt = (unsigned short *)result;
1.390 + *spkt++ = word_read(IDE_DATA);
1.391 + *spkt++ = word_read(IDE_DATA);
1.392 + *spkt++ = word_read(IDE_DATA);
1.393 + *spkt++ = word_read(IDE_DATA);
1.394 + CHECK_REGS( packet_data_ready_regs );
1.395 + *spkt++ = word_read(IDE_DATA);
1.396 + *spkt++ = word_read(IDE_DATA);
1.397 + CHECK_REGS( post_packet_data_regs );
1.398 + EXPECT_READY();
1.399 + CHECK_INTRQ_CLEAR();
1.400 + CHECK_REGS( packet_complete_regs );
1.401 + if( memcmp( result, expect_ident, 12 ) != 0 ) {
1.402 + fwrite_diff( stderr, expect_ident, 12, result, 12 );
1.403 + }
1.404 + return 0;
1.405 }
1.406 +
1.407 +/**
1.408 + * Test the SET FEATURE command
1.409 + */
1.410 +int test_set_feature()
1.411 +{
1.412 + return 0;
1.413 +}
1.414 +
1.415 +/**
1.416 + * Test DMA transfer (using the Inquiry packet comand)
1.417 + */
1.418 +int test_dma()
1.419 +{
1.420 + return 0;
1.421 +}
1.422 +
1.423 +/**
1.424 + * Test DMA abort
1.425 + */
1.426 +int test_dma_abort()
1.427 +{
1.428 + return 0;
1.429 +}
1.430 +
1.431 +typedef int (*test_func_t)();
1.432 +
1.433 +test_func_t test_fns[] = { test_packet, test_enable, test_reset,
1.434 + test_dma, test_dma_abort, NULL };
1.435 +
1.436 +int main()
1.437 +{
1.438 + int i;
1.439 + ide_init();
1.440 +
1.441 + /* run tests */
1.442 + for( i=0; test_fns[i] != NULL; i++ ) {
1.443 + test_count++;
1.444 + if( test_fns[i]() != 0 ) {
1.445 + test_failures++;
1.446 + }
1.447 + }
1.448 +
1.449 + /* report */
1.450 + fprintf( stderr, "%d/%d tests passed!\n", test_count - test_failures, test_count );
1.451 + return test_failures;
1.452 +}
.