⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 class2.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:

NTSTATUS
STDCALL
ScsiClassGetCapabilities(
    IN PDEVICE_OBJECT PortDeviceObject,
    OUT PIO_SCSI_CAPABILITIES *PortCapabilities
    )

/*++

Routine Description:

    This routine builds and sends a request to the port driver to
    get a pointer to a structure that describes the adapter's
    capabilities/limitations. This routine is sychronous.

Arguments:

    PortDeviceObject - Port driver device object representing the HBA.

    PortCapabilities - Location to store pointer to capabilities structure.

Return Value:

    Nt status indicating the results of the operation.

Notes:

    This routine should only be called at initialization time.

--*/

{
    PIRP            irp;
    IO_STATUS_BLOCK ioStatus;
    KEVENT          event;
    NTSTATUS        status;

    PAGED_CODE();

    //
    // Create notification event object to be used to signal the
    // request completion.
    //

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    //
    // Build the synchronous request  to be sent to the port driver
    // to perform the request.
    //

    irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES,
                                        PortDeviceObject,
                                        NULL,
                                        0,
                                        PortCapabilities,
                                        sizeof(PVOID),
                                        FALSE,
                                        &event,
                                        &ioStatus);

    if (irp == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Pass request to port driver and wait for request to complete.
    //

    status = IoCallDriver(PortDeviceObject, irp);

    if (status == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
        return(ioStatus.Status);
    }

    return status;

} // end ScsiClassGetCapabilities()


NTSTATUS
STDCALL
ScsiClassGetInquiryData(
    IN PDEVICE_OBJECT PortDeviceObject,
    OUT PSCSI_ADAPTER_BUS_INFO *ConfigInfo
    )

/*++

Routine Description:

    This routine sends a request to a port driver to return
    configuration information. Space for the information is
    allocated by this routine. The caller is responsible for
    freeing the configuration information. This routine is
    synchronous.

Arguments:

    PortDeviceObject - Port driver device object representing the HBA.

    ConfigInfo - Returns a pointer to the configuration information.

Return Value:

    Nt status indicating the results of the operation.

Notes:

    This routine should be called only at initialization time.

--*/

