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 Aug 04 08:46:28 2012 +1000 (5 years ago)
permissions -rw-r--r--
last change Handle corner case in pvr2_run_slice when we've previously slightly overrun
the end of the time slice
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 }
.