Search
lxdream.org :: lxdream/src/gdrom/ide.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/ide.c
changeset 152:d42a4c5cc709
prev149:d88dd2e9a190
next158:a0a82246b44e
author nkeynes
date Tue May 23 13:11:45 2006 +0000 (14 years ago)
permissions -rw-r--r--
last change Clean up the buffer and i/o handling
Implement save/load state
file annotate diff log raw
nkeynes@31
     1
/**
nkeynes@152
     2
 * $Id: ide.c,v 1.14 2006-05-23 13:11:45 nkeynes Exp $
nkeynes@2
     3
 *
nkeynes@31
     4
 * IDE interface implementation
nkeynes@31
     5
 *
nkeynes@152
     6
 *
nkeynes@152
     7
 * Note: All references to read/write are from the host's point of view.
nkeynes@152
     8
 *
nkeynes@152
     9
 * See: INF-8020 
nkeynes@31
    10
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@31
    11
 *
nkeynes@31
    12
 * This program is free software; you can redistribute it and/or modify
nkeynes@31
    13
 * it under the terms of the GNU General Public License as published by
nkeynes@31
    14
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@31
    15
 * (at your option) any later version.
nkeynes@31
    16
 *
nkeynes@31
    17
 * This program is distributed in the hope that it will be useful,
nkeynes@31
    18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@31
    19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@31
    20
 * GNU General Public License for more details.
nkeynes@2
    21
 */
nkeynes@35
    22
nkeynes@35
    23
#define MODULE ide_module
nkeynes@35
    24
nkeynes@138
    25
#include <assert.h>
nkeynes@2
    26
#include <stdlib.h>
nkeynes@35
    27
#include "dream.h"
nkeynes@125
    28
#include "asic.h"
nkeynes@39
    29
#include "gdrom/ide.h"
nkeynes@125
    30
#include "gdrom/gdrom.h"
nkeynes@142
    31
#include "gdrom/packet.h"
nkeynes@2
    32
nkeynes@138
    33
#define MAX_WRITE_BUF 4096
nkeynes@138
    34
#define MAX_SECTOR_SIZE 2352 /* Audio sector */
nkeynes@138
    35
#define DEFAULT_DATA_SECTORS 8
nkeynes@2
    36
nkeynes@138
    37
static void ide_init( void );
nkeynes@138
    38
static void ide_reset( void );
nkeynes@138
    39
static void ide_save_state( FILE *f );
nkeynes@138
    40
static int ide_load_state( FILE *f );
nkeynes@138
    41
static void ide_raise_interrupt( void );
nkeynes@138
    42
static void ide_clear_interrupt( void );
nkeynes@152
    43
static void ide_packet_command( unsigned char *data );
nkeynes@15
    44
nkeynes@15
    45
struct dreamcast_module ide_module = { "IDE", ide_init, ide_reset, NULL, NULL,
nkeynes@138
    46
				       NULL, ide_save_state, ide_load_state };
nkeynes@15
    47
nkeynes@2
    48
struct ide_registers idereg;
nkeynes@138
    49
unsigned char *data_buffer = NULL;
nkeynes@138
    50
uint32_t data_buffer_len = 0;
nkeynes@2
    51
nkeynes@152
    52
#define WRITE_BUFFER(x16) *((uint16_t *)(data_buffer + idereg.data_offset)) = x16
nkeynes@152
    53
#define READ_BUFFER() *((uint16_t *)(data_buffer + idereg.data_offset))
nkeynes@152
    54
nkeynes@2
    55
/* "\0\0\0\0\xb4\x19\0\0\x08SE      REV 6.42990316" */
nkeynes@125
    56
