|
|
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.