2 * $Id: ide.c,v 1.19 2006-12-19 11:58:12 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 = 0x50;
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.last_read_count = 0;
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;
190 idereg.status = 0x51;
191 ide_raise_interrupt();
193 idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
198 * Begin command packet write to the device. This is always 12 bytes of PIO data
200 static void ide_start_command_packet_write( )
202 idereg.state = IDE_STATE_CMD_WRITE;
203 idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
204 idereg.error = idereg.feature & 0x03; /* Copy values of OVL/DMA */
205 idereg.count = IDE_COUNT_CD;
206 idereg.data_offset = 0;
207 idereg.data_length = 12;
211 * Begin PIO read from the device. The data is assumed to already be
212 * in the buffer at this point.
214 static void ide_start_read( int length, int blocksize, gboolean dma )
216 idereg.count = IDE_COUNT_IO;
217 idereg.data_length = length;
218 idereg.data_offset = 0;
220 idereg.state = IDE_STATE_DMA_READ;
221 idereg.status = 0xD0;
223 idereg.state = IDE_STATE_PIO_READ;
224 idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
225 idereg.lba1 = length & 0xFF;
226 idereg.lba2 = (length >> 8) & 0xFF;
227 // idereg.lba1 = blocksize & 0xFF;
228 // idereg.lba2 = blocksize >> 8;
229 idereg.block_length = blocksize;
230 idereg.block_left = blocksize;
231 ide_raise_interrupt( );
235 static void ide_start_packet_read( int length, int blocksize )
237 ide_set_packet_result( PKT_ERR_OK );
238 ide_start_read( length, blocksize, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
241 static void ide_raise_interrupt( void )
243 if( idereg.intrq_pending == 0 ) {
244 idereg.intrq_pending = 1;
245 if( IS_IDE_IRQ_ENABLED() )
246 asic_event( EVENT_IDE );
250 static void ide_clear_interrupt( void )
252 if( idereg.intrq_pending != 0 ) {
253 idereg.intrq_pending = 0;
254 if( IS_IDE_IRQ_ENABLED() )
255 asic_clear_event( EVENT_IDE );
259 static void ide_set_error( int error_code )
261 idereg.status = 0x51;
262 idereg.error = error_code;
265 uint8_t ide_read_status( void )
267 if( (idereg.status & IDE_STATUS_BSY) == 0 )
268 ide_clear_interrupt();
269 return idereg.status;
272 uint16_t ide_read_data_pio( void ) {
273 if( idereg.state == IDE_STATE_PIO_READ ) {
274 uint16_t rv = READ_BUFFER();
275 idereg.data_offset += 2;
276 idereg.block_left -= 2;
277 if( idereg.data_offset >= idereg.data_length ) {
278 idereg.state = IDE_STATE_IDLE;
279 idereg.status &= ~IDE_STATUS_DRQ;
280 idereg.data_offset = -1;
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;
315 ide_raise_interrupt();
316 asic_event( EVENT_IDE_DMA );
323 void ide_write_data_pio( uint16_t val ) {
324 if( idereg.state == IDE_STATE_CMD_WRITE ) {
326 idereg.data_offset+=2;
327 if( idereg.data_offset >= idereg.data_length ) {
328 idereg.state = IDE_STATE_BUSY;
329 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
330 idereg.data_offset = -1;
331 ide_packet_command(data_buffer);
333 } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
335 if( idereg.data_offset >= idereg.data_length ) {
336 idereg.state = IDE_STATE_BUSY;
337 idereg.data_offset = -1;
338 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
339 /* ??? - no data writes yet anyway */
344 void ide_write_control( uint8_t val ) {
345 if( IS_IDE_IRQ_ENABLED() ) {
346 if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
347 asic_clear_event( EVENT_IDE );
349 if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
350 asic_event( EVENT_IDE );
352 idereg.control = val;
355 void ide_write_command( uint8_t val ) {
356 ide_clear_interrupt();
357 idereg.command = val;
359 case IDE_CMD_NOP: /* Effectively an "abort" */
360 idereg.state = IDE_STATE_IDLE;
361 idereg.status = 0x51;
363 idereg.data_offset = -1;
364 ide_raise_interrupt();
366 case IDE_CMD_RESET_DEVICE:
370 ide_start_command_packet_write();
372 case IDE_CMD_SET_FEATURE:
373 switch( idereg.feature ) {
374 case IDE_FEAT_SET_TRANSFER_MODE:
375 switch( idereg.count & 0xF8 ) {
377 INFO( "Set PIO default mode: %d", idereg.count&0x07 );
379 case IDE_XFER_PIO_FLOW:
380 INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
382 case IDE_XFER_MULTI_DMA:
383 INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
385 case IDE_XFER_ULTRA_DMA:
386 INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
389 INFO( "Setting unknown transfer mode: %02X", idereg.count );
394 WARN( "IDE: unimplemented feature: %02X", idereg.feature );
396 ide_raise_interrupt( );
399 WARN( "IDE: Unimplemented command: %02X", val );
401 idereg.status = (idereg.status | IDE_STATUS_DRDY | IDE_STATUS_SERV) & (~IDE_STATUS_CHK);
405 * Execute a packet command. This particular method is responsible for parsing
406 * the command buffers (12 bytes), and generating the appropriate responses,
407 * although the actual implementation is mostly delegated to gdrom.c
409 void ide_packet_command( unsigned char *cmd )
411 uint32_t length, datalen;
412 uint32_t lba, status;
414 int blocksize = idereg.lba1 + (idereg.lba2<<8);
416 /* Okay we have the packet in the command buffer */
417 INFO( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
418 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7],
419 cmd[8], cmd[9], cmd[10], cmd[11] );
421 case PKT_CMD_TEST_READY:
422 if( !gdrom_is_mounted() ) {
423 ide_set_packet_result( PKT_ERR_NODISC );
425 ide_set_packet_result( 0 );
426 ide_raise_interrupt();
427 idereg.status = 0x50;
430 case PKT_CMD_IDENTIFY:
432 if( lba >= sizeof(gdrom_ident) ) {
433 ide_set_error(PKT_ERR_BADFIELD);
436 if( lba+length > sizeof(gdrom_ident) )
437 length = sizeof(gdrom_ident) - lba;
438 memcpy( data_buffer, gdrom_ident + lba, length );
439 ide_start_packet_read( length, blocksize );
446 memcpy( data_buffer, idereg.gdrom_sense, length );
447 ide_start_packet_read( length, blocksize );
449 case PKT_CMD_READ_TOC:
450 length = (cmd[3]<<8) | cmd[4];
451 if( length > sizeof(struct gdrom_toc) )
452 length = sizeof(struct gdrom_toc);
454 status = gdrom_get_toc( data_buffer );
455 if( status != PKT_ERR_OK ) {
456 ide_set_packet_result( status );
458 ide_start_packet_read( length, blocksize );
461 case PKT_CMD_SESSION_INFO:
465 status = gdrom_get_info( data_buffer, cmd[2] );
466 if( status != PKT_ERR_OK ) {
467 ide_set_packet_result( status );
469 ide_start_packet_read( length, blocksize );
472 case PKT_CMD_PLAY_CD:
473 ide_set_packet_result( 0 );
474 ide_raise_interrupt();
475 idereg.status = 0x50;
477 case PKT_CMD_READ_SECTOR:
478 lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
479 length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
481 case 0x20: mode = GDROM_MODE1; break; /* TODO - might be unchecked? */
482 case 0x24: mode = GDROM_GD; break;
483 case 0x28: mode = GDROM_MODE2_XA1; break; /* ??? */
484 case 0x30: mode = GDROM_RAW; break;
486 ERROR( "Unrecognized read mode '%02X' in GD-Rom read request", cmd[1] );
487 ide_set_packet_result( PKT_ERR_BADFIELD );
491 if( length > data_buffer_len ) {
493 data_buffer_len = data_buffer_len << 1;
494 } while( data_buffer_len < length );
495 data_buffer = realloc( data_buffer, MAX_SECTOR_SIZE * data_buffer_len );
498 datalen = data_buffer_len;
499 status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );
501 ide_set_packet_result( status );
502 idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;
503 idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;
504 idereg.gdrom_sense[7] = lba & 0xFF;
506 idereg.last_read_count += length;
507 idereg.last_read_lba = lba + length;
508 idereg.last_read_track = gdrom_get_track_no_by_lba( idereg.last_read_lba );
509 ide_start_packet_read( datalen, blocksize );
512 case PKT_CMD_SPIN_UP:
514 ide_set_packet_result( PKT_ERR_OK );
515 ide_raise_interrupt();
519 if( !gdrom_is_mounted() ) {
520 ide_set_packet_result( PKT_ERR_NODISC );
524 if( length > sizeof(gdrom_status) ) {
525 length = sizeof(gdrom_status);
527 memcpy( data_buffer, gdrom_status, length );
528 ide_start_packet_read( length, blocksize );
534 data_buffer[0] = 0x00;
535 data_buffer[1] = 0x15; /* ??? */
536 data_buffer[2] = 0x00;
537 data_buffer[3] = 0x0E;
538 data_buffer[4] = gdrom_get_track(idereg.last_read_track)->flags;
539 data_buffer[5] = idereg.last_read_track;
540 data_buffer[6] = 0x01; /* ?? */
541 data_buffer[7] = (idereg.last_read_count >> 16) & 0xFF;
542 data_buffer[8] = (idereg.last_read_count >> 8) & 0xFF;
543 data_buffer[9] = idereg.last_read_count & 0xFF;
544 data_buffer[10] = (idereg.last_read_lba >> 24) & 0xFF;
545 data_buffer[11] = (idereg.last_read_lba >> 16) & 0xFF;
546 data_buffer[12] = (idereg.last_read_lba >> 8) & 0xFF;
547 data_buffer[13] = idereg.last_read_lba & 0xFF;
548 data_buffer[14] = 0x00;
549 data_buffer[15] = 0x00;
550 ide_start_packet_read( length, blocksize );
556 /* This is a weird one. As far as I can tell it returns random garbage
557 * (and not even the same length each time, never mind the same data).
558 * For sake of something to do, it returns the results from a test dump
560 memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );
561 ide_start_packet_read( sizeof(gdrom_71), blocksize );
564 ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
.