unsigned char gdrom_ident[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00,
nkeynes@2
    57
                       0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
nkeynes@2
    58
                       0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2e,
nkeynes@2
    59
                       0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
nkeynes@2
    60
nkeynes@2
    61
nkeynes@138
    62
static void ide_init( void )
nkeynes@138
    63
{
nkeynes@138
    64
    ide_reset();
nkeynes@138
    65
    data_buffer_len = DEFAULT_DATA_SECTORS; 
nkeynes@138
    66
    data_buffer = malloc( MAX_SECTOR_SIZE * data_buffer_len ); 
nkeynes@138
    67
    assert( data_buffer != NULL );
nkeynes@138
    68
}
nkeynes@138
    69
nkeynes@138
    70
static void ide_reset( void )
nkeynes@138
    71
{
nkeynes@138
    72
    ide_clear_interrupt();
nkeynes@138
    73
    idereg.error = 0x01;
nkeynes@138
    74
    idereg.count = 0x01;
nkeynes@138
    75
    idereg.lba0 = /* 0x21; */ 0x81;
nkeynes@138
    76
    idereg.lba1 = 0x14;
nkeynes@138
    77
    idereg.lba2 = 0xeb;
nkeynes@138
    78
    idereg.feature = 0; /* Indeterminate really */
nkeynes@138
    79
    idereg.status = 0x00;
nkeynes@138
    80
    idereg.device = 0x00;
nkeynes@143
    81
    idereg.disc = gdrom_is_mounted() ? (IDE_DISC_CDROM|IDE_DISC_READY) : IDE_DISC_NONE;
nkeynes@152
    82
    idereg.state = IDE_STATE_IDLE;
nkeynes@152
    83
    memset( idereg.gdrom_sense, '\0', 10 );
nkeynes@152
    84
    idereg.data_offset = -1;
nkeynes@152
    85
    idereg.data_length = -1;
nkeynes@138
    86
}
nkeynes@138
    87
nkeynes@138
    88
static void ide_save_state( FILE *f )
nkeynes@138
    89
{
nkeynes@152
    90
    fwrite( &idereg, sizeof(idereg), 1, f );
nkeynes@152
    91
    fwrite( &data_buffer_len, sizeof(data_buffer_len), 1, f );
nkeynes@152
    92
    fwrite( data_buffer, data_buffer_len, 1, f );
nkeynes@138
    93
}
nkeynes@138
    94
nkeynes@138
    95
static int ide_load_state( FILE *f )
nkeynes@138
    96
{
nkeynes@152
    97
    uint32_t length;
nkeynes@152
    98
    fread( &idereg, sizeof(idereg), 1, f );
nkeynes@152
    99
    fread( &length, sizeof(uint32_t), 1, f );
nkeynes@152
   100
    if( length > data_buffer_len ) {
nkeynes@152
   101
	if( data_buffer != NULL )
nkeynes@152
   102
	    free( data_buffer );
nkeynes@152
   103
	data_buffer = malloc( length );
nkeynes@152
   104
	assert( data_buffer != NULL );
nkeynes@152
   105
	data_buffer_len = length;
nkeynes@152
   106
    }
nkeynes@152
   107
    fread( data_buffer, length, 1, f );
nkeynes@138
   108
    return 0;
nkeynes@138
   109
}
nkeynes@125
   110
nkeynes@152
   111
/************************ State transitions *************************/
nkeynes@152
   112
nkeynes@152
   113
/**
nkeynes@152
   114
 * Begin command packet write to the device. This is always 12 bytes of PIO data
nkeynes@152
   115
 */
nkeynes@152
   116
static void ide_start_command_packet_write( )
nkeynes@2
   117
{
nkeynes@152
   118
    idereg.state = IDE_STATE_CMD_WRITE;
nkeynes@152
   119
    idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
nkeynes@152
   120
    idereg.error = idereg.feature & 0x03; /* Copy values of OVL/DMA */
nkeynes@152
   121
    idereg.count = IDE_COUNT_CD;
nkeynes@152
   122
    idereg.data_offset = 0;
nkeynes@152
   123
    idereg.data_length = 12;
nkeynes@2
   124
}
nkeynes@2
   125
nkeynes@152
   126
/**
nkeynes@152
   127
 * Begin PIO read from the device. The data is assumed to already be
nkeynes@152
   128
 * in the buffer at this point.
nkeynes@152
   129
 */
nkeynes@152
   130
static void ide_start_read( int length, int blocksize, gboolean dma ) 
nkeynes@2
   131
{
nkeynes@152
   132
    idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
nkeynes@152
   133
    idereg.count = IDE_COUNT_IO;
nkeynes@152
   134
    idereg.data_length = length;
nkeynes@152
   135
    idereg.data_offset = 0;
nkeynes@152
   136
    if( dma ) {
nkeynes@152
   137
	idereg.state = IDE_STATE_DMA_READ;
nkeynes@152
   138
	idereg.status |= IDE_STATUS_DMRD;
nkeynes@152
   139
    } else {
nkeynes@152
   140
	idereg.state = IDE_STATE_PIO_READ;
nkeynes@152
   141
	idereg.lba1 = length & 0xFF;
nkeynes@152
   142
	idereg.lba2 = (length >> 8) & 0xFF;
nkeynes@152
   143
	//	idereg.lba1 = blocksize & 0xFF;
nkeynes@152
   144
	//	idereg.lba2 = blocksize >> 8; 
nkeynes@152
   145
	idereg.block_length = blocksize;
nkeynes@152
   146
	idereg.block_left = blocksize;
nkeynes@152
   147
    }
nkeynes@152
   148
}
nkeynes@152
   149
nkeynes@152
   150
static void ide_start_packet_read( int length, int blocksize )
nkeynes@152
   151
{
nkeynes@152
   152
    ide_start_read( length, blocksize, idereg.feature & IDE_FEAT_DMA ? TRUE : FALSE );
nkeynes@2
   153
}
nkeynes@2
   154
nkeynes@125
   155
static void ide_raise_interrupt( void )
nkeynes@2
   156
{
nkeynes@125
   157
    if( idereg.intrq_pending == 0 ) {
nkeynes@125
   158
	idereg.intrq_pending = 1;
nkeynes@125
   159
	if( IS_IDE_IRQ_ENABLED() )
nkeynes@125
   160
	    asic_event( EVENT_IDE );
nkeynes@125
   161
    }
nkeynes@125
   162
}
nkeynes@125
   163
nkeynes@125
   164
static void ide_clear_interrupt( void ) 
nkeynes@125
   165
{
nkeynes@125
   166
    if( idereg.intrq_pending != 0 ) {
nkeynes@125
   167
	idereg.intrq_pending = 0;
nkeynes@125
   168
	if( IS_IDE_IRQ_ENABLED() )
nkeynes@125
   169
	    asic_clear_event( EVENT_IDE );
nkeynes@125
   170
    }
nkeynes@125
   171
}
nkeynes@125
   172
nkeynes@125
   173
static void ide_set_error( int error_code )
nkeynes@125
   174
{
nkeynes@125
   175
    idereg.status = 0x51;
nkeynes@125
   176
    idereg.error = error_code;
nkeynes@2
   177
}
nkeynes@2
   178
nkeynes@125
   179
uint8_t ide_read_status( void ) 
nkeynes@125
   180
{
nkeynes@152
   181
    if( (idereg.status & IDE_STATUS_BSY) == 0 )
nkeynes@125
   182
	ide_clear_interrupt();
nkeynes@125
   183
    return idereg.status;
nkeynes@2
   184
}
nkeynes@2
   185
nkeynes@2
   186
uint16_t ide_read_data_pio( void ) {
nkeynes@152
   187
    if( idereg.state == IDE_STATE_PIO_READ ) {
nkeynes@152
   188
	uint16_t rv = READ_BUFFER();
nkeynes@152
   189
	idereg.data_offset += 2;
nkeynes@152
   190
	idereg.block_left -= 2;
nkeynes@152
   191
	if( idereg.data_offset >= idereg.data_length ) {
nkeynes@152
   192
	    idereg.state = IDE_STATE_IDLE;
nkeynes@152
   193
	    idereg.status &= ~IDE_STATUS_DRQ;
nkeynes@152
   194
	    idereg.data_offset = -1;
nkeynes@152
   195
	    ide_raise_interrupt();
nkeynes@152
   196
	} else if( idereg.block_left <= 0 ) {
nkeynes@152
   197
	    idereg.block_left = idereg.block_length;
nkeynes@152
   198
	    ide_raise_interrupt();
nkeynes@152
   199
	}
nkeynes@152
   200
	return rv;
nkeynes@152
   201
    } else {
nkeynes@2
   202
        return 0xFFFF;
nkeynes@2
   203
    }
nkeynes@2
   204
}
nkeynes@2
   205
nkeynes@152
   206
nkeynes@152
   207
/**
nkeynes@152
   208
 * DMA read request
nkeynes@152
   209
 *
nkeynes@152
   210
 * This method is called from the ASIC side when a DMA read request is
nkeynes@152
   211
 * initiated. If there is a pending DMA transfer already, we copy the
nkeynes@152
   212
 * data immediately, otherwise we record the DMA buffer for use when we
nkeynes@152
   213
 * get to actually doing the transfer.
nkeynes@152
   214
 * @return number of bytes transfered
nkeynes@152
   215
 */
nkeynes@152
   216
uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )
nkeynes@152
   217
{
nkeynes@152
   218
    if( idereg.state == IDE_STATE_DMA_READ ) {
nkeynes@152
   219
	int xferlen = length;
nkeynes@152
   220
	int remaining = idereg.data_length - idereg.data_offset;
nkeynes@152
   221
	if( xferlen > remaining )
nkeynes@152
   222
	    xferlen = remaining;
nkeynes@152
   223
	mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );
nkeynes@152
   224
	idereg.data_offset += xferlen;
nkeynes@152
   225
	if( idereg.data_offset >= idereg.data_length ) {
nkeynes@152
   226
	    idereg.data_offset = -1;
nkeynes@152
   227
	    idereg.state = IDE_STATE_IDLE;
nkeynes@152
   228
	    idereg.status &= ~IDE_STATUS_DRQ;
nkeynes@152
   229
	    ide_raise_interrupt();
nkeynes@152
   230
	}
nkeynes@152
   231
	return xferlen;
nkeynes@152
   232
    }
