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.

451 lines
13 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1996-1999 Microsoft Corporation
  4. *
  5. * @doc
  6. * @module irsir.h | IrSIR NDIS Miniport Driver
  7. * @comm
  8. *
  9. *-----------------------------------------------------------------------------
  10. *
  11. * Author: Scott Holden (sholden)
  12. *
  13. * Date: 10/1/1996 (created)
  14. *
  15. * Contents:
  16. *
  17. *****************************************************************************/
  18. #ifndef _IRSIR_H
  19. #define _IRSIR_H
  20. #define IRSIR_EVENT_DRIVEN 0
  21. //
  22. // BINARY_COMPATIBLE = 0 is required so that we can include both
  23. // ntos.h and ndis.h (it is a flag in ndis.h). I think that it
  24. // is a flag to be binary compatible with Win95; however, since
  25. // we are using I/O manager we won't be.
  26. //
  27. #define BINARY_COMPATIBLE 0
  28. #include <ntosp.h>
  29. #include <zwapi.h>
  30. #include <ndis.h>
  31. #include <ntddndis.h> // defines OID's
  32. #include <ntddser.h> // defines structs to access serial info
  33. #include "debug.h"
  34. #include "ioctl.h"
  35. #include "settings.h"
  36. #include "queue.h"
  37. //
  38. // NDIS version compatibility.
  39. //
  40. #define NDIS_MAJOR_VERSION 5
  41. #define NDIS_MINOR_VERSION 0
  42. //
  43. // Wrapper to NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO.
  44. //
  45. PNDIS_IRDA_PACKET_INFO static __inline GetPacketInfo(PNDIS_PACKET packet)
  46. {
  47. MEDIA_SPECIFIC_INFORMATION *mediaInfo;
  48. UINT size;
  49. NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(packet, &mediaInfo, &size);
  50. return (PNDIS_IRDA_PACKET_INFO)mediaInfo->ClassInformation;
  51. }
  52. //
  53. // Structure to keep track of receive packets and buffers to indicate
  54. // receive data to the protocol.
  55. //
  56. typedef struct
  57. {
  58. LIST_ENTRY linkage;
  59. PNDIS_PACKET packet;
  60. UINT dataLen;
  61. PUCHAR dataBuf;
  62. } RCV_BUFFER, *PRCV_BUFFER;
  63. //
  64. // States for receive finite state machine.
  65. //
  66. typedef enum _RCV_PROCESS_STATE
  67. {
  68. RCV_STATE_READY = 0,
  69. RCV_STATE_BOF,
  70. RCV_STATE_EOF,
  71. RCV_STATE_IN_ESC,
  72. RCV_STATE_RX
  73. } RCV_PROCESS_STATE;
  74. //
  75. // Structure to keep track of current state and information
  76. // of the receive state machine.
  77. //
  78. typedef struct _RCV_INFORMATION
  79. {
  80. RCV_PROCESS_STATE rcvState;
  81. UINT rcvBufPos;
  82. PRCV_BUFFER pRcvBuffer;
  83. }RCV_INFORMATION, *PRCV_INFORMATION;
  84. //
  85. // Serial receive buffer size???
  86. //
  87. #define SERIAL_RECEIVE_BUFFER_LENGTH 2048
  88. //
  89. // Serial timeouts to use.
  90. //
  91. // Keep the write timeouts same as the default.
  92. //
  93. // When the interval = MAXULONG, the timeouts behave as follows:
  94. // 1) If both constant and multiplier are 0, then the serial device
  95. // object returns immediately with whatever it has...even if
  96. // it is nothing.
  97. // 2) If constant and multiplier are not MAXULONG, then the serial device
  98. // object returns immediately if any characters are present. If nothing
  99. // is there then the device object uses the timeouts as specified.
  100. // 3) If multiplier is MAXULONG, then the serial device object returns
  101. // immediately if any characters are present. If nothing is there, the
  102. // device object will return the first character that arrives or wait
  103. // for the specified timeout and return nothing.
  104. //
  105. #define SERIAL_READ_INTERVAL_TIMEOUT MAXULONG
  106. #define SERIAL_READ_TOTAL_TIMEOUT_MULTIPLIER 0
  107. #define SERIAL_READ_TOTAL_TIMEOUT_CONSTANT 10
  108. #define SERIAL_WRITE_TOTAL_TIMEOUT_MULTIPLIER 0
  109. #define SERIAL_WRITE_TOTAL_TIMEOUT_CONSTANT 0
  110. extern SERIAL_TIMEOUTS SerialTimeoutsInit;
  111. extern SERIAL_TIMEOUTS SerialTimeoutsIdle;
  112. extern SERIAL_TIMEOUTS SerialTimeoutsActive;
  113. //
  114. // Maximum size of the name of the serial device object.
  115. //
  116. #define MAX_SERIAL_NAME_SIZE 100
  117. //
  118. // Enumeration of primitives for the PASSIVE_LEVEL thread.
  119. //
  120. typedef enum _PASSIVE_PRIMITIVE
  121. {
  122. PASSIVE_SET_SPEED = 1,
  123. PASSIVE_RESET_DEVICE,
  124. PASSIVE_QUERY_MEDIA_BUSY,
  125. PASSIVE_CLEAR_MEDIA_BUSY,
  126. PASSIVE_HALT
  127. }PASSIVE_PRIMITIVE;
  128. typedef struct _IR_DEVICE
  129. {
  130. //
  131. // Allows the ir device object to be put on a queue.
  132. //
  133. LIST_ENTRY linkage;
  134. //
  135. // Keep track of the serial port name and device.
  136. //
  137. UNICODE_STRING serialDosName;
  138. UNICODE_STRING serialDevName;
  139. PDEVICE_OBJECT pSerialDevObj;
  140. HANDLE serialHandle;
  141. PFILE_OBJECT pSerialFileObj;
  142. //
  143. // This is the handle that the NDIS wrapper associates with a connection.
  144. // (The handle that the miniport driver associates with the connection
  145. // is just an index into the devStates array).
  146. //
  147. NDIS_HANDLE hNdisAdapter;
  148. //
  149. // The dongle interface allows us to check the tranceiver type once
  150. // and then set up the interface to allow us to init, set speed,
  151. // and deinit the dongle.
  152. //
  153. // We also want the dongle capabilities.
  154. //
  155. IR_TRANSCEIVER_TYPE transceiverType;
  156. DONGLE_INTERFACE dongle;
  157. DONGLE_CAPABILITIES dongleCaps;
  158. ULONG AllowedSpeedsMask;
  159. //
  160. // NDIS calls most of the MiniportXxx function with IRQL DISPATCH_LEVEL.
  161. // There are a number of instances where the ir device must send
  162. // requests to the serial device which may not be synchronous and
  163. // we can't block in DISPATCH_LEVEL. Therefore, we set up a thread to deal
  164. // with request which require PASSIVE_LEVEL. An event is used to signal
  165. // the thread that work is required.
  166. //
  167. LIST_ENTRY leWorkItems;
  168. NDIS_SPIN_LOCK slWorkItem;
  169. HANDLE hPassiveThread;
  170. KEVENT eventPassiveThread;
  171. KEVENT eventKillThread;
  172. //
  173. // Current speed setting, in bits/sec.
  174. // Note: This is updated when we ACTUALLY change the speed,
  175. // not when we get the request to change speed via
  176. // IrsirSetInformation.
  177. //
  178. UINT currentSpeed;
  179. //
  180. // Current link speed information. This also will maintain the
  181. // chosen speed if the protocol requests a speed change.
  182. //
  183. baudRateInfo *linkSpeedInfo;
  184. //
  185. // Maintain statistical debug info.
  186. //
  187. UINT packetsReceived;
  188. UINT packetsReceivedDropped;
  189. UINT packetsReceivedOverflow;
  190. UINT packetsSent;
  191. UINT packetsSentDropped;
  192. ULONG packetsHeldByProtocol;
  193. //
  194. // Indicates that we have received an OID_GEN_CURRENT_PACKET_FILTER
  195. // indication from the protocol. We can deliver received packets to the
  196. // protocol.
  197. //
  198. BOOLEAN fGotFilterIndication;
  199. //
  200. // The variable fMediaBusy is set TRUE any time that this miniport
  201. // driver receives a data frame. It can be reset by the protocol via
  202. // IrsirSetInformation and later checked via IrsirQueryInformation
  203. // to detect interleaving activity.
  204. //
  205. // In order to check for framing errors, when the protocol calls
  206. // IrsirSetInformation(OID_IRDA_MEDIA_BUSY), the miniport
  207. // sends an irp to the serial device object to clear the performance
  208. // statistics. When the protocol calls
  209. // IrsirQueryInformation(OID_IRDA_MEDIA_BUSY), if the miniport
  210. // hasn't sensed the media busy, the miniport will query the
  211. // serial device object for the performance statistics to check
  212. // for media busy.
  213. //
  214. // A spin lock is used to interleave access to fMediaBusy variable.
  215. //
  216. BOOLEAN fMediaBusy;
  217. NDIS_SPIN_LOCK mediaBusySpinLock;
  218. //
  219. // The variable fReceiving is used to indicate that the ir device
  220. // object in pending a receive from the serial device object. Note,
  221. // that this does NOT necessarily mean that any data is being
  222. // received from the serial device object, since we are constantly
  223. // polling the serial device object for data.
  224. //
  225. // Under normal circumstances fReceiving should always be TRUE.
  226. // However, when IrsirHalt or IrsirReset are called, the receive
  227. // has to be shut down and this variable is used to synchronize
  228. // the halt and reset handler.
  229. //
  230. BOOLEAN fReceiving;
  231. //
  232. // The variable fRequireMinTurnAround indicates whether a time
  233. // delay is required between the last byte of the last byte
  234. // of the last frame sent by ANOTHER station, and the point
  235. // at which it (the other station) is ready to receive the
  236. // first byte from THIS station.
  237. //
  238. // This variable is initially set to TRUE. Whenever this variable
  239. // is true and a send occurs, the a delay will be implemented by
  240. // a stall execution before the irp is sent to the serial
  241. // device object.
  242. //
  243. // After a transmission occurs with the min turnaround delay, this
  244. // variable is set to FALSE. Everytime data is received, the
  245. // variable is set to TRUE.
  246. //
  247. BOOLEAN fRequireMinTurnAround;
  248. //
  249. // The variable fPendingSetSpeed allows the receive completion routine
  250. // to check if the a set speed is required.
  251. //
  252. BOOLEAN fPendingSetSpeed;
  253. //
  254. // The variableis fPendingHalt/fPendingReset allows the send and receive
  255. // completion routines to complete the current pending irp and
  256. // then cleanup and stop sending irps to the serial driver.
  257. //
  258. BOOLEAN fPendingHalt;
  259. BOOLEAN fPendingReset;
  260. //
  261. // We keep an array of receive buffers so that we don't continually
  262. // need to allocate buffers to indicate packets to the protocol.
  263. // Since the protocol can retain ownership of up to eight packets
  264. // and we can be receiving some data while the protocol has
  265. // ownership of eight packets, we will allocate nine packets for
  266. // receiving.
  267. //
  268. #define NUM_RCV_BUFS 14
  269. RCV_BUFFER rcvBufs[NUM_RCV_BUFS];
  270. //
  271. // Handles to the NDIS packet pool and NDIS buffer pool
  272. // for allocating the receive buffers.
  273. //
  274. NDIS_HANDLE hPacketPool;
  275. NDIS_HANDLE hBufferPool;
  276. //
  277. // When we indicate a packet to the protocol, the protocol may
  278. // retain ownership until at some point (asynchronously), it calls
  279. // IrsirReturnPacket. No assumption is made about packet order.
  280. //
  281. // Therefore, we maintain a free queue and a pending queue of
  282. // receive buffers. Originally, all nine buffers are put on the
  283. // free queue. When data is being received, a receive buffer is
  284. // maintained in the RCV_INFORMATION described below. After we
  285. // indicate a full packet to the protocol and if the protocol
  286. // retains ownership of the packet, the receive buffer is queued
  287. // on the pending queue until IrsirReturnPacket is called.
  288. //
  289. // A spin lock is used to interleave access to both the free and
  290. // pending queues. There are three routines which use the
  291. // receive queues: InitializeReceive, SerialIoCompleteRead, and
  292. // IrsirReturnPacket.
  293. //
  294. LIST_ENTRY rcvFreeQueue;
  295. NDIS_SPIN_LOCK rcvQueueSpinLock;
  296. //
  297. // The rcvInfo object, allows the device to keep track of the
  298. // current receive buffer, the state of the finite state machine,
  299. // and the write position in the buffer.
  300. //
  301. RCV_INFORMATION rcvInfo;
  302. //
  303. // The send spin lock is used for both inserting and removing from the
  304. // send queue as well as checking and modifying the variable fSending.
  305. //
  306. //
  307. // Since we only want to send one packet at a time to the serial driver,
  308. // we need to queue other packets until each preceding send packet
  309. // has been completed by the serial device object.
  310. //
  311. // Therefore, we maintain a queue of send packets (if required).
  312. // The MiniportReserved element of the NDIS_PACKET is used as the
  313. // 'next' pointer. We keep a pointer to both the head and the
  314. // tail of the list to speed access to the queue.
  315. //
  316. PACKET_QUEUE SendPacketQueue;
  317. //
  318. // We will allocate irp buffers both send
  319. // and receive irps only once.
  320. //
  321. PUCHAR pSendIrpBuffer;
  322. PUCHAR pRcvIrpBuffer;
  323. // irp buffers and io status block for WaitOnMask
  324. ULONG MaskResult;
  325. IO_STATUS_BLOCK WaitIosb;
  326. // We use the following flag to indicate that a Wait has been issued
  327. // for the End of Frame character (0xc1). It's a ULONG because we
  328. // access it using InterlockedExchange()
  329. ULONG fWaitPending;
  330. PVOID pQueryInfoBuffer;
  331. BOOLEAN SerialBased;
  332. PVOID PnpNotificationEntry;
  333. // We do some timeout modulation during activity
  334. ULONG NumReads;
  335. ULONG ReadRecurseLevel;
  336. }IR_DEVICE, *PIR_DEVICE;
  337. VOID
  338. SendPacketToSerial(
  339. PVOID Context,
  340. PNDIS_PACKET Packet
  341. );
  342. typedef VOID (*WORK_PROC)(struct _IR_WORK_ITEM *);
  343. typedef struct _IR_WORK_ITEM
  344. {
  345. PASSIVE_PRIMITIVE Prim;
  346. PIR_DEVICE pIrDevice;
  347. WORK_PROC Callback;
  348. PVOID InfoBuf;
  349. ULONG InfoBufLen;
  350. LIST_ENTRY ListEntry;
  351. } IR_WORK_ITEM, *PIR_WORK_ITEM;
  352. //
  353. // We use a pointer to the IR_DEVICE structure as the miniport's device context.
  354. //
  355. #define CONTEXT_TO_DEV(__deviceContext) ((PIR_DEVICE)(__deviceContext))
  356. #define DEV_TO_CONTEXT(__irdev) ((NDIS_HANDLE)(__irdev))
  357. #define IRSIR_TAG ' RIS'
  358. #define DEVICE_PREFIX L"\\DEVICE\\"
  359. #include "externs.h"
  360. #endif // _IRSIR_H