wb35tx.c 7.4 KB

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