/private/ntos/fw/alpha/jensen/alpha/tbaqva.c

https://github.com/ZoloZiak/WinNT4 · C · 413 lines · 114 code · 93 blank · 206 comment · 23 complexity · 04ba4ef34ee1e1f841820da21fdbc1b4 MD5 · raw file

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1993 Digital Equipment Corporation
  4. Module Name:
  5. tbaqva.c
  6. Abstract:
  7. This module contains the platform dependent code to create bus addreses
  8. and QVAs.
  9. Author:
  10. Jeff McLeman (mcleman) 27-May-1992
  11. David Orbits 7-June-1992
  12. Environment:
  13. Kernel mode, local to I/O system
  14. Revision History:
  15. John DeRosa [DEC] 15-June-1993
  16. These differ from the HAL versions in that EISA memory addresses above
  17. 32MB are not mapped, and there is no tracking of multiple HAE values.
  18. --*/
  19. #include "fwp.h"
  20. #include "ntalpha.h"
  21. #include "jxfwhal.h"
  22. #include "jnsndma.h"
  23. #include "eisa.h"
  24. #include "jxisa.h"
  25. #define HAL_32MB 0x2000000
  26. QUASI_VIRTUAL_ADDRESS
  27. HalCreateQva(
  28. IN PHYSICAL_ADDRESS PA,
  29. IN PVOID VA
  30. );
  31. BOOLEAN
  32. HalTranslateBusAddress(
  33. IN INTERFACE_TYPE InterfaceType,
  34. IN ULONG BusNumber,
  35. IN PHYSICAL_ADDRESS BusAddress,
  36. IN OUT PULONG AddressSpace,
  37. OUT PPHYSICAL_ADDRESS TranslatedAddress
  38. )
  39. /*++
  40. Routine Description:
  41. This function returns the system physical address for a specified I/O bus
  42. address. The return value is suitable for use in a subsequent call to
  43. MmMapIoSpace.
  44. Arguments:
  45. InterfaceType - Supplies the type of bus which the address is for.
  46. BusNumber - Supplies the bus number for the device; not used in Jensen
  47. BusAddress - Supplies the bus relative address.
  48. AddressSpace - Supplies the address space number for the device: 0 for
  49. memory and 1 for I/O space. If the desired access mode is user mode,
  50. then bit 1 must be TRUE.
  51. TranslatedAddress - Supplies a pointer to return the translated address
  52. Notes:
  53. This is a variation of what began in the MIPS code. The intel code often
  54. assumes that if an address is in I/O space, the bottom 32 bits of the
  55. physical address can be used "like" a virtual address, and are returned
  56. to the user. This doesn't work on MIPs machines where physical
  57. addresses can be larger than 32 bits.
  58. Since we are using superpage addresses for I/O on Alpha, we can do
  59. almost what is done on intel. If AddressSpace is equal to 0 or 1, then
  60. we assume the user is doing kernel I/O and we call
  61. HalCreateQva to build a Quasi Virtual Address and return
  62. that to the caller. We then set AddressSpace to a 1, so that the caller
  63. will not call MmMapIoSpace. The Caller will use the low 32 bits of the
  64. physical address we return as the VA. (Which we built a QVA in).
  65. If the caller wants to access EISA I/O or Memory through user mode, then
  66. the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
  67. depending on whether EISA I/O or Memory), then the caller is returned the
  68. 34 bit Physical address. The caller will then call MmMapIoSpace, or
  69. ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
  70. of a VA mapped through the page tables.
  71. **** Note ****
  72. The QVA in user mode can only be accessed with the routines WRITE/READ_
  73. REGISTER_UCHAR/USHORT/ULONG, and they must be the ones in module
  74. JXIOUSER.C. The user CANNOT call the above routines in the HAL from
  75. usermode. (Which is pointless, since the HAL is superpage access
  76. only).
  77. Return Value:
  78. A return value of TRUE indicates that a system physical address
  79. corresponding to the supplied bus relative address and bus address
  80. number has been returned in TranslatedAddress.
  81. A return value of FALSE occurs if the translation for the address was
  82. not possible
  83. --*/
  84. {
  85. PVOID va = 0; // note, this is used for a placeholder
  86. //
  87. // If this is for the internal bus then the device is on the combo chip.
  88. // BusAddress.LowPart should contains the port of the device.
  89. //
  90. if (InterfaceType == Internal) {
  91. //
  92. // Return the passed parameters.
  93. //
  94. TranslatedAddress->HighPart = 1;
  95. TranslatedAddress->LowPart = 0xC0000000 + (BusAddress.LowPart << COMBO_BIT_SHIFT);
  96. //
  97. // Now call HalCreateQva. This will create a QVA
  98. // that we'll return to the caller. Then we will implicitly set
  99. // AddressSpace to a 1. The caller then will not call MmMapIoSpace
  100. // and will use the address we return as a VA.
  101. TranslatedAddress->LowPart = (ULONG) HalCreateQva(
  102. *TranslatedAddress, va);
  103. TranslatedAddress->HighPart = 0; // clear high longword for QVA
  104. *AddressSpace = 1; // Make sure user doesn't call
  105. // MmMapIoSpace.
  106. return(TRUE);
  107. }
  108. if (InterfaceType != Isa && InterfaceType != Eisa) {
  109. //
  110. // Not on this system return nothing.
  111. //
  112. *AddressSpace = 0;
  113. TranslatedAddress->LowPart = 0;
  114. return(FALSE);
  115. }
  116. //
  117. // Jensen only has one I/O bus which is an EISA, so the bus number is unused.
  118. //
  119. // Determine the address based on whether the bus address is in I/O space
  120. // or bus memory space.
  121. //
  122. switch (*AddressSpace) {
  123. case 0 : {
  124. //
  125. // The address is in EISA memory space, kernel mode.
  126. //
  127. //
  128. // If the address cannot be mapped, just return FALSE.
  129. //
  130. if ( BusAddress.LowPart > HAL_32MB ) {
  131. *AddressSpace = 0;
  132. TranslatedAddress->LowPart = 0;
  133. return(FALSE);
  134. }
  135. TranslatedAddress->HighPart = 0x2;
  136. //
  137. // There is no component of the bus address in the low part
  138. //
  139. TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
  140. //
  141. // Now call HalCreateQva. This will create a QVA
  142. // that we'll return to the caller. Then we will implicitly set
  143. // AddressSpace to a 1. The caller then will not call MmMapIoSpace
  144. // and will use the address we return as a VA.
  145. TranslatedAddress->LowPart = (ULONG) HalCreateQva(
  146. *TranslatedAddress, va);
  147. TranslatedAddress->HighPart = 0; // clear high longword for QVA
  148. *AddressSpace = 1; // don't let the user call MmMapIoSpace
  149. return(TRUE);
  150. }
  151. case 1 : {
  152. //
  153. // The address is in EISA I/O space, kernel mode.
  154. //
  155. TranslatedAddress->HighPart = 0x3;
  156. //
  157. // There is no component of the bus address in the low part
  158. //
  159. TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
  160. //
  161. // Now call HalCreateQva. This will create a QVA
  162. // that we'll return to the caller. Then we will implicitly set
  163. // AddressSpace to a 1. The caller then will not call MmMapIoSpace
  164. // and will use the address we return as a VA.
  165. TranslatedAddress->LowPart = (ULONG) HalCreateQva(
  166. *TranslatedAddress, va);
  167. TranslatedAddress->HighPart = 0; // clear high longword for QVA
  168. *AddressSpace = 1; // Make sure user doesn't call
  169. // MmMapIoSpace.
  170. return(TRUE);
  171. }
  172. case 2 : {
  173. //
  174. // The address is in EISA memory space, user mode.
  175. //
  176. TranslatedAddress->HighPart = 0x2;
  177. //
  178. // There is no component of the bus address in the low part
  179. //
  180. TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
  181. *AddressSpace = 0; // Let the user call MmMapIoSpace
  182. return(TRUE);
  183. }
  184. case 3 : {
  185. //
  186. // The address is in EISA I/O space, user mode.
  187. //
  188. TranslatedAddress->HighPart = 0x3;
  189. //
  190. // There is no component of the bus address in the low part
  191. //
  192. TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
  193. *AddressSpace = 0; // Make sure user can call
  194. // MmMapIoSpace.
  195. return(TRUE);
  196. }
  197. }
  198. }
  199. PVOID
  200. HalCreateQva(
  201. IN PHYSICAL_ADDRESS PA,
  202. IN PVOID VA
  203. )
  204. /*++
  205. Routine Description:
  206. This function is called two ways. First, from HalTranslateBusAddress,
  207. if the caller is going to run in kernel mode and use superpages.
  208. The second way is if the user is going to access in user mode.
  209. MmMapIoSpace or ZwViewMapOfSection will call this.
  210. If the input parameter VA is zero, then we assume super page and build
  211. a QUASI virtual address that is only usable by calling the hal I/O
  212. access routines.
  213. if the input parameter VA is non-zero, we assume the user has either
  214. called MmMapIoSpace or ZwMapViewOfSection and will use the access
  215. routines in JXIOUSER.C
  216. If the PA is not an I/O space address (Combo chip, Eisa I/O, Eisa
  217. memory), then return the VA as the QVA.
  218. Arguments:
  219. PA - the physical address generated by HalTranslateBusAddress
  220. VA - the virtual address returned by MmMapIoSpace
  221. Return Value:
  222. The returned value is a quasi virtual address in that it can be
  223. added to and subtracted from, but it cannot be used to access the
  224. bus directly. The top bits are set so that we can trap invalid
  225. accesses in the memory management subsystem. All access should be
  226. done through the Hal Access Routines in *ioacc.s if it was a superpage
  227. kernel mode access. If it is usermode, then JXIOUSER.C should be built
  228. into the users code.
  229. --*/
  230. {
  231. PVOID qva;
  232. if (PA.HighPart == 2) {
  233. //
  234. // in EISA MEMORY space
  235. //
  236. if (VA == 0) {
  237. PA.LowPart = PA.LowPart >> 2;
  238. qva = (PVOID)(RtlLargeIntegerShiftRight(PA, EISA_BIT_SHIFT-2).LowPart);
  239. } else {
  240. qva = (PVOID)((ULONG)VA >> EISA_BIT_SHIFT);
  241. }
  242. qva = (PVOID)((ULONG)qva | EISA_QVA);
  243. return(qva);
  244. }
  245. if (PA.HighPart == 3) {
  246. //
  247. // in EISA IO space
  248. //
  249. if (VA == 0) {
  250. PA.LowPart = PA.LowPart >> 2;
  251. qva = (PVOID)(RtlLargeIntegerShiftRight(PA, EISA_BIT_SHIFT-2).LowPart);
  252. } else {
  253. qva = (PVOID)((ULONG)VA >> EISA_BIT_SHIFT);
  254. }
  255. qva = (PVOID)((ULONG)qva | EISA_QVA);
  256. return(qva);
  257. }
  258. if (PA.HighPart == 1) {
  259. //
  260. // on the combo chip (82C106)
  261. //
  262. if (VA == 0) {
  263. qva = (PVOID)(RtlLargeIntegerShiftRight(PA, COMBO_BIT_SHIFT).LowPart);
  264. } else {
  265. qva = (PVOID)((ULONG)VA >> COMBO_BIT_SHIFT);
  266. }
  267. qva = (PVOID)((ULONG)qva | COMBO_QVA);
  268. return(qva);
  269. }
  270. //
  271. // It is not an I/O space address, return the VA as the QVA
  272. //
  273. return(VA);
  274. }