741 */ |
741 */ |
742 TInt DDmaHelper::GetPhysicalAddress(TLocDrvRequest& aReq, TPhysAddr& aAddr, TInt& aLen) |
742 TInt DDmaHelper::GetPhysicalAddress(TLocDrvRequest& aReq, TPhysAddr& aAddr, TInt& aLen) |
743 { |
743 { |
744 OstTraceFunctionEntry0( DDMAHELPER_GETPHYSICALADDRESS_ENTRY ); |
744 OstTraceFunctionEntry0( DDMAHELPER_GETPHYSICALADDRESS_ENTRY ); |
745 __ASSERT_DEBUG( (aReq.Flags() & TLocDrvRequest::ETClientBuffer) == 0, PHYSADDR_FAULT()); |
745 __ASSERT_DEBUG( (aReq.Flags() & TLocDrvRequest::ETClientBuffer) == 0, PHYSADDR_FAULT()); |
746 TLinAddr linAddr = (TLinAddr) aReq.RemoteDes(); |
746 |
747 TInt& offset = aReq.RemoteDesOffset(); |
|
748 TLinAddr currLinAddr = linAddr + offset; |
|
749 TInt reqLen = I64LOW(aReq.Length()); |
747 TInt reqLen = I64LOW(aReq.Length()); |
750 __ASSERT_DEBUG(I64HIGH(aReq.Length()) == 0, PHYSADDR_FAULT()); |
748 __ASSERT_DEBUG(I64HIGH(aReq.Length()) == 0, PHYSADDR_FAULT()); |
751 |
749 |
752 aAddr = Epoc::LinearToPhysical(currLinAddr); |
750 TInt& offset = aReq.RemoteDesOffset(); |
753 |
751 if (aReq.Flags() & TLocDrvRequest::EPhysAddrOnly) |
754 // Set the initial length to be the length remaining in this page or the request length (whichever is shorter). |
752 { |
755 // If there are subsequent pages, we then need to determine whether they are contiguous |
753 __KTRACE_DMA(Kern::Printf("-Physical Address Only")); |
756 aLen = Min( (TInt) (PageAlign(currLinAddr+iPageSize) - currLinAddr), reqLen - offset); |
754 __ASSERT_DEBUG(IsPageAligned((TLinAddr)reqLen), PHYSADDR_FAULT()); |
757 |
755 |
758 __ASSERT_DEBUG(aLen > 0, PHYSADDR_FAULT()); |
756 TPhysAddr* physArray = (TPhysAddr*)aReq.RemoteDes(); |
759 |
757 |
760 TPhysAddr currPhysPageAddr = PageAlign((TLinAddr) aAddr); |
758 // Adjust start to the next element to be issued |
761 |
759 TUint pageNo = offset>>iPageSizeLog2; |
762 offset+= aLen; |
760 TPhysAddr currPhysPageAddr = aAddr = physArray[pageNo]; |
763 |
761 __ASSERT_DEBUG(IsPageAligned((TLinAddr)currPhysPageAddr), PHYSADDR_FAULT()); |
764 |
762 offset+=iPageSize; |
765 while (offset < reqLen) |
763 aLen=iPageSize; |
766 { |
764 |
767 TPhysAddr nextPhysPageAddr = Epoc::LinearToPhysical(linAddr + offset); |
765 //Determine how many pages are contiguous |
768 __ASSERT_DEBUG(PageOffset((TLinAddr) nextPhysPageAddr) == 0, PHYSADDR_FAULT()); |
766 TPhysAddr nextPhysPageAddr; |
769 |
767 while (offset < reqLen) |
770 if (nextPhysPageAddr != currPhysPageAddr + iPageSize) |
768 { |
771 break; |
769 pageNo++; |
772 |
770 nextPhysPageAddr = physArray[pageNo]; |
773 currPhysPageAddr = nextPhysPageAddr; |
771 __ASSERT_DEBUG(PageOffset((TLinAddr) nextPhysPageAddr) == 0, PHYSADDR_FAULT()); |
774 |
772 |
775 TInt len = Min(iPageSize, reqLen - offset); |
773 if (nextPhysPageAddr != currPhysPageAddr + iPageSize) |
776 offset+= len; |
774 break; |
777 aLen+= len; |
775 |
778 } |
776 currPhysPageAddr = nextPhysPageAddr; |
779 |
777 offset+= iPageSize; |
780 |
778 aLen+= iPageSize; |
781 __KTRACE_DMA(Kern::Printf(">PHYSADDR:DP:GetPhysS(), linAddr %08X, physAddr %08X, len %x reqLen %x", linAddr + offset, aAddr, aLen, reqLen)); |
779 } |
782 OstTraceExt4(TRACE_DEMANDPAGING, DDMAHELPER_GETPHYSICALADDRESS_DP, "linAddr=0x%x; physAddr=0x%x; length=0x%x; reqLen=0x%x", linAddr + offset, aAddr, aLen, reqLen); |
780 |
|
781 __KTRACE_DMA(Kern::Printf(">PHYSADDR:DP:GetPhysS(PhysAddrOnly), physAddr %08X, len %x reqLen %x", aAddr, aLen, reqLen)); |
|
782 } |
|
783 else |
|
784 { |
|
785 TLinAddr linAddr = (TLinAddr) aReq.RemoteDes(); |
|
786 TLinAddr currLinAddr = linAddr + offset; |
|
787 |
|
788 aAddr = Epoc::LinearToPhysical(currLinAddr); |
|
789 |
|
790 // Set the initial length to be the length remaining in this page or the request length (whichever is shorter). |
|
791 // If there are subsequent pages, we then need to determine whether they are contiguous |
|
792 aLen = Min( (TInt) (PageAlign(currLinAddr+iPageSize) - currLinAddr), reqLen - offset); |
|
793 |
|
794 __ASSERT_DEBUG(aLen > 0, PHYSADDR_FAULT()); |
|
795 |
|
796 TPhysAddr currPhysPageAddr = PageAlign((TLinAddr) aAddr); |
|
797 |
|
798 offset+= aLen; |
|
799 |
|
800 while (offset < reqLen) |
|
801 { |
|
802 TPhysAddr nextPhysPageAddr = Epoc::LinearToPhysical(linAddr + offset); |
|
803 __ASSERT_DEBUG(PageOffset((TLinAddr) nextPhysPageAddr) == 0, PHYSADDR_FAULT()); |
|
804 |
|
805 if (nextPhysPageAddr != currPhysPageAddr + iPageSize) |
|
806 break; |
|
807 |
|
808 currPhysPageAddr = nextPhysPageAddr; |
|
809 |
|
810 TInt len = Min(iPageSize, reqLen - offset); |
|
811 offset+= len; |
|
812 aLen+= len; |
|
813 } |
|
814 |
|
815 __KTRACE_DMA(Kern::Printf(">PHYSADDR:DP:GetPhysS(), linAddr %08X, physAddr %08X, len %x reqLen %x", linAddr + offset, aAddr, aLen, reqLen)); |
|
816 OstTraceExt4(TRACE_DEMANDPAGING, DDMAHELPER_GETPHYSICALADDRESS_DP, "linAddr=0x%x; physAddr=0x%x; length=0x%x; reqLen=0x%x", linAddr + offset, aAddr, aLen, reqLen); |
|
817 } |
|
818 |
783 OstTraceFunctionExit0( DDMAHELPER_GETPHYSICALADDRESS_EXIT ); |
819 OstTraceFunctionExit0( DDMAHELPER_GETPHYSICALADDRESS_EXIT ); |
784 return KErrNone; |
820 return KErrNone; |
785 } |
821 } |
786 #endif // (__DEMAND_PAGING__) |
822 #endif // (__DEMAND_PAGING__) |
787 |
823 |