Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus
[linux-btrfs-devel.git] / drivers / staging / winbond / wb35tx.c
blob5df39d46cda48e1f26450229dc190111d4e52a9e
1 //============================================================================
2 // Copyright (c) 1996-2002 Winbond Electronic Corporation
3 //
4 // Module Name:
5 // Wb35Tx.c
6 //
7 // Abstract:
8 // Processing the Tx message and put into down layer
9 //
10 //============================================================================
11 #include <linux/usb.h>
12 #include <linux/gfp.h>
14 #include "wb35tx_f.h"
15 #include "mds_f.h"
17 unsigned char
18 Wb35Tx_get_tx_buffer(struct hw_data * pHwData, u8 **pBuffer)
20 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
22 *pBuffer = pWb35Tx->TxBuffer[0];
23 return true;
26 static void Wb35Tx(struct wbsoft_priv *adapter);
28 static void Wb35Tx_complete(struct urb * pUrb)
30 struct wbsoft_priv *adapter = pUrb->context;
31 struct hw_data * pHwData = &adapter->sHwData;
32 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
33 struct wb35_mds *pMds = &adapter->Mds;
35 printk("wb35: tx complete\n");
36 // Variable setting
37 pWb35Tx->EP4vm_state = VM_COMPLETED;
38 pWb35Tx->EP4VM_status = pUrb->status; //Store the last result of Irp
39 pMds->TxOwner[ pWb35Tx->TxSendIndex ] = 0;// Set the owner. Free the owner bit always.
40 pWb35Tx->TxSendIndex++;
41 pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER;
43 if (pHwData->SurpriseRemove) // Let WbWlanHalt to handle surprise remove
44 goto error;
46 if (pWb35Tx->tx_halt)
47 goto error;
49 // The URB is completed, check the result
50 if (pWb35Tx->EP4VM_status != 0) {
51 printk("URB submission failed\n");
52 pWb35Tx->EP4vm_state = VM_STOP;
53 goto error;
56 Mds_Tx(adapter);
57 Wb35Tx(adapter);
58 return;
60 error:
61 atomic_dec(&pWb35Tx->TxFireCounter);
62 pWb35Tx->EP4vm_state = VM_STOP;
65 static void Wb35Tx(struct wbsoft_priv *adapter)
67 struct hw_data * pHwData = &adapter->sHwData;
68 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
69 u8 *pTxBufferAddress;
70 struct wb35_mds *pMds = &adapter->Mds;
71 struct urb * pUrb = (struct urb *)pWb35Tx->Tx4Urb;
72 int retv;
73 u32 SendIndex;
76 if (pHwData->SurpriseRemove)
77 goto cleanup;
79 if (pWb35Tx->tx_halt)
80 goto cleanup;
82 // Ownership checking
83 SendIndex = pWb35Tx->TxSendIndex;
84 if (!pMds->TxOwner[SendIndex]) //No more data need to be sent, return immediately
85 goto cleanup;
87 pTxBufferAddress = pWb35Tx->TxBuffer[SendIndex];
89 // Issuing URB
91 usb_fill_bulk_urb(pUrb, pHwData->udev,
92 usb_sndbulkpipe(pHwData->udev, 4),
93 pTxBufferAddress, pMds->TxBufferSize[ SendIndex ],
94 Wb35Tx_complete, adapter);
96 pWb35Tx->EP4vm_state = VM_RUNNING;
97 retv = usb_submit_urb(pUrb, GFP_ATOMIC);
98 if (retv<0) {
99 printk("EP4 Tx Irp sending error\n");
100 goto cleanup;
103 // Check if driver needs issue Irp for EP2
104 pWb35Tx->TxFillCount += pMds->TxCountInBuffer[SendIndex];
105 if (pWb35Tx->TxFillCount > 12)
106 Wb35Tx_EP2VM_start(adapter);
108 pWb35Tx->ByteTransfer += pMds->TxBufferSize[SendIndex];
109 return;
111 cleanup:
112 pWb35Tx->EP4vm_state = VM_STOP;
113 atomic_dec(&pWb35Tx->TxFireCounter);
116 void Wb35Tx_start(struct wbsoft_priv *adapter)
118 struct hw_data * pHwData = &adapter->sHwData;
119 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
121 // Allow only one thread to run into function
122 if (atomic_inc_return(&pWb35Tx->TxFireCounter) == 1) {
123 pWb35Tx->EP4vm_state = VM_RUNNING;
124 Wb35Tx(adapter);
125 } else
126 atomic_dec(&pWb35Tx->TxFireCounter);
129 unsigned char Wb35Tx_initial(struct hw_data * pHwData)
131 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
133 pWb35Tx->Tx4Urb = usb_alloc_urb(0, GFP_ATOMIC);
134 if (!pWb35Tx->Tx4Urb)
135 return false;
137 pWb35Tx->Tx2Urb = usb_alloc_urb(0, GFP_ATOMIC);
138 if (!pWb35Tx->Tx2Urb)
140 usb_free_urb( pWb35Tx->Tx4Urb );
141 return false;
144 return true;
147 //======================================================
148 void Wb35Tx_stop(struct hw_data * pHwData)
150 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
152 // Trying to canceling the Trp of EP2
153 if (pWb35Tx->EP2vm_state == VM_RUNNING)
154 usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them
155 pr_debug("EP2 Tx stop\n");
157 // Trying to canceling the Irp of EP4
158 if (pWb35Tx->EP4vm_state == VM_RUNNING)
159 usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them
160 pr_debug("EP4 Tx stop\n");
163 //======================================================
164 void Wb35Tx_destroy(struct hw_data * pHwData)
166 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
168 // Wait for VM stop
169 do {
170 msleep(10); // Delay for waiting function enter 940623.1.a
171 } while( (pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP) );
172 msleep(10); // Delay for waiting function enter 940623.1.b
174 if (pWb35Tx->Tx4Urb)
175 usb_free_urb( pWb35Tx->Tx4Urb );
177 if (pWb35Tx->Tx2Urb)
178 usb_free_urb( pWb35Tx->Tx2Urb );
180 pr_debug("Wb35Tx_destroy OK\n");
183 void Wb35Tx_CurrentTime(struct wbsoft_priv *adapter, u32 TimeCount)
185 struct hw_data * pHwData = &adapter->sHwData;
186 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
187 unsigned char Trigger = false;
189 if (pWb35Tx->TxTimer > TimeCount)
190 Trigger = true;
191 else if (TimeCount > (pWb35Tx->TxTimer+500))
192 Trigger = true;
194 if (Trigger) {
195 pWb35Tx->TxTimer = TimeCount;
196 Wb35Tx_EP2VM_start(adapter);
200 static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter);
202 static void Wb35Tx_EP2VM_complete(struct urb * pUrb)
204 struct wbsoft_priv *adapter = pUrb->context;
205 struct hw_data * pHwData = &adapter->sHwData;
206 struct T02_descriptor T02, TSTATUS;
207 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
208 u32 * pltmp = (u32 *)pWb35Tx->EP2_buf;
209 u32 i;
210 u16 InterruptInLength;
213 // Variable setting
214 pWb35Tx->EP2vm_state = VM_COMPLETED;
215 pWb35Tx->EP2VM_status = pUrb->status;
217 // For Linux 2.4. Interrupt will always trigger
218 if (pHwData->SurpriseRemove) // Let WbWlanHalt to handle surprise remove
219 goto error;
221 if (pWb35Tx->tx_halt)
222 goto error;
224 //The Urb is completed, check the result
225 if (pWb35Tx->EP2VM_status != 0) {
226 printk("EP2 IoCompleteRoutine return error\n");
227 pWb35Tx->EP2vm_state= VM_STOP;
228 goto error;
231 // Update the Tx result
232 InterruptInLength = pUrb->actual_length;
233 // Modify for minimum memory access and DWORD alignment.
234 T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
235 InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
236 InterruptInLength >>= 2; // InterruptInLength/4
237 for (i = 1; i <= InterruptInLength; i++) {
238 T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
240 TSTATUS.value = T02.value; //20061009 anson's endian
241 Mds_SendComplete( adapter, &TSTATUS );
242 T02.value = cpu_to_le32(pltmp[i]) >> 8;
245 return;
246 error:
247 atomic_dec(&pWb35Tx->TxResultCount);
248 pWb35Tx->EP2vm_state = VM_STOP;
251 static void Wb35Tx_EP2VM(struct wbsoft_priv *adapter)
253 struct hw_data * pHwData = &adapter->sHwData;
254 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
255 struct urb * pUrb = (struct urb *)pWb35Tx->Tx2Urb;
256 u32 * pltmp = (u32 *)pWb35Tx->EP2_buf;
257 int retv;
259 if (pHwData->SurpriseRemove)
260 goto error;
262 if (pWb35Tx->tx_halt)
263 goto error;
266 // Issuing URB
268 usb_fill_int_urb( pUrb, pHwData->udev, usb_rcvintpipe(pHwData->udev,2),
269 pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, adapter, 32);
271 pWb35Tx->EP2vm_state = VM_RUNNING;
272 retv = usb_submit_urb(pUrb, GFP_ATOMIC);
274 if (retv < 0) {
275 pr_debug("EP2 Tx Irp sending error\n");
276 goto error;
279 return;
280 error:
281 pWb35Tx->EP2vm_state = VM_STOP;
282 atomic_dec(&pWb35Tx->TxResultCount);
285 void Wb35Tx_EP2VM_start(struct wbsoft_priv *adapter)
287 struct hw_data * pHwData = &adapter->sHwData;
288 struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
290 // Allow only one thread to run into function
291 if (atomic_inc_return(&pWb35Tx->TxResultCount) == 1) {
292 pWb35Tx->EP2vm_state = VM_RUNNING;
293 Wb35Tx_EP2VM(adapter);
294 } else
295 atomic_dec(&pWb35Tx->TxResultCount);