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