Search
lxdream.org :: lxdream/src/gdrom/ide.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/ide.c
changeset 158:a0a82246b44e
prev152:d42a4c5cc709
next166:8aa70cf503a2
author nkeynes
date Thu Jun 15 10:32:42 2006 +0000 (14 years ago)
permissions -rw-r--r--
last change Fix IDE DMA to actually work for real.
Implement the mystery packet 0x71 by cribbing a block of data from the dc.
file annotate diff log raw
1.1 --- a/src/gdrom/ide.c Tue May 23 13:11:45 2006 +0000
1.2 +++ b/src/gdrom/ide.c Thu Jun 15 10:32:42 2006 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: ide.c,v 1.14 2006-05-23 13:11:45 nkeynes Exp $
1.6 + * $Id: ide.c,v 1.15 2006-06-15 10:32:42 nkeynes Exp $
1.7 *
1.8 * IDE interface implementation
1.9 *
1.10 @@ -58,6 +58,57 @@
1.11 0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2e,
1.12 0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
1.13
1.14 +unsigned char gdrom_71[] = { 0x3E, 0x0F, 0x90, 0xBE, 0x1D, 0xD9, 0x89, 0x04, 0x28, 0x3A, 0x8E, 0x26, 0x5C, 0x95, 0x10, 0x5A,
1.15 + 0x0A, 0x99, 0xEE, 0xFB, 0x69, 0xCE, 0xD9, 0x63, 0x00, 0xF5, 0x0A, 0xBC, 0x2C, 0x0D, 0xF8, 0xE2,
1.16 + 0x05, 0x02, 0x00, 0x7C, 0x03, 0x00, 0x3D, 0x08, 0xD8, 0x8D, 0x08, 0x7A, 0x6D, 0x00, 0x35, 0x06,
1.17 + 0xBA, 0x66, 0x10, 0x00, 0x91, 0x08, 0x10, 0x29, 0xD0, 0x45, 0xDA, 0x00, 0x2D, 0x05, 0x69, 0x09,
1.18 + 0x00, 0x5E, 0x0F, 0x70, 0x86, 0x12, 0x6C, 0x77, 0x5A, 0xFB, 0xCD, 0x56, 0xFB, 0xF7, 0xB7, 0x00,
1.19 + 0x5D, 0x07, 0x19, 0x99, 0xF2, 0xAF, 0x00, 0x63, 0x03, 0x00, 0xF0, 0x10, 0xBE, 0xD7, 0xA0, 0x63,
1.20 + 0xFA, 0x84, 0xA7, 0x74, 0x94, 0xEF, 0xAD, 0xC2, 0xAC, 0x00, 0x78, 0x07, 0x9F, 0x57, 0x0B, 0x62,
1.21 + 0x00, 0xFE, 0x08, 0x08, 0x5D, 0x5A, 0x6A, 0x54, 0x00, 0xE2, 0x09, 0x93, 0x7E, 0x62, 0x2A, 0x5E,
1.22 + 0xDA, 0x00, 0x7E, 0x0F, 0xF0, 0x07, 0x01, 0x6D, 0x50, 0x86, 0xDD, 0x4A, 0x15, 0x54, 0xC7, 0xEC,
1.23 + 0x00, 0xF2, 0x0B, 0x07, 0xF8, 0x1A, 0xB0, 0x99, 0x3B, 0xF1, 0x36, 0x00, 0x94, 0x07, 0x34, 0xE3,
1.24 + 0xBC, 0x6E, 0x00, 0x34, 0x0D, 0x6F, 0xDA, 0xBD, 0xEE, 0xF7, 0xCC, 0xCE, 0x39, 0x7E, 0xE3, 0x00,
1.25 + 0x14, 0x08, 0xDC, 0xD2, 0xB9, 0xF9, 0x31, 0x00, 0xB0, 0x0C, 0x10, 0xA3, 0x45, 0x12, 0xC7, 0xCD,
1.26 + 0xBF, 0x05, 0x37, 0x00, 0xC4, 0x0D, 0x5F, 0xE0, 0x59, 0xBB, 0x01, 0x59, 0x03, 0xD6, 0x29, 0x9C,
1.27 + 0x00, 0x01, 0x0A, 0x09, 0xAA, 0xA8, 0xA8, 0x24, 0x0B, 0x66, 0x00, 0x5C, 0x05, 0xA5, 0xCE, 0x00,
1.28 + 0xC1, 0x0B, 0xB7, 0xA0, 0x6F, 0xE9, 0x2B, 0xCC, 0xB5, 0xFC, 0x00, 0x8D, 0x05, 0xF4, 0xAC, 0x00,
1.29 + 0x57, 0x04, 0xB6, 0x00, 0xFC, 0x03, 0x00, 0xC3, 0x10, 0x43, 0x3B, 0xBE, 0xA2, 0x96, 0xC3, 0x65,
1.30 + 0x9F, 0x9A, 0x88, 0xD5, 0x49, 0x68, 0x00, 0xDC, 0x11, 0x56, 0x23, 0x2D, 0xF9, 0xFC, 0xF5, 0x8B,
1.31 + 0x1B, 0xB1, 0xB7, 0x10, 0x21, 0x1C, 0x12, 0x00, 0x0D, 0x0D, 0xEB, 0x86, 0xA2, 0x49, 0x8D, 0x8D,
1.32 + 0xBE, 0xA1, 0x6D, 0x53, 0x00, 0xE1, 0x0A, 0x8E, 0x67, 0xAA, 0x16, 0x79, 0x39, 0x59, 0x00, 0x36,
1.33 + 0x0B, 0x2A, 0x4E, 0xAE, 0x51, 0x4B, 0xD0, 0x66, 0x33, 0x00, 0x8A, 0x07, 0xCD, 0x6F, 0xBA, 0x92,
1.34 + 0x00, 0x1A, 0x0E, 0xDF, 0x4A, 0xB3, 0x77, 0x1F, 0xA5, 0x90, 0x19, 0xFA, 0x59, 0xD7, 0x00, 0x04,
1.35 + 0x0F, 0xAC, 0xCA, 0x9F, 0xA4, 0xFC, 0x6D, 0x90, 0x86, 0x9E, 0x1F, 0x44, 0x40, 0x00, 0x9F, 0x04,
1.36 + 0x56, 0x00, 0x22, 0x03, 0x00, 0xB8, 0x10, 0x2C, 0x7A, 0x53, 0xA4, 0xBF, 0xA3, 0x90, 0x90, 0x14,
1.37 + 0x9D, 0x46, 0x6C, 0x96, 0x00, 0xC6, 0x0B, 0x9B, 0xBB, 0xB0, 0xAE, 0x60, 0x92, 0x8E, 0x0C, 0x00,
1.38 + 0x14, 0x06, 0x4B, 0xAE, 0x7F, 0x00, 0x5C, 0x0B, 0x23, 0xFA, 0xE7, 0x51, 0xDA, 0x61, 0x49, 0x5E,
1.39 + 0x00, 0xD7, 0x0B, 0x01, 0xFC, 0x55, 0x31, 0x84, 0xC5, 0x0C, 0x98, 0x00, 0x97, 0x50, 0x6E, 0xF9,
1.40 + 0xEE, 0x75, 0x92, 0x53, 0xD3, 0x66, 0xA4, 0xAF, 0x3B, 0xFE, 0x7B, 0x27, 0x30, 0xBB, 0xB6, 0xF2,
1.41 + 0x76, 0x22, 0x45, 0x42, 0xCA, 0xF9, 0xF0, 0xDE, 0x9F, 0x45, 0x16, 0x68, 0x22, 0xB9, 0x84, 0x28,
1.42 + 0x8F, 0x2B, 0xB5, 0x5C, 0xD2, 0xF5, 0x45, 0x36, 0x3E, 0x76, 0xC6, 0xBF, 0x32, 0x5C, 0x41, 0xA6,
1.43 + 0x26, 0xC7, 0x82, 0x2F, 0x2E, 0xB5, 0x75, 0xC6, 0xE6, 0x67, 0x9E, 0x77, 0x94, 0xAF, 0x6A, 0x05,
1.44 + 0xC0, 0x05, 0x61, 0x71, 0x89, 0x5A, 0xB1, 0xD0, 0xFC, 0x7E, 0xC0, 0x9B, 0xCB, 0x3B, 0x69, 0xD9,
1.45 + 0x5F, 0xAF, 0xCA, 0xAB, 0x25, 0xD5, 0xBE, 0x8A, 0x6B, 0xB0, 0xFB, 0x61, 0x6C, 0xEB, 0x85, 0x6E,
1.46 + 0x7A, 0x48, 0xFF, 0x97, 0x91, 0x06, 0x3D, 0x4D, 0x68, 0xD3, 0x65, 0x83, 0x90, 0xA0, 0x08, 0x5C,
1.47 + 0xFC, 0xEE, 0x7C, 0x33, 0x43, 0x7F, 0x80, 0x52, 0x8B, 0x19, 0x72, 0xF2, 0xC9, 0xAB, 0x93, 0xAF,
1.48 + 0x16, 0xED, 0x36, 0x48, 0xAB, 0xC9, 0xD1, 0x03, 0xB3, 0xDC, 0x2F, 0xF2, 0x92, 0x3F, 0x0A, 0x19,
1.49 + 0x25, 0xE2, 0xEF, 0x7A, 0x22, 0xDA, 0xDB, 0xCB, 0x32, 0x12, 0x61, 0x49, 0x5B, 0x74, 0x7C, 0x65,
1.50 + 0x20, 0x89, 0x54, 0x9E, 0x0E, 0xC9, 0x52, 0xE3, 0xC9, 0x9A, 0x44, 0xC9, 0x5D, 0xA6, 0x77, 0xC0,
1.51 + 0xE7, 0x60, 0x91, 0x80, 0x50, 0x1F, 0x33, 0xB1, 0xCD, 0xAD, 0xF4, 0x0D, 0xBB, 0x08, 0xB1, 0xD0,
1.52 + 0x13, 0x95, 0xAE, 0xC9, 0xE2, 0x64, 0xA2, 0x65, 0xFB, 0x8F, 0xE9, 0xA2, 0x8A, 0xBC, 0x98, 0x81,
1.53 + 0x45, 0xB4, 0x55, 0x4E, 0xB9, 0x74, 0xB4, 0x50, 0x76, 0xBF, 0xF0, 0x45, 0xE7, 0xEE, 0x41, 0x64,
1.54 + 0x9F, 0xB5, 0xE0, 0xBB, 0x1C, 0xBB, 0x28, 0x66, 0x1B, 0xDD, 0x2B, 0x02, 0x66, 0xBF, 0xFD, 0x7D,
1.55 + 0x37, 0x35, 0x1D, 0x76, 0x21, 0xC3, 0x8F, 0xAF, 0xF6, 0xF9, 0xE9, 0x27, 0x48, 0xE7, 0x3D, 0x95,
1.56 + 0x74, 0x0C, 0x77, 0x88, 0x56, 0xD9, 0x84, 0xC8, 0x7D, 0x20, 0x31, 0x43, 0x53, 0xF1, 0xC1, 0xC7,
1.57 + 0xC9, 0xF7, 0x5C, 0xC0, 0xA6, 0x5A, 0x27, 0x0A, 0x41, 0xD4, 0x44, 0x94, 0x65, 0x4F, 0xE2, 0x53,
1.58 + 0x60, 0x0B, 0xD1, 0x23, 0x6C, 0x0C, 0xBC, 0x70, 0x6C, 0x26, 0x1A, 0x61, 0x1D, 0x35, 0x88, 0xEC,
1.59 + 0xB8, 0x15, 0xE3, 0xB4, 0x82, 0xEE, 0xB3, 0x21, 0xAC, 0x6C, 0xB7, 0x33, 0x6D, 0x78, 0x0C, 0x0D,
1.60 + 0xB4, 0x0B, 0x29, 0xF2, 0xD4, 0x8C, 0x3F, 0xDD, 0x3F, 0x47, 0xDD, 0xF2, 0xD8, 0x39, 0x57, 0x20,
1.61 + 0x28, 0xD8, 0xDD, 0x32, 0xE2, 0x6A, 0x47, 0x53, 0x57, 0xC6, 0xFA, 0x7A, 0x38, 0x30, 0x31, 0x8F,
1.62 + 0xE7, 0xD3, 0x84, 0x2B, 0x5D, 0x4F, 0x95, 0x98, 0xED, 0x0B, 0xD7, 0x50, 0x0C, 0x49, 0xDA, 0x59,
1.63 + 0x15, 0xF1, 0x39, 0xF3, 0x40, 0xDC, 0xDC, 0x25, 0x24, 0x56, 0x6E, 0xA9, 0x2F, 0xF0, 0x00, 0x00 };
1.64 +
1.65
1.66 static void ide_init( void )
1.67 {
1.68 @@ -76,7 +127,7 @@
1.69 idereg.lba1 = 0x14;
1.70 idereg.lba2 = 0xeb;
1.71 idereg.feature = 0; /* Indeterminate really */
1.72 - idereg.status = 0x00;
1.73 + idereg.status = 0x50;
1.74 idereg.device = 0x00;
1.75 idereg.disc = gdrom_is_mounted() ? (IDE_DISC_CDROM|IDE_DISC_READY) : IDE_DISC_NONE;
1.76 idereg.state = IDE_STATE_IDLE;
1.77 @@ -89,7 +140,7 @@
1.78 {
1.79 fwrite( &idereg, sizeof(idereg), 1, f );
1.80 fwrite( &data_buffer_len, sizeof(data_buffer_len), 1, f );
1.81 - fwrite( data_buffer, data_buffer_len, 1, f );
1.82 + fwrite( data_buffer, MAX_SECTOR_SIZE, data_buffer_len, f );
1.83 }
1.84
1.85 static int ide_load_state( FILE *f )
1.86 @@ -100,16 +151,30 @@
1.87 if( length > data_buffer_len ) {
1.88 if( data_buffer != NULL )
1.89 free( data_buffer );
1.90 - data_buffer = malloc( length );
1.91 + data_buffer = malloc( MAX_SECTOR_SIZE * length );
1.92 assert( data_buffer != NULL );
1.93 data_buffer_len = length;
1.94 }
1.95 - fread( data_buffer, length, 1, f );
1.96 + fread( data_buffer, MAX_SECTOR_SIZE, length, f );
1.97 return 0;
1.98 }
1.99
1.100 /************************ State transitions *************************/
1.101
1.102 +void ide_set_packet_result( uint16_t result )
1.103 +{
1.104 + idereg.gdrom_sense[0] = 0xf0;
1.105 + idereg.gdrom_sense[2] = result & 0xFF;
1.106 + idereg.gdrom_sense[8] = (result >> 8) & 0xFF;
1.107 + idereg.error = (result & 0x0F) << 4;
1.108 + if( result != 0 ) {
1.109 + idereg.status = 0x51;
1.110 + ide_raise_interrupt();
1.111 + } else {
1.112 + idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
1.113 + }
1.114 +}
1.115 +
1.116 /**
1.117 * Begin command packet write to the device. This is always 12 bytes of PIO data
1.118 */
1.119 @@ -129,27 +194,29 @@
1.120 */
1.121 static void ide_start_read( int length, int blocksize, gboolean dma )
1.122 {
1.123 - idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
1.124 idereg.count = IDE_COUNT_IO;
1.125 idereg.data_length = length;
1.126 idereg.data_offset = 0;
1.127 if( dma ) {
1.128 idereg.state = IDE_STATE_DMA_READ;
1.129 - idereg.status |= IDE_STATUS_DMRD;
1.130 + idereg.status = 0xD0;
1.131 } else {
1.132 idereg.state = IDE_STATE_PIO_READ;
1.133 + idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
1.134 idereg.lba1 = length & 0xFF;
1.135 idereg.lba2 = (length >> 8) & 0xFF;
1.136 // idereg.lba1 = blocksize & 0xFF;
1.137 // idereg.lba2 = blocksize >> 8;
1.138 idereg.block_length = blocksize;
1.139 idereg.block_left = blocksize;
1.140 + ide_raise_interrupt( );
1.141 }
1.142 }
1.143
1.144 static void ide_start_packet_read( int length, int blocksize )
1.145 {
1.146 - ide_start_read( length, blocksize, idereg.feature & IDE_FEAT_DMA ? TRUE : FALSE );
1.147 + ide_set_packet_result( PKT_ERR_OK );
1.148 + ide_start_read( length, blocksize, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
1.149 }
1.150
1.151 static void ide_raise_interrupt( void )
1.152 @@ -225,15 +292,15 @@
1.153 if( idereg.data_offset >= idereg.data_length ) {
1.154 idereg.data_offset = -1;
1.155 idereg.state = IDE_STATE_IDLE;
1.156 - idereg.status &= ~IDE_STATUS_DRQ;
1.157 + idereg.status = 0x50;
1.158 ide_raise_interrupt();
1.159 + asic_event( EVENT_IDE_DMA );
1.160 }
1.161 return xferlen;
1.162 }
1.163 return 0;
1.164 }
1.165
1.166 -
1.167 void ide_write_data_pio( uint16_t val ) {
1.168 if( idereg.state == IDE_STATE_CMD_WRITE ) {
1.169 WRITE_BUFFER(val);
1.170 @@ -308,19 +375,6 @@
1.171 idereg.status = (idereg.status | IDE_STATUS_DRDY | IDE_STATUS_SERV) & (~IDE_STATUS_CHK);
1.172 }
1.173
1.174 -void ide_set_packet_result( uint16_t result )
1.175 -{
1.176 - idereg.gdrom_sense[0] = 0xf0;
1.177 - idereg.gdrom_sense[2] = result & 0xFF;
1.178 - idereg.gdrom_sense[8] = (result >> 8) & 0xFF;
1.179 - idereg.error = (result & 0x0F) << 4;
1.180 - if( result != 0 ) {
1.181 - idereg.status = 0x51;
1.182 - } else {
1.183 - idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
1.184 - }
1.185 -}
1.186 -
1.187 /**
1.188 * Execute a packet command. This particular method is responsible for parsing
1.189 * the command buffers (12 bytes), and generating the appropriate responses,
1.190 @@ -333,31 +387,31 @@
1.191 int mode;
1.192 int blocksize = idereg.lba1 + (idereg.lba2<<8);
1.193
1.194 - ide_raise_interrupt( );
1.195 /* Okay we have the packet in the command buffer */
1.196 WARN( "ATAPI: Received Packet command: %02X", cmd[0] );
1.197 fwrite_dump( (unsigned char *)cmd, 12, stderr );
1.198 + // fprint_stack_trace( stderr );
1.199 switch( cmd[0] ) {
1.200 case PKT_CMD_TEST_READY:
1.201 if( !gdrom_is_mounted() ) {
1.202 ide_set_packet_result( PKT_ERR_NODISC );
1.203 - return;
1.204 + } else {
1.205 + ide_set_packet_result( 0 );
1.206 + ide_raise_interrupt();
1.207 + idereg.status = 0x50;
1.208 }
1.209 - ide_set_packet_result( 0 );
1.210 - idereg.status = 0x50;
1.211 - return;
1.212 break;
1.213 case PKT_CMD_IDENTIFY:
1.214 lba = cmd[2];
1.215 if( lba >= sizeof(gdrom_ident) ) {
1.216 ide_set_error(PKT_ERR_BADFIELD);
1.217 - return;
1.218 + } else {
1.219 + length = cmd[4];
1.220 + if( lba+length > sizeof(gdrom_ident) )
1.221 + length = sizeof(gdrom_ident) - lba;
1.222 + memcpy( data_buffer, gdrom_ident + lba, length );
1.223 + ide_start_packet_read( length, blocksize );
1.224 }
1.225 - length = cmd[4];
1.226 - if( lba+length > sizeof(gdrom_ident) )
1.227 - length = sizeof(gdrom_ident) - lba;
1.228 - memcpy( data_buffer, gdrom_ident + lba, length );
1.229 - ide_start_packet_read( length, blocksize );
1.230 break;
1.231 case PKT_CMD_SENSE:
1.232 length = cmd[4];
1.233 @@ -374,31 +428,24 @@
1.234 status = gdrom_get_toc( data_buffer );
1.235 if( status != PKT_ERR_OK ) {
1.236 ide_set_packet_result( status );
1.237 - return;
1.238 + } else {
1.239 + ide_start_packet_read( length, blocksize );
1.240 }
1.241 - ide_start_packet_read( length, blocksize );
1.242 break;
1.243 - case PKT_CMD_DISC_INFO:
1.244 + case PKT_CMD_SESSION_INFO:
1.245 length = cmd[4];
1.246 if( length > 6 )
1.247 length = 6;
1.248 status = gdrom_get_info( data_buffer, cmd[2] );
1.249 if( status != PKT_ERR_OK ) {
1.250 ide_set_packet_result( status );
1.251 - return;
1.252 + } else {
1.253 + ide_start_packet_read( length, blocksize );
1.254 }
1.255 - ide_start_packet_read( length, blocksize );
1.256 break;
1.257 case PKT_CMD_READ_SECTOR:
1.258 lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
1.259 length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
1.260 - if( length > data_buffer_len ) {
1.261 - do {
1.262 - data_buffer_len = data_buffer_len << 1;
1.263 - } while( data_buffer_len < length );
1.264 - data_buffer = realloc( data_buffer, data_buffer_len );
1.265 - }
1.266 -
1.267 switch( cmd[1] ) {
1.268 case 0x20: mode = GDROM_MODE1; break;
1.269 case 0x24: mode = GDROM_GD; break;
1.270 @@ -409,6 +456,14 @@
1.271 ide_set_packet_result( PKT_ERR_BADFIELD );
1.272 return;
1.273 }
1.274 +
1.275 + if( length > data_buffer_len ) {
1.276 + do {
1.277 + data_buffer_len = data_buffer_len << 1;
1.278 + } while( data_buffer_len < length );
1.279 + data_buffer = realloc( data_buffer, MAX_SECTOR_SIZE * data_buffer_len );
1.280 + }
1.281 +
1.282 datalen = data_buffer_len;
1.283 status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );
1.284 if( status != 0 ) {
1.285 @@ -416,16 +471,25 @@
1.286 idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;
1.287 idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;
1.288 idereg.gdrom_sense[7] = lba & 0xFF;
1.289 - return;
1.290 + } else {
1.291 + ide_start_packet_read( datalen, blocksize );
1.292 }
1.293 - ide_start_packet_read( datalen, blocksize );
1.294 break;
1.295 case PKT_CMD_SPIN_UP:
1.296 /* do nothing? */
1.297 + ide_set_packet_result( PKT_ERR_OK );
1.298 + ide_raise_interrupt();
1.299 + break;
1.300 + case PKT_CMD_71:
1.301 + /* This is a weird one. As far as I can tell it returns random garbage
1.302 + * (and not even the same length each time, never mind the same data).
1.303 + * For sake of something to do, it returns the results from a test dump
1.304 + */
1.305 + memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );
1.306 + ide_start_packet_read( sizeof(gdrom_71), blocksize );
1.307 break;
1.308 default:
1.309 ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
1.310 return;
1.311 }
1.312 - ide_set_packet_result( PKT_ERR_OK );
1.313 }
.