Annotation of ntddk/src/video/inc/ioaccess.h, revision 1.1

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_

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.