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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
#include "miniport.h"
#include "BusLogic958.h"        // includes scsi.h
#include "wmistr.h"             // WMI definitions

#include "BT958dt.h"

#define BT958Wmi_MofResourceName        L"MofResource"

#define BT958_SETUP_GUID_INDEX 0

GUID BT958WmiExtendedSetupInfoGuid = BT958Wmi_ExtendedSetupInfo_Guid;

UCHAR
BT958ReadExtendedSetupInfo
(
   IN  PHW_DEVICE_EXTENSION HwDeviceExtension,
   OUT PUCHAR               Buffer
);

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
);

UCHAR
BT958QueryWmiRegInfo
(
    IN PVOID Context,
    IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
    OUT PWCHAR *MofResourceName
);

SCSIWMIGUIDREGINFO BT958GuidList[] =
{
   {&BT958WmiExtendedSetupInfoGuid,
    1,
    0
   },
};

#define BT958GuidCount (sizeof(BT958GuidList) / sizeof(SCSIWMIGUIDREGINFO))


void BT958WmiInitialize(
    IN PHW_DEVICE_EXTENSION HwDeviceExtension
    )
{
    PSCSI_WMILIB_CONTEXT WmiLibContext;

    WmiLibContext = &HwDeviceExtension->WmiLibContext;

    WmiLibContext->GuidList = BT958GuidList;
    WmiLibContext->GuidCount = BT958GuidCount;
    WmiLibContext->QueryWmiRegInfo = BT958QueryWmiRegInfo;
    WmiLibContext->QueryWmiDataBlock = BT958QueryWmiDataBlock;
    WmiLibContext->SetWmiDataItem = NULL;
    WmiLibContext->SetWmiDataBlock = NULL;
    WmiLibContext->WmiFunctionControl = NULL;
    WmiLibContext->ExecuteWmiMethod = NULL;
}



BOOLEAN
BT958WmiSrb(
    IN     PHW_DEVICE_EXTENSION    HwDeviceExtension,
    IN OUT PSCSI_WMI_REQUEST_BLOCK Srb
    )
/*++

Routine Description:

   Process an SRB_FUNCTION_WMI request packet.

   This routine is called from the SCSI port driver synchronized with the
   kernel via BT958StartIo.   On completion of WMI processing, the SCSI
   port driver is notified that the adapter can take another request,  if
   any are available.

Arguments:

   HwDeviceExtension - HBA miniport driver's adapter data storage.

   Srb               - IO request packet.

Return Value:

   Value to return to BT958StartIo caller.   Always TRUE.

--*/
{
   UCHAR status;
   SCSIWMI_REQUEST_CONTEXT requestContext;
   ULONG retSize;
   BOOLEAN pending;

   // Validate our assumptions.
   ASSERT(Srb->Function == SRB_FUNCTION_WMI);
   ASSERT(Srb->Length == sizeof(SCSI_WMI_REQUEST_BLOCK));
   ASSERT(Srb->DataTransferLength >= sizeof(ULONG));
   ASSERT(Srb->DataBuffer);

   // Check if the WMI SRB is targeted for the adapter or one of the disks
   if (!(Srb->WMIFlags & SRB_WMI_FLAGS_ADAPTER_REQUEST))
   {

      // This is targeted to one of the disks, since there are no per disk
      // wmi information we return an error. Note that if there was per
      // disk information, then you'd likely have a differen WmiLibContext
      // and a different set of guids.
      Srb->DataTransferLength = 0;
      Srb->SrbStatus = SRB_STATUS_SUCCESS;

   }
   else
   {
       // Process the incoming WMI request.
       pending = ScsiPortWmiDispatchFunction(&HwDeviceExtension->WmiLibContext,
                                                Srb->WMISubFunction,
                                                HwDeviceExtension,
                                                &requestContext,
                                                Srb->DataPath,
                                                Srb->DataTransferLength,
                                                Srb->DataBuffer);

       // We assume that the wmi request will never pend so that we can
       // allocate the requestContext from stack. If the WMI request could
       // ever pend then we'd need to allocate the request context from
       // the SRB extension.
       //
       ASSERT(! pending);

       retSize =  ScsiPortWmiGetReturnSize(&requestContext);
       status =  ScsiPortWmiGetReturnStatus(&requestContext);

       // We can do this since we assume it is done synchronously
       Srb->DataTransferLength = retSize;

       //
       // Adapter ready for next request.
       //

       Srb->SrbStatus = status;
   }

   ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
   ScsiPortNotification(NextRequest,     HwDeviceExtension, NULL);

   return TRUE;
}



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
    )
