Skip to content

Commit 09b0439

Browse files
[vioscsi] Extend VioScsiReadRegistryParameter()
Adds capability to do per HBA registry reads. This permits, e.g. PhysicalBreaks_001, PhysicalBreaks_002, etc. as an alternative to \Parameters\Device(d) by instead using the format \Parameters\Device\Valuename_123. Includes FIXME NOTE regarding StorPortGetSystemPortNumber(). StorPortGetSystemPortNumber() should return before HBA-specific registry reads can successfully use \Parameters\Device(d). Coincidentally updated the following in VioScsiFindAdapter(): adaptExt->dump_mode (new tracing) adaptExt->hba_id (new tracing and new definition) The HBA ID that determines the "123" in Valuename_123 of the registry path \Parameters\Device\Valuename_123 is the HBA slot number minus 1. Credit to @MartinDrab for eagle-eyed code review. 8^D Signed-off-by: benyamin-codez <[email protected]>
1 parent 2bcf04f commit 09b0439

File tree

1 file changed

+240
-17
lines changed

1 file changed

+240
-17
lines changed

vioscsi/vioscsi.c

Lines changed: 240 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -220,35 +220,247 @@ USHORT CopyBufferToAnsiString(void *_pDest, const void *_pSrc, const char delimi
220220

221221
BOOLEAN 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

254466
ULONG
@@ -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

Comments
 (0)