Staging: w35und: move source files to one directory
[linux-2.6] / drivers / staging / winbond / wb35tx.c
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
13 #include "wb35tx_f.h"
14 #include "mds_f.h"
15 #include "sysdef.h"
16
17 unsigned char
18 Wb35Tx_get_tx_buffer(phw_data_t pHwData, u8 **pBuffer)
19 {
20         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
21
22         *pBuffer = pWb35Tx->TxBuffer[0];
23         return true;
24 }
25
26 void Wb35Tx_start(phw_data_t pHwData)
27 {
28         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
29
30         // Allow only one thread to run into function
31         if (atomic_inc_return(&pWb35Tx->TxFireCounter) == 1) {
32                 pWb35Tx->EP4vm_state = VM_RUNNING;
33                 Wb35Tx(pHwData);
34         } else
35                 atomic_dec(&pWb35Tx->TxFireCounter);
36 }
37
38
39 void Wb35Tx(phw_data_t pHwData)
40 {
41         PWB35TX         pWb35Tx = &pHwData->Wb35Tx;
42         struct wb35_adapter *adapter = pHwData->adapter;
43         u8              *pTxBufferAddress;
44         PMDS            pMds = &adapter->Mds;
45         struct urb *    pUrb = (struct urb *)pWb35Tx->Tx4Urb;
46         int             retv;
47         u32             SendIndex;
48
49
50         if (pHwData->SurpriseRemove || pHwData->HwStop)
51                 goto cleanup;
52
53         if (pWb35Tx->tx_halt)
54                 goto cleanup;
55
56         // Ownership checking
57         SendIndex = pWb35Tx->TxSendIndex;
58         if (!pMds->TxOwner[SendIndex]) //No more data need to be sent, return immediately
59                 goto cleanup;
60
61         pTxBufferAddress = pWb35Tx->TxBuffer[SendIndex];
62         //
63         // Issuing URB
64         //
65         usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
66                           usb_sndbulkpipe(pHwData->WbUsb.udev, 4),
67                           pTxBufferAddress, pMds->TxBufferSize[ SendIndex ],
68                           Wb35Tx_complete, pHwData);
69
70         pWb35Tx->EP4vm_state = VM_RUNNING;
71         retv = usb_submit_urb(pUrb, GFP_ATOMIC);
72         if (retv<0) {
73                 printk("EP4 Tx Irp sending error\n");
74                 goto cleanup;
75         }
76
77         // Check if driver needs issue Irp for EP2
78         pWb35Tx->TxFillCount += pMds->TxCountInBuffer[SendIndex];
79         if (pWb35Tx->TxFillCount > 12)
80                 Wb35Tx_EP2VM_start( pHwData );
81
82         pWb35Tx->ByteTransfer += pMds->TxBufferSize[SendIndex];
83         return;
84
85  cleanup:
86         pWb35Tx->EP4vm_state = VM_STOP;
87         atomic_dec(&pWb35Tx->TxFireCounter);
88 }
89
90
91 void Wb35Tx_complete(struct urb * pUrb)
92 {
93         phw_data_t      pHwData = pUrb->context;
94         struct wb35_adapter *adapter = pHwData->adapter;
95         PWB35TX         pWb35Tx = &pHwData->Wb35Tx;
96         PMDS            pMds = &adapter->Mds;
97
98         printk("wb35: tx complete\n");
99         // Variable setting
100         pWb35Tx->EP4vm_state = VM_COMPLETED;
101         pWb35Tx->EP4VM_status = pUrb->status; //Store the last result of Irp
102         pMds->TxOwner[ pWb35Tx->TxSendIndex ] = 0;// Set the owner. Free the owner bit always.
103         pWb35Tx->TxSendIndex++;
104         pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER;
105
106         if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
107                 goto error;
108
109         if (pWb35Tx->tx_halt)
110                 goto error;
111
112         // The URB is completed, check the result
113         if (pWb35Tx->EP4VM_status != 0) {
114                 printk("URB submission failed\n");
115                 pWb35Tx->EP4vm_state = VM_STOP;
116                 goto error;
117         }
118
119         Mds_Tx(adapter);
120         Wb35Tx(pHwData);
121         return;
122
123 error:
124         atomic_dec(&pWb35Tx->TxFireCounter);
125         pWb35Tx->EP4vm_state = VM_STOP;
126 }
127
128 void Wb35Tx_reset_descriptor(  phw_data_t pHwData )
129 {
130         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
131
132         pWb35Tx->TxSendIndex = 0;
133         pWb35Tx->tx_halt = 0;
134 }
135
136 unsigned char Wb35Tx_initial(phw_data_t pHwData)
137 {
138         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
139
140         pWb35Tx->Tx4Urb = usb_alloc_urb(0, GFP_ATOMIC);
141         if (!pWb35Tx->Tx4Urb)
142                 return false;
143
144         pWb35Tx->Tx2Urb = usb_alloc_urb(0, GFP_ATOMIC);
145         if (!pWb35Tx->Tx2Urb)
146         {
147                 usb_free_urb( pWb35Tx->Tx4Urb );
148                 return false;
149         }
150
151         return true;
152 }
153
154 //======================================================
155 void Wb35Tx_stop(phw_data_t pHwData)
156 {
157         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
158
159         // Trying to canceling the Trp of EP2
160         if (pWb35Tx->EP2vm_state == VM_RUNNING)
161                 usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them
162         #ifdef _PE_TX_DUMP_
163         WBDEBUG(("EP2 Tx stop\n"));
164         #endif
165
166         // Trying to canceling the Irp of EP4
167         if (pWb35Tx->EP4vm_state == VM_RUNNING)
168                 usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them
169         #ifdef _PE_TX_DUMP_
170         WBDEBUG(("EP4 Tx stop\n"));
171         #endif
172 }
173
174 //======================================================
175 void Wb35Tx_destroy(phw_data_t pHwData)
176 {
177         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
178
179         // Wait for VM stop
180         do {
181                 msleep(10);  // Delay for waiting function enter 940623.1.a
182         } while( (pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP) );
183         msleep(10);  // Delay for waiting function enter 940623.1.b
184
185         if (pWb35Tx->Tx4Urb)
186                 usb_free_urb( pWb35Tx->Tx4Urb );
187
188         if (pWb35Tx->Tx2Urb)
189                 usb_free_urb( pWb35Tx->Tx2Urb );
190
191         #ifdef _PE_TX_DUMP_
192         WBDEBUG(("Wb35Tx_destroy OK\n"));
193         #endif
194 }
195
196 void Wb35Tx_CurrentTime(phw_data_t pHwData, u32 TimeCount)
197 {
198         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
199         unsigned char Trigger = false;
200
201         if (pWb35Tx->TxTimer > TimeCount)
202                 Trigger = true;
203         else if (TimeCount > (pWb35Tx->TxTimer+500))
204                 Trigger = true;
205
206         if (Trigger) {
207                 pWb35Tx->TxTimer = TimeCount;
208                 Wb35Tx_EP2VM_start( pHwData );
209         }
210 }
211
212 void Wb35Tx_EP2VM_start(phw_data_t pHwData)
213 {
214         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
215
216         // Allow only one thread to run into function
217         if (atomic_inc_return(&pWb35Tx->TxResultCount) == 1) {
218                 pWb35Tx->EP2vm_state = VM_RUNNING;
219                 Wb35Tx_EP2VM( pHwData );
220         }
221         else
222                 atomic_dec(&pWb35Tx->TxResultCount);
223 }
224
225
226 void Wb35Tx_EP2VM(phw_data_t pHwData)
227 {
228         PWB35TX pWb35Tx = &pHwData->Wb35Tx;
229         struct urb *    pUrb = (struct urb *)pWb35Tx->Tx2Urb;
230         u32 *   pltmp = (u32 *)pWb35Tx->EP2_buf;
231         int             retv;
232
233         if (pHwData->SurpriseRemove || pHwData->HwStop)
234                 goto error;
235
236         if (pWb35Tx->tx_halt)
237                 goto error;
238
239         //
240         // Issuing URB
241         //
242         usb_fill_int_urb( pUrb, pHwData->WbUsb.udev, usb_rcvintpipe(pHwData->WbUsb.udev,2),
243                           pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, pHwData, 32);
244
245         pWb35Tx->EP2vm_state = VM_RUNNING;
246         retv = usb_submit_urb(pUrb, GFP_ATOMIC);
247
248         if (retv < 0) {
249                 #ifdef _PE_TX_DUMP_
250                 WBDEBUG(("EP2 Tx Irp sending error\n"));
251                 #endif
252                 goto error;
253         }
254
255         return;
256 error:
257         pWb35Tx->EP2vm_state = VM_STOP;
258         atomic_dec(&pWb35Tx->TxResultCount);
259 }
260
261
262 void Wb35Tx_EP2VM_complete(struct urb * pUrb)
263 {
264         phw_data_t      pHwData = pUrb->context;
265         T02_DESCRIPTOR  T02, TSTATUS;
266         struct wb35_adapter *adapter = pHwData->adapter;
267         PWB35TX         pWb35Tx = &pHwData->Wb35Tx;
268         u32 *           pltmp = (u32 *)pWb35Tx->EP2_buf;
269         u32             i;
270         u16             InterruptInLength;
271
272
273         // Variable setting
274         pWb35Tx->EP2vm_state = VM_COMPLETED;
275         pWb35Tx->EP2VM_status = pUrb->status;
276
277         // For Linux 2.4. Interrupt will always trigger
278         if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
279                 goto error;
280
281         if (pWb35Tx->tx_halt)
282                 goto error;
283
284         //The Urb is completed, check the result
285         if (pWb35Tx->EP2VM_status != 0) {
286                 WBDEBUG(("EP2 IoCompleteRoutine return error\n"));
287                 pWb35Tx->EP2vm_state= VM_STOP;
288                 goto error;
289         }
290
291         // Update the Tx result
292         InterruptInLength = pUrb->actual_length;
293         // Modify for minimum memory access and DWORD alignment.
294         T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
295         InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
296         InterruptInLength >>= 2; // InterruptInLength/4
297         for (i = 1; i <= InterruptInLength; i++) {
298                 T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
299
300                 TSTATUS.value = T02.value;  //20061009 anson's endian
301                 Mds_SendComplete( adapter, &TSTATUS );
302                 T02.value = cpu_to_le32(pltmp[i]) >> 8;
303         }
304
305         return;
306 error:
307         atomic_dec(&pWb35Tx->TxResultCount);
308         pWb35Tx->EP2vm_state = VM_STOP;
309 }
310