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.

697 lines
21 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. service.c
  5. Abstract:
  6. ACPI Embedded Controller Driver
  7. Author:
  8. Ken Reneris
  9. Environment:
  10. Notes:
  11. Revision History:
  12. --*/
  13. #include "smbhcp.h"
  14. //
  15. // Transfer information based on protocol
  16. //
  17. struct {
  18. UCHAR SetupSize;
  19. UCHAR ReturnSize;
  20. UCHAR Protocol;
  21. } SmbTransfer[] = {
  22. 0, 0, SMB_HC_WRITE_QUICK, // 0
  23. 0, 0, SMB_HC_READ_QUICK, // 1
  24. 2, 0, SMB_HC_SEND_BYTE, // 2
  25. 1, 1, SMB_HC_RECEIVE_BYTE, // 3
  26. 3, 0, SMB_HC_WRITE_BYTE, // 4
  27. 2, 1, SMB_HC_READ_BYTE, // 5
  28. 4, 0, SMB_HC_WRITE_WORD, // 6
  29. 2, 2, SMB_HC_READ_WORD, // 7
  30. 35, 0, SMB_HC_WRITE_BLOCK, // 8
  31. 2, 33, SMB_HC_READ_BLOCK, // 9
  32. 4, 2, SMB_HC_PROCESS_CALL // A
  33. } ;
  34. VOID
  35. SmbHcStartIo (
  36. IN PSMB_CLASS SmbClass,
  37. IN PVOID SmbMiniport
  38. )
  39. /*++
  40. Routine Description:
  41. This routine is called by the class driver when a new request has been
  42. given to the device. If the device is not being processed, then IO is
  43. started; else, nothing is done as the context processing the device will
  44. handle it
  45. Arguments:
  46. SmbClass - SMB class data
  47. SmbMiniport - Miniport context
  48. Return Value:
  49. None
  50. --*/
  51. {
  52. PSMB_DATA SmbData;
  53. SmbData = (PSMB_DATA) SmbMiniport;
  54. switch (SmbData->IoState) {
  55. case SMB_IO_IDLE:
  56. //
  57. // Device is idle, go check it
  58. //
  59. SmbData->IoState = SMB_IO_CHECK_IDLE;
  60. SmbHcServiceIoLoop (SmbClass, SmbData);
  61. break;
  62. case SMB_IO_CHECK_IDLE:
  63. case SMB_IO_CHECK_ALARM:
  64. case SMB_IO_WAITING_FOR_HC_REG_IO:
  65. case SMB_IO_WAITING_FOR_STATUS:
  66. //
  67. // Device i/o is in process which will check for a CurrentIrp
  68. //
  69. break;
  70. default:
  71. SmbPrint (SMB_ERROR, ("SmbHcStartIo: Unexpected state\n"));
  72. break;
  73. }
  74. }
  75. VOID
  76. SmbHcQueryEvent (
  77. IN ULONG QueryVector,
  78. IN PSMB_DATA SmbData
  79. )
  80. /*++
  81. Routine Description:
  82. This routine is called by the embedded controller driver when the
  83. smb controller has signalled for servicing. This function sets
  84. the miniport state to ensure the STATUS register is read and checked
  85. and if needed starts the device processing to check it
  86. --*/
  87. {
  88. PSMB_CLASS SmbClass;
  89. SmbPrint (SMB_STATE, ("SmbHcQueryEvent\n"));
  90. //
  91. // Check status of device.
  92. //
  93. SmbClass = SmbData->Class;
  94. SmbClassLockDevice (SmbClass);
  95. switch (SmbData->IoState) {
  96. case SMB_IO_CHECK_IDLE:
  97. case SMB_IO_IDLE:
  98. //
  99. // Device is idle. Read status and check for an alarm
  100. //
  101. SmbData->IoState = SMB_IO_READ_STATUS;
  102. SmbData->IoStatusState = SMB_IO_CHECK_IDLE;
  103. SmbHcServiceIoLoop (SmbClass, SmbData);
  104. break;
  105. case SMB_IO_WAITING_FOR_STATUS:
  106. //
  107. // Waiting for completion status, read status now to see if alarm is set
  108. //
  109. SmbData->IoState = SMB_IO_READ_STATUS;
  110. SmbData->IoStatusState = SMB_IO_WAITING_FOR_STATUS;
  111. SmbHcServiceIoLoop (SmbClass, SmbData);
  112. break;
  113. case SMB_IO_CHECK_ALARM:
  114. //
  115. // Status is read after alarm is processed so state is OK
  116. //
  117. break;
  118. case SMB_IO_WAITING_FOR_HC_REG_IO:
  119. //
  120. // Waiting for register transfer to/from host controller interface,
  121. // check the waiting state
  122. //
  123. switch (SmbData->IoWaitingState) {
  124. case SMB_IO_CHECK_ALARM:
  125. case SMB_IO_START_PROTOCOL:
  126. case SMB_IO_READ_STATUS:
  127. //
  128. // Status will be read, so state is OK
  129. //
  130. break;
  131. case SMB_IO_CHECK_STATUS:
  132. //
  133. // Back check status up and re-read the status before
  134. // the check status
  135. //
  136. SmbData->IoWaitingState = SMB_IO_READ_STATUS;
  137. break;
  138. case SMB_IO_WAITING_FOR_STATUS:
  139. //
  140. // Going to wait for completion status, read status once
  141. // hc i/o has completed
  142. //
  143. SmbData->IoWaitingState = SMB_IO_READ_STATUS;
  144. SmbData->IoStatusState = SMB_IO_WAITING_FOR_STATUS;
  145. break;
  146. default:
  147. SmbPrint (SMB_ERROR, ("SmbHcQuery: Unknown IoWaitingState %d\n", SmbData->IoWaitingState));
  148. break;
  149. }
  150. break;
  151. default:
  152. SmbPrint (SMB_ERROR, ("SmbHcQuery: Unknown IoState %d\n", SmbData->IoState));
  153. break;
  154. }
  155. SmbClassUnlockDevice (SmbClass);
  156. }
  157. NTSTATUS
  158. SmbHcRegIoComplete (
  159. IN PDEVICE_OBJECT DeviceObject,
  160. IN PIRP Irp,
  161. IN PVOID Context
  162. )
  163. /*++
  164. Routine Description:
  165. Completion function for IRPs sent to the embedded control for EC io.
  166. --*/
  167. {
  168. PSMB_DATA SmbData;
  169. PSMB_CLASS SmbClass;
  170. SmbPrint (SMB_STATE, ("SmbHcRegIoComplete: Enter. Irp %x\n", Irp));
  171. SmbData = (PSMB_DATA) Context;
  172. SmbClass = SmbData->Class;
  173. SmbClassLockDevice (SmbClass);
  174. //
  175. // Move state to IoWaitingState and continue
  176. //
  177. ASSERT (SmbData->IoState == SMB_IO_WAITING_FOR_HC_REG_IO);
  178. SmbData->IoState = SMB_IO_COMPLETE_REG_IO;
  179. SmbHcServiceIoLoop (SmbClass, SmbData);
  180. SmbClassUnlockDevice (SmbClass);
  181. return STATUS_MORE_PROCESSING_REQUIRED;
  182. }
  183. VOID
  184. SmbHcServiceIoLoop (
  185. IN PSMB_CLASS SmbClass,
  186. IN PSMB_DATA SmbData
  187. )
  188. /*++
  189. Routine Description:
  190. Main host controller interface service loop.
  191. N.B. device lock is held by caller.
  192. N.B. device lock may be released and re-acquired during call
  193. --*/
  194. {
  195. PIRP Irp;
  196. PUCHAR IoBuffer;
  197. UCHAR IoWaitingState;
  198. UCHAR ErrorCode;
  199. BOOLEAN IoWrite;
  200. ULONG IoLength;
  201. PSMB_REQUEST SmbReq;
  202. PIO_STACK_LOCATION IrpSp;
  203. NTSTATUS Status;
  204. IoWrite = FALSE;
  205. IoBuffer = NULL;
  206. IoWaitingState = SMB_IO_IDLE;
  207. SmbPrint (SMB_STATE, ("SmbService: Enter - SmbData %x\n", SmbData));
  208. do {
  209. switch (SmbData->IoState) {
  210. case SMB_IO_CHECK_IDLE:
  211. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_CHECK_IDLE\n"));
  212. //
  213. // Fallthrough to SMB_IO_IDLE.
  214. //
  215. SmbData->IoState = SMB_IO_IDLE;
  216. case SMB_IO_IDLE:
  217. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_IDLE\n"));
  218. //
  219. // If there's an alarm pending, read and clear it
  220. //
  221. if (SmbData->HcState.Status & SMB_ALRM) {
  222. IoBuffer = &SmbData->HcState.AlarmAddress;
  223. IoLength = 3;
  224. IoWaitingState = SMB_IO_CHECK_ALARM;
  225. break;
  226. }
  227. //
  228. // If there's an IRP, lets start it
  229. //
  230. if (SmbClass->CurrentIrp) {
  231. SmbData->IoState = SMB_IO_START_TRANSFER;
  232. break;
  233. }
  234. break;
  235. case SMB_IO_START_TRANSFER:
  236. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_START_TRANSFER\n"));
  237. //
  238. // Begin CurrentIrp transfer
  239. //
  240. Irp = SmbClass->CurrentIrp;
  241. SmbReq = SmbClass->CurrentSmb;
  242. SmbData->HcState.Protocol = SmbTransfer[SmbReq->Protocol].Protocol;
  243. SmbData->HcState.Address = SmbReq->Address << 1;
  244. SmbData->HcState.Command = SmbReq->Command;
  245. SmbData->HcState.BlockLength = SmbReq->BlockLength;
  246. //
  247. // Write HC registers
  248. //
  249. IoWrite = TRUE;
  250. IoBuffer = &SmbData->HcState.Address;
  251. IoLength = SmbTransfer[SmbReq->Protocol].SetupSize;
  252. IoBuffer = &SmbData->HcState.Address;
  253. IoWaitingState = SMB_IO_START_PROTOCOL;
  254. //
  255. // Move data bytes (after address & command byte)
  256. //
  257. if (IoLength > 2) {
  258. memcpy (SmbData->HcState.Data, SmbReq->Data, IoLength-2);
  259. }
  260. //
  261. // Setup for result length once command completes
  262. //
  263. SmbData->IoReadData = SmbTransfer[SmbReq->Protocol].ReturnSize;
  264. //
  265. // Handle HC specific protocol mappings
  266. //
  267. switch (SmbData->HcState.Protocol) {
  268. case SMB_HC_WRITE_QUICK:
  269. case SMB_HC_READ_QUICK:
  270. //
  271. // Host controller wants quick data bit in bit 0
  272. // of address
  273. //
  274. SmbData->HcState.Address |=
  275. (SmbData->HcState.Protocol & 1);
  276. break;
  277. case SMB_HC_SEND_BYTE:
  278. //
  279. // Host controller wants SEND_BYTE byte in the command
  280. // register
  281. //
  282. SmbData->HcState.Command = SmbReq->Data[0];
  283. break;
  284. }
  285. break;
  286. case SMB_IO_START_PROTOCOL:
  287. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_START_PROTOCOL\n"));
  288. //
  289. // Transfer registers have been setup. Initiate the protocol
  290. //
  291. IoWrite = TRUE;
  292. IoBuffer = &SmbData->HcState.Protocol;
  293. IoLength = 1;
  294. IoWaitingState = SMB_IO_WAITING_FOR_STATUS;
  295. break;
  296. case SMB_IO_WAITING_FOR_STATUS:
  297. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_WAITING_FOR_STATUS\n"));
  298. //
  299. // Transfer is in progress, just waiting for a status to
  300. // indicate its complete
  301. //
  302. SmbData->IoState = SMB_IO_READ_STATUS;
  303. SmbData->IoStatusState = SMB_IO_WAITING_FOR_STATUS;
  304. break;
  305. case SMB_IO_READ_STATUS:
  306. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_READ_STATUS\n"));
  307. //
  308. // Read status+protocol and then check it (IoStatusState already set)
  309. //
  310. IoBuffer = &SmbData->HcState.Protocol;
  311. IoLength = 2; // read protocol & status bytes
  312. IoWaitingState = SMB_IO_CHECK_STATUS;
  313. break;
  314. case SMB_IO_CHECK_STATUS:
  315. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_CHECK_STATUS\n"));
  316. Irp = SmbClass->CurrentIrp;
  317. //
  318. // If there's an Irp
  319. //
  320. if (SmbData->IoStatusState == SMB_IO_WAITING_FOR_STATUS &&
  321. SmbData->HcState.Protocol == 0) {
  322. SmbReq = SmbClass->CurrentSmb;
  323. //
  324. // If there's an error set handle it
  325. //
  326. if (SmbData->HcState.Status & SMB_STATUS_MASK) {
  327. ErrorCode = SmbData->HcState.Status & SMB_STATUS_MASK;
  328. //
  329. // Complete/abort the IO with the error
  330. //
  331. SmbReq->Status = ErrorCode;
  332. SmbData->IoState = SMB_IO_COMPLETE_REQUEST;
  333. break;
  334. }
  335. //
  336. // If the done is set continue the IO
  337. //
  338. if (SmbData->HcState.Status & SMB_DONE) {
  339. //
  340. // Get any return data registers then complete it
  341. //
  342. SmbReq->Status = SMB_STATUS_OK;
  343. IoBuffer = SmbData->HcState.Data;
  344. IoLength = SmbData->IoReadData;
  345. IoWaitingState = SMB_IO_COMPLETE_REQUEST;
  346. break;
  347. }
  348. }
  349. //
  350. // Current status didn't have any effect
  351. //
  352. SmbData->IoState = SmbData->IoStatusState;
  353. break;
  354. case SMB_IO_COMPLETE_REQUEST:
  355. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_COMPLETE_REQUEST\n"));
  356. Irp = SmbClass->CurrentIrp;
  357. SmbReq = SmbClass->CurrentSmb;
  358. SmbData->IoState = SMB_IO_CHECK_IDLE;
  359. SmbData->IoStatusState = SMB_IO_INVALID;
  360. //
  361. // Return any read data if needed
  362. //
  363. memcpy (SmbReq->Data, SmbData->HcState.Data, SMB_MAX_DATA_SIZE);
  364. SmbReq->BlockLength = SmbData->HcState.BlockLength;
  365. Irp->IoStatus.Status = STATUS_SUCCESS;
  366. Irp->IoStatus.Information = sizeof(SMB_REQUEST);
  367. //
  368. // Note SmbClass driver will drop the lock during this call
  369. //
  370. SmbClassCompleteRequest (SmbClass);
  371. break;
  372. case SMB_IO_CHECK_ALARM:
  373. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_CHECK_ALARM\n"));
  374. //
  375. // HC alarm values read, check them
  376. //
  377. SmbPrint (SMB_NOTE, ("SmbHcService: Process Alarm Data %x %x %x\n",
  378. SmbData->HcState.AlarmAddress,
  379. SmbData->HcState.AlarmData[0],
  380. SmbData->HcState.AlarmData[1]
  381. ));
  382. //
  383. // Inform the class driver of the event.
  384. //
  385. SmbClassAlarm (
  386. SmbClass,
  387. (UCHAR) (SmbData->HcState.AlarmAddress >> 1),
  388. (USHORT) (SmbData->HcState.AlarmData[0] | (SmbData->HcState.AlarmData[1] << 8))
  389. );
  390. //
  391. // Clear the alarm bit in the status value, and then check
  392. // for idle state
  393. //
  394. SmbData->HcState.Status = 0;
  395. IoBuffer = &SmbData->HcState.Status;
  396. IoLength = 1;
  397. IoWrite = TRUE;
  398. IoWaitingState = SMB_IO_READ_STATUS;
  399. SmbData->IoStatusState = SMB_IO_CHECK_IDLE;
  400. break;
  401. case SMB_IO_COMPLETE_REG_IO:
  402. SmbPrint (SMB_STATE, ("SmbService: SMB_IO_COMPLETE_REQ_IO\n"));
  403. //
  404. // Irp for HC reg IO is complete, check it
  405. //
  406. Irp = SmbClass->CurrentIrp;
  407. if (!Irp) {
  408. //
  409. // No current irp - check for status irp
  410. //
  411. Irp = SmbData->StatusIrp;
  412. if (Irp) {
  413. // just reading status
  414. IoFreeIrp (Irp);
  415. SmbData->StatusIrp = NULL;
  416. } else {
  417. SmbPrint (SMB_WARN, ("SmbHcServiceIoLoop: HC Reg Io for what?\n"));
  418. }
  419. } else {
  420. //
  421. // Check for error on register access
  422. //
  423. if (!NT_SUCCESS(Irp->IoStatus.Status)) {
  424. SmbPrint (SMB_WARN, ("SmbHcServiceIoLoop: HC Reg Io request failed\n"));
  425. //
  426. // Condition is likely fatal, give it up
  427. //
  428. SmbData->HcState.Protocol = 0;
  429. SmbData->HcState.Status = SMB_UNKNOWN_ERROR;
  430. }
  431. }
  432. //
  433. // Continue to next state
  434. //
  435. SmbData->IoState = SmbData->IoWaitingState;
  436. SmbPrint (SMB_STATE, ("SmbService: Next state: %x\n", SmbData->IoState));
  437. break;
  438. default:
  439. SmbPrint (SMB_ERROR, ("SmbHcServiceIoLoop: Invalid state: %x\n", SmbData->IoState));
  440. SmbData->IoState = SMB_IO_CHECK_IDLE;
  441. break;
  442. }
  443. //
  444. // If there's an IO operation to the HC registers required, dispatch it
  445. //
  446. if (IoWaitingState != SMB_IO_IDLE) {
  447. SmbPrint (SMB_STATE, ("SmbService: IoWaitingState %d\n", IoWaitingState));
  448. if (IoLength) {
  449. //
  450. // There's an Io operation dispatch. Set status as REG IO pending,
  451. // and drop the device lock
  452. //
  453. SmbData->IoWaitingState = IoWaitingState;
  454. SmbData->IoState = SMB_IO_WAITING_FOR_HC_REG_IO;
  455. SmbClassUnlockDevice(SmbClass);
  456. //
  457. // Setup IRP to perform the register IO to the HC
  458. //
  459. Status = STATUS_INSUFFICIENT_RESOURCES;
  460. Irp = SmbClass->CurrentIrp;
  461. if (!Irp) {
  462. Irp = IoAllocateIrp (SmbClass->DeviceObject->StackSize, FALSE);
  463. SmbData->StatusIrp = Irp;
  464. }
  465. if (Irp) {
  466. //
  467. // Fill in register transfer request
  468. //
  469. IrpSp = IoGetNextIrpStackLocation (Irp);
  470. IrpSp->MajorFunction = IoWrite ? IRP_MJ_WRITE : IRP_MJ_READ;
  471. IrpSp->Parameters.Read.Length = IoLength;
  472. IrpSp->Parameters.Read.Key = 0;
  473. IrpSp->Parameters.Read.ByteOffset.HighPart = 0;
  474. IrpSp->Parameters.Read.ByteOffset.LowPart =
  475. (ULONG) ((PUCHAR) IoBuffer - (PUCHAR) &SmbData->HcState) +
  476. SmbData->EcBase;
  477. Irp->AssociatedIrp.SystemBuffer = IoBuffer;
  478. //
  479. // Setup completion routine
  480. //
  481. IoSetCompletionRoutine (
  482. Irp,
  483. SmbHcRegIoComplete,
  484. SmbData,
  485. TRUE,
  486. TRUE,
  487. TRUE
  488. );
  489. SmbPrint (SMB_STATE, ("SmbService: IRP=%x, IrpSp=%x\n", Irp, IrpSp));
  490. SmbPrint (SMB_STATE, ("SmbService: %s Off=%x, Len=%x, Buffer=%x\n",
  491. IoWrite ? "write" : "read",
  492. IrpSp->Parameters.Read.ByteOffset.LowPart,
  493. IoLength,
  494. IoBuffer
  495. ));
  496. //
  497. // Call lower FDO to perform the IO
  498. //
  499. Status = IoCallDriver (SmbData->LowerDeviceObject, Irp);
  500. }
  501. //
  502. // If the request is not pending, complete it
  503. //
  504. SmbClassLockDevice(SmbClass);
  505. if (Status != STATUS_PENDING) {
  506. SmbData->IoState = SMB_IO_COMPLETE_REG_IO;
  507. }
  508. } else {
  509. // no data to transfer continue with next state
  510. SmbData->IoState = IoWaitingState;
  511. }
  512. IoWaitingState = SMB_IO_IDLE; // was: SMB_IO_CHEC_IDLE
  513. IoBuffer = NULL;
  514. IoWrite = FALSE;
  515. }
  516. //
  517. // Loop unless state requires some asynchronous to exit
  518. //
  519. } while (SmbData->IoState != SMB_IO_IDLE &&
  520. SmbData->IoState != SMB_IO_WAITING_FOR_HC_REG_IO &&
  521. SmbData->IoState != SMB_IO_WAITING_FOR_STATUS) ;
  522. SmbPrint (SMB_STATE, ("SmbService: Exit\n"));
  523. }