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

📄 isapnp.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: isapnp.c 27433 2007-07-06 20:25:30Z cwittich $
 *
 * PROJECT:         ReactOS ISA PnP Bus driver
 * FILE:            isapnp.c
 * PURPOSE:         Driver entry
 * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
 * NOTE:            Parts adapted from linux ISA PnP driver
 * UPDATE HISTORY:
 *      01-05-2001  CSH  Created
 */
#include <isapnp.h>

#ifndef NDEBUG
#define NDEBUG
#endif
#include <debug.h>


#ifdef  ALLOC_PRAGMA

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

#pragma  alloc_text(init, DriverEntry)


#endif  /*  ALLOC_PRAGMA  */


PUCHAR IsaPnPReadPort;


#define UCHAR2USHORT(v0, v1) \
  ((v1 << 8) | v0)

#define UCHAR2ULONG(v0, v1, v2, v3) \
  ((UCHAR2USHORT(v2, v3) << 16) | UCHAR2USHORT(v0, v1))


#ifndef NDEBUG

struct
{
  PCH Name;
} SmallTags[] = {
  {"Unknown Small Tag"},
  {"ISAPNP_SRIN_VERSION"},
  {"ISAPNP_SRIN_LDEVICE_ID"},
  {"ISAPNP_SRIN_CDEVICE_ID"},
  {"ISAPNP_SRIN_IRQ_FORMAT"},
  {"ISAPNP_SRIN_DMA_FORMAT"},
  {"ISAPNP_SRIN_START_DFUNCTION"},
  {"ISAPNP_SRIN_END_DFUNCTION"},
  {"ISAPNP_SRIN_IO_DESCRIPTOR"},
  {"ISAPNP_SRIN_FL_IO_DESCRIPOTOR"},
  {"Reserved Small Tag"},
  {"Reserved Small Tag"},
  {"Reserved Small Tag"},
  {"Reserved Small Tag"},
  {"ISAPNP_SRIN_VENDOR_DEFINED"},
  {"ISAPNP_SRIN_END_TAG"}
};

struct
{
  PCH Name;
} LargeTags[] = {
  {"Unknown Large Tag"},
  {"ISAPNP_LRIN_MEMORY_RANGE"},
  {"ISAPNP_LRIN_ID_STRING_ANSI"},
  {"ISAPNP_LRIN_ID_STRING_UNICODE"},
  {"ISAPNP_LRIN_VENDOR_DEFINED"},
  {"ISAPNP_LRIN_MEMORY_RANGE32"},
  {"ISAPNP_LRIN_FL_MEMORY_RANGE32"}
};

PCSZ TagName(ULONG Tag, BOOLEAN Small)
{
  if (Small && (Tag <= ISAPNP_SRIN_END_TAG)) {
    return SmallTags[Tag].Name;
  } else if (Tag <= ISAPNP_LRIN_FL_MEMORY_RANGE32){
    return LargeTags[Tag].Name;
  }

  return NULL;
}

#endif

static __inline VOID WriteData(UCHAR Value)
{
  WRITE_PORT_UCHAR((PUCHAR)ISAPNP_WRITE_PORT, Value);
}

static __inline VOID WriteAddress(UCHAR Value)
{
	WRITE_PORT_UCHAR((PUCHAR)ISAPNP_ADDRESS_PORT, Value);
	KeStallExecutionProcessor(20);
}

static __inline UCHAR ReadData(VOID)
{
	return READ_PORT_UCHAR(IsaPnPReadPort);
}

static UCHAR ReadUchar(UCHAR Index)
{
	WriteAddress(Index);
	return ReadData();
}

#if 0
static USHORT ReadUshort(UCHAR Index)
{
	USHORT Value;

	Value = ReadUchar(Index);
	Value = (Value << 8) + ReadUchar(Index + 1);
	return Value;
}

static ULONG ReadUlong(UCHAR Index)
{
	ULONG Value;

	Value = ReadUchar(Index);
	Value = (Value << 8) + ReadUchar(Index + 1);
	Value = (Value << 8) + ReadUchar(Index + 2);
	Value = (Value << 8) + ReadUchar(Index + 3);
	return Value;
}
#endif

