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
);