mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2231 lines
53 KiB
2231 lines
53 KiB
/****************************************************************************
|
|
*
|
|
* MDGPNP.C
|
|
*
|
|
* ISA PnP Adapter Detection Module
|
|
*
|
|
* Copyright (c) Madge Networks Ltd 1994
|
|
*
|
|
* COMPANY CONFIDENTIAL - RELEASED TO MICROSOFT CORP. ONLY FOR DEVELOPMENT
|
|
* OF WINDOWS95 NETCARD DETECTION - THIS SOURCE IS NOT TO BE RELEASED OUTSIDE
|
|
* OF MICROSOFT WITHOUT EXPLICIT WRITTEN PERMISSION FROM AN AUTHORISED
|
|
* OFFICER OF MADGE NETWORKS LTD.
|
|
*
|
|
* Created: PBA 23/11/1994
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <ntddk.h>
|
|
#include <ntddnetd.h>
|
|
|
|
#include <windef.h>
|
|
#include <winerror.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "mdgncdet.h"
|
|
|
|
//
|
|
// Prototype "borrowed" from WINUSER.H
|
|
//
|
|
|
|
extern int WINAPIV wsprintfW(LPWSTR, LPCWSTR, ...);
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| Smart16 adapter types. These correspond to the indexes that the upper layers
|
|
| use for identifying adapters, so change them with care.
|
|
|
|
|
|--------------------------------------------------------------------------*/
|
|
|
|
#define SMART_NONE 0
|
|
#define SMART_PNP 1000
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| IO locations that PnP adapters can be at as of 23/11/1994.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static
|
|
ULONG PnPIoLocations[17] =
|
|
{0x1a20, 0x2a20, 0x3a20,
|
|
0x0140,
|
|
0x0920, 0x0940, 0x0960, 0x0980,
|
|
0x0a20, 0x0a40, 0x0a60, 0x0a80, 0x0aa0,
|
|
0x0b20, 0x0b40, 0x0b60, 0x0b80};
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| Various PnP card specific constants.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#define PNP_IO_RANGE 32
|
|
|
|
#define PNP_CONTROL_REGISTER_1 3
|
|
#define PNP_ID_REGISTER 8
|
|
|
|
#define PNP_CON_REG_OFFSET 4
|
|
#define PNP_EEDO 0x0002
|
|
#define PNP_EEDEN 0x0004
|
|
#define PNP_SSK 0x0001
|
|
#define PNP_DELAY_CNT 16
|
|
#define PNP_WAIT_CNT 1000
|
|
#define PNP_WRITE_CMD 0x00a0
|
|
#define PNP_READ_CMD 0x00a1
|
|
|
|
#define PNP_EEPROM_NODE_ADDRESS3 15
|
|
|
|
#define PNP_CONFIG_ADDRESS_REGISTER 1
|
|
#define PNP_CONFIG_DATA_REGISTER 2
|
|
|
|
#define PNP_VENDOR_CONFIG_IRQ 0x70
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| First three bytes of a Madge node address.
|
|
|
|
|
|---------------------------------------------------------------------------*/
|
|
|
|
static
|
|
UCHAR MadgeNodeAddressPrefix[3] =
|
|
{0x00, 0x00, 0xf6};
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| List of adapter types supported by this module.
|
|
|
|
|
|---------------------------------------------------------------------------*/
|
|
|
|
static
|
|
ADAPTER_INFO Adapters[] =
|
|
{
|
|
{
|
|
SMART_PNP,
|
|
MDGPNP,
|
|
L"Madge 16/4 ISA PnP Ringnode",
|
|
L"Madge Networks",
|
|
L"IOLOCATION\0"
|
|
L"000\0"
|
|
L"00100\0"
|
|
L"DMACHANNEL\0"
|
|
L"000\0"
|
|
L"00100\0"
|
|
L"INTERRUPTNUMBER\0"
|
|
L"000\0"
|
|
L"000\0"
|
|
L"MULTIPROCESSOR\0"
|
|
L"000\0"
|
|
L"00100\0",
|
|
NULL,
|
|
903
|
|
}
|
|
};
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| Madge specific parameter range information. The order entries in this
|
|
| table MUST match that in the Adapters table above. The first value
|
|
Ý in each list is the default.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static
|
|
struct
|
|
{
|
|
ULONG IrqRange[8];
|
|
ULONG DmaRange[2];
|
|
}
|
|
ParamRange[] =
|
|
{
|
|
//
|
|
// PnP.
|
|
//
|
|
|
|
{
|
|
{ 3, 2, 7, 9, 10, 11, 15, END_OF_LIST},
|
|
{ 0, END_OF_LIST}
|
|
}
|
|
};
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| Structure for holding state of a search.
|
|
|
|
|
|--------------------------------------------------------------------------*/
|
|
|
|
typedef struct
|
|
{
|
|
ULONG IoLocationIndex;
|
|
ULONG Irq;
|
|
}
|
|
PNP_SEARCH_STATE;
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| This is an array of search states. We need one state for each type
|
|
| of adapter supported.
|
|
|
|
|
|--------------------------------------------------------------------------*/
|
|
|
|
static
|
|
PNP_SEARCH_STATE SearchStates[sizeof(Adapters) / sizeof(ADAPTER_INFO)] = {0};
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| Structure for holding a particular adapter's complete information.
|
|
|
|
|
|--------------------------------------------------------------------------*/
|
|
|
|
typedef struct
|
|
{
|
|
BOOLEAN Found;
|
|
ULONG CardType;
|
|
ULONG BusNumber;
|
|
INTERFACE_TYPE InterfaceType;
|
|
ULONG IoLocation;
|
|
ULONG Dma;
|
|
ULONG Irq;
|
|
}
|
|
PNP_ADAPTER;
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPReadCtrl
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Read the PnP control register of an adapter at the
|
|
Ý specified location.
|
|
|
|
|
| Returns - The value read.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static UCHAR
|
|
PnPReadCtrl(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR byte;
|
|
|
|
if (DetectReadPortUchar(
|
|
interface,
|
|
busNumber,
|
|
ioLocation + PNP_CON_REG_OFFSET,
|
|
&byte
|
|
) != STATUS_SUCCESS)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return byte;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPWriteCtrl
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
| data -> The data to write.
|
|
Ý
|
|
| Purpose - Write to the PnP control register of an adapter at the
|
|
Ý specified location.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPWriteCtrl(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation,
|
|
UCHAR data
|
|
)
|
|
{
|
|
DetectWritePortUchar(
|
|
interface,
|
|
busNumber,
|
|
ioLocation + PNP_CON_REG_OFFSET,
|
|
data
|
|
);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPDelay
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Wait a short time.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPDelay(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UINT i;
|
|
UCHAR byte;
|
|
|
|
for (i = 0; i < PNP_DELAY_CNT; i++)
|
|
{
|
|
DetectReadPortUchar(
|
|
interface,
|
|
busNumber,
|
|
ioLocation,
|
|
&byte
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPSetClk
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Set the serial device clock bit.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPSetClk(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp |= PNP_SSK;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPClrClk
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Clear the serial device clock bit.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPClrClk(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp &= ~PNP_SSK;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPSetEEDEN
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Put the serial device into output mode.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPSetEEDEN(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp |= PNP_EEDEN;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPClrEEDEN
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Put the serial device into input mode.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPClrEEDEN(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp &= ~PNP_EEDEN;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPTwitchClk
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Toggle the serial device clock bit to strobe data into
|
|
Ý the device.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPTwitchClk(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
PnPSetClk(busNumber, interface, ioLocation);
|
|
PnPClrClk(busNumber, interface, ioLocation);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPStartBit
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Send a start bit to the serial device. This is done by a
|
|
Ý 1 to 0 transition of the data bit while the clock bit
|
|
Ý is 1.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPStartBit(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
|
|
temp |= (PNP_EEDO + PNP_EEDEN);
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
|
|
temp |= PNP_SSK;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
|
|
temp &= ~PNP_EEDO;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
|
|
temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPStopBit
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Send a stop bit to the serial device. This is done by a
|
|
Ý 0 to 1 transition of the data bit while the clock bit
|
|
Ý is 1.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPStopBit(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
|
|
temp |= (PNP_EEDEN);
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
|
|
temp |= PNP_SSK;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
|
|
temp |= PNP_EEDO;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
|
|
temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPWaitAck
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Wait for the serial device to indicate that it has
|
|
Ý accepted the last command or data.
|
|
|
|
|
| Returns - TRUE if the device has accepted the command or data
|
|
Ý or FALSE otherwise.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static BOOLEAN
|
|
PnPWaitAck(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
UINT i;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
|
|
for (i = 0; i < PNP_WAIT_CNT; i++)
|
|
{
|
|
PnPSetClk(busNumber, interface, ioLocation);
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
|
|
PnPClrClk(busNumber, interface, ioLocation);
|
|
|
|
if ((temp & PNP_EEDO) == 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPDummyWaitAck
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
|
|
|
| Purpose - Wait for the serial device to indicate that it has
|
|
Ý passed the last of the data to be read.
|
|
|
|
|
| Returns - TRUE if the device has passed data or FALSE otherwise.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static BOOLEAN
|
|
PnPDummyWaitAck(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
UINT i;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
|
|
for (i = 0; i < PNP_WAIT_CNT ; i++)
|
|
{
|
|
PnPSetClk(busNumber, interface, ioLocation);
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
|
|
PnPClrClk(busNumber, interface, ioLocation);
|
|
|
|
if ((temp & PNP_EEDO) != 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPWriteData
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
| data -> The data to write.
|
|
Ý
|
|
| Purpose - Writes a bit to the serial device.
|
|
|
|
|
| Returns - Nothing.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static void
|
|
PnPWriteData(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation,
|
|
UCHAR data
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
temp &= ~(PNP_EEDO);
|
|
temp |= (data & 0x0080) >> 6;
|
|
|
|
PnPWriteCtrl(busNumber, interface, ioLocation, temp);
|
|
|
|
PnPDelay(busNumber, interface, ioLocation);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Ý
|
|
Ý Function - PnPReadByte
|
|
Ý
|
|
| Parameters - busNumber -> The number of the bus.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location of the adapter.
|
|
| index -> Offset in the serial device to read.
|
|
Ý
|
|
| Purpose - Reads a byte from the serial device.
|
|
|
|
|
| Returns - The word read.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static UINT
|
|
PnPReadByte(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation,
|
|
UINT index
|
|
)
|
|
{
|
|
UCHAR temp;
|
|
UCHAR dataByte;
|
|
UINT i;
|
|
|
|
dataByte = 0;
|
|
|
|
//
|
|
// Wake up the device.
|
|
//
|
|
|
|
PnPStartBit(busNumber, interface, ioLocation);
|
|
|
|
//
|
|
// Set data 'OUTPUT' mode.
|
|
//
|
|
|
|
PnPSetEEDEN(busNumber, interface, ioLocation);
|
|
|
|
//
|
|
// Send WRITE CMD - a dummy really to allow us to set the
|
|
// READ address!
|
|
//
|
|
|
|
temp = PNP_WRITE_CMD;
|
|
|
|
//
|
|
// MSB first.
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
PnPWriteData(busNumber, interface, ioLocation, temp);
|
|
PnPTwitchClk(busNumber, interface, ioLocation);
|
|
temp = temp << 1;
|
|
}
|
|
|
|
if (!PnPWaitAck(busNumber, interface, ioLocation))
|
|
{
|
|
//
|
|
// Return something invalid if it timed out.
|
|
//
|
|
|
|
MadgePrint1("Timeout 1\n");
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
//
|
|
// Set data 'OUTPUT' mode.
|
|
//
|
|
|
|
PnPSetEEDEN(busNumber, interface, ioLocation);
|
|
|
|
//
|
|
// Send Address in EEPROM.
|
|
//
|
|
|
|
temp = index;
|
|
|
|
//
|
|
// MSB first.
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
PnPWriteData(busNumber, interface, ioLocation, temp);
|
|
PnPTwitchClk(busNumber, interface, ioLocation);
|
|
temp = temp << 1;
|
|
}
|
|
|
|
if (!PnPWaitAck(busNumber, interface, ioLocation))
|
|
{
|
|
//
|
|
// Return something invalid if it timed out.
|
|
//
|
|
|
|
MadgePrint1("Timeout 2\n");
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
PnPStartBit(busNumber, interface, ioLocation);
|
|
|
|
//
|
|
// Set data 'OUTPUT' mode.
|
|
//
|
|
|
|
PnPSetEEDEN(busNumber, interface, ioLocation);
|
|
|
|
//
|
|
// Send READ CMD.
|
|
//
|
|
|
|
temp = PNP_READ_CMD;
|
|
|
|
//
|
|
// MSB first.
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
PnPWriteData(busNumber, interface, ioLocation, temp);
|
|
PnPTwitchClk(busNumber, interface, ioLocation);
|
|
temp = temp << 1;
|
|
}
|
|
|
|
if (!PnPWaitAck(busNumber, interface, ioLocation))
|
|
{
|
|
//
|
|
// Return sommething invalid if it timed out.
|
|
//
|
|
|
|
MadgePrint1("Timeout 3\n");
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
//
|
|
// Set data 'INPUT' mode.
|
|
//
|
|
|
|
PnPClrEEDEN(busNumber, interface, ioLocation);
|
|
|
|
//
|
|
// Now read the serial data - MSB first.
|
|
//
|
|
|
|
for (i = 0; i < 8 ;i++)
|
|
{
|
|
PnPSetClk(busNumber, interface, ioLocation);
|
|
|
|
temp = PnPReadCtrl(busNumber, interface, ioLocation);
|
|
|
|
PnPClrClk(busNumber, interface, ioLocation);
|
|
|
|
temp &= PNP_EEDO;
|
|
temp = temp >> 1;
|
|
dataByte = dataByte << 1;
|
|
dataByte &= 0xfffe;
|
|
dataByte |= temp;
|
|
}
|
|
|
|
if (!PnPDummyWaitAck(busNumber, interface, ioLocation))
|
|
{
|
|
//
|
|
// Return something invalid if it timed out.
|
|
//
|
|
|
|
MadgePrint1("Timeout 4\n");
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
PnPStopBit(busNumber, interface, ioLocation);
|
|
|
|
return dataByte;
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| Function - CheckForCard
|
|
|
|
|
| Parameters - busNumber -> The number of the bus to check.
|
|
| interface -> The interface type of the bus.
|
|
| ioLocation -> The IO location to be checked.
|
|
Ý irq -> Pointer to a holder for the IRQ of the
|
|
Ý adapter.
|
|
|
|
|
| Purpose - Check to see if an Madge PnP card is at the specified
|
|
| IO location.
|
|
|
|
|
| Returns - A card type.
|
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
static ULONG
|
|
CheckForCard(
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
ULONG ioLocation,
|
|
ULONG * irq
|
|
)
|
|
{
|
|
UCHAR byte;
|
|
UINT i;
|
|
BOOLEAN found;
|
|
|
|
MadgePrint2("CheckForCard (ioLocation=%04lx)\n", ioLocation);
|
|
|
|
//
|
|
// Start of by assuming that we don't know the IRQ number.
|
|
//
|
|
|
|
*irq = RESOURCE_UNKNOWN;
|
|
|
|
//
|
|
// First check that the IO range is not in use by some other
|
|
// device.
|
|
//
|
|
|
|
if (DetectCheckPortUsage(
|
|
interface,
|
|
busNumber,
|
|
ioLocation,
|
|
PNP_IO_RANGE
|
|
) != STATUS_SUCCESS)
|
|
{
|
|
return SMART_NONE;
|
|
}
|
|
|
|
MadgePrint1("CheckForCard: DetectCheckPortUsage() OK\n");
|
|
|
|
//
|
|
// OK, lets see if there's a Madge PnP adapter at the specified
|
|
// IO location. We just check to see if we can read 'md' back from
|
|
// the identification register. We read the identification register
|
|
// up to four times to get the 'm' and then check that the next
|
|
// byte is a 'd'.
|
|
//
|
|
|
|
found = FALSE;
|
|
|
|
for (i = 0; i < 4 && !found; i++)
|
|
{
|
|
if (DetectReadPortUchar(
|
|
interface,
|
|
busNumber,
|
|
ioLocation + PNP_ID_REGISTER,
|
|
&byte
|
|
) != STATUS_SUCCESS)
|
|
{
|
|
return SMART_NONE;
|
|
}
|
|
|
|
if (byte == 'm')
|
|
{
|
|
if (DetectReadPortUchar(
|
|
interface,
|
|
busNumber,
|
|
ioLocation + PNP_ID_REGISTER,
|
|
&byte
|
|
) != STATUS_SUCCESS)
|
|
{
|
|
return SMART_NONE;
|
|
}
|
|
|
|
if (byte == 'd')
|
|
{
|
|
found = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
return SMART_NONE;
|
|
}
|
|
|
|
MadgePrint1("CheckForCard: found ID\n");
|
|
|
|
//
|
|
// Read the 3rd byte of the node address back. This should
|
|
// be 0xf6 if this is a Madge PnP adapter.
|
|
//
|
|
|
|
byte = PnPReadByte(
|
|
busNumber,
|
|
interface,
|
|
ioLocation,
|
|
PNP_EEPROM_NODE_ADDRESS3
|
|
);
|
|
|
|
MadgePrint2("CheckForCard: read node address byte = %02x\n", byte);
|
|
|
|
if (byte != MadgeNodeAddressPrefix[2])
|
|
{
|
|
return SMART_NONE;
|
|
}
|
|
|
|
//
|
|
// If we make it here we're as sure as we're ever going to be that
|
|
// we've found a PnP adapter. Next we'll read the configured
|
|
// IRQ number.
|
|
//
|
|
|
|
if (DetectWritePortUchar(
|
|
interface,
|
|
busNumber,
|
|
ioLocation + PNP_CONFIG_ADDRESS_REGISTER,
|
|
(UCHAR) PNP_VENDOR_CONFIG_IRQ
|
|
) != STATUS_SUCCESS)
|
|
{
|
|
return SMART_NONE;
|
|
}
|
|
|
|
|
|
if (DetectReadPortUchar(
|
|
interface,
|
|
busNumber,
|
|
ioLocation + PNP_CONFIG_DATA_REGISTER,
|
|
&byte
|
|
) != STATUS_SUCCESS)
|
|
{
|
|
return SMART_NONE;
|
|
}
|
|
|
|
*irq = byte;
|
|
|
|
MadgePrint2("CheckForCard: read IRQ byte = %d\n", byte);
|
|
|
|
//
|
|
// And return the adapter type found.
|
|
//
|
|
|
|
return SMART_PNP;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
|
| Function - FindPnPCard
|
|
|
|
|
| Parameters - adapterNumber -> Adapter type index used to index the
|
|
| global array SearchStates.
|
|
| busNumber -> The number of the bus to search.
|
|
| interface -> The interface type of the bus.
|
|
| first -> TRUE if this is the first call for
|
|
| a given adapter type.
|
|
| type -> The type of adapter to find.
|
|
| confidence -> Pointer a holder for the confidence in
|
|
| which the adapter was found.
|
|
|
|
|
| Purpose - Search the specified bus for an adapter of the
|
|
| specified type. If first is TRUE then the search
|
|
| starts from the first possible IO location. If first is
|
|
| FALSE then the search starts from one after the last
|
|
| IO location checked the previous time FindPnPCard was called.
|
|
|
|
|
| Returns - A WINERROR.H error code.
|
|
|
|
|
|--------------------------------------------------------------------------*/
|
|
|
|
static ULONG
|
|
FindPnPCard(
|
|
ULONG adapterNumber,
|
|
ULONG busNumber,
|
|
INTERFACE_TYPE interface,
|
|
BOOLEAN first,
|
|
ULONG type,
|
|
ULONG * confidence
|
|
)
|
|
{
|
|
//
|
|
// If this is the first call then we want to start from the
|
|
// first possible IO location.
|
|
//
|
|
|
|
if (first)
|
|
{
|
|
SearchStates[adapterNumber].IoLocationIndex = 0;
|
|
}
|
|
|
|
//
|
|
// Otherwise we want to start from 1 after were we left off
|
|
// last time.
|
|
//
|
|
|
|
else
|
|
{
|
|
SearchStates[adapterNumber].IoLocationIndex++;
|
|
}
|
|
|
|
//
|
|
// Step through the IO locations in the bus for which there aren't
|
|
// already Madge adapters installed looking for one with the
|
|
// required adapter type. If we don't find one we will return a
|
|
// confidence level of zero. (Note we check that there isn't a
|
|
// Madge adapter at the IO location first to avoid trashing a
|
|
// working adapter.)
|
|
//
|
|
|
|
*confidence = 0;
|
|
|
|
while (SearchStates[adapterNumber].IoLocationIndex <
|
|
sizeof(PnPIoLocations) / sizeof(ULONG))
|
|
{
|
|
if (!MadgeCardAlreadyInstalled(
|
|
FALSE,
|
|
busNumber,
|
|
PnPIoLocations[SearchStates[adapterNumber].IoLocationIndex]
|
|
))
|
|
{
|
|
if (CheckForCard(
|
|
busNumber,
|
|
interface,
|
|
PnPIoLocations[SearchStates[adapterNumber].IoLocationIndex],
|
|
&SearchStates[adapterNumber].Irq
|
|
) == type)
|
|
{
|
|
*confidence = 100;
|
|
break;
|
|
}
|
|
}
|
|
|
|
SearchStates[adapterNumber].IoLocationIndex++;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPIdentifyHandler
|
|
*
|
|
* Parameters - index -> Index of the adapter type. 1000 for the first
|
|
* type, 1100 for the second, 1200 for the third
|
|
* etc.
|
|
* buffer -> Buffer for the results.
|
|
* bufferSize -> Size of the buffer in WCHARs.
|
|
*
|
|
* Purpose - Return information about a type of adapter that this module
|
|
* supports.
|
|
*
|
|
* Returns - A WINERROR.H error code. ERROR_NO_MORE_ITEMS
|
|
* is returned if index refers to an adapter type not
|
|
* supported.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPIdentifyHandler(
|
|
LONG index,
|
|
WCHAR * buffer,
|
|
LONG bufferSize
|
|
)
|
|
{
|
|
LONG numberOfAdapters;
|
|
LONG action;
|
|
LONG length;
|
|
LONG i;
|
|
|
|
MadgePrint2("MadgePnPIdentifyHandler (index = %ld)\n", index);
|
|
|
|
//
|
|
// Do some initialisation.
|
|
//
|
|
|
|
numberOfAdapters = sizeof(Adapters) / sizeof(ADAPTER_INFO);
|
|
action = index % 100;
|
|
index = index - action;
|
|
|
|
//
|
|
// Check that index does not exceed the number of adapters we
|
|
// support.
|
|
//
|
|
|
|
if ((index - 1000) / 100 >= numberOfAdapters)
|
|
{
|
|
return ERROR_NO_MORE_ITEMS;
|
|
}
|
|
|
|
//
|
|
// If index refers to an adapter type supported then carry out the
|
|
// requested action.
|
|
//
|
|
|
|
for (i = 0; i < numberOfAdapters; i++)
|
|
{
|
|
if (Adapters[i].Index == index)
|
|
{
|
|
switch (action)
|
|
{
|
|
//
|
|
// Return the adapter's abbreviation.
|
|
//
|
|
|
|
case 0:
|
|
|
|
length = UnicodeStrLen(Adapters[i].InfId) + 1;
|
|
|
|
if (bufferSize < length)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
memcpy(
|
|
(VOID *) buffer,
|
|
Adapters[i].InfId,
|
|
length * sizeof(WCHAR)
|
|
);
|
|
|
|
break;
|
|
|
|
//
|
|
// Return the adapter's description.
|
|
//
|
|
|
|
case 1:
|
|
|
|
length = UnicodeStrLen(Adapters[i].CardDescription) + 1;
|
|
|
|
if (bufferSize < length)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
memcpy(
|
|
(VOID *) buffer,
|
|
Adapters[i].CardDescription,
|
|
length * sizeof(WCHAR)
|
|
);
|
|
|
|
break;
|
|
|
|
//
|
|
// Return the adapter's manufacturer.
|
|
//
|
|
|
|
case 2:
|
|
|
|
length = UnicodeStrLen(Adapters[i].Manufacturer) + 1;
|
|
|
|
if (bufferSize < length)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
memcpy(
|
|
(VOID *) buffer,
|
|
Adapters[i].Manufacturer,
|
|
length * sizeof(WCHAR)
|
|
);
|
|
|
|
break;
|
|
|
|
//
|
|
// Return the search order.
|
|
//
|
|
|
|
case 3:
|
|
|
|
if (bufferSize < 5)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
wsprintfW(
|
|
(VOID *) buffer,
|
|
L"%d",
|
|
Adapters[i].SearchOrder
|
|
);
|
|
|
|
break;
|
|
|
|
//
|
|
// Anything else is invalid.
|
|
//
|
|
|
|
default:
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We didn't find an adapter type that matched the index so
|
|
// return an error.
|
|
//
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPFirstNextHandler
|
|
*
|
|
* Parameters - index -> Index of the adapter type. 1000 for the first
|
|
* type, 1100 for the second, 1200 for the third
|
|
* etc.
|
|
* interface -> The NT interface type (ISA, EISA etc).
|
|
* busNumber -> The bus number to search.
|
|
* first -> TRUE if the search of this bus should start
|
|
* from scratch.
|
|
* token -> Pointer to holder for a token that identifies
|
|
* the adapter found.
|
|
* confidence -> Pointer to a holder for the confidence by
|
|
* which the adapter has been found.
|
|
*
|
|
* Purpose - Attempts to find an adapter on the specified bus. If first
|
|
* is TRUE then the search starts from scratch. Otherwise
|
|
* the search starts from where it left of the last time we
|
|
* were called.
|
|
*
|
|
* Returns - A WINERROR.H error code. A return code of NO_ERROR
|
|
* and a *confidence of 0 means we didn't find an adapter.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPFirstNextHandler(
|
|
LONG index,
|
|
INTERFACE_TYPE interface,
|
|
ULONG busNumber,
|
|
BOOL first,
|
|
VOID * * token,
|
|
LONG * confidence
|
|
)
|
|
{
|
|
LONG adapterNumber;
|
|
ULONG retCode;
|
|
|
|
MadgePrint2("MadgePnPFirstNextHandler (index = %ld)\n", index);
|
|
|
|
//
|
|
// Check the interface type (could be an ISA adapter in an EISA bus).
|
|
//
|
|
|
|
if (interface != Isa && interface != Eisa)
|
|
{
|
|
*confidence = 0;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Work out and validate the adapter type being searched for.
|
|
//
|
|
|
|
adapterNumber = (index - 1000) / 100;
|
|
|
|
if (adapterNumber < 0 ||
|
|
adapterNumber >= sizeof(Adapters) / sizeof(ADAPTER_INFO) ||
|
|
(index % 100) != 0)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Type to find an adapter.
|
|
//
|
|
|
|
retCode = FindPnPCard(
|
|
(ULONG) adapterNumber,
|
|
busNumber,
|
|
interface,
|
|
(BOOLEAN) first,
|
|
(ULONG) index,
|
|
confidence
|
|
);
|
|
|
|
if (retCode == NO_ERROR)
|
|
{
|
|
//
|
|
// In this module I use the token as follows: Remember that
|
|
// the token can only be 2 bytes long (the low 2) because of
|
|
// the interface to the upper part of this DLL.
|
|
//
|
|
// The rest of the high byte is the the bus number.
|
|
// The low byte is the driver index number into Adapters.
|
|
//
|
|
// NOTE: This presumes that there are < 129 buses in the
|
|
// system. Is this reasonable?
|
|
//
|
|
|
|
*token = (VOID *) ((busNumber & 0x7F) << 8);
|
|
*token = (VOID *) (((ULONG) *token) | (adapterNumber << 1));
|
|
|
|
if (interface == Eisa)
|
|
{
|
|
*token = (VOID *) (((ULONG) *token) | 1);
|
|
}
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPOpenHandleHandler
|
|
*
|
|
* Parameters - token -> Pointer to holder for a token that identifies
|
|
* an adapter found by FirstNextHandler.
|
|
* handle -> Pointer to a holder a handle the caller
|
|
* should use to query the adapter refered to
|
|
* by *token.
|
|
*
|
|
* Purpose - Generates a handle for an adapter just found by a call
|
|
* to FirstNextHandler.
|
|
*
|
|
* Returns - A WINERROR.H error code.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPOpenHandleHandler(
|
|
VOID * token,
|
|
VOID * * handle
|
|
)
|
|
{
|
|
PNP_ADAPTER * adapter;
|
|
ULONG adapterNumber;
|
|
ULONG busNumber;
|
|
INTERFACE_TYPE interface;
|
|
|
|
MadgePrint1("MadgePnPOpenHandleHandler\n");
|
|
|
|
//
|
|
// Get info from the token.
|
|
//
|
|
|
|
busNumber = (ULONG) (((ULONG) token >> 8) & 0x7F);
|
|
adapterNumber = (((ULONG) token) & 0xFF) >> 1;
|
|
|
|
MadgePrint2("adapterNumber = %ld\n", adapterNumber);
|
|
|
|
if ((((ULONG) token) & 1) == 1)
|
|
{
|
|
interface = Eisa;
|
|
}
|
|
else
|
|
{
|
|
interface = Isa;
|
|
}
|
|
|
|
//
|
|
// Allocate a structure for the details of the adapter.
|
|
//
|
|
|
|
adapter = (PNP_ADAPTER *) DetectAllocateHeap(sizeof(PNP_ADAPTER));
|
|
|
|
if (adapter == NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Copy the details.
|
|
//
|
|
|
|
adapter->Found = TRUE;
|
|
adapter->CardType = Adapters[adapterNumber].Index;
|
|
adapter->InterfaceType = interface;
|
|
adapter->BusNumber = busNumber;
|
|
adapter->IoLocation =
|
|
PnPIoLocations[SearchStates[adapterNumber].IoLocationIndex];
|
|
adapter->Dma = 0; // PnP's are always in PIO mode.
|
|
adapter->Irq = SearchStates[adapterNumber].Irq;
|
|
|
|
*handle = (VOID *) adapter;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPCreateHandleHandler
|
|
*
|
|
* Parameters - index -> Index of the adapter type. 1000 for the first
|
|
* type, 1100 for the second, 1200 for the third
|
|
* etc.
|
|
* interface -> NT interface type (Eisa, Isa etc).
|
|
* busNumber -> Number of the bus containing the adapter.
|
|
* handle -> Pointer to a holder a handle the caller
|
|
* should use to query the adapter.
|
|
*
|
|
* Purpose - Generates a handle for an adapter that has not been detected
|
|
* but the caller claims exists.
|
|
*
|
|
* Returns - A WINERROR.H error code.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPCreateHandleHandler(
|
|
LONG index,
|
|
INTERFACE_TYPE interface,
|
|
ULONG busNumber,
|
|
VOID * * handle
|
|
)
|
|
{
|
|
PNP_ADAPTER * adapter;
|
|
LONG numberOfAdapters;
|
|
LONG i;
|
|
|
|
MadgePrint2("MadgePnPCreateHandleHandler (index = %ld)\n", index);
|
|
|
|
//
|
|
// Check that the interface type is correct for this module
|
|
// (could be an Isa adapter in an Eisa slot).
|
|
//
|
|
|
|
if (interface != Isa && interface != Eisa)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// If the index is valid then create a handle.
|
|
//
|
|
|
|
numberOfAdapters = sizeof(Adapters) / sizeof(ADAPTER_INFO);
|
|
|
|
for (i = 0; i < numberOfAdapters; i++)
|
|
{
|
|
if (Adapters[i].Index == index)
|
|
{
|
|
//
|
|
// Allocate a structure for the adapter details.
|
|
//
|
|
|
|
adapter = (PNP_ADAPTER *) DetectAllocateHeap(sizeof(PNP_ADAPTER));
|
|
|
|
if (adapter == NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Copy the details.
|
|
//
|
|
|
|
adapter->Found = FALSE;
|
|
adapter->CardType = index;
|
|
adapter->InterfaceType = interface;
|
|
adapter->BusNumber = busNumber;
|
|
adapter->IoLocation = PnPIoLocations[0];
|
|
adapter->Dma = 0; // PnP's are always in PIO mode.
|
|
adapter->Irq = RESOURCE_UNKNOWN;
|
|
|
|
*handle = (VOID *) adapter;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We didn't find an adapter type that matched the one the caller
|
|
// claims exists so return an error.
|
|
//
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPCloseHandleHandler
|
|
*
|
|
* Parameters - handle -> Handle to be closed.
|
|
*
|
|
* Purpose - Closes a previously opened or created handle.
|
|
*
|
|
* Returns - A WINERROR.H error code.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPCloseHandleHandler(
|
|
VOID * handle
|
|
)
|
|
{
|
|
MadgePrint1("MadgePnPCloseHandleHandler\n");
|
|
|
|
DetectFreeHeap(handle);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPQueryCfgHandler
|
|
*
|
|
* Parameters - handle -> Handle to for the adapter to be queried.
|
|
* buffer -> Buffer for the returned parameters.
|
|
* bufferSize -> Size of the buffer in WCHARs.
|
|
*
|
|
* Purpose - Find out what the parameters are for the adapter identified
|
|
* by the handle. This function does not assume that the
|
|
* adapter described by the handle is valid if the handle
|
|
* was created rather than being opened. If the handle
|
|
* was created then a search is made for an adapter.
|
|
*
|
|
* Returns - A WINERROR.H error code.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPQueryCfgHandler(
|
|
VOID * handle,
|
|
WCHAR * buffer,
|
|
LONG bufferSize
|
|
)
|
|
{
|
|
PNP_ADAPTER * adapter;
|
|
ULONG confidence;
|
|
LONG adapterNumber;
|
|
LONG retCode;
|
|
|
|
MadgePrint1("MadgePnPQueryCfgHandler\n");
|
|
|
|
//
|
|
// Do some initialisation.
|
|
//
|
|
|
|
adapter = (PNP_ADAPTER *) handle;
|
|
|
|
//
|
|
// Check that the interface type specified by the handle is
|
|
// valid for this module (could be an Isa card in an Eisa slot).
|
|
//
|
|
|
|
if (adapter->InterfaceType != Isa && adapter->InterfaceType != Eisa)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// If the adapter was created rather than being opened we must search
|
|
// for an adapter.
|
|
//
|
|
|
|
if (!adapter->Found)
|
|
{
|
|
adapterNumber = (adapter->CardType - 1000) / 100;
|
|
|
|
retCode = FindPnPCard(
|
|
adapterNumber,
|
|
adapter->BusNumber,
|
|
adapter->InterfaceType,
|
|
TRUE,
|
|
adapter->CardType,
|
|
&confidence
|
|
);
|
|
|
|
//
|
|
// If we are not 100% sure that we found an adapter with
|
|
// the right ID we give up.
|
|
//
|
|
|
|
if (retCode != NO_ERROR || confidence != 100)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
adapter->Found = TRUE;
|
|
adapter->IoLocation =
|
|
PnPIoLocations[SearchStates[adapterNumber].IoLocationIndex];
|
|
adapter->Dma = 0; // PnP's are always in PIO mode.
|
|
adapter->Irq = SearchStates[adapterNumber].Irq;
|
|
}
|
|
|
|
//
|
|
// Build resulting buffer.
|
|
//
|
|
// Copy in the IO location.
|
|
//
|
|
|
|
if (AppendParameter(
|
|
&buffer,
|
|
&bufferSize,
|
|
IoAddrString,
|
|
adapter->IoLocation
|
|
) != NO_ERROR)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
//
|
|
// Copy in the DMA channel.
|
|
//
|
|
|
|
if (AppendParameter(
|
|
&buffer,
|
|
&bufferSize,
|
|
DmaChanString,
|
|
adapter->Dma
|
|
) != NO_ERROR)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
//
|
|
// Copy in the IRQ number.
|
|
//
|
|
|
|
if (AppendParameter(
|
|
&buffer,
|
|
&bufferSize,
|
|
IrqString,
|
|
adapter->Irq
|
|
) != NO_ERROR)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
//
|
|
// Copy in the multiprocessor flag.
|
|
//
|
|
|
|
if (AppendParameter(
|
|
&buffer,
|
|
&bufferSize,
|
|
MultiprocessorString,
|
|
IsMultiprocessor()
|
|
) != NO_ERROR)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
//
|
|
// Copy in final \0.
|
|
//
|
|
|
|
if (bufferSize < 1)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
*buffer = L'\0';
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPVerifyCfgHandler
|
|
*
|
|
* Parameters - handle -> Handle to for the adapter to be verified.
|
|
* buffer -> Buffer containing the returned parameters.
|
|
*
|
|
* Purpose - Verify that the parameters in buffer are correct for
|
|
* the adapter identified by handle.
|
|
*
|
|
* Returns - A WINERROR.H error code.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPVerifyCfgHandler(
|
|
VOID * handle,
|
|
WCHAR * buffer
|
|
)
|
|
{
|
|
PNP_ADAPTER * adapter;
|
|
WCHAR * place;
|
|
BOOLEAN found;
|
|
ULONG ioLocation;
|
|
ULONG dmaChannel;
|
|
ULONG irqNumber;
|
|
ULONG multiprocessor;
|
|
LONG adapterNumber;
|
|
|
|
MadgePrint1("MadgePnPVerifyCfgHandler\n");
|
|
|
|
//
|
|
// Do some initialisation.
|
|
//
|
|
|
|
adapter = (PNP_ADAPTER *) handle;
|
|
adapterNumber = (adapter->CardType - 1000) / 100;
|
|
|
|
//
|
|
// Check that the interface type is correct for this module
|
|
// (could be an Isa adapter in an Eisa slot).
|
|
//
|
|
|
|
if (adapter->InterfaceType != Isa && adapter->InterfaceType != Eisa)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
//
|
|
// Parse the parameters.
|
|
//
|
|
|
|
//
|
|
// Get the IO location.
|
|
//
|
|
|
|
place = FindParameterString(buffer, IoAddrString);
|
|
|
|
if (place == NULL)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
place += UnicodeStrLen(IoAddrString) + 1;
|
|
|
|
ScanForNumber(place, &ioLocation, &found);
|
|
|
|
if (!found)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
//
|
|
// Get the DMA channel.
|
|
//
|
|
|
|
place = FindParameterString(buffer, DmaChanString);
|
|
|
|
if (place == NULL)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
place += UnicodeStrLen(DmaChanString) + 1;
|
|
|
|
ScanForNumber(place, &dmaChannel, &found);
|
|
|
|
if (!found)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
//
|
|
// Get the IRQ number.
|
|
//
|
|
|
|
place = FindParameterString(buffer, IrqString);
|
|
|
|
if (place == NULL)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
place += UnicodeStrLen(IrqString) + 1;
|
|
|
|
ScanForNumber(place, &irqNumber, &found);
|
|
|
|
if (!found)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
//
|
|
// Get the multiprocessor flag.
|
|
//
|
|
|
|
place = FindParameterString(buffer, MultiprocessorString);
|
|
|
|
if (place == NULL)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
place += UnicodeStrLen(MultiprocessorString) + 1;
|
|
|
|
//
|
|
// Now parse the value.
|
|
//
|
|
|
|
ScanForNumber(place, &multiprocessor, &found);
|
|
|
|
//
|
|
// If the handle does not refer to an adapter that has been found
|
|
// by search we must query the hardware.
|
|
//
|
|
|
|
if (!adapter->Found)
|
|
{
|
|
if (CheckForCard(
|
|
adapter->BusNumber,
|
|
adapter->InterfaceType,
|
|
ioLocation,
|
|
&adapter->Irq
|
|
) != adapter->CardType)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
adapter->IoLocation = ioLocation;
|
|
adapter->Dma = 0; // PnP's are always in PIO mode.
|
|
adapter->Found = TRUE;
|
|
}
|
|
|
|
//
|
|
// Verify the parameters.
|
|
//
|
|
|
|
if (ioLocation != adapter->IoLocation ||
|
|
multiprocessor != IsMultiprocessor())
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if (adapter->Dma == RESOURCE_UNKNOWN)
|
|
{
|
|
if (!IsValueInList(dmaChannel, ParamRange[adapterNumber].DmaRange))
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
else if (adapter->Dma != dmaChannel)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if (adapter->Irq == RESOURCE_UNKNOWN)
|
|
{
|
|
if (!IsValueInList(irqNumber, ParamRange[adapterNumber].IrqRange))
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
else if (adapter->Irq != irqNumber)
|
|
{
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
//
|
|
// If we make it to here everything checked out ok.
|
|
//
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPQueryMaskHandler
|
|
*
|
|
* Parameters - index -> Index of the adapter type. 1000 for the first
|
|
* type, 1100 for the second, 1200 for the third
|
|
* etc.
|
|
* buffer -> Buffer for the returned parameters.
|
|
* bufferSize -> Size of buffer in WCHARs.
|
|
*
|
|
* Purpose - Return the list of parameters required for the adapter
|
|
* type specified by index.
|
|
*
|
|
* Returns - A WINERROR.H error code.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPQueryMaskHandler(
|
|
LONG index,
|
|
WCHAR * buffer,
|
|
LONG bufferSize
|
|
)
|
|
{
|
|
WCHAR * params;
|
|
LONG length;
|
|
LONG numberOfAdapters;
|
|
LONG i;
|
|
|
|
MadgePrint2("MadgePnPQueryMaskHandler (index = %ld)\n", index);
|
|
MadgePrint2("BufferSize = %ld\n", bufferSize);
|
|
|
|
//
|
|
// Find the adapter type.
|
|
//
|
|
|
|
numberOfAdapters = sizeof(Adapters) / sizeof(ADAPTER_INFO);
|
|
|
|
for (i = 0; i < numberOfAdapters; i++)
|
|
{
|
|
if (Adapters[i].Index == index)
|
|
{
|
|
params = Adapters[i].Parameters;
|
|
|
|
//
|
|
// Find the string length (Ends with 2 NULLs)
|
|
//
|
|
|
|
for (length = 0; ; length++)
|
|
{
|
|
if (params[length] == L'\0')
|
|
{
|
|
length++;
|
|
|
|
if (params[length] == L'\0')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
length++;
|
|
|
|
MadgePrint2("length = %ld\n", length);
|
|
|
|
//
|
|
// Copy the parameters into buffer.
|
|
//
|
|
|
|
if (bufferSize < length)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
memcpy((VOID *) buffer, params, length * sizeof(WCHAR));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we make it here we did not find a valid adapter type so
|
|
// return and error.
|
|
//
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPParamRangeHandler
|
|
*
|
|
* Parameters - index -> Index of the adapter type. 1000 for the first
|
|
* type, 1100 for the second, 1200 for the third
|
|
* etc.
|
|
* param -> Paramter being queried.
|
|
* buffer -> Buffer for the returned parameters.
|
|
* bufferSize -> Size of buffer in LONGs.
|
|
*
|
|
* Purpose - Return the list of acceptable values for the parameter
|
|
* specified.
|
|
*
|
|
* Returns - A WINERROR.H error code.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPParamRangeHandler(
|
|
LONG index,
|
|
WCHAR * param,
|
|
LONG * buffer,
|
|
LONG * bufferSize
|
|
)
|
|
{
|
|
LONG i;
|
|
LONG adapterNumber;
|
|
LONG count;
|
|
|
|
MadgePrint2("MadgePnPParamRangeHandler (index=%ld)\n", index);
|
|
|
|
//
|
|
// Work out and validate the adapter number.
|
|
//
|
|
|
|
adapterNumber = (index - 1000) / 100;
|
|
|
|
if (adapterNumber < 0 ||
|
|
adapterNumber >= sizeof(Adapters) / sizeof(ADAPTER_INFO) ||
|
|
(index % 100) != 0)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// The simplest parameter is the IO location because this is the
|
|
// same for all of the adapter types.
|
|
//
|
|
|
|
if (UnicodeStringsEqual(param, IoAddrString))
|
|
{
|
|
count = sizeof(PnPIoLocations) / sizeof(ULONG);
|
|
|
|
if (*bufferSize < count)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
buffer[i] = PnPIoLocations[i];
|
|
}
|
|
|
|
*bufferSize = count;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// IRQ number is slightly more complicated because it is different
|
|
// for different adapter types.
|
|
//
|
|
|
|
else if (UnicodeStringsEqual(param, IrqString))
|
|
{
|
|
count = 0;
|
|
|
|
while (ParamRange[adapterNumber].IrqRange[count] != END_OF_LIST)
|
|
{
|
|
count++;
|
|
}
|
|
|
|
if (*bufferSize < count)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
buffer[i] = ParamRange[adapterNumber].IrqRange[i];
|
|
}
|
|
|
|
*bufferSize = count;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
//
|
|
// Likewise DMA channel.
|
|
//
|
|
|
|
else if (UnicodeStringsEqual(param, DmaChanString))
|
|
{
|
|
count = 0;
|
|
|
|
while (ParamRange[adapterNumber].DmaRange[count] != END_OF_LIST)
|
|
{
|
|
count++;
|
|
}
|
|
|
|
if (*bufferSize < count)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
buffer[i] = ParamRange[adapterNumber].DmaRange[i];
|
|
}
|
|
|
|
*bufferSize = count;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Or fill in the allowable values for the multiprocessor flag.
|
|
//
|
|
|
|
else if (UnicodeStringsEqual(param, MultiprocessorString))
|
|
{
|
|
if (*bufferSize < 2)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
*bufferSize = 2;
|
|
|
|
buffer[0] = 0;
|
|
buffer[1] = 1;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// If we reach this point we have been passed a parameter we
|
|
// don't know about.
|
|
//
|
|
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function - MadgePnPQueryParameterNameHandler
|
|
*
|
|
* Parameters - param -> Paramter being queried.
|
|
* buffer -> Buffer for the returned name.
|
|
* bufferSize -> Size of buffer in WCHARs.
|
|
*
|
|
* Purpose - Return the name of a parameter.
|
|
*
|
|
* Returns - ERROR_INVALID_PARAMETER to cause the caller to use
|
|
* the Microsoft provided default names.
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG
|
|
MadgePnPQueryParameterNameHandler(
|
|
WCHAR * param,
|
|
WCHAR * buffer,
|
|
LONG bufferSize
|
|
)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
/********* End of MDGPNP.C *************************************************/
|
|
|