📄 isapnp.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// -----------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// -----------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <pc.h>
int __cdecl _inp (unsigned short);
unsigned short __cdecl _inpw (unsigned short);
unsigned long __cdecl _inpd (unsigned short);
int __cdecl _outp (unsigned short, int);
unsigned short __cdecl _outpw(unsigned short, unsigned short);
unsigned long __cdecl _outpd(unsigned short, unsigned long);
//
// Plug and Play Card Control Registers
//
#define SET_READ_DATA_PORT 0x00
#define SERIAL_ISOLATION_PORT 0x01
#define CONFIG_CONTROL_PORT 0x02
#define WAKE_CSN_PORT 0x03
#define SET_CSN_PORT 0x06
//
// Config Control command
//
#define CONTROL_WAIT_FOR_KEY 0x02
#define CONTROL_RESET_CSN 0x04
#define NUMBER_CARD_ID_BYTES 9
#define NUMBER_CARD_ID_BITS (NUMBER_CARD_ID_BYTES * 8)
#define CHECKSUMED_BITS 64
#define LFSR_SEED 0x6A
#define ISOLATION_TEST_BYTE_1 0x55
#define ISOLATION_TEST_BYTE_2 0xAA
#define PNP_ISA_IO_BASE ( (PUCHAR)0 )
#define PNP_ADDRESS_PORT 0x279
#define PNP_WRITE_DATA_PORT 0xA79
#define PNP_READ_DATA_PORT 0x203
#define pnpWriteAddress(data) _outp ((USHORT) PNP_ADDRESS_PORT, (UCHAR)(data))
#define pnpWriteData(data) _outp ((USHORT) PNP_WRITE_DATA_PORT, (UCHAR)(data))
#define pnpReadData() _inp ((USHORT) PNP_READ_DATA_PORT)
CRITICAL_SECTION g_csISAConfig;
BOOL g_bISAInitialized;
USHORT g_usISAReadPort;
UCHAR g_ucISANumberCSNs;
UCHAR PnPReadRegister (PUCHAR pIOSpace, UCHAR ucRegNo);
void PnPWriteRegister (PUCHAR pIOSpace, UCHAR ucRegNo, UCHAR ucValue);
void PnPSendInitiationKey (PUCHAR pIOSpace);
void PnPSetWaitForKey (PUCHAR pIOSpace);
void PnPWake (PUCHAR pIOSpace, UCHAR ucCSN);
void PnPReadSerialId (PUCHAR pIOSpace, PUCHAR ucSerialId);
int PnPReadResourceData (PUCHAR pIOSpace, PUCHAR ucResourceData, int iDataSize);
int PnPGetLogicalDeviceInfo(PUCHAR ucResourceData, int iDataSize,
PISA_PNP_LOGICAL_DEVICE_INFO pDeviceInfo);
void SC_Sleep(DWORD);
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
PnPIsolateCards (VOID)
{
USHORT j;
UCHAR cardId[NUMBER_CARD_ID_BYTES];
UCHAR bit, bit7, checksum, byte1, byte2;
ULONG csn = 0;
//
// First send Initiation Key to all the PNP ISA cards to enable PnP auto-config
// ports and put all cards in configuration mode.
//
PnPSendInitiationKey(NULL);
//
// Reset all Pnp ISA cards' CSN to 0 and return to wait-for-key state
//
pnpWriteAddress (CONFIG_CONTROL_PORT);
pnpWriteData (CONTROL_WAIT_FOR_KEY | CONTROL_RESET_CSN);
//
// Delay 2 msec for cards to load initial configuration state.
//
SC_Sleep(2);
//
// Put cards into configuration mode to ready isolation process.
// The hardware on each PnP Isa card expects 72 pairs of I/O read
// access to the read data port.
//
PnPSendInitiationKey(NULL);
//
// Starting Pnp Isa card isolation process.
//
//
// Send WAKE[CSN=0] to force all cards without CSN into isolation
// state to set READ DATA PORT.
//
pnpWriteAddress(WAKE_CSN_PORT);
pnpWriteData(0);
//
// Set read data port to current testing value.
//
pnpWriteAddress(SET_READ_DATA_PORT);
pnpWriteData((UCHAR)(PNP_READ_DATA_PORT >> 2));
//
// Isolate one PnP ISA card until fail
//
while ( TRUE ) {
//
// Read serial isolation port to cause PnP cards in the isolation
// state to compare one bit of the boards ID.
//
pnpWriteAddress(SERIAL_ISOLATION_PORT);
//
// We need to delay 1 msec prior to starting the first pair of isolation
// reads and must wait 250usec between each subsequent pair of isolation
// reads. This delay gives the ISA cards time to access information from
// possible very slow storage device.
//
SC_Sleep(1);
memset(cardId, 0, NUMBER_CARD_ID_BYTES);
checksum = LFSR_SEED;
for ( j = 0; j < NUMBER_CARD_ID_BITS; j++ ) {
//
// Read card id bit by bit
//
byte1 = pnpReadData();
byte2 = pnpReadData();
bit = (byte1 == ISOLATION_TEST_BYTE_1) && (byte2 == ISOLATION_TEST_BYTE_2);
cardId[j / 8] |= bit << (j % 8);
if ( j < CHECKSUMED_BITS ) {
//
// Calculate checksum and only do it for the first 64 bits
//
bit7 = (((checksum & 2) >> 1) ^ (checksum & 1) ^ (bit)) << 7;
checksum = (checksum >> 1) | bit7;
}
SC_Sleep(1);
}
//
// Verify the card id we read is legitimate
// First make sure checksum is valid. Note zero checksum is considered valid.
//
if ( cardId[8] == 0 || checksum == cardId[8] ) {
//
// Next make sure cardId is not zero
//
byte1 = 0;
for ( j = 0; j < NUMBER_CARD_ID_BYTES; j++ ) {
byte1 |= cardId[j];
}
if ( byte1 != 0 ) {
//
// Make sure the vender EISA ID bytes are nonzero
//
if ( (cardId[0] & 0x7f) != 0 && cardId[1] != 0 ) {
pnpWriteAddress(SET_CSN_PORT);
pnpWriteData(++csn);
//
// Do Wake[CSN] command to put the newly isolated card to
// sleep state and other un-isolated cards to isolation
// state.
//
pnpWriteAddress(WAKE_CSN_PORT);
pnpWriteData(0);
continue; // ... to isolate more cards ...
}
}
}
break; // could not isolate more cards ...
}
//
// Finaly put all cards into wait for key state.
//
pnpWriteAddress(CONFIG_CONTROL_PORT);
pnpWriteData(CONTROL_WAIT_FOR_KEY);
g_ucISANumberCSNs = (UCHAR) csn;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
VOID
ISAInitBusInfo()
{
if ( g_bISAInitialized ) {
return;
}
g_bISAInitialized = TRUE;
InitializeCriticalSection(&g_csISAConfig);
PnPIsolateCards();
RETAILMSG(1, (TEXT("PnP ISA InitBusInfo : %d card(s) found\r\n"), g_ucISANumberCSNs));
g_usISAReadPort = 0x203;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
ULONG
ISAGetBusDataByOffset(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
{
UCHAR ucCSNumber, ucLogicalDevice;
UCHAR ucSerialID[9];
UCHAR ucResourceData[2048];
int iResourceLength;
ULONG ulReturn;
if ( g_bISAInitialized == FALSE )
ISAInitBusInfo();
if ( g_ucISANumberCSNs == 0 || g_ucISANumberCSNs == ~0U ) {
return (0);
}
ucCSNumber = (UCHAR)(SlotNumber >> 8);
ucLogicalDevice = (UCHAR)SlotNumber;
if ( ucCSNumber > g_ucISANumberCSNs || ucCSNumber == 0 ||
(Offset == 0 && Length != sizeof(ISA_PNP_CONFIG)) ||
(Offset == 1 && Length != sizeof(ISA_PNP_RESOURCES)) ||
Offset > 1 ) {
return (0);
}
EnterCriticalSection(&g_csISAConfig);
PnPSendInitiationKey(PNP_ISA_IO_BASE);
PnPWake(PNP_ISA_IO_BASE, ucCSNumber);
if ( Offset == 0 ) {
PISA_PNP_CONFIG pPnPConfig = (PISA_PNP_CONFIG)Buffer;
PnPReadSerialId(PNP_ISA_IO_BASE, ucSerialID);
pPnPConfig->VendorID =
ucSerialID[0] << 24 | ucSerialID[1] << 16 | ucSerialID[2] << 8 |
ucSerialID[3];
pPnPConfig->SerialNumber =
ucSerialID[7] << 24 | ucSerialID[6] << 16 | ucSerialID[5] << 8 |
ucSerialID[4];
iResourceLength = PnPReadResourceData(
PNP_ISA_IO_BASE, ucResourceData, sizeof(ucResourceData));
pPnPConfig->NumberLogicalDevices = PnPGetLogicalDeviceInfo(
ucResourceData, sizeof(ucResourceData),
pPnPConfig->LogicalDeviceInfo);
ulReturn = sizeof(ISA_PNP_CONFIG);
} else {
PISA_PNP_RESOURCES pPnPResources = (PISA_PNP_RESOURCES)Buffer;
int i;
UCHAR ucActive;
PnPWriteRegister(PNP_ISA_IO_BASE, 0x07, ucLogicalDevice);
ucActive = PnPReadRegister(PNP_ISA_IO_BASE, 0x30);
if ( ucActive ) {
pPnPResources->Flags = ISA_PNP_RESOURCE_FLAG_ACTIVE;
for ( i = 0; i < 4; i++ ) {
pPnPResources->Memory24Descriptors[i].MemoryBase =
PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x40 + i * 8)) << 8;
pPnPResources->Memory24Descriptors[i].MemoryBase |=
(USHORT)PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x41 + i * 8));
pPnPResources->Memory24Descriptors[i].MemoryControl =
PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x42 + i * 8));
pPnPResources->Memory24Descriptors[i].MemoryUpperLimit =
(USHORT)(PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x43 + i * 8)) << 8);
pPnPResources->Memory24Descriptors[i].MemoryUpperLimit |=
(USHORT)PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x44 + i * 8));
}
for ( i = 0; i < 8; i++ ) {
pPnPResources->IoPortDescriptors[i] =
PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x60 + i * 2)) << 8;
pPnPResources->IoPortDescriptors[i] |=
PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x61 + i * 2));
}
pPnPResources->IRQDescriptors[0].IRQLevel = PnPReadRegister(PNP_ISA_IO_BASE, 0x70);
pPnPResources->IRQDescriptors[0].IRQType = PnPReadRegister(PNP_ISA_IO_BASE, 0x71);
pPnPResources->IRQDescriptors[1].IRQLevel = PnPReadRegister(PNP_ISA_IO_BASE, 0x72);
pPnPResources->IRQDescriptors[1].IRQType = PnPReadRegister(PNP_ISA_IO_BASE, 0x73);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -