filename | src/gdrom/ide.c |
changeset | 342:850502f0e8de |
prev | 258:8864fae65928 |
next | 422:61a0598e07ff |
author | nkeynes |
date | Tue Sep 04 08:32:10 2007 +0000 (16 years ago) |
permissions | -rw-r--r-- |
last change | Change sh4x86 test to translate/disasm full basic blocks Add prelim sym-tab support |
view | annotate | diff | log | raw |
1 /**
2 * $Id: ide.c,v 1.23 2007-01-31 10:58:42 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 uint32_t ide_run_slice( uint32_t nanosecs );
40 static void ide_save_state( FILE *f );
41 static int ide_load_state( FILE *f );
42 static void ide_raise_interrupt( void );
43 static void ide_clear_interrupt( void );
44 static void ide_packet_command( unsigned char *data );
45 static void ide_read_next_sector(void);
47 struct dreamcast_module ide_module = { "IDE", ide_init, ide_reset, NULL, ide_run_slice,
48 NULL, ide_save_state, ide_load_state };
50 struct ide_registers idereg;
51 gdrom_disc_t gdrom_disc = NULL;
53 unsigned char data_buffer[MAX_SECTOR_SIZE];
55 #define WRITE_BUFFER(x16) *((uint16_t *)(data_buffer + idereg.data_offset)) = x16
56 #define READ_BUFFER() *((uint16_t *)(data_buffer + idereg.data_offset))
58 /* "\0\0\0\0\xb4\x19\0\0\x08SE REV 6.42990316" */
59 unsigned char gdrom_ident[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00,
60 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
61 0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2e,
62 0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
64 unsigned char gdrom_71[] = { 0x3E, 0x0F, 0x90, 0xBE, 0x1D, 0xD9, 0x89, 0x04, 0x28, 0x3A, 0x8E, 0x26, 0x5C, 0x95, 0x10, 0x5A,
65 0x0A, 0x99, 0xEE, 0xFB, 0x69, 0xCE, 0xD9, 0x63, 0x00, 0xF5, 0x0A, 0xBC, 0x2C, 0x0D, 0xF8, 0xE2,
66 0x05, 0x02, 0x00, 0x7C, 0x03, 0x00, 0x3D, 0x08, 0xD8, 0x8D, 0x08, 0x7A, 0x6D, 0x00, 0x35, 0x06,
67 0xBA, 0x66, 0x10, 0x00, 0x91, 0x08, 0x10, 0x29, 0xD0, 0x45, 0xDA, 0x00, 0x2D, 0x05, 0x69, 0x09,
68 0x00, 0x5E, 0x0F, 0x70, 0x86, 0x12, 0x6C, 0x77, 0x5A, 0xFB, 0xCD, 0x56, 0xFB, 0xF7, 0xB7, 0x00,
69 0x5D, 0x07, 0x19, 0x99, 0xF2, 0xAF, 0x00, 0x63, 0x03, 0x00, 0xF0, 0x10, 0xBE, 0xD7, 0xA0, 0x63,
70 0xFA, 0x84, 0xA7, 0x74, 0x94, 0xEF, 0xAD, 0xC2, 0xAC, 0x00, 0x78, 0x07, 0x9F, 0x57, 0x0B, 0x62,
71 0x00, 0xFE, 0x08, 0x08, 0x5D, 0x5A, 0x6A, 0x54, 0x00, 0xE2, 0x09, 0x93, 0x7E, 0x62, 0x2A, 0x5E,
72 0xDA, 0x00, 0x7E, 0x0F, 0xF0, 0x07, 0x01, 0x6D, 0x50, 0x86, 0xDD, 0x4A, 0x15, 0x54, 0xC7, 0xEC,
73 0x00, 0xF2, 0x0B, 0x07, 0xF8, 0x1A, 0xB0, 0x99, 0x3B, 0xF1, 0x36, 0x00, 0x94, 0x07, 0x34, 0xE3,
74 0xBC, 0x6E, 0x00, 0x34, 0x0D, 0x6F, 0xDA, 0xBD, 0xEE, 0xF7, 0xCC, 0xCE, 0x39, 0x7E, 0xE3, 0x00,
75 0x14, 0x08, 0xDC, 0xD2, 0xB9, 0xF9, 0x31, 0x00, 0xB0, 0x0C, 0x10, 0xA3, 0x45, 0x12, 0xC7, 0xCD,
76 0xBF, 0x05, 0x37, 0x00, 0xC4, 0x0D, 0x5F, 0xE0, 0x59, 0xBB, 0x01, 0x59, 0x03, 0xD6, 0x29, 0x9C,
77 0x00, 0x01, 0x0A, 0x09, 0xAA, 0xA8, 0xA8, 0x24, 0x0B, 0x66, 0x00, 0x5C, 0x05, 0xA5, 0xCE, 0x00,
78 0xC1, 0x0B, 0xB7, 0xA0, 0x6F, 0xE9, 0x2B, 0xCC, 0xB5, 0xFC, 0x00, 0x8D, 0x05, 0xF4, 0xAC, 0x00,
79 0x57, 0x04, 0xB6, 0x00, 0xFC, 0x03, 0x00, 0xC3, 0x10, 0x43, 0x3B, 0xBE, 0xA2, 0x96, 0xC3, 0x65,
80 0x9F, 0x9A, 0x88, 0xD5, 0x49, 0x68, 0x00, 0xDC, 0x11, 0x56, 0x23, 0x2D, 0xF9, 0xFC, 0xF5, 0x8B,
81 0x1B, 0xB1, 0xB7, 0x10, 0x21, 0x1C, 0x12, 0x00, 0x0D, 0x0D, 0xEB, 0x86, 0xA2, 0x49, 0x8D, 0x8D,
82 0xBE, 0xA1, 0x6D, 0x53, 0x00, 0xE1, 0x0A, 0x8E, 0x67, 0xAA, 0x16, 0x79, 0x39, 0x59, 0x00, 0x36,
83 0x0B, 0x2A, 0x4E, 0xAE, 0x51, 0x4B, 0xD0, 0x66, 0x33, 0x00, 0x8A, 0x07, 0xCD, 0x6F, 0xBA, 0x92,
84 0x00, 0x1A, 0x0E, 0xDF, 0x4A, 0xB3, 0x77, 0x1F, 0xA5, 0x90, 0x19, 0xFA, 0x59, 0xD7, 0x00, 0x04,
85 0x0F, 0xAC, 0xCA, 0x9F, 0xA4, 0xFC, 0x6D, 0x90, 0x86, 0x9E, 0x1F, 0x44, 0x40, 0x00, 0x9F, 0x04,
86 0x56, 0x00, 0x22, 0x03, 0x00, 0xB8, 0x10, 0x2C, 0x7A, 0x53, 0xA4, 0xBF, 0xA3, 0x90, 0x90, 0x14,
87 0x9D, 0x46, 0x6C, 0x96, 0x00, 0xC6, 0x0B, 0x9B, 0xBB, 0xB0, 0xAE, 0x60, 0x92, 0x8E, 0x0C, 0x00,
88 0x14, 0x06, 0x4B, 0xAE, 0x7F, 0x00, 0x5C, 0x0B, 0x23, 0xFA, 0xE7, 0x51, 0xDA, 0x61, 0x49, 0x5E,
89 0x00, 0xD7, 0x0B, 0x01, 0xFC, 0x55, 0x31, 0x84, 0xC5, 0x0C, 0x98, 0x00, 0x97, 0x50, 0x6E, 0xF9,
90 0xEE, 0x75, 0x92, 0x53, 0xD3, 0x66, 0xA4, 0xAF, 0x3B, 0xFE, 0x7B, 0x27, 0x30, 0xBB, 0xB6, 0xF2,
91 0x76, 0x22, 0x45, 0x42, 0xCA, 0xF9, 0xF0, 0xDE, 0x9F, 0x45, 0x16, 0x68, 0x22, 0xB9, 0x84, 0x28,
92 0x8F, 0x2B, 0xB5, 0x5C, 0xD2, 0xF5, 0x45, 0x36, 0x3E, 0x76, 0xC6, 0xBF, 0x32, 0x5C, 0x41, 0xA6,
93 0x26, 0xC7, 0x82, 0x2F, 0x2E, 0xB5, 0x75, 0xC6, 0xE6, 0x67, 0x9E, 0x77, 0x94, 0xAF, 0x6A, 0x05,
94 0xC0, 0x05, 0x61, 0x71, 0x89, 0x5A, 0xB1, 0xD0, 0xFC, 0x7E, 0xC0, 0x9B, 0xCB, 0x3B, 0x69, 0xD9,
95 0x5F, 0xAF, 0xCA, 0xAB, 0x25, 0xD5, 0xBE, 0x8A, 0x6B, 0xB0, 0xFB, 0x61, 0x6C, 0xEB, 0x85, 0x6E,
96 0x7A, 0x48, 0xFF, 0x97, 0x91, 0x06, 0x3D, 0x4D, 0x68, 0xD3, 0x65, 0x83, 0x90, 0xA0, 0x08, 0x5C,
97 0xFC, 0xEE, 0x7C, 0x33, 0x43, 0x7F, 0x80, 0x52, 0x8B, 0x19, 0x72, 0xF2, 0xC9, 0xAB, 0x93, 0xAF,
98 0x16, 0xED, 0x36, 0x48, 0xAB, 0xC9, 0xD1, 0x03, 0xB3, 0xDC, 0x2F, 0xF2, 0x92, 0x3F, 0x0A, 0x19,
99 0x25, 0xE2, 0xEF, 0x7A, 0x22, 0xDA, 0xDB, 0xCB, 0x32, 0x12, 0x61, 0x49, 0x5B, 0x74, 0x7C, 0x65,
100 0x20, 0x89, 0x54, 0x9E, 0x0E, 0xC9, 0x52, 0xE3, 0xC9, 0x9A, 0x44, 0xC9, 0x5D, 0xA6, 0x77, 0xC0,
101 0xE7, 0x60, 0x91, 0x80, 0x50, 0x1F, 0x33, 0xB1, 0xCD, 0xAD, 0xF4, 0x0D, 0xBB, 0x08, 0xB1, 0xD0,
102 0x13, 0x95, 0xAE, 0xC9, 0xE2, 0x64, 0xA2, 0x65, 0xFB, 0x8F, 0xE9, 0xA2, 0x8A, 0xBC, 0x98, 0x81,
103 0x45, 0xB4, 0x55, 0x4E, 0xB9, 0x74, 0xB4, 0x50, 0x76, 0xBF, 0xF0, 0x45, 0xE7, 0xEE, 0x41, 0x64,
104 0x9F, 0xB5, 0xE0, 0xBB, 0x1C, 0xBB, 0x28, 0x66, 0x1B, 0xDD, 0x2B, 0x02, 0x66, 0xBF, 0xFD, 0x7D,
105 0x37, 0x35, 0x1D, 0x76, 0x21, 0xC3, 0x8F, 0xAF, 0xF6, 0xF9, 0xE9, 0x27, 0x48, 0xE7, 0x3D, 0x95,
106 0x74, 0x0C, 0x77, 0x88, 0x56, 0xD9, 0x84, 0xC8, 0x7D, 0x20, 0x31, 0x43, 0x53, 0xF1, 0xC1, 0xC7,
107 0xC9, 0xF7, 0x5C, 0xC0, 0xA6, 0x5A, 0x27, 0x0A, 0x41, 0xD4, 0x44, 0x94, 0x65, 0x4F, 0xE2, 0x53,
108 0x60, 0x0B, 0xD1, 0x23, 0x6C, 0x0C, 0xBC, 0x70, 0x6C, 0x26, 0x1A, 0x61, 0x1D, 0x35, 0x88, 0xEC,
109 0xB8, 0x15, 0xE3, 0xB4, 0x82, 0xEE, 0xB3, 0x21, 0xAC, 0x6C, 0xB7, 0x33, 0x6D, 0x78, 0x0C, 0x0D,
110 0xB4, 0x0B, 0x29, 0xF2, 0xD4, 0x8C, 0x3F, 0xDD, 0x3F, 0x47, 0xDD, 0xF2, 0xD8, 0x39, 0x57, 0x20,
111 0x28, 0xD8, 0xDD, 0x32, 0xE2, 0x6A, 0x47, 0x53, 0x57, 0xC6, 0xFA, 0x7A, 0x38, 0x30, 0x31, 0x8F,
112 0xE7, 0xD3, 0x84, 0x2B, 0x5D, 0x4F, 0x95, 0x98, 0xED, 0x0B, 0xD7, 0x50, 0x0C, 0x49, 0xDA, 0x59,
113 0x15, 0xF1, 0x39, 0xF3, 0x40, 0xDC, 0xDC, 0x25, 0x24, 0x56, 0x6E, 0xA9, 0x2F, 0xF0, 0x00, 0x00 };
116 char gdrom_status[] = {
117 0x00, 0x15, 0x00, 0x64, 0x00, 0x40, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
123 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40,
126 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
127 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40,
128 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00,
129 0x00, 0x40, 0x00, 0x00 };
132 static void ide_init( void )
133 {
134 ide_reset();
135 }
137 static void ide_reset( void )
138 {
139 ide_clear_interrupt();
140 idereg.error = 0x01;
141 idereg.count = 0x01;
142 idereg.lba0 = /* 0x21; */ 0x81;
143 idereg.lba1 = 0x14;
144 idereg.lba2 = 0xeb;
145 idereg.feature = 0; /* Indeterminate really */
146 idereg.status = 0x00;
147 idereg.device = 0x00;
148 idereg.state = IDE_STATE_IDLE;
149 memset( idereg.gdrom_sense, '\0', 10 );
150 idereg.data_offset = -1;
151 idereg.data_length = -1;
152 idereg.last_read_track = 1;
153 idereg.read_lba = 150;
154 idereg.read_mode = 0x28;
155 idereg.sectors_left = 0;
156 idereg.was_reset = TRUE;
157 }
159 static uint32_t ide_run_slice( uint32_t nanosecs )
160 {
161 if( gdrom_disc != NULL && gdrom_disc->run_time_slice != NULL ) {
162 gdrom_disc->run_time_slice(gdrom_disc, nanosecs);
163 }
164 return nanosecs;
165 }
167 static void ide_save_state( FILE *f )
168 {
169 fwrite( &idereg, sizeof(idereg), 1, f );
170 fwrite( data_buffer, MAX_SECTOR_SIZE, 1, f );
171 }
173 static int ide_load_state( FILE *f )
174 {
175 uint32_t length;
176 fread( &idereg, sizeof(idereg), 1, f );
177 fread( data_buffer, MAX_SECTOR_SIZE, 1, f );
178 return 0;
179 }
181 /************************ State transitions *************************/
183 void ide_set_packet_result( uint16_t result )
184 {
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;
189 idereg.count = 3;
190 if( result != 0 ) {
191 idereg.status = 0x51;
192 ide_raise_interrupt();
193 } else {
194 idereg.status = idereg.status & ~(IDE_STATUS_BSY|IDE_STATUS_CHK);
195 }
196 }
198 /**
199 * Begin command packet write to the device. This is always 12 bytes of PIO data
200 */
201 static void ide_start_command_packet_write( )
202 {
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;
209 }
211 /**
212 * Begin PIO read from the device. The data is assumed to already be
213 * in the buffer at this point.
214 */
215 static void ide_start_read( int length, gboolean dma )
216 {
217 idereg.count = IDE_COUNT_IO;
218 idereg.data_length = length;
219 idereg.data_offset = 0;
220 if( dma ) {
221 idereg.state = IDE_STATE_DMA_READ;
222 idereg.status = 0xD0;
223 } else {
224 idereg.state = IDE_STATE_PIO_READ;
225 idereg.status = 0x58;
226 idereg.lba1 = length & 0xFF;
227 idereg.lba2 = length >> 8;
228 ide_raise_interrupt( );
229 }
230 }
232 static void ide_start_packet_read( int length, int sector_count )
233 {
234 idereg.sectors_left = sector_count;
235 ide_set_packet_result( PKT_ERR_OK );
236 ide_start_read( length, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
237 }
239 static void ide_raise_interrupt( void )
240 {
241 if( idereg.intrq_pending == 0 ) {
242 idereg.intrq_pending = 1;
243 if( IS_IDE_IRQ_ENABLED() )
244 asic_event( EVENT_IDE );
245 }
246 }
248 static void ide_clear_interrupt( void )
249 {
250 if( idereg.intrq_pending != 0 ) {
251 idereg.intrq_pending = 0;
252 if( IS_IDE_IRQ_ENABLED() )
253 asic_clear_event( EVENT_IDE );
254 }
255 }
257 static void ide_set_error( int error_code )
258 {
259 idereg.status = 0x51;
260 idereg.error = error_code;
261 }
263 uint8_t ide_read_status( void )
264 {
265 if( (idereg.status & IDE_STATUS_BSY) == 0 )
266 ide_clear_interrupt();
267 return idereg.status;
268 }
270 uint16_t ide_read_data_pio( void ) {
271 if( idereg.state == IDE_STATE_PIO_READ ) {
272 uint16_t rv = READ_BUFFER();
273 idereg.data_offset += 2;
274 if( idereg.data_offset >= idereg.data_length ) {
275 idereg.state = IDE_STATE_IDLE;
276 idereg.status &= ~IDE_STATUS_DRQ;
277 idereg.data_offset = -1;
278 idereg.count = 3; /* complete */
279 ide_raise_interrupt();
280 if( idereg.sectors_left > 0 ) {
281 ide_read_next_sector();
282 }
283 }
284 return rv;
285 } else {
286 return 0xFFFF;
287 }
288 }
291 /**
292 * DMA read request
293 *
294 * This method is called from the ASIC side when a DMA read request is
295 * initiated. If there is a pending DMA transfer already, we copy the
296 * data immediately, otherwise we record the DMA buffer for use when we
297 * get to actually doing the transfer.
298 * @return number of bytes transfered
299 */
300 uint32_t ide_read_data_dma( uint32_t addr, uint32_t length )
301 {
302 uint32_t xfercount = 0;
303 if( idereg.state == IDE_STATE_DMA_READ ) {
304 while( xfercount < length ) {
305 int xferlen = length - xfercount;
306 int remaining = idereg.data_length - idereg.data_offset;
307 if( xferlen > remaining ) {
308 xferlen = remaining;
309 }
310 mem_copy_to_sh4( addr, data_buffer + idereg.data_offset, xferlen );
311 xfercount += xferlen;
312 addr += xferlen;
313 idereg.data_offset += xferlen;
314 if( idereg.data_offset >= idereg.data_length ) {
315 if( idereg.sectors_left > 0 ) {
316 ide_read_next_sector();
317 } else {
318 idereg.data_offset = -1;
319 idereg.state = IDE_STATE_IDLE;
320 idereg.status = 0x50;
321 idereg.count = 0x03;
322 ide_raise_interrupt();
323 asic_event( EVENT_IDE_DMA );
324 break;
325 }
326 }
327 }
328 }
329 return xfercount;
330 }
332 void ide_write_data_pio( uint16_t val ) {
333 if( idereg.state == IDE_STATE_CMD_WRITE ) {
334 WRITE_BUFFER(val);
335 idereg.data_offset+=2;
336 if( idereg.data_offset >= idereg.data_length ) {
337 idereg.state = IDE_STATE_BUSY;
338 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
339 idereg.data_offset = -1;
340 ide_packet_command(data_buffer);
341 }
342 } else if( idereg.state == IDE_STATE_PIO_WRITE ) {
343 WRITE_BUFFER(val);
344 if( idereg.data_offset >= idereg.data_length ) {
345 idereg.state = IDE_STATE_BUSY;
346 idereg.data_offset = -1;
347 idereg.status = (idereg.status & ~IDE_STATUS_DRQ) | IDE_STATUS_BSY;
348 /* ??? - no data writes yet anyway */
349 }
350 }
351 }
353 void ide_write_control( uint8_t val ) {
354 if( IS_IDE_IRQ_ENABLED() ) {
355 if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
356 asic_clear_event( EVENT_IDE );
357 } else {
358 if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
359 asic_event( EVENT_IDE );
360 }
361 idereg.control = val;
362 }
364 void ide_write_command( uint8_t val ) {
365 ide_clear_interrupt();
366 idereg.command = val;
367 switch( val ) {
368 case IDE_CMD_NOP: /* Effectively an "abort" */
369 idereg.state = IDE_STATE_IDLE;
370 idereg.status = 0x51;
371 idereg.error = 0x04;
372 idereg.data_offset = -1;
373 ide_raise_interrupt();
374 return;
375 case IDE_CMD_RESET_DEVICE:
376 ide_reset();
377 break;
378 case IDE_CMD_PACKET:
379 ide_start_command_packet_write();
380 break;
381 case IDE_CMD_SET_FEATURE:
382 switch( idereg.feature ) {
383 case IDE_FEAT_SET_TRANSFER_MODE:
384 switch( idereg.count & 0xF8 ) {
385 case IDE_XFER_PIO:
386 INFO( "Set PIO default mode: %d", idereg.count&0x07 );
387 break;
388 case IDE_XFER_PIO_FLOW:
389 INFO( "Set PIO Flow-control mode: %d", idereg.count&0x07 );
390 break;
391 case IDE_XFER_MULTI_DMA:
392 INFO( "Set Multiword DMA mode: %d", idereg.count&0x07 );
393 break;
394 case IDE_XFER_ULTRA_DMA:
395 INFO( "Set Ultra DMA mode: %d", idereg.count&0x07 );
396 break;
397 default:
398 INFO( "Setting unknown transfer mode: %02X", idereg.count );
399 break;
400 }
401 break;
402 default:
403 WARN( "IDE: unimplemented feature: %02X", idereg.feature );
404 }
405 idereg.status = 0x50;
406 idereg.error = 0x00;
407 idereg.lba1 = 0x00;
408 idereg.lba2 = 0x00;
409 ide_raise_interrupt();
410 break;
411 default:
412 WARN( "IDE: Unimplemented command: %02X", val );
413 }
414 }
416 uint8_t ide_get_drive_status( void )
417 {
418 if( gdrom_disc == NULL ) {
419 return IDE_DISC_NONE;
420 } else {
421 return gdrom_disc->drive_status(gdrom_disc);
422 }
423 }
425 #define REQUIRE_DISC() if( gdrom_disc == NULL ) { ide_set_packet_result( PKT_ERR_NODISC ); return; }
427 /**
428 * Read the next sector from the active read, if any
429 */
430 static void ide_read_next_sector( void )
431 {
432 int sector_size;
433 REQUIRE_DISC();
434 gdrom_error_t status =
435 gdrom_disc->read_sector( gdrom_disc, idereg.read_lba, idereg.read_mode,
436 data_buffer, §or_size );
437 if( status != PKT_ERR_OK ) {
438 ide_set_packet_result( status );
439 idereg.gdrom_sense[5] = (idereg.read_lba >> 16) & 0xFF;
440 idereg.gdrom_sense[6] = (idereg.read_lba >> 8) & 0xFF;
441 idereg.gdrom_sense[7] = idereg.read_lba & 0xFF;
442 WARN( " => Read CD returned sense key %02X, %02X", status & 0xFF, status >> 8 );
443 } else {
444 idereg.read_lba++;
445 idereg.sectors_left--;
446 ide_start_read( sector_size, (idereg.feature & IDE_FEAT_DMA) ? TRUE : FALSE );
447 }
448 }
450 /**
451 * Execute a packet command. This particular method is responsible for parsing
452 * the command buffers (12 bytes), and generating the appropriate responses,
453 * although the actual implementation is mostly delegated to gdrom.c
454 */
455 void ide_packet_command( unsigned char *cmd )
456 {
457 uint32_t length, datalen;
458 uint32_t lba, status;
459 int mode;
461 /* Okay we have the packet in the command buffer */
462 INFO( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
463 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7],
464 cmd[8], cmd[9], cmd[10], cmd[11] );
466 if( cmd[0] != PKT_CMD_SENSE && idereg.was_reset ) {
467 ide_set_packet_result( PKT_ERR_RESET );
468 idereg.was_reset = FALSE;
469 return;
470 }
472 switch( cmd[0] ) {
473 case PKT_CMD_TEST_READY:
474 REQUIRE_DISC();
475 ide_set_packet_result( 0 );
476 ide_raise_interrupt();
477 idereg.status = 0x50;
478 break;
479 case PKT_CMD_IDENTIFY:
480 lba = cmd[2];
481 if( lba >= sizeof(gdrom_ident) ) {
482 ide_set_error(PKT_ERR_BADFIELD);
483 } else {
484 length = cmd[4];
485 if( lba+length > sizeof(gdrom_ident) )
486 length = sizeof(gdrom_ident) - lba;
487 memcpy( data_buffer, gdrom_ident + lba, length );
488 ide_start_packet_read( length, 0 );
489 }
490 break;
491 case PKT_CMD_SENSE:
492 length = cmd[4];
493 if( length > 10 )
494 length = 10;
495 memcpy( data_buffer, idereg.gdrom_sense, length );
496 ide_start_packet_read( length, 0 );
497 break;
498 case PKT_CMD_READ_TOC:
499 REQUIRE_DISC();
500 length = (cmd[3]<<8) | cmd[4];
501 if( length > sizeof(struct gdrom_toc) )
502 length = sizeof(struct gdrom_toc);
504 status = gdrom_disc->read_toc( gdrom_disc, data_buffer );
505 if( status != PKT_ERR_OK ) {
506 ide_set_packet_result( status );
507 } else {
508 ide_start_packet_read( length, 0 );
509 }
510 break;
511 case PKT_CMD_SESSION_INFO:
512 REQUIRE_DISC();
513 length = cmd[4];
514 if( length > 6 )
515 length = 6;
516 status = gdrom_disc->read_session( gdrom_disc, cmd[2], data_buffer );
517 if( status != PKT_ERR_OK ) {
518 ide_set_packet_result( status );
519 } else {
520 ide_start_packet_read( length, 0 );
521 }
522 break;
523 case PKT_CMD_PLAY_AUDIO:
524 REQUIRE_DISC();
525 ide_set_packet_result( 0 );
526 ide_raise_interrupt();
527 idereg.status = 0x50;
528 break;
529 case PKT_CMD_READ_SECTOR:
530 REQUIRE_DISC();
531 idereg.read_lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
532 idereg.sectors_left = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
533 idereg.read_mode = cmd[1];
534 ide_read_next_sector();
535 break;
536 case PKT_CMD_SPIN_UP:
537 REQUIRE_DISC();
538 /* do nothing? */
539 ide_set_packet_result( PKT_ERR_OK );
540 ide_raise_interrupt();
541 break;
542 case PKT_CMD_STATUS:
543 REQUIRE_DISC();
544 length = cmd[4];
545 switch( cmd[1] ) {
546 case 0:
547 if( length > sizeof(gdrom_status) ) {
548 length = sizeof(gdrom_status);
549 }
550 memcpy( data_buffer, gdrom_status, length );
551 ide_start_packet_read( length, 0 );
552 break;
553 case 1:
554 if( length > 14 ) {
555 length = 14;
556 }
557 gdrom_disc->read_position( gdrom_disc, idereg.read_lba, data_buffer );
558 data_buffer[0] = 0x00;
559 data_buffer[1] = 0x15; /* audio status ? */
560 data_buffer[2] = 0x00;
561 data_buffer[3] = 0x0E;
562 ide_start_packet_read( length, 0 );
563 break;
564 }
565 break;
566 case PKT_CMD_71:
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
570 */
571 REQUIRE_DISC();
572 memcpy( data_buffer, gdrom_71, sizeof(gdrom_71) );
573 ide_start_packet_read( sizeof(gdrom_71), 0 );
574 break;
575 default:
576 ide_set_packet_result( PKT_ERR_BADCMD ); /* Invalid command */
577 return;
578 }
579 }
.