Search
lxdream.org :: lxdream/test/testide.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/testide.c
changeset 251:3c5953d944e0
prev248:f8022f2ef2a2
next252:cfd0ec3bfeec
author nkeynes
date Wed Dec 20 11:24:16 2006 +0000 (13 years ago)
permissions -rw-r--r--
last change Tidy up the core IDE test case - now passes (usually) on the real thing. Main
surprise was that it seems to always fail the first packet command after a
reset with code 06,29 (drive reset), no matter how long its been since the
reset.
view annotate diff log raw
     1 /**
     2  * $Id: testide.c,v 1.3 2006-12-20 11:24:16 nkeynes Exp $
     3  *
     4  * IDE interface test cases. Covers all (known) IDE registers in the 
     5  * 5F7000 - 5F74FF range including DMA, but does not cover any GD-Rom
     6  * device behaviour (ie packet comands).
     7  *
     8  * These tests should be run with the drive empty.
     9  *
    10  * Copyright (c) 2006 Nathan Keynes.
    11  *
    12  * This program is free software; you can redistribute it and/or modify
    13  * it under the terms of the GNU General Public License as published by
    14  * the Free Software Foundation; either version 2 of the License, or
    15  * (at your option) any later version.
    16  *
    17  * This program is distributed in the hope that it will be useful,
    18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    20  * GNU General Public License for more details.
    21  */
    23 #include <stdlib.h>
    24 #include <stdio.h>
    25 #include "lib.h"
    26 #include "ide.h"
    27 #include "asic.h"
    29 unsigned int test_count = 0, test_failures = 0;
    31 #define IDE_BASE 0xA05F7000
    33 #define IDE_ALTSTATUS IDE_BASE+0x018
    34 #define IDE_UNKNOWN   IDE_BASE+0x01C
    35 #define IDE_DATA      IDE_BASE+0x080 /* 16 bits */
    36 #define IDE_FEATURE   IDE_BASE+0x084
    37 #define IDE_COUNT     IDE_BASE+0x088
    38 #define IDE_LBA0      IDE_BASE+0x08C
    39 #define IDE_LBA1      IDE_BASE+0x090
    40 #define IDE_LBA2      IDE_BASE+0x094
    41 #define IDE_DEVICE    IDE_BASE+0x098
    42 #define IDE_COMMAND   IDE_BASE+0x09C
    43 #define IDE_ACTIVATE  IDE_BASE+0x4E4
    45 #define IDE_DEVCONTROL IDE_ALTSTATUS
    46 #define IDE_ERROR      IDE_FEATURE
    47 #define IDE_STATUS     IDE_COMMAND
    49 #define IDE_DMA_ADDR   IDE_BASE+0x404
    50 #define IDE_DMA_SIZE   IDE_BASE+0x408
    51 #define IDE_DMA_DIR    IDE_BASE+0x40C
    52 #define IDE_DMA_CTL1   IDE_BASE+0x414
    53 #define IDE_DMA_CTL2   IDE_BASE+0x418
    54 #define IDE_DMA_MAGIC  IDE_BASE+0x4B8
    55 #define IDE_DMA_STATUS IDE_BASE+0x4F8
    57 #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; }
    59 /* Wait for the standard timeout for an INTRQ. If none is received, print an
    60  * error and return -1
    61  */
    62 #define EXPECT_INTRQ() if( ide_wait_irq() != 0 ) { fprintf(stderr, "Timeout at %s:%d %s(): waiting for INTRQ\n", __FILE__, __LINE__, __func__ ); return -1; }
    64 /* Check if the INTRQ line is currently cleared (ie inactive) */
    65 #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; }
    67 #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; }
    69 int check_regs( uint32_t *regs,const char *file, int line, const char *fn ) 
    70 {
    71     int i;
    72     int rv = 0;
    73     for( i=0; regs[i] != 0; i+=2 ) {
    74 	uint32_t addr = regs[i];
    75 	uint32_t val = regs[i+1];
    76 	uint32_t actual;
    77 	if( addr == IDE_DATA ) {
    78 	    actual = (uint32_t)word_read(addr);
    79 	    if( val != actual ) { 
    80 		fprintf(stderr, "Assertion failed at %s:%d %s(): expected %04X from register %08X, but was %04X\n", file, line, fn, val, addr, actual ); 
    81 		rv = -1;
    82 	    }
    83 	} else if( addr <= IDE_COMMAND ) {
    84 	    actual = (uint32_t)byte_read(addr);
    85 	    if( val != actual ) { 
    86 		fprintf(stderr, "Assertion failed at %s:%d %s(): expected %02X from register %08X, but was %02X\n", file, line, fn, val, addr, actual ); 
    87 		rv = -1;
    88 	    }
    89 	} else {
    90 	    actual = long_read(addr);
    91 	    if( val != actual ) { 
    92 		fprintf(stderr, "Assertion failed at %s:%d %s(): expected %08X from register %08X, but was %08X\n", file, line, fn, val, addr, actual ); 
    93 		rv = -1;
    94 	    }
    95 	}
    96     }
    97     return rv;
    98 }
   100 #define CHECK_REGS( r ) if( check_regs(r, __FILE__, __LINE__, __func__) != 0 ) { return -1; }
   103 uint32_t post_packet_ready_regs[] = 
   104     { IDE_ALTSTATUS, 0x58,
   105       IDE_COUNT, 0x01,
   106       IDE_LBA1, 8,
   107       IDE_LBA2, 0,
   108       IDE_DEVICE, 0,
   109       IDE_STATUS, 0x58, 0, 0 };
   111 uint32_t post_packet_cmd_regs[] = 
   112     { IDE_ALTSTATUS, 0xD0,
   113       IDE_ERROR, 0x00,
   114       IDE_COUNT, 0x01,
   115       IDE_LBA1, 8,
   116       IDE_LBA2, 0,
   117       IDE_DEVICE, 0,
   118       IDE_STATUS, 0xD0, 0, 0 };
   120 uint32_t packet_cmd_error6_regs[] = 
   121     { IDE_ALTSTATUS, 0x51,
   122       IDE_ERROR, 0x60,
   123       IDE_COUNT, 0x03,
   124       IDE_LBA1, 8,
   125       IDE_LBA2, 0,
   126       IDE_DEVICE, 0,
   127       IDE_STATUS, 0x51, 0, 0 };
   129 uint32_t packet_data_ready_regs[] = 
   130     { IDE_ALTSTATUS, 0x58,
   131       IDE_ERROR, 0x00,
   132       IDE_COUNT, 0x02,
   133       IDE_LBA0, 0x00,
   134       IDE_LBA1, 0x0C,
   135       IDE_LBA2, 0,
   136       IDE_DEVICE, 0,
   137       IDE_STATUS, 0x58, 0, 0 };
   140 uint32_t post_packet_data_regs[] = 
   141     { IDE_ALTSTATUS, 0xD0,
   142       IDE_ERROR, 0x00,
   143       IDE_COUNT, 0x02,
   144       IDE_LBA0, 0x00,
   145       IDE_LBA1, 0x0C,
   146       IDE_LBA2, 0,
   147       IDE_DEVICE, 0,
   148       IDE_STATUS, 0xD0, 0, 0 };
   150 uint32_t packet_complete_regs[] = 
   151     { IDE_ALTSTATUS, 0x50,
   152       IDE_ERROR, 0x00,
   153       IDE_COUNT, 0x03,
   154       IDE_LBA1, 0x0C,
   155       IDE_LBA2, 0,
   156       IDE_DEVICE, 0,
   157       IDE_STATUS, 0x50, 0, 0 };
   159 int send_packet_command( char *cmd )
   160 {
   161     unsigned short *spkt = (unsigned short *)cmd;
   162     int i;
   164     EXPECT_READY();
   165     byte_write( IDE_FEATURE, 0 );
   166     byte_write( IDE_COUNT, 0 );
   167     byte_write( IDE_LBA0, 0 );
   168     byte_write( IDE_LBA1, 8 );
   169     byte_write( IDE_LBA2, 0 );
   170     byte_write( IDE_DEVICE, 0 );
   171     byte_write( IDE_COMMAND, 0xA0 );
   172     byte_read(IDE_ALTSTATUS); /* delay 1 PIO cycle */
   173     EXPECT_READY(); /* Wait until device is ready to accept command (usually immediate) */
   174     CHECK_INTRQ_CLEAR();
   175     CHECK_REGS( post_packet_ready_regs );
   177     /* Write the command */
   178     for( i=0; i<6; i++ ) {
   179         word_write( IDE_DATA, spkt[i] );
   180     }
   182     byte_read(IDE_ALTSTATUS); 
   184     // CHECK_REGS( post_packet_cmd_regs );
   185     EXPECT_INTRQ();
   186     EXPECT_READY();
   187     return 0;
   188 }
   191 uint32_t abort_regs[] = {
   192     IDE_ALTSTATUS, 0x51,
   193     IDE_ERROR, 0x04,
   194     IDE_COUNT, 0x02,
   195     IDE_LBA0, 0x06,
   196     IDE_LBA1, 0x00,
   197     IDE_LBA2, 0x50,
   198     IDE_DEVICE, 0,
   199     IDE_DATA, 0x0000,
   200     IDE_STATUS, 0x51, 
   201     0, 0 };
   203 uint32_t post_reset_regs[] = {
   204     IDE_ALTSTATUS, 0x00,
   205     IDE_ERROR, 0x01,
   206     IDE_COUNT, 0x01,
   207     IDE_LBA0, 0x01,
   208     IDE_LBA1, 0x14,
   209     IDE_LBA2, 0xEB,
   210     IDE_DEVICE, 0,
   211     IDE_DATA, 0xFFFF,
   212     IDE_STATUS, 0x00, 
   213     0, 0 };
   215 uint32_t post_set_feature_regs[] = {
   216     IDE_ALTSTATUS, 0x50,
   217     IDE_ERROR, 0x00,
   218     IDE_COUNT, 0x0B,
   219     IDE_LBA0, 0x01,
   220     IDE_LBA1, 0x00,
   221     IDE_LBA2, 0x00,
   222     IDE_DEVICE, 0,
   223     IDE_DATA, 0xFFFF,
   224     IDE_STATUS, 0x50, 
   225     0, 0 };    
   227 uint32_t post_set_feature2_regs[] = {
   228     IDE_ALTSTATUS, 0x50,
   229     IDE_ERROR, 0x00,
   230     IDE_COUNT, 0x22,
   231     IDE_LBA0, 0x01,
   232     IDE_LBA1, 0x00,
   233     IDE_LBA2, 0x00,
   234     IDE_DEVICE, 0,
   235     IDE_DATA, 0xFFFF,
   236     IDE_STATUS, 0x50, 
   237     0, 0 };    
   239 /**
   240  * Test enable/disable of the IDE interface via port
   241  * 0x4E4. 
   242  */
   243 int test_enable()
   244 {
   245     int i;
   246     int failed = 0;
   247     /* ensure deactivated */
   248     long_write( IDE_ACTIVATE, 0x00042FE );
   250     /* test registers to ensure all return 0xFF (need to wait a few cycles?) */
   251     for( i= IDE_BASE; i< IDE_BASE+0x400; i+= 4 ) {
   252 	CHECK_REG_EQUALS( i, 0xFFFFFFFF, long_read( i ) );
   253     }
   255     /* enable interface */
   256     ide_activate();
   258     /* test registers have default settings */
   259     //    CHECK_REGS( post_reset_regs );
   262     /* disable interface and re-test */
   263     long_write( IDE_ACTIVATE, 0x00042FE );
   265     /* Test registers all 0xFF */
   266     for( i= IDE_BASE; i< IDE_BASE+0x400; i+= 4 ) {
   267 	CHECK_REG_EQUALS( i, 0xFFFFFFFF, long_read( i ) );
   268     }
   270     /* Finally leave the interface in an enabled state */
   271     ide_activate();
   272     return 0;
   273 }
   276 uint32_t drive_ready_regs[] = {
   277     IDE_ALTSTATUS, 0x50,
   278     IDE_ERROR, 0x00,
   279     IDE_COUNT, 0x03,
   280     IDE_LBA1, 0x08,
   281     IDE_LBA2, 0x00,
   282     IDE_DEVICE, 0,
   283     IDE_DATA, 0xFFFF,
   284     IDE_STATUS, 0x50, 
   285     0, 0 };    
   287 /**
   288  * Test the reset command
   289  */
   290 int test_reset()
   291 {
   292     byte_write( IDE_COMMAND, 0x08 );
   293     EXPECT_READY();
   294     CHECK_INTRQ_CLEAR();
   295     CHECK_REGS( post_reset_regs );
   297     /** Set Default PIO mode */
   298     byte_write( IDE_FEATURE, 0x03 );
   299     byte_write( IDE_COUNT, 0x0B );
   300     byte_write( IDE_COMMAND, 0xEF );
   301     EXPECT_READY();
   302     CHECK_INTRQ_CLEAR();
   303     CHECK_REGS( post_set_feature_regs );
   305     /** Set Multi-word DMA mode 2 */
   306     long_write( 0xA05F7490, 0x222 );
   307     long_write( 0xA05F7494, 0x222 );
   308     byte_write( IDE_FEATURE, 0x03 );
   309     byte_write( IDE_COUNT, 0x22 );
   310     byte_write( IDE_COMMAND, 0xEF );
   311     EXPECT_READY();
   312     CHECK_INTRQ_CLEAR();
   313     CHECK_REGS( post_set_feature2_regs );
   315     char test_ready_cmd[12] = { 0,0,0,0, 0,0,0,0, 0,0,0,0 };
   316     if( send_packet_command(test_ready_cmd) != 0 ) {
   317 	return -1;
   318     }
   320     CHECK_REGS( packet_cmd_error6_regs );
   321     int sense = ide_get_sense_code();
   322     CHECK_IEQUALS( 0x2906, sense );
   324     if( send_packet_command(test_ready_cmd) != 0 ) {
   325 	return -1;
   326     }
   327     CHECK_REGS( drive_ready_regs );
   328     return 0;
   329 }
   331 char expect_ident[] = { 0x00, 0xb4, 0x19, 0x00,
   332 			0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20 };
   334 /**
   335  * Test the PACKET command (using the Inquiry command)
   336  */
   337 int test_packet()
   338 {
   339     int i;
   340     char cmd[12] = { 0x11, 0, 4, 0,  12, 0, 0, 0,  0, 0, 0, 0 };
   341     // char cmd[12] = { 0x00,0,0,0, 0,0,0,0, 0,0,0,0 };
   342     unsigned short *spkt;
   343     char result[12];
   345     send_packet_command( cmd );
   346     CHECK_REGS( packet_data_ready_regs );
   347     spkt = (unsigned short *)result;
   348     *spkt++ = word_read(IDE_DATA);
   349     *spkt++ = word_read(IDE_DATA);
   350     *spkt++ = word_read(IDE_DATA);
   351     *spkt++ = word_read(IDE_DATA);
   352     CHECK_REGS( packet_data_ready_regs );
   353     *spkt++ = word_read(IDE_DATA);
   354     *spkt++ = word_read(IDE_DATA);
   355     CHECK_REGS( post_packet_data_regs );
   356     EXPECT_READY();
   357     EXPECT_INTRQ();
   358     CHECK_REGS( packet_complete_regs );
   360     if( memcmp( result, expect_ident, 12 ) != 0 ) {
   361 	fwrite_diff( stderr, expect_ident, 12, result, 12 );
   362     }
   363     return 0;
   364 }
   366 /**
   367  * Test the SET FEATURE command
   368  */
   369 int test_set_feature()
   370 {
   371     return 0;
   372 }
   374 /**
   375  * Test DMA transfer (using the Inquiry packet comand)
   376  */
   377 int test_dma()
   378 {
   379     return 0;
   380 }
   382 /**
   383  * Test DMA abort
   384  */
   385 int test_dma_abort()
   386 {
   387     return 0;
   388 }
   390 typedef int (*test_func_t)();
   392 test_func_t test_fns[] = { test_enable, test_reset, test_packet,
   393 			   test_dma, test_dma_abort, NULL };
   395 int main() 
   396 {
   397     int i;
   398     ide_init();
   400     /* run tests */
   401     for( i=0; test_fns[i] != NULL; i++ ) {
   402 	test_count++;
   403 	if( test_fns[i]() != 0 ) {
   404 	    test_failures++;
   405 	}
   406     }
   408     /* report */
   409     fprintf( stderr, "%d/%d tests passed!\n", test_count - test_failures, test_count );
   410     return test_failures;
   411 }
.