Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1120 lines
27 KiB

  1. title "Cmos Access Routines"
  2. ;++
  3. ;
  4. ; Module Name:
  5. ;
  6. ; ixcmos.asm
  7. ;
  8. ; Abstract:
  9. ;
  10. ; Procedures necessary to access CMOS/ECMOS information.
  11. ;
  12. ; Author:
  13. ;
  14. ; David Risner (o-ncrdr) 20 Apr 1992
  15. ;
  16. ; Revision History:
  17. ;
  18. ; Landy Wang (corollary!landy) 04 Dec 1992
  19. ; - Move much code from ixclock.asm to here so different HALs
  20. ; can reuse the common functionality.
  21. ;
  22. ;--
  23. .386p
  24. .xlist
  25. include hal386.inc
  26. include callconv.inc ; calling convention macros
  27. include mac386.inc
  28. include i386\ix8259.inc
  29. include i386\ixcmos.inc
  30. .list
  31. EXTRNP _DbgBreakPoint,0,IMPORT
  32. extrn _HalpSystemHardwareLock:DWORD
  33. extrn _HalpBusType:DWORD
  34. extrn _HalpSerialLen:BYTE
  35. extrn _HalpSerialNumber:BYTE
  36. _DATA SEGMENT DWORD PUBLIC 'DATA'
  37. ;
  38. ; HalpRebootNow is a reboot vector. Set in an MP system, to
  39. ; cause any processors which may be looping in HalpAcquireCmosSinLock
  40. ; to transfer control to the vector in HalpRebootNow
  41. ;
  42. public _HalpRebootNow
  43. _HalpRebootNow dd 0
  44. ;
  45. ; Holds the value of the eflags register before a cmos spinlock is
  46. ; acquired (used in HalpAcquire/ReleaseCmosSpinLock().
  47. ;
  48. _HalpHardwareLockFlags dd 0
  49. ;
  50. ; Holds the offset to CMOS Century information.
  51. ;
  52. public _HalpCmosCenturyOffset
  53. _HalpCmosCenturyOffset dd 0
  54. _DATA ends
  55. subttl "HalpGetCmosData"
  56. ;++
  57. ;
  58. ; CMOS space read and write functions.
  59. ;
  60. ;--
  61. CmosAddressPort equ 70H
  62. CmosDataPort equ 71H
  63. ECmosAddressLsbPort equ 74H
  64. ECmosAddressMsbPort equ 75H
  65. ECmosDataPort equ 76H
  66. INIT SEGMENT DWORD PUBLIC 'CODE'
  67. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  68. ifndef ACPI_HAL
  69. ;++
  70. ;
  71. ; VOID
  72. ; HalpInitializeCmos(
  73. ; VOID
  74. ; )
  75. ;
  76. ; This routine reads CMOS and initializes globals required for
  77. ; CMOS access, such as the location of the century byte.
  78. ;
  79. ;--
  80. cPublicProc _HalpInitializeCmos,0
  81. push ebx
  82. push esi
  83. push edi
  84. ;
  85. ; Assume default
  86. ;
  87. mov eax, RTC_OFFSET_CENTURY
  88. mov _HalpCmosCenturyOffset, eax
  89. cmp _HalpBusType, MACHINE_TYPE_ISA
  90. jne icm40
  91. ;
  92. ; If control comes here, this is ISA machine. We need to check if this is
  93. ; IBM PS/1 or Pc/ValuePoint machine and use RTC_CENTURY_OFFSET_MCA to get
  94. ; Century byte from CMOS.
  95. ;
  96. ;
  97. ; Check if the CMOS 2e and 2f contains memory checksum. On PS/1 machine
  98. ; the check should fail.
  99. ;
  100. icm20: mov ecx, 2dh ; from 10h to 2dh
  101. mov eax, 0 ; clear ax
  102. mov edx, 0
  103. icm30: mov al, cl
  104. CMOS_READ
  105. add edx, eax
  106. dec ecx
  107. cmp ecx, 0fh
  108. jne short icm30
  109. mov eax, 2eh
  110. CMOS_READ
  111. mov ah, al
  112. mov al, 2fh
  113. CMOS_READ
  114. cmp eax, edx
  115. je short icm50 ; NOT PS/1
  116. mov eax, RTC_OFFSET_CENTURY_MCA
  117. mov _HalpCmosCenturyOffset, eax
  118. jmp icm90
  119. icm40: cmp _HalpBusType, MACHINE_TYPE_MCA
  120. jne short icm50
  121. ;
  122. ; See if this is a P700 MCA machine
  123. ;
  124. in al, 07fh ; get PD700 ID byte
  125. and al, 0F0h ; Mask high nibble
  126. cmp al, 0A0h ; Is the ID Ax?
  127. jz short icm50
  128. cmp al, 090h ; Or an 9X?
  129. jz short icm50 ; Yes, it's a 700
  130. mov eax, RTC_OFFSET_CENTURY_MCA
  131. mov _HalpCmosCenturyOffset, eax
  132. icm50:
  133. if 0
  134. - Selecting BANK1 causes some devices to mess up their month value
  135. - For now, I'm removing this code until this problem can be solved
  136. ;
  137. ; See if this is a Dallas Semiconductor DS17285 or later
  138. ; Switch to BANK 1
  139. ;
  140. mov al, 0Ah
  141. CMOS_READ
  142. and al, 7fh ; Don't write UIP
  143. mov ah, al
  144. mov esi, eax ; save it for restore
  145. or ah, 10h ; Set DV0 = 1
  146. mov al, 0Ah ; Write register A
  147. CMOS_WRITE
  148. ;
  149. ; Check for RTC serial # with matching crc
  150. ; (al) = current byte
  151. ; (ah) = scratch register
  152. ; (bl) = current crc
  153. ; (bh) = zero, non-zero, flag
  154. ; (ecx) = cmos offset
  155. ; (edx) = used by cmos_read macro
  156. ; (esi) = saved register 0A
  157. ;
  158. mov ecx, 40h
  159. xor ebx, ebx
  160. icm60: mov al, cl
  161. CMOS_READ
  162. mov byte ptr _HalpSerialNumber+2+-40h[ecx], al
  163. or bh, al ; or to check for all zeros
  164. mov ch, 8 ; Bits per byte
  165. icm65: mov ah, bl ; ah = crc
  166. xor ah, al ; xor LSb
  167. shr bl, 1 ; shift crc
  168. shr ah, 1 ; mov LSb to carry
  169. sbb ah, ah ; if carry set 1's else 0's
  170. and ah, (118h shr 1) ; crc polynomial
  171. xor bl, ah ; apply it
  172. shr al, 1 ; next bit
  173. dec ch ;
  174. jnz short icm65 ; if ch non-zero, loop
  175. inc cl ; next cmos location
  176. cmp cl, 48h ; at end?
  177. jne short icm60 ; no, loop
  178. ;
  179. ; (bh) = zero, non-zero flag
  180. ; (bl) = crc
  181. ;
  182. mov eax, RTC_OFFSET_CENTURY_DS ; Read century byte
  183. CMOS_READ
  184. BCD_TO_BIN
  185. movzx ecx, ax ; save it
  186. ;
  187. ; Switch back to BANK 0
  188. ;
  189. mov eax, esi
  190. mov al, 0Ah
  191. CMOS_WRITE
  192. ;
  193. ; Check for valid DS data
  194. ;
  195. cmp bh, 0 ; Was data all zeros?
  196. je short icm90
  197. cmp bl, 0 ; was CRC valid?
  198. jnz short icm90
  199. cmp ecx, 19 ; Is century before 19?
  200. jb short icm90
  201. cmp ecx, 20 ; Is century after 20?
  202. ja short icm90
  203. ;
  204. ; Setup for DS century byte
  205. ;
  206. mov byte ptr _HalpSerialNumber+0, 'D'
  207. mov byte ptr _HalpSerialNumber+1, 'S'
  208. mov _HalpSerialLen, 10
  209. mov eax, RTC_OFFSET_CENTURY_DS
  210. mov _HalpCmosCenturyOffset, eax
  211. endif
  212. icm90: pop edi
  213. pop esi
  214. pop ebx
  215. stdRET _HalpInitializeCmos
  216. stdENDP _HalpInitializeCmos
  217. endif
  218. INIT ends
  219. _TEXT SEGMENT DWORD PUBLIC 'CODE'
  220. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  221. ;++
  222. ;
  223. ; ULONG
  224. ; HalpGetCmosData(
  225. ; IN ULONG SourceLocation
  226. ; IN ULONG SourceAddress
  227. ; IN ULONG ReturnBuffer
  228. ; IN PUCHAR ByteCount
  229. ; )
  230. ;
  231. ; This routine reads the requested number of bytes from CMOS/ECMOS and
  232. ; stores the data read into the supplied buffer in system memory. If
  233. ; the requested data amount exceeds the allowable extent of the source
  234. ; location, the return data is truncated.
  235. ;
  236. ; Arguments:
  237. ;
  238. ; SourceLocation : where data is to be read from CMOS or ECMOS
  239. ; 0 - CMOS, 1 - ECMOS
  240. ;
  241. ; SourceAddress : address in CMOS/ECMOS where data is to be read from
  242. ;
  243. ; ReturnBuffer : address in system memory for return data
  244. ;
  245. ; ByteCount : number of bytes to be read
  246. ;
  247. ; Returns:
  248. ;
  249. ; Number of byte actually read.
  250. ;
  251. ;--
  252. SourceLocation equ 2*4[ebp]
  253. SourceAddress equ 3*4[ebp]
  254. ReturnBuffer equ 4*4[ebp]
  255. ByteCount equ 5*4[ebp]
  256. cPublicProc _HalpGetCmosData ,4
  257. push ebp
  258. mov ebp, esp
  259. push ebx
  260. push edi
  261. ;
  262. ; NOTE: The spinlock is needed even in the UP case, because
  263. ; the resource is also used in an interrupt handler (profiler).
  264. ; If we own the spinlock in this routine, and we service
  265. ; the profiler interrupt (which will wait for the spinlock forever),
  266. ; then we have a hosed system.
  267. ;
  268. stdCall _HalpAcquireCmosSpinLock
  269. xor edx, edx ; initialize return data length
  270. mov ecx, ByteCount
  271. or ecx, ecx ; validate requested byte count
  272. jz HalpGetCmosDataExit ; if no work to do, exit
  273. mov edx, SourceAddress
  274. mov edi, ReturnBuffer
  275. mov eax, SourceLocation ; cmos or extended cmos?
  276. cmp eax, 1
  277. je ECmosReadByte
  278. cmp eax, 0
  279. jne HalpGetCmosDataExit
  280. CmosReadByte:
  281. cmp edx, 0ffH ; validate cmos source address
  282. ja HalpGetCmosDataExit ; if out of range, exit
  283. mov al, dl
  284. out CmosAddressPort, al
  285. in al, CmosDataPort
  286. mov [edi], al
  287. inc edx
  288. inc edi
  289. dec ecx
  290. jnz CmosReadByte
  291. jmp SHORT HalpGetCmosDataExit
  292. ECmosReadByte:
  293. cmp edx,0ffffH ; validate ecmos source address
  294. ja HalpGetCmosDataExit ; if out of range, exit
  295. mov al, dl
  296. out ECmosAddressLsbPort, al
  297. mov al, dh
  298. out ECmosAddressMsbPort, al
  299. in al, ECmosDataPort
  300. mov [edi], al
  301. inc edx
  302. inc edi
  303. dec ecx
  304. jnz ECmosReadByte
  305. HalpGetCmosDataExit:
  306. stdCall _HalpReleaseCmosSpinLock
  307. mov eax, edx ; return bytes read
  308. sub eax, SourceAddress ; subtract the initial offset
  309. pop edi
  310. pop ebx
  311. pop ebp
  312. stdRET _HalpGetCmosData
  313. stdENDP _HalpGetCmosData
  314. ;++
  315. ;
  316. ; VOID
  317. ; HalpSetCmosData(
  318. ; IN ULONG SourceLocation
  319. ; IN ULONG SourceAddress
  320. ; IN ULONG ReturnBuffer
  321. ; IN PUCHAR ByteCount
  322. ; )
  323. ;
  324. ; This routine writes the requested number of bytes to CMOS/ECMOS
  325. ;
  326. ; Arguments:
  327. ;
  328. ; SourceLocation : where data is to be written to CMOS or ECMOS
  329. ; 0 - CMOS, 1 - ECMOS
  330. ;
  331. ; SourceAddress : address in CMOS/ECMOS where data is to write to.
  332. ;
  333. ; ReturnBuffer : address in system memory for data to write
  334. ;
  335. ; ByteCount : number of bytes to be write
  336. ;
  337. ; Returns:
  338. ;
  339. ; Number of byte actually written.
  340. ;
  341. ;--
  342. cPublicProc _HalpSetCmosData ,4
  343. push ebp
  344. mov ebp, esp
  345. push ebx
  346. push edi
  347. stdCall _HalpAcquireCmosSpinLock
  348. xor edx, edx ; initialize return data length
  349. mov ecx, ByteCount
  350. or ecx, ecx ; validate requested byte count
  351. jz HalpSetCmosDataExit ; if no work to do, exit
  352. mov edx, SourceAddress
  353. mov edi, ReturnBuffer
  354. mov eax, SourceLocation ; cmos or extended cmos?
  355. cmp eax, 1
  356. je ECmosWriteByte
  357. cmp eax, 0
  358. jne HalpSetCmosDataExit
  359. CmosWriteByte:
  360. cmp edx, 0ffH ; validate cmos source address
  361. ja HalpSetCmosDataExit ; if out of range, exit
  362. mov al, dl
  363. out CmosAddressPort, al
  364. mov al, [edi]
  365. out CmosDataPort, al
  366. inc edx
  367. inc edi
  368. dec ecx
  369. jnz CmosWriteByte
  370. jmp SHORT HalpSetCmosDataExit
  371. ECmosWriteByte:
  372. cmp edx,0ffffH ; validate ecmos source address
  373. ja HalpSetCmosDataExit ; if out of range, exit
  374. mov al, dl
  375. out ECmosAddressLsbPort, al
  376. mov al, dh
  377. out ECmosAddressMsbPort, al
  378. mov al, [edi]
  379. out ECmosDataPort, al
  380. inc edx
  381. inc edi
  382. dec ecx
  383. jnz ECmosWriteByte
  384. HalpSetCmosDataExit:
  385. stdCall _HalpReleaseCmosSpinLock
  386. mov eax, edx ; return bytes written
  387. sub eax, SourceAddress ; subtract the initial offset
  388. pop edi
  389. pop ebx
  390. pop ebp
  391. stdRET _HalpSetCmosData
  392. stdENDP _HalpSetCmosData
  393. page ,132
  394. subttl "Read System Time"
  395. ;++
  396. ;
  397. ; VOID
  398. ; HalpReadCmosTime (
  399. ; PTIME_FIELDS TimeFields
  400. ; )
  401. ;
  402. ; Routine Description:
  403. ;
  404. ; This routine reads current time from CMOS memory and stores it
  405. ; in the TIME_FIELDS structure passed in by caller.
  406. ;
  407. ; Arguments:
  408. ;
  409. ; TimeFields - A pointer to the TIME_FIELDS structure.
  410. ;
  411. ; Return Value:
  412. ;
  413. ; None.
  414. ;
  415. ;--
  416. ;
  417. ; Parameters:
  418. ;
  419. KrctPTimeFields equ [esp+4]
  420. cPublicProc _HalpReadCmosTime ,1
  421. if DBG
  422. krctwait0:
  423. mov ecx, 100
  424. krctwait:
  425. push ecx
  426. else
  427. krctwait:
  428. endif
  429. stdCall _HalpAcquireCmosSpinLock
  430. mov ecx, 100
  431. align 4
  432. krct00: mov al, 0Ah ; Specify register A
  433. CMOS_READ ; (al) = CMOS register A
  434. test al, CMOS_STATUS_BUSY ; Is time update in progress?
  435. jz short krct10 ; if z, no, go read CMOS time
  436. loop short krct00 ; otherwise, try again.
  437. ;
  438. ; CMOS is still busy. Try again ...
  439. ;
  440. stdCall _HalpReleaseCmosSpinLock
  441. if DBG
  442. pop ecx
  443. loop short krctwait
  444. stdCall _DbgBreakPoint
  445. jmp short krctwait0
  446. else
  447. jmp short krctwait
  448. endif
  449. align 4
  450. if DBG
  451. krct10:
  452. pop ecx
  453. else
  454. krct10:
  455. endif
  456. mov edx, KrctPTimeFields ; (edx)-> TIME_FIELDS structure
  457. xor eax, eax ; (eax) = 0
  458. ;
  459. ; The RTC is only accurate within one second. So
  460. ; add a half a second so that we are closer, on average,
  461. ; to the right answer.
  462. ;
  463. mov word ptr [edx].TfMilliseconds, 500 ; add a half a second
  464. mov al, RTC_OFFSET_SECOND
  465. CMOS_READ ; (al) = second in BCD form
  466. BCD_TO_BIN ; (ax) = second
  467. mov [edx].TfSecond, ax ; set second in TIME_FIELDS
  468. mov al, RTC_OFFSET_MINUTE
  469. CMOS_READ ; (al) = minute in BCD form
  470. BCD_TO_BIN ; (ax) = Minute
  471. mov [edx].TfMinute, ax ; set minute in TIME_FIELDS
  472. mov al, RTC_OFFSET_HOUR
  473. CMOS_READ ; (al) = hour in BCD form
  474. BCD_TO_BIN ; (ax) = Hour
  475. mov [edx].TfHour, ax ; set hour in TIME_FIELDS
  476. mov al, RTC_OFFSET_DAY_OF_WEEK
  477. CMOS_READ ; (al) = day-of-week in BCD form
  478. BCD_TO_BIN ; (ax) = day-of-week
  479. mov [edx].TfWeekday, ax ; set Weekday in TIME_FIELDS
  480. mov al, RTC_OFFSET_DATE_OF_MONTH
  481. CMOS_READ ; (al) = date-of-month in BCD form
  482. BCD_TO_BIN ; (ax) = date_of_month
  483. mov [edx].TfDay, ax ; set day in TIME_FIELDS
  484. mov al, RTC_OFFSET_MONTH
  485. CMOS_READ ; (al) = month in BCD form
  486. BCD_TO_BIN ; (ax) = month
  487. mov [edx].TfMonth, ax ; set month in TIME_FIELDS
  488. mov al, RTC_OFFSET_YEAR
  489. CMOS_READ ; (al) = year in BCD form
  490. BCD_TO_BIN ; (ax) = year
  491. push eax ; save year in stack
  492. push edx ; preserve edx
  493. call _HalpGetCmosCenturyByte ; (al)= century byte in BCD form
  494. BCD_TO_BIN ; (ax) = century
  495. pop edx
  496. mov ah, 100
  497. mul ah ; (ax) = century * 100
  498. pop ecx ; (cx) = year
  499. add ax, cx ; (ax)= year
  500. cmp ax, 1900 ; Is year > 1900
  501. jb short krct40
  502. cmp ax, 1920 ; and < 1920
  503. jae short krct40
  504. add ax, 100 ; Compensate for century field
  505. krct40:
  506. mov [edx].TfYear, ax ; set year in TIME_FIELDS
  507. stdCall _HalpReleaseCmosSpinLock
  508. stdRET _HalpReadCmosTime
  509. stdENDP _HalpReadCmosTime
  510. page ,132
  511. subttl "Write System Time"
  512. ;++
  513. ;
  514. ; VOID
  515. ; HalpWriteCmosTime (
  516. ; PTIME_FIELDS TimeFields
  517. ; )
  518. ;
  519. ; Routine Description:
  520. ;
  521. ; This routine writes current time from TIME_FILEDS structure
  522. ; to CMOS memory.
  523. ;
  524. ; Arguments:
  525. ;
  526. ; TimeFields - A pointer to the TIME_FIELDS structure.
  527. ;
  528. ; Return Value:
  529. ;
  530. ; None.
  531. ;
  532. ;--
  533. ;
  534. ; Parameters:
  535. ;
  536. KrctPTimeFields equ [esp+4]
  537. cPublicProc _HalpWriteCmosTime ,1
  538. if DBG
  539. kwctwait0:
  540. mov ecx, 100
  541. kwctwait:
  542. push ecx
  543. else
  544. kwctwait:
  545. endif
  546. stdCall _HalpAcquireCmosSpinLock
  547. mov ecx, 100
  548. align 4
  549. kwct00: mov al, 0Ah ; Specify register A
  550. CMOS_READ ; (al) = CMOS register A
  551. test al, CMOS_STATUS_BUSY ; Is time update in progress?
  552. jz short kwct10 ; if z, no, go write CMOS time
  553. loop short kwct00 ; otherwise, try again.
  554. ;
  555. ; CMOS is still busy. Try again ...
  556. ;
  557. stdCall _HalpReleaseCmosSpinLock
  558. if DBG
  559. pop ecx
  560. loop short kwctwait
  561. stdCall _DbgBreakPoint
  562. jmp short kwctwait0
  563. else
  564. jmp short kwctwait
  565. endif
  566. align 4
  567. if DBG
  568. kwct10:
  569. pop ecx
  570. else
  571. kwct10:
  572. endif
  573. mov edx, KrctPTimeFields ; (edx)-> TIME_FIELDS structure
  574. mov al, [edx].TfSecond ; Read second in TIME_FIELDS
  575. BIN_TO_BCD
  576. mov ah, al
  577. mov al, RTC_OFFSET_SECOND
  578. CMOS_WRITE
  579. mov al, [edx].TfMinute ; Read minute in TIME_FIELDS
  580. BIN_TO_BCD
  581. mov ah, al
  582. mov al, RTC_OFFSET_MINUTE
  583. CMOS_WRITE
  584. mov al, [edx].TfHour ; Read Hour in TIME_FIELDS
  585. BIN_TO_BCD
  586. mov ah, al
  587. mov al, RTC_OFFSET_HOUR
  588. CMOS_WRITE
  589. mov al, [edx].TfWeekDay ; Read WeekDay in TIME_FIELDS
  590. BIN_TO_BCD
  591. mov ah, al
  592. mov al, RTC_OFFSET_DAY_OF_WEEK
  593. CMOS_WRITE
  594. mov al, [edx].TfDay ; Read day in TIME_FIELDS
  595. BIN_TO_BCD
  596. mov ah, al
  597. mov al, RTC_OFFSET_DATE_OF_MONTH
  598. CMOS_WRITE
  599. mov al, [edx].TfMonth ; Read month in TIME_FIELDS
  600. BIN_TO_BCD
  601. mov ah, al
  602. mov al, RTC_OFFSET_MONTH
  603. CMOS_WRITE
  604. mov ax, [edx].TfYear ; Read Year in TIME_FIELDS
  605. cmp ax, 9999
  606. jbe short kwct15
  607. mov ax, 9999
  608. align 4
  609. kwct15:
  610. mov cl, 100
  611. div cl ; [ax]/[cl]->al=quo, ah=rem
  612. push eax
  613. BIN_TO_BCD
  614. push eax
  615. call _HalpSetCmosCenturyByte
  616. pop eax
  617. mov al, ah ; [al] = Year
  618. BIN_TO_BCD
  619. mov ah, al ; [ah] = year in BCD
  620. mov al, RTC_OFFSET_YEAR
  621. CMOS_WRITE
  622. stdCall _HalpReleaseCmosSpinLock
  623. stdRET _HalpWriteCmosTime
  624. stdENDP _HalpWriteCmosTime
  625. ;++
  626. ;
  627. ; Routine Description:
  628. ;
  629. ; Acquires a spinlock to access the cmos chip. The cmos chip is
  630. ; accessed at different irql levels, so to be safe, we 'cli'.
  631. ; We could replace that to raise irql to PROFILE_LEVEL, but that's
  632. ; a lot of code.
  633. ;
  634. ; Arguments:
  635. ;
  636. ; None
  637. ;
  638. ; Return Value:
  639. ;
  640. ; Interrupt is disabled.
  641. ; Irql level not affected.
  642. ; Flags saved in _HalpHardwareLockFlags.
  643. ;--
  644. cPublicProc _HalpAcquireCmosSpinLock ,0
  645. public _HalpAcquireSystemHardwareSpinLock@0
  646. _HalpAcquireSystemHardwareSpinLock@0:
  647. push eax
  648. Arsl10: pushfd
  649. cli
  650. lea eax, _HalpSystemHardwareLock
  651. ACQUIRE_SPINLOCK eax, Arsl20
  652. pop _HalpHardwareLockFlags ; save flags for release S.L.
  653. pop eax
  654. stdRET _HalpAcquireCmosSpinLock
  655. Arsl20: popfd
  656. Arsl30:
  657. YIELD
  658. ifndef NT_UP
  659. cmp _HalpRebootNow, 0
  660. jnz short Arsl50
  661. endif
  662. TEST_SPINLOCK eax, <short Arsl30>
  663. jmp short ARsl10
  664. Arsl50:
  665. ifndef NT_UP
  666. mov eax, _HalpRebootNow
  667. call eax
  668. int 3 ; should not return
  669. endif
  670. stdENDP _HalpAcquireCmosSpinLock
  671. ;++
  672. ;
  673. ; Routine Description:
  674. ;
  675. ; Release spinlock, and restore flags to the state it was before
  676. ; acquiring the spinlock.
  677. ;
  678. ; Arguments:
  679. ;
  680. ; None
  681. ;
  682. ; Return Value:
  683. ;
  684. ; Interrupts restored to their state before acquiring spinlock.
  685. ; Irql level not affected.
  686. ;
  687. ;--
  688. cPublicProc _HalpReleaseCmosSpinLock ,0
  689. public _HalpReleaseSystemHardwareSpinLock@0
  690. _HalpReleaseSystemHardwareSpinLock@0:
  691. push eax
  692. ;
  693. ; restore eflags as it was before acquiring spinlock. Put it on
  694. ; stack before releasing spinlock (so other cpus cannot overwrite
  695. ; it with their own eflags).
  696. ;
  697. push _HalpHardwareLockFlags ; old eflags on stack.
  698. lea eax, _HalpSystemHardwareLock
  699. RELEASE_SPINLOCK eax
  700. popfd ; restore eflags.
  701. pop eax
  702. stdRET _HalpReleaseCmosSpinLock
  703. stdENDP _HalpReleaseCmosSpinLock
  704. ;++
  705. ;
  706. ; UCHAR
  707. ; HalpGetCmosCenturyByte (
  708. ; VOID
  709. ; )
  710. ;
  711. ; Routine Description:
  712. ;
  713. ; This routine gets Century byte from CMOS.
  714. ;
  715. ; Arguments:
  716. ;
  717. ; None
  718. ;
  719. ; Return Value:
  720. ;
  721. ; (al) = Century byte in BCD form.
  722. ;
  723. ;--
  724. cPublicProc _HalpGetCmosCenturyByte, 0
  725. mov eax, _HalpCmosCenturyOffset
  726. if DBG
  727. ;
  728. ; Make sure the HalpCmosCenturyOffset is initialized
  729. ;
  730. cmp eax, 0
  731. jne short @f
  732. int 3
  733. @@:
  734. endif
  735. test eax, BANK1
  736. jnz short rcb50
  737. CMOS_READ ; (al) = century in BCD form
  738. stdRET _HalpGetCmosCenturyByte
  739. rcb50: mov edx, eax
  740. mov al, 0Ah
  741. CMOS_READ
  742. mov dh, al ; save it for restore
  743. or al, 10h ; Set DV0 = 1
  744. mov ah, al
  745. mov al, 0Ah ; Write register A
  746. CMOS_WRITE
  747. mov al, dl ; century offset
  748. CMOS_READ
  749. mov dl, al ; save it
  750. mov ah, dh ; Restore DV0
  751. mov al, 0Ah ; Write register A
  752. CMOS_WRITE
  753. mov al, dl
  754. stdRET _HalpGetCmosCenturyByte
  755. stdENDP _HalpGetCmosCenturyByte
  756. ;++
  757. ;
  758. ; VOID
  759. ; HalpSetCmosCenturyByte (
  760. ; UCHAR Century
  761. ; )
  762. ;
  763. ; Routine Description:
  764. ;
  765. ; This routine sets Century byte in CMOS.
  766. ;
  767. ; Arguments:
  768. ;
  769. ; Century - Supplies the value for CMOS century byte
  770. ;
  771. ; Return Value:
  772. ;
  773. ; None.
  774. ;
  775. ;--
  776. cPublicProc _HalpSetCmosCenturyByte, 1
  777. mov eax, _HalpCmosCenturyOffset
  778. if DBG
  779. ;
  780. ; Make sure the HalpCmosCenturyOffset is initialized
  781. ;
  782. cmp eax, 0
  783. jne short @f
  784. int 3
  785. @@:
  786. endif
  787. test eax, BANK1
  788. jnz short scb50
  789. mov ah, [esp+4] ; (ah) = Century in BCD form
  790. CMOS_WRITE
  791. stdRET _HalpSetCmosCenturyByte
  792. scb50: mov edx, eax
  793. mov al, 0Ah
  794. CMOS_READ
  795. mov dh, al ; save it for restore
  796. or al, 10h ; Set DV0 = 1
  797. mov ah, al
  798. mov al, 0Ah ; Write register A
  799. CMOS_WRITE
  800. mov ah, [esp+4] ; (ah) = Century in BCD form
  801. mov al, dl ; century offset
  802. CMOS_WRITE
  803. mov ah, dh ; Restore DV0
  804. mov al, 0Ah ; Write register A
  805. CMOS_WRITE
  806. stdRET _HalpSetCmosCenturyByte
  807. stdENDP _HalpSetCmosCenturyByte
  808. ;++
  809. ;
  810. ; VOID
  811. ; HalpCpuID (
  812. ; ULONG InEax,
  813. ; PULONG OutEax,
  814. ; PULONG OutEbx,
  815. ; PULONG OutEcx,
  816. ; PULONG OutEdx
  817. ; );
  818. ;
  819. ; Routine Description:
  820. ;
  821. ; Executes the CPUID instruction and returns the registers from it
  822. ;
  823. ; Only available at INIT time
  824. ;
  825. ; Arguments:
  826. ;
  827. ; Return Value:
  828. ;
  829. ;--
  830. cPublicProc _HalpCpuID,5
  831. push ebx
  832. push esi
  833. mov eax, [esp+12]
  834. db 0fh, 0a2h ; CPUID
  835. mov esi, [esp+16] ; return EAX
  836. mov [esi], eax
  837. mov esi, [esp+20] ; return EBX
  838. mov [esi], ebx
  839. mov esi, [esp+24] ; return ECX
  840. mov [esi], ecx
  841. mov esi, [esp+28] ; return EDX
  842. mov [esi], edx
  843. pop esi
  844. pop ebx
  845. stdRET _HalpCpuID
  846. stdENDP _HalpCpuID
  847. ;++
  848. ;
  849. ; VOID
  850. ; HalpFlushTLB (
  851. ; VOID
  852. ; );
  853. ;
  854. ; Routine Description:
  855. ;
  856. ; Flush the current TLB.
  857. ;
  858. ; Arguments:
  859. ;
  860. ; Return Value:
  861. ;
  862. ;--
  863. cPublicProc _HalpFlushTLB, 0
  864. .586p
  865. pushfd
  866. push ebx
  867. push esi
  868. cli
  869. mov esi, cr3
  870. mov ecx, PCR[PcPrcb]
  871. cmp byte ptr [ecx].PbCpuID, 0
  872. jz short ftb50
  873. mov eax, 1 ; Get feature bits
  874. cpuid ; (note "cpuid" between CR3 reload fixes
  875. ; P6 B step errata #11)
  876. test edx, 2000h ; see if 'G' bit is supported
  877. jz short ftb50
  878. mov ecx, cr4 ; 'G' bit is supported, due global flush
  879. mov edx, ecx ; Save orginal cr4
  880. and ecx, not CR4_PGE ; Make sure global bit is disabled
  881. mov cr4, ecx
  882. mov cr3, esi ; flush TLB
  883. mov cr4, edx ; restore cr4
  884. jmp short ftp99
  885. ftb50: mov cr3, esi
  886. ftp99: pop esi
  887. pop ebx
  888. popfd
  889. stdRET _HalpFlushTLB
  890. .486p
  891. stdENDP _HalpFlushTLB
  892. ;++
  893. ;
  894. ; VOID
  895. ; HalpYieldProcessor (
  896. ; VOID
  897. ; );
  898. ;
  899. ; Routine Description:
  900. ;
  901. ; Arguments:
  902. ;
  903. ; None
  904. ;
  905. ; Return Value:
  906. ;
  907. ; None
  908. ;
  909. ;--
  910. cPublicProc _HalpYieldProcessor
  911. YIELD
  912. stdRET _HalpYieldProcessor
  913. stdENDP _HalpYieldProcessor
  914. _TEXT ends
  915. end