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.

2412 lines
76 KiB

  1. /*** object.c - Object access functions
  2. *
  3. * Copyright (c) 1996,1997 Microsoft Corporation
  4. * Author: Michael Tsang (MikeTs)
  5. * Created 01/27/97
  6. *
  7. * MODIFICATION HISTORY
  8. */
  9. #include "pch.h"
  10. #ifdef LOCKABLE_PRAGMA
  11. #pragma ACPI_LOCKABLE_DATA
  12. #pragma ACPI_LOCKABLE_CODE
  13. #endif
  14. /***LP ReadObject - Read object
  15. *
  16. * ENTRY
  17. * pctxt -> CTXT
  18. * pdataObj -> object
  19. * pdataResult -> result object
  20. *
  21. * EXIT-SUCCESS
  22. * returns STATUS_SUCCESS
  23. * EXIT-FAILURE
  24. * returns AMLIERR_ code
  25. */
  26. NTSTATUS LOCAL ReadObject(PCTXT pctxt, POBJDATA pdataObj, POBJDATA pdataResult)
  27. {
  28. TRACENAME("READOBJECT")
  29. NTSTATUS rc = STATUS_SUCCESS;
  30. PACCFIELDUNIT pafu;
  31. ENTER(3, ("ReadObject(pctxt=%x,pdataObj=%x,pdataResult=%x)\n",
  32. pctxt, pdataObj, pdataResult));
  33. pdataObj = GetBaseData(pdataObj);
  34. switch (pdataObj->dwDataType)
  35. {
  36. case OBJTYPE_FIELDUNIT:
  37. if ((rc = PushFrame(pctxt, SIG_ACCFIELDUNIT, sizeof(ACCFIELDUNIT),
  38. AccFieldUnit, &pafu)) == STATUS_SUCCESS)
  39. {
  40. pafu->pdataObj = pdataObj;
  41. pafu->FrameHdr.dwfFrame = AFUF_READFIELDUNIT;
  42. pafu->pdata = pdataResult;
  43. }
  44. break;
  45. case OBJTYPE_BUFFFIELD:
  46. rc = ReadField(pctxt, pdataObj,
  47. &((PBUFFFIELDOBJ)pdataObj->pbDataBuff)->FieldDesc,
  48. pdataResult);
  49. break;
  50. default:
  51. ASSERT(pdataResult->dwDataType == OBJTYPE_UNKNOWN);
  52. CopyObjData(pdataResult, pdataObj);
  53. #ifdef DEBUGGER
  54. if (gDebugger.dwfDebugger & (DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
  55. {
  56. PRINTF("=");
  57. PrintObject(pdataResult);
  58. }
  59. #endif
  60. }
  61. EXIT(3, ("ReadObject=%x (Type=%s,Value=%x,Buff=%x)\n",
  62. rc, GetObjectTypeName(pdataResult->dwDataType),
  63. pdataResult->uipDataValue, pdataResult->pbDataBuff));
  64. return rc;
  65. } //ReadObject
  66. /***LP WriteObject - Write object
  67. *
  68. * ENTRY
  69. * pctxt -> CTXT
  70. * pdataObj -> object
  71. * pdataSrc -> source data
  72. *
  73. * EXIT-SUCCESS
  74. * returns STATUS_SUCCESS
  75. * EXIT-FAILURE
  76. * returns AMLIERR_ code
  77. */
  78. NTSTATUS LOCAL WriteObject(PCTXT pctxt, POBJDATA pdataObj, POBJDATA pdataSrc)
  79. {
  80. TRACENAME("WRITEOBJECT")
  81. NTSTATUS rc = STATUS_SUCCESS;
  82. PACCFIELDUNIT pafu;
  83. ENTER(3, ("WriteObject(pctxt=%x,pdataObj=%x,pdataSrc=%x)\n",
  84. pctxt, pdataObj, pdataSrc));
  85. pdataObj = GetBaseData(pdataObj);
  86. switch (pdataObj->dwDataType)
  87. {
  88. case OBJTYPE_FIELDUNIT:
  89. if ((rc = PushFrame(pctxt, SIG_ACCFIELDUNIT, sizeof(ACCFIELDUNIT),
  90. AccFieldUnit, &pafu)) == STATUS_SUCCESS)
  91. {
  92. pafu->pdataObj = pdataObj;
  93. pafu->pdata = pdataSrc;
  94. }
  95. break;
  96. case OBJTYPE_BUFFFIELD:
  97. rc = WriteField(pctxt, pdataObj,
  98. &((PBUFFFIELDOBJ)pdataObj->pbDataBuff)->FieldDesc,
  99. pdataSrc);
  100. break;
  101. case OBJTYPE_DEBUG:
  102. #ifdef DEBUGGER
  103. if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON)
  104. {
  105. DumpObject(pdataSrc, NULL, 0);
  106. }
  107. #endif
  108. rc = STATUS_SUCCESS;
  109. break;
  110. case OBJTYPE_UNKNOWN:
  111. //
  112. // Since the target object could be a global NameSpace object,
  113. // allocate memory from the global heap just to be safe.
  114. //
  115. rc = DupObjData(gpheapGlobal, pdataObj, pdataSrc);
  116. break;
  117. case OBJTYPE_INTDATA:
  118. rc = CopyObjBuffer((PUCHAR)&pdataObj->uipDataValue, sizeof(ULONG),
  119. pdataSrc);
  120. break;
  121. case OBJTYPE_STRDATA:
  122. rc = CopyObjBuffer(pdataObj->pbDataBuff, pdataObj->dwDataLen - 1,
  123. pdataSrc);
  124. break;
  125. case OBJTYPE_BUFFDATA:
  126. rc = CopyObjBuffer(pdataObj->pbDataBuff, pdataObj->dwDataLen,
  127. pdataSrc);
  128. break;
  129. default:
  130. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
  131. ("WriteObject: unexpected target object type (type=%s)",
  132. GetObjectTypeName(pdataObj->dwDataType)));
  133. }
  134. EXIT(3, ("WriteObject=%x (ObjType=%s,DataType=%x,Value=%x,Buff=%x)\n",
  135. rc, GetObjectTypeName(pdataObj->dwDataType), pdataSrc->dwDataType,
  136. pdataSrc->uipDataValue, pdataSrc->pbDataBuff));
  137. return rc;
  138. } //WriteObject
  139. /***LP AccFieldUnit - Access a FieldUnit object
  140. *
  141. * ENTRY
  142. * pctxt -> CTXT
  143. * pafu -> ACCFIELDUNIT
  144. * rc - status code
  145. *
  146. * EXIT-SUCCESS
  147. * returns STATUS_SUCCESS
  148. * EXIT-FAILURE
  149. * returns AMLIERR_ code
  150. */
  151. NTSTATUS LOCAL AccFieldUnit(PCTXT pctxt, PACCFIELDUNIT pafu, NTSTATUS rc)
  152. {
  153. TRACENAME("ACCFIELDUNIT")
  154. ULONG dwStage = (rc == STATUS_SUCCESS)?
  155. (pafu->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 3;
  156. PFIELDUNITOBJ pfu;
  157. POBJDATA pdataParent, pdataBank;
  158. PBANKFIELDOBJ pbf;
  159. ENTER(3, ("AccFieldUnit(Stage=%d,pctxt=%x,pafu=%x,rc=%x)\n",
  160. dwStage, pctxt, pafu, rc));
  161. ASSERT(pafu->FrameHdr.dwSig == SIG_ACCFIELDUNIT);
  162. pfu = (PFIELDUNITOBJ)pafu->pdataObj->pbDataBuff;
  163. switch (dwStage)
  164. {
  165. case 0:
  166. //
  167. // Stage 0: Set bank if necessary.
  168. //
  169. pafu->FrameHdr.dwfFrame++;
  170. pdataParent = &pfu->pnsFieldParent->ObjData;
  171. if (pdataParent->dwDataType == OBJTYPE_BANKFIELD)
  172. {
  173. pbf = (PBANKFIELDOBJ)pdataParent->pbDataBuff;
  174. pdataBank = &pbf->pnsBank->ObjData;
  175. rc = PushAccFieldObj(pctxt, WriteFieldObj, pdataBank,
  176. &((PFIELDUNITOBJ)pdataBank->pbDataBuff)->FieldDesc,
  177. (PUCHAR)&pbf->dwBankValue,
  178. sizeof(ULONG));
  179. break;
  180. }
  181. case 1:
  182. //
  183. // Stage 1: Acquire GlobalLock if necessary.
  184. //
  185. pafu->FrameHdr.dwfFrame++;
  186. if (NeedGlobalLock(pfu))
  187. {
  188. if ((rc = AcquireGL(pctxt)) != STATUS_SUCCESS)
  189. {
  190. break;
  191. }
  192. }
  193. case 2:
  194. //
  195. // Stage 2: Read/Write the field.
  196. //
  197. pafu->FrameHdr.dwfFrame++;
  198. //
  199. // If we come here and we need global lock, we must have got it.
  200. //
  201. if (pfu->FieldDesc.dwFieldFlags & FDF_NEEDLOCK)
  202. {
  203. pafu->FrameHdr.dwfFrame |= AFUF_HAVE_GLOBALLOCK;
  204. }
  205. if (pafu->FrameHdr.dwfFrame & AFUF_READFIELDUNIT)
  206. {
  207. rc = ReadField(pctxt, pafu->pdataObj, &pfu->FieldDesc,
  208. pafu->pdata);
  209. }
  210. else
  211. {
  212. rc = WriteField(pctxt, pafu->pdataObj, &pfu->FieldDesc,
  213. pafu->pdata);
  214. }
  215. if ((rc == AMLISTA_PENDING) ||
  216. (&pafu->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
  217. {
  218. break;
  219. }
  220. case 3:
  221. //
  222. // Stage 3: Clean up.
  223. //
  224. if (pafu->FrameHdr.dwfFrame & AFUF_HAVE_GLOBALLOCK)
  225. {
  226. ReleaseGL(pctxt);
  227. }
  228. #ifdef DEBUGGER
  229. if (gDebugger.dwfDebugger & (DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
  230. {
  231. if (pafu->FrameHdr.dwfFrame & AFUF_READFIELDUNIT)
  232. {
  233. PRINTF("=");
  234. PrintObject(pafu->pdata);
  235. }
  236. }
  237. #endif
  238. PopFrame(pctxt);
  239. }
  240. EXIT(3, ("AccFieldUnit=%x\n", rc));
  241. return rc;
  242. } //AccFieldUnit
  243. /***LP ReadField - Read data from a field object
  244. *
  245. * ENTRY
  246. * pctxt -> CTXT
  247. * pdataObj -> object
  248. * pfd -> field descriptor
  249. * pdataResult -> result object
  250. *
  251. * EXIT-SUCCESS
  252. * returns STATUS_SUCCESS
  253. * EXIT-FAILURE
  254. * returns AMLIERR_ code
  255. */
  256. NTSTATUS LOCAL ReadField(PCTXT pctxt, POBJDATA pdataObj, PFIELDDESC pfd,
  257. POBJDATA pdataResult)
  258. {
  259. TRACENAME("READFIELD")
  260. NTSTATUS rc = STATUS_SUCCESS;
  261. ENTER(3, ("ReadField(pctxt=%x,pdataObj=%x,FieldDesc=%x,pdataResult=%x)\n",
  262. pctxt, pdataObj, pfd, pdataResult));
  263. if ((pfd->dwFieldFlags & ACCTYPE_MASK) <= ACCTYPE_DWORD)
  264. {
  265. PUCHAR pb;
  266. ULONG dwcb;
  267. switch (pdataResult->dwDataType)
  268. {
  269. case OBJTYPE_UNKNOWN:
  270. if (!(pfd->dwFieldFlags & FDF_BUFFER_TYPE) &&
  271. (pfd->dwNumBits <= sizeof(ULONG)*8))
  272. {
  273. pdataResult->dwDataType = OBJTYPE_INTDATA;
  274. pb = (PUCHAR)&pdataResult->uipDataValue;
  275. dwcb = sizeof(ULONG);
  276. }
  277. else
  278. {
  279. pdataResult->dwDataType = OBJTYPE_BUFFDATA;
  280. pdataResult->dwDataLen = (pfd->dwNumBits + 7)/8;
  281. if ((pdataResult->pbDataBuff =
  282. NEWBDOBJ(gpheapGlobal, pdataResult->dwDataLen))
  283. == NULL)
  284. {
  285. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  286. ("ReadField: failed to allocate target buffer (size=%d)",
  287. pdataResult->dwDataLen));
  288. pb = NULL;
  289. dwcb = 0;
  290. }
  291. else
  292. {
  293. MEMZERO(pdataResult->pbDataBuff,
  294. pdataResult->dwDataLen);
  295. pb = pdataResult->pbDataBuff;
  296. dwcb = pdataResult->dwDataLen;
  297. }
  298. }
  299. break;
  300. case OBJTYPE_INTDATA:
  301. pb = (PUCHAR)&pdataResult->uipDataValue;
  302. dwcb = sizeof(ULONG);
  303. break;
  304. case OBJTYPE_STRDATA:
  305. pb = pdataResult->pbDataBuff;
  306. dwcb = pdataResult->dwDataLen - 1;
  307. break;
  308. case OBJTYPE_BUFFDATA:
  309. pb = pdataResult->pbDataBuff;
  310. dwcb = pdataResult->dwDataLen;
  311. break;
  312. default:
  313. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
  314. ("ReadField: invalid target data type (type=%s)",
  315. GetObjectTypeName(pdataResult->dwDataType)));
  316. pb = NULL;
  317. dwcb = 0;
  318. }
  319. if (rc == STATUS_SUCCESS)
  320. rc = PushAccFieldObj(pctxt, ReadFieldObj, pdataObj, pfd, pb, dwcb);
  321. }
  322. else if (pdataObj->dwDataType == OBJTYPE_FIELDUNIT)
  323. {
  324. //
  325. // This is an access type we don't know how to handle, so try to find
  326. // a raw access handler to handle it.
  327. //
  328. rc = RawFieldAccess(pctxt, RSACCESS_READ, pdataObj, pdataResult);
  329. }
  330. else
  331. {
  332. rc = AMLI_LOGERR(AMLIERR_INVALID_ACCSIZE,
  333. ("ReadField: invalid access size for buffer field (FieldFlags=%x)",
  334. pfd->dwFieldFlags));
  335. }
  336. EXIT(3, ("ReadField=%x\n", rc));
  337. return rc;
  338. } //ReadField
  339. /***LP WriteField - Write data to a field object
  340. *
  341. * ENTRY
  342. * pctxt -> CTXT
  343. * pdataObj -> object
  344. * pfd -> field descriptor
  345. * pdataSrc -> source data
  346. *
  347. * EXIT-SUCCESS
  348. * returns STATUS_SUCCESS
  349. * EXIT-FAILURE
  350. * returns AMLIERR_ code
  351. */
  352. NTSTATUS LOCAL WriteField(PCTXT pctxt, POBJDATA pdataObj, PFIELDDESC pfd,
  353. POBJDATA pdataSrc)
  354. {
  355. TRACENAME("WRITEFIELD")
  356. NTSTATUS rc = STATUS_SUCCESS;
  357. ULONG dwDataInc = (pfd->dwNumBits + 7)/8;
  358. PUCHAR pbBuff;
  359. ULONG dwBuffSize;
  360. ENTER(3, ("WriteField(pctxt=%x,pdataObj=%x,FieldDesc=%x,pdataSrc=%x)\n",
  361. pctxt, pdataObj, pfd, pdataSrc));
  362. if ((pfd->dwFieldFlags & ACCTYPE_MASK) <= ACCTYPE_DWORD)
  363. {
  364. PWRFIELDLOOP pwfl;
  365. switch (pdataSrc->dwDataType)
  366. {
  367. case OBJTYPE_INTDATA:
  368. dwBuffSize = MIN(sizeof(ULONG), dwDataInc);
  369. pbBuff = (PUCHAR)&pdataSrc->uipDataValue;
  370. break;
  371. case OBJTYPE_STRDATA:
  372. dwBuffSize = pdataSrc->dwDataLen - 1;
  373. pbBuff = pdataSrc->pbDataBuff;
  374. break;
  375. case OBJTYPE_BUFFDATA:
  376. dwBuffSize = pdataSrc->dwDataLen;
  377. pbBuff = pdataSrc->pbDataBuff;
  378. break;
  379. default:
  380. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
  381. ("WriteField: invalid source data type (type=%s)\n",
  382. GetObjectTypeName(pdataSrc->dwDataType)));
  383. dwBuffSize = 0;
  384. pbBuff = NULL;
  385. }
  386. if ((rc == STATUS_SUCCESS) &&
  387. ((rc = PushFrame(pctxt, SIG_WRFIELDLOOP, sizeof(WRFIELDLOOP),
  388. WriteFieldLoop, &pwfl)) == STATUS_SUCCESS))
  389. {
  390. pwfl->pdataObj = pdataObj;
  391. pwfl->pfd = pfd;
  392. pwfl->pbBuff = pbBuff;
  393. pwfl->dwBuffSize = dwBuffSize;
  394. pwfl->dwDataInc = dwDataInc;
  395. }
  396. }
  397. else if (pdataObj->dwDataType == OBJTYPE_FIELDUNIT)
  398. {
  399. //
  400. // This is an access type we don't know how to handle, so try to find
  401. // a raw access handler to handle it.
  402. //
  403. rc = RawFieldAccess(pctxt, RSACCESS_WRITE, pdataObj, pdataSrc);
  404. }
  405. else
  406. {
  407. rc = AMLI_LOGERR(AMLIERR_INVALID_ACCSIZE,
  408. ("WriteField: invalid access size for buffer field (FieldFlags=%x)",
  409. pfd->dwFieldFlags));
  410. }
  411. EXIT(3, ("WriteField=%x\n", rc));
  412. return rc;
  413. } //WriteField
  414. /***LP WriteFieldLoop - executing the loop for the WriteField operation
  415. *
  416. * ENTRY
  417. * pctxt -> CTXT
  418. * pwfl -> WRFIELDLOOP
  419. * rc - status code
  420. *
  421. * EXIT-SUCCESS
  422. * returns STATUS_SUCCESS
  423. * EXIT-FAILURE
  424. * returns AMLIERR_ code
  425. */
  426. NTSTATUS LOCAL WriteFieldLoop(PCTXT pctxt, PWRFIELDLOOP pwfl, NTSTATUS rc)
  427. {
  428. TRACENAME("WRITEFIELDLOOP")
  429. ULONG dwStage = (rc == STATUS_SUCCESS)?
  430. (pwfl->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 1;
  431. ULONG dwXactionSize;
  432. ENTER(3, ("WriteFieldLoop(Stage=%d,pctxt=%x,pwfl=%x,rc=%x)\n",
  433. dwStage, pctxt, pwfl, rc));
  434. ASSERT(pwfl->FrameHdr.dwSig == SIG_WRFIELDLOOP);
  435. switch (dwStage)
  436. {
  437. case 0:
  438. //
  439. // Stage 0: Do loop.
  440. //
  441. if (pwfl->dwBuffSize > 0)
  442. {
  443. dwXactionSize = MIN(pwfl->dwDataInc, pwfl->dwBuffSize);
  444. rc = PushAccFieldObj(pctxt, WriteFieldObj, pwfl->pdataObj,
  445. pwfl->pfd, pwfl->pbBuff, dwXactionSize);
  446. pwfl->dwBuffSize -= dwXactionSize;
  447. pwfl->pbBuff += dwXactionSize;
  448. break;
  449. }
  450. pwfl->FrameHdr.dwfFrame++;
  451. case 1:
  452. //
  453. // Stage 1: Clean up.
  454. //
  455. PopFrame(pctxt);
  456. }
  457. EXIT(3, ("WriteFieldLoop=%x\n", rc));
  458. return rc;
  459. } //WriteFieldLoop
  460. /***LP PushAccFieldObj - Push a AccFieldObj frame on the stack
  461. *
  462. * ENTRY
  463. * pctxt -> CTXT
  464. * pfnAcc -> access function
  465. * pdataObj -> object
  466. * pfd -> field descriptor
  467. * pb -> data buffer
  468. * dwcb - buffer size
  469. *
  470. * EXIT-SUCCESS
  471. * returns STATUS_SUCCESS
  472. * EXIT-FAILURE
  473. * returns AMLIERR_ code
  474. */
  475. NTSTATUS LOCAL PushAccFieldObj(PCTXT pctxt, PFNPARSE pfnAcc, POBJDATA pdataObj,
  476. PFIELDDESC pfd, PUCHAR pb, ULONG dwcb)
  477. {
  478. TRACENAME("PUSHACCFIELDOBJ")
  479. NTSTATUS rc = STATUS_SUCCESS;
  480. PACCFIELDOBJ pafo;
  481. ENTER(3, ("PushAccFieldObj(pctxt=%x,pfnAcc=%x,pdataObj=%x,FieldDesc=%x,pb=%x,Size=%d)\n",
  482. pctxt, pfnAcc, pdataObj, pfd, pb, dwcb));
  483. if ((rc = PushFrame(pctxt, SIG_ACCFIELDOBJ, sizeof(ACCFIELDOBJ), pfnAcc,
  484. &pafo)) == STATUS_SUCCESS)
  485. {
  486. pafo->pdataObj = pdataObj;
  487. pafo->pbBuff = pb;
  488. pafo->pbBuffEnd = pb + dwcb;
  489. pafo->dwAccSize = ACCSIZE(pfd->dwFieldFlags);
  490. ASSERT((pafo->dwAccSize == sizeof(UCHAR)) ||
  491. (pafo->dwAccSize == sizeof(USHORT)) ||
  492. (pafo->dwAccSize == sizeof(ULONG)));
  493. pafo->dwcAccesses = (pfd->dwStartBitPos + pfd->dwNumBits +
  494. pafo->dwAccSize*8 - 1)/(pafo->dwAccSize*8);
  495. pafo->dwDataMask = SHIFTLEFT(1L, pafo->dwAccSize*8) - 1;
  496. pafo->iLBits = pafo->dwAccSize*8 - pfd->dwStartBitPos;
  497. pafo->iRBits = (int)pfd->dwStartBitPos;
  498. MEMCPY(&pafo->fd, pfd, sizeof(FIELDDESC));
  499. }
  500. EXIT(3, ("PushAccFieldObj=%x\n", rc));
  501. return rc;
  502. } //PushAccFieldObj
  503. /***LP ReadFieldObj - Read data from a field object
  504. *
  505. * ENTRY
  506. * pctxt -> CTXT
  507. * pafo -> ACCFIELDOBJ
  508. * rc - status code
  509. *
  510. * EXIT-SUCCESS
  511. * returns STATUS_SUCCESS
  512. * EXIT-FAILURE
  513. * returns AMLIERR_ code
  514. */
  515. NTSTATUS LOCAL ReadFieldObj(PCTXT pctxt, PACCFIELDOBJ pafo, NTSTATUS rc)
  516. {
  517. TRACENAME("READFIELDOBJ")
  518. ULONG dwStage = (rc == STATUS_SUCCESS)?
  519. (pafo->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 3;
  520. POBJDATA pdataParent;
  521. ENTER(3, ("ReadFieldObj(Stage=%d,pctxt=%x,pafo=%x,rc=%x)\n",
  522. dwStage, pctxt, pafo, rc));
  523. ASSERT(pafo->FrameHdr.dwSig == SIG_ACCFIELDOBJ);
  524. switch (dwStage)
  525. {
  526. case 0:
  527. Stage0:
  528. //
  529. // Stage 0: Set Index if necessary.
  530. //
  531. if (pafo->iAccess >= (int)pafo->dwcAccesses)
  532. {
  533. //
  534. // No access necessary, go straight to clean up.
  535. //
  536. pafo->FrameHdr.dwfFrame += 3;
  537. goto Stage3;
  538. }
  539. else
  540. {
  541. pafo->FrameHdr.dwfFrame++;
  542. if (pafo->pdataObj->dwDataType == OBJTYPE_FIELDUNIT)
  543. {
  544. pdataParent =
  545. &((PFIELDUNITOBJ)pafo->pdataObj->pbDataBuff)->pnsFieldParent->ObjData;
  546. if (pdataParent->dwDataType == OBJTYPE_INDEXFIELD)
  547. {
  548. PINDEXFIELDOBJ pif = (PINDEXFIELDOBJ)pdataParent->pbDataBuff;
  549. rc = PushAccFieldObj(pctxt, WriteFieldObj,
  550. &pif->pnsIndex->ObjData,
  551. &((PFIELDUNITOBJ)pif->pnsIndex->ObjData.pbDataBuff)->FieldDesc,
  552. (PUCHAR)&pafo->fd.dwByteOffset,
  553. sizeof(ULONG));
  554. break;
  555. }
  556. }
  557. }
  558. case 1:
  559. //
  560. // Stage 1: Access field data.
  561. //
  562. pafo->FrameHdr.dwfFrame++;
  563. rc = AccessFieldData(pctxt, pafo->pdataObj, &pafo->fd,
  564. &pafo->dwData, TRUE);
  565. if ((rc != STATUS_SUCCESS) ||
  566. (&pafo->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
  567. {
  568. break;
  569. }
  570. case 2:
  571. //
  572. // Stage 2: Massage data into the right bit position.
  573. //
  574. if (pafo->iAccess > 0)
  575. {
  576. WriteSystemMem((ULONG_PTR)pafo->pbBuff, pafo->dwAccSize,
  577. SHIFTLEFT(pafo->dwData, pafo->iLBits) &
  578. pafo->dwDataMask,
  579. (SHIFTLEFT(1L, pafo->iRBits) - 1) << pafo->iLBits);
  580. pafo->pbBuff += pafo->dwAccSize;
  581. if (pafo->pbBuff >= pafo->pbBuffEnd)
  582. {
  583. //
  584. // We ran out of buffer, so we are done (go to clean up).
  585. //
  586. pafo->FrameHdr.dwfFrame++;
  587. goto Stage3;
  588. }
  589. }
  590. pafo->dwData >>= pafo->iRBits;
  591. if ((int)pafo->fd.dwNumBits < pafo->iLBits)
  592. {
  593. pafo->dwData &= SHIFTLEFT(1L, pafo->fd.dwNumBits) - 1;
  594. }
  595. WriteSystemMem((ULONG_PTR)pafo->pbBuff, pafo->dwAccSize,
  596. pafo->dwData,
  597. (SHIFTLEFT(1L, pafo->iLBits) - 1) >> pafo->iRBits);
  598. pafo->fd.dwByteOffset += pafo->dwAccSize;
  599. pafo->fd.dwNumBits -= pafo->dwAccSize*8 - pafo->fd.dwStartBitPos;
  600. pafo->fd.dwStartBitPos = 0;
  601. pafo->iAccess++;
  602. if (pafo->iAccess < (int)pafo->dwcAccesses)
  603. {
  604. //
  605. // Still more accesses to go, back to stage 0.
  606. //
  607. pafo->FrameHdr.dwfFrame -= 2;
  608. goto Stage0;
  609. }
  610. else
  611. {
  612. //
  613. // No more accesses, continue to clean up.
  614. //
  615. pafo->FrameHdr.dwfFrame++;
  616. }
  617. case 3:
  618. Stage3:
  619. //
  620. // Stage 3: Clean up.
  621. //
  622. PopFrame(pctxt);
  623. }
  624. EXIT(3, ("ReadFieldObj=%x\n", rc));
  625. return rc;
  626. } //ReadFieldObj
  627. /***LP WriteFieldObj - Write data to a field object
  628. *
  629. * ENTRY
  630. * pctxt -> CTXT
  631. * pafo -> ACCFIELDOBJ
  632. * rc - status code
  633. *
  634. * EXIT-SUCCESS
  635. * returns STATUS_SUCCESS
  636. * EXIT-FAILURE
  637. * returns AMLIERR_ code
  638. */
  639. NTSTATUS LOCAL WriteFieldObj(PCTXT pctxt, PACCFIELDOBJ pafo, NTSTATUS rc)
  640. {
  641. TRACENAME("WRITEFIELDOBJ")
  642. ULONG dwStage = (rc == STATUS_SUCCESS)?
  643. (pafo->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 3;
  644. POBJDATA pdataParent;
  645. ULONG dwData1;
  646. ENTER(3, ("WriteFieldObj(Stage=%d,pctxt=%x,pafo=%x,rc=%x)\n",
  647. dwStage, pctxt, pafo, rc));
  648. ASSERT(pafo->FrameHdr.dwSig == SIG_ACCFIELDOBJ);
  649. switch (dwStage)
  650. {
  651. case 0:
  652. Stage0:
  653. //
  654. // Stage 0: Set Index if necessary.
  655. //
  656. if (pafo->iAccess >= (int)pafo->dwcAccesses)
  657. {
  658. //
  659. // No access necessary, go straight to clean up.
  660. //
  661. pafo->FrameHdr.dwfFrame += 3;
  662. goto Stage3;
  663. }
  664. else
  665. {
  666. pafo->FrameHdr.dwfFrame++;
  667. if (pafo->pdataObj->dwDataType == OBJTYPE_FIELDUNIT)
  668. {
  669. pdataParent =
  670. &((PFIELDUNITOBJ)pafo->pdataObj->pbDataBuff)->pnsFieldParent->ObjData;
  671. if (pdataParent->dwDataType == OBJTYPE_INDEXFIELD)
  672. {
  673. PINDEXFIELDOBJ pif = (PINDEXFIELDOBJ)pdataParent->pbDataBuff;
  674. rc = PushAccFieldObj(pctxt, WriteFieldObj,
  675. &pif->pnsIndex->ObjData,
  676. &((PFIELDUNITOBJ)pif->pnsIndex->ObjData.pbDataBuff)->FieldDesc,
  677. (PUCHAR)&pafo->fd.dwByteOffset,
  678. sizeof(ULONG));
  679. break;
  680. }
  681. }
  682. }
  683. case 1:
  684. //
  685. // Stage 1: Massage data into the right bit position and write it.
  686. //
  687. pafo->FrameHdr.dwfFrame++;
  688. dwData1 = ReadSystemMem((ULONG_PTR)pafo->pbBuff, pafo->dwAccSize,
  689. pafo->dwDataMask);
  690. if (pafo->iAccess > 0)
  691. {
  692. pafo->dwData = dwData1 >> pafo->iLBits;
  693. pafo->pbBuff += pafo->dwAccSize;
  694. if (pafo->pbBuff >= pafo->pbBuffEnd)
  695. {
  696. dwData1 = 0;
  697. }
  698. else
  699. {
  700. dwData1 = ReadSystemMem((ULONG_PTR)pafo->pbBuff,
  701. pafo->dwAccSize, pafo->dwDataMask);
  702. }
  703. }
  704. else
  705. {
  706. pafo->dwData = 0;
  707. }
  708. pafo->dwData |= (dwData1 << pafo->iRBits) & pafo->dwDataMask;
  709. rc = AccessFieldData(pctxt, pafo->pdataObj, &pafo->fd,
  710. &pafo->dwData, FALSE);
  711. if ((rc == AMLISTA_PENDING) ||
  712. (&pafo->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
  713. {
  714. break;
  715. }
  716. case 2:
  717. //
  718. // Stage 2: Check for more iterations.
  719. //
  720. pafo->fd.dwByteOffset += pafo->dwAccSize;
  721. pafo->fd.dwNumBits -= pafo->dwAccSize*8 - pafo->fd.dwStartBitPos;
  722. pafo->fd.dwStartBitPos = 0;
  723. pafo->iAccess++;
  724. if (pafo->iAccess < (int)pafo->dwcAccesses)
  725. {
  726. //
  727. // Still more accesses to go, back to stage 0.
  728. //
  729. pafo->FrameHdr.dwfFrame -= 2;
  730. goto Stage0;
  731. }
  732. else
  733. {
  734. pafo->FrameHdr.dwfFrame++;
  735. }
  736. case 3:
  737. Stage3:
  738. //
  739. // Stage 3: Clean up.
  740. //
  741. PopFrame(pctxt);
  742. }
  743. EXIT(3, ("WriteFieldObj=%x\n", rc));
  744. return rc;
  745. } //WriteFieldObj
  746. /***LP RawFieldAccess - Find and call the RawAccess handler for the RegionSpace
  747. *
  748. * ENTRY
  749. * pctxt -> CTXT
  750. * dwAccType - read/write
  751. * pdataObj -> field unit object
  752. * pdataResult -> result object
  753. *
  754. * EXIT-SUCCESS
  755. * returns STATUS_SUCCESS
  756. * EXIT-FAILURE
  757. * returns AMLIERR_ code
  758. */
  759. NTSTATUS LOCAL RawFieldAccess(PCTXT pctxt, ULONG dwAccType, POBJDATA pdataObj,
  760. POBJDATA pdataResult)
  761. {
  762. TRACENAME("RAWFIELDACCESS")
  763. NTSTATUS rc = STATUS_SUCCESS;
  764. POBJDATA pdataParent;
  765. POPREGIONOBJ pop;
  766. PRSACCESS prsa;
  767. PFIELDUNITOBJ pfuFieldUnit;
  768. ENTER(3, ("RawFieldAccess(pctxt=%x,AccType=%x,pdataObj=%x,pdata=%x)\n",
  769. pctxt, dwAccType, pdataObj, pdataResult));
  770. pdataParent =
  771. &((PFIELDUNITOBJ)pdataObj->pbDataBuff)->pnsFieldParent->ObjData;
  772. switch (pdataParent->dwDataType)
  773. {
  774. case OBJTYPE_FIELD:
  775. pop = (POPREGIONOBJ)
  776. ((PFIELDOBJ)pdataParent->pbDataBuff)->pnsBase->ObjData.pbDataBuff;
  777. break;
  778. default:
  779. rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
  780. ("RawFieldAccess: invalid field parent type (type=%s)",
  781. pdataParent->dwDataType));
  782. pop = NULL;
  783. }
  784. if (rc == STATUS_SUCCESS)
  785. {
  786. if (((prsa = FindRSAccess(pop->bRegionSpace)) != NULL) &&
  787. (prsa->pfnRawAccess != NULL))
  788. {
  789. #ifdef DEBUGGER
  790. ULONG dwOldFlags = gDebugger.dwfDebugger;
  791. if (dwOldFlags & DBGF_AMLTRACE_ON)
  792. {
  793. gDebugger.dwfDebugger &= ~DBGF_AMLTRACE_ON;
  794. }
  795. #endif
  796. ASSERT(!(pctxt->dwfCtxt & CTXTF_READY));
  797. if ((pfuFieldUnit = NEWFUOBJ(pctxt->pheapCurrent, sizeof (FIELDUNITOBJ))) == NULL) {
  798. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  799. ("RawFieldAccess: failed to allocate Field unit"));
  800. } else {
  801. RtlCopyMemory (pfuFieldUnit, (PFIELDUNITOBJ)pdataObj->pbDataBuff, sizeof (FIELDUNITOBJ));
  802. pfuFieldUnit->FieldDesc.dwByteOffset += (ULONG) pop->uipOffset;
  803. rc = prsa->pfnRawAccess(dwAccType,
  804. pfuFieldUnit,
  805. pdataResult, prsa->uipRawParam,
  806. RestartCtxtCallback, &pctxt->CtxtData);
  807. if (rc == STATUS_BUFFER_TOO_SMALL) {
  808. //
  809. // When opregion handler returns STATUS_BUFFER_TOO_SMALL, this indicates that it
  810. // needs to have a buffer alloocated for it. The buffer size is returned in
  811. // pdataResult->dwDataValue
  812. //
  813. ASSERT(pdataResult->dwDataType == OBJTYPE_INTDATA);
  814. if ((pdataResult->pbDataBuff = NEWBDOBJ(gpheapGlobal, pdataResult->dwDataValue)) == NULL) {
  815. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  816. ("Buffer: failed to allocate data buffer (size=%d)",
  817. pdataResult->dwDataValue));
  818. } else {
  819. pdataResult->dwDataLen = pdataResult->dwDataValue;
  820. pdataResult->dwDataType = OBJTYPE_BUFFDATA;
  821. rc = prsa->pfnRawAccess(dwAccType,
  822. pfuFieldUnit,
  823. pdataResult, prsa->uipRawParam,
  824. RestartCtxtCallback, &pctxt->CtxtData);
  825. }
  826. }
  827. }
  828. #ifdef DEBUGGER
  829. gDebugger.dwfDebugger = dwOldFlags;
  830. #endif
  831. if (rc == STATUS_PENDING)
  832. {
  833. rc = AMLISTA_PENDING;
  834. }
  835. else if (rc != STATUS_SUCCESS)
  836. {
  837. rc = AMLI_LOGERR(AMLIERR_RS_ACCESS,
  838. ("RawFieldAccess: RegionSpace %x handler returned error %x",
  839. pop->bRegionSpace, rc));
  840. }
  841. }
  842. else
  843. {
  844. rc = AMLI_LOGERR(AMLIERR_INVALID_REGIONSPACE,
  845. ("RawFieldAccess: no handler for RegionSpace %x",
  846. pop->bRegionSpace));
  847. }
  848. }
  849. EXIT(3, ("RawFieldAccess=%x\n", rc));
  850. return rc;
  851. } //RawFieldAccess
  852. /***LP AccessFieldData - Read/Write field object data
  853. *
  854. * ENTRY
  855. * pctxt -> CTXT
  856. * pdataObj -> object
  857. * pfd -> field descriptor
  858. * pdwData -> to hold data read or data to be written
  859. * fRead - TRUE if read access
  860. *
  861. * EXIT-SUCCESS
  862. * returns STATUS_SUCCESS
  863. * EXIT-FAILURE
  864. * returns AMLIERR_ code
  865. */
  866. NTSTATUS LOCAL AccessFieldData(PCTXT pctxt, POBJDATA pdataObj, PFIELDDESC pfd,
  867. PULONG pdwData, BOOLEAN fRead)
  868. {
  869. TRACENAME("ACCESSFIELDDATA")
  870. NTSTATUS rc = STATUS_SUCCESS;
  871. ENTER(3, ("AccessFieldData(pctxt=%x,pdataObj=%x,FieldDesc=%x,pdwData=%x,fRead=%x)\n",
  872. pctxt, pdataObj, pfd, pdwData, fRead));
  873. if (pdataObj->dwDataType == OBJTYPE_BUFFFIELD)
  874. {
  875. if (fRead)
  876. {
  877. rc = ReadBuffField((PBUFFFIELDOBJ)pdataObj->pbDataBuff, pfd,
  878. pdwData);
  879. }
  880. else
  881. {
  882. rc = WriteBuffField((PBUFFFIELDOBJ)pdataObj->pbDataBuff, pfd,
  883. *pdwData);
  884. }
  885. }
  886. else //must be OBJTYPE_FIELDUNIT
  887. {
  888. POBJDATA pdataParent;
  889. PNSOBJ pnsBase = NULL;
  890. pdataParent = &((PFIELDUNITOBJ)pdataObj->pbDataBuff)->pnsFieldParent->ObjData;
  891. if (pdataParent->dwDataType == OBJTYPE_INDEXFIELD)
  892. {
  893. PINDEXFIELDOBJ pif = (PINDEXFIELDOBJ)pdataParent->pbDataBuff;
  894. if (fRead)
  895. {
  896. rc = PushAccFieldObj(pctxt, ReadFieldObj,
  897. &pif->pnsData->ObjData,
  898. &((PFIELDUNITOBJ)pif->pnsData->ObjData.pbDataBuff)->FieldDesc,
  899. (PUCHAR)pdwData, sizeof(ULONG));
  900. }
  901. else
  902. {
  903. ULONG dwPreserveMask, dwAccMask;
  904. dwPreserveMask = ~((SHIFTLEFT(1L, pfd->dwNumBits) - 1) <<
  905. pfd->dwStartBitPos);
  906. dwAccMask = SHIFTLEFT(1L, ACCSIZE(pfd->dwFieldFlags)*8) - 1;
  907. if (((pfd->dwFieldFlags & UPDATERULE_MASK) ==
  908. UPDATERULE_PRESERVE) &&
  909. ((dwPreserveMask & dwAccMask) != 0))
  910. {
  911. rc = PushPreserveWriteObj(pctxt, &pif->pnsData->ObjData,
  912. *pdwData, dwPreserveMask);
  913. }
  914. else
  915. {
  916. rc = PushAccFieldObj(pctxt, WriteFieldObj,
  917. &pif->pnsData->ObjData,
  918. &((PFIELDUNITOBJ)pif->pnsData->ObjData.pbDataBuff)->FieldDesc,
  919. (PUCHAR)pdwData, sizeof(ULONG));
  920. }
  921. }
  922. }
  923. else if ((rc = GetFieldUnitRegionObj(
  924. (PFIELDUNITOBJ)pdataObj->pbDataBuff, &pnsBase)) ==
  925. STATUS_SUCCESS && pnsBase != NULL)
  926. {
  927. rc = AccessBaseField(pctxt, pnsBase, pfd, pdwData, fRead);
  928. }
  929. }
  930. EXIT(3, ("AccessFieldData=%x (Data=%x)\n", rc, pdwData? *pdwData: 0));
  931. return rc;
  932. } //AccessFieldData
  933. /***LP PushPreserveWriteObj - Push a PreserveWrObj frame on the stack
  934. *
  935. * ENTRY
  936. * pctxt -> CTXT
  937. * pdataObj -> object
  938. * dwData - data to be written
  939. * dwPreserveMask - preserve bit mask
  940. *
  941. * EXIT-SUCCESS
  942. * returns STATUS_SUCCESS
  943. * EXIT-FAILURE
  944. * returns AMLIERR_ code
  945. */
  946. NTSTATUS LOCAL PushPreserveWriteObj(PCTXT pctxt, POBJDATA pdataObj,
  947. ULONG dwData, ULONG dwPreserveMask)
  948. {
  949. TRACENAME("PUSHPRESERVEWRITEOBJ")
  950. NTSTATUS rc = STATUS_SUCCESS;
  951. PPRESERVEWROBJ ppwro;
  952. ENTER(3, ("PushPreserveWriteObj(pctxt=%x,pdataObj=%x,Data=%x,PreserveMask=%x)\n",
  953. pctxt, pdataObj, dwData, dwPreserveMask));
  954. if ((rc = PushFrame(pctxt, SIG_PRESERVEWROBJ, sizeof(PRESERVEWROBJ),
  955. PreserveWriteObj, &ppwro)) == STATUS_SUCCESS)
  956. {
  957. ppwro->pdataObj = pdataObj;
  958. ppwro->dwWriteData = dwData;
  959. ppwro->dwPreserveMask = dwPreserveMask;
  960. }
  961. EXIT(3, ("PushPreserveWriteObj=%x\n", rc));
  962. return rc;
  963. } //PushPreserveWriteObj
  964. /***LP PreserveWriteObj - Preserve Write data to a field object
  965. *
  966. * ENTRY
  967. * pctxt -> CTXT
  968. * ppwro -> PRESERVEWROBJ
  969. * rc - status code
  970. *
  971. * EXIT-SUCCESS
  972. * returns STATUS_SUCCESS
  973. * EXIT-FAILURE
  974. * returns AMLIERR_ code
  975. */
  976. NTSTATUS LOCAL PreserveWriteObj(PCTXT pctxt, PPRESERVEWROBJ ppwro, NTSTATUS rc)
  977. {
  978. TRACENAME("PRESERVEWRITEOBJ")
  979. ULONG dwStage = (rc == STATUS_SUCCESS)?
  980. (ppwro->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 2;
  981. ENTER(3, ("PreserveWriteObj(Stage=%d,pctxt=%x,ppwro=%x,rc=%x)\n",
  982. dwStage, pctxt, ppwro, rc));
  983. ASSERT(ppwro->FrameHdr.dwSig == SIG_PRESERVEWROBJ);
  984. switch (dwStage)
  985. {
  986. case 0:
  987. //
  988. // Stage 0: Read the object first.
  989. //
  990. ppwro->FrameHdr.dwfFrame++;
  991. rc = PushAccFieldObj(pctxt, ReadFieldObj, ppwro->pdataObj,
  992. &((PFIELDUNITOBJ)ppwro->pdataObj->pbDataBuff)->FieldDesc,
  993. (PUCHAR)&ppwro->dwReadData, sizeof(ULONG));
  994. break;
  995. case 1:
  996. //
  997. // Stage 1: OR the preserve bits to the data to be written and
  998. // write it.
  999. //
  1000. ppwro->FrameHdr.dwfFrame++;
  1001. ppwro->dwWriteData |= ppwro->dwReadData & ppwro->dwPreserveMask;
  1002. rc = PushAccFieldObj(pctxt, WriteFieldObj, ppwro->pdataObj,
  1003. &((PFIELDUNITOBJ)ppwro->pdataObj->pbDataBuff)->FieldDesc,
  1004. (PUCHAR)&ppwro->dwWriteData, sizeof(ULONG));
  1005. break;
  1006. case 2:
  1007. //
  1008. // Stage 2: Clean up.
  1009. //
  1010. PopFrame(pctxt);
  1011. }
  1012. EXIT(3, ("PreserveWriteObj=%x\n", rc));
  1013. return rc;
  1014. } //PreserveWriteObj
  1015. /***LP AccessBaseField - Access the base field object
  1016. *
  1017. * ENTRY
  1018. * pctxt -> CTXT
  1019. * pnsBase -> OpRegion object
  1020. * pfd -> FIELDDESC
  1021. * pdwData -> result data (for read access) or data to be written
  1022. * fRead - TRUE if read access
  1023. *
  1024. * EXIT-SUCCESS
  1025. * returns STATUS_SUCCESS
  1026. * EXIT-FAILURE
  1027. * returns AMLIERR_ code
  1028. *
  1029. * NOTE
  1030. * If pdwData is NULL, it implies a read access.
  1031. */
  1032. NTSTATUS LOCAL AccessBaseField(PCTXT pctxt, PNSOBJ pnsBase, PFIELDDESC pfd,
  1033. PULONG pdwData, BOOLEAN fRead)
  1034. {
  1035. TRACENAME("ACCESSBASEFIELD")
  1036. NTSTATUS rc = STATUS_SUCCESS;
  1037. POPREGIONOBJ pop;
  1038. ULONG_PTR uipAddr;
  1039. ULONG dwSize, dwDataMask, dwAccMask;
  1040. PRSACCESS prsa;
  1041. BOOLEAN fPreserve;
  1042. ENTER(3, ("AccessBaseField(pctxt=%x,pnsBase=%x,pfd=%x,pdwData=%x,fRead=%x)\n",
  1043. pctxt, pnsBase, pfd, pdwData, fRead));
  1044. ASSERT(pnsBase->ObjData.dwDataType == OBJTYPE_OPREGION);
  1045. pop = (POPREGIONOBJ)pnsBase->ObjData.pbDataBuff;
  1046. uipAddr = (ULONG_PTR)(pop->uipOffset + pfd->dwByteOffset);
  1047. dwSize = ACCSIZE(pfd->dwFieldFlags);
  1048. dwDataMask = (SHIFTLEFT(1L, pfd->dwNumBits) - 1) << pfd->dwStartBitPos;
  1049. dwAccMask = SHIFTLEFT(1L, dwSize*8) - 1;
  1050. fPreserve = (BOOLEAN)(((pfd->dwFieldFlags & UPDATERULE_MASK) ==
  1051. UPDATERULE_PRESERVE) &&
  1052. ((~dwDataMask & dwAccMask) != 0));
  1053. if (!fRead &&
  1054. ((pfd->dwFieldFlags & UPDATERULE_MASK) == UPDATERULE_WRITEASONES))
  1055. {
  1056. *pdwData |= ~dwDataMask;
  1057. }
  1058. switch (pop->bRegionSpace)
  1059. {
  1060. case REGSPACE_MEM:
  1061. if (fRead)
  1062. {
  1063. *pdwData = ReadSystemMem(uipAddr, dwSize, dwDataMask);
  1064. }
  1065. else
  1066. {
  1067. if (fPreserve)
  1068. {
  1069. *pdwData |= ReadSystemMem(uipAddr, dwSize, ~dwDataMask);
  1070. }
  1071. WriteSystemMem(uipAddr, dwSize, *pdwData, dwAccMask);
  1072. }
  1073. break;
  1074. case REGSPACE_IO:
  1075. if (fRead)
  1076. {
  1077. *pdwData = ReadSystemIO((ULONG)uipAddr, dwSize, dwDataMask);
  1078. }
  1079. else
  1080. {
  1081. if (fPreserve)
  1082. {
  1083. *pdwData |= ReadSystemIO((ULONG)uipAddr, dwSize,
  1084. ~dwDataMask);
  1085. }
  1086. WriteSystemIO((ULONG)uipAddr, dwSize, *pdwData);
  1087. }
  1088. break;
  1089. default:
  1090. if (((prsa = FindRSAccess(pop->bRegionSpace)) != NULL) &&
  1091. (prsa->pfnCookAccess != NULL))
  1092. {
  1093. if (fRead)
  1094. {
  1095. #ifdef DEBUGGER
  1096. ULONG dwOldFlags = gDebugger.dwfDebugger;
  1097. if (dwOldFlags & DBGF_TRACE_NONEST)
  1098. {
  1099. gDebugger.dwfDebugger &= ~DBGF_AMLTRACE_ON;
  1100. }
  1101. #endif
  1102. //
  1103. // Read access.
  1104. //
  1105. ASSERT(!(pctxt->dwfCtxt & CTXTF_READY));
  1106. rc = prsa->pfnCookAccess(RSACCESS_READ, pnsBase, uipAddr,
  1107. dwSize, pdwData, prsa->uipCookParam,
  1108. RestartCtxtCallback,
  1109. &pctxt->CtxtData);
  1110. #ifdef DEBUGGER
  1111. gDebugger.dwfDebugger = dwOldFlags;
  1112. #endif
  1113. if (rc == STATUS_PENDING)
  1114. {
  1115. rc = AMLISTA_PENDING;
  1116. }
  1117. else if (rc != STATUS_SUCCESS)
  1118. {
  1119. rc = AMLI_LOGERR(AMLIERR_RS_ACCESS,
  1120. ("AccessBaseField: RegionSpace %x read handler returned error %x",
  1121. pop->bRegionSpace, rc));
  1122. }
  1123. }
  1124. else
  1125. {
  1126. PWRCOOKACC pwca;
  1127. //
  1128. // Write access.
  1129. //
  1130. if ((rc = PushFrame(pctxt, SIG_WRCOOKACC, sizeof(WRCOOKACC),
  1131. WriteCookAccess, &pwca)) ==
  1132. STATUS_SUCCESS)
  1133. {
  1134. pwca->pnsBase = pnsBase;
  1135. pwca->prsa = prsa;
  1136. pwca->dwAddr = (ULONG)uipAddr;
  1137. pwca->dwSize = dwSize;
  1138. pwca->dwData = *pdwData;
  1139. pwca->dwDataMask = dwDataMask;
  1140. pwca->fPreserve = fPreserve;
  1141. }
  1142. }
  1143. }
  1144. else
  1145. {
  1146. rc = AMLI_LOGERR(AMLIERR_INVALID_REGIONSPACE,
  1147. ("AccessBaseField: no handler for RegionSpace %x",
  1148. pop->bRegionSpace));
  1149. }
  1150. }
  1151. EXIT(3, ("AccessBaseField=%x (Value=%x,Addr=%x,Size=%d,DataMask=%x,AccMask=%x)\n",
  1152. rc, *pdwData, uipAddr, dwSize, dwDataMask, dwAccMask));
  1153. return rc;
  1154. } //AccessBaseField
  1155. /***LP WriteCookAccess - do a region space write cook access
  1156. *
  1157. * ENTRY
  1158. * pctxt -> CTXT
  1159. * pwca -> WRCOOKACC
  1160. * rc - status code
  1161. *
  1162. * EXIT-SUCCESS
  1163. * returns STATUS_SUCCESS
  1164. * EXIT-FAILURE
  1165. * returns AMLIERR_ code
  1166. */
  1167. NTSTATUS LOCAL WriteCookAccess(PCTXT pctxt, PWRCOOKACC pwca, NTSTATUS rc)
  1168. {
  1169. TRACENAME("WRCOOKACCESS")
  1170. ULONG dwStage = (rc == STATUS_SUCCESS)?
  1171. (pwca->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 3;
  1172. KIRQL oldIrql;
  1173. LONG busy;
  1174. POPREGIONOBJ pop = (POPREGIONOBJ)pwca->pnsBase->ObjData.pbDataBuff;
  1175. ENTER(3, ("WriteCookAccess(Stage=%d,pctxt=%x,pwca=%x,rc=%x)\n",
  1176. dwStage, pctxt, pwca, rc));
  1177. ASSERT(pwca->FrameHdr.dwSig == SIG_WRCOOKACC);
  1178. switch (dwStage)
  1179. {
  1180. case 0:
  1181. //
  1182. // Stage 0: if PRESERVE, do read first.
  1183. //
  1184. if (pwca->fPreserve)
  1185. {
  1186. #ifdef DEBUGGER
  1187. ULONG dwOldFlags = gDebugger.dwfDebugger;
  1188. if (dwOldFlags & DBGF_TRACE_NONEST)
  1189. {
  1190. gDebugger.dwfDebugger &= ~DBGF_AMLTRACE_ON;
  1191. }
  1192. #endif
  1193. KeAcquireSpinLock(&pop->listLock, &oldIrql);
  1194. if (busy = InterlockedExchange(&pop->RegionBusy, TRUE)) {
  1195. //
  1196. // Somebody is currently using this operation region.
  1197. // Queue this context so that it can be re-started later.
  1198. //
  1199. QueueContext(pctxt,
  1200. 0xffff,
  1201. &pop->plistWaiters);
  1202. }
  1203. KeReleaseSpinLock(&pop->listLock, oldIrql);
  1204. if (busy) {
  1205. rc = AMLISTA_PENDING;
  1206. break;
  1207. }
  1208. pwca->FrameHdr.dwfFrame++;
  1209. ASSERT(!(pctxt->dwfCtxt & CTXTF_READY));
  1210. rc = pwca->prsa->pfnCookAccess(RSACCESS_READ, pwca->pnsBase,
  1211. (ULONG_PTR)pwca->dwAddr,
  1212. pwca->dwSize,
  1213. &pwca->dwDataTmp,
  1214. pwca->prsa->uipCookParam,
  1215. RestartCtxtCallback,
  1216. &pctxt->CtxtData);
  1217. #ifdef DEBUGGER
  1218. gDebugger.dwfDebugger = dwOldFlags;
  1219. #endif
  1220. if (rc == STATUS_PENDING)
  1221. {
  1222. rc = AMLISTA_PENDING;
  1223. }
  1224. else if (rc != STATUS_SUCCESS)
  1225. {
  1226. rc = AMLI_LOGERR(AMLIERR_RS_ACCESS,
  1227. ("WriteCookAccess: RegionSpace %x read handler returned error %x",
  1228. pop->bRegionSpace, rc));
  1229. }
  1230. if (rc != STATUS_SUCCESS)
  1231. {
  1232. break;
  1233. }
  1234. }
  1235. else
  1236. {
  1237. //
  1238. // No preserve, we can skip the ORing.
  1239. //
  1240. pwca->FrameHdr.dwfFrame += 2;
  1241. goto Stage2;
  1242. }
  1243. case 1:
  1244. //
  1245. // Stage 1: OR the preserved bits.
  1246. //
  1247. pwca->dwData |= pwca->dwDataTmp & ~pwca->dwDataMask;
  1248. pwca->FrameHdr.dwfFrame++;
  1249. case 2:
  1250. Stage2:
  1251. //
  1252. // Stage 2: Write the data.
  1253. //
  1254. #ifdef DEBUGGER
  1255. {
  1256. ULONG dwOldFlags = gDebugger.dwfDebugger;
  1257. if (dwOldFlags & DBGF_TRACE_NONEST)
  1258. {
  1259. gDebugger.dwfDebugger &= ~DBGF_AMLTRACE_ON;
  1260. }
  1261. #endif
  1262. pwca->FrameHdr.dwfFrame++;
  1263. ASSERT(!(pctxt->dwfCtxt & CTXTF_READY));
  1264. rc = pwca->prsa->pfnCookAccess(RSACCESS_WRITE, pwca->pnsBase,
  1265. (ULONG_PTR)pwca->dwAddr,
  1266. pwca->dwSize,
  1267. &pwca->dwData,
  1268. pwca->prsa->uipCookParam,
  1269. RestartCtxtCallback,
  1270. &pctxt->CtxtData);
  1271. #ifdef DEBUGGER
  1272. gDebugger.dwfDebugger = dwOldFlags;
  1273. }
  1274. #endif
  1275. if (rc == STATUS_PENDING)
  1276. {
  1277. rc = AMLISTA_PENDING;
  1278. }
  1279. else if (rc != STATUS_SUCCESS)
  1280. {
  1281. rc = AMLI_LOGERR(AMLIERR_RS_ACCESS,
  1282. ("WriteCookAccess: RegionSpace %x read handler returned error %x",
  1283. pop->bRegionSpace, rc));
  1284. }
  1285. if (rc != STATUS_SUCCESS)
  1286. {
  1287. break;
  1288. }
  1289. case 3:
  1290. if (pwca->fPreserve) {
  1291. KeAcquireSpinLock(&pop->listLock, &oldIrql);
  1292. //
  1293. // Restart anybody who blocked while we were in here.
  1294. //
  1295. DequeueAndReadyContext(&pop->plistWaiters);
  1296. //
  1297. // Release the lock on this op-region.
  1298. //
  1299. InterlockedExchange(&pop->RegionBusy, FALSE);
  1300. KeReleaseSpinLock(&pop->listLock, oldIrql);
  1301. }
  1302. //
  1303. // Stage 3: Clean up.
  1304. //
  1305. PopFrame(pctxt);
  1306. }
  1307. EXIT(3, ("WriteCookAccess=%x\n", rc));
  1308. return rc;
  1309. } //WriteCookAccess
  1310. /***LP ReadBuffField - Read data from a buffer field
  1311. *
  1312. * ENTRY
  1313. * pbf -> buffer field object
  1314. * pfd -> field descriptor
  1315. * pdwData -> to hold result data
  1316. *
  1317. * EXIT-SUCCESS
  1318. * returns STATUS_SUCCESS
  1319. * EXIT-FAILURE
  1320. * returns AMLIERR_ code
  1321. */
  1322. NTSTATUS LOCAL ReadBuffField(PBUFFFIELDOBJ pbf, PFIELDDESC pfd, PULONG pdwData)
  1323. {
  1324. TRACENAME("READBUFFFIELD")
  1325. NTSTATUS rc = STATUS_SUCCESS;
  1326. ULONG dwAccSize = ACCSIZE(pfd->dwFieldFlags);
  1327. ENTER(3, ("ReadBuffField(pbf=%x,pfd=%x,pdwData=%x)\n", pbf, pfd, pdwData));
  1328. if (pfd->dwByteOffset + dwAccSize <= pbf->dwBuffLen)
  1329. {
  1330. ULONG dwMask = (SHIFTLEFT(1L, pfd->dwNumBits) - 1) <<
  1331. pfd->dwStartBitPos;
  1332. *pdwData = ReadSystemMem((ULONG_PTR)(pbf->pbDataBuff +
  1333. pfd->dwByteOffset),
  1334. dwAccSize, dwMask);
  1335. }
  1336. else
  1337. {
  1338. rc = AMLI_LOGERR(AMLIERR_INDEX_TOO_BIG,
  1339. ("ReadBuffField: offset exceeding buffer size (Offset=%x,BuffSize=%x,AccSize)",
  1340. pfd->dwByteOffset, pbf->dwBuffLen, dwAccSize));
  1341. }
  1342. EXIT(3, ("ReadBuffField=%x (Data=%x)\n", rc, *pdwData));
  1343. return rc;
  1344. } //ReadBuffField
  1345. /***LP WriteBuffField - Write data to a buffer field
  1346. *
  1347. * ENTRY
  1348. * pbf -> buffer field object
  1349. * pfd -> field descriptor
  1350. * dwData - data
  1351. *
  1352. * EXIT-SUCCESS
  1353. * returns STATUS_SUCCESS
  1354. * EXIT-FAILURE
  1355. * returns AMLIERR_ code
  1356. */
  1357. NTSTATUS LOCAL WriteBuffField(PBUFFFIELDOBJ pbf, PFIELDDESC pfd, ULONG dwData)
  1358. {
  1359. TRACENAME("WRITEBUFFFIELD")
  1360. NTSTATUS rc = STATUS_SUCCESS;
  1361. ULONG dwAccSize = ACCSIZE(pfd->dwFieldFlags);
  1362. ENTER(3, ("WriteBuffField(pbf=%x,pfd=%x,dwData=%x)\n", pbf, pfd, dwData));
  1363. if (pfd->dwByteOffset + dwAccSize <= pbf->dwBuffLen)
  1364. {
  1365. ULONG dwMask = (SHIFTLEFT(1L, pfd->dwNumBits) - 1) <<
  1366. pfd->dwStartBitPos;
  1367. WriteSystemMem((ULONG_PTR)(pbf->pbDataBuff + pfd->dwByteOffset),
  1368. dwAccSize, dwData & dwMask, dwMask);
  1369. }
  1370. else
  1371. {
  1372. rc = AMLI_LOGERR(AMLIERR_INDEX_TOO_BIG,
  1373. ("WriteBuffField: offset exceeding buffer size (Offset=%x,BuffSize=%x,AccSize=%x)",
  1374. pfd->dwByteOffset, pbf->dwBuffLen, dwAccSize));
  1375. }
  1376. EXIT(3, ("WriteBuffField=%x\n", rc));
  1377. return rc;
  1378. } //WriteBuffField
  1379. /***LP ReadSystemMem - Read system memory
  1380. *
  1381. * ENTRY
  1382. * uipAddr - memory address
  1383. * dwSize - size to read
  1384. * dwMask - data mask
  1385. *
  1386. * EXIT
  1387. * return memory content
  1388. */
  1389. ULONG LOCAL ReadSystemMem(ULONG_PTR uipAddr, ULONG dwSize, ULONG dwMask)
  1390. {
  1391. TRACENAME("READSYSTEMMEM")
  1392. ULONG dwData = 0;
  1393. ENTER(3, ("ReadSystemMem(Addr=%x,Size=%d,Mask=%x)\n",
  1394. uipAddr, dwSize, dwMask));
  1395. ASSERT((dwSize == sizeof(UCHAR)) || (dwSize == sizeof(USHORT)) ||
  1396. (dwSize == sizeof(ULONG)));
  1397. MEMCPY(&dwData, (PVOID)uipAddr, dwSize);
  1398. dwData &= dwMask;
  1399. EXIT(3, ("ReadSystemMem=%x\n", dwData));
  1400. return dwData;
  1401. } //ReadSystemMem
  1402. /***LP WriteSystemMem - Write system memory
  1403. *
  1404. * ENTRY
  1405. * uipAddr - memory address
  1406. * dwSize - size to write
  1407. * dwData - data to write
  1408. * dwMask - data mask
  1409. *
  1410. * EXIT
  1411. * return memory content
  1412. */
  1413. VOID LOCAL WriteSystemMem(ULONG_PTR uipAddr, ULONG dwSize, ULONG dwData,
  1414. ULONG dwMask)
  1415. {
  1416. TRACENAME("WRITESYSTEMMEM")
  1417. ULONG dwTmpData = 0;
  1418. ENTER(3, ("WriteSystemMem(Addr=%x,Size=%d,Data=%x,Mask=%x)\n",
  1419. uipAddr, dwSize, dwData, dwMask));
  1420. ASSERT((dwSize == sizeof(UCHAR)) || (dwSize == sizeof(USHORT)) ||
  1421. (dwSize == sizeof(ULONG)));
  1422. MEMCPY(&dwTmpData, (PVOID)uipAddr, dwSize);
  1423. dwTmpData &= ~dwMask;
  1424. dwTmpData |= dwData;
  1425. MEMCPY((PVOID)uipAddr, &dwTmpData, dwSize);
  1426. EXIT(3, ("WriteSystemMem!\n"));
  1427. } //WriteSystemMem
  1428. /***LP ReadSystemIO - Read system IO
  1429. *
  1430. * ENTRY
  1431. * dwAddr - memory address
  1432. * dwSize - size to read
  1433. * dwMask - data mask
  1434. *
  1435. * EXIT
  1436. * return memory content
  1437. */
  1438. ULONG LOCAL ReadSystemIO(ULONG dwAddr, ULONG dwSize, ULONG dwMask)
  1439. {
  1440. TRACENAME("READSYSTEMIO")
  1441. ULONG dwData = 0;
  1442. ENTER(3, ("ReadSystemIO(Addr=%x,Size=%d,Mask=%x)\n",
  1443. dwAddr, dwSize, dwMask));
  1444. ASSERT((dwSize == sizeof(UCHAR)) || (dwSize == sizeof(USHORT)) ||
  1445. (dwSize == sizeof(ULONG)));
  1446. if(CheckSystemIOAddressValidity(TRUE, dwAddr, dwSize, &dwData))
  1447. {
  1448. //
  1449. // HACKHACK: We are adding this here because Dell Latitude laptops with Older
  1450. // BIOS (A07 and older) hang in SMI because there is a non zero value\
  1451. // in CH. We now clear CX to work around their bug.
  1452. //
  1453. #ifdef _X86_
  1454. __asm
  1455. {
  1456. xor cx,cx
  1457. }
  1458. #endif //_X86_
  1459. switch (dwSize)
  1460. {
  1461. case sizeof(UCHAR):
  1462. dwData = (ULONG)READ_PORT_UCHAR((PUCHAR)UlongToPtr(dwAddr));
  1463. break;
  1464. case sizeof(USHORT):
  1465. dwData = (ULONG)READ_PORT_USHORT((PUSHORT)UlongToPtr(dwAddr));
  1466. break;
  1467. case sizeof(ULONG):
  1468. dwData = READ_PORT_ULONG((PULONG)UlongToPtr(dwAddr));
  1469. break;
  1470. }
  1471. }
  1472. dwData &= dwMask;
  1473. EXIT(3, ("ReadSystemIO=%x\n", dwData));
  1474. return dwData;
  1475. } //ReadSystemIO
  1476. /***LP WriteSystemIO - Write system IO
  1477. *
  1478. * ENTRY
  1479. * dwAddr - memory address
  1480. * dwSize - size to write
  1481. * dwData - data to write
  1482. *
  1483. * EXIT
  1484. * return memory content
  1485. */
  1486. VOID LOCAL WriteSystemIO(ULONG dwAddr, ULONG dwSize, ULONG dwData)
  1487. {
  1488. TRACENAME("WRITESYSTEMIO")
  1489. ENTER(3, ("WriteSystemIO(Addr=%x,Size=%d,Data=%x)\n",
  1490. dwAddr, dwSize, dwData));
  1491. ASSERT((dwSize == sizeof(UCHAR)) || (dwSize == sizeof(USHORT)) ||
  1492. (dwSize == sizeof(ULONG)));
  1493. if(CheckSystemIOAddressValidity(FALSE, dwAddr, dwSize, &dwData))
  1494. {
  1495. //
  1496. // HACKHACK: We are adding this here because Dell Latitude laptops with Older
  1497. // BIOS (A07 and older) hang in SMI because there is a non zero value\
  1498. // in CH. We now clear CX to work around their bug.
  1499. //
  1500. #ifdef _X86_
  1501. __asm
  1502. {
  1503. xor cx,cx
  1504. }
  1505. #endif //_X86_
  1506. switch (dwSize)
  1507. {
  1508. case sizeof(UCHAR):
  1509. WRITE_PORT_UCHAR((PUCHAR)UlongToPtr(dwAddr), (UCHAR)dwData);
  1510. break;
  1511. case sizeof(USHORT):
  1512. WRITE_PORT_USHORT((PUSHORT)UlongToPtr(dwAddr), (USHORT)dwData);
  1513. break;
  1514. case sizeof(ULONG):
  1515. WRITE_PORT_ULONG((PULONG)UlongToPtr(dwAddr), dwData);
  1516. break;
  1517. }
  1518. }
  1519. EXIT(3, ("WriteSystemIO!\n"));
  1520. } //WriteSystemIO
  1521. #ifdef DEBUGGER
  1522. /***LP DumpObject - Dump object info.
  1523. *
  1524. * ENTRY
  1525. * pdata -> data
  1526. * pszName -> object name
  1527. * iLevel - indent level
  1528. *
  1529. * EXIT
  1530. * None
  1531. *
  1532. * NOTE
  1533. * If iLevel is negative, no indentation and newline are printed.
  1534. */
  1535. VOID LOCAL DumpObject(POBJDATA pdata, PSZ pszName, int iLevel)
  1536. {
  1537. TRACENAME("DUMPOBJECT")
  1538. BOOLEAN fPrintNewLine;
  1539. int i;
  1540. char szName1[sizeof(NAMESEG) + 1],
  1541. szName2[sizeof(NAMESEG) + 1];
  1542. ENTER(3, ("DumpObject(pdata=%x,Name=%s,Level=%d)\n",
  1543. pdata, pszName, iLevel));
  1544. fPrintNewLine = (BOOLEAN)(iLevel >= 0);
  1545. for (i = 0; i < iLevel; ++i)
  1546. {
  1547. PRINTF("| ");
  1548. }
  1549. if (pszName == NULL)
  1550. {
  1551. pszName = "";
  1552. }
  1553. switch (pdata->dwDataType)
  1554. {
  1555. case OBJTYPE_UNKNOWN:
  1556. PRINTF("Unknown(%s)", pszName);
  1557. break;
  1558. case OBJTYPE_INTDATA:
  1559. PRINTF("Integer(%s:Value=0x%08x[%d])",
  1560. pszName, pdata->uipDataValue, pdata->uipDataValue);
  1561. break;
  1562. case OBJTYPE_STRDATA:
  1563. PRINTF("String(%s:Str=\"%s\")", pszName, pdata->pbDataBuff);
  1564. break;
  1565. case OBJTYPE_BUFFDATA:
  1566. PRINTF("Buffer(%s:Ptr=%x,Len=%d)",
  1567. pszName, pdata->pbDataBuff, pdata->dwDataLen);
  1568. PrintBuffData(pdata->pbDataBuff, pdata->dwDataLen);
  1569. break;
  1570. case OBJTYPE_PKGDATA:
  1571. PRINTF("Package(%s:NumElements=%d){",
  1572. pszName, ((PPACKAGEOBJ)pdata->pbDataBuff)->dwcElements);
  1573. if (fPrintNewLine)
  1574. {
  1575. PRINTF("\n");
  1576. }
  1577. for (i = 0;
  1578. i < (int)((PPACKAGEOBJ)pdata->pbDataBuff)->dwcElements;
  1579. ++i)
  1580. {
  1581. DumpObject(&((PPACKAGEOBJ)pdata->pbDataBuff)->adata[i], NULL,
  1582. fPrintNewLine? iLevel + 1: -1);
  1583. if (!fPrintNewLine &&
  1584. (i < (int)((PPACKAGEOBJ)pdata->pbDataBuff)->dwcElements))
  1585. {
  1586. PRINTF(",");
  1587. }
  1588. }
  1589. for (i = 0; i < iLevel; ++i)
  1590. {
  1591. PRINTF("| ");
  1592. }
  1593. PRINTF("}");
  1594. break;
  1595. case OBJTYPE_FIELDUNIT:
  1596. PRINTF("FieldUnit(%s:FieldParent=%p,ByteOffset=0x%x,StartBit=0x%x,NumBits=%d,FieldFlags=0x%x)",
  1597. pszName,
  1598. ((PFIELDUNITOBJ)pdata->pbDataBuff)->pnsFieldParent,
  1599. ((PFIELDUNITOBJ)pdata->pbDataBuff)->FieldDesc.dwByteOffset,
  1600. ((PFIELDUNITOBJ)pdata->pbDataBuff)->FieldDesc.dwStartBitPos,
  1601. ((PFIELDUNITOBJ)pdata->pbDataBuff)->FieldDesc.dwNumBits,
  1602. ((PFIELDUNITOBJ)pdata->pbDataBuff)->FieldDesc.dwFieldFlags);
  1603. break;
  1604. case OBJTYPE_DEVICE:
  1605. PRINTF("Device(%s)", pszName);
  1606. break;
  1607. case OBJTYPE_EVENT:
  1608. PRINTF("Event(%s:pKEvent=%x)", pszName, pdata->pbDataBuff);
  1609. break;
  1610. case OBJTYPE_METHOD:
  1611. PRINTF("Method(%s:Flags=0x%x,CodeBuff=%p,Len=%d)",
  1612. pszName, ((PMETHODOBJ)pdata->pbDataBuff)->bMethodFlags,
  1613. ((PMETHODOBJ)pdata->pbDataBuff)->abCodeBuff,
  1614. pdata->dwDataLen - FIELD_OFFSET(METHODOBJ, abCodeBuff));
  1615. break;
  1616. case OBJTYPE_MUTEX:
  1617. PRINTF("Mutex(%s:pKMutex=%x)", pszName, pdata->pbDataBuff);
  1618. break;
  1619. case OBJTYPE_OPREGION:
  1620. PRINTF("OpRegion(%s:RegionSpace=%s,Offset=0x%x,Len=%d)",
  1621. pszName,
  1622. GetRegionSpaceName(((POPREGIONOBJ)pdata->pbDataBuff)->bRegionSpace),
  1623. ((POPREGIONOBJ)pdata->pbDataBuff)->uipOffset,
  1624. ((POPREGIONOBJ)pdata->pbDataBuff)->dwLen);
  1625. break;
  1626. case OBJTYPE_POWERRES:
  1627. PRINTF("PowerResource(%s:SystemLevel=0x%x,ResOrder=%d)",
  1628. pszName, ((PPOWERRESOBJ)pdata->pbDataBuff)->bSystemLevel,
  1629. ((PPOWERRESOBJ)pdata->pbDataBuff)->bResOrder);
  1630. break;
  1631. case OBJTYPE_PROCESSOR:
  1632. PRINTF("Processor(%s:ApicID=0x%x,PBlk=0x%x,PBlkLen=%d)",
  1633. pszName, ((PPROCESSOROBJ)pdata->pbDataBuff)->bApicID,
  1634. ((PPROCESSOROBJ)pdata->pbDataBuff)->dwPBlk,
  1635. ((PPROCESSOROBJ)pdata->pbDataBuff)->dwPBlkLen);
  1636. break;
  1637. case OBJTYPE_THERMALZONE:
  1638. PRINTF("ThermalZone(%s)", pszName);
  1639. break;
  1640. case OBJTYPE_BUFFFIELD:
  1641. PRINTF("BufferField(%s:Ptr=%x,Len=%d,ByteOffset=0x%x,StartBit=0x%x,NumBits=%d,FieldFlags=0x%x)",
  1642. pszName, ((PBUFFFIELDOBJ)pdata->pbDataBuff)->pbDataBuff,
  1643. ((PBUFFFIELDOBJ)pdata->pbDataBuff)->dwBuffLen,
  1644. ((PBUFFFIELDOBJ)pdata->pbDataBuff)->FieldDesc.dwByteOffset,
  1645. ((PBUFFFIELDOBJ)pdata->pbDataBuff)->FieldDesc.dwStartBitPos,
  1646. ((PBUFFFIELDOBJ)pdata->pbDataBuff)->FieldDesc.dwNumBits,
  1647. ((PBUFFFIELDOBJ)pdata->pbDataBuff)->FieldDesc.dwFieldFlags);
  1648. break;
  1649. case OBJTYPE_DDBHANDLE:
  1650. PRINTF("DDBHandle(%s:Handle=%x)", pszName, pdata->pbDataBuff);
  1651. break;
  1652. case OBJTYPE_OBJALIAS:
  1653. PRINTF("ObjectAlias(%s:Alias=%s,Type=%s)",
  1654. pszName, GetObjectPath(pdata->pnsAlias),
  1655. GetObjectTypeName(pdata->pnsAlias->ObjData.dwDataType));
  1656. break;
  1657. case OBJTYPE_DATAALIAS:
  1658. PRINTF("DataAlias(%s:Link=%x)", pszName, pdata->pdataAlias);
  1659. if (fPrintNewLine)
  1660. {
  1661. DumpObject(pdata->pdataAlias, NULL, iLevel + 1);
  1662. fPrintNewLine = FALSE;
  1663. }
  1664. break;
  1665. case OBJTYPE_BANKFIELD:
  1666. STRCPYN(szName1,
  1667. (PSZ)(&((PBANKFIELDOBJ)pdata->pbDataBuff)->pnsBase->dwNameSeg),
  1668. sizeof(NAMESEG));
  1669. STRCPYN(szName2,
  1670. (PSZ)(&((PBANKFIELDOBJ)pdata->pbDataBuff)->pnsBank->dwNameSeg),
  1671. sizeof(NAMESEG));
  1672. PRINTF("BankField(%s:Base=%s,BankName=%s,BankValue=0x%x)",
  1673. pszName, szName1, szName2,
  1674. ((PBANKFIELDOBJ)pdata->pbDataBuff)->dwBankValue);
  1675. break;
  1676. case OBJTYPE_FIELD:
  1677. STRCPYN(szName1,
  1678. (PSZ)(&((PFIELDOBJ)pdata->pbDataBuff)->pnsBase->dwNameSeg),
  1679. sizeof(NAMESEG));
  1680. PRINTF("Field(%s:Base=%s)", pszName, szName1);
  1681. break;
  1682. case OBJTYPE_INDEXFIELD:
  1683. STRCPYN(szName1,
  1684. (PSZ)(&((PINDEXFIELDOBJ)pdata->pbDataBuff)->pnsIndex->dwNameSeg),
  1685. sizeof(NAMESEG));
  1686. STRCPYN(szName2,
  1687. (PSZ)(&((PINDEXFIELDOBJ)pdata->pbDataBuff)->pnsData->dwNameSeg),
  1688. sizeof(NAMESEG));
  1689. PRINTF("IndexField(%s:IndexName=%s,DataName=%s)",
  1690. pszName, szName1, szName2);
  1691. break;
  1692. default:
  1693. AMLI_ERROR(("DumpObject: unexpected data object type (type=%x)",
  1694. pdata->dwDataType));
  1695. }
  1696. if (fPrintNewLine)
  1697. {
  1698. PRINTF("\n");
  1699. }
  1700. EXIT(3, ("DumpObject!\n"));
  1701. } //DumpObject
  1702. #endif
  1703. /***LP NeedGlobalLock - check if global lock is required
  1704. *
  1705. * ENTRY
  1706. * pfu - FIELDUNITOBJ
  1707. *
  1708. * EXIT-SUCCESS
  1709. * returns TRUE
  1710. * EXIT-FAILURE
  1711. * returns FALSE
  1712. */
  1713. BOOLEAN LOCAL NeedGlobalLock(PFIELDUNITOBJ pfu)
  1714. {
  1715. TRACENAME("NEEDGLOBALLOCK")
  1716. BOOLEAN rc = FALSE;
  1717. ENTER(3, ("NeedGlobalLock(pfu=%x)\n", pfu));
  1718. if ((pfu->FieldDesc.dwFieldFlags & FDF_NEEDLOCK) ||
  1719. (pfu->FieldDesc.dwFieldFlags & LOCKRULE_LOCK))
  1720. {
  1721. rc = TRUE;
  1722. }
  1723. else
  1724. {
  1725. POBJDATA pdataParent = &pfu->pnsFieldParent->ObjData;
  1726. PFIELDUNITOBJ pfuParent;
  1727. if (pdataParent->dwDataType == OBJTYPE_BANKFIELD)
  1728. {
  1729. pfuParent = (PFIELDUNITOBJ)
  1730. ((PBANKFIELDOBJ)pdataParent->pbDataBuff)->pnsBank->ObjData.pbDataBuff;
  1731. if (pfuParent->FieldDesc.dwFieldFlags & LOCKRULE_LOCK)
  1732. {
  1733. rc = TRUE;
  1734. }
  1735. }
  1736. else if (pdataParent->dwDataType == OBJTYPE_INDEXFIELD)
  1737. {
  1738. pfuParent = (PFIELDUNITOBJ)
  1739. ((PINDEXFIELDOBJ)pdataParent->pbDataBuff)->pnsIndex->ObjData.pbDataBuff;
  1740. if (pfuParent->FieldDesc.dwFieldFlags & LOCKRULE_LOCK)
  1741. {
  1742. rc = TRUE;
  1743. }
  1744. else
  1745. {
  1746. pfuParent = (PFIELDUNITOBJ)
  1747. ((PINDEXFIELDOBJ)pdataParent->pbDataBuff)->pnsData->ObjData.pbDataBuff;
  1748. if (pfuParent->FieldDesc.dwFieldFlags & LOCKRULE_LOCK)
  1749. {
  1750. rc = TRUE;
  1751. }
  1752. }
  1753. }
  1754. }
  1755. if (rc == TRUE)
  1756. {
  1757. pfu->FieldDesc.dwFieldFlags |= FDF_NEEDLOCK;
  1758. }
  1759. EXIT(3, ("NeedGlobalLock=%x\n", rc));
  1760. return rc;
  1761. } //NeedGlobalLock
  1762. /***LP CheckSystemIOAddressValidity - Check if the address is a legal IO address
  1763. *
  1764. * ENTRY
  1765. * fRead - TRUE iff access is a read. FALSE on write
  1766. * dwAddr - memory address
  1767. * ULONG dwSize - Size of data
  1768. * PULONG pdwData - Pointer to the data buffer.
  1769. *
  1770. * EXIT
  1771. * return TRUE on Valid address
  1772. */
  1773. BOOLEAN LOCAL CheckSystemIOAddressValidity( BOOLEAN fRead,
  1774. ULONG dwAddr,
  1775. ULONG dwSize,
  1776. PULONG pdwData
  1777. )
  1778. {
  1779. TRACENAME("CHECKSYSTEMIOADDRESSVALIDITY")
  1780. ULONG i = 0;
  1781. BOOLEAN bRet = TRUE;
  1782. ENTER(3, ("CheckSystemIOAddressValidity(fRead=%s, dwAddr=%x, dwSize=%x, pdwData=%x)\n", (fRead?"TRUE":"FALSE"),dwAddr, dwSize, pdwData));
  1783. //
  1784. // check if list exists on this platform.
  1785. //
  1786. if(gpBadIOAddressList)
  1787. {
  1788. //
  1789. // Walk the list till we hit the end.
  1790. //
  1791. for(i=0; gpBadIOAddressList[i].BadAddrSize != 0 ; i++)
  1792. {
  1793. //
  1794. // Check if the incoming address is in the range
  1795. //
  1796. if((dwAddr >= (gpBadIOAddressList[i].BadAddrBegin)) && (dwAddr < ((gpBadIOAddressList[i].BadAddrBegin) + (gpBadIOAddressList[i].BadAddrSize))))
  1797. {
  1798. //
  1799. // Check if we need to ignore this address for legacy reasons.
  1800. //
  1801. if(gpBadIOAddressList[i].OSVersionTrigger <= gdwHighestOSVerQueried)
  1802. {
  1803. bRet = FALSE;
  1804. PRINTF("CheckSystemIOAddressValidity: failing illegal IO address (0x%x).\n", dwAddr);
  1805. }
  1806. else
  1807. {
  1808. PRINTF("CheckSystemIOAddressValidity: Passing for compatibility reasons on illegal IO address (0x%x).\n", dwAddr);
  1809. if(gpBadIOAddressList[i].IOHandler)
  1810. {
  1811. //
  1812. // Since we are handeling this here we can return FALSE. This way the
  1813. // calling function will not process this request.
  1814. //
  1815. bRet = FALSE;
  1816. //
  1817. // Call HAL and let it handle this IO request
  1818. //
  1819. (gpBadIOAddressList[i].IOHandler)(fRead, dwAddr, dwSize, pdwData);
  1820. PRINTF("CheckSystemIOAddressValidity: HAL IO handler called to %s address (0x%x). %s 0x%8lx\n",
  1821. fRead ? "read" : "write",
  1822. dwAddr,
  1823. fRead ? "Read" : "Wrote",
  1824. *pdwData
  1825. );
  1826. }
  1827. }
  1828. //
  1829. // Log the illegal access to the event log.
  1830. //
  1831. if (KeGetCurrentIrql() < DISPATCH_LEVEL)
  1832. {
  1833. LogInErrorLog(fRead,
  1834. dwAddr,
  1835. i
  1836. );
  1837. }
  1838. else
  1839. {
  1840. PIO_WORKITEM Log_WorkItem = NULL;
  1841. PDEVICE_OBJECT pACPIDeviceObject = ACPIGetRootDeviceObject();
  1842. if(pACPIDeviceObject)
  1843. {
  1844. Log_WorkItem = IoAllocateWorkItem(pACPIDeviceObject);
  1845. if(Log_WorkItem)
  1846. {
  1847. PAMLI_LOG_WORKITEM_CONTEXT pWorkItemContext = NULL;
  1848. pWorkItemContext = (PAMLI_LOG_WORKITEM_CONTEXT) ExAllocatePoolWithTag(NonPagedPool,
  1849. sizeof(AMLI_LOG_WORKITEM_CONTEXT),
  1850. PRIV_TAG
  1851. );
  1852. if(pWorkItemContext)
  1853. {
  1854. pWorkItemContext->fRead = fRead;
  1855. pWorkItemContext->Address = dwAddr;
  1856. pWorkItemContext->Index = i;
  1857. pWorkItemContext->pIOWorkItem = Log_WorkItem;
  1858. IoQueueWorkItem(
  1859. Log_WorkItem,
  1860. DelayedLogInErrorLog,
  1861. DelayedWorkQueue,
  1862. (VOID*)pWorkItemContext
  1863. );
  1864. }
  1865. else
  1866. {
  1867. //
  1868. // not enough free pool exists to satisfy the request.
  1869. //
  1870. PRINTF("CheckSystemIOAddressValidity: Failed to allocate contxt block from pool to spin off a logging work item.\n");
  1871. IoFreeWorkItem(Log_WorkItem);
  1872. }
  1873. }
  1874. else
  1875. {
  1876. //
  1877. // insufficient resources
  1878. //
  1879. PRINTF("CheckSystemIOAddressValidity: Failed to allocate a workitem to spin off delayed logging.\n");
  1880. }
  1881. }
  1882. else
  1883. {
  1884. //
  1885. // Failed to get ACPI root DeviceObject
  1886. //
  1887. PRINTF("CheckSystemIOAddressValidity: Failed to get ACPI root DeviceObject.\n");
  1888. }
  1889. }
  1890. break;
  1891. }
  1892. }
  1893. }
  1894. EXIT(3, ("CheckSystemIOAddressValidity!\n"));
  1895. return bRet;
  1896. }
  1897. /***LP DelayedLogInErrorLog - Call LogInErrorLog
  1898. *
  1899. * ENTRY
  1900. * PDEVICE_OBJECT DeviceObject - Device Object.
  1901. * PVOID Context - Context pointer with data to call LogInErrorLog with.
  1902. *
  1903. * EXIT
  1904. * VOID
  1905. */
  1906. VOID DelayedLogInErrorLog(
  1907. IN PDEVICE_OBJECT DeviceObject,
  1908. IN PVOID Context
  1909. )
  1910. {
  1911. LogInErrorLog(((PAMLI_LOG_WORKITEM_CONTEXT)Context)->fRead,
  1912. ((PAMLI_LOG_WORKITEM_CONTEXT)Context)->Address,
  1913. ((PAMLI_LOG_WORKITEM_CONTEXT)Context)->Index
  1914. );
  1915. IoFreeWorkItem((PIO_WORKITEM)((PAMLI_LOG_WORKITEM_CONTEXT)Context)->pIOWorkItem);
  1916. ExFreePool(Context);
  1917. }
  1918. /***LP LogInErrorLog - Log illegal IO access to event log
  1919. *
  1920. * ENTRY
  1921. * fRead - TRUE iff access is a read. FALSE on write
  1922. * dwAddr - Memory address
  1923. * ArrayIndex - Index into BadIOAddressList array.
  1924. *
  1925. * EXIT
  1926. * None.
  1927. */
  1928. VOID LOCAL LogInErrorLog(BOOLEAN fRead, ULONG dwAddr, ULONG ArrayIndex)
  1929. {
  1930. TRACENAME("LOGERROR")
  1931. PWCHAR illegalIOPortAddress[3];
  1932. WCHAR AMLIName[6];
  1933. WCHAR addressBuffer[13];
  1934. WCHAR addressRangeBuffer[16];
  1935. ENTER(3, ("LogInErrorLog(fRead=%s, Addr=%x, ArrayIndex=%x)\n", (fRead?"TRUE":"FALSE"),dwAddr, ArrayIndex));
  1936. //
  1937. // Check to see if we need to log this address.
  1938. //
  1939. if(gpBadIOErrorLogDoneList)
  1940. {
  1941. //
  1942. // Check to see if we need to log this address.
  1943. //
  1944. if (!(gpBadIOErrorLogDoneList[ArrayIndex] & (fRead?READ_ERROR_NOTED:WRITE_ERROR_NOTED)))
  1945. {
  1946. gpBadIOErrorLogDoneList[ArrayIndex] |= (fRead?READ_ERROR_NOTED:WRITE_ERROR_NOTED);
  1947. //
  1948. // Turn the address into a string
  1949. //
  1950. swprintf( AMLIName, L"AMLI");
  1951. swprintf( addressBuffer, L"0x%x", dwAddr );
  1952. swprintf( addressRangeBuffer, L"0x%x - 0x%x",
  1953. gpBadIOAddressList[ArrayIndex].BadAddrBegin,
  1954. (gpBadIOAddressList[ArrayIndex].BadAddrBegin + (gpBadIOAddressList[ArrayIndex].BadAddrSize - 1)));
  1955. //
  1956. // Build the list of arguments to pass to the function that will write the
  1957. // error log to the registry
  1958. //
  1959. illegalIOPortAddress[0] = AMLIName;
  1960. illegalIOPortAddress[1] = addressBuffer;
  1961. illegalIOPortAddress[2] = addressRangeBuffer;
  1962. //
  1963. // Log error to event log
  1964. //
  1965. ACPIWriteEventLogEntry((fRead ? ACPI_ERR_AMLI_ILLEGAL_IO_READ_FATAL : ACPI_ERR_AMLI_ILLEGAL_IO_WRITE_FATAL),
  1966. &illegalIOPortAddress,
  1967. 3,
  1968. NULL,
  1969. 0);
  1970. }
  1971. }
  1972. EXIT(3, ("LogInErrorLog!\n"));
  1973. return;
  1974. }
  1975. /***LP InitIllegalIOAddressListFromHAL - Initialize the Illegal IO
  1976. * address List from the HAL.
  1977. *
  1978. * ENTRY
  1979. * None.
  1980. *
  1981. * EXIT
  1982. * None.
  1983. */
  1984. VOID LOCAL InitIllegalIOAddressListFromHAL(VOID)
  1985. {
  1986. TRACENAME("InitIllegalIOAddressListFromHAL")
  1987. ULONG Length = 0;
  1988. NTSTATUS status;
  1989. ENTER(3, ("InitIllegalIOAddressListFromHAL\n"));
  1990. if(!gpBadIOAddressList)
  1991. {
  1992. //
  1993. // Query HAL to get the amount of memory to allocate
  1994. //
  1995. status = HalQuerySystemInformation (
  1996. HalQueryAMLIIllegalIOPortAddresses,
  1997. 0,
  1998. NULL,
  1999. &Length
  2000. );
  2001. if(status == STATUS_INFO_LENGTH_MISMATCH)
  2002. {
  2003. if(Length)
  2004. {
  2005. //
  2006. // Allocate memory.
  2007. //
  2008. if ((gpBadIOAddressList = (PHAL_AMLI_BAD_IO_ADDRESS_LIST) MALLOC(Length, PRIV_TAG)) == NULL)
  2009. {
  2010. AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  2011. ("InitIllegalIOAddressListFromHAL: failed to allocate Bad IO address list."));
  2012. }
  2013. else
  2014. {
  2015. //
  2016. // Get bad IO address list from HAL.
  2017. //
  2018. status = HalQuerySystemInformation(
  2019. HalQueryAMLIIllegalIOPortAddresses,
  2020. Length,
  2021. gpBadIOAddressList,
  2022. &Length
  2023. );
  2024. //
  2025. // Cleanup on failure.
  2026. //
  2027. if(status != STATUS_SUCCESS)
  2028. {
  2029. PRINTF("InitIllegalIOAddressListFromHAL: HalQuerySystemInformation failed to get list from HAL. Returned(%x).\n", status);
  2030. FreellegalIOAddressList();
  2031. }
  2032. // Allocate the errorlogdone list. this helps us track if we have logged
  2033. // a certain address.
  2034. //
  2035. else
  2036. {
  2037. //
  2038. // Calculate array length
  2039. //
  2040. ULONG ArrayLength = (Length / sizeof(HAL_AMLI_BAD_IO_ADDRESS_LIST)) - 1;
  2041. if(ArrayLength >= 1)
  2042. {
  2043. if ((gpBadIOErrorLogDoneList = (PULONG) MALLOC((ArrayLength * sizeof(ULONG)), PRIV_TAG)) == NULL)
  2044. {
  2045. AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  2046. ("InitIllegalIOAddressListFromHAL: failed to allocate ErrorLogDone list."));
  2047. }
  2048. else
  2049. {
  2050. RtlZeroMemory(gpBadIOErrorLogDoneList, (ArrayLength * sizeof(ULONG)));
  2051. }
  2052. }
  2053. }
  2054. }
  2055. }
  2056. else
  2057. {
  2058. PRINTF("InitIllegalIOAddressListFromHAL: HalQuerySystemInformation (HalQueryIllegalIOPortAddresses) returned 0 Length.\n");
  2059. }
  2060. }
  2061. else if(status == STATUS_INVALID_LEVEL)
  2062. {
  2063. PRINTF("InitIllegalIOAddressListFromHAL: HalQuerySystemInformation does not support HalQueryIllegalIOPortAddresses returned (STATUS_INVALID_LEVEL).\n");
  2064. }
  2065. else
  2066. {
  2067. PRINTF("InitIllegalIOAddressListFromHAL: failed. Returned(0x%08lx).\n", status);
  2068. }
  2069. }
  2070. EXIT(3, ("InitIllegalIOAddressListFromHAL!\n"));
  2071. return;
  2072. }
  2073. /***LP FreellegalIOAddressList - Free the Illegal IO
  2074. * address List.
  2075. *
  2076. * ENTRY
  2077. * None.
  2078. *
  2079. * EXIT
  2080. * None.
  2081. */
  2082. VOID LOCAL FreellegalIOAddressList(VOID)
  2083. {
  2084. TRACENAME("FreellegalIOAddressList")
  2085. ENTER(3, ("FreellegalIOAddressList\n"));
  2086. if(gpBadIOAddressList)
  2087. {
  2088. MFREE(gpBadIOAddressList);
  2089. gpBadIOAddressList = NULL;
  2090. }
  2091. if(gpBadIOErrorLogDoneList)
  2092. {
  2093. MFREE(gpBadIOErrorLogDoneList);
  2094. gpBadIOErrorLogDoneList = NULL;
  2095. }
  2096. EXIT(3, ("FreellegalIOAddressList!\n"));
  2097. return;
  2098. }