@@ -130,6 +130,229 @@ VOID WppCleanupRoutine(PVOID arg1)
130
130
}
131
131
#endif
132
132
133
+ USHORT CopyBufferToAnsiString (void * _pDest , const void * _pSrc , const char delimiter , size_t _maxlength )
134
+ {
135
+ PCHAR dst = (PCHAR )_pDest ;
136
+ PCHAR src = (PCHAR )_pSrc ;
137
+ USHORT _length = _maxlength ;
138
+
139
+ while (_length && (* src != delimiter ))
140
+ {
141
+ * dst ++ = * src ++ ;
142
+ -- _length ;
143
+ };
144
+ * dst = '\0' ;
145
+ return _length ;
146
+ }
147
+
148
+ BOOLEAN VioStorReadRegistryParameter (IN PVOID DeviceExtension , IN PUCHAR ValueName , IN LONG offset )
149
+ {
150
+ BOOLEAN bReadResult = FALSE;
151
+ BOOLEAN bUseAltPerHbaRegRead = FALSE;
152
+ ULONG pBufferLength = sizeof (ULONG );
153
+ UCHAR * pBuffer = NULL ;
154
+ PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION )DeviceExtension ;
155
+ ULONG spgspn_rc , i , j ;
156
+ STOR_ADDRESS HwAddress = {0 };
157
+ PSTOR_ADDRESS pHwAddress = & HwAddress ;
158
+ CHAR valname_as_str [64 ] = {0 };
159
+ CHAR hba_id_as_str [4 ] = {0 };
160
+ USHORT shAdapterId = (USHORT )adaptExt -> slot_number - 1 ;
161
+ ULONG value_as_ulong ;
162
+
163
+ /* Get a clean buffer to store the registry value... */
164
+ pBuffer = StorPortAllocateRegistryBuffer (DeviceExtension , & pBufferLength );
165
+ if (pBuffer == NULL )
166
+ {
167
+ RhelDbgPrint (TRACE_LEVEL_WARNING , " StorPortAllocateRegistryBuffer failed to allocate buffer\n" );
168
+ return FALSE;
169
+ }
170
+ memset (pBuffer , 0 , sizeof (ULONG ));
171
+
172
+ /* Check if we can get a System PortNumber to access the \Parameters\Device(d) subkey to get a per HBA value.
173
+ * FIXME NOTE
174
+ *
175
+ * Regarding StorPortGetSystemPortNumber():
176
+ *
177
+ * StorPort always reports STOR_STATUS_INVALID_DEVICE_STATE and does not update pHwAddress->Port.
178
+ * Calls to StorPortRegistryRead() and StorPortRegistryWrite() only read or write to \Parameters\Device-1,
179
+ * which appears to be an uninitialized value. Therefore, the alternate per HBA read technique will always be used.
180
+ *
181
+ * Please refer to PR #1216 for more details.
182
+ *
183
+ * FIXME NOTE END
184
+ */
185
+ pHwAddress -> Type = STOR_ADDRESS_TYPE_BTL8 ;
186
+ pHwAddress -> AddressLength = STOR_ADDR_BTL8_ADDRESS_LENGTH ;
187
+ RhelDbgPrint (TRACE_REGISTRY ,
188
+ " Checking whether the HBA system port number and HBA specific registry are available for reading... "
189
+ "\n" );
190
+ spgspn_rc = StorPortGetSystemPortNumber (DeviceExtension , pHwAddress );
191
+ if (spgspn_rc = STOR_STATUS_INVALID_DEVICE_STATE )
192
+ {
193
+ RhelDbgPrint (TRACE_REGISTRY ,
194
+ " WARNING : !!!...HBA Port not ready yet...!!! Returns : 0x%x (STOR_STATUS_INVALID_DEVICE_STATE) "
195
+ "\n" ,
196
+ spgspn_rc );
197
+ /*
198
+ * When we are unable to get a valid system PortNumber, we need to
199
+ * use an alternate per HBA registry read technique. The technique
200
+ * implemented here uses per HBA registry value names based on the
201
+ * Storport provided slot_number minus one, padded to hundreds,
202
+ * e.g. \Parameters\Device\Valuename_123.
203
+ *
204
+ * This permits up to 999 HBAs. That ought to be enough... c( O.O )ɔ
205
+ */
206
+ bUseAltPerHbaRegRead = TRUE;
207
+ RhelDbgPrint (TRACE_REGISTRY ,
208
+ " Using alternate per HBA registry read technique [\\Parameters\\Device\\Value_(ddd)]. \n" );
209
+
210
+ /* Grab the first 60 characters of the target Registry Value.
211
+ * Value name limit is 16,383 characters, so this is important.
212
+ * We leave the last 4 characters for the hba_id_as_str values.
213
+ * NULL terminator wraps things up. Also used in TRACING.
214
+ */
215
+ CopyBufferToAnsiString (& valname_as_str , ValueName , '\0' , 60 );
216
+ CopyBufferToAnsiString (& hba_id_as_str , & shAdapterId , '\0' , 4 );
217
+
218
+ /* Convert from integer to padded ASCII numbers. */
219
+ if (shAdapterId / 100 )
220
+ {
221
+ j = 0 ;
222
+ hba_id_as_str [j ] = (UCHAR )(shAdapterId / 100 ) + 48 ;
223
+ }
224
+ else
225
+ {
226
+ hba_id_as_str [0 ] = 48 ;
227
+ if (shAdapterId / 10 )
228
+ {
229
+ j = 1 ;
230
+ hba_id_as_str [j ] = (UCHAR )(shAdapterId / 10 ) + 48 ;
231
+ }
232
+ else
233
+ {
234
+ hba_id_as_str [1 ] = 48 ;
235
+ j = 2 ;
236
+ hba_id_as_str [j ] = (UCHAR )shAdapterId + 48 ;
237
+ }
238
+ }
239
+ if ((j < 1 ) && (shAdapterId / 10 ))
240
+ {
241
+ j = 1 ;
242
+ hba_id_as_str [j ] = (UCHAR )(((shAdapterId - ((shAdapterId / 100 ) * 100 )) / 10 ) + 48 );
243
+ }
244
+ else if ((j < 2 ) && (shAdapterId > 9 ))
245
+ {
246
+ j = 2 ;
247
+ hba_id_as_str [j ] = (UCHAR )((shAdapterId - ((shAdapterId / 10 ) * 10 )) + 48 );
248
+ }
249
+ else
250
+ {
251
+ j = 1 ;
252
+ hba_id_as_str [j ] = 48 ;
253
+ }
254
+ if ((j < 2 ) && (shAdapterId > 0 ))
255
+ {
256
+ j = 2 ;
257
+ hba_id_as_str [j ] = (UCHAR )((shAdapterId - ((shAdapterId / 10 ) * 10 )) + 48 );
258
+ }
259
+ else if (j < 2 )
260
+ {
261
+ j = 2 ;
262
+ hba_id_as_str [j ] = 48 ;
263
+ }
264
+ /* NULL-terminate the string. */
265
+ hba_id_as_str [3 ] = '\0' ;
266
+ /* Skip the exisitng ValueName. */
267
+ for (i = 0 ; valname_as_str [i ] != '\0' ; ++ i )
268
+ {
269
+ }
270
+ /* Append an underscore. */
271
+ valname_as_str [i ] = '\x5F' ;
272
+ /* Append the padded HBA ID and NULL terminator. */
273
+ for (j = 0 ; j < 4 ; ++ j )
274
+ {
275
+ valname_as_str [i + j + 1 ] = hba_id_as_str [j ];
276
+ }
277
+
278
+ PUCHAR ValueNamePerHba = (UCHAR * )& valname_as_str ;
279
+ bReadResult = StorPortRegistryRead (DeviceExtension ,
280
+ ValueNamePerHba ,
281
+ 1 ,
282
+ MINIPORT_REG_DWORD ,
283
+ pBuffer ,
284
+ & pBufferLength );
285
+ }
286
+ else
287
+ {
288
+ RhelDbgPrint (TRACE_REGISTRY , " HBA Port : %u | Returns : 0x%x \n" , pHwAddress -> Port , spgspn_rc );
289
+ RhelDbgPrint (TRACE_REGISTRY , " Using StorPort-based per HBA registry read [\\Parameters\\Device(d)]. \n" );
290
+ /* FIXME : THIS DOES NOT WORK. IT WILL NOT READ \Parameters\Device(d) subkeys...
291
+ * NOTE : Only MINIPORT_REG_DWORD values are supported.
292
+ */
293
+ bReadResult = StorPortRegistryRead (DeviceExtension , ValueName , 0 , MINIPORT_REG_DWORD , pBuffer , & pBufferLength );
294
+ /* Grab the first 64 characters of the target Registry Value.
295
+ * Value name limit is 16,383 characters, so this is important.
296
+ * NULL terminator wraps things up. Used in TRACING.
297
+ */
298
+ CopyBufferToAnsiString (& valname_as_str , ValueName , '\0' , 64 );
299
+ }
300
+
301
+ if ((bReadResult == FALSE) || (pBufferLength == 0 ))
302
+ {
303
+ RhelDbgPrint (TRACE_REGISTRY ,
304
+ " StorPortRegistryRead was unable to find a per HBA value %s. Attempting to find a global "
305
+ "value... \n" ,
306
+ (bUseAltPerHbaRegRead ) ? "using \\Parameters\\Device\\Value_(ddd) value names"
307
+ : "at the \\Parameters\\Device(d) subkey" );
308
+ bReadResult = FALSE;
309
+ pBufferLength = sizeof (ULONG );
310
+ memset (pBuffer , 0 , sizeof (ULONG ));
311
+
312
+ /* Do a "Global" read of the Parameters\Device subkey...
313
+ * NOTE : Only MINIPORT_REG_DWORD values are supported.
314
+ */
315
+ bReadResult = StorPortRegistryRead (DeviceExtension , ValueName , 1 , MINIPORT_REG_DWORD , pBuffer , & pBufferLength );
316
+ /* Grab the first 64 characters of the target Registry Value.
317
+ * Value name limit is 16,383 characters, so this is important.
318
+ * NULL terminator wraps things up. Used in TRACING.
319
+ */
320
+ CopyBufferToAnsiString (& valname_as_str , ValueName , '\0' , 64 );
321
+ }
322
+ /* Give me the DWORD Registry Value as a ULONG from the pointer.
323
+ * Used in TRACING.
324
+ */
325
+ memcpy (& value_as_ulong , pBuffer , sizeof (ULONG ));
326
+
327
+ if ((bReadResult == FALSE) || (pBufferLength == 0 ))
328
+ {
329
+ RhelDbgPrint (TRACE_REGISTRY ,
330
+ " StorPortRegistryRead of %s returned NOT FOUND or EMPTY, pBufferLength = %d, Possible "
331
+ "pBufferLength Hint = 0x%x (%lu) \n" ,
332
+ valname_as_str ,
333
+ pBufferLength ,
334
+ value_as_ulong ,
335
+ value_as_ulong );
336
+ StorPortFreeRegistryBuffer (DeviceExtension , pBuffer );
337
+ return FALSE;
338
+ }
339
+ else
340
+ {
341
+ RhelDbgPrint (TRACE_REGISTRY ,
342
+ " StorPortRegistryRead of %s returned SUCCESS, pBufferLength = %d, Value = 0x%x (%lu) \n" ,
343
+ valname_as_str ,
344
+ pBufferLength ,
345
+ value_as_ulong ,
346
+ value_as_ulong );
347
+
348
+ StorPortCopyMemory ((PVOID )((UINT_PTR )adaptExt + offset ), (PVOID )pBuffer , sizeof (ULONG ));
349
+
350
+ StorPortFreeRegistryBuffer (DeviceExtension , pBuffer );
351
+
352
+ return TRUE;
353
+ }
354
+ }
355
+
133
356
ULONG
134
357
DriverEntry (IN PVOID DriverObject , IN PVOID RegistryPath )
135
358
{
0 commit comments