Leaked source code of windows server 2003
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.

427 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. smbcsrv.c
  5. Abstract:
  6. SMBus class driver service functions
  7. Author:
  8. Ken Reneris
  9. Environment:
  10. Notes:
  11. Revision History:
  12. --*/
  13. #include "smbc.h"
  14. VOID
  15. SmbCRetry (
  16. IN struct _KDPC *Dpc,
  17. IN PVOID DeferredContext,
  18. IN PVOID SystemArgument1,
  19. IN PVOID SystemArgument2
  20. )
  21. /*++
  22. Routine Description:
  23. Handles retry timer
  24. --*/
  25. {
  26. PSMBDATA Smb;
  27. Smb = (PSMBDATA) DeferredContext;
  28. SmbClassLockDevice (&Smb->Class);
  29. //
  30. // State is waiting for retry, move it to send request
  31. //
  32. ASSERT (Smb->IoState == SMBC_WAITING_FOR_RETRY);
  33. Smb->IoState = SMBC_START_REQUEST;
  34. SmbClassStartIo (Smb);
  35. SmbClassUnlockDevice (&Smb->Class);
  36. }
  37. VOID
  38. SmbClassStartIo (
  39. IN PSMBDATA Smb
  40. )
  41. /*++
  42. Routine Description:
  43. Main class driver state loop
  44. N.B. device lock is held by caller.
  45. N.B. device lock may be released and re-acquired during call
  46. --*/
  47. {
  48. PLIST_ENTRY Entry;
  49. PIRP Irp;
  50. PIO_STACK_LOCATION IrpSp;
  51. PSMB_REQUEST SmbReq;
  52. LARGE_INTEGER duetime;
  53. //
  54. // If already servicing the device, done
  55. //
  56. if (Smb->InService) {
  57. return ;
  58. }
  59. //
  60. // Service the device
  61. //
  62. Smb->InService = TRUE;
  63. while (Smb->InService) {
  64. ASSERT_DEVICE_LOCKED (Smb);
  65. switch (Smb->IoState) {
  66. case SMBC_IDLE:
  67. //
  68. // Check if there is a request to give to the miniport
  69. //
  70. ASSERT (!Smb->Class.CurrentIrp);
  71. if (IsListEmpty(&Smb->WorkQueue)) {
  72. // nothing to do, stop servicing the device
  73. Smb->InService = FALSE;
  74. break;
  75. }
  76. //
  77. // Get the next IRP
  78. //
  79. Entry = RemoveHeadList(&Smb->WorkQueue);
  80. Irp = CONTAINING_RECORD (
  81. Entry,
  82. IRP,
  83. Tail.Overlay.ListEntry
  84. );
  85. //
  86. // Make it the current request
  87. //
  88. Smb->RetryCount = 0;
  89. Smb->Class.DeviceObject->CurrentIrp = Irp;
  90. Smb->IoState = SMBC_START_REQUEST;
  91. break;
  92. case SMBC_START_REQUEST:
  93. //
  94. // Tell miniport to start on this request
  95. //
  96. Irp = Smb->Class.DeviceObject->CurrentIrp;
  97. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  98. Smb->Class.CurrentIrp = Irp;
  99. Smb->Class.CurrentSmb = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  100. Smb->IoState = SMBC_WAITING_FOR_REQUEST;
  101. #if DEBUG
  102. if (SMBCDebug & SMB_TRANSACTION) {
  103. PUCHAR protocols [SMB_MAXIMUM_PROTOCOL+1] = {
  104. "SMB_WRITE_QUICK",
  105. "SMB_READ_QUICK",
  106. "SMB_SEND_BYTE",
  107. "SMB_RECEIVE_BYTE",
  108. "SMB_WRITE_BYTE",
  109. "SMB_READ_BYTE",
  110. "SMB_WRITE_WORD",
  111. "SMB_READ_WORD",
  112. "SMB_WRITE_BLOCK",
  113. "SMB_READ_BLOCK",
  114. "SMB_PROCESS_CALL",
  115. "SMB_BLOCK_PROCESS_CALL"};
  116. UCHAR i;
  117. SmbPrint (SMB_TRANSACTION, ("SmbClassStartIo: started %s (%02x) Add: %02x",
  118. (Smb->Class.CurrentSmb->Protocol <= SMB_MAXIMUM_PROTOCOL) ?
  119. protocols[Smb->Class.CurrentSmb->Protocol] : "BAD PROTOCOL",
  120. Smb->Class.CurrentSmb->Protocol, Smb->Class.CurrentSmb->Address));
  121. switch (Smb->Class.CurrentSmb->Protocol) {
  122. case SMB_WRITE_QUICK:
  123. case SMB_READ_QUICK:
  124. case SMB_RECEIVE_BYTE:
  125. SmbPrint (SMB_TRANSACTION, ("\n"));
  126. break;
  127. case SMB_SEND_BYTE:
  128. SmbPrint (SMB_TRANSACTION, (", Data: %02x\n", Smb->Class.CurrentSmb->Data[0]));
  129. break;
  130. case SMB_WRITE_BYTE:
  131. SmbPrint (SMB_TRANSACTION, (", Com: %02x, Data: %02x\n",
  132. Smb->Class.CurrentSmb->Command, Smb->Class.CurrentSmb->Data[0]));
  133. break;
  134. case SMB_READ_BYTE:
  135. case SMB_READ_WORD:
  136. case SMB_READ_BLOCK:
  137. SmbPrint (SMB_TRANSACTION, (", Com: %02x\n",
  138. Smb->Class.CurrentSmb->Command));
  139. break;
  140. case SMB_WRITE_WORD:
  141. case SMB_PROCESS_CALL:
  142. SmbPrint (SMB_TRANSACTION, (", Com: %02x, Data: %04x\n",
  143. Smb->Class.CurrentSmb->Command, *((PUSHORT)Smb->Class.CurrentSmb->Data)));
  144. break;
  145. case SMB_WRITE_BLOCK:
  146. case SMB_BLOCK_PROCESS_CALL:
  147. SmbPrint (SMB_TRANSACTION, (", Com: %02x, Len: %02x, Data:",
  148. Smb->Class.CurrentSmb->Command, Smb->Class.CurrentSmb->BlockLength));
  149. for (i=0; i < Smb->Class.CurrentSmb->BlockLength; i++) {
  150. SmbPrint (SMB_TRANSACTION, (" %02x", Smb->Class.CurrentSmb->Data[i]));
  151. }
  152. SmbPrint (SMB_TRANSACTION, ("\n"));
  153. break;
  154. default:
  155. SmbPrint (SMB_TRANSACTION, ("\n"));
  156. }
  157. }
  158. #endif
  159. Smb->Class.StartIo (&Smb->Class, Smb->Class.Miniport);
  160. break;
  161. case SMBC_WAITING_FOR_REQUEST:
  162. //
  163. // Waiting for miniport, just keep waiting
  164. //
  165. Smb->InService = FALSE;
  166. break;
  167. case SMBC_COMPLETE_REQUEST:
  168. //
  169. // Miniport has returned the request
  170. //
  171. Irp = Smb->Class.DeviceObject->CurrentIrp;
  172. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  173. SmbReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  174. #if DEBUG
  175. if (SMBCDebug & SMB_TRANSACTION) {
  176. PUCHAR protocols [SMB_MAXIMUM_PROTOCOL+1] = {
  177. "SMB_WRITE_QUICK",
  178. "SMB_READ_QUICK",
  179. "SMB_SEND_BYTE",
  180. "SMB_RECEIVE_BYTE",
  181. "SMB_WRITE_BYTE",
  182. "SMB_READ_BYTE",
  183. "SMB_WRITE_WORD",
  184. "SMB_READ_WORD",
  185. "SMB_WRITE_BLOCK",
  186. "SMB_READ_BLOCK",
  187. "SMB_PROCESS_CALL",
  188. "SMB_BLOCK_PROCESS_CALL"};
  189. UCHAR i;
  190. SmbPrint (SMB_TRANSACTION, ("SmbClassStartIo: finished %s (%02x) Status: %02x, Add: %02x",
  191. (SmbReq->Protocol <= SMB_MAXIMUM_PROTOCOL) ?
  192. protocols[SmbReq->Protocol] : "BAD PROTOCOL",
  193. SmbReq->Protocol, SmbReq->Status, SmbReq->Address));
  194. if (SmbReq->Status != SMB_STATUS_OK) {
  195. SmbPrint (SMB_TRANSACTION, ("\n"));
  196. } else {
  197. switch (SmbReq->Protocol) {
  198. case SMB_WRITE_QUICK:
  199. case SMB_READ_QUICK:
  200. case SMB_SEND_BYTE:
  201. SmbPrint (SMB_TRANSACTION, ("\n"));
  202. break;
  203. case SMB_RECEIVE_BYTE:
  204. SmbPrint (SMB_TRANSACTION, (", Data: %02x\n", SmbReq->Data[0]));
  205. break;
  206. case SMB_READ_BYTE:
  207. SmbPrint (SMB_TRANSACTION, (", Com: %02x, Data: %02x\n",
  208. SmbReq->Command, SmbReq->Data[0]));
  209. break;
  210. case SMB_WRITE_BYTE:
  211. case SMB_WRITE_WORD:
  212. case SMB_WRITE_BLOCK:
  213. SmbPrint (SMB_TRANSACTION, (", Com: %02x\n",
  214. SmbReq->Command));
  215. break;
  216. case SMB_READ_WORD:
  217. case SMB_PROCESS_CALL:
  218. SmbPrint (SMB_TRANSACTION, (", Com: %02x, Data: %04x\n",
  219. SmbReq->Command, *((PUSHORT)SmbReq->Data)));
  220. break;
  221. case SMB_READ_BLOCK:
  222. case SMB_BLOCK_PROCESS_CALL:
  223. SmbPrint (SMB_TRANSACTION, (", Com: %02x, Len: %02x, Data:",
  224. SmbReq->Command, SmbReq->BlockLength));
  225. for (i=0; i < SmbReq->BlockLength; i++) {
  226. SmbPrint (SMB_TRANSACTION, (" %02x", SmbReq->Data[i]));
  227. }
  228. SmbPrint (SMB_TRANSACTION, ("\n"));
  229. break;
  230. default:
  231. SmbPrint (SMB_TRANSACTION, ("\n"));
  232. }
  233. }
  234. }
  235. #endif
  236. if (SmbReq->Status != SMB_STATUS_OK) {
  237. //
  238. // SMB request had an error, check for a retry
  239. //
  240. SmbPrint (SMB_WARN, ("SmbCStartIo: smb request error %x\n", SmbReq->Status));
  241. if (Smb->RetryCount < MAX_RETRIES) {
  242. Smb->RetryCount += 1;
  243. Smb->IoState = SMBC_WAITING_FOR_RETRY;
  244. duetime.QuadPart = RETRY_TIME;
  245. KeSetTimer (&Smb->RetryTimer, duetime, &Smb->RetryDpc);
  246. break;
  247. }
  248. }
  249. //
  250. // Complete the request
  251. //
  252. Smb->Class.DeviceObject->CurrentIrp = NULL;
  253. Smb->IoState = SMBC_COMPLETING_REQUEST;
  254. SmbClassUnlockDevice (&Smb->Class);
  255. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  256. SmbClassLockDevice (&Smb->Class);
  257. //
  258. // Now idle
  259. //
  260. Smb->IoState = SMBC_IDLE;
  261. break;
  262. case SMBC_WAITING_FOR_RETRY:
  263. //
  264. // Waiting to retry, just keep waiting
  265. //
  266. Smb->InService = FALSE;
  267. break;
  268. default:
  269. SmbPrint(SMB_ERROR, ("SmbCStartIo: unknown state\n"));
  270. Smb->IoState = SMBC_IDLE;
  271. Smb->InService = FALSE;
  272. break;
  273. }
  274. }
  275. return ;
  276. }
  277. VOID
  278. SmbClassCompleteRequest (
  279. IN PSMB_CLASS SmbClass
  280. )
  281. /*++
  282. Routine Description:
  283. Called by the miniport to complete the request it was given
  284. N.B. device lock is held by caller.
  285. N.B. device lock may be released and re-acquired during call
  286. --*/
  287. {
  288. PSMBDATA Smb;
  289. //
  290. // Device must be locked, and waiting for a request to compelte
  291. //
  292. Smb = CONTAINING_RECORD (SmbClass, SMBDATA, Class);
  293. ASSERT_DEVICE_LOCKED (Smb);
  294. ASSERT (Smb->IoState == SMBC_WAITING_FOR_REQUEST);
  295. //
  296. // No irp at miniport
  297. //
  298. SmbClass->CurrentIrp = NULL;
  299. SmbClass->CurrentSmb = NULL;
  300. //
  301. // Update state to complete it and handle it
  302. //
  303. Smb->IoState = SMBC_COMPLETE_REQUEST;
  304. SmbClassStartIo (Smb);
  305. }
  306. VOID
  307. SmbClassLockDevice (
  308. IN PSMB_CLASS SmbClass
  309. )
  310. /*++
  311. Routine Description:
  312. Called to acquire the device lock
  313. --*/
  314. {
  315. PSMBDATA Smb;
  316. Smb = CONTAINING_RECORD (SmbClass, SMBDATA, Class);
  317. KeAcquireSpinLock (&Smb->SpinLock, &Smb->SpinLockIrql);
  318. #if DEBUG
  319. ASSERT (!Smb->SpinLockAcquired);
  320. Smb->SpinLockAcquired = TRUE;
  321. #endif
  322. }
  323. VOID
  324. SmbClassUnlockDevice (
  325. IN PSMB_CLASS SmbClass
  326. )
  327. /*++
  328. Routine Description:
  329. Called to release the device lock
  330. --*/
  331. {
  332. PSMBDATA Smb;
  333. Smb = CONTAINING_RECORD (SmbClass, SMBDATA, Class);
  334. #if DEBUG
  335. ASSERT_DEVICE_LOCKED (Smb);
  336. Smb->SpinLockAcquired = FALSE;
  337. #endif
  338. KeReleaseSpinLock (&Smb->SpinLock, Smb->SpinLockIrql);
  339. }