filename | test/testide.c |
changeset | 258:8864fae65928 |
prev | 252:cfd0ec3bfeec |
next | 263:6f641270b2aa |
author | nkeynes |
date | Wed Jan 03 09:00:17 2007 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Adjust timers when they're read rather than waiting until the next time slice. Also temporarily cut the CPU time by 4. Initialize the FRQCR register to 0x0E0A for convenience |
view | annotate | diff | log | raw |
1 /**
2 * $Id: testide.c,v 1.5 2006-12-29 00:23: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_DISC IDE_LBA0
46 #define IDE_DEVCONTROL IDE_ALTSTATUS
47 #define IDE_ERROR IDE_FEATURE
48 #define IDE_STATUS IDE_COMMAND
50 #define IDE_DMA_ADDR IDE_BASE+0x404
51 #define IDE_DMA_SIZE IDE_BASE+0x408
52 #define IDE_DMA_DIR IDE_BASE+0x40C
53 #define IDE_DMA_CTL1 IDE_BASE+0x414
54 #define IDE_DMA_CTL2 IDE_BASE+0x418
55 #define IDE_DMA_MAGIC IDE_BASE+0x4B8
56 #define IDE_DMA_STATUS IDE_BASE+0x4F8
58 #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; }
60 /* Wait for the standard timeout for an INTRQ. If none is received, print an
61 * error and return -1
62 */
63 #define EXPECT_INTRQ() if( ide_wait_irq() != 0 ) { fprintf(stderr, "Timeout at %s:%d %s(): waiting for INTRQ\n", __FILE__, __LINE__, __func__ ); return -1; }
65 /* Check if the INTRQ line is currently cleared (ie inactive) */
66 #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; }
68 #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; }
70 int check_regs( uint32_t *regs,const char *file, int line, const char *fn )
71 {
72 int i;
73 int rv = 0;
74 for( i=0; regs[i] != 0; i+=2 ) {
75 uint32_t addr = regs[i];
76 uint32_t val = regs[i+1];
77 uint32_t actual;
78 if( addr == IDE_DATA ) {
79 actual = (uint32_t)word_read(addr);
80 if( val != actual ) {
81 fprintf(stderr, "Assertion failed at %s:%d %s(): expected %04X from register %08X, but was %04X\n", file, line, fn, val, addr, actual );
82 rv = -1;
83 }
84 } else if( addr <= IDE_COMMAND ) {
85 actual = (uint32_t)byte_read(addr);
86 if( val != actual ) {
87 fprintf(stderr, "Assertion failed at %s:%d %s(): expected %02X from register %08X, but was %02X\n", file, line, fn, val, addr, actual );
88 rv = -1;
89 }
90 } else {
91 actual = long_read(addr);
92 if( val != actual ) {
93 fprintf(stderr, "Assertion failed at %s:%d %s(): expected %08X from register %08X, but was %08X\n", file, line, fn, val, addr, actual );
94 rv = -1;
95 }
96 }
97 }
98 return rv;
99 }
101 #define CHECK_REGS( r ) if( check_regs(r, __FILE__, __LINE__, __func__) != 0 ) { return -1; }
104 uint32_t post_packet_ready_regs[] =
105 { IDE_ALTSTATUS, 0x58,
106 IDE_COUNT, 0x01,
107 IDE_LBA1, 8,
108 IDE_LBA2, 0,
109 IDE_DEVICE, 0,
110 IDE_STATUS, 0x58, 0, 0 };
112 uint32_t post_packet_cmd_regs[] =
113 { IDE_ALTSTATUS, 0xD0,
114 IDE_ERROR, 0x00,
115 IDE_COUNT, 0x01,
116 IDE_LBA1, 8,
117 IDE_LBA2, 0,
118 IDE_DEVICE, 0,
119 IDE_STATUS, 0xD0, 0, 0 };
121 uint32_t packet_cmd_error6_regs[] =
122 { IDE_ALTSTATUS, 0x51,
123 IDE_ERROR, 0x60,
124 IDE_COUNT, 0x03,
125 IDE_LBA1, 8,
126 IDE_LBA2, 0,
127 IDE_DEVICE, 0,
128 IDE_STATUS, 0x51, 0, 0 };
130 uint32_t packet_data_ready_regs[] =
131 { IDE_ALTSTATUS, 0x58,
132 IDE_ERROR, 0x00,
133 IDE_COUNT, 0x02,
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_LBA1, 0x0C,
145 IDE_LBA2, 0,
146 IDE_DEVICE, 0,
147 IDE_STATUS, 0xD0, 0, 0 };
149 uint32_t packet_complete_regs[] =
150 { IDE_ALTSTATUS, 0x50,
151 IDE_ERROR, 0x00,
152 IDE_COUNT, 0x03,
153 IDE_LBA1, 0x0C,
154 IDE_LBA2, 0,
155 IDE_DEVICE, 0,
156 IDE_STATUS, 0x50, 0, 0 };
158 int send_packet_command( const char *cmd )
159 {
160 unsigned short *spkt = (unsigned short *)cmd;
161 int i;
163 EXPECT_READY();
164 byte_write( IDE_FEATURE, 0 );
165 byte_write( IDE_COUNT, 0 );
166 byte_write( IDE_LBA0, 0 );
167 byte_write( IDE_LBA1, 8 );
168 byte_write( IDE_LBA2, 0 );
169 byte_write( IDE_DEVICE, 0 );
170 byte_write( IDE_COMMAND, 0xA0 );
171 byte_read(IDE_ALTSTATUS); /* delay 1 PIO cycle */
172 EXPECT_READY(); /* Wait until device is ready to accept command (usually immediate) */
173 CHECK_INTRQ_CLEAR();
174 CHECK_REGS( post_packet_ready_regs );
176 /* Write the command */
177 for( i=0; i<6; i++ ) {
178 word_write( IDE_DATA, spkt[i] );
179 }
181 byte_read(IDE_ALTSTATUS);
183 // CHECK_REGS( post_packet_cmd_regs );
184 EXPECT_INTRQ();
185 EXPECT_READY();
186 return 0;
187 }
189 int read_pio( char *buf, int expected_length ) {
190 uint32_t ready_regs[] = {
191 IDE_ALTSTATUS, 0x58,
192 IDE_ERROR, 0x00,
193 IDE_COUNT, 0x02,
194 IDE_LBA1, expected_length & 0xFF,
195 IDE_LBA2, (expected_length >> 8),
196 IDE_DEVICE, 0,
197 IDE_STATUS, 0x58,
198 0, 0 };
200 int i;
201 unsigned short *bufptr = (unsigned short *)buf;
202 unsigned int length = 0, avail;
203 int status;
205 CHECK_REGS( ready_regs );
206 for( i=0; i<expected_length; i+=2 ) {
207 *bufptr++ = word_read(IDE_DATA);
208 }
210 EXPECT_INTRQ();
211 EXPECT_READY();
212 ready_regs[1] = 0x50;
213 ready_regs[5] = 0x03;
214 ready_regs[13] = 0x50;
215 CHECK_REGS( ready_regs );
216 return 0;
217 }
219 #define IDE_TEST_PACKET_OK( c,e,l ) if( ide_test_packet_ok( __FILE__, __LINE__, __func__, c, e, l ) != 0 ) { return -1; }
220 int ide_test_packet_ok( const char *file, int line, const char *func,
221 const char *cmd, char *expect, int expect_len )
222 {
223 char buf[expect_len];
224 int status = send_packet_command(cmd);
225 if( status != 0 ) {
226 return status;
227 }
228 status = byte_read( IDE_ALTSTATUS );
229 if( status & 1 ) { /* Error */
230 status = ide_get_sense_code();
231 fprintf( stderr, "Assertion failed at %s:%d %s(): Unexpected error %04X\n",
232 file, line, func, status );
233 return -1;
234 }
236 status = read_pio( buf, expect_len );
237 if( status != 0 ) {
238 return status;
239 }
240 if( expect != NULL && memcmp( expect, buf, expect_len ) != 0 ) {
241 fprintf(stderr, "Assertion failed at %s:%d %s(): Results differ from expected:\n",file,line,func );
242 fwrite_diff( stderr, expect, expect_len, buf, expect_len );
243 return -1;
244 }
245 return 0;
246 }
248 #define IDE_TEST_PACKET_ERROR( c,e ) if( ide_test_packet_error( __FILE__, __LINE__, __func__, c, e ) != 0 ) { return -1; }
249 int ide_test_packet_error( char *file, int line, char *func,
250 char *cmd, int expect_error )
251 {
252 uint32_t error_regs[] =
253 { IDE_ALTSTATUS, 0x51,
254 IDE_ERROR, (expect_error & 0x0F)<<4,
255 IDE_COUNT, 0x03,
256 IDE_DEVICE, 0,
257 IDE_STATUS, 0x51, 0, 0 };
258 uint32_t error_code;
259 int status = send_packet_command(cmd);
260 if( status != 0 ) {
261 return status;
262 }
263 CHECK_REGS(error_regs);
264 error_code = ide_get_sense_code();
265 CHECK_IEQUALS( expect_error, error_code );
267 return 0;
268 }
271 uint32_t abort_regs[] = {
272 IDE_ALTSTATUS, 0x51,
273 IDE_ERROR, 0x04,
274 IDE_COUNT, 0x02,
275 IDE_LBA1, 0x00,
276 IDE_LBA2, 0x50,
277 IDE_DEVICE, 0,
278 IDE_DATA, 0x0000,
279 IDE_STATUS, 0x51,
280 0, 0 };
282 uint32_t post_reset_regs[] = {
283 IDE_ALTSTATUS, 0x00,
284 IDE_ERROR, 0x01,
285 IDE_COUNT, 0x01,
286 IDE_LBA1, 0x14,
287 IDE_LBA2, 0xEB,
288 IDE_DEVICE, 0,
289 IDE_DATA, 0xFFFF,
290 IDE_STATUS, 0x00,
291 0, 0 };
293 uint32_t post_set_feature_regs[] = {
294 IDE_ALTSTATUS, 0x50,
295 IDE_ERROR, 0x00,
296 IDE_COUNT, 0x0B,
297 IDE_LBA1, 0x00,
298 IDE_LBA2, 0x00,
299 IDE_DEVICE, 0,
300 IDE_DATA, 0xFFFF,
301 IDE_STATUS, 0x50,
302 0, 0 };
304 uint32_t post_set_feature2_regs[] = {
305 IDE_ALTSTATUS, 0x50,
306 IDE_ERROR, 0x00,
307 IDE_COUNT, 0x22,
308 IDE_LBA1, 0x00,
309 IDE_LBA2, 0x00,
310 IDE_DEVICE, 0,
311 IDE_DATA, 0xFFFF,
312 IDE_STATUS, 0x50,
313 0, 0 };
315 /************************** Interface Tests *******************************/
317 /**
318 * Test enable/disable of the IDE interface via port
319 * 0x4E4.
320 */
321 int test_enable()
322 {
323 int i;
324 int failed = 0;
325 /* ensure deactivated */
326 long_write( IDE_ACTIVATE, 0x00042FE );
328 /* test registers to ensure all return 0xFF (need to wait a few cycles?) */
329 for( i= IDE_BASE; i< IDE_BASE+0x400; i+= 4 ) {
330 CHECK_REG_EQUALS( i, 0xFFFFFFFF, long_read( i ) );
331 }
333 /* enable interface */
334 ide_activate();
336 /* test registers have default settings */
337 // CHECK_REGS( post_reset_regs );
340 /* disable interface and re-test */
341 long_write( IDE_ACTIVATE, 0x00042FE );
343 /* Test registers all 0xFF */
344 for( i= IDE_BASE; i< IDE_BASE+0x400; i+= 4 ) {
345 CHECK_REG_EQUALS( i, 0xFFFFFFFF, long_read( i ) );
346 }
348 /* Finally leave the interface in an enabled state */
349 ide_activate();
350 return 0;
351 }
354 uint32_t drive_ready_regs[] = {
355 IDE_ALTSTATUS, 0x50,
356 IDE_ERROR, 0x00,
357 IDE_COUNT, 0x03,
358 IDE_LBA1, 0x08,
359 IDE_LBA2, 0x00,
360 IDE_DEVICE, 0,
361 IDE_DATA, 0xFFFF,
362 IDE_STATUS, 0x50,
363 0, 0 };
365 /**
366 * Test the reset command
367 */
368 int test_reset()
369 {
370 byte_write( IDE_COMMAND, 0x08 );
371 EXPECT_READY();
372 CHECK_INTRQ_CLEAR();
373 CHECK_REGS( post_reset_regs );
375 /** Set Default PIO mode */
376 byte_write( IDE_FEATURE, 0x03 );
377 byte_write( IDE_COUNT, 0x0B );
378 byte_write( IDE_COMMAND, 0xEF );
379 EXPECT_READY();
380 CHECK_REGS( post_set_feature_regs );
382 /** Set Multi-word DMA mode 2 */
383 long_write( 0xA05F7490, 0x222 );
384 long_write( 0xA05F7494, 0x222 );
385 byte_write( IDE_FEATURE, 0x03 );
386 byte_write( IDE_COUNT, 0x22 );
387 byte_write( IDE_COMMAND, 0xEF );
388 EXPECT_READY();
389 CHECK_INTRQ_CLEAR();
390 CHECK_REGS( post_set_feature2_regs );
392 char test_ready_cmd[12] = { 0,0,0,0, 0,0,0,0, 0,0,0,0 };
393 if( send_packet_command(test_ready_cmd) != 0 ) {
394 return -1;
395 }
397 CHECK_REGS( packet_cmd_error6_regs );
398 int sense = ide_get_sense_code();
399 CHECK_IEQUALS( 0x2906, sense );
401 if( send_packet_command(test_ready_cmd) != 0 ) {
402 return -1;
403 }
404 CHECK_REGS( drive_ready_regs );
405 return 0;
406 }
408 char expect_ident[] = { 0x00, 0xb4, 0x19, 0x00,
409 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20 };
411 /**
412 * Test the PACKET command (using the Inquiry command)
413 */
414 int test_packet()
415 {
416 int i;
417 char cmd[12] = { 0x11, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0 };
418 // char cmd[12] = { 0x00,0,0,0, 0,0,0,0, 0,0,0,0 };
419 unsigned short *spkt;
420 char result[12];
422 send_packet_command( cmd );
423 CHECK_REGS( packet_data_ready_regs );
424 spkt = (unsigned short *)result;
425 *spkt++ = word_read(IDE_DATA);
426 *spkt++ = word_read(IDE_DATA);
427 *spkt++ = word_read(IDE_DATA);
428 *spkt++ = word_read(IDE_DATA);
429 CHECK_REGS( packet_data_ready_regs );
430 *spkt++ = word_read(IDE_DATA);
431 *spkt++ = word_read(IDE_DATA);
432 // CHECK_REGS( post_packet_data_regs );
433 EXPECT_READY();
434 EXPECT_INTRQ();
435 CHECK_REGS( packet_complete_regs );
437 if( memcmp( result, expect_ident, 12 ) != 0 ) {
438 fwrite_diff( stderr, expect_ident, 12, result, 12 );
439 return -1;
440 }
441 return 0;
442 }
444 /**
445 * Test the SET FEATURE command
446 */
447 int test_set_feature()
448 {
449 return 0;
450 }
454 /**
455 * Test DMA transfer (using the Inquiry packet comand)
456 */
457 int test_dma()
458 {
459 return 0;
460 }
462 /**
463 * Test DMA abort
464 */
465 int test_dma_abort()
466 {
467 return 0;
468 }
470 /***************************** GD-Rom Tests **********************************/
472 int test_read_toc()
473 {
474 char cmd[12] = { 0x14,0,0,0x00, 0x0C,0,0,0, 0,0,0,0 };
475 char expect[12] = { 0x41, 0,0, 0x96, 0x41, 0, 0x2E, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF };
477 IDE_TEST_PACKET_OK( cmd, expect, 12 );
478 return 0;
479 }
481 int test_read_pio()
482 {
483 int i,j;
484 char cmd[12] = {0x30, 0x28, 0, 0x2E, 0x4C, 0, 0, 0, 0, 0, 7, 0 };
485 uint32_t read_pio_ready_regs[] =
486 { IDE_ALTSTATUS, 0x58,
487 IDE_ERROR, 0x00,
488 IDE_COUNT, 0x02,
489 IDE_LBA1, 0x00,
490 IDE_LBA2, 0x08,
491 IDE_DEVICE, 0,
492 IDE_STATUS, 0x58, 0, 0 };
494 if( send_packet_command(cmd) != 0 ) {
495 return -1;
496 }
498 for( j=0; j<7; j++ ) {
499 CHECK_REGS(read_pio_ready_regs);
500 CHECK_INTRQ_CLEAR();
501 for( i=0; i<0x0800; i+=2 ) {
502 word_read(IDE_DATA); // throw away for now.
503 }
505 EXPECT_INTRQ();
506 EXPECT_READY();
507 }
509 read_pio_ready_regs[1] = 0x50;
510 read_pio_ready_regs[5] = 0x03;
511 read_pio_ready_regs[13] = 0x50;
512 CHECK_REGS( read_pio_ready_regs );
513 return 0;
514 }
516 /**
517 * Test interaction of Read CD (0x30) with Status (0x40,1)
518 */
519 int test_status1()
520 {
521 char cmd[12] = { 0x40, 0x01, 0, 0, 16,0,0,0, 0,0,0,0 };
522 char read1cmd[12] = { 0x30, 0x28, 0, 0x2E, 0x4C, 0, 0, 0, 0, 0,1,0 };
523 char expect1[16] = { 0,0x15,0,0x0E, 0x41,2,1,0, 0,1,0,0, 0x2E,0x4D,0,0 };
524 char read2cmd[12] = { 0x30, 0x28, 0, 0x2E, 0x4D, 0, 0, 0, 0, 0,1,0 };
525 char expect2[16] = { 0,0x15,0,0x0E, 0x41,2,1,0, 0,4,0,0, 0x2E,0x50,0,0 };
526 char read3cmd[12] = { 0x30, 0x28, 0, 0x2E, 0x4E, 0, 0, 0, 0, 0,1,0 };
527 char expect3[16] = { 0,0x15,0,0x0E, 0x41,2,1,0, 0,5,0,0, 0x2E,0x51,0,0 };
528 char expect4[16] = { 0,0x15,0,0x0E, 0x41,2,1,0, 0,2,0,0, 0x2E,0x4E,0,0 };
529 char read5cmd[12] = { 0x30, 0x28, 0, 0x2F, 0x01, 0, 0, 0, 0, 0,1,0 };
530 char expect5[16] = { 0,0x15,0,0x0E, 0x41,2,1,0, 0,0xB6,0,0, 0x2F,0x02,0,0 };
531 char read6cmd[12] = { 0x30, 0x28, 0, 0x2F, 0x50, 0, 0, 0, 0, 0,1,0 };
532 char expect6[16] = { 0,0x15,0,0x0E, 0x41,2,1,0, 0x01,0x05,0,0, 0x2F,0x51,0,0 };
533 char read7cmd[12] = { 0x30, 0x28, 0, 0x2F, 0x51, 0, 0, 0, 0, 0,1,0 };
534 char expect7[16] = { 0,0x15,0,0x0E, 0x41,2,1,0, 0x01,0x06,0,0, 0x2F,0x52,0,0 };
537 IDE_TEST_PACKET_OK(read1cmd, NULL, 2048);
538 IDE_TEST_PACKET_OK(cmd, expect1, 14 );
539 IDE_TEST_PACKET_OK(read2cmd, NULL, 2048);
540 IDE_TEST_PACKET_OK(cmd, expect2, 14 );
541 IDE_TEST_PACKET_OK(read3cmd, NULL, 2048);
542 IDE_TEST_PACKET_OK(cmd, expect3, 14 );
543 IDE_TEST_PACKET_OK(read2cmd, NULL, 2048);
544 IDE_TEST_PACKET_OK(cmd, expect4, 14 );
545 IDE_TEST_PACKET_OK(read5cmd, NULL, 2048);
546 IDE_TEST_PACKET_OK(cmd, expect5, 14 );
547 IDE_TEST_PACKET_OK(read6cmd, NULL, 2048);
548 IDE_TEST_PACKET_OK(cmd, expect6, 14 );
550 return 0;
551 }
553 /********************************* Main **************************************/
555 typedef int (*test_func_t)();
557 test_func_t test_fns[] = { test_enable, test_reset, test_packet,
558 test_dma, test_dma_abort, test_read_pio,
559 test_read_toc,
560 test_status1, NULL };
562 int main()
563 {
564 int i;
565 ide_init();
567 /* run tests */
568 for( i=0; test_fns[i] != NULL; i++ ) {
569 test_count++;
570 if( test_fns[i]() != 0 ) {
571 fprintf( stderr, "Test %d failed\n", i+1 );
572 test_failures++;
573 }
574 }
576 /* report */
577 fprintf( stderr, "%d/%d tests passed!\n", test_count - test_failures, test_count );
578 return test_failures;
579 }
.