1 //============================================================================
2 // Copyright (c) 1996-2002 Winbond Electronic Corporation
8 // Processing the Tx message and put into down layer
10 //============================================================================
11 #include <linux/usb.h>
18 Wb35Tx_get_tx_buffer(phw_data_t pHwData, u8 **pBuffer)
20 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
22 *pBuffer = pWb35Tx->TxBuffer[0];
26 void Wb35Tx_start(struct wbsoft_priv *adapter)
28 phw_data_t pHwData = &adapter->sHwData;
29 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
31 // Allow only one thread to run into function
32 if (atomic_inc_return(&pWb35Tx->TxFireCounter) == 1) {
33 pWb35Tx->EP4vm_state = VM_RUNNING;
36 atomic_dec(&pWb35Tx->TxFireCounter);
40 void Wb35Tx(struct wbsoft_priv *adapter)
42 phw_data_t pHwData = &adapter->sHwData;
43 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
45 PMDS pMds = &adapter->Mds;
46 struct urb * pUrb = (struct urb *)pWb35Tx->Tx4Urb;
51 if (pHwData->SurpriseRemove || pHwData->HwStop)
58 SendIndex = pWb35Tx->TxSendIndex;
59 if (!pMds->TxOwner[SendIndex]) //No more data need to be sent, return immediately
62 pTxBufferAddress = pWb35Tx->TxBuffer[SendIndex];
66 usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
67 usb_sndbulkpipe(pHwData->WbUsb.udev, 4),
68 pTxBufferAddress, pMds->TxBufferSize[ SendIndex ],
69 Wb35Tx_complete, adapter);
71 pWb35Tx->EP4vm_state = VM_RUNNING;
72 retv = usb_submit_urb(pUrb, GFP_ATOMIC);
74 printk("EP4 Tx Irp sending error\n");
78 // Check if driver needs issue Irp for EP2
79 pWb35Tx->TxFillCount += pMds->TxCountInBuffer[SendIndex];
80 if (pWb35Tx->TxFillCount > 12)
81 Wb35Tx_EP2VM_start(adapter);
83 pWb35Tx->ByteTransfer += pMds->TxBufferSize[SendIndex];
87 pWb35Tx->EP4vm_state = VM_STOP;
88 atomic_dec(&pWb35Tx->TxFireCounter);
92 void Wb35Tx_complete(struct urb * pUrb)
94 struct wbsoft_priv *adapter = pUrb->context;
95 phw_data_t pHwData = &adapter->sHwData;
96 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
97 PMDS pMds = &adapter->Mds;
99 printk("wb35: tx complete\n");
101 pWb35Tx->EP4vm_state = VM_COMPLETED;
102 pWb35Tx->EP4VM_status = pUrb->status; //Store the last result of Irp
103 pMds->TxOwner[ pWb35Tx->TxSendIndex ] = 0;// Set the owner. Free the owner bit always.
104 pWb35Tx->TxSendIndex++;
105 pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER;
107 if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
110 if (pWb35Tx->tx_halt)
113 // The URB is completed, check the result
114 if (pWb35Tx->EP4VM_status != 0) {
115 printk("URB submission failed\n");
116 pWb35Tx->EP4vm_state = VM_STOP;
125 atomic_dec(&pWb35Tx->TxFireCounter);
126 pWb35Tx->EP4vm_state = VM_STOP;
129 void Wb35Tx_reset_descriptor( phw_data_t pHwData )
131 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
133 pWb35Tx->TxSendIndex = 0;
134 pWb35Tx->tx_halt = 0;
137 unsigned char Wb35Tx_initial(phw_data_t pHwData)
139 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
141 pWb35Tx->Tx4Urb = usb_alloc_urb(0, GFP_ATOMIC);
142 if (!pWb35Tx->Tx4Urb)
145 pWb35Tx->Tx2Urb = usb_alloc_urb(0, GFP_ATOMIC);
146 if (!pWb35Tx->Tx2Urb)
148 usb_free_urb( pWb35Tx->Tx4Urb );
155 //======================================================
156 void Wb35Tx_stop(phw_data_t pHwData)
158 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
160 // Trying to canceling the Trp of EP2
161 if (pWb35Tx->EP2vm_state == VM_RUNNING)
162 usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them
164 WBDEBUG(("EP2 Tx stop\n"));
167 // Trying to canceling the Irp of EP4
168 if (pWb35Tx->EP4vm_state == VM_RUNNING)
169 usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them
171 WBDEBUG(("EP4 Tx stop\n"));
175 //======================================================
176 void Wb35Tx_destroy(phw_data_t pHwData)
178 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
182 msleep(10); // Delay for waiting function enter 940623.1.a
183 } while( (pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP) );
184 msleep(10); // Delay for waiting function enter 940623.1.b
187 usb_free_urb( pWb35Tx->Tx4Urb );
190 usb_free_urb( pWb35Tx->Tx2Urb );
193 WBDEBUG(("Wb35Tx_destroy OK\n"));
197 void Wb35Tx_CurrentTime(struct wbsoft_priv *adapter, u32 TimeCount)
199 phw_data_t pHwData = &adapter->sHwData;
200 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
201 unsigned char Trigger = false;
203 if (pWb35Tx->TxTimer > TimeCount)
205 else if (TimeCount > (pWb35Tx->TxTimer+500))
209 pWb35Tx->TxTimer = TimeCount;
210 Wb35Tx_EP2VM_start(adapter);
214 void Wb35Tx_EP2VM_start(struct wbsoft_priv *adapter)
216 phw_data_t pHwData = &adapter->sHwData;
217 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
219 // Allow only one thread to run into function
220 if (atomic_inc_return(&pWb35Tx->TxResultCount) == 1) {
221 pWb35Tx->EP2vm_state = VM_RUNNING;
222 Wb35Tx_EP2VM(adapter);
225 atomic_dec(&pWb35Tx->TxResultCount);
229 void Wb35Tx_EP2VM(struct wbsoft_priv *adapter)
231 phw_data_t pHwData = &adapter->sHwData;
232 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
233 struct urb * pUrb = (struct urb *)pWb35Tx->Tx2Urb;
234 u32 * pltmp = (u32 *)pWb35Tx->EP2_buf;
237 if (pHwData->SurpriseRemove || pHwData->HwStop)
240 if (pWb35Tx->tx_halt)
246 usb_fill_int_urb( pUrb, pHwData->WbUsb.udev, usb_rcvintpipe(pHwData->WbUsb.udev,2),
247 pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, adapter, 32);
249 pWb35Tx->EP2vm_state = VM_RUNNING;
250 retv = usb_submit_urb(pUrb, GFP_ATOMIC);
254 WBDEBUG(("EP2 Tx Irp sending error\n"));
261 pWb35Tx->EP2vm_state = VM_STOP;
262 atomic_dec(&pWb35Tx->TxResultCount);
266 void Wb35Tx_EP2VM_complete(struct urb * pUrb)
268 struct wbsoft_priv *adapter = pUrb->context;
269 phw_data_t pHwData = &adapter->sHwData;
270 T02_DESCRIPTOR T02, TSTATUS;
271 PWB35TX pWb35Tx = &pHwData->Wb35Tx;
272 u32 * pltmp = (u32 *)pWb35Tx->EP2_buf;
274 u16 InterruptInLength;
278 pWb35Tx->EP2vm_state = VM_COMPLETED;
279 pWb35Tx->EP2VM_status = pUrb->status;
281 // For Linux 2.4. Interrupt will always trigger
282 if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
285 if (pWb35Tx->tx_halt)
288 //The Urb is completed, check the result
289 if (pWb35Tx->EP2VM_status != 0) {
290 WBDEBUG(("EP2 IoCompleteRoutine return error\n"));
291 pWb35Tx->EP2vm_state= VM_STOP;
295 // Update the Tx result
296 InterruptInLength = pUrb->actual_length;
297 // Modify for minimum memory access and DWORD alignment.
298 T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
299 InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
300 InterruptInLength >>= 2; // InterruptInLength/4
301 for (i = 1; i <= InterruptInLength; i++) {
302 T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
304 TSTATUS.value = T02.value; //20061009 anson's endian
305 Mds_SendComplete( adapter, &TSTATUS );
306 T02.value = cpu_to_le32(pltmp[i]) >> 8;
311 atomic_dec(&pWb35Tx->TxResultCount);
312 pWb35Tx->EP2vm_state = VM_STOP;