static VOID WriteUchar(UCHAR Index, UCHAR Value)
{
	WriteAddress(Index);
	WriteData(Value);
}

#if 0
static VOID WriteUshort(UCHAR Index, USHORT Value)
{
	WriteUchar(Index, Value >> 8);
	WriteUchar(Index + 1, Value);
}

static VOID WriteUlong(UCHAR Index, ULONG Value)
{
	WriteUchar(Index, Value >> 24);
	WriteUchar(Index + 1, Value >> 16);
	WriteUchar(Index + 2, Value >> 8);
	WriteUchar(Index + 3, Value);
}
#endif

static __inline VOID SetReadDataPort(ULONG Port)
{
  IsaPnPReadPort = (PUCHAR)Port;
	WriteUchar(0x00, (UCHAR) (Port >> 2));
	KeStallExecutionProcessor(100);
}

static VOID SendKey(VOID)
{
  ULONG i;
  UCHAR msb;
	UCHAR code;

  /* FIXME: Is there something better? */
	KeStallExecutionProcessor(1000);
	WriteAddress(0x00);
	WriteAddress(0x00);

  code = 0x6a;
	WriteAddress(code);
	for (i = 1; i < 32; i++) {
		msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;
		code = (code >> 1) | msb;
		WriteAddress(code);
	}
}

/* Place all PnP cards in wait-for-key state */
static VOID SendWait(VOID)
{
	WriteUchar(0x02, 0x02);
}

static VOID SendWake(UCHAR csn)
{
	WriteUchar(ISAPNP_CARD_WAKECSN, csn);
}

#if 0
static VOID SelectLogicalDevice(UCHAR LogicalDevice)
{
	WriteUchar(ISAPNP_CARD_LOG_DEVICE_NUM, LogicalDevice);
}

static VOID ActivateLogicalDevice(UCHAR LogicalDevice)
{
	SelectLogicalDevice(LogicalDevice);
	WriteUchar(ISAPNP_CONTROL_ACTIVATE, 0x1);
	KeStallExecutionProcessor(250);
}

static VOID DeactivateLogicalDevice(UCHAR LogicalDevice)
{
	SelectLogicalDevice(LogicalDevice);
	WriteUchar(ISAPNP_CONTROL_ACTIVATE, 0x0);
	KeStallExecutionProcessor(500);
}
#endif

#define READ_DATA_PORT_STEP 32  /* Minimum is 4 */

static ULONG FindNextReadPort(VOID)
{
	ULONG Port;



	Port = (ULONG)IsaPnPReadPort;

	while (TRUE) {

		Port += READ_DATA_PORT_STEP;



		if (Port > ISAPNP_MAX_READ_PORT)

		{

			return 0;

		}



		/*

		 * We cannot use NE2000 probe spaces for

		 * ISAPnP or we will lock up machines

		 */

		if ((Port < 0x280) || (Port > 0x380))

		{

			return Port;

		}

	}

}

static BOOLEAN IsolateReadDataPortSelect(VOID)
{
  ULONG Port;

	SendWait();
	SendKey();

	/* Control: reset CSN and conditionally everything else too */
	WriteUchar(0x02, 0x05);
	KeStallExecutionProcessor(2000);

	SendWait();
	SendKey();
	SendWake(0x00);

	Port = FindNextReadPort();
  if (Port == 0) {
		SendWait();
		return FALSE;
	}

	SetReadDataPort(Port);
	KeStallExecutionProcessor(1000);
  WriteAddress(0x01);
	KeStallExecutionProcessor(1000);
	return TRUE;
}

/*
 * Isolate (assign uniqued CSN) to all ISA PnP devices
 */
