@@ -220,35 +220,247 @@ USHORT CopyBufferToAnsiString(void *_pDest, const void *_pSrc, const char delimi
220220
221221BOOLEAN VioScsiReadRegistryParameter (IN PVOID DeviceExtension , IN PUCHAR ValueName , IN LONG offset )
222222{
223- BOOLEAN Ret = FALSE;
224- ULONG Len = sizeof (ULONG );
225- UCHAR * pBuf = NULL ;
226- PADAPTER_EXTENSION adaptExt ;
223+ BOOLEAN bReadResult = FALSE;
224+ BOOLEAN bUseAltPerHbaRegRead = FALSE;
225+ ULONG pBufferLength = sizeof (ULONG );
226+ UCHAR * pBuffer = NULL ;
227+ PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION )DeviceExtension ;
228+ ULONG spgspn_rc , i , j ;
229+ STOR_ADDRESS HwAddress = {0 };
230+ PSTOR_ADDRESS pHwAddress = & HwAddress ;
231+ CHAR valname_as_str [64 ] = {0 };
232+ CHAR hba_id_as_str [4 ] = {0 };
233+ USHORT shAdapterId = (USHORT )adaptExt -> hba_id ;
234+ #if !defined(RUN_UNCHECKED )
235+ ULONG value_as_ulong ; // Used in TRACING.
236+ #endif
227237
228- adaptExt = ( PADAPTER_EXTENSION ) DeviceExtension ;
229- pBuf = StorPortAllocateRegistryBuffer (DeviceExtension , & Len );
230- if (pBuf == NULL )
238+ /* Get a clean buffer to store the registry value... */
239+ pBuffer = StorPortAllocateRegistryBuffer (DeviceExtension , & pBufferLength );
240+ if (pBuffer == NULL )
231241 {
232- RhelDbgPrint (TRACE_LEVEL_FATAL , "StorPortAllocateRegistryBuffer failed to allocate buffer\n" );
242+ #if !defined(RUN_UNCHECKED )
243+ RhelDbgPrint (TRACE_LEVEL_WARNING , " StorPortAllocateRegistryBuffer failed to allocate buffer\n" );
244+ #endif
233245 return FALSE;
234246 }
247+ memset (pBuffer , 0 , sizeof (ULONG ));
235248
236- memset (pBuf , 0 , sizeof (ULONG ));
249+ /* Check if we can get a System PortNumber to access the \Parameters\Device(d) subkey to get a per HBA value.
250+ * FIXME NOTE
251+ *
252+ * Regarding StorPortGetSystemPortNumber():
253+ *
254+ * StorPort always reports STOR_STATUS_INVALID_DEVICE_STATE and does not update pHwAddress->Port.
255+ * Calls to StorPortRegistryRead() and StorPortRegistryWrite() only read or write to \Parameters\Device-1,
256+ * which appears to be an uninitialized value. Therefore, the alternate per HBA read technique will always be used.
257+ *
258+ * Various initialisation syntaxes were attempted, including partial and fully initialized STOR_ADDRESS and
259+ * STOR_ADDR_BTL8 structs and pointers. Attempts to initialize most of the deprecated HW_INITIALIZATION_DATA
260+ * and PORT_CONFIGURATION_INFORMATION members were also made, but of no effect with regard to this function.
261+ * Using DeviceExtension or the adaptExt pointer as the first parameter to the function had no effect.
262+ * Attempts to set the InitiatorBusId were successful, but of no effect with regard to this function.
263+ * Also attempted BusType = BusTypeScsi (rather than BusTypeSas per inf default) - in both the inf and using
264+ * StorPortSetAdapterBusType() too. Also tried many other BusTypes via StorPortSetAdapterBusType() mechanics.
265+ * Maybe something in WMI or VPD processing...? Do we need PortAttributes.PortState = HBA_PORTSTATE_ONLINE and
266+ * PortAttributes.PortType = HBA_PORTTYPE_SASDEVICE to be set...? Should we be initializing adaptExt->wwn,
267+ * adaptExt->port_wwn or adaptExt->port_idx...? The wMI routines are not using the InstanceIndex and InstanceCount
268+ * parameters to cycle through HBAs. Maybe they should...
269+ *
270+ * Difficult to determine what is wrong here...
271+ * ¯\_(ツ)_/¯
272+ *
273+ * FIXME NOTE END
274+ */
275+ pHwAddress -> Type = STOR_ADDRESS_TYPE_BTL8 ;
276+ pHwAddress -> AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH ;
277+ #if !defined(RUN_UNCHECKED )
278+ RhelDbgPrint (TRACE_REGISTRY ,
279+ " Checking whether the HBA system port number and HBA specific registry are available for reading... "
280+ "\n" );
281+ #endif
282+ spgspn_rc = StorPortGetSystemPortNumber (DeviceExtension , pHwAddress );
283+ if (spgspn_rc == STOR_STATUS_INVALID_DEVICE_STATE )
284+ {
285+ #if !defined(RUN_UNCHECKED )
286+ RhelDbgPrint (TRACE_REGISTRY ,
287+ " WARNING : !!!...HBA Port not ready yet...!!! Returns : 0x%x (STOR_STATUS_INVALID_DEVICE_STATE) "
288+ "\n" ,
289+ spgspn_rc );
290+ #endif
291+ /*
292+ * When we are unable to get a valid system PortNumber, we need to
293+ * use an alternate per HBA registry read technique. The technique
294+ * implemented here uses per HBA registry value names based on the
295+ * hba_id, which is the Storport provided slot_number minus one,
296+ * padded to hundreds, e.g. \Parameters\Device\Valuename_123.
297+ *
298+ * This permits up to 999 HBAs. That ought to be enough... c( O.O )ɔ
299+ */
300+ bUseAltPerHbaRegRead = TRUE;
301+ #if !defined(RUN_UNCHECKED )
302+ RhelDbgPrint (TRACE_REGISTRY ,
303+ " Using alternate per HBA registry read technique [\\Parameters\\Device\\Value_(ddd)]. \n" );
304+ #endif
237305
238- Ret = StorPortRegistryRead (DeviceExtension , ValueName , 1 , MINIPORT_REG_DWORD , pBuf , & Len );
306+ /* Grab the first 60 characters of the target Registry Value.
307+ * Value name limit is 16,383 characters, so this is important.
308+ * We leave the last 4 characters for the hba_id_as_str values.
309+ * NULL terminator wraps things up. Also used in TRACING.
310+ */
311+ CopyBufferToAnsiString (& valname_as_str , ValueName , '\0' , 60 );
312+ CopyBufferToAnsiString (& hba_id_as_str , & shAdapterId , '\0' , 4 );
239313
240- if ((Ret == FALSE) || (Len == 0 ))
314+ /* Convert from integer to padded ASCII numbers. */
315+ if (shAdapterId / 100 )
316+ {
317+ j = 0 ;
318+ hba_id_as_str [j ] = (UCHAR )(shAdapterId / 100 ) + 48 ;
319+ }
320+ else
321+ {
322+ hba_id_as_str [0 ] = 48 ;
323+ if (shAdapterId / 10 )
324+ {
325+ j = 1 ;
326+ hba_id_as_str [j ] = (UCHAR )(shAdapterId / 10 ) + 48 ;
327+ }
328+ else
329+ {
330+ hba_id_as_str [1 ] = 48 ;
331+ j = 2 ;
332+ hba_id_as_str [j ] = (UCHAR )shAdapterId + 48 ;
333+ }
334+ }
335+ if ((j < 1 ) && (shAdapterId / 10 ))
336+ {
337+ j = 1 ;
338+ hba_id_as_str [j ] = (UCHAR )(((shAdapterId - ((shAdapterId / 100 ) * 100 )) / 10 ) + 48 );
339+ }
340+ else if ((j < 2 ) && (shAdapterId > 9 ))
341+ {
342+ j = 2 ;
343+ hba_id_as_str [j ] = (UCHAR )((shAdapterId - ((shAdapterId / 10 ) * 10 )) + 48 );
344+ }
345+ else
346+ {
347+ j = 1 ;
348+ hba_id_as_str [j ] = 48 ;
349+ }
350+ if ((j < 2 ) && (shAdapterId > 0 ))
351+ {
352+ j = 2 ;
353+ hba_id_as_str [j ] = (UCHAR )((shAdapterId - ((shAdapterId / 10 ) * 10 )) + 48 );
354+ }
355+ else if (j < 2 )
356+ {
357+ j = 2 ;
358+ hba_id_as_str [j ] = 48 ;
359+ }
360+ /* NULL-terminate the string. */
361+ hba_id_as_str [3 ] = '\0' ;
362+ /* Skip the exisitng ValueName. */
363+ for (i = 0 ; valname_as_str [i ] != '\0' ; ++ i )
364+ {
365+ }
366+ /* Append an underscore. */
367+ valname_as_str [i ] = '\x5F' ;
368+ /* Append the padded HBA ID and NULL terminator. */
369+ for (j = 0 ; j < 4 ; ++ j )
370+ {
371+ valname_as_str [i + j + 1 ] = hba_id_as_str [j ];
372+ }
373+
374+ PUCHAR ValueNamePerHba = (UCHAR * )& valname_as_str ;
375+ bReadResult = StorPortRegistryRead (DeviceExtension ,
376+ ValueNamePerHba ,
377+ 1 ,
378+ MINIPORT_REG_DWORD ,
379+ pBuffer ,
380+ & pBufferLength );
381+ }
382+ else
383+ {
384+ #if !defined(RUN_UNCHECKED )
385+ RhelDbgPrint (TRACE_REGISTRY , " HBA Port : %u | Returns : 0x%x \n" , pHwAddress -> Port , spgspn_rc );
386+ RhelDbgPrint (TRACE_REGISTRY , " Using StorPort-based per HBA registry read [\\Parameters\\Device(d)]. \n" );
387+ #endif
388+ /* FIXME : THIS DOES NOT WORK. IT WILL NOT READ \Parameters\Device(d) subkeys...
389+ * NOTE : Only MINIPORT_REG_DWORD values are supported.
390+ */
391+ bReadResult = StorPortRegistryRead (DeviceExtension , ValueName , 0 , MINIPORT_REG_DWORD , pBuffer , & pBufferLength );
392+ #if !defined(RUN_UNCHECKED )
393+ /* Grab the first 64 characters of the target Registry Value.
394+ * Value name limit is 16,383 characters, so this is important.
395+ * NULL terminator wraps things up. Used in TRACING.
396+ */
397+ CopyBufferToAnsiString (& valname_as_str , ValueName , '\0' , 64 );
398+ #endif
399+ }
400+
401+ if ((bReadResult == FALSE) || (pBufferLength == 0 ))
402+ {
403+ #if !defined(RUN_UNCHECKED )
404+ RhelDbgPrint (TRACE_REGISTRY ,
405+ " StorPortRegistryRead was unable to find a per HBA value %s. Attempting to find a global "
406+ "value... \n" ,
407+ (bUseAltPerHbaRegRead ) ? "using \\Parameters\\Device\\Value_(ddd) value names"
408+ : "at the \\Parameters\\Device(d) subkey" );
409+ #endif
410+ bReadResult = FALSE;
411+ pBufferLength = sizeof (ULONG );
412+ memset (pBuffer , 0 , sizeof (ULONG ));
413+
414+ /* Do a "Global" read of the Parameters\Device subkey...
415+ * NOTE : Only MINIPORT_REG_DWORD values are supported.
416+ */
417+ bReadResult = StorPortRegistryRead (DeviceExtension , ValueName , 1 , MINIPORT_REG_DWORD , pBuffer , & pBufferLength );
418+ #if !defined(RUN_UNCHECKED )
419+ /* Grab the first 64 characters of the target Registry Value.
420+ * Value name limit is 16,383 characters, so this is important.
421+ * NULL terminator wraps things up. Used in TRACING.
422+ */
423+ CopyBufferToAnsiString (& valname_as_str , ValueName , '\0' , 64 );
424+ #endif
425+ }
426+ #if !defined(RUN_UNCHECKED )
427+ /* Give me the DWORD Registry Value as a ULONG from the pointer.
428+ * Used in TRACING.
429+ */
430+ memcpy (& value_as_ulong , pBuffer , sizeof (ULONG ));
431+ #endif
432+
433+ if ((bReadResult == FALSE) || (pBufferLength == 0 ))
241434 {
242- RhelDbgPrint (TRACE_LEVEL_FATAL , "StorPortRegistryRead returned 0x%x, Len = %d\n" , Ret , Len );
243- StorPortFreeRegistryBuffer (DeviceExtension , pBuf );
435+ #if !defined(RUN_UNCHECKED )
436+ RhelDbgPrint (TRACE_REGISTRY ,
437+ " StorPortRegistryRead of %s returned NOT FOUND or EMPTY, pBufferLength = %d, Possible "
438+ "pBufferLength Hint = 0x%x (%lu) \n" ,
439+ valname_as_str ,
440+ pBufferLength ,
441+ value_as_ulong ,
442+ value_as_ulong );
443+ #endif
444+ StorPortFreeRegistryBuffer (DeviceExtension , pBuffer );
244445 return FALSE;
245446 }
447+ else
448+ {
449+ #if !defined(RUN_UNCHECKED )
450+ RhelDbgPrint (TRACE_REGISTRY ,
451+ " StorPortRegistryRead of %s returned SUCCESS, pBufferLength = %d, Value = 0x%x (%lu) \n" ,
452+ valname_as_str ,
453+ pBufferLength ,
454+ value_as_ulong ,
455+ value_as_ulong );
456+ #endif
246457
247- StorPortCopyMemory ((PVOID )((UINT_PTR )adaptExt + offset ), (PVOID )pBuf , sizeof (ULONG ));
458+ StorPortCopyMemory ((PVOID )((UINT_PTR )adaptExt + offset ), (PVOID )pBuffer , sizeof (ULONG ));
248459
249- StorPortFreeRegistryBuffer (DeviceExtension , pBuf );
460+ StorPortFreeRegistryBuffer (DeviceExtension , pBuffer );
250461
251- return TRUE;
462+ return TRUE;
463+ }
252464}
253465
254466ULONG
@@ -360,7 +572,18 @@ VioScsiFindAdapter(IN PVOID DeviceExtension,
360572 RtlZeroMemory (adaptExt , sizeof (ADAPTER_EXTENSION ));
361573
362574 adaptExt -> dump_mode = IsCrashDumpMode ;
363- adaptExt -> hba_id = HBA_ID ;
575+ #if !defined(RUN_UNCHECKED )
576+ RhelDbgPrint (TRACE_LEVEL_INFORMATION ,
577+ " Crash dump mode : %s \n" ,
578+ (adaptExt -> dump_mode == IsCrashDumpMode ) ? "ACTIVATED" : "NOT ACTIVATED" );
579+ #endif
580+
581+ /* Set the hba_id to the StorPort supplied SlotNumber minus one. Used as an analogue for the system PortNumber. */
582+ adaptExt -> hba_id = (CCHAR )ConfigInfo -> SlotNumber - 1 ;
583+ #if !defined(RUN_UNCHECKED )
584+ RhelDbgPrint (TRACE_LEVEL_INFORMATION , " HBA ID [adaptExt->hba_id] : %I64d \n" , adaptExt -> hba_id );
585+ #endif
586+
364587 ConfigInfo -> Master = TRUE;
365588 ConfigInfo -> ScatterGather = TRUE;
366589 ConfigInfo -> DmaWidth = Width32Bits ;
0 commit comments