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>
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");
37 pWb35Tx
->EP4vm_state
= VM_COMPLETED
;
38 pWb35Tx
->EP4VM_status
= pUrb
->status
; //Store the last result of Irp
39 pMds
->TxOwner
[ pWb35Tx
->TxSendIndex
] = 0;// Set the owner. Free the owner bit always.
40 pWb35Tx
->TxSendIndex
++;
41 pWb35Tx
->TxSendIndex
%= MAX_USB_TX_BUFFER_NUMBER
;
43 if (pHwData
->SurpriseRemove
) // Let WbWlanHalt to handle surprise remove
49 // The URB is completed, check the result
50 if (pWb35Tx
->EP4VM_status
!= 0) {
51 printk("URB submission failed\n");
52 pWb35Tx
->EP4vm_state
= VM_STOP
;
61 atomic_dec(&pWb35Tx
->TxFireCounter
);
62 pWb35Tx
->EP4vm_state
= VM_STOP
;
65 static void Wb35Tx(struct wbsoft_priv
*adapter
)
67 struct hw_data
* pHwData
= &adapter
->sHwData
;
68 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
70 struct wb35_mds
*pMds
= &adapter
->Mds
;
71 struct urb
* pUrb
= (struct urb
*)pWb35Tx
->Tx4Urb
;
76 if (pHwData
->SurpriseRemove
)
83 SendIndex
= pWb35Tx
->TxSendIndex
;
84 if (!pMds
->TxOwner
[SendIndex
]) //No more data need to be sent, return immediately
87 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
)
140 usb_free_urb( pWb35Tx
->Tx4Urb
);
147 //======================================================
148 void Wb35Tx_stop(struct hw_data
* pHwData
)
150 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
152 // Trying to canceling the Trp of EP2
153 if (pWb35Tx
->EP2vm_state
== VM_RUNNING
)
154 usb_unlink_urb( pWb35Tx
->Tx2Urb
); // Only use unlink, let Wb35Tx_destrot to free them
155 pr_debug("EP2 Tx stop\n");
157 // Trying to canceling the Irp of EP4
158 if (pWb35Tx
->EP4vm_state
== VM_RUNNING
)
159 usb_unlink_urb( pWb35Tx
->Tx4Urb
); // Only use unlink, let Wb35Tx_destrot to free them
160 pr_debug("EP4 Tx stop\n");
163 //======================================================
164 void Wb35Tx_destroy(struct hw_data
* pHwData
)
166 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
170 msleep(10); // Delay for waiting function enter 940623.1.a
171 } while( (pWb35Tx
->EP2vm_state
!= VM_STOP
) && (pWb35Tx
->EP4vm_state
!= VM_STOP
) );
172 msleep(10); // Delay for waiting function enter 940623.1.b
175 usb_free_urb( pWb35Tx
->Tx4Urb
);
178 usb_free_urb( pWb35Tx
->Tx2Urb
);
180 pr_debug("Wb35Tx_destroy OK\n");
183 void Wb35Tx_CurrentTime(struct wbsoft_priv
*adapter
, u32 TimeCount
)
185 struct hw_data
* pHwData
= &adapter
->sHwData
;
186 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
187 unsigned char Trigger
= false;
189 if (pWb35Tx
->TxTimer
> TimeCount
)
191 else if (TimeCount
> (pWb35Tx
->TxTimer
+500))
195 pWb35Tx
->TxTimer
= TimeCount
;
196 Wb35Tx_EP2VM_start(adapter
);
200 static void Wb35Tx_EP2VM(struct wbsoft_priv
*adapter
);
202 static void Wb35Tx_EP2VM_complete(struct urb
* pUrb
)
204 struct wbsoft_priv
*adapter
= pUrb
->context
;
205 struct hw_data
* pHwData
= &adapter
->sHwData
;
206 struct T02_descriptor T02
, TSTATUS
;
207 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
208 u32
* pltmp
= (u32
*)pWb35Tx
->EP2_buf
;
210 u16 InterruptInLength
;
214 pWb35Tx
->EP2vm_state
= VM_COMPLETED
;
215 pWb35Tx
->EP2VM_status
= pUrb
->status
;
217 // For Linux 2.4. Interrupt will always trigger
218 if (pHwData
->SurpriseRemove
) // Let WbWlanHalt to handle surprise remove
221 if (pWb35Tx
->tx_halt
)
224 //The Urb is completed, check the result
225 if (pWb35Tx
->EP2VM_status
!= 0) {
226 printk("EP2 IoCompleteRoutine return error\n");
227 pWb35Tx
->EP2vm_state
= VM_STOP
;
231 // Update the Tx result
232 InterruptInLength
= pUrb
->actual_length
;
233 // Modify for minimum memory access and DWORD alignment.
234 T02
.value
= cpu_to_le32(pltmp
[0]) >> 8; // [31:8] -> [24:0]
235 InterruptInLength
-= 1;// 20051221.1.c Modify the follow for more stable
236 InterruptInLength
>>= 2; // InterruptInLength/4
237 for (i
= 1; i
<= InterruptInLength
; i
++) {
238 T02
.value
|= ((cpu_to_le32(pltmp
[i
]) & 0xff) << 24);
240 TSTATUS
.value
= T02
.value
; //20061009 anson's endian
241 Mds_SendComplete( adapter
, &TSTATUS
);
242 T02
.value
= cpu_to_le32(pltmp
[i
]) >> 8;
247 atomic_dec(&pWb35Tx
->TxResultCount
);
248 pWb35Tx
->EP2vm_state
= VM_STOP
;
251 static void Wb35Tx_EP2VM(struct wbsoft_priv
*adapter
)
253 struct hw_data
* pHwData
= &adapter
->sHwData
;
254 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
255 struct urb
* pUrb
= (struct urb
*)pWb35Tx
->Tx2Urb
;
256 u32
* pltmp
= (u32
*)pWb35Tx
->EP2_buf
;
259 if (pHwData
->SurpriseRemove
)
262 if (pWb35Tx
->tx_halt
)
268 usb_fill_int_urb( pUrb
, pHwData
->udev
, usb_rcvintpipe(pHwData
->udev
,2),
269 pltmp
, MAX_INTERRUPT_LENGTH
, Wb35Tx_EP2VM_complete
, adapter
, 32);
271 pWb35Tx
->EP2vm_state
= VM_RUNNING
;
272 retv
= usb_submit_urb(pUrb
, GFP_ATOMIC
);
275 pr_debug("EP2 Tx Irp sending error\n");
281 pWb35Tx
->EP2vm_state
= VM_STOP
;
282 atomic_dec(&pWb35Tx
->TxResultCount
);
285 void Wb35Tx_EP2VM_start(struct wbsoft_priv
*adapter
)
287 struct hw_data
* pHwData
= &adapter
->sHwData
;
288 struct wb35_tx
*pWb35Tx
= &pHwData
->Wb35Tx
;
290 // Allow only one thread to run into function
291 if (atomic_inc_return(&pWb35Tx
->TxResultCount
) == 1) {
292 pWb35Tx
->EP2vm_state
= VM_RUNNING
;
293 Wb35Tx_EP2VM(adapter
);
296 atomic_dec(&pWb35Tx
->TxResultCount
);