Fix merge r65567.
[reactos.git] / boot / freeldr / freeldr / disk / scsiport.c
1 #include <freeldr.h>
2
3 #define _SCSIPORT_
4
5 #include <ntddk.h>
6 #include <srb.h>
7 #include <scsi.h>
8 #include <ntddscsi.h>
9 #include <ntddstor.h>
10 #include <ntdddisk.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13
14 #undef ScsiPortLogError
15 #undef ScsiPortMoveMemory
16 #undef ScsiPortWritePortBufferUchar
17 #undef ScsiPortWritePortBufferUlong
18 #undef ScsiPortWritePortBufferUshort
19 #undef ScsiPortWritePortUchar
20 #undef ScsiPortWritePortUlong
21 #undef ScsiPortWritePortUshort
22 #undef ScsiPortWriteRegisterBufferUchar
23 #undef ScsiPortWriteRegisterBufferUlong
24 #undef ScsiPortWriteRegisterBufferUshort
25 #undef ScsiPortWriteRegisterUchar
26 #undef ScsiPortWriteRegisterUlong
27 #undef ScsiPortWriteRegisterUshort
28 #undef ScsiPortReadPortBufferUchar
29 #undef ScsiPortReadPortBufferUlong
30 #undef ScsiPortReadPortBufferUshort
31 #undef ScsiPortReadPortUchar
32 #undef ScsiPortReadPortUlong
33 #undef ScsiPortReadPortUshort
34 #undef ScsiPortReadRegisterBufferUchar
35 #undef ScsiPortReadRegisterBufferUlong
36 #undef ScsiPortReadRegisterBufferUshort
37 #undef ScsiPortReadRegisterUchar
38 #undef ScsiPortReadRegisterUlong
39 #undef ScsiPortReadRegisterUshort
40
41 #define NDEBUG
42 #include <debug.h>
43
44 #define SCSI_PORT_NEXT_REQUEST_READY 0x0008
45
46 #define TAG_SCSI_DEVEXT 'DscS'
47 #define TAG_SCSI_ACCESS_RANGES 'AscS'
48
49 DBG_DEFAULT_CHANNEL(SCSIPORT);
50
51 typedef struct
52 {
53 PVOID NonCachedExtension;
54
55 ULONG BusNum;
56 ULONG MaxTargedIds;
57
58 ULONG InterruptFlags;
59
60 /* SRB extension stuff */
61 ULONG SrbExtensionSize;
62 PVOID SrbExtensionBuffer;
63
64 IO_SCSI_CAPABILITIES PortCapabilities;
65
66 PHW_INITIALIZE HwInitialize;
67 PHW_STARTIO HwStartIo;
68 PHW_INTERRUPT HwInterrupt;
69 PHW_RESET_BUS HwResetBus;
70
71 /* DMA related stuff */
72 PADAPTER_OBJECT AdapterObject;
73
74 ULONG CommonBufferLength;
75
76 PVOID MiniPortDeviceExtension;
77 } SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
78
79 PSCSI_PORT_DEVICE_EXTENSION ScsiDeviceExtensions[SCSI_MAXIMUM_BUSES];
80
81 ULONG
82 ntohl(
83 IN ULONG Value)
84 {
85 FOUR_BYTE Dest;
86 PFOUR_BYTE Source = (PFOUR_BYTE)&Value;
87
88 Dest.Byte0 = Source->Byte3;
89 Dest.Byte1 = Source->Byte2;
90 Dest.Byte2 = Source->Byte1;
91 Dest.Byte3 = Source->Byte0;
92
93 return Dest.AsULong;
94 }
95
96 BOOLEAN
97 SpiSendSynchronousSrb(
98 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
99 IN PSCSI_REQUEST_BLOCK Srb)
100 {
101 BOOLEAN ret;
102
103 ASSERT(!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE));
104
105 /* HACK: handle lack of interrupts */
106 while (!(DeviceExtension->InterruptFlags & SCSI_PORT_NEXT_REQUEST_READY))
107 {
108 KeStallExecutionProcessor(100 * 1000);
109 DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension);
110 }
111
112 DeviceExtension->InterruptFlags &= ~SCSI_PORT_NEXT_REQUEST_READY;
113 Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
114
115 if (!DeviceExtension->HwStartIo(
116 DeviceExtension->MiniPortDeviceExtension,
117 Srb))
118 {
119 ExFreePool(Srb);
120 return FALSE;
121 }
122
123 /* HACK: handle lack of interrupts */
124 while (Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)
125 {
126 KeStallExecutionProcessor(100 * 1000);
127 DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension);
128 }
129
130 ret = SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS;
131 ExFreePool(Srb);
132
133 return ret;
134 }
135
136 typedef struct tagDISKCONTEXT
137 {
138 /* Device ID */
139 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
140 UCHAR PathId;
141 UCHAR TargetId;
142 UCHAR Lun;
143
144 /* Device characteristics */
145 ULONG SectorSize;
146 ULONGLONG SectorOffset;
147 ULONGLONG SectorCount;
148 ULONGLONG SectorNumber;
149 } DISKCONTEXT;
150
151 static LONG DiskClose(ULONG FileId)
152 {
153 DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
154
155 ExFreePool(Context);
156 return ESUCCESS;
157 }
158
159 static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
160 {
161 DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
162
163 RtlZeroMemory(Information, sizeof(FILEINFORMATION));
164 Information->EndingAddress.QuadPart = Context->SectorCount * Context->SectorSize;
165 Information->CurrentAddress.QuadPart = Context->SectorNumber * Context->SectorSize;
166
167 return ESUCCESS;
168 }
169
170 static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
171 {
172 PSCSI_REQUEST_BLOCK Srb;
173 PCDB Cdb;
174 READ_CAPACITY_DATA ReadCapacityBuffer;
175
176 DISKCONTEXT* Context;
177 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
178 ULONG ScsiBus, PathId, TargetId, Lun, Partition, PathSyntax;
179 ULONG SectorSize;
180 ULONGLONG SectorOffset = 0;
181 ULONGLONG SectorCount;
182
183 /* Parse ARC path */
184 if (!DissectArcPath2(Path, &ScsiBus, &TargetId, &Lun, &Partition, &PathSyntax))
185 return EINVAL;
186 if (PathSyntax != 0) /* scsi() format */
187 return EINVAL;
188 DeviceExtension = ScsiDeviceExtensions[ScsiBus];
189 PathId = ScsiBus - DeviceExtension->BusNum;
190
191 /* Get disk capacity and sector size */
192 Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
193 if (!Srb)
194 return ENOMEM;
195 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
196 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
197 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
198 Srb->PathId = (UCHAR)PathId;
199 Srb->TargetId = (UCHAR)TargetId;
200 Srb->Lun = (UCHAR)Lun;
201 Srb->CdbLength = 10;
202 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
203 Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
204 Srb->TimeOutValue = 5; /* in seconds */
205 Srb->DataBuffer = &ReadCapacityBuffer;
206 Cdb = (PCDB)Srb->Cdb;
207 Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
208 if (!SpiSendSynchronousSrb(DeviceExtension, Srb))
209 {
210 return EIO;
211 }
212
213 /* Transform result to host endianness */
214 SectorCount = ntohl(ReadCapacityBuffer.LogicalBlockAddress);
215 SectorSize = ntohl(ReadCapacityBuffer.BytesPerBlock);
216
217 if (Partition != 0)
218 {
219 /* Need to offset start of disk and length */
220 UNIMPLEMENTED;
221 return EIO;
222 }
223
224 Context = ExAllocatePool(PagedPool, sizeof(DISKCONTEXT));
225 if (!Context)
226 return ENOMEM;
227 Context->DeviceExtension = DeviceExtension;
228 Context->PathId = (UCHAR)PathId;
229 Context->TargetId = (UCHAR)TargetId;
230 Context->Lun = (UCHAR)Lun;
231 Context->SectorSize = SectorSize;
232 Context->SectorOffset = SectorOffset;
233 Context->SectorCount = SectorCount;
234 Context->SectorNumber = 0;
235 FsSetDeviceSpecific(*FileId, Context);
236
237 return ESUCCESS;
238 }
239
240 static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
241 {
242 DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
243 PSCSI_REQUEST_BLOCK Srb;
244 PCDB Cdb;
245 ULONG FullSectors, NbSectors;
246 ULONG Lba;
247
248 *Count = 0;
249
250 if (N == 0)
251 return ESUCCESS;
252
253 FullSectors = N / Context->SectorSize;
254 NbSectors = (N + Context->SectorSize - 1) / Context->SectorSize;
255 if (Context->SectorNumber + NbSectors >= Context->SectorCount)
256 return EINVAL;
257 if (FullSectors > 0xffff)
258 return EINVAL;
259
260 /* Read full sectors */
261 ASSERT(Context->SectorNumber < 0xFFFFFFFF);
262 Lba = (ULONG)Context->SectorNumber;
263 if (FullSectors > 0)
264 {
265 Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
266 if (!Srb)
267 return ENOMEM;
268
269 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
270 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
271 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
272 Srb->PathId = Context->PathId;
273 Srb->TargetId = Context->TargetId;
274 Srb->Lun = Context->Lun;
275 Srb->CdbLength = 10;
276 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
277 Srb->DataTransferLength = FullSectors * Context->SectorSize;
278 Srb->TimeOutValue = 5; /* in seconds */
279 Srb->DataBuffer = Buffer;
280 Cdb = (PCDB)Srb->Cdb;
281 Cdb->CDB10.OperationCode = SCSIOP_READ;
282 Cdb->CDB10.LogicalUnitNumber = Srb->Lun;
283 Cdb->CDB10.LogicalBlockByte0 = (Lba >> 24) & 0xff;
284 Cdb->CDB10.LogicalBlockByte1 = (Lba >> 16) & 0xff;
285 Cdb->CDB10.LogicalBlockByte2 = (Lba >> 8) & 0xff;
286 Cdb->CDB10.LogicalBlockByte3 = Lba & 0xff;
287 Cdb->CDB10.TransferBlocksMsb = (FullSectors >> 8) & 0xff;
288 Cdb->CDB10.TransferBlocksLsb = FullSectors & 0xff;
289 if (!SpiSendSynchronousSrb(Context->DeviceExtension, Srb))
290 {
291 return EIO;
292 }
293 Buffer = (PUCHAR)Buffer + FullSectors * Context->SectorSize;
294 N -= FullSectors * Context->SectorSize;
295 *Count += FullSectors * Context->SectorSize;
296 Lba += FullSectors;
297 }
298
299 /* Read incomplete last sector */
300 if (N > 0)
301 {
302 PUCHAR Sector;
303
304 Sector = ExAllocatePool(PagedPool, Context->SectorSize);
305 if (!Sector)
306 return ENOMEM;
307
308 Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
309 if (!Srb)
310 {
311 ExFreePool(Sector);
312 return ENOMEM;
313 }
314
315 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
316 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
317 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
318 Srb->PathId = Context->PathId;
319 Srb->TargetId = Context->TargetId;
320 Srb->Lun = Context->Lun;
321 Srb->CdbLength = 10;
322 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
323 Srb->DataTransferLength = Context->SectorSize;
324 Srb->TimeOutValue = 5; /* in seconds */
325 Srb->DataBuffer = Sector;
326 Cdb = (PCDB)Srb->Cdb;
327 Cdb->CDB10.OperationCode = SCSIOP_READ;
328 Cdb->CDB10.LogicalUnitNumber = Srb->Lun;
329 Cdb->CDB10.LogicalBlockByte0 = (Lba >> 24) & 0xff;
330 Cdb->CDB10.LogicalBlockByte1 = (Lba >> 16) & 0xff;
331 Cdb->CDB10.LogicalBlockByte2 = (Lba >> 8) & 0xff;
332 Cdb->CDB10.LogicalBlockByte3 = Lba & 0xff;
333 Cdb->CDB10.TransferBlocksMsb = 0;
334 Cdb->CDB10.TransferBlocksLsb = 1;
335 if (!SpiSendSynchronousSrb(Context->DeviceExtension, Srb))
336 {
337 ExFreePool(Sector);
338 return EIO;
339 }
340 RtlCopyMemory(Buffer, Sector, N);
341 *Count += N;
342 ExFreePool(Sector);
343 }
344
345 return ESUCCESS;
346 }
347
348 static LONG DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
349 {
350 DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
351
352 if (SeekMode != SeekAbsolute)
353 return EINVAL;
354 if (Position->QuadPart & (Context->SectorSize - 1))
355 return EINVAL;
356
357 Context->SectorNumber = Position->QuadPart / Context->SectorSize;
358 return ESUCCESS;
359 }
360
361 static const DEVVTBL DiskVtbl = {
362 DiskClose,
363 DiskGetFileInformation,
364 DiskOpen,
365 DiskRead,
366 DiskSeek,
367 };
368
369 NTSTATUS
370 SpiCreatePortConfig(
371 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
372 IN PHW_INITIALIZATION_DATA HwInitData,
373 OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
374 IN BOOLEAN ZeroStruct)
375 {
376 ULONG Bus;
377
378 /* Zero out the struct if told so */
379 if (ZeroStruct)
380 {
381 /* First zero the portconfig */
382 RtlZeroMemory(ConfigInfo, sizeof(PORT_CONFIGURATION_INFORMATION));
383
384 /* Initialize the struct */
385 ConfigInfo->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
386 ConfigInfo->AdapterInterfaceType = HwInitData->AdapterInterfaceType;
387 ConfigInfo->InterruptMode = Latched;
388 ConfigInfo->DmaChannel = SP_UNINITIALIZED_VALUE;
389 ConfigInfo->DmaPort = SP_UNINITIALIZED_VALUE;
390 ConfigInfo->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
391 ConfigInfo->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS_PER_BUS;
392
393 /* Store parameters */
394 ConfigInfo->NeedPhysicalAddresses = HwInitData->NeedPhysicalAddresses;
395 ConfigInfo->MapBuffers = HwInitData->MapBuffers;
396 ConfigInfo->AutoRequestSense = HwInitData->AutoRequestSense;
397 ConfigInfo->ReceiveEvent = HwInitData->ReceiveEvent;
398 ConfigInfo->TaggedQueuing = HwInitData->TaggedQueuing;
399 ConfigInfo->MultipleRequestPerLu = HwInitData->MultipleRequestPerLu;
400
401 /* Get the disk usage */
402 ConfigInfo->AtdiskPrimaryClaimed = FALSE; // FIXME
403 ConfigInfo->AtdiskSecondaryClaimed = FALSE; // FIXME
404
405 /* Initiator bus id is not set */
406 for (Bus = 0; Bus < 8; Bus++)
407 ConfigInfo->InitiatorBusId[Bus] = (CCHAR)SP_UNINITIALIZED_VALUE;
408 }
409
410 ConfigInfo->NumberOfPhysicalBreaks = 17;
411
412 return STATUS_SUCCESS;
413 }
414
415 VOID
416 __cdecl
417 ScsiDebugPrint(
418 IN ULONG DebugPrintLevel,
419 IN PCCHAR DebugMessage,
420 IN ...)
421 {
422 va_list ap;
423 CHAR Buffer[512];
424 ULONG Length;
425
426 if (DebugPrintLevel > 10)
427 return;
428
429 va_start(ap, DebugMessage);
430
431 /* Construct a string */
432 Length = _vsnprintf(Buffer, 512, DebugMessage, ap);
433
434 /* Check if we went past the buffer */
435 if (Length == MAXULONG)
436 {
437 /* Terminate it if we went over-board */
438 Buffer[sizeof(Buffer) - 1] = '\0';
439
440 /* Put maximum */
441 Length = sizeof(Buffer);
442 }
443
444 /* Print the message */
445 TRACE("%s", Buffer);
446
447 /* Cleanup */
448 va_end(ap);
449 }
450
451 VOID
452 NTAPI
453 ScsiPortCompleteRequest(
454 IN PVOID HwDeviceExtension,
455 IN UCHAR PathId,
456 IN UCHAR TargetId,
457 IN UCHAR Lun,
458 IN UCHAR SrbStatus)
459 {
460 // FIXME
461 UNIMPLEMENTED;
462 }
463
464 #undef ScsiPortConvertPhysicalAddressToUlong
465 ULONG
466 NTAPI
467 ScsiPortConvertPhysicalAddressToUlong(
468 IN SCSI_PHYSICAL_ADDRESS Address)
469 {
470 return Address.LowPart;
471 }
472
473 SCSI_PHYSICAL_ADDRESS
474 NTAPI
475 ScsiPortConvertUlongToPhysicalAddress(
476 IN ULONG_PTR UlongAddress)
477 {
478 SCSI_PHYSICAL_ADDRESS Address;
479
480 Address.QuadPart = UlongAddress;
481 return Address;
482 }
483
484 VOID
485 NTAPI
486 ScsiPortFlushDma(
487 IN PVOID DeviceExtension)
488 {
489 // FIXME
490 UNIMPLEMENTED;
491 }
492
493 VOID
494 NTAPI
495 ScsiPortFreeDeviceBase(
496 IN PVOID HwDeviceExtension,
497 IN PVOID MappedAddress)
498 {
499 // Nothing to do
500 }
501
502 ULONG
503 NTAPI
504 ScsiPortGetBusData(
505 IN PVOID DeviceExtension,
506 IN ULONG BusDataType,
507 IN ULONG SystemIoBusNumber,
508 IN ULONG SlotNumber,
509 IN PVOID Buffer,
510 IN ULONG Length)
511 {
512 return HalGetBusDataByOffset(BusDataType, SystemIoBusNumber, SlotNumber, Buffer, 0, Length);
513 }
514
515 PVOID
516 NTAPI
517 ScsiPortGetDeviceBase(
518 IN PVOID HwDeviceExtension,
519 IN INTERFACE_TYPE BusType,
520 IN ULONG SystemIoBusNumber,
521 IN SCSI_PHYSICAL_ADDRESS IoAddress,
522 IN ULONG NumberOfBytes,
523 IN BOOLEAN InIoSpace)
524 {
525 PHYSICAL_ADDRESS TranslatedAddress;
526 ULONG AddressSpace;
527
528 AddressSpace = (ULONG)InIoSpace;
529 if (HalTranslateBusAddress(BusType,
530 SystemIoBusNumber,
531 IoAddress,
532 &AddressSpace,
533 &TranslatedAddress) == FALSE)
534 {
535 return NULL;
536 }
537
538 /* I/O space */
539 if (AddressSpace != 0)
540 return (PVOID)TranslatedAddress.u.LowPart;
541
542 // FIXME
543 UNIMPLEMENTED;
544 return (PVOID)IoAddress.LowPart;
545 }
546
547 PVOID
548 NTAPI
549 ScsiPortGetLogicalUnit(
550 IN PVOID HwDeviceExtension,
551 IN UCHAR PathId,
552 IN UCHAR TargetId,
553 IN UCHAR Lun)
554 {
555 // FIXME
556 UNIMPLEMENTED;
557 return NULL;
558 }
559
560 SCSI_PHYSICAL_ADDRESS
561 NTAPI
562 ScsiPortGetPhysicalAddress(
563 IN PVOID HwDeviceExtension,
564 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
565 IN PVOID VirtualAddress,
566 OUT ULONG *Length)
567 {
568 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
569 SCSI_PHYSICAL_ADDRESS PhysicalAddress;
570 ULONG BufferLength = 0;
571 ULONG Offset;
572
573 TRACE("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
574 HwDeviceExtension, Srb, VirtualAddress, Length);
575
576 DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
577
578 if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)
579 {
580 /* Simply look it up in the allocated common buffer */
581 Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer;
582
583 BufferLength = DeviceExtension->CommonBufferLength - Offset;
584 PhysicalAddress.QuadPart = Offset;
585 }
586 else
587 {
588 /* Nothing */
589 *Length = 0;
590 PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
591 }
592
593 *Length = BufferLength;
594 return PhysicalAddress;
595 }
596
597 PSCSI_REQUEST_BLOCK
598 NTAPI
599 ScsiPortGetSrb(
600 IN PVOID DeviceExtension,
601 IN UCHAR PathId,
602 IN UCHAR TargetId,
603 IN UCHAR Lun,
604 IN LONG QueueTag)
605 {
606 // FIXME
607 UNIMPLEMENTED;
608 return NULL;
609 }
610
611 NTSTATUS
612 SpiAllocateCommonBuffer(
613 IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
614 IN ULONG NonCachedSize)
615 {
616 PVOID CommonBuffer;
617 ULONG CommonBufferLength, BufSize;
618
619 /* If size is 0, set it to 16 */
620 if (!DeviceExtension->SrbExtensionSize)
621 DeviceExtension->SrbExtensionSize = 16;
622
623 /* Calculate size */
624 BufSize = DeviceExtension->SrbExtensionSize;
625
626 /* Round it */
627 BufSize = (BufSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
628
629 /* Sum up into the total common buffer length, and round it to page size */
630 CommonBufferLength =
631 ROUND_TO_PAGES(NonCachedSize);
632
633 /* Allocate it */
634 if (!DeviceExtension->AdapterObject)
635 {
636 /* From nonpaged pool if there is no DMA */
637 CommonBuffer = ExAllocatePool(NonPagedPool, CommonBufferLength);
638 }
639 else
640 {
641 /* Perform a full request since we have a DMA adapter*/
642 UNIMPLEMENTED;
643 CommonBuffer = NULL;
644 }
645
646 /* Fail in case of error */
647 if (!CommonBuffer)
648 return STATUS_INSUFFICIENT_RESOURCES;
649
650 /* Zero it */
651 RtlZeroMemory(CommonBuffer, CommonBufferLength);
652
653 /* Store its size in Device Extension */
654 DeviceExtension->CommonBufferLength = CommonBufferLength;
655
656 /* SrbExtension buffer is located at the beginning of the buffer */
657 DeviceExtension->SrbExtensionBuffer = CommonBuffer;
658
659 /* Non-cached extension buffer is located at the end of
660 the common buffer */
661 if (NonCachedSize)
662 {
663 CommonBufferLength -= NonCachedSize;
664 DeviceExtension->NonCachedExtension = (PUCHAR)CommonBuffer + CommonBufferLength;
665 }
666 else
667 {
668 DeviceExtension->NonCachedExtension = NULL;
669 }
670
671 return STATUS_SUCCESS;
672 }
673
674 PVOID
675 NTAPI
676 ScsiPortGetUncachedExtension(
677 IN PVOID HwDeviceExtension,
678 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
679 IN ULONG NumberOfBytes)
680 {
681 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
682 DEVICE_DESCRIPTION DeviceDescription;
683 ULONG MapRegistersCount;
684 NTSTATUS Status;
685
686 TRACE("ScsiPortGetUncachedExtension(%p %p %lu)\n",
687 HwDeviceExtension, ConfigInfo, NumberOfBytes);
688
689 DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
690
691 /* Check for allocated common DMA buffer */
692 if (DeviceExtension->SrbExtensionBuffer != NULL)
693 {
694 return NULL;
695 }
696
697 /* Check for DMA adapter object */
698 if (DeviceExtension->AdapterObject == NULL)
699 {
700 /* Initialize DMA adapter description */
701 RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
702
703 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
704 DeviceDescription.Master = ConfigInfo->Master;
705 DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
706 DeviceDescription.DemandMode = ConfigInfo->DemandMode;
707 DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
708 DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
709 DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
710 DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
711 DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
712 DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
713 DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
714 DeviceDescription.DmaPort = ConfigInfo->DmaPort;
715
716 /* Get a DMA adapter object */
717 #if 0
718 DeviceExtension->AdapterObject =
719 HalGetAdapter(&DeviceDescription, &MapRegistersCount);
720
721 /* Fail in case of error */
722 if (DeviceExtension->AdapterObject == NULL)
723 {
724 return NULL;
725 }
726 #else
727 MapRegistersCount = 0;
728 #endif
729
730 /* Set number of physical breaks */
731 if (ConfigInfo->NumberOfPhysicalBreaks != 0 &&
732 MapRegistersCount > ConfigInfo->NumberOfPhysicalBreaks)
733 {
734 DeviceExtension->PortCapabilities.MaximumPhysicalPages =
735 ConfigInfo->NumberOfPhysicalBreaks;
736 }
737 else
738 {
739 DeviceExtension->PortCapabilities.MaximumPhysicalPages = MapRegistersCount;
740 }
741 }
742
743 /* Update Srb extension size */
744 if (DeviceExtension->SrbExtensionSize != ConfigInfo->SrbExtensionSize)
745 DeviceExtension->SrbExtensionSize = ConfigInfo->SrbExtensionSize;
746
747 /* Allocate a common DMA buffer */
748 Status = SpiAllocateCommonBuffer(DeviceExtension, NumberOfBytes);
749
750 if (!NT_SUCCESS(Status))
751 {
752 TRACE("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status);
753 return NULL;
754 }
755
756 return DeviceExtension->NonCachedExtension;
757 }
758
759 PVOID
760 NTAPI
761 ScsiPortGetVirtualAddress(
762 IN PVOID HwDeviceExtension,
763 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
764 {
765 // FIXME
766 UNIMPLEMENTED;
767 return NULL;
768 }
769
770 VOID
771 SpiScanDevice(
772 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
773 IN PCHAR ArcName,
774 IN ULONG ScsiBus,
775 IN ULONG TargetId,
776 IN ULONG Lun)
777 {
778 ULONG FileId, i;
779 ULONG Status;
780 NTSTATUS ret;
781 struct _DRIVE_LAYOUT_INFORMATION *PartitionBuffer;
782 CHAR PartitionName[64];
783
784 /* Register device with partition(0) suffix */
785 sprintf(PartitionName, "%spartition(0)", ArcName);
786 FsRegisterDevice(PartitionName, &DiskVtbl);
787
788 /* Read device partition table */
789 Status = ArcOpen(PartitionName, OpenReadOnly, &FileId);
790 if (Status == ESUCCESS)
791 {
792 ret = HALDISPATCH->HalIoReadPartitionTable((PDEVICE_OBJECT)FileId, 512, FALSE, &PartitionBuffer);
793 if (NT_SUCCESS(ret))
794 {
795 for (i = 0; i < PartitionBuffer->PartitionCount; i++)
796 {
797 if (PartitionBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED)
798 {
799 sprintf(PartitionName, "%spartition(%lu)",
800 ArcName, PartitionBuffer->PartitionEntry[i].PartitionNumber);
801 FsRegisterDevice(PartitionName, &DiskVtbl);
802 }
803 }
804 ExFreePool(PartitionBuffer);
805 }
806 ArcClose(FileId);
807 }
808 }
809
810 VOID
811 SpiScanAdapter(
812 IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
813 IN ULONG ScsiBus,
814 IN UCHAR PathId)
815 {
816 CHAR ArcName[64];
817 PSCSI_REQUEST_BLOCK Srb;
818 PCDB Cdb;
819 INQUIRYDATA InquiryBuffer;
820 UCHAR TargetId;
821 UCHAR Lun;
822
823 if (!DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, PathId))
824 {
825 return;
826 }
827
828 /* Remember the extension */
829 ScsiDeviceExtensions[ScsiBus] = DeviceExtension;
830
831 for (TargetId = 0; TargetId < DeviceExtension->MaxTargedIds; TargetId++)
832 {
833 Lun = 0;
834 do
835 {
836 TRACE("Scanning SCSI device %d.%d.%d\n",
837 ScsiBus, TargetId, Lun);
838
839 Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
840 if (!Srb)
841 break;
842 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
843 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
844 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
845 Srb->PathId = PathId;
846 Srb->TargetId = TargetId;
847 Srb->Lun = Lun;
848 Srb->CdbLength = 6;
849 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
850 Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
851 Srb->TimeOutValue = 5; /* in seconds */
852 Srb->DataBuffer = &InquiryBuffer;
853 Cdb = (PCDB)Srb->Cdb;
854 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
855 Cdb->CDB6INQUIRY.LogicalUnitNumber = Srb->Lun;
856 Cdb->CDB6INQUIRY.AllocationLength = (UCHAR)Srb->DataTransferLength;
857 if (!SpiSendSynchronousSrb(DeviceExtension, Srb))
858 {
859 /* Don't check next LUNs */
860 break;
861 }
862
863 /* Device exists, create its ARC name */
864 if (InquiryBuffer.RemovableMedia)
865 {
866 sprintf(ArcName, "scsi(%ld)cdrom(%d)fdisk(%d)",
867 ScsiBus, TargetId, Lun);
868 FsRegisterDevice(ArcName, &DiskVtbl);
869 }
870 else
871 {
872 sprintf(ArcName, "scsi(%ld)disk(%d)rdisk(%d)",
873 ScsiBus, TargetId, Lun);
874 /* Now, check if it has partitions */
875 SpiScanDevice(DeviceExtension, ArcName, PathId, TargetId, Lun);
876 }
877
878 /* Check next LUN */
879 Lun++;
880 } while (Lun < SCSI_MAXIMUM_LOGICAL_UNITS);
881 }
882 }
883
884 VOID
885 SpiResourceToConfig(
886 IN PHW_INITIALIZATION_DATA HwInitializationData,
887 IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
888 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig)
889 {
890 PACCESS_RANGE AccessRange;
891 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData;
892 ULONG RangeNumber;
893 ULONG Index;
894
895 RangeNumber = 0;
896
897 /* Loop through all entries */
898 for (Index = 0; Index < ResourceDescriptor->PartialResourceList.Count; Index++)
899 {
900 PartialData = &ResourceDescriptor->PartialResourceList.PartialDescriptors[Index];
901
902 switch (PartialData->Type)
903 {
904 case CmResourceTypePort:
905 /* Copy access ranges */
906 if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
907 {
908 TRACE("Got port at 0x%I64x, len 0x%x\n",
909 PartialData->u.Port.Start.QuadPart, PartialData->u.Port.Length);
910 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
911
912 AccessRange->RangeStart = PartialData->u.Port.Start;
913 AccessRange->RangeLength = PartialData->u.Port.Length;
914
915 AccessRange->RangeInMemory = FALSE;
916 RangeNumber++;
917 }
918 break;
919
920 case CmResourceTypeMemory:
921 /* Copy access ranges */
922 if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
923 {
924 TRACE("Got memory at 0x%I64x, len 0x%x\n",
925 PartialData->u.Memory.Start.QuadPart, PartialData->u.Memory.Length);
926 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
927
928 AccessRange->RangeStart = PartialData->u.Memory.Start;
929 AccessRange->RangeLength = PartialData->u.Memory.Length;
930
931 AccessRange->RangeInMemory = TRUE;
932 RangeNumber++;
933 }
934 break;
935
936 case CmResourceTypeInterrupt:
937 /* Copy interrupt data */
938 TRACE("Got interrupt level %d, vector %d\n",
939 PartialData->u.Interrupt.Level, PartialData->u.Interrupt.Vector);
940 PortConfig->BusInterruptLevel = PartialData->u.Interrupt.Level;
941 PortConfig->BusInterruptVector = PartialData->u.Interrupt.Vector;
942
943 /* Set interrupt mode accordingly to the resource */
944 if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
945 {
946 PortConfig->InterruptMode = Latched;
947 }
948 else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
949 {
950 PortConfig->InterruptMode = LevelSensitive;
951 }
952 break;
953
954 case CmResourceTypeDma:
955 TRACE("Got DMA channel %d, port %d\n",
956 PartialData->u.Dma.Channel, PartialData->u.Dma.Port);
957 PortConfig->DmaChannel = PartialData->u.Dma.Channel;
958 PortConfig->DmaPort = PartialData->u.Dma.Port;
959 break;
960 }
961 }
962 }
963
964 BOOLEAN
965 SpiGetPciConfigData(
966 IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
967 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
968 IN ULONG BusNumber,
969 IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
970 {
971 PCI_COMMON_CONFIG PciConfig;
972 PCI_SLOT_NUMBER SlotNumber;
973 ULONG DataSize;
974 ULONG DeviceNumber;
975 ULONG FunctionNumber;
976 CHAR VendorIdString[8];
977 CHAR DeviceIdString[8];
978 PCM_RESOURCE_LIST ResourceList = NULL;
979 NTSTATUS Status;
980
981 SlotNumber.u.AsULONG = 0;
982
983 /* Loop through all devices */
984 for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
985 {
986 SlotNumber.u.bits.DeviceNumber = DeviceNumber;
987
988 /* Loop through all functions */
989 for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
990 {
991 SlotNumber.u.bits.FunctionNumber = FunctionNumber;
992
993 /* Get PCI config bytes */
994 DataSize = HalGetBusDataByOffset(
995 PCIConfiguration,
996 BusNumber,
997 SlotNumber.u.AsULONG,
998 &PciConfig,
999 0,
1000 sizeof(ULONG));
1001
1002 /* If result of HalGetBusData is 0, then the bus is wrong */
1003 if (DataSize == 0)
1004 return FALSE;
1005
1006 /* If result is PCI_INVALID_VENDORID, then this device has no more
1007 "Functions" */
1008 if (PciConfig.VendorID == PCI_INVALID_VENDORID)
1009 break;
1010
1011 sprintf(VendorIdString, "%04hx", PciConfig.VendorID);
1012 sprintf(DeviceIdString, "%04hx", PciConfig.DeviceID);
1013
1014 if (_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) ||
1015 _strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength))
1016 {
1017 /* It is not our device */
1018 continue;
1019 }
1020
1021 TRACE( "Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1022 PciConfig.VendorID, PciConfig.DeviceID,
1023 BusNumber,
1024 SlotNumber.u.bits.DeviceNumber, SlotNumber.u.bits.FunctionNumber);
1025
1026 Status = HalAssignSlotResources(NULL,
1027 NULL,
1028 NULL,
1029 NULL,
1030 PCIBus,
1031 BusNumber,
1032 SlotNumber.u.AsULONG,
1033 &ResourceList);
1034
1035 if (!NT_SUCCESS(Status))
1036 break;
1037
1038 /* Create configuration information */
1039 SpiResourceToConfig(HwInitializationData,
1040 ResourceList->List,
1041 PortConfig);
1042
1043 /* Free the resource list */
1044 ExFreePool(ResourceList);
1045
1046 /* Set dev & fn numbers */
1047 NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
1048 NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1;
1049
1050 /* Save the slot number */
1051 PortConfig->SlotNumber = SlotNumber.u.AsULONG;
1052
1053 return TRUE;
1054 }
1055 NextSlotNumber->u.bits.FunctionNumber = 0;
1056 }
1057
1058 NextSlotNumber->u.bits.DeviceNumber = 0;
1059
1060 return FALSE;
1061 }
1062
1063 ULONG
1064 NTAPI
1065 ScsiPortInitialize(
1066 IN PVOID Argument1,
1067 IN PVOID Argument2,
1068 IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
1069 IN PVOID HwContext OPTIONAL)
1070 {
1071 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1072 ULONG DeviceExtensionSize;
1073 PORT_CONFIGURATION_INFORMATION PortConfig;
1074 BOOLEAN Again;
1075 BOOLEAN FirstConfigCall = TRUE;
1076 PCI_SLOT_NUMBER SlotNumber;
1077 UCHAR ScsiBus;
1078 NTSTATUS Status;
1079
1080 if (HwInitializationData->HwInitializationDataSize != sizeof(HW_INITIALIZATION_DATA))
1081 {
1082 return STATUS_INVALID_PARAMETER;
1083 }
1084
1085 /* Check params for validity */
1086 if ((HwInitializationData->HwInitialize == NULL) ||
1087 (HwInitializationData->HwStartIo == NULL) ||
1088 (HwInitializationData->HwInterrupt == NULL) ||
1089 (HwInitializationData->HwFindAdapter == NULL) ||
1090 (HwInitializationData->HwResetBus == NULL))
1091 {
1092 return STATUS_INVALID_PARAMETER;
1093 }
1094
1095 /* Zero starting slot number */
1096 SlotNumber.u.AsULONG = 0;
1097
1098 while (TRUE)
1099 {
1100 Again = FALSE;
1101
1102 DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) + HwInitializationData->DeviceExtensionSize;
1103 DeviceExtension = FrLdrTempAlloc(DeviceExtensionSize, TAG_SCSI_DEVEXT);
1104 if (!DeviceExtension)
1105 {
1106 return STATUS_NO_MEMORY;
1107 }
1108 RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
1109 DeviceExtension->InterruptFlags = SCSI_PORT_NEXT_REQUEST_READY;
1110 DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
1111 DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
1112 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
1113 DeviceExtension->HwResetBus = HwInitializationData->HwResetBus;
1114 DeviceExtension->MiniPortDeviceExtension = (PVOID)(DeviceExtension + 1);
1115
1116 Status = SpiCreatePortConfig(DeviceExtension,
1117 HwInitializationData,
1118 &PortConfig,
1119 FirstConfigCall);
1120 if (Status != STATUS_SUCCESS)
1121 {
1122 FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
1123 return Status;
1124 }
1125
1126 PortConfig.NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
1127 PortConfig.AccessRanges = FrLdrTempAlloc(sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges,
1128 TAG_SCSI_ACCESS_RANGES);
1129 if (!PortConfig.AccessRanges)
1130 {
1131 FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
1132 return STATUS_NO_MEMORY;
1133 }
1134 RtlZeroMemory(PortConfig.AccessRanges, sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges);
1135
1136 /* Search for matching PCI device */
1137 if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
1138 (HwInitializationData->VendorIdLength > 0) &&
1139 (HwInitializationData->VendorId != NULL) &&
1140 (HwInitializationData->DeviceIdLength > 0) &&
1141 (HwInitializationData->DeviceId != NULL))
1142 {
1143 PortConfig.BusInterruptLevel = 0;
1144
1145 /* Get PCI device data */
1146 TRACE("VendorId '%.*s' DeviceId '%.*s'\n",
1147 HwInitializationData->VendorIdLength,
1148 HwInitializationData->VendorId,
1149 HwInitializationData->DeviceIdLength,
1150 HwInitializationData->DeviceId);
1151
1152 if (!SpiGetPciConfigData(HwInitializationData,
1153 &PortConfig,
1154 0, /* FIXME */
1155 &SlotNumber))
1156 {
1157 /* Continue to the next bus, nothing here */
1158 FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
1159 return STATUS_INTERNAL_ERROR;
1160 }
1161
1162 if (!PortConfig.BusInterruptLevel)
1163 {
1164 /* Bypass this slot, because no interrupt was assigned */
1165 FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
1166 return STATUS_INTERNAL_ERROR;
1167 }
1168 }
1169
1170 if (HwInitializationData->HwFindAdapter(
1171 DeviceExtension->MiniPortDeviceExtension,
1172 HwContext,
1173 NULL,
1174 NULL,
1175 &PortConfig,
1176 &Again) != SP_RETURN_FOUND)
1177 {
1178 FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
1179 return STATUS_INTERNAL_ERROR;
1180 }
1181
1182 /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
1183 if (PortConfig.MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)
1184 DeviceExtension->MaxTargedIds = SCSI_MAXIMUM_TARGETS_PER_BUS;
1185 else
1186 DeviceExtension->MaxTargedIds = PortConfig.MaximumNumberOfTargets;
1187
1188 DeviceExtension->BusNum = PortConfig.SystemIoBusNumber;
1189
1190 TRACE("Adapter found: buses = %d, targets = %d\n",
1191 PortConfig.NumberOfBuses, DeviceExtension->MaxTargedIds);
1192
1193 /* Initialize adapter */
1194 if (!DeviceExtension->HwInitialize(DeviceExtension->MiniPortDeviceExtension))
1195 {
1196 FrLdrTempFree(DeviceExtension, TAG_SCSI_DEVEXT);
1197 return STATUS_INTERNAL_ERROR;
1198 }
1199
1200 /* Scan bus */
1201 for (ScsiBus = 0; ScsiBus < PortConfig.NumberOfBuses; ScsiBus++)
1202 {
1203 SpiScanAdapter(DeviceExtension, PortConfig.SystemIoBusNumber, ScsiBus);
1204 PortConfig.SystemIoBusNumber++;
1205 }
1206
1207 FirstConfigCall = FALSE;
1208 if (!Again)
1209 {
1210 break;
1211 }
1212 }
1213
1214 return STATUS_SUCCESS;
1215 }
1216
1217 VOID
1218 NTAPI
1219 ScsiPortIoMapTransfer(
1220 IN PVOID HwDeviceExtension,
1221 IN PSCSI_REQUEST_BLOCK Srb,
1222 IN PVOID LogicalAddress,
1223 IN ULONG Length)
1224 {
1225 // FIXME
1226 UNIMPLEMENTED;
1227 }
1228
1229 VOID
1230 NTAPI
1231 ScsiPortLogError(
1232 IN PVOID HwDeviceExtension,
1233 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
1234 IN UCHAR PathId,
1235 IN UCHAR TargetId,
1236 IN UCHAR Lun,
1237 IN ULONG ErrorCode,
1238 IN ULONG UniqueId)
1239 {
1240 // FIXME
1241 UNIMPLEMENTED;
1242 }
1243
1244 VOID
1245 NTAPI
1246 ScsiPortMoveMemory(
1247 IN PVOID WriteBuffer,
1248 IN PVOID ReadBuffer,
1249 IN ULONG Length)
1250 {
1251 RtlMoveMemory(WriteBuffer, ReadBuffer, Length);
1252 }
1253
1254 VOID
1255 __cdecl
1256 ScsiPortNotification(
1257 IN SCSI_NOTIFICATION_TYPE NotificationType,
1258 IN PVOID HwDeviceExtension,
1259 IN ...)
1260 {
1261 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1262 PSCSI_REQUEST_BLOCK Srb;
1263 va_list ap;
1264
1265 DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
1266
1267 va_start(ap, HwDeviceExtension);
1268
1269 switch (NotificationType)
1270 {
1271 case RequestComplete:
1272 /* Mask the SRB as completed */
1273 Srb = va_arg(ap, PSCSI_REQUEST_BLOCK);
1274 Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
1275 break;
1276
1277 case NextRequest:
1278 /* Say that device is ready */
1279 DeviceExtension->InterruptFlags |= SCSI_PORT_NEXT_REQUEST_READY;
1280 break;
1281
1282 default:
1283 // FIXME
1284 UNIMPLEMENTED;
1285 }
1286
1287 va_end(ap);
1288 }
1289
1290 VOID
1291 NTAPI
1292 ScsiPortReadPortBufferUchar(
1293 IN PUCHAR Port,
1294 OUT PUCHAR Buffer,
1295 IN ULONG Count)
1296 {
1297 __inbytestring(H2I(Port), Buffer, Count);
1298 }
1299
1300 VOID
1301 NTAPI
1302 ScsiPortReadPortBufferUlong(
1303 IN PULONG Port,
1304 OUT PULONG Buffer,
1305 IN ULONG Count)
1306 {
1307 __indwordstring(H2I(Port), Buffer, Count);
1308 }
1309
1310 VOID
1311 NTAPI
1312 ScsiPortReadPortBufferUshort(
1313 IN PUSHORT Port,
1314 OUT PUSHORT Buffer,
1315 IN ULONG Count)
1316 {
1317 __inwordstring(H2I(Port), Buffer, Count);
1318 }
1319
1320 UCHAR
1321 NTAPI
1322 ScsiPortReadPortUchar(
1323 IN PUCHAR Port)
1324 {
1325 TRACE("ScsiPortReadPortUchar(%p)\n", Port);
1326
1327 return READ_PORT_UCHAR(Port);
1328 }
1329
1330 ULONG
1331 NTAPI
1332 ScsiPortReadPortUlong(
1333 IN PULONG Port)
1334 {
1335 return READ_PORT_ULONG(Port);
1336 }
1337
1338 USHORT
1339 NTAPI
1340 ScsiPortReadPortUshort(
1341 IN PUSHORT Port)
1342 {
1343 return READ_PORT_USHORT(Port);
1344 }
1345
1346 VOID
1347 NTAPI
1348 ScsiPortReadRegisterBufferUchar(
1349 IN PUCHAR Register,
1350 IN PUCHAR Buffer,
1351 IN ULONG Count)
1352 {
1353 // FIXME
1354 UNIMPLEMENTED;
1355 }
1356
1357 VOID
1358 NTAPI
1359 ScsiPortReadRegisterBufferUlong(
1360 IN PULONG Register,
1361 IN PULONG Buffer,
1362 IN ULONG Count)
1363 {
1364 // FIXME
1365 UNIMPLEMENTED;
1366 }
1367
1368 VOID
1369 NTAPI
1370 ScsiPortReadRegisterBufferUshort(
1371 IN PUSHORT Register,
1372 IN PUSHORT Buffer,
1373 IN ULONG Count)
1374 {
1375 // FIXME
1376 UNIMPLEMENTED;
1377 }
1378
1379 UCHAR
1380 NTAPI
1381 ScsiPortReadRegisterUchar(
1382 IN PUCHAR Register)
1383 {
1384 return READ_REGISTER_UCHAR(Register);
1385 }
1386
1387 ULONG
1388 NTAPI
1389 ScsiPortReadRegisterUlong(
1390 IN PULONG Register)
1391 {
1392 return READ_REGISTER_ULONG(Register);
1393 }
1394
1395 USHORT
1396 NTAPI
1397 ScsiPortReadRegisterUshort(
1398 IN PUSHORT Register)
1399 {
1400 return READ_REGISTER_USHORT(Register);
1401 }
1402
1403 ULONG
1404 NTAPI
1405 ScsiPortSetBusDataByOffset(
1406 IN PVOID DeviceExtension,
1407 IN ULONG BusDataType,
1408 IN ULONG SystemIoBusNumber,
1409 IN ULONG SlotNumber,
1410 IN PVOID Buffer,
1411 IN ULONG Offset,
1412 IN ULONG Length)
1413 {
1414 // FIXME
1415 UNIMPLEMENTED;
1416 return 0;
1417 }
1418
1419 VOID
1420 NTAPI
1421 ScsiPortStallExecution(
1422 IN ULONG Delay)
1423 {
1424 KeStallExecutionProcessor(Delay);
1425 }
1426
1427 BOOLEAN
1428 NTAPI
1429 ScsiPortValidateRange(
1430 IN PVOID HwDeviceExtension,
1431 IN INTERFACE_TYPE BusType,
1432 IN ULONG SystemIoBusNumber,
1433 IN SCSI_PHYSICAL_ADDRESS IoAddress,
1434 IN ULONG NumberOfBytes,
1435 IN BOOLEAN InIoSpace)
1436 {
1437 // FIXME
1438 UNIMPLEMENTED;
1439 return TRUE;
1440 }
1441
1442 #if 0
1443 // ScsiPortWmi*
1444 #endif
1445
1446
1447 VOID
1448 NTAPI
1449 ScsiPortWritePortBufferUchar(
1450 IN PUCHAR Port,
1451 IN PUCHAR Buffer,
1452 IN ULONG Count)
1453 {
1454 __outbytestring(H2I(Port), Buffer, Count);
1455 }
1456
1457 VOID
1458 NTAPI
1459 ScsiPortWritePortBufferUlong(
1460 IN PULONG Port,
1461 IN PULONG Buffer,
1462 IN ULONG Count)
1463 {
1464 __outdwordstring(H2I(Port), Buffer, Count);
1465 }
1466
1467 VOID
1468 NTAPI
1469 ScsiPortWritePortBufferUshort(
1470 IN PUSHORT Port,
1471 IN PUSHORT Buffer,
1472 IN ULONG Count)
1473 {
1474 __outwordstring(H2I(Port), Buffer, Count);
1475 }
1476
1477 VOID
1478 NTAPI
1479 ScsiPortWritePortUchar(
1480 IN PUCHAR Port,
1481 IN UCHAR Value)
1482 {
1483 WRITE_PORT_UCHAR(Port, Value);
1484 }
1485
1486 VOID
1487 NTAPI
1488 ScsiPortWritePortUlong(
1489 IN PULONG Port,
1490 IN ULONG Value)
1491 {
1492 WRITE_PORT_ULONG(Port, Value);
1493 }
1494
1495 VOID
1496 NTAPI
1497 ScsiPortWritePortUshort(
1498 IN PUSHORT Port,
1499 IN USHORT Value)
1500 {
1501 WRITE_PORT_USHORT(Port, Value);
1502 }
1503
1504 VOID
1505 NTAPI
1506 ScsiPortWriteRegisterBufferUchar(
1507 IN PUCHAR Register,
1508 IN PUCHAR Buffer,
1509 IN ULONG Count)
1510 {
1511 // FIXME
1512 UNIMPLEMENTED;
1513 }
1514
1515 VOID
1516 NTAPI
1517 ScsiPortWriteRegisterBufferUlong(
1518 IN PULONG Register,
1519 IN PULONG Buffer,
1520 IN ULONG Count)
1521 {
1522 // FIXME
1523 UNIMPLEMENTED;
1524 }
1525
1526 VOID
1527 NTAPI
1528 ScsiPortWriteRegisterBufferUshort(
1529 IN PUSHORT Register,
1530 IN PUSHORT Buffer,
1531 IN ULONG Count)
1532 {
1533 // FIXME
1534 UNIMPLEMENTED;
1535 }
1536
1537 VOID
1538 NTAPI
1539 ScsiPortWriteRegisterUchar(
1540 IN PUCHAR Register,
1541 IN UCHAR Value)
1542 {
1543 WRITE_REGISTER_UCHAR(Register, Value);
1544 }
1545
1546 VOID
1547 NTAPI
1548 ScsiPortWriteRegisterUlong(
1549 IN PULONG Register,
1550 IN ULONG Value)
1551 {
1552 WRITE_REGISTER_ULONG(Register, Value);
1553 }
1554
1555 VOID
1556 NTAPI
1557 ScsiPortWriteRegisterUshort(
1558 IN PUSHORT Register,
1559 IN USHORT Value)
1560 {
1561 WRITE_REGISTER_USHORT(Register, Value);
1562 }
1563
1564 extern char __ImageBase;
1565
1566 ULONG
1567 LoadBootDeviceDriver(VOID)
1568 {
1569 PIMAGE_NT_HEADERS NtHeaders;
1570 LIST_ENTRY ModuleListHead;
1571 PIMAGE_IMPORT_DESCRIPTOR ImportTable;
1572 ULONG ImportTableSize;
1573 PLDR_DATA_TABLE_ENTRY BootDdDTE, FreeldrDTE;
1574 CHAR NtBootDdPath[MAX_PATH];
1575 PVOID ImageBase = NULL;
1576 ULONG (NTAPI *EntryPoint)(IN PVOID DriverObject, IN PVOID RegistryPath);
1577 BOOLEAN Status;
1578
1579 /* Initialize the loaded module list */
1580 InitializeListHead(&ModuleListHead);
1581
1582 /* Create full ntbootdd.sys path */
1583 MachDiskGetBootPath(NtBootDdPath, sizeof(NtBootDdPath));
1584 strcat(NtBootDdPath, "\\NTBOOTDD.SYS");
1585
1586 /* Load file */
1587 Status = WinLdrLoadImage(NtBootDdPath, LoaderBootDriver, &ImageBase);
1588 if (!Status)
1589 {
1590 /* That's OK. File simply doesn't exist */
1591 return ESUCCESS;
1592 }
1593
1594 /* Allocate a DTE for ntbootdd */
1595 Status = WinLdrAllocateDataTableEntry(&ModuleListHead, "ntbootdd.sys",
1596 "NTBOOTDD.SYS", ImageBase, &BootDdDTE);
1597 if (!Status)
1598 return EIO;
1599
1600 /* Add the PE part of freeldr.sys to the list of loaded executables, it
1601 contains Scsiport* exports, imported by ntbootdd.sys */
1602 Status = WinLdrAllocateDataTableEntry(&ModuleListHead, "scsiport.sys",
1603 "FREELDR.SYS", &__ImageBase, &FreeldrDTE);
1604 if (!Status)
1605 {
1606 RemoveEntryList(&BootDdDTE->InLoadOrderLinks);
1607 return EIO;
1608 }
1609
1610 /* Fix imports */
1611 Status = WinLdrScanImportDescriptorTable(&ModuleListHead, "", BootDdDTE);
1612
1613 /* Now unlinkt the DTEs, they won't be valid later */
1614 RemoveEntryList(&BootDdDTE->InLoadOrderLinks);
1615 RemoveEntryList(&FreeldrDTE->InLoadOrderLinks);
1616
1617 if (!Status)
1618 return EIO;
1619
1620 /* Change imports to PA */
1621 ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(BootDdDTE->DllBase),
1622 TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize);
1623 for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != 0);ImportTable++)
1624 {
1625 PIMAGE_THUNK_DATA ThunkData = (PIMAGE_THUNK_DATA)VaToPa(RVA(BootDdDTE->DllBase, ImportTable->FirstThunk));
1626
1627 while (((PIMAGE_THUNK_DATA)ThunkData)->u1.AddressOfData != 0)
1628 {
1629 ThunkData->u1.Function = (ULONG)VaToPa((PVOID)ThunkData->u1.Function);
1630 ThunkData++;
1631 }
1632 }
1633
1634 /* Relocate image to PA */
1635 NtHeaders = RtlImageNtHeader(VaToPa(BootDdDTE->DllBase));
1636 if (!NtHeaders)
1637 return EIO;
1638 Status = (BOOLEAN)LdrRelocateImageWithBias(
1639 VaToPa(BootDdDTE->DllBase),
1640 NtHeaders->OptionalHeader.ImageBase - (ULONG_PTR)BootDdDTE->DllBase,
1641 "FreeLdr",
1642 TRUE,
1643 TRUE, /* in case of conflict still return success */
1644 FALSE);
1645 if (!Status)
1646 return EIO;
1647
1648 /* Call the entrypoint */
1649 EntryPoint = VaToPa(BootDdDTE->EntryPoint);
1650 (*EntryPoint)(NULL, NULL);
1651
1652 return ESUCCESS;
1653 }
1654
1655 /* EOF */