Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

io_m3sd.c

#define io_M3SD_c
#include "io_m3sd.h"
#ifdef SUPPORT_M3SD
//M3-SD interface SD card.

#define DMA3SAD      *(volatile u32*)0x040000D4
#define DMA3DAD      *(volatile u32*)0x040000D8
#define DMA3CNT      *(volatile u32*)0x040000DC
#define DMA3CR       *(volatile u16*)0x040000DE

//SD dir control bit cmddir=bit0 clken=bit1
//output
#define SDDIR                 (*(volatile u16*)0x8800000)

//SD send get control bit send=bit0 get=bit1
//output
#define SDCON                 (*(volatile u16*)0x9800000)

//SD output data obyte[7:0]=AD[7:0]
//output
#define SDODA                 (*(volatile u16*)0x9000000)

//SD input data AD[7:0]=ibyte[7:0]
//input
#define SDIDA                 (*(volatile u16*)0x9000000)

//readsector data1
#define SDIDA1                (*(volatile u16*)0x9200000)

//readsector data2
#define SDIDA2                (*(volatile u16*)0x9400000)

//readsector data3
#define SDIDA3                (*(volatile u16*)0x9600000)

//SD stutas cmdneg=bit0 cmdpos=bit1 issend=bit2 isget=bit3
//input
#define SDSTA                 (*(volatile u16*)0x9800000)

#define M3_REG_STS            *(vu16*)(0x09800000)    // Status of the CF Card / Device control
#define M3_DATA               (vu16*)(0x08800000)           // Pointer to buffer of CF data transered from card

// CF Card status
#define CF_STS_INSERTED1            0x20
#define CF_STS_INSERTED2            0x30
#define CF_STS_INSERTED3            0x22
#define CF_STS_INSERTED4            0x32
#define isM3ins(sta)    ((sta==CF_STS_INSERTED1) || (sta==CF_STS_INSERTED2) || (sta==CF_STS_INSERTED3) || (sta==CF_STS_INSERTED4))


#define CARD_TIMEOUT    400000            // Updated due to suggestion from SaTa, otherwise card will timeout sometimes on a write
//#define CARD_TIMEOUT  (500*100)   // M3SD timeout nomal:500

void SendCommand(u16 command, u32 sectorn);
void PassRespond(u32 num);
void SD_crc16(u16* buff,u16 num,u16* crc16buff);
void SD_data_write(u16 *buff,u16* crc16buff);
u16 M3_SetChipReg(u32 Data);

//=========================================================
u16 M3_SetChipReg(u32 Data)
{
      u16 i,j;

      i = *(volatile u16*)(0x700001*2+0x8000000);

      i = *(volatile u16*)(0x000007*2+0x8000000);
      i = *(volatile u16*)(0x400ffe*2+0x8000000);
      i = *(volatile u16*)(0x000825*2+0x8000000);

      i = *(volatile u16*)(0x400309*2+0x8000000);
      i = *(volatile u16*)(0x000000*2+0x8000000);
      i = *(volatile u16*)(0x400db3*2+0x8000000);

      i = *(volatile u16*)((Data*2)+0x8000000);

      j = *(volatile u16*)(0x000407*2+0x8000000);
      i = *(volatile u16*)(0x000000*2+0x8000000);

      return j;
}

void M3_SelectSaver(u8 Bank)
{
      u16 i;

      i = *(volatile u16*)(0x700001*2+0x8000000);

      i = *(volatile u16*)(0x000007*2+0x8000000);
      i = *(volatile u16*)(0x400FFE*2+0x8000000);
      i = *(volatile u16*)(0x000825*2+0x8000000);

      i = *(volatile u16*)(0x400309*2+0x8000000);
      i = *(volatile u16*)(0x000000*2+0x8000000);
      i = *(volatile u16*)(0x400db3*2+0x8000000);

      i = *(volatile u16*)((Bank<<4)*2+0x8000000);

      i = *(volatile u16*)(0x000407*2+0x8000000);
      i = *(volatile u16*)(0x000000*2+0x8000000);
}

