diff -r b7e488c49d0d -r 117faf51deac omap3530/beagle_drivers/medwb/medwb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/beagle_drivers/medwb/medwb.cpp Wed Mar 03 13:10:32 2010 +0000 @@ -0,0 +1,1149 @@ +/* Cypress West Bridge API source file +## =========================== +## +## Copyright Cypress Semiconductor Corporation, 2006-2009, +## All Rights Reserved +## UNPUBLISHED, LICENSED SOFTWARE. +## +## CONFIDENTIAL AND PROPRIETARY INFORMATION +## WHICH IS THE PROPERTY OF CYPRESS. +## +## Use of this file is governed +## by the license agreement included in the file +## +## /license/license.txt +## +## where is the Cypress software +## installation root directory path. +## +## =========================== +*/ + +#include "locmedia.h" +#include "platform.h" +//#include "variantmediadef.h" +#include + +//#define REGIST_MEDIA_USE_MMC +#define _MEDWB_DEBUG_1_ +//#define _MEDWB_DEBUG_2_ + +//#define INTERVAL_FOR_WB 15 // 15 -- OK +#define WB_BUFFER_SIZE 2*(65536 + 512) +#define WB_RETRY_COUNT 2 + +//const TInt KStackNumber = 0; +const TInt KDiskSectorSize=512; +const TInt KDiskSectorShift=9; +//const TInt KIdleCurrentInMilliAmps = 1; + +const TInt KMBRFirstPartitionEntry=0x1BE; + +TUint8 ptrWBBuffer[WB_BUFFER_SIZE]; + + +template +inline T UMin(T aLeft,T aRight) + {return(aLeft KErrNotSupported\n"); + #endif + return KErrNotSupported; + } + if (aDeviceType!=MEDIA_DEVICE_MMC) + { + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf("Validate -> Wrong DeviceType\n"); + #endif + return KErrNotSupported; + } + return KErrNone; + } + + +TInt DPhysicalDeviceMediaWB::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /*aInfo*/, const TVersion& aVer) +// +// Create an MMC Card media driver. +// + { + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf("=mmd:crt"); + #endif + if (!Kern::QueryVersionSupported(iVersion,aVer)) + return KErrNotSupported; + + DMediaDriverWB* pD = new DMediaDriverWB(aMediaId); + aChannel=pD; + + TInt r=KErrNoMemory; + if (pD) + r=pD->DoCreate(aMediaId); + + #ifdef REGIST_MEDIA_USE_MMC + if (r==KErrNone) + pD->OpenMediaDriverComplete(KErrNone); + #endif + __KTRACE_OPT(KPBUSDRV, Kern::Printf(" +inline T* KernAlloc(const TUint32 n) + { return static_cast(Kern::Alloc(n * sizeof(T))); } + +// ---- ctor, open, close, dtor ---- + +#pragma warning( disable : 4355 ) // this used in initializer list +DMediaDriverWB::DMediaDriverWB(TInt aMediaId) + :DMediaDriver(aMediaId), + iMediaId(iPrimaryMedia->iNextMediaId) + { + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("=mmd:wb"); + // NB aMedia Id = the media ID of the primary media, iMediaId = the media ID of this media + Kern::Printf("DMediaDriverWB(), iMediaId %d, aMediaId %d\n", iMediaId, aMediaId); + #endif + } + +#pragma warning( default : 4355 ) +TInt DMediaDriverWB::DoCreate(TInt /*aMediaId*/) + { + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf(">mmd:opn"); + #endif + iUnitSize = CyAsSymbianStorageDriver::GetUnitSize(); + iBlockSize = CyAsSymbianStorageDriver::GetBlockSize(); + if( iBlockSize == 0 ) + iBlockSize = 1; + + read_pos = 0x7FFFFFFF; + read_size = 0; + + // get card characteristics + SetTotalSizeInBytes(CyAsSymbianStorageDriver::GetMediaSize()); + + // get buffer memory from EPBUS + ptrReadBuf = ptrWBBuffer; + ptrWriteBuf = &ptrWBBuffer[65536+512]; + + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf("KMaxTInt) + return KErrGeneral; + TInt p=(TInt)pos; + TInt l=(TInt)length; + + if (p+l>CyAsSymbianStorageDriver::GetMediaSize()) + return KErrGeneral; + + TInt pos_block = p / iBlockSize; + TInt pos_offset = p % iBlockSize; + TInt size_block = l / iBlockSize; + TInt size_offset = l % iBlockSize; + + TUint buf_offset = 0; + TInt local_pos; + + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("WB::Read> real (%d@%d)", l, p); + Kern::Printf("WB::Read> pos_block - %d", pos_block) ; + Kern::Printf("WB::Read> pos_offset - %d", pos_offset) ; + Kern::Printf("WB::Read> size_block - %d", size_block) ; + Kern::Printf("WB::Read> size_offset - %d", size_offset) ; + #endif + + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + if( pos_block == read_pos ) + { + if( read_size < l ) + { + buf_offset = read_size; + size_block = (l-read_size) / iBlockSize; + size_offset = (l-read_size) % iBlockSize; + + local_pos = pos_block + (read_size /iBlockSize); + } + else + { + TPtrC8 des((ptrReadBuf+pos_offset), l); + + r = iCurrentReq.WriteRemote(&des, 0); + + return r; + } + } + #if 0 + else if( (read_pos + (read_size/iBlockSize)) > pos_block ) + { + TInt adjust_offset; + TInt adjust_size; + adjust_offset = (read_pos - pos_block) * iBlockSize; + adjust_size = read_size - adjust_offset; + + memcpy(ptrReadBuf, &ptrReadBuf[adjust_offset], adjust_size ); + + read_pos = pos_block; + read_size = adjust_size; + + if( read_size < l ) + { + buf_offset = read_size; + size_block = (l-read_size) / iBlockSize; + size_offset = (l-read_size) % iBlockSize; + + local_pos = pos_block + (read_size /iBlockSize); + } + else + { + TPtrC8 des((ptrReadBuf+pos_offset), l); + + r = iCurrentReq.WriteRemote(&des, 0); + + return r; + } + } + #endif + else + local_pos = read_pos = pos_block; + + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("WB::Read> local_pos - %d", local_pos) ; + Kern::Printf("WB::Read> buf_offset - %d", buf_offset) ; + #endif + + + if( size_block ) + { + CyAsSymbianStorageDriver::Read(local_pos, size_block, (void *)(ptrReadBuf+buf_offset)); + local_pos += size_block; + buf_offset += (size_block*iBlockSize); + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + } + + if( pos_offset || size_offset ) + { + CyAsSymbianStorageDriver::Read(local_pos, 1, (void *)(ptrReadBuf+buf_offset) ); + local_pos += size_block; + buf_offset += iBlockSize; + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + } + + read_size = buf_offset; + + TPtrC8 des((ptrReadBuf+pos_offset), l); + + r = iCurrentReq.WriteRemote(&des, 0); + + return r; + } + + +TInt DMediaDriverWB::DoWrite(TLocDrvRequest& iCurrentReq) +// +// set up iReqStart, iReqEnd, and iReqCur, and launch first write. Any subsequent +// writes are launched from the session end DFC. LaunchWrite() handles pre-reading +// any sectors that are only partially modified. +// + { + Int64 pos = iCurrentReq.Pos(); + Int64 length = iCurrentReq.Length(); + TInt r; + if (length<0 || pos<0 || (pos+length)>KMaxTInt) + return KErrGeneral; + TInt p=(TInt)pos; + TInt l=(TInt)length; + + if (p+l>CyAsSymbianStorageDriver::GetMediaSize()) + return KErrGeneral; + + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("WB::Write> (%d@%d)", l, p); + #endif + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + + TInt pos_block = p / iBlockSize; + TInt pos_offset = p % iBlockSize; + TInt size_block = l / iBlockSize; + TInt size_offset = l % iBlockSize; + + TUint buf_offset = 0; + TInt local_pos; + TInt w_block_size = 0; + + local_pos = pos_block; + + if( size_block ) + { + CyAsSymbianStorageDriver::Read(local_pos, size_block, (void *)(ptrWriteBuf+buf_offset)); + local_pos += size_block; + buf_offset += (size_block*iBlockSize); + w_block_size += size_block; + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + } + + if( pos_offset || size_offset ) + { + CyAsSymbianStorageDriver::Read(local_pos, 1, (void *)(ptrWriteBuf+buf_offset) ); + local_pos += size_block; + buf_offset += iBlockSize; + w_block_size ++; + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + } + + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("WB::Write> pos_block - %d", pos_block) ; + Kern::Printf("WB::Write> pos_offset - %d", pos_offset) ; + Kern::Printf("WB::Write> size_block - %d", size_block) ; + Kern::Printf("WB::Write> size_offset - %d", size_offset) ; + #endif + + TPtr8 des((ptrWriteBuf+pos_offset), l); + + if ( (r = iCurrentReq.ReadRemote(&des,0)) !=KErrNone) + { + return r; + } + + + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("WB::Write> local_pos - %d", local_pos) ; + Kern::Printf("WB::Write> w_block_size - %d", w_block_size) ; + #endif + + CyAsSymbianStorageDriver::Write(local_pos, w_block_size, ptrWriteBuf); + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + return r; + } + + +TInt DMediaDriverWB::DoFormat(TLocDrvRequest& iCurrentReq) + { + Int64 pos = iCurrentReq.Pos(); + Int64 length = iCurrentReq.Length(); + TInt r; + if (length<0 || pos<0 || (pos+length)>KMaxTInt) + return KErrGeneral; + TInt p=(TInt)pos; + TInt l=(TInt)length; + + if (p+l>CyAsSymbianStorageDriver::GetMediaSize()) + return KErrGeneral; + + #ifdef _MEDWB_DEBUG_1_ + Kern::Printf("WB::Format> (%d@%d)", l, p); + #endif + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + TInt pos_block = p / iBlockSize; + TInt pos_offset = p % iBlockSize; + TInt size_block = l / iBlockSize; + TInt size_offset = l % iBlockSize; + + TUint buf_offset = 0; + TInt local_pos; + TInt w_block_size = 0; + + local_pos = pos_block; + + if( size_block ) + { + CyAsSymbianStorageDriver::Read(local_pos, size_block, (void *)(ptrWriteBuf+buf_offset)); + local_pos += size_block; + buf_offset += (size_block*iBlockSize); + w_block_size += size_block; + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + } + + if( pos_offset || size_offset ) + { + CyAsSymbianStorageDriver::Read(local_pos, 1, (void *)(ptrWriteBuf+buf_offset) ); + local_pos += size_block; + buf_offset += iBlockSize; + w_block_size ++; + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + } + + memclr(ptrWriteBuf + pos_offset, l); + + CyAsSymbianStorageDriver::Write(local_pos, w_block_size, ptrWriteBuf); + #ifdef INTERVAL_FOR_WB + NKern::Sleep(INTERVAL_FOR_WB); + #endif + return r; + } + + +TInt DMediaDriverWB::PartitionInfo(TPartitionInfo& anInfo) +// +// Read the partition information for the media. If the user supplied a password, +// then unlock the card before trying to read the first sector. +// + { + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf(">mmd:rpi"); + #endif + iPartitionInfo = &anInfo; + + // Assume MBR will be present or is not required + iMbrMissing = EFalse; + + TInt r = DecodePartitionInfo(); + + + if(r == KErrLocked) + { + // If the media is locked, we present a default partition entry to the local + // media subsystem, which will be updated when the media is finally unlocked. + r = CreateDefaultPartition(); + if (r != KErrNone) + return r; + return KErrLocked; + } + + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf("iPartitionCount=0; + TInt defaultPartitionNumber=-1; + TMBRPartitionEntry* pe; + const TUint KMBRFirstPartitionOffsetAligned = KMBRFirstPartitionOffset & ~3; + TInt i; + + CyAsSymbianStorageDriver::Read(0, 1, (void *)ptrReadBuf); + read_pos = 0; + read_size = 512; + // Read of the first sector successful so check for a Master Boot Record + if (*(TUint16*)(&ptrReadBuf[KMBRSignatureOffset])!=0xAA55) + goto mbr_done; + + __ASSERT_COMPILE(KMBRFirstPartitionOffsetAligned + KMBRMaxPrimaryPartitions * sizeof(TMBRPartitionEntry) <= KMBRSignatureOffset); + + memmove(&ptrReadBuf[0], &ptrReadBuf[2], + KMBRFirstPartitionOffsetAligned + KMBRMaxPrimaryPartitions * sizeof(TMBRPartitionEntry)); + + + for (i=0, pe = (TMBRPartitionEntry*)(&ptrReadBuf[KMBRFirstPartitionOffsetAligned]); + pe->iPartitionType != 0 && i < KMBRMaxPrimaryPartitions;i++,pe++) + { + if (pe->IsDefaultBootPartition()) + { + SetPartitionEntry(&iPartitionInfo->iEntry[0],pe->iFirstSector,pe->iNumSectors); + defaultPartitionNumber=i; + partitionCount++; + break; + } + } + + // Now add any other partitions + for (i=0, pe = (TMBRPartitionEntry*)(&ptrReadBuf[KMBRFirstPartitionOffsetAligned]); + pe->iPartitionType != 0 && i < KMBRMaxPrimaryPartitions;i++,pe++) + { + TBool validPartition = ETrue; // assume partition valid + + if (defaultPartitionNumber==i) + { + // Already sorted + } + + // FAT partition ? + else if (pe->IsValidDosPartition() || pe->IsValidFAT32Partition()) + { + SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors); + #ifdef _MEDWB_DEBUG_1_ + Kern::Printf("WB: FAT partition found at sector #%u", pe->iFirstSector); + #endif + partitionCount++; + } + else + { + validPartition = EFalse; + } + + if (validPartition && partitionCount == 1) + iHiddenSectors = pe->iFirstSector; + + } + + // Check the validity of the partition address boundaries + // If there is any + if(partitionCount > 0) + { + const TInt64 deviceSize = CyAsSymbianStorageDriver::GetMediaSize(); + TPartitionEntry& part = iPartitionInfo->iEntry[partitionCount - 1]; + // Check that the card address space boundary is not exceeded by the last partition + // In case of only 1 partition in the media check also it + if(part.iPartitionBaseAddr + part.iPartitionLen > deviceSize) + { + Kern::Printf("WB: MBR partition exceeds card memory space"); + // Adjust the partition length to card address boundary + part.iPartitionLen = (deviceSize - part.iPartitionBaseAddr); + + // Check that the base address contained valid information + if(part.iPartitionLen <= 0) + { + Kern::Printf("WB: Invalid base address"); + // Invalid MBR - assume the boot sector is in the first sector + defaultPartitionNumber =-1; + partitionCount=0; + } + } + // More than one partition. Go through all of them + if (partitionCount > 0) + { + for(i=partitionCount-1; i>0; i--) + { + const TPartitionEntry& curr = iPartitionInfo->iEntry[i]; + TPartitionEntry& prev = iPartitionInfo->iEntry[i-1]; + // Check if partitions overlap + if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen)) + { + Kern::Printf("WB: Overlapping partitions"); + // Adjust the partition length to not overlap the next partition + prev.iPartitionLen = (curr.iPartitionBaseAddr - prev.iPartitionBaseAddr); + + // Check that the base address contained valid information + if(prev.iPartitionLen <= 0) + { + Kern::Printf("WB: Invalid base address"); + // Invalid MBR - assume the boot sector is in the first sector + defaultPartitionNumber=(-1); + partitionCount=0; + } + } + } + } + } + +mbr_done: + if (defaultPartitionNumber==(-1) && partitionCount==0) + { + Kern::Printf("WB:PartitionInfo no MBR"); + { + // Assume it has no MBR, and the Boot Sector is in the 1st sector + SetPartitionEntry(&iPartitionInfo->iEntry[0],0,I64LOW(CyAsSymbianStorageDriver::GetMediaSize()>>KDiskSectorShift)); + iHiddenSectors=0; + } + partitionCount=1; + } + + iPartitionInfo->iPartitionCount=partitionCount; + iPartitionInfo->iMediaSizeInBytes=TotalSizeInBytes(); + #ifdef _MEDWB_DEBUG_1_ + + Kern::Printf("iPartitionCount); + Kern::Printf(" Partition1 (B:%xH L:%xH)",I64LOW(iPartitionInfo->iEntry[0].iPartitionBaseAddr),I64LOW(iPartitionInfo->iEntry[0].iPartitionLen)); + Kern::Printf(" Partition2 (B:%xH L:%xH)",I64LOW(iPartitionInfo->iEntry[1].iPartitionBaseAddr),I64LOW(iPartitionInfo->iEntry[1].iPartitionLen)); + Kern::Printf(" Partition3 (B:%xH L:%xH)",I64LOW(iPartitionInfo->iEntry[2].iPartitionBaseAddr),I64LOW(iPartitionInfo->iEntry[2].iPartitionLen)); + Kern::Printf(" Partition4 (B:%xH L:%xH)",I64LOW(iPartitionInfo->iEntry[3].iPartitionBaseAddr),I64LOW(iPartitionInfo->iEntry[3].iPartitionLen)); + + + Kern::Printf(" iMediaSizeInBytes (%d)",iPartitionInfo->iMediaSizeInBytes); + Kern::Printf(" iHiddenSectors (%d)",iHiddenSectors); + #endif + + #ifdef _MEDWB_DEBUG_3_ + + TMBRPartitionEntry cPe; + if(GetDefaultPartitionInfo(cPe) == KErrNone) + { + pe = (TMBRPartitionEntry*)(&ptrReadBuf[0]); + + Kern::Printf("-------------------------------------------"); + Kern::Printf("-- Partition Entry Validation/Comparison --"); + Kern::Printf("-------------------------------------------"); + Kern::Printf("-- iX86BootIndicator [%02x:%02x] %c -", pe->iX86BootIndicator, cPe.iX86BootIndicator, pe->iX86BootIndicator == cPe.iX86BootIndicator ? ' ' : 'X'); + Kern::Printf("-- iStartHead [%02x:%02x] %c -", pe->iStartHead, cPe.iStartHead, pe->iStartHead == cPe.iStartHead ? ' ' : 'X'); + Kern::Printf("-- iStartSector [%02x:%02x] %c -", pe->iStartSector, cPe.iStartSector, pe->iStartSector == cPe.iStartSector ? ' ' : 'X'); + Kern::Printf("-- iStartCylinder [%02x:%02x] %c -", pe->iStartCylinder, cPe.iStartCylinder, pe->iStartCylinder == cPe.iStartCylinder ? ' ' : 'X'); + Kern::Printf("-- iPartitionType [%02x:%02x] %c -", pe->iPartitionType, cPe.iPartitionType, pe->iPartitionType == cPe.iPartitionType ? ' ' : 'X'); + Kern::Printf("-- iEndHead [%02x:%02x] %c -", pe->iEndHead, cPe.iEndHead, pe->iEndHead == cPe.iEndHead ? ' ' : 'X'); + Kern::Printf("-- iEndSector [%02x:%02x] %c -", pe->iEndSector, cPe.iEndSector, pe->iEndSector == cPe.iEndSector ? ' ' : 'X'); + Kern::Printf("-- iEndCylinder [%02x:%02x] %c -", pe->iEndCylinder, cPe.iEndCylinder, pe->iEndCylinder == cPe.iEndCylinder ? ' ' : 'X'); + Kern::Printf("-- iFirstSector [%08x:%08x] %c -", pe->iFirstSector, cPe.iFirstSector, pe->iFirstSector == cPe.iFirstSector ? ' ' : 'X'); + Kern::Printf("-- iNumSectors [%08x:%08x] %c -", pe->iNumSectors, cPe.iNumSectors, pe->iNumSectors == cPe.iNumSectors ? ' ' : 'X'); + Kern::Printf("-------------------------------------------"); + } + #endif + + return(KErrNone); + } + + +TInt DMediaDriverWB::WritePartitionInfo() +/** + Write the default partition table to freshly formatted media + @return Standard Symbian OS Error Code + */ + { + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf(">mmd:wpi"); + #endif + TMBRPartitionEntry partitionEntry; + TInt err = GetDefaultPartitionInfo(partitionEntry); + if(err == KErrNone) + { + TUint8 *iPartitionBuf; + + iPartitionBuf = new TUint8[KDiskSectorSize]; + + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("mmd:MBR/Partition Table"); + Kern::Printf(" Boot ID : %02xh", partitionEntry.iX86BootIndicator); + Kern::Printf(" Start Head : %02xh", partitionEntry.iStartHead); + Kern::Printf(" Start Sector : %02xh", partitionEntry.iStartSector); + Kern::Printf(" Start Cyclinder : %02xh", partitionEntry.iStartCylinder); + Kern::Printf(" System ID : %02xh", partitionEntry.iPartitionType); + Kern::Printf(" End Head : %02xh", partitionEntry.iEndHead); + Kern::Printf(" End Sector : %02xh", partitionEntry.iEndSector); + Kern::Printf(" End Cyclinder : %02xh", partitionEntry.iEndCylinder); + Kern::Printf(" Relative Sector : %08xh", partitionEntry.iFirstSector); + Kern::Printf(" Number of Sectors: %08xh", partitionEntry.iNumSectors); + #endif + // + // Clear all other partition entries and align the partition info into the minor buffer for writing... + // + memclr(iPartitionBuf, KDiskSectorSize); + memcpy(&iPartitionBuf[KMBRFirstPartitionEntry], &partitionEntry, sizeof(TMBRPartitionEntry)); + + *(TUint16*)(&iPartitionBuf[KMBRSignatureOffset]) = 0xAA55; + + err = CyAsSymbianStorageDriver::Write(0, 1, iPartitionBuf); + + // + // Write the partition table and engage the read to validate and complete the mount process + // + delete iPartitionBuf; + iMbrMissing = EFalse; + } + + #ifdef _MEDWB_DEBUG_3_ + __KTRACE_OPT(KPBUSDRV, Kern::Printf("iEntry[0], defPartition.iFirstSector, defPartition.iNumSectors); + iHiddenSectors = defPartition.iFirstSector; + iPartitionInfo->iPartitionCount = 1; + iPartitionInfo->iMediaSizeInBytes = TotalSizeInBytes(); + } + return r; + } + +TInt DMediaDriverWB::GetDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry) +/** + Calculates the default patition information for an specific card. + @param aPartitionEntry The TMBRPartitionEntry to be filled in with the format parameters + @return Standard Symbian OS Error Code + */ + { + memclr(&aPartitionEntry, sizeof(TMBRPartitionEntry)); + + const TUint32 KTotalSectors = I64LOW(CyAsSymbianStorageDriver::GetMediaSize() >> KDiskSectorShift); + + aPartitionEntry.iFirstSector = (CyAsSymbianStorageDriver::GetEraseBlockSize()>> KDiskSectorShift); + aPartitionEntry.iNumSectors = KTotalSectors - aPartitionEntry.iFirstSector; + aPartitionEntry.iX86BootIndicator = 0x00; + + if(aPartitionEntry.iNumSectors < 32680) + { + aPartitionEntry.iPartitionType = KPartitionTypeFAT12; + } + else if(aPartitionEntry.iNumSectors < 65536) + { + aPartitionEntry.iPartitionType = KPartitionTypeFAT16small; + } + else if (aPartitionEntry.iNumSectors < 1048576) + { + aPartitionEntry.iPartitionType = KPartitionTypeFAT16; + } + else + { + aPartitionEntry.iPartitionType = KPartitionTypeWin95FAT32; + } + + return(KErrNone); + } + +void DMediaDriverWB::SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors) +// +// auxiliary static function to record partition information in TPartitionEntry object +// + { + aEntry->iPartitionBaseAddr=aFirstSector; + aEntry->iPartitionBaseAddr<<=KDiskSectorShift; + aEntry->iPartitionLen=aNumSectors; + aEntry->iPartitionLen<<=KDiskSectorShift; + aEntry->iPartitionType=KPartitionTypeFAT12; + } + +// ---- device status, callback DFC ---- + +TInt DMediaDriverWB::CheckDevice(int aReqType) +// +// Check the device before initiating a command +// + { + + __KTRACE_OPT(KPBUSDRV, Kern::Printf(">wb:cd:%d",aReqType)); + + TInt r=KErrNone; +#if 0 + if (!iCard->IsReady()) + r=KErrNotReady; + + // The card must be locked if attempting to unlock during RPI, and + // unlocked at all other times. + else if (aReqType!=EMReqTypeUnlockPswd && iCard->IsLocked()) + r=KErrLocked; + // Don't perform Password setting for WriteProtected cards, + // unable to recover (ForcedErase) if password lost. + else if (aReqType==EMReqTypeChangePswd) + { + if (iCard->MediaType()==EMultiMediaROM) + { + r=KErrAccessDenied; + } + } + else if (iMbrMissing && aReqType==EMReqTypeNormalRd) + r=KErrCorrupt; + + // Don't perform write operations when the mechanical write protect switch is set + else if (aReqType==EMReqTypeNormalWr && iCard->IsWriteProtected()) + r=KErrAccessDenied; + // Don't perform write/format operations on MMC ROM cards + else if (iMediaType==EMultiMediaROM && aReqType == EMReqTypeNormalWr) + r=KErrAccessDenied; +#endif + __KTRACE_OPT(KPBUSDRV, Kern::Printf("WB::Caps "); + #endif + // Fill buffer with current media caps. + aInfo.iType = EMediaHardDisk; + aInfo.iBattery = EBatNotSupported; + aInfo.iDriveAtt = KDriveAttLocal; + aInfo.iMediaAtt = KMediaAttFormattable; + + //if(CyAsSymbianStorageDriver::GetIsLocked()) + // aInfo.iMediaAtt |= KMediaAttLockable; + //if (iCard->HasPassword()) + //aInfo.iMediaAtt |= KMediaAttHasPassword; + + if ( !CyAsSymbianStorageDriver::GetIsWriteable()) + aInfo.iMediaAtt |= KMediaAttWriteProtected; + if (CyAsSymbianStorageDriver::GetIsLocked()) + aInfo.iMediaAtt |= KMediaAttLocked; + + aInfo.iFileSystemId = KDriveFileSysFAT; + + // Format is performed in multiples of the erase sector (or multiple block) size + aInfo.iMaxBytesPerFormat = CyAsSymbianStorageDriver::GetBlockSize(); + + // Set serial number to CID + aInfo.iSerialNumLength = 16; + for (TUint i=0; i<16; i++) + aInfo.iSerialNum[i] = 0; + + // Get block size & erase block size to allow the file system to align first usable cluster correctly + aInfo.iBlockSize = CyAsSymbianStorageDriver::GetBlockSize(); + aInfo.iEraseBlockSize = CyAsSymbianStorageDriver::GetEraseBlockSize(); + + if ( CyAsSymbianStorageDriver::GetIsRemovable()) + aInfo.iDriveAtt|= KDriveAttRemovable; + + // Must return KErrCompletion to indicate that this + // is a synchronous version of the function + return KErrNone; + } + + +void DMediaDriverWB::NotifyPowerDown() + { + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf(">Mmc:NotifyPowerDown"); + #endif + + EndInCritical(); + + //CompleteRequest(KErrNotReady); + } + +void DMediaDriverWB::NotifyEmergencyPowerDown() + { + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf(">Ata:NotifyEmergencyPowerDown"); + #endif + //TInt r=KErrNotReady; + //if (iCritical) + // r=KErrAbort; + EndInCritical(); + + // need to cancel the session as the stack doesn't take too kindly to having the same session engaged more than once. + + //CompleteRequest(r); + } + +TInt DMediaDriverWB::Request(TLocDrvRequest& aRequest) + { + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf("MmcMd:Req %08x id %d",&aRequest,aRequest.Id()); + #endif + TInt r=KErrNotSupported; + TInt id=aRequest.Id(); + + NKern::ThreadEnterCS(); + + TUint partitionType = aRequest.Drive()->iPartitionType; + TBool readOnly = (partitionType == KPartitionTypeRofs || partitionType == KPartitionTypeROM); + + switch (id) + { + case DLocalDrive::ECaps: + { + TLocalDriveCapsV6& c = *(TLocalDriveCapsV6*)aRequest.RemoteDes(); + TLocDrv& drive = *aRequest.Drive(); + r = Caps(drive, c); + c.iSize = drive.iPartitionLen; + c.iPartitionType = drive.iPartitionType; + c.iHiddenSectors = (TUint) (drive.iPartitionBaseAddr >> KDiskSectorShift); + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("caps : c.iSize = %d ", c.iSize); + Kern::Printf("caps : c.iPartitionType = %d ", c.iPartitionType); + Kern::Printf("caps : c.iHiddenSectors = %d ", c.iHiddenSectors); + #endif + } + break; + case DLocalDrive::EQueryDevice: + Kern::Printf(">WB::EQueryDevice "); + r = KErrNotSupported; + break; + + case DLocalDrive::ERead: + r=DoRead(aRequest); + break; + case DLocalDrive::EWrite: + if (readOnly) + return KErrNotSupported; + r=DoWrite(aRequest); + break; + case DLocalDrive::EFormat: + if (readOnly) + return KErrNotSupported; + r=DoFormat(aRequest); + break; + + + case DLocalDrive::EPasswordUnlock: + case DLocalDrive::EPasswordLock: + case DLocalDrive::EPasswordClear: + case DLocalDrive::EPasswordErase: + case DLocalDrive::EWritePasswordStore: + Kern::Printf(">WB::EPassword "); + break; + case DLocalDrive::EEnlarge: + case DLocalDrive::EReduce: + Kern::Printf(">WB::EReduce "); + default: + Kern::Printf(">WB::default "); + r=KErrNotSupported; + break; + } + + NKern::ThreadLeaveCS(); + #ifdef _MEDWB_DEBUG_3_ + Kern::Printf("MmcMd:Req %08x cmp %d",&aRequest,r); + #endif + return r; + } + +void DMediaDriverWB::Disconnect(DLocalDrive* aLocalDrive, TThreadMessage* aMsg) + { + // Complete using the default implementation + DMediaDriver::Disconnect(aLocalDrive, aMsg); + } + + +DECLARE_EXTENSION_PDD() + { + // NB if the media driver has been defined as a kernel extension in the .OBY/.IBY file + // i.e the "extension" keyword has been used rather than "device", then an instance of + // DPhysicalDeviceMediaMmcFlash will already have been created by InitExtension(). In this + // case the kernel will see that an object of the same name already exists and delete the + // new one. + return new DPhysicalDeviceMediaWB; + } +#ifdef REGIST_MEDIA_USE_MMC +DECLARE_STANDARD_EXTENSION() + { + Kern::Printf("Creating WestBridge PDD"); + + DPhysicalDeviceMediaWB* device = new DPhysicalDeviceMediaWB; + + TInt r; + if (device==NULL) + r=KErrNoMemory; + else + r=Kern::InstallPhysicalDevice(device); + Kern::Printf("Installing WestBridge PDD in kernel returned %d",r); + + if( CyAsSymbianStorageDriver::Open() ) + Kern::Printf("**CyAsSymbianStorageDriver::Open() - Success"); + else + Kern::Printf("**CyAsSymbianStorageDriver::Open() - Fail"); + + Kern::Printf("WestBridge extension entry point drive returns %d",r); + return r; + } + +#else +static const TInt WBDriveNumbers[1]={1}; +_LIT(KWBDriveName,"WestBridge"); + +DECLARE_STANDARD_EXTENSION() + { + __KTRACE_OPT(KBOOT,Kern::Printf("Registering WB drive")); + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("Registering WB drive"); + #endif + TInt r=KErrNoMemory; + DPrimaryMediaBase* pM=new DPrimaryMediaBase; + if (pM) + { + r=LocDrv::RegisterMediaDevice(MEDIA_DEVICE_MMC,1,&WBDriveNumbers[0],pM,1,KWBDriveName); + } + + + if( CyAsSymbianStorageDriver::Open() ) + { + #ifdef _MEDWB_DEBUG_1_ + Kern::Printf("**CyAsSymbianStorageDriver::Open() - Success"); + #endif + } + else + { + #ifdef _MEDWB_DEBUG_1_ + Kern::Printf("**CyAsSymbianStorageDriver::Open() - Fail"); + #endif + } + + __KTRACE_OPT(KBOOT,Kern::Printf("Registering WB drive - return %d",r)); + #ifdef _MEDWB_DEBUG_2_ + Kern::Printf("Registering WB drive - return %d",r); + #endif + + return r; + } + + +#endif +