/*++

Routine Description:

    This routine is a callback into the miniport to query for the contents of
    one or more instances of a data block. This callback may be called with
    an output buffer that is too small to return all of the data queried.
    In this case the callback is responsible to report the correct output
        buffer size needed.

    If the request can be completed immediately without pending,
        ScsiPortWmiPostProcess should be called from within this callback and
    FALSE returned.

    If the request cannot be completed within this callback then TRUE should
    be returned. Once the pending operations are finished the miniport should
    call ScsiPortWmiPostProcess and then complete the srb.

Arguments:

    DeviceContext is a caller specified context value originally passed to
        ScsiPortWmiDispatchFunction.

    RequestContext is a context associated with the srb being processed.

    GuidIndex is the index into the list of guids provided when the
        miniport registered

    InstanceIndex is the index that denotes first instance of the data block
        is being queried.

    InstanceCount is the number of instances expected to be returned for
        the data block.

    InstanceLengthArray is a pointer to an array of ULONG that returns the
        lengths of each instance of the data block. This may be NULL when
        there is not enough space in the output buffer to fufill the request.
        In this case the miniport should call ScsiPortWmiPostProcess with
        a status of SRB_STATUS_DATA_OVERRUN and the size of the output buffer
        needed to fufill the request.

    BufferAvail on entry has the maximum size available to write the data
        blocks in the output buffer. If the output buffer is not large enough
        to return all of the data blocks then the miniport should call
        ScsiPortWmiPostProcess with a status of SRB_STATUS_DATA_OVERRUN
        and the size of the output buffer needed to fufill the request.

    Buffer on return is filled with the returned data blocks. Note that each
        instance of the data block must be aligned on a 8 byte boundry. This
        may be NULL when there is not enough space in the output buffer to
        fufill the request. In this case the miniport should call
        ScsiPortWmiPostProcess with a status of SRB_STATUS_DATA_OVERRUN and
        the size of the output buffer needed to fufill the request.


Return Value:

    TRUE if request is pending else FALSE

--*/
{
    PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION)Context;
    ULONG size = 0;
    UCHAR status;

    //
    // Only ever registers 1 instance per guid
    ASSERT((InstanceIndex == 0) &&
           (InstanceCount == 1));

    switch (GuidIndex)
    {
        case BT958_SETUP_GUID_INDEX:
        {
            size = sizeof(BT958ExtendedSetupInfo)-1;
            if (OutBufferSize < size)
            {
                //
                // The buffer passed to return the data is too small
                //
                status = SRB_STATUS_DATA_OVERRUN;
                break;
            }

            if ( !BT958ReadExtendedSetupInfo(HwDeviceExtension,
                                     Buffer))
            {
                ASSERT(FALSE);
                size = 0;
                status = SRB_STATUS_ERROR;
            }
			else
			{
                *InstanceLengthArray = size;
                status = SRB_STATUS_SUCCESS;
            }
            break;
        }

        default:
        {
            status = SRB_STATUS_ERROR;
        }
    }

    ScsiPortWmiPostProcess(       RequestContext,
                                  status,
                                  size);

    return status;
}

UCHAR
BT958QueryWmiRegInfo(
    IN PVOID Context,
    IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
    OUT PWCHAR *MofResourceName
    )
/*++

Routine Description:

    This routine is a callback into the driver to retrieve information about
    the guids being registered.

    Implementations of this routine may be in paged memory

Arguments:

    DeviceObject is the device whose registration information is needed

    *RegFlags returns with a set of flags that describe all of the guids being
        registered for this device. If the device wants enable and disable
        collection callbacks before receiving queries for the registered
        guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
        returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
        the instance name is determined from the PDO associated with the
        device object. Note that the PDO must have an associated devnode. If
        WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
        name for the device. These flags are ORed into the flags specified
        by the GUIDREGINFO for each guid.

    InstanceName returns with the instance name for the guids if
        WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
        caller will call ExFreePool with the buffer returned.

    *RegistryPath returns with the registry path of the driver. This is
        required

    *MofResourceName returns with the name of the MOF resource attached to
        the binary file. If the driver does not have a mof resource attached
        then this can be returned as NULL.

    *Pdo returns with the device object for the PDO associated with this
        device if the WMIREG_FLAG_INSTANCE_PDO flag is returned in
        *RegFlags.

Return Value:

    status

--*/
{
    *MofResourceName = BT958Wmi_MofResourceName;
    return SRB_STATUS_SUCCESS;
}


