1 //============================================================================
2 // Copyright (c) 1996-2002 Winbond Electronic Corporation
8 // Processing the Tx message and put into down layer
10 //============================================================================
15 Wb35Tx_get_tx_buffer(phw_data_t pHwData
, PUCHAR
*pBuffer
)
17 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
19 *pBuffer
= pWb35Tx
->TxBuffer
[0];
23 void Wb35Tx_start(phw_data_t pHwData
)
25 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
27 // Allow only one thread to run into function
28 if (OS_ATOMIC_INC(pHwData
->Adapter
, &pWb35Tx
->TxFireCounter
) == 1) {
29 pWb35Tx
->EP4vm_state
= VM_RUNNING
;
32 OS_ATOMIC_DEC( pHwData
->Adapter
, &pWb35Tx
->TxFireCounter
);
36 void Wb35Tx(phw_data_t pHwData
)
38 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
39 PADAPTER Adapter
= pHwData
->Adapter
;
40 PUCHAR pTxBufferAddress
;
41 PMDS pMds
= &Adapter
->Mds
;
42 struct urb
* pUrb
= (struct urb
*)pWb35Tx
->Tx4Urb
;
47 if (pHwData
->SurpriseRemove
|| pHwData
->HwStop
)
54 SendIndex
= pWb35Tx
->TxSendIndex
;
55 if (!pMds
->TxOwner
[SendIndex
]) //No more data need to be sent, return immediately
58 pTxBufferAddress
= pWb35Tx
->TxBuffer
[SendIndex
];
62 usb_fill_bulk_urb(pUrb
, pHwData
->WbUsb
.udev
,
63 usb_sndbulkpipe(pHwData
->WbUsb
.udev
, 4),
64 pTxBufferAddress
, pMds
->TxBufferSize
[ SendIndex
],
65 Wb35Tx_complete
, pHwData
);
67 pWb35Tx
->EP4vm_state
= VM_RUNNING
;
68 retv
= wb_usb_submit_urb( pUrb
);
70 printk("EP4 Tx Irp sending error\n");
74 // Check if driver needs issue Irp for EP2
75 pWb35Tx
->TxFillCount
+= pMds
->TxCountInBuffer
[SendIndex
];
76 if (pWb35Tx
->TxFillCount
> 12)
77 Wb35Tx_EP2VM_start( pHwData
);
79 pWb35Tx
->ByteTransfer
+= pMds
->TxBufferSize
[SendIndex
];
83 pWb35Tx
->EP4vm_state
= VM_STOP
;
84 OS_ATOMIC_DEC( pHwData
->Adapter
, &pWb35Tx
->TxFireCounter
);
88 void Wb35Tx_complete(struct urb
* pUrb
)
90 phw_data_t pHwData
= pUrb
->context
;
91 PADAPTER Adapter
= (PADAPTER
)pHwData
->Adapter
;
92 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
93 PMDS pMds
= &Adapter
->Mds
;
95 printk("wb35: tx complete\n");
97 pWb35Tx
->EP4vm_state
= VM_COMPLETED
;
98 pWb35Tx
->EP4VM_status
= pUrb
->status
; //Store the last result of Irp
99 pMds
->TxOwner
[ pWb35Tx
->TxSendIndex
] = 0;// Set the owner. Free the owner bit always.
100 pWb35Tx
->TxSendIndex
++;
101 pWb35Tx
->TxSendIndex
%= MAX_USB_TX_BUFFER_NUMBER
;
104 if (pHwData
->SurpriseRemove
|| pHwData
->HwStop
) // Let WbWlanHalt to handle surprise remove
107 if (pWb35Tx
->tx_halt
)
110 // The URB is completed, check the result
111 if (pWb35Tx
->EP4VM_status
!= 0) {
112 printk("URB submission failed\n");
113 pWb35Tx
->EP4vm_state
= VM_STOP
;
114 break; // Exit while(FALSE);
122 OS_ATOMIC_DEC( pHwData
->Adapter
, &pWb35Tx
->TxFireCounter
);
123 pWb35Tx
->EP4vm_state
= VM_STOP
;
126 void Wb35Tx_reset_descriptor( phw_data_t pHwData
)
128 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
130 pWb35Tx
->TxSendIndex
= 0;
131 pWb35Tx
->tx_halt
= 0;
134 unsigned char Wb35Tx_initial(phw_data_t pHwData
)
136 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
138 pWb35Tx
->Tx4Urb
= wb_usb_alloc_urb(0);
139 if (!pWb35Tx
->Tx4Urb
)
142 pWb35Tx
->Tx2Urb
= wb_usb_alloc_urb(0);
143 if (!pWb35Tx
->Tx2Urb
)
145 usb_free_urb( pWb35Tx
->Tx4Urb
);
152 //======================================================
153 void Wb35Tx_stop(phw_data_t pHwData
)
155 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
157 // Trying to canceling the Trp of EP2
158 if (pWb35Tx
->EP2vm_state
== VM_RUNNING
)
159 usb_unlink_urb( pWb35Tx
->Tx2Urb
); // Only use unlink, let Wb35Tx_destrot to free them
161 WBDEBUG(("EP2 Tx stop\n"));
164 // Trying to canceling the Irp of EP4
165 if (pWb35Tx
->EP4vm_state
== VM_RUNNING
)
166 usb_unlink_urb( pWb35Tx
->Tx4Urb
); // Only use unlink, let Wb35Tx_destrot to free them
168 WBDEBUG(("EP4 Tx stop\n"));
172 //======================================================
173 void Wb35Tx_destroy(phw_data_t pHwData
)
175 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
179 OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
180 } while( (pWb35Tx
->EP2vm_state
!= VM_STOP
) && (pWb35Tx
->EP4vm_state
!= VM_STOP
) );
181 OS_SLEEP(10000); // Delay for waiting function enter 940623.1.b
184 usb_free_urb( pWb35Tx
->Tx4Urb
);
187 usb_free_urb( pWb35Tx
->Tx2Urb
);
190 WBDEBUG(("Wb35Tx_destroy OK\n"));
194 void Wb35Tx_CurrentTime(phw_data_t pHwData
, u32 TimeCount
)
196 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
197 unsigned char Trigger
= FALSE
;
199 if (pWb35Tx
->TxTimer
> TimeCount
)
201 else if (TimeCount
> (pWb35Tx
->TxTimer
+500))
205 pWb35Tx
->TxTimer
= TimeCount
;
206 Wb35Tx_EP2VM_start( pHwData
);
210 void Wb35Tx_EP2VM_start(phw_data_t pHwData
)
212 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
214 // Allow only one thread to run into function
215 if (OS_ATOMIC_INC( pHwData
->Adapter
, &pWb35Tx
->TxResultCount
) == 1) {
216 pWb35Tx
->EP2vm_state
= VM_RUNNING
;
217 Wb35Tx_EP2VM( pHwData
);
220 OS_ATOMIC_DEC( pHwData
->Adapter
, &pWb35Tx
->TxResultCount
);
224 void Wb35Tx_EP2VM(phw_data_t pHwData
)
226 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
227 struct urb
* pUrb
= (struct urb
*)pWb35Tx
->Tx2Urb
;
228 PULONG pltmp
= (PULONG
)pWb35Tx
->EP2_buf
;
232 if (pHwData
->SurpriseRemove
|| pHwData
->HwStop
)
235 if (pWb35Tx
->tx_halt
)
241 usb_fill_int_urb( pUrb
, pHwData
->WbUsb
.udev
, usb_rcvintpipe(pHwData
->WbUsb
.udev
,2),
242 pltmp
, MAX_INTERRUPT_LENGTH
, Wb35Tx_EP2VM_complete
, pHwData
, 32);
244 pWb35Tx
->EP2vm_state
= VM_RUNNING
;
245 retv
= wb_usb_submit_urb( pUrb
);
249 WBDEBUG(("EP2 Tx Irp sending error\n"));
258 pWb35Tx
->EP2vm_state
= VM_STOP
;
259 OS_ATOMIC_DEC( pHwData
->Adapter
, &pWb35Tx
->TxResultCount
);
263 void Wb35Tx_EP2VM_complete(struct urb
* pUrb
)
265 phw_data_t pHwData
= pUrb
->context
;
266 T02_DESCRIPTOR T02
, TSTATUS
;
267 PADAPTER Adapter
= (PADAPTER
)pHwData
->Adapter
;
268 PWB35TX pWb35Tx
= &pHwData
->Wb35Tx
;
269 PULONG pltmp
= (PULONG
)pWb35Tx
->EP2_buf
;
271 u16 InterruptInLength
;
275 pWb35Tx
->EP2vm_state
= VM_COMPLETED
;
276 pWb35Tx
->EP2VM_status
= pUrb
->status
;
279 // For Linux 2.4. Interrupt will always trigger
280 if( pHwData
->SurpriseRemove
|| pHwData
->HwStop
) // Let WbWlanHalt to handle surprise remove
283 if( pWb35Tx
->tx_halt
)
286 //The Urb is completed, check the result
287 if (pWb35Tx
->EP2VM_status
!= 0) {
288 WBDEBUG(("EP2 IoCompleteRoutine return error\n"));
289 pWb35Tx
->EP2vm_state
= VM_STOP
;
290 break; // Exit while(FALSE);
293 // Update the Tx result
294 InterruptInLength
= pUrb
->actual_length
;
295 // Modify for minimum memory access and DWORD alignment.
296 T02
.value
= cpu_to_le32(pltmp
[0]) >> 8; // [31:8] -> [24:0]
297 InterruptInLength
-= 1;// 20051221.1.c Modify the follow for more stable
298 InterruptInLength
>>= 2; // InterruptInLength/4
299 for (i
=1; i
<=InterruptInLength
; i
++) {
300 T02
.value
|= ((cpu_to_le32(pltmp
[i
]) & 0xff) << 24);
302 TSTATUS
.value
= T02
.value
; //20061009 anson's endian
303 Mds_SendComplete( Adapter
, &TSTATUS
);
304 T02
.value
= cpu_to_le32(pltmp
[i
]) >> 8;
310 OS_ATOMIC_DEC( pHwData
->Adapter
, &pWb35Tx
->TxResultCount
);
311 pWb35Tx
->EP2vm_state
= VM_STOP
;