2 * $Id: ide.c,v 1.22 2006-12-29 00:23:13 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 = blocksize & 0xFF;
227 idereg.lba2 = blocksize >> 8;
228 idereg.block_length = blocksize;
229 idereg.block_left = blocksize;
230 ide_raise_interrupt( );
234 static void ide_start_packet_read( int length, int blocksize )
236 ide_set_packet_result( PKT_ERR_OK );
237 ide_start_read( length, blocksize, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
240 static void ide_raise_interrupt( void )
242 if( idereg.intrq_pending == 0 ) {
243 idereg.intrq_pending = 1;
244 if( IS_IDE_IRQ_ENABLED() )
245 asic_event( EVENT_IDE );
249 static void ide_clear_interrupt( void )
251 if( idereg.intrq_pending != 0 ) {
252 idereg.intrq_pending = 0;
253 if( IS_IDE_IRQ_ENABLED() )
254 asic_clear_event( EVENT_IDE );
258 static void ide_set_error( int error_code )
260 idereg.status = 0x51;
261 idereg.error = error_code;
264 uint8_t ide_read_status( void )
266 if( (idereg.status & IDE_STATUS_BSY) == 0 )
267 ide_clear_interrupt();
268 return idereg.status;
271 uint16_t ide_read_data_pio( void ) {
272 if( idereg.state == IDE_STATE_PIO_READ ) {
273 uint16_t rv = READ_BUFFER();
274 idereg.data_offset += 2;
275 idereg.block_left -= 2;
276 if( idereg.data_offset >= idereg.data_length ) {
277 idereg.state = IDE_STATE_IDLE;
278 idereg.status &= ~IDE_STATUS_DRQ;
279 idereg.data_offset = -1;
280 idereg.count = 3; /* complete */
281 ide_raise_interrupt();
282 } else if( idereg.block_left <= 0 ) {
283 idereg.block_left = idereg.block_length;
284 ide_raise_interrupt();
296 * This method is called from the ASIC side when a DMA read request is
297 * initiated. If there is a pending DMA transfer already, we copy the
298 * data immediately, otherwise we record the DMA buffer for use when we
299 * get to actually doing the transfer.
300 * @return number of bytes transfered
302 uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )
304 if( idereg.state == IDE_STATE_DMA_READ ) {
305 int xferlen = length;
306 int remaining = idereg.data_length - idereg.data_offset;
307 if( xferlen > remaining )
309 mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );
310 idereg.data_offset += xferlen;
311 if( idereg.data_offset >= idereg.data_length ) {
312 idereg.data_offset = -1;
313 idereg.state = IDE_STATE_IDLE;
314 idereg.status = 0x50;
316 ide_raise_interrupt();
317 asic_event( EVENT_IDE_DMA );
324 void ide_write_data_pio( uint16_t val ) {
325 if( idereg.state == IDE_STATE_CMD_WRITE ) {
327 idereg.data_offset+=2;
328 if( idereg.data_offset >= idereg.data_length ) {
329 idereg.state = IDE_STATE_BUSY;
330 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
331 idereg.data_offset = -1;
332 ide_packet_command(data_buffer);
334 } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
336 if( idereg.data_offset >= idereg.data_length ) {
337 idereg.state = IDE_STATE_BUSY;
338 idereg.data_offset = -1;
339 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
340 /* ??? - no data writes yet anyway */
345 void ide_write_control( uint8_t val ) {
346 if( IS_IDE_IRQ_ENABLED() ) {
347 if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
348 asic_clear_event( EVENT_IDE );
350 if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
351 asic_event( EVENT_IDE );
353 idereg.control = val;
356 void ide_write_command( uint8_t val ) {
357 ide_clear_interrupt();
358 idereg.command = val;
360 case IDE_CMD_NOP: /* Effectively an "abort" */
361 idereg.state = IDE_STATE_IDLE;
362 idereg.status = 0x51;
364 idereg.data_offset = -1;
365 ide_raise_interrupt();
367 case IDE_CMD_RESET_DEVICE:
371 ide_start_command_packet_write();
373 case IDE_CMD_SET_FEATURE:
374 switch( idereg.feature ) {
375 case IDE_FEAT_SET_TRANSFER_MODE:
376 switch( idereg.count & 0xF8 ) {
378 INFO( "Set PIO default mode: %d", idereg.count&0x07 );
380 case IDE_XFER_PIO_FLOW:
381 INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
383 case IDE_XFER_MULTI_DMA:
384 INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
386 case IDE_XFER_ULTRA_DMA:
387 INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
390 INFO( "Setting unknown transfer mode: %02X", idereg.count );
395 WARN( "IDE: unimplemented feature: %02X", idereg.feature );
397 idereg.status = 0x50;
401 ide_raise_interrupt();
404 WARN( "IDE: Unimplemented command: %02X", val );
409 * Execute a packet command. This particular method is responsible for parsing
410 * the command buffers (12 bytes), and generating the appropriate responses,
411 * although the actual implementation is mostly delegated to gdrom.c
413 void ide_packet_command( unsigned char *cmd )
415 uint32_t length, datalen;
416 uint32_t lba, status;
418 int blocksize = idereg.lba1 + (idereg.lba2<<8);
420 /* Okay we have the packet in the command buffer */
421 INFO( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
422 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7],
423 cmd[8], cmd[9], cmd[10], cmd[11] );
425 if( cmd[0] != PKT_CMD_SENSE && idereg.was_reset ) {
426 ide_set_packet_result( PKT_ERR_RESET );
427 idereg.was_reset = FALSE;
432 case PKT_CMD_TEST_READY:
433 if( !gdrom_is_mounted() ) {
434 ide_set_packet_result( PKT_ERR_NODISC );
436 ide_set_packet_result( 0 );
437 ide_raise_interrupt();
438 idereg.status = 0x50;
441 case PKT_CMD_IDENTIFY:
443 if( lba >= sizeof(gdrom_ident) ) {
444 ide_set_error(PKT_ERR_BADFIELD);
447 if( lba+length > sizeof(gdrom_ident) )
448 length = sizeof(gdrom_ident) - lba;
449 memcpy( data_buffer, gdrom_ident + lba, length );
450 ide_start_packet_read( length, length );
457 memcpy( data_buffer, idereg.gdrom_sense, length );
458 ide_start_packet_read( length, length );
460 case PKT_CMD_READ_TOC:
461 length = (cmd[3]<<8) | cmd[4];
462 if( length > sizeof(struct gdrom_toc) )
463 length = sizeof(struct gdrom_toc);
465 status = gdrom_get_toc( data_buffer );
466 if( status != PKT_ERR_OK ) {
467 ide_set_packet_result( status );
469 ide_start_packet_read( length, length );
472 case PKT_CMD_SESSION_INFO:
476 status = gdrom_get_info( data_buffer, cmd[2] );
477 if( status != PKT_ERR_OK ) {
478 ide_set_packet_result( status );
480 ide_start_packet_read( length, length );
483 case PKT_CMD_PLAY_CD:
484 ide_set_packet_result( 0 );
485 ide_raise_interrupt();
486 idereg.status = 0x50;
488 case PKT_CMD_READ_SECTOR:
489 lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
490 length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
492 case 0x20: mode = GDROM_MODE1; break; /* TODO - might be unchecked? */
493 case 0x24: mode = GDROM_GD; break;
494 case 0x28: mode = GDROM_MODE2_XA1; break; /* ??? */
495 case 0x30: mode = GDROM_RAW; break;
497 ERROR( "Unrecognized read mode '%02X' in GD-Rom read request", cmd[1] );
498 ide_set_packet_result( PKT_ERR_BADFIELD );
502 if( length > data_buffer_len ) {
504 data_buffer_len = data_buffer_len << 1;
505 } while( data_buffer_len < length );
506 data_buffer = realloc( data_buffer, MAX_SECTOR_SIZE * data_buffer_len );
509 datalen = data_buffer_len;
510 status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );
512 ide_set_packet_result( status );
513 idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;
514 idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;
515 idereg.gdrom_sense[7] = lba & 0xFF;
516 WARN( " => Read CD returned sense key %02X, %02X", status & 0xFF, status >> 8 );
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, 0x0800 );
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, length );
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, length );
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), sizeof(gdrom_71) );
575 ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
.