UCHAR
BT958ReadExtendedSetupInfo(
   IN  PHW_DEVICE_EXTENSION HwDeviceExtension,
   OUT PUCHAR               Buffer
   )
/*++

Routine Description:

   Read the adapter setup information into the supplied buffer.  The buffer
   must be RM_CFG_MAX_SIZE (255) bytes large.

Arguments:

   HwDeviceExtension - HBA miniport driver's adapter data storage.

   Buffer - Buffer to hold adapter's setup information structure [manual 5-10].

Return Value:

   TRUE on success, FALSE on failure.

--*/
{
   UCHAR numberOfBytes = sizeof(BT958ExtendedSetupInfo)-1;

   PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
   BusLogic_RequestedReplyLength_T RequestedReplyLength = sizeof(ExtendedSetupInformation);<--- RequestedReplyLength is initialized
   BOOLEAN Result = TRUE;

   BusLogic_WmiExtendedSetupInformation_T WmiExtendedSetupInfo;
   PUCHAR SourceBuf = (PUCHAR) &WmiExtendedSetupInfo;


   //
   //  Issue the Inquire Extended Setup Information command.  Only genuine
   //  BusLogic Host Adapters and TRUE clones support this command.  Adaptec 1542C
   //  series Host Adapters that respond to the Geometry Register I/O port will
   //  fail this command.
   RequestedReplyLength = sizeof(ExtendedSetupInformation);<--- RequestedReplyLength is overwritten
   if (BusLogic_Command(HostAdapter,
					   BusLogic_InquireExtendedSetupInformation,
					   &RequestedReplyLength,
					   sizeof(RequestedReplyLength),
					   &ExtendedSetupInformation,
					   sizeof(ExtendedSetupInformation))
      != sizeof(ExtendedSetupInformation))
   {
     Result = FALSE;
   }

   WmiExtendedSetupInfo.BusType      =        ExtendedSetupInformation.BusType;
   WmiExtendedSetupInfo.BIOS_Address =        ExtendedSetupInformation.BIOS_Address;
   WmiExtendedSetupInfo.ScatterGatherLimit =  ExtendedSetupInformation.ScatterGatherLimit;
   WmiExtendedSetupInfo.MailboxCount       =  ExtendedSetupInformation.MailboxCount;
   WmiExtendedSetupInfo.BaseMailboxAddress =  ExtendedSetupInformation.BaseMailboxAddress;
   WmiExtendedSetupInfo.FastOnEISA         =  ExtendedSetupInformation.Misc.FastOnEISA;
   WmiExtendedSetupInfo.LevelSensitiveInterrupt = ExtendedSetupInformation.Misc.LevelSensitiveInterrupt;
   WmiExtendedSetupInfo.FirmwareRevision[0] = ExtendedSetupInformation.FirmwareRevision[0];
   WmiExtendedSetupInfo.FirmwareRevision[1] = ExtendedSetupInformation.FirmwareRevision[1];
   WmiExtendedSetupInfo.FirmwareRevision[2] = ExtendedSetupInformation.FirmwareRevision[2];
   WmiExtendedSetupInfo.HostWideSCSI        = ExtendedSetupInformation.HostWideSCSI;
   WmiExtendedSetupInfo.HostDifferentialSCSI= ExtendedSetupInformation.HostDifferentialSCSI;
   WmiExtendedSetupInfo.HostSupportsSCAM    = ExtendedSetupInformation.HostSupportsSCAM;
   WmiExtendedSetupInfo.HostUltraSCSI       = ExtendedSetupInformation.HostUltraSCSI;
   WmiExtendedSetupInfo.HostSmartTermination= ExtendedSetupInformation.HostSmartTermination;

   for (; numberOfBytes; numberOfBytes--)
   {
      *Buffer++ = *SourceBuf++;
   }
   return TRUE;
}