Search
lxdream.org :: lxdream/test/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/ide.c
changeset 247:b356d391d02a
prev243:df1671d533bf
next251:3c5953d944e0
author nkeynes
date Tue Dec 19 09:56:09 2006 +0000 (13 years ago)
permissions -rw-r--r--
last change Remove debug_dump call and dump at end of wait_irq
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) != 0x80 )
   128 	    return 0;
   129     }
   130     printf( "Timeout waiting for IDE to become ready\n" );
   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     printf( "After writing PACKET command byte:\n" );
   168     ide_dump_registers();
   169     /* Wait until device is ready to accept command */
   170     if( ide_wait_ready() )
   171 	return 1;
   172     printf( "Device ready to receive packet:\n" );
   173     ide_dump_registers();
   175     /* Write the command */
   176     for( i=0; i<6; i++ ) {
   177         word_write( IDE_DATA, spkt[i] );
   178     }
   179     printf( "After writing command packet:\n" );
   180     ide_dump_registers();
   181 }
   183 int ide_read_pio( char *buf, int buflen ) {
   184     int i;
   185     unsigned short *bufptr = (unsigned short *)buf;
   186     unsigned int length = 0, avail;
   187     int status;
   189     while(1) {
   190 	if( ide_wait_ready() )
   191 	    return -1;
   192 	status = byte_read( IDE_STATUS );
   193 	if( (status & 0xE9) == 0x48 ) {
   194 	    /* Bytes available */
   195 	    avail = (byte_read( IDE_LBA1 )) | (byte_read(IDE_LBA2)<<8);
   196 	    for( i=0; i<avail; i+=2 ) {
   197 		if( buflen > 0 ) {
   198 		    *bufptr++ = word_read(IDE_DATA);
   199 		    buflen-=2;
   200 		}
   201 	    }
   202 	    length += avail;
   203 	    if( avail == 0 ) {
   204 		/* Should never happen */
   205 		printf( "[IDE] Unexpected read length 0\n" );
   206 		return -1;
   207 	    }
   208 	} else {
   209 	    if( status&0x01 ) {
   210 		printf( "[IDE] ERROR! (%02X)\n", status );
   211 		return -1;
   212 	    } else if( (status&0x08) == 0 ) {
   213 		/* No more data */
   214 		return length;
   215 	    } else {
   216 		printf( "[IDE] Unexpected status result: %02X\n", status );
   217 		return -1;
   218 	    }
   219 	}
   220     }
   221 }
   223 int ide_read_dma( char *buf, int buflen ) 
   224 {
   225     int status;
   227     long_write( IDE_DMA_CTL1, 1 );
   228     long_write( IDE_DMA_CTL2, 1 );
   230     printf( "Started DMA\n" );
   231     ide_dump_registers();
   233     ide_wait_irq();
   234     printf( "After IRQ\n" );
   235     ide_dump_registers();
   236     long_write( IDE_DMA_CTL1, 0 );
   237     status = ide_wait_dma();
   238     printf( "After DMA finished\n");
   239     ide_dump_registers();
   240     if( status != 0 ) {
   241 	return -1;
   242     }
   243     status = long_read(ASIC_STATUS0);
   244     if( (status & (1<<14)) == 0 ) {
   245 	printf( "DMARQ cleared already\n");
   246     } else {
   247 	/*
   248 	status &= ~(1<<14);
   249 	long_write(ASIC_STATUS0, status);
   250 	status = long_read(ASIC_STATUS0);
   251 	*/
   252 	byte_read(IDE_STATUS );
   253 	if( (status & (1<<14)) == 0 ) {
   254 	    printf( "DMARQ cleared successfully\n" );
   255 	} else {
   256 	    printf( "DMARQ not cleared: %08X\n", long_read(ASIC_STATUS0) );
   257 	}
   258     }
   259     status = ide_wait_ready();
   260     printf( "After IDE ready\n");
   261     ide_dump_registers();
   262     if( status != 0 ) {
   263 	return -1;
   264     }
   265     return long_read( IDE_DMA_STATUS );
   266 }
   268 int ide_do_packet_command_pio( char *cmd, char *buf, int length ) 
   269 {
   270     ide_write_command_packet( cmd, 0 );
   271     length = ide_read_pio( buf, length );
   272     return length;
   273 }
   275 int ide_do_packet_command_dma( char *cmd, char *buf, int length )
   276 {
   277     long_write( QUEUECR0, 0x10 );
   278     long_write( QUEUECR1, 0x10 );
   279     long_write( IDE_DMA_MAGIC, IDE_DMA_MAGIC_VALUE );
   280     long_write( IDE_DMA_ADDR, (unsigned int)buf );
   281     long_write( IDE_DMA_SIZE, length );
   282     long_write( IDE_DMA_DIR, 1 );
   283     ide_write_command_packet( cmd, 1 );
   284     length = ide_read_dma( buf, length );
   285     return length;
   286 }
   288 void ide_activate() {
   289   register unsigned long p, x;
   291   /* Reactivate GD-ROM drive */
   293   *((volatile unsigned long *)0xa05f74e4) = 0x1fffff;
   294   for(p=0; p<0x200000/4; p++)
   295     x = ((volatile unsigned long *)0xa0000000)[p];
   296 }
   299 int ide_init()
   300 {
   301     ide_activate();
   303     if( ide_wait_ready() )
   304 	return -1;
   306     /** Set Default PIO mode */
   307     byte_write( IDE_FEATURE, 0x03 );
   308     byte_write( IDE_COUNT, 0x0B );
   309     byte_write( IDE_COMMAND, 0xEF );
   311     if( ide_wait_ready() )
   312 	return -1;
   314     /** Set Multi-word DMA mode 2 */
   315     long_write( 0xA05F7490, 0x222 );
   316     long_write( 0xA05F7494, 0x222 );
   317     byte_write( IDE_FEATURE, 0x03 );
   318     byte_write( IDE_COUNT, 0x22 );
   319     byte_write( IDE_COMMAND, 0xEF );
   320     if( ide_wait_ready() )
   321 	return -1;
   323     word_write( 0xA05F7480, 0x400 );
   324     long_write( 0xA05F7488, 0x200 );
   325     long_write( 0xA05F748C, 0x200 );
   326     long_write( 0xA05F74A0, 0x2001 );
   327     long_write( 0xA05F74A4, 0x2001 );
   328     long_write( 0xA05F74B4, 0x0001 );
   329 }
   331 int ide_sense_error( char *buf ) 
   332 {
   333     char cmd[12] = { 0x13,0,0,0, 10,0,0,0, 0,0,0,0 };
   334     return ide_do_packet_command_pio( cmd, buf, 10 );
   335 }
   337 void ide_print_sense_error()
   338 {
   339     char buf[10];
   340     if( ide_sense_error(buf) != 10 ) {
   341 	printf( "ERROR - Sense error failed!\n" );
   342 	return;
   343     }
   344     int major = buf[2] & 0xFF;
   345     int minor = buf[8] & 0xFF;
   346     printf( "[IDE] Error code %02X,%02X\n", major, minor );
   347 }
   349 int ide_test_ready()
   350 {
   351     char cmd[12] = { 0,0,0,0, 0,0,0,0, 0,0,0,0 };
   352     int length = ide_do_packet_command_pio( cmd, NULL, 0 );
   353     return length;
   354 }
   356 int ide_read_toc( char *buf, int length ) 
   357 {
   358     char cmd[12] = { 0x14,0,0,0, 0x98,0,0,0, 0,0,0,0 };
   359     return ide_do_packet_command_pio( cmd, buf, length );
   360 }
   362 int ide_get_session( int session, struct gdrom_session *session_data )
   363 {
   364     char cmd[12] = {0x15, 0, session, 0, 6,0,0,0, 0,0,0,0 };
   365     char buf[6];
   366     int length = ide_do_packet_command_pio( cmd, buf, sizeof(buf) );
   367     if( length < 0 )
   368 	return length;
   369     if( length != 6 )
   370 	return -1;
   371     assert(length == 6);
   372     session_data->track = ((int)buf[2])&0xFF;
   373     session_data->lba = (((int)buf[3])&0xFF) << 16 | 
   374 	(((int)buf[4])&0xFF) << 8 | 
   375 	(((int)buf[5])&0xFF);
   376     return 0;
   377 }
   379 int ide_spinup( )
   380 {
   381     char cmd[12] = {0x70,0x1F,0,0, 0,0,0,0, 0,0,0,0};
   382     int length = ide_do_packet_command_pio( cmd, NULL, 0 );
   383     return length;
   384 }
   386 int ide_unknown71( char *buf, int length )
   387 {
   388     char cmd[12] = {0x71,0,0,0, 0,0,0,0, 0,0,0,0};
   389     return ide_do_packet_command_pio( cmd, buf, length );
   390 }
   392 int ide_read_sector_pio( uint32_t sector, uint32_t count, int mode,
   393 			 char *buf, int length )
   394 {
   395     char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
   397     cmd[1] = mode;
   398     cmd[2] = (sector>>16)&0xFF;
   399     cmd[3] = (sector>>8)&0xFF;
   400     cmd[4] = sector&0xFF;
   401     cmd[8] = (count>>16)&0xFF;
   402     cmd[9] = (count>>8)&0xFF;
   403     cmd[10] = count&0xFF;
   404     return ide_do_packet_command_pio( cmd, buf, length );
   405 }
   408 int ide_read_sector_dma( uint32_t sector, uint32_t count, int mode,
   409 			 char *buf, int length )
   410 {
   411     char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
   413     cmd[1] = mode;
   414     cmd[2] = (sector>>16)&0xFF;
   415     cmd[3] = (sector>>8)&0xFF;
   416     cmd[4] = sector&0xFF;
   417     cmd[8] = (count>>16)&0xFF;
   418     cmd[9] = (count>>8)&0xFF;
   419     cmd[10] = count&0xFF;
   420     return ide_do_packet_command_dma( cmd, buf, length );
   421 }
   423 int ide_read_something( )
   424 {
   425     char cmd[12] = { 0x12,0,0,0, 0x0a,0,0,0, 0,0,0,0 };
   426     char result[10];
   427     ide_do_packet_command_pio( cmd, result, 10 );
   428     return 0;
   429 }
   431 int ide_read_status( char *buf, int length )
   432 {
   433     char cmd[12] = { 0x40,0,0,0, 0xFF,0,0,0, 0,0,0,0 };
   435     return ide_do_packet_command_pio( cmd, buf, length );
   436 }
   438 int ide_play_cd( char *buf, int length )
   439 {
   440     char cmd[12] = { 0x21, 0x04,0,0, 0,0,0,0, 0,0,0,0 };
   441     return ide_do_packet_command_pio( cmd, buf, length );
   442 }
.