static ULONG IsolatePnPCards(VOID)
{
	UCHAR checksum = 0x6a;
	UCHAR chksum = 0x00;
	UCHAR bit = 0x00;
	ULONG data;
	ULONG csn = 0;
	ULONG i;
	ULONG iteration = 1;

  DPRINT("Called\n");

	IsaPnPReadPort = (PUCHAR)ISAPNP_MIN_READ_PORT;
  if (!IsolateReadDataPortSelect()) {
    DPRINT("Could not set read data port\n");
		return 0;
  }

	while (TRUE) {
		for (i = 1; i <= 64; i++) {
			data = ReadData() << 8;
			KeStallExecutionProcessor(250);
			data = data | ReadData();
			KeStallExecutionProcessor(250);
			if (data == 0x55aa)
				bit = 0x01;
			checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
			bit = 0x00;
		}
		for (i = 65; i <= 72; i++) {
			data = ReadData() << 8;
			KeStallExecutionProcessor(250);
			data = data | ReadData();
			KeStallExecutionProcessor(250);
			if (data == 0x55aa)
				chksum |= (1 << (i - 65));
		}
		if ((checksum != 0x00) && (checksum == chksum)) {
			csn++;

			WriteUchar(0x06, (UCHAR) csn);
			KeStallExecutionProcessor(250);
			iteration++;
			SendWake(0x00);
			SetReadDataPort((ULONG)IsaPnPReadPort);
			KeStallExecutionProcessor(1000);
			WriteAddress(0x01);
			KeStallExecutionProcessor(1000);
			goto next;
		}
		if (iteration == 1) {
			IsaPnPReadPort += READ_DATA_PORT_STEP;
      if (!IsolateReadDataPortSelect()) {
        DPRINT("Could not set read data port\n");
				return 0;
      }
		} else if (iteration > 1) {
			break;
		}
next:
		checksum = 0x6a;
		chksum = 0x00;
		bit = 0x00;
	}
	SendWait();
	return csn;
}


static VOID Peek(PUCHAR Data, ULONG Count)
{
	ULONG i, j;
	UCHAR d = 0;

	for (i = 1; i <= Count; i++) {
		for (j = 0; j < 20; j++) {
			d = ReadUchar(0x05);
			if (d & 0x1)
				break;
			KeStallExecutionProcessor(100);
		}
		if (!(d & 0x1)) {
			if (Data != NULL)
				*Data++ = 0xff;
			continue;
		}
		d = ReadUchar(0x04); /* PRESDI */
		if (Data != NULL)
			*Data++ = d;
	}
}


/*
 * Skip specified number of bytes from stream
 */
static VOID Skip(ULONG Count)
{
	Peek(NULL, Count);
}


/*
 * Read one tag from stream
 */
static BOOLEAN ReadTag(PUCHAR Type,
  PUSHORT Size,
  PBOOLEAN Small)
{
	UCHAR tag, tmp[2];

	Peek(&tag, 1);
  if (tag == 0) {
    /* Invalid tag */
    DPRINT("Invalid tag with value 0\n");
#ifndef NDEBUG
    for (;;);
#endif
		return FALSE;
  }

	if (tag & ISAPNP_RESOURCE_ITEM_TYPE) {
    /* Large resource item */
		*Type = (tag & 0x7f);
		Peek(tmp, 2);
		*Size = UCHAR2USHORT(tmp[0], tmp[1]);
    *Small = FALSE;
#ifndef NDEBUG
    if (*Type > ISAPNP_LRIN_FL_MEMORY_RANGE32) {
      DPRINT("Invalid large tag with value 0x%X\n", *Type);
      for (;;);
    }
#endif
	} else {
    /* Small resource item */
		*Type = (tag >> 3) & 0x0f;
		*Size = tag & 0x07;
    *Small = TRUE;
#ifndef NDEBUG
    if (*Type > ISAPNP_SRIN_END_TAG) {
      DPRINT("Invalid small tag with value 0x%X\n", *Type);
      for (;;);
    }
#endif
  }
#if 0
	DPRINT("Tag = 0x%X, Type = 0x%X, Size = %d (%s)\n",
    tag, *Type, *Size, TagName(*Type, *Small));
#endif
  /* Probably invalid data */
  if ((*Type == 0xff) && (*Size == 0xffff)) {
    DPRINT("Invalid data (Type 0x%X  Size 0x%X)\n", *Type, *Size);
    for (;;);
		return FALSE;
  }

	return TRUE;
}


/*
 * Parse ANSI name for ISA PnP logical device
 */
