atapi.c

来自「一个类似windows」· C语言 代码 · 共 2,047 行 · 第 1/5 页

C
2,047
字号
/*
 *  ReactOS kernel
 *  Copyright (C) 2001, 2002, 2003, 2004, 2005 ReactOS Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/* $Id: atapi.c 21260 2006-03-08 23:23:57Z audit $
 *
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS ATAPI miniport driver
 * FILE:        drivers/storage/atapi/atapi.c
 * PURPOSE:     ATAPI miniport driver
 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
 * REVISIONS:
 *              09-09-2001 Created
 */

/*
 * Note:
 *   This driver is derived from Rex Jolliff's ide driver. Lots of his
 *   routines are still in here although they belong into the higher level
 *   drivers. They will be moved away as soon as possible.
 */

/*
 * TODO:
 *	- implement sending of atapi commands
 *	- handle removable atapi non-cdrom drives
 */

#define ENABLE_PCI
#define ENABLE_NATIVE_PCI
#define ENABLE_ISA
#define ENABLE_DMA

//  -------------------------------------------------------------------------

#include <ntddk.h>
#include <srb.h>
#include <scsi.h>
#include <ntddscsi.h>
#include <ntdddisk.h>
#include <ntddstor.h>

#include "atapi.h"

#define NDEBUG
#include <debug.h>

#define VERSION  "0.0.1"


NTSTATUS NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath);

//  -------------------------------------------------------  File Static Data

#ifdef ENABLE_DMA
typedef struct _PRD
{
  ULONG PhysAddress;
  ULONG Length;
} PRD, *PPRD;
#endif

//    ATAPI_MINIPORT_EXTENSION
//
//  DESCRIPTION:
//    Extension to be placed in each port device object
//
//  ACCESS:
//    Allocated from NON-PAGED POOL
//    Available at any IRQL
//

typedef struct _ATAPI_MINIPORT_EXTENSION
{
  IDE_DRIVE_IDENTIFY DeviceParams[2];
  ULONG DeviceFlags[2];
  ULONG TransferSize[2];

  ULONG CommandPortBase;
  ULONG ControlPortBase;
  ULONG BusMasterRegisterBase;

  PSCSI_REQUEST_BLOCK CurrentSrb;

  PUCHAR DataBuffer;
  ULONG DataTransferLength;

  BOOLEAN (FASTCALL *Handler)(IN struct _ATAPI_MINIPORT_EXTENSION* DevExt);
#ifdef ENABLE_DMA
  BOOLEAN UseDma;
  ULONG PRDCount;
  ULONG PRDMaxCount;
  PPRD PRDTable;
  SCSI_PHYSICAL_ADDRESS PRDTablePhysicalAddress;
#endif
} ATAPI_MINIPORT_EXTENSION, *PATAPI_MINIPORT_EXTENSION;

/* DeviceFlags */
#define DEVICE_PRESENT           0x00000001
#define DEVICE_ATAPI             0x00000002
#define DEVICE_MULTI_SECTOR_CMD  0x00000004
#define DEVICE_DWORD_IO          0x00000008
#define DEVICE_48BIT_ADDRESS     0x00000010
#define DEVICE_MEDIA_STATUS      0x00000020
#define DEVICE_DMA_CMD           0x00000040
#define DEVICE_NO_FLUSH          0x00000080


typedef struct _UNIT_EXTENSION
{
  ULONG Dummy;
} UNIT_EXTENSION, *PUNIT_EXTENSION;

PCI_SLOT_NUMBER LastSlotNumber;

#ifdef ENABLE_NATIVE_PCI
typedef struct _PCI_NATIVE_CONTROLLER
{
  USHORT VendorID;
  USHORT DeviceID;
}
PCI_NATIVE_CONTROLLER, *PPCI_NATIVE_CONTROLLER;

PCI_NATIVE_CONTROLLER const PciNativeController[] =
{
    {
	0x105A,		    // Promise
	0x4D68,		    // PDC20268, Ultra100TX2
    },
    {
	0x105A,		    // Promise
	0x4D30,		    // PDC20267, Ultra100
    }
};
#endif


