1 #include "miniport.h"
2 #include "BusLogic958.h" // includes scsi.h
3 #include "wmistr.h" // WMI definitions
4
5 #include "BT958dt.h"
6
7 #define BT958Wmi_MofResourceName L"MofResource"
8
9 #define BT958_SETUP_GUID_INDEX 0
10
11 GUID BT958WmiExtendedSetupInfoGuid = BT958Wmi_ExtendedSetupInfo_Guid;
12
13 UCHAR
14 BT958ReadExtendedSetupInfo
15 (
16 IN PHW_DEVICE_EXTENSION HwDeviceExtension,
17 OUT PUCHAR Buffer
18 );
19
20 BOOLEAN
21 BT958QueryWmiDataBlock
22 (
23 IN PVOID Context,
24 IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
25 IN ULONG GuidIndex,
26 IN ULONG InstanceIndex,
27 IN ULONG InstanceCount,
28 IN OUT PULONG InstanceLengthArray,
29 IN ULONG OutBufferSize,
30 OUT PUCHAR Buffer
31 );
32
33 UCHAR
34 BT958QueryWmiRegInfo
35 (
36 IN PVOID Context,
37 IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
38 OUT PWCHAR *MofResourceName
39 );
40
41 SCSIWMIGUIDREGINFO BT958GuidList[] =
42 {
43 {&BT958WmiExtendedSetupInfoGuid,
44 1,
45 0
46 },
47 };
48
49 #define BT958GuidCount (sizeof(BT958GuidList) / sizeof(SCSIWMIGUIDREGINFO))
50
51
BT958WmiInitialize(IN PHW_DEVICE_EXTENSION HwDeviceExtension)52 void BT958WmiInitialize(
53 IN PHW_DEVICE_EXTENSION HwDeviceExtension
54 )
55 {
56 PSCSI_WMILIB_CONTEXT WmiLibContext;
57
58 WmiLibContext = &HwDeviceExtension->WmiLibContext;
59
60 WmiLibContext->GuidList = BT958GuidList;
61 WmiLibContext->GuidCount = BT958GuidCount;
62 WmiLibContext->QueryWmiRegInfo = BT958QueryWmiRegInfo;
63 WmiLibContext->QueryWmiDataBlock = BT958QueryWmiDataBlock;
64 WmiLibContext->SetWmiDataItem = NULL;
65 WmiLibContext->SetWmiDataBlock = NULL;
66 WmiLibContext->WmiFunctionControl = NULL;
67 WmiLibContext->ExecuteWmiMethod = NULL;
68 }
69
70
71
72 BOOLEAN
BT958WmiSrb(IN PHW_DEVICE_EXTENSION HwDeviceExtension,IN OUT PSCSI_WMI_REQUEST_BLOCK Srb)73 BT958WmiSrb(
74 IN PHW_DEVICE_EXTENSION HwDeviceExtension,
75 IN OUT PSCSI_WMI_REQUEST_BLOCK Srb
76 )
77 /*++
78
79 Routine Description:
80
81 Process an SRB_FUNCTION_WMI request packet.
82
83 This routine is called from the SCSI port driver synchronized with the
84 kernel via BT958StartIo. On completion of WMI processing, the SCSI
85 port driver is notified that the adapter can take another request, if
86 any are available.
87
88 Arguments:
89
90 HwDeviceExtension - HBA miniport driver's adapter data storage.
91
92 Srb - IO request packet.
93
94 Return Value:
95
96 Value to return to BT958StartIo caller. Always TRUE.
97
98 --*/
99 {
100 UCHAR status;
101 SCSIWMI_REQUEST_CONTEXT requestContext;
102 ULONG retSize;
103 BOOLEAN pending;
104
105 // Validate our assumptions.
106 ASSERT(Srb->Function == SRB_FUNCTION_WMI);
107 ASSERT(Srb->Length == sizeof(SCSI_WMI_REQUEST_BLOCK));
108 ASSERT(Srb->DataTransferLength >= sizeof(ULONG));
109 ASSERT(Srb->DataBuffer);
110
111 // Check if the WMI SRB is targeted for the adapter or one of the disks
112 if (!(Srb->WMIFlags & SRB_WMI_FLAGS_ADAPTER_REQUEST))
113 {
114
115 // This is targeted to one of the disks, since there are no per disk
116 // wmi information we return an error. Note that if there was per
117 // disk information, then you'd likely have a differen WmiLibContext
118 // and a different set of guids.
119 Srb->DataTransferLength = 0;
120 Srb->SrbStatus = SRB_STATUS_SUCCESS;
121
122 }
123 else
124 {
125 // Process the incoming WMI request.
126 pending = ScsiPortWmiDispatchFunction(&HwDeviceExtension->WmiLibContext,
127 Srb->WMISubFunction,
128 HwDeviceExtension,
129 &requestContext,
130 Srb->DataPath,
131 Srb->DataTransferLength,
132 Srb->DataBuffer);
133
134 // We assume that the wmi request will never pend so that we can
135 // allocate the requestContext from stack. If the WMI request could
136 // ever pend then we'd need to allocate the request context from
137 // the SRB extension.
138 //
139 ASSERT(! pending);
140
141 retSize = ScsiPortWmiGetReturnSize(&requestContext);
142 status = ScsiPortWmiGetReturnStatus(&requestContext);
143
144 // We can do this since we assume it is done synchronously
145 Srb->DataTransferLength = retSize;
146
147 //
148 // Adapter ready for next request.
149 //
150
151 Srb->SrbStatus = status;
152 }
153
154 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
155 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
156
157 return TRUE;
158 }
159
160
161
162 BOOLEAN
BT958QueryWmiDataBlock(IN PVOID Context,IN PSCSIWMI_REQUEST_CONTEXT RequestContext,IN ULONG GuidIndex,IN ULONG InstanceIndex,IN ULONG InstanceCount,IN OUT PULONG InstanceLengthArray,IN ULONG OutBufferSize,OUT PUCHAR Buffer)163 BT958QueryWmiDataBlock(
164 IN PVOID Context,
165 IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
166 IN ULONG GuidIndex,
167 IN ULONG InstanceIndex,
168 IN ULONG InstanceCount,
169 IN OUT PULONG InstanceLengthArray,
170 IN ULONG OutBufferSize,
171 OUT PUCHAR Buffer
172 )
173 /*++
174
175 Routine Description:
176
177 This routine is a callback into the miniport to query for the contents of
178 one or more instances of a data block. This callback may be called with
179 an output buffer that is too small to return all of the data queried.
180 In this case the callback is responsible to report the correct output
181 buffer size needed.
182
183 If the request can be completed immediately without pending,
184 ScsiPortWmiPostProcess should be called from within this callback and
185 FALSE returned.
186
187 If the request cannot be completed within this callback then TRUE should
188 be returned. Once the pending operations are finished the miniport should
189 call ScsiPortWmiPostProcess and then complete the srb.
190
191 Arguments:
192
193 DeviceContext is a caller specified context value originally passed to
194 ScsiPortWmiDispatchFunction.
195
196 RequestContext is a context associated with the srb being processed.
197
198 GuidIndex is the index into the list of guids provided when the
199 miniport registered
200
201 InstanceIndex is the index that denotes first instance of the data block
202 is being queried.
203
204 InstanceCount is the number of instances expected to be returned for
205 the data block.
206
207 InstanceLengthArray is a pointer to an array of ULONG that returns the
208 lengths of each instance of the data block. This may be NULL when
209 there is not enough space in the output buffer to fufill the request.
210 In this case the miniport should call ScsiPortWmiPostProcess with
211 a status of SRB_STATUS_DATA_OVERRUN and the size of the output buffer
212 needed to fufill the request.
213
214 BufferAvail on entry has the maximum size available to write the data
215 blocks in the output buffer. If the output buffer is not large enough
216 to return all of the data blocks then the miniport should call
217 ScsiPortWmiPostProcess with a status of SRB_STATUS_DATA_OVERRUN
218 and the size of the output buffer needed to fufill the request.
219
220 Buffer on return is filled with the returned data blocks. Note that each
221 instance of the data block must be aligned on a 8 byte boundry. This
222 may be NULL when there is not enough space in the output buffer to
223 fufill the request. In this case the miniport should call
224 ScsiPortWmiPostProcess with a status of SRB_STATUS_DATA_OVERRUN and
225 the size of the output buffer needed to fufill the request.
226
227
228 Return Value:
229
230 TRUE if request is pending else FALSE
231
232 --*/
233 {
234 PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION)Context;
235 ULONG size = 0;
236 UCHAR status;
237
238 //
239 // Only ever registers 1 instance per guid
240 ASSERT((InstanceIndex == 0) &&
241 (InstanceCount == 1));
242
243 switch (GuidIndex)
244 {
245 case BT958_SETUP_GUID_INDEX:
246 {
247 size = sizeof(BT958ExtendedSetupInfo)-1;
248 if (OutBufferSize < size)
249 {
250 //
251 // The buffer passed to return the data is too small
252 //
253 status = SRB_STATUS_DATA_OVERRUN;
254 break;
255 }
256
257 if ( !BT958ReadExtendedSetupInfo(HwDeviceExtension,
258 Buffer))
259 {
260 ASSERT(FALSE);
261 size = 0;
262 status = SRB_STATUS_ERROR;
263 }
264 else
265 {
266 *InstanceLengthArray = size;
267 status = SRB_STATUS_SUCCESS;
268 }
269 break;
270 }
271
272 default:
273 {
274 status = SRB_STATUS_ERROR;
275 }
276 }
277
278 ScsiPortWmiPostProcess( RequestContext,
279 status,
280 size);
281
282 return status;
283 }
284
285 UCHAR
BT958QueryWmiRegInfo(IN PVOID Context,IN PSCSIWMI_REQUEST_CONTEXT RequestContext,OUT PWCHAR * MofResourceName)286 BT958QueryWmiRegInfo(
287 IN PVOID Context,
288 IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
289 OUT PWCHAR *MofResourceName
290 )
291 /*++
292
293 Routine Description:
294
295 This routine is a callback into the driver to retrieve information about
296 the guids being registered.
297
298 Implementations of this routine may be in paged memory
299
300 Arguments:
301
302 DeviceObject is the device whose registration information is needed
303
304 *RegFlags returns with a set of flags that describe all of the guids being
305 registered for this device. If the device wants enable and disable
306 collection callbacks before receiving queries for the registered
307 guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
308 returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
309 the instance name is determined from the PDO associated with the
310 device object. Note that the PDO must have an associated devnode. If
311 WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
312 name for the device. These flags are ORed into the flags specified
313 by the GUIDREGINFO for each guid.
314
315 InstanceName returns with the instance name for the guids if
316 WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
317 caller will call ExFreePool with the buffer returned.
318
319 *RegistryPath returns with the registry path of the driver. This is
320 required
321
322 *MofResourceName returns with the name of the MOF resource attached to
323 the binary file. If the driver does not have a mof resource attached
324 then this can be returned as NULL.
325
326 *Pdo returns with the device object for the PDO associated with this
327 device if the WMIREG_FLAG_INSTANCE_PDO flag is returned in
328 *RegFlags.
329
330 Return Value:
331
332 status
333
334 --*/
335 {
336 *MofResourceName = BT958Wmi_MofResourceName;
337 return SRB_STATUS_SUCCESS;
338 }
339
340
341 UCHAR
BT958ReadExtendedSetupInfo(IN PHW_DEVICE_EXTENSION HwDeviceExtension,OUT PUCHAR Buffer)342 BT958ReadExtendedSetupInfo(
343 IN PHW_DEVICE_EXTENSION HwDeviceExtension,
344 OUT PUCHAR Buffer
345 )
346 /*++
347
348 Routine Description:
349
350 Read the adapter setup information into the supplied buffer. The buffer
351 must be RM_CFG_MAX_SIZE (255) bytes large.
352
353 Arguments:
354
355 HwDeviceExtension - HBA miniport driver's adapter data storage.
356
357 Buffer - Buffer to hold adapter's setup information structure [manual 5-10].
358
359 Return Value:
360
361 TRUE on success, FALSE on failure.
362
363 --*/
364 {
365 UCHAR numberOfBytes = sizeof(BT958ExtendedSetupInfo)-1;
366
367 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
368 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
369 BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
370 BusLogic_RequestedReplyLength_T RequestedReplyLength = sizeof(ExtendedSetupInformation);
371 BOOLEAN Result = TRUE;
372
373 BusLogic_WmiExtendedSetupInformation_T WmiExtendedSetupInfo;
374 PUCHAR SourceBuf = (PUCHAR) &WmiExtendedSetupInfo;
375
376
377 //
378 // Issue the Inquire Extended Setup Information command. Only genuine
379 // BusLogic Host Adapters and TRUE clones support this command. Adaptec 1542C
380 // series Host Adapters that respond to the Geometry Register I/O port will
381 // fail this command.
382 RequestedReplyLength = sizeof(ExtendedSetupInformation);
383 if (BusLogic_Command(HostAdapter,
384 BusLogic_InquireExtendedSetupInformation,
385 &RequestedReplyLength,
386 sizeof(RequestedReplyLength),
387 &ExtendedSetupInformation,
388 sizeof(ExtendedSetupInformation))
389 != sizeof(ExtendedSetupInformation))
390 {
391 Result = FALSE;
392 }
393
394 WmiExtendedSetupInfo.BusType = ExtendedSetupInformation.BusType;
395 WmiExtendedSetupInfo.BIOS_Address = ExtendedSetupInformation.BIOS_Address;
396 WmiExtendedSetupInfo.ScatterGatherLimit = ExtendedSetupInformation.ScatterGatherLimit;
397 WmiExtendedSetupInfo.MailboxCount = ExtendedSetupInformation.MailboxCount;
398 WmiExtendedSetupInfo.BaseMailboxAddress = ExtendedSetupInformation.BaseMailboxAddress;
399 WmiExtendedSetupInfo.FastOnEISA = ExtendedSetupInformation.Misc.FastOnEISA;
400 WmiExtendedSetupInfo.LevelSensitiveInterrupt = ExtendedSetupInformation.Misc.LevelSensitiveInterrupt;
401 WmiExtendedSetupInfo.FirmwareRevision[0] = ExtendedSetupInformation.FirmwareRevision[0];
402 WmiExtendedSetupInfo.FirmwareRevision[1] = ExtendedSetupInformation.FirmwareRevision[1];
403 WmiExtendedSetupInfo.FirmwareRevision[2] = ExtendedSetupInformation.FirmwareRevision[2];
404 WmiExtendedSetupInfo.HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
405 WmiExtendedSetupInfo.HostDifferentialSCSI= ExtendedSetupInformation.HostDifferentialSCSI;
406 WmiExtendedSetupInfo.HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
407 WmiExtendedSetupInfo.HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
408 WmiExtendedSetupInfo.HostSmartTermination= ExtendedSetupInformation.HostSmartTermination;
409
410 for (; numberOfBytes; numberOfBytes--)
411 {
412 *Buffer++ = *SourceBuf++;
413 }
414 return TRUE;
415 }
416
417