ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

scsiport.c
Go to the documentation of this file.
00001 #include <freeldr.h>
00002 
00003 #define _SCSIPORT_
00004 
00005 #include <ntddk.h>
00006 #include <srb.h>
00007 #include <scsi.h>
00008 #include <ntddscsi.h>
00009 #include <ntddstor.h>
00010 #include <ntdddisk.h>
00011 #include <stdio.h>
00012 #include <stdarg.h>
00013 
00014 #undef ScsiPortLogError
00015 #undef ScsiPortMoveMemory
00016 #undef ScsiPortWritePortBufferUchar
00017 #undef ScsiPortWritePortBufferUlong
00018 #undef ScsiPortWritePortBufferUshort
00019 #undef ScsiPortWritePortUchar
00020 #undef ScsiPortWritePortUlong
00021 #undef ScsiPortWritePortUshort
00022 #undef ScsiPortWriteRegisterBufferUchar
00023 #undef ScsiPortWriteRegisterBufferUlong
00024 #undef ScsiPortWriteRegisterBufferUshort
00025 #undef ScsiPortWriteRegisterUchar
00026 #undef ScsiPortWriteRegisterUlong
00027 #undef ScsiPortWriteRegisterUshort
00028 #undef ScsiPortReadPortBufferUchar
00029 #undef ScsiPortReadPortBufferUlong
00030 #undef ScsiPortReadPortBufferUshort
00031 #undef ScsiPortReadPortUchar
00032 #undef ScsiPortReadPortUlong
00033 #undef ScsiPortReadPortUshort
00034 #undef ScsiPortReadRegisterBufferUchar
00035 #undef ScsiPortReadRegisterBufferUlong
00036 #undef ScsiPortReadRegisterBufferUshort
00037 #undef ScsiPortReadRegisterUchar
00038 #undef ScsiPortReadRegisterUlong
00039 #undef ScsiPortReadRegisterUshort
00040 
00041 #define NDEBUG
00042 #include <debug.h>
00043 
00044 #define SCSI_PORT_NEXT_REQUEST_READY  0x0008
00045 
00046 DBG_DEFAULT_CHANNEL(SCSIPORT);
00047 
00048 typedef struct
00049 {
00050     PVOID NonCachedExtension;
00051 
00052     ULONG BusNum;
00053     ULONG MaxTargedIds;
00054 
00055     ULONG InterruptFlags;
00056 
00057     /* SRB extension stuff */
00058     ULONG SrbExtensionSize;
00059     PVOID SrbExtensionBuffer;
00060 
00061     IO_SCSI_CAPABILITIES PortCapabilities;
00062 
00063     PHW_INITIALIZE HwInitialize;
00064     PHW_STARTIO HwStartIo;
00065     PHW_INTERRUPT HwInterrupt;
00066     PHW_RESET_BUS HwResetBus;
00067 
00068     /* DMA related stuff */
00069     PADAPTER_OBJECT AdapterObject;
00070 
00071     ULONG CommonBufferLength;
00072 
00073     PVOID MiniPortDeviceExtension;
00074 } SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
00075 
00076 PSCSI_PORT_DEVICE_EXTENSION ScsiDeviceExtensions[SCSI_MAXIMUM_BUSES];
00077 
00078 ULONG
00079 ntohl(
00080     IN ULONG Value)
00081 {
00082     FOUR_BYTE Dest;
00083     PFOUR_BYTE Source = (PFOUR_BYTE)&Value;
00084 
00085     Dest.Byte0 = Source->Byte3;
00086     Dest.Byte1 = Source->Byte2;
00087     Dest.Byte2 = Source->Byte1;
00088     Dest.Byte3 = Source->Byte0;
00089 
00090     return Dest.AsULong;
00091 }
00092 
00093 BOOLEAN
00094 SpiSendSynchronousSrb(
00095     IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
00096     IN PSCSI_REQUEST_BLOCK Srb)
00097 {
00098     BOOLEAN ret;
00099 
00100     ASSERT(!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE));
00101 
00102     /* HACK: handle lack of interrupts */
00103     while (!(DeviceExtension->InterruptFlags & SCSI_PORT_NEXT_REQUEST_READY))
00104     {
00105         KeStallExecutionProcessor(100 * 1000);
00106         DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension);
00107     }
00108 
00109     DeviceExtension->InterruptFlags &= ~SCSI_PORT_NEXT_REQUEST_READY;
00110     Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
00111 
00112     if (!DeviceExtension->HwStartIo(
00113             DeviceExtension->MiniPortDeviceExtension,
00114             Srb))
00115     {
00116         ExFreePool(Srb);
00117         return FALSE;
00118     }
00119 
00120     /* HACK: handle lack of interrupts */
00121     while (Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)
00122     {
00123         KeStallExecutionProcessor(100 * 1000);
00124         DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension);
00125     }
00126 
00127     ret = SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS;
00128     ExFreePool(Srb);
00129 
00130     return ret;
00131 }
00132 
00133 typedef struct tagDISKCONTEXT
00134 {
00135     /* Device ID */
00136     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
00137     UCHAR PathId;
00138     UCHAR TargetId;
00139     UCHAR Lun;
00140 
00141     /* Device characteristics */
00142     ULONG SectorSize;
00143     ULONGLONG SectorOffset;
00144     ULONGLONG SectorCount;
00145     ULONGLONG SectorNumber;
00146 } DISKCONTEXT;
00147 
00148 static LONG DiskClose(ULONG FileId)
00149 {
00150     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
00151 
00152     ExFreePool(Context);
00153     return ESUCCESS;
00154 }
00155 
00156 static LONG DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
00157 {
00158     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
00159 
00160     RtlZeroMemory(Information, sizeof(FILEINFORMATION));
00161     Information->EndingAddress.QuadPart = Context->SectorCount * Context->SectorSize;
00162     Information->CurrentAddress.QuadPart = Context->SectorNumber * Context->SectorSize;
00163 
00164     return ESUCCESS;
00165 }
00166 
00167 static LONG DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
00168 {
00169     PSCSI_REQUEST_BLOCK Srb;
00170     PCDB Cdb;
00171     READ_CAPACITY_DATA ReadCapacityBuffer;
00172 
00173     DISKCONTEXT* Context;
00174     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
00175     ULONG ScsiBus, PathId, TargetId, Lun, Partition, PathSyntax;
00176     ULONG SectorSize;
00177     ULONGLONG SectorOffset = 0;
00178     ULONGLONG SectorCount;
00179 
00180     /* Parse ARC path */
00181     if (!DissectArcPath2(Path, &ScsiBus, &TargetId, &Lun, &Partition, &PathSyntax))
00182         return EINVAL;
00183     if (PathSyntax != 0) /* scsi() format */
00184         return EINVAL;
00185     DeviceExtension = ScsiDeviceExtensions[ScsiBus];
00186     PathId = ScsiBus - DeviceExtension->BusNum;
00187 
00188     /* Get disk capacity and sector size */
00189     Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
00190     if (!Srb)
00191         return ENOMEM;
00192     RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
00193     Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
00194     Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
00195     Srb->PathId = (UCHAR)PathId;
00196     Srb->TargetId = (UCHAR)TargetId;
00197     Srb->Lun = (UCHAR)Lun;
00198     Srb->CdbLength = 10;
00199     Srb->SrbFlags = SRB_FLAGS_DATA_IN;
00200     Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
00201     Srb->TimeOutValue = 5; /* in seconds */
00202     Srb->DataBuffer = &ReadCapacityBuffer;
00203     Cdb = (PCDB)Srb->Cdb;
00204     Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
00205     if (!SpiSendSynchronousSrb(DeviceExtension, Srb))
00206     {
00207         return EIO;
00208     }
00209 
00210     /* Transform result to host endianness */
00211     SectorCount = ntohl(ReadCapacityBuffer.LogicalBlockAddress);
00212     SectorSize = ntohl(ReadCapacityBuffer.BytesPerBlock);
00213 
00214     if (Partition != 0)
00215     {
00216         /* Need to offset start of disk and length */
00217         UNIMPLEMENTED;
00218         return EIO;
00219     }
00220 
00221     Context = ExAllocatePool(PagedPool, sizeof(DISKCONTEXT));
00222     if (!Context)
00223         return ENOMEM;
00224     Context->DeviceExtension = DeviceExtension;
00225     Context->PathId = (UCHAR)PathId;
00226     Context->TargetId = (UCHAR)TargetId;
00227     Context->Lun = (UCHAR)Lun;
00228     Context->SectorSize = SectorSize;
00229     Context->SectorOffset = SectorOffset;
00230     Context->SectorCount = SectorCount;
00231     Context->SectorNumber = 0;
00232     FsSetDeviceSpecific(*FileId, Context);
00233 
00234     return ESUCCESS;
00235 }
00236 
00237 static LONG DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
00238 {
00239     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
00240     PSCSI_REQUEST_BLOCK Srb;
00241     PCDB Cdb;
00242     ULONG FullSectors, NbSectors;
00243     ULONG Lba;
00244 
00245     *Count = 0;
00246 
00247     if (N == 0)
00248         return ESUCCESS;
00249 
00250     FullSectors = N / Context->SectorSize;
00251     NbSectors = (N + Context->SectorSize - 1) / Context->SectorSize;
00252     if (Context->SectorNumber + NbSectors >= Context->SectorCount)
00253         return EINVAL;
00254     if (FullSectors > 0xffff)
00255         return EINVAL;
00256 
00257     /* Read full sectors */
00258     ASSERT(Context->SectorNumber < 0xFFFFFFFF);
00259     Lba = (ULONG)Context->SectorNumber;
00260     if (FullSectors > 0)
00261     {
00262         Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
00263         if (!Srb)
00264             return ENOMEM;
00265 
00266         RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
00267         Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
00268         Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
00269         Srb->PathId = Context->PathId;
00270         Srb->TargetId = Context->TargetId;
00271         Srb->Lun = Context->Lun;
00272         Srb->CdbLength = 10;
00273         Srb->SrbFlags = SRB_FLAGS_DATA_IN;
00274         Srb->DataTransferLength = FullSectors * Context->SectorSize;
00275         Srb->TimeOutValue = 5; /* in seconds */
00276         Srb->DataBuffer = Buffer;
00277         Cdb = (PCDB)Srb->Cdb;
00278         Cdb->CDB10.OperationCode = SCSIOP_READ;
00279         Cdb->CDB10.LogicalUnitNumber = Srb->Lun;
00280         Cdb->CDB10.LogicalBlockByte0 = (Lba >> 24) & 0xff;
00281         Cdb->CDB10.LogicalBlockByte1 = (Lba >> 16) & 0xff;
00282         Cdb->CDB10.LogicalBlockByte2 = (Lba >> 8) & 0xff;
00283         Cdb->CDB10.LogicalBlockByte3 = Lba & 0xff;
00284         Cdb->CDB10.TransferBlocksMsb = (FullSectors >> 8) & 0xff;
00285         Cdb->CDB10.TransferBlocksLsb = FullSectors & 0xff;
00286         if (!SpiSendSynchronousSrb(Context->DeviceExtension, Srb))
00287         {
00288             return EIO;
00289         }
00290         Buffer = (PUCHAR)Buffer + FullSectors * Context->SectorSize;
00291         N -= FullSectors * Context->SectorSize;
00292         *Count += FullSectors * Context->SectorSize;
00293         Lba += FullSectors;
00294     }
00295 
00296     /* Read incomplete last sector */
00297     if (N > 0)
00298     {
00299         PUCHAR Sector;
00300 
00301         Sector = ExAllocatePool(PagedPool, Context->SectorSize);
00302         if (!Sector)
00303             return ENOMEM;
00304 
00305         Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
00306         if (!Srb)
00307         {
00308             ExFreePool(Sector);
00309             return ENOMEM;
00310         }
00311 
00312         RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
00313         Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
00314         Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
00315         Srb->PathId = Context->PathId;
00316         Srb->TargetId = Context->TargetId;
00317         Srb->Lun = Context->Lun;
00318         Srb->CdbLength = 10;
00319         Srb->SrbFlags = SRB_FLAGS_DATA_IN;
00320         Srb->DataTransferLength = Context->SectorSize;
00321         Srb->TimeOutValue = 5; /* in seconds */
00322         Srb->DataBuffer = Sector;
00323         Cdb = (PCDB)Srb->Cdb;
00324         Cdb->CDB10.OperationCode = SCSIOP_READ;
00325         Cdb->CDB10.LogicalUnitNumber = Srb->Lun;
00326         Cdb->CDB10.LogicalBlockByte0 = (Lba >> 24) & 0xff;
00327         Cdb->CDB10.LogicalBlockByte1 = (Lba >> 16) & 0xff;
00328         Cdb->CDB10.LogicalBlockByte2 = (Lba >> 8) & 0xff;
00329         Cdb->CDB10.LogicalBlockByte3 = Lba & 0xff;
00330         Cdb->CDB10.TransferBlocksMsb = 0;
00331         Cdb->CDB10.TransferBlocksLsb = 1;
00332         if (!SpiSendSynchronousSrb(Context->DeviceExtension, Srb))
00333         {
00334             ExFreePool(Sector);
00335             return EIO;
00336         }
00337         RtlCopyMemory(Buffer, Sector, N);
00338         *Count += N;
00339         ExFreePool(Sector);
00340     }
00341 
00342     return ESUCCESS;
00343 }
00344 
00345 static LONG DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
00346 {
00347     DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
00348 
00349     if (SeekMode != SeekAbsolute)
00350         return EINVAL;
00351     if (Position->QuadPart & (Context->SectorSize - 1))
00352         return EINVAL;
00353 
00354     Context->SectorNumber = Position->QuadPart / Context->SectorSize;
00355     return ESUCCESS;
00356 }
00357 
00358 static const DEVVTBL DiskVtbl = {
00359     DiskClose,
00360     DiskGetFileInformation,
00361     DiskOpen,
00362     DiskRead,
00363     DiskSeek,
00364 };
00365 
00366 NTSTATUS
00367 SpiCreatePortConfig(
00368     IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
00369     IN PHW_INITIALIZATION_DATA HwInitData,
00370     OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
00371     IN BOOLEAN ZeroStruct)
00372 {
00373     ULONG Bus;
00374 
00375     /* Zero out the struct if told so */
00376     if (ZeroStruct)
00377     {
00378         /* First zero the portconfig */
00379         RtlZeroMemory(ConfigInfo, sizeof(PORT_CONFIGURATION_INFORMATION));
00380 
00381         /* Initialize the struct */
00382         ConfigInfo->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
00383         ConfigInfo->AdapterInterfaceType = HwInitData->AdapterInterfaceType;
00384         ConfigInfo->InterruptMode = Latched;
00385         ConfigInfo->DmaChannel = SP_UNINITIALIZED_VALUE;
00386         ConfigInfo->DmaPort = SP_UNINITIALIZED_VALUE;
00387         ConfigInfo->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
00388         ConfigInfo->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS_PER_BUS;
00389 
00390         /* Store parameters */
00391         ConfigInfo->NeedPhysicalAddresses = HwInitData->NeedPhysicalAddresses;
00392         ConfigInfo->MapBuffers = HwInitData->MapBuffers;
00393         ConfigInfo->AutoRequestSense = HwInitData->AutoRequestSense;
00394         ConfigInfo->ReceiveEvent = HwInitData->ReceiveEvent;
00395         ConfigInfo->TaggedQueuing = HwInitData->TaggedQueuing;
00396         ConfigInfo->MultipleRequestPerLu = HwInitData->MultipleRequestPerLu;
00397 
00398         /* Get the disk usage */
00399         ConfigInfo->AtdiskPrimaryClaimed = FALSE; // FIXME
00400         ConfigInfo->AtdiskSecondaryClaimed = FALSE; // FIXME
00401 
00402         /* Initiator bus id is not set */
00403         for (Bus = 0; Bus < 8; Bus++)
00404             ConfigInfo->InitiatorBusId[Bus] = (CCHAR)SP_UNINITIALIZED_VALUE;
00405     }
00406 
00407     ConfigInfo->NumberOfPhysicalBreaks = 17;
00408 
00409     return STATUS_SUCCESS;
00410 }
00411 
00412 VOID
00413 __cdecl
00414 ScsiDebugPrint(
00415     IN ULONG DebugPrintLevel,
00416     IN PCCHAR DebugMessage,
00417     IN ...)
00418 {
00419     va_list ap;
00420     CHAR Buffer[512];
00421     ULONG Length;
00422 
00423     if (DebugPrintLevel > 10)
00424         return;
00425 
00426     va_start(ap, DebugMessage);
00427 
00428     /* Construct a string */
00429     Length = _vsnprintf(Buffer, 512, DebugMessage, ap);
00430 
00431     /* Check if we went past the buffer */
00432     if (Length == MAXULONG)
00433     {
00434         /* Terminate it if we went over-board */
00435         Buffer[sizeof(Buffer) - 1] = '\0';
00436 
00437         /* Put maximum */
00438         Length = sizeof(Buffer);
00439     }
00440 
00441     /* Print the message */
00442     TRACE("%s", Buffer);
00443 
00444     /* Cleanup */
00445     va_end(ap);
00446 }
00447 
00448 VOID
00449 NTAPI
00450 ScsiPortCompleteRequest(
00451     IN PVOID HwDeviceExtension,
00452     IN UCHAR PathId,
00453     IN UCHAR TargetId,
00454     IN UCHAR Lun,
00455     IN UCHAR SrbStatus)
00456 {
00457     // FIXME
00458     UNIMPLEMENTED;
00459 }
00460 
00461 #undef ScsiPortConvertPhysicalAddressToUlong
00462 ULONG
00463 NTAPI
00464 ScsiPortConvertPhysicalAddressToUlong(
00465     IN SCSI_PHYSICAL_ADDRESS Address)
00466 {
00467     return Address.LowPart;
00468 }
00469 
00470 SCSI_PHYSICAL_ADDRESS
00471 NTAPI
00472 ScsiPortConvertUlongToPhysicalAddress(
00473     IN ULONG_PTR UlongAddress)
00474 {
00475     SCSI_PHYSICAL_ADDRESS Address;
00476 
00477     Address.QuadPart = UlongAddress;
00478     return Address;
00479 }
00480 
00481 VOID
00482 NTAPI
00483 ScsiPortFlushDma(
00484     IN PVOID DeviceExtension)
00485 {
00486     // FIXME
00487     UNIMPLEMENTED;
00488 }
00489 
00490 VOID
00491 NTAPI
00492 ScsiPortFreeDeviceBase(
00493     IN PVOID HwDeviceExtension,
00494     IN PVOID MappedAddress)
00495 {
00496     // Nothing to do
00497 }
00498 
00499 ULONG
00500 NTAPI
00501 ScsiPortGetBusData(
00502     IN PVOID DeviceExtension,
00503     IN ULONG BusDataType,
00504     IN ULONG SystemIoBusNumber,
00505     IN ULONG SlotNumber,
00506     IN PVOID Buffer,
00507     IN ULONG Length)
00508 {
00509     return HalGetBusDataByOffset(BusDataType, SystemIoBusNumber, SlotNumber, Buffer, 0, Length);
00510 }
00511 
00512 PVOID
00513 NTAPI
00514 ScsiPortGetDeviceBase(
00515     IN PVOID HwDeviceExtension,
00516     IN INTERFACE_TYPE BusType,
00517     IN ULONG SystemIoBusNumber,
00518     IN SCSI_PHYSICAL_ADDRESS IoAddress,
00519     IN ULONG NumberOfBytes,
00520     IN BOOLEAN InIoSpace)
00521 {
00522     PHYSICAL_ADDRESS TranslatedAddress;
00523     ULONG AddressSpace;
00524 
00525     AddressSpace = (ULONG)InIoSpace;
00526     if (HalTranslateBusAddress(BusType,
00527                                SystemIoBusNumber,
00528                                IoAddress,
00529                                &AddressSpace,
00530                                &TranslatedAddress) == FALSE)
00531     {
00532         return NULL;
00533     }
00534 
00535     /* I/O space */
00536     if (AddressSpace != 0)
00537         return (PVOID)TranslatedAddress.u.LowPart;
00538 
00539     // FIXME
00540     UNIMPLEMENTED;
00541     return (PVOID)IoAddress.LowPart;
00542 }
00543 
00544 PVOID
00545 NTAPI
00546 ScsiPortGetLogicalUnit(
00547     IN PVOID HwDeviceExtension,
00548     IN UCHAR PathId,
00549     IN UCHAR TargetId,
00550     IN UCHAR Lun)
00551 {
00552     // FIXME
00553     UNIMPLEMENTED;
00554     return NULL;
00555 }
00556 
00557 SCSI_PHYSICAL_ADDRESS
00558 NTAPI
00559 ScsiPortGetPhysicalAddress(
00560     IN PVOID HwDeviceExtension,
00561     IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
00562     IN PVOID VirtualAddress,
00563     OUT ULONG *Length)
00564 {
00565     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
00566     SCSI_PHYSICAL_ADDRESS PhysicalAddress;
00567     ULONG BufferLength = 0;
00568     ULONG Offset;
00569 
00570     TRACE("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
00571         HwDeviceExtension, Srb, VirtualAddress, Length);
00572 
00573     DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
00574 
00575     if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)
00576     {
00577         /* Simply look it up in the allocated common buffer */
00578         Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer;
00579 
00580         BufferLength = DeviceExtension->CommonBufferLength - Offset;
00581         PhysicalAddress.QuadPart = Offset;
00582     }
00583     else
00584     {
00585         /* Nothing */
00586         *Length = 0;
00587         PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
00588     }
00589 
00590     *Length = BufferLength;
00591     return PhysicalAddress;
00592 }
00593 
00594 PSCSI_REQUEST_BLOCK
00595 NTAPI
00596 ScsiPortGetSrb(
00597     IN PVOID DeviceExtension,
00598     IN UCHAR PathId,
00599     IN UCHAR TargetId,
00600     IN UCHAR Lun,
00601     IN LONG QueueTag)
00602 {
00603     // FIXME
00604     UNIMPLEMENTED;
00605     return NULL;
00606 }
00607 
00608 NTSTATUS
00609 SpiAllocateCommonBuffer(
00610     IN OUT PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
00611     IN ULONG NonCachedSize)
00612 {
00613     PVOID CommonBuffer;
00614     ULONG CommonBufferLength, BufSize;
00615 
00616     /* If size is 0, set it to 16 */
00617     if (!DeviceExtension->SrbExtensionSize)
00618         DeviceExtension->SrbExtensionSize = 16;
00619 
00620     /* Calculate size */
00621     BufSize = DeviceExtension->SrbExtensionSize;
00622 
00623     /* Round it */
00624     BufSize = (BufSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
00625 
00626     /* Sum up into the total common buffer length, and round it to page size */
00627     CommonBufferLength =
00628         ROUND_TO_PAGES(NonCachedSize);
00629 
00630     /* Allocate it */
00631     if (!DeviceExtension->AdapterObject)
00632     {
00633         /* From nonpaged pool if there is no DMA */
00634         CommonBuffer = ExAllocatePool(NonPagedPool, CommonBufferLength);
00635     }
00636     else
00637     {
00638         /* Perform a full request since we have a DMA adapter*/
00639         UNIMPLEMENTED;
00640         CommonBuffer = NULL;
00641     }
00642 
00643     /* Fail in case of error */
00644     if (!CommonBuffer)
00645         return STATUS_INSUFFICIENT_RESOURCES;
00646 
00647     /* Zero it */
00648     RtlZeroMemory(CommonBuffer, CommonBufferLength);
00649 
00650     /* Store its size in Device Extension */
00651     DeviceExtension->CommonBufferLength = CommonBufferLength;
00652 
00653     /* SrbExtension buffer is located at the beginning of the buffer */
00654     DeviceExtension->SrbExtensionBuffer = CommonBuffer;
00655 
00656     /* Non-cached extension buffer is located at the end of
00657        the common buffer */
00658     if (NonCachedSize)
00659     {
00660         CommonBufferLength -=  NonCachedSize;
00661         DeviceExtension->NonCachedExtension = (PUCHAR)CommonBuffer + CommonBufferLength;
00662     }
00663     else
00664     {
00665         DeviceExtension->NonCachedExtension = NULL;
00666     }
00667 
00668     return STATUS_SUCCESS;
00669 }
00670 
00671 PVOID
00672 NTAPI
00673 ScsiPortGetUncachedExtension(
00674     IN PVOID HwDeviceExtension,
00675     IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
00676     IN ULONG NumberOfBytes)
00677 {
00678     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
00679     DEVICE_DESCRIPTION DeviceDescription;
00680     ULONG MapRegistersCount;
00681     NTSTATUS Status;
00682 
00683     TRACE("ScsiPortGetUncachedExtension(%p %p %lu)\n",
00684         HwDeviceExtension, ConfigInfo, NumberOfBytes);
00685 
00686     DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
00687 
00688     /* Check for allocated common DMA buffer */
00689     if (DeviceExtension->SrbExtensionBuffer != NULL)
00690     {
00691         return NULL;
00692     }
00693 
00694     /* Check for DMA adapter object */
00695     if (DeviceExtension->AdapterObject == NULL)
00696     {
00697         /* Initialize DMA adapter description */
00698         RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
00699 
00700         DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
00701         DeviceDescription.Master = ConfigInfo->Master;
00702         DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
00703         DeviceDescription.DemandMode = ConfigInfo->DemandMode;
00704         DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
00705         DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
00706         DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
00707         DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
00708         DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
00709         DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
00710         DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
00711         DeviceDescription.DmaPort = ConfigInfo->DmaPort;
00712 
00713         /* Get a DMA adapter object */
00714 #if 0
00715         DeviceExtension->AdapterObject =
00716             HalGetAdapter(&DeviceDescription, &MapRegistersCount);
00717 
00718         /* Fail in case of error */
00719         if (DeviceExtension->AdapterObject == NULL)
00720         {
00721             return NULL;
00722         }
00723 #else
00724         MapRegistersCount = 0;
00725 #endif
00726 
00727         /* Set number of physical breaks */
00728         if (ConfigInfo->NumberOfPhysicalBreaks != 0 &&
00729             MapRegistersCount > ConfigInfo->NumberOfPhysicalBreaks)
00730         {
00731             DeviceExtension->PortCapabilities.MaximumPhysicalPages =
00732                 ConfigInfo->NumberOfPhysicalBreaks;
00733         }
00734         else
00735         {
00736             DeviceExtension->PortCapabilities.MaximumPhysicalPages = MapRegistersCount;
00737         }
00738     }
00739 
00740     /* Update Srb extension size */
00741     if (DeviceExtension->SrbExtensionSize != ConfigInfo->SrbExtensionSize)
00742         DeviceExtension->SrbExtensionSize = ConfigInfo->SrbExtensionSize;
00743 
00744     /* Allocate a common DMA buffer */
00745     Status = SpiAllocateCommonBuffer(DeviceExtension, NumberOfBytes);
00746 
00747     if (!NT_SUCCESS(Status))
00748     {
00749         TRACE("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status);
00750         return NULL;
00751     }
00752 
00753     return DeviceExtension->NonCachedExtension;
00754 }
00755 
00756 PVOID
00757 NTAPI
00758 ScsiPortGetVirtualAddress(
00759     IN PVOID HwDeviceExtension,
00760     IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
00761 {
00762     // FIXME
00763     UNIMPLEMENTED;
00764     return NULL;
00765 }
00766 
00767 VOID
00768 SpiScanDevice(
00769     IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
00770     IN PCHAR ArcName,
00771     IN ULONG ScsiBus,
00772     IN ULONG TargetId,
00773     IN ULONG Lun)
00774 {
00775     ULONG FileId, i;
00776     ULONG Status;
00777     NTSTATUS ret;
00778     struct _DRIVE_LAYOUT_INFORMATION *PartitionBuffer;
00779     CHAR PartitionName[64];
00780 
00781     /* Register device with partition(0) suffix */
00782     sprintf(PartitionName, "%spartition(0)", ArcName);
00783     FsRegisterDevice(PartitionName, &DiskVtbl);
00784 
00785     /* Read device partition table */
00786     Status = ArcOpen(PartitionName, OpenReadOnly, &FileId);
00787     if (Status == ESUCCESS)
00788     {
00789         ret = HALDISPATCH->HalIoReadPartitionTable((PDEVICE_OBJECT)FileId, 512, FALSE, &PartitionBuffer);
00790         if (NT_SUCCESS(ret))
00791         {
00792             for (i = 0; i < PartitionBuffer->PartitionCount; i++)
00793             {
00794                 if (PartitionBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED)
00795                 {
00796                     sprintf(PartitionName, "%spartition(%lu)",
00797                             ArcName, PartitionBuffer->PartitionEntry[i].PartitionNumber);
00798                     FsRegisterDevice(PartitionName, &DiskVtbl);
00799                 }
00800             }
00801             ExFreePool(PartitionBuffer);
00802         }
00803         ArcClose(FileId);
00804     }
00805 }
00806 
00807 VOID
00808 SpiScanAdapter(
00809     IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
00810     IN ULONG ScsiBus,
00811     IN UCHAR PathId)
00812 {
00813     CHAR ArcName[64];
00814     PSCSI_REQUEST_BLOCK Srb;
00815     PCDB Cdb;
00816     INQUIRYDATA InquiryBuffer;
00817     UCHAR TargetId;
00818     UCHAR Lun;
00819 
00820     if (!DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, PathId))
00821     {
00822         return;
00823     }
00824 
00825     /* Remember the extension */
00826     ScsiDeviceExtensions[ScsiBus] = DeviceExtension;
00827 
00828     for (TargetId = 0; TargetId < DeviceExtension->MaxTargedIds; TargetId++)
00829     {
00830         Lun = 0;
00831         do
00832         {
00833             TRACE("Scanning SCSI device %d.%d.%d\n",
00834                 ScsiBus, TargetId, Lun);
00835 
00836             Srb = ExAllocatePool(PagedPool, sizeof(SCSI_REQUEST_BLOCK));
00837             if (!Srb)
00838                 break;
00839             RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
00840             Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
00841             Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
00842             Srb->PathId = PathId;
00843             Srb->TargetId = TargetId;
00844             Srb->Lun = Lun;
00845             Srb->CdbLength = 6;
00846             Srb->SrbFlags = SRB_FLAGS_DATA_IN;
00847             Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
00848             Srb->TimeOutValue = 5; /* in seconds */
00849             Srb->DataBuffer = &InquiryBuffer;
00850             Cdb = (PCDB)Srb->Cdb;
00851             Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
00852             Cdb->CDB6INQUIRY.LogicalUnitNumber = Srb->Lun;
00853             Cdb->CDB6INQUIRY.AllocationLength = (UCHAR)Srb->DataTransferLength;
00854             if (!SpiSendSynchronousSrb(DeviceExtension, Srb))
00855             {
00856                 /* Don't check next LUNs */
00857                 break;
00858             }
00859 
00860             /* Device exists, create its ARC name */
00861             if (InquiryBuffer.RemovableMedia)
00862             {
00863                 sprintf(ArcName, "scsi(%ld)cdrom(%d)fdisk(%d)",
00864                     ScsiBus, TargetId, Lun);
00865                 FsRegisterDevice(ArcName, &DiskVtbl);
00866             }
00867             else
00868             {
00869                 sprintf(ArcName, "scsi(%ld)disk(%d)rdisk(%d)",
00870                     ScsiBus, TargetId, Lun);
00871                 /* Now, check if it has partitions */
00872                 SpiScanDevice(DeviceExtension, ArcName, PathId, TargetId, Lun);
00873             }
00874 
00875             /* Check next LUN */
00876             Lun++;
00877         } while (Lun < SCSI_MAXIMUM_LOGICAL_UNITS);
00878     }
00879 }
00880 
00881 VOID
00882 SpiResourceToConfig(
00883     IN PHW_INITIALIZATION_DATA HwInitializationData,
00884     IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
00885     IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig)
00886 {
00887     PACCESS_RANGE AccessRange;
00888     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData;
00889     ULONG RangeNumber;
00890     ULONG Index;
00891 
00892     RangeNumber = 0;
00893 
00894     /* Loop through all entries */
00895     for (Index = 0; Index < ResourceDescriptor->PartialResourceList.Count; Index++)
00896     {
00897         PartialData = &ResourceDescriptor->PartialResourceList.PartialDescriptors[Index];
00898 
00899         switch (PartialData->Type)
00900         {
00901         case CmResourceTypePort:
00902             /* Copy access ranges */
00903             if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
00904             {
00905                 TRACE("Got port at 0x%I64x, len 0x%x\n",
00906                     PartialData->u.Port.Start.QuadPart, PartialData->u.Port.Length);
00907                 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
00908 
00909                 AccessRange->RangeStart = PartialData->u.Port.Start;
00910                 AccessRange->RangeLength = PartialData->u.Port.Length;
00911 
00912                 AccessRange->RangeInMemory = FALSE;
00913                 RangeNumber++;
00914             }
00915             break;
00916 
00917         case CmResourceTypeMemory:
00918             /* Copy access ranges */
00919             if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
00920             {
00921                 TRACE("Got memory at 0x%I64x, len 0x%x\n",
00922                     PartialData->u.Memory.Start.QuadPart, PartialData->u.Memory.Length);
00923                 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
00924 
00925                 AccessRange->RangeStart = PartialData->u.Memory.Start;
00926                 AccessRange->RangeLength = PartialData->u.Memory.Length;
00927 
00928                 AccessRange->RangeInMemory = TRUE;
00929                 RangeNumber++;
00930             }
00931             break;
00932 
00933         case CmResourceTypeInterrupt:
00934             /* Copy interrupt data */
00935             TRACE("Got interrupt level %d, vector %d\n",
00936                 PartialData->u.Interrupt.Level, PartialData->u.Interrupt.Vector);
00937             PortConfig->BusInterruptLevel = PartialData->u.Interrupt.Level;
00938             PortConfig->BusInterruptVector = PartialData->u.Interrupt.Vector;
00939 
00940             /* Set interrupt mode accordingly to the resource */
00941             if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
00942             {
00943                 PortConfig->InterruptMode = Latched;
00944             }
00945             else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
00946             {
00947                 PortConfig->InterruptMode = LevelSensitive;
00948             }
00949             break;
00950 
00951         case CmResourceTypeDma:
00952             TRACE("Got DMA channel %d, port %d\n",
00953                 PartialData->u.Dma.Channel, PartialData->u.Dma.Port);
00954             PortConfig->DmaChannel = PartialData->u.Dma.Channel;
00955             PortConfig->DmaPort = PartialData->u.Dma.Port;
00956             break;
00957         }
00958     }
00959 }
00960 
00961 BOOLEAN
00962 SpiGetPciConfigData(
00963     IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
00964     IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
00965     IN ULONG BusNumber,
00966     IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
00967 {
00968     PCI_COMMON_CONFIG PciConfig;
00969     PCI_SLOT_NUMBER SlotNumber;
00970     ULONG DataSize;
00971     ULONG DeviceNumber;
00972     ULONG FunctionNumber;
00973     CHAR VendorIdString[8];
00974     CHAR DeviceIdString[8];
00975     PCM_RESOURCE_LIST ResourceList = NULL;
00976     NTSTATUS Status;
00977 
00978     SlotNumber.u.AsULONG = 0;
00979 
00980     /* Loop through all devices */
00981     for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
00982     {
00983         SlotNumber.u.bits.DeviceNumber = DeviceNumber;
00984 
00985         /* Loop through all functions */
00986         for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
00987         {
00988             SlotNumber.u.bits.FunctionNumber = FunctionNumber;
00989 
00990             /* Get PCI config bytes */
00991             DataSize = HalGetBusDataByOffset(
00992                 PCIConfiguration,
00993                 BusNumber,
00994                 SlotNumber.u.AsULONG,
00995                 &PciConfig,
00996                 0,
00997                 sizeof(ULONG));
00998 
00999             /* If result of HalGetBusData is 0, then the bus is wrong */
01000             if (DataSize == 0)
01001                 return FALSE;
01002 
01003             /* If result is PCI_INVALID_VENDORID, then this device has no more
01004                "Functions" */
01005             if (PciConfig.VendorID == PCI_INVALID_VENDORID)
01006                 break;
01007 
01008             sprintf(VendorIdString, "%04hx", PciConfig.VendorID);
01009             sprintf(DeviceIdString, "%04hx", PciConfig.DeviceID);
01010 
01011             if (_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) ||
01012                 _strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength))
01013             {
01014                 /* It is not our device */
01015                 continue;
01016             }
01017 
01018             TRACE( "Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
01019                 PciConfig.VendorID, PciConfig.DeviceID,
01020                 BusNumber,
01021                 SlotNumber.u.bits.DeviceNumber, SlotNumber.u.bits.FunctionNumber);
01022 
01023             Status = HalAssignSlotResources(NULL,
01024                                             NULL,
01025                                             NULL,
01026                                             NULL,
01027                                             PCIBus,
01028                                             BusNumber,
01029                                             SlotNumber.u.AsULONG,
01030                                             &ResourceList);
01031 
01032             if (!NT_SUCCESS(Status))
01033                 break;
01034 
01035             /* Create configuration information */
01036             SpiResourceToConfig(HwInitializationData,
01037                                 ResourceList->List,
01038                                 PortConfig);
01039 
01040             /* Free the resource list */
01041             ExFreePool(ResourceList);
01042 
01043             /* Set dev & fn numbers */
01044             NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
01045             NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1;
01046 
01047             /* Save the slot number */
01048             PortConfig->SlotNumber = SlotNumber.u.AsULONG;
01049 
01050             return TRUE;
01051         }
01052         NextSlotNumber->u.bits.FunctionNumber = 0;
01053     }
01054 
01055     NextSlotNumber->u.bits.DeviceNumber = 0;
01056 
01057     return FALSE;
01058 }
01059 
01060 ULONG
01061 NTAPI
01062 ScsiPortInitialize(
01063     IN PVOID Argument1,
01064     IN PVOID Argument2,
01065     IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
01066     IN PVOID HwContext OPTIONAL)
01067 {
01068     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
01069     ULONG DeviceExtensionSize;
01070     PORT_CONFIGURATION_INFORMATION PortConfig;
01071     BOOLEAN Again;
01072     BOOLEAN FirstConfigCall = TRUE;
01073     PCI_SLOT_NUMBER SlotNumber;
01074     UCHAR ScsiBus;
01075     NTSTATUS Status;
01076 
01077     if (HwInitializationData->HwInitializationDataSize != sizeof(HW_INITIALIZATION_DATA))
01078     {
01079         return STATUS_INVALID_PARAMETER;
01080     }
01081 
01082     /* Check params for validity */
01083     if ((HwInitializationData->HwInitialize == NULL) ||
01084         (HwInitializationData->HwStartIo == NULL) ||
01085         (HwInitializationData->HwInterrupt == NULL) ||
01086         (HwInitializationData->HwFindAdapter == NULL) ||
01087         (HwInitializationData->HwResetBus == NULL))
01088     {
01089         return STATUS_INVALID_PARAMETER;
01090     }
01091 
01092     /* Zero starting slot number */
01093     SlotNumber.u.AsULONG = 0;
01094 
01095     while (TRUE)
01096     {
01097         Again = FALSE;
01098 
01099         DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) + HwInitializationData->DeviceExtensionSize;
01100         DeviceExtension = MmHeapAlloc(DeviceExtensionSize);
01101         if (!DeviceExtension)
01102         {
01103             return STATUS_NO_MEMORY;
01104         }
01105         RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
01106         DeviceExtension->InterruptFlags = SCSI_PORT_NEXT_REQUEST_READY;
01107         DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
01108         DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
01109         DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
01110         DeviceExtension->HwResetBus = HwInitializationData->HwResetBus;
01111         DeviceExtension->MiniPortDeviceExtension = (PVOID)(DeviceExtension + 1);
01112 
01113         Status = SpiCreatePortConfig(DeviceExtension,
01114                                      HwInitializationData,
01115                                      &PortConfig,
01116                                      FirstConfigCall);
01117         if (Status != STATUS_SUCCESS)
01118         {
01119             MmHeapFree(DeviceExtension);
01120             return Status;
01121         }
01122 
01123         PortConfig.NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
01124         PortConfig.AccessRanges = MmHeapAlloc(sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges);
01125         if (!PortConfig.AccessRanges)
01126         {
01127            MmHeapFree(DeviceExtension);
01128            return STATUS_NO_MEMORY;
01129         }
01130         RtlZeroMemory(PortConfig.AccessRanges, sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges);
01131 
01132         /* Search for matching PCI device */
01133         if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
01134             (HwInitializationData->VendorIdLength > 0) &&
01135             (HwInitializationData->VendorId != NULL) &&
01136             (HwInitializationData->DeviceIdLength > 0) &&
01137             (HwInitializationData->DeviceId != NULL))
01138         {
01139             PortConfig.BusInterruptLevel = 0;
01140 
01141             /* Get PCI device data */
01142             TRACE("VendorId '%.*s'  DeviceId '%.*s'\n",
01143                 HwInitializationData->VendorIdLength,
01144                 HwInitializationData->VendorId,
01145                 HwInitializationData->DeviceIdLength,
01146                 HwInitializationData->DeviceId);
01147 
01148             if (!SpiGetPciConfigData(HwInitializationData,
01149                                      &PortConfig,
01150                                      0, /* FIXME */
01151                                      &SlotNumber))
01152             {
01153                 /* Continue to the next bus, nothing here */
01154                 MmHeapFree(DeviceExtension);
01155                 return STATUS_INTERNAL_ERROR;
01156             }
01157 
01158             if (!PortConfig.BusInterruptLevel)
01159             {
01160                 /* Bypass this slot, because no interrupt was assigned */
01161                 MmHeapFree(DeviceExtension);
01162                 return STATUS_INTERNAL_ERROR;
01163             }
01164         }
01165 
01166         if (HwInitializationData->HwFindAdapter(
01167              DeviceExtension->MiniPortDeviceExtension,
01168              HwContext,
01169              NULL,
01170              NULL,
01171              &PortConfig,
01172              &Again) != SP_RETURN_FOUND)
01173         {
01174             MmHeapFree(DeviceExtension);
01175             return STATUS_INTERNAL_ERROR;
01176         }
01177 
01178         /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
01179         if (PortConfig.MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)
01180             DeviceExtension->MaxTargedIds = SCSI_MAXIMUM_TARGETS_PER_BUS;
01181         else
01182             DeviceExtension->MaxTargedIds = PortConfig.MaximumNumberOfTargets;
01183 
01184         DeviceExtension->BusNum = PortConfig.SystemIoBusNumber;
01185 
01186         TRACE("Adapter found: buses = %d, targets = %d\n",
01187                  PortConfig.NumberOfBuses, DeviceExtension->MaxTargedIds);
01188 
01189         /* Initialize adapter */
01190         if (!DeviceExtension->HwInitialize(DeviceExtension->MiniPortDeviceExtension))
01191         {
01192             MmHeapFree(DeviceExtension);
01193             return STATUS_INTERNAL_ERROR;
01194         }
01195 
01196         /* Scan bus */
01197         for (ScsiBus = 0; ScsiBus < PortConfig.NumberOfBuses; ScsiBus++)
01198         {
01199             SpiScanAdapter(DeviceExtension, PortConfig.SystemIoBusNumber, ScsiBus);
01200             PortConfig.SystemIoBusNumber++;
01201         }
01202 
01203         FirstConfigCall = FALSE;
01204         if (!Again)
01205         {
01206             break;
01207         }
01208     }
01209 
01210     return STATUS_SUCCESS;
01211 }
01212 
01213 VOID
01214 NTAPI
01215 ScsiPortIoMapTransfer(
01216     IN PVOID HwDeviceExtension,
01217     IN PSCSI_REQUEST_BLOCK Srb,
01218     IN PVOID LogicalAddress,
01219     IN ULONG Length)
01220 {
01221     // FIXME
01222     UNIMPLEMENTED;
01223 }
01224 
01225 VOID
01226 NTAPI
01227 ScsiPortLogError(
01228     IN PVOID HwDeviceExtension,
01229     IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
01230     IN UCHAR PathId,
01231     IN UCHAR TargetId,
01232     IN UCHAR Lun,
01233     IN ULONG ErrorCode,
01234     IN ULONG UniqueId)
01235 {
01236     // FIXME
01237     UNIMPLEMENTED;
01238 }
01239 
01240 VOID
01241 NTAPI
01242 ScsiPortMoveMemory(
01243     IN PVOID WriteBuffer,
01244     IN PVOID ReadBuffer,
01245     IN ULONG Length)
01246 {
01247     RtlMoveMemory(WriteBuffer, ReadBuffer, Length);
01248 }
01249 
01250 VOID
01251 __cdecl
01252 ScsiPortNotification(
01253     IN SCSI_NOTIFICATION_TYPE NotificationType,
01254     IN PVOID HwDeviceExtension,
01255     IN ...)
01256 {
01257     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
01258     PSCSI_REQUEST_BLOCK Srb;
01259     va_list ap;
01260 
01261     DeviceExtension = ((PSCSI_PORT_DEVICE_EXTENSION)HwDeviceExtension) - 1;
01262 
01263     va_start(ap, HwDeviceExtension);
01264 
01265     switch (NotificationType)
01266     {
01267         case RequestComplete:
01268             /* Mask the SRB as completed */
01269             Srb = va_arg(ap, PSCSI_REQUEST_BLOCK);
01270             Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
01271             break;
01272 
01273         case NextRequest:
01274             /* Say that device is ready */
01275             DeviceExtension->InterruptFlags |= SCSI_PORT_NEXT_REQUEST_READY;
01276             break;
01277 
01278         default:
01279             // FIXME
01280             UNIMPLEMENTED;
01281     }
01282 
01283     va_end(ap);
01284 }
01285 
01286 VOID
01287 NTAPI
01288 ScsiPortReadPortBufferUchar(
01289     IN PUCHAR Port,
01290     OUT PUCHAR Buffer,
01291     IN ULONG Count)
01292 {
01293     __inbytestring(H2I(Port), Buffer, Count);
01294 }
01295 
01296 VOID
01297 NTAPI
01298 ScsiPortReadPortBufferUlong(
01299     IN PULONG Port,
01300     OUT PULONG Buffer,
01301     IN ULONG Count)
01302 {
01303     __indwordstring(H2I(Port), Buffer, Count);
01304 }
01305 
01306 VOID
01307 NTAPI
01308 ScsiPortReadPortBufferUshort(
01309     IN PUSHORT Port,
01310     OUT PUSHORT Buffer,
01311     IN ULONG Count)
01312 {
01313     __inwordstring(H2I(Port), Buffer, Count);
01314 }
01315 
01316 UCHAR
01317 NTAPI
01318 ScsiPortReadPortUchar(
01319     IN PUCHAR Port)
01320 {
01321     TRACE("ScsiPortReadPortUchar(%p)\n", Port);
01322 
01323     return READ_PORT_UCHAR(Port);
01324 }
01325 
01326 ULONG
01327 NTAPI
01328 ScsiPortReadPortUlong(
01329     IN PULONG Port)
01330 {
01331     return READ_PORT_ULONG(Port);
01332 }
01333 
01334 USHORT
01335 NTAPI
01336 ScsiPortReadPortUshort(
01337     IN PUSHORT Port)
01338 {
01339     return READ_PORT_USHORT(Port);
01340 }
01341 
01342 VOID
01343 NTAPI
01344 ScsiPortReadRegisterBufferUchar(
01345     IN PUCHAR Register,
01346     IN PUCHAR Buffer,
01347     IN ULONG Count)
01348 {
01349     // FIXME
01350     UNIMPLEMENTED;
01351 }
01352 
01353 VOID
01354 NTAPI
01355 ScsiPortReadRegisterBufferUlong(
01356     IN PULONG Register,
01357     IN PULONG Buffer,
01358     IN ULONG Count)
01359 {
01360     // FIXME
01361     UNIMPLEMENTED;
01362 }
01363 
01364 VOID
01365 NTAPI
01366 ScsiPortReadRegisterBufferUshort(
01367     IN PUSHORT Register,
01368     IN PUSHORT Buffer,
01369     IN ULONG Count)
01370 {
01371     // FIXME
01372     UNIMPLEMENTED;
01373 }
01374 
01375 UCHAR
01376 NTAPI
01377 ScsiPortReadRegisterUchar(
01378     IN PUCHAR Register)
01379 {
01380     return READ_REGISTER_UCHAR(Register);
01381 }
01382 
01383 ULONG
01384 NTAPI
01385 ScsiPortReadRegisterUlong(
01386     IN PULONG Register)
01387 {
01388     return READ_REGISTER_ULONG(Register);
01389 }
01390 
01391 USHORT
01392 NTAPI
01393 ScsiPortReadRegisterUshort(
01394     IN PUSHORT Register)
01395 {
01396     return READ_REGISTER_USHORT(Register);
01397 }
01398 
01399 ULONG
01400 NTAPI
01401 ScsiPortSetBusDataByOffset(
01402     IN PVOID DeviceExtension,
01403     IN ULONG BusDataType,
01404     IN ULONG SystemIoBusNumber,
01405     IN ULONG SlotNumber,
01406     IN PVOID Buffer,
01407     IN ULONG Offset,
01408     IN ULONG Length)
01409 {
01410     // FIXME
01411     UNIMPLEMENTED;
01412     return 0;
01413 }
01414 
01415 VOID
01416 NTAPI
01417 ScsiPortStallExecution(
01418     IN ULONG Delay)
01419 {
01420     KeStallExecutionProcessor(Delay);
01421 }
01422 
01423 BOOLEAN
01424 NTAPI
01425 ScsiPortValidateRange(
01426     IN PVOID HwDeviceExtension,
01427     IN INTERFACE_TYPE BusType,
01428     IN ULONG SystemIoBusNumber,
01429     IN SCSI_PHYSICAL_ADDRESS IoAddress,
01430     IN ULONG NumberOfBytes,
01431     IN BOOLEAN InIoSpace)
01432 {
01433     // FIXME
01434     UNIMPLEMENTED;
01435     return TRUE;
01436 }
01437 
01438 #if 0
01439 // ScsiPortWmi*
01440 #endif
01441 
01442 
01443 VOID
01444 NTAPI
01445 ScsiPortWritePortBufferUchar(
01446     IN PUCHAR Port,
01447     IN PUCHAR Buffer,
01448     IN ULONG Count)
01449 {
01450     __outbytestring(H2I(Port), Buffer, Count);
01451 }
01452 
01453 VOID
01454 NTAPI
01455 ScsiPortWritePortBufferUlong(
01456     IN PULONG Port,
01457     IN PULONG Buffer,
01458     IN ULONG Count)
01459 {
01460     __outdwordstring(H2I(Port), Buffer, Count);
01461 }
01462 
01463 VOID
01464 NTAPI
01465 ScsiPortWritePortBufferUshort(
01466     IN PUSHORT Port,
01467     IN PUSHORT Buffer,
01468     IN ULONG Count)
01469 {
01470     __outwordstring(H2I(Port), Buffer, Count);
01471 }
01472 
01473 VOID
01474 NTAPI
01475 ScsiPortWritePortUchar(
01476     IN PUCHAR Port,
01477     IN UCHAR Value)
01478 {
01479     WRITE_PORT_UCHAR(Port, Value);
01480 }
01481 
01482 VOID
01483 NTAPI
01484 ScsiPortWritePortUlong(
01485     IN PULONG Port,
01486     IN ULONG Value)
01487 {
01488     WRITE_PORT_ULONG(Port, Value);
01489 }
01490 
01491 VOID
01492 NTAPI
01493 ScsiPortWritePortUshort(
01494     IN PUSHORT Port,
01495     IN USHORT Value)
01496 {
01497     WRITE_PORT_USHORT(Port, Value);
01498 }
01499 
01500 VOID
01501 NTAPI
01502 ScsiPortWriteRegisterBufferUchar(
01503     IN PUCHAR Register,
01504     IN PUCHAR Buffer,
01505     IN ULONG Count)
01506 {
01507     // FIXME
01508     UNIMPLEMENTED;
01509 }
01510 
01511 VOID
01512 NTAPI
01513 ScsiPortWriteRegisterBufferUlong(
01514     IN PULONG Register,
01515     IN PULONG Buffer,
01516     IN ULONG Count)
01517 {
01518     // FIXME
01519     UNIMPLEMENTED;
01520 }
01521 
01522 VOID
01523 NTAPI
01524 ScsiPortWriteRegisterBufferUshort(
01525     IN PUSHORT Register,
01526     IN PUSHORT Buffer,
01527     IN ULONG Count)
01528 {
01529     // FIXME
01530     UNIMPLEMENTED;
01531 }
01532 
01533 VOID
01534 NTAPI
01535 ScsiPortWriteRegisterUchar(
01536     IN PUCHAR Register,
01537     IN UCHAR Value)
01538 {
01539     WRITE_REGISTER_UCHAR(Register, Value);
01540 }
01541 
01542 VOID
01543 NTAPI
01544 ScsiPortWriteRegisterUlong(
01545     IN PULONG Register,
01546     IN ULONG Value)
01547 {
01548     WRITE_REGISTER_ULONG(Register, Value);
01549 }
01550 
01551 VOID
01552 NTAPI
01553 ScsiPortWriteRegisterUshort(
01554     IN PUSHORT Register,
01555     IN USHORT Value)
01556 {
01557     WRITE_REGISTER_USHORT(Register, Value);
01558 }
01559 
01560 extern char __ImageBase;
01561 
01562 ULONG
01563 LoadBootDeviceDriver(VOID)
01564 {
01565     PIMAGE_NT_HEADERS NtHeaders;
01566     LIST_ENTRY ModuleListHead;
01567     PIMAGE_IMPORT_DESCRIPTOR ImportTable;
01568     ULONG ImportTableSize;
01569     PLDR_DATA_TABLE_ENTRY BootDdDTE, FreeldrDTE;
01570     CHAR NtBootDdPath[MAX_PATH];
01571     PVOID ImageBase;
01572     ULONG (NTAPI *EntryPoint)(IN PVOID DriverObject, IN PVOID RegistryPath);
01573     BOOLEAN Status;
01574 
01575     /* Initialize the loaded module list */
01576     InitializeListHead(&ModuleListHead);
01577 
01578     /* Create full ntbootdd.sys path */
01579     MachDiskGetBootPath(NtBootDdPath, sizeof(NtBootDdPath));
01580     strcat(NtBootDdPath, "\\NTBOOTDD.SYS");
01581 
01582     /* Load file */
01583     Status = WinLdrLoadImage(NtBootDdPath, LoaderBootDriver, &ImageBase);
01584     if (!Status)
01585     {
01586         /* That's OK. File simply doesn't exist */
01587         return ESUCCESS;
01588     }
01589 
01590     /* Allocate a DTE for ntbootdd */
01591     Status = WinLdrAllocateDataTableEntry(&ModuleListHead, "ntbootdd.sys",
01592         "NTBOOTDD.SYS", ImageBase, &BootDdDTE);
01593     if (!Status)
01594         return EIO;
01595 
01596     /* Add the PE part of freeldr.sys to the list of loaded executables, it
01597        contains Scsiport* exports, imported by ntbootdd.sys */
01598     Status = WinLdrAllocateDataTableEntry(&ModuleListHead, "scsiport.sys",
01599         "FREELDR.SYS", &__ImageBase, &FreeldrDTE);
01600     if (!Status)
01601     {
01602         RemoveEntryList(&BootDdDTE->InLoadOrderLinks);
01603         return EIO;
01604     }
01605 
01606     /* Fix imports */
01607     Status = WinLdrScanImportDescriptorTable(&ModuleListHead, "", BootDdDTE);
01608 
01609     /* Now unlinkt the DTEs, they won't be valid later */
01610     RemoveEntryList(&BootDdDTE->InLoadOrderLinks);
01611     RemoveEntryList(&FreeldrDTE->InLoadOrderLinks);
01612 
01613     if (!Status)
01614         return EIO;
01615 
01616     /* Change imports to PA */
01617     ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(BootDdDTE->DllBase),
01618         TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize);
01619     for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != 0);ImportTable++)
01620     {
01621         PIMAGE_THUNK_DATA ThunkData = (PIMAGE_THUNK_DATA)VaToPa(RVA(BootDdDTE->DllBase, ImportTable->FirstThunk));
01622 
01623         while (((PIMAGE_THUNK_DATA)ThunkData)->u1.AddressOfData != 0)
01624         {
01625             ThunkData->u1.Function = (ULONG)VaToPa((PVOID)ThunkData->u1.Function);
01626             ThunkData++;
01627         }
01628     }
01629 
01630     /* Relocate image to PA */
01631     NtHeaders = RtlImageNtHeader(VaToPa(BootDdDTE->DllBase));
01632     if (!NtHeaders)
01633         return EIO;
01634     Status = (BOOLEAN)LdrRelocateImageWithBias(
01635         VaToPa(BootDdDTE->DllBase),
01636         NtHeaders->OptionalHeader.ImageBase - (ULONG_PTR)BootDdDTE->DllBase,
01637         "FreeLdr",
01638         TRUE,
01639         TRUE, /* in case of conflict still return success */
01640         FALSE);
01641     if (!Status)
01642         return EIO;
01643 
01644     /* Call the entrypoint */
01645     EntryPoint = VaToPa(BootDdDTE->EntryPoint);
01646     (*EntryPoint)(NULL, NULL);
01647 
01648     return ESUCCESS;
01649 }
01650 
01651 /* EOF */

Generated on Sat May 26 2012 04:17:56 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.