Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
10 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1996-1999 Microsoft Corporation
  4. *
  5. * @doc
  6. * @module send.c | IrSIR NDIS Miniport Driver
  7. * @comm
  8. *
  9. *-----------------------------------------------------------------------------
  10. *
  11. * Author: Scott Holden (sholden)
  12. *
  13. * Date: 10/4/1996 (created)
  14. *
  15. * Contents:
  16. *
  17. *****************************************************************************/
  18. #include "irsir.h"
  19. //
  20. // Declarations.
  21. //
  22. NDIS_STATUS SendPacket(
  23. IN PIR_DEVICE pThisDev,
  24. IN PNDIS_PACKET Packet,
  25. IN UINT Flags
  26. );
  27. NTSTATUS SerialIoCompleteWrite(
  28. IN PDEVICE_OBJECT pSerialDevObj,
  29. IN PIRP pIrp,
  30. IN PVOID Context
  31. );
  32. VOID
  33. SendPacketToSerial(
  34. PVOID Context,
  35. PNDIS_PACKET Packet
  36. )
  37. {
  38. PIR_DEVICE pThisDev=(PIR_DEVICE)Context;
  39. NDIS_STATUS status;
  40. PPACKET_RESERVED_BLOCK Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
  41. Reserved->Context=pThisDev;
  42. status = SendPacket(
  43. pThisDev,
  44. Packet,
  45. 0
  46. );
  47. if (status != NDIS_STATUS_PENDING) {
  48. //
  49. // failed for some reason
  50. //
  51. NdisMSendComplete(
  52. pThisDev->hNdisAdapter,
  53. Packet,
  54. (NDIS_STATUS)status
  55. );
  56. //
  57. // This packet is finished, start the next on in the queue
  58. //
  59. StartNextPacket(&pThisDev->SendPacketQueue);
  60. }
  61. //
  62. // the write irp completion routine will finish things up
  63. //
  64. return;
  65. }
  66. /*****************************************************************************
  67. *
  68. * Function: IrsirSend
  69. *
  70. * Synopsis: Send a packet to the serial driver or queue the packet to
  71. * be sent at a later time if a send is pending.
  72. *
  73. * Arguments: MiniportAdapterContext - pointer to current ir device object
  74. * pPacketToSend - pointer to packet to send
  75. * Flags - any flags set by protocol
  76. *
  77. * Returns: NDIS_STATUS_PENDING - This is generally what we should
  78. * return. We will call NdisMSendComplete
  79. * when the serial driver completes the
  80. * send.
  81. *
  82. * NDIS_STATUS_SUCCESS - We should never return this since
  83. * results will always be pending from
  84. * the serial driver.
  85. *
  86. * Algorithm:
  87. *
  88. * History: dd-mm-yyyy Author Comment
  89. * 10/7/1996 sholden author
  90. *
  91. * Notes:
  92. *
  93. *
  94. *****************************************************************************/
  95. NDIS_STATUS
  96. IrsirSend(
  97. IN NDIS_HANDLE MiniportAdapterContext,
  98. IN PNDIS_PACKET pPacketToSend,
  99. IN UINT Flags
  100. )
  101. {
  102. PIR_DEVICE pThisDev;
  103. BOOLEAN fCompletionRoutine;
  104. NDIS_STATUS status;
  105. DEBUGMSG(DBG_FUNC, ("+IrsirSend\n"));
  106. pThisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
  107. if (pThisDev->pSerialDevObj==NULL) {
  108. return NDIS_STATUS_SUCCESS;
  109. }
  110. QueuePacket(
  111. &pThisDev->SendPacketQueue,
  112. pPacketToSend
  113. );
  114. DEBUGMSG(DBG_FUNC, ("-IrsirSend\n"));
  115. return NDIS_STATUS_PENDING;
  116. }
  117. /*****************************************************************************
  118. *
  119. * Function: SendPacket
  120. *
  121. * Synopsis:
  122. *
  123. * Arguments: pThisDev - a pointer to the current ir device object
  124. * pPacketToSend -
  125. * Flags -
  126. * fCompletionRoutine - return TRUE if the completion routine will
  127. * be called
  128. * - else return FALSE
  129. *
  130. * Returns: NDIS_STATUS_PENDING - if irp is successfully sent to the serial
  131. * driver
  132. * NDIS_STATUS_INVALID_PACKET - if NdisToIrPacket fails
  133. * STATUS_Xxx - if IoCallDriver fails
  134. *
  135. * Algorithm:
  136. *
  137. * History: dd-mm-yyyy Author Comment
  138. * 10/7/1996 sholden author
  139. *
  140. * Notes:
  141. *
  142. * Since we know that we will only have one pending IRP_MJ_WRITE request at
  143. * a time, we will build an irp once in IrsirInitialize and keep it in the
  144. * ir device object, so we don't have to allocate it all the time and
  145. * allocate a new buffer all the time.
  146. *
  147. *
  148. *****************************************************************************/
  149. NDIS_STATUS
  150. SendPacket(
  151. IN PIR_DEVICE pThisDev,
  152. IN PNDIS_PACKET pPacketToSend,
  153. IN UINT Flags
  154. )
  155. {
  156. PIRP pSendIrp;
  157. UINT BytesToWrite;
  158. NDIS_STATUS status;
  159. BOOLEAN fConvertedPacket;
  160. DEBUGMSG(DBG_FUNC, ("+SendPacket\n"));
  161. //
  162. // Initialize the mem of our buffer and io status block.
  163. //
  164. #if DBG
  165. NdisZeroMemory(
  166. pThisDev->pSendIrpBuffer,
  167. MAX_IRDA_DATA_SIZE
  168. );
  169. #endif
  170. //
  171. // Assume that the irp is all set with the proper parameters, all we
  172. // need to do is convert the packet to an ir frame and copy into our buffer
  173. // and send the irp.
  174. //
  175. fConvertedPacket = NdisToIrPacket(
  176. pThisDev,
  177. pPacketToSend,
  178. (PUCHAR)pThisDev->pSendIrpBuffer,
  179. MAX_IRDA_DATA_SIZE,
  180. &BytesToWrite
  181. );
  182. if (fConvertedPacket == FALSE)
  183. {
  184. DEBUGMSG(DBG_ERR, (" NdisToIrPacket failed. Couldn't convert packet!\n"));
  185. status = NDIS_STATUS_INVALID_PACKET;
  186. goto done;
  187. }
  188. {
  189. LARGE_INTEGER Time;
  190. KeQuerySystemTime(&Time);
  191. LOG_ENTRY('XT', pThisDev, Time.LowPart/10000, BytesToWrite);
  192. }
  193. pSendIrp = SerialBuildReadWriteIrp(
  194. pThisDev->pSerialDevObj,
  195. IRP_MJ_WRITE,
  196. pThisDev->pSendIrpBuffer,
  197. BytesToWrite,
  198. NULL
  199. );
  200. if (pSendIrp == NULL)
  201. {
  202. DEBUGMSG(DBG_ERR, (" SerialBuildReadWriteIrp failed.\n"));
  203. status = NDIS_STATUS_RESOURCES;
  204. goto done;
  205. }
  206. //
  207. // Set up the completion routine for the write irp.
  208. //
  209. IoSetCompletionRoutine(
  210. pSendIrp, // irp to use
  211. SerialIoCompleteWrite, // routine to call when irp is done
  212. pPacketToSend,
  213. TRUE, // call on success
  214. TRUE, // call on error
  215. TRUE // call on cancel
  216. );
  217. //
  218. // Call IoCallDriver to send the irp to the serial port.
  219. //
  220. DBGTIME("Send ");
  221. //
  222. // The completion routine will be called no matter what the status
  223. // of IoCallDriver is.
  224. //
  225. status=NDIS_STATUS_PENDING;
  226. IoCallDriver(
  227. pThisDev->pSerialDevObj,
  228. pSendIrp
  229. );
  230. done:
  231. DEBUGMSG(DBG_FUNC, ("-SendPacket\n"));
  232. return status;
  233. }
  234. /*****************************************************************************
  235. *
  236. * Function: SerialIoCompleteWrite
  237. *
  238. * Synopsis:
  239. *
  240. * Arguments: pSerialDevObj - pointer to the serial device object which
  241. * completed the irp
  242. * pIrp - the irp which was completed by the serial
  243. * device object
  244. * Context - the context given to IoSetCompletionRoutine
  245. * before calling IoCallDriver on the irp
  246. * The Context is a pointer to the ir device object.
  247. *
  248. * Returns: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
  249. * (IofCompleteRequest) to stop working on the irp.
  250. *
  251. * Algorithm:
  252. * 1a) Indicate to the protocol the status of the write.
  253. * 1b) Return ownership of the packet to the protocol.
  254. *
  255. * 2) If any more packets are queue for sending, send another packet
  256. * to the serial driver.
  257. * If the attempt to send the packet to the serial driver fails,
  258. * return ownership of the packet to the protocol and
  259. * try another packet (until one succeeds).
  260. *
  261. * History: dd-mm-yyyy Author Comment
  262. * 10/8/1996 sholden author
  263. *
  264. * Notes:
  265. *
  266. *
  267. *****************************************************************************/
  268. NTSTATUS
  269. SerialIoCompleteWrite(
  270. IN PDEVICE_OBJECT pSerialDevObj,
  271. IN PIRP pIrp,
  272. IN PVOID Context
  273. )
  274. {
  275. PIR_DEVICE pThisDev;
  276. PNDIS_PACKET pPacketToSend;
  277. NTSTATUS status;
  278. PPACKET_RESERVED_BLOCK Reserved;
  279. DEBUGMSG(DBG_FUNC, ("+SerialIoCompleteWrite\n"));
  280. //
  281. // The context given to IoSetCompletionRoutine is simply the the ir
  282. // device object pointer.
  283. //
  284. pPacketToSend=(PNDIS_PACKET)Context;
  285. Reserved=(PPACKET_RESERVED_BLOCK)&pPacketToSend->MiniportReservedEx[0];
  286. pThisDev = (PIR_DEVICE)Reserved->Context;
  287. status = pIrp->IoStatus.Status;
  288. //
  289. // Free the irp. We keep our buffer and user io status block.
  290. //
  291. IoFreeIrp(pIrp);
  292. pIrp=NULL;
  293. {
  294. LARGE_INTEGER Time;
  295. KeQuerySystemTime(&Time);
  296. LOG_ENTRY('CT', pThisDev, Time.LowPart/10000, status);
  297. }
  298. //
  299. // Keep statistics.
  300. //
  301. if (status == STATUS_SUCCESS) {
  302. pThisDev->packetsSent++;
  303. } else {
  304. pThisDev->packetsSentDropped++;
  305. }
  306. //
  307. // Indicate to the protocol the status of the sent packet and return
  308. // ownership of the packet.
  309. //
  310. NdisMSendComplete(
  311. pThisDev->hNdisAdapter,
  312. pPacketToSend,
  313. (NDIS_STATUS)status
  314. );
  315. //////////////////////////////////////////////////////////////
  316. //
  317. // We have completed a packet. Start another if there is one
  318. // on the send queue.
  319. //
  320. //////////////////////////////////////////////////////////////
  321. StartNextPacket(&pThisDev->SendPacketQueue);
  322. DEBUGMSG(DBG_FUNC, ("-SerialIoCompleteWrite\n"));
  323. return STATUS_MORE_PROCESSING_REQUIRED;
  324. }