Search
lxdream.org :: lxdream/test/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/ide.c
changeset 243:df1671d533bf
prev185:6755a04c447f
next247:b356d391d02a
author nkeynes
date Sat Dec 16 12:37:44 2006 +0000 (14 years ago)
permissions -rw-r--r--
last change Add activation and status functions
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 		return -1;
   214 	    } else if( (status&0x08) == 0 ) {
   215 		/* No more data */
   216 		return length;
   217 	    } else {
   218 		printf( "[IDE] Unexpected status result: %02X\n", status );
   219 		return -1;
   220 	    }
   221 	}
   222     }
   223 }
   225 int ide_read_dma( char *buf, int buflen ) 
   226 {
   227     int status;
   229     long_write( IDE_DMA_CTL1, 1 );
   230     long_write( IDE_DMA_CTL2, 1 );
   232     printf( "Started DMA\n" );
   233     ide_dump_registers();
   235     ide_wait_irq();
   236     printf( "After IRQ\n" );
   237     ide_dump_registers();
   238     long_write( IDE_DMA_CTL1, 0 );
   239     status = ide_wait_dma();
   240     printf( "After DMA finished\n");
   241     ide_dump_registers();
   242     if( status != 0 ) {
   243 	return -1;
   244     }
   245     status = long_read(ASIC_STATUS0);
   246     if( (status & (1<<14)) == 0 ) {
   247 	printf( "DMARQ cleared already\n");
   248     } else {
   249 	/*
   250 	status &= ~(1<<14);
   251 	long_write(ASIC_STATUS0, status);
   252 	status = long_read(ASIC_STATUS0);
   253 	*/
   254 	byte_read(IDE_STATUS );
   255 	if( (status & (1<<14)) == 0 ) {
   256 	    printf( "DMARQ cleared successfully\n" );
   257 	} else {
   258 	    printf( "DMARQ not cleared: %08X\n", long_read(ASIC_STATUS0) );
   259 	}
   260     }
   261     status = ide_wait_ready();
   262     printf( "After IDE ready\n");
   263     ide_dump_registers();
   264     if( status != 0 ) {
   265 	return -1;
   266     }
   267     return long_read( IDE_DMA_STATUS );
   268 }
   270 int ide_do_packet_command_pio( char *cmd, char *buf, int length ) 
   271 {
   272     ide_write_command_packet( cmd, 0 );
   273     length = ide_read_pio( buf, length );
   274     return length;
   275 }
   277 int ide_do_packet_command_dma( char *cmd, char *buf, int length )
   278 {
   279     long_write( QUEUECR0, 0x10 );
   280     long_write( QUEUECR1, 0x10 );
   281     long_write( IDE_DMA_MAGIC, IDE_DMA_MAGIC_VALUE );
   282     long_write( IDE_DMA_ADDR, (unsigned int)buf );
   283     long_write( IDE_DMA_SIZE, length );
   284     long_write( IDE_DMA_DIR, 1 );
   285     ide_write_command_packet( cmd, 1 );
   286     length = ide_read_dma( buf, length );
   287     return length;
   288 }
   290 void ide_activate() {
   291   register unsigned long p, x;
   293   /* Reactivate GD-ROM drive */
   295   *((volatile unsigned long *)0xa05f74e4) = 0x1fffff;
   296   for(p=0; p<0x200000/4; p++)
   297     x = ((volatile unsigned long *)0xa0000000)[p];
   298 }
   301 int ide_init()
   302 {
   303     ide_activate();
   305     if( ide_wait_ready() )
   306 	return -1;
   308     /** Set Default PIO mode */
   309     byte_write( IDE_FEATURE, 0x03 );
   310     byte_write( IDE_COUNT, 0x0B );
   311     byte_write( IDE_COMMAND, 0xEF );
   313     if( ide_wait_ready() )
   314 	return -1;
   316     /** Set Multi-word DMA mode 2 */
   317     long_write( 0xA05F7490, 0x222 );
   318     long_write( 0xA05F7494, 0x222 );
   319     byte_write( IDE_FEATURE, 0x03 );
   320     byte_write( IDE_COUNT, 0x22 );
   321     byte_write( IDE_COMMAND, 0xEF );
   322     if( ide_wait_ready() )
   323 	return -1;
   325     word_write( 0xA05F7480, 0x400 );
   326     long_write( 0xA05F7488, 0x200 );
   327     long_write( 0xA05F748C, 0x200 );
   328     long_write( 0xA05F74A0, 0x2001 );
   329     long_write( 0xA05F74A4, 0x2001 );
   330     long_write( 0xA05F74B4, 0x0001 );
   331 }
   333 int ide_sense_error( char *buf ) 
   334 {
   335     char cmd[12] = { 0x13,0,0,0, 10,0,0,0, 0,0,0,0 };
   336     return ide_do_packet_command_pio( cmd, buf, 10 );
   337 }
   339 void ide_print_sense_error()
   340 {
   341     char buf[10];
   342     if( ide_sense_error(buf) != 10 ) {
   343 	printf( "ERROR - Sense error failed!\n" );
   344 	return;
   345     }
   346     int major = buf[2] & 0xFF;
   347     int minor = buf[8] & 0xFF;
   348     printf( "[IDE] Error code %02X,%02X\n", major, minor );
   349 }
   351 int ide_test_ready()
   352 {
   353     char cmd[12] = { 0,0,0,0, 0,0,0,0, 0,0,0,0 };
   354     int length = ide_do_packet_command_pio( cmd, NULL, 0 );
   355     return length;
   356 }
   358 int ide_read_toc( char *buf, int length ) 
   359 {
   360     char cmd[12] = { 0x14,0,0,0, 0x98,0,0,0, 0,0,0,0 };
   361     return ide_do_packet_command_pio( cmd, buf, length );
   362 }
   364 int ide_get_session( int session, struct gdrom_session *session_data )
   365 {
   366     char cmd[12] = {0x15, 0, session, 0, 6,0,0,0, 0,0,0,0 };
   367     char buf[6];
   368     int length = ide_do_packet_command_pio( cmd, buf, sizeof(buf) );
   369     if( length < 0 )
   370 	return length;
   371     if( length != 6 )
   372 	return -1;
   373     assert(length == 6);
   374     session_data->track = ((int)buf[2])&0xFF;
   375     session_data->lba = (((int)buf[3])&0xFF) << 16 | 
   376 	(((int)buf[4])&0xFF) << 8 | 
   377 	(((int)buf[5])&0xFF);
   378     return 0;
   379 }
   381 int ide_spinup( )
   382 {
   383     char cmd[12] = {0x70,0x1F,0,0, 0,0,0,0, 0,0,0,0};
   384     int length = ide_do_packet_command_pio( cmd, NULL, 0 );
   385     return length;
   386 }
   388 int ide_unknown71( char *buf, int length )
   389 {
   390     char cmd[12] = {0x71,0,0,0, 0,0,0,0, 0,0,0,0};
   391     return ide_do_packet_command_pio( cmd, buf, length );
   392 }
   394 int ide_read_sector_pio( uint32_t sector, uint32_t count, int mode,
   395 			 char *buf, int length )
   396 {
   397     char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
   399     cmd[1] = mode;
   400     cmd[2] = (sector>>16)&0xFF;
   401     cmd[3] = (sector>>8)&0xFF;
   402     cmd[4] = sector&0xFF;
   403     cmd[8] = (count>>16)&0xFF;
   404     cmd[9] = (count>>8)&0xFF;
   405     cmd[10] = count&0xFF;
   406     return ide_do_packet_command_pio( cmd, buf, length );
   407 }
   410 int ide_read_sector_dma( uint32_t sector, uint32_t count, int mode,
   411 			 char *buf, int length )
   412 {
   413     char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
   415     cmd[1] = mode;
   416     cmd[2] = (sector>>16)&0xFF;
   417     cmd[3] = (sector>>8)&0xFF;
   418     cmd[4] = sector&0xFF;
   419     cmd[8] = (count>>16)&0xFF;
   420     cmd[9] = (count>>8)&0xFF;
   421     cmd[10] = count&0xFF;
   422     return ide_do_packet_command_dma( cmd, buf, length );
   423 }
   425 int ide_read_something( )
   426 {
   427     char cmd[12] = { 0x12,0,0,0, 0x0a,0,0,0, 0,0,0,0 };
   428     char result[10];
   429     ide_do_packet_command_pio( cmd, result, 10 );
   430     debug_dump_buffer(result,10);
   431     return 0;
   432 }
   434 int ide_read_status( char *buf, int length )
   435 {
   436     char cmd[12] = { 0x40,0,0,0, 0xFF,0,0,0, 0,0,0,0 };
   438     return ide_do_packet_command_pio( cmd, buf, length );
   439 }
   441 int ide_play_cd( char *buf, int length )
   442 {
   443     char cmd[12] = { 0x21, 0x04,0,0, 0,0,0,0, 0,0,0,0 };
   444     return ide_do_packet_command_pio( cmd, buf, length );
   445 }
.