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