filename | src/gdrom/ide.c |
changeset | 166:8aa70cf503a2 |
prev | 158:a0a82246b44e |
next | 240:9ae4bd697292 |
author | nkeynes |
date | Fri Aug 04 01:38:30 2006 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Add more tile list limit tests Implement tile list limits in the ta core. Rename TA_TILEEND to TA_LISTEND |
view | annotate | diff | log | raw |
1 /**
2 * $Id: ide.c,v 1.16 2006-06-18 12:01:53 nkeynes Exp $
3 *
4 * IDE interface implementation
5 *
6 *
7 * Note: All references to read/write are from the host's point of view.
8 *
9 * See: INF-8020
10 * Copyright (c) 2005 Nathan Keynes.
11 *
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.
16 *
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.
21 */
23 #define MODULE ide_module
25 #include <assert.h>
26 #include <stdlib.h>
27 #include "dream.h"
28 #include "asic.h"
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 static void ide_init( void )
114 {
115 ide_reset();
116 data_buffer_len = DEFAULT_DATA_SECTORS;
117 data_buffer = malloc( MAX_SECTOR_SIZE * data_buffer_len );
118 assert( data_buffer != NULL );
119 }
121 static void ide_reset( void )
122 {
123 ide_clear_interrupt();
124 idereg.error = 0x01;
125 idereg.count = 0x01;
126 idereg.lba0 = /* 0x21; */ 0x81;
127 idereg.lba1 = 0x14;
128 idereg.lba2 = 0xeb;
129 idereg.feature = 0; /* Indeterminate really */
130 idereg.status = 0x50;
131 idereg.device = 0x00;
132 idereg.disc = gdrom_is_mounted() ? (IDE_DISC_CDROM|IDE_DISC_READY) : IDE_DISC_NONE;
133 idereg.state = IDE_STATE_IDLE;
134 memset( idereg.gdrom_sense, '\0', 10 );
135 idereg.data_offset = -1;
136 idereg.data_length = -1;
137 }
139 static void ide_save_state( FILE *f )
140 {
141 fwrite( &idereg, sizeof(idereg), 1, f );
142 fwrite( &data_buffer_len, sizeof(data_buffer_len), 1, f );
143 fwrite( data_buffer, MAX_SECTOR_SIZE, data_buffer_len, f );
144 }
146 static int ide_load_state( FILE *f )
147 {
148 uint32_t length;
149 fread( &idereg, sizeof(idereg), 1, f );
150 fread( &length, sizeof(uint32_t), 1, f );
151 if( length > data_buffer_len ) {
152 if( data_buffer != NULL )
153 free( data_buffer );
154 data_buffer = malloc( MAX_SECTOR_SIZE * length );
155 assert( data_buffer != NULL );
156 data_buffer_len = length;
157 }
158 fread( data_buffer, MAX_SECTOR_SIZE, length, f );
159 return 0;
160 }
162 /************************ State transitions *************************/
164 void ide_set_packet_result( uint16_t result )
165 {
166 idereg.gdrom_sense[0] = 0xf0;
167 idereg.gdrom_sense[2] = result & 0xFF;
168 idereg.gdrom_sense[8] = (result >> 8) & 0xFF;
169 idereg.error = (result & 0x0F) << 4;
170 if( result != 0 ) {
171 idereg.status = 0x51;
172 ide_raise_interrupt();
173 } else {
174 idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
175 }
176 }
178 /**
179 * Begin command packet write to the device. This is always 12 bytes of PIO data
180 */
181 static void ide_start_command_packet_write( )
182 {
183 idereg.state = IDE_STATE_CMD_WRITE;
184 idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
185 idereg.error = idereg.feature & 0x03; /* Copy values of OVL/DMA */
186 idereg.count = IDE_COUNT_CD;
187 idereg.data_offset = 0;
188 idereg.data_length = 12;
189 }
191 /**
192 * Begin PIO read from the device. The data is assumed to already be
193 * in the buffer at this point.
194 */
195 static void ide_start_read( int length, int blocksize, gboolean dma )
196 {
197 idereg.count = IDE_COUNT_IO;
198 idereg.data_length = length;
199 idereg.data_offset = 0;
200 if( dma ) {
201 idereg.state = IDE_STATE_DMA_READ;
202 idereg.status = 0xD0;
203 } else {
204 idereg.state = IDE_STATE_PIO_READ;
205 idereg.status = IDE_STATUS_DRDY | IDE_STATUS_DRQ;
206 idereg.lba1 = length & 0xFF;
207 idereg.lba2 = (length >> 8) & 0xFF;
208 // idereg.lba1 = blocksize & 0xFF;
209 // idereg.lba2 = blocksize >> 8;
210 idereg.block_length = blocksize;
211 idereg.block_left = blocksize;
212 ide_raise_interrupt( );
213 }
214 }
216 static void ide_start_packet_read( int length, int blocksize )
217 {
218 ide_set_packet_result( PKT_ERR_OK );
219 ide_start_read( length, blocksize, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
220 }
222 static void ide_raise_interrupt( void )
223 {
224 if( idereg.intrq_pending == 0 ) {
225 idereg.intrq_pending = 1;
226 if( IS_IDE_IRQ_ENABLED() )
227 asic_event( EVENT_IDE );
228 }
229 }
231 static void ide_clear_interrupt( void )
232 {
233 if( idereg.intrq_pending != 0 ) {
234 idereg.intrq_pending = 0;
235 if( IS_IDE_IRQ_ENABLED() )
236 asic_clear_event( EVENT_IDE );
237 }
238 }
240 static void ide_set_error( int error_code )
241 {
242 idereg.status = 0x51;
243 idereg.error = error_code;
244 }
246 uint8_t ide_read_status( void )
247 {
248 if( (idereg.status & IDE_STATUS_BSY) == 0 )
249 ide_clear_interrupt();
250 return idereg.status;
251 }
253 uint16_t ide_read_data_pio( void ) {
254 if( idereg.state == IDE_STATE_PIO_READ ) {
255 uint16_t rv = READ_BUFFER();
256 idereg.data_offset += 2;
257 idereg.block_left -= 2;
258 if( idereg.data_offset >= idereg.data_length ) {
259 idereg.state = IDE_STATE_IDLE;
260 idereg.status &= ~IDE_STATUS_DRQ;
261 idereg.data_offset = -1;
262 ide_raise_interrupt();
263 } else if( idereg.block_left <= 0 ) {
264 idereg.block_left = idereg.block_length;
265 ide_raise_interrupt();
266 }
267 return rv;
268 } else {
269 return 0xFFFF;
270 }
271 }
274 /**
275 * DMA read request
276 *
277 * This method is called from the ASIC side when a DMA read request is
278 * initiated. If there is a pending DMA transfer already, we copy the
279 * data immediately, otherwise we record the DMA buffer for use when we
280 * get to actually doing the transfer.
281 * @return number of bytes transfered
282 */
283 uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )
284 {
285 if( idereg.state == IDE_STATE_DMA_READ ) {
286 int xferlen = length;
287 int remaining = idereg.data_length - idereg.data_offset;
288 if( xferlen > remaining )
289 xferlen = remaining;
290 mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );
291 idereg.data_offset += xferlen;
292 if( idereg.data_offset >= idereg.data_length ) {
293 idereg.data_offset = -1;
294 idereg.state = IDE_STATE_IDLE;
295 idereg.status = 0x50;
296 ide_raise_interrupt();
297 asic_event( EVENT_IDE_DMA );
298 }
299 return xferlen;
300 }
301 return 0;
302 }
304 void ide_write_data_pio( uint16_t val ) {
305 if( idereg.state == IDE_STATE_CMD_WRITE ) {
306 WRITE_BUFFER(val);
307 idereg.data_offset+=2;
308 if( idereg.data_offset >= idereg.data_length ) {
309 idereg.state = IDE_STATE_BUSY;
310 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
311 idereg.data_offset = -1;
312 ide_packet_command(data_buffer);
313 }
314 } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
315 WRITE_BUFFER(val);
316 if( idereg.data_offset >= idereg.data_length ) {
317 idereg.state = IDE_STATE_BUSY;
318 idereg.data_offset = -1;
319 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
320 /* ??? - no data writes yet anyway */
321 }
322 }
323 }
325 void ide_write_control( uint8_t val ) {
326 if( IS_IDE_IRQ_ENABLED() ) {
327 if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
328 asic_clear_event( EVENT_IDE );
329 } else {
330 if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
331 asic_event( EVENT_IDE );
332 }
333 idereg.control = val;
334 }
336 void ide_write_command( uint8_t val ) {
337 ide_clear_interrupt();
338 idereg.command = val;
339 switch( val ) {
340 case IDE_CMD_RESET_DEVICE:
341 ide_reset();
342 break;
343 case IDE_CMD_PACKET:
344 ide_start_command_packet_write();
345 break;
346 case IDE_CMD_SET_FEATURE:
347 switch( idereg.feature ) {
348 case IDE_FEAT_SET_TRANSFER_MODE:
349 switch( idereg.count & 0xF8 ) {
350 case IDE_XFER_PIO:
351 INFO( "Set PIO default mode: %d", idereg.count&0x07 );
352 break;
353 case IDE_XFER_PIO_FLOW:
354 INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
355 break;
356 case IDE_XFER_MULTI_DMA:
357 INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
358 break;
359 case IDE_XFER_ULTRA_DMA:
360 INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
361 break;
362 default:
363 INFO( "Setting unknown transfer mode: %02X", idereg.count );
364 break;
365 }
366 break;
367 default:
368 WARN( "IDE: unimplemented feature: %02X", idereg.feature );
369 }
370 ide_raise_interrupt( );
371 break;
372 default:
373 WARN( "IDE: Unimplemented command: %02X", val );
374 }
375 idereg.status = (idereg.status | IDE_STATUS_DRDY | IDE_STATUS_SERV) & (~IDE_STATUS_CHK);
376 }
378 /**
379 * Execute a packet command. This particular method is responsible for parsing
380 * the command buffers (12 bytes), and generating the appropriate responses,
381 * although the actual implementation is mostly delegated to gdrom.c
382 */
383 void ide_packet_command( unsigned char *cmd )
384 {
385 uint32_t length, datalen;
386 uint32_t lba, status;
387 int mode;
388 int blocksize = idereg.lba1 + (idereg.lba2<<8);
390 /* Okay we have the packet in the command buffer */
391 INFO( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
392 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7],
393 cmd[8], cmd[9], cmd[10], cmd[11] );
394 switch( cmd[0] ) {
395 case PKT_CMD_TEST_READY:
396 if( !gdrom_is_mounted() ) {
397 ide_set_packet_result( PKT_ERR_NODISC );
398 } else {
399 ide_set_packet_result( 0 );
400 ide_raise_interrupt();
401 idereg.status = 0x50;
402 }
403 break;
404 case PKT_CMD_IDENTIFY:
405 lba = cmd[2];
406 if( lba >= sizeof(gdrom_ident) ) {
407 ide_set_error(PKT_ERR_BADFIELD);
408 } else {
409 length = cmd[4];
410 if( lba+length > sizeof(gdrom_ident) )
411 length = sizeof(gdrom_ident) - lba;
412 memcpy( data_buffer, gdrom_ident + lba, length );
413 ide_start_packet_read( length, blocksize );
414 }
415 break;
416 case PKT_CMD_SENSE:
417 length = cmd[4];
418 if( length > 10 )
419 length = 10;
420 memcpy( data_buffer, idereg.gdrom_sense, length );
421 ide_start_packet_read( length, blocksize );
422 break;
423 case PKT_CMD_READ_TOC:
424 length = (cmd[3]<<8) | cmd[4];
425 if( length > sizeof(struct gdrom_toc) )
426 length = sizeof(struct gdrom_toc);
428 status = gdrom_get_toc( data_buffer );
429 if( status != PKT_ERR_OK ) {
430 ide_set_packet_result( status );
431 } else {
432 ide_start_packet_read( length, blocksize );
433 }
434 break;
435 case PKT_CMD_SESSION_INFO:
436 length = cmd[4];
437 if( length > 6 )
438 length = 6;
439 status = gdrom_get_info( data_buffer, cmd[2] );
440 if( status != PKT_ERR_OK ) {
441 ide_set_packet_result( status );
442 } else {
443 ide_start_packet_read( length, blocksize );
444 }
445 break;
446 case PKT_CMD_READ_SECTOR:
447 lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
448 length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
449 switch( cmd[1] ) {
450 case 0x20: mode = GDROM_MODE1; break;
451 case 0x24: mode = GDROM_GD; break;
452 case 0x28: mode = GDROM_MODE1; break; /* ??? */
453 case 0x30: mode = GDROM_RAW; break;
454 default:
455 ERROR( "Unrecognized read mode '%02X' in GD-Rom read request", cmd[1] );
456 ide_set_packet_result( PKT_ERR_BADFIELD );
457 return;
458 }
460 if( length > data_buffer_len ) {
461 do {
462 data_buffer_len = data_buffer_len << 1;
463 } while( data_buffer_len < length );
464 data_buffer = realloc( data_buffer, MAX_SECTOR_SIZE * data_buffer_len );
465 }
467 datalen = data_buffer_len;
468 status = gdrom_read_sectors( lba, length, mode, data_buffer, &datalen );
469 if( status != 0 ) {
470 ide_set_packet_result( status );
471 idereg.gdrom_sense[5] = (lba >> 16) & 0xFF;
472 idereg.gdrom_sense[6] = (lba >> 8) & 0xFF;
473 idereg.gdrom_sense[7] = lba & 0xFF;
474 } else {
475 ide_start_packet_read( datalen, blocksize );
476 }
477 break;
478 case PKT_CMD_SPIN_UP:
479 /* do nothing? */
480 ide_set_packet_result( PKT_ERR_OK );
481 ide_raise_interrupt();
482 break;
483 case PKT_CMD_71:
484 /* This is a weird one. As far as I can tell it returns random garbage
485 * (and not even the same length each time, never mind the same data).
486 * For sake of something to do, it returns the results from a test dump
487 */
488 memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );
489 ide_start_packet_read( sizeof(gdrom_71), blocksize );
490 break;
491 default:
492 ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
493 return;
494 }
495 }
.