static NTSTATUS ParseAnsiName(PUNICODE_STRING Name, PUSHORT Size)
{
  ANSI_STRING AnsiString;
  UCHAR Buffer[256];
  USHORT size1;

  size1 = (*Size >= sizeof(Buffer)) ? (sizeof(Buffer) - 1) : *Size;

  Peek(Buffer, size1);
  Buffer[size1] = '\0';
  *Size -= size1;

  /* Clean whitespace from end of string */
  while ((size1 > 0) && (Buffer[--size1] == ' '))
    Buffer[size1] = '\0';

  DPRINT("ANSI name: %s\n", Buffer);

  RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
  return RtlAnsiStringToUnicodeString(Name, &AnsiString, TRUE);
}


/*
 * Add a resource list to the
 * resource lists of a logical device
 */
static NTSTATUS AddResourceList(
  PISAPNP_LOGICAL_DEVICE LogicalDevice,
  ULONG Priority,
  PISAPNP_CONFIGURATION_LIST *NewList)
{
  PISAPNP_CONFIGURATION_LIST List;

  DPRINT("Adding resource list for logical device %d on card %d (Priority %d)\n",
        LogicalDevice->Number,
        LogicalDevice->Card->CardId,
        Priority);

  List = (PISAPNP_CONFIGURATION_LIST)
      ExAllocatePoolWithTag(PagedPool, sizeof(ISAPNP_CONFIGURATION_LIST), TAG_ISAPNP);
  if (!List)
    return STATUS_INSUFFICIENT_RESOURCES;

  RtlZeroMemory(List, sizeof(ISAPNP_CONFIGURATION_LIST));

  List->Priority = Priority;

  InitializeListHead(&List->ListHead);

  InsertTailList(&LogicalDevice->Configuration, &List->ListEntry);

  *NewList = List;

  return STATUS_SUCCESS;
}


/*
 * Add a resource entry to the
 * resource list of a logical device
 */
static NTSTATUS AddResourceDescriptor(
  PISAPNP_LOGICAL_DEVICE LogicalDevice,
  ULONG Priority,
  ULONG Option,
  PISAPNP_DESCRIPTOR *Descriptor)
{
  PLIST_ENTRY CurrentEntry;
  PISAPNP_CONFIGURATION_LIST List;
  PISAPNP_DESCRIPTOR d;
  NTSTATUS Status;

  DPRINT("Adding resource descriptor for logical device %d on card %d (%d of %d)\n",
        LogicalDevice->Number,
        LogicalDevice->Card->CardId,
        LogicalDevice->CurrentDescriptorCount,
        LogicalDevice->DescriptorCount);

  d = (PISAPNP_DESCRIPTOR)
    ExAllocatePoolWithTag(PagedPool, sizeof(ISAPNP_DESCRIPTOR), TAG_ISAPNP);
  if (!d)
    return STATUS_NO_MEMORY;

  RtlZeroMemory(d, sizeof(ISAPNP_DESCRIPTOR));

  d->Descriptor.Option = (UCHAR) Option;

  *Descriptor = d;

  CurrentEntry = LogicalDevice->Configuration.Flink;
  while (CurrentEntry != &LogicalDevice->Configuration) {
    List = CONTAINING_RECORD(
      CurrentEntry, ISAPNP_CONFIGURATION_LIST, ListEntry);

    if (List->Priority == Priority) {

      LogicalDevice->ConfigurationSize += sizeof(IO_RESOURCE_DESCRIPTOR);
      InsertTailList(&List->ListHead, &d->ListEntry);
      LogicalDevice->CurrentDescriptorCount++;
      if (LogicalDevice->DescriptorCount <
        LogicalDevice->CurrentDescriptorCount) {
        LogicalDevice->DescriptorCount =
          LogicalDevice->CurrentDescriptorCount;
      }

      return STATUS_SUCCESS;
    }
    CurrentEntry = CurrentEntry->Flink;
  }

  Status = AddResourceList(LogicalDevice, Priority, &List);
  if (NT_SUCCESS(Status)) {
    LogicalDevice->ConfigurationSize += sizeof(IO_RESOURCE_LIST);
    LogicalDevice->CurrentDescriptorCount = 0;
    InsertTailList(&List->ListHead, &d->ListEntry);
  }

  return Status;
}


/*
 * Add IRQ resource to resources list
 */
static NTSTATUS AddIrqResource(
  PISAPNP_LOGICAL_DEVICE LogicalDevice,

⌨️ 快捷键说明

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