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>
12 #include <linux/gfp.h>
19 Wb35Tx_get_tx_buffer(struct hw_data * pHwData, u8 **pBuffer)
21 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
23 *pBuffer = pWb35Tx->TxBuffer[0];
27 static void Wb35Tx(struct wbsoft_priv *adapter);
29 static void Wb35Tx_complete(struct urb * pUrb)
31 struct wbsoft_priv *adapter = pUrb->context;
32 struct hw_data * pHwData = &adapter->sHwData;
33 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
34 struct wb35_mds *pMds = &adapter->Mds;
36 printk("wb35: tx complete\n");
38 pWb35Tx->EP4vm_state = VM_COMPLETED;
39 pWb35Tx->EP4VM_status = pUrb->status; //Store the last result of Irp
40 pMds->TxOwner[ pWb35Tx->TxSendIndex ] = 0;// Set the owner. Free the owner bit always.
41 pWb35Tx->TxSendIndex++;
42 pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER;
44 if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
50 // The URB is completed, check the result
51 if (pWb35Tx->EP4VM_status != 0) {
52 printk("URB submission failed\n");
53 pWb35Tx->EP4vm_state = VM_STOP;
62 atomic_dec(&pWb35Tx->TxFireCounter);
63 pWb35Tx->EP4vm_state = VM_STOP;
66 static void Wb35Tx(struct wbsoft_priv *adapter)
68 struct hw_data * pHwData = &adapter->sHwData;
69 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
71 struct wb35_mds *pMds = &adapter->Mds;
72 struct urb * pUrb = (struct urb *)pWb35Tx->Tx4Urb;
77 if (pHwData->SurpriseRemove || pHwData->HwStop)
84 SendIndex = pWb35Tx->TxSendIndex;
85 if (!pMds->TxOwner[SendIndex]) //No more data need to be sent, return immediately
88 pTxBufferAddress = pWb35Tx->TxBuffer[SendIndex];
92 usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
93 usb_sndbulkpipe(pHwData->WbUsb.udev, 4),
94 pTxBufferAddress, pMds->TxBufferSize[ SendIndex ],
95 Wb35Tx_complete, adapter);
97 pWb35Tx->EP4vm_state = VM_RUNNING;
98 retv = usb_submit_urb(pUrb, GFP_ATOMIC);
100 printk("EP4 Tx Irp sending error\n");
104 // Check if driver needs issue Irp for EP2
105 pWb35Tx->TxFillCount += pMds->TxCountInBuffer[SendIndex];
106 if (pWb35Tx->TxFillCount > 12)
107 Wb35Tx_EP2VM_start(adapter);
109 pWb35Tx->ByteTransfer += pMds->TxBufferSize[SendIndex];
113 pWb35Tx->EP4vm_state = VM_STOP;
114 atomic_dec(&pWb35Tx->TxFireCounter);
117 void Wb35Tx_start(struct wbsoft_priv *adapter)
119 struct hw_data * pHwData = &adapter->sHwData;
120 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
122 // Allow only one thread to run into function
123 if (atomic_inc_return(&pWb35Tx->TxFireCounter) == 1) {
124 pWb35Tx->EP4vm_state = VM_RUNNING;
127 atomic_dec(&pWb35Tx->TxFireCounter);
130 unsigned char Wb35Tx_initial(struct hw_data * pHwData)
132 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
134 pWb35Tx->Tx4Urb = usb_alloc_urb(0, GFP_ATOMIC);
135 if (!pWb35Tx->Tx4Urb)
138 pWb35Tx->Tx2Urb = usb_alloc_urb(0, GFP_ATOMIC);
139 if (!pWb35Tx->Tx2Urb)
141 usb_free_urb( pWb35Tx->Tx4Urb );
148 //======================================================
149 void Wb35Tx_stop(struct hw_data * pHwData)
151 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
153 // Trying to canceling the Trp of EP2
154 if (pWb35Tx->EP2vm_state == VM_RUNNING)
155 usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them
157 printk("EP2 Tx stop\n");
160 // Trying to canceling the Irp of EP4
161 if (pWb35Tx->EP4vm_state == VM_RUNNING)
162 usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them
164 printk("EP4 Tx stop\n");
168 //======================================================
169 void Wb35Tx_destroy(struct hw_data * pHwData)
171 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
175 msleep(10); // Delay for waiting function enter 940623.1.a
176 } while( (pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP) );
177 msleep(10); // Delay for waiting function enter 940623.1.b
180 usb_free_urb( pWb35Tx->Tx4Urb );
183 usb_free_urb( pWb35Tx->Tx2Urb );
186 printk("Wb35Tx_destroy OK\n");
190 void Wb35Tx_CurrentTime(struct wbsoft_priv *adapter, u32 TimeCount)
192 struct hw_data * pHwData = &adapter->sHwData;
193 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
194 unsigned char Trigger = false;
196 if (pWb35Tx->TxTimer > TimeCount)
198 else if (TimeCount > (pWb35Tx->TxTimer+500))
202 pWb35Tx->TxTimer = TimeCount;
203 Wb35Tx_EP2VM_start(adapter);
207 static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter);
209 static void Wb35Tx_EP2VM_complete(struct urb * pUrb)
211 struct wbsoft_priv *adapter = pUrb->context;
212 struct hw_data * pHwData = &adapter->sHwData;
213 T02_DESCRIPTOR T02, TSTATUS;
214 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
215 u32 * pltmp = (u32 *)pWb35Tx->EP2_buf;
217 u16 InterruptInLength;
221 pWb35Tx->EP2vm_state = VM_COMPLETED;
222 pWb35Tx->EP2VM_status = pUrb->status;
224 // For Linux 2.4. Interrupt will always trigger
225 if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
228 if (pWb35Tx->tx_halt)
231 //The Urb is completed, check the result
232 if (pWb35Tx->EP2VM_status != 0) {
233 printk("EP2 IoCompleteRoutine return error\n");
234 pWb35Tx->EP2vm_state= VM_STOP;
238 // Update the Tx result
239 InterruptInLength = pUrb->actual_length;
240 // Modify for minimum memory access and DWORD alignment.
241 T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
242 InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
243 InterruptInLength >>= 2; // InterruptInLength/4
244 for (i = 1; i <= InterruptInLength; i++) {
245 T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
247 TSTATUS.value = T02.value; //20061009 anson's endian
248 Mds_SendComplete( adapter, &TSTATUS );
249 T02.value = cpu_to_le32(pltmp[i]) >> 8;
254 atomic_dec(&pWb35Tx->TxResultCount);
255 pWb35Tx->EP2vm_state = VM_STOP;
258 static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter)
260 struct hw_data * pHwData = &adapter->sHwData;
261 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
262 struct urb * pUrb = (struct urb *)pWb35Tx->Tx2Urb;
263 u32 * pltmp = (u32 *)pWb35Tx->EP2_buf;
266 if (pHwData->SurpriseRemove || pHwData->HwStop)
269 if (pWb35Tx->tx_halt)
275 usb_fill_int_urb( pUrb, pHwData->WbUsb.udev, usb_rcvintpipe(pHwData->WbUsb.udev,2),
276 pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, adapter, 32);
278 pWb35Tx->EP2vm_state = VM_RUNNING;
279 retv = usb_submit_urb(pUrb, GFP_ATOMIC);
283 printk("EP2 Tx Irp sending error\n");
290 pWb35Tx->EP2vm_state = VM_STOP;
291 atomic_dec(&pWb35Tx->TxResultCount);
294 void Wb35Tx_EP2VM_start(struct wbsoft_priv *adapter)
296 struct hw_data * pHwData = &adapter->sHwData;
297 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
299 // Allow only one thread to run into function
300 if (atomic_inc_return(&pWb35Tx->TxResultCount) == 1) {
301 pWb35Tx->EP2vm_state = VM_RUNNING;
302 Wb35Tx_EP2VM(adapter);
305 atomic_dec(&pWb35Tx->TxResultCount);