{
    PIRP                   irp;
    IO_STATUS_BLOCK        ioStatus;
    KEVENT                 event;
    NTSTATUS               status;
    PSCSI_ADAPTER_BUS_INFO buffer;

    PAGED_CODE();

    buffer = ExAllocatePool(PagedPool, INQUIRY_DATA_SIZE);
    *ConfigInfo = buffer;

    if (buffer == NULL) {
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // Create notification event object to be used to signal the inquiry
    // request completion.
    //

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    //
    // Build the synchronous request to be sent to the port driver
    // to perform the inquiries.
    //

    irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA,
                                        PortDeviceObject,
                                        NULL,
                                        0,
                                        buffer,
                                        INQUIRY_DATA_SIZE,
                                        FALSE,
                                        &event,
                                        &ioStatus);

    if (irp == NULL) {
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // Pass request to port driver and wait for request to complete.
    //

    status = IoCallDriver(PortDeviceObject, irp);

    if (status == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
        status = ioStatus.Status;
    }

    if (!NT_SUCCESS(status)) {

        //
        // Free the buffer on an error.
        //

        ExFreePool(buffer);
        *ConfigInfo = NULL;

    }

    return status;

} // end ScsiClassGetInquiryData()


NTSTATUS
STDCALL
ScsiClassReadDriveCapacity(
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This routine sends a READ CAPACITY to the requested device, updates
    the geometry information in the device object and returns
    when it is complete.  This routine is synchronous.

Arguments:

    DeviceObject - Supplies a pointer to the device object that represents
        the device whose capacity is to be read.

Return Value:

    Status is returned.

--*/
{
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
    ULONG               retries = 1;
    ULONG               lastSector;
    PCDB                cdb;
    PREAD_CAPACITY_DATA readCapacityBuffer;
    SCSI_REQUEST_BLOCK  srb;
    NTSTATUS            status;

    //
    // Allocate read capacity buffer from nonpaged pool.
    //

    readCapacityBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
                                        sizeof(READ_CAPACITY_DATA));

    if (!readCapacityBuffer) {
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));

    //
    // Build the read capacity CDB.
    //

    srb.CdbLength = 10;
    cdb = (PCDB)srb.Cdb;

    //
    // Set timeout value from device extension.
    //

    srb.TimeOutValue = deviceExtension->TimeOutValue;

    cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;

Retry:

    status = ScsiClassSendSrbSynchronous(DeviceObject,
                                &srb,
                                readCapacityBuffer,
                                sizeof(READ_CAPACITY_DATA),
                                FALSE);

    if (NT_SUCCESS(status)) {

        //
        // Copy sector size from read capacity buffer to device extension
        // in reverse byte order.
        //

        ((PFOUR_BYTE)&deviceExtension->DiskGeometry->BytesPerSector)->Byte0 =
            ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte3;

        ((PFOUR_BYTE)&deviceExtension->DiskGeometry->BytesPerSector)->Byte1 =
            ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte2;

        ((PFOUR_BYTE)&deviceExtension->DiskGeometry->BytesPerSector)->Byte2 =
            ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte1;

        ((PFOUR_BYTE)&deviceExtension->DiskGeometry->BytesPerSector)->Byte3 =
            ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte0;

        //
        // Copy last sector in reverse byte order.
        //

        ((PFOUR_BYTE)&lastSector)->Byte0 =
            ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte3;

        ((PFOUR_BYTE)&lastSector)->Byte1 =
            ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte2;

        ((PFOUR_BYTE)&lastSector)->Byte2 =
            ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte1;

        ((PFOUR_BYTE)&lastSector)->Byte3 =
            ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte0;

        //
        // Calculate sector to byte shift.
        //

        WHICH_BIT(deviceExtension->DiskGeometry->BytesPerSector, deviceExtension->SectorShift);

        DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n",
            deviceExtension->DiskGeometry->BytesPerSector));

        DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n",
            lastSector + 1));

        //
        // Calculate media capacity in bytes.
        //

        deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);

        //
        // Calculate number of cylinders.
        //

        deviceExtension->DiskGeometry->Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64));

        deviceExtension->PartitionLength.QuadPart =
            (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);

        if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {

            //
            // This device supports removable media.
            //

            deviceExtension->DiskGeometry->MediaType = RemovableMedia;

        } else {

            //
            // Assume media type is fixed disk.
            //

            deviceExtension->DiskGeometry->MediaType = FixedMedia;
        }

        //
        // Assume sectors per track are 32;
        //

        deviceExtension->DiskGeometry->SectorsPerTrack = 32;

        //
        // Assume tracks per cylinder (number of heads) is 64.
        //

        deviceExtension->DiskGeometry->TracksPerCylinder = 64;
    }

    if (status == STATUS_VERIFY_REQUIRED) {

        //
        // Routine ScsiClassSendSrbSynchronous does not retry
        // requests returned with this status.
        // Read Capacities should be retried
        // anyway.
        //

        if (retries--) {

            //
            // Retry request.
            //

            goto Retry;
        }
    }

    if (!NT_SUCCESS(status)) {

        //
        // If the read capacity fails, set the geometry to reasonable parameter
        // so things don't fail at unexpected places.  Zero the geometry
        // except for the bytes per sector and sector shift.
        //

        RtlZeroMemory(deviceExtension->DiskGeometry, sizeof(DISK_GEOMETRY));
        deviceExtension->DiskGeometry->BytesPerSector = 512;
        deviceExtension->SectorShift = 9;
        deviceExtension->PartitionLength.QuadPart = (LONGLONG) 0;

        if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {

            //
            // This device supports removable media.
            //

            deviceExtension->DiskGeometry->MediaType = RemovableMedia;

        } else {

            //
            // Assume media type is fixed disk.
            //

            deviceExtension->DiskGeometry->MediaType = FixedMedia;
        }
    }

    //
    // Deallocate read capacity buffer.
    //

    ExFreePool(readCapacityBuffer);

    return status;

} // end ScsiClassReadDriveCapacity()


VOID
STDCALL
ScsiClassReleaseQueue(
    IN PDEVICE_OBJECT DeviceObject
    )

/*++

Routine Description:

    This routine issues an internal device control command
    to the port driver to release a frozen queue. The call
    is issued asynchronously as ScsiClassReleaseQueue will be invoked
    from the IO completion DPC (and will have no context to
    wait for a synchronous call to complete).

Arguments:

    DeviceObject - The device object for the logical unit with
        the frozen queue.

Return Value:

    None.

--*/
{
    PIO_STACK_LOCATION irpStack;
    PIRP irp;
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    PCOMPLETION_CONTEXT context;
    PSCSI_REQUEST_BLOCK srb;
    KIRQL currentIrql;

    //
    // Allocate context from nonpaged pool.
    //

    context = ExAllocatePool(NonPagedPoolMustSucceed,
                             sizeof(COMPLETION_CONTEXT));

    //
    // Save the device object in the context for use by the completion
    // routine.
    //

    context->DeviceObject = DeviceObject;
    srb = &context->Srb;

    //
    // Zero out srb.
    //

    RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);

    //
    // Write length to SRB.
    //

    srb->Length = SCSI_REQUEST_BLOCK_SIZE;

    //
    // Set up SCSI bus address.
    //

    srb->PathId = deviceExtension->PathId;
    srb->TargetId = deviceExtension->TargetId;
    srb->Lun = deviceExtension->Lun;

    //
    // If this device is removable then flush the queue.  This will also
    // release it.
    //

    if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {

       srb->Function = SRB_FUNCTION_FLUSH_QUEUE;

    } else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -