Windows NT 4.0 source code leak
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.

971 lines
20 KiB

4 years ago
  1. #if defined (JENSEN)
  2. /*++
  3. Copyright (c) 1992 Digital Equipment Corporation
  4. Module Name:
  5. jxioacc.c
  6. Abstract:
  7. This module contains the Jensen I/O space access routines for user mode
  8. mapped addresses.
  9. The READ_PORT_Uxxx MACROs simply call the equivalent READ_REGISTER_Uxxx
  10. routine. Similarly, the WRITE_PORT_Uxxx MACROs call the equivalent
  11. WRITE_REGISTER_Uxxx routines. Since Jensen uses 64 bit super pages for
  12. Virtual I/O, and that super pages are only accessable through kernel
  13. mode, these routines here will decode a QVA and do the access, but
  14. through normal translations.
  15. All these routines ensure that the calling argument is a QVA, such
  16. as would be returned by the wrapper around MmMapIoSpace - this should
  17. have QVA_ENABLE set. They determine which type of shift should be
  18. used, based on the next bit in the longword.
  19. Note that the argument is declared as PUCHAR or PUSHORT or
  20. whatever, even though it really is a QUASI_VIRTUAL_ADDRESS. This
  21. is for driver compatibility: all the drivers out there get a
  22. PVOID from MmMapIoSpace, then cast it to PU* before calling these
  23. routines. If we insisted on declaring them correctly, we would
  24. have to change all the drivers, which is what we are trying to avoid.
  25. Lane shifting: the Jensen box will not do lane shifting in EISA
  26. space. That means that for access shorter than a longword, the
  27. data will NOT show up in the lowest bit position, but will be in
  28. the byte/word that it would have started in. For longwords, the
  29. value will show up on the data path correctly. For, say, the 3rd
  30. byte in a word, a longword would be returned, and bytes 0, 1 and 3
  31. would be garbage, and the value in byte 2 would be the one you
  32. wanted. The same applies for writing: a longword will always be
  33. sent out onto the bus, and we must move the valid data byte into
  34. the correct position, and set the byte enables to say which byte
  35. to use. Note that what you cannot do is leave the byte in the
  36. lowest position, and set the byte enable to the lowest byte,
  37. because this would generate an unaligned longword access, which
  38. the chip cannot handle.
  39. So, for bytes, the access must be an aligned longword, with byte
  40. enables set to indicate which byte to get/set, and the byte moved
  41. to/from the desired position within the longword. Similarly for
  42. shorts. Tribytes are not supported.
  43. Lane shifting is not an issue for accessing the Combo chip, which
  44. only allows byte accesses, and for which the data is always moved
  45. to the low 8 bits of the HBUS data longword, according to the spec.
  46. Performance: If the buffer routines get used alot, something we
  47. could do to improve performance would be to send four byte or two
  48. shorts out to the bus at a time (or get them). This would work
  49. because the PIC queries the device about the size of transfer that
  50. it can accept (or the device rejects a transfer that it cannot
  51. handle) and parcels the data out in correct size chunks.
  52. Author:
  53. Rod N. Gamache (DEC) 5-May-1992
  54. Miche Baker-Harvey (miche) 21-May-1992
  55. Jeff McLeman (DEC) 30-Jul-1992
  56. Revision History:
  57. --*/
  58. // Include files
  59. #include "halp.h"
  60. #include "jnsndef.h"
  61. UCHAR
  62. READ_REGISTER_UCHAR(
  63. volatile PUCHAR Register
  64. )
  65. /*++
  66. Routine Description:
  67. Read from the specified register address.
  68. Arguments:
  69. Register - Supplies a pointer to the register in EISA I/O space.
  70. Return Value:
  71. Returns the value read from the specified register address.
  72. --*/
  73. {
  74. ULONG mv; // Local value
  75. ULONG byte; // which byte we want
  76. volatile PULONG ma; // Local address
  77. HalpMb;
  78. //
  79. // If it's an EISA address, use EISA shifts, byte enables
  80. //
  81. if (IS_EISA_QVA(Register)) {
  82. //
  83. // Determine which byte it is that we want.
  84. //
  85. byte = (ULONG)Register & 0x3;
  86. //
  87. // Shift the virtual address into position, and indicate that
  88. // we want a byte.
  89. //
  90. // The desired byte enable is set automatically because the
  91. // Jensen designers picked values which correspond exactly
  92. // to the actual byte addresses
  93. //
  94. ma = (volatile PULONG)
  95. (EISA_BYTE_LEN | ((ULONG)Register << EISA_BIT_SHIFT));
  96. //
  97. // Get the longword value, which will only have one valid byte
  98. //
  99. mv = *ma;
  100. //
  101. // Extract out and return the desired byte
  102. // The compiler should convert the multiplication
  103. //
  104. return((UCHAR)(mv >> (byte * 8)));
  105. }
  106. //
  107. // If it's a Combo Chip address, use those shifts, byte enables
  108. //
  109. if (IS_COMBO_QVA(Register)) {
  110. return ((UCHAR)(*(volatile PULONG )(COMBO_BYTE_LEN |
  111. ((ULONG)Register << COMBO_BIT_SHIFT))));
  112. }
  113. //
  114. // It's not a valid QVA
  115. //
  116. KeBugCheck("Invalid QVA in READ_REGISTER_UCHAR\n");
  117. }
  118. USHORT
  119. READ_REGISTER_USHORT(
  120. volatile PUSHORT Register
  121. )
  122. /*++
  123. Routine Description:
  124. Read from the specified Register address.
  125. Arguments:
  126. Register - Supplies a pointer to the register in EISA I/O space.
  127. Return Value:
  128. Returns the value read from the specified register address.
  129. --*/
  130. {
  131. ULONG mv, word; // Local value and word we want
  132. volatile PULONG ma; // Local address
  133. //
  134. // This works as long as we don't want the fourth short!
  135. //
  136. ASSERT(((ULONG)Register & 0x3) != 0x3);
  137. //
  138. // If it's an EISA address, use EISA shifts, word enables
  139. //
  140. if (IS_EISA_QVA(Register)) {
  141. //
  142. // Determine which word it is that we want.
  143. //
  144. word = (ULONG)Register & 0x3;
  145. //
  146. // Shift the virtual address into position, and indicate that
  147. // we want a word.
  148. //
  149. // The desired word enable is set automatically because the
  150. // Jensen designers picked values which correspond exactly
  151. // to the actual word addresses
  152. //
  153. ma = (volatile PULONG)
  154. (EISA_WORD_LEN | ((ULONG)Register << EISA_BIT_SHIFT));
  155. //
  156. // Get the longword value, which will only have one valid word
  157. //
  158. mv = *ma;
  159. //
  160. // Extract out and return the desired word
  161. // The compiler should convert the multiplication
  162. //
  163. return((USHORT)(mv >> (8 * word)));
  164. }
  165. //
  166. // USHORT operations are not supported on the combo chip
  167. //
  168. if (IS_COMBO_QVA(Register)) {
  169. KeBugCheck("Invalid Combo QVA in READ_REGISTER_USHORT\n");
  170. }
  171. KeBugCheck("Invalid QVA in READ_REGISTER_USHORT\n");
  172. }
  173. ULONG
  174. READ_REGISTER_ULONG(
  175. volatile PULONG Register
  176. )
  177. /*++
  178. Routine Description:
  179. Read from the specified register address.
  180. Arguments:
  181. Register - Supplies a pointer to the register in EISA I/O space.
  182. Return Value:
  183. Returns the value read from the specified register address.
  184. --*/
  185. {
  186. //
  187. // We are assuming that the longword is aligned
  188. //
  189. ASSERT(((ULONG)Register & 0x3) == 0x0);
  190. if (IS_EISA_QVA(Register)) {
  191. HalpMb;
  192. return (*(volatile PULONG)(EISA_LONG_LEN |
  193. ((ULONG)Register << EISA_BIT_SHIFT)));
  194. }
  195. //
  196. // ULONG operations are not supported on the combo chip
  197. //
  198. if (IS_COMBO_QVA(Register)) {
  199. KeBugCheck("Invalid Combo QVA in READ_REGISTER_ULONG\n");
  200. }
  201. KeBugCheck("Invalid QVA in READ_REGISTER_ULONG\n");
  202. }
  203. VOID
  204. WRITE_REGISTER_UCHAR(
  205. volatile PUCHAR Register,
  206. UCHAR Value
  207. )
  208. /*++
  209. Routine Description:
  210. Write to the specified register address.
  211. Arguments:
  212. Register - Supplies a pointer to the register in EISA I/O space.
  213. Value - The value to be written to the register.
  214. Return Value:
  215. None
  216. --*/
  217. {
  218. ULONG mv; // local copy of value for shifting
  219. ULONG byte; // the byte position requested
  220. //
  221. // If it's an EISA address, use EISA shifts, byte enables
  222. //
  223. if (IS_EISA_QVA(Register)) {
  224. //
  225. // Determine which byte it is that we want.
  226. //
  227. byte = (ULONG)Register & 0x3;
  228. //
  229. // Move value into appropriate byte position in longword
  230. // The compiler should convert the multiplication
  231. //
  232. mv = (ULONG)(Value << (8 * byte));
  233. //
  234. // The address is long aligned and the byte enables set
  235. // automagically by the way the Jensen physical map is set
  236. //
  237. *(volatile PULONG)(EISA_BYTE_LEN |
  238. ((ULONG)Register << EISA_BIT_SHIFT)) = mv;
  239. HalpMb;
  240. return;
  241. }
  242. //
  243. // If it's a Combo Chip address, use those shifts, byte enables
  244. // No lane shifting is required for the Combo chip.
  245. //
  246. if (IS_COMBO_QVA(Register)) {
  247. *(volatile PULONG)(COMBO_BYTE_LEN |
  248. ((ULONG)Register << COMBO_BIT_SHIFT)) = Value;
  249. HalpMb;
  250. return;
  251. }
  252. //
  253. // It's not a valid QVA
  254. //
  255. KeBugCheck("Invalid QVA in WRITE_REGISTER_UCHAR\n");
  256. }
  257. VOID
  258. WRITE_REGISTER_USHORT(
  259. volatile PUSHORT Register,
  260. USHORT Value
  261. )
  262. /*++
  263. Routine Description:
  264. Write to the specified register address.
  265. Arguments:
  266. Register - Supplies a pointer to the register in EISA I/O space.
  267. Value - The value to be written to the register.
  268. Return Value:
  269. None
  270. --*/
  271. {
  272. ULONG mv; // local copy of value for shifting
  273. UCHAR word; // the word position requested
  274. //
  275. // This works as long as we don't want the fourth short!
  276. //
  277. ASSERT(((ULONG)Register & 0x3) != 0x3);
  278. //
  279. // If it's an EISA address, use EISA shifts, word enables
  280. //
  281. if (IS_EISA_QVA(Register)) {
  282. //
  283. // Determine which word it is that we want.
  284. //
  285. word = (ULONG)Register & 0x3;
  286. //
  287. // Move value into appropriate word position in longword
  288. // The compiler should convert the multiplication
  289. //
  290. mv = (ULONG)(Value << (8 * word));
  291. //
  292. // The address is long aligned and the word enables set
  293. // automagically by the way the Jensen physical map is set
  294. //
  295. *(volatile PULONG)(EISA_WORD_LEN |
  296. ((ULONG)Register << EISA_BIT_SHIFT)) = mv;
  297. HalpMb;
  298. return;
  299. }
  300. //
  301. // USHORT operations are not supported on the combo chip
  302. //
  303. if (IS_COMBO_QVA(Register)) {
  304. KeBugCheck("Invalid Combo QVA in WRITE_REGISTER_USHORT\n");
  305. }
  306. KeBugCheck("Invalid QVA in WRITE_REGISTER_USHORT\n");
  307. }
  308. VOID
  309. WRITE_REGISTER_ULONG(
  310. volatile PULONG Register,
  311. ULONG Value
  312. )
  313. /*++
  314. Routine Description:
  315. Write to the specified register address.
  316. Arguments:
  317. Register - Supplies a pointer to the register in EISA I/O space.
  318. Value - The value to be written to the register.
  319. Return Value:
  320. None
  321. --*/
  322. {
  323. //
  324. // We are assuming that the longword is aligned
  325. //
  326. ASSERT(((ULONG)Register & 0x3) == 0x0);
  327. if (IS_EISA_QVA(Register)) {
  328. *(volatile PULONG)(EISA_LONG_LEN |
  329. ((ULONG)Register << EISA_BIT_SHIFT)) = Value;
  330. HalpMb;
  331. return;
  332. }
  333. //
  334. // ULONG operations are not supported on the combo chip
  335. //
  336. if (IS_COMBO_QVA(Register)) {
  337. KeBugCheck("Invalid Combo QVA in WRITE_REGISTER_ULONG\n");
  338. }
  339. KeBugCheck("Invalid QVA in WRITE_REGISTER_ULONG\n");
  340. }
  341. VOID
  342. READ_PORT_BUFFER_UCHAR(
  343. volatile PUCHAR Port,
  344. PUCHAR Buffer,
  345. ULONG Count
  346. )
  347. /*++
  348. Routine Description:
  349. Read from the specified port buffer address.
  350. Arguments:
  351. Port - Supplies a pointer to the port in EISA space.
  352. Buffer - the address of the buffer in memory to copy the data to.
  353. Count - the number of bytes to move.
  354. Return Value:
  355. None
  356. --*/
  357. {
  358. ULONG i, mv;
  359. volatile PULONG ma;
  360. ULONG byte;
  361. HalpMb;
  362. if (IS_EISA_QVA(Port)) {
  363. //
  364. // Shift the virtual address into position, and indicate that
  365. // we want a byte.
  366. //
  367. // The desired byte enable is set automatically because the
  368. // Jensen designers picked values which correspond exactly
  369. // to the actual byte addresses
  370. //
  371. ma = (volatile PULONG)
  372. (EISA_BYTE_LEN | ((ULONG)Port << EISA_BIT_SHIFT));
  373. for ( i = 0 ; i < Count ; i++) {
  374. //
  375. // Determine which byte it is that we want.
  376. //
  377. byte = (ULONG)ma & (0x3 << EISA_BIT_SHIFT);
  378. //
  379. // Get the longword value, which will only have one valid byte
  380. //
  381. mv = *ma;
  382. //
  383. // Extract out the desired byte
  384. // The compiler should convert the multiplication
  385. //
  386. *Buffer++ = ((UCHAR)(mv >> (8 * byte)));
  387. }
  388. } else if (IS_COMBO_QVA(Port)) {
  389. ma = (volatile PULONG) (COMBO_BYTE_LEN |
  390. ((ULONG)Port << COMBO_BIT_SHIFT));
  391. for ( i = 0 ; i < Count ; i++) {
  392. *Buffer++ = *ma;
  393. ma = (PULONG)((PUCHAR)ma + COMBO_BYTE_OFFSET);
  394. }
  395. } else {
  396. //
  397. // Invalid QVA
  398. //
  399. KeBugCheck("Invalid QVA in READ_PORT_BUFFER_UCHAR\n");
  400. }
  401. }
  402. VOID
  403. READ_PORT_BUFFER_USHORT(
  404. volatile PUSHORT Port,
  405. PUSHORT Buffer,
  406. ULONG Count
  407. )
  408. /*++
  409. Routine Description:
  410. Read from the specified port buffer address.
  411. Arguments:
  412. Port - Supplies a pointer to the port in EISA space.
  413. Buffer - the address of the buffer in memory to copy the data to.
  414. Count - the number of shorts to move.
  415. Return Value:
  416. None
  417. --*/
  418. {
  419. ULONG i, mv;
  420. volatile PULONG ma;
  421. ULONG word;
  422. //
  423. // The code gets really ugly if shorts are not aligned!
  424. //
  425. ASSERT(((ULONG)Port & 0x1) == 0x0);
  426. if (IS_EISA_QVA(Port)) {
  427. HalpMb;
  428. //
  429. // Shift the virtual address into position, and indicate that
  430. // we want a word.
  431. //
  432. // The desired word enable is set automatically because the
  433. // Jensen designers picked values which correspond exactly
  434. // to the actual word addresses
  435. //
  436. ma = (volatile PULONG)
  437. (EISA_WORD_LEN | ((ULONG)Port << EISA_BIT_SHIFT));
  438. for ( i = 0 ; i < Count ; i++) {
  439. //
  440. // Determine which word it is that we want; the low
  441. // order bit cannot be set.
  442. //
  443. word = (ULONG)ma & (0x2 << EISA_BIT_SHIFT);
  444. //
  445. // Get the longword value, which will only have one valid word
  446. //
  447. mv = *ma;
  448. //
  449. // Extract out the desired word
  450. // The compiler should convert the multiplication
  451. //
  452. *Buffer++ = ((USHORT)(mv >> (8 * word)));
  453. }
  454. return;
  455. }
  456. //
  457. // USHORT operations are not supported on the combo chip
  458. //
  459. if (IS_COMBO_QVA(Port)) {
  460. KeBugCheck("Invalid Combo QVA in READ_PORT_BUFFER_USHORT\n");
  461. }
  462. KeBugCheck("Invalid QVA in READ_PORT_BUFFER_USHORT\n");
  463. }
  464. VOID
  465. READ_PORT_BUFFER_ULONG(
  466. volatile PULONG Port,
  467. PULONG Buffer,
  468. ULONG Count
  469. )
  470. /*++
  471. Routine Description:
  472. Read from the specified port address.
  473. Arguments:
  474. Port - Supplies a pointer to the port in EISA space.
  475. Buffer - the address of the buffer in memory to copy the data to.
  476. Count - the number of longs to move.
  477. Return Value:
  478. None
  479. --*/
  480. {
  481. ULONG i;
  482. volatile PULONG ptr;
  483. //
  484. // We are assuming that the longword is aligned
  485. //
  486. ASSERT(((ULONG)Port & 0x3) == 0x0);
  487. if (IS_EISA_QVA(Port)) {
  488. HalpMb;
  489. ptr = (volatile ULONG *) (EISA_LONG_LEN |
  490. ((ULONG)Port << EISA_BIT_SHIFT));
  491. for ( i = 0 ; i < Count ; i++) {
  492. *Buffer++ = *ptr;
  493. }
  494. return;
  495. }
  496. //
  497. // ULONG operations are not supported on the combo chip
  498. //
  499. if (IS_COMBO_QVA(Port)) {
  500. KeBugCheck("Invalid Combo QVA in READ_PORT_BUFFER_ULONG\n");
  501. }
  502. KeBugCheck("Invalid QVA in READ_PORT_BUFFER_ULONG\n");
  503. }
  504. VOID
  505. WRITE_PORT_BUFFER_UCHAR(
  506. volatile PUCHAR Port,
  507. PUCHAR Buffer,
  508. ULONG Count
  509. )
  510. /*++
  511. Routine Description:
  512. Write to the specified port buffer address.
  513. If the Port and Buffer addresses are aligned with respect to each
  514. other, we don't have to do a shift on each move - which would be a
  515. bit faster. On the other hand, no one calls this routine, and it
  516. would be more complicated to handle the two cases, so let it be.
  517. Arguments:
  518. Port - Supplies a pointer to the port in EISA space.
  519. Buffer - the address of the buffer in memory to copy the data from.
  520. Count - the number of bytes to move.
  521. Return Value:
  522. None
  523. --*/
  524. {
  525. ULONG i, mv;
  526. volatile PULONG ma;
  527. ULONG byte;
  528. if (IS_EISA_QVA(Port)) {
  529. ma = (volatile PULONG) (EISA_BYTE_LEN |
  530. ((ULONG)Port << EISA_BIT_SHIFT));
  531. for ( i = 0 ; i < Count ; i++) {
  532. //
  533. // Determine which byte it is that we want to write to
  534. // This changes with every byte written.
  535. //
  536. byte = (ULONG)ma & (0x3 << EISA_BIT_SHIFT);
  537. //
  538. // Move value into appropriate byte position in longword,
  539. // and advance our position in the buffer.
  540. // The compiler should convert the multiplication
  541. //
  542. mv = (ULONG)(*Buffer << (8 * byte));
  543. Buffer++;
  544. //
  545. // send the lane shifted value to the EISA bus
  546. //
  547. *ma = mv;
  548. }
  549. HalpMb;
  550. return;
  551. }
  552. if (IS_COMBO_QVA(Port)) {
  553. ma = (volatile PULONG) (COMBO_BYTE_LEN |
  554. ((ULONG)Port << COMBO_BIT_SHIFT));
  555. for ( i = 0 ; i < Count ; i++) {
  556. *ma = *Buffer++;
  557. ma = (PULONG)((PUCHAR)ma + COMBO_BYTE_OFFSET);
  558. }
  559. HalpMb;
  560. return;
  561. }
  562. //
  563. // Invalid QVA
  564. //
  565. KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_UCHAR\n");
  566. }
  567. VOID
  568. WRITE_PORT_BUFFER_USHORT(
  569. volatile PUSHORT Port,
  570. PUSHORT Buffer,
  571. ULONG Count
  572. )
  573. /*++
  574. Routine Description:
  575. Write to the specified port buffer address.
  576. Arguments:
  577. Port - Supplies a pointer to the port in EISA space.
  578. Buffer - the address of the buffer in memory to copy the data from.
  579. Count - the number of shorts to move.
  580. Return Value:
  581. None
  582. --*/
  583. {
  584. ULONG i, mv;
  585. volatile PULONG ma;
  586. ULONG word;
  587. //
  588. // The code gets really ugly if shorts are not aligned!
  589. //
  590. ASSERT(((ULONG)Port & 0x1) == 0x0);
  591. if (IS_EISA_QVA(Port)) {
  592. ma = (volatile PULONG) (EISA_WORD_LEN |
  593. ((ULONG)Port << EISA_BIT_SHIFT));
  594. for ( i = 0 ; i < Count ; i++) {
  595. //
  596. // Determine which word it is that we want to write to
  597. // This changes with every word written.
  598. //
  599. word = (ULONG)ma & (0x2 << EISA_BIT_SHIFT);
  600. //
  601. // Move value into appropriate word position in longword,
  602. // and advance our position in the buffer.
  603. // The compiler should convert the multiplication
  604. //
  605. mv = (ULONG)(*Buffer++ << (8 * word));
  606. //
  607. // send the lane shifted value to the EISA bus
  608. //
  609. *ma = mv;
  610. }
  611. HalpMb;
  612. return;
  613. }
  614. //
  615. // USHORT operations are not supported on the combo chip
  616. //
  617. if (IS_COMBO_QVA(Port)) {
  618. KeBugCheck("Invalid Combo QVA in WRITE_PORT_BUFFER_USHORT\n");
  619. }
  620. KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_USHORT\n");
  621. }
  622. VOID
  623. WRITE_PORT_BUFFER_ULONG(
  624. volatile PULONG Port,
  625. PULONG Buffer,
  626. ULONG Count
  627. )
  628. /*++
  629. Routine Description:
  630. Write to teh specified port buffer address.
  631. Arguments:
  632. Port - Supplies a pointer to the port in EISA space.
  633. Buffer - the address of the buffer in memory to copy the data from.
  634. Count - the number of longs to move.
  635. Return Value:
  636. None
  637. --*/
  638. {
  639. ULONG i;
  640. volatile PULONG ptr;
  641. //
  642. // We are assuming that the port address is long aligned
  643. //
  644. ASSERT(((ULONG)Port & 0x3) == 0x0);
  645. if (IS_EISA_QVA(Port)) {
  646. ptr = (volatile ULONG *) (EISA_LONG_LEN |
  647. ((ULONG)Port << EISA_BIT_SHIFT));
  648. for ( i = 0 ; i < Count ; i++) {
  649. *ptr = *Buffer++;
  650. }
  651. HalpMb;
  652. return;
  653. }
  654. //
  655. // ULONG operations are not supported on the combo chip
  656. //
  657. if (IS_COMBO_QVA(Port)) {
  658. KeBugCheck("Invalid Combo QVA in WRITE_PORT_BUFFER_ULONG\n");
  659. }
  660. KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_ULONG\n");
  661. }
  662. #endif // JENSEN