Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenscsiport.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
1.7.6.1
|