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.

1069 lines
28 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. smbali.c
  5. Abstract:
  6. SMB Host Controller Driver for ALI chipset
  7. Author:
  8. Michael Hills
  9. Environment:
  10. Notes:
  11. Revision History:
  12. --*/
  13. #include "smbalip.h"
  14. #if DBG
  15. ULONG SmbAliDebug = SMB_ERROR|SMB_ALARM;
  16. ULONG DbgSuccess = 0;
  17. ULONG DbgFailure = 0;
  18. ULONG DbgAddrNotAck = 0;
  19. ULONG DbgTimeOut = 0;
  20. ULONG DbgOtherErr = 0;
  21. #endif
  22. LARGE_INTEGER SmbIoPollRate = {-20*MILLISECONDS, -1}; // 20 millisecond poll rate. Relative time, so has to be negative
  23. ULONG SmbIoInitTimeOut = 15; // 15 IoPollRate intervals before timeout
  24. ULONG SmbIoCompleteTimeOut = 20; // 20 IoPollRate intervals before timeout
  25. NTSTATUS
  26. DriverEntry (
  27. IN PDRIVER_OBJECT DriverObject,
  28. IN PUNICODE_STRING RegistryPath
  29. )
  30. /*++
  31. Routine Description:
  32. This routine initializes the SMBus Host Controller Driver
  33. Arguments:
  34. DriverObject - Pointer to driver object created by system.
  35. RegistryPath - Pointer to the Unicode name of the registry path
  36. for this driver.
  37. Return Value:
  38. The function value is the final status from the initialization operation.
  39. --*/
  40. {
  41. NTSTATUS status;
  42. // DbgBreakPoint();
  43. status = SmbClassInitializeDevice (
  44. SMB_ALI_MAJOR_VERSION,
  45. SMB_ALI_MINOR_VERSION,
  46. DriverObject
  47. );
  48. DriverObject->DriverExtension->AddDevice = SmbAliAddDevice;
  49. return status;
  50. }
  51. NTSTATUS
  52. SmbAliInitializeMiniport (
  53. IN PSMB_CLASS SmbClass,
  54. IN PVOID MiniportExtension,
  55. IN PVOID MiniportContext
  56. )
  57. /*++
  58. Routine Description:
  59. This routine Initializes miniport data, and sets up communication with
  60. lower device objects.
  61. Arguments:
  62. DriverObject - Pointer to driver object created by system.
  63. Pdo - Pointer to physical device object
  64. Return Value:
  65. STATUS_SUCCESS
  66. STATUS_INSUFFICIENT_RESOURCES
  67. --*/
  68. {
  69. PSMB_ALI_DATA AliData = (PSMB_ALI_DATA) MiniportExtension;
  70. NTSTATUS status = STATUS_SUCCESS;
  71. PIRP irp;
  72. PIO_STACK_LOCATION irpSp;
  73. KEVENT syncEvent;
  74. AliData->IoState = SmbIoIdle;
  75. //
  76. // Fill in SmbClass info
  77. //
  78. SmbClass->StartIo = SmbAliStartIo;
  79. SmbClass->ResetDevice = SmbAliResetDevice;
  80. SmbClass->StopDevice = SmbAliStopDevice;
  81. //
  82. // Get Acpi Interfaces
  83. //
  84. //
  85. // Allocate an IRP for below
  86. //
  87. irp = IoAllocateIrp (SmbClass->LowerDeviceObject->StackSize, FALSE);
  88. if (!irp) {
  89. SmbPrint((SMB_ERROR),
  90. ("SmbAliInitializeMiniport: Failed to allocate Irp\n"));
  91. return STATUS_INSUFFICIENT_RESOURCES;
  92. }
  93. irpSp = IoGetNextIrpStackLocation(irp);
  94. //
  95. // Use QUERY_INTERFACE to get the address of the direct-call ACPI interfaces.
  96. //
  97. irpSp->MajorFunction = IRP_MJ_PNP;
  98. irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  99. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  100. irpSp->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_ACPI_INTERFACE_STANDARD;
  101. irpSp->Parameters.QueryInterface.Version = 1;
  102. irpSp->Parameters.QueryInterface.Size = sizeof (AliData->AcpiInterfaces);
  103. irpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &AliData->AcpiInterfaces;
  104. irpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  105. //
  106. // Initialize an event so this will be a syncronous call.
  107. //
  108. KeInitializeEvent(&syncEvent, SynchronizationEvent, FALSE);
  109. IoSetCompletionRoutine (irp, SmbAliSyncronousIrpCompletion, &syncEvent, TRUE, TRUE, TRUE);
  110. //
  111. // Call ACPI
  112. //
  113. status = IoCallDriver (SmbClass->LowerDeviceObject, irp);
  114. //
  115. // Wait if necessary, then clean up.
  116. //
  117. if (status == STATUS_PENDING) {
  118. KeWaitForSingleObject(&syncEvent, Executive, KernelMode, FALSE, NULL);
  119. status = irp->IoStatus.Status;
  120. }
  121. IoFreeIrp (irp);
  122. if (!NT_SUCCESS(status)) {
  123. SmbPrint(SMB_ERROR,
  124. ("SmbAliInitializeMiniport: Could not get ACPI driver interfaces, status = %x\n", status));
  125. }
  126. //
  127. // Initiaize worker thread
  128. //
  129. AliData->WorkItem = IoAllocateWorkItem (SmbClass->LowerDeviceObject);
  130. return status;
  131. }
  132. NTSTATUS
  133. SmbAliAddDevice (
  134. IN PDRIVER_OBJECT DriverObject,
  135. IN PDEVICE_OBJECT Pdo
  136. )
  137. /*++
  138. Routine Description:
  139. This routine calls SMBClassCreateFdo to create the FDO
  140. Arguments:
  141. DriverObject - Pointer to driver object created by system.
  142. Pdo - Pointer to physical device object
  143. Return Value:
  144. STATUS_SUCCESS
  145. STATUS_INSUFFICIENT_RESOURCES
  146. --*/
  147. {
  148. NTSTATUS status;
  149. PDEVICE_OBJECT fdo = NULL;
  150. PAGED_CODE();
  151. SmbPrint(SMB_TRACE, ("SmbAliAddDevice Entered with pdo %x\n", Pdo));
  152. if (Pdo == NULL) {
  153. //
  154. // Have we been asked to do detection on our own?
  155. // if so just return no more devices
  156. //
  157. SmbPrint(SMB_ERROR, ("SmbHcAddDevice - asked to do detection\n"));
  158. return STATUS_NO_MORE_ENTRIES;
  159. }
  160. //
  161. // Create and initialize the new functional device object
  162. //
  163. status = SmbClassCreateFdo(
  164. DriverObject,
  165. Pdo,
  166. sizeof (SMB_ALI_DATA),
  167. SmbAliInitializeMiniport,
  168. NULL,
  169. &fdo
  170. );
  171. if (!NT_SUCCESS(status) || fdo == NULL) {
  172. SmbPrint(SMB_ERROR, ("SmbAliAddDevice - error creating Fdo. Status = %08x\n", status));
  173. }
  174. return status;
  175. }
  176. NTSTATUS
  177. SmbAliResetDevice (
  178. IN struct _SMB_CLASS* SmbClass,
  179. IN PVOID SmbMiniport
  180. )
  181. {
  182. PCM_FULL_RESOURCE_DESCRIPTOR fullResourceDesc;
  183. PCM_PARTIAL_RESOURCE_LIST partialResourceList;
  184. PCM_PARTIAL_RESOURCE_DESCRIPTOR partialResourceDesc;
  185. ULONG i;
  186. PIO_STACK_LOCATION irpStack;
  187. NTSTATUS status = STATUS_UNSUCCESSFUL;
  188. PSMB_ALI_DATA AliData = (PSMB_ALI_DATA) SmbMiniport;
  189. PAGED_CODE();
  190. if (SmbClass->CurrentIrp == NULL) {
  191. SmbPrint(SMB_ERROR, ("SmbAliResetDevice: Null CurrentIrp. Can't get Alloocated Resources.\n"));
  192. return STATUS_NO_MORE_ENTRIES;
  193. }
  194. irpStack = IoGetCurrentIrpStackLocation(SmbClass->CurrentIrp);
  195. if (irpStack->Parameters.StartDevice.AllocatedResources == NULL) {
  196. SmbPrint(SMB_ERROR, ("SmbAliResetDevice: Null resource pointer\n"));
  197. return STATUS_NO_MORE_ENTRIES;
  198. }
  199. if (irpStack->Parameters.StartDevice.AllocatedResources->Count <= 0 ) {
  200. SmbPrint(SMB_ERROR, ("SmbAliResetDevice: Count <= 0\n"));
  201. return status;
  202. }
  203. //
  204. // Traverse the resource list
  205. //
  206. AliData->SmbBaseIo = NULL;
  207. fullResourceDesc=&irpStack->Parameters.StartDevice.AllocatedResources->List[0];
  208. partialResourceList = &fullResourceDesc->PartialResourceList;
  209. partialResourceDesc = partialResourceList->PartialDescriptors;
  210. for (i=0; i<partialResourceList->Count; i++, partialResourceDesc++) {
  211. if (partialResourceDesc->Type == CmResourceTypePort) {
  212. if (AliData->SmbBaseIo == NULL) {
  213. AliData->SmbBaseIo = (PUCHAR)((ULONG_PTR)partialResourceDesc->u.Port.Start.LowPart);
  214. if (partialResourceDesc->u.Port.Length != SMB_ALI_IO_RESOURCE_LENGTH) {
  215. SmbPrint(SMB_ERROR, ("SmbAliResetDevice: Wrong Resource length = 0x%08x\n", partialResourceDesc->u.Port.Length));
  216. DbgBreakPoint();
  217. }
  218. status = STATUS_SUCCESS;
  219. } else {
  220. SmbPrint(SMB_ERROR, ("SmbAliResetDevice: More than 1 IO resource. Resources = 0x%08x\n", irpStack->Parameters.StartDevice.AllocatedResources));
  221. DbgBreakPoint();
  222. }
  223. }
  224. }
  225. if (!NT_SUCCESS (status)) {
  226. SmbPrint(SMB_ERROR, ("SmbAliResetDevice: IO resource error. Resources = 0x%08x\n", irpStack->Parameters.StartDevice.AllocatedResources));
  227. DbgBreakPoint();
  228. }
  229. SmbPrint(SMB_TRACE, ("SmbAliResetDevice: IO Address = 0x%08x\n", AliData->SmbBaseIo));
  230. //
  231. // Register for device notification
  232. //
  233. // But this device can't seem to notify so never mind for now
  234. //status = AliData->AcpiInterfaces.RegisterForDeviceNotifications (
  235. // AliData->AcpiInterfaces.Context,
  236. // SmbAliNotifyHandler,
  237. // AliData);
  238. //
  239. //if (!NT_SUCCESS(status)) {
  240. // SmbPrint(SMB_ERROR, ("SmbAliResetDevice: Failed RegisterForDeviceNotification. 0x%08x\n", status));
  241. //}
  242. KeInitializeTimer (&AliData->InitTimer);
  243. KeInitializeDpc (&AliData->InitDpc,
  244. SmbAliInitTransactionDpc,
  245. SmbClass);
  246. AliData->InitWorker = IoAllocateWorkItem (SmbClass->DeviceObject);
  247. KeInitializeTimer (&AliData->CompleteTimer);
  248. KeInitializeDpc (&AliData->CompleteDpc,
  249. SmbAliCompleteTransactionDpc,
  250. SmbClass);
  251. AliData->CompleteWorker = IoAllocateWorkItem (SmbClass->DeviceObject);
  252. SmbAliStartDevicePolling (SmbClass);
  253. return status;
  254. }
  255. NTSTATUS
  256. SmbAliStopDevice (
  257. IN struct _SMB_CLASS* SmbClass,
  258. IN PSMB_ALI_DATA AliData
  259. )
  260. {
  261. SmbAliStopDevicePolling (SmbClass);
  262. AliData->SmbBaseIo = NULL;
  263. return STATUS_SUCCESS;
  264. }
  265. VOID
  266. SmbAliStartIo (
  267. IN struct _SMB_CLASS* SmbClass,
  268. IN PSMB_ALI_DATA AliData
  269. )
  270. {
  271. SmbPrint (SMB_TRACE, ("SmbAliStartIo: \n"));
  272. SmbPrint (SMB_IO_REQUEST, (" Prtcl = %02x Addr = %02x Cmd = %02x BlkLen = %02x Data[0] = %02x\n",
  273. SmbClass->CurrentSmb->Protocol,
  274. SmbClass->CurrentSmb->Address,
  275. SmbClass->CurrentSmb->Command,
  276. SmbClass->CurrentSmb->BlockLength,
  277. SmbClass->CurrentSmb->Data[0]));
  278. // KeSetTimer (&AliData->InitTimer,
  279. // Smb100ns,
  280. // &AliData->InitDpc);
  281. AliData->InternalRetries = 0;
  282. AliData->InitTimeOut = SmbIoInitTimeOut;
  283. IoQueueWorkItem (AliData->InitWorker,
  284. SmbAliInitTransactionWorker,
  285. DelayedWorkQueue,
  286. SmbClass);
  287. }
  288. VOID
  289. SmbAliInitTransactionDpc (
  290. IN struct _KDPC *Dpc,
  291. IN struct _SMB_CLASS* SmbClass,
  292. IN PVOID SystemArgument1,
  293. IN PVOID SystemArgument2
  294. )
  295. {
  296. PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport);
  297. IoQueueWorkItem (AliData->InitWorker,
  298. SmbAliInitTransactionWorker,
  299. DelayedWorkQueue,
  300. SmbClass);
  301. }
  302. VOID
  303. SmbAliInitTransactionWorker (
  304. IN PDEVICE_OBJECT DeviceObject,
  305. IN struct _SMB_CLASS* SmbClass
  306. )
  307. {
  308. PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport);
  309. UCHAR address;
  310. UCHAR protocol;
  311. SmbPrint (SMB_TRACE, ("SmbAliInitTransaction: Entered \n"));
  312. if (SmbClass->CurrentSmb->Protocol >= SMB_MAXIMUM_PROTOCOL) {
  313. SmbClass->CurrentSmb->Status = SMB_UNSUPPORTED_PROTOCOL;
  314. // REVIEW: Shouldn't this complete the request? jimmat
  315. return;
  316. }
  317. if (SmbAliHostBusy(AliData)) {
  318. if (AliData->InitTimeOut == 4) {
  319. // Time out. Issue kill command. If that fixes it, good, otherwise
  320. // issue bus timeout command next time.
  321. SmbAliResetHost (AliData);
  322. }
  323. if (AliData->InitTimeOut == 0) {
  324. // Time out. Issue Bus timeout and kill command to reset host.
  325. SmbAliResetBus (AliData);
  326. AliData->InitTimeOut = SmbIoInitTimeOut;
  327. } else {
  328. SmbPrint (SMB_TRACE, ("SmbAliInitTransaction: Waiting (%d) \n", AliData->InitTimeOut));
  329. AliData->InitTimeOut--;
  330. }
  331. KeSetTimer (&AliData->InitTimer,
  332. SmbIoPollRate,
  333. &AliData->InitDpc);
  334. return;
  335. }
  336. //
  337. // Ready to go
  338. //
  339. // Set Address and read/write bit
  340. address = SmbClass->CurrentSmb->Address << 1 | (SmbClass->CurrentSmb->Protocol & 1);
  341. SmbPrint (SMB_IO, ("SmbAliInitTransaction: IO write DEV_ADDR = 0x%02x \n", address));
  342. WRITE_PORT_UCHAR (DEV_ADDR_REG, address);
  343. SMBDELAY;
  344. // Set transaction type: Inserts bits 3-1 of protocol into bits 6-4 of SMB_TYP
  345. // protocol = READ_PORT_UCHAR (SMB_TYP_REG);
  346. // SmbPrint (SMB_IO, ("SmbAliInitTransaction: IO read SMB_TYP = 0x%02x \n", protocol));
  347. protocol = /*(protocol & ~SMB_TYP_MASK) |*/
  348. ((SmbClass->CurrentSmb->Protocol << 3) & SMB_TYP_MASK);
  349. SmbPrint (SMB_IO, ("SmbAliInitTransaction: IO write SMB_TYP = 0x%02x, Protocol = 0x%02x \n", protocol,SmbClass->CurrentSmb->Protocol));
  350. WRITE_PORT_UCHAR (SMB_TYP_REG, protocol);
  351. SMBDELAY;
  352. // Set SMBus Device Command value
  353. if (SmbClass->CurrentSmb->Protocol >= SMB_WRITE_BYTE) {
  354. SmbPrint (SMB_IO, ("SmbAliInitTransaction: IO write SMB_CMD = 0x%02x \n", SmbClass->CurrentSmb->Command));
  355. WRITE_PORT_UCHAR (SMB_CMD_REG, SmbClass->CurrentSmb->Command);
  356. SMBDELAY;
  357. }
  358. switch (SmbClass->CurrentSmb->Protocol) {
  359. case SMB_WRITE_WORD:
  360. case SMB_PROCESS_CALL:
  361. // Set Data
  362. SmbPrint (SMB_IO, ("SmbAliInitTransaction: IO write DEV_DATA1 = 0x%02x \n", SmbClass->CurrentSmb->Data[1]));
  363. WRITE_PORT_UCHAR (DEV_DATA1_REG, SmbClass->CurrentSmb->Data[1]);
  364. SMBDELAY;
  365. // Fall through to set low byte of word
  366. case SMB_SEND_BYTE:
  367. case SMB_WRITE_BYTE:
  368. // Set Data
  369. SmbPrint (SMB_IO, ("SmbAliInitTransaction: IO write DEV_DATA0 = 0x%02x \n", SmbClass->CurrentSmb->Data[0]));
  370. WRITE_PORT_UCHAR (DEV_DATA0_REG, SmbClass->CurrentSmb->Data[0]);
  371. SMBDELAY;
  372. break;
  373. case SMB_WRITE_BLOCK:
  374. // BUGBUG: not yet implemented.
  375. SmbPrint (SMB_ERROR, ("SmbAliInitTransaction: Write Block not implemented. press 'g' to write random data.\n"));
  376. DbgBreakPoint();
  377. break;
  378. }
  379. // Initiate Transaction
  380. SmbPrint (SMB_IO, ("SmbAliInitTransaction: IO write STR_PORT = 0x%02x \n", STR_PORT_START));
  381. WRITE_PORT_UCHAR (STR_PORT_REG, STR_PORT_START);
  382. AliData->CompleteTimeOut = SmbIoCompleteTimeOut;
  383. KeSetTimer (&AliData->CompleteTimer,
  384. SmbIoPollRate,
  385. &AliData->CompleteDpc);
  386. }
  387. VOID
  388. SmbAliCompleteTransactionDpc (
  389. IN struct _KDPC *Dpc,
  390. IN struct _SMB_CLASS* SmbClass,
  391. IN PVOID SystemArgument1,
  392. IN PVOID SystemArgument2
  393. )
  394. {
  395. PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport);
  396. IoQueueWorkItem (AliData->CompleteWorker,
  397. SmbAliCompleteTransactionWorker,
  398. DelayedWorkQueue,
  399. SmbClass);
  400. }
  401. VOID
  402. SmbAliCompleteTransactionWorker (
  403. IN PDEVICE_OBJECT DeviceObject,
  404. IN struct _SMB_CLASS* SmbClass
  405. )
  406. {
  407. PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport);
  408. UCHAR i, smb_sts;
  409. UCHAR smbStatus;
  410. SmbPrint (SMB_TRACE, ("SmbAliCompleteTransactionWorker: Entered \n"));
  411. smbStatus = SMB_STATUS_OK;
  412. if (!SmbAliTransactionComplete(AliData, &smbStatus)) {
  413. //
  414. // Timeout
  415. //
  416. if (AliData->CompleteTimeOut == 0) {
  417. SmbPrint (SMB_TRACE, ("SmbAliCompleteTransactionWorker: Transation timed out. Resetting host. \n"));
  418. SmbAliResetHost (AliData);
  419. smbStatus = SMB_TIMEOUT;
  420. } else {
  421. SmbPrint (SMB_TRACE, ("SmbAliCompleteTransactionWorker: Not complete. Waiting (%d)... \n", AliData->CompleteTimeOut));
  422. AliData->CompleteTimeOut--;
  423. KeSetTimer (&AliData->CompleteTimer,
  424. SmbIoPollRate,
  425. &AliData->CompleteDpc);
  426. return;
  427. }
  428. }
  429. if (smbStatus == SMB_STATUS_OK) {
  430. //
  431. // If transaction was successful, read data.
  432. //
  433. switch (SmbClass->CurrentSmb->Protocol) {
  434. case SMB_READ_WORD:
  435. case SMB_PROCESS_CALL:
  436. // Read High byte
  437. SmbClass->CurrentSmb->Data[1] = READ_PORT_UCHAR (DEV_DATA1_REG);
  438. SMBDELAY;
  439. SmbPrint (SMB_IO, ("SmbAliCompleteTransactionWorker: IO read DEV_DATA1 = 0x%02x \n", SmbClass->CurrentSmb->Data[1]));
  440. // Fall through to set low byte of word
  441. case SMB_RECEIVE_BYTE:
  442. case SMB_READ_BYTE:
  443. // Read Low Byte
  444. SmbClass->CurrentSmb->Data[0] = READ_PORT_UCHAR (DEV_DATA0_REG);
  445. SMBDELAY;
  446. SmbPrint (SMB_IO, ("SmbAliCompleteTransactionWorker: IO read DEV_DATA0 = 0x%02x \n", SmbClass->CurrentSmb->Data[0]));
  447. break;
  448. case SMB_READ_BLOCK:
  449. // Read Block Count
  450. SmbClass->CurrentSmb->BlockLength = READ_PORT_UCHAR (DEV_DATA0_REG);
  451. SMBDELAY;
  452. SmbPrint (SMB_IO, ("SmbAliCompleteTransactionWorker: IO read DEV_DATA0 (block length)= 0x%02x \n", SmbClass->CurrentSmb->BlockLength));
  453. if (SmbClass->CurrentSmb->BlockLength >= 32) {
  454. DbgBreakPoint();
  455. SmbClass->CurrentSmb->BlockLength = 0;
  456. }
  457. // Reset Data pointer
  458. // smb_sts = READ_PORT_UCHAR (SMB_STS_REG);
  459. // SMBDELAY;
  460. // SmbPrint (SMB_IO, ("SmbAliCompleteTransaction: IO read SMB_STS = 0x%02x \n", smb_sts));
  461. smb_sts = SMB_STS_SMB_IDX_CLR;
  462. SmbPrint (SMB_IO, ("SmbAliCompleteTransactionWorker: IO write SMB_STS = 0x%02x \n", smb_sts));
  463. WRITE_PORT_UCHAR (SMB_STS_REG, smb_sts);
  464. SMBDELAY;
  465. // Read data
  466. for (i = 0; i < SmbClass->CurrentSmb->BlockLength; i++) {
  467. SmbClass->CurrentSmb->Data[i] = READ_PORT_UCHAR (BLK_DATA_REG);
  468. SMBDELAY;
  469. SmbPrint (SMB_IO, ("SmbAliCompleteTransactionWorker: IO read BLK_DATA_REG (i = %d) = 0x%02x \n", i, SmbClass->CurrentSmb->Data[i]));
  470. }
  471. break;
  472. }
  473. }
  474. else // smbStatus != SMB_STATUS_OK
  475. {
  476. //
  477. // Retry the transaction up to 5 times before returning to the caller.
  478. // REVIEW: Only do this for certain devices, commands, or error status results?
  479. //
  480. if (AliData->InternalRetries < 5)
  481. {
  482. //SmbPrint (SMB_IO_RESULT, (" SMBus Transaction status: %02x, retrying...\n", smbStatus));
  483. AliData->InternalRetries += 1;
  484. // Send the work item back to the init worker
  485. AliData->InitTimeOut = SmbIoInitTimeOut;
  486. KeSetTimer (&AliData->InitTimer,
  487. SmbIoPollRate,
  488. &AliData->InitDpc);
  489. return;
  490. }
  491. }
  492. // Clear any previous status.
  493. //SmbPrint (SMB_IO, ("SmbAliCompleteTransaction: IO write SMB_STS = 0x%02x \n", SMB_STS_CLEAR));
  494. //WRITE_PORT_UCHAR (SMB_STS_REG, SMB_STS_CLEAR);
  495. // SMBDELAY;
  496. SmbClass->CurrentSmb->Status = smbStatus;
  497. SmbPrint (SMB_IO, ("SmbAliCompleteTransactionWorker: SMB Status = 0x%x\n", smbStatus));
  498. SmbClass->CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
  499. SmbClass->CurrentIrp->IoStatus.Information = sizeof(SMB_REQUEST);
  500. SmbPrint (SMB_IO_RESULT, (" Prtcl = %02x Addr = %02x Cmd = %02x BL = %02x Data[0,1] = %02x %02x Sts = %02x Rty = %02x\n",
  501. SmbClass->CurrentSmb->Protocol,
  502. SmbClass->CurrentSmb->Address,
  503. SmbClass->CurrentSmb->Command,
  504. SmbClass->CurrentSmb->BlockLength,
  505. SmbClass->CurrentSmb->Data[0],
  506. (SMB_READ_WORD == SmbClass->CurrentSmb->Protocol ||
  507. SMB_WRITE_WORD == SmbClass->CurrentSmb->Protocol ||
  508. (SMB_READ_BLOCK == SmbClass->CurrentSmb->Protocol &&
  509. SmbClass->CurrentSmb->BlockLength >= 2)) ?
  510. SmbClass->CurrentSmb->Data[1] : 0xFF,
  511. SmbClass->CurrentSmb->Status,
  512. AliData->InternalRetries));
  513. SmbClassLockDevice (SmbClass);
  514. SmbClassCompleteRequest (SmbClass);
  515. SmbClassUnlockDevice (SmbClass);
  516. #if DBG
  517. //
  518. // Track the # of successful transactions, and if not successful,
  519. // the types of errors encountered.
  520. //
  521. if (SMB_STATUS_OK == smbStatus)
  522. DbgSuccess += 1;
  523. else
  524. {
  525. DbgFailure += 1;
  526. if (SMB_TIMEOUT == smbStatus)
  527. DbgTimeOut += 1;
  528. else if (SMB_ADDRESS_NOT_ACKNOWLEDGED == smbStatus)
  529. DbgAddrNotAck += 1;
  530. else
  531. DbgOtherErr += 1;
  532. }
  533. if ((DbgSuccess + DbgFailure) % 100 == 0)
  534. SmbPrint(SMB_STATS, ("SmbAliCompleteTransactionWorker: Stats:\n"
  535. " Success: %d, Failure: %d, %%: %d\n"
  536. " TimeOut: %d, AddrNotAck: %d, Other: %d\n",
  537. DbgSuccess, DbgFailure, DbgSuccess * 100 / (DbgSuccess + DbgFailure),
  538. DbgTimeOut, DbgAddrNotAck, DbgOtherErr));
  539. #endif
  540. }
  541. VOID
  542. SmbAliNotifyHandler (
  543. IN PVOID Context,
  544. IN ULONG NotifyValue
  545. )
  546. {
  547. PSMB_ALI_DATA AliData = (PSMB_ALI_DATA) Context;
  548. ULONG address;
  549. ULONG data;
  550. UCHAR smb_sts;
  551. SmbPrint (SMB_TRACE, ("SmbAliNotifyHandler: Entered"));
  552. smb_sts = READ_PORT_UCHAR (SMB_STS_REG);
  553. SMBDELAY;
  554. SmbPrint (SMB_TRACE, ("SmbAliNotifyHandler: SMB_STS = %02x", smb_sts));
  555. if (smb_sts & (SMB_STS_ALERT_STS || SMB_STS_SCI_I_STS)) {
  556. //
  557. // Alert Reponse
  558. //
  559. } else if (smb_sts & SMB_STS_SCI_I_STS) {
  560. //
  561. // Last Transaction completed
  562. //
  563. } else {
  564. //
  565. // Check for errors, etc.
  566. //
  567. }
  568. IoQueueWorkItem (AliData->WorkItem,
  569. SmbAliWorkerThread,
  570. DelayedWorkQueue,
  571. AliData);
  572. }
  573. VOID
  574. SmbAliWorkerThread (
  575. IN PDEVICE_OBJECT DeviceObject,
  576. IN PVOID Context
  577. )
  578. {
  579. PSMB_ALI_DATA AliData = (PSMB_ALI_DATA) Context;
  580. SmbPrint (SMB_TRACE, ("SmbAliIrpCompletionWorker: Entered"));
  581. //
  582. // Complete Irps here
  583. //
  584. }
  585. NTSTATUS
  586. SmbAliSyncronousIrpCompletion (
  587. IN PDEVICE_OBJECT DeviceObject,
  588. IN PIRP Irp,
  589. IN PVOID Context
  590. )
  591. /*++
  592. Routine Description:
  593. This routine is called when the lower driver completes an IRP.
  594. Arguments:
  595. DeviceObject - Pointer to the device object for the device.
  596. Irp - Irp completed.
  597. Context - Driver defined context.
  598. Return Value:
  599. The function value is the final status from the operation.
  600. --*/
  601. {
  602. PKEVENT event = Context;
  603. KeSetEvent(event,
  604. 1,
  605. FALSE);
  606. return STATUS_MORE_PROCESSING_REQUIRED;
  607. }
  608. BOOLEAN
  609. SmbAliTransactionComplete (
  610. PSMB_ALI_DATA AliData,
  611. PUCHAR SmbStatus
  612. )
  613. /*++
  614. Routine Description:
  615. This routine checks to see if there is the last transation was completed.
  616. Arguments:
  617. AliData - minidriver device extension.
  618. SmbStatus - Status being returned.
  619. Return Value:
  620. True if transaction completed or had an error.
  621. False if it is still waiting.
  622. --*/
  623. {
  624. UCHAR smb_sts;
  625. smb_sts = READ_PORT_UCHAR (SMB_STS_REG);
  626. SMBDELAY;
  627. SmbPrint (SMB_IO, ("SmbAliTransactionComplete: IO read SMB_STS = 0x%02x \n", smb_sts));
  628. if (smb_sts & SMB_STS_HOST_BSY) {
  629. SmbPrint (SMB_IO, ("SmbAliTransactionComplete: Transaction Not Complete: HOST BUSY\n"));
  630. return FALSE;
  631. }
  632. if (!(smb_sts & SMB_STS_IDLE_STS)) {
  633. SmbPrint (SMB_IO, ("SmbAliTransactionComplete: Transaction Not Complete: Idle Not Indicated\n"));
  634. return FALSE;
  635. }
  636. if (smb_sts & SMB_STS_SCI_I_STS) {
  637. //
  638. // Transaction is complete
  639. //
  640. *SmbStatus = SMB_STATUS_OK;
  641. return TRUE;
  642. }
  643. if (smb_sts & SMB_STS_FAILED) {
  644. *SmbStatus = SMB_UNKNOWN_FAILURE;
  645. } else if (smb_sts & SMB_STS_BUS_ERR) {
  646. *SmbStatus = SMB_ADDRESS_NOT_ACKNOWLEDGED;
  647. } else if (smb_sts & SMB_STS_DRV_ERR) {
  648. *SmbStatus = SMB_TIMEOUT;
  649. } else {
  650. //
  651. // This state really shouldn't be reached.
  652. // Reset the SMBus host
  653. //
  654. SmbPrint (SMB_BUS_ERROR, ("SmbAliTransactionComplete: Invalid SMBus host state.\n"));
  655. *SmbStatus = SMB_UNKNOWN_ERROR;
  656. }
  657. //
  658. // For the three know error tpes we want to reset the bus
  659. //
  660. SmbPrint (SMB_BUS_ERROR, ("SmbAliTransactionComplete: SMBus error: 0x%x \n", *SmbStatus));
  661. // Don't reset the bus etc. if this is a Bus Collision error
  662. if ( *SmbStatus == SMB_ADDRESS_NOT_ACKNOWLEDGED )
  663. {
  664. // Should we clear the bits, lets try it
  665. SmbPrint (SMB_IO, ("SmbAliCompleteTransaction: Clearing Error Bits. IO write SMB_STS = 0x%02x \n", SMB_STS_CLEAR));
  666. WRITE_PORT_UCHAR (SMB_STS_REG, SMB_STS_CLEAR);
  667. SMBDELAY;
  668. }
  669. else
  670. {
  671. SmbAliResetHost (AliData);
  672. SmbAliResetBus (AliData);
  673. }
  674. return TRUE;
  675. }
  676. BOOLEAN
  677. SmbAliHostBusy (
  678. PSMB_ALI_DATA AliData
  679. )
  680. /*++
  681. Routine Description:
  682. This routine checks to see if the Host controller is free to start a
  683. new transaction.
  684. Arguments:
  685. AliData - minidriver device extension.
  686. Return Value:
  687. True if The host is busy.
  688. False if it free for use.
  689. --*/
  690. {
  691. UCHAR smb_sts;
  692. SmbPrint (SMB_TRACE, ("SmbAliHostBusy: Entered \n"));
  693. smb_sts = READ_PORT_UCHAR (SMB_STS_REG);
  694. SMBDELAY;
  695. SmbPrint (SMB_IO, ("SmbAliHostBusy: IO read SMB_STS = 0x%02x \n", smb_sts));
  696. if (smb_sts & SMB_STS_ALERT_STS) {
  697. SmbPrint (SMB_TRACE, ("SmbAliHostBusy: Alert Detected \n"));
  698. DbgBreakPoint();
  699. SmbAliHandleAlert (AliData);
  700. //
  701. // Say device is still busy for now. BUGBUG
  702. return TRUE;
  703. }
  704. if ( smb_sts == SMB_STS_LAST_CMD_COMPLETED )
  705. {
  706. //
  707. // Clear the done bit
  708. SmbPrint (SMB_IO, ("SmbAliHostBusy: IO write SMB_TYP = 0x%02x \n", SMB_STS_CLEAR_DONE));
  709. WRITE_PORT_UCHAR (SMB_STS_REG, SMB_STS_CLEAR_DONE);
  710. SMBDELAY;
  711. return FALSE;
  712. }
  713. if ( smb_sts == SMB_STS_IDLE_STS )
  714. {
  715. //
  716. // No bits are set, Host is not busy
  717. //
  718. SmbPrint (SMB_TRACE, ("SmbAliHostBusy: Not busy \n"));
  719. return FALSE;
  720. }
  721. if ( smb_sts & SMB_STS_ERRORS ) {
  722. //
  723. // Clear it.
  724. // Wait a cycle before continuing.
  725. //
  726. SmbPrint (SMB_IO, ("SmbAliHostBusy: IO write SMB_TYP = 0x%02x \n", SMB_STS_CLEAR));
  727. WRITE_PORT_UCHAR (SMB_STS_REG, SMB_STS_CLEAR);
  728. SMBDELAY;
  729. return TRUE;
  730. }
  731. if ((smb_sts & SMB_STS_HOST_BSY) || !(smb_sts & SMB_STS_IDLE_STS)) {
  732. //
  733. // Host is busy
  734. //
  735. SmbPrint (SMB_TRACE, ("SmbAliHostBusy: Host Busy \n"));
  736. return TRUE;
  737. }
  738. SmbPrint (SMB_ERROR, ("SmbAliHostBusy: Exiting (Why?) \n"));
  739. return TRUE;
  740. }
  741. VOID
  742. SmbAliHandleAlert (
  743. PSMB_ALI_DATA AliData
  744. )
  745. /*++
  746. Routine Description:
  747. This routine reads the alert data and sends notification to SMB class.
  748. Arguments:
  749. AliData - minidriver device extension.
  750. Return Value:
  751. None
  752. --*/
  753. {
  754. //BUGBUG not yet implemented
  755. return;
  756. }
  757. VOID
  758. SmbAliResetBus (
  759. PSMB_ALI_DATA AliData
  760. )
  761. /*++
  762. Routine Description:
  763. This resets the bus by sending the timeout command.
  764. Arguments:
  765. AliData - minidriver device extension.
  766. Return Value:
  767. --*/
  768. {
  769. UCHAR smb_sts;
  770. smb_sts = SMB_TYP_T_OUT_CMD;
  771. SmbPrint (SMB_IO, ("SmbAliResetBus: IO write SMB_TYP = 0x%02x \n", smb_sts));
  772. WRITE_PORT_UCHAR (SMB_TYP_REG, smb_sts);
  773. SMBDELAY;
  774. SmbPrint (SMB_IO, ("SmbAliResetBus: IO write SMB_STS = 0x%02x \n", SMB_STS_CLEAR));
  775. WRITE_PORT_UCHAR (SMB_STS_REG, SMB_STS_CLEAR);
  776. SMBDELAY;
  777. }
  778. VOID
  779. SmbAliResetHost (
  780. PSMB_ALI_DATA AliData
  781. )
  782. /*++
  783. Routine Description:
  784. This resets the host by sending the kill command.
  785. Arguments:
  786. AliData - minidriver device extension.
  787. Return Value:
  788. --*/
  789. {
  790. UCHAR smb_sts;
  791. UCHAR timeout = 5;
  792. smb_sts = SMB_TYP_KILL;
  793. SmbPrint (SMB_IO, ("SmbAliResetHost: IO write SMB_TYP = 0x%02x \n", smb_sts));
  794. WRITE_PORT_UCHAR (SMB_TYP_REG, smb_sts);
  795. SMBDELAY;
  796. SmbPrint (SMB_IO, ("SmbAliResetHost: IO write SMB_STS = 0x%02x \n", SMB_STS_CLEAR));
  797. WRITE_PORT_UCHAR (SMB_STS_REG, SMB_STS_CLEAR);
  798. SMBDELAY;
  799. do {
  800. KeDelayExecutionThread (KernelMode, FALSE, &SmbIoPollRate);
  801. smb_sts = READ_PORT_UCHAR (SMB_STS_REG);
  802. SmbPrint (SMB_IO, ("SmbAliResetHost: IO read SMB_STS = 0x%02x \n", smb_sts));
  803. if (! (timeout--)) {
  804. break;
  805. }
  806. } while (smb_sts & SMB_STS_FAILED);
  807. }
  808. #ifdef USE_IO_DELAY
  809. LARGE_INTEGER DbgDelay = {-1,-1};
  810. VOID SmbDelay(VOID)
  811. {
  812. KeDelayExecutionThread (KernelMode, FALSE, &DbgDelay);
  813. }
  814. #endif