summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halmca/i386/ixmcabus.c
blob: 82cc981cd436e4221b1ff8f9d978dafecbfe2d69 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*++
Copyright (c) 1989  Microsoft Corporation

Module Name:

    ixmcabus.c

Abstract:

Author:

Environment:

Revision History:

--*/

#include "halp.h"

extern KSPIN_LOCK HalpSystemHardwareLock;

ULONG
HalpGetPosData (
    IN PBUS_HANDLER BusHandler,
    IN PBUS_HANDLER RootHandler,
    IN ULONG SlotNumber,
    IN PVOID Buffer,
    IN ULONG DOffset,
    IN ULONG Length
    )
{
    ULONG DataLength = 0;
    ULONG Offset = 0;
    ULONG Index = 0;
    PUCHAR DataBuffer = Buffer;
    PVOID McaRegisterBase = 0;
    PUCHAR PosBase;
    KIRQL Irql;
    PHYSICAL_ADDRESS BusAddress;
    BOOLEAN  Status;
    ULONG   AddressSpace;


    if (DOffset != 0) {
        // bugbug: should support this
        return 0;
    }

    //
    // Translate the Mca Base port for this MCA bus
    //

    BusAddress.LowPart = (ULONG) McaRegisterBase;
    BusAddress.HighPart = 0;
    AddressSpace = 1;           // I/O space
    Status = BusHandler->TranslateBusAddress(
                    BusHandler,
                    RootHandler,
                    BusAddress,
                    &AddressSpace,                      // I/O Space
                    &BusAddress);

    if (Status == FALSE  ||  AddressSpace != 1) {
        return 0;
    }

    McaRegisterBase = (PVOID) BusAddress.LowPart;

    PosBase = (PUCHAR) &((PMCA_CONTROL) McaRegisterBase)->Pos;

    Irql = KfAcquireSpinLock(&HalpSystemHardwareLock);

    //
    //  Place the specified adapter into setup mode.
    //

    WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup,
                      (UCHAR) ( MCA_ADAPTER_SETUP_ON | SlotNumber ));

    while (DataLength < Length && DataLength < 6) {
        DataBuffer[DataLength] = READ_PORT_UCHAR( PosBase + DataLength );
        DataLength++;
    }

    while (DataLength < Length) {

        WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT)
            PosBase)->SubaddressExtensionLsb, (UCHAR) Index);

        WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT)
            PosBase)->SubaddressExtensionMsb, (UCHAR) (Index >> 8));

        DataBuffer[Index + 6] = READ_PORT_UCHAR(
            (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData2);

        DataLength++;

        if (DataLength < Length) {
            Offset = DataLength + ((Length - DataLength) / 2);
            DataBuffer[Offset] = READ_PORT_UCHAR(
                (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData3);
            DataLength++;
            Index++;
        }
    }

    //
    //  Disable adapter setup.
    //

    WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup,
                  (UCHAR) ( MCA_ADAPTER_SETUP_OFF ));


    KfReleaseSpinLock( &HalpSystemHardwareLock, Irql );
    return DataLength;
}