//  -----------------------------------------------  Discardable Declarations

#ifdef  ALLOC_PRAGMA

//  make the initialization routines discardable, so that they
//  don't waste space

#pragma  alloc_text(init, DriverEntry)

//  make the PASSIVE_LEVEL routines pageable, so that they don't
//  waste nonpaged memory

#endif  /*  ALLOC_PRAGMA  */

//  ---------------------------------------------------- Forward Declarations

#ifdef ENABLE_DMA
static BOOLEAN
AtapiInitDma(PATAPI_MINIPORT_EXTENSION DevExt,
	     PSCSI_REQUEST_BLOCK Srb,
	     UCHAR cmd);
#endif

static ULONG STDCALL
AtapiFindCompatiblePciController(PVOID DeviceExtension,
				 PVOID HwContext,
				 PVOID BusInformation,
				 PCHAR ArgumentString,
				 PPORT_CONFIGURATION_INFORMATION ConfigInfo,
				 PBOOLEAN Again);

static ULONG STDCALL
AtapiFindIsaBusController(PVOID DeviceExtension,
			  PVOID HwContext,
			  PVOID BusInformation,
			  PCHAR ArgumentString,
			  PPORT_CONFIGURATION_INFORMATION ConfigInfo,
			  PBOOLEAN Again);

static ULONG STDCALL
AtapiFindNativePciController(PVOID DeviceExtension,
			     PVOID HwContext,
			     PVOID BusInformation,
			     PCHAR ArgumentString,
			     PPORT_CONFIGURATION_INFORMATION ConfigInfo,
			     PBOOLEAN Again);

static BOOLEAN STDCALL
AtapiInitialize(IN PVOID DeviceExtension);

static BOOLEAN STDCALL
AtapiResetBus(IN PVOID DeviceExtension,
	      IN ULONG PathId);

static BOOLEAN STDCALL
AtapiStartIo(IN PVOID DeviceExtension,
	     IN PSCSI_REQUEST_BLOCK Srb);

static VOID
AtapiExecuteCommand(PATAPI_MINIPORT_EXTENSION DevExt,
		    UCHAR command,
		    BOOLEAN (FASTCALL *Handler)(PATAPI_MINIPORT_EXTENSION));

static BOOLEAN STDCALL
AtapiInterrupt(IN PVOID DeviceExtension);

static BOOLEAN FASTCALL
AtapiNoDataInterrupt(PATAPI_MINIPORT_EXTENSION DevExt);

static BOOLEAN FASTCALL
AtapiPacketInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);

static BOOLEAN FASTCALL
AtapiSmartInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);

static BOOLEAN FASTCALL
AtapiReadInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);

#ifdef ENABLE_DMA
static BOOLEAN FASTCALL
AtapiDmaPacketInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);

static BOOLEAN FASTCALL
AtapiDmaInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);
#endif

static BOOLEAN FASTCALL
AtapiWriteInterrupt(IN PATAPI_MINIPORT_EXTENSION DevExt);

static BOOLEAN
AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
		 PPORT_CONFIGURATION_INFORMATION ConfigInfo);

static BOOLEAN
AtapiIdentifyDevice(IN ULONG CommandPort,
		    IN ULONG ControlPort,
		    IN ULONG DriveNum,
		    IN BOOLEAN Atapi,
		    OUT PIDE_DRIVE_IDENTIFY DrvParms);

static BOOLEAN
AtapiPolledRead(IN ULONG CommandPort,
		IN ULONG ControlPort,
		IN UCHAR PreComp,
		IN UCHAR SectorCnt,
		IN UCHAR SectorNum,
		IN UCHAR CylinderLow,
		IN UCHAR CylinderHigh,
		IN UCHAR DrvHead,
		IN UCHAR Command,
		OUT PUCHAR Buffer);

static ULONG
AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
		      IN PSCSI_REQUEST_BLOCK Srb);

static ULONG
AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
		    IN PSCSI_REQUEST_BLOCK Srb);

static ULONG
AtapiSendSmartCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
                      IN PSCSI_REQUEST_BLOCK Srb);

static ULONG
AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
	     IN PSCSI_REQUEST_BLOCK Srb);

