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