Author Topic: disc_io.c  (Read 5390 times)

0 Members and 1 Guest are viewing this topic.

Offline Dr.neo

  • Administrator
  • Hero Member
  • *****
  • Posts: 3826
disc_io.c
« on: July 02, 2007, 01:14:33 AM »
//
//
//     Welcome to join our develope team 
//      contact us now for more details
//
//    Mail&MSN: neoflash_team@hotmail.com
//           mIRC : #neo @ EFnet
//
//         http://www.neoflash.com     
//                                     
//

/*

   disc_io.c

   uniformed io-interface to work with Chishm's FAT library

   Written by MightyMax

   Modified by Chishm:
   2005-11-06
      * Added WAIT_CR modifications for NDS

   Modified by www.neoflash.com:
   2006-02-03
      * Added SUPPORT_* defines, comment out any of the SUPPORT_* defines in disc_io.h to remove support
        for the given interface and stop code being linked to the binary

       * Added support for MK2 MMC interface

      * Added disc_Cache* functions

   Modified by Chishm:
   2006-02-05
      * Added Supercard SD support

   Modified by CyteX:
   2006-02-26
      * Added EFA2 support
*/

#include "disc_io.h"

#ifdef NDS
   #include <nds.h>
#endif


// Include known io-interfaces:
#ifdef SUPPORT_MPCF
 #include "io_mpcf.h"
#endif

#ifdef SUPPORT_M3CF
 #include "io_m3cf.h"
#endif

#ifdef SUPPORT_M3SD
 #include "io_m3sd.h"
#endif

#ifdef SUPPORT_SCCF
 #include "io_sccf.h"
#endif

#ifdef SUPPORT_SCSD
 #include "io_scsd.h"
#endif

#ifdef SUPPORT_FCSR
 #include "io_fcsr.h"
#endif

#ifdef SUPPORT_NMMC
 #include "io_nmmc.h"
#endif

#ifdef SUPPORT_NMMC2
 #include "io_nmmc2.h"
#endif

#ifdef SUPPORT_EFA2
 #include "io_efa2.h"
#endif

#ifdef SUPPORT_MK6
   #include "io_mk6.h"
#endif

// Keep a pointer to the active interface
LPIO_INTERFACE active_interface = 0;


/*

   Disc Cache functions
   2006-02-03:
      Added by www.neoflash.com

*/

#ifdef DISC_CACHE

#include <string.h>

#define CACHE_FREE 0xFFFFFFFF

static u8 cacheBuffer[ DISC_CACHE_COUNT * 512 ];

static struct {
   u32 sector;
   u32 dirty;
   u32 count;
} cache[ DISC_CACHE_COUNT ];

#define memcpy neo_memcpy
void neo_memcpy( void *dst, void *src, u32 len );

static u32 disc_CacheFind(u32 sector) {
   u32 i;

   for( i = 0; i < DISC_CACHE_COUNT; i++ )   {
      if( cache[ i ].sector == sector )
         return i;
   }

   return CACHE_FREE;
}

static u32 disc_CacheFindFree(void) {

   u32 i = 0, j;
   u32 count = -1;

   for( j = 0; j < DISC_CACHE_COUNT; j++ )   {

      if( cache[ j ].sector == CACHE_FREE ) {
         i = j;
         break;
      }

      if( cache[ j ].count < count ) {
         count = cache[ j ].count;
         i = j;
      }
   }

   if( cache[ i ].sector != CACHE_FREE && cache.dirty != 0 ) {

      active_interface->fn_WriteSectors( cache[ i ].sector, 1, &cacheBuffer[ i * 512 ] );
      /* todo: handle write error here */

      cache[ i ].sector = CACHE_FREE;
      cache[ i ].dirty = 0;
      cache[ i ].count = 0;
   }

   return i;
}

void disc_CacheInit(void)   {

   u32 i;

   for( i = 0; i < DISC_CACHE_COUNT; i++ )   {
      cache[ i ].sector = CACHE_FREE;
      cache[ i ].dirty = 0;
      cache[ i ].count = 0;
   }

}