void DMA3(u32 src, u32 dst, u32 cnt)
{
      u16 i,j,cnttmp;

      cnttmp = (cnt&0xffff);
      if( ((dst&0x03) == 0)
            &&((cnttmp&0x0f) == 0)
            &&(cnttmp>0))
      {
            DC_FlushRange(dst,cnttmp*2);
            DMA3CR &= (~0x3a00);
            DMA3CR &= (~0x8000);
            i = DMA3CR;
            j = DMA3CR;

            DMA3SAD=src;
            DMA3DAD=dst;
            DMA3CNT=cnt;
      }
      else
      {
            for(j=0;j<cnttmp;j++)
            {
                  *(u16*)(dst+j*2) = *(u16*)(src+j*2);
            }
      }
}

void SendCommand(u16 command, u32 sectorn)
{
      SDCON=0x8;
      SDIDA1=0x40+command;
      SDIDA2=(sectorn>>7);
      SDIDA3=(sectorn<<9);

      SDDIR=0x29;
      while ((SDSTA&0x01) != 0x01);
      SDDIR=0x09;
}

void PassRespond(u32 num)
{
      u32 i,j,dmanum;

      dmanum=(64+(num<<3))>>2;
      SDDIR=0x8;
      SDCON=0x4;

      for(j=0;j<dmanum;j++)
      {
            i = SDDIR;
      }
}

//read multi sectors function
void readsectors(u16 * p,u32 sectorn,u16 number)
{
      u32 i,j;

      SendCommand(18,sectorn);
      for(i=0;i<number;i++,p+=0x100)
      {
            SDDIR=0x49;
            while ( (SDSTA&0x40) !=0x40);
            SDDIR=0x09;

            SDDIR=0x8;
            SDCON=0x4;
            j = *(volatile u16*)0x8800000;
            DMA3(0x8800000,(u32)p,0x80000100);
            j = *(volatile u16*)0x8800000;
            j = *(volatile u16*)0x8800000;
            j = *(volatile u16*)0x8800000;
            j = *(volatile u16*)0x8800000;

            SDCON=0x8;
      }

      SendCommand(12,sectorn);
      PassRespond(6);
}

//write one sector function
void M3SD_writesector(u16 * p,u32 sectorn)
{
      u16 crc[4];
      u16* check = (u16 *) malloc(512);
      u16* data = (u16 *) malloc(512);
      memcpy(data, p, 512);

      int verify = 0;
      int tries = 0;
      do {
            SendCommand(24,sectorn);
            PassRespond(6);

            SDDIR=0x4;
            SDCON=0x0;

            SD_crc16(data,512,crc);
            SD_data_write(data,crc);

            readsectors(check, sectorn, 1);

            int r;
            verify = 0;
            for (r = 0; r < 256; r++) {
                  if (check[r] != data[r]) {
                        verify++;
                  }
            }

            if (verify > 0) {
                  tries++;
            }

      } while ((verify > 0) && (tries < 16));

      free(data);
      free(check);
}     // */

/*-----------------------------------------------------------------
M3SD_IsInserted
Is a compact flash card inserted?
bool return OUT:  true if a CF card is inserted
-----------------------------------------------------------------*/
bool M3SD_IsInserted (void)
{
      u16 sta;
      bool i;

      M3_SetChipReg(0x400003);
      M3_REG_STS = CF_STS_INSERTED1;
      sta=M3_REG_STS;
      i = ( isM3ins(sta) );

      M3_SetChipReg(0x400002);
      return i;
}

/*-----------------------------------------------------------------
M3SD_ClearStatus
Tries to make the CF card go back to idle mode
bool return OUT:  true if a CF card is idle
-----------------------------------------------------------------*/
bool M3SD_ClearStatus (void)
{
      int i;
      u16 sta;

      M3_SetChipReg(0x400003);
      i = 0;
      M3_REG_STS = CF_STS_INSERTED1;
      while (i < CARD_TIMEOUT)
      {
            sta=M3_REG_STS;
            if(  isM3ins(sta)  )break;
            i++;
      }

      M3_SetChipReg(0x400002);
      if (i >= CARD_TIMEOUT) return false;

      return true;
}

