summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/madge/detect/mdgpnp.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/madge/detect/mdgpnp.c2231
1 files changed, 2231 insertions, 0 deletions
diff --git a/private/ntos/ndis/madge/detect/mdgpnp.c b/private/ntos/ndis/madge/detect/mdgpnp.c
new file mode 100644
index 000000000..4c2d3d1c2
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgpnp.c
@@ -0,0 +1,2231 @@
+/****************************************************************************
+*
+* 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 *************************************************/
+