bool disc_CacheFlush(void)   {

   u32 i;

   if( !active_interface )   return false;

   for( i = 0; i < DISC_CACHE_COUNT; i++ )   {
      if( cache[ i ].sector != CACHE_FREE && cache[ i ].dirty != 0 )   {
         if( active_interface->fn_WriteSectors( cache[ i ].sector, 1, &cacheBuffer[ i * 512 ] ) == false )
            return false;

         cache[ i ].dirty = 0;
      }
   }
   return true;
}

bool disc_CacheReadSector( void *buffer, u32 sector) {
   u32 i = disc_CacheFind( sector );
   if( i == CACHE_FREE ) {
      i = disc_CacheFindFree();
      cache[ i ].sector = sector;
      if( active_interface->fn_ReadSectors( sector, 1, &cacheBuffer[ i * 512 ] ) == false )
         return false;
   }
#ifdef DISK_CACHE_DMA
      DMA3_SRC = (u32)&cacheBuffer[ i * 512 ]
      DMA3_DEST = (u32)buffer;
      DMA3_CR = 128 | DMA_COPY_WORDS;
#else
   memcpy( buffer, &cacheBuffer[ i * 512 ], 512 );
#endif
   cache[ i ].count++;
   return true;
}

bool disc_CacheWriteSector( void *buffer, u32 sector ) {
   u32 i = disc_CacheFind( sector );
   if( i == CACHE_FREE ) {
      i = disc_CacheFindFree();
      cache [ i ].sector = sector;
   }
#ifdef DISK_CACHE_DMA
      DMA3_SRC = (u32)buffer;
      DMA3_DEST = (u32)&cacheBuffer[ i * 512 ];
      DMA3_CR = 128 | DMA_COPY_WORDS;
#else
   memcpy( &cacheBuffer[ i * 512 ], buffer, 512 );
#endif
   cache[ i ].dirty=1;
   cache[ i ].count++;
   return true;
}

#endif

/*

   Hardware level disc funtions

*/

bool disc_setGbaSlotInterface (void)
{
   // If running on an NDS, make sure the correct CPU can access
   // the GBA cart. First implemented by SaTa.
#ifdef NDS
 #ifdef ARM9
   //WAIT_CR &= ~(0x8080);            // 0x001A = fastest // 0x000E = slowest
   WAIT_CR = ((WAIT_CR & ~0x809F) | 0x001A);
 #endif
 #ifdef ARM7
   //WAIT_CR |= (0x8080);
   WAIT_CR = ((WAIT_CR & ~0x001F) | 0x809A);
 #endif
#endif
   u16 ime=REG_IME;
   REG_IME=0;
   // check if we have a Neo2 plugged in - the best of all devices!
   active_interface = NSD2_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      REG_IME = ime;
      // set Neo2 as default IO
      return true ;
   } ;
   REG_IME = ime;


#ifdef SUPPORT_NMMC2
   // check if we have a Neo2 plugged in - the best of all devices!
   active_interface = NMMC2_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set Neo2 as default IO
      return true ;
   } ;
#endif

#ifdef SUPPORT_M3CF
   // check if we have a M3 perfect CF plugged in
   active_interface = M3CF_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set M3 CF as default IO
      return true ;
   } ;
#endif

#ifdef SUPPORT_M3SD
   // check if we have a M3 perfect SD plugged in
   active_interface = M3SD_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set M3 SD as default IO
      return true ;
   } ;
#endif

#ifdef SUPPORT_MPCF
   // check if we have a GBA Movie Player plugged in
   active_interface = MPCF_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set GBAMP as default IO
      return true ;
   } ;
#endif

#ifdef SUPPORT_SCSD
   // check if we have a SuperCard SD plugged in
   active_interface = SCSD_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set SC SD as default IO
      return true ;
   } ;
#endif

#ifdef SUPPORT_SCCF
   // check if we have a SuperCard CF plugged in
   active_interface = SCCF_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set SC CF as default IO
      return true ;
   } ;
#endif

#ifdef SUPPORT_EFA2
   // check if we have a EFA2 plugged in
   active_interface = EFA2_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      return true ;
   } ;
#endif

#ifdef SUPPORT_FCSR
   // check if we have a GBA Flash Cart plugged in
   active_interface = FCSR_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set FC as default IO
      return true ;
   } ;
#endif

   return false;
}