nkeynes@152
   233
    return 0;
nkeynes@152
   234
}
nkeynes@152
   235
nkeynes@152
   236
nkeynes@2
   237
void ide_write_data_pio( uint16_t val ) {
nkeynes@152
   238
    if( idereg.state == IDE_STATE_CMD_WRITE ) {
nkeynes@152
   239
	WRITE_BUFFER(val);
nkeynes@152
   240
	idereg.data_offset+=2;
nkeynes@152
   241
	if( idereg.data_offset >= idereg.data_length ) {
nkeynes@152
   242
	    idereg.state = IDE_STATE_BUSY;
nkeynes@152
   243
	    idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
nkeynes@152
   244
	    idereg.data_offset = -1;
nkeynes@152
   245
	    ide_packet_command(data_buffer);
nkeynes@152
   246
	}
nkeynes@152
   247
    } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
nkeynes@152
   248
	WRITE_BUFFER(val);
nkeynes@152
   249
	if( idereg.data_offset >= idereg.data_length ) {
nkeynes@152
   250
	    idereg.state = IDE_STATE_BUSY;
nkeynes@152
   251
	    idereg.data_offset = -1;
nkeynes@152
   252
	    idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
nkeynes@152
   253
	    /* ??? - no data writes yet anyway */
nkeynes@152
   254
	}
nkeynes@2
   255
    }
