xref: /reactos/drivers/storage/port/buslogic/wmi.c (revision 1734f297)
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 
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
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
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
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
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