2 * $Id: ide.c,v 1.20 2006-12-21 10:15:54 nkeynes Exp $
4 * IDE interface implementation
7 * Note: All references to read/write are from the host's point of view.
10 * Copyright (c) 2005 Nathan Keynes.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
23 #define MODULE ide_module
29 #include "gdrom/ide.h"
30 #include "gdrom/gdrom.h"
31 #include "gdrom/packet.h"
33 #define MAX_WRITE_BUF 4096
34 #define MAX_SECTOR_SIZE 2352 /* Audio sector */
35 #define DEFAULT_DATA_SECTORS 8
37 static void ide_init( void );
38 static void ide_reset( void );
39 static void ide_save_state( FILE *f );
40 static int ide_load_state( FILE *f );
41 static void ide_raise_interrupt( void );
42 static void ide_clear_interrupt( void );
43 static void ide_packet_command( unsigned char *data );
45 struct dreamcast_module ide_module = { "IDE", ide_init, ide_reset, NULL, NULL,
46 NULL, ide_save_state, ide_load_state };
48 struct ide_registers idereg;
49 unsigned char *data_buffer = NULL;
50 uint32_t data_buffer_len = 0;
52 #define WRITE_BUFFER(x16) *((uint16_t *)(data_buffer + idereg.data_offset)) = x16
53 #define READ_BUFFER() *((uint16_t *)(data_buffer + idereg.data_offset))
55 /* "\0\0\0\0\xb4\x19\0\0\x08SE REV 6.42990316" */
56 unsigned char gdrom_ident[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00,
57 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
58 0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2e,
59 0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
61 unsigned char gdrom_71[] = { 0x3E, 0x0F, 0x90, 0xBE, 0x1D, 0xD9, 0x89, 0x04, 0x28, 0x3A, 0x8E, 0x26, 0x5C, 0x95, 0x10, 0x5A,
62 0x0A, 0x99, 0xEE, 0xFB, 0x69, 0xCE, 0xD9, 0x63, 0x00, 0xF5, 0x0A, 0xBC, 0x2C, 0x0D, 0xF8, 0xE2,
63 0x05, 0x02, 0x00, 0x7C, 0x03, 0x00, 0x3D, 0x08, 0xD8, 0x8D, 0x08, 0x7A, 0x6D, 0x00, 0x35, 0x06,
64 0xBA, 0x66, 0x10, 0x00, 0x91, 0x08, 0x10, 0x29, 0xD0, 0x45, 0xDA, 0x00, 0x2D, 0x05, 0x69, 0x09,
65 0x00, 0x5E, 0x0F, 0x70, 0x86, 0x12, 0x6C, 0x77, 0x5A, 0xFB, 0xCD, 0x56, 0xFB, 0xF7, 0xB7, 0x00,
66 0x5D, 0x07, 0x19, 0x99, 0xF2, 0xAF, 0x00, 0x63, 0x03, 0x00, 0xF0, 0x10, 0xBE, 0xD7, 0xA0, 0x63,
67 0xFA, 0x84, 0xA7, 0x74, 0x94, 0xEF, 0xAD, 0xC2, 0xAC, 0x00, 0x78, 0x07, 0x9F, 0x57, 0x0B, 0x62,
68 0x00, 0xFE, 0x08, 0x08, 0x5D, 0x5A, 0x6A, 0x54, 0x00, 0xE2, 0x09, 0x93, 0x7E, 0x62, 0x2A, 0x5E,
69 0xDA, 0x00, 0x7E, 0x0F, 0xF0, 0x07, 0x01, 0x6D, 0x50, 0x86, 0xDD, 0x4A, 0x15, 0x54, 0xC7, 0xEC,
70 0x00, 0xF2, 0x0B, 0x07, 0xF8, 0x1A, 0xB0, 0x99, 0x3B, 0xF1, 0x36, 0x00, 0x94, 0x07, 0x34, 0xE3,
71 0xBC, 0x6E, 0x00, 0x34, 0x0D, 0x6F, 0xDA, 0xBD, 0xEE, 0xF7, 0xCC, 0xCE, 0x39, 0x7E, 0xE3, 0x00,
72 0x14, 0x08, 0xDC, 0xD2, 0xB9, 0xF9, 0x31, 0x00, 0xB0, 0x0C, 0x10, 0xA3, 0x45, 0x12, 0xC7, 0xCD,
73 0xBF, 0x05, 0x37, 0x00, 0xC4, 0x0D, 0x5F, 0xE0, 0x59, 0xBB, 0x01, 0x59, 0x03, 0xD6, 0x29, 0x9C,
74 0x00, 0x01, 0x0A, 0x09, 0xAA, 0xA8, 0xA8, 0x24, 0x0B, 0x66, 0x00, 0x5C, 0x05, 0xA5, 0xCE, 0x00,
75 0xC1, 0x0B, 0xB7, 0xA0, 0x6F, 0xE9, 0x2B, 0xCC, 0xB5, 0xFC, 0x00, 0x8D, 0x05, 0xF4, 0xAC, 0x00,
76 0x57, 0x04, 0xB6, 0x00, 0xFC, 0x03, 0x00, 0xC3, 0x10, 0x43, 0x3B, 0xBE, 0xA2, 0x96, 0xC3, 0x65,
77 0x9F, 0x9A, 0x88, 0xD5, 0x49, 0x68, 0x00, 0xDC, 0x11, 0x56, 0x23, 0x2D, 0xF9, 0xFC, 0xF5, 0x8B,
78 0x1B, 0xB1, 0xB7, 0x10, 0x21, 0x1C, 0x12, 0x00, 0x0D, 0x0D, 0xEB, 0x86, 0xA2, 0x49, 0x8D, 0x8D,
79 0xBE, 0xA1, 0x6D, 0x53, 0x00, 0xE1, 0x0A, 0x8E, 0x67, 0xAA, 0x16, 0x79, 0x39, 0x59, 0x00, 0x36,
80 0x0B, 0x2A, 0x4E, 0xAE, 0x51, 0x4B, 0xD0, 0x66, 0x33, 0x00, 0x8A, 0x07, 0xCD, 0x6F, 0xBA, 0x92,
81 0x00, 0x1A, 0x0E, 0xDF, 0x4A, 0xB3, 0x77, 0x1F, 0xA5, 0x90, 0x19, 0xFA, 0x59, 0xD7, 0x00, 0x04,
82 0x0F, 0xAC, 0xCA, 0x9F, 0xA4, 0xFC, 0x6D, 0x90, 0x86, 0x9E, 0x1F, 0x44, 0x40, 0x00, 0x9F, 0x04,
83 0x56, 0x00, 0x22, 0x03, 0x00, 0xB8, 0x10, 0x2C, 0x7A, 0x53, 0xA4, 0xBF, 0xA3, 0x90, 0x90, 0x14,
84 0x9D, 0x46, 0x6C, 0x96, 0x00, 0xC6, 0x0B, 0x9B, 0xBB, 0xB0, 0xAE, 0x60, 0x92, 0x8E, 0x0C, 0x00,
85 0x14, 0x06, 0x4B, 0xAE, 0x7F, 0x00, 0x5C, 0x0B, 0x23, 0xFA, 0xE7, 0x51, 0xDA, 0x61, 0x49, 0x5E,
86 0x00, 0xD7, 0x0B, 0x01, 0xFC, 0x55, 0x31, 0x84, 0xC5, 0x0C, 0x98, 0x00, 0x97, 0x50, 0x6E, 0xF9,
87 0xEE, 0x75, 0x92, 0x53, 0xD3, 0x66, 0xA4, 0xAF, 0x3B, 0xFE, 0x7B, 0x27, 0x30, 0xBB, 0xB6, 0xF2,
88 0x76, 0x22, 0x45, 0x42, 0xCA, 0xF9, 0xF0, 0xDE, 0x9F, 0x45, 0x16, 0x68, 0x22, 0xB9, 0x84, 0x28,
89 0x8F, 0x2B, 0xB5, 0x5C, 0xD2, 0xF5, 0x45, 0x36, 0x3E, 0x76, 0xC6, 0xBF, 0x32, 0x5C, 0x41, 0xA6,
90 0x26, 0xC7, 0x82, 0x2F, 0x2E, 0xB5, 0x75, 0xC6, 0xE6, 0x67, 0x9E, 0x77, 0x94, 0xAF, 0x6A, 0x05,
91 0xC0, 0x05, 0x61, 0x71, 0x89, 0x5A, 0xB1, 0xD0, 0xFC, 0x7E, 0xC0, 0x9B, 0xCB, 0x3B, 0x69, 0xD9,
92 0x5F, 0xAF, 0xCA, 0xAB, 0x25, 0xD5, 0xBE, 0x8A, 0x6B, 0xB0, 0xFB, 0x61, 0x6C, 0xEB, 0x85, 0x6E,
93 0x7A, 0x48, 0xFF, 0x97, 0x91, 0x06, 0x3D, 0x4D, 0x68, 0xD3, 0x65, 0x83, 0x90, 0xA0, 0x08, 0x5C,
94 0xFC, 0xEE, 0x7C, 0x33, 0x43, 0x7F, 0x80, 0x52, 0x8B, 0x19, 0x72, 0xF2, 0xC9, 0xAB, 0x93, 0xAF,
95 0x16, 0xED, 0x36, 0x48, 0xAB, 0xC9, 0xD1, 0x03, 0xB3, 0xDC, 0x2F, 0xF2, 0x92, 0x3F, 0x0A, 0x19,
96 0x25, 0xE2, 0xEF, 0x7A, 0x22, 0xDA, 0xDB, 0xCB, 0x32, 0x12, 0x61, 0x49, 0x5B, 0x74, 0x7C, 0x65,
97 0x20, 0x89, 0x54, 0x9E, 0x0E, 0xC9, 0x52, 0xE3, 0xC9, 0x9A, 0x44, 0xC9, 0x5D, 0xA6, 0x77, 0xC0,
98 0xE7, 0x60, 0x91, 0x80, 0x50, 0x1F, 0x33, 0xB1, 0xCD, 0xAD, 0xF4, 0x0D, 0xBB, 0x08, 0xB1, 0xD0,
99 0x13, 0x95, 0xAE, 0xC9, 0xE2, 0x64, 0xA2, 0x65, 0xFB, 0x8F, 0xE9, 0xA2, 0x8A, 0xBC, 0x98, 0x81,
100 0x45, 0xB4, 0x55, 0x4E, 0xB9, 0x74, 0xB4, 0x50, 0x76, 0xBF, 0xF0, 0x45, 0xE7, 0xEE, 0x41, 0x64,
101 0x9F, 0xB5, 0xE0, 0xBB, 0x1C, 0xBB, 0x28, 0x66, 0x1B, 0xDD, 0x2B, 0x02, 0x66, 0xBF, 0xFD, 0x7D,
102 0x37, 0x35, 0x1D, 0x76, 0x21, 0xC3, 0x8F, 0xAF, 0xF6, 0xF9, 0xE9, 0x27, 0x48, 0xE7, 0x3D, 0x95,
103 0x74, 0x0C, 0x77, 0x88, 0x56, 0xD9, 0x84, 0xC8, 0x7D, 0x20, 0x31, 0x43, 0x53, 0xF1, 0xC1, 0xC7,
104 0xC9, 0xF7, 0x5C, 0xC0, 0xA6, 0x5A, 0x27, 0x0A, 0x41, 0xD4, 0x44, 0x94, 0x65, 0x4F, 0xE2, 0x53,
105 0x60, 0x0B, 0xD1, 0x23, 0x6C, 0x0C, 0xBC, 0x70, 0x6C, 0x26, 0x1A, 0x61, 0x1D, 0x35, 0x88, 0xEC,
106 0xB8, 0x15, 0xE3, 0xB4, 0x82, 0xEE, 0xB3, 0x21, 0xAC, 0x6C, 0xB7, 0x33, 0x6D, 0x78, 0x0C, 0x0D,
107 0xB4, 0x0B, 0x29, 0xF2, 0xD4, 0x8C, 0x3F, 0xDD, 0x3F, 0x47, 0xDD, 0xF2, 0xD8, 0x39, 0x57, 0x20,
108 0x28, 0xD8, 0xDD, 0x32, 0xE2, 0x6A, 0x47, 0x53, 0x57, 0xC6, 0xFA, 0x7A, 0x38, 0x30, 0x31, 0x8F,
109 0xE7, 0xD3, 0x84, 0x2B, 0x5D, 0x4F, 0x95, 0x98, 0xED, 0x0B, 0xD7, 0x50, 0x0C, 0x49, 0xDA, 0x59,
110 0x15, 0xF1, 0x39, 0xF3, 0x40, 0xDC, 0xDC, 0x25, 0x24, 0x56, 0x6E, 0xA9, 0x2F, 0xF0, 0x00, 0x00 };
113 char gdrom_status[] = {
114 0x00, 0x15, 0x00, 0x64, 0x00, 0x40, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
120 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40,
123 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
124 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40,
125 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00,
126 0x00, 0x40, 0x00, 0x00 };
129 static void ide_init( void )
132 data_buffer_len = DEFAULT_DATA_SECTORS;
133 data_buffer = malloc( MAX_SECTOR_SIZE * data_buffer_len );
134 assert( data_buffer != NULL );
137 static void ide_reset( void )
139 ide_clear_interrupt();
142 idereg.lba0 = /* 0x21; */ 0x81;
145 idereg.feature = 0; /* Indeterminate really */
146 idereg.status = 0x00;
147 idereg.device = 0x00;
148 idereg.disc = gdrom_is_mounted() ? (IDE_DISC_CDROM|IDE_DISC_READY) : IDE_DISC_NONE;
149 idereg.state = IDE_STATE_IDLE;
150 memset( idereg.gdrom_sense, '\0', 10 );
151 idereg.data_offset = -1;
152 idereg.data_length = -1;
153 idereg.last_read_track = 1;
154 idereg.last_read_lba = 150;
155 idereg.was_reset = TRUE;
158 static void ide_save_state( FILE *f )
160 fwrite( &idereg, sizeof(idereg), 1, f );
161 fwrite( &data_buffer_len, sizeof(data_buffer_len), 1, f );
162 fwrite( data_buffer, MAX_SECTOR_SIZE, data_buffer_len, f );
165 static int ide_load_state( FILE *f )
168 fread( &idereg, sizeof(idereg), 1, f );
169 fread( &length, sizeof(uint32_t), 1, f );
170 if( length > data_buffer_len ) {
171 if( data_buffer != NULL )
173 data_buffer = malloc( MAX_SECTOR_SIZE * length );
174 assert( data_buffer != NULL );
175 data_buffer_len = length;
177 fread( data_buffer, MAX_SECTOR_SIZE, length, f );
181 /************************ State transitions *************************/
183 void ide_set_packet_result( uint16_t result )
185 idereg.gdrom_sense[0] = 0xf0;
186 idereg.gdrom_sense[2] = result & 0xFF;
187 idereg.gdrom_sense[8] = (result >> 8) & 0xFF;
188 idereg.error = (result & 0x0F) << 4;
191 idereg.status = 0x51;
192 ide_raise_interrupt();
194 idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
199 * Begin command packet write to the device. This is always 12 bytes of PIO data
201 static void ide_start_command_packet_write( )
203 idereg.state = IDE_STATE_CMD_WRITE;
204 idereg.status = 0x58;
205 idereg.error = idereg.feature & 0x03; /* Copy values of OVL/DMA */
206 idereg.count = IDE_COUNT_CD;
207 idereg.data_offset = 0;
208 idereg.data_length = 12;
212 * Begin PIO read from the device. The data is assumed to already be
213 * in the buffer at this point.
215 static void ide_start_read( int length, int blocksize, gboolean dma )
217 idereg.count = IDE_COUNT_IO;
218 idereg.data_length = length;
219 idereg.data_offset = 0;
221 idereg.state = IDE_STATE_DMA_READ;
222 idereg.status = 0xD0;
224 idereg.state = IDE_STATE_PIO_READ;
225 idereg.status = 0x58;
226 idereg.lba1 = length & 0xFF;
227 idereg.lba2 = (length >> 8) & 0xFF;
228 // idereg.lba1 = blocksize & 0xFF;
229 // idereg.lba2 = blocksize >> 8;
230 idereg.block_length = blocksize;
231 idereg.block_left = blocksize;
232 ide_raise_interrupt( );
236 static void ide_start_packet_read( int length, int blocksize )
238 ide_set_packet_result( PKT_ERR_OK );
239 ide_start_read( length, blocksize, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
242 static void ide_raise_interrupt( void )
244 if( idereg.intrq_pending == 0 ) {
245 idereg.intrq_pending = 1;
246 if( IS_IDE_IRQ_ENABLED() )
247 asic_event( EVENT_IDE );
251 static void ide_clear_interrupt( void )
253 if( idereg.intrq_pending != 0 ) {
254 idereg.intrq_pending = 0;
255 if( IS_IDE_IRQ_ENABLED() )
256 asic_clear_event( EVENT_IDE );
260 static void ide_set_error( int error_code )
262 idereg.status = 0x51;
263 idereg.error = error_code;
266 uint8_t ide_read_status( void )
268 if( (idereg.status & IDE_STATUS_BSY) == 0 )
269 ide_clear_interrupt();
270 return idereg.status;
273 uint16_t ide_read_data_pio( void ) {
274 if( idereg.state == IDE_STATE_PIO_READ ) {
275 uint16_t rv = READ_BUFFER();
276 idereg.data_offset += 2;
277 idereg.block_left -= 2;
278 if( idereg.data_offset >= idereg.data_length ) {
279 idereg.state = IDE_STATE_IDLE;
280 idereg.status &= ~IDE_STATUS_DRQ;
281 idereg.data_offset = -1;
282 idereg.count = 3; /* complete */
283 ide_raise_interrupt();
284 } else if( idereg.block_left <= 0 ) {
285 idereg.block_left = idereg.block_length;
286 ide_raise_interrupt();
298 * This method is called from the ASIC side when a DMA read request is
299 * initiated. If there is a pending DMA transfer already, we copy the
300 * data immediately, otherwise we record the DMA buffer for use when we
301 * get to actually doing the transfer.
302 * @return number of bytes transfered
304 uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )
306 if( idereg.state == IDE_STATE_DMA_READ ) {
307 int xferlen = length;
308 int remaining = idereg.data_length - idereg.data_offset;
309 if( xferlen > remaining )
311 mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );
312 idereg.data_offset += xferlen;
313 if( idereg.data_offset >= idereg.data_length ) {
314 idereg.data_offset = -1;
315 idereg.state = IDE_STATE_IDLE;
316 idereg.status = 0x50;
318 ide_raise_interrupt();
319 asic_event( EVENT_IDE_DMA );
326 void ide_write_data_pio( uint16_t val ) {
327 if( idereg.state == IDE_STATE_CMD_WRITE ) {
329 idereg.data_offset+=2;
330 if( idereg.data_offset >= idereg.data_length ) {
331 idereg.state = IDE_STATE_BUSY;
332 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
333 idereg.data_offset = -1;
334 ide_packet_command(data_buffer);
336 } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
338 if( idereg.data_offset >= idereg.data_length ) {
339 idereg.state = IDE_STATE_BUSY;
340 idereg.data_offset = -1;
341 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
342 /* ??? - no data writes yet anyway */
347 void ide_write_control( uint8_t val ) {
348 if( IS_IDE_IRQ_ENABLED() ) {
349 if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
350 asic_clear_event( EVENT_IDE );
352 if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
353 asic_event( EVENT_IDE );
355 idereg.control = val;
358 void ide_write_command( uint8_t val ) {
359 ide_clear_interrupt();
360 idereg.command = val;
362 case IDE_CMD_NOP: /* Effectively an "abort" */
363 idereg.state = IDE_STATE_IDLE;
364 idereg.status = 0x51;
366 idereg.data_offset = -1;
367 ide_raise_interrupt();
369 case IDE_CMD_RESET_DEVICE:
373 ide_start_command_packet_write();
375 case IDE_CMD_SET_FEATURE:
376 switch( idereg.feature ) {
377 case IDE_FEAT_SET_TRANSFER_MODE:
378 switch( idereg.count & 0xF8 ) {
380 INFO( "Set PIO default mode: %d", idereg.count&0x07 );
382 case IDE_XFER_PIO_FLOW:
383 INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
385 case IDE_XFER_MULTI_DMA:
386 INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
388 case IDE_XFER_ULTRA_DMA:
389 INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
392 INFO( "Setting unknown transfer mode: %02X", idereg.count );
397 WARN( "IDE: unimplemented feature: %02X", idereg.feature );
399 idereg.status = 0x50;
405 WARN( "IDE: Unimplemented command: %02X", val );
410 * Execute a packet command. This particular method is responsible for parsing
411 * the command buffers (12 bytes), and generating the appropriate responses,
412 * although the actual implementation is mostly delegated to gdrom.c
414 void ide_packet_command( unsigned char *cmd )
416 uint32_t length, datalen;
417 uint32_t lba, status;
419 int blocksize = idereg.lba1 + (idereg.lba2<<8);
421 /* Okay we have the packet in the command buffer */
422 INFO( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
423 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7],
424 cmd[8], cmd[9], cmd[10], cmd[11] );
426 if( cmd[0] != PKT_CMD_SENSE && idereg.was_reset ) {
427 ide_set_packet_result( PKT_ERR_RESET );
428 idereg.was_reset = FALSE;
433 case PKT_CMD_TEST_READY:
434 if( !gdrom_is_mounted() ) {
435 ide_set_packet_result( PKT_ERR_NODISC );
437 ide_set_packet_result( 0 );
438 ide_raise_interrupt();
439 idereg.status = 0x50;
442 case PKT_CMD_IDENTIFY:
444 if( lba >= sizeof(gdrom_ident) ) {
445 ide_set_error(PKT_ERR_BADFIELD);
448 if( lba+length > sizeof(gdrom_ident) )
449 length = sizeof(gdrom_ident) - lba;
450 memcpy( data_buffer, gdrom_ident + lba, length );
451 ide_start_packet_read( length, blocksize );
458 memcpy( data_buffer, idereg.gdrom_sense, length );
459 ide_start_packet_read( length, blocksize );
461 case PKT_CMD_READ_TOC:
462 length = (cmd[3]<<8) | cmd[4];
463 if( length > sizeof(struct gdrom_toc) )
464 length = sizeof(struct gdrom_toc);
466 status = gdrom_get_toc( data_buffer );
467 if( status != PKT_ERR_OK ) {
468 ide_set_packet_result( status );
470 ide_start_packet_read( length, blocksize );
473 case PKT_CMD_SESSION_INFO:
477 status = gdrom_get_info( data_buffer, cmd[2] );
478 if( status != PKT_ERR_OK ) {
479 ide_set_packet_result( status );
481 ide_start_packet_read( length, blocksize );
484 case PKT_CMD_PLAY_CD:
485 ide_set_packet_result( 0 );
486 ide_raise_interrupt();
487 idereg.status = 0x50;
489 case PKT_CMD_READ_SECTOR:
490 lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
491 length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
493 case 0x20: mode = GDROM_MODE1; break; /* TODO - might be unchecked? */
494 case 0x24: mode = GDROM_GD; break;
495 case 0x28: mode = GDROM_MODE2_XA1; break; /* ??? */
496 case 0x30: mode = GDROM_RAW; break;
498 ERROR( "Unrecognized read mode '%02X' in GD-Rom read request", cmd[1] );
499 ide_set_packet_result( PKT_ERR_BADFIELD );
503 if( length > data_buffer_len ) {
505 data_buffer_len = data_buffer_len << 1;
506 } while( data_buffer_len < length );
507 data_buffer = realloc( data_buffer, MAX_SECTOR_SIZE * data_buffer_len );
510 datalen = data_buffer_len;
511 status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );
513 ide_set_packet_result( status );
514 idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;
515 idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;
516 idereg.gdrom_sense[7] = lba & 0xFF;
518 idereg.last_read_lba = lba + length;
519 idereg.last_read_track = gdrom_get_track_no_by_lba( idereg.last_read_lba );
520 ide_start_packet_read( datalen, blocksize );
523 case PKT_CMD_SPIN_UP:
525 ide_set_packet_result( PKT_ERR_OK );
526 ide_raise_interrupt();
530 if( !gdrom_is_mounted() ) {
531 ide_set_packet_result( PKT_ERR_NODISC );
535 if( length > sizeof(gdrom_status) ) {
536 length = sizeof(gdrom_status);
538 memcpy( data_buffer, gdrom_status, length );
539 ide_start_packet_read( length, blocksize );
545 gdrom_track_t track = gdrom_get_track(idereg.last_read_track);
546 int offset = idereg.last_read_lba - track->lba;
547 data_buffer[0] = 0x00;
548 data_buffer[1] = 0x15; /* ??? */
549 data_buffer[2] = 0x00;
550 data_buffer[3] = 0x0E;
551 data_buffer[4] = track->flags;
552 data_buffer[5] = idereg.last_read_track;
553 data_buffer[6] = 0x01; /* ?? */
554 data_buffer[7] = (offset >> 16) & 0xFF;
555 data_buffer[8] = (offset >> 8) & 0xFF;
556 data_buffer[9] = offset & 0xFF;
557 data_buffer[10] = (idereg.last_read_lba >> 24) & 0xFF;
558 data_buffer[11] = (idereg.last_read_lba >> 16) & 0xFF;
559 data_buffer[12] = (idereg.last_read_lba >> 8) & 0xFF;
560 data_buffer[13] = idereg.last_read_lba & 0xFF;
561 ide_start_packet_read( length, blocksize );
567 /* This is a weird one. As far as I can tell it returns random garbage
568 * (and not even the same length each time, never mind the same data).
569 * For sake of something to do, it returns the results from a test dump
571 memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );
572 ide_start_packet_read( sizeof(gdrom_71), blocksize );
575 ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
.