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