1 /*
2 * PROJECT: PCI IDE bus driver extension
3 * LICENSE: See COPYING in the top level directory
4 * PURPOSE: Miniport functions
5 * COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
6 */
7
8 #include "pciidex.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 /** @brief Global debugging level. Valid values are between 0 (Error) and 3 (Trace). */
14 ULONG PciIdeDebug = 0;
15
16 CODE_SEG("PAGE")
17 NTSTATUS
PciIdeXStartMiniport(_In_ PFDO_DEVICE_EXTENSION FdoExtension)18 PciIdeXStartMiniport(
19 _In_ PFDO_DEVICE_EXTENSION FdoExtension)
20 {
21 PPCIIDEX_DRIVER_EXTENSION DriverExtension;
22 NTSTATUS Status;
23
24 PAGED_CODE();
25
26 if (FdoExtension->MiniportStarted)
27 return STATUS_SUCCESS;
28
29 DPRINT("Starting miniport\n");
30
31 DriverExtension = IoGetDriverObjectExtension(FdoExtension->DriverObject,
32 FdoExtension->DriverObject);
33 ASSERT(DriverExtension);
34
35 FdoExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
36 FdoExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
37 Status = DriverExtension->HwGetControllerProperties(FdoExtension->MiniControllerExtension,
38 &FdoExtension->Properties);
39 if (!NT_SUCCESS(Status))
40 return Status;
41
42 FdoExtension->MiniportStarted = TRUE;
43 return STATUS_SUCCESS;
44 }
45
46 CODE_SEG("PAGE")
47 IDE_CHANNEL_STATE
PciIdeXChannelState(_In_ PFDO_DEVICE_EXTENSION FdoExtension,_In_ ULONG Channel)48 PciIdeXChannelState(
49 _In_ PFDO_DEVICE_EXTENSION FdoExtension,
50 _In_ ULONG Channel)
51 {
52 PCIIDE_CHANNEL_ENABLED MiniportChannelEnabled;
53
54 PAGED_CODE();
55
56 MiniportChannelEnabled = FdoExtension->Properties.PciIdeChannelEnabled;
57 if (MiniportChannelEnabled)
58 return MiniportChannelEnabled(FdoExtension->MiniControllerExtension, Channel);
59
60 return ChannelStateUnknown;
61 }
62
63 /**
64 * @brief Prints the given string with printf-like formatting to the kernel debugger.
65 * @param[in] DebugPrintLevel Level of the debug message.
66 * Valid values are between 0 (Error) and 3 (Trace).
67 * @param[in] DebugMessage Format of the string/arguments.
68 * @param[in] ... Variable number of arguments matching the format
69 * specified in \a DebugMessage.
70 * @sa PciIdeDebug
71 */
72 VOID
PciIdeXDebugPrint(_In_ ULONG DebugPrintLevel,_In_z_ _Printf_format_string_ PCCHAR DebugMessage,...)73 PciIdeXDebugPrint(
74 _In_ ULONG DebugPrintLevel,
75 _In_z_ _Printf_format_string_ PCCHAR DebugMessage,
76 ...)
77 {
78 va_list ap;
79
80 /* Check if we can print anything */
81 if (DebugPrintLevel <= PciIdeDebug)
82 DebugPrintLevel = 0;
83
84 va_start(ap, DebugMessage);
85 vDbgPrintEx(DPFLTR_PCIIDE_ID, DebugPrintLevel, DebugMessage, ap);
86 va_end(ap);
87 }
88
89 /* May be called at IRQL <= DISPATCH_LEVEL */
90 NTSTATUS
91 NTAPI
PciIdeXGetBusData(_In_ PVOID DeviceExtension,_Out_writes_bytes_all_ (BufferLength)PVOID Buffer,_In_ ULONG ConfigDataOffset,_In_ ULONG BufferLength)92 PciIdeXGetBusData(
93 _In_ PVOID DeviceExtension,
94 _Out_writes_bytes_all_(BufferLength) PVOID Buffer,
95 _In_ ULONG ConfigDataOffset,
96 _In_ ULONG BufferLength)
97 {
98 PFDO_DEVICE_EXTENSION FdoExtension;
99 ULONG BytesRead;
100
101 DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
102 DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
103
104 FdoExtension = CONTAINING_RECORD(DeviceExtension,
105 FDO_DEVICE_EXTENSION,
106 MiniControllerExtension);
107
108 BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
109 PCI_WHICHSPACE_CONFIG,
110 Buffer,
111 ConfigDataOffset,
112 BufferLength);
113 if (BytesRead != BufferLength)
114 return STATUS_UNSUCCESSFUL;
115
116 return STATUS_SUCCESS;
117 }
118
119 /* May be called at IRQL <= DISPATCH_LEVEL */
120 NTSTATUS
121 NTAPI
PciIdeXSetBusData(_In_ PVOID DeviceExtension,_In_reads_bytes_ (BufferLength)PVOID Buffer,_In_reads_bytes_ (BufferLength)PVOID DataMask,_In_ ULONG ConfigDataOffset,_In_ ULONG BufferLength)122 PciIdeXSetBusData(
123 _In_ PVOID DeviceExtension,
124 _In_reads_bytes_(BufferLength) PVOID Buffer,
125 _In_reads_bytes_(BufferLength) PVOID DataMask,
126 _In_ ULONG ConfigDataOffset,
127 _In_ ULONG BufferLength)
128 {
129 PFDO_DEVICE_EXTENSION FdoExtension;
130 ULONG i, BytesWritten;
131 PUCHAR CurrentBuffer;
132 KIRQL OldIrql;
133 NTSTATUS Status;
134
135 DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
136 DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
137
138 CurrentBuffer = ExAllocatePoolWithTag(NonPagedPool, BufferLength, TAG_PCIIDEX);
139 if (!CurrentBuffer)
140 return STATUS_INSUFFICIENT_RESOURCES;
141
142 FdoExtension = CONTAINING_RECORD(DeviceExtension,
143 FDO_DEVICE_EXTENSION,
144 MiniControllerExtension);
145
146 KeAcquireSpinLock(&FdoExtension->BusDataLock, &OldIrql);
147
148 Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
149 if (!NT_SUCCESS(Status))
150 goto Cleanup;
151
152 for (i = 0; i < BufferLength; i++)
153 {
154 CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) |
155 (((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
156 }
157
158 BytesWritten = (*FdoExtension->BusInterface.SetBusData)(FdoExtension->BusInterface.Context,
159 PCI_WHICHSPACE_CONFIG,
160 CurrentBuffer,
161 ConfigDataOffset,
162 BufferLength);
163 if (BytesWritten != BufferLength)
164 Status = STATUS_UNSUCCESSFUL;
165 else
166 Status = STATUS_SUCCESS;
167
168 Cleanup:
169 KeReleaseSpinLock(&FdoExtension->BusDataLock, OldIrql);
170
171 ExFreePoolWithTag(CurrentBuffer, TAG_PCIIDEX);
172 return Status;
173 }
174