/**************************************************************************** *-Copyright (c) 2004 Digital Stream Technologies Inc. All Rights Reserved. * * Module: dstdddev.c * Author: Jun-ku Park, hwatk@dstreamtech.com * Description: DST HAL [Device] Platform/Project Specific Source * * notes: hwatk20040609 * * hwatk/20041116, DHL_DEV_NFLASHSetMode() ÇÔ¼ö Ãß°¡. * * TO DO LIST * ***************************************************************************/ #include "dsthalcommon.h" #include "dsthaldev.h" #include "dstdddev.h" #include #include #include #include #include #include #include #include #include #include #include #ifndef USE_CYGWIN #include #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 00)) # include #else # include #endif #include #endif #include #ifdef DMALLOC #include #endif /****************************************************************************** * Global variable declaration ******************************************************************************/ int gddDevDbgLvl = 2; /****************************************************************************** * Imported variable declaration ******************************************************************************/ /****************************************************************************** * Imported function declaration ******************************************************************************/ /****************************************************************************** * Local definitions ******************************************************************************/ /****************************************************************************** * Local typedefs ******************************************************************************/ /****************************************************************************** * Local variables declaration ******************************************************************************/ static int NFLASH_WRITE_SIZE = NFLASH_WRITE_SIZE_NORMAL_NOR; static int NFLASH_WRITE_ALIGN = NFLASH_WRITE_ALIGN_NORMAL_NOR; static int NFLASH_ERASE_ALIGN = NFLASH_ERASE_ALIGN_NORMAL_NOR; /****************************************************************************** * Local function prototypes ******************************************************************************/ /**************************************************************************** NAND Flash DST Device Driver DD_DEV_NFLASHInit - To be done for DD_DEV_NFLASHInit . Initialize the bus for NFLASH. . Setup reserved area for NFLASH. DD_DEV_NFLASHStart - DO NOTHING DD_DEV_NFLASHStop - DO NOTHING DD_DEV_NFLASHClose - DO NOTHING DD_DEV_NFLASHRead - Read data from NAND Flash. DD_DEV_NFLASHWrite - Write data to NAND Flash. DD_DEV_NFLASHErase - ÇöÀç¿¡´Â Erase¸¦ ¼±Åÿµ¿ªÀ¸·Î ¼öÇàÇϰí ÀÖÀ¸³ª, ¸¸¾à Sector (¶Ç´Â Erase Block) ´ÜÀ§·Î Erase¸¦ ¼öÇàÇØ¾ß ÇÑ´Ù¸é, À̸¦ °í·ÁÇÏ¿© EraseµÇ¾î¾ß ÇÑ´Ù. ***************************************************************************/ static int get_freemem(DS_U32 len) { int retSize; #ifndef USE_CYGWIN struct sysinfo info; if ( len == 0 ) { sysinfo(&info); } else { info.freeram = len; } if ( 64*1024 <= info.freeram ) retSize = 64*1024; else if ( 32*1024 <= info.freeram) retSize = 32*1024; else if ( 16*1024 <= info.freeram ) retSize = 16*1024; else if ( 8*1024 <= info.freeram ) retSize = 8*1024; else if ( 4*1024 <= info.freeram ) retSize = 4*1024; else if ( 2*1024 <= info.freeram ) retSize = 2*1024; else retSize = -1; // printf("retSize = 0x%x, info.freeram = 0x%x, freehigh = 0x%x\n", retSize, info.freeram, info.freehigh ); #else retSize = 64*1024; #endif return retSize; } static int NFlashInit(NFLASHID Id, DS_U32 size) { int fd; off_t pos; #if defined(USE_NFLASH_FILE) DS_U8 buf[256]; int i, retval; FILE *fp; //fd = open(NANDFLASH_FILE, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR|S_IXUSR); fp = fopen(NANDFLASH_FILE, "r+b"); if ( !fp ) { fp = fopen(NANDFLASH_FILE, "w+b"); if ( !fp ) return -1; } fd = fileno(fp); if ( fd < 0 ) return fd; pos = lseek( fd, 0, SEEK_SET ); if ( pos != 0L ) return -1; for (i=0; i<256; i++) buf[i] = 0xFF; pos = lseek( fd, 0, SEEK_END ); if ( pos == 0L ) { for (i=0; i<(size/256); i++) { retval = write( fd, &buf[0], 256 ); if ( retval != 256 ) return -1; } } #else DS_U8 mtdname[256]; /* make mtd pathname */ strcpy( (char *)&mtdname[0], ( char *)"/dev/mtd" ); #if 0 mtdname[strlen(mtdname)] = 0; mtdname[strlen(mtdname)-1] = Id; #endif fd = open( (char *)mtdname, O_RDWR, S_IRUSR|S_IWUSR); if ( fd < 0 ) { DHL_DbgPrintf( 0, DHLDBG_DEV, "ERROR, LINE=%d\n", __LINE__); return fd; } pos = lseek( fd, 0, SEEK_SET ); if ( pos != 0L ) { DHL_DbgPrintf( 0, DHLDBG_DEV, "ERROR, LINE=%d\n", __LINE__); return -1; } #endif return fd; } static int NFlashRead(int NFlashHandle, DS_U8 *pBuffer, DS_U32 offset, DS_U32 len) { int RetVal = len; int totalLen=0, remainLen, readSize; off_t pos; /* Argument Checking */ if ( NFlashHandle < 0 ) { DHL_DbgPrintf(1,DHLDBG_DEV,"Invalid Handle!\n"); return -1; } /* Set Position */ pos = lseek( NFlashHandle, offset, SEEK_SET ); if ( pos != offset ) { DHL_DbgPrintf(1,DHLDBG_DEV,"lseek()\n"); return -1; } /* Read from file */ readSize = get_freemem(0); if ( readSize < 0 ) { DHL_DbgPrintf(0,DHLDBG_DEV," Out of Memory\n"); return -1; } if ( readSize >= len ) { RetVal = read( NFlashHandle, pBuffer, len ); totalLen = RetVal; if ( RetVal <= 0 ) { perror("read from nand flash"); DHL_DbgPrintf(1,DHLDBG_DEV,"read()\n"); return -1; } } else { remainLen = len; totalLen = 0; do { if ( remainLen < readSize ) { RetVal = read( NFlashHandle, &pBuffer[totalLen], remainLen ); } else { RetVal = read( NFlashHandle, &pBuffer[totalLen], readSize ); } if ( RetVal <= 0 ) { if ( errno == ENOMEM ) { readSize = get_freemem( readSize - 1 ); if ( readSize < 0 ) { DHL_DbgPrintf(0,DHLDBG_DEV," Out of Memory\n"); return -1; } } else { perror("read from nand flash"); get_freemem(0); return -1; } } else { totalLen += RetVal; remainLen -= RetVal; } } while ( totalLen < len ); } return totalLen; } #if (!defined(USE_CYGWIN) && !defined(USE_NFLASH_FILE)) static struct mtd_info_user mtd; #endif static DS_U8 writeBuffer[64*1024]; static int NFlashWrite(int NFlashHandle, DS_U8 *pBuffer, DS_U32 offset, DS_U32 len) { int retVal = len; int totalLen, remainLen; off_t pos; /* Argument Checking */ if ( NFlashHandle < 0 ) return -1; /* Set Position */ pos = lseek( NFlashHandle, offset, SEEK_SET ); if ( pos != offset ) { DHL_DbgPrintf(1,DHLDBG_DEV,"lseek()\n"); return -1; } remainLen = len; totalLen = 0; do { /* * ½á ³Ö¾î¾ß ÇÒ ¹ÙÀÌÆ®°¡ NFLASH_WRITE_SIZEÀÌÇÏÀΰ¡? */ if ( remainLen < NFLASH_WRITE_SIZE ) { /* ÀÌÇÏÀ̸é, ¹öÆÛ¸¦ »ý¼ºÇÏ¿© NFLASH_WRITE_SIZE Writing */ memset( &writeBuffer[0], 0xFF, NFLASH_WRITE_SIZE ); memcpy( &writeBuffer[0], &pBuffer[totalLen], remainLen ); retVal = write( NFlashHandle, &writeBuffer[0], NFLASH_WRITE_SIZE ); totalLen += remainLen; remainLen = 0; } else { /* ÀÌ»óÀ̸é, ´Ü¼øÈ÷ NFLASH_WRITE_SIZE Writing */ retVal = write( NFlashHandle, &pBuffer[totalLen], NFLASH_WRITE_SIZE ); totalLen += NFLASH_WRITE_SIZE; remainLen -= NFLASH_WRITE_SIZE; } if ( retVal <= 0 ) { perror("write()"); DHL_DbgPrintf(1,DHLDBG_DEV," offset=0x%lx, RetVal = %d, TotalLen = 0x%x\n", pos, retVal, totalLen); return -1; } } while ( totalLen < len ); return totalLen; } #if defined(USE_NFLASH_FILE) static DS_U8 erasebuffer[256]; #endif char ebuf[64*1024] = {0}; // hwatk/070628, moved from local variable. (Display flickering problem on flash erase.) static int NFlashErase(int NFlashHandle, DS_U32 offset, DS_U32 len) { #if defined(USE_NFLASH_FILE) int RetVal = len, RemainLen, EraseLen; off_t pos; int i; #else int i; int RemainLen = 0; int EraseLen =0; struct erase_info_user erase; #endif /* Argument Checking */ if ( NFlashHandle < 0 ) return -1; #if defined(USE_NFLASH_FILE) /* Set Position */ pos = lseek( NFlashHandle, offset, SEEK_SET ); if ( pos != offset ) { DHL_DbgPrintf(1,DHLDBG_DEV,"lseek()\n"); return -1; } for (i=0; i<256; i++) erasebuffer[i] = 0xFF; RemainLen = len; while ( RemainLen ) { if ( len > 256 ) EraseLen = 256; else EraseLen = len; /* Read from file */ RetVal = write( NFlashHandle, &erasebuffer[0], EraseLen ); if ( RetVal == 0 ) { DHL_DbgPrintf(1,DHLDBG_DEV,"write()\n"); return -1; } RemainLen -= EraseLen; } return (len - RemainLen); #else /* set space. */ if(mtd.type == 0x03){ erase.start = offset; erase.length = len; if ( ioctl(NFlashHandle, MEMERASE, &erase) < 0 ) return -1; return len; }else{ /* set space. */ EraseLen = 0x10000; RemainLen = len; erase.start = offset; erase.length = EraseLen; while ( RemainLen ) { /* Read from file */ // RetVal = write( NFlashHandle, &erasebuffer[0], EraseLen ); #if 1 if ( ioctl(NFlashHandle, MEMUNLOCK, &erase) < 0 ) { printf("|%s:%d| ERROR. offset=0x%08lX, len=0x%08lX\n", __FUNCTION__, __LINE__, (unsigned long int)offset, (unsigned long int)len); perror("ioctl()\n"); return -1; } #endif if ( ioctl(NFlashHandle, MEMERASE, &erase) < 0 ) { printf("|%s:%d| ERROR. offset=0x%08lX, len=0x%08lX\n", __FUNCTION__, __LINE__, (unsigned long int)offset, (unsigned long int)len); return -1; } RemainLen -= EraseLen; if(RemainLen > 0){ erase.start = offset + EraseLen; erase.length = EraseLen; }else{ RemainLen = 0; break; } } // static int NFlashWrite(int NFlashHandle, DS_U8 *pBuffer, DS_U32 offset, DS_U32 len) for(i=0;inflash_fd,MEMGETINFO,&mtd); if (err) { DHL_DbgPrintf( 0, DHLDBG_DEV, "ERROR: Line=%d\n", __LINE__); return (err); } if(mtd.type == 0x4) { NFLASH_WRITE_SIZE = NFLASH_WRITE_SIZE_NORMAL_NAND; NFLASH_WRITE_ALIGN = NFLASH_WRITE_ALIGN_NORMAL_NAND; NFLASH_ERASE_ALIGN = NFLASH_ERASE_ALIGN_NORMAL_NAND; } else if(mtd.type == 0x3) { NFLASH_WRITE_SIZE = NFLASH_WRITE_SIZE_NORMAL_NOR; NFLASH_WRITE_ALIGN = NFLASH_WRITE_ALIGN_NORMAL_NOR; NFLASH_ERASE_ALIGN = NFLASH_ERASE_ALIGN_NORMAL_NOR; } sz = mtd.size; off = 0; end = sz; #else sz = 0x100000; off = 0; end = sz; #endif *Size = sz; *Start = off; *End = end; DHL_DbgPrintf( 0, DHLDBG_DEV, "Flash%d: Start = 0x%08lX, End = 0x%08lX, Size = 0x%08lX\n", pNFLASH->NFlashId-1, off, end, sz); return 0; } static int nflash_fd; DHL_RESULT DD_DEV_NFLASHInit( P_DST_DEV_NFLASH pNFLASH, DS_U32 Size, DS_U32 Start, DS_U32 End ) { DHL_RESULT dhlResult = DHL_OK; DS_U32 offset, end, sz; if ( NFLASH_WRITE_SIZE == 0 ) NFLASH_WRITE_SIZE = NFLASH_WRITE_SIZE_NORMAL_NOR; if ( NFLASH_WRITE_ALIGN == 0 ) NFLASH_WRITE_ALIGN = NFLASH_WRITE_ALIGN_NORMAL_NOR; if ( NFLASH_ERASE_ALIGN == 0 ) NFLASH_ERASE_ALIGN = NFLASH_ERASE_ALIGN_NORMAL_NOR; //#if defined(USE_NFLASH_FILE) hwatk, 2004.06.30 pNFLASH->nflash_fd = NFlashInit(pNFLASH->NFlashId, Size); if ( pNFLASH->nflash_fd < 0 ) return DHL_FAIL; nflash_fd = pNFLASH->nflash_fd; //#endif if ( Size == 0 ) { NFlashInfo( pNFLASH, &sz, &offset, &end ); pNFLASH->uSize = sz; pNFLASH->uAvlStart = offset; pNFLASH->uAvlEnd = end; } else { NFlashInfo( pNFLASH, &sz, &offset, &end ); pNFLASH->uSize = Size; pNFLASH->uAvlStart = Start; pNFLASH->uAvlEnd = End; } return dhlResult; } DHL_RESULT DD_DEV_NFLASHStart( P_DST_DEV_NFLASH pNFLASH ) { DHL_RESULT dhlResult = DHL_OK; /* DO NOTHING */ return dhlResult; } DHL_RESULT DD_DEV_NFLASHStop( P_DST_DEV_NFLASH pNFLASH ) { DHL_RESULT dhlResult = DHL_OK; /* DO NOTHING */ return dhlResult; } DHL_RESULT DD_DEV_NFLASHClose(P_DST_DEV_NFLASH pNFLASH ) { DHL_RESULT dhlResult = DHL_OK; /* DO NOTHING */ return dhlResult; } int DD_DEV_NFLASHRead(P_DST_DEV_NFLASH pNFLASH, DS_U32 Address, DS_U8 *pBuffer, DS_U32 Len ) { int RetVal = Len; RetVal = NFlashRead( pNFLASH->nflash_fd, pBuffer, Address, Len ); return RetVal; } int DD_DEV_NFLASHWrite(P_DST_DEV_NFLASH pNFLASH, DS_U32 Address, DS_U8 *pBuffer, DS_U32 Len ) { int RetVal = Len; // if ( (Len & NFLASH_WRITE_ALIGN) || (Address & NFLASH_WRITE_ALIGN) ) { if ( (Address & NFLASH_WRITE_ALIGN) ) { return -1; } RetVal = NFlashWrite( pNFLASH->nflash_fd, pBuffer, Address, Len ); return RetVal; } DHL_RESULT DD_DEV_NFLASHErase( P_DST_DEV_NFLASH pNFLASH, DS_U32 Address, DS_U32 Len ) { DHL_RESULT dhlResult = DHL_OK; int RetVal = Len; if ( Len & NFLASH_ERASE_ALIGN ) { return DHL_DEV_FAIL_NOTALIGN; } RetVal = NFlashErase( pNFLASH->nflash_fd, Address, Len ); if ( RetVal <= 0 ) dhlResult = DHL_FAIL; return dhlResult; } /**************************************************************************** Serial Flash DST Device Driver DD_DEV_SFLASHInit - To be done for DD_DEV_SFLASHInit . Initialize the bus for SFLASH. . Setup reserved area for SFLASH. DD_DEV_SFLASHStart - DO NOTHING DD_DEV_SFLASHStop - DO NOTHING DD_DEV_SFLASHClose - DO NOTHING DD_DEV_SFLASHRead - Read data from NAND Flash. DD_DEV_SFLASHWrite - Write data to NAND Flash. DD_DEV_SFLASHErase - ÇöÀç¿¡´Â Erase¸¦ ¼±Åÿµ¿ªÀ¸·Î ¼öÇàÇϰí ÀÖÀ¸³ª, ¸¸¾à Sector (¶Ç´Â Erase Block) ´ÜÀ§·Î Erase¸¦ ¼öÇàÇØ¾ß ÇÑ´Ù¸é, À̸¦ °í·ÁÇÏ¿© EraseµÇ¾î¾ß ÇÑ´Ù. ***************************************************************************/ #if defined(USE_SFLASH_FILE) static int SFLASHInit(DS_U32 size) { int fd; off_t pos; DS_U8 buf[256]; int i, retval; fd = open(SERIALFLASH_FILE, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR|S_IXUSR); if ( fd < 0 ) return fd; pos = lseek( fd, 0, SEEK_SET ); if ( pos != 0L ) return -1; for (i=0; i<256; i++) buf[i] = 0xFF; pos = lseek( fd, 0, SEEK_END ); if ( pos == 0L ) { for (i=0; i<(size/256); i++) { retval = write( fd, &buf[0], 256 ); if ( retval != 256 ) return -1; } } return fd; } static int SFLASHRead(int SFLASHHandle, DS_U8 *pBuffer, DS_U32 offset, DS_U32 len) { int RetVal = len; off_t pos; /* Argument Checking */ if ( SFLASHHandle < 0 ) return -1; /* Set Position */ pos = lseek( SFLASHHandle, offset, SEEK_SET ); if ( pos != offset ) { DHL_DbgPrintf(1,DHLDBG_DEV,"lseek()\n"); return -1; } /* Read from file */ RetVal = read( SFLASHHandle, pBuffer, len ); if ( RetVal == 0 ) { DHL_DbgPrintf(1,DHLDBG_DEV,"read()\n"); return -1; } return RetVal; } static int SFLASHWrite(int SFLASHHandle, DS_U8 *pBuffer, DS_U32 offset, DS_U32 len) { int RetVal = len; off_t pos; /* Argument Checking */ if ( SFLASHHandle < 0 ) return -1; /* Set Position */ pos = lseek( SFLASHHandle, offset, SEEK_SET ); if ( pos != offset ) { DHL_DbgPrintf(1,DHLDBG_DEV,"lseek()\n"); return -1; } /* Write to file */ RetVal = write( SFLASHHandle, pBuffer, len ); if ( RetVal == 0 ) { DHL_DbgPrintf(1,DHLDBG_DEV,"write()\n"); return -1; } return RetVal; } static DS_U8 erasebuffer[256]; static int SFLASHErase(int SFLASHHandle, DS_U32 offset, DS_U32 len) { int RetVal = len, RemainLen, EraseLen; off_t pos; int i; /* Argument Checking */ if ( SFLASHHandle < 0 ) return -1; /* Set Position */ pos = lseek( SFLASHHandle, offset, SEEK_SET ); if ( pos != offset ) { DHL_DbgPrintf(1,DHLDBG_DEV,"lseek()\n"); return -1; } for (i=0; i<256; i++) erasebuffer[i] = 0xFF; RemainLen = len; while ( RemainLen ) { if ( len > 256 ) EraseLen = 256; else EraseLen = len; /* Read from file */ RetVal = write( SFLASHHandle, &erasebuffer[0], EraseLen ); if ( RetVal == 0 ) { DHL_DbgPrintf(1,DHLDBG_DEV,"write()\n"); return -1; } RemainLen -= EraseLen; } return (len - RemainLen); } #endif DHL_RESULT DD_DEV_SFLASHInit( P_DST_DEV_SFLASH pSFLASH, DS_U32 Size, DS_U32 Start, DS_U32 End ) { DHL_RESULT dhlResult = DHL_OK; pSFLASH->uSize = Size; pSFLASH->uAvlStart = Start; pSFLASH->uAvlEnd = End; #if defined(USE_SFLASH_FILE) pSFLASH->sflash_fd = SFLASHInit(Size); if ( pSFLASH->sflash_fd < 0 ) return DHL_FAIL; #endif return dhlResult; } DHL_RESULT DD_DEV_SFLASHStart( P_DST_DEV_SFLASH pSFLASH ) { DHL_RESULT dhlResult = DHL_OK; /* DO NOTHING */ return dhlResult; } DHL_RESULT DD_DEV_SFLASHStop( P_DST_DEV_SFLASH pSFLASH ) { DHL_RESULT dhlResult = DHL_OK; /* DO NOTHING */ return dhlResult; } DHL_RESULT DD_DEV_SFLASHClose(P_DST_DEV_SFLASH pSFLASH ) { DHL_RESULT dhlResult = DHL_OK; /* DO NOTHING */ return dhlResult; } int DD_DEV_SFLASHRead(P_DST_DEV_SFLASH pSFLASH, DS_U32 Address, DS_U8 *pBuffer, DS_U32 Len ) { int RetVal = Len; #if defined(USE_SFLASH_FILE) RetVal = SFLASHRead( pSFLASH->sflash_fd, pBuffer, Address, Len ); #endif return RetVal; } int DD_DEV_SFLASHWrite(P_DST_DEV_SFLASH pSFLASH, DS_U32 Address, DS_U8 *pBuffer, DS_U32 Len ) { int RetVal = Len; #if defined(USE_SFLASH_FILE) RetVal = SFLASHWrite( pSFLASH->sflash_fd, pBuffer, Address, Len ); #endif return RetVal; } DHL_RESULT DD_DEV_SFLASHErase( P_DST_DEV_SFLASH pSFLASH, DS_U32 Address, DS_U32 Len ) { DHL_RESULT dhlResult = DHL_OK; int RetVal = Len; #if defined(USE_SFLASH_FILE) RetVal = SFLASHErase( pSFLASH->sflash_fd, Address, Len ); if ( RetVal <= 0 ) dhlResult = DHL_FAIL; #endif return dhlResult; } #if 0 ___CAS_Functions___() #endif #define FRM_CMD_CLASS 0x90 /* Initial Settings */ #define FRM_INS_CMD_INT 0x30 /* Basic Processing */ #define FRM_INS_CMD_ECM 0x34 #define FRM_INS_CMD_EMM 0x36 /* Display Card ID */ #define FRM_INS_CMD_IDI 0x32 #define FRM_INS_CMD_CLA 0x32 #define SCI_MAX 0x3F DHL_RESULT DD_DEV_InitSmartCard(void) { DHL_RESULT dhlResult = DHL_OK; return dhlResult; } DHL_RESULT DD_DEV_GetCARDStatus(DHL_DEV_CARD_STATUS *Status) { DHL_RESULT dhlResult = DHL_OK; *Status = DHL_DEV_CARD_ACTIVATED; return dhlResult; } DS_S32 DD_DEV_WriteCARDBlock( DS_U8 *data ) { return 0; } DS_S32 DD_DEV_ReadCARDBlock( DS_U8 PCB, DS_U8 *data ) { return 0; } DHL_RESULT DD_CA_InitMULTI2(DS_U8 *SystemKey, DS_U8 *CBC) { DHL_RESULT dhlResult = DHL_OK; return dhlResult; } DHL_RESULT DD_CA_ResetMULTI2(void) { DHL_RESULT dhlResult = DHL_OK; return dhlResult; } DHL_RESULT DD_CA_SetMULTI2Key(DS_U8 Slot, DS_U8 *EvenData, DS_U8 *OddData) { DHL_RESULT dhlResult = DHL_OK; return dhlResult; } DHL_RESULT DD_CA_SetMULTI2Pid(DS_U16 Pid, DS_U32 *slot, DS_BOOL enable) { DHL_RESULT dhlResult = DHL_OK; return dhlResult; } #if 0 ___DEBUG_Functions___() #endif int f_read(DS_U32 offset, DS_U32 len) { DS_U8 buf[128*1024] = {0}; int retVal = 0; off_t pos; int i; for(i=0;i