baseport/syborg/soundsc/virtio_audio.cpp
changeset 72 d00bf4f57250
parent 45 01c1ffcc4fca
equal deleted inserted replaced
71:5158c0d3bde3 72:d00bf4f57250
    17 
    17 
    18 namespace VirtIo
    18 namespace VirtIo
    19 {
    19 {
    20 namespace Audio
    20 namespace Audio
    21 {
    21 {
       
    22 
       
    23 static TBool CheckProcessing( TAny* aSelf )
       
    24 	{
       
    25 	MQueue* queue = reinterpret_cast<MQueue*>( aSelf );
       
    26 	return queue->Processing() == 0;
       
    27 	}
       
    28 
       
    29 static void WaitForCompletion( MQueue& aQueue )
       
    30 	{
       
    31 	SYBORG_VIRTIO_DEBUG("AddBufferHelperWaitForCompletion : {");
       
    32 
       
    33 	TInt st = Kern::PollingWait( &CheckProcessing, &aQueue, 50, 100 );
       
    34 	ASSERT ( (st == KErrNone) && "Polling problem" )
       
    35 	
       
    36 	SYBORG_VIRTIO_DEBUG("AddBufferHelperWaitForCompletion : }");
       
    37 	}
       
    38 
       
    39 static void AddBufferHelper( MQueue& aQueue, TAddrLen aList[], TUint aBufInCount, TUint aBufOutCount, Token aToken)
       
    40 	{
       
    41 	TInt st = aQueue.AddBuf(aList, aBufInCount, aBufOutCount, aToken );
       
    42 	if ( st == KErrNotReady )
       
    43 		{
       
    44 		SYBORG_VIRTIO_DEBUG("AddBufferHelper - no free descriptors at Control Queue, forcing wait");
       
    45 		TUint transferred;
       
    46 		Token t;
       
    47 		while ( ( t = aQueue.GetBuf(transferred), t ) != 0 )
       
    48 			{
       
    49 			SYBORG_VIRTIO_DEBUG("flushing Q%x, T%x, L%x\n", 0, t, transferred );
       
    50 			}
       
    51 			
       
    52 		st = aQueue.AddBuf(aList, aBufInCount, aBufOutCount, aToken ); 
       
    53 		}
       
    54 	ASSERT( st == KErrNone );
       
    55 	}
    22 
    56 
    23 DControl::~DControl()
    57 DControl::~DControl()
    24 	{
    58 	{
    25 	if (iCmdMem)
    59 	if (iCmdMem)
    26 		{ Kern::Free( iCmdMem ); }
    60 		{ Kern::Free( iCmdMem ); }
    60 	iCmd[6].iArg = Audio::EDoStop; //stop stream		
    94 	iCmd[6].iArg = Audio::EDoStop; //stop stream		
    61 	iCmd[7].iCommand = Audio::ECmdRun;
    95 	iCmd[7].iCommand = Audio::ECmdRun;
    62 	iCmd[7].iArg = Audio::EDoStop; //kind of pause
    96 	iCmd[7].iArg = Audio::EDoStop; //kind of pause
    63 	iCmd[8].iCommand = Audio::ECmdRun;
    97 	iCmd[8].iCommand = Audio::ECmdRun;
    64 	iCmd[8].iArg = Audio::EDoRun; //kind of resume
    98 	iCmd[8].iArg = Audio::EDoRun; //kind of resume
       
    99 	iCmd[9].iCommand = Audio::ECmdInit; // kind of shutdown
       
   100     iCmd[9].iArg = EDirectionNone;
    65 	return KErrNone;
   101 	return KErrNone;
    66 	}
   102 	}
    67 
   103 
    68 TInt DControl::Setup( StreamDirection aDirection, TInt aChannelNum, 
   104 TInt DControl::Setup( StreamDirection aDirection, TInt aChannelNum, 
    69 	FormatId aFormat, TInt aFreq)
   105 	FormatId aFormat, TInt aFreq)
    70 	{
   106 	{
       
   107     if (iIsRunning 
       
   108         && (( aDirection != iDirection ) 
       
   109             || (aFormat != iCmd[2].iArg )
       
   110             || (aFreq != iCmd[3].iArg )
       
   111             || (aChannelNum != iCmd[1].iArg )
       
   112         ))
       
   113         { return KErrInUse; }
       
   114 
    71 	iCmd[1].iArg = aChannelNum;
   115 	iCmd[1].iArg = aChannelNum;
    72 	iCmd[2].iArg = aFormat;
   116 	iCmd[2].iArg = aFormat;
    73 	iCmd[3].iArg = aFreq;		
   117 	iCmd[3].iArg = aFreq;		
    74 	iCmd[4].iArg = iDirection = aDirection;		
   118 	iCmd[4].iArg = iDirection = aDirection;
    75 	AddCommand(&iCmd[0],(Token)0);
       
    76 	AddCommand(&iCmd[1],(Token)1);
   119 	AddCommand(&iCmd[1],(Token)1);
    77 	AddCommand(&iCmd[2],(Token)2);
   120 	AddCommand(&iCmd[2],(Token)2);
    78 	AddCommand(&iCmd[3],(Token)3);
   121 	AddCommand(&iCmd[3],(Token)3);
    79 	AddCommand(&iCmd[4],(Token)4, iBufferInfo, sizeof(*iBufferInfo) );
   122     if (!iIsRunning) {
       
   123             AddCommand(&iCmd[4],(Token)4, iBufferInfo, sizeof(*iBufferInfo) );
       
   124             AddCommand(&iCmd[6],(Token)6);
       
   125         }
    80 	ControlQueue().Sync();
   126 	ControlQueue().Sync();
    81 	return KErrNone;
   127 	return KErrNone;
    82 	}
   128 	}
    83 	
   129 
    84 void DControl::AddCommand( TCommandPadded* aCmd, Token aToken )
   130 void DControl::AddCommand( TCommandPadded* aCmd, Token aToken )
    85 	{
   131 	{
    86 	TAddrLen list;
   132 	TAddrLen list;
    87 	list.iLen = sizeof(TCommand);
   133 	list.iLen = sizeof(TCommand);
    88 	list.iAddr = Epoc::LinearToPhysical((TUint32)aCmd);
   134 	list.iAddr = Epoc::LinearToPhysical((TUint32)aCmd);
    89 	SYBORG_VIRTIO_DEBUG("AddCommand %x %x %x", aCmd->iCommand, aCmd->iStream, aCmd->iArg);
   135 	SYBORG_VIRTIO_DEBUG("AddCommand %x %x %x", aCmd->iCommand, aCmd->iStream, aCmd->iArg);
    90 	ControlQueue().AddBuf(&list, 1, 0, aToken );
   136 	AddBufferHelper( ControlQueue(), &list, 1, 0, aToken );
    91 	}
   137 	}
    92 
   138 
    93 void DControl::AddCommand( TCommandPadded* aCmd, Token aToken, 
   139 void DControl::AddCommand( TCommandPadded* aCmd, Token aToken, 
    94 	TAny* aMem, TUint aSize )
   140 	TAny* aMem, TUint aSize )
    95 	{
   141 	{
    96 	TAddrLen list[2];
   142 	TAddrLen list[2];
    97 	list[0].iLen = sizeof(TCommand);
   143 	list[0].iLen = sizeof(TCommand);
    98 	list[0].iAddr = Epoc::LinearToPhysical((TUint32)aCmd);
   144 	list[0].iAddr = Epoc::LinearToPhysical((TUint32)aCmd);
    99 	list[1].iLen = aSize;
   145 	list[1].iLen = aSize;
   100 	list[1].iAddr = Epoc::LinearToPhysical((TUint32)aMem);
   146 	list[1].iAddr = Epoc::LinearToPhysical((TUint32)aMem);
   101 	ControlQueue().AddBuf(list, 1, 1, aToken );
   147 	AddBufferHelper( ControlQueue(),list, 1, 1, aToken );
   102 	}
       
   103 	
       
   104 	
       
   105 // Waits until device processes all pending requests
       
   106 // there would be no need to have it here at all 
       
   107 // if there was no bug in qemu:
       
   108 // once you send stop command the buffers processing stops... but the buffers are never returned.
       
   109 
       
   110 void DControl::WaitForCompletion()
       
   111 	{
       
   112 	SYBORG_VIRTIO_DEBUG("DControl::WaitForCompletion : {");
       
   113 
       
   114 	TInt st = Kern::PollingWait( &DControl::CheckProcessing, this, 10, 100 );
       
   115 	ASSERT ( (st == KErrNone) && "Polling problem" )
       
   116 	
       
   117 	SYBORG_VIRTIO_DEBUG("DControlWaitForCompletion : }");
       
   118 	}
   148 	}
   119 
   149 
   120 TBool DControl::CheckProcessing( TAny* aSelf )
       
   121 	{
       
   122 	DControl* self = reinterpret_cast<DControl*>( aSelf );
       
   123 	return self->DataQueue().Processing() == 0;
       
   124 	}
       
   125 	
       
   126 void DControl::AddCommand( Command aCmd )
   150 void DControl::AddCommand( Command aCmd )
   127 	{
   151 	{
   128 	TUint idx = aCmd;
   152 	TUint idx = aCmd;
   129 	if (aCmd == EStop)
   153 	if ( (aCmd == EStop) || (aCmd == EShutDown) )
   130 		{
   154 		{
   131 		// due to bug on qemu's side we need to stop sending buffers
   155 		// due to bug on qemu's side we need to stop sending buffers
   132 		// and wait for all pending buffers to get filled...
   156 		// and wait for all pending buffers to get filled...
   133 		WaitForCompletion();
   157 		WaitForCompletion(DataQueue());
   134 		}
   158         WaitForCompletion(ControlQueue());
       
   159         iIsRunning = 0;
       
   160         }
   135 	AddCommand(&iCmd[idx], (Token)idx );
   161 	AddCommand(&iCmd[idx], (Token)idx );
       
   162     if (aCmd == ERun )
       
   163         {
       
   164         iIsRunning = 1;
       
   165         }
   136 	}
   166 	}
   137 
   167 
   138 TInt DControl::SendDataBuffer( TAny* virtaulAddr, TUint aSize, Token aToken )
   168 TInt DControl::SendDataBuffer( TAny* virtaulAddr, TUint aSize, Token aToken )
   139 	{
   169 	{
   140 	TAddrLen sgl[KMaxSGLItemCountPerAudioBuffer];
   170 	TAddrLen sgl[KMaxSGLItemCountPerAudioBuffer];