baseport/syborg/soundsc/virtio_queue.cpp
changeset 72 d00bf4f57250
parent 45 01c1ffcc4fca
equal deleted inserted replaced
71:5158c0d3bde3 72:d00bf4f57250
    13 *
    13 *
    14 */
    14 */
    15 
    15 
    16 #include "virtio_queue.h"
    16 #include "virtio_queue.h"
    17 
    17 
    18 #define ENABLE_QEMU_AUDIO_MODEL_BUG_WORKAROUND
    18 // #define ENABLE_QEMU_AUDIO_MODEL_BUG_WORKAROUND
    19 #define ENABLE_QEMU_VIRTIO_CLEANUP_BUG_WORKAROUND
    19 #define ENABLE_QEMU_VIRTIO_CLEANUP_BUG_WORKAROUND
    20 #define PHYS_ADDR(x) Epoc::LinearToPhysical( reinterpret_cast<TUint32>(x))
    20 #define PHYS_ADDR(x) Epoc::LinearToPhysical( reinterpret_cast<TUint32>(x))
    21 	
    21 	
    22 namespace VirtIo
    22 namespace VirtIo
    23 {
    23 {
    99 		}
    99 		}
   100 	if (outLeft+inLeft) // rollback descs if not all could have been claimed
   100 	if (outLeft+inLeft) // rollback descs if not all could have been claimed
   101 		{
   101 		{
   102 		if (first>=0)
   102 		if (first>=0)
   103 			{ FreeDescs(first); }
   103 			{ FreeDescs(first); }
       
   104 		SYBORG_VIRTIO_DEBUG("AddBuf Q%x - not ready", iId ); 			
   104 		return KErrNotReady;
   105 		return KErrNotReady;
   105 		}
   106 		}
   106 	iToken[first].iTotalLen = totalLen;
   107 	iToken[first].iTotalLen = totalLen;
   107 	
   108 	
   108 	// fill a slot in avail ring
   109 	// fill a slot in avail ring
   144 		{ return 0; }
   145 		{ return 0; }
   145 	TUint nextUsedSlot = Slot(iNextUsedToRead);
   146 	TUint nextUsedSlot = Slot(iNextUsedToRead);
   146 	TUint len = iUsed->iRing[nextUsedSlot].iLen;
   147 	TUint len = iUsed->iRing[nextUsedSlot].iLen;
   147 	TUint descId = iUsed->iRing[nextUsedSlot].iId;
   148 	TUint descId = iUsed->iRing[nextUsedSlot].iId;
   148 	ASSERT(descId<iCount);
   149 	ASSERT(descId<iCount);
   149 	Token token = iToken[descId].iToken;	
   150 	Token token = iToken[descId].iToken;		
   150 	TUint orderedLen = iToken[descId].iTotalLen;	
   151 	SYBORG_VIRTIO_DEBUG( "GetBuf Q%x %x ..%x t%x D%x L%x OL%x", iId, iNextUsedToRead, usedIdx, token, descId, len, iToken[descId].iTotalLen );
   151 	SYBORG_VIRTIO_DEBUG( "GetBuf Q%x %x ..%x t%x D%x L%x OL%x", iId, iNextUsedToRead, usedIdx, token, descId, len, orderedLen );
       
   152 
   152 
   153 	++iNextUsedToRead;
   153 	++iNextUsedToRead;
   154 	FreeDescs( descId );
   154 	FreeDescs( descId );
   155 	
   155 	
   156 #ifdef ENABLE_QEMU_AUDIO_MODEL_BUG_WORKAROUND	
   156 #ifdef ENABLE_QEMU_AUDIO_MODEL_BUG_WORKAROUND	
   157 	aLen = len?len:orderedLen; // @TODO kind of a hack to solve virtio-audio's failure to report len by syborg on the side of qemu
   157 	aLen = len?len:iToken[descId].iTotalLen; // @TODO kind of a hack to solve virtio-audio's failure to report len by syborg on the side of qemu
       
   158 #else
       
   159     aLen = len;
   158 #endif
   160 #endif
   159 	return token;
   161 	return token;
   160 	}	
   162 	}	
   161 	
   163 	
   162 TInt DQueue::Processing()
   164 TInt DQueue::Processing()
   206 	
   208 	
   207 void DQueue::DumpDescs(TUint descId )
   209 void DQueue::DumpDescs(TUint descId )
   208 	{
   210 	{
   209 	do {
   211 	do {
   210 		TRingDesc& d = iDesc[descId];
   212 		TRingDesc& d = iDesc[descId];
       
   213         if ( (-1) == ((signed)d.iAddr) )
       
   214             break;
   211 		SYBORG_VIRTIO_DEBUG(" Desc %x,addr %x, len %x, flags %x, next %x",
   215 		SYBORG_VIRTIO_DEBUG(" Desc %x,addr %x, len %x, flags %x, next %x",
   212 			(TUint32)descId, (TUint32)d.iAddr, (TUint32)d.iLen, (TUint32)d.iFlags, (TUint32)d.iNext );
   216 			(TUint32)descId, (TUint32)d.iAddr, (TUint32)d.iLen, (TUint32)d.iFlags, (TUint32)d.iNext );
   213 		if ((d.iFlags&TRingDesc::EFlagNext)==0)
   217 		if ((d.iFlags&TRingDesc::EFlagNext)==0)
   214 			{ break; }
   218 			{ break; }
       
   219         if ( KFreeDescriptorMarker == d.iNext )
       
   220             break;
   215 		descId = d.iNext;
   221 		descId = d.iNext;
   216 		} while (ETrue);
   222 		} while (ETrue);
   217 	}
   223 	}
   218 	
   224 	
   219 void DQueue::DumpAll()
   225 void DQueue::DumpAll()
   233 		ASSERT( flags != KFreeDescriptorMarker );
   239 		ASSERT( flags != KFreeDescriptorMarker );
   234 		iDesc[i].iFlags = KFreeDescriptorMarker;
   240 		iDesc[i].iFlags = KFreeDescriptorMarker;
   235 		ASSERT( iToken[i].iToken == token );
   241 		ASSERT( iToken[i].iToken == token );
   236 		iToken[i].iToken = 0;
   242 		iToken[i].iToken = 0;
   237 		iToken[i].iTotalLen = 0;
   243 		iToken[i].iTotalLen = 0;
   238 		i = (flags&TRingDesc::EFlagNext)
   244         if ((flags&TRingDesc::EFlagNext)==0)
   239 			? iDesc[i].iNext : -1;
   245             break;
       
   246 		i = iDesc[i].iNext;
   240 		}
   247 		}
   241 	}		
   248 	}		
   242 	
   249 	
   243 TUint8* DQueue::AllocMem( TUint aSize )
   250 TUint8* DQueue::AllocMem( TUint aSize )
   244 	{
   251 	{
   280 	{
   287 	{
   281 	iDescSize = iCount * sizeof(TRingDesc);
   288 	iDescSize = iCount * sizeof(TRingDesc);
   282 	iAvailSize = sizeof(TRingAvail) + (iCount-1) * sizeof(((TRingAvail*)0)->iRing[0]);
   289 	iAvailSize = sizeof(TRingAvail) + (iCount-1) * sizeof(((TRingAvail*)0)->iRing[0]);
   283 	iTokenSize = iCount * sizeof(TTransactionInfo);
   290 	iTokenSize = iCount * sizeof(TTransactionInfo);
   284 	TUint usedOffset = Align( iDescSize +  iAvailSize, KVirtIoAlignment );
   291 	TUint usedOffset = Align( iDescSize +  iAvailSize, KVirtIoAlignment );
   285 	TUint iUsedSize = sizeof(TRingUsed) + (iCount-1) * sizeof(((TRingUsed*)0)->iRing[0]);
   292 	iUsedSize = sizeof(TRingUsed) + (iCount-1) * sizeof(((TRingUsed*)0)->iRing[0]);
   286 	TUint size = usedOffset + iUsedSize;
   293 	TUint size = usedOffset + iUsedSize;
   287 	TUint8* iMemAligned;
   294 	TUint8* iMemAligned;
   288 
   295 
   289 	iMemAligned = AllocMem( size );
   296 	iMemAligned = AllocMem( size );
   290 	
   297 	
   293 	
   300 	
   294 	iDesc = reinterpret_cast<TRingDesc*>( iMemAligned );
   301 	iDesc = reinterpret_cast<TRingDesc*>( iMemAligned );
   295 	iAvail = reinterpret_cast<TRingAvail*>( iMemAligned + iDescSize );
   302 	iAvail = reinterpret_cast<TRingAvail*>( iMemAligned + iDescSize );
   296 	iUsed = reinterpret_cast<TRingUsed*>( iMemAligned + usedOffset );
   303 	iUsed = reinterpret_cast<TRingUsed*>( iMemAligned + usedOffset );
   297 	iToken = reinterpret_cast<TTransactionInfo*>( Kern::Alloc( iTokenSize ) );
   304 	iToken = reinterpret_cast<TTransactionInfo*>( Kern::Alloc( iTokenSize ) );
   298 	SYBORG_VIRTIO_DEBUG("DQueue %d, Virt iDesc=%x,iAvail=%x,iToken=%x,iUsed=%x",
   305 	SYBORG_VIRTIO_DEBUG("DQueue %d, Virt iDesc=%x/%x,iAvail=%x/%x,iToken=%x,iUsed=%x/%x",
   299 		iId, iDesc, iAvail, iToken, iUsed );
   306 		iId, iDesc, iDescSize, iAvail, iAvailSize, iToken, iUsed, iUsedSize );
   300 	SYBORG_VIRTIO_DEBUG("DQueue %d, Phys iDesc=%x, iUsed=%x",
   307 	SYBORG_VIRTIO_DEBUG("DQueue %d, Phys iDesc=%x, iUsed=%x",
   301 		iId, PHYS_ADDR(iDesc), PHYS_ADDR(iUsed) );
   308 		iId, PHYS_ADDR(iDesc), PHYS_ADDR(iUsed) );
   302 	ASSERT( ((PHYS_ADDR(iUsed)-PHYS_ADDR(iDesc))) == ((TUint32)((TUint8*)iUsed-(TUint8*)iDesc)) );
   309 	ASSERT( ((PHYS_ADDR(iUsed)-PHYS_ADDR(iDesc))) == ((TUint32)((TUint8*)iUsed-(TUint8*)iDesc)) );
   303 	return KErrNone;
   310 	return KErrNone;
   304 	}	
   311 	}	
   305 	
   312 	
   306 void DQueue::PreInitQueue()
   313 void DQueue::PreInitQueue()
   307 	{
   314 	{
   308 	memset(iDesc, -1, iDescSize );
   315 	memset(iDesc, -1, iDescSize );
   309 	memset( ((TUint8*) iAvail) + 4, -1, iDescSize - 4 );
   316 	memset( ((TUint8*) iAvail) + 4, -1, iAvailSize - 4 );
   310 	memset( ((TUint8*) iUsed) + 4, -1, iDescSize - 4 );
   317 	memset( ((TUint8*) iUsed) + 4, -1, iUsedSize - 4 );
   311 	
   318 	
   312 	iAvail->iFlags = 0; // no notifications from control queue
   319 	iAvail->iFlags = 0; // no notifications from control queue
   313 	iUsed->iFlags = 0;
   320 	iUsed->iFlags = 0;
   314 	if ( iPhysMemReallyAllocated )
   321 	if ( iPhysMemReallyAllocated )
   315 		{
   322 		{