filename | test/ide.c |
changeset | 251:3c5953d944e0 |
prev | 247:b356d391d02a |
author | nkeynes |
date | Sat Dec 27 02:59:35 2008 +0000 (15 years ago) |
branch | lxdream-mem |
permissions | -rw-r--r-- |
last change | Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode, which tracks the field of the same name in sh4r - actually a little faster this way. Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR flag yet). Also fixed the failure to check the flags in the common case (code address returned by previous block) which took away the performance benefits, but oh well. |
view | annotate | diff | log | raw |
1 #include <assert.h>
2 #include <stdlib.h>
3 #include "ide.h"
4 #include "lib.h"
6 #define IDE_BASE 0xA05F7000
8 #define IDE_ALTSTATUS IDE_BASE+0x018
9 #define IDE_UNKNOWN IDE_BASE+0x01C
10 #define IDE_DATA IDE_BASE+0x080 /* 16 bits */
11 #define IDE_FEATURE IDE_BASE+0x084
12 #define IDE_COUNT IDE_BASE+0x088
13 #define IDE_LBA0 IDE_BASE+0x08C
14 #define IDE_LBA1 IDE_BASE+0x090
15 #define IDE_LBA2 IDE_BASE+0x094
16 #define IDE_DEVICE IDE_BASE+0x098
17 #define IDE_COMMAND IDE_BASE+0x09C
18 #define IDE_ACTIVATE IDE_BASE+0x4E4
20 #define IDE_DEVCONTROL IDE_ALTSTATUS
21 #define IDE_ERROR IDE_FEATURE
22 #define IDE_STATUS IDE_COMMAND
24 #define IDE_DMA_ADDR IDE_BASE+0x404
25 #define IDE_DMA_SIZE IDE_BASE+0x408
26 #define IDE_DMA_DIR IDE_BASE+0x40C
27 #define IDE_DMA_CTL1 IDE_BASE+0x414
28 #define IDE_DMA_CTL2 IDE_BASE+0x418
29 #define IDE_DMA_MAGIC IDE_BASE+0x4B8
30 #define IDE_DMA_STATUS IDE_BASE+0x4F8
32 #define DMA_BASE 0xFFA00000
33 #define DMA_SAR1 DMA_BASE+0x010
34 #define DMA_DAR1 DMA_BASE+0x014
35 #define DMA_TCR1 DMA_BASE+0x018
36 #define DMA_CHCR1 DMA_BASE+0x01C
37 #define DMA_SAR2 DMA_BASE+0x020
38 #define DMA_DAR2 DMA_BASE+0x024
39 #define DMA_TCR2 DMA_BASE+0x028
40 #define DMA_CHCR2 DMA_BASE+0x02C
41 #define DMA_SAR3 DMA_BASE+0x030
42 #define DMA_DAR3 DMA_BASE+0x034
43 #define DMA_TCR3 DMA_BASE+0x038
44 #define DMA_CHCR3 DMA_BASE+0x03C
45 #define DMA_DMAOR DMA_BASE+0x040
46 #define QUEUECR0 0xFF000038
47 #define QUEUECR1 0xFF00003C
49 #define IDE_CMD_RESET 0x08
50 #define IDE_CMD_PACKET 0xA0
51 #define IDE_CMD_IDENTIFY_PACKET_DEVICE 0xA1
52 #define IDE_CMD_IDENTIFY_DEVICE 0xEC
54 #define MMC_CMD_GET_CONFIGURATION 0x46
55 #define GD_CMD_IDENTIFY 0x11 /* guessing */
58 #define IDE_DMA_MAGIC_VALUE 0x8843407F
61 #define MAX_WAIT 10000000
62 #define MAX_IRQ_WAIT 1000000000
64 /**
65 * Dump all ide registers to stdout.
66 */
67 void ide_dump_registers() {
68 int i,j;
69 printf( "IDE registers:\n");
70 printf( "Stats: %02X ", byte_read(IDE_ALTSTATUS) );
71 printf( "Error: %02X ", byte_read(IDE_ERROR) );
72 printf( "Count: %02X ", byte_read(IDE_COUNT) );
73 printf( "Dvice: %02X ", byte_read(IDE_DEVICE) );
74 if( long_read(ASIC_STATUS1)&1 ) {
75 printf( "INTRQ! " );
76 }
77 if( (long_read(ASIC_STATUS0)>>14)&1 ) {
78 printf( "DMARQ! " );
79 }
80 printf( "\nLBA 0: %02X ", byte_read(IDE_LBA0) );
81 printf( "LBA 1: %02X ", byte_read(IDE_LBA1) );
82 printf( "LBA 2: %02X ", byte_read(IDE_LBA2) );
83 printf( "0x01C: %02X\n", byte_read(IDE_UNKNOWN) );
84 printf( "DAddr: %08X ", long_read(IDE_DMA_ADDR) );
85 printf( "DSize: %08X ", long_read(IDE_DMA_SIZE) );
86 printf( "DDir : %08X ", long_read(IDE_DMA_DIR) );
87 printf( "DCtl1: %08X ", long_read(IDE_DMA_CTL1) );
88 printf( "DCtl2: %08X\n", long_read(IDE_DMA_CTL2) );
89 printf( "DStat: %08X\n", long_read(IDE_DMA_STATUS) );
90 printf( "ASIC: " );
91 for( i=0; i<12; i+=4 ) {
92 unsigned int val = long_read(ASIC_STATUS0+i);
93 for( j=0; j<32; j++ ) {
94 if( val & (1<<j) ) {
95 printf( "%d ", j );
96 }
97 }
98 printf( "| " );
99 }
100 printf( "\n" );
101 }
103 /**
104 * Wait for the IDE INTRQ line to go active (bit 0 of the second word)
105 * @return 0 on success, non-zero on timeout
106 */
107 int ide_wait_irq() {
108 unsigned int status;
109 int i;
110 for( i=0; i<MAX_WAIT; i++ ) {
111 status = long_read( ASIC_STATUS1 );
112 if( (status&1) != 0 )
113 return 0;
114 }
115 return 1;
116 }
118 /**
119 * Wait for the IDE BSY flag to be de-asserted.
120 * @return 0 on success, non-zero on timeout
121 */
122 int ide_wait_ready() {
123 unsigned char status;
124 int i;
125 for( i=0; i<MAX_WAIT; i++ ) {
126 status = byte_read(IDE_ALTSTATUS);
127 if( (status & 0x80) == 0 )
128 return 0;
129 }
130 printf( "Timeout waiting for IDE to become ready (status = 0x%02X)\n", status );
131 ide_dump_registers();
132 return 1;
133 }
135 int ide_wait_dma() {
136 unsigned int status;
137 int i;
138 for( i=0; i<MAX_WAIT; i++ ) {
139 status = long_read(IDE_DMA_CTL2);
140 if( (status & 1) == 0 )
141 return 0;
142 }
143 printf( "[IDE] Timeout waiting for DMA to become ready\n" );
144 return 1;
145 }
147 /**
148 * Write the command packet out to the interface.
149 * @param cmd 12 byte ATAPI command packet
150 * @param dma 1 = dma mode, 0 = pio mode
151 */
152 int ide_write_command_packet( char *cmd, int dma )
153 {
154 int i, status;
155 unsigned short *spkt = (unsigned short *)cmd;
156 unsigned short length = 8;
157 if( ide_wait_ready() )
158 return 1;
159 byte_write( IDE_FEATURE, dma );
160 byte_write( IDE_COUNT, 0 );
161 byte_write( IDE_LBA0, 0 );
162 byte_write( IDE_LBA1, (length&0xFF) );
163 byte_write( IDE_LBA2, (length>>8)&0xFF );
164 byte_write( IDE_DEVICE, 0 );
165 byte_write( IDE_COMMAND, IDE_CMD_PACKET );
166 status = byte_read(IDE_ALTSTATUS); /* delay 1 PIO cycle as per spec */
167 /* Wait until device is ready to accept command */
168 if( ide_wait_ready() )
169 return 1;
171 /* Write the command */
172 for( i=0; i<6; i++ ) {
173 word_write( IDE_DATA, spkt[i] );
174 }
175 }
177 int ide_read_pio( char *buf, int buflen ) {
178 int i;
179 unsigned short *bufptr = (unsigned short *)buf;
180 unsigned int length = 0, avail;
181 int status;
183 while(1) {
184 if( ide_wait_ready() )
185 return -1;
186 status = byte_read( IDE_STATUS );
187 if( (status & 0xE9) == 0x48 ) {
188 /* Bytes available */
189 avail = (byte_read( IDE_LBA1 )) | (byte_read(IDE_LBA2)<<8);
190 for( i=0; i<avail; i+=2 ) {
191 if( buflen > 0 ) {
192 *bufptr++ = word_read(IDE_DATA);
193 buflen-=2;
194 }
195 }
196 length += avail;
197 if( avail == 0 ) {
198 /* Should never happen */
199 printf( "[IDE] Unexpected read length 0\n" );
200 return -1;
201 }
202 } else {
203 if( status&0x01 ) {
204 printf( "[IDE] ERROR! (%02X)\n", status );
205 return -1;
206 } else if( (status&0x08) == 0 ) {
207 /* No more data */
208 return length;
209 } else {
210 printf( "[IDE] Unexpected status result: %02X\n", status );
211 return -1;
212 }
213 }
214 }
215 }
217 int ide_read_dma( char *buf, int buflen )
218 {
219 int status;
221 long_write( IDE_DMA_CTL1, 1 );
222 long_write( IDE_DMA_CTL2, 1 );
224 printf( "Started DMA\n" );
225 ide_dump_registers();
227 ide_wait_irq();
228 printf( "After IRQ\n" );
229 ide_dump_registers();
230 long_write( IDE_DMA_CTL1, 0 );
231 status = ide_wait_dma();
232 printf( "After DMA finished\n");
233 ide_dump_registers();
234 if( status != 0 ) {
235 return -1;
236 }
237 status = long_read(ASIC_STATUS0);
238 if( (status & (1<<14)) == 0 ) {
239 printf( "DMARQ cleared already\n");
240 } else {
241 /*
242 status &= ~(1<<14);
243 long_write(ASIC_STATUS0, status);
244 status = long_read(ASIC_STATUS0);
245 */
246 byte_read(IDE_STATUS );
247 if( (status & (1<<14)) == 0 ) {
248 printf( "DMARQ cleared successfully\n" );
249 } else {
250 printf( "DMARQ not cleared: %08X\n", long_read(ASIC_STATUS0) );
251 }
252 }
253 status = ide_wait_ready();
254 printf( "After IDE ready\n");
255 ide_dump_registers();
256 if( status != 0 ) {
257 return -1;
258 }
259 return long_read( IDE_DMA_STATUS );
260 }
262 int ide_do_packet_command_pio( char *cmd, char *buf, int length )
263 {
264 ide_write_command_packet( cmd, 0 );
265 length = ide_read_pio( buf, length );
266 return length;
267 }
269 int ide_do_packet_command_dma( char *cmd, char *buf, int length )
270 {
271 long_write( QUEUECR0, 0x10 );
272 long_write( QUEUECR1, 0x10 );
273 long_write( IDE_DMA_MAGIC, IDE_DMA_MAGIC_VALUE );
274 long_write( IDE_DMA_ADDR, (unsigned int)buf );
275 long_write( IDE_DMA_SIZE, length );
276 long_write( IDE_DMA_DIR, 1 );
277 ide_write_command_packet( cmd, 1 );
278 length = ide_read_dma( buf, length );
279 return length;
280 }
282 void ide_activate() {
283 register unsigned long p, x;
285 /* Reactivate GD-ROM drive */
287 *((volatile unsigned long *)0xa05f74e4) = 0x1fffff;
288 for(p=0; p<0x200000/4; p++)
289 x = ((volatile unsigned long *)0xa0000000)[p];
290 }
293 int ide_init()
294 {
295 ide_activate();
297 if( ide_wait_ready() )
298 return -1;
300 /** Set Default PIO mode */
301 byte_write( IDE_FEATURE, 0x03 );
302 byte_write( IDE_COUNT, 0x0B );
303 byte_write( IDE_COMMAND, 0xEF );
305 if( ide_wait_ready() )
306 return -1;
308 /** Set Multi-word DMA mode 2 */
309 long_write( 0xA05F7490, 0x222 );
310 long_write( 0xA05F7494, 0x222 );
311 byte_write( IDE_FEATURE, 0x03 );
312 byte_write( IDE_COUNT, 0x22 );
313 byte_write( IDE_COMMAND, 0xEF );
314 if( ide_wait_ready() )
315 return -1;
317 word_write( 0xA05F7480, 0x400 );
318 long_write( 0xA05F7488, 0x200 );
319 long_write( 0xA05F748C, 0x200 );
320 long_write( 0xA05F74A0, 0x2001 );
321 long_write( 0xA05F74A4, 0x2001 );
322 long_write( 0xA05F74B4, 0x0001 );
323 }
325 int ide_sense_error( char *buf )
326 {
327 char cmd[12] = { 0x13,0,0,0, 10,0,0,0, 0,0,0,0 };
328 return ide_do_packet_command_pio( cmd, buf, 10 );
329 }
331 int ide_get_sense_code()
332 {
333 char buf[10];
334 int len = ide_sense_error( buf );
335 if( len != 10 ) {
336 printf( "ERROR: Sense request failed!\n" );
337 return -1;
338 }
339 return ((int)buf[8] << 8) | buf[2];
340 }
342 void ide_print_sense_error()
343 {
344 char buf[10];
345 if( ide_sense_error(buf) != 10 ) {
346 printf( "ERROR - Sense error failed!\n" );
347 return;
348 }
349 int major = buf[2] & 0xFF;
350 int minor = buf[8] & 0xFF;
351 printf( "[IDE] Error code %02X,%02X\n", major, minor );
352 }
354 int ide_test_ready()
355 {
356 char cmd[12] = { 0,0,0,0, 0,0,0,0, 0,0,0,0 };
357 int length = ide_do_packet_command_pio( cmd, NULL, 0 );
358 return length;
359 }
361 int ide_read_toc( char *buf, int length )
362 {
363 char cmd[12] = { 0x14,0,0,0, 0x98,0,0,0, 0,0,0,0 };
364 return ide_do_packet_command_pio( cmd, buf, length );
365 }
367 int ide_get_session( int session, struct gdrom_session *session_data )
368 {
369 char cmd[12] = {0x15, 0, session, 0, 6,0,0,0, 0,0,0,0 };
370 char buf[6];
371 int length = ide_do_packet_command_pio( cmd, buf, sizeof(buf) );
372 if( length < 0 )
373 return length;
374 if( length != 6 )
375 return -1;
376 assert(length == 6);
377 session_data->track = ((int)buf[2])&0xFF;
378 session_data->lba = (((int)buf[3])&0xFF) << 16 |
379 (((int)buf[4])&0xFF) << 8 |
380 (((int)buf[5])&0xFF);
381 return 0;
382 }
384 int ide_spinup( )
385 {
386 char cmd[12] = {0x70,0x1F,0,0, 0,0,0,0, 0,0,0,0};
387 int length = ide_do_packet_command_pio( cmd, NULL, 0 );
388 return length;
389 }
391 int ide_unknown71( char *buf, int length )
392 {
393 char cmd[12] = {0x71,0,0,0, 0,0,0,0, 0,0,0,0};
394 return ide_do_packet_command_pio( cmd, buf, length );
395 }
397 int ide_read_sector_pio( uint32_t sector, uint32_t count, int mode,
398 char *buf, int length )
399 {
400 char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
402 cmd[1] = mode;
403 cmd[2] = (sector>>16)&0xFF;
404 cmd[3] = (sector>>8)&0xFF;
405 cmd[4] = sector&0xFF;
406 cmd[8] = (count>>16)&0xFF;
407 cmd[9] = (count>>8)&0xFF;
408 cmd[10] = count&0xFF;
409 return ide_do_packet_command_pio( cmd, buf, length );
410 }
413 int ide_read_sector_dma( uint32_t sector, uint32_t count, int mode,
414 char *buf, int length )
415 {
416 char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
418 cmd[1] = mode;
419 cmd[2] = (sector>>16)&0xFF;
420 cmd[3] = (sector>>8)&0xFF;
421 cmd[4] = sector&0xFF;
422 cmd[8] = (count>>16)&0xFF;
423 cmd[9] = (count>>8)&0xFF;
424 cmd[10] = count&0xFF;
425 return ide_do_packet_command_dma( cmd, buf, length );
426 }
428 int ide_read_something( )
429 {
430 char cmd[12] = { 0x12,0,0,0, 0x0a,0,0,0, 0,0,0,0 };
431 char result[10];
432 ide_do_packet_command_pio( cmd, result, 10 );
433 return 0;
434 }
436 int ide_read_status( char *buf, int length, int type )
437 {
438 char cmd[12] = { 0x40,0,0,0, 0xFF,0,0,0, 0,0,0,0 };
440 cmd[1] = type;
441 return ide_do_packet_command_pio( cmd, buf, length );
442 }
444 int ide_play_cd( char *buf, int length )
445 {
446 char cmd[12] = { 0x21, 0x04,0,0, 0,0,0,0, 0,0,0,0 };
447 return ide_do_packet_command_pio( cmd, buf, length );
448 }
.