Search
lxdream.org :: lxdream/src/gdrom/ide.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/gdrom/ide.c
changeset 125:49bf45f8210a
prev47:da09bcb7ce69
next138:afabd7e6d26d
author nkeynes
date Wed Mar 22 14:29:02 2006 +0000 (14 years ago)
permissions -rw-r--r--
last change Rename IDE DMA registers appropriately
Remove forced irq hack
Add correct irq handling for IDE
Miscellaneous WIP for the GD-rom drive
file annotate diff log raw
1.1 --- a/src/gdrom/ide.c Tue Dec 27 12:41:33 2005 +0000
1.2 +++ b/src/gdrom/ide.c Wed Mar 22 14:29:02 2006 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: ide.c,v 1.7 2005-12-27 12:41:33 nkeynes Exp $
1.6 + * $Id: ide.c,v 1.8 2006-03-22 14:29:02 nkeynes Exp $
1.7 *
1.8 * IDE interface implementation
1.9 *
1.10 @@ -20,7 +20,9 @@
1.11
1.12 #include <stdlib.h>
1.13 #include "dream.h"
1.14 +#include "asic.h"
1.15 #include "gdrom/ide.h"
1.16 +#include "gdrom/gdrom.h"
1.17
1.18 #define MAX_WRITE_BUF 4096;
1.19
1.20 @@ -32,16 +34,18 @@
1.21
1.22 struct ide_registers idereg;
1.23
1.24 -static char command_buffer[12];
1.25 +static unsigned char command_buffer[12];
1.26
1.27 /* "\0\0\0\0\xb4\x19\0\0\x08SE REV 6.42990316" */
1.28 -char gdrom_ident[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00,
1.29 +unsigned char gdrom_ident[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x19, 0x00,
1.30 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
1.31 0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2e,
1.32 0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36 };
1.33
1.34
1.35 -void set_write_buffer( char *buf, int len )
1.36 +gdrom_disc_t gdrom_disc = NULL;
1.37 +
1.38 +static void ide_set_write_buffer( unsigned char *buf, int len )
1.39 {
1.40 idereg.status |= IDE_ST_DATA;
1.41 idereg.data = buf;
1.42 @@ -50,7 +54,7 @@
1.43 idereg.readptr = NULL;
1.44 }
1.45
1.46 -void set_read_buffer( char *buf, int len )
1.47 +static void ide_set_read_buffer( unsigned char *buf, int len, int blocksize )
1.48 {
1.49 idereg.status |= IDE_ST_DATA;
1.50 idereg.data = buf;
1.51 @@ -59,11 +63,31 @@
1.52 idereg.writeptr = NULL;
1.53 idereg.lba1 = len&0xFF;
1.54 idereg.lba2 = len>>8;
1.55 + idereg.blocksize = idereg.blockleft = blocksize;
1.56 }
1.57
1.58 -void ide_clear_interrupt( void )
1.59 +static void ide_raise_interrupt( void )
1.60 {
1.61 - /* TODO */
1.62 + if( idereg.intrq_pending == 0 ) {
1.63 + idereg.intrq_pending = 1;
1.64 + if( IS_IDE_IRQ_ENABLED() )
1.65 + asic_event( EVENT_IDE );
1.66 + }
1.67 +}
1.68 +
1.69 +static void ide_clear_interrupt( void )
1.70 +{
1.71 + if( idereg.intrq_pending != 0 ) {
1.72 + idereg.intrq_pending = 0;
1.73 + if( IS_IDE_IRQ_ENABLED() )
1.74 + asic_clear_event( EVENT_IDE );
1.75 + }
1.76 +}
1.77 +
1.78 +static void ide_set_error( int error_code )
1.79 +{
1.80 + idereg.status = 0x51;
1.81 + idereg.error = error_code;
1.82 }
1.83
1.84 void ide_init( void )
1.85 @@ -76,13 +100,20 @@
1.86 ide_clear_interrupt();
1.87 idereg.error = 0x01;
1.88 idereg.count = 0x01;
1.89 - idereg.lba0 = 0x21;
1.90 + idereg.lba0 = /* 0x21; */ 0x81;
1.91 idereg.lba1 = 0x14;
1.92 idereg.lba2 = 0xeb;
1.93 idereg.feature = 0; /* Indeterminate really */
1.94 idereg.status = 0x00;
1.95 idereg.device = 0x00;
1.96 - idereg.disc = IDE_DISC_GDROM | IDE_DISC_READY;
1.97 + idereg.disc = (gdrom_disc == NULL ? IDE_DISC_NONE : (IDE_DISC_CDROM|IDE_DISC_READY));
1.98 +}
1.99 +
1.100 +uint8_t ide_read_status( void )
1.101 +{
1.102 + if( (idereg.status & IDE_ST_BUSY) == 0 )
1.103 + ide_clear_interrupt();
1.104 + return idereg.status;
1.105 }
1.106
1.107 uint16_t ide_read_data_pio( void ) {
1.108 @@ -90,9 +121,13 @@
1.109 return 0xFFFF;
1.110 uint16_t rv = *idereg.readptr++;
1.111 idereg.datalen-=2;
1.112 + idereg.blockleft-=2;
1.113 if( idereg.datalen <=0 ) {
1.114 idereg.readptr = NULL;
1.115 idereg.status &= ~IDE_ST_DATA;
1.116 + } else if( idereg.blockleft <= 0 ) {
1.117 + ide_raise_interrupt();
1.118 + idereg.blockleft = idereg.blocksize;
1.119 }
1.120 return rv;
1.121 }
1.122 @@ -103,26 +138,33 @@
1.123 *idereg.writeptr++ = val;
1.124 idereg.datalen-=2;
1.125 if( idereg.datalen <= 0 ) {
1.126 + int len = ((unsigned char *)idereg.writeptr) - idereg.data;
1.127 idereg.writeptr = NULL;
1.128 idereg.status &= ~IDE_ST_DATA;
1.129 - ide_write_buffer( idereg.data );
1.130 + ide_write_buffer( idereg.data, len );
1.131 }
1.132 }
1.133
1.134 void ide_write_control( uint8_t val ) {
1.135 - /* TODO: In theory we can cause a soft-reset here, but the DC doesn't
1.136 - * appear to support it.
1.137 - */
1.138 + if( IS_IDE_IRQ_ENABLED() ) {
1.139 + if( (val & 0x02) != 0 && idereg.intrq_pending != 0 )
1.140 + asic_clear_event( EVENT_IDE );
1.141 + } else {
1.142 + if( (val & 0x02) == 0 && idereg.intrq_pending != 0 )
1.143 + asic_event( EVENT_IDE );
1.144 + }
1.145 + idereg.control = val;
1.146 }
1.147
1.148 void ide_write_command( uint8_t val ) {
1.149 + ide_clear_interrupt();
1.150 idereg.command = val;
1.151 switch( val ) {
1.152 case IDE_CMD_RESET_DEVICE:
1.153 ide_reset();
1.154 break;
1.155 case IDE_CMD_PACKET:
1.156 - set_write_buffer(command_buffer,12);
1.157 + ide_set_write_buffer(command_buffer,12);
1.158 break;
1.159 case IDE_CMD_SET_FEATURE:
1.160 switch( idereg.feature ) {
1.161 @@ -148,6 +190,7 @@
1.162 default:
1.163 WARN( "IDE: unimplemented feature: %02X", idereg.feature );
1.164 }
1.165 + ide_raise_interrupt( );
1.166 break;
1.167 default:
1.168 WARN( "IDE: Unimplemented command: %02X", val );
1.169 @@ -155,24 +198,65 @@
1.170 idereg.status |= IDE_ST_READY | IDE_ST_SERV;
1.171 }
1.172
1.173 -void ide_write_buffer( char *data ) {
1.174 - uint16_t length;
1.175 +void ide_packet_command( unsigned char *cmd )
1.176 +{
1.177 + uint32_t length;
1.178 + uint32_t lba;
1.179 + int blocksize = idereg.lba1 + (idereg.lba2<<8);
1.180 +
1.181 + ide_raise_interrupt( );
1.182 + /* Okay we have the packet in the command buffer */
1.183 + WARN( "ATAPI: Received Packet command: %02X", cmd[0] );
1.184 + fwrite_dump( (unsigned char *)cmd, 12, stderr );
1.185 + switch( cmd[0] ) {
1.186 + case PKT_CMD_IDENTIFY:
1.187 + /* NB: Bios sets cmd[4] = 0x08, no idea what this is for;
1.188 + * different values here appear to have no effect.
1.189 + */
1.190 + length = *((uint16_t*)(cmd+2));
1.191 + if( length > sizeof(gdrom_ident) )
1.192 + length = sizeof(gdrom_ident);
1.193 + ide_set_read_buffer(gdrom_ident, length, blocksize);
1.194 + break;
1.195 + case PKT_CMD_READ_TOC:
1.196 +
1.197 + break;
1.198 + case PKT_CMD_READ_SECTOR:
1.199 + lba = cmd[2] << 16 | cmd[3] << 8 | cmd[4];
1.200 + length = cmd[8] << 16 | cmd[9] << 8 | cmd[10]; /* blocks */
1.201 + if( gdrom_disc == NULL ) {
1.202 + ide_set_error( 0x50 );
1.203 + return;
1.204 + }
1.205 + /*
1.206 + if( gdrom_disc->read_data_sectors( lba, length ) == FALSE ) {
1.207 + ide_set_error( 0x50 );
1.208 + return;
1.209 + }
1.210 +
1.211 + */
1.212 + break;
1.213 + }
1.214 +}
1.215 +
1.216 +void ide_write_buffer( unsigned char *data, int datalen ) {
1.217 switch( idereg.command ) {
1.218 case IDE_CMD_PACKET:
1.219 - /* Okay we have the packet in the command buffer */
1.220 - WARN( "ATAPI: Received Packet command: %02X", data[0] );
1.221 -
1.222 - switch( command_buffer[0] ) {
1.223 - case PKT_CMD_IDENTIFY:
1.224 - /* NB: Bios sets data[4] = 0x08, no idea what this is for;
1.225 - * different values here appear to have no effect.
1.226 - */
1.227 - length = *((uint16_t*)(data+2));
1.228 - if( length > sizeof(gdrom_ident) )
1.229 - length = sizeof(gdrom_ident);
1.230 - set_read_buffer(gdrom_ident, length);
1.231 - break;
1.232 - }
1.233 + ide_packet_command( data );
1.234 break;
1.235 }
1.236 }
1.237 +
1.238 +/**
1.239 + * DMA read request
1.240 + *
1.241 + * This method is called from the ASIC side when a DMA read request is
1.242 + * initiated. If there is a pending DMA transfer already, we copy the
1.243 + * data immediately, otherwise we record the DMA buffer for use when we
1.244 + * get to actually doing the transfer.
1.245 + */
1.246 +void ide_dma_read_req( uint32_t addr, uint32_t length )
1.247 +{
1.248 +
1.249 +
1.250 +}
.