filename | src/gdrom/ide.c |
changeset | 342:850502f0e8de |
prev | 258:8864fae65928 |
next | 422:61a0598e07ff |
author | nkeynes |
date | Fri Sep 28 07:25:22 2007 +0000 (16 years ago) |
permissions | -rw-r--r-- |
last change | Remove MMU check (probably shouldn't be here anyway), and disable TRACE_IO checks by default |
file | annotate | diff | log | raw |
1.1 --- a/src/gdrom/ide.c Fri Dec 29 00:23:16 2006 +00001.2 +++ b/src/gdrom/ide.c Fri Sep 28 07:25:22 2007 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: ide.c,v 1.22 2006-12-29 00:23:13 nkeynes Exp $1.6 + * $Id: ide.c,v 1.23 2007-01-31 10:58:42 nkeynes Exp $1.7 *1.8 * IDE interface implementation1.9 *1.10 @@ -36,18 +36,21 @@1.12 static void ide_init( void );1.13 static void ide_reset( void );1.14 +static uint32_t ide_run_slice( uint32_t nanosecs );1.15 static void ide_save_state( FILE *f );1.16 static int ide_load_state( FILE *f );1.17 static void ide_raise_interrupt( void );1.18 static void ide_clear_interrupt( void );1.19 static void ide_packet_command( unsigned char *data );1.20 +static void ide_read_next_sector(void);1.22 -struct dreamcast_module ide_module = { "IDE", ide_init, ide_reset, NULL, NULL,1.23 +struct dreamcast_module ide_module = { "IDE", ide_init, ide_reset, NULL, ide_run_slice,1.24 NULL, ide_save_state, ide_load_state };1.26 struct ide_registers idereg;1.27 -unsigned char *data_buffer = NULL;1.28 -uint32_t data_buffer_len = 0;1.29 +gdrom_disc_t gdrom_disc = NULL;1.30 +1.31 +unsigned char data_buffer[MAX_SECTOR_SIZE];1.33 #define WRITE_BUFFER(x16) *((uint16_t *)(data_buffer + idereg.data_offset)) = x161.34 #define READ_BUFFER() *((uint16_t *)(data_buffer + idereg.data_offset))1.35 @@ -129,9 +132,6 @@1.36 static void ide_init( void )1.37 {1.38 ide_reset();1.39 - data_buffer_len = DEFAULT_DATA_SECTORS;1.40 - data_buffer = malloc( MAX_SECTOR_SIZE * data_buffer_len );1.41 - assert( data_buffer != NULL );1.42 }1.44 static void ide_reset( void )1.45 @@ -145,36 +145,36 @@1.46 idereg.feature = 0; /* Indeterminate really */1.47 idereg.status = 0x00;1.48 idereg.device = 0x00;1.49 - idereg.disc = gdrom_is_mounted() ? (IDE_DISC_CDROM|IDE_DISC_READY) : IDE_DISC_NONE;1.50 idereg.state = IDE_STATE_IDLE;1.51 memset( idereg.gdrom_sense, '\0', 10 );1.52 idereg.data_offset = -1;1.53 idereg.data_length = -1;1.54 idereg.last_read_track = 1;1.55 - idereg.last_read_lba = 150;1.56 + idereg.read_lba = 150;1.57 + idereg.read_mode = 0x28;1.58 + idereg.sectors_left = 0;1.59 idereg.was_reset = TRUE;1.60 }1.62 +static uint32_t ide_run_slice( uint32_t nanosecs )1.63 +{1.64 + if( gdrom_disc != NULL && gdrom_disc->run_time_slice != NULL ) {1.65 + gdrom_disc->run_time_slice(gdrom_disc, nanosecs);1.66 + }1.67 + return nanosecs;1.68 +}1.69 +1.70 static void ide_save_state( FILE *f )1.71 {1.72 fwrite( &idereg, sizeof(idereg), 1, f );1.73 - fwrite( &data_buffer_len, sizeof(data_buffer_len), 1, f );1.74 - fwrite( data_buffer, MAX_SECTOR_SIZE, data_buffer_len, f );1.75 + fwrite( data_buffer, MAX_SECTOR_SIZE, 1, f );1.76 }1.78 static int ide_load_state( FILE *f )1.79 {1.80 uint32_t length;1.81 fread( &idereg, sizeof(idereg), 1, f );1.82 - fread( &length, sizeof(uint32_t), 1, f );1.83 - if( length > data_buffer_len ) {1.84 - if( data_buffer != NULL )1.85 - free( data_buffer );1.86 - data_buffer = malloc( MAX_SECTOR_SIZE * length );1.87 - assert( data_buffer != NULL );1.88 - data_buffer_len = length;1.89 - }1.90 - fread( data_buffer, MAX_SECTOR_SIZE, length, f );1.91 + fread( data_buffer, MAX_SECTOR_SIZE, 1, f );1.92 return 0;1.93 }1.95 @@ -212,7 +212,7 @@1.96 * Begin PIO read from the device. The data is assumed to already be1.97 * in the buffer at this point.1.98 */1.99 -static void ide_start_read( int length, int blocksize, gboolean dma )1.100 +static void ide_start_read( int length, gboolean dma )1.101 {1.102 idereg.count = IDE_COUNT_IO;1.103 idereg.data_length = length;1.104 @@ -223,18 +223,17 @@1.105 } else {1.106 idereg.state = IDE_STATE_PIO_READ;1.107 idereg.status = 0x58;1.108 - idereg.lba1 = blocksize & 0xFF;1.109 - idereg.lba2 = blocksize >> 8;1.110 - idereg.block_length = blocksize;1.111 - idereg.block_left = blocksize;1.112 + idereg.lba1 = length & 0xFF;1.113 + idereg.lba2 = length >> 8;1.114 ide_raise_interrupt( );1.115 }1.116 }1.118 -static void ide_start_packet_read( int length, int blocksize )1.119 +static void ide_start_packet_read( int length, int sector_count )1.120 {1.121 + idereg.sectors_left = sector_count;1.122 ide_set_packet_result( PKT_ERR_OK );1.123 - ide_start_read( length, blocksize, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );1.124 + ide_start_read( length, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );1.125 }1.127 static void ide_raise_interrupt( void )1.128 @@ -272,16 +271,15 @@1.129 if( idereg.state == IDE_STATE_PIO_READ ) {1.130 uint16_t rv = READ_BUFFER();1.131 idereg.data_offset += 2;1.132 - idereg.block_left -= 2;1.133 if( idereg.data_offset >= idereg.data_length ) {1.134 idereg.state = IDE_STATE_IDLE;1.135 idereg.status &= ~IDE_STATUS_DRQ;1.136 idereg.data_offset = -1;1.137 idereg.count = 3; /* complete */1.138 ide_raise_interrupt();1.139 - } else if( idereg.block_left <= 0 ) {1.140 - idereg.block_left = idereg.block_length;1.141 - ide_raise_interrupt();1.142 + if( idereg.sectors_left > 0 ) {1.143 + ide_read_next_sector();1.144 + }1.145 }1.146 return rv;1.147 } else {1.148 @@ -301,24 +299,34 @@1.149 */1.150 uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )1.151 {1.152 + uint32_t xfercount = 0;1.153 if( idereg.state == IDE_STATE_DMA_READ ) {1.154 - int xferlen = length;1.155 - int remaining = idereg.data_length - idereg.data_offset;1.156 - if( xferlen > remaining )1.157 - xferlen = remaining;1.158 - mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );1.159 - idereg.data_offset += xferlen;1.160 - if( idereg.data_offset >= idereg.data_length ) {1.161 - idereg.data_offset = -1;1.162 - idereg.state = IDE_STATE_IDLE;1.163 - idereg.status = 0x50;1.164 - idereg.count = 0x03;1.165 - ide_raise_interrupt();1.166 - asic_event( EVENT_IDE_DMA );1.167 + while( xfercount < length ) {1.168 + int xferlen = length - xfercount;1.169 + int remaining = idereg.data_length - idereg.data_offset;1.170 + if( xferlen > remaining ) {1.171 + xferlen = remaining;1.172 + }1.173 + mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );1.174 + xfercount += xferlen;1.175 + addr += xferlen;1.176 + idereg.data_offset += xferlen;1.177 + if( idereg.data_offset >= idereg.data_length ) {1.178 + if( idereg.sectors_left > 0 ) {1.179 + ide_read_next_sector();1.180 + } else {1.181 + idereg.data_offset = -1;1.182 + idereg.state = IDE_STATE_IDLE;1.183 + idereg.status = 0x50;1.184 + idereg.count = 0x03;1.185 + ide_raise_interrupt();1.186 + asic_event( EVENT_IDE_DMA );1.187 + break;1.188 + }1.189 + }1.190 }1.191 - return xferlen;1.192 }1.193 - return 0;1.194 + return xfercount;1.195 }1.197 void ide_write_data_pio( uint16_t val ) {1.198 @@ -405,6 +413,40 @@1.199 }1.200 }1.202 +uint8_t ide_get_drive_status( void )1.203 +{1.204 + if( gdrom_disc == NULL ) {1.205 + return IDE_DISC_NONE;1.206 + } else {1.207 + return gdrom_disc->drive_status(gdrom_disc);1.208 + }1.209 +}1.210 +1.211 +#define REQUIRE_DISC() if( gdrom_disc == NULL ) { ide_set_packet_result( PKT_ERR_NODISC ); return; }1.212 +1.213 +/**1.214 + * Read the next sector from the active read, if any1.215 + */1.216 +static void ide_read_next_sector( void )1.217 +{1.218 + int sector_size;1.219 + REQUIRE_DISC();1.220 + gdrom_error_t status =1.221 + gdrom_disc->read_sector( gdrom_disc, idereg.read_lba, idereg.read_mode,1.222 + data_buffer, §or_size );1.223 + if( status != PKT_ERR_OK ) {1.224 + ide_set_packet_result( status );1.225 + idereg.gdrom_sense[5] = (idereg.read_lba >> 16) & 0xFF;1.226 + idereg.gdrom_sense[6] = (idereg.read_lba >> 8) & 0xFF;1.227 + idereg.gdrom_sense[7] = idereg.read_lba & 0xFF;1.228 + WARN( " => Read CD returned sense key %02X, %02X", status & 0xFF, status >> 8 );1.229 + } else {1.230 + idereg.read_lba++;1.231 + idereg.sectors_left--;1.232 + ide_start_read( sector_size, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );1.233 + }1.234 +}1.235 +1.236 /**1.237 * Execute a packet command. This particular method is responsible for parsing1.238 * the command buffers (12 bytes), and generating the appropriate responses,1.239 @@ -415,7 +457,6 @@1.240 uint32_t length, datalen;1.241 uint32_t lba, status;1.242 int mode;1.243 - int blocksize = idereg.lba1 + (idereg.lba2<<8);1.245 /* Okay we have the packet in the command buffer */1.246 INFO( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",1.247 @@ -430,13 +471,10 @@1.249 switch( cmd[0] ) {1.250 case PKT_CMD_TEST_READY:1.251 - if( !gdrom_is_mounted() ) {1.252 - ide_set_packet_result( PKT_ERR_NODISC );1.253 - } else {1.254 - ide_set_packet_result( 0 );1.255 - ide_raise_interrupt();1.256 - idereg.status = 0x50;1.257 - }1.258 + REQUIRE_DISC();1.259 + ide_set_packet_result( 0 );1.260 + ide_raise_interrupt();1.261 + idereg.status = 0x50;1.262 break;1.263 case PKT_CMD_IDENTIFY:1.264 lba = cmd[2];1.265 @@ -447,7 +485,7 @@1.266 if( lba+length > sizeof(gdrom_ident) )1.267 length = sizeof(gdrom_ident) - lba;1.268 memcpy( data_buffer, gdrom_ident + lba, length );1.269 - ide_start_packet_read( length, length );1.270 + ide_start_packet_read( length, 0 );1.271 }1.272 break;1.273 case PKT_CMD_SENSE:1.274 @@ -455,112 +493,74 @@1.275 if( length > 10 )1.276 length = 10;1.277 memcpy( data_buffer, idereg.gdrom_sense, length );1.278 - ide_start_packet_read( length, length );1.279 + ide_start_packet_read( length, 0 );1.280 break;1.281 case PKT_CMD_READ_TOC:1.282 + REQUIRE_DISC();1.283 length = (cmd[3]<<8) | cmd[4];1.284 if( length > sizeof(struct gdrom_toc) )1.285 length = sizeof(struct gdrom_toc);1.287 - status = gdrom_get_toc( data_buffer );1.288 + status = gdrom_disc->read_toc( gdrom_disc, data_buffer );1.289 if( status != PKT_ERR_OK ) {1.290 ide_set_packet_result( status );1.291 } else {1.292 - ide_start_packet_read( length, length );1.293 + ide_start_packet_read( length, 0 );1.294 }1.295 break;1.296 case PKT_CMD_SESSION_INFO:1.297 + REQUIRE_DISC();1.298 length = cmd[4];1.299 if( length > 6 )1.300 length = 6;1.301 - status = gdrom_get_info( data_buffer, cmd[2] );1.302 + status = gdrom_disc->read_session( gdrom_disc, cmd[2], data_buffer );1.303 if( status != PKT_ERR_OK ) {1.304 ide_set_packet_result( status );1.305 } else {1.306 - ide_start_packet_read( length, length );1.307 + ide_start_packet_read( length, 0 );1.308 }1.309 break;1.310 - case PKT_CMD_PLAY_CD:1.311 + case PKT_CMD_PLAY_AUDIO:1.312 + REQUIRE_DISC();1.313 ide_set_packet_result( 0 );1.314 ide_raise_interrupt();1.315 idereg.status = 0x50;1.316 break;1.317 case PKT_CMD_READ_SECTOR:1.318 - lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];1.319 - length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */1.320 - switch( cmd[1] ) {1.321 - case 0x20: mode = GDROM_MODE1; break; /* TODO - might be unchecked? */1.322 - case 0x24: mode = GDROM_GD; break;1.323 - case 0x28: mode = GDROM_MODE2_XA1; break; /* ??? */1.324 - case 0x30: mode = GDROM_RAW; break;1.325 - default:1.326 - ERROR( "Unrecognized read mode '%02X' in GD-Rom read request", cmd[1] );1.327 - ide_set_packet_result( PKT_ERR_BADFIELD );1.328 - return;1.329 - }1.330 -1.331 - if( length > data_buffer_len ) {1.332 - do {1.333 - data_buffer_len = data_buffer_len << 1;1.334 - } while( data_buffer_len < length );1.335 - data_buffer = realloc( data_buffer, MAX_SECTOR_SIZE * data_buffer_len );1.336 - }1.337 -1.338 - datalen = data_buffer_len;1.339 - status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );1.340 - if( status != 0 ) {1.341 - ide_set_packet_result( status );1.342 - idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;1.343 - idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;1.344 - idereg.gdrom_sense[7] = lba & 0xFF;1.345 - WARN( " => Read CD returned sense key %02X, %02X", status & 0xFF, status >> 8 );1.346 - } else {1.347 - idereg.last_read_lba = lba + length;1.348 - idereg.last_read_track = gdrom_get_track_no_by_lba( idereg.last_read_lba );1.349 - ide_start_packet_read( datalen, 0x0800 );1.350 - }1.351 + REQUIRE_DISC();1.352 + idereg.read_lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];1.353 + idereg.sectors_left = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */1.354 + idereg.read_mode = cmd[1];1.355 + ide_read_next_sector();1.356 break;1.357 case PKT_CMD_SPIN_UP:1.358 + REQUIRE_DISC();1.359 /* do nothing? */1.360 ide_set_packet_result( PKT_ERR_OK );1.361 ide_raise_interrupt();1.362 break;1.363 case PKT_CMD_STATUS:1.364 + REQUIRE_DISC();1.365 length = cmd[4];1.366 - if( !gdrom_is_mounted() ) {1.367 - ide_set_packet_result( PKT_ERR_NODISC );1.368 - } else {1.369 - switch( cmd[1] ) {1.370 - case 0:1.371 - if( length > sizeof(gdrom_status) ) {1.372 - length = sizeof(gdrom_status);1.373 - }1.374 - memcpy( data_buffer, gdrom_status, length );1.375 - ide_start_packet_read( length, length );1.376 - break;1.377 - case 1:1.378 - if( length > 14 ) {1.379 - length = 14;1.380 - }1.381 - gdrom_track_t track = gdrom_get_track(idereg.last_read_track);1.382 - int offset = idereg.last_read_lba - track->lba;1.383 - data_buffer[0] = 0x00;1.384 - data_buffer[1] = 0x15; /* ??? */1.385 - data_buffer[2] = 0x00;1.386 - data_buffer[3] = 0x0E;1.387 - data_buffer[4] = track->flags;1.388 - data_buffer[5] = idereg.last_read_track;1.389 - data_buffer[6] = 0x01; /* ?? */1.390 - data_buffer[7] = (offset >> 16) & 0xFF;1.391 - data_buffer[8] = (offset >> 8) & 0xFF;1.392 - data_buffer[9] = offset & 0xFF;1.393 - data_buffer[10] = (idereg.last_read_lba >> 24) & 0xFF;1.394 - data_buffer[11] = (idereg.last_read_lba >> 16) & 0xFF;1.395 - data_buffer[12] = (idereg.last_read_lba >> 8) & 0xFF;1.396 - data_buffer[13] = idereg.last_read_lba & 0xFF;1.397 - ide_start_packet_read( length, length );1.398 - break;1.399 + switch( cmd[1] ) {1.400 + case 0:1.401 + if( length > sizeof(gdrom_status) ) {1.402 + length = sizeof(gdrom_status);1.403 }1.404 + memcpy( data_buffer, gdrom_status, length );1.405 + ide_start_packet_read( length, 0 );1.406 + break;1.407 + case 1:1.408 + if( length > 14 ) {1.409 + length = 14;1.410 + }1.411 + gdrom_disc->read_position( gdrom_disc, idereg.read_lba, data_buffer );1.412 + data_buffer[0] = 0x00;1.413 + data_buffer[1] = 0x15; /* audio status ? */1.414 + data_buffer[2] = 0x00;1.415 + data_buffer[3] = 0x0E;1.416 + ide_start_packet_read( length, 0 );1.417 + break;1.418 }1.419 break;1.420 case PKT_CMD_71:1.421 @@ -568,8 +568,9 @@1.422 * (and not even the same length each time, never mind the same data).1.423 * For sake of something to do, it returns the results from a test dump1.424 */1.425 + REQUIRE_DISC();1.426 memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );1.427 - ide_start_packet_read( sizeof(gdrom_71), sizeof(gdrom_71) );1.428 + ide_start_packet_read( sizeof(gdrom_71), 0 );1.429 break;1.430 default:1.431 ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
.