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]; |