static ULONG
AtapiReadCapacity(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
		  IN PSCSI_REQUEST_BLOCK Srb);

static ULONG
AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
	       IN PSCSI_REQUEST_BLOCK Srb);

static ULONG
AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
		PSCSI_REQUEST_BLOCK Srb);

static ULONG
AtapiTestUnitReady(PATAPI_MINIPORT_EXTENSION DeviceExtension,
		   PSCSI_REQUEST_BLOCK Srb);

static UCHAR
AtapiErrorToScsi(PVOID DeviceExtension,
		 PSCSI_REQUEST_BLOCK Srb);

static VOID
AtapiScsiSrbToAtapi (PSCSI_REQUEST_BLOCK Srb);

//  ----------------------------------------------------------------  Inlines

void
IDESwapBytePairs(UCHAR *Buf,
                 int Cnt)
{
  UCHAR  t;
  int   i;

  for (i = 0; i < Cnt; i += 2)
    {
      t = Buf[i];
      Buf[i] = Buf[i+1];
      Buf[i+1] = t;
    }
}


//  -------------------------------------------------------  Public Interface

//    DriverEntry
//
//  DESCRIPTION:
//    This function initializes the driver, locates and claims
//    hardware resources, and creates various NT objects needed
//    to process I/O requests.
//
//  RUN LEVEL:
//    PASSIVE_LEVEL
//
//  ARGUMENTS:
//    IN  PDRIVER_OBJECT   DriverObject  System allocated Driver Object
//                                       for this driver
//    IN  PUNICODE_STRING  RegistryPath  Name of registry driver service
//                                       key
//
//  RETURNS:
//    NTSTATUS

NTSTATUS NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath)
{
  HW_INITIALIZATION_DATA InitData;
  NTSTATUS Status;

  DPRINT("ATAPI Driver %s\n", VERSION);
  DPRINT("RegistryPath: '%wZ'\n", RegistryPath);

  /* Initialize data structure */
  RtlZeroMemory(&InitData,
		sizeof(HW_INITIALIZATION_DATA));
  InitData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
  InitData.HwInitialize = AtapiInitialize;
  InitData.HwResetBus = AtapiResetBus;
  InitData.HwStartIo = AtapiStartIo;
  InitData.HwInterrupt = AtapiInterrupt;

  InitData.DeviceExtensionSize = sizeof(ATAPI_MINIPORT_EXTENSION);
  InitData.SpecificLuExtensionSize = sizeof(UNIT_EXTENSION);

  InitData.MapBuffers = TRUE;

  /* Search the PCI bus for compatibility mode ide controllers */
#ifdef ENABLE_PCI
  InitData.NeedPhysicalAddresses = TRUE;

  InitData.HwFindAdapter = AtapiFindCompatiblePciController;
  InitData.NumberOfAccessRanges = 3;
  InitData.AdapterInterfaceType = PCIBus;

  InitData.VendorId = NULL;
  InitData.VendorIdLength = 0;
  InitData.DeviceId = NULL;
  InitData.DeviceIdLength = 0;

  Status = ScsiPortInitialize(DriverObject,
			      RegistryPath,
			      &InitData,
			      NULL);
//  if (newStatus < statusToReturn)
//    statusToReturn = newStatus;
#endif

  /* Search the PCI bus for all ide controllers */
#ifdef ENABLE_NATIVE_PCI
  InitData.NeedPhysicalAddresses = TRUE;

  InitData.HwFindAdapter = AtapiFindNativePciController;
  InitData.NumberOfAccessRanges = 3;
  InitData.AdapterInterfaceType = PCIBus;

  InitData.VendorId = 0;
  InitData.VendorIdLength = 0;
  InitData.DeviceId = 0;
  InitData.DeviceIdLength = 0;

  LastSlotNumber.u.AsULONG = 0xFFFFFFFF;

  Status = ScsiPortInitialize(DriverObject,
			      RegistryPath,
			      &InitData,
			      NULL);
//  if (newStatus < statusToReturn)
//    statusToReturn = newStatus;
#endif

⌨️ 快捷键说明

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