|
|
1.1 ! root 1: /*++ BUILD Version: 0002 // Increment this if a change has global effects ! 2: ! 3: Copyright (c) 1989-91 Microsoft Corporation ! 4: Copyright (c) 1992 Digital Equipment Corporation ! 5: ! 6: Module Name: ! 7: ! 8: ioaccess.h ! 9: ! 10: Abstract: ! 11: ! 12: Definitions of function prototypes for accessing I/O ports and ! 13: memory on I/O adapters from user mode programs. ! 14: ! 15: Cloned from parts of nti386.h. ! 16: ! 17: Author: ! 18: ! 19: ! 20: --*/ ! 21: ! 22: #ifndef _IOACCESS_ ! 23: #define _IOACCESS_ ! 24: ! 25: ! 26: // Only define these prototypes if they're not already defined ! 27: ! 28: #if defined (i386) ! 29: ! 30: // ! 31: // I/O space read and write macros. ! 32: // ! 33: // These have to be actual functions on the 386, because we need ! 34: // to use assembler, but cannot return a value if we inline it. ! 35: // ! 36: // The READ/WRITE_REGISTER_* calls manipulate I/O registers in MEMORY space. ! 37: // (Use x86 move instructions, with LOCK prefix to force correct behavior ! 38: // w.r.t. caches and write buffers.) ! 39: // ! 40: // The READ/WRITE_PORT_* calls manipulate I/O registers in PORT space. ! 41: // (Use x86 in/out instructions.) ! 42: // ! 43: ! 44: #define READ_REGISTER_UCHAR(Register) (*(PUCHAR)(Register)) ! 45: ! 46: #define READ_REGISTER_USHORT(Register) (*(PUSHORT)(Register)) ! 47: ! 48: #define READ_REGISTER_ULONG(Register) (*(PULONG)(Register)) ! 49: ! 50: #define WRITE_REGISTER_UCHAR(Register, Value) (*(volatile UCHAR *)(Register) = (Value)) ! 51: ! 52: #define WRITE_REGISTER_USHORT(Register, Value) (*(volatile USHORT *)(Register) = (Value)) ! 53: ! 54: #define WRITE_REGISTER_ULONG(Register, Value) (*(volatile ULONG *)(Register) = (Value)) ! 55: ! 56: #define READ_PORT_UCHAR(Port) inp (Port) ! 57: ! 58: #define READ_PORT_USHORT(Port) inpw (Port) ! 59: ! 60: #define WRITE_PORT_UCHAR(Port, Value) outp ((Port), (Value)) ! 61: ! 62: #define WRITE_PORT_USHORT(Port, Value) outpw ((Port), (Value)) ! 63: ! 64: #define MEMORY_BARRIER() ! 65: ! 66: #endif // defined(i386) ! 67: ! 68: ! 69: #if defined (ALPHA) ! 70: // ! 71: // I/O space read and write macros. ! 72: // ! 73: // The READ/WRITE_REGISTER_* calls manipulate I/O registers in MEMORY space. ! 74: // (Use simple C macros. The caller is responsible for inserting memory ! 75: // barriers, as appropriate.) ! 76: // ! 77: // The READ/WRITE_PORT_* calls manipulate I/O registers in PORT space. ! 78: // (Use subroutine calls, since these are used less frequently than the ! 79: // register routines, and require more context.) ! 80: // ! 81: ! 82: ! 83: /*++ ! 84: ! 85: VOID ! 86: MEMORY_BARRIER( ! 87: VOID ! 88: ) ! 89: ! 90: Routine Description: ! 91: ! 92: Execute an Alpha AXP MB instruction, to force pending writes ! 93: out to the bus. ! 94: ! 95: Arguments: ! 96: ! 97: None. ! 98: ! 99: Return Value: ! 100: ! 101: None. ! 102: ! 103: --*/ ! 104: ! 105: #if defined(_MSC_VER) ! 106: ! 107: #define MEMORY_BARRIER() __MB() ! 108: ! 109: #else ! 110: #if defined(ACCASM) && !defined(__CPLUSPLUS) ! 111: ! 112: long asm(const char *,...); ! 113: #pragma intrinsic(asm) ! 114: ! 115: // ! 116: // ACC has a bug whereby an "asm" directive that occurs in a ! 117: // routine *before* any function calls, will bugcheck the ! 118: // compiler. ! 119: // Remove the following symbol definition when this is fixed. ! 120: // ! 121: ! 122: #define ACC_ASM_BUG 1 ! 123: ! 124: #define MEMORY_BARRIER() asm("mb") ! 125: ! 126: #endif // ACCASM ! 127: #endif // _MSC_VER ! 128: ! 129: ! 130: // Alpha AXP Platform support ! 131: // ! 132: // Note that these macros are cloned from ...\ntos\hal\alpha.jxiouser.c. ! 133: // ! 134: // All these macros require that the calling argument is a QVA, such ! 135: // as would be returned by HalCreateQva - this should ! 136: // have QVA_ENABLE set. They assume the QVA represents an I/O bus address, ! 137: // and do conditionally select QVA-to-VA decoding based on this. ! 138: // ! 139: // Note that the argument is declared as PUCHAR or PUSHORT or ! 140: // whatever, even though it really is a QUASI_VIRTUAL_ADDRESS. This ! 141: // is for driver compatibility: all the drivers out there get a ! 142: // PVOID from ZwMapViewOfSection, then cast it to PU* before calling these ! 143: // routines. If we insisted on declaring them correctly, we would ! 144: // have to change all the drivers, which is what we are trying to avoid. ! 145: // ! 146: // Lane shifting: Alpha AXP PC's will not do lane shifting in sparse ! 147: // I/O bus address spaces That means that for access shorter than a ! 148: // longword, the data will NOT show up in the lowest bit position, ! 149: // but will be in the byte/word that it would have started in. ! 150: // For longwords, the value will show up on the data path correctly. ! 151: // For, say, the 3rd byte in a word, a longword would be returned, ! 152: // and bytes 0, 1 and 3 would be garbage, and the value in byte 2 ! 153: // would be the one you wanted. The same applies for writing: a ! 154: // longword will always be sent out onto the bus, and we must move ! 155: // the valid data byte into the correct position, and set the byte ! 156: // enables to say which byte to use. Note that what you cannot do is ! 157: // leave the byte in the lowest position, and set the byte enable ! 158: // to the lowest byte, because this would generate an unaligned ! 159: // longword access, which the Alpha AXP chip cannot handle. ! 160: // ! 161: // So, for bytes, the access must be an aligned longword, with byte ! 162: // enables set to indicate which byte to get/set, and the byte moved ! 163: // to/from the desired position within the longword. Similarly for ! 164: // shorts. Tribytes are not supported. ! 165: // ! 166: ! 167: // ! 168: // I/O access values ! 169: // ! 170: ! 171: // QVA Encoding: ! 172: // Bits (31:29) are used to tag a QVA ! 173: // Bits (28:27) in QVA used for address space encoding ! 174: ! 175: #define QVA_ENABLE 0xa0000000 ! 176: #define QVA_ADDRESS_SPACE 0x18000000 ! 177: #define QVA_SELECTORS 0xb8000000 // (QVA_ENABLE | QVA_ADDRESS_SPACE) ! 178: ! 179: // Jensen-style sparse address space definition (JENSEN_QVA) ! 180: // Used for EISA bus I/O accesses. ! 181: ! 182: #define JENSEN_QVA 0xb0000000 // (QVA_ENABLE | 0x10000000) ! 183: ! 184: #define EISA_BIT_SHIFT 0x07 // Bits to shift address ! 185: ! 186: #define EISA_BYTE_LEN 0x00 // Byte length ! 187: #define EISA_WORD_LEN 0x20 // Word length ! 188: #define EISA_LONG_LEN 0x60 // LONGWORD length ! 189: ! 190: // Morgan-style sparse address space definition (OTHER_QVA) ! 191: // Used for ISA and PCI bus I/O accesses in sparse space. ! 192: ! 193: #define OTHER_QVA 0xa0000000 // (QVA_ENABLE | 0x00000000) ! 194: ! 195: #define IO_BIT_SHIFT 0x05 // Bits to shift address ! 196: ! 197: #define IO_BYTE_LEN 0x00 // Byte length ! 198: #define IO_WORD_LEN 0x08 // Word length ! 199: #define IO_LONG_LEN 0x18 // LONGWORD length ! 200: ! 201: ! 202: /*++ ! 203: ! 204: UCHAR ! 205: READ_PORT_Usize( ! 206: volatile PUsize Port ! 207: ) ! 208: ! 209: Routine Description: ! 210: ! 211: Read from the specified I/O port (CSR) address. ! 212: ! 213: Note these macros do *not* perform a memory barrier. The ! 214: rationale for this is that reading from a CSR is informative, ! 215: rather than active. This is a weak rationale, but fits in OK ! 216: with the VGA driver. Trying to use this module for other ! 217: purposes may require the use of memory barriers. ! 218: ! 219: Arguments: ! 220: ! 221: Port - Supplies a pointer to the port in I/O space. ! 222: ! 223: Return Value: ! 224: ! 225: Returns the value read from the specified port address. ! 226: ! 227: --*/ ! 228: ! 229: #define READ_PORT_UCHAR READ_REGISTER_UCHAR ! 230: ! 231: #define READ_PORT_USHORT READ_REGISTER_USHORT ! 232: ! 233: #define READ_PORT_ULONG READ_REGISTER_ULONG ! 234: ! 235: /*++ ! 236: ! 237: VOID ! 238: WRITE_PORT_Usize( ! 239: volatile PUsize Port, ! 240: Usize Value ! 241: ) ! 242: ! 243: Routine Description: ! 244: ! 245: Write to the specified port (CSR) address. ! 246: ! 247: Note we perform a memory barrier before we modify the CSR. The ! 248: rationale for this is that writing to a CSR clearly has active ! 249: effects, and thus all writes that take place before the CSR is ! 250: changed must be completed before the CSR change takes effect. ! 251: ! 252: We also perform a memory barrier after we modify the CSR. The ! 253: rationale for this is that any writes which follow the CSR ! 254: modification may be affected by the change in state, and thus ! 255: must be ordered with respect to the CSR modification. ! 256: ! 257: Note that if you're updating multiple CSRs in a row, there will ! 258: be more memory barriers than needed. Do we want another set of ! 259: macros to get around this? ! 260: ! 261: The QUICK_WRITE_PORT_Usize functions perform the same functions ! 262: as their WRITE_PORT_Usize variants, except they do *not* execute ! 263: memory barriers. The invoker is responsible for using the ! 264: MEMORY_BARRIER function to synchronize with the write buffers and ! 265: cache. ! 266: ! 267: Arguments: ! 268: ! 269: Port - Supplies a pointer to the port in I/O space. ! 270: Value - The value to be written to the port. ! 271: ! 272: Return Value: ! 273: ! 274: None ! 275: ! 276: --*/ ! 277: ! 278: #define WRITE_PORT_UCHAR(Port,Value) \ ! 279: \ ! 280: MEMORY_BARRIER(); \ ! 281: WRITE_REGISTER_UCHAR ((Port), (Value)); \ ! 282: MEMORY_BARRIER(); \ ! 283: ! 284: ! 285: #define QUICK_WRITE_PORT_UCHAR(Port,Value) \ ! 286: WRITE_REGISTER_UCHAR ((Port), (Value)) ! 287: ! 288: #define WRITE_PORT_USHORT(Port,Value) \ ! 289: \ ! 290: MEMORY_BARRIER(); \ ! 291: WRITE_REGISTER_USHORT ((Port), (Value)); \ ! 292: MEMORY_BARRIER(); \ ! 293: ! 294: ! 295: #define QUICK_WRITE_PORT_USHORT(Port,Value) \ ! 296: WRITE_REGISTER_USHORT ((Port), (Value)) ! 297: ! 298: #define WRITE_PORT_ULONG(Port,Value) \ ! 299: \ ! 300: MEMORY_BARRIER(); \ ! 301: WRITE_REGISTER_ULONG ((Port), (Value)); \ ! 302: MEMORY_BARRIER(); \ ! 303: ! 304: ! 305: #define QUICK_WRITE_PORT_ULONG(Port,Value) \ ! 306: WRITE_REGISTER_ULONG ((Port), (Value)) ! 307: ! 308: /*++ ! 309: ! 310: UCHAR ! 311: READ_REGISTER_Usize( ! 312: volatile PUsize Register ! 313: ) ! 314: ! 315: Routine Description: ! 316: ! 317: Read from the specified register address. ! 318: ! 319: Arguments: ! 320: ! 321: Register - Supplies a pointer to the register in I/O space. ! 322: ! 323: Return Value: ! 324: ! 325: Returns the value read from the specified register address. ! 326: ! 327: --*/ ! 328: ! 329: #define READ_REGISTER_UCHAR(Register) \ ! 330: ( \ ! 331: ( ((ULONG) (Register) & QVA_SELECTORS) == OTHER_QVA ) ? \ ! 332: ((UCHAR)((*(volatile ULONG *)((((ULONG)(Register) \ ! 333: ) << IO_BIT_SHIFT) | IO_BYTE_LEN )) >> (((ULONG)(Register) & 3) * 8))) \ ! 334: : \ ! 335: ((UCHAR)((*(volatile ULONG *)((((ULONG)(Register) \ ! 336: ) << EISA_BIT_SHIFT) | EISA_BYTE_LEN)) >> (((ULONG)(Register) & 3) * 8))) \ ! 337: ) ! 338: ! 339: #define READ_REGISTER_USHORT(Register) \ ! 340: ( \ ! 341: ( ((ULONG) (Register) & QVA_SELECTORS) == OTHER_QVA ) ? \ ! 342: ((USHORT)((*(volatile ULONG *)((((ULONG)(Register) \ ! 343: ) << IO_BIT_SHIFT) | IO_WORD_LEN )) >> (((ULONG)(Register) & 3) * 8))) \ ! 344: : \ ! 345: ((USHORT)((*(volatile ULONG *)((((ULONG)(Register) \ ! 346: ) << EISA_BIT_SHIFT) | EISA_WORD_LEN)) >> (((ULONG)(Register) & 3) * 8))) \ ! 347: ) ! 348: ! 349: #define READ_REGISTER_ULONG(Register) \ ! 350: ( \ ! 351: ( ((ULONG) (Register) & QVA_SELECTORS) == OTHER_QVA ) ? \ ! 352: (*(volatile ULONG *)((((ULONG)(Register) ) << IO_BIT_SHIFT) | IO_LONG_LEN)) \ ! 353: : \ ! 354: (*(volatile ULONG *)((((ULONG)(Register) ) << EISA_BIT_SHIFT) | EISA_LONG_LEN)) \ ! 355: ) ! 356: ! 357: ! 358: /*++ ! 359: ! 360: VOID ! 361: WRITE_REGISTER_Usize( ! 362: volatile PUsize Register, ! 363: Usize Value ! 364: ) ! 365: ! 366: Routine Description: ! 367: ! 368: Write to the specified register address. ! 369: ! 370: Arguments: ! 371: ! 372: Register - Supplies a pointer to the register in I/O space. ! 373: Value - The value to be written to the register. ! 374: ! 375: Return Value: ! 376: ! 377: None ! 378: ! 379: --*/ ! 380: ! 381: #define WRITE_REGISTER_UCHAR(Register,Value) \ ! 382: if ( (((ULONG) (Register)) & QVA_SELECTORS) == OTHER_QVA) \ ! 383: (*(volatile ULONG *)((((ULONG)(Register) ) << IO_BIT_SHIFT) | IO_BYTE_LEN) = \ ! 384: (ULONG)((ULONG)(Value) << (((ULONG)(Register) & 3) * 8))); \ ! 385: else \ ! 386: (*(volatile ULONG *)((((ULONG)(Register) ) << EISA_BIT_SHIFT) | EISA_BYTE_LEN) = \ ! 387: (ULONG)((ULONG)(Value) << (((ULONG)(Register) & 3) * 8))); ! 388: ! 389: ! 390: #define WRITE_REGISTER_USHORT(Register,Value) \ ! 391: if ( (((ULONG) (Register)) & QVA_SELECTORS) == OTHER_QVA) \ ! 392: (*(volatile ULONG *)((((ULONG)(Register) ) << IO_BIT_SHIFT) | IO_WORD_LEN) = \ ! 393: (ULONG)((ULONG)(Value) << (((ULONG)(Register) & 3) * 8))); \ ! 394: else \ ! 395: (*(volatile ULONG *)((((ULONG)(Register) ) << EISA_BIT_SHIFT) | EISA_WORD_LEN) = \ ! 396: (ULONG)((ULONG)(Value) << (((ULONG)(Register) & 3) * 8))) ; ! 397: ! 398: ! 399: #define WRITE_REGISTER_ULONG(Register,Value) \ ! 400: if ( (((ULONG) (Register)) & QVA_SELECTORS) == OTHER_QVA) \ ! 401: (*(volatile ULONG *)((((ULONG)(Register) ) << IO_BIT_SHIFT) | IO_LONG_LEN) = \ ! 402: (ULONG)(Value)) ; \ ! 403: else \ ! 404: (*(volatile ULONG *)((((ULONG)(Register) ) << EISA_BIT_SHIFT) | EISA_LONG_LEN) = \ ! 405: (ULONG)(Value)); ! 406: ! 407: ! 408: ! 409: #endif // defined(ALPHA) ! 410: ! 411: ! 412: #if defined(MIPS) ! 413: ! 414: // ! 415: // There is no such thing as a memory barrier on MIPS ... ! 416: // ! 417: ! 418: #define MEMORY_BARRIER() ! 419: ! 420: ! 421: /*++ ! 422: ! 423: UCHAR ! 424: READ_WRITE_PORT_Usize( ! 425: volatile PUsize Port ! 426: ) ! 427: ! 428: Routine Description: ! 429: ! 430: Read from the specified I/O port (CSR) address. ! 431: ! 432: Note these macros do *not* perform a memory barrier. The ! 433: rationale for this is that reading from a CSR is informative, ! 434: rather than active. This is a weak rationale, but fits in OK ! 435: with the VGA driver. Trying to use this module for other ! 436: purposes may require the use of memory barriers. ! 437: ! 438: Arguments: ! 439: ! 440: Port - Supplies a pointer to the port in I/O space. ! 441: ! 442: Return Value: ! 443: ! 444: Returns the value read from the specified port address. ! 445: ! 446: --*/ ! 447: ! 448: #define READ_PORT_UCHAR(A) READ_REGISTER_UCHAR((PUCHAR)(A)) ! 449: ! 450: #define READ_PORT_USHORT(A) READ_REGISTER_USHORT((PUSHORT)(A)) ! 451: ! 452: #define READ_PORT_ULONG(A) READ_REGISTER_ULONG((PULONG)(A)) ! 453: ! 454: #define WRITE_PORT_UCHAR(A,V) WRITE_REGISTER_UCHAR((PUCHAR)(A),(UCHAR)(V)) ! 455: ! 456: #define WRITE_PORT_USHORT(A,V) WRITE_REGISTER_USHORT((PUSHORT)(A),(USHORT)(V)) ! 457: ! 458: #define WRITE_PORT_ULONG(A,V) WRITE_REGISTER_ULONG((PULONG)(A),(ULONG)(V)) ! 459: ! 460: ! 461: /*++ ! 462: ! 463: UCHAR ! 464: READ_REGISTER_Usize( ! 465: volatile PUsize Register ! 466: ) ! 467: ! 468: Routine Description: ! 469: ! 470: Read from the specified register address. ! 471: ! 472: Arguments: ! 473: ! 474: Register - Supplies a pointer to the register in I/O space. ! 475: ! 476: Return Value: ! 477: ! 478: Returns the value read from the specified register address. ! 479: ! 480: --*/ ! 481: ! 482: #define READ_REGISTER_UCHAR(x) \ ! 483: (*(volatile UCHAR * const)(x)) ! 484: ! 485: #define READ_REGISTER_USHORT(x) \ ! 486: (*(volatile USHORT * const)(x)) ! 487: ! 488: #define READ_REGISTER_ULONG(x) \ ! 489: (*(volatile ULONG * const)(x)) ! 490: ! 491: ! 492: /*++ ! 493: ! 494: VOID ! 495: WRITE_REGISTER_Usize( ! 496: volatile PUsize Register, ! 497: Usize Value ! 498: ) ! 499: ! 500: Routine Description: ! 501: ! 502: Write to the specified register address. ! 503: ! 504: Arguments: ! 505: ! 506: Register - Supplies a pointer to the register in I/O space. ! 507: Value - The value to be written to the register. ! 508: ! 509: Return Value: ! 510: ! 511: None ! 512: ! 513: --*/ ! 514: ! 515: #define WRITE_REGISTER_UCHAR(x, y) \ ! 516: (*(volatile UCHAR * const)(x) = (y)) ! 517: ! 518: #define WRITE_REGISTER_USHORT(x, y) \ ! 519: (*(volatile USHORT * const)(x) = (y)) ! 520: ! 521: #define WRITE_REGISTER_ULONG(x, y) \ ! 522: (*(volatile ULONG * const)(x) = (y)) ! 523: ! 524: #endif // defined(MIPS) ! 525: ! 526: #endif // _IOACCESS_
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.