nkeynes@2
   256
}
nkeynes@2
   257
nkeynes@2
   258
void ide_write_control( uint8_t val ) {
nkeynes@125
   259
    if( IS_IDE_IRQ_ENABLED() ) {
nkeynes@125
   260
	if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
nkeynes@125
   261
	    asic_clear_event( EVENT_IDE );
nkeynes@125
   262
    } else {
nkeynes@125
   263
	if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
nkeynes@125
   264
	    asic_event( EVENT_IDE );
nkeynes@125
   265
    }
nkeynes@125
   266
    idereg.control = val;
nkeynes@2
   267
}
nkeynes@2
   268
nkeynes@2
   269
void ide_write_command( uint8_t val ) {
nkeynes@125
   270
    ide_clear_interrupt();
nkeynes@2
   271
    idereg.command = val;
nkeynes@2
   272
    switch( val ) {
nkeynes@39
   273
    case IDE_CMD_RESET_DEVICE:
nkeynes@39
   274
	ide_reset();
nkeynes@39
   275
	break;
nkeynes@39
   276
    case IDE_CMD_PACKET:
nkeynes@152
   277
	ide_start_command_packet_write();
nkeynes@39
   278
	break;
nkeynes@39
   279
    case IDE_CMD_SET_FEATURE:
nkeynes@39
   280
	switch( idereg.feature ) {
nkeynes@47
   281
	case IDE_FEAT_SET_TRANSFER_MODE:
nkeynes@47
   282
	    switch( idereg.count & 0xF8 ) {
nkeynes@47
   283
	    case IDE_XFER_PIO:
nkeynes@47
   284
		INFO( "Set PIO default mode: %d", idereg.count&0x07 );
nkeynes@47
   285
		break;
nkeynes@47
   286
	    case IDE_XFER_PIO_FLOW:
nkeynes@47
   287
		INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
nkeynes@47
   288
		break;
nkeynes@47
   289
	    case IDE_XFER_MULTI_DMA:
nkeynes@47
   290
		INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
nkeynes@47
   291
		break;
nkeynes@47
   292
	    case IDE_XFER_ULTRA_DMA:
nkeynes@47
   293
		INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
nkeynes@47
   294
		break;
nkeynes@47
   295
	    default:
nkeynes@47
   296
		INFO( "Setting unknown transfer mode: %02X", idereg.count );
nkeynes@47
   297
		break;
nkeynes@47
   298
	    }
nkeynes@47
   299
	    break;
nkeynes@39
   300
	default:
nkeynes@39
   301
	    WARN( "IDE: unimplemented feature: %02X", idereg.feature );
nkeynes@39
   302
	}
nkeynes@125
   303
	ide_raise_interrupt( );
nkeynes@39
   304
	break;
nkeynes@39
   305
    default:
nkeynes@39
   306
	WARN( "IDE: Unimplemented command: %02X", val );
nkeynes@2
   307
    }
nkeynes@152
   308
    idereg.status = (idereg.status | IDE_STATUS_DRDY | IDE_STATUS_SERV) & (~IDE_STATUS_CHK);
nkeynes@2
   309
}
nkeynes@2
   310
