[SCSIPORT] Split scsiport.c file into several ones, prepare for the refactoring
[reactos.git] / drivers / storage / port / scsiport / registry.c
1 /*
2 * PROJECT: ReactOS Storage Stack / SCSIPORT storage port library
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Registry operations
5 * COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
6 * Aleksey Bragin (aleksey@reactos.org)
7 */
8
9 #include "scsiport.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14
15 VOID
16 SpiInitOpenKeys(
17 _Inout_ PCONFIGURATION_INFO ConfigInfo,
18 _In_ PUNICODE_STRING RegistryPath)
19 {
20 OBJECT_ATTRIBUTES ObjectAttributes;
21 UNICODE_STRING KeyName;
22 NTSTATUS Status;
23
24 /* Open the service key */
25 InitializeObjectAttributes(&ObjectAttributes,
26 RegistryPath,
27 OBJ_CASE_INSENSITIVE,
28 NULL,
29 NULL);
30
31 Status = ZwOpenKey(&ConfigInfo->ServiceKey,
32 KEY_READ,
33 &ObjectAttributes);
34
35 if (!NT_SUCCESS(Status))
36 {
37 DPRINT("Unable to open driver's registry key %wZ, status 0x%08x\n", RegistryPath, Status);
38 ConfigInfo->ServiceKey = NULL;
39 }
40
41 /* If we could open driver's service key, then proceed to the Parameters key */
42 if (ConfigInfo->ServiceKey != NULL)
43 {
44 RtlInitUnicodeString(&KeyName, L"Parameters");
45 InitializeObjectAttributes(&ObjectAttributes,
46 &KeyName,
47 OBJ_CASE_INSENSITIVE,
48 ConfigInfo->ServiceKey,
49 (PSECURITY_DESCRIPTOR) NULL);
50
51 /* Try to open it */
52 Status = ZwOpenKey(&ConfigInfo->DeviceKey,
53 KEY_READ,
54 &ObjectAttributes);
55
56 if (NT_SUCCESS(Status))
57 {
58 /* Yes, Parameters key exist, and it must be used instead of
59 the Service key */
60 ZwClose(ConfigInfo->ServiceKey);
61 ConfigInfo->ServiceKey = ConfigInfo->DeviceKey;
62 ConfigInfo->DeviceKey = NULL;
63 }
64 }
65
66 if (ConfigInfo->ServiceKey != NULL)
67 {
68 /* Open the Device key */
69 RtlInitUnicodeString(&KeyName, L"Device");
70 InitializeObjectAttributes(&ObjectAttributes,
71 &KeyName,
72 OBJ_CASE_INSENSITIVE,
73 ConfigInfo->ServiceKey,
74 NULL);
75
76 /* We don't check for failure here - not needed */
77 ZwOpenKey(&ConfigInfo->DeviceKey,
78 KEY_READ,
79 &ObjectAttributes);
80 }
81 }
82
83 /**********************************************************************
84 * NAME INTERNAL
85 * SpiBuildDeviceMap
86 *
87 * DESCRIPTION
88 * Builds the registry device map of all device which are attached
89 * to the given SCSI HBA port. The device map is located at:
90 * \Registry\Machine\DeviceMap\Scsi
91 *
92 * RUN LEVEL
93 * PASSIVE_LEVEL
94 *
95 * ARGUMENTS
96 * DeviceExtension
97 * ...
98 *
99 * RegistryPath
100 * Name of registry driver service key.
101 *
102 * RETURNS
103 * NTSTATUS
104 */
105
106 NTSTATUS
107 SpiBuildDeviceMap(
108 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
109 _In_ PUNICODE_STRING RegistryPath)
110 {
111 PSCSI_PORT_LUN_EXTENSION LunExtension;
112 OBJECT_ATTRIBUTES ObjectAttributes;
113 UNICODE_STRING KeyName;
114 UNICODE_STRING ValueName;
115 WCHAR NameBuffer[64];
116 ULONG Disposition;
117 HANDLE ScsiKey;
118 HANDLE ScsiPortKey = NULL;
119 HANDLE ScsiBusKey = NULL;
120 HANDLE ScsiInitiatorKey = NULL;
121 HANDLE ScsiTargetKey = NULL;
122 HANDLE ScsiLunKey = NULL;
123 ULONG BusNumber;
124 ULONG Target;
125 ULONG CurrentTarget;
126 ULONG Lun;
127 PWCHAR DriverName;
128 ULONG UlongData;
129 PWCHAR TypeName;
130 NTSTATUS Status;
131
132 DPRINT("SpiBuildDeviceMap() called\n");
133
134 if (DeviceExtension == NULL || RegistryPath == NULL)
135 {
136 DPRINT1("Invalid parameter\n");
137 return STATUS_INVALID_PARAMETER;
138 }
139
140 /* Open or create the 'Scsi' subkey */
141 RtlInitUnicodeString(&KeyName,
142 L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
143 InitializeObjectAttributes(&ObjectAttributes,
144 &KeyName,
145 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE,
146 0,
147 NULL);
148 Status = ZwCreateKey(&ScsiKey,
149 KEY_ALL_ACCESS,
150 &ObjectAttributes,
151 0,
152 NULL,
153 REG_OPTION_VOLATILE,
154 &Disposition);
155 if (!NT_SUCCESS(Status))
156 {
157 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
158 return Status;
159 }
160
161 /* Create new 'Scsi Port X' subkey */
162 DPRINT("Scsi Port %lu\n", DeviceExtension->PortNumber);
163
164 swprintf(NameBuffer,
165 L"Scsi Port %lu",
166 DeviceExtension->PortNumber);
167 RtlInitUnicodeString(&KeyName, NameBuffer);
168 InitializeObjectAttributes(&ObjectAttributes,
169 &KeyName,
170 OBJ_KERNEL_HANDLE,
171 ScsiKey,
172 NULL);
173 Status = ZwCreateKey(&ScsiPortKey,
174 KEY_ALL_ACCESS,
175 &ObjectAttributes,
176 0,
177 NULL,
178 REG_OPTION_VOLATILE,
179 &Disposition);
180 ZwClose(ScsiKey);
181 if (!NT_SUCCESS(Status))
182 {
183 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
184 return Status;
185 }
186
187 /*
188 * Create port-specific values
189 */
190
191 /* Set 'DMA Enabled' (REG_DWORD) value */
192 UlongData = (ULONG)!DeviceExtension->PortCapabilities.AdapterUsesPio;
193 DPRINT(" DMA Enabled = %s\n", UlongData ? "TRUE" : "FALSE");
194 RtlInitUnicodeString(&ValueName, L"DMA Enabled");
195 Status = ZwSetValueKey(ScsiPortKey,
196 &ValueName,
197 0,
198 REG_DWORD,
199 &UlongData,
200 sizeof(UlongData));
201 if (!NT_SUCCESS(Status))
202 {
203 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status);
204 ZwClose(ScsiPortKey);
205 return Status;
206 }
207
208 /* Set 'Driver' (REG_SZ) value */
209 DriverName = wcsrchr(RegistryPath->Buffer, L'\\') + 1;
210 RtlInitUnicodeString(&ValueName, L"Driver");
211 Status = ZwSetValueKey(ScsiPortKey,
212 &ValueName,
213 0,
214 REG_SZ,
215 DriverName,
216 (ULONG)((wcslen(DriverName) + 1) * sizeof(WCHAR)));
217 if (!NT_SUCCESS(Status))
218 {
219 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
220 ZwClose(ScsiPortKey);
221 return Status;
222 }
223
224 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
225 UlongData = (ULONG)DeviceExtension->PortConfig->BusInterruptLevel;
226 DPRINT(" Interrupt = %lu\n", UlongData);
227 RtlInitUnicodeString(&ValueName, L"Interrupt");
228 Status = ZwSetValueKey(ScsiPortKey,
229 &ValueName,
230 0,
231 REG_DWORD,
232 &UlongData,
233 sizeof(UlongData));
234 if (!NT_SUCCESS(Status))
235 {
236 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status);
237 ZwClose(ScsiPortKey);
238 return Status;
239 }
240
241 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
242 UlongData = ScsiPortConvertPhysicalAddressToUlong((*DeviceExtension->PortConfig->AccessRanges)[0].RangeStart);
243 DPRINT(" IOAddress = %lx\n", UlongData);
244 RtlInitUnicodeString(&ValueName, L"IOAddress");
245 Status = ZwSetValueKey(ScsiPortKey,
246 &ValueName,
247 0,
248 REG_DWORD,
249 &UlongData,
250 sizeof(UlongData));
251 if (!NT_SUCCESS(Status))
252 {
253 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status);
254 ZwClose(ScsiPortKey);
255 return Status;
256 }
257
258 /* Enumerate buses */
259 for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig->NumberOfBuses; BusNumber++)
260 {
261 /* Create 'Scsi Bus X' key */
262 DPRINT(" Scsi Bus %lu\n", BusNumber);
263 swprintf(NameBuffer,
264 L"Scsi Bus %lu",
265 BusNumber);
266 RtlInitUnicodeString(&KeyName, NameBuffer);
267 InitializeObjectAttributes(&ObjectAttributes,
268 &KeyName,
269 0,
270 ScsiPortKey,
271 NULL);
272 Status = ZwCreateKey(&ScsiBusKey,
273 KEY_ALL_ACCESS,
274 &ObjectAttributes,
275 0,
276 NULL,
277 REG_OPTION_VOLATILE,
278 &Disposition);
279 if (!NT_SUCCESS(Status))
280 {
281 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
282 goto ByeBye;
283 }
284
285 /* Create 'Initiator Id X' key */
286 DPRINT(" Initiator Id %lu\n",
287 DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
288 swprintf(NameBuffer,
289 L"Initiator Id %lu",
290 (ULONG)(UCHAR)DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
291 RtlInitUnicodeString(&KeyName, NameBuffer);
292 InitializeObjectAttributes(&ObjectAttributes,
293 &KeyName,
294 0,
295 ScsiBusKey,
296 NULL);
297 Status = ZwCreateKey(&ScsiInitiatorKey,
298 KEY_ALL_ACCESS,
299 &ObjectAttributes,
300 0,
301 NULL,
302 REG_OPTION_VOLATILE,
303 &Disposition);
304 if (!NT_SUCCESS(Status))
305 {
306 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
307 goto ByeBye;
308 }
309
310 /* FIXME: Are there any initiator values (??) */
311
312 ZwClose(ScsiInitiatorKey);
313 ScsiInitiatorKey = NULL;
314
315
316 /* Enumerate targets */
317 CurrentTarget = (ULONG)-1;
318 ScsiTargetKey = NULL;
319 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
320 {
321 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
322 {
323 LunExtension = SpiGetLunExtension(DeviceExtension,
324 (UCHAR)BusNumber,
325 (UCHAR)Target,
326 (UCHAR)Lun);
327 if (LunExtension == NULL)
328 continue;
329
330 if (Target != CurrentTarget)
331 {
332 /* Close old target key */
333 if (ScsiTargetKey != NULL)
334 {
335 ZwClose(ScsiTargetKey);
336 ScsiTargetKey = NULL;
337 }
338
339 /* Create 'Target Id X' key */
340 DPRINT(" Target Id %lu\n", Target);
341 swprintf(NameBuffer,
342 L"Target Id %lu",
343 Target);
344 RtlInitUnicodeString(&KeyName, NameBuffer);
345 InitializeObjectAttributes(&ObjectAttributes,
346 &KeyName,
347 0,
348 ScsiBusKey,
349 NULL);
350 Status = ZwCreateKey(&ScsiTargetKey,
351 KEY_ALL_ACCESS,
352 &ObjectAttributes,
353 0,
354 NULL,
355 REG_OPTION_VOLATILE,
356 &Disposition);
357 if (!NT_SUCCESS(Status))
358 {
359 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
360 goto ByeBye;
361 }
362
363 CurrentTarget = Target;
364 }
365
366 /* Create 'Logical Unit Id X' key */
367 DPRINT(" Logical Unit Id %lu\n", Lun);
368 swprintf(NameBuffer,
369 L"Logical Unit Id %lu",
370 Lun);
371 RtlInitUnicodeString(&KeyName, NameBuffer);
372 InitializeObjectAttributes(&ObjectAttributes,
373 &KeyName,
374 0,
375 ScsiTargetKey,
376 NULL);
377 Status = ZwCreateKey(&ScsiLunKey,
378 KEY_ALL_ACCESS,
379 &ObjectAttributes,
380 0,
381 NULL,
382 REG_OPTION_VOLATILE,
383 &Disposition);
384 if (!NT_SUCCESS(Status))
385 {
386 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
387 goto ByeBye;
388 }
389
390 /* Set 'Identifier' (REG_SZ) value */
391 swprintf(NameBuffer,
392 L"%.8S%.16S%.4S",
393 LunExtension->InquiryData.VendorId,
394 LunExtension->InquiryData.ProductId,
395 LunExtension->InquiryData.ProductRevisionLevel);
396 DPRINT(" Identifier = '%S'\n", NameBuffer);
397 RtlInitUnicodeString(&ValueName, L"Identifier");
398 Status = ZwSetValueKey(ScsiLunKey,
399 &ValueName,
400 0,
401 REG_SZ,
402 NameBuffer,
403 (ULONG)((wcslen(NameBuffer) + 1) * sizeof(WCHAR)));
404 if (!NT_SUCCESS(Status))
405 {
406 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
407 goto ByeBye;
408 }
409
410 /* Set 'Type' (REG_SZ) value */
411 /*
412 * See https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-ide-devices
413 * and https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-scsi-devices
414 * for a list of types with their human-readable forms.
415 */
416 switch (LunExtension->InquiryData.DeviceType)
417 {
418 case 0:
419 TypeName = L"DiskPeripheral";
420 break;
421 case 1:
422 TypeName = L"TapePeripheral";
423 break;
424 case 2:
425 TypeName = L"PrinterPeripheral";
426 break;
427 // case 3: "ProcessorPeripheral", classified as 'other': fall back to default case.
428 case 4:
429 TypeName = L"WormPeripheral";
430 break;
431 case 5:
432 TypeName = L"CdRomPeripheral";
433 break;
434 case 6:
435 TypeName = L"ScannerPeripheral";
436 break;
437 case 7:
438 TypeName = L"OpticalDiskPeripheral";
439 break;
440 case 8:
441 TypeName = L"MediumChangerPeripheral";
442 break;
443 case 9:
444 TypeName = L"CommunicationsPeripheral";
445 break;
446
447 /* New peripheral types (SCSI only) */
448 case 10: case 11:
449 TypeName = L"ASCPrePressGraphicsPeripheral";
450 break;
451 case 12:
452 TypeName = L"ArrayPeripheral";
453 break;
454 case 13:
455 TypeName = L"EnclosurePeripheral";
456 break;
457 case 14:
458 TypeName = L"RBCPeripheral";
459 break;
460 case 15:
461 TypeName = L"CardReaderPeripheral";
462 break;
463 case 16:
464 TypeName = L"BridgePeripheral";
465 break;
466
467 default:
468 TypeName = L"OtherPeripheral";
469 break;
470 }
471 DPRINT(" Type = '%S'\n", TypeName);
472 RtlInitUnicodeString(&ValueName, L"Type");
473 Status = ZwSetValueKey(ScsiLunKey,
474 &ValueName,
475 0,
476 REG_SZ,
477 TypeName,
478 (ULONG)((wcslen(TypeName) + 1) * sizeof(WCHAR)));
479 if (!NT_SUCCESS(Status))
480 {
481 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
482 goto ByeBye;
483 }
484
485 ZwClose(ScsiLunKey);
486 ScsiLunKey = NULL;
487 }
488
489 /* Close old target key */
490 if (ScsiTargetKey != NULL)
491 {
492 ZwClose(ScsiTargetKey);
493 ScsiTargetKey = NULL;
494 }
495 }
496
497 ZwClose(ScsiBusKey);
498 ScsiBusKey = NULL;
499 }
500
501 ByeBye:
502 if (ScsiLunKey != NULL)
503 ZwClose(ScsiLunKey);
504
505 if (ScsiInitiatorKey != NULL)
506 ZwClose(ScsiInitiatorKey);
507
508 if (ScsiTargetKey != NULL)
509 ZwClose(ScsiTargetKey);
510
511 if (ScsiBusKey != NULL)
512 ZwClose(ScsiBusKey);
513
514 if (ScsiPortKey != NULL)
515 ZwClose(ScsiPortKey);
516
517 DPRINT("SpiBuildDeviceMap() done\n");
518
519 return Status;
520 }