Search
lxdream.org :: lxdream/test/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/ide.c
changeset 251:3c5953d944e0
prev247:b356d391d02a
author nkeynes
date Sat Dec 27 02:59:35 2008 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode,
which tracks the field of the same name in sh4r - actually a little faster this way.
Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR
flag yet).

Also fixed the failure to check the flags in the common case (code address returned
by previous block) which took away the performance benefits, but oh well.
view annotate diff log raw
     1 #include <assert.h>
     2 #include <stdlib.h>
     3 #include "ide.h"
     4 #include "lib.h"
     6 #define IDE_BASE 0xA05F7000
     8 #define IDE_ALTSTATUS IDE_BASE+0x018
     9 #define IDE_UNKNOWN   IDE_BASE+0x01C
    10 #define IDE_DATA      IDE_BASE+0x080 /* 16 bits */
    11 #define IDE_FEATURE   IDE_BASE+0x084
    12 #define IDE_COUNT     IDE_BASE+0x088
    13 #define IDE_LBA0      IDE_BASE+0x08C
    14 #define IDE_LBA1      IDE_BASE+0x090
    15 #define IDE_LBA2      IDE_BASE+0x094
    16 #define IDE_DEVICE    IDE_BASE+0x098
    17 #define IDE_COMMAND   IDE_BASE+0x09C
    18 #define IDE_ACTIVATE  IDE_BASE+0x4E4
    20 #define IDE_DEVCONTROL IDE_ALTSTATUS
    21 #define IDE_ERROR      IDE_FEATURE
    22 #define IDE_STATUS     IDE_COMMAND
    24 #define IDE_DMA_ADDR   IDE_BASE+0x404
    25 #define IDE_DMA_SIZE   IDE_BASE+0x408
    26 #define IDE_DMA_DIR    IDE_BASE+0x40C
    27 #define IDE_DMA_CTL1   IDE_BASE+0x414
    28 #define IDE_DMA_CTL2   IDE_BASE+0x418
    29 #define IDE_DMA_MAGIC  IDE_BASE+0x4B8
    30 #define IDE_DMA_STATUS IDE_BASE+0x4F8
    32 #define DMA_BASE 0xFFA00000
    33 #define DMA_SAR1    DMA_BASE+0x010
    34 #define DMA_DAR1    DMA_BASE+0x014
    35 #define DMA_TCR1    DMA_BASE+0x018
    36 #define DMA_CHCR1   DMA_BASE+0x01C
    37 #define DMA_SAR2    DMA_BASE+0x020
    38 #define DMA_DAR2    DMA_BASE+0x024
    39 #define DMA_TCR2    DMA_BASE+0x028
    40 #define DMA_CHCR2   DMA_BASE+0x02C
    41 #define DMA_SAR3    DMA_BASE+0x030
    42 #define DMA_DAR3    DMA_BASE+0x034
    43 #define DMA_TCR3    DMA_BASE+0x038
    44 #define DMA_CHCR3   DMA_BASE+0x03C
    45 #define DMA_DMAOR   DMA_BASE+0x040
    46 #define QUEUECR0    0xFF000038
    47 #define QUEUECR1    0xFF00003C
    49 #define IDE_CMD_RESET 0x08
    50 #define IDE_CMD_PACKET 0xA0
    51 #define IDE_CMD_IDENTIFY_PACKET_DEVICE 0xA1
    52 #define IDE_CMD_IDENTIFY_DEVICE 0xEC
    54 #define MMC_CMD_GET_CONFIGURATION 0x46
    55 #define GD_CMD_IDENTIFY 0x11 /* guessing */
    58 #define IDE_DMA_MAGIC_VALUE 0x8843407F
    61 #define MAX_WAIT     10000000
    62 #define MAX_IRQ_WAIT 1000000000
    64 /**
    65  * Dump all ide registers to stdout.
    66  */
    67 void ide_dump_registers() {
    68     int i,j;
    69     printf( "IDE registers:\n");
    70     printf( "Stats: %02X ", byte_read(IDE_ALTSTATUS) );
    71     printf( "Error: %02X ", byte_read(IDE_ERROR) );
    72     printf( "Count: %02X ", byte_read(IDE_COUNT) );
    73     printf( "Dvice: %02X ", byte_read(IDE_DEVICE) );
    74     if( long_read(ASIC_STATUS1)&1 ) {
    75 	printf( "INTRQ! " );
    76     }
    77     if( (long_read(ASIC_STATUS0)>>14)&1 ) {
    78 	printf( "DMARQ! " );
    79     }
    80     printf( "\nLBA 0: %02X ", byte_read(IDE_LBA0) );
    81     printf( "LBA 1: %02X ", byte_read(IDE_LBA1) );
    82     printf( "LBA 2: %02X ", byte_read(IDE_LBA2) );
    83     printf( "0x01C: %02X\n", byte_read(IDE_UNKNOWN) );
    84     printf( "DAddr: %08X ", long_read(IDE_DMA_ADDR) );
    85     printf( "DSize: %08X ", long_read(IDE_DMA_SIZE) );
    86     printf( "DDir : %08X ", long_read(IDE_DMA_DIR) );
    87     printf( "DCtl1: %08X ", long_read(IDE_DMA_CTL1) );
    88     printf( "DCtl2: %08X\n", long_read(IDE_DMA_CTL2) );
    89     printf( "DStat: %08X\n", long_read(IDE_DMA_STATUS) );
    90     printf( "ASIC: " );
    91     for( i=0; i<12; i+=4 ) {
    92 	unsigned int val = long_read(ASIC_STATUS0+i);
    93 	for( j=0; j<32; j++ ) {
    94 	    if( val & (1<<j) ) {
    95 		printf( "%d ", j );
    96 	    }
    97 	}
    98 	printf( "| " );
    99     }
   100     printf( "\n" );
   101 }
   103 /**
   104  * Wait for the IDE INTRQ line to go active (bit 0 of the second word)
   105  * @return 0 on success, non-zero on timeout
   106  */
   107 int ide_wait_irq() {
   108     unsigned int status;
   109     int i;
   110     for( i=0; i<MAX_WAIT; i++ ) {
   111 	status = long_read( ASIC_STATUS1 );
   112 	if( (status&1) != 0 )
   113 	    return 0;
   114     }
   115     return 1;
   116 }
   118 /**
   119  * Wait for the IDE BSY flag to be de-asserted.
   120  * @return 0 on success, non-zero on timeout
   121  */
   122 int ide_wait_ready() {
   123     unsigned char status;
   124     int i;
   125     for( i=0; i<MAX_WAIT; i++ ) {
   126         status = byte_read(IDE_ALTSTATUS);
   127 	if( (status & 0x80) == 0 )
   128 	    return 0;
   129     }
   130     printf( "Timeout waiting for IDE to become ready (status = 0x%02X)\n", status );
   131     ide_dump_registers();
   132     return 1;
   133 }
   135 int ide_wait_dma() {
   136     unsigned int status;
   137     int i;
   138     for( i=0; i<MAX_WAIT; i++ ) {
   139 	status = long_read(IDE_DMA_CTL2);
   140 	if( (status & 1) == 0 )
   141 	    return 0;
   142     }
   143     printf( "[IDE] Timeout waiting for DMA to become ready\n" );
   144     return 1;
   145 }
   147 /**
   148  * Write the command packet out to the interface.
   149  * @param cmd 12 byte ATAPI command packet
   150  * @param dma 1 = dma mode, 0 = pio mode
   151  */
   152 int ide_write_command_packet( char *cmd, int dma ) 
   153 {
   154     int i, status;
   155     unsigned short *spkt = (unsigned short *)cmd;
   156     unsigned short length = 8;
   157     if( ide_wait_ready() )
   158 	return 1;
   159     byte_write( IDE_FEATURE, dma );
   160     byte_write( IDE_COUNT, 0 );
   161     byte_write( IDE_LBA0, 0 );
   162     byte_write( IDE_LBA1, (length&0xFF) );
   163     byte_write( IDE_LBA2, (length>>8)&0xFF );
   164     byte_write( IDE_DEVICE, 0 );
   165     byte_write( IDE_COMMAND, IDE_CMD_PACKET );
   166     status = byte_read(IDE_ALTSTATUS); /* delay 1 PIO cycle as per spec */
   167     /* Wait until device is ready to accept command */
   168     if( ide_wait_ready() )
   169 	return 1;
   171     /* Write the command */
   172     for( i=0; i<6; i++ ) {
   173         word_write( IDE_DATA, spkt[i] );
   174     }
   175 }
   177 int ide_read_pio( char *buf, int buflen ) {
   178     int i;
   179     unsigned short *bufptr = (unsigned short *)buf;
   180     unsigned int length = 0, avail;
   181     int status;
   183     while(1) {
   184 	if( ide_wait_ready() )
   185 	    return -1;
   186 	status = byte_read( IDE_STATUS );
   187 	if( (status & 0xE9) == 0x48 ) {
   188 	    /* Bytes available */
   189 	    avail = (byte_read( IDE_LBA1 )) | (byte_read(IDE_LBA2)<<8);
   190 	    for( i=0; i<avail; i+=2 ) {
   191 		if( buflen > 0 ) {
   192 		    *bufptr++ = word_read(IDE_DATA);
   193 		    buflen-=2;
   194 		}
   195 	    }
   196 	    length += avail;
   197 	    if( avail == 0 ) {
   198 		/* Should never happen */
   199 		printf( "[IDE] Unexpected read length 0\n" );
   200 		return -1;
   201 	    }
   202 	} else {
   203 	    if( status&0x01 ) {
   204 		printf( "[IDE] ERROR! (%02X)\n", status );
   205 		return -1;
   206 	    } else if( (status&0x08) == 0 ) {
   207 		/* No more data */
   208 		return length;
   209 	    } else {
   210 		printf( "[IDE] Unexpected status result: %02X\n", status );
   211 		return -1;
   212 	    }
   213 	}
   214     }
   215 }
   217 int ide_read_dma( char *buf, int buflen ) 
   218 {
   219     int status;
   221     long_write( IDE_DMA_CTL1, 1 );
   222     long_write( IDE_DMA_CTL2, 1 );
   224     printf( "Started DMA\n" );
   225     ide_dump_registers();
   227     ide_wait_irq();
   228     printf( "After IRQ\n" );
   229     ide_dump_registers();
   230     long_write( IDE_DMA_CTL1, 0 );
   231     status = ide_wait_dma();
   232     printf( "After DMA finished\n");
   233     ide_dump_registers();
   234     if( status != 0 ) {
   235 	return -1;
   236     }
   237     status = long_read(ASIC_STATUS0);
   238     if( (status & (1<<14)) == 0 ) {
   239 	printf( "DMARQ cleared already\n");
   240     } else {
   241 	/*
   242 	status &= ~(1<<14);
   243 	long_write(ASIC_STATUS0, status);
   244 	status = long_read(ASIC_STATUS0);
   245 	*/
   246 	byte_read(IDE_STATUS );
   247 	if( (status & (1<<14)) == 0 ) {
   248 	    printf( "DMARQ cleared successfully\n" );
   249 	} else {
   250 	    printf( "DMARQ not cleared: %08X\n", long_read(ASIC_STATUS0) );
   251 	}
   252     }
   253     status = ide_wait_ready();
   254     printf( "After IDE ready\n");
   255     ide_dump_registers();
   256     if( status != 0 ) {
   257 	return -1;
   258     }
   259     return long_read( IDE_DMA_STATUS );
   260 }
   262 int ide_do_packet_command_pio( char *cmd, char *buf, int length ) 
   263 {
   264     ide_write_command_packet( cmd, 0 );
   265     length = ide_read_pio( buf, length );
   266     return length;
   267 }
   269 int ide_do_packet_command_dma( char *cmd, char *buf, int length )
   270 {
   271     long_write( QUEUECR0, 0x10 );
   272     long_write( QUEUECR1, 0x10 );
   273     long_write( IDE_DMA_MAGIC, IDE_DMA_MAGIC_VALUE );
   274     long_write( IDE_DMA_ADDR, (unsigned int)buf );
   275     long_write( IDE_DMA_SIZE, length );
   276     long_write( IDE_DMA_DIR, 1 );
   277     ide_write_command_packet( cmd, 1 );
   278     length = ide_read_dma( buf, length );
   279     return length;
   280 }
   282 void ide_activate() {
   283   register unsigned long p, x;
   285   /* Reactivate GD-ROM drive */
   287   *((volatile unsigned long *)0xa05f74e4) = 0x1fffff;
   288   for(p=0; p<0x200000/4; p++)
   289     x = ((volatile unsigned long *)0xa0000000)[p];
   290 }
   293 int ide_init()
   294 {
   295     ide_activate();
   297     if( ide_wait_ready() )
   298 	return -1;
   300     /** Set Default PIO mode */
   301     byte_write( IDE_FEATURE, 0x03 );
   302     byte_write( IDE_COUNT, 0x0B );
   303     byte_write( IDE_COMMAND, 0xEF );
   305     if( ide_wait_ready() )
   306 	return -1;
   308     /** Set Multi-word DMA mode 2 */
   309     long_write( 0xA05F7490, 0x222 );
   310     long_write( 0xA05F7494, 0x222 );
   311     byte_write( IDE_FEATURE, 0x03 );
   312     byte_write( IDE_COUNT, 0x22 );
   313     byte_write( IDE_COMMAND, 0xEF );
   314     if( ide_wait_ready() )
   315 	return -1;
   317     word_write( 0xA05F7480, 0x400 );
   318     long_write( 0xA05F7488, 0x200 );
   319     long_write( 0xA05F748C, 0x200 );
   320     long_write( 0xA05F74A0, 0x2001 );
   321     long_write( 0xA05F74A4, 0x2001 );
   322     long_write( 0xA05F74B4, 0x0001 );
   323 }
   325 int ide_sense_error( char *buf ) 
   326 {
   327     char cmd[12] = { 0x13,0,0,0, 10,0,0,0, 0,0,0,0 };
   328     return ide_do_packet_command_pio( cmd, buf, 10 );
   329 }
   331 int ide_get_sense_code()
   332 {
   333     char buf[10];
   334     int len = ide_sense_error( buf );
   335     if( len != 10 ) {
   336 	printf( "ERROR: Sense request failed!\n" );
   337 	return -1;
   338     }
   339     return ((int)buf[8] << 8) | buf[2];
   340 }
   342 void ide_print_sense_error()
   343 {
   344     char buf[10];
   345     if( ide_sense_error(buf) != 10 ) {
   346 	printf( "ERROR - Sense error failed!\n" );
   347 	return;
   348     }
   349     int major = buf[2] & 0xFF;
   350     int minor = buf[8] & 0xFF;
   351     printf( "[IDE] Error code %02X,%02X\n", major, minor );
   352 }
   354 int ide_test_ready()
   355 {
   356     char cmd[12] = { 0,0,0,0, 0,0,0,0, 0,0,0,0 };
   357     int length = ide_do_packet_command_pio( cmd, NULL, 0 );
   358     return length;
   359 }
   361 int ide_read_toc( char *buf, int length ) 
   362 {
   363     char cmd[12] = { 0x14,0,0,0, 0x98,0,0,0, 0,0,0,0 };
   364     return ide_do_packet_command_pio( cmd, buf, length );
   365 }
   367 int ide_get_session( int session, struct gdrom_session *session_data )
   368 {
   369     char cmd[12] = {0x15, 0, session, 0, 6,0,0,0, 0,0,0,0 };
   370     char buf[6];
   371     int length = ide_do_packet_command_pio( cmd, buf, sizeof(buf) );
   372     if( length < 0 )
   373 	return length;
   374     if( length != 6 )
   375 	return -1;
   376     assert(length == 6);
   377     session_data->track = ((int)buf[2])&0xFF;
   378     session_data->lba = (((int)buf[3])&0xFF) << 16 | 
   379 	(((int)buf[4])&0xFF) << 8 | 
   380 	(((int)buf[5])&0xFF);
   381     return 0;
   382 }
   384 int ide_spinup( )
   385 {
   386     char cmd[12] = {0x70,0x1F,0,0, 0,0,0,0, 0,0,0,0};
   387     int length = ide_do_packet_command_pio( cmd, NULL, 0 );
   388     return length;
   389 }
   391 int ide_unknown71( char *buf, int length )
   392 {
   393     char cmd[12] = {0x71,0,0,0, 0,0,0,0, 0,0,0,0};
   394     return ide_do_packet_command_pio( cmd, buf, length );
   395 }
   397 int ide_read_sector_pio( uint32_t sector, uint32_t count, int mode,
   398 			 char *buf, int length )
   399 {
   400     char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
   402     cmd[1] = mode;
   403     cmd[2] = (sector>>16)&0xFF;
   404     cmd[3] = (sector>>8)&0xFF;
   405     cmd[4] = sector&0xFF;
   406     cmd[8] = (count>>16)&0xFF;
   407     cmd[9] = (count>>8)&0xFF;
   408     cmd[10] = count&0xFF;
   409     return ide_do_packet_command_pio( cmd, buf, length );
   410 }
   413 int ide_read_sector_dma( uint32_t sector, uint32_t count, int mode,
   414 			 char *buf, int length )
   415 {
   416     char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
   418     cmd[1] = mode;
   419     cmd[2] = (sector>>16)&0xFF;
   420     cmd[3] = (sector>>8)&0xFF;
   421     cmd[4] = sector&0xFF;
   422     cmd[8] = (count>>16)&0xFF;
   423     cmd[9] = (count>>8)&0xFF;
   424     cmd[10] = count&0xFF;
   425     return ide_do_packet_command_dma( cmd, buf, length );
   426 }
   428 int ide_read_something( )
   429 {
   430     char cmd[12] = { 0x12,0,0,0, 0x0a,0,0,0, 0,0,0,0 };
   431     char result[10];
   432     ide_do_packet_command_pio( cmd, result, 10 );
   433     return 0;
   434 }
   436 int ide_read_status( char *buf, int length, int type )
   437 {
   438     char cmd[12] = { 0x40,0,0,0, 0xFF,0,0,0, 0,0,0,0 };
   440     cmd[1] = type;
   441     return ide_do_packet_command_pio( cmd, buf, length );
   442 }
   444 int ide_play_cd( char *buf, int length )
   445 {
   446     char cmd[12] = { 0x21, 0x04,0,0, 0,0,0,0, 0,0,0,0 };
   447     return ide_do_packet_command_pio( cmd, buf, length );
   448 }
.