Search
lxdream.org :: lxdream/test/ide.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename test/ide.c
changeset 185:6755a04c447f
next243:df1671d533bf
author nkeynes
date Fri Aug 18 09:31:12 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change Add float_read, float_write for fp registers
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/test/ide.c Fri Aug 18 09:31:12 2006 +0000
1.3 @@ -0,0 +1,418 @@
1.4 +#include <assert.h>
1.5 +#include <stdlib.h>
1.6 +#include "ide.h"
1.7 +#include "lib.h"
1.8 +
1.9 +#define IDE_BASE 0xA05F7000
1.10 +
1.11 +#define IDE_ALTSTATUS IDE_BASE+0x018
1.12 +#define IDE_UNKNOWN IDE_BASE+0x01C
1.13 +#define IDE_DATA IDE_BASE+0x080 /* 16 bits */
1.14 +#define IDE_FEATURE IDE_BASE+0x084
1.15 +#define IDE_COUNT IDE_BASE+0x088
1.16 +#define IDE_LBA0 IDE_BASE+0x08C
1.17 +#define IDE_LBA1 IDE_BASE+0x090
1.18 +#define IDE_LBA2 IDE_BASE+0x094
1.19 +#define IDE_DEVICE IDE_BASE+0x098
1.20 +#define IDE_COMMAND IDE_BASE+0x09C
1.21 +#define IDE_ACTIVATE IDE_BASE+0x4E4
1.22 +
1.23 +#define IDE_DEVCONTROL IDE_ALTSTATUS
1.24 +#define IDE_ERROR IDE_FEATURE
1.25 +#define IDE_STATUS IDE_COMMAND
1.26 +
1.27 +#define IDE_DMA_ADDR IDE_BASE+0x404
1.28 +#define IDE_DMA_SIZE IDE_BASE+0x408
1.29 +#define IDE_DMA_DIR IDE_BASE+0x40C
1.30 +#define IDE_DMA_CTL1 IDE_BASE+0x414
1.31 +#define IDE_DMA_CTL2 IDE_BASE+0x418
1.32 +#define IDE_DMA_MAGIC IDE_BASE+0x4B8
1.33 +#define IDE_DMA_STATUS IDE_BASE+0x4F8
1.34 +
1.35 +#define DMA_BASE 0xFFA00000
1.36 +#define DMA_SAR1 DMA_BASE+0x010
1.37 +#define DMA_DAR1 DMA_BASE+0x014
1.38 +#define DMA_TCR1 DMA_BASE+0x018
1.39 +#define DMA_CHCR1 DMA_BASE+0x01C
1.40 +#define DMA_SAR2 DMA_BASE+0x020
1.41 +#define DMA_DAR2 DMA_BASE+0x024
1.42 +#define DMA_TCR2 DMA_BASE+0x028
1.43 +#define DMA_CHCR2 DMA_BASE+0x02C
1.44 +#define DMA_SAR3 DMA_BASE+0x030
1.45 +#define DMA_DAR3 DMA_BASE+0x034
1.46 +#define DMA_TCR3 DMA_BASE+0x038
1.47 +#define DMA_CHCR3 DMA_BASE+0x03C
1.48 +#define DMA_DMAOR DMA_BASE+0x040
1.49 +#define QUEUECR0 0xFF000038
1.50 +#define QUEUECR1 0xFF00003C
1.51 +
1.52 +#define IDE_CMD_RESET 0x08
1.53 +#define IDE_CMD_PACKET 0xA0
1.54 +#define IDE_CMD_IDENTIFY_PACKET_DEVICE 0xA1
1.55 +#define IDE_CMD_IDENTIFY_DEVICE 0xEC
1.56 +
1.57 +#define MMC_CMD_GET_CONFIGURATION 0x46
1.58 +#define GD_CMD_IDENTIFY 0x11 /* guessing */
1.59 +
1.60 +
1.61 +#define IDE_DMA_MAGIC_VALUE 0x8843407F
1.62 +
1.63 +
1.64 +#define MAX_WAIT 10000000
1.65 +#define MAX_IRQ_WAIT 1000000000
1.66 +
1.67 +/**
1.68 + * Dump all ide registers to stdout.
1.69 + */
1.70 +void ide_dump_registers() {
1.71 + int i,j;
1.72 + printf( "IDE registers:\n");
1.73 + printf( "Stats: %02X ", byte_read(IDE_ALTSTATUS) );
1.74 + printf( "Error: %02X ", byte_read(IDE_ERROR) );
1.75 + printf( "Count: %02X ", byte_read(IDE_COUNT) );
1.76 + printf( "Dvice: %02X ", byte_read(IDE_DEVICE) );
1.77 + if( long_read(ASIC_STATUS1)&1 ) {
1.78 + printf( "INTRQ! " );
1.79 + }
1.80 + if( (long_read(ASIC_STATUS0)>>14)&1 ) {
1.81 + printf( "DMARQ! " );
1.82 + }
1.83 + printf( "\nLBA 0: %02X ", byte_read(IDE_LBA0) );
1.84 + printf( "LBA 1: %02X ", byte_read(IDE_LBA1) );
1.85 + printf( "LBA 2: %02X ", byte_read(IDE_LBA2) );
1.86 + printf( "0x01C: %02X\n", byte_read(IDE_UNKNOWN) );
1.87 + printf( "DAddr: %08X ", long_read(IDE_DMA_ADDR) );
1.88 + printf( "DSize: %08X ", long_read(IDE_DMA_SIZE) );
1.89 + printf( "DDir : %08X ", long_read(IDE_DMA_DIR) );
1.90 + printf( "DCtl1: %08X ", long_read(IDE_DMA_CTL1) );
1.91 + printf( "DCtl2: %08X\n", long_read(IDE_DMA_CTL2) );
1.92 + printf( "DStat: %08X\n", long_read(IDE_DMA_STATUS) );
1.93 + printf( "ASIC: " );
1.94 + for( i=0; i<12; i+=4 ) {
1.95 + unsigned int val = long_read(ASIC_STATUS0+i);
1.96 + for( j=0; j<32; j++ ) {
1.97 + if( val & (1<<j) ) {
1.98 + printf( "%d ", j );
1.99 + }
1.100 + }
1.101 + printf( "| " );
1.102 + }
1.103 + printf( "\n" );
1.104 +}
1.105 +
1.106 +/**
1.107 + * Wait for the IDE INTRQ line to go active (bit 0 of the second word)
1.108 + * @return 0 on success, non-zero on timeout
1.109 + */
1.110 +int ide_wait_irq() {
1.111 + unsigned int status;
1.112 + int i;
1.113 + for( i=0; i<MAX_WAIT; i++ ) {
1.114 + status = long_read( ASIC_STATUS1 );
1.115 + if( (status&1) != 0 )
1.116 + return 0;
1.117 + }
1.118 + printf( "Timeout waiting for IDE INTRQ\n" );
1.119 + ide_dump_registers();
1.120 + return 1;
1.121 +}
1.122 +
1.123 +/**
1.124 + * Wait for the IDE BSY flag to be de-asserted.
1.125 + * @return 0 on success, non-zero on timeout
1.126 + */
1.127 +int ide_wait_ready() {
1.128 + unsigned char status;
1.129 + int i;
1.130 + for( i=0; i<MAX_WAIT; i++ ) {
1.131 + status = byte_read(IDE_ALTSTATUS);
1.132 + if( (status & 0x80) != 0x80 )
1.133 + return 0;
1.134 + }
1.135 + printf( "Timeout waiting for IDE to become ready\n" );
1.136 + ide_dump_registers();
1.137 + return 1;
1.138 +}
1.139 +
1.140 +int ide_wait_dma() {
1.141 + unsigned int status;
1.142 + int i;
1.143 + for( i=0; i<MAX_WAIT; i++ ) {
1.144 + status = long_read(IDE_DMA_CTL2);
1.145 + if( (status & 1) == 0 )
1.146 + return 0;
1.147 + }
1.148 + printf( "[IDE] Timeout waiting for DMA to become ready\n" );
1.149 + return 1;
1.150 +}
1.151 +
1.152 +/**
1.153 + * Write the command packet out to the interface.
1.154 + * @param cmd 12 byte ATAPI command packet
1.155 + * @param dma 1 = dma mode, 0 = pio mode
1.156 + */
1.157 +int ide_write_command_packet( char *cmd, int dma )
1.158 +{
1.159 + int i, status;
1.160 + unsigned short *spkt = (unsigned short *)cmd;
1.161 + unsigned short length = 8;
1.162 + if( ide_wait_ready() )
1.163 + return 1;
1.164 + byte_write( IDE_FEATURE, dma );
1.165 + byte_write( IDE_COUNT, 0 );
1.166 + byte_write( IDE_LBA0, 0 );
1.167 + byte_write( IDE_LBA1, (length&0xFF) );
1.168 + byte_write( IDE_LBA2, (length>>8)&0xFF );
1.169 + byte_write( IDE_DEVICE, 0 );
1.170 + byte_write( IDE_COMMAND, IDE_CMD_PACKET );
1.171 + status = byte_read(IDE_ALTSTATUS); /* delay 1 PIO cycle as per spec */
1.172 + printf( "After writing PACKET command byte:\n" );
1.173 + ide_dump_registers();
1.174 + /* Wait until device is ready to accept command */
1.175 + if( ide_wait_ready() )
1.176 + return 1;
1.177 + printf( "Device ready to receive packet:\n" );
1.178 + ide_dump_registers();
1.179 +
1.180 + /* Write the command */
1.181 + for( i=0; i<6; i++ ) {
1.182 + word_write( IDE_DATA, spkt[i] );
1.183 + }
1.184 + printf( "After writing command packet:\n" );
1.185 + ide_dump_registers();
1.186 +}
1.187 +
1.188 +int ide_read_pio( char *buf, int buflen ) {
1.189 + int i;
1.190 + unsigned short *bufptr = (unsigned short *)buf;
1.191 + unsigned int length = 0, avail;
1.192 + int status;
1.193 +
1.194 + while(1) {
1.195 + if( ide_wait_ready() )
1.196 + return -1;
1.197 + status = byte_read( IDE_STATUS );
1.198 + if( (status & 0xE9) == 0x48 ) {
1.199 + /* Bytes available */
1.200 + avail = (byte_read( IDE_LBA1 )) | (byte_read(IDE_LBA2)<<8);
1.201 + for( i=0; i<avail; i+=2 ) {
1.202 + if( buflen > 0 ) {
1.203 + *bufptr++ = word_read(IDE_DATA);
1.204 + buflen-=2;
1.205 + }
1.206 + }
1.207 + length += avail;
1.208 + if( avail == 0 ) {
1.209 + /* Should never happen */
1.210 + printf( "[IDE] Unexpected read length 0\n" );
1.211 + return -1;
1.212 + }
1.213 + } else {
1.214 + if( status&0x01 ) {
1.215 + printf( "[IDE] ERROR! (%02X)\n", status );
1.216 + } else if( (status&0x08) == 0 ) {
1.217 + /* No more data */
1.218 + return length;
1.219 + } else {
1.220 + printf( "[IDE] Unexpected status result: %02X\n", status );
1.221 + return -1;
1.222 + }
1.223 + }
1.224 + }
1.225 +}
1.226 +
1.227 +int ide_read_dma( char *buf, int buflen )
1.228 +{
1.229 + int status;
1.230 +
1.231 + long_write( IDE_DMA_CTL1, 1 );
1.232 + long_write( IDE_DMA_CTL2, 1 );
1.233 +
1.234 + printf( "Started DMA\n" );
1.235 + ide_dump_registers();
1.236 +
1.237 + ide_wait_irq();
1.238 + printf( "After IRQ\n" );
1.239 + ide_dump_registers();
1.240 + long_write( IDE_DMA_CTL1, 0 );
1.241 + status = ide_wait_dma();
1.242 + printf( "After DMA finished\n");
1.243 + ide_dump_registers();
1.244 + if( status != 0 ) {
1.245 + return -1;
1.246 + }
1.247 + status = long_read(ASIC_STATUS0);
1.248 + if( (status & (1<<14)) == 0 ) {
1.249 + printf( "DMARQ cleared already\n");
1.250 + } else {
1.251 + /*
1.252 + status &= ~(1<<14);
1.253 + long_write(ASIC_STATUS0, status);
1.254 + status = long_read(ASIC_STATUS0);
1.255 + */
1.256 + byte_read(IDE_STATUS );
1.257 + if( (status & (1<<14)) == 0 ) {
1.258 + printf( "DMARQ cleared successfully\n" );
1.259 + } else {
1.260 + printf( "DMARQ not cleared: %08X\n", long_read(ASIC_STATUS0) );
1.261 + }
1.262 + }
1.263 + status = ide_wait_ready();
1.264 + printf( "After IDE ready\n");
1.265 + ide_dump_registers();
1.266 + if( status != 0 ) {
1.267 + return -1;
1.268 + }
1.269 + return long_read( IDE_DMA_STATUS );
1.270 +}
1.271 +
1.272 +int ide_do_packet_command_pio( char *cmd, char *buf, int length )
1.273 +{
1.274 + ide_write_command_packet( cmd, 0 );
1.275 + length = ide_read_pio( buf, length );
1.276 + return length;
1.277 +}
1.278 +
1.279 +int ide_do_packet_command_dma( char *cmd, char *buf, int length )
1.280 +{
1.281 + long_write( QUEUECR0, 0x10 );
1.282 + long_write( QUEUECR1, 0x10 );
1.283 + long_write( IDE_DMA_MAGIC, IDE_DMA_MAGIC_VALUE );
1.284 + long_write( IDE_DMA_ADDR, (unsigned int)buf );
1.285 + long_write( IDE_DMA_SIZE, length );
1.286 + long_write( IDE_DMA_DIR, 1 );
1.287 + ide_write_command_packet( cmd, 1 );
1.288 + length = ide_read_dma( buf, length );
1.289 + return length;
1.290 +}
1.291 +
1.292 +int ide_init()
1.293 +{
1.294 + if( ide_wait_ready() )
1.295 + return -1;
1.296 +
1.297 + /** Set Default PIO mode */
1.298 + byte_write( IDE_FEATURE, 0x03 );
1.299 + byte_write( IDE_COUNT, 0x0B );
1.300 + byte_write( IDE_COMMAND, 0xEF );
1.301 +
1.302 + if( ide_wait_ready() )
1.303 + return -1;
1.304 +
1.305 + /** Set Multi-word DMA mode 2 */
1.306 + long_write( 0xA05F7490, 0x222 );
1.307 + long_write( 0xA05F7494, 0x222 );
1.308 + byte_write( IDE_FEATURE, 0x03 );
1.309 + byte_write( IDE_COUNT, 0x22 );
1.310 + byte_write( IDE_COMMAND, 0xEF );
1.311 + if( ide_wait_ready() )
1.312 + return -1;
1.313 +
1.314 + word_write( 0xA05F7480, 0x400 );
1.315 + long_write( 0xA05F7488, 0x200 );
1.316 + long_write( 0xA05F748C, 0x200 );
1.317 + long_write( 0xA05F74A0, 0x2001 );
1.318 + long_write( 0xA05F74A4, 0x2001 );
1.319 + long_write( 0xA05F74B4, 0x0001 );
1.320 +}
1.321 +
1.322 +int ide_sense_error( char *buf )
1.323 +{
1.324 + char cmd[12] = { 0x13,0,0,0, 10,0,0,0, 0,0,0,0 };
1.325 + return ide_do_packet_command_pio( cmd, buf, 10 );
1.326 +}
1.327 +
1.328 +void ide_print_sense_error()
1.329 +{
1.330 + char buf[10];
1.331 + if( ide_sense_error(buf) != 10 ) {
1.332 + printf( "ERROR - Sense error failed!\n" );
1.333 + return;
1.334 + }
1.335 + int major = buf[2] & 0xFF;
1.336 + int minor = buf[8] & 0xFF;
1.337 + printf( "[IDE] Error code %02X,%02X\n", major, minor );
1.338 +}
1.339 +
1.340 +int ide_test_ready()
1.341 +{
1.342 + char cmd[12] = { 0,0,0,0, 0,0,0,0, 0,0,0,0 };
1.343 + int length = ide_do_packet_command_pio( cmd, NULL, 0 );
1.344 + return length;
1.345 +}
1.346 +
1.347 +int ide_read_toc( char *buf, int length )
1.348 +{
1.349 + char cmd[12] = { 0x14,0,0,0, 0x98,0,0,0, 0,0,0,0 };
1.350 + return ide_do_packet_command_pio( cmd, buf, length );
1.351 +}
1.352 +
1.353 +int ide_get_session( int session, struct gdrom_session *session_data )
1.354 +{
1.355 + char cmd[12] = {0x15, 0, session, 0, 6,0,0,0, 0,0,0,0 };
1.356 + char buf[6];
1.357 + int length = ide_do_packet_command_pio( cmd, buf, sizeof(buf) );
1.358 + if( length < 0 )
1.359 + return length;
1.360 + if( length != 6 )
1.361 + return -1;
1.362 + assert(length == 6);
1.363 + session_data->track = ((int)buf[2])&0xFF;
1.364 + session_data->lba = (((int)buf[3])&0xFF) << 16 |
1.365 + (((int)buf[4])&0xFF) << 8 |
1.366 + (((int)buf[5])&0xFF);
1.367 + return 0;
1.368 +}
1.369 +
1.370 +int ide_spinup( )
1.371 +{
1.372 + char cmd[12] = {0x70,0x1F,0,0, 0,0,0,0, 0,0,0,0};
1.373 + int length = ide_do_packet_command_pio( cmd, NULL, 0 );
1.374 + return length;
1.375 +}
1.376 +
1.377 +int ide_unknown71( char *buf, int length )
1.378 +{
1.379 + char cmd[12] = {0x71,0,0,0, 0,0,0,0, 0,0,0,0};
1.380 + return ide_do_packet_command_pio( cmd, buf, length );
1.381 +}
1.382 +
1.383 +int ide_read_sector_pio( uint32_t sector, uint32_t count, int mode,
1.384 + char *buf, int length )
1.385 +{
1.386 + char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
1.387 +
1.388 + cmd[1] = mode;
1.389 + cmd[2] = (sector>>16)&0xFF;
1.390 + cmd[3] = (sector>>8)&0xFF;
1.391 + cmd[4] = sector&0xFF;
1.392 + cmd[8] = (count>>16)&0xFF;
1.393 + cmd[9] = (count>>8)&0xFF;
1.394 + cmd[10] = count&0xFF;
1.395 + return ide_do_packet_command_pio( cmd, buf, length );
1.396 +}
1.397 +
1.398 +
1.399 +int ide_read_sector_dma( uint32_t sector, uint32_t count, int mode,
1.400 + char *buf, int length )
1.401 +{
1.402 + char cmd[12] = { 0x30,0,0,0, 0,0,0,0, 0,0,0,0 };
1.403 +
1.404 + cmd[1] = mode;
1.405 + cmd[2] = (sector>>16)&0xFF;
1.406 + cmd[3] = (sector>>8)&0xFF;
1.407 + cmd[4] = sector&0xFF;
1.408 + cmd[8] = (count>>16)&0xFF;
1.409 + cmd[9] = (count>>8)&0xFF;
1.410 + cmd[10] = count&0xFF;
1.411 + return ide_do_packet_command_dma( cmd, buf, length );
1.412 +}
1.413 +
1.414 +int ide_read_something( )
1.415 +{
1.416 + char cmd[12] = { 0x12,0,0,0, 0x0a,0,0,0, 0,0,0,0 };
1.417 + char result[10];
1.418 + ide_do_packet_command_pio( cmd, result, 10 );
1.419 + debug_dump_buffer(result,10);
1.420 + return 0;
1.421 +}
1.422 \ No newline at end of file
.