filename | test/ide.c |
changeset | 251:3c5953d944e0 |
prev | 247:b356d391d02a |
author | nkeynes |
date | Thu Jan 11 06:51:11 2007 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Fix crash in texcache_evict Fix crash decoding small VQ textures Implement mip-mapped textures of all types |
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 }
.