/*-----------------------------------------------------------------
M3SD_ReadSectors
Read 512 byte sector numbered "sector" into "buffer"
u32 sector IN: address of first 512 byte sector on CF card to read
u8 numSecs IN: number of 512 byte sectors to read,
 1 to 256 sectors can be read, 0 = 256
void* buffer OUT: pointer to 512 byte buffer to store data in
bool return OUT: true if successful
-----------------------------------------------------------------*/
bool M3SD_ReadSectors(u32 sector, u8 numSecs, void* buffer)
{
      //read multi sectors function
      M3_SetChipReg(0x400003);
      readsectors((u16*)buffer,sector,numSecs);
      M3_SetChipReg(0x400002);
      return true;      // */
}
/*-----------------------------------------------------------------
M3SD_WriteSectors
Write 512 byte sector numbered "sector" from "buffer"
u32 sector IN: address of 512 byte sector on CF card to read
u8 numSecs IN: number of 512 byte sectors to read,
 1 to 256 sectors can be read, 0 = 256
void* buffer IN: pointer to 512 byte buffer to read data from
bool return OUT: true if successful
-----------------------------------------------------------------*/
bool M3SD_WriteSectors (u32 sector, u8 numSecs, void* buffer)
{
      bool r=true;
      int i;
      M3_SetChipReg(0x400003);
      for(i=0;i<numSecs;i++)
      {
            M3SD_writesector((u16*)((u32)buffer+512*i),sector+i);
      }
      M3_SetChipReg(0x400002);
      return r;
}

/*-----------------------------------------------------------------
M3_Unlock
Returns true if M3 was unlocked, false if failed
Added by MightyMax
-----------------------------------------------------------------*/
bool M3SD_Unlock(void)
{
      vu16 sta;
      bool i;

      // run unlock sequence
      volatile unsigned short tmp;

      M3_SetChipReg(0x400003);
      tmp = *(volatile unsigned short *)0x08000000 ;
      tmp = *(volatile unsigned short *)0x08E00002 ;
      tmp = *(volatile unsigned short *)0x0800000E ;
      tmp = *(volatile unsigned short *)0x08801FFC ;
      tmp = *(volatile unsigned short *)0x0800104A ;
      tmp = *(volatile unsigned short *)0x08800612 ;
      tmp = *(volatile unsigned short *)0x08000000 ;
      tmp = *(volatile unsigned short *)0x08801B66 ;
      tmp = *(volatile unsigned short *)0x08800006 ;
      tmp = *(volatile unsigned short *)0x08000000 ;

      // test that we have register access
      sta=M3_REG_STS;
      sta=M3_REG_STS;
      if(  isM3ins(sta)  )
      {
            i = true;
      }
      else
      {
            i = false;
      }

      M3_SetChipReg(0x400002);
      return i;
}

bool M3SD_Shutdown(void)
{
      return M3SD_ClearStatus() ;
}

bool M3SD_StartUp(void)
{
      vu16* waitCr = (vu16*)0x4000204;

      *waitCr |= 0x6000;
//    *(vu16*)0x4000204=0x6000;
      // Try unlocking 3 times, because occationally it fails to detect the reader.
      return M3SD_Unlock() | M3SD_Unlock() | M3SD_Unlock();
}

IO_INTERFACE io_m3sd =
{
      0x4453334D, // 'M3SD'
      FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE,
      (FN_MEDIUM_STARTUP)&M3SD_StartUp,
      (FN_MEDIUM_ISINSERTED)&M3SD_IsInserted,
      (FN_MEDIUM_READSECTORS)&M3SD_ReadSectors,
      (FN_MEDIUM_WRITESECTORS)&M3SD_WriteSectors,
      (FN_MEDIUM_CLEARSTATUS)&M3SD_ClearStatus,
      (FN_MEDIUM_SHUTDOWN)&M3SD_Shutdown
};

LPIO_INTERFACE M3SD_GetInterface(void)
{
      return &io_m3sd ;
}

#endif

Generated by  Doxygen 1.6.0   Back to index