/** 2nd stage constructor. @param aNumPages number of pages in the directory cache. @param aPageSizeLog2 Log2 of the page size in bytes, this is the cache read granularity @param aWrGranularityLog2 Log2(cache write granularity) */ void CMediaWTCache::InitialiseL(TUint32 aNumPages, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2) { ASSERT(aNumPages && aPageSizeLog2); __PRINT3(_L("#CMediaWTCache::InitialiseL() Pages=%d, PageSzLog2=%d, WrGrLog2:%d"), aNumPages, aPageSizeLog2, aWrGranularityLog2); ASSERT(aNumPages); ASSERT(aPageSizeLog2); if(aWrGranularityLog2) { ASSERT(aWrGranularityLog2 >= KDefSectorSzLog2 && aWrGranularityLog2 <= aPageSizeLog2); } iPageSizeLog2 = aPageSizeLog2; iWrGranularityLog2 = aWrGranularityLog2; //-- create cache pages for(TUint cnt=0; cnt<aNumPages; ++cnt) { CWTCachePage* pPage = CWTCachePage::NewL(aPageSizeLog2); iPages.AppendL(pPage); } InvalidateCache(); }
/** Publishing method Sends a property event on behalf of CMassStorageDrive, with the mountstate and drivestate values encoded into one 32-bit word. */ void RDriveStateChangedPublisher::DriveStateChanged() { __MSFNLOG TUsbMsDrivesStatus allDrivesStatus; for(TUint8 i = 0; i < iDrives.Count(); i++) { allDrivesStatus.Append(iDriveMap[i]); CMassStorageDrive::TMountState ms = iDrives[i]->MountState(); TLocalDriveRef::TDriveState ds = iDrives[i]->DriveState(); TInt driveStatus = EUsbMsDriveState_Error; if((TUint8)ds < sizeof(table[0]) && (TUint8)ms < sizeof(table)/sizeof(table[0])) { driveStatus = table[ms][ds]; __PRINT3(_L("ms=%d ds=%d %d"), ms, ds, driveStatus); } allDrivesStatus.Append(driveStatus); } __PRINT1(_L("Publishing EUsbMsDriveState_DriveStatus for %d drives\n"), allDrivesStatus.Length()/2); if(KErrNone != RProperty::Set(KUsbMsDriveState_Category, EUsbMsDriveState_DriveStatus, allDrivesStatus)) { __ASSERT_DEBUG(EFalse,User::Invariant()); } }
/** Dump cache content, only enabled in debug mode. @see CDynamicDirCache::Control() */ void CDynamicDirCache::Dump() { __PRINT(_L("======== CDynamicDirCache::Dump =========")); if (!iLockedQ.IsEmpty()) { TDblQueIter<TDynamicDirCachePage> q(iLockedQ); q.SetToFirst(); TInt i = 0; while((TDynamicDirCachePage*)q) { TDynamicDirCachePage* pP = q++; __PRINT3(_L("=== CDynamicDirCache::iLockedQ\t[%4d](pos=%lx, size=%d)"), i++, pP->StartPos(), pP->PageSizeInBytes()); } } if (!iUnlockedQ.IsEmpty()) { TDblQueIter<TDynamicDirCachePage> q(iUnlockedQ); q.SetToFirst(); TInt i = 0; while((TDynamicDirCachePage*)q) { TDynamicDirCachePage* pP = q++; __PRINT3(_L("=== CDynamicDirCache::iUnlockedQ\t[%4d](pos=%lx, size=%u)"), i++, pP->StartPos(), pP->PageSizeInBytes()); } } __PRINT2(_L("=== CDynamicDirCache::iActivePage\t[*](pos=%lx, size=%u)"), iActivePage->StartPos(), iActivePage->PageSizeInBytes()); if (iLookupTable.Count()) { TInt i = 0; THashSetIter<TLookupEntry> iter(iLookupTable); TLookupEntry* pEntry; pEntry = (TLookupEntry*) iter.Next(); while(pEntry) { TDynamicDirCachePage* pP = pEntry->iPage; __PRINT3(_L("=== CDynamicDirCache::iLookupTable\t[%4d](pos=%lx, size=%u)"), i++, pP->StartPos(), pP->PageSizeInBytes()); pEntry = (TLookupEntry*) iter.Next(); }; } __PRINT(_L("===========================================\n")); }
/* Print out current tree content */ void CLeafDirTree::DumpTreeContentL() const { RPointerArray<CLeafDirTreeNode>* nodeStack = new(ELeave) RPointerArray<CLeafDirTreeNode>(4); RFs fs; TInt nRes = fs.Connect(); User::LeaveIfError(nRes); const TUint32 debugRegister = DebugRegister(); fs.SetDebugRegister(debugRegister|KFSYS); if (iRoot != NULL) { nodeStack->Insert(iRoot, 0); while(nodeStack->Count() > 0) { CLeafDirTreeNode* current = (*nodeStack)[0]; if (current->Parent() != NULL) { __PRINT3(_L("(\"%S\") -> \"%S\" : (%d)\n"), ¤t->Parent()->Path(), ¤t->Path(), current->StartClusterNum()); } else { __PRINT2(_L("\"%S\" : (%d)\n"), ¤t->Path(), current->StartClusterNum()); } nodeStack->Remove(0); TInt currentCount = current->Children().Count(); if (currentCount > 0) { RPointerArray<CLeafDirTreeNode> children = current->Children(); for (TInt i = 0; i < currentCount; i++) { nodeStack->Insert(children[i], 0); } } } } fs.SetDebugRegister(debugRegister); fs.Close(); nodeStack->Close(); delete nodeStack; }
/** Open the device and do some initalisation work. @param aParams device parameters @return Epoc error code, KErrNone if everything is OK */ TInt CWinVolumeDevice::Connect(const TMediaDeviceParams& aParams) { __PRINT(_L("#-- CWinVolumeDevice::Connect()")); if(!aParams.ipDevName) { __LOG(_L("#-- CWinVolumeDevice::Connect() device name is not set!")); return KErrBadName; } __PRINTF(aParams.ipDevName); ASSERT(!HandleValid() && ipScratchBuf); //-- open the device DWORD dwAccess = GENERIC_READ; if(!aParams.iReadOnly) dwAccess |= GENERIC_WRITE; iDevHandle = CreateFileA(aParams.ipDevName, dwAccess, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(!HandleValid()) { __LOG1(_L("#-- CWinVolumeDevice::Connect() Error creating device handle! WinErr:%d"), GetLastError()); return KErrGeneral; } //-- find out device geometry iMediaType = Unknown; iDrvGeometry.iBytesPerSector = KDefaultSectorSz; DWORD junk; //-- 1. try to query disk geometry, but it can produce wrong results for partitioned media BOOL bResult = DeviceIoControl(Handle(), IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, ipScratchBuf, KScratchBufSz, &junk, (LPOVERLAPPED)NULL); if(bResult) { const DISK_GEOMETRY& dg = (const DISK_GEOMETRY&)*ipScratchBuf; iDrvGeometry.iBytesPerSector = dg.BytesPerSector; iMediaType = dg.MediaType; __PRINT3(_L("#-- dev geometry: Cyl:%d Heads:%d Sectors:%d"), dg.Cylinders.LowPart, dg.TracksPerCylinder, dg.SectorsPerTrack); __PRINT2(_L("#-- dev geometry: MediaType:%d, bps:%d"), dg.MediaType, dg.BytesPerSector); } else { iMediaType = Unknown; iDrvGeometry.iBytesPerSector = KDefaultSectorSz; __LOG1(_L("#-- CWinVolumeDevice::Connect() IOCTL_DISK_GET_DRIVE_GEOMETRY WinError:%d !"), GetLastError()); } //-- 1.1 check "bytes per sector" value and how it corresponds to the request from parameters if(aParams.iDrvGeometry.iBytesPerSector == 0) {//-- do nothing, this parameter is not set in config file, use media's } else if(aParams.iDrvGeometry.iBytesPerSector != iDrvGeometry.iBytesPerSector) {//-- we can't set "SectorSize" value for the physical media __LOG1(_L("#-- CWinVolumeDevice::Connect() can not use 'Sec. Size' value from config:%d !"), aParams.iDrvGeometry.iBytesPerSector); Disconnect(); return KErrArgument; } ASSERT(IsPowerOf2(BytesPerSector()) && BytesPerSector() >= KDefaultSectorSz && BytesPerSector() < 4096); //-- find out partition information in order to determine volume size. bResult = DeviceIoControl(Handle(), IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, ipScratchBuf, KScratchBufSz, &junk, (LPOVERLAPPED)NULL); if(!bResult) {//-- this is a fatal error __LOG1(_L("#-- CWinVolumeDevice::Connect() IOCTL_DISK_GET_PARTITION_INFO WinError:%d !"), GetLastError()); Disconnect(); return KErrBadHandle; } //-- get partition informaton const PARTITION_INFORMATION& pi = (const PARTITION_INFORMATION&)*ipScratchBuf; TInt64 volSz = MAKE_TINT64(pi.PartitionLength.HighPart, pi.PartitionLength.LowPart); iDrvGeometry.iSizeInSectors = (TUint32)(volSz / iDrvGeometry.iBytesPerSector); __LOG3(_L("#-- partition size, bytes:%LU (%uMB), sectors:%u"), volSz, (TUint32)(volSz>>20), iDrvGeometry.iSizeInSectors); //-- check if the media size is set in coonfig and if we can use this setting. if(aParams.iDrvGeometry.iSizeInSectors == 0) {//-- do nothing, the media size is not set in the ini file, use existing media parameters } else if(aParams.iDrvGeometry.iSizeInSectors > iDrvGeometry.iSizeInSectors) {//-- requested media size in ini file is bigger than physical media, error. //-- we can't increase physical media size __LOG2(_L("#-- CWinVolumeDevice::Connect() 'MediaSizeSectors' value from config:%d > than physical:%d !"), aParams.iDrvGeometry.iSizeInSectors, iDrvGeometry.iSizeInSectors); Disconnect(); return KErrArgument; } else if(aParams.iDrvGeometry.iSizeInSectors < iDrvGeometry.iSizeInSectors) {//-- settings specify smaller media than physical one, adjust the size __PRINT1(_L("#-- reducing media size to %d sectors"), aParams.iDrvGeometry.iSizeInSectors); iDrvGeometry.iSizeInSectors = aParams.iDrvGeometry.iSizeInSectors; } ASSERT(iDrvGeometry.iSizeInSectors > KMinMediaSizeInSectors); return KErrNone; }
/** Mount a Fat volume. @param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown. */ void CFatMountCB::MountL(TBool aForceMount) { const TInt driveNo = Drive().DriveNumber(); __PRINT3(_L("CFatMountCB::MountL() drv:%d, forceMount=%d, RuggedFAT:%d\n"), driveNo, aForceMount, IsRuggedFSys()); ASSERT(State() == ENotMounted || State() == EDismounted); SetState(EMounting); SetReadOnly(EFalse); User::LeaveIfError(CreateDrive(driveNo)); //-- read FAT configuration parameters from estart.txt iFatConfig.ReadConfig(driveNo); //-- initialise interface to the low-level drive access if(!iDriverInterface.Init(this)) User::LeaveIfError(KErrNoMemory); //-- get drive capabilities TLocalDriveCapsV2Buf capsBuf; User::LeaveIfError(LocalDrive()->Caps(capsBuf)); iSize=capsBuf().iSize; iRamDrive = EFalse; if(capsBuf().iMediaAtt & KMediaAttVariableSize) {//-- this is a RAM drive UserSvr::UnlockRamDrive(); iRamDrive = ETrue; } if(aForceMount) {//-- the state is "forcedly mounted", special case. This is an inconsistent state. SetState(EInit_Forced); return; } //-- read boot sector. If main is damaged, try to use backup one instead if this is not a RAM drive. TFatBootSector bootSector; User::LeaveIfError(ReadBootSector(bootSector, iRamDrive)); //-- print out boot sector debug information bootSector.PrintDebugInfo(); //-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt SetFatType(bootSector.FatType()); ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector() if(bootSector.RootDirEntries() == 0 && !Is32BitFat()) {//-- FAT types mismatch. BPB_RootEntCnt is 0, which can be only for FAT32, but the number of clusters is less //-- than required for FAT32. Probably this is incorrectly FAT32 formatted media. Put the drive into ReadOnly mode, assuming //-- that is FAT32. __PRINT(_L("FAT type mismatch! Setting drive to ReadOnly mode for FAT32. \n")); SetFatType(EFat32); //-- force FAT type to be FAT32 SetReadOnly(ETrue); } //-- store volume UID, it can be checked on Remount iUniqueID = bootSector.UniqueID(); //-- populate volume parameters with the values from boot sector. They had been validated in TFatBootSector::IsValid() iVolParam.Populate(bootSector); //-- initialize the volume InitializeL(capsBuf()); ASSERT(State()==EInit_R); GetVolumeLabelFromDiskL(bootSector); __PRINT2(_L("CFatMountCB::MountL() Completed, drv: %d, state:%d"), DriveNumber(), State()); }