nkeynes@152
   311
void ide_set_packet_result( uint16_t result )
nkeynes@142
   312
{
nkeynes@152
   313
    idereg.gdrom_sense[0] = 0xf0;
nkeynes@152
   314
    idereg.gdrom_sense[2] = result & 0xFF;
nkeynes@152
   315
    idereg.gdrom_sense[8] = (result >> 8) & 0xFF;
nkeynes@152
   316
    idereg.error = (result & 0x0F) << 4;
nkeynes@152
   317
    if( result != 0 ) {
nkeynes@142
   318
	idereg.status = 0x51;
nkeynes@152
   319
    } else {
nkeynes@152
   320
	idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
nkeynes@142
   321
    }
nkeynes@142
   322
}
nkeynes@142
   323
nkeynes@142
   324
/**
nkeynes@142
   325
 * Execute a packet command. This particular method is responsible for parsing
nkeynes@142
   326
 * the command buffers (12 bytes), and generating the appropriate responses, 
nkeynes@142
   327
 * although the actual implementation is mostly delegated to gdrom.c
nkeynes@142
   328
 */
nkeynes@125
   329
void ide_packet_command( unsigned char *cmd )
nkeynes@125
   330
{
nkeynes@138
   331
    uint32_t length, datalen;
nkeynes@143
   332
    uint32_t lba, status;
nkeynes@143
   333
    int mode;
nkeynes@125
   334
    int blocksize = idereg.lba1 + (idereg.lba2<<8);
nkeynes@125
   335
nkeynes@125
   336
    ide_raise_interrupt( );
nkeynes@125
   337
    /* Okay we have the packet in the command buffer */
nkeynes@125
   338
    WARN( "ATAPI: Received Packet command: %02X", cmd[0] );
nkeynes@125
   339
    fwrite_dump( (unsigned char *)cmd, 12, stderr );
nkeynes@125
   340
    switch( cmd[0] ) {
nkeynes@142
   341
    case PKT_CMD_TEST_READY:
nkeynes@142
   342
	if( !gdrom_is_mounted() ) {
nkeynes@152
   343
	    ide_set_packet_result( PKT_ERR_NODISC );
nkeynes@142
   344
	    return;
nkeynes@142
   345
	}
nkeynes@152
   346
	ide_set_packet_result( 0 );
nkeynes@142
   347
	idereg.status = 0x50;
nkeynes@142
   348
	return;
nkeynes@142
   349
	break;
nkeynes@125
   350
    case PKT_CMD_IDENTIFY:
nkeynes@140
   351
	lba = cmd[2];
nkeynes@140
   352
	if( lba >= sizeof(gdrom_ident) ) {
nkeynes@142
   353
	    ide_set_error(PKT_ERR_BADFIELD);
nkeynes@140
   354
	    return;
nkeynes@140
   355
	}
nkeynes@140
   356
	length = cmd[4];
nkeynes@140
   357
	if( lba+length > sizeof(gdrom_ident) )
nkeynes@140
   358
	    length = sizeof(gdrom_ident) - lba;
nkeynes@152
   359
	memcpy( data_buffer, gdrom_ident + lba, length );
nkeynes@152
   360
	ide_start_packet_read( length, blocksize );
nkeynes@125
   361
	break;
nkeynes@142
   362
    case PKT_CMD_SENSE:
nkeynes@142
   363
	length = cmd[4];
nkeynes@142
   364
	if( length > 10 )
nkeynes@142
   365
	    length = 10;
nkeynes@152
   366
	memcpy( data_buffer, idereg.gdrom_sense, length );
nkeynes@152
   367
	ide_start_packet_read( length, blocksize );
nkeynes@142
   368
	break;
nkeynes@125
   369
    case PKT_CMD_READ_TOC:
nkeynes@142
   370
	length = (cmd[3]<<8) | cmd[4];
nkeynes@142
   371
	if( length > sizeof(struct gdrom_toc) )
nkeynes@142
   372
	    length = sizeof(struct gdrom_toc);
nkeynes@152
   373
nkeynes@152
   374
	status = gdrom_get_toc( data_buffer );
nkeynes@152
   375
	if( status != PKT_ERR_OK ) {
nkeynes@152
   376
	    ide_set_packet_result( status );
nkeynes@152
   377
	    return;
nkeynes@152
   378
	}
nkeynes@152
   379
	ide_start_packet_read( length, blocksize );
nkeynes@125
   380
	break;
nkeynes@149
   381
    case PKT_CMD_DISC_INFO:
nkeynes@149
   382
	length = cmd[4];
nkeynes@149
   383
	if( length > 6 )
nkeynes@149
   384
	    length = 6;
nkeynes@152
   385
	status = gdrom_get_info( data_buffer, cmd[2] );
nkeynes@152
   386
	if( status != PKT_ERR_OK ) {
nkeynes@152
   387
	    ide_set_packet_result( status );
nkeynes@152
   388
	    return;
nkeynes@152
   389
	}
nkeynes@152
   390
	ide_start_packet_read( length, blocksize );
nkeynes@149
   391
	break;
nkeynes@125
   392
    case PKT_CMD_READ_SECTOR:
nkeynes@125
   393
	lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
nkeynes@125
   394
	length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
nkeynes@138
   395
	if( length > data_buffer_len ) {
nkeynes@138
   396
	    do {
nkeynes@138
   397
		data_buffer_len = data_buffer_len << 1;
nkeynes@138
   398
	    } while( data_buffer_len < length );
nkeynes@138
   399
	    data_buffer = realloc( data_buffer, data_buffer_len );
nkeynes@138
   400
	}
nkeynes@142
   401
nkeynes@143
   402
	switch( cmd[1] ) {
nkeynes@143
   403
	case 0x20: mode = GDROM_MODE1; break;
nkeynes@143
   404
	case 0x24: mode = GDROM_GD; break;
nkeynes@143
   405
	case 0x28: mode = GDROM_MODE1; break; /* ??? */
nkeynes@143
   406
	case 0x30: mode = GDROM_RAW; break;
nkeynes@143
   407
	default:
nkeynes@143
   408
	    ERROR( "Unrecognized read mode '%02X' in GD-Rom read request", cmd[1] );
nkeynes@152
   409
	    ide_set_packet_result( PKT_ERR_BADFIELD );
nkeynes@142
   410
	    return;
nkeynes@142
   411
	}
nkeynes@152
   412
	datalen = data_buffer_len;
nkeynes@152
   413
	status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );
nkeynes@143
   414
	if( status != 0 ) {
nkeynes@152
   415
	    ide_set_packet_result( status );
nkeynes@152
   416
	    idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;
nkeynes@152
   417
	    idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;
nkeynes@152
   418
	    idereg.gdrom_sense[7] = lba & 0xFF;
nkeynes@125
   419
	    return;
nkeynes@125
   420
	}
nkeynes@152
   421
	ide_start_packet_read( datalen, blocksize );
nkeynes@125
   422
	break;
nkeynes@149
   423
    case PKT_CMD_SPIN_UP:
nkeynes@149
   424
	/* do nothing? */
nkeynes@149
   425
	break;
nkeynes@142
   426
    default:
nkeynes@152
   427
	ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
nkeynes@142
   428
	return;
nkeynes@125
   429
    }
nkeynes@152
   430
    ide_set_packet_result( PKT_ERR_OK );
nkeynes@125
   431
}
.