summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/hal0jens/alpha/jxiouser.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/hal0jens/alpha/jxiouser.c')
-rw-r--r--private/ntos/nthals/hal0jens/alpha/jxiouser.c971
1 files changed, 971 insertions, 0 deletions
diff --git a/private/ntos/nthals/hal0jens/alpha/jxiouser.c b/private/ntos/nthals/hal0jens/alpha/jxiouser.c
new file mode 100644
index 000000000..8ab422c06
--- /dev/null
+++ b/private/ntos/nthals/hal0jens/alpha/jxiouser.c
@@ -0,0 +1,971 @@
+#if defined (JENSEN)
+
+/*++
+
+Copyright (c) 1992 Digital Equipment Corporation
+
+Module Name:
+
+ jxioacc.c
+
+Abstract:
+
+ This module contains the Jensen I/O space access routines for user mode
+ mapped addresses.
+
+ The READ_PORT_Uxxx MACROs simply call the equivalent READ_REGISTER_Uxxx
+ routine. Similarly, the WRITE_PORT_Uxxx MACROs call the equivalent
+ WRITE_REGISTER_Uxxx routines. Since Jensen uses 64 bit super pages for
+ Virtual I/O, and that super pages are only accessable through kernel
+ mode, these routines here will decode a QVA and do the access, but
+ through normal translations.
+
+ All these routines ensure that the calling argument is a QVA, such
+ as would be returned by the wrapper around MmMapIoSpace - this should
+ have QVA_ENABLE set. They determine which type of shift should be
+ used, based on the next bit in the longword.
+
+ Note that the argument is declared as PUCHAR or PUSHORT or
+ whatever, even though it really is a QUASI_VIRTUAL_ADDRESS. This
+ is for driver compatibility: all the drivers out there get a
+ PVOID from MmMapIoSpace, then cast it to PU* before calling these
+ routines. If we insisted on declaring them correctly, we would
+ have to change all the drivers, which is what we are trying to avoid.
+
+ Lane shifting: the Jensen box will not do lane shifting in EISA
+ space. That means that for access shorter than a longword, the
+ data will NOT show up in the lowest bit position, but will be in
+ the byte/word that it would have started in. For longwords, the
+ value will show up on the data path correctly. For, say, the 3rd
+ byte in a word, a longword would be returned, and bytes 0, 1 and 3
+ would be garbage, and the value in byte 2 would be the one you
+ wanted. The same applies for writing: a longword will always be
+ sent out onto the bus, and we must move the valid data byte into
+ the correct position, and set the byte enables to say which byte
+ to use. Note that what you cannot do is leave the byte in the
+ lowest position, and set the byte enable to the lowest byte,
+ because this would generate an unaligned longword access, which
+ the chip cannot handle.
+
+ So, for bytes, the access must be an aligned longword, with byte
+ enables set to indicate which byte to get/set, and the byte moved
+ to/from the desired position within the longword. Similarly for
+ shorts. Tribytes are not supported.
+
+ Lane shifting is not an issue for accessing the Combo chip, which
+ only allows byte accesses, and for which the data is always moved
+ to the low 8 bits of the HBUS data longword, according to the spec.
+
+ Performance: If the buffer routines get used alot, something we
+ could do to improve performance would be to send four byte or two
+ shorts out to the bus at a time (or get them). This would work
+ because the PIC queries the device about the size of transfer that
+ it can accept (or the device rejects a transfer that it cannot
+ handle) and parcels the data out in correct size chunks.
+
+Author:
+
+ Rod N. Gamache (DEC) 5-May-1992
+ Miche Baker-Harvey (miche) 21-May-1992
+ Jeff McLeman (DEC) 30-Jul-1992
+
+Revision History:
+
+--*/
+// Include files
+
+#include "halp.h"
+#include "jnsndef.h"
+
+
+UCHAR
+READ_REGISTER_UCHAR(
+ volatile PUCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+
+Return Value:
+
+ Returns the value read from the specified register address.
+
+--*/
+
+{
+ ULONG mv; // Local value
+ ULONG byte; // which byte we want
+ volatile PULONG ma; // Local address
+
+ HalpMb;
+
+ //
+ // If it's an EISA address, use EISA shifts, byte enables
+ //
+
+ if (IS_EISA_QVA(Register)) {
+
+ //
+ // Determine which byte it is that we want.
+ //
+
+ byte = (ULONG)Register & 0x3;
+
+ //
+ // Shift the virtual address into position, and indicate that
+ // we want a byte.
+ //
+ // The desired byte enable is set automatically because the
+ // Jensen designers picked values which correspond exactly
+ // to the actual byte addresses
+ //
+
+ ma = (volatile PULONG)
+ (EISA_BYTE_LEN | ((ULONG)Register << EISA_BIT_SHIFT));
+
+ //
+ // Get the longword value, which will only have one valid byte
+ //
+
+ mv = *ma;
+
+ //
+ // Extract out and return the desired byte
+ // The compiler should convert the multiplication
+ //
+
+ return((UCHAR)(mv >> (byte * 8)));
+
+ }
+
+ //
+ // If it's a Combo Chip address, use those shifts, byte enables
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+ return ((UCHAR)(*(volatile PULONG )(COMBO_BYTE_LEN |
+ ((ULONG)Register << COMBO_BIT_SHIFT))));
+ }
+
+ //
+ // It's not a valid QVA
+ //
+
+ KeBugCheck("Invalid QVA in READ_REGISTER_UCHAR\n");
+}
+
+
+
+USHORT
+READ_REGISTER_USHORT(
+ volatile PUSHORT Register
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified Register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+
+Return Value:
+
+ Returns the value read from the specified register address.
+
+--*/
+
+{
+ ULONG mv, word; // Local value and word we want
+ volatile PULONG ma; // Local address
+
+ //
+ // This works as long as we don't want the fourth short!
+ //
+ ASSERT(((ULONG)Register & 0x3) != 0x3);
+
+ //
+ // If it's an EISA address, use EISA shifts, word enables
+ //
+
+ if (IS_EISA_QVA(Register)) {
+
+ //
+ // Determine which word it is that we want.
+ //
+
+ word = (ULONG)Register & 0x3;
+
+ //
+ // Shift the virtual address into position, and indicate that
+ // we want a word.
+ //
+ // The desired word enable is set automatically because the
+ // Jensen designers picked values which correspond exactly
+ // to the actual word addresses
+ //
+
+ ma = (volatile PULONG)
+ (EISA_WORD_LEN | ((ULONG)Register << EISA_BIT_SHIFT));
+
+ //
+ // Get the longword value, which will only have one valid word
+ //
+
+ mv = *ma;
+
+ //
+ // Extract out and return the desired word
+ // The compiler should convert the multiplication
+ //
+
+ return((USHORT)(mv >> (8 * word)));
+
+ }
+
+ //
+ // USHORT operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ KeBugCheck("Invalid Combo QVA in READ_REGISTER_USHORT\n");
+ }
+
+ KeBugCheck("Invalid QVA in READ_REGISTER_USHORT\n");
+}
+
+
+ULONG
+READ_REGISTER_ULONG(
+ volatile PULONG Register
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+
+Return Value:
+
+ Returns the value read from the specified register address.
+
+--*/
+
+{
+
+ //
+ // We are assuming that the longword is aligned
+ //
+ ASSERT(((ULONG)Register & 0x3) == 0x0);
+
+ if (IS_EISA_QVA(Register)) {
+
+ HalpMb;
+ return (*(volatile PULONG)(EISA_LONG_LEN |
+ ((ULONG)Register << EISA_BIT_SHIFT)));
+
+ }
+
+ //
+ // ULONG operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ KeBugCheck("Invalid Combo QVA in READ_REGISTER_ULONG\n");
+ }
+
+ KeBugCheck("Invalid QVA in READ_REGISTER_ULONG\n");
+}
+
+
+VOID
+WRITE_REGISTER_UCHAR(
+ volatile PUCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+ Value - The value to be written to the register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG mv; // local copy of value for shifting
+ ULONG byte; // the byte position requested
+
+ //
+ // If it's an EISA address, use EISA shifts, byte enables
+ //
+
+ if (IS_EISA_QVA(Register)) {
+
+ //
+ // Determine which byte it is that we want.
+ //
+
+ byte = (ULONG)Register & 0x3;
+
+ //
+ // Move value into appropriate byte position in longword
+ // The compiler should convert the multiplication
+ //
+
+ mv = (ULONG)(Value << (8 * byte));
+
+ //
+ // The address is long aligned and the byte enables set
+ // automagically by the way the Jensen physical map is set
+ //
+ *(volatile PULONG)(EISA_BYTE_LEN |
+ ((ULONG)Register << EISA_BIT_SHIFT)) = mv;
+ HalpMb;
+ return;
+ }
+
+ //
+ // If it's a Combo Chip address, use those shifts, byte enables
+ // No lane shifting is required for the Combo chip.
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ *(volatile PULONG)(COMBO_BYTE_LEN |
+ ((ULONG)Register << COMBO_BIT_SHIFT)) = Value;
+ HalpMb;
+ return;
+ }
+
+ //
+ // It's not a valid QVA
+ //
+
+ KeBugCheck("Invalid QVA in WRITE_REGISTER_UCHAR\n");
+}
+
+
+VOID
+WRITE_REGISTER_USHORT(
+ volatile PUSHORT Register,
+ USHORT Value
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+ Value - The value to be written to the register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG mv; // local copy of value for shifting
+ UCHAR word; // the word position requested
+
+ //
+ // This works as long as we don't want the fourth short!
+ //
+ ASSERT(((ULONG)Register & 0x3) != 0x3);
+
+ //
+ // If it's an EISA address, use EISA shifts, word enables
+ //
+
+ if (IS_EISA_QVA(Register)) {
+
+
+ //
+ // Determine which word it is that we want.
+ //
+
+ word = (ULONG)Register & 0x3;
+
+ //
+ // Move value into appropriate word position in longword
+ // The compiler should convert the multiplication
+ //
+
+ mv = (ULONG)(Value << (8 * word));
+
+ //
+ // The address is long aligned and the word enables set
+ // automagically by the way the Jensen physical map is set
+ //
+
+ *(volatile PULONG)(EISA_WORD_LEN |
+ ((ULONG)Register << EISA_BIT_SHIFT)) = mv;
+ HalpMb;
+ return;
+ }
+
+ //
+ // USHORT operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ KeBugCheck("Invalid Combo QVA in WRITE_REGISTER_USHORT\n");
+ }
+
+ KeBugCheck("Invalid QVA in WRITE_REGISTER_USHORT\n");
+}
+
+
+VOID
+WRITE_REGISTER_ULONG(
+ volatile PULONG Register,
+ ULONG Value
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified register address.
+
+Arguments:
+
+ Register - Supplies a pointer to the register in EISA I/O space.
+ Value - The value to be written to the register.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ //
+ // We are assuming that the longword is aligned
+ //
+ ASSERT(((ULONG)Register & 0x3) == 0x0);
+
+ if (IS_EISA_QVA(Register)) {
+
+ *(volatile PULONG)(EISA_LONG_LEN |
+ ((ULONG)Register << EISA_BIT_SHIFT)) = Value;
+ HalpMb;
+ return;
+ }
+
+ //
+ // ULONG operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Register)) {
+
+ KeBugCheck("Invalid Combo QVA in WRITE_REGISTER_ULONG\n");
+ }
+
+ KeBugCheck("Invalid QVA in WRITE_REGISTER_ULONG\n");
+}
+
+
+
+VOID
+READ_PORT_BUFFER_UCHAR(
+ volatile PUCHAR Port,
+ PUCHAR Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified port buffer address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data to.
+ Count - the number of bytes to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i, mv;
+ volatile PULONG ma;
+ ULONG byte;
+
+ HalpMb;
+ if (IS_EISA_QVA(Port)) {
+
+ //
+ // Shift the virtual address into position, and indicate that
+ // we want a byte.
+ //
+ // The desired byte enable is set automatically because the
+ // Jensen designers picked values which correspond exactly
+ // to the actual byte addresses
+ //
+
+ ma = (volatile PULONG)
+ (EISA_BYTE_LEN | ((ULONG)Port << EISA_BIT_SHIFT));
+
+ for ( i = 0 ; i < Count ; i++) {
+
+ //
+ // Determine which byte it is that we want.
+ //
+
+ byte = (ULONG)ma & (0x3 << EISA_BIT_SHIFT);
+
+ //
+ // Get the longword value, which will only have one valid byte
+ //
+
+ mv = *ma;
+
+ //
+ // Extract out the desired byte
+ // The compiler should convert the multiplication
+ //
+
+ *Buffer++ = ((UCHAR)(mv >> (8 * byte)));
+
+
+ }
+
+ } else if (IS_COMBO_QVA(Port)) {
+
+ ma = (volatile PULONG) (COMBO_BYTE_LEN |
+ ((ULONG)Port << COMBO_BIT_SHIFT));
+ for ( i = 0 ; i < Count ; i++) {
+ *Buffer++ = *ma;
+ ma = (PULONG)((PUCHAR)ma + COMBO_BYTE_OFFSET);
+ }
+
+ } else {
+
+ //
+ // Invalid QVA
+ //
+ KeBugCheck("Invalid QVA in READ_PORT_BUFFER_UCHAR\n");
+ }
+}
+
+
+VOID
+READ_PORT_BUFFER_USHORT(
+ volatile PUSHORT Port,
+ PUSHORT Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified port buffer address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data to.
+ Count - the number of shorts to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i, mv;
+ volatile PULONG ma;
+ ULONG word;
+
+ //
+ // The code gets really ugly if shorts are not aligned!
+ //
+ ASSERT(((ULONG)Port & 0x1) == 0x0);
+
+ if (IS_EISA_QVA(Port)) {
+
+ HalpMb;
+
+ //
+ // Shift the virtual address into position, and indicate that
+ // we want a word.
+ //
+ // The desired word enable is set automatically because the
+ // Jensen designers picked values which correspond exactly
+ // to the actual word addresses
+ //
+
+ ma = (volatile PULONG)
+ (EISA_WORD_LEN | ((ULONG)Port << EISA_BIT_SHIFT));
+
+ for ( i = 0 ; i < Count ; i++) {
+
+ //
+ // Determine which word it is that we want; the low
+ // order bit cannot be set.
+ //
+
+ word = (ULONG)ma & (0x2 << EISA_BIT_SHIFT);
+
+ //
+ // Get the longword value, which will only have one valid word
+ //
+
+ mv = *ma;
+
+ //
+ // Extract out the desired word
+ // The compiler should convert the multiplication
+ //
+
+ *Buffer++ = ((USHORT)(mv >> (8 * word)));
+
+
+ }
+ return;
+ }
+
+ //
+ // USHORT operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Port)) {
+
+ KeBugCheck("Invalid Combo QVA in READ_PORT_BUFFER_USHORT\n");
+ }
+
+ KeBugCheck("Invalid QVA in READ_PORT_BUFFER_USHORT\n");
+
+}
+
+
+VOID
+READ_PORT_BUFFER_ULONG(
+ volatile PULONG Port,
+ PULONG Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Read from the specified port address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data to.
+ Count - the number of longs to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i;
+ volatile PULONG ptr;
+
+ //
+ // We are assuming that the longword is aligned
+ //
+ ASSERT(((ULONG)Port & 0x3) == 0x0);
+
+ if (IS_EISA_QVA(Port)) {
+ HalpMb;
+ ptr = (volatile ULONG *) (EISA_LONG_LEN |
+ ((ULONG)Port << EISA_BIT_SHIFT));
+ for ( i = 0 ; i < Count ; i++) {
+ *Buffer++ = *ptr;
+ }
+ return;
+ }
+
+ //
+ // ULONG operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Port)) {
+
+ KeBugCheck("Invalid Combo QVA in READ_PORT_BUFFER_ULONG\n");
+ }
+
+ KeBugCheck("Invalid QVA in READ_PORT_BUFFER_ULONG\n");
+
+}
+
+
+VOID
+WRITE_PORT_BUFFER_UCHAR(
+ volatile PUCHAR Port,
+ PUCHAR Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified port buffer address.
+
+ If the Port and Buffer addresses are aligned with respect to each
+ other, we don't have to do a shift on each move - which would be a
+ bit faster. On the other hand, no one calls this routine, and it
+ would be more complicated to handle the two cases, so let it be.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data from.
+ Count - the number of bytes to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i, mv;
+ volatile PULONG ma;
+ ULONG byte;
+
+
+ if (IS_EISA_QVA(Port)) {
+
+ ma = (volatile PULONG) (EISA_BYTE_LEN |
+ ((ULONG)Port << EISA_BIT_SHIFT));
+
+ for ( i = 0 ; i < Count ; i++) {
+
+ //
+ // Determine which byte it is that we want to write to
+ // This changes with every byte written.
+ //
+
+ byte = (ULONG)ma & (0x3 << EISA_BIT_SHIFT);
+
+ //
+ // Move value into appropriate byte position in longword,
+ // and advance our position in the buffer.
+ // The compiler should convert the multiplication
+ //
+
+ mv = (ULONG)(*Buffer << (8 * byte));
+ Buffer++;
+
+ //
+ // send the lane shifted value to the EISA bus
+ //
+
+ *ma = mv;
+
+ }
+
+ HalpMb;
+ return;
+ }
+
+ if (IS_COMBO_QVA(Port)) {
+
+ ma = (volatile PULONG) (COMBO_BYTE_LEN |
+ ((ULONG)Port << COMBO_BIT_SHIFT));
+ for ( i = 0 ; i < Count ; i++) {
+ *ma = *Buffer++;
+ ma = (PULONG)((PUCHAR)ma + COMBO_BYTE_OFFSET);
+ }
+ HalpMb;
+ return;
+
+ }
+
+ //
+ // Invalid QVA
+ //
+ KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_UCHAR\n");
+
+}
+
+
+VOID
+WRITE_PORT_BUFFER_USHORT(
+ volatile PUSHORT Port,
+ PUSHORT Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the specified port buffer address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data from.
+ Count - the number of shorts to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i, mv;
+ volatile PULONG ma;
+ ULONG word;
+
+ //
+ // The code gets really ugly if shorts are not aligned!
+ //
+ ASSERT(((ULONG)Port & 0x1) == 0x0);
+
+ if (IS_EISA_QVA(Port)) {
+
+ ma = (volatile PULONG) (EISA_WORD_LEN |
+ ((ULONG)Port << EISA_BIT_SHIFT));
+
+ for ( i = 0 ; i < Count ; i++) {
+
+ //
+ // Determine which word it is that we want to write to
+ // This changes with every word written.
+ //
+
+ word = (ULONG)ma & (0x2 << EISA_BIT_SHIFT);
+
+ //
+ // Move value into appropriate word position in longword,
+ // and advance our position in the buffer.
+ // The compiler should convert the multiplication
+ //
+
+ mv = (ULONG)(*Buffer++ << (8 * word));
+
+ //
+ // send the lane shifted value to the EISA bus
+ //
+
+ *ma = mv;
+
+ }
+
+ HalpMb;
+ return;
+
+ }
+
+ //
+ // USHORT operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Port)) {
+
+ KeBugCheck("Invalid Combo QVA in WRITE_PORT_BUFFER_USHORT\n");
+ }
+
+ KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_USHORT\n");
+
+}
+
+
+VOID
+WRITE_PORT_BUFFER_ULONG(
+ volatile PULONG Port,
+ PULONG Buffer,
+ ULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ Write to teh specified port buffer address.
+
+Arguments:
+
+ Port - Supplies a pointer to the port in EISA space.
+ Buffer - the address of the buffer in memory to copy the data from.
+ Count - the number of longs to move.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i;
+ volatile PULONG ptr;
+
+ //
+ // We are assuming that the port address is long aligned
+ //
+ ASSERT(((ULONG)Port & 0x3) == 0x0);
+
+ if (IS_EISA_QVA(Port)) {
+ ptr = (volatile ULONG *) (EISA_LONG_LEN |
+ ((ULONG)Port << EISA_BIT_SHIFT));
+ for ( i = 0 ; i < Count ; i++) {
+ *ptr = *Buffer++;
+ }
+ HalpMb;
+ return;
+ }
+
+ //
+ // ULONG operations are not supported on the combo chip
+ //
+
+ if (IS_COMBO_QVA(Port)) {
+
+ KeBugCheck("Invalid Combo QVA in WRITE_PORT_BUFFER_ULONG\n");
+ }
+
+ KeBugCheck("Invalid QVA in WRITE_PORT_BUFFER_ULONG\n");
+
+}
+#endif // JENSEN