Search
lxdream.org :: lxdream/test/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/ide.c
changeset 185:6755a04c447f
next243:df1671d533bf
author nkeynes
date Fri Aug 18 09:32:32 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change Add code to check for memory-wraparound on the vertex buffer (it doesn't)
Add in-theory support for re-init (doesn't do anything)
Fix addresses of result and tilematrix
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     printf( "Timeout waiting for IDE INTRQ\n" );
   116     ide_dump_registers();
   117     return 1;
   118 }
   120 /**
   121  * Wait for the IDE BSY flag to be de-asserted.
   122  * @return 0 on success, non-zero on timeout
   123  */
   124 int ide_wait_ready() {
   125     unsigned char status;
   126     int i;
   127     for( i=0; i<MAX_WAIT; i++ ) {
   128         status = byte_read(IDE_ALTSTATUS);
   129 	if( (status & 0x80) != 0x80 )
   130 	    return 0;
   131     }
   132     printf( "Timeout waiting for IDE to become ready\n" );
   133     ide_dump_registers();
   134     return 1;
   135 }
   137 int ide_wait_dma() {
   138     unsigned int status;
   139     int i;
   140     for( i=0; i<MAX_WAIT; i++ ) {
   141 	status = long_read(IDE_DMA_CTL2);
   142 	if( (status & 1) == 0 )
   143 	    return 0;
   144     }
   145     printf( "[IDE] Timeout waiting for DMA to become ready\n" );
   146     return 1;
   147 }
   149 /**
   150  * Write the command packet out to the interface.
   151  * @param cmd 12 byte ATAPI command packet
   152  * @param dma 1 = dma mode, 0 = pio mode
   153  */
   154 int ide_write_command_packet( char *cmd, int dma ) 
   155 {
   156     int i, status;
   157     unsigned short *spkt = (unsigned short *)cmd;
   158     unsigned short length = 8;
   159     if( ide_wait_ready() )
   160 	return 1;
   161     byte_write( IDE_FEATURE, dma );
   162     byte_write( IDE_COUNT, 0 );
   163     byte_write( IDE_LBA0, 0 );
   164     byte_write( IDE_LBA1, (length&0xFF) );
   165     byte_write( IDE_LBA2, (length>>8)&0xFF );
   166     byte_write( IDE_DEVICE, 0 );
   167     byte_write( IDE_COMMAND, IDE_CMD_PACKET );
   168     status = byte_read(IDE_ALTSTATUS); /* delay 1 PIO cycle as per spec */
   169     printf( "After writing PACKET command byte:\n" );
   170     ide_dump_registers();
   171     /* Wait until device is ready to accept command */
   172     if( ide_wait_ready() )
   173 	return 1;
   174     printf( "Device ready to receive packet:\n" );
   175     ide_dump_registers();
   177     /* Write the command */
   178     for( i=0; i<6; i++ ) {
   179         word_write( IDE_DATA, spkt[i] );
   180     }
   181     printf( "After writing command packet:\n" );
   182     ide_dump_registers();
   183 }
   185 int ide_read_pio( char *buf, int buflen ) {
   186     int i;
   187     unsigned short *bufptr = (unsigned short *)buf;
   188     unsigned int length = 0, avail;
   189     int status;
   191     while(1) {
   192 	if( ide_wait_ready() )
   193 	    return -1;
   194 	status = byte_read( IDE_STATUS );
   195 	if( (status & 0xE9) == 0x48 ) {
   196 	    /* Bytes available */
   197 	    avail = (byte_read( IDE_LBA1 )) | (byte_read(IDE_LBA2)<<8);
   198 	    for( i=0; i<avail; i+=2 ) {
   199 		if( buflen > 0 ) {
   200 		    *bufptr++ = word_read(IDE_DATA);
   201 		    buflen-=2;
   202 		}
   203 	    }
   204 	    length += avail;
   205 	    if( avail == 0 ) {
   206 		/* Should never happen */
   207 		printf( "[IDE] Unexpected read length 0\n" );
   208 		return -1;
   209 	    }
   210 	} else {
   211 	    if( status&0x01 ) {
   212 		printf( "[IDE] ERROR! (%02X)\n", status );
   213 	    } else if( (status&0x08) == 0 ) {
   214 		/* No more data */
   215 		return length;
   216 	    } else {
   217 		printf( "[IDE] Unexpected status result: %02X\n", status );
   218 		return -1;
   219 	    }
   220 	}
   221     }
   222 }
   224 int ide_read_dma( char *buf, int buflen ) 
   225 {
   226     int status;
   228     long_write( IDE_DMA_CTL1, 1 );
   229     long_write( IDE_DMA_CTL2, 1 );
   231     printf( "Started DMA\n" );
   232     ide_dump_registers();
   234     ide_wait_irq();
   235     printf( "After IRQ\n" );
   236     ide_dump_registers();
   237     long_write( IDE_DMA_CTL1, 0 );
   238     status = ide_wait_dma();
   239     printf( "After DMA finished\n");
   240     ide_dump_registers();
   241     if( status != 0 ) {
   242 	return -1;
   243     }
   244     status = long_read(ASIC_STATUS0);
   245     if( (status & (1<<14)) == 0 ) {
   246 	printf( "DMARQ cleared already\n");
   247     } else {
   248 	/*
   249 	status &= ~(1<<14);
   250 	long_write(ASIC_STATUS0, status);
   251 	status = long_read(ASIC_STATUS0);
   252 	*/
   253 	byte_read(IDE_STATUS );
   254 	if( (status & (1<<14)) == 0 ) {
   255 	    printf( "DMARQ cleared successfully\n" );
   256 	} else {
   257 	    printf( "DMARQ not cleared: %08X\n", long_read(ASIC_STATUS0) );
   258 	}
   259     }
   260     status = ide_wait_ready();
   261     printf( "After IDE ready\n");
   262     ide_dump_registers();
   263     if( status != 0 ) {
   264 	return -1;
   265     }
   266     return long_read( IDE_DMA_STATUS );
   267 }
   269 int ide_do_packet_command_pio( char *cmd, char *buf, int length ) 
   270 {
   271     ide_write_command_packet( cmd, 0 );
   272     length = ide_read_pio( buf, length );
   273     return length;
   274 }
   276 int ide_do_packet_command_dma( char *cmd, char *buf, int length )
   277 {
   278     long_write( QUEUECR0, 0x10 );
   279     long_write( QUEUECR1, 0x10 );
   280     long_write( IDE_DMA_MAGIC, IDE_DMA_MAGIC_VALUE );
   281     long_write( IDE_DMA_ADDR, (unsigned int)buf );
   282     long_write( IDE_DMA_SIZE, length );
   283     long_write( IDE_DMA_DIR, 1 );
   284     ide_write_command_packet( cmd, 1 );
   285     length = ide_read_dma( buf, length );
   286     return length;
   287 }
   289 int ide_init()
   290 {
   291     if( ide_wait_ready() )
   292 	return -1;
   294     /** Set Default PIO mode */
   295     byte_write( IDE_FEATURE, 0x03 );
   296     byte_write( IDE_COUNT, 0x0B );
   297     byte_write( IDE_COMMAND, 0xEF );
   299     if( ide_wait_ready() )
   300 	return -1;
   302     /** Set Multi-word DMA mode 2 */
   303     long_write( 0xA05F7490, 0x222 );
   304     long_write( 0xA05F7494, 0x222 );
   305     byte_write( IDE_FEATURE, 0x03 );
   306     byte_write( IDE_COUNT, 0x22 );
   307     byte_write( IDE_COMMAND, 0xEF );
   308     if( ide_wait_ready() )
   309 	return -1;
   311     word_write( 0xA05F7480, 0x400 );
   312     long_write( 0xA05F7488, 0x200 );
   313     long_write( 0xA05F748C, 0x200 );
   314     long_write( 0xA05F74A0, 0x2001 );
   315     long_write( 0xA05F74A4, 0x2001 );
   316     long_write( 0xA05F74B4, 0x0001 );
   317 }
   319 int ide_sense_error( char *buf ) 
   320 {
   321     char cmd[12] = { 0x13,0,0,0, 10,0,0,0, 0,0,0,0 };
   322     return ide_do_packet_command_pio( cmd, buf, 10 );
   323 }
   325 void ide_print_sense_error()
   326 {
   327     char buf[10];
   328     if( ide_sense_error(buf) != 10 ) {
   329 	printf( "ERROR - Sense error failed!\n" );
   330 	return;
   331     }
   332     int major = buf[2] & 0xFF;
   333     int minor = buf[8] & 0xFF;
   334     printf( "[IDE] Error code %02X,%02X\n", major, minor );
   335 }
   337 int ide_test_ready()
   338 {
   339     char cmd[12] = { 0,0,0,0, 0,0,0,0, 0,0,0,0 };
   340     int length = ide_do_packet_command_pio( cmd, NULL, 0 );
   341     return length;
   342 }
   344 int ide_read_toc( char *buf, int length ) 
   345 {
   346     char cmd[12] = { 0x14,0,0,0, 0x98,0,0,0, 0,0,0,0 };
   347     return ide_do_packet_command_pio( cmd, buf, length );
   348 }
   350 int ide_get_session( int session, struct gdrom_session *session_data )
   351 {
   352     char cmd[12] = {0x15, 0, session, 0, 6,0,0,0, 0,0,0,0 };
   353     char buf[6];
   354     int length = ide_do_packet_command_pio( cmd, buf, sizeof(buf) );
   355     if( length < 0 )
   356 	return length;
   357     if( length != 6 )
   358 	return -1;
   359     assert(length == 6);
   360     session_data->track = ((int)buf[2])&0xFF;
   361     session_data->lba = (((int)buf[3])&0xFF) << 16 | 
   362 	(((int)buf[4])&0xFF) << 8 | 
   363 	(((int)buf[5])&0xFF);
   364     return 0;
   365 }
   367 int ide_spinup( )
   368 {
   369     char cmd[12] = {0x70,0x1F,0,0, 0,0,0,0, 0,0,0,0};
   370     int length = ide_do_packet_command_pio( cmd, NULL, 0 );
   371     return length;
   372 }
   374 int ide_unknown71( char *buf, int length )
   375 {
   376     char cmd[12] = {0x71,0,0,0, 0,0,0,0, 0,0,0,0};
   377     return ide_do_packet_command_pio( cmd, buf, length );
   378 }
   380 int ide_read_sector_pio( uint32_t sector, uint32_t count, int mode,
   381 			 char *buf, int length )
   382 {
   383     char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
   385     cmd[1] = mode;
   386     cmd[2] = (sector>>16)&0xFF;
   387     cmd[3] = (sector>>8)&0xFF;
   388     cmd[4] = sector&0xFF;
   389     cmd[8] = (count>>16)&0xFF;
   390     cmd[9] = (count>>8)&0xFF;
   391     cmd[10] = count&0xFF;
   392     return ide_do_packet_command_pio( cmd, buf, length );
   393 }
   396 int ide_read_sector_dma( uint32_t sector, uint32_t count, int mode,
   397 			 char *buf, int length )
   398 {
   399     char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
   401     cmd[1] = mode;
   402     cmd[2] = (sector>>16)&0xFF;
   403     cmd[3] = (sector>>8)&0xFF;
   404     cmd[4] = sector&0xFF;
   405     cmd[8] = (count>>16)&0xFF;
   406     cmd[9] = (count>>8)&0xFF;
   407     cmd[10] = count&0xFF;
   408     return ide_do_packet_command_dma( cmd, buf, length );
   409 }
   411 int ide_read_something( )
   412 {
   413     char cmd[12] = { 0x12,0,0,0, 0x0a,0,0,0, 0,0,0,0 };
   414     char result[10];
   415     ide_do_packet_command_pio( cmd, result, 10 );
   416     debug_dump_buffer(result,10);
   417     return 0;
.