2 * Copyright (c) 1996-2002 Winbond Electronic Corporation
8 * Processing the Tx message and put into down layer
11 #include <linux/usb.h>
12 #include <linux/gfp.h>
18 Wb35Tx_get_tx_buffer(struct hw_data
*pHwData
, u8
**pBuffer
)
20 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
22 *pBuffer
= pWb35Tx
->TxBuffer
[0];
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 /* Set the owner. Free the owner bit always. */
40 pMds
->TxOwner
[pWb35Tx
->TxSendIndex
] = 0;
41 pWb35Tx
->TxSendIndex
++;
42 pWb35Tx
->TxSendIndex
%= MAX_USB_TX_BUFFER_NUMBER
;
44 if (pHwData
->SurpriseRemove
) /* Let WbWlanHalt 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
;
76 if (pHwData
->SurpriseRemove
)
82 /* Ownership checking */
83 SendIndex
= pWb35Tx
->TxSendIndex
;
84 /* No more data need to be sent, return immediately */
85 if (!pMds
->TxOwner
[SendIndex
])
88 pTxBufferAddress
= pWb35Tx
->TxBuffer
[SendIndex
];
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
);
99 printk("EP4 Tx Irp sending error\n");
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
];
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
;
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
)
137 pWb35Tx
->Tx2Urb
= usb_alloc_urb(0, GFP_ATOMIC
);
138 if (!pWb35Tx
->Tx2Urb
) {
139 usb_free_urb(pWb35Tx
->Tx4Urb
);
146 void Wb35Tx_stop(struct hw_data
*pHwData
)
148 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
150 /* Try to cancel the Trp of EP2 */
151 if (pWb35Tx
->EP2vm_state
== VM_RUNNING
)
152 /* Only use unlink, let Wb35Tx_destroy free them */
153 usb_unlink_urb(pWb35Tx
->Tx2Urb
);
154 pr_debug("EP2 Tx stop\n");
156 /* Try to cancel the Irp of EP4 */
157 if (pWb35Tx
->EP4vm_state
== VM_RUNNING
)
158 /* Only use unlink, let Wb35Tx_destroy free them */
159 usb_unlink_urb(pWb35Tx
->Tx4Urb
);
160 pr_debug("EP4 Tx stop\n");
163 void Wb35Tx_destroy(struct hw_data
*pHwData
)
165 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
167 /* Wait for VM stop */
169 msleep(10); /* Delay for waiting function enter 940623.1.a */
170 } while ((pWb35Tx
->EP2vm_state
!= VM_STOP
) && (pWb35Tx
->EP4vm_state
!= VM_STOP
));
171 msleep(10); /* Delay for waiting function enter 940623.1.b */
173 usb_free_urb(pWb35Tx
->Tx4Urb
);
174 usb_free_urb(pWb35Tx
->Tx2Urb
);
176 pr_debug("Wb35Tx_destroy OK\n");
179 void Wb35Tx_CurrentTime(struct wbsoft_priv
*adapter
, u32 TimeCount
)
181 struct hw_data
*pHwData
= &adapter
->sHwData
;
182 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
183 bool Trigger
= false;
185 if (pWb35Tx
->TxTimer
> TimeCount
)
187 else if (TimeCount
> (pWb35Tx
->TxTimer
+500))
191 pWb35Tx
->TxTimer
= TimeCount
;
192 Wb35Tx_EP2VM_start(adapter
);
196 static void Wb35Tx_EP2VM(struct wbsoft_priv
*adapter
);
198 static void Wb35Tx_EP2VM_complete(struct urb
*pUrb
)
200 struct wbsoft_priv
*adapter
= pUrb
->context
;
201 struct hw_data
*pHwData
= &adapter
->sHwData
;
202 struct T02_descriptor T02
, TSTATUS
;
203 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
204 u32
*pltmp
= (u32
*)pWb35Tx
->EP2_buf
;
206 u16 InterruptInLength
;
208 /* Variable setting */
209 pWb35Tx
->EP2vm_state
= VM_COMPLETED
;
210 pWb35Tx
->EP2VM_status
= pUrb
->status
;
212 /* For Linux 2.4. Interrupt will always trigger */
213 if (pHwData
->SurpriseRemove
) /* Let WbWlanHalt handle surprise remove */
216 if (pWb35Tx
->tx_halt
)
219 /* The Urb is completed, check the result */
220 if (pWb35Tx
->EP2VM_status
!= 0) {
221 printk("EP2 IoCompleteRoutine return error\n");
222 pWb35Tx
->EP2vm_state
= VM_STOP
;
226 /* Update the Tx result */
227 InterruptInLength
= pUrb
->actual_length
;
228 /* Modify for minimum memory access and DWORD alignment. */
229 T02
.value
= cpu_to_le32(pltmp
[0]) >> 8; /* [31:8] -> [24:0] */
230 InterruptInLength
-= 1; /* 20051221.1.c Modify the follow for more stable */
231 InterruptInLength
>>= 2; /* InterruptInLength/4 */
232 for (i
= 1; i
<= InterruptInLength
; i
++) {
233 T02
.value
|= ((cpu_to_le32(pltmp
[i
]) & 0xff) << 24);
235 TSTATUS
.value
= T02
.value
; /* 20061009 anson's endian */
236 Mds_SendComplete(adapter
, &TSTATUS
);
237 T02
.value
= cpu_to_le32(pltmp
[i
]) >> 8;
242 atomic_dec(&pWb35Tx
->TxResultCount
);
243 pWb35Tx
->EP2vm_state
= VM_STOP
;
246 static void Wb35Tx_EP2VM(struct wbsoft_priv
*adapter
)
248 struct hw_data
*pHwData
= &adapter
->sHwData
;
249 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
250 struct urb
*pUrb
= (struct urb
*)pWb35Tx
->Tx2Urb
;
251 u32
*pltmp
= (u32
*)pWb35Tx
->EP2_buf
;
254 if (pHwData
->SurpriseRemove
)
257 if (pWb35Tx
->tx_halt
)
261 usb_fill_int_urb(pUrb
, pHwData
->udev
, usb_rcvintpipe(pHwData
->udev
, 2),
262 pltmp
, MAX_INTERRUPT_LENGTH
, Wb35Tx_EP2VM_complete
,
265 pWb35Tx
->EP2vm_state
= VM_RUNNING
;
266 retv
= usb_submit_urb(pUrb
, GFP_ATOMIC
);
269 pr_debug("EP2 Tx Irp sending error\n");
275 pWb35Tx
->EP2vm_state
= VM_STOP
;
276 atomic_dec(&pWb35Tx
->TxResultCount
);
279 void Wb35Tx_EP2VM_start(struct wbsoft_priv
*adapter
)
281 struct hw_data
*pHwData
= &adapter
->sHwData
;
282 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
284 /* Allow only one thread to run into function */
285 if (atomic_inc_return(&pWb35Tx
->TxResultCount
) == 1) {
286 pWb35Tx
->EP2vm_state
= VM_RUNNING
;
287 Wb35Tx_EP2VM(adapter
);
289 atomic_dec(&pWb35Tx
->TxResultCount
);