Search
lxdream.org :: lxdream/src/gdrom/ide.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/ide.c
changeset 342:850502f0e8de
prev258:8864fae65928
next422:61a0598e07ff
author nkeynes
date Sun Feb 04 11:30:41 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Fix handling of (some?) v3.0 cdi files
file annotate diff log raw
1.1 --- a/src/gdrom/ide.c Fri Dec 29 00:23:16 2006 +0000
1.2 +++ b/src/gdrom/ide.c Sun Feb 04 11:30:41 2007 +0000
1.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 implementation
1.9 *
1.10 @@ -36,18 +36,21 @@
1.11
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.21
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.25
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.32
1.33 #define WRITE_BUFFER(x16) *((uint16_t *)(data_buffer + idereg.data_offset)) = x16
1.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.43
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.61
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.77
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.94
1.95 @@ -212,7 +212,7 @@
1.96 * Begin PIO read from the device. The data is assumed to already be
1.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.117
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.126
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.196
1.197 void ide_write_data_pio( uint16_t val ) {
1.198 @@ -405,6 +413,40 @@
1.199 }
1.200 }
1.201
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 any
1.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, &sector_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 parsing
1.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.244
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.248
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.286
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 dump
1.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 */
.