#ifdef NDS
// Check the DS card slot for a valid memory card interface
// If an interface is found, it is set as the default interace
// and it returns true. Otherwise the default interface is left
// untouched and it returns false.
bool disc_setDsSlotInterface (void)
{
#ifdef ARM9
   WAIT_CR &= ~(1<<11);
#endif
#ifdef ARM7
   WAIT_CR |= (1<<11);
#endif

#ifdef SUPPORT_NMMC
   // check if we have a Neoflash MK2 / MK3 plugged in
   active_interface = NMMC_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set Neoflash MK2 / MK3 as default IO
      return true ;
   } ;
#endif

#ifdef SUPPORT_MK6
   // check if we have a Neoflash MK6 plugged in
   active_interface = MK6_GetInterface() ;
   if (active_interface->fn_StartUp())
   {
      // set Neoflash MK6 as default IO
      return true ;
   } ;
#endif

   return false;
}
#endif


bool disc_Init(void)
{
#ifdef DISC_CACHE
   disc_CacheInit();
#endif

// www.neoflash.com - this is not good, because if FAT_InitFiles fails
// we want to re-initialize the card, or further FAT_InitFiles will
// always fail!

//   if (active_interface != 0) {
//      return true;
//   }

#ifdef NDS
   if (disc_setDsSlotInterface()) {
      return true;
   }
#endif

   if (disc_setGbaSlotInterface()) {
      return true;
   }

   // could not find a working IO Interface
   active_interface = 0 ;
   return false ;
}

bool disc_IsInserted(void)
{
   if (active_interface) return active_interface->fn_IsInserted() ;
   return false ;
}

bool disc_ReadSectors(u32 sector, u8 numSecs, void* buffer)
{
   u16 ime=REG_IME;
   REG_IME=0;
restartRead:
#ifdef DISC_CACHE
   u8 *p=(u8*)buffer;
   u32 i;
   u32 inumSecs=numSecs;
   if(numSecs==0)
      inumSecs=256;
   for( i = 0; i<inumSecs; i++)   {
      if( disc_CacheReadSector( &p[i*512], sector + i ) == false )   {
         REG_IME=ime;
         return false;
      }
   }
   REG_IME=ime;
   return true;
#else
   if (active_interface)   {
      bool success = active_interface->fn_ReadSectors(sector,numSecs,buffer) ;
      REG_IME=ime;
      if(!success)   goto restartRead;
      return success;
   }
   REG_IME=ime;
   return false ;
#endif
}

bool disc_WriteSectors(u32 sector, u8 numSecs, void* buffer)
{

   u16 ime=REG_IME;
   REG_IME=0;
restartWrite:
#ifdef DISC_CACHE
   u8 *p=(u8*)buffer;
   u32 i;
   u32 inumSecs=numSecs;
   if(numSecs==0)
      inumSecs=256;
   for( i = 0; i<inumSecs; i++)   {
      if( disc_CacheWriteSector( &p[i*512], sector + i ) == false )   {
            REG_IME=ime;
            return false ;
         }
   }
   REG_IME=ime;
   return true;
#else
   if (active_interface) {
      bool success = active_interface->fn_WriteSectors(sector,numSecs,buffer) ;
      REG_IME=ime;
      if(!success)   goto restartWrite;
      return success;
   }
   REG_IME=ime;
   return false ;
#endif
}

bool disc_ClearStatus(void)
{
   if (active_interface) return active_interface->fn_ClearStatus() ;
   return false ;
}

bool disc_Shutdown(void)
{
#ifdef DISC_CACHE
   disc_CacheFlush();
#endif
   if (active_interface) active_interface->fn_Shutdown() ;
   active_interface = 0 ;
   return true ;
}

u32   disc_HostType (void)
{
   if (active_interface) {
      return active_interface->ul_ioType;
   } else {
      return 0;
   }
}

In my world,have 0 and 1 only ......Matrix World......

Offline TeenDev

  • Newbie
  • *
  • Posts: 26
  • The pirate basher
    • TeenDev
Re: disc_io.c
« Reply #1 on: July 14, 2007, 09:55:20 PM »
A DLDI patch is being made of this, however this piece of data is only useful for GBA_NDS_FAT.