summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/madge
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/madge/detect/makefile7
-rw-r--r--private/ntos/ndis/madge/detect/mdgat.c1956
-rw-r--r--private/ntos/ndis/madge/detect/mdgeisa.c1288
-rw-r--r--private/ntos/ndis/madge/detect/mdgmc.c1316
-rw-r--r--private/ntos/ndis/madge/detect/mdgncdet.c1101
-rw-r--r--private/ntos/ndis/madge/detect/mdgncdet.def18
-rw-r--r--private/ntos/ndis/madge/detect/mdgncdet.h930
-rw-r--r--private/ntos/ndis/madge/detect/mdgncdet.rc27
-rw-r--r--private/ntos/ndis/madge/detect/mdgncdet.upd200
-rw-r--r--private/ntos/ndis/madge/detect/mdgpci.c1446
-rw-r--r--private/ntos/ndis/madge/detect/mdgpcmc.c1396
-rw-r--r--private/ntos/ndis/madge/detect/mdgpnp.c2231
-rw-r--r--private/ntos/ndis/madge/detect/mdgsm16.c1495
-rw-r--r--private/ntos/ndis/madge/detect/mdgutils.c1599
-rw-r--r--private/ntos/ndis/madge/detect/sources47
-rw-r--r--private/ntos/ndis/madge/dirs29
-rw-r--r--private/ntos/ndis/madge/dll/blmadge.icobin0 -> 766 bytes
-rw-r--r--private/ntos/ndis/madge/dll/brmadge.icobin0 -> 766 bytes
-rw-r--r--private/ntos/ndis/madge/dll/madge.icobin0 -> 766 bytes
-rw-r--r--private/ntos/ndis/madge/dll/makefile1
-rw-r--r--private/ntos/ndis/madge/dll/makefile.inc5
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.c124
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.def8
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.dlg111
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.h6
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.hlpbin0 -> 18350 bytes
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.hpj18
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.rc36
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.resbin0 -> 6496 bytes
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.rtf307
-rw-r--r--private/ntos/ndis/madge/dll/mdgmpdlg.upd181
-rw-r--r--private/ntos/ndis/madge/dll/oemsetup.upd241
-rw-r--r--private/ntos/ndis/madge/dll/sources42
-rw-r--r--private/ntos/ndis/madge/dll/tlmadge.icobin0 -> 766 bytes
-rw-r--r--private/ntos/ndis/madge/dll/trmadge.icobin0 -> 766 bytes
-rw-r--r--private/ntos/ndis/madge/dll/uilstf.h481
-rw-r--r--private/ntos/ndis/madge/driver/dispatch.c919
-rw-r--r--private/ntos/ndis/madge/driver/drv_err.c555
-rw-r--r--private/ntos/ndis/madge/driver/drv_init.c1656
-rw-r--r--private/ntos/ndis/madge/driver/drv_irq.c413
-rw-r--r--private/ntos/ndis/madge/driver/drv_srb.c1849
-rw-r--r--private/ntos/ndis/madge/driver/ftk.upd279
-rw-r--r--private/ntos/ndis/madge/driver/ftk_poke.c267
-rw-r--r--private/ntos/ndis/madge/driver/ftk_user.c2187
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_adap.h280
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_at.h234
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_card.h341
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_defs.h52
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_down.h128
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_eisa.h132
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_err.h389
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_fm.h351
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_init.h330
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_macr.h157
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_mc.h195
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_pci.h150
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_pci2.h122
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_pcit.h109
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_pcmc.h256
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_pnp.h142
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_poke.h52
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_sm16.h100
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_srb.h279
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_tab.h1054
-rw-r--r--private/ntos/ndis/madge/driver/head_def/ftk_user.h666
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/drv_err.h56
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/drv_init.h79
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/drv_irq.h48
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/drv_misc.h81
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/drv_rxtx.h201
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/drv_srb.h110
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/ftk_extr.h67
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/ftk_intr.h76
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_at.h75
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_eisa.h72
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_gen.h127
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_mc.h72
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_pci.h61
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_pci2.h56
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_pcit.h56
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_pcmc.h77
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_pnp.h72
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/hwi_sm16.h70
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_allo.h95
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_buff.h67
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_cs.h651
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_dma.h60
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_irq.h65
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_mem.h206
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_pci.h93
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_pcmc.h50
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/sys_time.h52
-rw-r--r--private/ntos/ndis/madge/driver/head_mod/util.h80
-rw-r--r--private/ntos/ndis/madge/driver/hwi_at.c2206
-rw-r--r--private/ntos/ndis/madge/driver/hwi_eisa.c1054
-rw-r--r--private/ntos/ndis/madge/driver/hwi_gen.c2077
-rw-r--r--private/ntos/ndis/madge/driver/hwi_mc.c1326
-rw-r--r--private/ntos/ndis/madge/driver/hwi_pci.c1567
-rw-r--r--private/ntos/ndis/madge/driver/hwi_pci2.c1792
-rw-r--r--private/ntos/ndis/madge/driver/hwi_pcit.c2028
-rw-r--r--private/ntos/ndis/madge/driver/hwi_pcmc.c3366
-rw-r--r--private/ntos/ndis/madge/driver/hwi_pnp.c2490
-rw-r--r--private/ntos/ndis/madge/driver/hwi_sm16.c1191
-rw-r--r--private/ntos/ndis/madge/driver/inc/ndismod.h792
-rw-r--r--private/ntos/ndis/madge/driver/inc/user.h235
-rw-r--r--private/ntos/ndis/madge/driver/madge.c3393
-rw-r--r--private/ntos/ndis/madge/driver/makefile7
-rw-r--r--private/ntos/ndis/madge/driver/makefile.inc5
-rw-r--r--private/ntos/ndis/madge/driver/mdgerrs.h154
-rw-r--r--private/ntos/ndis/madge/driver/mdgerrs.rc2
-rw-r--r--private/ntos/ndis/madge/driver/mdgmport.binbin0 -> 57142 bytes
-rw-r--r--private/ntos/ndis/madge/driver/mdgmport.rc26
-rw-r--r--private/ntos/ndis/madge/driver/mdgmport.upd553
-rw-r--r--private/ntos/ndis/madge/driver/msg00001.binbin0 -> 2744 bytes
-rw-r--r--private/ntos/ndis/madge/driver/request.c1158
-rw-r--r--private/ntos/ndis/madge/driver/sources56
-rw-r--r--private/ntos/ndis/madge/driver/sys_allo.c492
-rw-r--r--private/ntos/ndis/madge/driver/sys_dma.c233
-rw-r--r--private/ntos/ndis/madge/driver/sys_irq.c119
-rw-r--r--private/ntos/ndis/madge/driver/sys_mem.c925
-rw-r--r--private/ntos/ndis/madge/driver/sys_time.c80
-rw-r--r--private/ntos/ndis/madge/driver/util.c252
122 files changed, 60745 insertions, 0 deletions
diff --git a/private/ntos/ndis/madge/detect/makefile b/private/ntos/ndis/madge/detect/makefile
new file mode 100644
index 000000000..58189757d
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/madge/detect/mdgat.c b/private/ntos/ndis/madge/detect/mdgat.c
new file mode 100644
index 000000000..2897b550b
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgat.c
@@ -0,0 +1,1956 @@
+/****************************************************************************
+*
+* MDGAT.C
+*
+* ATULA Based 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 25/08/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, ...);
+
+
+/*---------------------------------------------------------------------------
+|
+| AT 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_AT 1000
+#define SMART_AT_P 1100
+#define SMART_ISA_C 1200
+#define SMART_ISA_C_P 1300
+#define SMART_PC 1400
+
+
+/*---------------------------------------------------------------------------
+|
+| IO locations that AT adapters can be at.
+|
+---------------------------------------------------------------------------*/
+
+static
+ULONG ATIoLocations[4] =
+ {0x0a20, 0x1a20, 0x2a20, 0x3a20};
+
+
+/*---------------------------------------------------------------------------
+|
+| Various ATULA card specific constants.
+|
+---------------------------------------------------------------------------*/
+
+#define AT_IO_RANGE 32
+
+#define AT_CONTROL_REGISTER_1 1
+#define AT_CONTROL_REGISTER_2 2
+#define AT_STATUS_REGISTER 3
+#define AT_CONTROL_REGISTER_6 6
+#define AT_CONTROL_REGISTER_7 7
+
+#define AT_BIA_PROM_BASE 8
+#define AT_P_SW_CONFIG_REG 22
+
+#define BIA_PROM_ID 0
+#define BIA_PROM_BOARD 1
+#define BIA_PROM_REVISION 2
+
+#define BIA_PROM_NODE_ADDRESS 1
+
+#define BIA_PROM_TYPE_16_4_AT 0x04
+#define BIA_PROM_TYPE_16_4_MC 0x08
+#define BIA_PROM_TYPE_16_4_PC 0x0B
+#define BIA_PROM_TYPE_16_4_MAXY 0x0C
+#define BIA_PROM_TYPE_16_4_MC_32 0x0D
+#define BIA_PROM_TYPE_16_4_AT_P 0x0E
+
+#define MAX_ADAPTER_CARD_AT_REV 6
+
+#define ADAPTER_CARD_16_4_PC 0
+#define ADAPTER_CARD_16_4_MAXY 1
+#define ADAPTER_CARD_16_4_AT 2
+#define ADAPTER_CARD_16_4_FIBRE 3
+#define ADAPTER_CARD_16_4_BRIDGE 4
+#define ADAPTER_CARD_16_4_ISA_C 5
+#define ADAPTER_CARD_16_4_AT_P_REV 6
+#define ADAPTER_CARD_16_4_FIBRE_P 7
+#define ADAPTER_CARD_16_4_ISA_C_P 8
+#define ADAPTER_CARD_16_4_AT_P 9
+
+#define ADAPTER_CARD_UNKNOWN 255
+
+#define AT_CTRL7_PAGE 0x08
+
+#define ATP_INTSEL_MASK 0x07
+#define ATP_DMASEL_MASK 0x18
+
+
+/*---------------------------------------------------------------------------
+|
+| Soft configurable adapter IRQ number mapping table.
+|
+---------------------------------------------------------------------------*/
+
+static
+UCHAR IrqMapTable[16] =
+{
+ 0xff, // 0 Unused
+ 0xff, // 1 Unused
+ 0x07, // 2
+ 0x06, // 3
+ 0xff, // 4 Unused
+ 0x05, // 5
+ 0xff, // 6 Unused
+ 0x04, // 7
+ 0xff, // 8 Unused
+ 0xff, // 9 Unused
+ 0x03, // 10
+ 0x02, // 11
+ 0x01, // 12
+ 0xff, // 13 Unused
+ 0xff, // 14 Unused
+ 0x00 // 15
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Soft configurable adapter DMA channel mapping table.
+|
+---------------------------------------------------------------------------*/
+
+static
+UCHAR DmaMapTable[7] =
+{
+ 0xff, // 0 Unused
+ 0xff, // 1 Unused
+ 0xff, // 2 Unused
+ 0x08, // 3
+ 0xff, // 4 Unused
+ 0x10, // 5
+ 0x18 // 6
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| 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_AT,
+ MDGAT,
+ L"Madge 16/4 AT Ringnode/Bridgnode",
+ L"Madge Networks",
+ L"IOLOCATION\0"
+ L"000\0"
+ L"00100\0"
+ L"DMACHANNEL\0"
+ L"000\0"
+ L"000\0"
+ L"INTERRUPTNUMBER\0"
+ L"000\0"
+ L"000\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 902
+ },
+
+ {
+ SMART_AT_P,
+ MDGATP,
+ L"Madge 16/4 ATP 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"00100\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 902
+ },
+
+ {
+ SMART_ISA_C,
+ MDGISAC,
+ L"Madge 16/4 ISA Client 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,
+ 902
+ },
+
+ {
+ SMART_ISA_C_P,
+ MDGISACP,
+ L"Madge 16/4 ISA Client Plus 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"00100\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 902
+ },
+
+ {
+ SMART_PC,
+ MDGPC,
+ L"Madge 16/4 PC Ringnode",
+ L"Madge Networks",
+ L"IOLOCATION\0"
+ L"000\0"
+ L"00100\0"
+ L"DMACHANNEL\0"
+ L"000\0"
+ L"000\0"
+ L"INTERRUPTNUMBER\0"
+ L"000\0"
+ L"000\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 902
+ }
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| 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[9];
+ ULONG DmaRange[6];
+}
+ParamRange[] =
+{
+ //
+ // Smart 16/4 AT.
+ //
+
+ {
+ { 3, 2, 5, 7, 10, 11, 12, 15, END_OF_LIST},
+
+#if defined(_PPC_) || defined(_MIPS_)
+
+ { 0, END_OF_LIST}
+
+#else
+
+ { 5, 1, 3, 0, 6, END_OF_LIST}
+
+#endif
+ },
+
+ //
+ // Smart 16/4 ATP.
+ //
+
+ {
+ { 3, 2, 5, 7, 10, 11, 12, 15, END_OF_LIST},
+
+#if defined(_PPC_) || defined(_MIPS_)
+
+ { 0, END_OF_LIST}
+
+#else
+
+ { 5, 3, 0, 6, END_OF_LIST}
+
+#endif
+ },
+
+ //
+ // Smart 16/4 ISA Client.
+ //
+
+ {
+ { 3, 2, 5, 7, 10, 11, 12, 15, END_OF_LIST},
+ { 0, END_OF_LIST}
+ },
+
+ //
+ // Smart 16/4 ISA Client Plus.
+ //
+
+ {
+ { 3, 2, 5, 7, 10, 11, 12, 15, END_OF_LIST},
+ { 0, END_OF_LIST}
+ },
+
+ //
+ // Smart 16/4 PC.
+ //
+
+ {
+ { 3, 2, 5, 7, END_OF_LIST},
+ { 0, END_OF_LIST}
+ }
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding state of a search.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ ULONG IoLocationIndex;
+ ULONG Irq;
+ ULONG Dma;
+}
+AT_SEARCH_STATE;
+
+
+/*---------------------------------------------------------------------------
+|
+| This is an array of search states. We need one state for each type
+| of adapter supported.
+|
+|--------------------------------------------------------------------------*/
+
+static
+AT_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 Irq;
+ ULONG Dma;
+}
+AT_ADAPTER;
+
+
+/*---------------------------------------------------------------------------
+|
+| 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 if
+| discovered.
+| dma -> Pointer to a holder for the DMA
+| channel if discovered.
+|
+| Purpose - Check to see if an Madge AT card is at the specified
+| IO location. If the card is soft programmable then the
+| IRQ number and DMA channel are also determined.
+|
+| Returns - A card type.
+|
+---------------------------------------------------------------------------*/
+
+static ULONG
+CheckForCard(
+ ULONG busNumber,
+ INTERFACE_TYPE interface,
+ ULONG ioLocation,
+ ULONG * irq,
+ ULONG * dma
+ )
+{
+ UCHAR byte;
+ ULONG board;
+ ULONG revision;
+ ULONG type;
+ ULONG found;
+ UINT i;
+
+ MadgePrint2("CheckForCard (ioLocation=%04lx)\n", ioLocation);
+
+ //
+ // For the moment we don't know what these are.
+ //
+
+ *irq = RESOURCE_UNKNOWN;
+ *dma = RESOURCE_UNKNOWN;
+
+ //
+ // First check that the IO range is not in use by some other
+ // device.
+ //
+
+ if (DetectCheckPortUsage(
+ interface,
+ busNumber,
+ ioLocation,
+ AT_IO_RANGE
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ MadgePrint1("CheckForCard: DetectCheckPortUsage() OK\n");
+
+ //
+ // Now we must reset the ATULA (if it's there).
+ //
+
+ if (DetectWritePortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_CONTROL_REGISTER_1,
+ 0
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ MadgePrint1("CheckForCard: Reset ATULA OK\n");
+
+ //
+ // And map in the first page of the BIA PROM.
+ //
+
+ if (DetectWritePortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_CONTROL_REGISTER_7,
+ 0
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ MadgePrint1("CheckForCard: Map in BIA OK\n");
+
+ //
+ // Next look to see if there is an 'M' in the BIA PROM identification
+ // field.
+ //
+
+ if (DetectReadPortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_BIA_PROM_BASE + BIA_PROM_ID,
+ &byte
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ if (byte != 'M')
+ {
+ return SMART_NONE;
+ }
+
+ MadgePrint1("CheckForCard: Read Madge byte OK\n");
+
+ //
+ // If we reach this point there is a reasonable chance that
+ // there is a Madge AT adapter at the IO location. Now we will
+ // try and work out what type it is.
+ //
+
+ if (DetectReadPortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_BIA_PROM_BASE + BIA_PROM_BOARD,
+ &byte
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ board = byte;
+
+ MadgePrint2("CheckForCard: Read board type OK (board = %lx)\n", board);
+
+ if (DetectReadPortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_BIA_PROM_BASE + BIA_PROM_REVISION,
+ &byte
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ revision = byte;
+
+ MadgePrint2("CheckForCard: Read revision OK (revision = %lx)\n", revision);
+
+ //
+ // Work out the hardware type based on the board type and revision.
+ //
+
+ type = ADAPTER_CARD_UNKNOWN;
+
+ if (board == BIA_PROM_TYPE_16_4_PC)
+ {
+ type = ADAPTER_CARD_16_4_PC;
+ }
+ else if (board == BIA_PROM_TYPE_16_4_AT)
+ {
+ if (revision < ADAPTER_CARD_16_4_AT)
+ {
+ type = ADAPTER_CARD_16_4_AT;
+ }
+ else
+ {
+ type = revision;
+ }
+ }
+ else if (board == BIA_PROM_TYPE_16_4_AT_P)
+ {
+ if (revision == ADAPTER_CARD_16_4_FIBRE)
+ {
+ type = ADAPTER_CARD_16_4_FIBRE_P;
+ }
+ else if (revision == ADAPTER_CARD_16_4_ISA_C)
+ {
+ type = ADAPTER_CARD_16_4_ISA_C_P;
+ }
+ else if (revision == ADAPTER_CARD_16_4_AT_P_REV)
+ {
+ type = ADAPTER_CARD_16_4_AT_P;
+ }
+ }
+
+ //
+ // Convert the hardware type into our nomencalculature or abort
+ // if we couldn't identify the adapter.
+ //
+
+ switch (type)
+ {
+ case ADAPTER_CARD_16_4_AT:
+ case ADAPTER_CARD_16_4_FIBRE:
+ case ADAPTER_CARD_16_4_BRIDGE:
+
+ found = SMART_AT;
+ break;
+
+ case ADAPTER_CARD_16_4_ISA_C:
+
+ found = SMART_ISA_C;
+ break;
+
+ case ADAPTER_CARD_16_4_AT_P_REV:
+ case ADAPTER_CARD_16_4_AT_P:
+ case ADAPTER_CARD_16_4_FIBRE_P:
+
+ found = SMART_AT_P;
+ break;
+
+ case ADAPTER_CARD_16_4_ISA_C_P:
+
+ found = SMART_ISA_C_P;
+ break;
+
+ case ADAPTER_CARD_16_4_PC:
+
+ found = SMART_PC;
+ break;
+
+ default:
+
+ return SMART_NONE;
+ }
+
+ MadgePrint2("CheckForCard: Idetification OK (found = %ld)\n", found);
+
+ //
+ // As a final check read the first three bytes of the BIA node
+ // address and check they are a valid Madge prefix.
+ //
+
+ //
+ // Map in the second page of the BIA PROM.
+ //
+
+ if (DetectReadPortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_CONTROL_REGISTER_7,
+ &byte
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ byte |= AT_CTRL7_PAGE;
+
+ if (DetectWritePortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_CONTROL_REGISTER_7,
+ byte
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ //
+ // Now read and check the node address.
+ //
+
+ for (i = 0; i < 3; i++)
+ {
+ if (DetectReadPortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_BIA_PROM_BASE + BIA_PROM_NODE_ADDRESS + i,
+ &byte
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ if (byte != MadgeNodeAddressPrefix[i])
+ {
+ return SMART_NONE;
+ }
+ }
+
+ MadgePrint1("CheckForCard: Read node address OK\n");
+
+ //
+ // At this point we're as sure as we will ever be that there is
+ // an ATULA based Madge adapter at ioLocation. If the card is
+ // an ISA/C or an ISA/C/P then the DMA channel is always 0
+ // (for PIO).
+ //
+
+ if (found == SMART_ISA_C || found == SMART_ISA_C_P)
+ {
+ *dma = 0;
+ }
+
+ // If the card is soft programmable then we'll read the
+ // config register to out the IRQ number and the DMA channel
+ // (if there is one).
+ //
+
+ if (found == SMART_AT_P || found == SMART_ISA_C_P)
+ {
+ //
+ // Read the soft configuration byte.
+ //
+
+ if (DetectReadPortUchar(
+ interface,
+ busNumber,
+ ioLocation + AT_P_SW_CONFIG_REG,
+ &byte
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ //
+ // Find out what the IRQ number is.
+ //
+
+ for (i = 0; i < sizeof(IrqMapTable) / sizeof(UCHAR); i++)
+ {
+ if (IrqMapTable[i] == (byte & ATP_INTSEL_MASK))
+ {
+ *irq = i;
+ }
+ }
+
+ //
+ // If it's an ATP then find out the DMA channel.
+ //
+
+ if (found == SMART_AT_P)
+ {
+ //
+ // We'll start of with the DMA channel being zero since
+ // if we don't find a valid DMA setting DMA must be
+ // disabled and we should use PIO.
+ //
+
+ *dma = 0;
+
+ for (i = 0; i < sizeof(DmaMapTable) / sizeof(UCHAR); i++)
+ {
+ if (DmaMapTable[i] == (byte & ATP_DMASEL_MASK))
+ {
+ *dma = i;
+ }
+ }
+ }
+ }
+
+ MadgePrint3("IRQ = %ld DMA = %ld\n", *irq, *dma);
+
+ return found;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - FindATCard
+|
+| 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 FindATCard was called.
+|
+| Returns - A WINERROR.H error code.
+|
+|--------------------------------------------------------------------------*/
+
+static ULONG
+FindATCard(
+ 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(ATIoLocations) / sizeof(ULONG))
+ {
+ if (!MadgeCardAlreadyInstalled(
+ FALSE,
+ busNumber,
+ ATIoLocations[SearchStates[adapterNumber].IoLocationIndex]
+ ))
+ {
+ if (CheckForCard(
+ busNumber,
+ interface,
+ ATIoLocations[SearchStates[adapterNumber].IoLocationIndex],
+ &SearchStates[adapterNumber].Irq,
+ &SearchStates[adapterNumber].Dma
+ ) == type)
+ {
+ *confidence = 100;
+ break;
+ }
+ }
+
+ SearchStates[adapterNumber].IoLocationIndex++;
+ }
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeATIdentifyHandler
+*
+* 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
+MadgeATIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG numberOfAdapters;
+ LONG action;
+ LONG length;
+ LONG i;
+
+ MadgePrint2("MadgeATIdentifyHandler (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 - MadgeATFirstNextHandler
+*
+* 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
+MadgeATFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ )
+{
+ LONG adapterNumber;
+ ULONG retCode;
+
+ MadgePrint2("MadgeATFirstNextHandler (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 = FindATCard(
+ (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 - MadgeATOpenHandleHandler
+*
+* 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
+MadgeATOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ )
+{
+ AT_ADAPTER * adapter;
+ ULONG adapterNumber;
+ ULONG busNumber;
+ INTERFACE_TYPE interface;
+
+ MadgePrint1("MadgeATOpenHandleHandler\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 = (AT_ADAPTER *) DetectAllocateHeap(sizeof(AT_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 =
+ ATIoLocations[SearchStates[adapterNumber].IoLocationIndex];
+ adapter->Irq = SearchStates[adapterNumber].Irq;
+ adapter->Dma = SearchStates[adapterNumber].Dma;
+
+ *handle = (VOID *) adapter;
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeATCreateHandleHandler
+*
+* 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
+MadgeATCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ )
+{
+ AT_ADAPTER * adapter;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgeATCreateHandleHandler (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 = (AT_ADAPTER *) DetectAllocateHeap(sizeof(AT_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 = ATIoLocations[0];
+ adapter->Irq = RESOURCE_UNKNOWN;
+ adapter->Dma = 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 - MadgeATCloseHandleHandler
+*
+* Parameters - handle -> Handle to be closed.
+*
+* Purpose - Closes a previously opened or created handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgeATCloseHandleHandler(
+ VOID * handle
+ )
+{
+ MadgePrint1("MadgeATCloseHandleHandler\n");
+
+ DetectFreeHeap(handle);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeATQueryCfgHandler
+*
+* 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
+MadgeATQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ AT_ADAPTER * adapter;
+ ULONG confidence;
+ LONG adapterNumber;
+ LONG retCode;
+
+ MadgePrint1("MadgeATQueryCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (AT_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 = FindATCard(
+ 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 =
+ ATIoLocations[SearchStates[adapterNumber].IoLocationIndex];
+ adapter->Irq = SearchStates[adapterNumber].Irq;
+ adapter->Dma = SearchStates[adapterNumber].Dma;
+
+ }
+
+ //
+ // 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 - MadgeATVerifyCfgHandler
+*
+* 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
+MadgeATVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ )
+{
+ AT_ADAPTER * adapter;
+ WCHAR * place;
+ BOOLEAN found;
+ ULONG ioLocation;
+ ULONG dmaChannel;
+ ULONG irqNumber;
+ ULONG multiprocessor;
+ LONG adapterNumber;
+
+ MadgePrint1("MadgeATVerifyCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (AT_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->Dma
+ ) != adapter->CardType)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ adapter->IoLocation = ioLocation;
+ 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 - MadgeATQueryMaskHandler
+*
+* 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
+MadgeATQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ WCHAR * params;
+ LONG length;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgeATQueryMaskHandler (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 - MadgeATParamRangeHandler
+*
+* 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
+MadgeATParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ )
+{
+ LONG i;
+ LONG adapterNumber;
+ LONG count;
+
+ MadgePrint2("MadgeATParamRangeHandler (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(ATIoLocations) / sizeof(ULONG);
+
+ if (*bufferSize < count)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ buffer[i] = ATIoLocations[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 - MadgeATQueryParameterNameHandler
+*
+* 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
+MadgeATQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/********* End of MDGAT.C **************************************************/
+
diff --git a/private/ntos/ndis/madge/detect/mdgeisa.c b/private/ntos/ndis/madge/detect/mdgeisa.c
new file mode 100644
index 000000000..a832e2728
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgeisa.c
@@ -0,0 +1,1288 @@
+/****************************************************************************
+*
+* MDGEISA.C
+*
+* EISA 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 16/08/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, ...);
+
+
+/*---------------------------------------------------------------------------
+|
+| EISA 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_EISA 1000
+
+
+/*---------------------------------------------------------------------------
+|
+| EISA Compressed ID.
+|
+| NT only seems to use the bottom 3 bytes of an EISA compressed ID.
+| This has mixed blessings. The advantage is that all of our EISA
+| adapters appear with the same compressed ID.
+|
+|--------------------------------------------------------------------------*/
+
+#define MADGE_COMPRESSED_ID 0x00008734L
+
+
+/*---------------------------------------------------------------------------
+|
+| List of adapter types supported by this module.
+|
+|---------------------------------------------------------------------------*/
+
+static
+ADAPTER_INFO Adapters[] =
+{
+ {
+ SMART_EISA,
+ MDGEISA,
+ L"Madge 16/4 Eisa Ringnode/Bridgnode",
+ L"Madge Networks",
+ L"SLOTNUMBER\0"
+ L"000\0"
+ L"00100\0"
+ L"DMACHANNEL\0"
+ L"000\0"
+ L"00100\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 900
+ }
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| 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 SlotNumber[16];
+ ULONG DmaRange[2];
+}
+ParamRange[] =
+{
+ //
+ // Smart 16/4 EISA.
+ //
+
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, END_OF_LIST},
+
+ {GENERAL_DMA, END_OF_LIST}
+ }
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding state of a search.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ ULONG SlotNumber;
+}
+EISA_SEARCH_STATE;
+
+
+/*---------------------------------------------------------------------------
+|
+| This is an array of search states. We need one state for each type
+| of adapter supported.
+|
+|--------------------------------------------------------------------------*/
+
+static
+EISA_SEARCH_STATE SearchStates[sizeof(Adapters) / sizeof(ADAPTER_INFO)] = {0};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding a particular adapter's complete information.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ BOOLEAN Found;
+ ULONG CardType;
+ INTERFACE_TYPE InterfaceType;
+ ULONG BusNumber;
+ ULONG SlotNumber;
+ ULONG Dma;
+}
+EISA_ADAPTER;
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - CompIdToCardType
+|
+| Parameters - compId -> A compressed EISA Id.
+|
+| Purpose - Translate a compressed EISA Id into a card type.
+|
+| Returns - A Madge card type of SMART_NONE if the compressed Id
+| is not recognised.
+|
+---------------------------------------------------------------------------*/
+
+static ULONG
+CompIdToCardType(
+ ULONG compId
+ )
+{
+ if (compId == MADGE_COMPRESSED_ID)
+ {
+ return SMART_EISA;
+ }
+
+ return SMART_NONE;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - FindEisaCard
+|
+| Parameters - adapterNumber -> Adapter type index used to index the
+| global array SearchStates.
+| busNumber -> The bus number to search.
+| first -> TRUE if this is the first call for
+| a given adapter type.
+| type -> The type of adapter being searched for.
+| confidence -> Pointer a holder for the confidence in
+| which the adapter was found.
+|
+| Purpose - Search the specified EISA bus for an adapter with the
+| specified compressed ID. If first is TRUE then the search
+| starts from slot number 1. If first is FALSE then the
+| search starts from one after the last slot checked the
+| previous time FindEisaCard was called.
+|
+| Returns - A WINERROR.H error code.
+|
+|--------------------------------------------------------------------------*/
+
+static ULONG
+FindEisaCard(
+ ULONG adapterNumber,
+ ULONG busNumber,
+ BOOLEAN first,
+ ULONG type,
+ ULONG * confidence
+ )
+{
+ VOID * busHandle;
+ ULONG compressedId;
+
+ //
+ // If this is the first call then we want to start from slot
+ // number 1.
+ //
+
+ if (first)
+ {
+ SearchStates[adapterNumber].SlotNumber = 1;
+ }
+
+ //
+ // Otherwise we want to start from 1 after were we left off
+ // last time.
+ //
+
+ else
+ {
+ SearchStates[adapterNumber].SlotNumber++;
+ }
+
+ //
+ // Get a handle onto NT's information for the EISA bus with the
+ // number busNumber.
+ //
+
+ if (!GetEisaKey(busNumber, &busHandle))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // Step through the slots in the bus looking for one with our
+ // compressed ID for which there isn't already a Madge card installed.
+ // If we don't find one we will return a confidence level of zero.
+ //
+
+ *confidence = 0;
+
+ while (GetEisaCompressedId(
+ busHandle,
+ SearchStates[adapterNumber].SlotNumber,
+ &compressedId
+ ))
+ {
+ if (CompIdToCardType(compressedId) == type)
+ {
+ if (!MadgeCardAlreadyInstalled(
+ TRUE,
+ busNumber,
+ SearchStates[adapterNumber].SlotNumber
+ ))
+ {
+ *confidence = 100;
+ break;
+ }
+ }
+
+ SearchStates[adapterNumber].SlotNumber++;
+ }
+
+ DeleteEisaKey(busHandle);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeEisaIdentifyHandler
+*
+* 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
+MadgeEisaIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG numberOfAdapters;
+ LONG action;
+ LONG length;
+ LONG i;
+
+ MadgePrint2("MadgeEisaIdentifyHandler (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 - MadgeEisaFirstNextHandler
+*
+* 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
+MadgeEisaFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ )
+{
+ ULONG retCode;
+ LONG adapterNumber;
+
+ MadgePrint2("MadgeEisaFirstNextHandler (index = %ld)\n", index);
+
+ //
+ // Check the interface type.
+ //
+
+ if (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 = FindEisaCard(
+ (ULONG) adapterNumber,
+ busNumber,
+ (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);
+ }
+
+ return retCode;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeEisaOpenHandleHandler
+*
+* 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
+MadgeEisaOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ )
+{
+ EISA_ADAPTER * adapter;
+ ULONG adapterNumber;
+ ULONG busNumber;
+ INTERFACE_TYPE interface;
+
+ MadgePrint1("MadgeEisaOpenHandleHandler\n");
+
+ //
+ // Get info from the token.
+ //
+
+ interface = Eisa;
+ busNumber = (ULONG) (((ULONG) token >> 8) & 0x7F);
+ adapterNumber = ((ULONG) token) & 0xFF;
+
+ //
+ // Allocate a structure for the details of the adapter.
+ //
+
+ adapter = (EISA_ADAPTER *) DetectAllocateHeap(sizeof(EISA_ADAPTER));
+
+ if (adapter == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ //
+ // Copy the details.
+ //
+
+ adapter->Found = TRUE;
+ adapter->SlotNumber = SearchStates[adapterNumber].SlotNumber;
+ adapter->CardType = Adapters[adapterNumber].Index;
+ adapter->InterfaceType = interface;
+ adapter->BusNumber = busNumber;
+ adapter->Dma = GENERAL_DMA; // EISA is always DMA.
+
+ *handle = (VOID *) adapter;
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeEisaCreateHandleHandler
+*
+* 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
+MadgeEisaCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ )
+{
+ EISA_ADAPTER * adapter;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgeEisaCreateHandleHandler (index = %ld)\n", index);
+
+ //
+ // Check that the interface type is correct for this module.
+ //
+
+ if (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 = (EISA_ADAPTER *) DetectAllocateHeap(
+ sizeof(EISA_ADAPTER)
+ );
+ if (adapter == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ //
+ // Copy the details.
+ //
+
+ adapter->Found = FALSE;
+ adapter->SlotNumber = 1;
+ adapter->CardType = index;
+ adapter->InterfaceType = interface;
+ adapter->BusNumber = busNumber;
+ adapter->Dma = GENERAL_DMA; // EISA is always DMA.
+
+ *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 - MadgeEisaCloseHandleHandler
+*
+* Parameters - handle -> Handle to be closed.
+*
+* Purpose - Closes a previously opened or created handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgeEisaCloseHandleHandler(
+ VOID * handle
+ )
+{
+ MadgePrint1("MadgeEisaCloseHandleHandler\n");
+
+ DetectFreeHeap(handle);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeEisaQueryCfgHandler
+*
+* 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. This is because
+* the handle could have been created rather than opened.
+* The function validates the handle and if the handle does
+* not identify a physical adapter then we attempt to
+* find an adapter that matches the handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgeEisaQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ EISA_ADAPTER * adapter;
+ VOID * busHandle;
+ ULONG confidence;
+ BOOLEAN found;
+ LONG adapterNumber;
+ LONG retCode;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (EISA_ADAPTER *) handle;
+
+ //
+ // Check that the interface type specified by the handle is
+ // valid for this module.
+ //
+
+ if (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 = FindEisaCard(
+ adapterNumber,
+ adapter->BusNumber,
+ 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->SlotNumber = SearchStates[adapterNumber].SlotNumber;
+ }
+
+ //
+ // Build resulting buffer.
+ //
+ // Copy in the slot number title and value.
+ //
+
+ if (AppendParameter(
+ &buffer,
+ &bufferSize,
+ SlotNumberString,
+ adapter->SlotNumber
+ ) != NO_ERROR)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ //
+ // Copy in the DMA channel title and value.
+ //
+
+ if (AppendParameter(
+ &buffer,
+ &bufferSize,
+ DmaChanString,
+ adapter->Dma
+ ) != 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 - MadgeEisaVerifyCfgHandler
+*
+* 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
+MadgeEisaVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ )
+{
+ EISA_ADAPTER * adapter;
+ WCHAR * place;
+ ULONG compressedId;
+ ULONG slotNumber;
+ ULONG dmaChannel;
+ ULONG multiprocessor;
+ VOID * busHandle;
+ BOOLEAN found;
+ LONG adapterNumber;
+
+ MadgePrint1("MadgeEisaVerifyCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (EISA_ADAPTER *) handle;
+ adapterNumber = (adapter->CardType - 1000) / 100;
+
+ //
+ // Check that the interface type is correct for this module.
+ //
+
+ if (adapter->InterfaceType != Eisa)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ //
+ // Parse the parameters.
+ //
+ // Get the slot number.
+ //
+
+ place = FindParameterString(buffer, SlotNumberString);
+
+ if (place == NULL)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ place += UnicodeStrLen(SlotNumberString) + 1;
+
+ //
+ // Now parse the slot number.
+ //
+
+ ScanForNumber(place, &slotNumber, &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 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 adapter was created rather than being opened we must check
+ // the EISA configuration table to make sure the slot contains a
+ // Madge adapter.
+ //
+
+ if (!adapter->Found)
+ {
+ if (!GetEisaKey(adapter->BusNumber, &busHandle))
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ found = GetEisaCompressedId(
+ busHandle,
+ slotNumber,
+ &compressedId
+ );
+
+ DeleteEisaKey(busHandle);
+
+ if (!found || CompIdToCardType(compressedId) != adapter->CardType)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ adapter->Found = TRUE;
+ adapter->SlotNumber = slotNumber;
+ }
+
+ //
+ // Verify the parameter.
+ //
+
+ if (slotNumber != adapter->SlotNumber ||
+ 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 we make it to here everything checked out ok.
+ //
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeEisaQueryMaskHandler
+*
+* 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
+MadgeEisaQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ WCHAR * params;
+ LONG length;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint1("MadgeEisaQueryMaskHandler\n");
+
+ //
+ // 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++;
+
+ //
+ // 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 - MadgeEisaParamRangeHandler
+*
+* 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
+MadgeEisaParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ )
+{
+ LONG adapterNumber;
+ LONG count;
+ LONG i;
+
+ //
+ // 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;
+ }
+
+ //
+ // Fill in the allowable slot numbers in the buffer.
+ //
+
+ if (UnicodeStringsEqual(param, SlotNumberString))
+ {
+ count = 0;
+
+ while (ParamRange[adapterNumber].SlotNumber[count] != END_OF_LIST)
+ {
+ count++;
+ }
+
+ if (*bufferSize < count)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ buffer[i] = ParamRange[adapterNumber].SlotNumber[i];
+ }
+
+ *bufferSize = count;
+
+ return NO_ERROR;
+ }
+
+ //
+ // Or the valid DMA channels.
+ //
+
+ 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 - MadgeEisaQueryParameterNameHandler
+*
+* 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
+MadgeEisaQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/********* End of MDGEISA.C ************************************************/
+
diff --git a/private/ntos/ndis/madge/detect/mdgmc.c b/private/ntos/ndis/madge/detect/mdgmc.c
new file mode 100644
index 000000000..112af2532
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgmc.c
@@ -0,0 +1,1316 @@
+/****************************************************************************
+*
+* MDGMC.C
+*
+* MC 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 14/09/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, ...);
+
+
+/*---------------------------------------------------------------------------
+|
+| MC 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_MC16 1000
+#define SMART_MC32 1100
+
+
+/*---------------------------------------------------------------------------
+|
+| Madge MC ADF IDs.
+|
+|--------------------------------------------------------------------------*/
+
+#define MADGE_MC16_ID 0x002d
+#define MADGE_MC32_ID 0x0074
+
+
+/*---------------------------------------------------------------------------
+|
+| List of adapter types supported by this module.
+|
+|---------------------------------------------------------------------------*/
+
+static
+ADAPTER_INFO Adapters[] =
+{
+ {
+ SMART_MC16,
+ MDGMC16,
+ L"Madge 16/4 MC16 Ringnode",
+ L"Madge Networks",
+ L"SLOTNUMBER\0"
+ L"000\0"
+ L"00100\0"
+ L"DMACHANNEL\0"
+ L"000\0"
+ L"00100\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 900
+ },
+
+ {
+ SMART_MC32,
+ MDGMC32,
+ L"Madge 16/4 MC32 Ringnode",
+ L"Madge Networks",
+ L"SLOTNUMBER\0"
+ L"000\0"
+ L"00100\0"
+ L"DMACHANNEL\0"
+ L"000\0"
+ L"00100\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 900
+ }
+
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| 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 SlotNumber[11];
+ ULONG DmaRange[2];
+}
+ParamRange[] =
+{
+ //
+ // Smart 16/4 MC16.
+ //
+
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, END_OF_LIST},
+ { GENERAL_DMA, END_OF_LIST}
+ },
+
+ //
+ // Smart 16/4 MC32.
+ //
+
+ {
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, END_OF_LIST},
+ { GENERAL_DMA, END_OF_LIST}
+ }
+
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding state of a search.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ ULONG SlotNumber;
+}
+MC_SEARCH_STATE;
+
+
+/*---------------------------------------------------------------------------
+|
+| This is an array of search states. We need one state for each type
+| of adapter supported.
+|
+|--------------------------------------------------------------------------*/
+
+static
+MC_SEARCH_STATE SearchStates[sizeof(Adapters) / sizeof(ADAPTER_INFO)] = {0};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding a particular adapter's complete information.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ BOOLEAN Found;
+ ULONG CardType;
+ INTERFACE_TYPE InterfaceType;
+ ULONG BusNumber;
+ ULONG SlotNumber;
+ ULONG Dma;
+}
+MC_ADAPTER;
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - AdfIdToCardType
+|
+| Parameters - adfId -> An MC ADF Id.
+|
+| Purpose - Translate an ADF Id into a card type.
+|
+| Returns - A Madge card type of SMART_NONE if the ADF Id
+| is not recognised.
+|
+---------------------------------------------------------------------------*/
+
+static ULONG
+AdfIdToCardType(
+ ULONG adfId
+ )
+{
+ if (adfId == MADGE_MC16_ID)
+ {
+ return SMART_MC16;
+ }
+ else if (adfId == MADGE_MC32_ID)
+ {
+ return SMART_MC32;
+ }
+
+ return SMART_NONE;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - FindMCCard
+|
+| Parameters - adapterNumber -> Adapter type index used to index the
+| global array SearchStates.
+| busNumber -> The bus number to search.
+| first -> TRUE if this is the first call for
+| a given adapter type.
+| type -> The type of adapter being searched for.
+| confidence -> Pointer a holder for the confidence in
+| which the adapter was found.
+|
+| Purpose - Search the specified MC bus for an adapter with the
+| specified compressed ID. If first is TRUE then the search
+| starts from slot number 1. If first is FALSE then the
+| search starts from one after the last slot checked the
+| previous time FindMCCard was called.
+|
+| Returns - A WINERROR.H error code.
+|
+|--------------------------------------------------------------------------*/
+
+static ULONG
+FindMCCard(
+ ULONG adapterNumber,
+ ULONG busNumber,
+ BOOLEAN first,
+ ULONG type,
+ ULONG * confidence
+ )
+{
+ VOID * busHandle;
+ ULONG adfId;
+
+ //
+ // If this is the first call then we want to start from slot
+ // number 1.
+ //
+
+ if (first)
+ {
+ SearchStates[adapterNumber].SlotNumber = 1;
+ }
+
+ //
+ // Otherwise we want to start from 1 after were we left off
+ // last time.
+ //
+
+ else
+ {
+ SearchStates[adapterNumber].SlotNumber++;
+ }
+
+ //
+ // Get a handle onto NT's information for the MC bus with the
+ // number busNumber.
+ //
+
+ if (!GetMcaKey(busNumber, &busHandle))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // Step through the slots in the bus looking for one with our
+ // ADF ID for which there isn't a Madge card installed.
+ // If we don't find one we will return a confidence
+ // level of zero.
+ //
+
+ *confidence = 0;
+
+ while (GetMcaPosId(
+ busHandle,
+ SearchStates[adapterNumber].SlotNumber,
+ &adfId
+ ))
+ {
+ if (AdfIdToCardType(adfId) == type)
+ {
+ if (!MadgeCardAlreadyInstalled(
+ TRUE,
+ busNumber,
+ SearchStates[adapterNumber].SlotNumber
+ ))
+ {
+ *confidence = 100;
+ break;
+ }
+ }
+
+ SearchStates[adapterNumber].SlotNumber++;
+ }
+
+ DeleteMcaKey(busHandle);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeMCIdentifyHandler
+*
+* 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
+MadgeMCIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG numberOfAdapters;
+ LONG action;
+ LONG length;
+ LONG i;
+
+ MadgePrint2("MadgeMCIdentifyHandler (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 - MadgeMCFirstNextHandler
+*
+* 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
+MadgeMCFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ )
+{
+ ULONG retCode;
+ LONG adapterNumber;
+
+ MadgePrint2("MadgeMCFirstNextHandler (index = %ld)\n", index);
+
+ //
+ // Check the interface type.
+ //
+
+ if (interface != MicroChannel)
+ {
+ *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 = FindMCCard(
+ (ULONG) adapterNumber,
+ busNumber,
+ (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);
+ }
+
+ return retCode;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeMCOpenHandleHandler
+*
+* 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
+MadgeMCOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ )
+{
+ MC_ADAPTER * adapter;
+ ULONG adapterNumber;
+ ULONG busNumber;
+ INTERFACE_TYPE interface;
+
+ MadgePrint1("MadgeMCOpenHandleHandler\n");
+
+ //
+ // Get info from the token.
+ //
+
+ interface = MicroChannel;
+ busNumber = (ULONG) (((ULONG) token >> 8) & 0x7F);
+ adapterNumber = ((ULONG) token) & 0xFF;
+
+ //
+ // Allocate a structure for the details of the adapter.
+ //
+
+ adapter = (MC_ADAPTER *) DetectAllocateHeap(sizeof(MC_ADAPTER));
+
+ if (adapter == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ //
+ // Copy the details.
+ //
+
+ adapter->Found = TRUE;
+ adapter->SlotNumber = SearchStates[adapterNumber].SlotNumber;
+ adapter->CardType = Adapters[adapterNumber].Index;
+ adapter->InterfaceType = interface;
+ adapter->BusNumber = busNumber;
+ adapter->Dma = GENERAL_DMA; // MC's are always DMA.
+
+ *handle = (VOID *) adapter;
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeMCCreateHandleHandler
+*
+* 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
+MadgeMCCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ )
+{
+ MC_ADAPTER * adapter;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgeMCCreateHandleHandler (index = %ld)\n", index);
+
+ //
+ // Check that the interface type is correct for this module.
+ //
+
+ if (interface != MicroChannel)
+ {
+ 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 = (MC_ADAPTER *) DetectAllocateHeap(sizeof(MC_ADAPTER));
+
+ if (adapter == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ //
+ // Copy the details.
+ //
+
+ adapter->Found = FALSE;
+ adapter->SlotNumber = 1;
+ adapter->CardType = index;
+ adapter->InterfaceType = interface;
+ adapter->BusNumber = busNumber;
+ adapter->Dma = GENERAL_DMA; // MC's are always DMA.
+
+ *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 - MadgeMCCloseHandleHandler
+*
+* Parameters - handle -> Handle to be closed.
+*
+* Purpose - Closes a previously opened or created handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgeMCCloseHandleHandler(
+ VOID * handle
+ )
+{
+ MadgePrint1("MadgeMCCloseHandleHandler\n");
+
+ DetectFreeHeap(handle);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeMCQueryCfgHandler
+*
+* 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. This is because
+* the handle could have been created rather than opened.
+* The function validates the handle and if the handle does
+* not identify a physical adapter then we attempt to
+* find an adapter that matches the handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgeMCQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ MC_ADAPTER * adapter;
+ VOID * busHandle;
+ ULONG confidence;
+ BOOLEAN found;
+ LONG adapterNumber;
+ LONG retCode;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (MC_ADAPTER *) handle;
+
+ //
+ // Check that the interface type specified by the handle is
+ // valid for this module.
+ //
+
+ if (adapter->InterfaceType != MicroChannel)
+ {
+ 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 = FindMCCard(
+ adapterNumber,
+ adapter->BusNumber,
+ 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->SlotNumber = SearchStates[adapterNumber].SlotNumber;
+ }
+
+ //
+ // Build resulting buffer.
+ //
+ // Copy in the slot number title and value.
+ //
+
+ if (AppendParameter(
+ &buffer,
+ &bufferSize,
+ SlotNumberString,
+ adapter->SlotNumber
+ ) != NO_ERROR)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ //
+ // Copy in the DMA channel title and value.
+ //
+
+ if (AppendParameter(
+ &buffer,
+ &bufferSize,
+ DmaChanString,
+ adapter->Dma
+ ) != 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 - MadgeMCVerifyCfgHandler
+*
+* 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
+MadgeMCVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ )
+{
+ MC_ADAPTER * adapter;
+ WCHAR * place;
+ ULONG adfId;
+ ULONG slotNumber;
+ ULONG dmaChannel;
+ ULONG multiprocessor;
+ VOID * busHandle;
+ BOOLEAN found;
+ LONG adapterNumber;
+
+ MadgePrint1("MadgeMCVerifyCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (MC_ADAPTER *) handle;
+ adapterNumber = (adapter->CardType - 1000) / 100;
+
+ //
+ // Check that the interface type is correct for this module.
+ //
+
+ if (adapter->InterfaceType != MicroChannel)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ //
+ // Parse the parameters.
+ //
+ // Get the slot number.
+ //
+
+ place = FindParameterString(buffer, SlotNumberString);
+
+ if (place == NULL)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ place += UnicodeStrLen(SlotNumberString) + 1;
+
+ //
+ // Now parse the slot number.
+ //
+
+ ScanForNumber(place, &slotNumber, &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 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 adapter was created rather than being opened we must check
+ // the POS table to make sure the slot contains a Madge adapter.
+ //
+
+ if (!adapter->Found)
+ {
+ if (!GetMcaKey(adapter->BusNumber, &busHandle))
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ found = GetMcaPosId(
+ busHandle,
+ slotNumber,
+ &adfId
+ );
+
+ DeleteMcaKey(busHandle);
+
+ if (!found || AdfIdToCardType(adfId) != adapter->CardType)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ adapter->Found = TRUE;
+ adapter->SlotNumber = slotNumber;
+ }
+
+ //
+ // Verify the parameter.
+ //
+
+ if (slotNumber != adapter->SlotNumber ||
+ 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 we make it to here everything checked out ok.
+ //
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeMCQueryMaskHandler
+*
+* 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
+MadgeMCQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ WCHAR * params;
+ LONG length;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint1("MadgeMCQueryMaskHandler\n");
+
+ //
+ // 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++;
+
+ //
+ // 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 - MadgeMCParamRangeHandler
+*
+* 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
+MadgeMCParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ )
+{
+ LONG adapterNumber;
+ LONG count;
+ LONG i;
+
+ //
+ // 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;
+ }
+
+ //
+ // Fill in the allowable slot numbers in the buffer.
+ //
+
+ if (UnicodeStringsEqual(param, SlotNumberString))
+ {
+ count = 0;
+
+ while (ParamRange[adapterNumber].SlotNumber[count] != END_OF_LIST)
+ {
+ count++;
+ }
+
+ if (*bufferSize < count)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ buffer[i] = ParamRange[adapterNumber].SlotNumber[i];
+ }
+
+ *bufferSize = count;
+
+ return NO_ERROR;
+ }
+
+ //
+ // Or the valid DMA channels.
+ //
+
+ 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 - MadgeMCQueryParameterNameHandler
+*
+* 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
+MadgeMCQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/********* End of MDGMC.C **************************************************/
+
diff --git a/private/ntos/ndis/madge/detect/mdgncdet.c b/private/ntos/ndis/madge/detect/mdgncdet.c
new file mode 100644
index 000000000..9d1a7ef75
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgncdet.c
@@ -0,0 +1,1101 @@
+/****************************************************************************
+*
+* MDGNCDET.C
+*
+* Adapter Detection DLL
+*
+* 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 18/08/1994
+* Derived from the DTEXAMPL.C DDK sample. As far as possible
+* the structure of the Microsoft example NetDetect DLL has
+* been preserved so that our individual adapter detection
+* modules could be plugged into the Microsoft DLL.
+*
+* This module provides a wrapper for the modules that detect individual
+* adapter types. It fields calls out to the individual detection modules
+* so that the caller is unaware that it is dealing with multiple modules.
+*
+****************************************************************************/
+
+#include <ntddk.h>
+#include <ntddnetd.h>
+
+#include <windef.h>
+#include <winerror.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mdgncdet.h"
+#include "mdgncdet.upd"
+
+//
+// Prototype "borrowed" from WINUSER.H
+//
+
+extern int WINAPIV wsprintfW(LPWSTR, LPCWSTR, ...);
+
+//
+// MVER string.
+//
+
+static
+char MVerString[] = MVER_STRING;
+
+
+/*---------------------------------------------------------------------------
+|
+| This is the structure for all the cards that the DLL can detect.
+| To add detection for a new adapter(s), simply add the proper routines to
+| this structure. The rest is automatic.
+|
+---------------------------------------------------------------------------*/
+
+static
+DETECT_ADAPTER DetectAdapters[] =
+{
+ {
+ MadgeEisaIdentifyHandler,
+ MadgeEisaFirstNextHandler,
+ MadgeEisaOpenHandleHandler,
+ MadgeEisaCreateHandleHandler,
+ MadgeEisaCloseHandleHandler,
+ MadgeEisaQueryCfgHandler,
+ MadgeEisaVerifyCfgHandler,
+ MadgeEisaQueryMaskHandler,
+ MadgeEisaParamRangeHandler,
+ MadgeEisaQueryParameterNameHandler,
+ 0
+ },
+
+ {
+ MadgeATIdentifyHandler,
+ MadgeATFirstNextHandler,
+ MadgeATOpenHandleHandler,
+ MadgeATCreateHandleHandler,
+ MadgeATCloseHandleHandler,
+ MadgeATQueryCfgHandler,
+ MadgeATVerifyCfgHandler,
+ MadgeATQueryMaskHandler,
+ MadgeATParamRangeHandler,
+ MadgeATQueryParameterNameHandler,
+ 0
+ },
+
+ {
+ MadgeSm16IdentifyHandler,
+ MadgeSm16FirstNextHandler,
+ MadgeSm16OpenHandleHandler,
+ MadgeSm16CreateHandleHandler,
+ MadgeSm16CloseHandleHandler,
+ MadgeSm16QueryCfgHandler,
+ MadgeSm16VerifyCfgHandler,
+ MadgeSm16QueryMaskHandler,
+ MadgeSm16ParamRangeHandler,
+ MadgeSm16QueryParameterNameHandler,
+ 0
+ },
+
+ {
+ MadgePnPIdentifyHandler,
+ MadgePnPFirstNextHandler,
+ MadgePnPOpenHandleHandler,
+ MadgePnPCreateHandleHandler,
+ MadgePnPCloseHandleHandler,
+ MadgePnPQueryCfgHandler,
+ MadgePnPVerifyCfgHandler,
+ MadgePnPQueryMaskHandler,
+ MadgePnPParamRangeHandler,
+ MadgePnPQueryParameterNameHandler,
+ 0
+ },
+
+ {
+ MadgeMCIdentifyHandler,
+ MadgeMCFirstNextHandler,
+ MadgeMCOpenHandleHandler,
+ MadgeMCCreateHandleHandler,
+ MadgeMCCloseHandleHandler,
+ MadgeMCQueryCfgHandler,
+ MadgeMCVerifyCfgHandler,
+ MadgeMCQueryMaskHandler,
+ MadgeMCParamRangeHandler,
+ MadgeMCQueryParameterNameHandler,
+ 0
+ },
+
+ {
+ MadgePciIdentifyHandler,
+ MadgePciFirstNextHandler,
+ MadgePciOpenHandleHandler,
+ MadgePciCreateHandleHandler,
+ MadgePciCloseHandleHandler,
+ MadgePciQueryCfgHandler,
+ MadgePciVerifyCfgHandler,
+ MadgePciQueryMaskHandler,
+ MadgePciParamRangeHandler,
+ MadgePciQueryParameterNameHandler,
+ 0
+ },
+
+ {
+ MadgePcmciaIdentifyHandler,
+ MadgePcmciaFirstNextHandler,
+ MadgePcmciaOpenHandleHandler,
+ MadgePcmciaCreateHandleHandler,
+ MadgePcmciaCloseHandleHandler,
+ MadgePcmciaQueryCfgHandler,
+ MadgePcmciaVerifyCfgHandler,
+ MadgePcmciaQueryMaskHandler,
+ MadgePcmciaParamRangeHandler,
+ MadgePcmciaQueryParameterNameHandler,
+ 0
+ }
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Constant strings for parameters.
+|
+---------------------------------------------------------------------------*/
+
+WCHAR IrqString[] = L"INTERRUPTNUMBER";
+WCHAR IoAddrString[] = L"IOLOCATION";
+WCHAR DmaChanString[] = L"DMACHANNEL";
+WCHAR AdapTypeString[] = L"ADAPTERTYPE";
+WCHAR SlotNumberString[] = L"SLOTNUMBER";
+WCHAR MultiprocessorString[] = L"MULTIPROCESSOR";
+
+
+/****************************************************************************
+*
+* Function - NcDetectInitialInit
+*
+* Parameters - dllHandle -> Our DLL handle.
+* reason -> The reason this function has been called.
+* context -> Context information.
+*
+* Purpose - Standard DLL initialisation/closedown function. If called
+* with reason == 0 then we closedown. If called with
+* reason != 0 then we initialise.
+*
+* Returns - TRUE on success or FALSE on failure.
+*
+****************************************************************************/
+
+BOOLEAN PASCAL
+NcDetectInitialInit(
+ VOID * dllHandle,
+ ULONG reason,
+ CONTEXT * context
+ )
+{
+ LONG supportedDrivers;
+ LONG currentDriver;
+ LONG supportedAdapters;
+ LONG totalAdapters;
+
+ MadgePrint2("MADGE: NcDetectInitialInit (reason = %ld)\n", reason);
+
+ //
+ // If reason == 0 then this is a closedown call so free any resources
+ // we have allocated.
+ //
+
+ if (reason == 0)
+ {
+ return TRUE;
+ }
+
+ //
+ // If we get here it we should initialise.
+ //
+
+ totalAdapters = 0;
+ supportedDrivers = sizeof(DetectAdapters) / sizeof(DETECT_ADAPTER);
+
+ //
+ // Count the total number of adapters supported by this DLL by
+ // iterating through each module, finding the number of adapters
+ // each module supports.
+ //
+
+ for (currentDriver = 0;
+ currentDriver < supportedDrivers;
+ currentDriver++)
+ {
+ for (supportedAdapters = 0; ; supportedAdapters++)
+ {
+ if ((*(DetectAdapters[currentDriver].NcDetectIdentifyHandler))(
+ ((supportedAdapters + 10) * 100),
+ NULL,
+ 0
+ ) == ERROR_NO_MORE_ITEMS)
+ {
+ break;
+ }
+ }
+
+ totalAdapters += supportedAdapters;
+
+ DetectAdapters[currentDriver].SupportedAdapters = supportedAdapters;
+ }
+
+ //
+ // We don't support more than 65535 adapters in this DLL because of
+ // the way we build the Tokens and NetcardIds.
+ //
+
+ if (totalAdapters > 65535L)
+ {
+ return FALSE;
+ }
+
+ //
+ // We have successfully completed initialisation.
+ //
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectIdentify
+*
+* 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
+NcDetectIdentify(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG supportedDrivers;
+ LONG currentDriver;
+ LONG adapterNumber;
+ LONG codeNumber;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapterNumber = (index / 100) - 10;
+ codeNumber = index % 100;
+
+ //
+ // First we check the index for any of the 'special' values.
+ //
+ // index == 0 means return manufacturers identfication.
+ //
+
+ if (index == 0)
+ {
+
+ if (bufferSize < 4)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ wsprintfW(buffer, L"0x0");
+
+ return NO_ERROR;
+ }
+
+ //
+ // index == 1 means return the date and version.
+ //
+
+ if (index == 1)
+ {
+ if (bufferSize < 12) {
+
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ wsprintfW(buffer, L"0x10920301");
+
+ return NO_ERROR;
+ }
+
+ //
+ // Make sure the adapter number is sensible.
+ //
+
+ if (adapterNumber < 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // Now we find the number of drivers this DLL is supporting.
+ //
+
+ supportedDrivers = sizeof(DetectAdapters) / sizeof(DETECT_ADAPTER);
+
+ //
+ // Iterate through index until we find the the adapter indicated above.
+ //
+
+ for (currentDriver = 0;
+ currentDriver < supportedDrivers;
+ currentDriver++)
+ {
+ //
+ // See if the one we want is in here
+ //
+
+ if (adapterNumber < DetectAdapters[currentDriver].SupportedAdapters)
+ {
+ return (*(DetectAdapters[currentDriver].NcDetectIdentifyHandler))(
+ ((adapterNumber + 10) * 100) + codeNumber,
+ buffer,
+ bufferSize
+ );
+ }
+
+ //
+ // No, move on to next driver.
+ //
+
+ adapterNumber -= DetectAdapters[currentDriver].SupportedAdapters;
+ }
+
+ //
+ // If we get here we didn't find a module that supports the adapter
+ // type.
+ //
+
+ return ERROR_NO_MORE_ITEMS;
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectFirstNext
+*
+* 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
+NcDetectFirstNext(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ )
+{
+ LONG supportedDrivers;
+ LONG currentDriver;
+ LONG adapterNumber;
+ LONG retCode;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapterNumber = (index / 100) - 10;
+
+ //
+ // Check that the adapter type and operation are sensible.
+ //
+
+ if (adapterNumber < 0 || (index % 100) != 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // Now we find the number of drivers this DLL is supporting.
+ //
+
+ supportedDrivers = sizeof(DetectAdapters) / sizeof(DETECT_ADAPTER);
+
+ //
+ // Iterate through index until we find the the adapter indicated above.
+ //
+
+ for (currentDriver = 0;
+ currentDriver < supportedDrivers;
+ currentDriver++)
+ {
+ //
+ // See if the one we want is in here.
+ //
+
+ if (adapterNumber < DetectAdapters[currentDriver].SupportedAdapters)
+ {
+ //
+ // Yes, so call to get the right one.
+ //
+
+ retCode =
+ (*(DetectAdapters[currentDriver].NcDetectFirstNextHandler))(
+ (adapterNumber + 10) * 100,
+ interface,
+ busNumber,
+ first,
+ token,
+ confidence
+ );
+
+ //
+ // If it worked then include the driver number in the token.
+ //
+
+ if (retCode == NO_ERROR)
+ {
+ *token = (VOID *)
+ (((ULONG) (*token)) | (currentDriver << 16));
+ }
+ else
+ {
+ *token = NULL;
+ }
+
+ return retCode;
+ }
+
+ //
+ // No, move on to next driver.
+ //
+
+ adapterNumber -= DetectAdapters[currentDriver].SupportedAdapters;
+ }
+
+ //
+ // If we get here we didn't find a module that supports the adapter
+ // type.
+ //
+
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectOpenHandle
+*
+* 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 FirstNext.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+NcDetectOpenHandle(
+ VOID * token,
+ VOID * * handle
+ )
+{
+ LONG driverToken;
+ LONG driverNumber;
+ LONG retCode;
+ ADAPTER_HANDLE * adapter;
+
+ //
+ // Get the driver number and the driver's token out of the
+ // token.
+ //
+
+ driverToken = ((ULONG) token & 0xFFFF);
+ driverNumber = ((ULONG) token >> 16);
+
+ //
+ // Call the appropriate driver.
+ //
+
+ retCode = (*(DetectAdapters[driverNumber].NcDetectOpenHandleHandler))(
+ (VOID *) driverToken,
+ handle
+ );
+
+ //
+ // If the driver succeeded then create a handle for the adapter.
+ //
+
+ if (retCode == NO_ERROR)
+ {
+ adapter = DetectAllocateHeap(sizeof(ADAPTER_HANDLE));
+
+ if (adapter == NULL)
+ {
+ (*(DetectAdapters[driverNumber].NcDetectCloseHandleHandler))(
+ *handle
+ );
+
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ adapter->Handle = *handle;
+ adapter->DriverNumber = driverNumber;
+
+ *handle = (VOID *) adapter;
+ }
+ else
+ {
+ *handle = NULL;
+ }
+
+ return retCode;
+
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectCreateHandle
+*
+* 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
+NcDetectCreateHandle(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ )
+{
+ LONG supportedDrivers;
+ LONG currentDriver;
+ LONG retCode;
+ LONG adapterNumber;
+ ADAPTER_HANDLE * adapter;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapterNumber = (index / 100) - 10;
+
+ //
+ // Check that the adapter number and the operation requested
+ // are sensible.
+ //
+
+ if (adapterNumber < 0 || (index % 100) != 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // Now we find the number of drivers this DLL is supporting.
+ //
+
+ supportedDrivers = sizeof(DetectAdapters) / sizeof(DETECT_ADAPTER);
+
+ //
+ // Iterate through index until we find the the adapter indicated above.
+ //
+
+ for (currentDriver = 0;
+ currentDriver < supportedDrivers;
+ currentDriver++)
+ {
+ //
+ // See if the one we want is in here
+ //
+
+ if (adapterNumber < DetectAdapters[currentDriver].SupportedAdapters)
+ {
+ //
+ // Yes, so call to get the right one.
+ //
+
+ retCode =
+ (*(DetectAdapters[currentDriver].NcDetectCreateHandleHandler))(
+ (adapterNumber + 10) * 100,
+ interface,
+ busNumber,
+ handle
+ );
+
+ //
+ // If the driver succeeded then create a handle for the adapter.
+ //
+
+ if (retCode == NO_ERROR)
+ {
+ adapter = DetectAllocateHeap(sizeof(ADAPTER_HANDLE));
+
+ if (adapter == NULL)
+ {
+ (*(DetectAdapters[currentDriver].NcDetectCloseHandleHandler))(
+ *handle
+ );
+
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ adapter->Handle = *handle;
+ adapter->DriverNumber = currentDriver;
+
+ *handle = (VOID *) adapter;
+ }
+ else
+ {
+ *handle = NULL;
+ }
+
+ return retCode;
+ }
+
+ //
+ // No, move on to next driver.
+ //
+
+ adapterNumber -= DetectAdapters[currentDriver].SupportedAdapters;
+ }
+
+ //
+ // If we get here we didn't find a module that supports the adapter
+ // type.
+ //
+
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+
+/****************************************************************************
+*
+* Function - NcDetectCloseHandle
+*
+* Parameters - handle -> Handle to be closed.
+*
+* Purpose - Closes a previously opened or created handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+NcDetectCloseHandle(
+ VOID * handle
+ )
+{
+ ADAPTER_HANDLE * adapter;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (ADAPTER_HANDLE *) handle;
+
+ //
+ // Call the appropriate driver.
+ //
+
+ (*(DetectAdapters[adapter->DriverNumber].NcDetectCloseHandleHandler))(
+ adapter->Handle
+ );
+
+ DetectFreeHeap(adapter);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectQueryCfg
+*
+* 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. This is because
+* the handle could have been created rather than opened.
+* The function validates the handle and if the handle does
+* not identify a physical adapter then we attempt to
+* find an adapter that matches the handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+NcDetectQueryCfg(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ ADAPTER_HANDLE * adapter;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (ADAPTER_HANDLE *) handle;
+
+ //
+ // Call the appropriate driver.
+ //
+
+ return (*(DetectAdapters[adapter->DriverNumber].NcDetectQueryCfgHandler))(
+ adapter->Handle,
+ buffer,
+ bufferSize
+ );
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectVerifyCfg
+*
+* 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
+NcDetectVerifyCfg(
+ VOID * handle,
+ WCHAR * buffer
+ )
+{
+ ADAPTER_HANDLE * adapter;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (ADAPTER_HANDLE *) handle;
+
+ //
+ // Call the appropriate driver.
+ //
+
+ return (*(DetectAdapters[adapter->DriverNumber].NcDetectVerifyCfgHandler))(
+ adapter->Handle,
+ buffer
+ );
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectQueryMask
+*
+* 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
+NcDetectQueryMask(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG supportedDrivers;
+ LONG currentDriver;
+ LONG adapterNumber;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapterNumber = (index / 100) - 10;
+
+ //
+ // Check that the adapter number and operation requested are
+ // sensible.
+ //
+
+ if (adapterNumber < 0 || (index % 100) != 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // Now we find the number of drivers this DLL is supporting.
+ //
+
+ supportedDrivers = sizeof(DetectAdapters) / sizeof(DETECT_ADAPTER);
+
+ //
+ // Iterate through index until we find the the adapter indicated above.
+ //
+
+
+ for (currentDriver = 0;
+ currentDriver < supportedDrivers;
+ currentDriver++)
+ {
+ //
+ // See if the one we want is in here.
+ //
+
+ if (adapterNumber < DetectAdapters[currentDriver].SupportedAdapters)
+ {
+ //
+ // Yes, so call to get the right one.
+ //
+
+ return (*(DetectAdapters[currentDriver].NcDetectQueryMaskHandler))(
+ ((adapterNumber + 10) * 100),
+ buffer,
+ bufferSize
+ );
+ }
+
+ //
+ // No, move on to next driver.
+ //
+
+ adapterNumber -= DetectAdapters[currentDriver].SupportedAdapters;
+ }
+
+ //
+ // If we get here we didn't find a module that supports the adapter
+ // type.
+ //
+
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectParamRange
+*
+* 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
+NcDetectParamRange(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ )
+{
+ LONG supportedDrivers;
+ LONG currentDriver;
+ LONG adapterNumber;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapterNumber = (index / 100) - 10;
+
+ //
+ // Check that the adapter number and operation requested are
+ // sensible.
+ //
+
+ if (adapterNumber < 0 || (index % 100) != 0)
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ //
+ // Now we find the number of drivers this DLL is supporting.
+ //
+
+ supportedDrivers = sizeof(DetectAdapters) / sizeof(DETECT_ADAPTER);
+
+ //
+ // Iterate through index until we find the the adapter indicated above.
+ //
+
+ for (currentDriver = 0;
+ currentDriver < supportedDrivers;
+ currentDriver++)
+ {
+ //
+ // See if the one we want is in here.
+ //
+
+ if (adapterNumber < DetectAdapters[currentDriver].SupportedAdapters)
+ {
+ //
+ // Yes, so call to get the right one.
+ //
+
+ return (*(DetectAdapters[currentDriver].NcDetectParamRangeHandler))(
+ ((adapterNumber + 10) * 100),
+ param,
+ buffer,
+ bufferSize
+ );
+ }
+
+ //
+ // No, move on to next driver.
+ //
+
+ adapterNumber -= DetectAdapters[currentDriver].SupportedAdapters;
+ }
+
+ //
+ // If we get here we didn't find a module that supports the adapter
+ // type.
+ //
+
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/****************************************************************************
+*
+* Function - NcDetectQueryParameterNameHandler
+*
+* 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 - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+NcDetectQueryParameterName(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG supportedDrivers;
+ LONG currentDriver;
+ LONG retCode;
+
+ //
+ // Now we find the number of drivers this DLL is supporting.
+ //
+
+ supportedDrivers = sizeof(DetectAdapters) / sizeof(DETECT_ADAPTER);
+
+ //
+ // Iterate through index until we find the the adapter indicated above.
+ //
+
+ for (currentDriver = 0;
+ currentDriver < supportedDrivers;
+ currentDriver++)
+ {
+ //
+ // No way to tell where this came from -- guess until success.
+ //
+
+ retCode =
+ (*(DetectAdapters[currentDriver].NcDetectQueryParameterNameHandler))(
+ param,
+ buffer,
+ bufferSize
+ );
+
+ if (retCode == NO_ERROR)
+ {
+ return NO_ERROR;
+ }
+ }
+
+ //
+ // If we make it here we did not find a driver that could
+ // provide a name for the parameter.
+ //
+
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/******** End of MDGNCDET.C ************************************************/
+
diff --git a/private/ntos/ndis/madge/detect/mdgncdet.def b/private/ntos/ndis/madge/detect/mdgncdet.def
new file mode 100644
index 000000000..aaed20a5d
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgncdet.def
@@ -0,0 +1,18 @@
+LIBRARY MDGNCDET
+
+DESCRIPTION 'Net Card Detection For Madge Cards'
+
+EXPORTS
+ NcDetectIdentify
+ NcDetectFirstNext
+ NcDetectOpenHandle
+ NcDetectCreateHandle
+ NcDetectCloseHandle
+ NcDetectQueryCfg
+ NcDetectVerifyCfg
+ NcDetectQueryMask
+ NcDetectParamRange
+ NcDetectQueryParameterName
+ NcDetectInitialInit
+
+
diff --git a/private/ntos/ndis/madge/detect/mdgncdet.h b/private/ntos/ndis/madge/detect/mdgncdet.h
new file mode 100644
index 000000000..0fc2046c5
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgncdet.h
@@ -0,0 +1,930 @@
+/****************************************************************************
+*
+* MDGNCDET.H
+*
+* Madge Adapter Dection DLL Global Header File
+*
+* 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 19/08/1994
+*
+****************************************************************************/
+
+#ifndef __MDGNCDET__
+#define __MDGNCDET__
+
+
+/*---------------------------------------------------------------------------
+|
+| Debugging macros.
+|
+|--------------------------------------------------------------------------*/
+
+#if DBG
+
+#define MadgePrint1(p1) DbgPrint("MdgNcDet: "##p1)
+#define MadgePrint2(p1, p2) DbgPrint("MdgNcDet: "##p1, (p2))
+#define MadgePrint3(p1, p2, p3) DbgPrint("MdgNcDet: "##p1, (p2), (p3))
+
+#else
+
+#define MadgePrint1(p1)
+#define MadgePrint2(p1, p2)
+#define MadgePrint3(p1, p2, p3)
+
+#endif
+
+
+/*---------------------------------------------------------------------------
+|
+| Adapter option tokens.
+|
+Ý Note: The MDGMPISA and MDGMPMCA tokens are used so that the OEMSETUP.INF
+Ý can be backwards compatible (and therefore upgradeable).
+|--------------------------------------------------------------------------*/
+
+#define MDGMPORT
+
+#ifdef MDGMPORT
+
+#define MDGAT L"MSMDGMPISA"
+#define MDGATP L"MSMDGMPATP"
+#define MDGISAC L"MSMDGMPISAC"
+#define MDGISACP L"MSMDGMPISACP"
+#define MDGPC L"MSMDGMPPC"
+#define MDGSM16 L"MSMDGMPSM16"
+#define MDGPNP L"MSMDGMPPNP"
+#define MDGEISA L"MSMDGMPEISA"
+#define MDGMC16 L"MSMDGMPMCA"
+#define MDGMC32 L"MSMDGMPMC32"
+#define MDGPCI L"MSMDGMPPCI"
+#define MDGPCIBM L"MSMDGMPPCIBM"
+#define MDGPCMCIA L"MSMDGMPPCMCIA"
+
+#endif
+
+
+/*---------------------------------------------------------------------------
+|
+Ý Name of the net detect DLL.
+--------------------------------------------------------------------------*/
+
+#define NET_DETECT_DLL_NAME "NETDTECT"
+
+
+/*---------------------------------------------------------------------------
+|
+| Resource constants.
+Ý Note: For historical reasons DMA channel 0 is used to mean PIO and
+Ý 0 < DMA channel < 16 means bus master DMA on ATULA based adapters.
+Ý (This scheme also works well for Windows95 where we have to
+Ý give a DMA resource range in the NETMADGE.INF file. The user
+Ý must choose one of the valid DMA channels at installtion time.
+Ý The simplest way to say to Windows95 that although we have
+Ý said the we use a DMA channel we don't actually wont want is
+Ý specify a DMA channel of 0 when the use wants PIO.) To make things
+Ý easier for OEMSETUP.INF we have extended this approach.
+Ý A DMA channel of GENERAL_DMA means the adapter uses DMA but
+Ý the channel is determined by the driver at start up (EISA and MC).
+Ý A DMA channel of GENERAL_MMIO means that the driver uses MMIO.
+|
+|--------------------------------------------------------------------------*/
+
+#define RESOURCE_UNKNOWN 0xffff // Unknown DMA, IRQ etc.
+
+#define GENERAL_DMA 500 // DMA without explicit channel
+ // (EISA/MC).
+#define GENERAL_MMIO 501 // General memory mapped IO.
+
+#define END_OF_LIST 1000 // End of a resource list.
+
+
+/*---------------------------------------------------------------------------
+|
+| Function typedefs for the functions exported by the individual adapter
+| detection modules.
+|
+|--------------------------------------------------------------------------*/
+
+typedef
+LONG
+(*NC_DETECT_IDENTIFY)(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+typedef
+LONG
+(*NC_DETECT_FIRST_NEXT)(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ );
+
+typedef
+LONG
+(*NC_DETECT_OPEN_HANDLE)(
+ VOID * token,
+ VOID * * handle
+ );
+
+typedef
+LONG
+(*NC_DETECT_CREATE_HANDLE)(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ );
+
+typedef
+LONG
+(*NC_DETECT_CLOSE_HANDLE)(
+ VOID * handle
+ );
+
+typedef
+LONG
+(*NC_DETECT_QUERY_CFG)(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+typedef
+LONG
+(*NC_DETECT_VERIFY_CFG)(
+ VOID * handle,
+ WCHAR * buffer
+ );
+
+typedef
+LONG
+(*NC_DETECT_QUERY_MASK)(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+typedef
+LONG
+(*NC_DETECT_PARAM_RANGE)(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ );
+
+typedef
+LONG
+(*NC_DETECT_QUERY_PARAMETER_NAME)(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure used to hold all the information required by the main wrapper
+| about an individual adapter setection module.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ NC_DETECT_IDENTIFY NcDetectIdentifyHandler;
+ NC_DETECT_FIRST_NEXT NcDetectFirstNextHandler;
+ NC_DETECT_OPEN_HANDLE NcDetectOpenHandleHandler;
+ NC_DETECT_CREATE_HANDLE NcDetectCreateHandleHandler;
+ NC_DETECT_CLOSE_HANDLE NcDetectCloseHandleHandler;
+ NC_DETECT_QUERY_CFG NcDetectQueryCfgHandler;
+ NC_DETECT_VERIFY_CFG NcDetectVerifyCfgHandler;
+ NC_DETECT_QUERY_MASK NcDetectQueryMaskHandler;
+ NC_DETECT_PARAM_RANGE NcDetectParamRangeHandler;
+ NC_DETECT_QUERY_PARAMETER_NAME NcDetectQueryParameterNameHandler;
+
+ LONG SupportedAdapters;
+
+}
+DETECT_ADAPTER;
+
+
+/*--------------------------------------------------------------------------
+|
+| Structure for holding information about an adapter type.
+|
+---------------------------------------------------------------------------*/
+
+typedef struct
+{
+ LONG Index;
+ WCHAR * InfId;
+ WCHAR * CardDescription;
+ WCHAR * Manufacturer;
+ WCHAR * Parameters;
+ NC_DETECT_FIRST_NEXT FirstNext;
+ ULONG SearchOrder;
+
+}
+ADAPTER_INFO;
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding handles in the NcDetect routines.
+|
+---------------------------------------------------------------------------*/
+
+typedef struct
+{
+ VOID * Handle;
+ LONG DriverNumber;
+
+}
+ADAPTER_HANDLE;
+
+
+/*---------------------------------------------------------------------------
+|
+| Parameter identifier strings. Instantiated in MDGNCDET.C.
+|
+|--------------------------------------------------------------------------*/
+
+extern WCHAR IrqString[];
+extern WCHAR IoAddrString[];
+extern WCHAR DmaChanString[];
+extern WCHAR AdapTypeString[];
+extern WCHAR SlotNumberString[];
+extern WCHAR MultiprocessorString[];
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions exported by MDGUTILS.C
+|
+|--------------------------------------------------------------------------*/
+
+ULONG
+UnicodeStrLen(
+ WCHAR * string
+ );
+
+WCHAR *
+FindParameterString(
+ WCHAR * string1,
+ WCHAR * string2
+ );
+
+VOID
+ScanForNumber(
+ WCHAR * place,
+ ULONG * value,
+ BOOLEAN * found
+ );
+
+VOID *
+DetectAllocateHeap(
+ LONG size
+ );
+
+VOID
+DetectFreeHeap(
+ VOID * ptr
+ );
+
+BOOLEAN
+GetMcaKey(
+ ULONG busNumber,
+ VOID * * infoHandle
+ );
+
+BOOLEAN
+GetMcaPosId(
+ VOID * infoHandle,
+ ULONG slotNumber,
+ ULONG * posId
+ );
+
+VOID
+DeleteMcaKey(
+ VOID * infoHandle
+ );
+
+BOOLEAN
+GetEisaKey(
+ ULONG busNumber,
+ VOID * * infoHandle
+ );
+
+BOOLEAN
+GetEisaCompressedId(
+ VOID * infoHandle,
+ ULONG slotNumber,
+ ULONG * compressedId
+ );
+
+VOID
+DeleteEisaKey(
+ VOID * infoHandle
+ );
+
+LONG
+AppendParameter(
+ WCHAR * * buffer,
+ LONG * bufferSize,
+ WCHAR * title,
+ ULONG value
+ );
+
+BOOLEAN
+UnicodeStringsEqual(
+ WCHAR *string1,
+ WCHAR *string2
+ );
+
+BOOLEAN
+MadgeCardAlreadyInstalled(
+ BOOLEAN useSlotNumber,
+ ULONG busNumber,
+ ULONG descriptor
+ );
+
+ULONG
+IsMultiprocessor(void);
+
+BOOLEAN
+IsValueInList(
+ ULONG value,
+ ULONG * list
+ );
+
+BOOLEAN
+CheckForPcmciaCard(
+ ULONG * ioLocation,
+ ULONG * irqNumber
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions exported by MDGEISA.C.
+|
+|--------------------------------------------------------------------------*/
+
+LONG
+MadgeEisaIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeEisaFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ );
+
+LONG
+MadgeEisaOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ );
+
+LONG
+MadgeEisaCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ );
+
+LONG
+MadgeEisaCloseHandleHandler(
+ VOID * handle
+ );
+
+LONG
+MadgeEisaQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeEisaVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ );
+
+LONG
+MadgeEisaQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeEisaParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ );
+
+LONG
+MadgeEisaQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions exported by MDGPCI.C.
+|
+|--------------------------------------------------------------------------*/
+
+LONG
+MadgePciIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePciFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ );
+
+LONG
+MadgePciOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ );
+
+LONG
+MadgePciCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ );
+
+LONG
+MadgePciCloseHandleHandler(
+ VOID * handle
+ );
+
+LONG
+MadgePciQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePciVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ );
+
+LONG
+MadgePciQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePciParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ );
+
+LONG
+MadgePciQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions exported by MDGPCMC.C.
+|
+|--------------------------------------------------------------------------*/
+
+LONG
+MadgePcmciaIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePcmciaFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ );
+
+LONG
+MadgePcmciaOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ );
+
+LONG
+MadgePcmciaCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ );
+
+LONG
+MadgePcmciaCloseHandleHandler(
+ VOID * handle
+ );
+
+LONG
+MadgePcmciaQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePcmciaVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ );
+
+LONG
+MadgePcmciaQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePcmciaParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ );
+
+LONG
+MadgePcmciaQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions exported by MDGAT.C.
+|
+|--------------------------------------------------------------------------*/
+
+LONG
+MadgeATIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeATFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ );
+
+LONG
+MadgeATOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ );
+
+LONG
+MadgeATCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ );
+
+LONG
+MadgeATCloseHandleHandler(
+ VOID * handle
+ );
+
+LONG
+MadgeATQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeATVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ );
+
+LONG
+MadgeATQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeATParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ );
+
+LONG
+MadgeATQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions exported by MDGSM16.C.
+|
+|--------------------------------------------------------------------------*/
+
+LONG
+MadgeSm16IdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeSm16FirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ );
+
+LONG
+MadgeSm16OpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ );
+
+LONG
+MadgeSm16CreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ );
+
+LONG
+MadgeSm16CloseHandleHandler(
+ VOID * handle
+ );
+
+LONG
+MadgeSm16QueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeSm16VerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ );
+
+LONG
+MadgeSm16QueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeSm16ParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ );
+
+LONG
+MadgeSm16QueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions exported by MDGPNP.C.
+|
+|--------------------------------------------------------------------------*/
+
+LONG
+MadgePnPIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePnPFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ );
+
+LONG
+MadgePnPOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ );
+
+LONG
+MadgePnPCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ );
+
+LONG
+MadgePnPCloseHandleHandler(
+ VOID * handle
+ );
+
+LONG
+MadgePnPQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePnPVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ );
+
+LONG
+MadgePnPQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgePnPParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ );
+
+LONG
+MadgePnPQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions exported by MDGMC.C.
+|
+|--------------------------------------------------------------------------*/
+
+LONG
+MadgeMCIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeMCFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ );
+
+LONG
+MadgeMCOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ );
+
+LONG
+MadgeMCCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ );
+
+LONG
+MadgeMCCloseHandleHandler(
+ VOID * handle
+ );
+
+LONG
+MadgeMCQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeMCVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ );
+
+LONG
+MadgeMCQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+LONG
+MadgeMCParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ );
+
+LONG
+MadgeMCQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ );
+
+
+#endif
+
+/******** End of MDGNCDET.H ************************************************/
+
diff --git a/private/ntos/ndis/madge/detect/mdgncdet.rc b/private/ntos/ndis/madge/detect/mdgncdet.rc
new file mode 100644
index 000000000..bda6f9427
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgncdet.rc
@@ -0,0 +1,27 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#include "mdgncdet.upd"
+
+#undef VER_COMPANYNAME_STR
+#undef VER_PRODUCTNAME_STR
+#undef VER_PRODUCTVERSION
+#undef VER_PRODUCTVERSION_STR
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+#define VER_COMPANYNAME_STR "Madge Networks Ltd"
+#define VER_PRODUCTNAME_STR "Madge Networks Smart Ringnode Netcard Detection"
+#define VER_FILEDESCRIPTION_STR "Madge NetDetect"
+#define VER_INTERNALNAME_STR "MdgNcDet.DLL"
+
+#define VER_LEGALCOPYRIGHT_YEARS "1994"
+#define VER_LEGALCOPYRIGHT_STR "Copyright (C) Madge Networks Ltd " VER_LEGALCOPYRIGHT_YEARS
+#define VER_FILEVERSION MADGE_DLL_VERSION
+#define VER_FILEVERSION_STR MADGE_DLL_VERSION_STR
+#define VER_PRODUCTVERSION MADGE_NT_VERSION
+#define VER_PRODUCTVERSION_STR MADGE_NT_VERSION_STR
+
+#include <common.ver>
+
diff --git a/private/ntos/ndis/madge/detect/mdgncdet.upd b/private/ntos/ndis/madge/detect/mdgncdet.upd
new file mode 100644
index 000000000..42d021ec4
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgncdet.upd
@@ -0,0 +1,200 @@
+/***************************************************************************
+*
+* MDGNCDET.UPD
+*
+* Update log and version information for Madge Smart Adapter NetDetect DLL.
+*
+* Copyright (c) Madge Networks Ltd 1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: 21/09/1994
+*
+****************************************************************************/
+
+#include "..\driver\mdgmport.upd"
+
+/*---------------------------------------------------------------------------
+|
+| Version number.
+|
+---------------------------------------------------------------------------*/
+
+//
+// Define both a string and a comma separated list of numbers. These will be
+// used by the resource compiler when version stamping the driver file.
+//
+
+#define MADGE_DLL_VERSION 2,04,02,00
+#define MADGE_DLL_VERSION_STR "2.04.02"
+
+#define MADGE_DLL_NAME "MdgNcDet.DLL"
+
+#define _DRIVER_DESC MADGE_NT_NAME##" "##MADGE_NT_VERSION_STR
+#define _DLL_DESC MADGE_DLL_NAME##" "##MADGE_DLL_VERSION_STR
+
+
+/*---------------------------------------------------------------------------
+|
+| String for identification by MVER.
+|
+|--------------------------------------------------------------------------*/
+
+#ifdef MVER_STRING
+#undef MVER_STRING
+#endif
+
+#define MVER_STRING \
+ "VeRsIoN="##_DLL_DESC##" (for "##_DRIVER_DESC##")"
+
+
+/*---------------------------------------------------------------------------
+|
+| Update history.
+|
+|----------------------------------------------------------------------------
+
+ 2.04.01-.49 Reserved for 4.3(1) maintanance.
+
+ 2.04.02 07/12/1995 PBA
+
+ We now check the bus number as well as the slot number
+ or I/O location when checking if a card is already
+ installed. We need this for machines with multiple
+ PCI buses. CR=59/SOL=117
+
+ 2.04.01 30/10/1995 PBA
+
+ Maintenance build.
+
+ 2.04 21/07/1995 PBA
+
+ Re-released for 4.3(1) with PCI-TI DMA/DIO fix.
+
+ 2.03.01-.49 Reserved for 4.3(1) maintanance.
+
+ 2.03 30/06/1995 PBA
+
+ Released for LSS 4.3(1) hardware thread with support
+ for PCI-TI adapters and untested support for PCI-Abyss
+ adapters.
+
+ 2.02 Useds for non-intel thread derived from LSS 4.3(0).
+
+ 2.01.04 09/05/1995 PBA
+
+ Changed the PCI detection code so that it manually
+ gets a pointer to DetectReadPciSlotInformation
+ using GetProcAddress rather than just calling it
+ in line. This allows the same DLL to be used under
+ NT 3.5 and NT 3.51 (though PCI adapters will only
+ be found under NT 3.51+).
+
+ 2.01.03 02/05/1995 PBA
+
+ Added code to actually find a PCI adapter. Made
+ PIO the default mode for PCI adapters and removed
+ MMIO support for PowerPC.
+
+ 2.01.02 07/04/1995 PBA
+
+ Changed PCMCIA support so that it reads the hardware
+ resources from the registry.
+
+ 2.01.01 04/04/1995 PBA
+
+ Added proper PCMCIA report. MDGMPORT 2.01.01.
+
+ Power PC build. Only supports PIO on ISA and PCI
+ adapters.
+
+
+ 2.01.02 - .49 Reserved for 4.3(0 and/or PnP) maintenance.
+
+ 2.01 02/02/1995 PBA
+
+ Released for 4.3(0 and/or PnP). All previous 4.(x)
+ threads are now dead.
+
+ MDGMPORT 2.01.
+
+ 2.00.53 02/02/1995 PBA
+
+ Given to DaveF for Chicago testing and possible
+ shipment to Microsoft for M8 and/or NT 3.51.
+ MDGMPORT 2.00.61.
+
+ 2.00.52 31/01/1995 PBA
+
+ Added partial support for PCMCIA adapters. Cannot actually
+ detect an adapter put can provide parameter range
+ information.
+
+ 2.00.51 06/01/1995 PBA
+
+ Shipped source to FrancisT so that he could do a MIPs
+ build.
+
+ 2.00.50 15/12/1994 PBA
+
+ Live development continues.
+
+ Version numbers 1.50.01 to 1.99.99 are used for a FastMAC version.
+
+ 1.02.01 - .49 Reserved for release 4.3(1) maintenance.
+
+ Version number 1.02 is reserved for use in the 4.3(1) release. Live
+ development continues with 2.02.50.
+
+ 1.01.50 15/12/1994 PBA
+
+ Alpha release for product marketing to test. For use with
+ MDGMPORT 1.05.07.
+
+ 1.01.01 - .49 Reserved for release 4.3(0) maintenance.
+
+ Due the delay in getting the 4.3(0) release out it was decided to use
+ the new installtion software for 4.3(0). Version number 2.01 is
+ reserved for this. Live development continues with 2.01.50.
+
+ 1.00.05 25/11/1994 PBA
+
+ Arranged that all adapter modules return a DMA channel
+ value. In the case of EISA and MC this always returns
+ a constant to means DMA without a specific channel. PCI
+ always returns a constant to mean MMIO.
+
+ 1.00.04 24/11/1994 PBA
+
+ Added partial support for PCI adapters. Cannot actually
+ detect an adapter put can provide parameter range
+ information.
+
+ -- Special -----------------------------------------------------------------
+
+ 1.00.03a 11/01/1995 PBA
+
+ Added PCMCIA module that doesn't do anything other than
+ provide parameter lists. Shipped to Jameel Hyder at
+ Microsoft for NT 3.51 beta. MDGMPORT 1.06.80.
+
+ ----------------------------------------------------------------------------
+
+ 1.00.03 23/11/1994 PBA
+
+ Shipped to Microsoft for possible inclusion in the next
+ NT release. MDGMPORT v1.06.50.
+
+ 1.00.02 23/11/1994 PBA
+
+ Added support for ISA PnP adapters.
+
+ 1.00.01 12/09/1994 PBA
+
+ First version.
+
+---------------------------------------------------------------------------*/
+
+
+/******** End of MDGNCDET.UPD **********************************************/
+ \ No newline at end of file
diff --git a/private/ntos/ndis/madge/detect/mdgpci.c b/private/ntos/ndis/madge/detect/mdgpci.c
new file mode 100644
index 000000000..7c52f25df
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgpci.c
@@ -0,0 +1,1446 @@
+/****************************************************************************
+*
+* MDGPCI.C
+*
+* PCI 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 24/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, ...);
+
+
+//
+// Prototypes "borrowed" from WINBASE.H
+//
+
+#if !defined(_KERNEL32_)
+#define WINBASEAPI DECLSPEC_IMPORT
+#else
+#define WINBASEAPI
+#endif
+
+WINBASEAPI
+FARPROC
+WINAPI
+GetProcAddress(
+ HINSTANCE hModule,
+ LPCSTR lpProcName
+ );
+
+WINBASEAPI
+HMODULE
+WINAPI
+GetModuleHandleA(
+ LPCSTR lpModuleName
+ );
+
+WINBASEAPI
+HMODULE
+WINAPI
+GetModuleHandleW(
+ LPCWSTR lpModuleName
+ );
+
+#ifdef UNICODE
+#define GetModuleHandle GetModuleHandleW
+#else
+#define GetModuleHandle GetModuleHandleA
+#endif // !UNICODE
+
+
+/*---------------------------------------------------------------------------
+|
+| PCI 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_PCI 1000
+#define SMART_PCI_BM 1100
+
+
+/*---------------------------------------------------------------------------
+|
+| PCI Vendor ID.
+|
+|--------------------------------------------------------------------------*/
+
+#define MADGE_VENDOR_ID 0x10b6
+
+
+/*---------------------------------------------------------------------------
+|
+| PCI revision IDs.
+|
+|--------------------------------------------------------------------------*/
+
+#define MADGE_PCI_RAP1B_REVISION 0x0001
+#define MADGE_PCI_PCI2_REVISION 0x0002
+#define MADGE_PCI_PCIT_REVISION 0x0004
+
+
+/*---------------------------------------------------------------------------
+|
+| PCI Configuration Space.
+|
+|--------------------------------------------------------------------------*/
+
+#define PCI_CONFIG_SIZE 64
+#define PCI_VENDOR_ID(buff) (((UINT *) (buff))[0] & 0x0000ffffL)
+#define PCI_REVISION(buff) ((((UINT *) (buff))[0] & 0xffff0000L) >> 16)
+
+
+/*---------------------------------------------------------------------------
+|
+| Maximum PCI slot number. (Slot numbers range from 0 to MAX_PCI_SLOT.)
+|
+|---------------------------------------------------------------------------*/
+
+#define MAX_PCI_SLOT 31
+
+
+/*---------------------------------------------------------------------------
+|
+| List of adapter types supported by this module.
+|
+|---------------------------------------------------------------------------*/
+
+static
+ADAPTER_INFO Adapters[] =
+{
+ {
+ SMART_PCI,
+ MDGPCI,
+ L"Madge 16/4 PCI Ringnode",
+ L"Madge Networks",
+ L"SLOTNUMBER\0"
+ L"000\0"
+ L"00100\0"
+ L"DMACHANNEL\0"
+ L"000\0"
+ L"00100\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 900
+ },
+
+ {
+ SMART_PCI_BM,
+ MDGPCIBM,
+ L"Madge 16/4 PCI Ringnode (BM)",
+ L"Madge Networks",
+ L"SLOTNUMBER\0"
+ L"000\0"
+ L"00100\0"
+ L"DMACHANNEL\0"
+ L"000\0"
+ L"00100\0"
+ L"MULTIPROCESSOR\0"
+ L"000\0"
+ L"00100\0",
+ NULL,
+ 900
+ }
+
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| 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 SlotNumber[34];
+ ULONG DmaRange[3];
+}
+ParamRange[] =
+{
+ //
+ // Smart 16/4 PCI.
+ //
+
+ {
+ { RESOURCE_UNKNOWN,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ END_OF_LIST},
+
+#if defined(_PPC_) || defined(_MIPS_)
+
+ { 0, END_OF_LIST}
+
+#else
+
+ { 0, GENERAL_MMIO, END_OF_LIST}
+
+#endif
+ },
+
+ //
+ // Smart 16/4 PciT and Pci2 (i.e. Smart 16/4 PCI (BM)).
+ //
+
+ {
+ { RESOURCE_UNKNOWN,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ END_OF_LIST},
+
+#if defined(_PPC_) || defined(_MIPS_)
+
+ { GENERAL_DMA, 0, END_OF_LIST}
+
+#else
+
+ { GENERAL_DMA, 0, END_OF_LIST}
+
+#endif
+ }
+
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding state of a search.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ ULONG SlotNumber;
+}
+PCI_SEARCH_STATE;
+
+
+/*---------------------------------------------------------------------------
+|
+| This is an array of search states. We need one state for each type
+| of adapter supported.
+|
+|--------------------------------------------------------------------------*/
+
+static
+PCI_SEARCH_STATE SearchStates[sizeof(Adapters) / sizeof(ADAPTER_INFO)] = {0};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding a particular adapter's complete information.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ BOOLEAN Found;
+ ULONG CardType;
+ INTERFACE_TYPE InterfaceType;
+ ULONG BusNumber;
+ ULONG SlotNumber;
+ ULONG Dma;
+}
+PCI_ADAPTER;
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - CheckForCard
+|
+| Parameters - busNumber -> The number of the bus to check.
+| interface -> The interface type of the bus.
+| slotNumber -> The slot number to be checked.
+|
+| Purpose - Check to see if an Madge PCI card in the specified
+| slot.
+|
+| Returns - A card type.
+|
+---------------------------------------------------------------------------*/
+
+static ULONG
+CheckForCard(
+ ULONG busNumber,
+ INTERFACE_TYPE interface,
+ ULONG slotNumber
+ )
+{
+ HMODULE detectDll;
+ FARPROC readPciSlot;
+ UCHAR pciInfo[PCI_CONFIG_SIZE];
+
+ MadgePrint2("CheckForCard (slotNumber=%ld)\n", slotNumber);
+
+ //
+ // The DetectReadPciSlotInformation function was not exported under
+ // NT 3.5 but is available under NT 3.51. So that we can have code
+ // that works on both versions of NT we will obtain the address of
+ // the function explicitly rather than using load time linking.
+ //
+
+ detectDll = GetModuleHandle(NET_DETECT_DLL_NAME);
+
+ if (detectDll == NULL)
+ {
+ MadgePrint1("GetModuleHandle failed\n");
+ return SMART_NONE;
+ }
+
+ readPciSlot = GetProcAddress(detectDll, "DetectReadPciSlotInformation");
+
+ if (readPciSlot == NULL)
+ {
+ MadgePrint1("GetProcAddress failed\n");
+ return SMART_NONE;
+ }
+
+ //
+ // If we make it here we should have a pointer to the
+ // DetectReadPciSlotInformation function. All we have to
+ // do now is cast the function and call.
+ //
+
+ if (((NTSTATUS (*)(ULONG, ULONG, ULONG, ULONG, PVOID)) readPciSlot)(
+ busNumber,
+ slotNumber,
+ 0,
+ PCI_CONFIG_SIZE,
+ (void *) pciInfo
+ ) == NO_ERROR)
+ {
+ if (PCI_VENDOR_ID(pciInfo) == MADGE_VENDOR_ID)
+ {
+
+ switch (PCI_REVISION(pciInfo))
+ {
+ case MADGE_PCI_RAP1B_REVISION:
+
+ return SMART_PCI;
+
+ case MADGE_PCI_PCI2_REVISION:
+ case MADGE_PCI_PCIT_REVISION:
+
+ return SMART_PCI_BM;
+ }
+ }
+ }
+
+ return SMART_NONE;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - FindPciCard
+|
+| 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
+| slot number checked the previous time FindPciCard was called.
+|
+| Returns - A WINERROR.H error code.
+|
+|--------------------------------------------------------------------------*/
+
+static ULONG
+FindPciCard(
+ 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 slot number.
+ //
+
+ if (first)
+ {
+ SearchStates[adapterNumber].SlotNumber = 0;
+ }
+
+ //
+ // Otherwise we want to start from 1 after were we left off
+ // last time.
+ //
+
+ else
+ {
+ SearchStates[adapterNumber].SlotNumber++;
+ }
+
+ //
+ // Step through the slots 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.
+ //
+
+ *confidence = 0;
+
+ while (SearchStates[adapterNumber].SlotNumber <= MAX_PCI_SLOT)
+ {
+ if (!MadgeCardAlreadyInstalled(
+ TRUE,
+ busNumber,
+ SearchStates[adapterNumber].SlotNumber
+ ))
+ {
+ if (CheckForCard(
+ busNumber,
+ interface,
+ SearchStates[adapterNumber].SlotNumber
+ ) == type)
+ {
+ *confidence = 100;
+ break;
+ }
+ }
+
+ SearchStates[adapterNumber].SlotNumber++;
+ }
+
+ return NO_ERROR;
+}
+
+
+
+/****************************************************************************
+*
+* Function - MadgePciIdentifyHandler
+*
+* 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
+MadgePciIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG numberOfAdapters;
+ LONG action;
+ LONG length;
+ LONG i;
+
+ MadgePrint2("MadgePciIdentifyHandler (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 - MadgePciFirstNextHandler
+*
+* 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
+MadgePciFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ )
+{
+ ULONG retCode;
+ LONG adapterNumber;
+
+ MadgePrint2("MadgePciFirstNextHandler (index = %ld)\n", index);
+
+ //
+ // Check the interface type.
+ //
+
+ if (interface != PCIBus)
+ {
+ *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 = FindPciCard(
+ (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);
+ }
+
+ return retCode;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgePciOpenHandleHandler
+*
+* 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
+MadgePciOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ )
+{
+ PCI_ADAPTER * adapter;
+ ULONG adapterNumber;
+ ULONG busNumber;
+ INTERFACE_TYPE interface;
+
+ MadgePrint1("MadgePciOpenHandleHandler\n");
+
+ //
+ // Get info from the token.
+ //
+
+ interface = PCIBus;
+ busNumber = (ULONG) (((ULONG) token >> 8) & 0x7F);
+ adapterNumber = ((ULONG) token) & 0xFF;
+
+ //
+ // Allocate a structure for the details of the adapter.
+ //
+
+ adapter = (PCI_ADAPTER *) DetectAllocateHeap(sizeof(PCI_ADAPTER));
+
+ if (adapter == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ //
+ // Copy the details.
+ //
+
+ adapter->Found = TRUE;
+ adapter->SlotNumber = SearchStates[adapterNumber].SlotNumber;
+ adapter->CardType = Adapters[adapterNumber].Index;
+ adapter->InterfaceType = interface;
+ adapter->BusNumber = busNumber;
+ adapter->Dma = ParamRange[adapterNumber].DmaRange[0];
+
+ *handle = (VOID *) adapter;
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgePciCreateHandleHandler
+*
+* 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
+MadgePciCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ )
+{
+ PCI_ADAPTER * adapter;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgePciCreateHandleHandler (index = %ld)\n", index);
+
+ //
+ // Check that the interface type is correct for this module.
+ //
+
+ if (interface != PCIBus)
+ {
+ 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 = (PCI_ADAPTER *) DetectAllocateHeap(sizeof(PCI_ADAPTER));
+
+ if (adapter == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ //
+ // Copy the details.
+ //
+
+ adapter->Found = FALSE;
+ adapter->SlotNumber = 1;
+ adapter->CardType = index;
+ adapter->InterfaceType = interface;
+ adapter->BusNumber = busNumber;
+ adapter->Dma = ParamRange[i].DmaRange[0];
+
+ *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 - MadgePciCloseHandleHandler
+*
+* Parameters - handle -> Handle to be closed.
+*
+* Purpose - Closes a previously opened or created handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgePciCloseHandleHandler(
+ VOID * handle
+ )
+{
+ MadgePrint1("MadgePciCloseHandleHandler\n");
+
+ DetectFreeHeap(handle);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgePciQueryCfgHandler
+*
+* 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. This is because
+* the handle could have been created rather than opened.
+* The function validates the handle and if the handle does
+* not identify a physical adapter then we attempt to
+* find an adapter that matches the handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgePciQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ PCI_ADAPTER * adapter;
+ VOID * busHandle;
+ ULONG confidence;
+ BOOLEAN found;
+ LONG adapterNumber;
+ LONG retCode;
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (PCI_ADAPTER *) handle;
+
+ //
+ // Check that the interface type specified by the handle is
+ // valid for this module.
+ //
+
+ if (adapter->InterfaceType != PCIBus)
+ {
+ 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 = FindPciCard(
+ 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->SlotNumber = SearchStates[adapterNumber].SlotNumber;
+ }
+
+ //
+ // Build resulting buffer.
+ //
+ // Copy in the slot number title and value.
+ //
+
+ if (AppendParameter(
+ &buffer,
+ &bufferSize,
+ SlotNumberString,
+ adapter->SlotNumber
+ ) != NO_ERROR)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ //
+ // Copy in the DMA channel title and value.
+ //
+
+ if (AppendParameter(
+ &buffer,
+ &bufferSize,
+ DmaChanString,
+ adapter->Dma
+ ) != 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 - MadgePciVerifyCfgHandler
+*
+* 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
+MadgePciVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ )
+{
+ PCI_ADAPTER * adapter;
+ WCHAR * place;
+ ULONG compressedId;
+ ULONG slotNumber;
+ ULONG dmaChannel;
+ ULONG multiprocessor;
+ VOID * busHandle;
+ BOOLEAN found;
+ LONG adapterNumber;
+
+ MadgePrint1("MadgePciVerifyCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (PCI_ADAPTER *) handle;
+ adapterNumber = (adapter->CardType - 1000) / 100;
+
+ //
+ // Check that the interface type is correct for this module.
+ //
+
+ if (adapter->InterfaceType != PCIBus)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ //
+ // Parse the parameters.
+ //
+ // Get the slot number.
+ //
+
+ place = FindParameterString(buffer, SlotNumberString);
+
+ if (place == NULL)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ place += UnicodeStrLen(SlotNumberString) + 1;
+
+ //
+ // Now parse the slot number.
+ //
+
+ ScanForNumber(place, &slotNumber, &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 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 adapter was created rather than being opened we must check
+ // the PCI configuration to make sure the slot contains a
+ // Madge adapter.
+ //
+
+ if (!adapter->Found)
+ {
+ if (CheckForCard(
+ adapter->BusNumber,
+ adapter->InterfaceType,
+ slotNumber
+ ) != adapter->CardType)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ adapter->Found = TRUE;
+ adapter->SlotNumber = slotNumber;
+ }
+
+ //
+ // Verify the parameter.
+ //
+
+ if (slotNumber != adapter->SlotNumber ||
+ 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 we make it to here everything checked out ok.
+ //
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgePciQueryMaskHandler
+*
+* 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
+MadgePciQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ WCHAR * params;
+ LONG length;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint1("MadgePciQueryMaskHandler\n");
+
+ //
+ // 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++;
+
+ //
+ // 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 - MadgePciParamRangeHandler
+*
+* 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
+MadgePciParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ )
+{
+ LONG adapterNumber;
+ LONG count;
+ LONG i;
+
+ //
+ // 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;
+ }
+
+ //
+ // Fill in the allowable slot numbers in the buffer.
+ //
+
+ if (UnicodeStringsEqual(param, SlotNumberString))
+ {
+ count = 0;
+
+ while (ParamRange[adapterNumber].SlotNumber[count] != END_OF_LIST)
+ {
+ count++;
+ }
+
+ if (*bufferSize < count)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ buffer[i] = ParamRange[adapterNumber].SlotNumber[i];
+ }
+
+ *bufferSize = count;
+
+ return NO_ERROR;
+ }
+
+ //
+ // Or the valid DMA channels.
+ //
+
+ 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 - MadgePciQueryParameterNameHandler
+*
+* 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
+MadgePciQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/********* End of MDGPCI.C *************************************************/
+
diff --git a/private/ntos/ndis/madge/detect/mdgpcmc.c b/private/ntos/ndis/madge/detect/mdgpcmc.c
new file mode 100644
index 000000000..b07547c5b
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgpcmc.c
@@ -0,0 +1,1396 @@
+/****************************************************************************
+*
+* MDGPCMC.C
+*
+* PCMCIA Adapter Detection Module
+*
+* Copyright (c) Madge Networks Ltd 1995
+*
+* 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 11/01/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, ...);
+
+
+
+/*---------------------------------------------------------------------------
+|
+| PCMCIA 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_PCMCIA 1000
+
+
+/*---------------------------------------------------------------------------
+|
+| A selection of IO locations that PCMCIA adapters can be at.
+|
+---------------------------------------------------------------------------*/
+
+static
+ULONG PcmciaIoLocations[18] =
+ {0x0300,
+ 0x1a20, 0x2a20, 0x3a20,
+ 0x0140,
+ 0x0920, 0x0940, 0x0960, 0x0980,
+ 0x0a20, 0x0a40, 0x0a60, 0x0a80, 0x0aa0,
+ 0x0b20, 0x0b40, 0x0b60, 0x0b80};
+
+
+/*---------------------------------------------------------------------------
+|
+| List of adapter types supported by this module.
+|
+|---------------------------------------------------------------------------*/
+
+static
+ADAPTER_INFO Adapters[] =
+{
+ {
+ SMART_PCMCIA,
+ MDGPCMCIA,
+ L"Madge 16/4 PCMCIA 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. (99 is a null entry.)
+|
+---------------------------------------------------------------------------*/
+
+static
+struct
+{
+ ULONG IrqRange[16];
+ ULONG DmaRange[2];
+}
+ParamRange[] =
+{
+ //
+ // PCMCIA.
+ //
+
+ {
+ { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15,
+ END_OF_LIST},
+ { 0, END_OF_LIST}
+ }
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding state of a search.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ ULONG IoLocationIndex;
+ ULONG Irq;
+}
+PCMCIA_SEARCH_STATE;
+
+
+/*---------------------------------------------------------------------------
+|
+| This is an array of search states. We need one state for each type
+| of adapter supported.
+|
+|--------------------------------------------------------------------------*/
+
+static
+PCMCIA_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;
+}
+PCMCIA_ADAPTER;
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - CheckForCard
+|
+| Parameters - busNumber -> The number of the bus to check.
+| interface -> The interface type of the bus.
+| ioLocation -> IO location to check.
+Ý irqNumber -> Pointer to a holder for the returned
+Ý IRQ number.
+|
+| Purpose - Check to see if an Madge Pcmcia card is present in the
+Ý machine at the given IO location.
+|
+| Returns - A card type.
+|
+---------------------------------------------------------------------------*/
+
+static ULONG
+CheckForCard(
+ ULONG busNumber,
+ INTERFACE_TYPE interface,
+ ULONG ioLocation,
+ ULONG * irqNumber
+ )
+{
+ ULONG ioBase;
+
+ MadgePrint2("CheckForCard (ioLocation=%04lx)\n", ioLocation);
+
+ if (CheckForPcmciaCard(&ioBase, irqNumber))
+ {
+ if (ioBase == ioLocation)
+ {
+ MadgePrint1("Found PCMCIA card\n");
+
+ return SMART_PCMCIA;
+ }
+ }
+
+ MadgePrint1("Did not find PCMCIA card\n");
+
+ return SMART_NONE;
+}
+
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - FindPcmciaCard
+|
+| 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 FindPcmciaCard was called.
+|
+| Returns - A WINERROR.H error code.
+|
+|--------------------------------------------------------------------------*/
+
+static ULONG
+FindPcmciaCard(
+ 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(PcmciaIoLocations) / sizeof(ULONG))
+ {
+ if (!MadgeCardAlreadyInstalled(
+ FALSE,
+ busNumber,
+ PcmciaIoLocations[SearchStates[adapterNumber].IoLocationIndex]
+ ))
+ {
+ if (CheckForCard(
+ busNumber,
+ interface,
+ PcmciaIoLocations[SearchStates[adapterNumber].IoLocationIndex],
+ &SearchStates[adapterNumber].Irq
+ ) == type)
+ {
+ *confidence = 100;
+ break;
+ }
+ }
+
+ SearchStates[adapterNumber].IoLocationIndex++;
+ }
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgePcmciaIdentifyHandler
+*
+* 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
+MadgePcmciaIdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG numberOfAdapters;
+ LONG action;
+ LONG length;
+ LONG i;
+
+ MadgePrint2("MadgePcmciaIdentifyHandler (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 - MadgePcmciaFirstNextHandler
+*
+* 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
+MadgePcmciaFirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ )
+{
+ LONG adapterNumber;
+ ULONG retCode;
+
+ MadgePrint2("MadgePcmciaFirstNextHandler (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 = FindPcmciaCard(
+ (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 - MadgePcmciaOpenHandleHandler
+*
+* 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
+MadgePcmciaOpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ )
+{
+ PCMCIA_ADAPTER * adapter;
+ ULONG adapterNumber;
+ ULONG busNumber;
+ INTERFACE_TYPE interface;
+
+ MadgePrint1("MadgePcmciaOpenHandleHandler\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 = (PCMCIA_ADAPTER *) DetectAllocateHeap(sizeof(PCMCIA_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 =
+ PcmciaIoLocations[SearchStates[adapterNumber].IoLocationIndex];
+ adapter->Dma = 0; // Pcmcia's are always in PIO mode.
+ adapter->Irq = SearchStates[adapterNumber].Irq;
+
+ *handle = (VOID *) adapter;
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgePcmciaCreateHandleHandler
+*
+* 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
+MadgePcmciaCreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ )
+{
+ PCMCIA_ADAPTER * adapter;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgePcmciaCreateHandleHandler (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 = (PCMCIA_ADAPTER *) DetectAllocateHeap(sizeof(PCMCIA_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 = PcmciaIoLocations[0];
+ adapter->Dma = 0; // Pcmcia'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 - MadgePcmciaCloseHandleHandler
+*
+* Parameters - handle -> Handle to be closed.
+*
+* Purpose - Closes a previously opened or created handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgePcmciaCloseHandleHandler(
+ VOID * handle
+ )
+{
+ MadgePrint1("MadgePcmciaCloseHandleHandler\n");
+
+ DetectFreeHeap(handle);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgePcmciaQueryCfgHandler
+*
+* 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
+MadgePcmciaQueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ PCMCIA_ADAPTER * adapter;
+ ULONG confidence;
+ LONG adapterNumber;
+ LONG retCode;
+
+ MadgePrint1("MadgePcmciaQueryCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (PCMCIA_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 = FindPcmciaCard(
+ 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 =
+ PcmciaIoLocations[SearchStates[adapterNumber].IoLocationIndex];
+ adapter->Dma = 0; // Pcmcia'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 - MadgePcmciaVerifyCfgHandler
+*
+* 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
+MadgePcmciaVerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ )
+{
+ PCMCIA_ADAPTER * adapter;
+ WCHAR * place;
+ BOOLEAN found;
+ ULONG ioLocation;
+ ULONG dmaChannel;
+ ULONG irqNumber;
+ ULONG multiprocessor;
+ LONG adapterNumber;
+ ULONG irq;
+
+ MadgePrint1("MadgePcmciaVerifyCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (PCMCIA_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,
+ &irq
+ ) != adapter->CardType)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ adapter->IoLocation = ioLocation;
+ adapter->Dma = 0; // Pcmcia's are always in PIO mode.
+ adapter->Irq = irq;
+ 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 - MadgePcmciaQueryMaskHandler
+*
+* 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
+MadgePcmciaQueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ WCHAR * params;
+ LONG length;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgePcmciaQueryMaskHandler (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 - MadgePcmciaParamRangeHandler
+*
+* 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
+MadgePcmciaParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ )
+{
+ LONG i;
+ LONG adapterNumber;
+ LONG count;
+
+ MadgePrint2("MadgePcmciaParamRangeHandler (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(PcmciaIoLocations) / sizeof(ULONG);
+
+ if (*bufferSize < count)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ buffer[i] = PcmciaIoLocations[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 - MadgePcmciaQueryParameterNameHandler
+*
+* 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
+MadgePcmciaQueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/********* End of MDGPCMC.C ************************************************/
+
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 *************************************************/
+
diff --git a/private/ntos/ndis/madge/detect/mdgsm16.c b/private/ntos/ndis/madge/detect/mdgsm16.c
new file mode 100644
index 000000000..bbaabc051
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgsm16.c
@@ -0,0 +1,1495 @@
+/****************************************************************************
+*
+* MDGSM16.C
+*
+* Smart 16 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 12/09/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_SM16 1000
+
+
+/*---------------------------------------------------------------------------
+|
+| IO locations that Smart16 adapters can be at. The second for are
+| REV3 only locations that are normally specified as one of the first
+| four locations with the ALTERNATE flag set.
+|
+---------------------------------------------------------------------------*/
+
+static
+ULONG Sm16IoLocations[4] =
+ {0x4a20, 0x4e20, 0x6a20, 0x6e20};
+
+
+/*---------------------------------------------------------------------------
+|
+| Various Smart16 card specific constants.
+|
+---------------------------------------------------------------------------*/
+
+#define SM16_IO_RANGE 32
+
+#define SM16_CONTROL_REGISTER_1 0
+#define SM16_CONTROL_REGISTER_2 8
+
+
+/*---------------------------------------------------------------------------
+|
+| 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_SM16,
+ MDGSM16,
+ L"Madge Smart 16 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,
+ 901
+ }
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| 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[4];
+ ULONG DmaRange[2];
+}
+ParamRange[] =
+{
+ //
+ // Smart16.
+ //
+
+ {
+ { 3, 2, 7, END_OF_LIST},
+ { 0, END_OF_LIST}
+ }
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure for holding state of a search.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ ULONG IoLocationIndex;
+}
+SM16_SEARCH_STATE;
+
+
+/*---------------------------------------------------------------------------
+|
+| This is an array of search states. We need one state for each type
+| of adapter supported.
+|
+|--------------------------------------------------------------------------*/
+
+static
+SM16_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;
+}
+SM16_ADAPTER;
+
+
+/*---------------------------------------------------------------------------
+|
+| 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.
+|
+| Purpose - Check to see if an Madge Smart16 card is at the specified
+| IO location.
+|
+| Returns - A card type.
+|
+---------------------------------------------------------------------------*/
+
+static ULONG
+CheckForCard(
+ ULONG busNumber,
+ INTERFACE_TYPE interface,
+ ULONG ioLocation
+ )
+{
+ UCHAR byte;
+ ULONG dword;
+ UINT i;
+ UINT j;
+
+ MadgePrint2("CheckForCard (ioLocation=%04lx)\n", ioLocation);
+
+ //
+ // First check that the IO range is not in use by some other
+ // device.
+ //
+
+ if (DetectCheckPortUsage(
+ interface,
+ busNumber,
+ ioLocation,
+ SM16_IO_RANGE
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ MadgePrint1("CheckForCard: DetectCheckPortUsage() OK\n");
+
+ //
+ // Now we must reset the adapter (if it's there).
+ //
+
+ if (DetectWritePortUchar(
+ interface,
+ busNumber,
+ ioLocation + SM16_CONTROL_REGISTER_1,
+ 0
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ MadgePrint1("CheckForCard: Reset Smart16 OK\n");
+
+ //
+ // Now read and check the node address. The Smart16 does not store
+ // the two leading 0 bytes of the address so we can only really
+ // check the 0xf6; but we read the whole node address to make sure
+ // we can.
+ //
+ // The node address is stored in some wierd sort of EEPROM that
+ // is read by writing a byte number into control register 2 and
+ // then reading the bits of the byte in pairs from IO locations
+ // 8 appart. i.e. bits 7 and 6 come from the base IO location,
+ // bits 5 and 4 from the base IO location plus 8 and so on.
+ //
+
+ dword = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (DetectWritePortUchar(
+ interface,
+ busNumber,
+ ioLocation + SM16_CONTROL_REGISTER_2,
+ (UCHAR) i) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ if (DetectReadPortUchar(
+ interface,
+ busNumber,
+ ioLocation + j * 8,
+ &byte
+ ) != STATUS_SUCCESS)
+ {
+ return SMART_NONE;
+ }
+
+ dword = (dword << 2) | (byte & 0x03);
+ }
+ }
+
+ MadgePrint2("CheckForCard: node address = %lx\n", dword);
+
+ //
+ // Check that the first byte of the node address read is
+ // correct for a Madge adapter. We also check that the rest
+ // of the address isn't all 1s or all 0s just to be on the
+ // safe side.
+ //
+
+ if (((dword >> 24) & 0x000000ffL) != MadgeNodeAddressPrefix[2] ||
+ (dword & 0x00ffffffL) == 0x00ffffffL ||
+ (dword & 0x00ffffffL) == 0x00000000L)
+ {
+ return SMART_NONE;
+ }
+
+ MadgePrint1("CheckForCard: Read node address OK\n");
+
+ //
+ // If we make it here we're as sure as we're ever going to be that
+ // we've found a Smart16 adapter.
+
+ return SMART_SM16;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - FindSm16Card
+|
+| 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 FindSm16Card was called.
+|
+| Returns - A WINERROR.H error code.
+|
+|--------------------------------------------------------------------------*/
+
+static ULONG
+FindSm16Card(
+ 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(Sm16IoLocations) / sizeof(ULONG))
+ {
+ if (!MadgeCardAlreadyInstalled(
+ FALSE,
+ busNumber,
+ Sm16IoLocations[SearchStates[adapterNumber].IoLocationIndex]
+ ))
+ {
+ if (CheckForCard(
+ busNumber,
+ interface,
+ Sm16IoLocations[SearchStates[adapterNumber].IoLocationIndex]
+ ) == type)
+ {
+ *confidence = 100;
+ break;
+ }
+ }
+
+ SearchStates[adapterNumber].IoLocationIndex++;
+ }
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeSm16IdentifyHandler
+*
+* 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
+MadgeSm16IdentifyHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ LONG numberOfAdapters;
+ LONG action;
+ LONG length;
+ LONG i;
+
+ MadgePrint2("MadgeSm16IdentifyHandler (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 - MadgeSm16FirstNextHandler
+*
+* 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
+MadgeSm16FirstNextHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ BOOL first,
+ VOID * * token,
+ LONG * confidence
+ )
+{
+ LONG adapterNumber;
+ ULONG retCode;
+
+ MadgePrint2("MadgeSm16FirstNextHandler (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 = FindSm16Card(
+ (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 - MadgeSm16OpenHandleHandler
+*
+* 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
+MadgeSm16OpenHandleHandler(
+ VOID * token,
+ VOID * * handle
+ )
+{
+ SM16_ADAPTER * adapter;
+ ULONG adapterNumber;
+ ULONG busNumber;
+ INTERFACE_TYPE interface;
+
+ MadgePrint1("MadgeSm16OpenHandleHandler\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 = (SM16_ADAPTER *) DetectAllocateHeap(sizeof(SM16_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 =
+ Sm16IoLocations[SearchStates[adapterNumber].IoLocationIndex];
+ adapter->Dma = 0; // Smart16's are always in PIO mode.
+ adapter->Irq = RESOURCE_UNKNOWN;
+
+ *handle = (VOID *) adapter;
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeSm16CreateHandleHandler
+*
+* 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
+MadgeSm16CreateHandleHandler(
+ LONG index,
+ INTERFACE_TYPE interface,
+ ULONG busNumber,
+ VOID * * handle
+ )
+{
+ SM16_ADAPTER * adapter;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgeSm16CreateHandleHandler (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 = (SM16_ADAPTER *) DetectAllocateHeap(sizeof(SM16_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 = Sm16IoLocations[0];
+ adapter->Dma = 0; // Smart16'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 - MadgeSm16CloseHandleHandler
+*
+* Parameters - handle -> Handle to be closed.
+*
+* Purpose - Closes a previously opened or created handle.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+MadgeSm16CloseHandleHandler(
+ VOID * handle
+ )
+{
+ MadgePrint1("MadgeSm16CloseHandleHandler\n");
+
+ DetectFreeHeap(handle);
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeSm16QueryCfgHandler
+*
+* 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
+MadgeSm16QueryCfgHandler(
+ VOID * handle,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ SM16_ADAPTER * adapter;
+ ULONG confidence;
+ LONG adapterNumber;
+ LONG retCode;
+
+ MadgePrint1("MadgeSm16QueryCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (SM16_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 = FindSm16Card(
+ 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 =
+ Sm16IoLocations[SearchStates[adapterNumber].IoLocationIndex];
+ adapter->Dma = 0; // Smart16's are always in PIO mode.
+ adapter->Irq = RESOURCE_UNKNOWN;
+ }
+
+ //
+ // 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 - MadgeSm16VerifyCfgHandler
+*
+* 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
+MadgeSm16VerifyCfgHandler(
+ VOID * handle,
+ WCHAR * buffer
+ )
+{
+ SM16_ADAPTER * adapter;
+ WCHAR * place;
+ BOOLEAN found;
+ ULONG ioLocation;
+ ULONG dmaChannel;
+ ULONG irqNumber;
+ ULONG multiprocessor;
+ LONG adapterNumber;
+
+ MadgePrint1("MadgeSm16VerifyCfgHandler\n");
+
+ //
+ // Do some initialisation.
+ //
+
+ adapter = (SM16_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->CardType)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ adapter->IoLocation = ioLocation;
+ adapter->Dma = 0; // Smart16's are always in PIO mode.
+ adapter->Irq = RESOURCE_UNKNOWN;
+ 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 - MadgeSm16QueryMaskHandler
+*
+* 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
+MadgeSm16QueryMaskHandler(
+ LONG index,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ WCHAR * params;
+ LONG length;
+ LONG numberOfAdapters;
+ LONG i;
+
+ MadgePrint2("MadgeSm16QueryMaskHandler (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 - MadgeSm16ParamRangeHandler
+*
+* 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
+MadgeSm16ParamRangeHandler(
+ LONG index,
+ WCHAR * param,
+ LONG * buffer,
+ LONG * bufferSize
+ )
+{
+ LONG i;
+ LONG adapterNumber;
+ LONG count;
+
+ MadgePrint2("MadgeSm16ParamRangeHandler (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(Sm16IoLocations) / sizeof(ULONG);
+
+ if (*bufferSize < count)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ buffer[i] = Sm16IoLocations[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 - MadgeSm16QueryParameterNameHandler
+*
+* 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
+MadgeSm16QueryParameterNameHandler(
+ WCHAR * param,
+ WCHAR * buffer,
+ LONG bufferSize
+ )
+{
+ return ERROR_INVALID_PARAMETER;
+}
+
+
+/********* End of MDGSM16.C ************************************************/
+
diff --git a/private/ntos/ndis/madge/detect/mdgutils.c b/private/ntos/ndis/madge/detect/mdgutils.c
new file mode 100644
index 000000000..9ee0cdec4
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/mdgutils.c
@@ -0,0 +1,1599 @@
+/****************************************************************************
+*
+* MDGUTILS.C
+*
+* Adapter Detection DLL Utility Functions
+*
+* 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 19/08/1994
+* Derived initially from the DTAUX.C DDK sample.
+*
+****************************************************************************/
+
+#include <ntddk.h>
+#include <ntddnetd.h>
+#include <windef.h>
+#include <winerror.h>
+
+//
+// Prototype "borrowed" from WINUSER.H
+//
+
+extern int WINAPIV wsprintfW(LPWSTR, LPCWSTR, ...);
+
+
+/*---------------------------------------------------------------------------
+|
+| Define API decoration for direct importing of DLL references.
+|
+---------------------------------------------------------------------------*/
+
+#if !defined(_ADVAPI32_)
+#define WINADVAPI DECLSPEC_IMPORT
+#else
+#define WINADVAPI
+#endif
+
+
+/*---------------------------------------------------------------------------
+|
+| FUDGE the definition of LPSECURITY_ATTRIBUTES.
+|
+|--------------------------------------------------------------------------*/
+
+typedef void * LPSECURITY_ATTRIBUTES;
+
+
+/*---------------------------------------------------------------------------
+|
+| File System time stamps are represented with the following structure.
+|
+---------------------------------------------------------------------------*/
+
+typedef struct _FILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+}
+FILETIME, *PFILETIME, *LPFILETIME;
+
+
+//
+// These includes require the typedefs above.
+//
+
+#include <winreg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "mdgncdet.h"
+
+
+/*---------------------------------------------------------------------------
+|
+| Maximum size of the bus information that can be extracted from the
+| registry.
+|
+---------------------------------------------------------------------------*/
+
+#define MAX_BUS_INFO_SIZE 16384
+
+
+/*---------------------------------------------------------------------------
+|
+| Registry key strings.
+|
+---------------------------------------------------------------------------*/
+
+static PSTR BusTypeBase = "Hardware\\Description\\System\\";
+static PSTR ConfigData = "Configuration Data";
+static PSTR MicroChanTypeName = "MultifunctionAdapter";
+static PSTR EisaTypeName = "EisaAdapter";
+static PSTR PcmciaTypeName = "PCMCIA PCCARDs";
+
+static PSTR NetworkCardsBase =
+ "Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
+static PSTR ServiceName = "ServiceName";
+static PSTR ManufacturerName = "Manufacturer";
+static PSTR MadgeName = "Madge";
+static PSTR DriverName = "mdgmport";
+static PSTR ServicesBase = "System\\CurrentControlSet\\Services\\";
+static PSTR ParametersName = "\\Parameters";
+static PSTR SlotNumberName = "SlotNumber";
+static PSTR IoLocationName = "IoLocation";
+static PSTR BusNumberName = "BusNumber";
+
+static PSTR ProcessorsBase =
+ "Hardware\\Description\\System\\CentralProcessor";
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - GetBusTypeKey
+|
+| Parameters - busNumber -> Number of the bus we're interested in.
+| busTypeName -> The name of the bus type.
+| interfaceType -> The NT interface type of the bus.
+| infoHandle -> Pointer to a holder for a pointer to
+| a returned bus information structure.
+|
+| Purpose - Extract the information about a bus from the registry.
+|
+| Returns - TRUE on success or FALSE on failure.
+|
+---------------------------------------------------------------------------*/
+
+static BOOLEAN
+GetBusTypeKey(
+ ULONG busNumber,
+ const CHAR * busTypeName,
+ INT interfaceType,
+ VOID * * infoHandle
+ )
+{
+ CHAR busTypePath[MAX_PATH];
+ UCHAR * bufferPointer;
+ char subkeyName[MAX_PATH];
+ PCM_FULL_RESOURCE_DESCRIPTOR fullResource;
+ HKEY busTypeHandle;
+ HKEY busHandle;
+ FILETIME lastWrite;
+ ULONG index;
+ DWORD type;
+ DWORD bufferSize;
+ DWORD nameSize;
+ LONG err;
+ BOOL result;
+
+ //
+ // Do some initialisation.
+ //
+
+ bufferPointer = NULL;
+ busTypeHandle = NULL;
+ busHandle = NULL;
+ result = FALSE;
+ *infoHandle = NULL;
+
+ //
+ // Can only deal with 98 busses.
+ //
+
+ if (busNumber > 98)
+ {
+ return FALSE;
+ }
+
+ //
+ // Open the root of the registry section for our bus type.
+ //
+
+ strcpy(busTypePath, BusTypeBase) ;
+ strcat(busTypePath, busTypeName);
+
+ err = RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ busTypePath,
+ 0,
+ KEY_READ,
+ &busTypeHandle
+ );
+
+ if (err != NO_ERROR)
+ {
+ return FALSE;
+ }
+
+ //
+ // Search through the entries in our bus section of the registry looking
+ // for an entry whose Configuration Data sub-entry is for our
+ // interface type and bus number.
+ //
+
+ for (index = 0; !result; index++)
+ {
+ //
+ // If we have already allocated a buffer for some registry
+ // data then trash it.
+ //
+
+ if (bufferPointer != NULL)
+ {
+ free(bufferPointer);
+ bufferPointer = NULL;
+ }
+
+ //
+ // If we have already opened a registry key for an individual
+ // bus then close it.
+ //
+
+ if (busHandle != NULL)
+ {
+ RegCloseKey(busHandle);
+ busHandle = NULL ;
+ }
+
+ //
+ // Enumerate through keys, searching for the proper bus number
+ //
+
+ nameSize = sizeof(subkeyName);
+
+ err = RegEnumKeyExA(
+ busTypeHandle,
+ index,
+ subkeyName,
+ &nameSize,
+ 0,
+ NULL,
+ 0,
+ &lastWrite
+ );
+
+ if (err != NO_ERROR)
+ {
+ break;
+ }
+
+ //
+ // Open the BusType root + Bus Number.
+ //
+
+ err = RegOpenKeyExA(
+ busTypeHandle,
+ subkeyName,
+ 0,
+ KEY_READ,
+ &busHandle
+ );
+
+ if (err != NO_ERROR)
+ {
+ continue;
+ }
+
+ //
+ // Get some memory for the bus information.
+ //
+
+ bufferSize = MAX_BUS_INFO_SIZE;
+ bufferPointer = (UCHAR *) malloc(bufferSize) ;
+
+ if (bufferPointer == NULL)
+ {
+ break;
+ }
+
+ //
+ // Get the configuration data for this bus instance.
+ //
+
+ err = RegQueryValueExA(
+ busHandle,
+ ConfigData,
+ NULL,
+ &type,
+ bufferPointer,
+ &bufferSize
+ );
+
+ if (err != NO_ERROR)
+ {
+ break;
+ }
+
+ //
+ // Check for our bus number and type.
+ //
+
+ fullResource = (PCM_FULL_RESOURCE_DESCRIPTOR) bufferPointer;
+
+ result = fullResource->InterfaceType == interfaceType &&
+ fullResource->BusNumber == busNumber;
+ }
+
+ //
+ // Close any open registry handles.
+ //
+
+ if (busTypeHandle != NULL)
+ {
+ RegCloseKey(busTypeHandle);
+ }
+
+ if (busHandle != NULL)
+ {
+ RegCloseKey(busHandle);
+ }
+
+ //
+ // If we were successful then pass a pointer to the bus information
+ // back to the caller.
+ //
+
+ if (result)
+ {
+ *infoHandle = bufferPointer ;
+ }
+
+ //
+ // If not then free any memory.
+ //
+
+ else if (bufferPointer != NULL)
+ {
+ free(bufferPointer);
+ }
+
+ return result;
+}
+
+
+/****************************************************************************
+*
+* Function - GetMcaKey
+*
+* Parameters - busNumber -> Number of the bus we're interested in.
+* infoHandle -> Pointer to a holder for a pointer to
+* a returned bus information structure.
+*
+* Purpose - Extract the information about a microchannel bus from
+* the registry.
+*
+* Returns - TRUE on success or FALSE on failure.
+*
+****************************************************************************/
+
+BOOLEAN
+GetMcaKey(
+ ULONG busNumber,
+ VOID * * infoHandle
+ )
+{
+ return GetBusTypeKey(
+ busNumber,
+ MicroChanTypeName,
+ MicroChannel,
+ infoHandle
+ );
+}
+
+
+/****************************************************************************
+*
+* Function - GetMcaPosId
+*
+* Parameters - infoHandle -> Pointer to the bus information for an
+* MCA bus.
+* slotNumber -> The slot number to read.
+* posId -> A pointer to a holder for the pos ID read.
+*
+* Purpose - Read the pos id for a slot from the bus information of
+* an MCA bus.
+*
+* Returns - TRUE on success or FALSE on failure.
+*
+****************************************************************************/
+
+BOOLEAN
+GetMcaPosId(
+ VOID * infoHandle,
+ ULONG slotNumber,
+ ULONG * posId
+ )
+{
+ PCM_FULL_RESOURCE_DESCRIPTOR fullResource;
+ PCM_PARTIAL_RESOURCE_LIST resourceList;
+ ULONG i;
+ ULONG totalSlots;
+ PCM_MCA_POS_DATA posData;
+
+ fullResource = (PCM_FULL_RESOURCE_DESCRIPTOR) infoHandle;
+ resourceList = &fullResource->PartialResourceList;
+
+ //
+ // Find the device-specific information, which is where the POS data is.
+ //
+
+ for (i = 0; i < resourceList->Count; i++)
+ {
+ if (resourceList->PartialDescriptors[i].Type == CmResourceTypeDeviceSpecific)
+ {
+ break;
+ }
+ }
+
+ if (i == resourceList->Count)
+ {
+ //
+ // Couldn't find device-specific information.
+ //
+
+ return FALSE;
+ }
+
+ //
+ // Now examine the device specific data.
+ //
+
+ totalSlots = resourceList->PartialDescriptors[i].u.DeviceSpecificData.DataSize;
+ totalSlots = totalSlots / sizeof(CM_MCA_POS_DATA);
+
+ if (slotNumber <= totalSlots)
+ {
+ posData = (PCM_MCA_POS_DATA) (&resourceList->PartialDescriptors[i + 1]);
+ posData += slotNumber - 1;
+
+ *posId = posData->AdapterId;
+
+ return TRUE;
+ }
+
+ //
+ // If we make it here there wasn't any pos data for the specified slot.
+ //
+
+ return FALSE;
+}
+
+
+/****************************************************************************
+*
+* Function - DeleteMcaKey
+*
+* Parameters - infoHandle -> Pointer to a bus information structure.
+*
+* Purpose - Free the memory associated with a bus information
+* structure prevously returned by GetMcaKey.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+DeleteMcaKey(
+ VOID * infoHandle
+ )
+{
+ free(infoHandle) ;
+}
+
+
+/****************************************************************************
+*
+* Function - GetEisaKey
+*
+* Parameters - busNumber -> Number of the bus we're interested in.
+* infoHandle -> Pointer to a holder for a pointer to
+* a returned bus information structure.
+*
+* Purpose - Extract the information about an EISA bus from
+* the registry.
+*
+* Returns - TRUE on success or FALSE on failure.
+*
+****************************************************************************/
+
+BOOLEAN
+GetEisaKey(
+ ULONG busNumber,
+ VOID * * infoHandle
+ )
+{
+ return GetBusTypeKey(
+ busNumber,
+ EisaTypeName,
+ Eisa,
+ infoHandle
+ );
+}
+
+
+/****************************************************************************
+*
+* Function - GetEisaCompressedId
+*
+* Parameters - infoHandle -> Pointer to the bus information for an
+* EISA bus.
+* slotNumber -> The slot number to read.
+* compressedId -> A pointer to a holder for the compressed
+* ID read.
+*
+* Purpose - Read the compressed id for a slot from the bus information
+* of an EISA bus.
+*
+* Returns - TRUE on success or FALSE on failure.
+*
+****************************************************************************/
+
+BOOLEAN
+GetEisaCompressedId(
+ VOID * infoHandle,
+ ULONG slotNumber,
+ ULONG * compressedId
+ )
+{
+ PCM_FULL_RESOURCE_DESCRIPTOR fullResource;
+ PCM_PARTIAL_RESOURCE_LIST resourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor;
+ ULONG i;
+ ULONG totalDataSize;
+ ULONG slotDataSize;
+ PCM_EISA_SLOT_INFORMATION slotInformation;
+
+ fullResource = (PCM_FULL_RESOURCE_DESCRIPTOR) infoHandle;
+ resourceList = &fullResource->PartialResourceList;
+
+ //
+ // Find the device-specific information, which is where the slot data is.
+ //
+
+ for (i = 0; i < resourceList->Count; i++)
+ {
+ if (resourceList->PartialDescriptors[i].Type == CmResourceTypeDeviceSpecific)
+ {
+ break;
+ }
+ }
+
+ if (i == resourceList->Count)
+ {
+ //
+ // Couldn't find device-specific information.
+ //
+
+ return FALSE;
+ }
+
+ //
+ // Now examine the device specific data.
+ //
+
+ resourceDescriptor = &(resourceList->PartialDescriptors[i]);
+ totalDataSize = resourceDescriptor->u.DeviceSpecificData.DataSize;
+
+ slotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((UCHAR *) resourceDescriptor +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ //
+ // Iterate through the slot list until we reach our slot number.
+ //
+
+ while (((LONG) totalDataSize) > 0)
+ {
+ if (slotInformation->ReturnCode == EISA_EMPTY_SLOT)
+ {
+ slotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+ }
+ else
+ {
+ slotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ slotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (slotDataSize > totalDataSize)
+ {
+ //
+ // Something is wrong.
+ //
+
+ return FALSE;
+ }
+
+ //
+ // If we haven't reached our slot yet then advance one slot.
+ //
+
+ if (slotNumber > 0)
+ {
+ slotNumber--;
+
+ slotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR) slotInformation + slotDataSize);
+
+ totalDataSize -= slotDataSize;
+
+ continue;
+ }
+
+ //
+ // This is our slot.
+ //
+
+ break;
+ }
+
+ //
+ // Check that we have really found a slot.
+ //
+
+ if (slotNumber != 0 || totalDataSize == 0)
+ {
+ return FALSE;
+ }
+
+ //
+ // If we make it here we have found a valid slot list entry
+ // for our slot number.
+ //
+
+ *compressedId = slotInformation->CompressedId & 0x00FFFFFF;
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* Function - DeleteEisaKey
+*
+* Parameters - infoHandle -> Pointer to a bus information structure.
+*
+* Purpose - Free the memory associated with a bus information
+* structure prevously returned by GetEisaKey.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+DeleteEisaKey(
+ VOID * infoHandle
+ )
+{
+ free(infoHandle);
+}
+
+
+/****************************************************************************
+*
+* Function - CheckForPcmciaCard
+*
+* Parameters - ioLocation -> Pointer to a holder for the IO location.
+* irqNumber -> Pointer to a holder for the IRQ number.
+*
+* Purpose - Check for PCMCIA entry for Madge card in the registry.
+*
+* Returns - TRUE if there is an entry, FALSE otherwise.
+*
+****************************************************************************/
+
+BOOLEAN
+CheckForPcmciaCard(
+ ULONG * ioLocation,
+ ULONG * irqNumber
+ )
+{
+ CHAR busTypePath[MAX_PATH];
+ UCHAR * bufferPointer;
+ PCM_FULL_RESOURCE_DESCRIPTOR fullResource;
+ PCM_PARTIAL_RESOURCE_LIST resList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR resDesc;
+ HKEY busTypeHandle;
+ DWORD type;
+ DWORD bufferSize;
+ LONG err;
+ BOOL result;
+ UINT i;
+
+ //
+ // Do some initialisation.
+ //
+
+ bufferPointer = NULL;
+ busTypeHandle = NULL;
+ result = FALSE;
+ *ioLocation = RESOURCE_UNKNOWN;
+ *irqNumber = RESOURCE_UNKNOWN;
+
+ //
+ // Open the root of the registry section for PCMCIA cards.
+ //
+
+ strcpy(busTypePath, BusTypeBase) ;
+ strcat(busTypePath, PcmciaTypeName);
+
+ err = RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ busTypePath,
+ 0,
+ KEY_READ,
+ &busTypeHandle
+ );
+
+ if (err != NO_ERROR)
+ {
+ MadgePrint1("RegOpenKeyExA failed\n");
+ return FALSE;
+ }
+
+ //
+ // Query the entry for 'mdgmport.' If this works then there must be
+ // a Madge PCMCIA card present.
+ //
+
+ //
+ // Get some memory for the bus information.
+ //
+
+ bufferSize = MAX_BUS_INFO_SIZE;
+ bufferPointer = (UCHAR *) malloc(bufferSize) ;
+
+ if (bufferPointer == NULL)
+ {
+ return FALSE;
+ }
+
+ //
+ // Get the configuration data for Madge PCMCIA card.
+ //
+
+ err = RegQueryValueExA(
+ busTypeHandle,
+ DriverName,
+ NULL,
+ &type,
+ bufferPointer,
+ &bufferSize
+ );
+
+ if (err != NO_ERROR)
+ {
+ MadgePrint1("RegQueryValueExA failed\n");
+ result = FALSE;
+ }
+ else
+ {
+ MadgePrint1("RegQueryValueExA succeeded\n");
+ result = TRUE;
+ }
+
+ //
+ // Now look at the returned resource list to find our
+ // IO location and IRQ number.
+ //
+
+ if (result)
+ {
+ fullResource = (PCM_FULL_RESOURCE_DESCRIPTOR) bufferPointer;
+ resList = &fullResource->PartialResourceList;
+
+ for (i = 0; i < resList->Count; i++)
+ {
+ resDesc = &resList->PartialDescriptors[i];
+
+ switch (resDesc->Type)
+ {
+ case CmResourceTypeInterrupt:
+
+ *irqNumber = (ULONG) resDesc->u.Interrupt.Vector;
+ break;
+
+ case CmResourceTypePort:
+
+ *ioLocation = (ULONG) resDesc->u.Port.Start.LowPart;
+ break;
+ }
+ }
+
+ MadgePrint2("IO Location = %x\n", *ioLocation);
+ MadgePrint2("IRQ Number = %d\n", *irqNumber);
+ }
+
+ //
+ // Close any open registry handles.
+ //
+
+ RegCloseKey(busTypeHandle);
+
+ //
+ // Free memory used for query. We don't pass anything back since the
+ // data would mean very little. A PCMCIA card is programmed with what-
+ // ever values the user chooses. There isn't really a concept of reading
+ // the cofiguration information from the card.
+ //
+
+ free(bufferPointer);
+
+ return result;
+}
+
+
+/****************************************************************************
+*
+* Function - UnicodeStrLen
+*
+* Parameters - string -> A unicode string.
+*
+* Purpose - Determine the length of a unicode string.
+*
+* Returns - The length of string.
+*
+****************************************************************************/
+
+ULONG
+UnicodeStrLen(WCHAR * string)
+{
+ ULONG length;
+
+ length = 0;
+
+ while (string[length] != L'\0')
+ {
+ length++;
+ }
+
+ return length;
+}
+
+
+/****************************************************************************
+*
+* Function - FindParameterString
+*
+* Parameters - string1 -> A unicode parameter list string to be searched.
+* string2 -> A unicode string to be searched for.
+*
+* Purpose - Search string1 for string2 and return a pointer to
+* the place in string1 where string2 starts.
+*
+* Returns - A pointer to the start of string2 in string1 or NULL.
+*
+****************************************************************************/
+
+WCHAR *
+FindParameterString(
+ WCHAR * string1,
+ WCHAR * string2
+ )
+{
+ ULONG length1;
+ ULONG length2;
+ WCHAR * place;
+
+ //
+ // Do some initialisation.
+ //
+
+ place = string1;
+ length2 = UnicodeStrLen(string2) + 1;
+ length1 = UnicodeStrLen(string1) + 1;
+
+ //
+ // While there's more than the last NULL left look for
+ // string2.
+ //
+
+ while (length1 > 1)
+ {
+ //
+ // Are these the same?
+ //
+
+ if (memcmp(place, string2, length2 * sizeof(WCHAR)) == 0)
+ {
+ return place;
+ }
+
+ place = place + length1;
+ length1 = UnicodeStrLen(place) + 1;
+
+ }
+
+ return NULL;
+}
+
+
+/****************************************************************************
+*
+* Function - ScanForNumber
+*
+* Parameters - place -> A unicode string to search for a number.
+* value -> Pointer to holder for the number found.
+* found -> Pointer to a flag that indicates if we
+* found a number.
+*
+* Purpose - Search the unicode string that starts a place for
+* a number.
+*
+* Returns - Nothing. *found indicates if a number was found.
+*
+****************************************************************************/
+
+VOID
+ScanForNumber(
+ WCHAR * place,
+ ULONG * value,
+ BOOLEAN * found
+ )
+{
+ ULONG tmp;
+
+ *value = 0;
+ *found = FALSE;
+
+ //
+ // Skip leading blanks.
+ //
+
+ while (*place == L' ')
+ {
+ place++;
+ }
+
+ //
+ // Is this a hex number?
+ //
+
+ if ((place[0] == L'0') && (place[1] == L'x'))
+ {
+ //
+ // Yes, parse it as a hex number.
+ //
+
+ *found = TRUE;
+
+ //
+ // Skip leading '0x'.
+ //
+
+ place += 2;
+
+ //
+ // Convert a hex number.
+ //
+
+ for (;;)
+ {
+ if ((*place >= L'0') && (*place <= L'9'))
+ {
+ tmp = ((ULONG) *place) - ((ULONG) L'0');
+ }
+ else
+ {
+ switch (*place)
+ {
+ case L'a':
+ case L'A':
+
+ tmp = 10;
+ break;
+
+ case L'b':
+ case L'B':
+
+ tmp = 11;
+ break;
+
+ case L'c':
+ case L'C':
+
+ tmp = 12;
+ break;
+
+ case L'd':
+ case L'D':
+
+ tmp = 13;
+ break;
+
+ case L'e':
+ case L'E':
+
+ tmp = 14;
+ break;
+
+ case L'f':
+ case L'F':
+
+ tmp = 15;
+ break;
+
+ default:
+
+ return;
+ }
+ }
+
+ (*value) = (*value * 16) + tmp;
+
+ place++;
+ }
+ }
+
+ //
+ // Is it a decimal number?
+ //
+
+ else if ((*place >= L'0') && (*place <= L'9'))
+ {
+ //
+ // Parse it as a decimal number.
+ //
+
+ *found = TRUE;
+
+ //
+ // Convert a decimal number.
+ //
+
+ for (;;)
+ {
+ if ((*place >= L'0') && (*place <= L'9'))
+ {
+ tmp = ((ULONG) *place) - ((ULONG) L'0');
+ }
+ else
+ {
+ return;
+ }
+
+ (*value) *= (*value * 10) + tmp;
+
+ place++;
+ }
+ }
+}
+
+/****************************************************************************
+*
+* Function - DetectAllocateHeap
+*
+* Parameters - size -> Number of bytes of heap required.
+*
+* Purpose - Allocate some heap space.
+*
+* Returns - A pointer to some heap or NULL.
+*
+****************************************************************************/
+
+VOID *
+DetectAllocateHeap(LONG size)
+{
+ VOID * ptr;
+
+ if (size > 0)
+ {
+ ptr = malloc(size);
+
+ if (ptr != NULL)
+ {
+ memset(ptr, 0, size);
+ }
+
+ return ptr;
+ }
+
+ return NULL;
+}
+
+
+/****************************************************************************
+*
+* Function - DetectFreeHeap
+*
+* Parameters - ptr -> A pointer to the start of some heap to free.
+*
+* Purpose - Free some heap space.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+DetectFreeHeap(VOID *ptr)
+{
+ free(ptr);
+}
+
+
+/****************************************************************************
+*
+* Function - AppendParameter
+*
+* Parameters - buffer -> Pointer to pointer buffer to append to.
+* bufferSize -> Pointer to the buffer size.
+* title -> Parameter title.
+* value -> Parameter value.
+*
+* Purpose - Append a parameter's title and value to a buffer. *buffer
+* and *bufferSize are incremented and decremented accordinlgy.
+*
+* Returns - A WINERROR.H error code.
+*
+****************************************************************************/
+
+LONG
+AppendParameter(
+ WCHAR * * buffer,
+ LONG * bufferSize,
+ WCHAR * title,
+ ULONG value
+ )
+{
+ LONG copyLength;
+
+ //
+ // Copy in the title.
+ //
+
+ copyLength = UnicodeStrLen(title)+ 1;
+
+ if (*bufferSize < copyLength)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ memcpy(
+ (VOID *) *buffer,
+ (VOID *) title,
+ (copyLength * sizeof(WCHAR))
+ );
+
+ *buffer += copyLength;
+ *bufferSize -= copyLength;
+
+ //
+ // Copy in the value
+ //
+
+ if (*bufferSize < 8)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ copyLength = wsprintfW(*buffer, L"0x%x", value);
+
+ if (copyLength < 0)
+ {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ copyLength++; // Add in the \0.
+
+ *buffer += copyLength;
+ *bufferSize -= copyLength;
+
+ return NO_ERROR;
+}
+
+
+/****************************************************************************
+*
+* Function - UnicodeStringsEqual
+*
+* Parameters - string1
+* string2 -> Unicode strings to compare.
+*
+* Purpose - Test two unicode strings for equality.
+*
+* Returns - TRUE if the strings are equal and FALSE otherwise.
+*
+****************************************************************************/
+
+BOOLEAN
+UnicodeStringsEqual(
+ WCHAR *string1,
+ WCHAR *string2
+ )
+{
+ while (*string1 != L'\0' && *string1 == *string2)
+ {
+ string1++;
+ string2++;
+ }
+
+ return *string1 == *string2;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeCardAlreadyInstalled
+*
+* Parameters - useSlotNumber -> TRUE if we are to search on slot number or
+* FALSE if we are to search on IO location.
+* busNumber -> The bus number.
+* descriptor -> The slot number or IO location.
+*
+* Purpose - Search the registry to see if a Madge adapter is already
+* installed at the specified slot number or IO location.
+*
+* Returns - TRUE if an adapter is installed or FALSE if not.
+*
+****************************************************************************/
+
+BOOLEAN
+MadgeCardAlreadyInstalled(
+ BOOLEAN useSlotNumber,
+ ULONG busNumber,
+ ULONG descriptor
+ )
+{
+ CHAR driverPath[MAX_PATH];
+ UCHAR buffer[MAX_PATH];
+ char subkeyName[MAX_PATH];
+ HKEY netCardsHandle;
+ HKEY cardHandle;
+ HKEY driverHandle;
+ FILETIME lastWrite;
+ ULONG index;
+ DWORD type;
+ DWORD bufferSize;
+ DWORD nameSize;
+ LONG err;
+ BOOLEAN found;
+ ULONG tempDescriptor;
+ ULONG tempBusNumber;
+
+ //
+ // Do some initialisation.
+ //
+
+ netCardsHandle = NULL;
+ cardHandle = NULL;
+ driverHandle = NULL;
+ found = FALSE;
+
+ //
+ // Open the root of the registry section net cards.
+ //
+
+ err = RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ NetworkCardsBase,
+ 0,
+ KEY_READ,
+ &netCardsHandle
+ );
+
+ if (err != NO_ERROR)
+ {
+ return FALSE;
+ }
+
+ //
+ // Search through the network card entries looking for entries
+ // that are for drivers with manufacturer set to "Madge".
+ //
+
+ for (index = 0; !found; index++)
+ {
+ //
+ // Close any open registry handles.
+ //
+
+ if (cardHandle != NULL)
+ {
+ RegCloseKey(cardHandle);
+ cardHandle = NULL;
+ }
+
+ if (driverHandle != NULL)
+ {
+ RegCloseKey(driverHandle);
+ driverHandle = NULL;
+ }
+
+ //
+ // Enumerate through keys.
+ //
+
+ nameSize = sizeof(subkeyName);
+
+ err = RegEnumKeyExA(
+ netCardsHandle,
+ index,
+ subkeyName,
+ &nameSize,
+ 0,
+ NULL,
+ 0,
+ &lastWrite
+ );
+
+ if (err != NO_ERROR)
+ {
+ break;
+ }
+
+ //
+ // Open the net card key.
+ //
+
+ err = RegOpenKeyExA(
+ netCardsHandle,
+ subkeyName,
+ 0,
+ KEY_READ,
+ &cardHandle
+ );
+
+ if (err != NO_ERROR)
+ {
+ continue;
+ }
+
+ //
+ // Get the manufacturer name and check that it is
+ // "Madge".
+ //
+
+ bufferSize = sizeof(buffer);
+
+ err = RegQueryValueExA(
+ cardHandle,
+ ManufacturerName,
+ NULL,
+ &type,
+ buffer,
+ &bufferSize
+ );
+
+ if (err != NO_ERROR)
+ {
+ continue;
+ }
+
+ if (strcmp(buffer, MadgeName) != 0)
+ {
+ continue;
+ }
+
+ //
+ // Get the driver name.
+ //
+
+ bufferSize = sizeof(buffer);
+
+ err = RegQueryValueExA(
+ cardHandle,
+ ServiceName,
+ NULL,
+ &type,
+ buffer,
+ &bufferSize
+ );
+
+ if (err != NO_ERROR)
+ {
+ continue;
+ }
+
+ //
+ // Open a key for the driver entry under services.
+ //
+
+ strcpy(driverPath, ServicesBase);
+ strcat(driverPath, buffer);
+ strcat(driverPath, ParametersName);
+
+ err = RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ driverPath,
+ 0,
+ KEY_READ,
+ &driverHandle
+ );
+
+ if (err != NO_ERROR)
+ {
+ continue;
+ }
+
+ //
+ // Try and read the slot number or IO location.
+ //
+
+ bufferSize = sizeof(buffer);
+
+ if (useSlotNumber)
+ {
+ err = RegQueryValueExA(
+ driverHandle,
+ SlotNumberName,
+ NULL,
+ &type,
+ buffer,
+ &bufferSize
+ );
+ }
+ else
+ {
+ err = RegQueryValueExA(
+ driverHandle,
+ IoLocationName,
+ NULL,
+ &type,
+ buffer,
+ &bufferSize
+ );
+ }
+
+ if (err != NO_ERROR)
+ {
+ continue;
+ }
+
+ tempDescriptor = (ULONG) *((DWORD *) buffer);
+
+ //
+ // Try and read the bus number.
+ //
+
+ bufferSize = sizeof(buffer);
+
+ err = RegQueryValueExA(
+ driverHandle,
+ BusNumberName,
+ NULL,
+ &type,
+ buffer,
+ &bufferSize
+ );
+
+ if (err != NO_ERROR)
+ {
+ continue;
+ }
+
+ tempBusNumber = (ULONG) *((DWORD *) buffer);
+
+ //
+ // Check to see if we have a match.
+ //
+
+ if (descriptor == tempDescriptor &&
+ busNumber == tempBusNumber)
+ {
+ MadgePrint2("Found Madge adapter at %lx\n", descriptor);
+ found = TRUE;
+ break;
+ }
+ }
+
+ //
+ // Close any open registry handles.
+ //
+
+ if (netCardsHandle != NULL)
+ {
+ RegCloseKey(netCardsHandle);
+ }
+
+ if (cardHandle != NULL)
+ {
+ RegCloseKey(cardHandle);
+ }
+
+ if (driverHandle != NULL)
+ {
+ RegCloseKey(driverHandle);
+ }
+
+ return found;
+}
+
+
+/****************************************************************************
+*
+* Function - IsMultiprocessor
+*
+* Parameters - None.
+*
+* Purpose - Examine the registry to find out if the machine is a
+* multiprocessor.
+*
+* Returns - 0 for a single processor or 1 for a multiprocessor.
+*
+****************************************************************************/
+
+ULONG
+IsMultiprocessor(void)
+{
+ char subkeyName[MAX_PATH];
+ HKEY cpuHandle;
+ FILETIME lastWrite;
+ ULONG count;
+ DWORD nameSize;
+ LONG err;
+
+ //
+ // Open the root of the registry section net cards.
+ //
+
+ err = RegOpenKeyExA(
+ HKEY_LOCAL_MACHINE,
+ ProcessorsBase,
+ 0,
+ KEY_READ,
+ &cpuHandle
+ );
+
+ if (err != NO_ERROR)
+ {
+ return 0;
+ }
+
+ //
+ // Enumerate the processors.
+ //
+
+ count = 0;
+
+ for (;;)
+ {
+ nameSize = sizeof(subkeyName);
+
+ err = RegEnumKeyExA(
+ cpuHandle,
+ count,
+ subkeyName,
+ &nameSize,
+ 0,
+ NULL,
+ 0,
+ &lastWrite
+ );
+
+ if (err != NO_ERROR)
+ {
+ break;
+ }
+
+ count++;
+
+ MadgePrint2("Found a CPU, number %d\n", count);
+ }
+
+ //
+ // Close any open registry handles.
+ //
+
+ RegCloseKey(cpuHandle);
+
+ return (count <= 1) ? 0 : 1;
+}
+
+
+/****************************************************************************
+*
+* Function - IsValueInList
+*
+* Parameters - value -> Value to be checked.
+* list -> Pointer to a list of values.
+*
+* Purpose - Check to see if a value is present in a list of values. The
+* list should be terminated with a value of END_OF_LIST.
+*
+* Returns - TRUE if the value is in the list or FALSE if it is not.
+*
+****************************************************************************/
+
+BOOLEAN
+IsValueInList(
+ ULONG value,
+ ULONG * list
+ )
+{
+ while (*list != END_OF_LIST && *list != value)
+ {
+ list++;
+ }
+
+ return *list == value;
+}
+
+
+/******** End of MDGUTILS.C ************************************************/
diff --git a/private/ntos/ndis/madge/detect/sources b/private/ntos/ndis/madge/detect/sources
new file mode 100644
index 000000000..41b1595da
--- /dev/null
+++ b/private/ntos/ndis/madge/detect/sources
@@ -0,0 +1,47 @@
+!if 0
+
+ Copyright (C) 1992-1995 by Digital Equipment Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the MADGE NDIS3 miniport driver being built
+ and the list of sources files needed to build it.
+ It specifies also the compiler switches specific to this driver
+
+Author:
+
+!endif
+
+TARGETNAME=mdgncdet
+TARGETTYPE=DYNLINK
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\netdtect.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
+
+INCLUDES=..\..\..\inc;$(BASEDIR)\public\sdk\inc
+C_DEFINES=$(C_DEFINES) -DNDIS_NT=1
+USE_CRTDLL=1
+
+DLLBASE=0x1C000000
+DLLENTRY=NcDetectInitialInit
+
+SOURCES=mdgncdet.c \
+ mdgeisa.c \
+ mdgat.c \
+ mdgsm16.c \
+ mdgpnp.c \
+ mdgmc.c \
+ mdgpci.c \
+ mdgpcmc.c \
+ mdgutils.c \
+ mdgncdet.rc
+
+
+
diff --git a/private/ntos/ndis/madge/dirs b/private/ntos/ndis/madge/dirs
new file mode 100644
index 000000000..b934a0f79
--- /dev/null
+++ b/private/ntos/ndis/madge/dirs
@@ -0,0 +1,29 @@
+!IF 0
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ dirs
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=dll \
+ detect \
+ driver
+
+
+
+
diff --git a/private/ntos/ndis/madge/dll/blmadge.ico b/private/ntos/ndis/madge/dll/blmadge.ico
new file mode 100644
index 000000000..df38f5b23
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/blmadge.ico
Binary files differ
diff --git a/private/ntos/ndis/madge/dll/brmadge.ico b/private/ntos/ndis/madge/dll/brmadge.ico
new file mode 100644
index 000000000..1a3a00324
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/brmadge.ico
Binary files differ
diff --git a/private/ntos/ndis/madge/dll/madge.ico b/private/ntos/ndis/madge/dll/madge.ico
new file mode 100644
index 000000000..4958cd770
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/madge.ico
Binary files differ
diff --git a/private/ntos/ndis/madge/dll/makefile b/private/ntos/ndis/madge/dll/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/madge/dll/makefile.inc b/private/ntos/ndis/madge/dll/makefile.inc
new file mode 100644
index 000000000..b4798f5d7
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/makefile.inc
@@ -0,0 +1,5 @@
+mdgmpdlg.hlp: $(TARGETEXEFILES)
+ chmode -r mdgmpdlg.hlp
+ binplace mdgmpdlg.hlp
+ touch mdgmpdlg.hlp
+ chmode +r mdgmpdlg.hlp
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.c b/private/ntos/ndis/madge/dll/mdgmpdlg.c
new file mode 100644
index 000000000..f0f27797f
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.c
@@ -0,0 +1,124 @@
+
+#include <ntddk.h>
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "mdgmpdlg.upd"
+
+typedef int BOOL;
+typedef unsigned long DWORD;
+typedef unsigned char BYTE;
+
+
+//
+// Identification string for MVER.
+//
+
+static char MVerString[] = MVER_STRING;
+
+BOOL
+MadgeLAACheck(DWORD cargs,
+ LPSTR lpszArgs[],
+ LPSTR *lpszTextOut)
+ {
+ /* We are expecting one argument, a node address, and we want to parse */
+ /* it, check it, and return true/false. */
+ /* NB According to the book, the arguments are not Unicode, so we can */
+ /* use old style routines. */
+
+ static char buffer[50] = "";
+ BYTE nodeaddr[6] = { 0, };
+ char ch;
+ int nibbles;
+ int nibble;
+ BOOL hyphens, hyphen;
+
+ *lpszTextOut = buffer;
+
+ if (cargs != 1)
+ {
+ sprintf(buffer, "MadgeLAACheck: too few arguments");
+ return FALSE;
+ }
+
+ /* We have the correct number of arguments, now parse it */
+
+ hyphens = FALSE;
+ hyphen = FALSE;
+ nibbles = 0;
+
+ while (nibbles < 12)
+ {
+ ch = *(lpszArgs[0]++);
+
+ /* First make sure the hyphenation of the node address is correct. */
+ /* We allow either fully hyphenated or not hyphenated, but not a */
+ /* mixture. */
+
+ if ((nibbles % 2) == 0)
+ {
+ if (nibbles == 2)
+ {
+ if (ch == '-' && !hyphen)
+ {
+ hyphens = TRUE;
+ hyphen = TRUE;
+ continue;
+ }
+ }
+ else
+ if (hyphens)
+ if (ch == '-')
+ if (!hyphen)
+ {
+ hyphen = TRUE;
+ continue;
+ }
+ else
+ break;
+ else
+ if (!hyphen)
+ break;
+ }
+ else
+ hyphen = FALSE;
+
+ if (ch >= '0' && ch <= '9')
+ nibble = ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ nibble = ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ nibble = ch - 'a' + 10;
+ else
+ break;
+
+ /* So we've got a valid nibble - now slot it into place */
+
+ nodeaddr[nibbles / 2] |= nibble << (nibbles % 2 ? 0 : 4);
+
+ nibbles++;
+ }
+
+ if ((nibbles != 12) || (*lpszArgs[0] != '\0' && !isspace(*lpszArgs[0])))
+ {
+ sprintf(buffer, "Bad node address. Use xx-xx-xx-xx-xx-xx.");
+ return FALSE;
+ }
+
+ /* We have a valid node address - just check that it is good as a LAA */
+
+ if ((nodeaddr[0] & 0xC0) != 0x40)
+ {
+ sprintf(buffer, "Illegal LAA (first digit must be between 4 and 7)");
+ return FALSE;
+ }
+
+ sprintf(buffer, "MADGE_STATUS_SUCCESS");
+
+ return TRUE;
+ }
+
+/*****************************************************************************/
+/* End of file. */
+/*****************************************************************************/
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.def b/private/ntos/ndis/madge/dll/mdgmpdlg.def
new file mode 100644
index 000000000..f6d51e565
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.def
@@ -0,0 +1,8 @@
+LIBRARY MDGMPDLG
+
+DESCRIPTION 'Madge Installation assist DLL'
+
+EXPORTS
+ MadgeLAACheck
+
+; VERSION 1.02
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.dlg b/private/ntos/ndis/madge/dll/mdgmpdlg.dlg
new file mode 100644
index 000000000..d90541aa0
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.dlg
@@ -0,0 +1,111 @@
+1 DLGINCLUDE "UILSTF.H"
+
+MDGEISA DIALOG PRELOAD 8, 23, 243, 232
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@Caption"
+FONT 8, "MS Shell Dlg"
+CLASS "mydlg"
+BEGIN
+ PUSHBUTTON "@Continue", IDC_C, 19, 202, 40, 14
+ PUSHBUTTON "@Cancel", IDC_X, 99, 202, 40, 14
+ PUSHBUTTON "@Help", IDC_H, 179, 202, 40, 14
+ ICON 102, 200, 183, 119, 16, 16, WS_GROUP
+ ICON 103, 200, 201, 119, 16, 16
+ ICON 104, 200, 201, 101, 16, 16
+ ICON 105, 200, 183, 101, 16, 16
+ EDITTEXT IDC_EDIT1, 67, 83, 96, 12, ES_AUTOHSCROLL
+ LTEXT "@Edit1Label", 205, 3, 83, 50, 8
+ EDITTEXT IDC_EDIT2, 67, 101, 96, 12, ES_AUTOHSCROLL
+ LTEXT "@Edit2Label", 206, 3, 102, 50, 8
+ LTEXT "@Combo4Label", 101, 3, 140, 54, 8
+ COMBOBOX IDC_COMBO4, 66, 139, 96, 50, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@ConsultHelp", 106, 3, 123, 159, 8, NOT WS_GROUP
+ LTEXT "@Combo5Label", 107, 3, 160, 100, 8
+ COMBOBOX IDC_COMBO5, 109, 159, 53, 36, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@Combo7Label", 108, 3, 65, 100, 8
+ COMBOBOX IDC_COMBO7, 110, 64, 53, 32, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_COMBO8, 67, 25, 96, 51, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@Combo8Label", 109, 3, 26, 61, 8
+ LTEXT "@AdapterTitle", 110, 3, 7, 167, 8, NOT WS_GROUP
+ LTEXT "@OldValueTitle", 111, 173, 7, 70, 17, NOT WS_GROUP
+ LTEXT "@OldSlotNumber", 112, 173, 26, 64, 8, NOT WS_GROUP
+ LTEXT "@OldMpFlag", 113, 173, 65, 64, 8, NOT WS_GROUP
+ LTEXT "@Combo3Label", 114, 3, 46, 61, 8
+ COMBOBOX IDC_COMBO3, 67, 45, 96, 51, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@OldDmaChannel", 115, 173, 46, 64, 8
+ LTEXT "@Combo9Label", 116, 3, 180, 55, 8
+ COMBOBOX IDC_COMBO9, 66, 179, 96, 35, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+END
+
+MDGISA DIALOG PRELOAD 13, 23, 243, 244
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "@Caption"
+FONT 8, "MS Shell Dlg"
+CLASS "mydlg"
+BEGIN
+ PUSHBUTTON "@Continue", IDC_C, 19, 220, 40, 14
+ PUSHBUTTON "@Cancel", IDC_X, 99, 220, 40, 14
+ PUSHBUTTON "@Help", IDC_H, 179, 220, 40, 14
+ LTEXT "@Combo2Label", 202, 3, 26, 61, 8
+ COMBOBOX IDC_COMBO2, 67, 25, 96, 45, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@Combo1Label", 203, 3, 48, 60, 8
+ COMBOBOX IDC_COMBO1, 67, 47, 96, 54, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@Combo3Label", 204, 3, 69, 61, 8
+ COMBOBOX IDC_COMBO3, 67, 68, 96, 55, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ ICON 102, 200, 183, 148, 16, 16, WS_GROUP
+ ICON 103, 200, 201, 148, 16, 16
+ ICON 104, 200, 201, 130, 16, 16
+ ICON 105, 200, 183, 130, 16, 16
+ EDITTEXT IDC_EDIT1, 67, 110, 96, 12, ES_AUTOHSCROLL
+ LTEXT "@Edit1Label", 205, 3, 111, 62, 8
+ EDITTEXT IDC_EDIT2, 67, 129, 96, 12, ES_AUTOHSCROLL
+ LTEXT "@Edit2Label", 206, 3, 130, 44, 8
+ LTEXT "@Combo4Label", 301, 3, 161, 57, 8
+ COMBOBOX IDC_COMBO4, 67, 160, 96, 48, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@Combo5Label", 303, 3, 181, 100, 8
+ COMBOBOX IDC_COMBO5, 110, 180, 53, 36, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@Combo7Label", 304, 3, 90, 100, 8
+ COMBOBOX IDC_COMBO7, 110, 89, 53, 36, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "@AdapterTitle", 305, 3, 7, 167, 8, NOT WS_GROUP
+ LTEXT "@ConsultHelp", 306, 3, 146, 160, 8, NOT WS_GROUP
+ LTEXT "@OldValueTitle", 302, 173, 7, 70, 17, NOT WS_GROUP
+ LTEXT "@OldIoLocation", 307, 173, 26, 64, 8, NOT WS_GROUP
+ LTEXT "@OldIrqNumber", 308, 173, 48, 64, 8, NOT WS_GROUP
+ LTEXT "@OldDmaChannel", 309, 173, 69, 64, 8, NOT WS_GROUP
+ LTEXT "@OldMpFlag", 310, 173, 90, 64, 9, NOT WS_GROUP
+ LTEXT "@Combo9Label", 311, 3, 201, 62, 8
+ COMBOBOX IDC_COMBO9, 67, 200, 96, 35, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+END
+
+MDGADAPTERS DIALOG 3, 15, 229, 106
+LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "@Caption"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ PUSHBUTTON "@Continue", IDC_C, 13, 83, 40, 14
+ PUSHBUTTON "@Cancel", IDC_X, 93, 83, 40, 14
+ LTEXT "", 201, 5, 0, 20, 8
+ LTEXT "@Combo6Label", 202, 6, 7, 215, 11
+ ICON 102, 203, 183, 82, 16, 16, WS_GROUP
+ ICON 103, 204, 201, 82, 16, 16
+ ICON 104, 205, 201, 64, 16, 16
+ ICON 105, 206, 183, 64, 16, 16
+ COMBOBOX IDC_COMBO6, 6, 23, 214, 76, CBS_DROPDOWNLIST |
+ CBS_OEMCONVERT | WS_VSCROLL | WS_TABSTOP
+END
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.h b/private/ntos/ndis/madge/dll/mdgmpdlg.h
new file mode 100644
index 000000000..a295b2e68
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.h
@@ -0,0 +1,6 @@
+/* Definitions for the icons in the dialog boxes. */
+
+#define dllicon1 102
+#define dllicon2 103
+#define dllicon3 104
+#define dllicon4 105
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.hlp b/private/ntos/ndis/madge/dll/mdgmpdlg.hlp
new file mode 100644
index 000000000..6a5069858
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.hlp
Binary files differ
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.hpj b/private/ntos/ndis/madge/dll/mdgmpdlg.hpj
new file mode 100644
index 000000000..bd87e3a7e
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.hpj
@@ -0,0 +1,18 @@
+
+[OPTIONS]
+CONTENTS=Contents
+COMPRESS=YES
+TITLE=Madge Smart Ringnode Driver
+
+[FILES]
+mdgmpdlg.rtf
+
+[CONFIG]
+BrowseButtons()
+
+[MAP]
+Contents 6000
+Madge_ISA_Dialog 6001
+Madge_EISA_MCA_Dialog 6002
+Madge_PCI_Dialog 6003
+ \ No newline at end of file
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.rc b/private/ntos/ndis/madge/dll/mdgmpdlg.rc
new file mode 100644
index 000000000..abc16d8da
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.rc
@@ -0,0 +1,36 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#include "mdgmpdlg.upd"
+
+#undef VER_COMPANYNAME_STR
+#undef VER_PRODUCTNAME_STR
+#undef VER_PRODUCTVERSION
+#undef VER_PRODUCTVERSION_STR
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+#define VER_COMPANYNAME_STR "Madge Networks Ltd"
+#define VER_PRODUCTNAME_STR "Madge Networks Smart 16/4 Ringnode Driver"
+#define VER_FILEDESCRIPTION_STR "Madge Installation Dialog"
+#define VER_INTERNALNAME_STR "MdgMPDlg.dll"
+
+#define VER_LEGALCOPYRIGHT_YEARS "1994"
+#define VER_LEGALCOPYRIGHT_STR "Copyright (C) Madge Networks Ltd " VER_LEGALCOPYRIGHT_YEARS
+#define VER_FILEVERSION MADGE_DLL_VERSION
+#define VER_FILEVERSION_STR MADGE_DLL_VERSION_STR
+#define VER_PRODUCTVERSION MADGE_NT_VERSION
+#define VER_PRODUCTVERSION_STR MADGE_NT_VERSION_STR
+
+#include <common.ver>
+
+#include "uilstf.h"
+#include "mdgmpdlg.h"
+
+dllicon4 ICON "tlmadge.ico"
+dllicon1 ICON "blmadge.ico"
+dllicon2 ICON "brmadge.ico"
+dllicon3 ICON "trmadge.ico"
+
+#include "mdgmpdlg.dlg"
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.res b/private/ntos/ndis/madge/dll/mdgmpdlg.res
new file mode 100644
index 000000000..8a2160c4a
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.res
Binary files differ
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.rtf b/private/ntos/ndis/madge/dll/mdgmpdlg.rtf
new file mode 100644
index 000000000..c3277fde8
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.rtf
@@ -0,0 +1,307 @@
+{\rtf1\ansi
+\deff0\deflang1024
+{\fonttbl
+{\f0\froman Times New Roman;}
+{\f1\froman Symbol;}
+{\f2\fswiss Arial;}
+{\f3\froman ;}}
+{\colortbl;
+\red0\green0\blue0;
+\red0\green0\blue255;
+\red0\green255\blue255;
+\red0\green255\blue0;
+\red255\green0\blue255;
+\red255\green0\blue0;
+\red255\green255\blue0;
+\red255\green255\blue255;
+\red0\green0\blue127;
+\red0\green127\blue127;
+\red0\green127\blue0;
+\red127\green0\blue127;
+\red127\green0\blue0;
+\red127\green127\blue0;
+\red127\green127\blue127;
+\red192\green192\blue192;}
+{\stylesheet
+{\s242\tqc\tx4320\tqr\tx8640 \fs20\lang2057 \sbasedon0\snext242 footer;}
+{\s244 \fs16\up6\lang2057 \sbasedon0\snext0 footnote reference;}
+{\s245 \fs20\lang2057 \sbasedon0\snext245 footnote text;}
+{\fs20\lang2057\snext0 Normal;}}
+{\info
+{\author Paul Austin}
+{\creatim\yr1994\mo2\dy9\hr16\min56}
+{\version1}
+{\edmins977}
+{\nofpages0}
+{\nofwords0}
+{\nofchars0}
+{\vern16504}}
+\paperw12240\paperh15840\margl1800\margr1800\margt1440\margb1440\gutter0 \makebackup \sectd
+\pard\plain \keepn \fs20\lang2057
+#{\footnote \pard\plain \s245 \fs20\lang2057 Contents}
+${\footnote \pard\plain \s245 \fs20\lang2057 Contents}
++{\footnote madgehelp:01}
+K{\footnote Contents}
+\pard \keepn \par {\plain\b Madge Smart 16/4 Ringnode NDIS3 Driver Help}
+\par \pard
+\par\plain Help is available on the following topics : \par\par\tx360
+\tab{\uldb Madge Smart 16/4 ISA Ringnode Configuration}{\v Madge_ISA_Dialog}\line
+\tab{\uldb Madge Smart 16/4 EISA and MCA Ringnode Configuration}{\v Madge_EISA_MCA_Dialog}\line
+\tab{\uldb Madge Smart 16/4 PCI Ringnode Configuration}{\v Madge_PCI_Dialog}\line
+\tab{\uldb Locally Administered Addresses}{\v locally_administered_address}\line
+\tab{\uldb Maximum Frame Sizes}{\v max_frame_size}\line
+\tab{\uldb Rx/Tx Buffers}{\v rx_tx_slots}\line
+\tab{\uldb Traffic Statistics Gathering}{\v stats}\line
+\par\pard\page
+#{\footnote \pard\plain \fs20\lang2057 Madge_ISA_Dialog}
+${\footnote \pard\plain \fs20\lang2057 Madge Smart 16/4 ISA Ringnodes Help}
++{\footnote madgehelp:02}
+K{\footnote ISA Bus Cards; AT Bus Cards}
+\keepn\par{\plain\b Madge Smart 16/4 Ringnode ISA Configuration Dialog}
+\par\pard\sb200
+This dialog allows you to configure the Madge Smart 16/4 Ringnode Driver to
+ work with any Madge ISA bus adapters that you have installed.
+ You should set the switches on the cards as directed in the documentation
+ that accompany them, being careful to avoid conflicts with other devices
+ in the system.
+\par
+The driver must then be told how each card has been configured, using
+ this dialog for each one.
+ You must set the {\ul IO Location}{\v io_location}, the {\ul IRQ Level}{\v irq_channel},
+ and the {\ul Transfer method}{\v dma_channel} to match the switch settings on
+ the card.
+ If you have disabled DMA, or the adapter card does not support
+ DMA, then for transfer method select {\i PIO}.
+ Otherwise select the DMA channel for which your adapter is configured.
+\par
+If you chose automatic Smart Ringnode installation then some or all
+ of the settings may have been automatically determined.
+ Settings that have been determined will be shown on the right of the dialog
+ box under the headering "Current hardware settings".
+ Any settings that are not shown as {\i UNKNOWN} should not need changing.
+ Those that are shown as {\i UNKNOWN} must be manually set to match the
+ values set by the switches on the adapter.
+\par
+If the machine you are installing the driver on only has one processor
+ then you should set the {\i Number of processors in PC} value to {\i one}.
+ If the machine is a multi-processor then this value should be set to
+ {\i multiple}.
+\par
+The remaining fields in the dialog are optional and allow modification
+ of the behaviour of the
+ adapter card. The driver will work quite happily if they are not touched,
+ however. For further details, see the following topics :
+\par\tx360\tab{\uldb Maximum Frame Size}{\v max_frame_size}\line
+\tab{\uldb Locally Administered Addresses}{\v locally_administered_address}\line
+\tab{\uldb Rx/Tx Buffers}{\v rx_tx_slots}\line
+\tab{\uldb Traffic Statistics Gathering}{\v stats}
+\par \pard \page
+#{\footnote \pard\plain \s245 \fs20\lang2057 Madge_EISA_MCA_Dialog}
+${\footnote \pard\plain \s245 \fs20\lang2057 Madge Smart 16/4 EISA and MCA Ringnodes Help}
++{\footnote madgehelp:03}
+K{\footnote EISA Bus Cards; MicroChannel Cards; MCA Cards}
+\pard \keepn\par{\plain\b Madge Smart 16/4 Ringnode EISA and MCA Configuration Dialog}
+\par\pard\sb200\tx360
+This dialog allows you to configure the Madge Smart 16/4 Ringnode Driver to
+ work with any Madge EISA bus or Madge MCA bus adapters that you have
+ installed.
+ An EISA or MC adapter is identified by the number of the slot containing
+ the adapter.
+ This should be printed on the back of the machine near where the lobe
+ cable is plugged into the adapter.
+\par
+If you chose automatic Smart Ringnode installation then this
+ setting should have been automatically determined.
+ Settings that have been determined will be shown on the right of the
+ dialog box under the headering "Current hardware settings".
+ Any settings that are not shown as {\i UNKNOWN} should not need changing.
+\par
+If the machine you are installing the driver on only has one processor
+ then you should set the {\i Number of processors in PC} value to {\i one}.
+ If the machine is a multi-processor then this value should be set to
+ {\i multiple}.
+\par
+The remaining fields in the dialog are optional and allow modification
+ of the behaviour of the
+ adapter card. The driver will work quite happily if they are not touched,
+ however. For further details, see the following topics :
+\par\tx360\tab{\uldb Maximum Frame Size}{\v max_frame_size}\line
+\tab{\uldb Locally Administered Addresses}{\v locally_administered_address}\line
+\tab{\uldb Rx/Tx Buffers}{\v rx_tx_slots}\line
+\tab{\uldb Traffic Statistics Gathering}{\v stats}
+\par \pard \page
+#{\footnote \pard\plain \s245 \fs20\lang2057 Madge_PCI_Dialog}
+${\footnote \pard\plain \s245 \fs20\lang2057 Madge Smart 16/4 PCI Ringnodes Help}
++{\footnote madgehelp:04}
+K{\footnote PCI Bus Cards}
+\pard \keepn\par{\plain\b Madge Smart 16/4 Ringnode PCI Configuration Dialog}
+\par\pard\sb200\tx360
+This dialog allows you to configure the Madge Smart 16/4 Ringnode Driver to
+ work with any Madge PCI bus adapters that you have installed.
+ PCI adapters are identified by the {\i PCI Device Number}.
+ This value is assigned to the adapter by the PCI BIOS when the PC is
+ powered up or reset.
+ If you do not have a way of determining the PCI Device Number of your
+ Madge PCI Ringonde(s) (some manufacturer's configuration utilities provide
+ this information) then it is recommended that you set the PCI Device
+ Number setting to {\i UNKNOWN}.
+ If the Madge NDIS3 Miniport driver is installed with the PCI Device Number
+ setting set to {\i UNKNOWN} then when the driver starts it searches for
+ the Madge PCI Ringnode with the lowest PCI Device Number that is not
+ already in use.
+\par
+Many PCs and workstations have numbers marked on their PCI slots and it
+ is common for the PCI Device Numbers assigned to PCI adapters to increase
+ with the slot numbers.
+ (Though it is unlikely that the PCI Device Numbers will be the same as
+ the slot numbers.)
+ Therefore, if the Madge NDIS3 Miniport driver is installed for multiple
+ Madge PCI Ringnodes and all of the PCI Device Numbers are set to
+ {\i UNKNOWN}, it is quite likely that the first installation will be for
+ the Madge PCI Ringnode in the lowest number slot, the second installation
+ for the Madge PCI Ringnode in the second lowest numbered slot and so on.
+\par
+Smart 16/4 PCI Ringnodes support two {\ul Transfer methods}{\v dma_channel}.
+ The extremely high performance MMIO method and the PIO method.
+ Normally you should select {\i MMIO} for the transfer method.
+ However, if you have experienced problems using the MMIO method
+ then select {\i PIO}.
+ (You may experience problems with MMIO in certain PCI PC's or with
+ certain combinations of PCI adapters.)
+\par
+Smart 16/4 PCI Ringnodes (BM) also support
+ two {\ul Transfer methods}{\v dma_channel}.
+ Bus Master DMA and PIO.
+ Normally you should select {\i DMA} for the transfer method.
+\par
+ If the machine you are installing the driver on only has one processor
+ then you should set the {\i Number of processors in PC} value to {\i one}.
+ If the machine is a multi-processor then this value should be set to
+ {\i multiple}.
+\par
+The remaining fields in the dialog are optional and allow modification
+ of the behaviour of the
+ adapter card. The driver will work quite happily if they are not touched,
+ however. For further details, see the following topics :
+\par\tx360\tab{\uldb Maximum Frame Size}{\v max_frame_size}\line
+\tab{\uldb Locally Administered Addresses}{\v locally_administered_address}\line
+\tab{\uldb Rx/Tx Buffers}{\v rx_tx_slots}\line
+\tab{\uldb Traffic Statistics Gathering}{\v stats}
+\par \pard \page
+#{\footnote \pard\plain \fs20\lang2057 max_frame_size}
+${\footnote \pard\plain \fs20\lang2057 Maximum Frame Size}
++{\footnote madgehelp:05}
+K{\footnote Maximum Frame Size; MFS}
+\pard\keepn\par{\plain\b Maximum Frame Size}
+\par\pard
+\sb200\plain
+On a sixteen megabits per second token ring, the adapter card can send and
+ receive frames up to 17839 bytes in length. For many applications this may
+ be too big, so a facility is provided to limit the size of frames sent onto
+ the ring. On a four megabits per second token ring the maximum frame size is
+ nearer four and a half thousand bytes. By default, the driver will use a frame
+ size of 4096 bytes, but you
+ can edit the {\i MaxFrameSize} control to set it to a larger
+ (or indeed smaller) value.
+\par Note that if you set a value which is too big, the software will
+ automatically truncate it, and write an error into the event log that
+ contains as one of the data words the actual maximum frame size.
+\par Note also that if you know how big the frames used by higher
+ layer prototocols are going to be, you should set the driver maximum
+ frame size accordingly to enable it to make more efficient use of its
+ buffer space.
+\par\pard {\plain \lang2057 \page }
+#{\footnote \pard\plain \s245 \fs20\lang2057 locally_administered_address}
+${\footnote \pard\plain \s245 \fs20\lang2057 Locally Administered Address}
++{\footnote madgehelp:06}
+K{\footnote LAA; Locally Adminstered Address}
+\pard\keepn\par{\plain\b Locally Administered Addresses}\par\pard
+\sb200
+Every network adapter card has a unique six byte address encoded in it
+ which it uses in network frames to identify itself. It is possible
+ to override the address that the adapter recognises as its own by
+ setting the {\b Locally Administered Address}.
+ As the name suggests, this is locally administered, and so cannot
+ be guaranteed unique - it is up to the network manager to ensure this.
+\par The {\i LAA} can be set to any six byte value at all, as long
+ as the first digit is somewhere between four and seven (i.e. the
+ first two binary bits of the address must be "01"). Other than that,
+ there are no restrictions on its value.
+ In setting it, it can be entered as either a string of twelve contiguous
+ hexadecimal digits, or it can be entered as a sequence of six pairs
+ of hexadecimal digits separated by "-" (minus) characters\line
+e.g. 40-01-02-03-04-05.
+\par Normally, the {\b LAA} need not be set, but certain pieces of
+ communications software do use this facility.
+\page
+#{\footnote \pard\plain \s245 \fs20\lang2057 rx_tx_slots}
+${\footnote \pard\plain \s245 \fs20\lang2057 Rx/Tx Buffers}
++{\footnote madgehelp:07}
+K{\footnote Rx/Tx Buffers}
+\pard\keepn\par{\plain\b Rx/Tx Buffers}\par\pard
+\sb200
+MdgMPort associates a pool of receive (Rx) and transmit (Tx) buffers with each
+ adapter card installed.
+ The default value of 4 receive buffers and 4 transmit buffers has been
+ chosen to be optimal for a '486' class machine being used as a workstation.
+ If you have a machine that will be used as a server or is a high performance
+ RISC platform then you may wish to increase the number of receive and
+ transmit buffers. However, be warned that increasing the number
+ of buffers increases MdgMPort's use of memory, which may cause problems
+ if there are multiple adapters in the machine.
+\page
+#{\footnote \pard\plain \s245 \fs20\lang2057 stats}
+${\footnote \pard\plain \s245 \fs20\lang2057 Traffic Statistics Gathering}
++{\footnote madgehelp:08}
+K{\footnote Traffic Statistics Gathering}
+\pard\keepn\par{\plain\b Traffic Statistics Gathering}\par\pard
+\sb200
+The Madge NDIS3 Miniport driver can support products that gather statistics on,
+ and analyse network traffic.
+ To enable this support select the "enabled" option.
+ Unfortunately enabling this support results in the computer having to perform
+ much more network processing and performance may be degraded.
+ Madge therefore recommend that unless you must have this support you
+ set the option to "disabled".
+\page
+#{\footnote \pard\plain \fs20\lang2057 io_location}
+\plain The {\i IO Location} specifies the address of a range of I/O ports
+ used to communicate with the adapter card.
+ These must not conflict with any other device in the system, including
+ other network adapter cards.
+\par\page
+#{\footnote \pard\plain \fs20\lang2057 irq_channel}
+\plain The {\i Interrupt Level} is how the adapter card is identified
+ when it interrupts the host.
+ For each Interrupt Level that is in use in the system, there will be a
+ handler to attend to the device's needs.
+\par\page
+#{\footnote \pard\plain \fs20\lang2057 dma_channel}
+\plain The {\i Transfer method} is used to indicate what method
+ an adapter should use to transfer data to and from host memory.
+\par
+ Some adapters support bus master DMA and do not required a specific
+ channel to be identified; in which case {\i DMA} can be specified as the
+ transfer method.
+ Other adapters may support bus master DMA but require a particular
+ DMA channel to be identified.
+ In this case {\i DMA Channel nn} can be specified for the transfer method.
+ {\i nn} is the number of the DMA channel for which the adapter is
+ configured (by switches on older adapters or the DIAG configuration
+ utility on newer adapters).
+\par
+An alternative transfer method is {\i PIO} (Programmed I/O)
+ which causes the card to interrupt the host when it wants to perform
+ a transfer.
+ The host then reads/writes one of the IO Locations repeatedly
+ until the transfer is complete.
+ This transfer method is supported by all adapter types except for
+ EISA and MC.
+ {\i PIO} can be used if an adapter does not support DMA or DMA has been
+ disabled by switches on the adapter or the configuration utility.
+\par
+A final transfer method is {\i MMIO} (Memory Mapped I/O) which is similar
+ to but faster than {\i PIO}.
+\par\page
+}
+ \ No newline at end of file
diff --git a/private/ntos/ndis/madge/dll/mdgmpdlg.upd b/private/ntos/ndis/madge/dll/mdgmpdlg.upd
new file mode 100644
index 000000000..bd926863d
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/mdgmpdlg.upd
@@ -0,0 +1,181 @@
+/***************************************************************************
+*
+* MDGMPDLG.UPD: MdgMPDlg (MdgMPort.SYS install helper DLL) update history.
+*
+* Copyright (c) Madge Networks Ltd. 1994
+*
+* Created: PBA 23/06/1994
+*
+***************************************************************************/
+
+#include "..\driver\mdgmport.upd"
+
+#define MADGE_DLL_VERSION 3,04,30,00
+#define MADGE_DLL_VERSION_STR "3.04.30"
+#define MADGE_DLL_NAME "MdgMPDlg"
+
+#define _DRIVER_DESC MADGE_NT_NAME##" "##MADGE_NT_VERSION_STR
+#define _DLL_DESC MADGE_DLL_NAME##" "##MADGE_DLL_VERSION_STR
+
+//
+// Identification string for MVER.
+//
+
+#ifdef MVER_STRING
+#undef MVER_STRING
+#endif
+
+#define MVER_STRING "VeRsIoN="##_DLL_DESC##" (for "##_DRIVER_DESC##")"
+
+
+/*---------------------------------------------------------------------------
+|
+| Update History.
+|
+|---------------------------------------------------------------------------
+
+ 3.04.30 10/10/1995 PBA
+
+ Source to be shipped to Microsoft. This is the LSS 4.31
+ build with support added for non-intel platforms.
+
+ 3.04.01-.29 Reserved for 4.3(1) maintanance.
+
+ 3.04 21/07/1995 PBA
+
+ Re-released for 4.3(1) with PCI-TI DMA/DIO fix.
+
+ 3.03.01-.49 Reserved for 4.3(1) maintanance.
+
+ 3.03 30/06/1995 PBA
+
+ Hardware thread released for LSS 4.3(1) with support
+ for PCI-TI adapters and untested support for PCI-Abyss
+ adapters.
+
+ 3.02 Used for non-intel thread derived from LSS 4.3(0).
+
+ 3.01.02 07/04/1995 PBA
+
+ Unchanged maintenance build.
+
+ 3.01.01 04/04/1995 PBA
+
+ Power PC build.
+
+
+ 3.01.02 - .49 Reserved for 4.3(0 and/or PnP) maintenance.
+
+ 3.01 02/02/1995 PBA
+
+ Released for 4.3(0 and/or PnP). All previous 4.3(x)
+ threads are now dead.
+
+ MDGMPORT 2.01.
+
+ 3.00.53 02/02/1995 PBA
+
+ Given to DaveF for Chicago testing and possible
+ shipment to Microsoft for M8 and/or NT 3.51.
+ MDGMPORT 2.00.61.
+
+ 3.00.52 24/01/1995 PBA
+
+ Added support for setting the ring speed.
+
+ 3.00.51 06/01/1995 PBA
+
+ Shipped source to FrancisT so that he could do a MIPs
+ build.
+
+ 3.00.50 15/12/1994 PBA
+
+ Live development continues.
+
+ Version numbers 2.50.01 to 2.99.99 are used for a FastMAC version.
+
+ 2.02.01 - .49 Reserved for release 4.3(1) maintenance.
+
+ Version number 2.02 is reserved for use in the 4.3(1) release. Live
+ development continues with 2.02.50.
+
+ 2.01.50 15/12/1994 PBA
+
+ Alpha release for product marketing to test. For use
+ with MDGMPORT 1.05.07.
+
+ 2.01.01 - .49 Reserved for release 4.3(0) maintenance.
+
+ Due the delay in getting the 4.3(0) release out it was decided to use
+ the new installtion software for 4.3(0). Version number 2.01 is
+ reserved for this. Live development continues with 2.01.50.
+
+ 2.00.03 25/11/1994 PBA
+
+ Added support for "Transfer method" for all adapters.
+
+ -- Special -----------------------------------------------------------------
+
+ 2.00.02a 11/01/1995 PBA
+
+ As 2.00.02 but has support for PCMCIA adapters. Shipped
+ to Jameel Hyder at Microsoft for NT 3.51 beta.
+ MDGMPORT 1.06.80.
+
+ ----------------------------------------------------------------------------
+
+ 2.00.02 23/11/1994 PBA
+
+ Shipped to Microsoft for possible inclusion in the next
+ NT release. MDGMPORT v1.06.50.
+
+ 2.00.01 21/09/1994 PBA
+
+ Major changes to support NetDetect based installation.
+ No PCI support at the moment.
+
+ 1.04 Reserved for release 4.3(1).
+
+ 1.03 08/11/1994 PBA
+
+ Re-released for the PCI release 4.2(3). MdgMPort.SYS
+ version 1.04.
+
+ 1.02 28/09/1994 PBA
+
+ Released for the PCI release 4.2(3). MdgMPort.SYS
+ version 1.03.
+
+ 1.01.50 28/09/1994 PBA
+
+ Added a new dialog box for PCI.
+
+ Due to the problems with FastMAC Plus a re-release with a new FastMAC
+ plus image will be needed for LSS 4.30. This release will be based on
+ 1.01.02 which is the same as the earlier LSS 4.30 with some minor bug
+ fixes. Live development continues with 1.01.50.
+
+ 1.01.02 02/09/1994 PBA
+
+ Dialog box now has support for enabling promiscuous mode.
+
+ 1.01.01 31/08/1994 PBA
+
+ Source shipped to Microsoft.
+
+ 1.01 22/07/1994 PBA
+
+ Released for 4.30 for MdgMPort.SYS 1.01.
+
+ 1.00.01 23/06/1994 PBA
+
+ First version derived from MDGNTDLG v1.04.01.
+
+---------------------------------------------------------------------------*/
+
+/******** End of MDGMPDLG.UPD **********************************************/
+
+
+
+
+ \ No newline at end of file
diff --git a/private/ntos/ndis/madge/dll/oemsetup.upd b/private/ntos/ndis/madge/dll/oemsetup.upd
new file mode 100644
index 000000000..57bbaf58c
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/oemsetup.upd
@@ -0,0 +1,241 @@
+/***************************************************************************
+*
+* OEMSETUP.UPD: Update log for the MdgMPort.SYS OEMSETUP.INF file.
+*
+* Copyright (c) Madge Networks Ltd. 1994
+*
+* Created: PBA 23/06/1994
+*
+***************************************************************************/
+
+/*--------------------------------------------------------------------------
+
+ 3.04.30 10/10/1995 PBA
+
+ Source to be shipped to Microsoft. This is the LSS 4.31
+ build with support added for non-intel platforms.
+
+ 3.04.01-.29 Reserved for 4.3(1) maintanance.
+
+ 3.04 21/07/1995 PBA
+
+ Re-released for 4.3(1) with PCI-TI DMA/DIO fix.
+
+ 3.03.01-.49 Reserved for 4.3(1) maintanance.
+
+ 3.03 30/06/1995 PBA
+
+ Hardware thread released for LSS 4.3(1) with support
+ for PCI-TI adapters and untested support for PCI-Abyss
+ adapters.
+
+ 3.01.02 07/04/1995 PBA
+
+ Added 0x0300 to the list of IO locations for PCMCIA
+ adapters.
+
+ 3.01.01 04/04/1995 PBA
+
+ Added PCMCIA support back in. MDGMPORT 2.01.01.
+ Power PC build.
+
+
+ 3.01.02 - .49 Reserved for 4.3(0 and/or PnP) maintenance.
+
+ 3.01 02/02/1995 PBA
+
+ Removed PCMCIA support just for this version as the
+ rest of the world doesn't know about NT 3.51 PCMCIA
+ support.
+
+ Released for 4.3(0 and/or PnP). All previous 4.3(x)
+ threads are now dead.
+
+ MDGMPORT 2.01.
+
+ 3.00.55 02/02/1995 PBA
+
+ Given to DaveF for Chicago testing and possible
+ shipment to Microsoft for M8 and/or NT 3.51.
+ MDGMPORT 2.00.61.
+
+ 3.00.54 01/02/1995 PBA
+
+ Now add an "AdapterType" to the registry for all adapter
+ types.
+
+ 3.00.53 31/01/1995 PBA
+
+ Added support for PCMCIA. I.e. now supports "IoBaseAddress"
+ as well as "IoLocation" and adds "AdapterType = 200" and
+ "Pcmcia = 1" to the registry.
+
+ 3.00.52 24/01/1995 PBA
+
+ Added support for setting the ring speed.
+
+ 3.00.51 06/01/1995 PBA
+
+ Shipped source to FrancisT so he could do a MIPs build.
+
+ 3.00.50 15/12/1994 PBA
+
+ Live development continues.
+
+ Version numbers 2.50.01 to 2.99.99 are used for a FastMAC version.
+
+ 2.02.01 - .49 Reserved for release 4.3(1) maintenance.
+
+ Version number 2.02 is reserved for use in the 4.3(1) release. Live
+ development continues with 2.02.50.
+
+ 2.01.50 15/12/1994 PBA
+
+ ALpha release for product marketing to test. For use with
+ MDGMPORT 1.05.07.
+
+ 2.01.01 - .49 Reserved for release 4.3(0) maintenance.
+
+ Due the delay in getting the 4.3(0) release out it was decided to use
+ the new installtion software for 4.3(0). Version number 2.01 is
+ reserved for this. Live development continues with 2.01.50.
+
+ 2.00.09 25/11/1994 PBA
+
+ Removed PCI and PnP support for a special version
+ for the "frozen" release 4.3(0) thread.
+
+ 2.00.08 25/11/1994 PBA
+
+ The detection DLL now completely describes the transfer
+ mode (DMA, PIO, MMIO) in the DmaChannel value. The
+ The DmaChannel and NoMmio values in the registry are
+ used to specify the transfer mode. We now translate between
+ the two schemes and allow the user to enable and disable
+ MMIO in a way that is consistent with choosing PIO or DMA.
+
+ 2.00.07 24/11/1994 PBA
+
+ Tidied up the code that sets default values if adapters
+ were not auto-detected.
+
+ 2.00.06 24/11/1994 PBA
+
+ Added support for PCI adapters.
+
+ -- Special -----------------------------------------------------------------
+
+ 2.00.05a 11/01/1995 PBA
+
+ As 2.00.05 but has support for PCMCIA adapters. Shipped
+ to Jameel Hyder at Microsoft for NT 3.51 beta.
+ MDGMPORT 1.06.80.
+
+ ----------------------------------------------------------------------------
+
+ 2.00.05 23/11/1994 PBA
+
+ Shipped to Microsoft for possible inclusion in the
+ next NT release. MDGMPORT v1.06.50.
+
+ 2.00.04 23/11/1994 PBA
+
+ Added support for ISA PnP adapters.
+
+ 2.00.03 22/11/1994 PBA
+
+ Changed the RX/TX slot list to range from 2/2 to 10/10
+ to try and alleviate Microsoft's multi-adapter problems.
+
+ 2.00.02 21/10/1994 PBA
+
+ Changed the RX/TX slot default to 4/4 to try and alleviate
+ some of Microsoft's multi-adapter memory problems.
+
+ 2.00.01 20/09/1994 PBA
+
+ Major re-write to use our NetDetect DLL.
+ No PCI support at the moment.
+
+ 1.05 Reserved for release 4.3(1)
+
+ 1.04 08/11/1994 PBA
+
+ Re-release for PCI release 4.2(3). MdgMPort.SYS
+ version 1.03.
+
+ 1.03 28/09/1994 PBA
+
+ Released for the PCI release 4.2(3). MdgMPort.SYS
+ version 1.03.
+
+ 1.02.50 28/09/1994 PBA
+
+ Added support for PCI.
+
+ Due to the problems with FastMAC Plus a re-release with a new FastMAC
+ plus image will be needed for LSS 4.30. This release will be based on
+ 1.02.02 which is the same as the earlier LSS 4.30 with some minor bug
+ fixes. Live development continues with 1.02.50.
+
+ 1.02.02 02/09/1994 PBA
+
+ Added support for setting promiscuous mode from the
+ dialog box.
+
+ 1.02.01 31/08/1994 PBA
+
+ Source shipped to Microsoft.
+
+ 1.02 24/08/1994 PBA
+
+ Re-released for 4.3. For use with MdgMPort.SYS v1.02.
+
+ 1.01.03 16/08/1994 PBA
+
+ Re-arranged the order of some of the sections and arranged
+ for all of the files to be copied in one go rather than
+ DLL and HELP and then driver later. Also set the file
+ sizes accurately in the file sections. Hopefully this may
+ make the file work under MCL's build of Daytona.
+
+ 1.01.02 15/08/1994 PBA
+
+ It looks possible that under later builds of Daytona we
+ may be called with DoCopy set to NO. To make sure we copy
+ the help and DLL files we ignore the value of DoCopy and
+ always do the copy.
+
+ 1.01.01 10/08/1994 PBA
+
+ Now has a multiprocessor PIO option.
+
+ 1.01 22/07/1994 PBA
+
+ Released for 4.30 for MdgMPort.SYS 1.01.
+
+ 1.00.04 19/07/1994 PBA
+
+ Increased the default maximum frame size to 4096 bytes.
+
+ 1.00.03 11/07/1994 PBA
+
+ Fixed bug where the MCA adapter enumeration code did not
+ merge two lists properly so if there where MC16 and MC32
+ adapters present the installation didn't work properly.
+
+ 1.00.02 28/06/1994 PBA
+
+ Fixed update option. Now copies .dll and .hlp files as
+ well as binaries. Displays error message if user tries
+ to update the hardware.
+
+ 1.00.01 23/06/1994 PBA
+
+ First version derived from 1.01.02 for MdgNT.SYS.
+
+--------------------------------------------------------------------------*/
+
+/******** End of OEMSETUP.UPD *********************************************/
+
+ \ No newline at end of file
diff --git a/private/ntos/ndis/madge/dll/sources b/private/ntos/ndis/madge/dll/sources
new file mode 100644
index 000000000..192a7f7cf
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/sources
@@ -0,0 +1,42 @@
+!if 0
+
+ Copyright (C) 1992-1995 by Digital Equipment Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the MADGE NDIS3 miniport driver being built
+ and the list of sources files needed to build it.
+ It specifies also the compiler switches specific to this driver
+
+Author:
+
+!endif
+
+TARGETNAME=MDGMPDLG
+TARGETTYPE=DYNLINK
+
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib
+
+INCLUDES=..\..\..\inc;$(BASEDIR)\public\sdk\inc
+C_DEFINES=$(C_DEFINES) -DNDIS_NT=1
+
+#MSC_WARNING_LEVEL=/W3 /WX
+MSC_WARNING_LEVEL=/W3
+
+SOURCES=mdgmpdlg.c \
+ mdgmpdlg.rc
+
+DLLBASE=0x1C000000
+
+DLLENTRY=_CRT_INIT
+
+USE_CRTDLL=1 # (link with crtdll.lib)
+
+MAKEDLL=1
+
+NTTARGETFILES=mdgmpdlg.hlp
diff --git a/private/ntos/ndis/madge/dll/tlmadge.ico b/private/ntos/ndis/madge/dll/tlmadge.ico
new file mode 100644
index 000000000..50d82343b
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/tlmadge.ico
Binary files differ
diff --git a/private/ntos/ndis/madge/dll/trmadge.ico b/private/ntos/ndis/madge/dll/trmadge.ico
new file mode 100644
index 000000000..6d650c9fd
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/trmadge.ico
Binary files differ
diff --git a/private/ntos/ndis/madge/dll/uilstf.h b/private/ntos/ndis/madge/dll/uilstf.h
new file mode 100644
index 000000000..562975e2c
--- /dev/null
+++ b/private/ntos/ndis/madge/dll/uilstf.h
@@ -0,0 +1,481 @@
+/***************************************************************************/
+/*********************** include file for UI Library *********************/
+/***************************************************************************/
+
+#define STF_MESSAGE (WM_USER + 0x8000)
+
+/*
+** Window Messages
+*/
+_dt_public
+#define STF_UI_EVENT (STF_MESSAGE)
+_dt_public
+#define STF_DESTROY_DLG (STF_MESSAGE + 1)
+_dt_public
+#define STF_HELP_DLG_DESTROYED (STF_MESSAGE + 2)
+_dt_public
+#define STF_INFO_DLG_DESTROYED (STF_MESSAGE + 3)
+_dt_public
+#define STF_EDIT_DLG_DESTROYED (STF_MESSAGE + 4)
+_dt_public
+#define STF_RADIO_DLG_DESTROYED (STF_MESSAGE + 5)
+_dt_public
+#define STF_CHECK_DLG_DESTROYED (STF_MESSAGE + 6)
+_dt_public
+#define STF_LIST_DLG_DESTROYED (STF_MESSAGE + 7)
+_dt_public
+#define STF_MULTI_DLG_DESTROYED (STF_MESSAGE + 8)
+_dt_public
+#define STF_QUIT_DLG_DESTROYED (STF_MESSAGE + 9)
+_dt_public
+#define STF_DLG_ACTIVATE (STF_MESSAGE + 10)
+_dt_public
+#define STF_UILIB_ACTIVATE (STF_MESSAGE + 11)
+_dt_public
+#define STF_REINITDIALOG (STF_MESSAGE + 12)
+_dt_public
+#define STF_SHL_INTERP (STF_MESSAGE + 13)
+_dt_hidden
+#define STF_COMBO_DLG_DESTROYED (STF_MESSAGE + 14)
+_dt_hidden
+#define STF_MULTICOMBO_DLG_DESTROYED (STF_MESSAGE + 15)
+_dt_hidden
+#define STF_DUAL_DLG_DESTROYED (STF_MESSAGE + 16)
+_dt_hidden
+#define STF_MULTICOMBO_RADIO_DLG_DESTROYED (STF_MESSAGE + 17)
+_dt_hidden
+#define STF_MAINT_DLG_DESTROYED (STF_MESSAGE + 18)
+
+
+_dt_hidden
+#define STF_SET_INSTRUCTION_TEXT (STF_MESSAGE + 0x100)
+
+_dt_hidden
+#define STF_SET_HELP_CONTEXT (STF_MESSAGE + 0x101)
+
+_dt_hidden
+#define STF_ENABLE_EXIT_BUTTON (STF_MESSAGE + 0x102)
+
+_dt_hidden
+#define STF_ERROR_ABORT (STF_MESSAGE + 0x103)
+
+
+
+
+//
+// Button IDS to communicate help and exit button messages to shell
+//
+#define ID_EXITBUTTON 7
+#define ID_HELPBUTTON 8
+
+
+/*
+** Symbols used by Basic Dialog Class procedures
+*/
+
+#define CLS_MYDLGS "mydlg"
+#define DLGTEXT "DlgText"
+#define DLGCAPTION "Caption"
+#define DLGTYPE "DlgType"
+#define DLGTEMPLATE "DlgTemplate"
+
+
+
+#define INSTRUCTIONTEXT "InstructionText"
+#define HELPCONTEXT "HelpContext"
+#define EXITSTATE "ExitState"
+
+#define EXIT_ENABLE "Active"
+#define EXIT_DISABLE "Inactive"
+
+
+/*
+** PushButton Control IDs
+*/
+_dt_public
+#define IDC_A 401
+_dt_public
+#define IDC_B 402
+_dt_public
+#define IDC_C 403
+_dt_public
+#define IDC_D 404
+_dt_public
+#define IDC_E 405
+_dt_public
+#define IDC_F 406
+_dt_public
+#define IDC_G 407
+_dt_public
+#define IDC_H 408
+_dt_public
+#define IDC_I 409
+_dt_public
+#define IDC_J 410
+_dt_public
+#define IDC_K 411
+_dt_public
+#define IDC_L 412
+_dt_public
+#define IDC_M 413
+_dt_public
+#define IDC_N 414
+_dt_public
+#define IDC_O 415
+_dt_public
+#define IDC_P 416
+_dt_public
+#define IDC_Q 417
+_dt_public
+#define IDC_R 418
+_dt_public
+#define IDC_S 419
+_dt_public
+#define IDC_T 420
+_dt_public
+#define IDC_U 421
+_dt_public
+#define IDC_V 422
+_dt_public
+#define IDC_W 423
+_dt_public
+#define IDC_X 424
+_dt_public
+#define IDC_Y 425
+_dt_public
+#define IDC_Z 426
+
+
+/*
+** Text Control IDs
+*/
+_dt_public
+#define IDC_TEXT1 431
+_dt_public
+#define IDC_TEXT2 432
+_dt_public
+#define IDC_TEXT3 433
+_dt_public
+#define IDC_TEXT4 434
+_dt_public
+#define IDC_TEXT5 435
+_dt_public
+#define IDC_TEXT6 436
+_dt_public
+#define IDC_TEXT7 437
+_dt_public
+#define IDC_TEXT8 438
+_dt_public
+#define IDC_TEXT9 439
+_dt_public
+#define IDC_TEXT10 440
+_dt_public
+#define IDC_TEXT11 441
+
+
+/*
+** Radio and Checkbox Button Control IDs
+*/
+_dt_public
+#define IDC_B0 450
+_dt_public
+#define IDC_B1 451
+_dt_public
+#define IDC_B2 452
+_dt_public
+#define IDC_B3 453
+_dt_public
+#define IDC_B4 454
+_dt_public
+#define IDC_B5 455
+_dt_public
+#define IDC_B6 456
+_dt_public
+#define IDC_B7 457
+_dt_public
+#define IDC_B8 458
+_dt_public
+#define IDC_B9 459
+_dt_public
+#define IDC_B10 460
+
+_dt_public
+#define IDC_RB0 610
+_dt_public
+#define IDC_RB1 611
+_dt_public
+#define IDC_RB2 612
+_dt_public
+#define IDC_RB3 613
+_dt_public
+#define IDC_RB4 614
+_dt_public
+#define IDC_RB5 615
+_dt_public
+#define IDC_RB6 616
+_dt_public
+#define IDC_RB7 617
+_dt_public
+#define IDC_RB8 618
+_dt_public
+#define IDC_RB9 619
+_dt_public
+#define IDC_RB10 620
+
+/*
+** Generic Dialog Button IDs
+*/
+
+_dt_public
+#define IDC_BTN0 630
+_dt_public
+#define IDC_BTN1 631
+_dt_public
+#define IDC_BTN2 632
+_dt_public
+#define IDC_BTN3 633
+_dt_public
+#define IDC_BTN4 634
+_dt_public
+#define IDC_BTN5 635
+_dt_public
+#define IDC_BTN6 636
+_dt_public
+#define IDC_BTN7 637
+_dt_public
+#define IDC_BTN8 638
+_dt_public
+#define IDC_BTN9 639
+
+
+/*
+** Combo box IDs
+*/
+_dt_public
+#define IDC_COMBO0 480
+_dt_public
+#define IDC_COMBO1 481
+_dt_public
+#define IDC_COMBO2 482
+_dt_public
+#define IDC_COMBO3 483
+_dt_public
+#define IDC_COMBO4 484
+_dt_public
+#define IDC_COMBO5 485
+_dt_public
+#define IDC_COMBO6 486
+_dt_public
+#define IDC_COMBO7 487
+_dt_public
+#define IDC_COMBO8 488
+_dt_public
+#define IDC_COMBO9 489
+
+/*
+** ICON IDs
+*/
+_dt_public
+#define IDC_ICON0 500
+_dt_public
+#define IDC_ICON1 501
+_dt_public
+#define IDC_ICON2 502
+_dt_public
+#define IDC_ICON3 503
+_dt_public
+#define IDC_ICON4 504
+_dt_public
+#define IDC_ICON5 505
+_dt_public
+#define IDC_ICON6 506
+_dt_public
+#define IDC_ICON7 507
+_dt_public
+#define IDC_ICON8 508
+_dt_public
+#define IDC_ICON9 509
+
+/*
+** SPECIAL PUSHBUTTONS
+*/
+
+_dt_public
+#define IDC_SP1 521
+_dt_public
+#define IDC_SP2 522
+_dt_public
+#define IDC_SP3 523
+_dt_public
+#define IDC_SP4 524
+_dt_public
+#define IDC_SP5 525
+_dt_public
+#define IDC_SP6 526
+_dt_public
+#define IDC_SP7 527
+_dt_public
+#define IDC_SP8 528
+_dt_public
+#define IDC_SP9 529
+_dt_public
+#define IDC_SP10 530
+
+/*
+** STATUS TEXT FIELDS
+*/
+
+_dt_public
+#define IDC_STATUS1 541
+_dt_public
+#define IDC_STATUS2 542
+_dt_public
+#define IDC_STATUS3 543
+_dt_public
+#define IDC_STATUS4 544
+_dt_public
+#define IDC_STATUS5 545
+_dt_public
+#define IDC_STATUS6 546
+_dt_public
+#define IDC_STATUS7 547
+_dt_public
+#define IDC_STATUS8 548
+_dt_public
+#define IDC_STATUS9 549
+_dt_public
+#define IDC_STATUS10 550
+
+
+
+/*
+** SIZE FIELDS ASSOCIATED WITH CHECK OPTIONAL COMPONENTS
+*/
+
+_dt_public
+#define IDC_SIZE1 551
+_dt_public
+#define IDC_SIZE2 552
+_dt_public
+#define IDC_SIZE3 553
+_dt_public
+#define IDC_SIZE4 554
+_dt_public
+#define IDC_SIZE5 555
+_dt_public
+#define IDC_SIZE6 556
+_dt_public
+#define IDC_SIZE7 557
+_dt_public
+#define IDC_SIZE8 558
+_dt_public
+#define IDC_SIZE9 559
+_dt_public
+#define IDC_SIZE10 560
+
+
+
+/*
+** TOTALS OF SIZES
+*/
+
+_dt_public
+#define IDC_TOTAL1 561
+_dt_public
+#define IDC_TOTAL2 562
+_dt_public
+#define IDC_TOTAL3 563
+_dt_public
+#define IDC_TOTAL4 564
+_dt_public
+#define IDC_TOTAL5 565
+_dt_public
+#define IDC_TOTAL6 566
+_dt_public
+#define IDC_TOTAL7 567
+_dt_public
+#define IDC_TOTAL8 568
+_dt_public
+#define IDC_TOTAL9 569
+_dt_public
+#define IDC_TOTAL10 570
+
+/*
+** MAXIMUM SIZES
+*/
+
+_dt_public
+#define IDC_MAX1 571
+_dt_public
+#define IDC_MAX2 572
+_dt_public
+#define IDC_MAX3 573
+_dt_public
+#define IDC_MAX4 574
+_dt_public
+#define IDC_MAX5 575
+_dt_public
+#define IDC_MAX6 576
+_dt_public
+#define IDC_MAX7 577
+_dt_public
+#define IDC_MAX8 578
+_dt_public
+#define IDC_MAX9 579
+_dt_public
+#define IDC_MAX10 580
+
+/*
+** Edit Control IDs
+*/
+
+#define IDC_EDIT1 581
+#define IDC_EDIT2 582
+#define IDC_EDIT3 583
+#define IDC_EDIT4 584
+#define IDC_EDIT5 585
+#define IDC_EDIT6 586
+#define IDC_EDIT7 587
+#define IDC_EDIT8 588
+#define IDC_EDIT9 589
+#define IDC_EDIT10 590
+
+/*
+** ListBox Control IDs
+*/
+
+#define IDC_LIST1 591
+#define IDC_LIST2 592
+#define IDC_LIST3 593
+#define IDC_LIST4 594
+#define IDC_LIST5 595
+#define IDC_LIST6 596
+#define IDC_LIST7 597
+#define IDC_LIST8 598
+#define IDC_LIST9 599
+#define IDC_LIST10 600
+
+
+/*
+** MENU IDS
+*/
+
+#define ID_MAINTAIN 651
+
+
+/*
+** ID_MAINTAIN MENU IDS
+*/
+
+#define MENU_CHANGE 701
+#define MENU_INSTALL 702
+#define MENU_ADD_REMOVE 703
+#define MENU_EXIT 704
+#define MENU_HELPINDEX 705
+#define MENU_HELPSEARCH 706
+#define MENU_HELPONHELP 708
+#define MENU_HELPONLINE 709
+#define MENU_ABOUT 710
+#define MENU_PROFILE 711
+#define MENU_ADD_REMOVE_SCSI 712
+#define MENU_ADD_REMOVE_TAPE 713
diff --git a/private/ntos/ndis/madge/driver/dispatch.c b/private/ntos/ndis/madge/driver/dispatch.c
new file mode 100644
index 000000000..593ef071d
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/dispatch.c
@@ -0,0 +1,919 @@
+/***************************************************************************
+*
+* DISPATCH.C
+*
+* FastMAC Plus based NDIS3 miniport driver dispatch routines. This module
+* contains all of the upper interface functions that are not purely
+* for initialization and closedown (i.e. DriverEntry, MadgeInitialize
+* and MadgeHalt) excluding MadgeSetInformation and MadgeQueryInformation.
+*
+* Copyright (c) Madge Networks Ltd 1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_intr.h"
+#include "ftk_extr.h"
+
+#include "mdgmport.upd"
+#include "ndismod.h"
+
+
+/****************************************************************************
+*
+* Function - MadgeGetAdapterStatus
+*
+* Parameters - systemSpecific1 -> Unused.
+* context -> Actually a pointer to our NDIS3 level
+* adapter structure.
+* systemSpecific2 -> Unused.
+* systemSpecific3 -> Unused.
+*
+* Purpose - This function is called of a timer tick and notifies
+* open bindings of any interesting events.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeGetAdapterStatus(
+ PVOID systemSpecific1,
+ PVOID context,
+ PVOID systemSpecific2,
+ PVOID systemSpecific3
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ NDIS_STATUS notifyStatus;
+ WORD ringStatus;
+
+ //
+ // Do some pre-calculation.
+ //
+
+ ndisAdap = (PMADGE_ADAPTER) context;
+ notifyStatus = 0;
+ ringStatus = ndisAdap->CurrentRingStatus;
+
+ if (ndisAdap->CurrentRingState == NdisRingStateOpened)
+ {
+ //
+ // WARNING: If the adapter has been shutdown, this will return zero
+ // in the two fields.
+ //
+
+ driver_get_open_and_ring_status(
+ ndisAdap->FtkAdapterHandle,
+ &ndisAdap->CurrentRingStatus,
+ &ndisAdap->LastOpenStatus
+ );
+
+ if (ringStatus != ndisAdap->CurrentRingStatus)
+ {
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_RING_RECOVERY)
+ {
+ notifyStatus |= NDIS_RING_RING_RECOVERY;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_SINGLE_STATION)
+ {
+ notifyStatus |= NDIS_RING_SINGLE_STATION;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_COUNTER_OVERFLOW)
+ {
+ notifyStatus |= NDIS_RING_COUNTER_OVERFLOW;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_REMOVE_RECEIVED)
+ {
+ notifyStatus |= NDIS_RING_REMOVE_RECEIVED;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_AUTO_REMOVAL)
+ {
+ notifyStatus |= NDIS_RING_AUTO_REMOVAL_ERROR;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_LOBE_FAULT)
+ {
+ notifyStatus |= NDIS_RING_LOBE_WIRE_FAULT;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_TRANSMIT_BEACON)
+ {
+ notifyStatus |= NDIS_RING_TRANSMIT_BEACON;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_SOFT_ERROR)
+ {
+ notifyStatus |= NDIS_RING_SOFT_ERROR;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_HARD_ERROR)
+ {
+ notifyStatus |= NDIS_RING_HARD_ERROR;
+ }
+
+ if (ndisAdap->CurrentRingStatus & RING_STATUS_SIGNAL_LOSS)
+ {
+ notifyStatus |= NDIS_RING_SIGNAL_LOSS;
+ }
+
+ if (notifyStatus != 0)
+ {
+ NdisMIndicateStatus(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_STATUS_RING_STATUS,
+ (PVOID) &notifyStatus,
+ sizeof(notifyStatus)
+ );
+
+ NdisMIndicateStatusComplete(
+ ndisAdap->UsedInISR.MiniportHandle
+ );
+
+ MadgePrint2(
+ "Ring Status %04x\n", ndisAdap->CurrentRingStatus);
+ }
+ }
+ }
+
+ //
+ // Just before we go, clear the JustReadErrorLog flag, so that requests
+ // for statistics will cause an SRB to be issued every now and then.
+ //
+
+ ndisAdap->JustReadErrorLog = 0;
+
+ //
+ // And finally re-arm the timer.
+ //
+
+ NdisMSetTimer(&ndisAdap->WakeUpTimer, EVERY_2_SECONDS);
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeCheckForHang
+*
+* Parameters - adapterContext -> A pointer to our NDIS adapter structure.
+*
+* Purpose - Process a call from the NDIS3 wrapper to check if
+* an adapter has hung.
+*
+* Returns - We always return FALSE since the only action the wrapper
+* can take is to invoke a reset, which we don't support
+* anyway.
+*
+****************************************************************************/
+
+BOOLEAN
+MadgeCheckForHang(NDIS_HANDLE adapterContext)
+{
+ return FALSE;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeReset
+*
+* Parameters - adapterContext -> A pointer to our NDIS adapter structure.
+* addressReset -> Ignored.
+*
+* Purpose - Process a call from the NDIS3 wrapper to reset an
+* adapter.
+*
+* Returns - NDIS_STATUS_NOT_RESETTABLE as we don't support resets.
+*
+****************************************************************************/
+
+NDIS_STATUS
+MadgeReset(PBOOLEAN addressReset, NDIS_HANDLE adapterContext)
+{
+ MadgePrint1("MadgeReset\n");
+
+ MadgePrint2(
+ "ndisAdap = %x\n",
+ PMADGE_ADAPTER_FROM_CONTEXT(adapterContext)
+ );
+
+ return NDIS_STATUS_NOT_RESETTABLE;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeDisableInterrupts
+*
+* Parameters - adapterContext -> A pointer to our NDIS adapter structure.
+*
+* Purpose - Process a call from the NDIS3 wrapper to turn adapter
+* interrupts off.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeDisableInterrupts(NDIS_HANDLE adapterContext)
+{
+// MadgePrint1("MadgeDisableInterrupts\n");
+
+ //
+ // Note: it is very difficult for use to disble interrupts at the
+ // adapter so we don't. We use a spin lock to protect our DPR
+ // routine.
+ //
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeEnableInterrupts
+*
+* Parameters - adapterContext -> A pointer to our NDIS adapter structure.
+*
+* Purpose - Process a call from the NDIS3 wrapper to turn adapter
+* interrupts on.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeEnableInterrupts(NDIS_HANDLE adapterContext)
+{
+// MadgePrint1("MadgeEnableInterrupts\n");
+
+ //
+ // Note: it is very difficult for use to disble interrupts at the
+ // adapter so we don't. We use a spin lock to protect our DPR
+ // routine.
+ //
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeSend
+*
+* Parameters - adapterContext -> Pointer to our NDIS level adapter
+* structure.
+* packet -> Pointer to the NDIS3 packet to send.
+* flags -> Optional flags.
+*
+* Purpose - Called by the NDIS3 wrapper when it wants us to send a
+* frame.
+*
+* Returns - NDIS3 status code.
+*
+****************************************************************************/
+
+NDIS_STATUS
+MadgeSend(NDIS_HANDLE adapterContext, PNDIS_PACKET packet, UINT flags)
+{
+ ULONG *pagePtr;
+ UINT pageCount;
+ UINT physFrags;
+ UINT i;
+ UINT size;
+ UINT bytes;
+ UINT count;
+ NDIS_BUFFER *bufPtr;
+ NDIS_STATUS retCode;
+ PMADGE_ADAPTER ndisAdap;
+ UINT totalPacketSize;
+ WORD status;
+
+ //
+ // Set up a pointer to our adapter handle.
+ //
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
+
+ //
+ // Find out how long the frame is and where it's header is.
+ //
+
+ NdisQueryPacket(packet, NULL, NULL, NULL, &totalPacketSize);
+
+ //
+ // Make sure the frame isn't too long or two short.
+ //
+
+ if (totalPacketSize > ndisAdap->MaxFrameSize ||
+ totalPacketSize < FRAME_HEADER_SIZE)
+ {
+ retCode = NDIS_STATUS_INVALID_PACKET;
+ }
+
+ //
+ // Check that a PCMCIA adapter is still physically present.
+ //
+
+ else if (ndisAdap->AdapterRemoved)
+ {
+ MadgePrint1("MadgeSend aborting - adapter removed\n");
+ retCode = NDIS_STATUS_SUCCESS;
+ }
+
+ //
+ // Otherwise we need to send the frame over the ring.
+ //
+
+ else
+ {
+ status = rxtx_transmit_frame(
+ ndisAdap->FtkAdapterHandle,
+ (DWORD) packet,
+ (WORD) totalPacketSize,
+ TRUE
+ );
+
+ //
+ // Check if the frame has been transmitted completely.
+ //
+
+ if (status == DRIVER_TRANSMIT_SUCCEED)
+ {
+ ndisAdap->FramesTransmitted++;
+ retCode = NDIS_STATUS_SUCCESS;
+
+#ifdef OID_MADGE_MONITOR
+ //
+ // Update the appropriate parts of the monitor structure
+ //
+
+ (ndisAdap->MonitorInfo).TransmitFrames++;
+ (ndisAdap->MonitorInfo).TransmitFrameSize[totalPacketSize/128]++;
+
+ //
+ // Find the number of physical fragments sent
+ //
+
+ NdisQueryPacket(packet,
+ NULL,
+ NULL,
+ &bufPtr,
+ &totalPacketSize);
+
+ physFrags = 0;
+ count = 0;
+
+ while (bufPtr != NULL)
+ {
+ MDL *mdl = (MDL *) bufPtr;
+
+ count++;
+ pageCount = (((MDL *) bufPtr)->Size - sizeof(MDL)) / sizeof(ULONG);
+ pagePtr = (ULONG *) (((MDL *) bufPtr) + 1);
+
+ physFrags++; // First page.
+
+ bytes = mdl->ByteCount;
+
+ if (pageCount <= 1)
+ {
+ size = bytes;
+ }
+ else
+ {
+ size = 4096 - mdl->ByteOffset;
+ bytes -= size;
+ }
+
+ for (i = 1; i < pageCount; i++)
+ {
+ if (pagePtr[i] != pagePtr[i - 1] + 1)
+ {
+ size = 0;
+ physFrags++;
+ }
+
+ if (i == pageCount - 1)
+ {
+ size += bytes;
+ }
+ else
+ {
+ bytes -= 4096;
+ size += 4096;
+ }
+
+ }
+
+ NdisGetNextBuffer(bufPtr, &bufPtr);
+ }
+
+ if (count < 65)
+ {
+ (ndisAdap->MonitorInfo).NumberOfVFrags[count]++;
+ }
+
+ if (physFrags < 65)
+ {
+ (ndisAdap->MonitorInfo).NumberOfPFrags[physFrags]++;
+ }
+#endif
+ }
+
+ //
+ // Or not transmitted at all, in which case we must
+ // queue it for later.
+ //
+
+ else
+ {
+ retCode = NDIS_STATUS_RESOURCES;
+ }
+ }
+
+ return retCode;
+}
+
+
+/***************************************************************************
+*
+* Function - MadgeCopyFromPacketToBuffer
+*
+* Parameters - packet -> The NDIS3 packet to copy.
+* offset -> Starting offset into the packet.
+* bytesToCopy -> Number of bytes to copy.
+* destPtr -> Pointer to the destination buffer.
+* bytesCopied -> Pointer to a holder for the number of
+* bytes actually copied.
+*
+* Purpose - Copy data from an NDIS3 packet into a buffer.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeCopyFromPacketToBuffer(
+ PNDIS_PACKET packet,
+ UINT offset,
+ UINT bytesToCopy,
+ PCHAR destPtr,
+ PUINT bytesCopied
+ )
+{
+ UINT bufferCount;
+ PNDIS_BUFFER currentBuffer;
+ PVOID currentPtr;
+ UINT currentLength;
+ UINT amountToMove;
+ UINT localBytesCopied;
+
+ *bytesCopied = 0;
+ localBytesCopied = 0;
+
+ if (bytesToCopy == 0)
+ {
+ return;
+ }
+
+ NdisQueryPacket(packet, NULL, &bufferCount, &currentBuffer, NULL);
+ if (bufferCount == 0)
+ {
+ return;
+ }
+
+ NdisQueryBuffer(currentBuffer, &currentPtr, &currentLength);
+
+ while (localBytesCopied < bytesToCopy)
+ {
+ if (currentLength == 0)
+ {
+ NdisGetNextBuffer(currentBuffer, &currentBuffer);
+ if (currentBuffer == 0)
+ {
+ break;
+ }
+
+ NdisQueryBuffer(currentBuffer, &currentPtr, &currentLength);
+ continue;
+ }
+
+ if (offset > 0)
+ {
+ if (offset > currentLength)
+ {
+ offset -= currentLength;
+ currentLength = 0;
+ continue;
+ }
+ else
+ {
+ currentPtr = (PCHAR) currentPtr + offset;
+ currentLength -= offset;
+ offset = 0;
+ }
+ }
+
+ amountToMove =
+ (currentLength <= (bytesToCopy - localBytesCopied))
+ ? currentLength
+ : bytesToCopy - localBytesCopied;
+
+ MADGE_MOVE_MEMORY(destPtr, currentPtr, amountToMove);
+
+ destPtr = (PCHAR) destPtr + amountToMove;
+ currentPtr = (PCHAR) currentPtr + amountToMove;
+
+ localBytesCopied += amountToMove;
+ currentLength -= amountToMove;
+ }
+
+ *bytesCopied = localBytesCopied;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeTransferData
+*
+* Parameters - adapterContext -> Pointer to our NDIS level adapter
+* structure.
+* receiveContext -> Pointer to the start of the frame data.
+* byteOffset -> Offset to start copying from.
+* bytesToTransfer -> Number of bytes to copy.
+* packet -> NDIS packet for the data.
+* bytesTransferred -> Pointer to a holder for the number of
+* bytes actually copied.
+*
+* Purpose - Copy data from the received frame just indicated into an
+* NDIS packet. This function is called by the NDIS3 wrapper
+* in response to our indication frame rxtx_irq_received_frame.
+*
+* Returns - An NDIS3 status code.
+*
+****************************************************************************/
+
+NDIS_STATUS
+MadgeTransferData(
+ PNDIS_PACKET packet,
+ PUINT bytesTransferred,
+ NDIS_HANDLE adapterContext,
+ NDIS_HANDLE receiveContext,
+ UINT byteOffset,
+ UINT bytesToTransfer
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ NDIS_STATUS retCode;
+
+ //
+ // Pre-calculate some values.
+ //
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
+
+ //
+ // Check that the data pointer is valid.
+ //
+
+ if ((PCHAR) receiveContext == NULL)
+ {
+ retCode = NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // If it is, copy from the frame from the receive buffer
+ // into the packet.
+ //
+
+ else
+ {
+ MadgeCopyFromBufferToPacket(
+ (PCHAR) receiveContext + byteOffset,
+ bytesToTransfer,
+ packet,
+ 0,
+ bytesTransferred
+ );
+
+ retCode = NDIS_STATUS_SUCCESS;
+
+#ifdef OID_MADGE_MONITOR
+ //
+ // Update the appropriate parts of the monitor structure
+ //
+ if ((ndisAdap->MonitorInfo).ReceiveFlag > 0)
+ {
+ (ndisAdap->MonitorInfo).TransferFrames++;
+ (ndisAdap->MonitorInfo).TransferFrameSize[(ndisAdap->MonitorInfo).CurrentFrameSize/128]++;
+ (ndisAdap->MonitorInfo).ReceiveFlag = 0;
+ }
+#endif
+
+ }
+
+ return retCode;
+}
+
+
+/***************************************************************************
+*
+* Function - MadgeCopyFromBufferToPacket
+*
+* Parameters - srcPtr -> Pointer to the source buffer.
+* bytesToCopy -> Number of bytes to copy.
+* packet -> The NDIS3 destination packet.
+* offset -> Starting offset into the buffer.
+* bytesCopied -> Pointer to a holder for the number of
+* bytes actually copied.
+*
+* Purpose - Copy data from a buffer into an NDIS3 packet.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeCopyFromBufferToPacket(
+ PCHAR srcPtr,
+ UINT bytesToCopy,
+ PNDIS_PACKET packet,
+ UINT offset,
+ PUINT bytesCopied
+ )
+{
+ UINT bufferCount;
+ PNDIS_BUFFER currentBuffer;
+ PVOID virtualAddress;
+ UINT currentLength;
+ UINT amountToMove;
+ UINT localBytesCopied;
+
+ *bytesCopied = 0;
+ localBytesCopied = 0;
+
+ if (bytesToCopy == 0)
+ {
+ return;
+ }
+
+ NdisQueryPacket(packet, NULL, &bufferCount, &currentBuffer, NULL);
+ if (bufferCount == 0)
+ {
+ return;
+ }
+
+ NdisQueryBuffer(currentBuffer, &virtualAddress, &currentLength);
+
+ while (localBytesCopied < bytesToCopy)
+ {
+ if (currentLength == 0)
+ {
+ NdisGetNextBuffer(currentBuffer, &currentBuffer);
+ if (currentBuffer == NULL)
+ {
+ break;
+ }
+
+ NdisQueryBuffer(currentBuffer, &virtualAddress, &currentLength);
+ continue;
+ }
+
+ if (offset > 0)
+ {
+ if (offset > currentLength)
+ {
+ offset -= currentLength;
+ currentLength = 0;
+ continue;
+ }
+ else
+ {
+ virtualAddress = (PCHAR) virtualAddress + offset;
+ currentLength -= offset;
+ offset = 0;
+ }
+ }
+
+ amountToMove = (bytesToCopy - localBytesCopied < currentLength)
+ ? bytesToCopy - localBytesCopied
+ : currentLength;
+
+ MADGE_MOVE_MEMORY(
+ virtualAddress,
+ srcPtr,
+ amountToMove
+ );
+
+ srcPtr += amountToMove;
+ localBytesCopied += amountToMove;
+ currentLength -= amountToMove;
+ }
+
+ *bytesCopied = localBytesCopied;
+}
+
+
+/***************************************************************************
+*
+* Function - MadgeISR
+*
+* Parameters - interruptRecognised -> Pointer to an interrupt recognised
+* flag we set if we recognise the
+* interrupt.
+* queueDPR -> Pointer to DPR required flag we
+* set if we need a DPR.
+* adapterContext -> Pointer to our NDIS level adapter
+* structure.
+*
+* Purpose - Process an IRQ from an adapter. All we do is call the
+* HWI and schedule a DPR if required.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeISR(
+ PBOOLEAN interruptRecognised,
+ PBOOLEAN queueDPR,
+ NDIS_HANDLE adapterContext
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
+
+ hwi_interrupt_entry(
+ ndisAdap->FtkAdapterHandle,
+ (WORD) ndisAdap->UsedInISR.InterruptNumber
+ );
+
+ //
+ // If ndisAdap->DprRequired is TRUE then we recognised the interrupt
+ // and found something that requires further processing (e.g. received
+ // a frame). If ndisAdap->DprRequired is FALSE then we either didn't
+ // recognise the interrupt or we don't need any further processing.
+ // The only operation that doesn't need further processing is ISA
+ // PIO. Since ISA cards cannot share interrupt lines it doesn't
+ // matter if we say we don't recognise the interrupt if we don't
+ // need any further processing. Hence we can use ndisAdap->DprRequired
+ // to set both *interruptRecognised and *queueDpr.
+ //
+
+ //
+ // However ...
+ // There is a race condition with ATULA based cards in PIO mode.
+ // Normally we do not claim interrupts that are used for PIO transfers
+ // to avoid the overhead of a DPR on PIO transfers. However, in some
+ // instances if we do not claim the PIO interrupts used for the
+ // initial "DMA" tests then WFWG (and possibly NT) permanently disables
+ // our interrupts. To get around this we claim all interrupts until
+ // our rx/tx buffers have been allocated since the optimisation of not
+ // queuing a DPR for PIO interrupts doesn't matter until we have
+ // rx/tx buffers in place.
+ //
+
+ *interruptRecognised =
+ (ndisAdap->RxTxBufferState != MADGE_RXTX_INITIALIZED)
+ ? TRUE
+ : ndisAdap->DprRequired;
+
+ *queueDPR = ndisAdap->DprRequired;
+
+ ndisAdap->DprRequired = FALSE;
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - MadgeSyncSRBPending
+|
+| Parameters - synchonizedContext -> A pointer to an NDIS3 level adapter
+| structure.
+|
+| Purpose - Process a completed SRBs. This routine is always
+| syncronised with IRQs.
+|
+| Returns - TRUE if the SRB has actually completed or FALSE if not.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MadgeSyncSRBPending(PVOID synchronizeContext)
+{
+ PMADGE_ADAPTER ndisAdap;
+ BOOLEAN retCode;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(synchronizeContext);
+ retCode = ndisAdap->UsedInISR.SrbRequestCompleted;
+
+ if (retCode)
+ {
+ ndisAdap->UsedInISR.SrbRequestCompleted = FALSE;
+ ndisAdap->SrbRequestStatus = ndisAdap->UsedInISR.SrbRequestStatus;
+ }
+
+ return retCode;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeHandleInterrupt
+*
+* Parameters - adapterContext -> Pointer to our NDIS level adapter
+* structure.
+*
+* Purpose - Our DPR routine.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeHandleInterrupt(NDIS_HANDLE adapterContext)
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
+
+ //
+ // Must do anything if we don't have tx/rx buffers.
+ //
+
+ if (ndisAdap->RxTxBufferState != MADGE_RXTX_INITIALIZED)
+ {
+ return;
+ }
+
+ //
+ // I think this check is a bit paranoid. I think DPRs are guaranteed
+ // to be single threaded. I suppose it might be needed on a multi-
+ // processor. Just 'cos your've paraonoid doesn't mean they're not
+ // out to get you!
+ //
+
+ if (!ndisAdap->DprInProgress)
+ {
+ ndisAdap->DprInProgress = TRUE;
+
+ //
+ // Handle completed SRBs first.
+ //
+
+ if (NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MadgeSyncSRBPending,
+ adapterContext))
+ {
+ MadgeCompletePendingRequest(ndisAdap);
+ }
+
+ //
+ // If the adapter has been removed then call the housekeeping
+ // function.
+ //
+
+ if (ndisAdap->AdapterRemoved)
+ {
+ rxtx_adapter_removed(ndisAdap->FtkAdapterHandle);
+ }
+
+ //
+ // Check for transmit completions.
+ //
+
+ rxtx_irq_tx_completion_check(
+ ndisAdap->FtkAdapterHandle,
+ adapter_record[ndisAdap->FtkAdapterHandle]
+ );
+
+ //
+ // See if there are any received frames.
+ //
+
+ driver_get_outstanding_receive(ndisAdap->FtkAdapterHandle);
+
+ ndisAdap->DprInProgress = FALSE;
+ }
+
+ //
+ // This else should never be executed!
+ //
+
+ else
+ {
+ MadgePrint1("DPR reentered!!!!\n");
+ }
+}
+
+/******** End of DISPATCH.C ************************************************/
+
diff --git a/private/ntos/ndis/madge/driver/drv_err.c b/private/ntos/ndis/madge/driver/drv_err.c
new file mode 100644
index 000000000..a254c8669
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/drv_err.c
@@ -0,0 +1,555 @@
+/****************************************************************************
+*
+* DRV_ERR.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* THE ERROR EXPLANATION MODULE
+*
+* Copyright (c) Madge Networks Ltd. 1991-1993
+*
+* COMPANY CONFIDENTIAL
+*
+*****************************************************************************
+*
+* The driver module provides a simple interface to allow the use of
+* Fastmac in as general a setting as possible. It handles the downloading
+* of the Fastmac code and the initialization of the adapter card. It
+* provides simple transmit and receive routines. It is desgined to
+* quickly allow the implementation of Fastmac applications. It is not
+* designed as the fastest or most memory efficient solution.
+*
+* The DRV_ERR.C module contains the routine to explain the cause of errors
+* when other driver routines fail.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL VARIABLES
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_tab.h"
+
+/****************************************************************************
+*
+* driver_explain_error
+* ====================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter for which the error has occured.
+*
+* BYTE * returned_error_type
+*
+* The byte pointed to is filled in with a value representing the type of
+* error that has occured. If no error has actually occured it is filled in
+* woth the value zero (0).
+*
+* BYTE * returned_error_value
+*
+* The byte pointed to is filled in with a value representing the
+* particular error of a given type that has occured. If no error has
+* actually occured it is filled in with the value zero (0).
+*
+* char * * returned_error_message
+*
+* This pointer, on exit, points to a string containing a message
+* describing the error that has occured. If no error has actually occured
+* then it points to a null message.
+*
+* BODY :
+* ======
+*
+* The driver_explain_error routine returns details of the most recent
+* error to occur using a given adapter.
+*
+* RETURNS :
+* =========
+*
+* The routine returns a boolean value indicating whether the error is
+* fatal or not. If the error is fatal (returns FALSE) then the adapter can
+* not be used subsequently except via a call to driver_remove_adapter.
+* However, the adapter can, after a call to driver_remove_adapter, be
+* initialized again etc.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_explain_error)
+#endif
+
+export WBOOLEAN
+driver_explain_error(
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * returned_error_type,
+ BYTE * returned_error_value,
+ char * * returned_error_message
+ )
+{
+
+ ERROR_MESSAGE_RECORD * err_msg_record;
+ char * err_msg_header;
+ ADAPTER * adapter;
+ ERROR_RECORD * adapter_error_record;
+
+
+ if (adapter_handle >= MAX_NUMBER_OF_ADAPTERS)
+ {
+ /*
+ * Adapter handle is invalid if greater than max number of adapters.
+ */
+
+ *returned_error_type = ERROR_TYPE_DRIVER;
+ *returned_error_value = DRIVER_E_01_INVALID_HANDLE;
+
+ /*
+ * Set up returned error msg to point to special string.
+ * No adapter structure so can not use error message adapter field.
+ */
+
+#ifdef FTK_NO_ERROR_MESSAGES
+ *returned_error_message = "";
+#else
+ *returned_error_message = drv_err_msg_1;
+#endif
+ /*
+ * This is a fatal error.
+ */
+
+ return FALSE;
+ }
+
+ if (adapter_record[adapter_handle] == NULL)
+ {
+ /*
+ * Adapter handle is invalid when no adapter structure for handle.
+ * Caused by either the adapter handle being invalid or
+ * the call to sys_alloc_adapter_structure having failed.
+ * Fill in returned error type and value.
+ */
+
+ *returned_error_type = ERROR_TYPE_DRIVER;
+ *returned_error_value = DRIVER_E_02_NO_ADAP_STRUCT;
+
+ /*
+ * Set up returned error msg to point to special string.
+ * No adapter structure so can not use error message adapter field.
+ */
+
+#ifdef FTK_NO_ERROR_MESSAGES
+ *returned_error_message = "";
+#else
+ *returned_error_message = drv_err_msg_2;
+#endif
+ /*
+ * This is a fatal error.
+ */
+
+ return FALSE;
+ }
+
+ /*
+ * Now know adapter handle is valid. Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Get pointer to error record for adapter.
+ */
+
+ adapter_error_record = &adapter->error_record;
+
+ /*
+ * Check for special case when no error has actually occured.
+ */
+
+ if (adapter_error_record->type == ERROR_TYPE_NONE)
+ {
+ /*
+ * Fill in returned error type and value as zero.
+ */
+
+ *returned_error_type = 0;
+ *returned_error_value = 0;
+
+ /*
+ * Set the returned error message string to be null.
+ * If no error then adapter error message field must be null.
+ */
+
+#ifdef FTK_NO_ERROR_MESSAGES
+ *returned_error_message = "";
+#else
+ *returned_error_message = adapter->error_message.string;
+#endif
+
+ /*
+ * This is a non-fatal 'error'.
+ */
+
+ return TRUE;
+ }
+
+ /*
+ * Now know have genuine error recorded by FTK. Fill in
+ * returned error type and value.
+ */
+
+ *returned_error_type = adapter_error_record->type;
+ *returned_error_value = adapter_error_record->value;
+
+#ifdef FTK_NO_ERROR_MESSAGES
+ *returned_error_message = "";
+#else
+
+ /*
+ * All error messages are got from error message tables.
+ * First get error message header. Note it is known that
+ * *returned_error_type is valid here.
+ */
+
+ err_msg_header = error_msg_headers_table[(*returned_error_type) - 1];
+
+ /*
+ * Copy error message header to error message in adapter structure.
+ */
+
+ util_string_copy(adapter->error_message.string, err_msg_header);
+
+ /*
+ * Get pointer to correct error message table for rest of message.
+ */
+
+ err_msg_record = list_of_error_msg_tables[(*returned_error_type) - 1];
+
+ /*
+ * Search for required error message within table. Table ends with
+ * special marked entry. So if error message not found will use
+ * "Unknown error" message.
+ */
+
+ while (err_msg_record->value != ERR_MSG_UNKNOWN_END_MARKER)
+ {
+ if (err_msg_record->value == *returned_error_value)
+ {
+ break;
+ }
+ err_msg_record++;
+ }
+
+ /*
+ * Concatenate error message onto end of error header in
+ * error message field of adapter structure.
+ */
+
+ util_string_concatenate(
+ adapter->error_message.string,
+ err_msg_record->err_msg_string
+ );
+
+ /*
+ * Set up return pointer to error message.
+ */
+
+ *returned_error_message = adapter->error_message.string;
+
+#endif
+
+ /*
+ * Return FALSE for fatal errors.
+ */
+
+ if (macro_fatal_error(*returned_error_type))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Return TRUE for non-fatal errors.
+ */
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* driver_check_version
+* ====================
+*
+* PARAMETERS :
+* ============
+*
+* UINT * returned_version_number
+*
+* The returned version number is zero (0) if the version numbers of all
+* the FTK modules do not match correctly. If they do, then the returned
+* version number is the real version number mutiplied by 100 (eg. 1.01
+* becomes 101).
+*
+*
+* BODY :
+* ======
+*
+* The driver_check_version routine checks the version number consistency
+* of the FTK by looking at all the different code modules and header
+* files.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if the version numbers are consistent.
+* Otherwise, it returns FALSE.
+*
+****************************************************************************/
+
+/*
+ * Marker at end of version number array.
+ */
+
+#define VERSION_NUMBERS_END_MARK 0xFFFF
+
+/*
+ * Version number array containing version numbers of ALL header files.
+ */
+
+local UINT version_number[] =
+{
+ FTK_VERSION_NUMBER_FTK_ADAP_H,
+ FTK_VERSION_NUMBER_FTK_AT_H,
+ FTK_VERSION_NUMBER_FTK_CARD_H,
+ FTK_VERSION_NUMBER_FTK_DOWN_H,
+ FTK_VERSION_NUMBER_FTK_EISA_H,
+ FTK_VERSION_NUMBER_FTK_PCI_H,
+ FTK_VERSION_NUMBER_FTK_PCMC_H,
+ FTK_VERSION_NUMBER_FTK_PNP_H,
+ FTK_VERSION_NUMBER_FTK_ERR_H,
+ FTK_VERSION_NUMBER_FTK_FM_H,
+ FTK_VERSION_NUMBER_FTK_INIT_H,
+ FTK_VERSION_NUMBER_FTK_MACR_H,
+ FTK_VERSION_NUMBER_FTK_MC_H,
+ FTK_VERSION_NUMBER_FTK_SRB_H,
+ FTK_VERSION_NUMBER_FTK_TAB_H,
+ FTK_VERSION_NUMBER_FTK_USER_H,
+ FTK_VERSION_NUMBER_DRV_ERR_H,
+ FTK_VERSION_NUMBER_DRV_INIT_H,
+ FTK_VERSION_NUMBER_DRV_IRQ_H,
+ FTK_VERSION_NUMBER_DRV_MISC_H,
+ FTK_VERSION_NUMBER_DRV_SRB_H,
+ FTK_VERSION_NUMBER_DRV_RXTX_H,
+ FTK_VERSION_NUMBER_HWI_GEN_H,
+ FTK_VERSION_NUMBER_HWI_AT_H,
+ FTK_VERSION_NUMBER_HWI_EISA_H,
+ FTK_VERSION_NUMBER_HWI_MC_H,
+ FTK_VERSION_NUMBER_HWI_PCI_H,
+ FTK_VERSION_NUMBER_HWI_PCMC_H,
+ FTK_VERSION_NUMBER_HWI_PNP_H,
+ FTK_VERSION_NUMBER_SYS_ALLO_H,
+ FTK_VERSION_NUMBER_SYS_BUFF_H,
+ FTK_VERSION_NUMBER_SYS_DMA_H,
+ FTK_VERSION_NUMBER_SYS_IRQ_H,
+ FTK_VERSION_NUMBER_SYS_MEM_H,
+ FTK_VERSION_NUMBER_SYS_TIME_H,
+ FTK_VERSION_NUMBER_SYS_PCI_H,
+ FTK_VERSION_NUMBER_SYS_CS_H,
+ FTK_VERSION_NUMBER_USER_H,
+ FTK_VERSION_NUMBER_UTIL_H,
+ VERSION_NUMBERS_END_MARK};
+
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_check_version)
+#endif
+
+export WBOOLEAN
+driver_check_version(
+ UINT * returned_version_number
+ )
+{
+ UINT i;
+
+ /*
+ * Check for consistent version number.
+ */
+
+ i = 0;
+
+ while (version_number[i+1] != VERSION_NUMBERS_END_MARK)
+ {
+ if (version_number[i] != version_number[i + 1])
+ {
+ /*
+ * Inconsistent version numbers so return failure.
+ */
+
+ *returned_version_number = 0;
+ return FALSE;
+ }
+
+ i++;
+ }
+
+ /*
+ * Version numbers are consistent so return version number and success.
+ */
+
+ *returned_version_number = version_number[0];
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* driver_check_adapter
+* ====================
+*
+* The driver_check_adapter routine is called at the beginning of every
+* driver routine, except driver_remove_adapter and driver_prepare_adapter,
+* in order to check the validity of the adapter handle. It also checks
+* that the adapter is in the correct operative state, and that the SRB
+* associated with the adapter is in the correct state (if any particular
+* state is required).
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_check_adapter)
+#endif
+
+export WBOOLEAN
+driver_check_adapter(
+ ADAPTER_HANDLE adapter_handle,
+ UINT required_adapter_status,
+ UINT required_srb_status
+ )
+{
+ ADAPTER * adapter;
+
+ /*
+ * Adapter handle is invalid if greater than max number of adapter.
+ * Can not set up error record but see driver_explain_error.
+ */
+
+ if (adapter_handle >= MAX_NUMBER_OF_ADAPTERS)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Adapter handle is invalid when no adapter structure for handle.
+ * Can not set up error record but see driver_explain_error.
+ */
+
+ if (adapter_record[adapter_handle] == NULL)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * If fatal error already exists for adapter then fail. Do not not
+ * change error code in this case. Fatal errors are - driver, hwi,
+ * init, bring-up, adapter, auto_open.
+ */
+
+ if (macro_fatal_error(adapter->error_record.type))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Check if status of adapter is that required.
+ */
+
+ if (adapter->adapter_status != required_adapter_status)
+ {
+ if (required_adapter_status == ADAPTER_PREPARED_FOR_START)
+ {
+ /*
+ * Required adapter status is ADAPTER_PREPARED_FOR_START.
+ * Fill in error record and fail.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_07_NOT_PREPARED;
+
+ return FALSE;
+ }
+ else
+ {
+ /*
+ * Required adapter status is ADAPTER_RUNNING.
+ * Fill in error record and fail.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_08_NOT_RUNNING;
+
+ return FALSE;
+ }
+ }
+
+ /*
+ * Check if status of SRB is that required. Only do if particular
+ * state is needed.
+ */
+
+ if ((required_srb_status != SRB_ANY_STATE) &&
+ (adapter->srb_status != required_srb_status))
+ {
+ if (required_srb_status == SRB_FREE)
+ {
+ /*
+ * Required srb status is SRB_FREE fill in error record
+ * and fail.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_09_SRB_NOT_FREE;
+
+ return FALSE;
+ }
+ else
+ {
+ /*
+ * Never require srb status to be SRB_NOT_FREE.
+ */
+ }
+ }
+
+ /*
+ * Adapter handle and status are okay so complete successfully.
+ */
+
+ return TRUE;
+}
+
+
+/******** End of DRV_ERR.C *************************************************/
diff --git a/private/ntos/ndis/madge/driver/drv_init.c b/private/ntos/ndis/madge/driver/drv_init.c
new file mode 100644
index 000000000..28539f67c
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/drv_init.c
@@ -0,0 +1,1656 @@
+/****************************************************************************
+*
+* DRV_INIT.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* THE DRIVER MODULE (INITIALIZE / REMOVE)
+*
+* Copyright (c) Madge Networks Ltd. 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+*****************************************************************************
+*
+* The driver module provides a simple interface to allow the use of
+* Fastmac in as general a setting as possible. It handles the downloading
+* of the Fastmac code and the initialization of the adapter card. It
+* provides simple transmit and receive routines. It is desgined to
+* quickly allow the implementation of Fastmac applications. It is not
+* designed as the fastest or most memory efficient solution.
+*
+* The DRV_INIT.C module contains the routines necessary to initialize
+* Fastmac and the adapter and remove, ie. terminate usage of, the
+* adapter. Upon adapter initialization the user is returned a handle
+* which is used to identify the adapter in all future accesses to the
+* driver module.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL FUNCTIONS
+|
+---------------------------------------------------------------------------*/
+
+local WBOOLEAN
+driver_wait_for_adapter_open(
+ UINT * open_status,
+ ADAPTER * adapter
+ );
+
+local WORD
+driver_get_max_frame_size(
+ ADAPTER * adapter,
+ FASTMAC_INIT_PARMS * fastmac_parms
+ );
+
+/*---------------------------------------------------------------------------
+|
+| GLOBAL VARIABLES
+|
+---------------------------------------------------------------------------*/
+
+export ADAPTER * adapter_record[MAX_NUMBER_OF_ADAPTERS] = {NULL};
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* driver_probe_card
+* =================
+*
+*
+* PARAMETERS :
+* ============
+*
+* WORD adapter_card_bus_type
+*
+* The bus type (card family) the adapters for which to search. e.g.
+* ADAPTER_CARD_ATULA_BUS_TYPE or ADAPTER_CARD_EISA_BUS_TYPE.
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is an array of IO locations to examine for the presence
+* of an adapter. For ATULA based adapters with should be a subset of
+* {0x0a20, 0x1a20, 0x2a20, 0x3a20}.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_atula_probe_card routine is called by hwi_probe_adapter. It
+* probes the adapter card for information such as DMA channel, IRQ number
+* etc. This information can then be supplied by the user when starting the
+* adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE
+* if there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(driver_probe_adapter)
+#endif
+
+export UINT
+driver_probe_adapter(
+ WORD adapter_card_bus_type,
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ )
+{
+ return hwi_probe_adapter(
+ adapter_card_bus_type,
+ resources,
+ length,
+ valid_locations,
+ number_locations
+ );
+}
+
+
+/****************************************************************************
+*
+* driver_deprobe_adapter
+* ======================
+*
+* PARAMETERS :
+* ============
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* BODY :
+* ======
+*
+* This function frees any resources that were claimed by a call to
+* driver_probe_adapter. Every valid PROBE structure returned by
+* driver_probe_adapter MUST be passed to driver_deprobe adapter otherwise
+* resources that were claimed from the operating system by
+* driver_probe_adapter (such as PCMCIA sockets) will not be freed.
+*
+* RETURNS :
+* =========
+*
+* TRUE if everything worked or FALSE if it did not.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_deprobe_adapter)
+#endif
+
+export WBOOLEAN
+driver_deprobe_adapter(
+ PROBE * resources,
+ UINT length
+ )
+{
+ return hwi_deprobe_adapter(
+ resources,
+ length
+ );
+}
+
+#endif
+
+/****************************************************************************
+*
+* driver_prepare_adapter
+* ======================
+*
+*
+* PARAMETERS :
+* ============
+*
+* PREPARE_ARGS * arguments
+*
+* This is a pointer to the arguments structure set up by the user code.
+*
+* ADAPTER_HANDLE * returned_adapter_handle
+*
+* An adapter handle is returned that is used for all subsequent calls to
+* the driver to identify the particular adapter.
+*
+* BODY :
+* ======
+*
+* The driver_prepare_adapter routine firstly sets up the adapter structure
+* for this adapter. Then it gets memory for the status information
+* structure that is filled in by driver_get_status calls. It then
+* requests memory for the Fastmac transmit and receive buffers. This memory
+* must be static, it must not be swapped out to disk because of DMA issues.
+*
+* This routine should be called once for every adapter that is to have
+* Fastmac used on it.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the returned
+* adapter handle will give an explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(driver_prepare_adapter)
+#endif
+
+export WBOOLEAN
+driver_prepare_adapter(
+ PREPARE_ARGS * arguments,
+ ADAPTER_HANDLE * returned_adapter_handle
+ )
+{
+ ADAPTER_HANDLE adapter_handle;
+ ADAPTER * adapter;
+ FASTMAC_INIT_PARMS * fastmac_parms;
+ WORD i;
+
+ /*
+ * Set up adapter handle which is an index to an array of pointers.
+ * Find first a pointer not yet used.
+ */
+
+ for (i = 0; i < MAX_NUMBER_OF_ADAPTERS; i++)
+ {
+ if (adapter_record[i] == NULL)
+ {
+ break;
+ }
+ }
+
+ /*
+ * Set up returned adapter handle ( = index to adapter structure).
+ * returned_adapter_handle is set up here before any failure.
+ * This is so can use adapter handle for call to driver_explain_error.
+ */
+
+ adapter_handle = (ADAPTER_HANDLE) i;
+ *returned_adapter_handle = adapter_handle;
+
+ /*
+ * If all pointers to adapter structures are used then return error.
+ * Can not set up error record but see driver_explain_error.
+ */
+
+ if (i == MAX_NUMBER_OF_ADAPTERS)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get memory for adapter structure.
+ */
+
+ adapter_record[adapter_handle] = (ADAPTER *)
+ sys_alloc_adapter_structure(adapter_handle, sizeof(ADAPTER));
+
+ /*
+ * Check that the memory allocation was successful. Can not set up
+ * error record but see driver_explain_error.
+ */
+
+ if (adapter_record[adapter_handle] == NULL)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Remember pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Zero adapter structure memory.
+ */
+
+ util_zero_memory((BYTE *) adapter, sizeof(ADAPTER));
+
+ /*
+ * Save handle, so that HWI routines that need it can find it.
+ */
+
+ adapter->adapter_handle = adapter_handle;
+
+ /*
+ * Save the user's private information for the users sys_ functions.
+ */
+
+ adapter->user_information = arguments->user_information;
+
+#ifdef FMPLUS
+
+ /*
+ * Allocate memory for the FastMAC Plus to do its DMA tests.
+ * This is now a byte longer to allocate the byte used
+ * to handshake the DMA on a PCI(T) card with broken DMA.
+ */
+
+ if (!sys_alloc_dma_phys_buffer(
+ adapter_handle,
+ SCB_TEST_PATTERN_LENGTH + SSB_TEST_PATTERN_LENGTH + 1,
+ &(adapter->dma_test_buf_phys),
+ &(adapter->dma_test_buf_virt)))
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_12_FAIL_ALLOC_DMA_BUF;
+
+ return FALSE;
+ }
+
+#endif
+
+ /*
+ * Indicate no errors have occured for this adapter yet.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_NONE;
+
+ /*
+ * Get memory for status information structure.
+ */
+
+ adapter->status_info = (STATUS_INFORMATION *)
+ sys_alloc_status_structure(adapter_handle,sizeof(STATUS_INFORMATION));
+
+ /*
+ * Check that the memory allocation was successful.
+ */
+
+ if (adapter->status_info == NULL)
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_03_FAIL_ALLOC_STATUS;
+
+ return FALSE;
+ }
+
+ /*
+ * Zero status information structure memory.
+ */
+
+ util_zero_memory(
+ (BYTE *) adapter->status_info,
+ sizeof(STATUS_INFORMATION)
+ );
+
+ /*
+ * Get memory for initialization block.
+ */
+
+ adapter->init_block = (INITIALIZATION_BLOCK *)
+ sys_alloc_init_block(adapter_handle, sizeof(INITIALIZATION_BLOCK));
+
+ /*
+ * Check that the memory allocation was successful.
+ */
+
+ if (adapter->init_block == NULL)
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_04_FAIL_ALLOC_INIT;
+
+ return FALSE;
+ }
+
+ /*
+ * Zero initialization block memory.
+ */
+
+ util_zero_memory(
+ (BYTE *) adapter->init_block,
+ sizeof(INITIALIZATION_BLOCK)
+ );
+
+ /*
+ * Get pointer to Fastmac init parameters for this adapter.
+ */
+
+ fastmac_parms = &adapter->init_block->fastmac_parms;
+
+ /*
+ * Ensure that the fastmac_parms->features reserved bits and the
+ * fastmac_parms->int_flags reserved bits are zero (bits 4,11-15
+ * of features, and bits 3-15 of int_flags).
+ * (In fact they will be already from the above util_zero_memory.)
+ */
+
+ /*
+ * Now fill in all of the hardware independant non-zero fields in the
+ * Fastmac part of init block.
+ */
+
+ /*
+ * Check that the frame size requested in within the bounds
+ * of possibility.
+ */
+
+ if (arguments->max_frame_size < MIN_FRAME_SIZE ||
+ arguments->max_frame_size > MAX_FRAME_SIZE_16_MBITS)
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_13_BAD_FRAME_SIZE;
+
+ return FALSE;
+ }
+
+ /*
+ * Make a note of the maximum frame size requested.
+ */
+
+ fastmac_parms->max_frame_size = arguments->max_frame_size;
+
+
+#ifndef FMPLUS
+
+ /*
+ * Set up the header.
+ */
+
+ fastmac_parms->header.length = sizeof(FASTMAC_INIT_PARMS);
+ fastmac_parms->header.signature = FASTMAC_INIT_HEADER_SIGNATURE;
+ fastmac_parms->header.version = FASTMAC_INIT_HEADER_VERSION;
+
+ /*
+ * Now set up the interrupt options.
+ */
+
+#ifdef FTK_TX_WITH_COMPLETION
+ fastmac_parms->int_flags |= INT_FLAG_TX_BUF_EMPTY;
+#endif
+
+ /*
+ * Check have sensible value for Fastmac receive buffer size.
+ */
+
+ if ((arguments->receive_buffer_byte_size < FASTMAC_MINIMUM_BUFFER_SIZE) ||
+ (arguments->receive_buffer_byte_size > FASTMAC_MAXIMUM_BUFFER_SIZE))
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_0A_RX_BUF_BAD_SIZE;
+
+ return FALSE;
+ }
+
+ /*
+ * Get memory for the receive buffer.
+ */
+
+ if (!sys_alloc_dma_phys_buffer(
+ adapter_handle,
+ arguments->receive_buffer_byte_size,
+ &adapter->rx_buffer_phys,
+ &adapter->rx_buffer_virt))
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_05_FAIL_ALLOC_RX_BUF;
+
+ return FALSE;
+ }
+
+ fastmac_parms->rx_buf_physaddr = adapter->rx_buffer_phys;
+
+ /*
+ * Check that Fastmac receive buffer begins on a DWORD boundary.
+ */
+
+ if ((fastmac_parms->rx_buf_physaddr & 0x00000003) != 0L)
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_0B_RX_BUF_NOT_DWORD;
+
+ return FALSE;
+ }
+
+ /*
+ * Fill in Fastmac receive buffer size.
+ */
+
+ fastmac_parms->rx_buf_size = arguments->receive_buffer_byte_size;
+
+ /*
+ * Check have sensible value for Fastmac transmit buffer size.
+ */
+
+ if ((arguments->transmit_buffer_byte_size < FASTMAC_MINIMUM_BUFFER_SIZE) ||
+ (arguments->transmit_buffer_byte_size > FASTMAC_MAXIMUM_BUFFER_SIZE))
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_0C_TX_BUF_BAD_SIZE;
+
+ return FALSE;
+ }
+
+ /*
+ * Get memory for the transmit buffer.
+ */
+
+ if (!sys_alloc_dma_phys_buffer(
+ adapter_handle,
+ arguments->receive_buffer_byte_size,
+ &adapter->tx_buffer_phys,
+ &adapter->tx_buffer_virt))
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_06_FAIL_ALLOC_TX_BUF;
+
+ return FALSE;
+ }
+
+ fastmac_parms->tx_buf_physaddr = adapter->tx_buffer_phys;
+
+ /*
+ * Check that Fastmac transmit buffer begins on a DWORD boundary.
+ */
+
+ if ((fastmac_parms->tx_buf_physaddr & 0x00000003) != 0L)
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_0D_TX_BUF_NOT_DWORD;
+
+ return FALSE;
+ }
+
+ /*
+ * Fill in Fastmac transmit buffer size.
+ */
+
+ fastmac_parms->tx_buf_size = arguments->transmit_buffer_byte_size;
+
+ /*
+ * Mark adapter structure as containing details of initialized Fastmac
+ * and indicate that SRB is free.
+ */
+
+ adapter->adapter_status = ADAPTER_PREPARED_FOR_START;
+ adapter->srb_status = SRB_FREE;
+
+#else
+
+ /*
+ * Set set up the header.
+ */
+
+ fastmac_parms->header.length = sizeof(FASTMAC_INIT_PARMS);
+ fastmac_parms->header.signature = FMPLUS_INIT_HEADER_SIGNATURE;
+ fastmac_parms->header.version = FMPLUS_INIT_HEADER_VERSION;
+
+ /*
+ * Now set up the interrupt options.
+ */
+
+#ifdef FTK_RX_OUT_OF_INTERRUPTS
+ fastmac_parms->int_flags |= INT_FLAG_RX;
+#endif
+
+#ifdef FTK_RX_BY_SCHEDULED_PROCESS
+ fastmac_parms->int_flags |= INT_FLAG_RX;
+#endif
+
+#ifdef FTK_TX_WITH_COMPLETION
+ fastmac_parms->int_flags |= INT_FLAG_LARGE_DMA;
+#endif
+
+ /*
+ * Now fill in the number of slots that are required. These are user
+ * specified, since the numbers are host dependent (each slot must have
+ * a maximum frame sized buffer on the host).
+ */
+
+ if (arguments->number_of_rx_slots < FMPLUS_MIN_RX_SLOTS ||
+ arguments->number_of_rx_slots > FMPLUS_MAX_RX_SLOTS)
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_10_BAD_RX_SLOT_NUMBER;
+
+ return FALSE;
+ }
+
+ fastmac_parms->rx_slots = arguments->number_of_rx_slots;
+
+ if (arguments->number_of_tx_slots < FMPLUS_MIN_TX_SLOTS ||
+ arguments->number_of_tx_slots > FMPLUS_MAX_TX_SLOTS)
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_11_BAD_TX_SLOT_NUMBER;
+
+ return FALSE;
+ }
+
+ fastmac_parms->tx_slots = arguments->number_of_tx_slots;
+
+ /*
+ * Allocate the receive slot buffers.
+ */
+
+ if (!rxtx_allocate_rx_buffers(
+ adapter,
+ arguments->max_frame_size,
+ arguments->number_of_rx_slots
+ ))
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_05_FAIL_ALLOC_RX_BUF;
+
+ return FALSE;
+ }
+
+ /*
+ * Allocate the transmit slot buffers.
+ */
+
+ if (!rxtx_allocate_tx_buffers(
+ adapter,
+ arguments->max_frame_size,
+ arguments->number_of_tx_slots
+ ))
+ {
+ adapter->error_record.type = ERROR_TYPE_DRIVER;
+ adapter->error_record.value = DRIVER_E_06_FAIL_ALLOC_TX_BUF;
+
+ return FALSE;
+ }
+
+ /*
+ * Mark adapter structure as containing details of initialized Fastmac
+ * and indicate that SRB is free.
+ */
+
+ adapter->adapter_status = ADAPTER_PREPARED_FOR_START;
+ adapter->srb_status = SRB_FREE;
+
+#endif
+
+ /*
+ * Complete successfully.
+ */
+
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* driver_start_adapter
+* ====================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter to be initialized. This should be a
+* handle returned by a call to driver_prepare_adapter.
+*
+* START_ARGS * arguments
+*
+* This is a pointer to the arguments structure set up by the user code.
+*
+* NODE_ADDRESS * returned_permanent_address
+*
+* The node address pointed to is always filled in with the BIA PROM node
+* address of the adapter. This is so the user of the FTK can fill in MAC
+* headers etc. with the source node address (unless the user has supplied
+* an opening address to driver_prepare_adapter which they should then use
+* instead).
+*
+*
+* BODY :
+* ======
+*
+* The driver_start_adapter routine is called once per adapter after a call
+* to driver_prepare_adapter. It takes the user supplied adapter
+* information and passes it in a form usable by the HWI so that the HWI
+* can install and then initialize the adapter (that is initialize
+* registers on the card, download the Fastmac image and set up the IRQ and
+* DMA channels if necessary). After initialization, this routine waits for
+* the adapter to open if the auto-open option is enabled.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(driver_start_adapter)
+#endif
+
+export WBOOLEAN
+driver_start_adapter(
+ ADAPTER_HANDLE adapter_handle,
+ START_ARGS * arguments,
+ NODE_ADDRESS * returned_permanent_address
+ )
+{
+ ADAPTER * adapter;
+ FASTMAC_INIT_PARMS * fastmac_parms;
+ WBOOLEAN init_success;
+ WORD max_frame_size;
+ UINT i;
+#ifdef FMPLUS
+ RX_SLOT * next_rx_slot;
+ TX_SLOT * next_tx_slot;
+ RX_SLOT * * rx_slot_array;
+ TX_SLOT * * tx_slot_array;
+ UINT slot_index;
+#endif
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter(
+ adapter_handle,
+ ADAPTER_PREPARED_FOR_START,
+ SRB_ANY_STATE
+ ))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Fill user supplied info into adapter structure.
+ */
+
+ adapter->mmio_base_address = arguments->mmio_base_address;
+ adapter->adapter_card_bus_type = arguments->adapter_card_bus_type;
+ adapter->io_location = arguments->io_location;
+ adapter->dma_channel = arguments->dma_channel;
+ adapter->transfer_mode = arguments->transfer_mode;
+ adapter->interrupt_number = arguments->interrupt_number;
+ adapter->set_dma = arguments->set_dma_channel;
+ adapter->set_irq = arguments->set_interrupt_number;
+ adapter->set_ring_speed = arguments->set_ring_speed;
+ adapter->download_image = arguments->code;
+ adapter->pci_handle = arguments->pci_handle;
+
+
+#ifdef FMPLUS
+
+ /*
+ * Need these values later.
+ */
+
+ rx_slot_array = adapter->rx_slot_array;
+ tx_slot_array = adapter->tx_slot_array;
+
+#endif
+
+ /*
+ * Call the HWI routine to install the adapter. This also downloads
+ * the Fastmac image to the adapter. If routine fails return failure
+ * (error record already filled in). DMA and IRQ are only enabled
+ * if hwi_install_adapter succeeds.
+ */
+
+ /*
+ * WARNING: we must mark the adapter as running NOW, before downloading
+ * the microcode, because on AT cards in PIO mode ONLY, bring
+ * up diagnostics on the card fail when carrying out DMA tests.
+ * This occurs because the interrupt handling routine ignores
+ * all interrupts from the card until it is marked as running,
+ * but this unfortunately masks off PIO interrupts too.
+ */
+
+ /*
+ * Mark adapter structure that adapter is now going to be running.
+ * Hence hwi_interrupt_entry will check adapter for interrupts
+ */
+
+ adapter->adapter_status = ADAPTER_RUNNING;
+
+ if (!hwi_install_adapter(adapter, adapter->download_image))
+ {
+ /*
+ * Now that initial installation has failed, we can turn off the
+ * above indication that the card is running.
+ */
+
+ adapter->adapter_status = ADAPTER_PREPARED_FOR_START;
+
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to Fastmac init parameters for this adapter.
+ */
+
+ fastmac_parms = &adapter->init_block->fastmac_parms;
+
+ /*
+ * Now fill in max frame size in init block that Fastmac should support.
+ * This is based on the size of the Fastmac buffers and
+ * max frame size supported by adapter because of ring speed. We
+ * put the requested max frame is into fastmac_parms->max_frame_size
+ * in driver_prepare_adapter.
+ */
+
+ max_frame_size = driver_get_max_frame_size(adapter, fastmac_parms);
+
+ fastmac_parms->max_frame_size =
+ min(max_frame_size, fastmac_parms->max_frame_size);
+
+ /*
+ * Write the actual max frame size back up to the caller, so they know
+ * what it is too.
+ */
+
+ arguments->max_frame_size = fastmac_parms->max_frame_size;
+
+
+#ifdef FMPLUS
+
+ /*
+ * Set up the user selected RX/TX buffer size. This will be changed
+ * in hwi_gen.c if the value given is not sensible.
+ */
+
+ adapter->init_block->smart_parms.rx_tx_buffer_size =
+ arguments->rx_tx_buffer_size;
+
+#endif
+
+ /*
+ * If auto open option is on then put necessary info into init block.
+ */
+
+ if (arguments->auto_open_option)
+ {
+#ifndef FMPLUS
+
+ /*
+ * Use delay_rx to prevent race condition occuring whereby
+ * on auto-open an interrupt could occur before the host
+ * code has had a chance to read the location of the status
+ * block on the card. The other half of the code to fix this
+ * problem is in driver_start_adapter, where the ARB is freed.
+ */
+
+ fastmac_parms->feature_flags =
+ FEATURE_FLAG_AUTO_OPEN | FEATURE_FLAG_DELAY_RX;
+
+#else
+
+ fastmac_parms->feature_flags = FEATURE_FLAG_AUTO_OPEN;
+
+#endif
+
+ fastmac_parms->open_options = arguments->open_options;
+
+ /*
+ * Check if auto-opening node address is set (ie. not all zeroes).
+ */
+
+ for (i = 0; i < sizeof(NODE_ADDRESS); i++)
+ {
+ if (arguments->opening_node_address.byte[i] != 0)
+ {
+ break;
+ }
+ }
+
+ /*
+ * If opening node address not set up use BIA PROM address.
+ */
+
+ if (i == sizeof(NODE_ADDRESS))
+ {
+ fastmac_parms->open_address = adapter->permanent_address;
+ }
+ else
+ {
+ fastmac_parms->open_address = arguments->opening_node_address;
+ }
+
+ fastmac_parms->group_address = arguments->opening_group_address;
+ fastmac_parms->functional_address = arguments->opening_functional_address;
+ }
+
+ /*
+ * Call the HWI routine to initialize the adapter. This downloads the
+ * init block to the adapter. Leaves EAGLE_SIFADRX=0x0001 so driver
+ * never use extended SIF regs. If routine fails return failure
+ * (error record already filled in).
+ */
+
+ if (!hwi_initialize_adapter(adapter, adapter->init_block))
+ {
+ return FALSE;
+ }
+
+ /*
+ * At this stage the actual adapter card type is known.
+ * Get the IO location of the first SIF register for the adapter.
+ * Inform the system about the IO ports we are going to access.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Get the DIO addresses of the Fastmac SSB and STB (ststus block).
+ * Only use non-extended SIF regs (EAGLE_SIFADR and EAGLE_SIFDAT_INC).
+ * Hence can use same code for all adapter card types.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_SRB_POINTER);
+
+ adapter->srb_dio_addr = (SRB_HEADER *) (card_t)
+ sys_insw(adapter_handle, adapter->sif_datinc);
+
+ sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_STB_POINTER);
+
+ adapter->stb_dio_addr = (FASTMAC_STATUS_BLOCK *) (card_t)
+ sys_insw(adapter_handle, adapter->sif_datinc);
+
+#ifndef FMPLUS
+
+ /*
+ * In the case of auto-open :
+ * Free the ARB to enable data to be received from here on... This only
+ * occurs now because it is only now that we know where to look for the
+ * pointers in the status block that will tell us whether data has come
+ * in or not.
+ */
+
+ if (arguments->auto_open_option)
+ {
+ sys_outsw(adapter_handle, adapter->sif_int, EAGLE_ARB_FREE_CODE);
+ }
+
+#else
+
+ /*
+ * Now recover the receive slot and transmit slot chains.
+ */
+
+ /*
+ * Start with the receive slot chain. We must poll the location in the
+ * status block that holds the start address until it is non-zero. It
+ * is then safe to run down the chain finding the other slots.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) &adapter->stb_dio_addr->rx_slot_start
+ );
+
+ /*
+ * Poll this address until it is non-zero.
+ */
+
+ do
+ {
+ rx_slot_array[0] = (RX_SLOT *) (card_t)
+ sys_insw(adapter_handle, adapter->sif_dat);
+ }
+ while (rx_slot_array[0] == 0);
+
+ /*
+ * Recover all the other slots by running down the chain.
+ */
+
+ slot_index = 0;
+
+ do
+ {
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) &rx_slot_array[slot_index]->next_slot
+ );
+
+ next_rx_slot = (RX_SLOT *) (card_t)
+ sys_insw(adapter_handle, adapter->sif_dat);
+
+ if (next_rx_slot != rx_slot_array[0])
+ {
+ rx_slot_array[++slot_index] = next_rx_slot;
+ }
+ }
+ while (next_rx_slot != rx_slot_array[0]);
+
+ /*
+ * Now do the same for the transmit slots.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) &adapter->stb_dio_addr->tx_slot_start
+ );
+
+ /*
+ * Poll this address until it is non-zero.
+ */
+
+ do
+ {
+ tx_slot_array[0] = (TX_SLOT *) (card_t)
+ sys_insw(adapter_handle, adapter->sif_dat);
+ }
+ while (tx_slot_array[0] == 0);
+
+ /*
+ * Now recover all the other slots by running down the chain.
+ */
+
+ slot_index = 0;
+
+ do
+ {
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) &tx_slot_array[slot_index]->next_slot
+ );
+
+ next_tx_slot = (TX_SLOT *) (card_t)
+ sys_insw(adapter_handle, adapter->sif_dat);
+
+ if (next_tx_slot != tx_slot_array[0])
+ {
+ tx_slot_array[++slot_index] = next_tx_slot;
+ }
+ }
+ while (next_tx_slot != tx_slot_array[0]);
+
+ /*
+ * Now that we have the slot locations on the card, we can associate
+ * buffers with each of them. The user needs to supply a routine that
+ * set up the slots from the host buffers previously allocated as
+ * we don't enforce an organisation on the allocation of multiple
+ * slot buffers. We tell the user routine if it should program the
+ * adapter slots with physical addresses (for DMA) or virtual
+ * addresses (for PIO or MMIO).
+ */
+
+
+ rxtx_setup_rx_buffers(
+ adapter,
+ (WBOOLEAN) (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE),
+ fastmac_parms->rx_slots
+ );
+
+
+ rxtx_setup_tx_buffers(
+ adapter,
+ (WBOOLEAN) (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE),
+ fastmac_parms->tx_slots
+ );
+
+#endif
+
+ /*
+ * Let the system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+
+ /*
+ * Check that Fastmac has correctly installed. Do this by reading
+ * node address from Fastmac status block. If routine fails return
+ * failure (error record already filled in). Note for EISA cards,
+ * this is actually first time get node address.
+ */
+
+ if (!hwi_get_node_address_check(adapter))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Copy permanent BIA PROM node address into user supplied node address.
+ */
+
+ *returned_permanent_address = adapter->permanent_address;
+
+ /*
+ * If the auto open option is on then wait to see if adapter opens okay.
+ * Enable and disable accessing IO locations around check.
+ * If adapter open routine fails then error record already filled in.
+ */
+
+ if (arguments->auto_open_option)
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter);
+#endif
+
+ init_success = driver_wait_for_adapter_open(
+ &(arguments->open_status),
+ adapter
+ );
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+ }
+ else
+ {
+ init_success = TRUE;
+ }
+
+ /*
+ * Initialization completed.
+ */
+
+ return init_success;
+}
+
+#ifdef FMPLUS
+
+/****************************************************************************
+*
+* driver_start_receive_process
+* ============================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter to be initialized. This should be a
+* handle returned by a call to driver_prepare_adapter.
+*
+* BODY :
+* ======
+*
+* The driver_start_adapter routine is called once per adapter after a call
+* to driver_start_adapter. It uses the supplied handle to identify which
+* adapter it should affect : by writing a zero into the Fastmac Plus init-
+* ialization block on the adapter (as specified in the manual), the card
+* will start to receive frames and pass them up to the host.
+*
+* NOTE: If SRBs are going to be used, this MUST be called first.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(driver_start_receive_process)
+#endif
+
+export WBOOLEAN
+driver_start_receive_process(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+
+ /*
+ * Adapter handle is invalid if greater than max number of adapters.
+ * Can not set up error record but see driver_explain_error.
+ */
+
+ if (adapter_handle >= MAX_NUMBER_OF_ADAPTERS)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Adapter handle is invalid when no adapter structure for handle.
+ * Can not set up error record but see driver_explain_error.
+ */
+
+ if (adapter_record[adapter_handle] == NULL)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Inform the system about the IO ports we are going to access.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Let's fire off the receive process from here then...
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) &adapter->stb_dio_addr->rx_slot_start
+ );
+
+ sys_outsw(adapter_handle, adapter->sif_dat, 0);
+
+ /*
+ * Let the system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ return TRUE;
+}
+
+#endif
+
+/****************************************************************************
+*
+* driver_remove_adapter
+* =====================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter to be removed.
+*
+* BODY :
+* ======
+*
+* The driver_remove_adapter routine is written such that, whatever the
+* current state of the adapter, a call to driver_remove_adapter will place
+* the adapter in a state whereby driver_prepare_adapter must be called to
+* start using the adapter once more. Hence, on ANY fatal adapter error, a
+* call to driver_remove adapter is needed before installing the adapter
+* again.
+*
+* The routine calls the HWI to reset the required adapter if the adapter
+* has been running. It also calls certain system routines in order to
+* free the memory used by the Fastmac receive and transmit buffers as well
+* as that used by the adapter structure. However, it only does this when
+* the allocate calls were successful.
+*
+* RETURNS :
+* =========
+*
+* The routine always succeeds. Even if the adapter handle is invalid then
+* the routine does not fail it just does nothing.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_remove_adapter)
+#endif
+
+export WBOOLEAN
+driver_remove_adapter(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+ FASTMAC_INIT_PARMS * fastmac_parms;
+
+ /*
+ * Adapter handle is invalid if greater than max number of adapters.
+ * Can not set up error record but see driver_explain_error.
+ */
+
+ if (adapter_handle >= MAX_NUMBER_OF_ADAPTERS)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Adapter handle is invalid when no adapter structure for handle.
+ * Can not set up error record but see driver_explain_error.
+ */
+
+ if (adapter_record[adapter_handle] == NULL)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Call the HWI routine to kill the adapter (DMA channel, IRQ number).
+ * Only call it if either DMA or interrupts are enabled at adapter.
+ * Note in this case the actual adapter card type is known.
+ */
+
+ if (adapter->interrupts_on || adapter->dma_on)
+ {
+ hwi_remove_adapter(adapter);
+ }
+
+ /*
+ * Free all memory that was allocated for handling use of this adapter.
+ * Includes Fastmac buffers, init block and adapter structure.
+ * Only free memory if allocate memory calls were successful.
+ */
+
+ if (adapter->init_block != NULL)
+ {
+ /*
+ * Initialize variable used for freeing memory.
+ */
+
+ fastmac_parms = &adapter->init_block->fastmac_parms;
+
+#ifndef FMPLUS
+
+ /*
+ * Free transmit buffer space if allocated.
+ */
+
+ if (adapter->tx_buffer_phys != NULL_PHYSADDR)
+ {
+ sys_free_dma_phys_buffer(
+ adapter_handle,
+ fastmac_parms->tx_buf_size,
+ adapter->tx_buffer_phys,
+ adapter->tx_buffer_virt
+ );
+ }
+
+ /*
+ * Free receive buffer space if allocated.
+ */
+
+ if (adapter->rx_buffer_phys != NULL_PHYSADDR)
+ {
+ sys_free_dma_phys_buffer(
+ adapter_handle,
+ fastmac_parms->rx_buf_size,
+ adapter->rx_buffer_phys,
+ adapter->rx_buffer_virt
+ );
+ }
+
+#else
+
+ /*
+ * Free receive buffer space if allocated.
+ */
+
+ rxtx_free_rx_buffers(
+ adapter,
+ fastmac_parms->max_frame_size,
+ fastmac_parms->rx_slots
+ );
+
+ /*
+ * Free transmit buffer space if allocated.
+ */
+
+ rxtx_free_tx_buffers(
+ adapter,
+ fastmac_parms->max_frame_size,
+ fastmac_parms->tx_slots
+ );
+
+#endif
+
+ /*
+ * Free the initialization block allocated memory.
+ */
+
+ sys_free_init_block(
+ adapter_handle,
+ (BYTE *) adapter->init_block,
+ sizeof(INITIALIZATION_BLOCK)
+ );
+ }
+
+ /*
+ * Free status structure if allocated.
+ */
+
+ if (adapter->status_info != NULL)
+ {
+ sys_free_status_structure(
+ adapter_handle,
+ (BYTE *) adapter->status_info,
+ sizeof(STATUS_INFORMATION)
+ );
+ }
+
+#ifdef FMPLUS
+
+ if (adapter->dma_test_buf_virt != 0)
+ {
+ sys_free_dma_phys_buffer(
+ adapter->adapter_handle,
+ SCB_TEST_PATTERN_LENGTH + SSB_TEST_PATTERN_LENGTH + 1,
+ adapter->dma_test_buf_phys,
+ adapter->dma_test_buf_virt
+ );
+ }
+
+#endif
+
+ /*
+ * Already know adapter allocate was successful hence always free it.
+ */
+
+ sys_free_adapter_structure(
+ adapter_handle,
+ (BYTE *) adapter,
+ sizeof(ADAPTER)
+ );
+
+ /*
+ * Clear entry in adapter pointers array.
+ */
+
+ adapter_record[adapter_handle] = NULL;
+
+ /*
+ * Complete successfully.
+ */
+
+ return TRUE;
+}
+
+/*---------------------------------------------------------------------------
+|
+| driver_wait_for_adapter_open
+| ============================
+|
+| The driver_wait_for_adapter_open routine waits at least 40 seconds for
+| the adapter to open. It discovers whether the adapter has opened
+| successfully or not by looking in the Fastmac status block (STB). If the
+| adapter fails to open then this routine fills in the adapter error
+| record.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(driver_wait_for_adapter_open)
+#endif
+
+local WBOOLEAN
+driver_wait_for_adapter_open(
+ UINT * open_status,
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WBOOLEAN open_okay;
+ UINT open_error;
+ UINT index;
+
+ /*
+ * Wait at least a total of 40 seconds for adapter to open.
+ */
+
+ for (index = 0; index < 160; index++)
+ {
+ /*
+ * Set up DIO address to open status field in STB (status block).
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) &adapter->stb_dio_addr->adapter_open
+ );
+
+ /*
+ * Read open status field from DIO space. If successfully
+ * opened then complete successfully.
+ */
+
+ open_okay = (WBOOLEAN) sys_insw(
+ adapter_handle,
+ adapter->sif_datinc
+ );
+
+ if (open_okay)
+ {
+ *open_status = EAGLE_OPEN_ERROR_SUCCESS;
+ return TRUE;
+ }
+
+ /*
+ * If not opened, see if an error has occured to prevent opening.
+ */
+
+ open_error = sys_insw(adapter_handle, adapter->sif_datinc);
+ *open_status = open_error;
+
+ if (open_error != EAGLE_OPEN_ERROR_SUCCESS)
+ {
+ adapter->error_record.type = ERROR_TYPE_AUTO_OPEN;
+ adapter->error_record.value = AUTO_OPEN_E_01_OPEN_ERROR;
+
+ return FALSE;
+ }
+
+ /*
+ * Opening procedure not completed. Wait at least 250 milliseconds
+ * before checkig again. Disable and re-enable accessing IO locations
+ * around wait so delay can reschedule this task and not effect others
+ * running.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+
+ sys_wait_at_least_milliseconds(250);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter);
+#endif
+
+ }
+
+ /*
+ * At least 40 seconds have gone so return time out failure.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_AUTO_OPEN;
+ adapter->error_record.value = AUTO_OPEN_E_80_TIME_OUT;
+
+ return FALSE;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| driver_get_max_frame_size
+| =========================
+|
+| The driver_get_max_frame_size routine calculates the maximum sized frame
+| that can be transmitted or received. This calculation is based on the
+| maximum frame size determined by ring speed alone, the size of the
+| Fastmac buffers, and the fact that Fastmac pointers have to be DWORD
+| aligned.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(driver_get_max_frame_size)
+#endif
+
+local WORD
+driver_get_max_frame_size(
+ ADAPTER * adapter,
+ FASTMAC_INIT_PARMS * fastmac_parms
+ )
+{
+#ifdef FMPLUS
+
+ return adapter->max_frame_size;
+
+#else
+
+ WORD tx_max_frame_size;
+ WORD rx_max_frame_size;
+ WORD max_frame_size;
+
+ /*
+ * Calculate max transmit frame size from size of buffer, size of
+ * header and knowing that one frame must leave space such that host
+ * and adapter ptrs into buffer are not the same.
+ */
+
+ tx_max_frame_size =
+ fastmac_parms->tx_buf_size - macro_dword_align(
+ FASTMAC_BUFFER_HEADER_SIZE +
+ fastmac_parms->tx_buf_space +
+ sizeof(DWORD)
+ );
+
+ /*
+ * Calculate max receive frame size from size of buffer, size of
+ * header and knowing that one frame must leave space such that host
+ * and adapter ptrs into buffer are not the same.
+ */
+
+ rx_max_frame_size =
+ fastmac_parms->rx_buf_size - macro_dword_align(
+ FASTMAC_BUFFER_HEADER_SIZE +
+ fastmac_parms->rx_buf_space +
+ sizeof(DWORD)
+ );
+
+ /*
+ * Actual max frame size is minimum of max transmit and receive frame
+ * sizes and max frame size for adapter (ring speed dependent).
+ */
+
+ max_frame_size = util_minimum(
+ tx_max_frame_size,
+ rx_max_frame_size,
+ adapter->max_frame_size
+ );
+
+ return max_frame_size;
+
+#endif
+}
+
+/**** End of DRV_INIT.C file ***********************************************/
diff --git a/private/ntos/ndis/madge/driver/drv_irq.c b/private/ntos/ndis/madge/driver/drv_irq.c
new file mode 100644
index 000000000..5d484aa61
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/drv_irq.c
@@ -0,0 +1,413 @@
+/****************************************************************************
+*
+* DRV_IRQ.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* THE DRIVER MODULE (INTERRUPT HANDLE)
+*
+* Copyright (c) Madge Networks Ltd. 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+*****************************************************************************
+*
+* The driver module provides a simple interface to allow the use of
+* Fastmac in as general a setting as possible. It handles the downloading
+* of the Fastmac code and the initialization of the adapter card. It
+* provides simple transmit and receive routines. It is desgined to
+* quickly allow the implementation of Fastmac applications. It is not
+* designed as the fastest or most memory efficient solution.
+*
+* DRV_IRQ.C contains code to handle SIF interrupts from the adapter card.
+* The HWI_ modules take care of any PIO interrupts, and anything else is
+* passed here. There is also code for calling the received frame handler
+* from the foreground task rather than at interrupt time.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+/****************************************************************************
+*
+* driver_interrupt_entry
+* ======================
+*
+* PARAMETERS (passed by hwi_<card_type>_sif_interrupt) :
+* ======================================================
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* The adapter handle for the adapter so it can be passed to the user
+* supplied user_receive_frame or user_completed_srb routine.
+*
+* ADAPTER * adapter
+*
+* The details of the adapter that the interrupt has occured on.
+*
+* WORD sifint_actual
+*
+* The actual contents of the EAGLE SIF interrupt register.
+*
+* BODY :
+* ======
+*
+* The driver_interupt_entry routine is called by the HWI. It is entered
+* when an interrupt has occured for the given adapter. This could be
+* because of an SRB free interrupt, an adapter chack interrupt or because
+* frames are in the Fastmac receive buffer. Note these frames may have
+* been in the receive buffer some time but not yet dealt with.
+*
+* On an SRB free interrupt, the interrupt is acknowledged and the
+* driver_completing_srb routine in DRV_SRB.C is called. This results in
+* the user supplied routine user_completed_srb being called informing the
+* user on the success or failure of the current SRB and letting the user
+* know that another SRB can be issued.
+*
+* On adapter check interrupts, the error record for the adapter is filled
+* in to mark the adapter as no longer working. A call to a user function
+* is made in case higher level code needs to take action.
+*
+* On receive frame interrupts, the action taken depends on the receive
+* method being used. In FTK_RX_BY_SCHEDULED_PROCESS mode, the user routine
+* user_schedule_receive_process is called with the adapter handle as the
+* only parameter. It is the job of this user routine to schedule a process
+* to call driver_get_outstanding_receive to get the received frames out of
+* the Fastmac receive buffer. In FTK_RX_OUT_OF_INTERRUPTS mode, the received
+* frames are dealt with immediately via the rxtx_irq_rx_frame_handler
+* routine and the user supplied receive routine user_receive_frame.
+*
+* The rxtx_irq_rx_frame_handler routine is actually the same routine
+* that is called by the driver_get_outstanding_receive routine if the
+* FTK_RX_BY_SCHEDULED_PROCESS receive method is being used.
+*
+*
+* Note on increasing speed:
+*
+* One way of speeding up execution of the receive routine would be to
+* replace the sys_outsw and sys_insw routines by similar routines supplied
+* with your C compiler and have them compiled in-line.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always succeeds and returns control to the HWI routine
+* hwi_<type>_sif_interrupt.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(driver_interrupt_entry)
+#endif
+
+export void
+driver_interrupt_entry(
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter,
+ WORD sifint_actual
+ )
+{
+ WORD sifint_value;
+ WBOOLEAN ack_needed = FALSE;
+
+ /*
+ * XOR the high byte and low byte of contents of EAGLE_SIFINT register.
+ */
+
+ sifint_value = (sifint_actual & 0x00FF) ^ (sifint_actual >> 8);
+
+ /*
+ * AND with 0x000F so left with a nibble identifying interrupt type.
+ */
+
+ sifint_value = sifint_value & 0x000F;
+
+ /*
+ * Action depends on interrupt type.
+ */
+
+ if (sifint_value != 0)
+ {
+ if ((sifint_value & FASTMAC_SIFINT_ADAPTER_CHECK) != 0)
+ {
+ /*
+ * For adapter check, fill in error record so adapter now dead.
+ * No need to check if any other interrupt bits set.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_ADAPTER;
+ adapter->error_record.value = ADAPTER_E_01_ADAPTER_CHECK;
+
+ /*
+ * Allow the user to give some sort of warning.
+ */
+
+ user_handle_adapter_check(adapter_handle);
+ }
+ else
+ {
+ if ((sifint_value & FASTMAC_SIFINT_SRB_FREE) != 0)
+ {
+ /*
+ * For SRB free interrupts, call routine which informs user.
+ */
+
+ driver_completing_srb(adapter_handle, adapter);
+ ack_needed = TRUE;
+ }
+
+ if ((sifint_value & FASTMAC_SIFINT_ARB_COMMAND) != 0)
+ {
+ /*
+ * For ARB command interrupts, do nothing as
+ * they should never happen.
+ */
+
+ ack_needed = TRUE;
+ }
+
+ if ((sifint_value & FASTMAC_SIFINT_SSB_RESPONSE) != 0)
+ {
+ /*
+ * For SSB response interrupts, do nothing as
+ * they should never happen.
+ */
+
+ ack_needed = TRUE;
+ }
+ }
+ }
+
+ /*
+ * Now check for receives and transmits...
+ */
+
+#ifdef FMPLUS
+
+ /*
+ * For Fastmac Plus, we must allow for the possibility that the
+ * interrupt is because a large transmit buffer DMA is complete.
+ */
+
+#ifdef FTK_TX_WITH_COMPLETION
+
+#ifndef FTK_NO_TX_COMPLETION_CALL
+
+ rxtx_irq_tx_completion_check(adapter_handle, adapter);
+
+#endif
+
+#endif
+
+#endif
+
+ /*
+ * Invoke received frame processing based on the receive mode.
+ */
+
+#ifdef FTK_RX_OUT_OF_INTERRUPTS
+
+ rxtx_irq_rx_frame_handler(adapter_handle, adapter);
+
+#endif
+
+#ifdef FTK_RX_BY_SCHEDULED_PROCESS
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ user_schedule_receive_process(adapter_handle);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+#endif
+
+ /*
+ * Now do any cleaning up that is needed ...
+ * For certain interrupts, need to interrupt Fastmac to acknowledge.
+ */
+
+ if (ack_needed)
+ {
+ /*
+ * Convert from FASTMAC_SIFINT interrupt into DRIVER_SIFINT_ACK
+ * to acknowledge interrupt.
+ */
+
+ sifint_value = (sifint_value << 8);
+
+ /*
+ * Set interrupt adapter bit in SIFCMD.
+ */
+
+ sifint_value = (sifint_value | DRIVER_SIFINT_IRQ_FASTMAC);
+
+ /*
+ * Mask SIFSTS so not clear interrupt if Fastmac interrupted again.
+ */
+
+ sifint_value = (sifint_value | DRIVER_SIFINT_FASTMAC_IRQ_MASK);
+
+ /*
+ * Interrupt Fastmac.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_int, sifint_value);
+ }
+
+ /*
+ * Return to hwi_interrupt_entry routine.
+ */
+}
+
+/****************************************************************************
+*
+* driver_get_outstanding_receive
+* ==============================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter which we wish to deal with
+* outstanding received frames on.
+*
+* BODY :
+* ======
+*
+* The driver_get_outstanding_receive routine should be called only when
+* using the FTK_RX_BY_SCHEDULED_PROCESS receive method. The user supplied
+* receive routine (user_receive_frame) is called with the adapter handle
+* and the length and a physical address pointer to the oldest unprocessed
+* received frame for the given adapter. If there are no oustanding
+* received frames the user routine is never called but this is not an
+* error and is not regsitered as such.
+*
+* If the receive routine processes the frame (returns DO_NOT_KEEP_FRAME),
+* and if the Fastmac receive buffer is not empty, the receive routine is
+* called again with the details of the next frame. This continues until
+* either the Fastmac buffer is empty or the receive routine does not
+* process the frame (returns KEEP_FRAME). However, no more than one buffer
+* full of frames is passed to the user receive routine on any one entry to
+* driver_get_outstanding_receive. Note that if the receive buffer is not
+* emptied by the user then another interrupt will occur later and the
+* process that calls driver_get_outstanding_receive will be rescheduled.
+*
+* To deal with the details of handling received frames in the Fastmac
+* buffers, this routine uses rxtx_irq_rx_frame_handler. This is the
+* same routine called out of driver_interrupt_entry if the
+* FTK_RX_OUT_OF_INTERRUPTS receive method is being used. The routine uses
+* an algorithm for dealing with received frames similar to that in the
+* Fastmac specification document.
+*
+* Dealing with received frames using the driver_get_outstanding_receive
+* routine is different to using the driver_interrupt_entry routine in that
+* the former routine is called under user control, in strategy time as
+* opposed to interrupt time, and hence gives the user receive frame
+* routine more time to process frames. This is necessary under certain
+* operating systems such as AIX.
+*
+* Notes on increasing speed:
+*
+* The code between "#ifndef SPEED_ABOVE_TESTING" to "#endif" is only for
+* testing purposes. If SPEED_ABOVE_TESTING is defined during compilation
+* then the code will not be included so the receive routine will execute
+* faster. However, an erroneous adapter handle would then cause a program
+* to crash unpredicatably. The SPEED_ABOVE_TESTING option should be used
+* with care.
+*
+* Another way of speeding up execution of the receive routine would be to
+* replace the sys_outsw and sys_insw routines by similar routines supplied
+* with your C compiler and have them compiled in-line.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation. Note that it will not fail just
+* because there are no frames to receive.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_get_outstanding_receive)
+#endif
+
+export WBOOLEAN
+driver_get_outstanding_receive(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+#ifndef SPEED_ABOVE_TESTING
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_ANY_STATE))
+ {
+ return FALSE;
+ }
+
+#endif
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Inform the system about the IO ports we are going to access.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Perform the actual frame receiving uses same routine called out
+ * of interrupts with FTK_RX_OUT_OF_INTERRUPTS.
+ */
+
+ rxtx_irq_rx_frame_handler(adapter_handle, adapter);
+
+ /*
+ * Let the system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ /*
+ * Receive completed.
+ */
+
+ return TRUE;
+}
+
+
+/**** End of DRV_IRQ.C file ************************************************/
diff --git a/private/ntos/ndis/madge/driver/drv_srb.c b/private/ntos/ndis/madge/driver/drv_srb.c
new file mode 100644
index 000000000..cd84d70d3
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/drv_srb.c
@@ -0,0 +1,1849 @@
+/****************************************************************************
+*
+* DRV_SRB.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* THE DRIVER MODULE (SRBs)
+*
+* Copyright (c) Madge Networks Ltd. 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+*****************************************************************************
+*
+* The driver module provides a simple interface to allow the use of
+* Fastmac in as general a setting as possible. It handles the downloading
+* of the Fastmac code and the initialization of the adapter card. It
+* provides simple transmit and receive routines. It is desgined to
+* quickly allow the implementation of Fastmac applications. It is not
+* designed as the fastest or most memory efficient solution.
+*
+* The DRV_SRB.C module contains those routines that involve issuing SRBs,
+* such as open adapter and set functional address. It also contains the
+* code that calls the user when an SRB completes.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+/*---------------------------------------------------------------------------
+|
+| GLOBAL VARIABLES
+|
+---------------------------------------------------------------------------*/
+
+export char ftk_product_inst_id[SIZEOF_PRODUCT_ID] = FASTMAC_PRODUCT_ID;
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL FUNCTIONS
+|
+---------------------------------------------------------------------------*/
+
+local void
+driver_issue_srb(
+ ADAPTER * adapter
+ );
+
+local WBOOLEAN
+get_open_and_ring_status(
+ void * ptr
+ );
+
+local WBOOLEAN
+issue_srb(
+ void * ptr
+ );
+
+/****************************************************************************
+*
+* driver_ring_speed
+* =================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter whose ring speed is to be returned.
+*
+* BODY :
+* ======
+*
+* This is a short helper function (that could easily be replaced by a
+* macro). It just digs out the stored ring speed from the adapter
+* structure, so that external users of the FTK have some way of getting at
+* this piece of information.
+*
+* RETURNS :
+* =========
+*
+* The current ring speed.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_ring_speed)
+#endif
+
+export UINT
+driver_ring_speed(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ return adapter_record[adapter_handle]->ring_speed;
+}
+
+/****************************************************************************
+*
+* driver_max_frame_size
+* =====================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter whose maximum supported frame size is
+* to be returned.
+*
+* BODY :
+* ======
+*
+* This is a short helper function (that could easily be replaced by a
+* macro). It just digs out the stored maximum frame size from the adapter
+* structure, so that external users of the FTK have some way of getting at
+* this piece of information.
+*
+* RETURNS :
+* =========
+*
+* The current maximum frame size.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_max_frame_size)
+#endif
+
+export UINT
+driver_max_frame_size(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ return adapter_record[adapter_handle]->max_frame_size;
+}
+
+/****************************************************************************
+*
+* driver_modify_open_options
+* ==========================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter on which to modify the open options.
+*
+* WORD open_options
+*
+* This gives the new modified open options for the adapter.
+*
+* BODY :
+* ======
+*
+* The driver_modify_open_options routine issues a modify open parms SRB.
+* The adapter must be open for this command to complete successfully. It
+* does not matter whether the adapter has been opened in auto-open mode or
+* using an open adapter SRB.
+*
+* As with all the routines that involve issuing SRBs, the user routine
+* user_completed_srb is called when the SRB completes. It is this user
+* routine that is informed as to whether the SRB completed successfully.
+* Also, until this routine is called by the driver, no other driver
+* routines involving the issuing of SRBs for the given adapter will work.
+* This is because there is only one SRB per adapter.
+*
+* Note that only those fields that are used in the SRB (ie. have non-zero
+* values) that need to be byte swapped are byte swapped either in this
+* routine or in driver_issue_srb. Hence, if any adjustments are made to
+* the code it may be necessary to make sure that any newly used fields are
+* correctly byte swapped before downloading.
+*
+* Take special note of the fact that the user_completed_srb routine can be
+* called before this routine completes. This is because it is called out
+* of interrupts.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+* Note that a successful call to this routine only means that the SRB has
+* been issued successfully. It does not mean that it has completed
+* successfully. The success or failure of the SRB is indicated in a
+* subsequent call to user_completed_srb.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_modify_open_options)
+#endif
+
+export WBOOLEAN
+driver_modify_open_options(
+ ADAPTER_HANDLE adapter_handle,
+ WORD open_options
+ )
+{
+ ADAPTER * adapter;
+ SRB_GENERAL * srb_gen;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Set adapter SRB status to show that SRB is now in use.
+ */
+
+ adapter->srb_status = SRB_NOT_FREE;
+
+ /*
+ * Get pointer to general SRB structure to be used.
+ */
+
+ srb_gen = &adapter->srb_general;
+
+ /*
+ * Clear part of general SRB to be used.
+ */
+
+ util_zero_memory((BYTE *) srb_gen, sizeof(SRB_MODIFY_OPEN_PARMS));
+
+ /*
+ * Set up non-zero modify open parms SRB fields.
+ */
+
+ srb_gen->mod_parms.header.function = MODIFY_OPEN_PARMS_SRB;
+ srb_gen->mod_parms.open_options = open_options;
+
+ /*
+ * Save a copy of the open options in the fastmac init block, in
+ * case we later have to re-open the adapter with the same state. This
+ * is the case with NDIS3 MacReset(), which causes the card to be re-
+ * initialized, but the open options must be left as they were before
+ * the reset.
+ */
+
+ adapter->init_block->fastmac_parms.open_options = open_options;
+
+ /*
+ * Record size of SRB that is being issued.
+ */
+
+ adapter->size_of_srb = sizeof(SRB_MODIFY_OPEN_PARMS);
+
+ /*
+ * Call routine to issue SRB.
+ */
+
+ driver_issue_srb(adapter);
+
+ /*
+ * SRB issued successfully.
+ */
+
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* driver_open_adapter
+* ===================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter to be opened.
+*
+* PTR_OPEN_DATA open_data
+*
+* This points to a structure containing : the open options, the opening
+* node address, the opening functional address, and the opening group
+* address. If the opening node address is NULL, the BIA PROM node address
+* will be used instead.
+*
+* BODY :
+* ======
+*
+* The driver_open_adapter routine issues an open adapter SRB. This routine
+* is not needed when the Fastmac auto_open option is used.
+*
+* As with all the routines that involve issuing SRBs, the user routine
+* user_completed_srb is called when the SRB completes. It is this user
+* routine that is informed as to whether the SRB completed successfully.
+* Also, until this routine is called by the driver, no other driver
+* routines involving the issuing of SRBs for the given adapter will work.
+* This is because there is only one SRB per adapter.
+*
+* Note that only those fields that are used in the SRB (ie. have non-zero
+* values) that need to be byte swapped are byte swapped either in this
+* routine or in driver_issue_srb. Hence, if any adjustments are made to
+* the code it may be necessary to make sure that any newly used fields are
+* correctly byte swapped before downloading.
+*
+* Take special note of the fact that the user_completed_srb routine can be
+* called before this routine completes. This is because it is called out
+* of interrupts.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+* Note that a successful call to this routine only means that the SRB has
+* been issued successfully. It does not mean that it has completed
+* successfully. The success or failure of the SRB is indicated in a
+* subsequent call to user_completed_srb.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_open_adapter)
+#endif
+
+export WBOOLEAN
+driver_open_adapter(
+ ADAPTER_HANDLE adapter_handle,
+ PTR_OPEN_DATA open_data
+ )
+{
+ ADAPTER * adapter;
+ SRB_GENERAL * srb_gen;
+ UINT i;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter( adapter_handle, ADAPTER_RUNNING, SRB_FREE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Set adapter SRB status to show that SRB is now in use.
+ */
+
+ adapter->srb_status = SRB_NOT_FREE;
+
+ /*
+ * get pointer to general SRB structure to be used.
+ */
+
+ srb_gen = &adapter->srb_general;
+
+ /*
+ * Clear part of general SRB to be used.
+ */
+
+ util_zero_memory((BYTE *) srb_gen, sizeof(SRB_OPEN_ADAPTER));
+
+ /*
+ * Set up non-zero open adapter SRB fields.
+ */
+
+ srb_gen->open_adap.header.function = OPEN_ADAPTER_SRB;
+ srb_gen->open_adap.open_options = open_data->open_options;
+
+ /*
+ * Fill in opening node address field.
+ */
+
+ for (i = 0; i < sizeof(NODE_ADDRESS); i++)
+ {
+ if (open_data->opening_node_address.byte[i] != 0)
+ {
+ break;
+ }
+ }
+
+ if (i == sizeof(NODE_ADDRESS))
+ {
+ /*
+ * If opening node address not given then use BIA PROM address.
+ */
+
+ srb_gen->open_adap.open_address = adapter->permanent_address;
+ }
+ else
+ {
+ /*
+ * Otherwise use supplied node address.
+ */
+
+ srb_gen->open_adap.open_address = open_data->opening_node_address;
+ }
+
+ srb_gen->open_adap.group_address = open_data->group_address;
+ srb_gen->open_adap.functional_address = open_data->functional_address;
+
+ /*
+ * Byte swap node address before downloading to adapter.
+ */
+
+ util_byte_swap_structure(
+ (BYTE *) &srb_gen->open_adap.open_address,
+ sizeof(NODE_ADDRESS)
+ );
+
+ /*
+ * Fill in the product id with product ID string.
+ */
+
+ util_mem_copy(
+ srb_gen->open_adap.product_id,
+ ftk_product_inst_id,
+ SIZEOF_PRODUCT_ID
+ );
+
+ /*
+ * Byte swap the product id string before downloading.
+ */
+
+ util_byte_swap_structure(
+ (BYTE *) srb_gen->open_adap.product_id,
+ SIZEOF_PRODUCT_ID
+ );
+
+ /*
+ * Record size of SRB that is being issued.
+ */
+
+ adapter->size_of_srb = sizeof(SRB_OPEN_ADAPTER);
+
+ /*
+ * Call routine to issue SRB.
+ */
+
+ driver_issue_srb(adapter);
+
+ /*
+ * SRB issued successfully.
+ */
+
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* driver_close_adapter
+* ====================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter to be closed.
+*
+*
+* BODY :
+* ======
+*
+* The driver_close_adapter routine issues a close adapter SRB. If the
+* auto_open feature is being used then it is disabled by this call.
+*
+* As with all the routines that involve issuing SRBs, the user routine
+* user_completed_srb is called when the SRB completes. It is this user
+* routine that is informed as to whether the SRB completed successfully.
+* Also, until this routine is called by the driver, no other driver
+* routines involving the issuing of SRBs for the given adapter will work.
+* This is because there is only one SRB per adapter.
+*
+* Note that only those fields that are used in the SRB (ie. have non-zero
+* values) that need to be byte swapped are byte swapped either in this
+* routine or in driver_issue_srb. Hence, if any adjustments are made to
+* the code it may be necessary to make sure that any newly used fields are
+* correctly byte swapped before downloading.
+*
+* Take special note of the fact that the user_completed_srb routine can be
+* called before this routine completes. This is because it is called out
+* of interrupts.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+* Note that a successful call to this routine only means that the SRB has
+* been issued successfully. It does not mean that it has completed
+* successfully. The success or failure of the SRB is indicated in a
+* subsequent call to user_completed_srb.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_close_adapter)
+#endif
+
+export WBOOLEAN
+driver_close_adapter(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+ SRB_GENERAL * srb_gen;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Set adapter SRB status to show that SRB is now in use.
+ */
+
+ adapter->srb_status = SRB_NOT_FREE;
+
+ /*
+ * Get pointer to general SRB structure to be used.
+ */
+
+ srb_gen = &adapter->srb_general;
+
+ /*
+ * Clear part of general SRB to be used.
+ */
+
+ util_zero_memory((BYTE *) srb_gen, sizeof(SRB_CLOSE_ADAPTER));
+
+ /*
+ * Place SRB type into header.
+ */
+
+ srb_gen->close_adap.header.function = CLOSE_ADAPTER_SRB;
+
+ /*
+ * Record size of SRB that is being issued.
+ */
+
+ adapter->size_of_srb = sizeof(SRB_CLOSE_ADAPTER);
+
+ /*
+ * Call routine to issue SRB.
+ */
+
+ driver_issue_srb(adapter);
+
+ /*
+ * SRB issued successfully.
+ */
+
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* driver_set_group_address
+* ========================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the required adapter.
+*
+* MULTI_ADDRESS * group_address
+*
+* The adapter is configured to receive frames sent to the group address
+* formed from this parameter with the prefix 0xC000 and logically ANDed
+* with 0x80000000. For example {0x12,0x34,0x56,0x78} gives the group
+* address 0xC00092345678.
+*
+* BODY :
+* ======
+*
+* The driver_set_group_address routine issues a set group address SRB. The
+* adapter must be open for the SRB to complete successfully.
+*
+* As with all the routines that involve issuing SRBs, the user routine
+* user_completed_srb is called when the SRB completes. It is this user
+* routine that is informed as to whether the SRB completed successfully.
+* Also, until this routine is called by the driver, no other driver
+* routines involving the issuing of SRBs for the given adapter will work.
+* This is because there is only one SRB per adapter.
+*
+* Note that only those fields that are used in the SRB (ie. have non-zero
+* values) that need to be byte swapped are byte swapped either in this
+* routine or in driver_issue_srb. Hence, if any adjustments are made to
+* the code it may be necessary to make sure that any newly used fields are
+* correctly byte swapped before downloading.
+*
+* Take special note of the fact that the user_completed_srb routine can be
+* called before this routine completes. This is because it is called out
+* of interrupts.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+* Note that a successful call to this routine only means that the SRB has
+* been issued successfully. It does not mean that it has completed
+* successfully. The success or failure of the SRB is indicated in a
+* subsequent call to user_completed_srb.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_set_group_address)
+#endif
+
+export WBOOLEAN
+driver_set_group_address(
+ ADAPTER_HANDLE adapter_handle,
+ MULTI_ADDRESS * group_address
+ )
+{
+ ADAPTER * adapter;
+ SRB_GENERAL * srb_gen;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Set adapter SRB status to show that SRB is now in use.
+ */
+
+ adapter->srb_status = SRB_NOT_FREE;
+
+ /*
+ * Get pointer to general SRB structure to be used.
+ */
+
+ srb_gen = &adapter->srb_general;
+
+ /*
+ * Clear part of general SRB to be used.
+ */
+
+ util_zero_memory((BYTE *) srb_gen, sizeof(SRB_SET_GROUP_ADDRESS));
+
+ /*
+ * Place SRB type into header.
+ */
+
+ srb_gen->set_group.header.function = SET_GROUP_ADDRESS_SRB;
+
+ /*
+ * Byte swap group address (for downloading) when putting it in SRB.
+ */
+
+ srb_gen->set_group.multi_address = *group_address;
+
+ util_byte_swap_structure(
+ (BYTE *) &srb_gen->set_group.multi_address,
+ sizeof(MULTI_ADDRESS)
+ );
+
+ /*
+ * Record size of SRB that is being issued.
+ */
+
+ adapter->size_of_srb = sizeof(SRB_SET_GROUP_ADDRESS);
+
+ /*
+ * Call routine to issue SRB.
+ */
+
+ driver_issue_srb(adapter);
+
+ /*
+ * SRB issued successfully.
+ */
+
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* driver_set_functional_address
+* =============================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the required adapter.
+*
+* MULTI_ADDRESS * functional_address
+*
+* For each bit set in this parameter, the adapter is configured to receive
+* frames sent to that functional address (0xC000xxxxxxxx). For example, if
+* functional_address equals {0x40,0x00,0x00,0x80} then the corresponding
+* functional addresses are 0xC00040000000 and 0xC00000000080.
+*
+*
+* BODY :
+* ======
+*
+* The driver_set_functional_address routine issues a set functional
+* address SRB. The adapter must be open for the SRB to complete
+* successfully. The effects of this call are not cumulative - that is
+* each call must specify ALL functional addresses required.
+*
+* As with all the routines that involve issuing SRBs, the user routine
+* user_completed_srb is called when the SRB completes. It is this user
+* routine that is informed as to whether the SRB completed successfully.
+* Also, until this routine is called by the driver, no other driver
+* routines involving the issuing of SRBs for the given adapter will work.
+* This is because there is only one SRB per adapter.
+*
+* Note that only those fields that are used in the SRB (ie. have non-zero
+* values) that need to be byte swapped are byte swapped either in this
+* routine or in driver_issue_srb. Hence, if any adjustments are made to
+* the code it may be necessary to make sure that any newly used fields are
+* correctly byte swapped before downloading.
+*
+* Take special note of the fact that the user_completed_srb routine can be
+* called before this routine completes. This is because it is called out
+* of interrupts.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+* Note that a successful call to this routine only means that the SRB has
+* been issued successfully. It does not mean that it has completed
+* successfully. The success or failure of the SRB is indicated in a
+* subsequent call to user_completed_srb.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_set_functional_address)
+#endif
+
+export WBOOLEAN
+driver_set_functional_address(
+ ADAPTER_HANDLE adapter_handle,
+ MULTI_ADDRESS * functional_address
+ )
+{
+ ADAPTER * adapter;
+ SRB_GENERAL * srb_gen;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Set adapter SRB status to show that SRB is now in use.
+ */
+
+ adapter->srb_status = SRB_NOT_FREE;
+
+ /*
+ * Get pointer to general SRB structure to be used.
+ */
+
+ srb_gen = &adapter->srb_general;
+
+ /*
+ * Clear part of general SRB to be used.
+ */
+
+ util_zero_memory((BYTE *) srb_gen, sizeof(SRB_SET_FUNCTIONAL_ADDRESS));
+
+ /*
+ * Place SRB type into header.
+ */
+
+ srb_gen->set_func.header.function = SET_FUNCTIONAL_ADDRESS_SRB;
+
+ /*
+ * Byte swap functional address (for downloading) when putting in SRB.
+ */
+
+ srb_gen->set_func.multi_address = *functional_address;
+
+ util_byte_swap_structure(
+ (BYTE *) &srb_gen->set_func.multi_address,
+ sizeof(MULTI_ADDRESS)
+ );
+
+ /*
+ * Record size of SRB that is being issued.
+ */
+
+ adapter->size_of_srb = sizeof(SRB_SET_FUNCTIONAL_ADDRESS);
+
+ /*
+ * Call routine to issue SRB.
+ */
+
+ driver_issue_srb(adapter);
+
+ /*
+ * SRB issued successfully.
+ */
+
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* driver_get_open_and_ring_status
+* ===============================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter to get the adapter status information
+* on.
+*
+* WORD * pwRingStatus
+* WORD * pwOpenStatus
+*
+* These OUT parameters are filled with the Open and Ring status values in
+* addition to them being written into the status structure. It is often
+* convenient to be able to have these values stored at the callers whim.
+* They can be NULL if the caller does not need these values directly.
+*
+* BODY :
+* ======
+*
+* The driver_get_open_and_ring_status routine accesses DIO space to get
+* the current adapter open status and the current ring status. These two
+* bits of information are filled into the status information structure in
+* the adapter structure, and written to the supplied locations.
+*
+* RETURNS :
+* =========
+*
+* Nothing. But see the status information structure in the current adapter
+* for the open status and ring status.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_get_open_and_ring_status)
+#endif
+
+export void
+driver_get_open_and_ring_status(
+ ADAPTER_HANDLE adapter_handle,
+ WORD * pwRingStatus,
+ WORD * pwOpenStatus
+ )
+{
+ ADAPTER * adapter;
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ if (adapter == NULL)
+ {
+ if (pwRingStatus != NULL)
+ {
+ *pwRingStatus = 0;
+ }
+ if (pwOpenStatus != NULL)
+ {
+ *pwOpenStatus = 0;
+ }
+ return;
+ }
+
+ /*
+ * Inform the system about the IO ports we are going to access.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Get adapter open status from the STB in DIO space.
+ */
+
+ sys_sync_with_interrupt(
+ adapter->adapter_handle,
+ get_open_and_ring_status,
+ adapter);
+
+ /*
+ * Let the system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ if (pwRingStatus != NULL)
+ {
+ *pwRingStatus = adapter->status_info->ring_status;
+ }
+ if (pwOpenStatus != NULL)
+ {
+ *pwOpenStatus = adapter->status_info->adapter_open;
+ }
+}
+
+/****************************************************************************
+*
+* driver_get_status
+* =================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter to get the adapter status information
+* on.
+*
+* BODY :
+* ======
+*
+* The driver_get_status routine issues a read error log SRB in order to
+* get the error log maintained by the protocol handler. This routine also
+* accesses DIO space to get the current adapter open status and the
+* current ring status. These two bits of information are actually filled
+* into the status information structure immediately - they are available
+* before the user_completed_srb routine is called.
+*
+* As with all the routines that involve issuing SRBs, the user routine
+* user_completed_srb is called when the actual SRB completes. It is this
+* user routine that is informed as to whether the SRB completed
+* successfully and it is at this time that the error log is filled into
+* the status information structure. Also, until the user_completed_srb
+* routine is called by the driver, no other driver routines involving the
+* issuing of SRBs for the given adapter will work. This is because there
+* is only one SRB per adapter.
+*
+* Note that only those fields that are used in the SRB (ie. have non-zero
+* values) that need to be byte swapped are byte swapped either in this
+* routine or in driver_issue_srb. Hence, if any adjustments are made to
+* the code it may be necessary to make sure that any newly used fields are
+* correctly byte swapped before downloading.
+*
+* Take special note of the fact that the user_completed_srb routine can be
+* called before this routine completes. This is because it is called out
+* of interrupts.
+*
+* Note there is no need to worry about an interrupt occuring, (between the
+* setting of the EAGLE SIFADR register and the reading/writing of the
+* required DIO space data), that would alter the contents of the EAGLE
+* SIFADR register (and hence the SIFDAT and SIFDAT_INC registers too).
+* This is because the receive frame interrupt handler exits leaving the
+* contents of SIFADR as on entry.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds and will have filled in the
+* requested status information but not the error log. If this routine
+* fails (returns FALSE) then a subsequent call to driver_explain_error
+* with the same adapter handle will give an explanation.
+*
+* Note that a successful call to this routine only means that the SRB has
+* been issued successfully. It does not mean that it has completed
+* successfully. The success or failure of the SRB is indicated in a
+* subsequent call to user_completed_srb. Also, in this particular case, it
+* is important to note that the error log is not filled in until the SRB
+* completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_get_status)
+#endif
+
+export WBOOLEAN
+driver_get_status(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+ SRB_GENERAL * srb_gen;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Get the adapter open status and ring status.
+ */
+
+ driver_get_open_and_ring_status(adapter_handle, NULL, NULL);
+
+ /*
+ * Set adapter SRB status to show that SRB is now in use.
+ */
+
+ adapter->srb_status = SRB_NOT_FREE;
+
+ /*
+ * Get pointer to general SRB structure to be used.
+ */
+
+ srb_gen = &adapter->srb_general;
+
+ /*
+ * Clear part of general SRB to be used.
+ */
+
+ util_zero_memory((BYTE *) srb_gen, sizeof(SRB_READ_ERROR_LOG));
+
+ /*
+ * Place SRB type into header.
+ */
+
+ srb_gen->err_log.header.function = READ_ERROR_LOG_SRB;
+
+ /*
+ * Record size of SRB that is being issued.
+ */
+
+ adapter->size_of_srb = sizeof(SRB_READ_ERROR_LOG);
+
+ /*
+ * Call routine to issue SRB.
+ */
+
+ driver_issue_srb(adapter);
+
+ /*
+ * SRB issued successfully.
+ */
+
+ return TRUE;
+}
+
+
+
+/****************************************************************************
+*
+* driver_set_bridge_parms
+* =======================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter to get the adapter status information
+* on.
+*
+* WBOOLEAN single_route_bcast
+*
+* If this is TRUE, then single route broadcast frames will be rejected
+* by the SRA.
+*
+* UINT this_ring
+*
+* This is the ring number that the SRA will recognise as the source ring.
+* It must be the number of the ring to which this adapter is connected. It
+* will be matched against the source ring field in the routing information
+* section of frames received from this ring.
+*
+* UINT that_ring
+*
+* This is the ring number that the SRA will recognise as the destination
+* ring. It must be the number of the ring to which the other adapter in
+* this host is connected. It will be matched against the target ring field
+* in the routing information section of frames received from the source
+* ring.
+*
+* UINT bridge_num
+*
+* This is the number that identifies this bridge on both rings. It will be
+* matched against the bridge number field in the routing information field
+* of frames received from the source ring.
+*
+* BODY :
+* ======
+*
+* The driver_set_bridge_parms routine issues a set bridge parms SRB.
+* The adapter must be open for the SRB to complete successfully.
+* Two of the fields use default values to simplify the calling procedure a
+* little - these are the number of bridge bits and the maximum length of
+* the routing information field. The number of bridge bits defaults to 4
+* allowing bridge numbers between 0 and 0xF, and ring numbers between 0
+* and 0xFFF. All bridges on the network must agree on this value. The max.
+* routing field causes all frames with routing information fields longer
+* than the specified value to be rejected by the SRA. To be IBM compatible
+* this value should be 18, which is the default value.
+* These values are defined in FTK_SRB.H.
+*
+* As with all the routines that involve issuing SRBs, the user routine
+* user_completed_srb is called when the SRB completes. It is this user
+* routine that is informed as to whether the SRB completed successfully.
+* Also, until this routine is called by the driver, no other driver
+* routines involving the issuing of SRBs for the given adapter will work.
+* This is because there is only one SRB per adapter.
+*
+* Note that only those fields that are used in the SRB (ie. have non-zero
+* values) that need to be byte swapped are byte swapped either in this
+* routine or in driver_issue_srb. Hence, if any adjustments are made to
+* the code it may be necessary to make sure that any newly used fields are
+* correctly byte swapped before downloading.
+*
+* Take special note of the fact that the user_completed_srb routine can be
+* called before this routine completes. This is because it is called out
+* of interrupts.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_set_bridge_parms)
+#endif
+
+export WBOOLEAN
+driver_set_bridge_parms(
+ ADAPTER_HANDLE adapter_handle,
+ WBOOLEAN single_route_bcast,
+ UINT this_ring,
+ UINT that_ring,
+ UINT bridge_num
+ )
+{
+ ADAPTER * adapter;
+ SRB_GENERAL * srb_gen;
+ WORD options;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Set adapter SRB status to show that SRB is now in use.
+ */
+
+ adapter->srb_status = SRB_NOT_FREE;
+
+ /*
+ * Get pointer to general SRB structure to be used.
+ */
+
+ srb_gen = &adapter->srb_general;
+
+ /*
+ * Clear part of general SRB to be used.
+ */
+
+ util_zero_memory((BYTE *) srb_gen, sizeof(SRB_SET_BRIDGE_PARMS));
+
+ /*
+ * Place SRB type into header.
+ */
+
+ srb_gen->set_bridge_parms.header.function = SET_BRIDGE_PARMS_SRB;
+
+ /*
+ * Fill in the bridge parameters, using defaults from FTK_SRB.H and the
+ * user supplied values.
+ *
+ * Note that the bit fields in the options word are filled in here using
+ * shifts and ORs, because of the danger that different compilers will
+ * order bit fields in a structure differently.
+ */
+
+ options = ((single_route_bcast ? 0x8000 : 0)
+ | ((SRB_SBP_DFLT_ROUTE_LEN & 0x3f) << 4)
+ | (SRB_SBP_DFLT_BRIDGE_BITS & 0xf));
+
+ srb_gen->set_bridge_parms.options = options;
+ srb_gen->set_bridge_parms.this_ring = this_ring;
+ srb_gen->set_bridge_parms.that_ring = that_ring;
+ srb_gen->set_bridge_parms.bridge_num = bridge_num;
+
+ /*
+ * Record size of SRB that is being issued.
+ */
+
+ adapter->size_of_srb = sizeof(SRB_SET_BRIDGE_PARMS);
+
+ /*
+ * Call routine to issue SRB.
+ */
+
+ driver_issue_srb(adapter);
+
+ /*
+ * SRB issued successfully.
+ */
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* driver_set_product_instance_id
+* ==============================
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* This handle identifies the adapter on which to set the product instance
+* identification string.
+*
+* BYTE * product_id
+*
+* A pointer to an eighteen byte ASCII Identification string.
+*
+* BODY :
+* ======
+*
+* The driver_set_product_instance_id issues an SRB to set the product id
+* string. This string is written into certain MAC frames to report various
+* software and hardware conditions.
+* As with all the routines that involve issuing SRBs, the user routine
+* user_completed_srb is called when the actual SRB completes. It is this
+* user routine that is informed as to whether the SRB completed
+* successfully and it is at this time that the error log is filled into
+* the status information structure. Also, until the user_completed_srb
+* routine is called by the driver, no other driver routines involving the
+* issuing of SRBs for the given adapter will work. This is because there
+* is only one SRB per adapter.
+*
+* Note that only those fields that are used in the SRB (ie. have non-zero
+* values) that need to be byte swapped are byte swapped either in this
+* routine or in driver_issue_srb. Hence, if any adjustments are made to
+* the code it may be necessary to make sure that any newly used fields are
+* correctly byte swapped before downloading.
+*
+* Take special note of the fact that the user_completed_srb routine can be
+* called before this routine completes. This is because it is called out
+* of interrupts.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error with the same
+* adapter handle will give an explanation.
+*
+* Note that a successful call to this routine only means that the SRB has
+* been issued successfully. It does not mean that it has completed
+* successfully. The success or failure of the SRB is indicated in a
+* subsequent call to user_completed_srb. Also, in this particular case, it
+* is important to note that the error log is not filled in until the SRB
+* completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_set_product_instance_id)
+#endif
+
+export WBOOLEAN
+driver_set_product_instance_id(
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * product_id
+ )
+{
+ ADAPTER * adapter;
+ SRB_GENERAL * srb_gen;
+
+ /*
+ * Check adapter handle and status of adapter for validity.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_FREE))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * Set adapter SRB status to show that SRB is now in use.
+ */
+
+ adapter->srb_status = SRB_NOT_FREE;
+
+ /*
+ * Get pointer to general SRB structure to be used.
+ */
+
+ srb_gen = &adapter->srb_general;
+
+ /*
+ * Clear part of general SRB to be used.
+ */
+
+ util_zero_memory((BYTE *) srb_gen, sizeof(SRB_SET_PROD_INST_ID));
+
+ /*
+ * Place SRB type into header - this is a Fastmac Plus specific one, so
+ * we have to set a subcode value too.
+ */
+
+ srb_gen->set_prod_inst_id.header.function = FMPLUS_SPECIFIC_SRB;
+ srb_gen->set_prod_inst_id.subcode = SET_PROD_INST_ID_SUBCODE;
+
+ /*
+ * Copy in the product instance id.
+ */
+
+ util_mem_copy(
+ srb_gen->set_prod_inst_id.product_id,
+ product_id,
+ SIZEOF_PRODUCT_ID
+ );
+
+ /*
+ * Byte swap the product instance id.
+ */
+
+ util_byte_swap_structure(
+ (BYTE *) srb_gen->set_prod_inst_id.product_id,
+ SIZEOF_PRODUCT_ID
+ );
+
+ /*
+ * Record size of SRB that is being issued.
+ */
+
+ adapter->size_of_srb = sizeof(SRB_SET_PROD_INST_ID);
+
+ /*
+ * Call routine to issue SRB.
+ */
+
+ driver_issue_srb(adapter);
+
+ /*
+ * SRB issued successfully.
+ */
+
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* driver_issue_srb
+* ================
+*
+* The driver_issue_srb routine issues an SRB. It does this by copying it
+* into DIO space and issuing an SRB command interrupt to Fastmac via the
+* SIFINT register.
+*
+* Note there is no need to worry about an interrupt occuring, (between the
+* setting of the EAGLE SIFADR register and the reading/writing of the
+* required DIO space data), that would alter the contents of the EAGLE
+* SIFADR register (and hence the SIFDAT and SIFDAT_INC registers too).
+* This is because the receive frame interrupt handler exits leaving the
+* contents of SIFADR as on entry.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(driver_issue_srb)
+#endif
+
+local void
+driver_issue_srb(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE hnd = adapter->adapter_handle;
+ SRB_GENERAL * srb_gen = &adapter->srb_general;
+
+ /*
+ * Before downloading need to byte swap the SRB header.
+ */
+
+ util_byte_swap_structure(
+ (BYTE *) &srb_gen->header,
+ sizeof(SRB_HEADER)
+ );
+
+ /*
+ * Inform the system about the IO ports we are going to access.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter);
+#endif
+
+ sys_sync_with_interrupt(hnd, issue_srb, adapter);
+
+ /*
+ * Let the system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+}
+
+/****************************************************************************
+*
+* driver_completing_srb
+* =====================
+*
+* PARAMETERS (passed by driver_interrupt_entry) :
+* ===============================================
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* The adapter handle for the adapter so it can be passed to the user
+* supplied user_completed_srb routine.
+*
+* ADAPTER * adapter
+*
+* The details of the adapter that the SRB has completed on.
+*
+* BODY :
+* ======
+*
+* The driver_completing_srb routine is called by driver_interrupt_entry.
+* It is called when Fastmac has generated an interrupt to say that the
+* SRB, associated with a particular adapter, has completed and further
+* SRBs can be issued.
+*
+* The routine reads the SRB out of DIO space into the SRB structure
+* maintained for the correct adapter. It then checks the SRB return code
+* to see if the SRB completed successfully and records the fact that the
+* SRB is now free. Then, it informs the user as to the success of the
+* completed SRB by calling user_completed_srb.
+*
+* The user_completed_srb routine should do a minimum amount of processing
+* because it is being called out of interrupts. Sensibly, it should just
+* set a flag, to say that the SRB has completed, that can be checked for
+* at strategy time when a further driver routine involving the use of the
+* SRB is called.
+*
+* Note that only those fields that are needed in the completed SRB that
+* need to be byte swapped back to Intel format are byte swapped. Hence,
+* if any adjustments are made to the code it may be necessary to make sure
+* that any newly used fields are correctly byte swapped back.
+*
+* RETURNS :
+* =========
+*
+* The routine always succeeds and returns control to the driver routine
+* driver_interrupt_entry.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(driver_completing_srb)
+#endif
+
+export void
+driver_completing_srb(
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ )
+{
+ SRB_GENERAL * srb_gen = &adapter->srb_general;
+ WORD saved_sifadr_value;
+ WBOOLEAN user_success_code;
+
+ /*
+ * Before accessing SIFADR, save current value for restoring on exit.
+ * Do this so interrupt not effect SIFADR value.
+ */
+
+ saved_sifadr_value = sys_insw(adapter_handle, adapter->sif_adr);
+
+ /*
+ * Copy SRB out of DIO space into adapter's SRB structure.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) adapter->srb_dio_addr
+ );
+
+ sys_rep_insw(
+ adapter_handle,
+ adapter->sif_datinc,
+ (BYTE *) srb_gen,
+ (WORD) (adapter->size_of_srb / 2)
+ );
+
+ if (adapter->size_of_srb & 1)
+ {
+ *(((BYTE * ) srb_gen) + adapter->size_of_srb - 1) =
+ sys_insb(adapter_handle, adapter->sif_datinc);
+ }
+
+ /*
+ * Once read from DIO space, byte swap SRB header back to Intel format.
+ */
+
+ util_byte_swap_structure((BYTE *) &srb_gen->header, sizeof(SRB_HEADER));
+
+ /*
+ * Check if SRB has completed successfully.
+ */
+
+ if (srb_gen->header.return_code == SRB_E_00_SUCCESS)
+ {
+ /*
+ * SRB completed successfully so record this to inform user.
+ */
+
+ user_success_code = TRUE;
+
+ /*
+ * If read error log SRB completed successfully
+ * then copy error log information into user's structure.
+ * Need to byte swap error log structure to Intel format first.
+ */
+
+ if (srb_gen->header.function == READ_ERROR_LOG_SRB)
+ {
+ util_byte_swap_structure(
+ (BYTE *) &srb_gen->err_log.error_log,
+ sizeof(ERROR_LOG)
+ );
+
+ adapter->status_info->error_log = srb_gen->err_log.error_log;
+ }
+ }
+ else
+ {
+ /*
+ * SRB not completed successfully so record this to inform user
+ * and fill in error record.
+ */
+
+ user_success_code = FALSE;
+ adapter->error_record.type = ERROR_TYPE_SRB;
+ adapter->error_record.value = srb_gen->header.return_code;
+ }
+
+ /*
+ * If issued an open adapter SRB and error is E_07_CMD_CANCELLED_FAIL
+ * then actually have an open error so change adapter error record.
+ */
+
+ if ((srb_gen->header.function == OPEN_ADAPTER_SRB) &&
+ (srb_gen->header.return_code == SRB_E_07_CMD_CANCELLED_FAIL))
+ {
+ /*
+ * Fill in error record with open error (not SRB error).
+ */
+
+ adapter->error_record.type = ERROR_TYPE_OPEN;
+ adapter->error_record.value = OPEN_E_01_OPEN_ERROR;
+ }
+
+ /*
+ * Set adapter SRB status to show that SRB is now free.
+ */
+
+ adapter->srb_status = SRB_FREE;
+
+ /*
+ * Inform user as to success of completed SRB.
+ * Disable and re-enable accessing IO locations around user call.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+
+ user_completed_srb(adapter_handle, user_success_code);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter);
+#endif
+
+ /*
+ * Before finishing, restore saved value of EAGLE SIFADR register.
+ * Do this so interrupt does not effect SIFADR value.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_adr, saved_sifadr_value);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - get_open_and_ring_status
+|
+| Paramters - ptr -> Pointer to our ADAPTER structure.
+|
+| Purpose - Reads status information from DIO space. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+|--------------------------------------------------------------------------*/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(get_open_and_ring_status)
+#endif
+
+local WBOOLEAN
+get_open_and_ring_status(
+ void * ptr
+ )
+{
+ ADAPTER * adapter = (ADAPTER *) ptr;
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD saved_sifadr;
+
+ /*
+ * Get adapter open status from the STB in DIO space.
+ */
+
+ saved_sifadr = sys_insw(adapter_handle, adapter->sif_adr);
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) &adapter->stb_dio_addr->adapter_open
+ );
+
+ adapter->status_info->adapter_open =
+ sys_insw(adapter_handle, adapter->sif_dat);
+
+ /*
+ * Get ring status from the STB in DIO space.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ (WORD) (card_t) &adapter->stb_dio_addr->ring_status
+ );
+
+ adapter->status_info->ring_status =
+ sys_insw(adapter_handle, adapter->sif_dat);
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr, saved_sifadr
+ );
+
+ return FALSE;
+}
+
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - issue_srb
+|
+| Paramters - ptr -> Pointer to our ADAPTER structure.
+|
+| Purpose - Copy an SRB to the adapter. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+|--------------------------------------------------------------------------*/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(issue_srb)
+#endif
+
+local WBOOLEAN
+issue_srb(
+ void * ptr
+ )
+{
+ ADAPTER * adapter = (ADAPTER *) ptr;
+ ADAPTER_HANDLE hnd = adapter->adapter_handle;
+ SRB_GENERAL * srb_gen = &adapter->srb_general;
+ WORD sifint_value;
+
+ /*
+ * Copy the SRB into DIO space at Fastmac specified location.
+ * only copy the required amount for the specific type of SRB.
+ */
+
+ sys_outsw(
+ hnd,
+ adapter->sif_adr,
+ (WORD) (card_t) adapter->srb_dio_addr
+ );
+
+ sys_rep_outsw(
+ hnd,
+ adapter->sif_datinc,
+ (BYTE *) srb_gen,
+ (WORD) (adapter->size_of_srb / 2)
+ );
+
+ if (adapter->size_of_srb & 1)
+ {
+ sys_outsb(
+ hnd,
+ adapter->sif_datinc,
+ *(((BYTE * ) srb_gen) + adapter->size_of_srb - 1)
+ );
+ }
+
+ /*
+ * Set up SIFCMD value for SRB command interrupt.
+ */
+
+ sifint_value = DRIVER_SIFINT_SRB_COMMAND;
+
+ /*
+ * Set interrupt adapter bit in SIFCMD.
+ */
+
+ sifint_value = (sifint_value | DRIVER_SIFINT_IRQ_FASTMAC);
+
+ /*
+ * Mask SIFSTS so not clear interrupt if outstanding Fastmac interrupt.
+ */
+
+ sifint_value = (sifint_value | DRIVER_SIFINT_FASTMAC_IRQ_MASK);
+
+ /*
+ * Interrupt Fastmac.
+ */
+
+ sys_outsw(hnd, adapter->sif_int, sifint_value);
+
+ return FALSE;
+}
+
+/**** End of DRV_SRB.C file ************************************************/
diff --git a/private/ntos/ndis/madge/driver/ftk.upd b/private/ntos/ndis/madge/driver/ftk.upd
new file mode 100644
index 000000000..a1dc10fa1
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/ftk.upd
@@ -0,0 +1,279 @@
+/****************************************************************************
+*
+* FTK.UPD
+*
+* FastMAC and FastMAC Plus Toolkit
+*
+* Copyright (c) Madge Networks Ltd 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+
+ Update History
+
+-----------------------------------------------------------------------------
+
+2.21.12 PBA 17/07/1995
+
+ Fixed a bug in hwi_pci.c. We were doing MMIO processing
+ if either the TX or RX bit in SIFINT was set without
+ requiring the host interrupt bit to also be set. This
+ meant that if we were on a shared interrupt we could
+ do an erroneous MMIO transfer because the RX or TX was
+ set but the adapter had not generated an interrupt.
+
+2.21.11 PRR 11/07/1995
+
+ Added another PCI fix to all the PCI cards, when using PIO
+ we need to handshake the transfer because of some PCI/Eagle
+ problems.
+
+2.21.10 PRR 10/07/11995
+
+ Added the fix for the PCI-Ti ASIC for DMA, also found a bug in
+ the ISR which is worth noting. To check for Pseudo DMA we need
+ to check the SWHRQ and PSDMAEN bits we were just checking SWHRQ
+ (DMA in progress). This causes a few problems if we go into the
+ Pseudo DMA code whilst in DMA mode.
+
+2.21.09 PRR 05/07/1995
+
+ Added the new fix to DMA on the PCI-Ti card.
+
+2.21.08 PRR & PBA 28/06/1995
+
+ Added the WinBook PCMCIA fix. Define WIN_BOOK_FIX
+ to enable it.
+
+2.21.07 PBA 22/06/1995
+
+ Fixed a bug where hwi_gen.c was not setting the MAC
+ buffer size to 504 bytes for PCIx adapters.
+
+2.21.06 PRR (& PBA) 21/06/1995
+
+ Finished support for TI ASIC based PCI adapter.
+
+2.21.05 PBA 24/05/1995
+
+ Fixed a bug in hwi_eisa.c where interrupts were not
+ being regenerated properly. Only affected edge triggered
+ interrupts.
+
+2.21.04 PBA 24/05/1995
+
+ Added support for the mark 3 EISA adapter.
+
+2.21.03 PRR 02/05/1995
+
+ Support for PCI-Ti and PCI-BM cards added.
+ The Ti one is works with all 3 demo programs in Pseudo-DMA
+ mode, the ASIC does not work for DMA so I have not tested it.
+ The BM code is as yet untested because of Silicon features.
+
+2.21.02 PBA 12/05/1995
+
+ It appears that certain sorts of PCMCIA socket
+ controllers can generate stray interrupts as soon as
+ we touch the adapter. Re-ordered some of the interrupt
+ initialisation code so that we can cope with the stray
+ interrupt.
+
+2.21.01 PBA 07/04/1995
+
+ Changed hwi_pci.c so that is uses the extended
+ handshake on transmit MMIO.
+
+2.21 PD 03/04/1995
+
+ Second version of the combined FastMAC and FastMAC
+ Plus toolkit. Uses FastMAC v4.50 and FastMAC Plus v1.34.
+
+2.20.27 PD 09/02/1995
+
+ Added a pokeouts module to allow debug information to be
+ sent to the serial ports on an IBM or clone. See head_def\
+ ftk_poke.h for the macros to use.
+ Also altered hwi_pcmc.c with calls for point enabling a
+ PCMCIA adapter. They are protected by #ifdef PCMCIA_POINT_
+ ENABLE. The prototypes for the calls are in sys_pcmc.h, but
+ no example DOS sys_pcmc.c or sys_pcmc.asm file is included.
+ DOS programs should use MADGECS or similar to provide card
+ and socket services - in which case the point enabler code
+ is not required.
+
+2.20.26 PBA 23/01/1995
+
+ hwi_pcmc.c now sets the MC_AND_ISACP_USE_PIO flag in
+ the adapter->mc32_config byte to get the software
+ handshake to work properly.
+
+2.20.25 PBA 12/01/1995
+
+ Removed bug in driver_remove_adapter where the FastMAC
+ Plus dma test buffer was freed if the pointer was NULL
+ rather than not NULL!
+
+2.20.24 PBA 12/01/1995
+
+ Changed hwi_get_node_address_check so that it doesn't
+ check for a Madge node address so that the FTK will
+ work on none Madge adapters.
+
+ Also changed drv_init.c so that the Madgic bits are only
+ set if MADGIC_BIT is defined. This allows support for
+ Madgic bits to be removed with RIFFDEF for releases.
+
+2.20.23 PBA 03/01/1995
+
+ Changed sys_allocate_dma_phys_buffer and
+ sys_free_dma_phys_buffer so that they take a DWORD
+ for the memory block size.
+
+2.20.22 PBA 12/12/1994
+
+ Tidied up some differences between the PCMCIA FTK and
+ HWI to do with interrupt regeneration that was causing
+ Windows95 to hang occassionally.
+
+2.20.21 PBA 12/12/1994
+
+ There us a problem with pseduo DMA on PnP and Smart16.
+ We have to read SIFACL, set the SINTEN bit and write
+ it back to regenerate interrupts. However, sometimes
+ when we read SIFACL the SWHLDA bit has not been cleared
+ by the Eagle. If at the same time the SWHRQ bit has been
+ set by the Eagle to indicate another transfer is pending
+ we may accidentally start another transfer when we write
+ the value of SIFACL + SINTEN back. The solution is
+ to poll SIFACL until the SWHLDA bit is cleared. This
+ fix gets rid of the delay in 2.20.19.
+
+2.20.20 PBA 08/12/1994
+
+ Added 32 bit PCMCIA support.
+
+2.20.19 PBA 08/12/1994
+
+ Put the code back that was removed in 2.20.17. Under
+ NT/Win95 we seem to need a short delay at the pointer
+ where under DOS we would clear the interrupt controller.
+
+2.20.18 PBA 07/12/1994
+
+ Added code in hwi_pcmc.c to call user_adapter_removed
+ if the PCMCIA adapter goes away. Enabled by defining
+ FTK_ADAPTER_REMOVED_NOTIFY.
+
+2.20.17 PBA 06/12/1994
+
+ Removed some code in hwi_pnp.c and hwi_sm16.c that toggled
+ EAGLE_SIFACL_SINTEN. I don't know why this code was there
+ and it breaks the hwi.
+
+2.20.16 PBA 06/12/1994
+
+ Now sets the "Madgic" bits.
+
+2.20.15 PBA 06/12/1994
+
+ Added lots of casts to stop the NT compiler from generating
+ warnings.
+
+2.20.14 PBA 06/12/1994
+
+ Added compile directive FTK_NO_TX_COMPLETION_CALL that
+ stops drv_irq.c calling rxtx_irq_completion_check even
+ if we have asked for TX complete interrupts by defining
+ FTK_TX_WITH_COMPLETION.
+
+2.20.13 PBA 02/12/1994
+
+ Fixed a bug in hwi_sm16.c where the node address wasn't
+ read properly because of an unitialised variable.
+
+2.20.12 PBA 01/12/1994
+
+ Changed the minumum number of RX/TX slots to 2.
+
+2.20.11 PBA 01/12/1994
+
+ Removed the calls to driver_remove_adapter in
+ driver_prepare_adapter, otherwise there's
+ no way to return an error message.
+
+2.20.10 PBA 01/12/1994
+
+ Fixed some places where macro_enable_io calls where
+ not enclosed by an #ifndef FTK_NO_IO_EMABLE. Also
+ changed an errant sys_probe_insb to a sys_insb.
+
+2.20.09 PBA 01/12/1994
+
+ Changed sys_sync_with_interrupt so that it takes an
+ abapter_handle parameter and returns a WBOOLEAN. Also
+ moved the definition to sys_mem.h.
+
+2.20.08 PBA 01/12/1994
+
+ Added a tx_flags parameter to rxtx_transmit_frame.
+
+2.20.07 PBA 30/11/1994
+
+ Fixed driver_prepare_adapter so that it always
+ calls driver_remove_adapter if it fails to
+ free up any memory allocated.
+
+2.20.06 PBA 29/11/1994
+
+ Initialise time functions are now marked with
+ #pragma FTK_INIT_FUNCTION(...), interrupt time
+ functions with #pragma FTK_IRQ_FUNCTION(...)
+ and run time but not interrupt time functions with
+ #pragma FTK_RES_FUNCTION(...). The #pragma's are
+ prefixed by #ifdef FTK_xxx_FUNCTION. The
+ FTK_xxx_FUNCTION definitions should be in user.h.
+
+2.20.05 PBA 21/11/1994
+
+ Change get_bring_up_code to retry the bring-up up to
+ 10 times. There is a problem with ICL PCs/ATPs with
+ SMARTNT.SYS where the bring up occassionally fails.
+ Retrying is the way the HWI fixes it.
+
+2.20.04 PBA 18/11/1994
+
+ Changed driver_open_adapter so that it takes the product
+ instance id from the string ftk_product_inst_id. This
+ string is initialised to FASTMAC_PRODUCT_ID so if
+ the user doesn't do anything it behaves as before.
+ However the user can change the string before calling
+ driver_open_adapter.
+
+2.20.03 PBA 16/11/1994
+
+ Fixed HWI_PCMC.C which was not setting the RAM size in
+ the adapter structure.
+
+2.20.02 PRR 16/11/1994
+
+ Change the polling routing for PNP cards such that it only
+ looks for md not md01.
+
+2.20.01 PBA 16/11/1994
+
+ Fixed spelling mistake in user.h of header files.
+ FTK_NO_PROBING should have been FTK_NO_PROBE.
+
+2.20 PD & PBA 15/11/1994
+
+ First recorded version of the combined FastMAC and FastMAC
+ Plus toolkit. Heaviliy revised from v1.x and the 2.x
+ beta. Uses FastMAC v4.48 and FastMAC Plus v1.22.
+
+---------------------------------------------------------------------------*/
+
+ \ No newline at end of file
diff --git a/private/ntos/ndis/madge/driver/ftk_poke.c b/private/ntos/ndis/madge/driver/ftk_poke.c
new file mode 100644
index 000000000..a9074dd76
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/ftk_poke.c
@@ -0,0 +1,267 @@
+/****************************************************************************
+*
+* FTK_POKE.C
+*
+* Part of the FastMAC Toolkit.
+* Copyright (c) Madge Networks Ltd 1995
+*
+* This module provides some functions that will send tracing information
+* to either serial port (COM1 or COM2) on a standard IBM PC clone.
+*
+*****************************************************************************/
+
+#include "ftk_defs.h"
+#include "ftk_intr.h"
+#include "ftk_extr.h"
+
+#ifdef FTK_POKEOUTS
+
+/*---------------------------------------------------------------------------
+|
+| Private constants.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef USE_COM2
+#define COM_BASE 0x0200 /* Base address for COM2. */
+#else
+#define COM_BASE 0x0300 /* Base address for COM1. */
+#endif
+
+#define THR (COM_BASE + 0x0f8) /* Transmit holding register. */
+#define IER (COM_BASE + 0x0f9) /* IRQ enable register. */
+#define IDR (COM_BASE + 0x0fa) /* IRQ identification register. */
+#define LCR (COM_BASE + 0x0fb) /* Line control register. */
+#define MCR (COM_BASE + 0x0fc) /* Modem control register. */
+#define LSR (COM_BASE + 0x0fd) /* Line status register. */
+#define MSR (COM_BASE + 0x0fe) /* Modem status register. */
+
+#define TX_RDY 0x020 /* THR empty flag bit in LSR. */
+#define BAUD_MASK 0x080 /* Baud rate mask in LCR. */
+#define PARAMS_MASK 0x07f /* Parameter mask in LCR. */
+#define EOUT2 0x008 /* EOUT2 flag in MCR. */
+#define CMCR 0x0f0 /* Clear MCR command. */
+#define DTR 0x001 /* DTR flag in MCR. */
+
+#define PARITY_TYPE 0
+#define STOP_BITS 1
+#define DATA_BITS 8
+#define BAUD_RATE 9600
+
+
+/*----------------------------------------------------------------------------
+|
+| Private global variables.
+|
+----------------------------------------------------------------------------*/
+
+int ftk_poke_initialised = FALSE;
+char ftk_hex_chars[16] = "0123456789abcdef";
+
+
+/*----------------------------------------------------------------------------
+|
+| Function - ftk_poke_init
+|
+| Parameters - Node.
+|
+| Purpose - Initialise the serial port.
+|
+| Returns - Nothing.
+|
+----------------------------------------------------------------------------*/
+
+void
+ftk_poke_init(void)
+{
+ unsigned t;
+ unsigned v;
+
+ /*
+ * Data, stop and parity bits.
+ */
+
+ t = DATA_BITS - 5;
+ if (STOP_BITS == 2)
+ {
+ t |= 0x04;
+ }
+ if (PARITY_TYPE > 0)
+ {
+ t |= ((PARITY_TYPE << 1) - 1) << 3;
+ }
+
+ OUTB(LCR, (BYTE) (INB(LCR) & PARAMS_MASK));
+ OUTB(LCR, (BYTE) t);
+
+ /*
+ * Set up the baud rate.
+ */
+
+ t = 115200L / BAUD_RATE;
+ v = INB(LCR) | BAUD_MASK;
+ OUTB(LCR, (BYTE) v);
+ OUTB(THR, (BYTE) (t & 0xff));
+ OUTB(IER, (BYTE) ((t >> 8) & 0xff));
+ OUTB(LCR, (BYTE) (v & PARAMS_MASK));
+
+ /*
+ * Empty the transmit buffer.
+ */
+
+ INB(THR);
+
+ /*
+ * Clear the modem control register and enable OUT2.
+ */
+
+ OUTB(MCR, (BYTE) ((INB(MCR) & CMCR) | EOUT2));
+
+ /*
+ * Turn DTR on.
+ */
+
+ OUTB(MCR, (BYTE) (INB(MCR) | DTR));
+}
+
+
+/*****************************************************************************
+*
+* Function - _ftk_poke_char
+*
+* Parameters - ch -> Character to poke out.
+*
+* Purpose - Poke a single character to the serial port.
+*
+* Returns - Nothing.
+*
+*****************************************************************************/
+
+void
+_ftk_poke_char(int ch)
+{
+ /*
+ * Initialise the serial port if this is the first access.
+ */
+
+ if (!ftk_poke_initialised)
+ {
+ ftk_poke_init();
+ ftk_poke_initialised = TRUE;
+ }
+
+ /*
+ * Wait until the transmit holding register is empty.
+ */
+
+ while ((INB(LSR) & TX_RDY) == 0);
+
+ /*
+ * And transmit the character.
+ */
+
+ OUTB(THR, (unsigned char) ch);
+}
+
+
+/*****************************************************************************
+*
+* Function - _ftk_poke_string
+*
+* Parameters - str -> String to poke out.
+*
+* Purpose - Poke a string to the serial port.
+*
+* Returns - Nothing.
+*
+*****************************************************************************/
+
+void
+_ftk_poke_string(char *str)
+{
+ while (*str != '\0')
+ {
+ if (*str == '\n')
+ {
+ _ftk_poke_char('\n');
+ _ftk_poke_char('\r');
+ }
+ else
+ {
+ _ftk_poke_char(*str);
+ }
+ str++;
+ }
+}
+
+
+/*****************************************************************************
+*
+* Function - _ftk_poke_byte
+*
+* Parameters - byte -> The byte to poke out.
+*
+* Purpose - Poke the hex string for a byte to the serial port.
+*
+* Returns - Nothing.
+*
+*****************************************************************************/
+
+void
+_ftk_poke_byte(int byte)
+{
+ _ftk_poke_char(ftk_hex_chars[(byte >> 4) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(byte ) & 0x000f]);
+}
+
+
+/*****************************************************************************
+*
+* Function - _ftk_poke_word
+*
+* Parameters - word -> The word to poke out.
+*
+* Purpose - Poke the hex string for a word to the serial port.
+*
+* Returns - Nothing.
+*
+*****************************************************************************/
+
+void
+_ftk_poke_word(int word)
+{
+ _ftk_poke_char(ftk_hex_chars[(word >> 12) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(word >> 8) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(word >> 4) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(word ) & 0x000f]);
+}
+
+
+/*****************************************************************************
+*
+* Function - _ftk_poke_dword
+*
+* Parameters - dword -> The dword to poke out.
+*
+* Purpose - Poke the hex string for a dword to the serial port.
+*
+* Returns - Nothing.
+*
+*****************************************************************************/
+
+void
+_ftk_poke_dword(long dword)
+{
+ _ftk_poke_char(ftk_hex_chars[(dword >> 28) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(dword >> 24) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(dword >> 20) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(dword >> 16) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(dword >> 12) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(dword >> 8) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(dword >> 4) & 0x000f]);
+ _ftk_poke_char(ftk_hex_chars[(dword ) & 0x000f]);
+}
+
+#endif
+
+
diff --git a/private/ntos/ndis/madge/driver/ftk_user.c b/private/ntos/ndis/madge/driver/ftk_user.c
new file mode 100644
index 000000000..5a58b90d4
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/ftk_user.c
@@ -0,0 +1,2187 @@
+/****************************************************************************
+*
+* FTK_USER.C
+*
+* FastMAC Plus based NDIS3 miniport driver FTK interface. This module
+* contains all of the routines required to interface with the FastMAC
+* Plus FTK. This is includes the routines traditionally found in transmit.c
+* and receive.c.
+*
+* Copyright (c) Madge Networks Ltd 1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_extr.h"
+#include "ftk_intr.h"
+
+#include "mdgmport.upd"
+#include "ndismod.h"
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL VARIABLES
+|
+---------------------------------------------------------------------------*/
+
+//
+// To cut down on accesses to the slot structures on the card we keep
+// a host cache of various detaisl we need.
+//
+
+typedef struct
+{
+ DWORD PhysicalAddress;
+ PVOID VirtualAddress;
+}
+RX_SLOT_CACHE, *PRX_SLOT_CACHE;
+
+
+typedef struct
+{
+ ULONG BufferSize;
+ ULONG SharedMemoryAllocation;
+ PVOID SharedMemoryVirtAddr;
+ DWORD SharedMemoryPhysAddr;
+
+ RX_SLOT_CACHE rx_slot_cache[FMPLUS_MAX_RX_SLOTS];
+
+ UINT active_rx_slot; /* Used to count through the slot array */
+}
+RX_SLOT_MGMNT, *PRX_SLOT_MGMNT;
+
+
+typedef struct
+{
+ DWORD PhysicalAddress;
+ PVOID VirtualAddress;
+}
+TX_SLOT_CACHE, *PTX_SLOT_CACHE;
+
+
+typedef struct
+{
+ ULONG BufferSize;
+ ULONG SharedMemoryAllocation;
+ PVOID SharedMemoryVirtAddr;
+ DWORD SharedMemoryPhysAddr;
+
+ TX_SLOT_CACHE tx_slot_cache[FMPLUS_MAX_TX_SLOTS];
+
+ UINT active_tx_slot;
+ UINT first_tx_in_use;
+ UINT number_tx_in_use;
+}
+TX_SLOT_MGMNT, *PTX_SLOT_MGMNT;
+
+
+#define FRAME_TYPE_MASK ((BYTE) 0xC0) // What is ANDed with FC byte.
+#define FRAME_TYPE_MAC ((BYTE) 0x00) // What's left for a MAC frame.
+
+
+typedef struct
+{
+ ADAPTER_HANDLE adapter_handle;
+ ADAPTER * adapter;
+ TX_SLOT * tx_slot_ptr;
+ RX_SLOT * rx_slot_ptr;
+ UINT frame_length;
+ UINT result1;
+ UINT result2;
+}
+MPSAFE_INFO;
+
+
+#if 0
+
+typedef struct
+{
+ ADAPTER_HANDLE handle;
+ WORD location;
+ WORD result;
+}
+RDIO;
+
+WORD
+_madge_rdio(
+ void * ptr
+ )
+{
+ RDIO * rdio;
+
+ rdio = (RDIO *) ptr;
+
+ sys_outsw(
+ rdio->handle,
+ adapter_record[rdio->handle]->sif_adr,
+ rdio->location
+ );
+
+ rdio->result = sys_insw(
+ rdio->handle,
+ adapter_record[rdio->handle]->sif_dat
+ );
+
+ return 0;
+}
+
+
+WORD
+madge_rdio(
+ ADAPTER_HANDLE adapter_handle,
+ WORD dio_location
+ )
+{
+ RDIO rdio;
+
+ rdio.handle = adapter_handle;
+ rdio.location = dio_location;
+
+ sys_sync_with_interrupt(
+ adapter_handle,
+ _madge_rdio,
+ (void *) &rdio
+ );
+
+ return rdio.result;
+}
+
+
+void
+madge_dump_fmplus_info(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ PMADGE_ADAPTER ndisAdap;
+ RX_SLOT * * rx_slot_array;
+ TX_SLOT * * tx_slot_array;
+ UINT active_rx_slot;
+ UINT active_tx_slot;
+ UINT first_tx_slot;
+ UINT rx_slots;
+ UINT tx_slots;
+ UINT i;
+
+ adapter = adapter_record[adapter_handle];
+
+ rx_slot_array = adapter->rx_slot_array;
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+ active_rx_slot = rx_slot_mgmnt->active_rx_slot;
+ rx_slots = adapter->init_block->fastmac_parms.rx_slots;
+
+ tx_slot_array = adapter->tx_slot_array;
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ active_tx_slot = tx_slot_mgmnt->active_tx_slot;
+ first_tx_slot = tx_slot_mgmnt->first_tx_in_use;
+ tx_slots = adapter->init_block->fastmac_parms.tx_slots;
+
+ DbgPrint("----------------------------------------------------------\n");
+
+ DbgPrint(
+ "SIFADR high word = %04x\n\n",
+ sys_insw(adapter_handle, adapter->sif_adx)
+ );
+
+ DbgPrint("RX SLOTS:\n\n");
+ DbgPrint("Active slot = %d\n", active_rx_slot);
+
+ DbgPrint(" Len Res Buffer Stat Next\n");
+ DbgPrint(" ---- ---- --------- ---- ----\n");
+
+ for (i = 0; i < rx_slots; i++)
+ {
+ DbgPrint(
+ "%04x: %04x %04x %04x %04x %04x %04x\n",
+ (WORD) (card_t) rx_slot_array[i],
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_len),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->reserved),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_hiw),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_low),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->rx_status),
+ madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->next_slot)
+ );
+ }
+
+ DbgPrint("\n");
+
+ DbgPrint("TX SLOTS:\n\n");
+ DbgPrint("Active slot = %d\n", active_tx_slot);
+ DbgPrint("First used slot = %d\n", first_tx_slot);
+
+ DbgPrint(" Stat SLen LLen Res1 Res2 Sbuffer Next LBuffer\n");
+ DbgPrint(" ---- ---- ---- ---- ---- --------- ---- ---------\n");
+
+ for (i = 0; i < tx_slots; i++)
+ {
+ DbgPrint(
+ "%04x: %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ (WORD) (card_t) tx_slot_array[i],
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->tx_status),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_len),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_len),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->reserved[0]),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->reserved[1]),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_hiw),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_low),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->next_slot),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_hiw),
+ madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_low)
+ );
+ }
+
+ DbgPrint("\n");
+
+ DbgPrint("DIO LOCATION 0x0CE0\n\n");
+
+ for (i = 0; i < 32; i++)
+ {
+ DbgPrint(" %04x", madge_rdio(adapter_handle, (WORD) (0x0ce0 + i * 2)));
+ if (i == 15)
+ {
+ DbgPrint("\n");
+ }
+ }
+
+ DbgPrint("\n");
+}
+
+#endif
+
+/***************************************************************************
+*
+* Function - rxtx_allocate_rx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* max_frame_size -> Maximum frame size.
+* number_of_slots -> Number of receive slots.
+*
+* Purpose - Allocate buffer space for the receive slots.
+*
+* Returns - TRUE if it succeeds or FALSE otherwise.
+*
+****************************************************************************/
+
+WBOOLEAN
+rxtx_allocate_rx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ );
+
+#pragma FTK_INIT_FUNCTION(rxtx_allocate_rx_buffers)
+
+WBOOLEAN
+rxtx_allocate_rx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ )
+{
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+ NDIS_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ DWORD SharedMemVirtAddr;
+ DWORD SharedMemPhysAddr;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+
+ //
+ // Only want to allocate the receive buffers and slot management once
+ // per adapter.
+ //
+
+ if (rx_slot_mgmnt == NULL)
+ {
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // Allocate the slot management structure.
+ //
+
+ MADGE_ALLOC_MEMORY(
+ &status,
+ &adapter->rx_slot_mgmnt,
+ sizeof(RX_SLOT_MGMNT)
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ MADGE_ZERO_MEMORY(adapter->rx_slot_mgmnt, sizeof(RX_SLOT_MGMNT));
+
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+
+ //
+ // Work out how big the buffer should be. Remember to add
+ // four to the buffer allocation for the CRC. The addition
+ // of 32 provides a little space between receive buffers
+ // for those naughty transport protocols that read more
+ // then the indicated lookahead.
+ //
+
+ rx_slot_mgmnt->BufferSize = (max_frame_size + 4 + 32 + 3) & ~3;
+
+ rx_slot_mgmnt->SharedMemoryAllocation =
+ rx_slot_mgmnt->BufferSize * number_of_slots;
+
+ //
+ // Allocate the buffer.
+ //
+
+ if (!sys_alloc_dma_phys_buffer(
+ adapter_handle,
+ rx_slot_mgmnt->SharedMemoryAllocation,
+ &SharedMemPhysAddr,
+ &SharedMemVirtAddr
+ ))
+ {
+ return FALSE;
+ }
+
+ rx_slot_mgmnt->SharedMemoryVirtAddr = (VOID *) SharedMemVirtAddr;
+ rx_slot_mgmnt->SharedMemoryPhysAddr = SharedMemPhysAddr;
+ }
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_setup_rx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* physical_addresses -> Use physical addresses?
+* number_of_slots -> Number of receive slots.
+*
+* Purpose - Set up the adapter receive slots.
+*
+* Returns - TRUE if it succeeds or FALSE otherwise.
+*
+****************************************************************************/
+
+void
+rxtx_setup_rx_buffers(
+ ADAPTER * adapter,
+ WBOOLEAN physical_addresses,
+ WORD number_of_slots
+ );
+
+#pragma FTK_INIT_FUNCTION(rxtx_setup_rx_buffers)
+
+void
+rxtx_setup_rx_buffers(
+ ADAPTER * adapter,
+ WBOOLEAN physical_addresses,
+ WORD number_of_slots
+ )
+{
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+ NDIS_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ PVOID SharedMemVirtAddr;
+ DWORD SharedMemPhysAddr;
+ PRX_SLOT_CACHE rx_slot_cache;
+ RX_SLOT * * rx_slot_array;
+ DWORD phys_addr;
+ WORD slot_index;
+ WORD sifadr;
+ WORD sifdat;
+ WORD sifdatinc;
+ UINT buffer_size;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ rx_slot_array = adapter->rx_slot_array;
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+ rx_slot_cache = rx_slot_mgmnt->rx_slot_cache;
+ SharedMemVirtAddr = rx_slot_mgmnt->SharedMemoryVirtAddr;
+ SharedMemPhysAddr = rx_slot_mgmnt->SharedMemoryPhysAddr;
+ buffer_size = rx_slot_mgmnt->BufferSize;
+
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+ sifdatinc = adapter->sif_datinc;
+
+ MadgePrint2("rxtx_setup_rx_buffers number_of_slots = %d\n", number_of_slots);
+ MadgePrint2("rxtx_setup_rx_buffers buffer_size = %d\n", buffer_size);
+
+ //
+ // Work out the physical and virtual address of each buffer.
+ //
+
+ for (slot_index = 0; slot_index < number_of_slots; slot_index++)
+ {
+ rx_slot_cache[slot_index].VirtualAddress = SharedMemVirtAddr;
+ (PUCHAR) SharedMemVirtAddr += buffer_size;
+
+ rx_slot_cache[slot_index].PhysicalAddress = SharedMemPhysAddr;
+ SharedMemPhysAddr += buffer_size;
+
+ phys_addr = (physical_addresses)
+ ? (DWORD) rx_slot_cache[slot_index].PhysicalAddress
+ : (DWORD) rx_slot_cache[slot_index].VirtualAddress;
+
+ //
+ // Write the buffer locations into the slots.
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_array[slot_index]->buffer_hiw
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdatinc,
+ (WORD) (phys_addr >> 16)
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ (WORD) (phys_addr & 0x0FFFF)
+ );
+ }
+
+ ndisAdap->RxTxBufferState |= MADGE_RX_INITIALIZED;
+ rx_slot_mgmnt->active_rx_slot = 0;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_free_rx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* max_frame_size -> Maximum frame size.
+* number_of_slots -> Number of receive slots.
+*
+* Purpose - Free the previously allocated receive buffers.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_free_rx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ )
+{
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+
+ //
+ // If the slot management structure exists them free it
+ // and the buffers.
+ //
+
+ if (rx_slot_mgmnt != NULL)
+ {
+ if (rx_slot_mgmnt->SharedMemoryVirtAddr != NULL)
+ {
+ sys_free_dma_phys_buffer(
+ adapter_handle,
+ rx_slot_mgmnt->SharedMemoryAllocation,
+ (DWORD) rx_slot_mgmnt->SharedMemoryPhysAddr,
+ (DWORD) rx_slot_mgmnt->SharedMemoryVirtAddr
+ );
+ }
+
+ MADGE_FREE_MEMORY(adapter->rx_slot_mgmnt, sizeof(RX_SLOT_MGMNT));
+
+ adapter->rx_slot_mgmnt = NULL;
+
+ ndisAdap->RxTxBufferState &= ~MADGE_RX_INITIALIZED;
+ }
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_allocate_tx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* max_frame_size -> Maximum frame size.
+* number_of_slots -> Number of transmit slots.
+*
+* Purpose - Allocate buffer space for the transmit slots.
+*
+* Returns - TRUE if it succeeds or FALSE otherwise.
+*
+****************************************************************************/
+
+WBOOLEAN
+rxtx_allocate_tx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ );
+
+#pragma FTK_INIT_FUNCTION(rxtx_allocate_tx_buffers)
+
+WBOOLEAN
+rxtx_allocate_tx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ )
+{
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ NDIS_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ DWORD SharedMemVirtAddr;
+ DWORD SharedMemPhysAddr;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+
+ //
+ // Only want to allocate the receive buffers and slot management once
+ // per adapter.
+ //
+
+ if (tx_slot_mgmnt == NULL)
+ {
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // Allocate the slot management structure.
+ //
+
+ MADGE_ALLOC_MEMORY(
+ &status,
+ &adapter->tx_slot_mgmnt,
+ sizeof(TX_SLOT_MGMNT)
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ MADGE_ZERO_MEMORY(adapter->tx_slot_mgmnt, sizeof(TX_SLOT_MGMNT));
+
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+
+ //
+ // Work out how big the buffer should be.
+ //
+
+ tx_slot_mgmnt->BufferSize = (max_frame_size + 3) & ~3;
+
+ tx_slot_mgmnt->SharedMemoryAllocation =
+ tx_slot_mgmnt->BufferSize * number_of_slots;
+
+ //
+ // Allocate the buffer.
+ //
+
+ if (!sys_alloc_dma_phys_buffer(
+ adapter_handle,
+ tx_slot_mgmnt->SharedMemoryAllocation,
+ &SharedMemPhysAddr,
+ &SharedMemVirtAddr
+ ))
+ {
+ return FALSE;
+ }
+
+ tx_slot_mgmnt->SharedMemoryVirtAddr = (VOID *) SharedMemVirtAddr;
+ tx_slot_mgmnt->SharedMemoryPhysAddr = SharedMemPhysAddr;
+ }
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_setup_tx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* physical_addresses -> Use physical addresses?
+* number_of_slots -> Number of transmit slots.
+*
+* Purpose - Set up the adapter transmit slots.
+*
+* Returns - TRUE if it succeeds or FALSE otherwise.
+*
+****************************************************************************/
+
+void
+rxtx_setup_tx_buffers(
+ ADAPTER * adapter,
+ WBOOLEAN physical_addresses,
+ WORD number_of_slots
+ );
+
+#pragma FTK_INIT_FUNCTION(rxtx_setup_tx_buffers)
+
+void
+rxtx_setup_tx_buffers(
+ ADAPTER * adapter,
+ WBOOLEAN physical_addresses,
+ WORD number_of_slots
+ )
+{
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ NDIS_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ PVOID SharedMemVirtAddr;
+ DWORD SharedMemPhysAddr;
+ PTX_SLOT_CACHE tx_slot_cache;
+ TX_SLOT * * tx_slot_array;
+ DWORD phys_addr;
+ WORD slot_index;
+ WORD sifadr;
+ WORD sifdat;
+ WORD sifdatinc;
+ UINT buffer_size;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ tx_slot_array = adapter->tx_slot_array;
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
+ SharedMemVirtAddr = tx_slot_mgmnt->SharedMemoryVirtAddr;
+ SharedMemPhysAddr = tx_slot_mgmnt->SharedMemoryPhysAddr;
+ buffer_size = tx_slot_mgmnt->BufferSize;
+
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+ sifdatinc = adapter->sif_datinc;
+
+ MadgePrint2("rxtx_setup_tx_buffers number_of_slots = %d\n", number_of_slots);
+ MadgePrint2("rxtx_setup_tx_buffers buffer_size = %d\n", buffer_size);
+
+ //
+ // Work out the physical and virtual address of each buffer.
+ //
+
+ for (slot_index = 0; slot_index < number_of_slots; slot_index++)
+ {
+ tx_slot_cache[slot_index].VirtualAddress = SharedMemVirtAddr;
+ (PUCHAR) SharedMemVirtAddr += buffer_size;
+
+ tx_slot_cache[slot_index].PhysicalAddress = SharedMemPhysAddr;
+ SharedMemPhysAddr += buffer_size;
+
+ phys_addr = (physical_addresses)
+ ? (DWORD) tx_slot_cache[slot_index].PhysicalAddress
+ : (DWORD) tx_slot_cache[slot_index].VirtualAddress;
+
+ //
+ // Write the buffer locations into the slots.
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_array[slot_index]->large_buffer_hiw
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdatinc,
+ (WORD) (phys_addr >> 16)
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ (WORD) (phys_addr & 0x0FFFF)
+ );
+ }
+
+ ndisAdap->RxTxBufferState |= MADGE_TX_INITIALIZED;
+ tx_slot_mgmnt->active_tx_slot = 0;
+ tx_slot_mgmnt->first_tx_in_use = 0;
+ tx_slot_mgmnt->number_tx_in_use = 0;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_free_tx_buffers
+*
+* Parameters - adapter -> Pointer to an FTK adapter structure.
+* max_frame_size -> Maximum frame size.
+* number_of_slots -> Number of transmit slots.
+*
+* Purpose - Free the previously allocated transmit buffers.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_free_tx_buffers(
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ )
+{
+ ADAPTER_HANDLE adapter_handle;
+ PMADGE_ADAPTER ndisAdap;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter_handle = adapter->adapter_handle;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+
+ //
+ // If the slot management structure exists them free it
+ // and the buffers.
+ //
+
+ if (tx_slot_mgmnt != NULL)
+ {
+ if (tx_slot_mgmnt->SharedMemoryVirtAddr != NULL)
+ {
+ sys_free_dma_phys_buffer(
+ adapter_handle,
+ tx_slot_mgmnt->SharedMemoryAllocation,
+ (DWORD) tx_slot_mgmnt->SharedMemoryPhysAddr,
+ (DWORD) tx_slot_mgmnt->SharedMemoryVirtAddr
+ );
+ }
+
+ MADGE_FREE_MEMORY(adapter->tx_slot_mgmnt, sizeof(TX_SLOT_MGMNT));
+
+ adapter->tx_slot_mgmnt = NULL;
+
+ ndisAdap->RxTxBufferState &= ~MADGE_TX_INITIALIZED;
+ }
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - MPSafeReadTxStatus
+|
+| Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
+|
+| Purpose - Reads the transmit status from the next slot to use. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MPSafeReadTxStatus(PVOID ptr)
+{
+ MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
+
+ //
+ // Read the transmit status from the slot.
+ //
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->tx_slot_ptr)->tx_status
+ );
+
+ info->result1 = sys_insw(
+ info->adapter_handle,
+ info->adapter->sif_dat
+ );
+
+ return FALSE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_irq_tx_completion_check
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* adapter -> Pointer to FTK adapter structure.
+*
+* Purpose - Complete any outstanding transmits.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_irq_tx_completion_check(
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ )
+{
+ UINT tx_slots;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ PTX_SLOT_CACHE tx_slot_cache;
+ TX_SLOT * * tx_slot_array;
+ PMADGE_ADAPTER ndisAdap;
+ UINT tx_status;
+ MPSAFE_INFO info;
+ WORD sifadr;
+ WORD sifdat;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
+ tx_slot_array = adapter->tx_slot_array;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ tx_slots = adapter->init_block->fastmac_parms.tx_slots;
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+
+ //
+ // If we're doing multiprocessor safe PIO then we need to set up
+ // the info structure.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.adapter_handle = adapter_handle;
+ info.adapter = adapter;
+ }
+
+ //
+ // Iterate around the transmit slots that are are marked as in use
+ // checking if they are now free. Note: we must work with the
+ // global coopies of the first_tx_in_use and number_tx_in_use
+ // in case rxtx_transmit_frame is called during our up-call
+ // to the wrapper.
+ //
+
+ while (tx_slot_mgmnt->number_tx_in_use > 0)
+ {
+ //
+ // Read the transmit status from the slot. If we're doing
+ // multiprocessor safe PIO we must do the DIO via an ISR
+ // synchronized function.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.tx_slot_ptr = tx_slot_array[tx_slot_mgmnt->first_tx_in_use];
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeReadTxStatus,
+ &info
+ );
+
+ tx_status = info.result1;
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_array[
+ tx_slot_mgmnt->first_tx_in_use
+ ]->tx_status
+ );
+
+ tx_status = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+ }
+
+ //
+ // If the slot is still in use then we must give up. This will
+ // also work if a PCMCIA adapter has been removed because
+ // tx_status will have been read as 0xffff.
+ //
+
+ if (tx_status >= 0x8000 || tx_status == 0)
+ {
+ break;
+ }
+
+ //
+ // Update the appropriate counters from the frame transmit
+ // status.
+ //
+
+ if ((tx_status & TX_RECEIVE_STATUS_MASK) == TX_RECEIVE_LOST_FRAME)
+ {
+ ndisAdap->LostFrames++;
+ }
+ else if ((tx_status & GOOD_TX_FRAME_MASK) != GOOD_TX_FRAME_VALUE)
+ {
+ ndisAdap->FrameTransmitErrors++;
+ }
+
+ //
+ // Update the slot usage.
+ //
+
+ tx_slot_mgmnt->number_tx_in_use--;
+
+ if (++tx_slot_mgmnt->first_tx_in_use == tx_slots)
+ {
+ tx_slot_mgmnt->first_tx_in_use = 0;
+ }
+
+ //
+ // Tell the wrapper that there is a free slot.
+ //
+
+ NdisMSendResourcesAvailable(ndisAdap->UsedInISR.MiniportHandle);
+ }
+
+ //
+ // If there are any frames we have queued for transmit that
+ // have not been completed then arm the timer so we are guaranteed
+ // to be called again. Under normal operation our DPR gets called
+ // often enough that this function is called frequently enough to
+ // complete all of the frames. However if we have an adapter in a
+ // fast bus (PCI/EISA) with a lot of RAM and we are not
+ // getting any recieve interrupts we can occasionally miss
+ // completing a frame. Hence the timer.
+ //
+
+ if (tx_slot_mgmnt->number_tx_in_use > 0)
+ {
+ NdisMSetTimer(&ndisAdap->CompletionTimer, 20);
+ }
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - MPSafeStartTx
+|
+| Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
+|
+| Purpose - Set up a tx slot and start the transmit going. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MPSafeStartTx(PVOID ptr)
+{
+ MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
+
+ //
+ // Reset the transmit status in the transmit slot.
+ //
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->tx_slot_ptr)->tx_status
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_dat,
+ 0x8000
+ );
+
+ //
+ // Write in the length of the buffer into the transmit slot
+ // (large buffer).
+ //
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->tx_slot_ptr)->large_buffer_len
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_dat,
+ (WORD) info->frame_length
+ );
+
+ //
+ // Write the length of the small buffer in the transmit slot to
+ // start the transmit going.
+ //
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->tx_slot_ptr)->small_buffer_len
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_dat,
+ FMPLUS_SBUFF_ZERO_LENGTH
+ );
+
+ return FALSE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_transmit_frame
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* tx_frame_identifier -> NDIS packet handle or a pointer
+* to some data to send.
+* tx_frame_length -> Length of the frame.
+* tx_is_packet -> TRUE if tx_frame_identifier is
+* an NDIS packet handle.
+*
+* Purpose - Attempts to transmit a frame by copying it into a transmit
+* buffer and activating a FastMAC Plus tx slot.
+*
+* Returns - DRIVER_TRANSMIT_SUCCESS if it succeeds or
+* DRIVER_TRANSMIT_FAILURE if it does not.
+*
+****************************************************************************/
+
+WORD
+rxtx_transmit_frame(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD tx_frame_identifier,
+ WORD tx_frame_length,
+ WORD tx_is_packet
+ )
+{
+ ADAPTER * adapter;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ PTX_SLOT_CACHE tx_slot_cache;
+ TX_SLOT * tx_slot_ptr;
+ UINT active_tx_slot;
+ UINT tx_slots;
+ PMADGE_ADAPTER ndisAdap;
+ UINT bytes_copied;
+ UINT tx_status;
+ MPSAFE_INFO info;
+ WORD sifadr;
+ WORD sifdat;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter = adapter_record[adapter_handle];
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
+ active_tx_slot = tx_slot_mgmnt->active_tx_slot;
+ tx_slot_ptr = adapter->tx_slot_array[active_tx_slot];
+ tx_slots = adapter->init_block->fastmac_parms.tx_slots;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+
+ //
+ // If we are a PCMCIA adapter it is possible that the adapter
+ // may have been removed. To detect this we check if SIFADR
+ // is 0xffff since this should not normally be true.
+ //
+
+ if (adapter->adapter_card_bus_type == ADAPTER_CARD_PCMCIA_BUS_TYPE)
+ {
+ if (sys_insw(adapter_handle, sifadr) == 0xffff)
+ {
+ rxtx_adapter_removed(adapter_handle);
+
+ return DRIVER_TRANSMIT_SUCCEED;
+ }
+ }
+
+ //
+ // If the next slot to be used is still in use then we must
+ // give up.
+ //
+
+ if (tx_slot_mgmnt->number_tx_in_use == tx_slots)
+ {
+
+#ifdef OID_MADGE_MONITOR
+ (ndisAdap->MonitorInfo).FailedToTransmit++;
+#endif
+
+ return DRIVER_TRANSMIT_FAIL;
+ }
+
+ //
+ // Copy the frame into the transmit buffer.
+ //
+
+ if (tx_is_packet)
+ {
+ MadgeCopyFromPacketToBuffer(
+ (PNDIS_PACKET) tx_frame_identifier,
+ 0,
+ tx_frame_length,
+ (PUCHAR) tx_slot_cache[active_tx_slot].VirtualAddress,
+ &bytes_copied
+ );
+ }
+ else
+ {
+ MADGE_MOVE_MEMORY(
+ tx_slot_cache[active_tx_slot].VirtualAddress,
+ (PUCHAR) tx_frame_identifier,
+ tx_frame_length
+ );
+ }
+
+ //
+ // Set up the tx slot and start the transmit. If we're using
+ // multiprocessor safe PIO then we must do the DIO via an ISR
+ // synchronised function.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.adapter_handle = adapter_handle;
+ info.adapter = adapter;
+ info.tx_slot_ptr = tx_slot_ptr;
+ info.frame_length = tx_frame_length;
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeStartTx,
+ &info
+ );
+ }
+ else
+ {
+ //
+ // Reset the transmit status in the transmit slot.
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_ptr->tx_status
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ (WORD) 0x8000
+ );
+
+ //
+ // Write in the length of the buffer into the transmit slot
+ // (large buffer).
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_ptr->large_buffer_len
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ (WORD) tx_frame_length
+ );
+
+ //
+ // Write the length of the small buffer in the transmit slot to
+ // start the transmit going.
+ //
+
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_ptr->small_buffer_len
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ FMPLUS_SBUFF_ZERO_LENGTH
+ );
+ }
+
+ //
+ // Note that the slot is in use.
+ //
+
+ tx_slot_mgmnt->number_tx_in_use++;
+
+ //
+ // Update the slot counter ready for the next transmit.
+ //
+
+ if (++tx_slot_mgmnt->active_tx_slot == tx_slots)
+ {
+ tx_slot_mgmnt->active_tx_slot = 0;
+ }
+
+ return DRIVER_TRANSMIT_SUCCEED;
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - ProcessTestAndXIDFrames
+|
+| Paramters - adapHnd -> An FTK adapter handle.
+| framePtr -> Pointer to the start of the frame.
+| frameLen -> The length of the frame.
+| headerLen -> The length of the frame header.
+|
+| Purpose - Process LLC Test and XID frames in the same way as IBM
+| adapter hardware.
+|
+| Returns - TRUE if the frame was processed or FALSE if not.
+|
+|-------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+ProcessTestAndXIDFrames(
+ ADAPTER_HANDLE adapHnd,
+ UCHAR *framePtr,
+ UINT frameLen,
+ UINT headerLen
+ )
+{
+ UINT llcCmd;
+ UINT sSAP;
+ NODE_ADDRESS tempNodeAddr;
+ BOOLEAN doneFrame;
+
+ doneFrame = FALSE;
+
+ //
+ // We are only interested in frames that are LLC (i.e. frame
+ // control byte is 0x40), have a null destination SAP and are
+ // commands (i.e. 0x01 bit of the source SAP is clear).
+ //
+
+ sSAP = framePtr[headerLen + 1];
+
+ if (framePtr[1] == 0x40 &&
+ framePtr[headerLen] == 0x00 &&
+ (sSAP & 0x01) == 0x00)
+ {
+ llcCmd = framePtr[headerLen + 2] & 0xef;
+
+ //
+ // Test frames have an LLC command byte of 0b111x0011.
+ //
+
+ if (llcCmd == 0xe3)
+ {
+ MadgePrint1("Got TEST frame\n");
+
+ //
+ // We don't need to do anything to a test frame
+ // other than send it back.
+ //
+
+ doneFrame = TRUE;
+ }
+
+ //
+ // XID frames have an LLC command byte of 0b101x1111 and
+ // a standard IEEE defined XID frame will have 3 data
+ // bytes and its first data byte set to 0x81.
+ //
+
+ else if (llcCmd == 0xaf &&
+ frameLen == headerLen + 6 &&
+ framePtr[headerLen + 3] == 0x81)
+ {
+ MadgePrint1("Got XID frame\n");
+
+ //
+ // Fill in the XID frame data with 0x81 0x01 0x00
+ // (Standard XID frame, type 1 only and 0 sized
+ // receive window).
+ //
+
+ framePtr[headerLen + 4] = 0x01;
+ framePtr[headerLen + 5] = 0x00;
+
+ doneFrame = TRUE;
+ }
+
+ //
+ // If we've had a TEST or a XID frame then doneFrame will
+ // be TRUE and we should send a frame back.
+ //
+
+ if (doneFrame)
+ {
+ //
+ // Flip the direction bit in the source routing
+ // control word and switch the source routing flag
+ // from the source to destination address.
+ //
+
+ if ((framePtr[8] & 0x80) != 0)
+ {
+ framePtr[14] &= 0x1f; // Clear broadcast bits.
+ framePtr[15] ^= 0x80; // Flip direction bit.
+ framePtr[8] &= 0x7f; // Clear source routing bit.
+ framePtr[2] |= 0x80; // Set source routing bit.
+ }
+
+ //
+ // Swap the node addresses around.
+ //
+
+ tempNodeAddr = *((NODE_ADDRESS *) &framePtr[2]);
+ *((NODE_ADDRESS *) &framePtr[2]) = *((NODE_ADDRESS *) &framePtr[8]);
+ *((NODE_ADDRESS *) &framePtr[8]) = tempNodeAddr;
+
+ //
+ // Swap the SAPs around and set the response bit in the
+ // new source SAP.
+ //
+
+ framePtr[headerLen + 1] = 0x01;
+ framePtr[headerLen] = sSAP;
+ framePtr[0] = 0x10;
+
+ //
+ // And now send the frame.
+ //
+
+ rxtx_transmit_frame(
+ adapHnd,
+ (DWORD) framePtr,
+ (WORD) frameLen,
+ FALSE
+ );
+ }
+ }
+
+ return doneFrame;
+}
+
+
+/*--------------------------------------------------------------------------
+|
+| Function - MPSafeReadRxStatus
+|
+| Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
+|
+| Purpose - Read the status and length of the current rx slot. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MPSafeReadRxStatus(PVOID ptr)
+{
+ MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->rx_slot_ptr)->buffer_len
+ );
+
+ info->result1 = sys_insw(
+ info->adapter_handle,
+ info->adapter->sif_dat
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->rx_slot_ptr)->rx_status
+ );
+
+ info->result2 = sys_insw(
+ info->adapter_handle,
+ info->adapter->sif_dat
+ );
+
+ return FALSE;
+}
+
+/*--------------------------------------------------------------------------
+|
+| Function - MPSafeFreeRxSlot
+|
+| Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
+|
+| Purpose - Free an rx slot. This
+| function is called via NdisSynchronizeWithInterrupt when
+| in PIO mode so that we don't get SIF register contention
+| on a multiprocessor.
+|
+| Returns - Nothing.
+|
+--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MPSafeFreeRxSlot(PVOID ptr)
+{
+ MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_adr,
+ (WORD) (card_t) &(info->rx_slot_ptr)->buffer_len
+ );
+
+ sys_outsw(
+ info->adapter_handle,
+ info->adapter->sif_dat,
+ (WORD) 0x0000
+ );
+
+ return FALSE;
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_irq_rx_frame_handler
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* adapter -> Pointer to an FTK adapter structure.
+*
+* Purpose - Called out of the back or our DPR route via
+* driver_get_outstanding_receive() to process received
+* frames.
+*
+* Note we preserve the value of SIFADR so that the transmit
+* code does not have to worry about it changing under its
+* feet. No we don't because we are called out of a DPR
+* and the wrapper will have grabbed a spin lock so
+* we can't be executing at the same time as the transmit
+* code.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+#define PROM_OR_MAC \
+ (NDIS_PACKET_TYPE_PROMISCUOUS | NDIS_PACKET_TYPE_MAC_FRAME)
+
+void
+rxtx_irq_rx_frame_handler(
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ )
+{
+ BYTE * rx_frame_addr;
+ UINT rx_frame_stat;
+ UINT rx_frame_length;
+ UINT slot_count;
+ UINT active_rx_slot;
+ PRX_SLOT_MGMNT rx_slot_mgmnt;
+ PRX_SLOT_CACHE rx_slot_cache;
+ RX_SLOT * * rx_slot_array;
+ RX_SLOT * rx_slot_ptr;
+ UINT rx_slots;
+ PMADGE_ADAPTER ndisAdap;
+ UINT packet_filter;
+ UINT header_len;
+ BOOLEAN done_frame;
+ BOOLEAN ignore_frame;
+ BOOLEAN test_and_xid;
+ MPSAFE_INFO info;
+ WORD sifadr;
+ WORD sifdat;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ rx_slot_array = adapter->rx_slot_array;
+ rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
+ active_rx_slot = rx_slot_mgmnt->active_rx_slot;
+ rx_slot_cache = rx_slot_mgmnt->rx_slot_cache;
+ rx_slots = adapter->init_block->fastmac_parms.rx_slots;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ packet_filter = ndisAdap->CurrentPacketFilter;
+ test_and_xid = ndisAdap->TestAndXIDEnabled;
+ done_frame = FALSE;
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+
+ //
+ // If we're doing multiprocessor safe PIO then we need to set up
+ // the info structure.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.adapter_handle = adapter_handle;
+ info.adapter = adapter;
+ }
+
+ //
+ // Now read the length and status fields of the current receive slot.
+ // If we are doing multiprocessor safe PIO then we must do the DIO via
+ // an ISR synchronised function.
+ //
+
+ rx_slot_ptr = rx_slot_array[active_rx_slot];
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.rx_slot_ptr = rx_slot_ptr;
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeReadRxStatus,
+ &info
+ );
+
+ rx_frame_length = info.result1;
+ rx_frame_stat = info.result2;
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->buffer_len
+ );
+
+ rx_frame_length = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->rx_status
+ );
+
+ rx_frame_stat = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+
+ }
+
+ //
+ // Try to receive as many frames as possible, but only examine as many
+ // slots as we have, otherwise we might end up going round this loop
+ // forever! If we do stop and there is still a frame to be received, we
+ // will be re-interrupted anyway.
+ //
+
+ slot_count = 0;
+
+ while (rx_frame_length != 0 && slot_count++ < rx_slots)
+ {
+ //
+ // It is possible that a PCMCIA adapter may have been removed
+ // in which case we must not wait forever. If an adapter has
+ // been removed we would expect to read 0xffff from any IO
+ // location occupied by the adapter. 0xffff is not a valid
+ // value for an FMP RX status.
+ //
+
+ if (rx_frame_stat == 0xffff)
+ {
+ MadgePrint1("Rx frame: RX status == 0xffff\n");
+ ndisAdap->AdapterRemoved = TRUE;
+ return;
+ }
+
+ //
+ // FastMAC Plus includes the CRC in the frame length.
+ //
+
+ rx_frame_length -= 4;
+
+ if ((rx_frame_stat & GOOD_RX_FRAME_MASK) == 0)
+ {
+ //
+ // We have got a good frame here.
+ //
+
+ rx_frame_addr = rx_slot_cache[active_rx_slot].VirtualAddress;
+
+ header_len = (FRAME_IS_SOURCE_ROUTED(rx_frame_addr))
+ ? FRAME_HEADER_SIZE + FRAME_SOURCE_ROUTING_BYTES(rx_frame_addr)
+ : FRAME_HEADER_SIZE;
+
+ //
+ // Check for a frame copied error.
+ //
+
+ if ((rx_frame_addr[2] & 0x80) && (rx_frame_stat & 0x80))
+ {
+ ndisAdap->FrameCopiedErrors++;
+ }
+
+ //
+ // We may have to behave like the hardware of an IBM adapter
+ // and process LLC TEST and XID frames ourselves.
+ //
+
+ if (test_and_xid)
+ {
+ ignore_frame = ProcessTestAndXIDFrames(
+ adapter_handle,
+ rx_frame_addr,
+ rx_frame_length,
+ header_len
+ );
+ }
+ else
+ {
+ ignore_frame = FALSE;
+ }
+
+ //
+ // If we've got a valid frame then pass it up to the user.
+ //
+
+ if (!ignore_frame &&
+ ((rx_frame_addr[1] & FRAME_TYPE_MASK) != FRAME_TYPE_MAC ||
+ (packet_filter & PROM_OR_MAC) != 0))
+ {
+ //
+ // When indicating the frame, we can pass all of it
+ // as lookahead if we want, but we ought to take
+ // account of the current lookahead setting in case it
+ // is less than the frame size. This becomes important in
+ // WFWG, where it is unable to cope with large lookaheads. The
+ // lookahead length used to be :
+ // (UINT) rx_frame_length - header_len
+ //
+
+ NdisMTrIndicateReceive(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (NDIS_HANDLE) (rx_frame_addr + header_len),
+ (PVOID) rx_frame_addr,
+ (UINT) header_len,
+ (PVOID) (rx_frame_addr + header_len),
+ (UINT) MIN(
+ ndisAdap->CurrentLookahead,
+ (rx_frame_length - header_len)
+ ),
+ (UINT) (rx_frame_length - header_len)
+ );
+
+ //
+ // Note that we've given the upper protocol at
+ // least one frame.
+ //
+
+ done_frame = TRUE;
+
+ ndisAdap->FramesReceived++;
+
+#ifdef OID_MADGE_MONITOR
+ //
+ // Update the appropriate parts of the monitor structure
+ //
+ (ndisAdap->MonitorInfo).ReceiveFrames++;
+ (ndisAdap->MonitorInfo).ReceiveFrameSize[rx_frame_length/128]++;
+ (ndisAdap->MonitorInfo).CurrentFrameSize = rx_frame_length;
+ (ndisAdap->MonitorInfo).ReceiveFlag = 1;
+#endif
+ }
+ }
+
+ //
+ // Otherwise we have some sort of receive error.
+ //
+
+ else
+ {
+ ndisAdap->FrameReceiveErrors++;
+ }
+
+ //
+ // Zero the frame length so that FastMAC Plus can reuse the buffer.
+ // If we're doing multiprocessor safe PIO then we must do the DIO
+ // via an ISR synchronised function.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.rx_slot_ptr = rx_slot_ptr;
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeFreeRxSlot,
+ &info
+ );
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->buffer_len
+ );
+
+ sys_outsw(
+ adapter_handle,
+ sifdat,
+ 0x0000
+ );
+ }
+
+ //
+ // Update the active receive slot pointer.
+ //
+
+ if (++active_rx_slot == rx_slots)
+ {
+ active_rx_slot = 0;
+ }
+
+ rx_slot_mgmnt->active_rx_slot = active_rx_slot;
+
+ //
+ // Now we had better look at the next slot in case another frame
+ // has been received.
+ //
+
+ rx_slot_ptr = rx_slot_array[active_rx_slot];
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.rx_slot_ptr = rx_slot_ptr;
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeReadRxStatus,
+ &info
+ );
+
+ rx_frame_length = info.result1;
+ rx_frame_stat = info.result2;
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->buffer_len
+ );
+
+ rx_frame_length = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &rx_slot_ptr->rx_status
+ );
+
+ rx_frame_stat = sys_insw(
+ adapter_handle,
+ sifdat
+ );
+
+ }
+ }
+
+ //
+ // If we've given the upper protocol a frame then call the
+ // receive completion routine.
+ //
+
+ if (done_frame)
+ {
+ NdisMTrIndicateReceiveComplete(ndisAdap->UsedInISR.MiniportHandle);
+ }
+}
+
+
+
+/***************************************************************************
+*
+* Function - rxtx_abort_txing_frames
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Stop sending frames.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_abort_txing_frames(ADAPTER_HANDLE adapter_handle)
+{
+ //
+ // Nothing to do here.
+ //
+}
+
+
+/***************************************************************************
+*
+* Function - rxtx_await_empty_tx_slots
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Wait until all of the tx slots are empty.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_await_empty_tx_slots(ADAPTER_HANDLE adapter_handle)
+{
+ ADAPTER * adapter;
+ FASTMAC_INIT_PARMS * fastmac_parms;
+ TX_SLOT * * tx_slot_array;
+ UINT i;
+ UINT status;
+ PMADGE_ADAPTER ndisAdap;
+ MPSAFE_INFO info;
+ WORD sifadr;
+ WORD sifdat;
+
+ if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_ANY_STATE))
+ {
+ MadgePrint1("rxtx_await_empty_tx_slots: adapter not running\n");
+ return;
+ }
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter = adapter_record[adapter_handle];
+ fastmac_parms = &adapter->init_block->fastmac_parms;
+ tx_slot_array = adapter->tx_slot_array;
+ info.adapter_handle = adapter_handle;
+ info.adapter = adapter;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ sifadr = adapter->sif_adr;
+ sifdat = adapter->sif_dat;
+
+ for (i = 0; i < fastmac_parms->tx_slots; i++)
+ {
+ do
+ {
+ //
+ // Get the slot status. If we are doing multiprocessor safe
+ // PIO then we must do this with an ISR synchronised function.
+ //
+
+ if (ndisAdap->UseMPSafePIO)
+ {
+ info.tx_slot_ptr = tx_slot_array[i];
+
+ NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ MPSafeReadTxStatus,
+ &info
+ );
+
+ status = info.result1;
+ }
+ else
+ {
+ sys_outsw(
+ adapter_handle,
+ sifadr,
+ (WORD) (card_t) &tx_slot_array[i]->tx_status
+ );
+
+ status = sys_insw(adapter_handle, sifdat);
+ }
+
+ //
+ // It is possible that a PCMCIA adapter may have been removed
+ // in which case we must not wait forever. If an adapter has
+ // been removed we would expect to read 0xffff from any IO
+ // location occupied by the adapter. 0xffff is not a valid
+ // value for an FMP TX status.
+ //
+
+ if (status == 0xffff)
+ {
+ MadgePrint1("Await empty tx: TX status == 0xffff\n");
+ return;
+ }
+ }
+ while (status >= 0x8000 || status == 0);
+ }
+}
+
+
+/***************************************************************************
+*
+* Function - user_completed_srb
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* srb_completed_successfully -> SRB successful?
+*
+* Purpose - Record that an SRB has completed and arrange for our
+* DPR to be scheduled.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+user_completed_srb(
+ ADAPTER_HANDLE adapter_handle,
+ WBOOLEAN srb_completed_successfully
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // If we have issued a private SRB then we just clear the
+ // private SRB flag. Otherwise we need to arrange for our
+ // DPR to be told about the SRB.
+ //
+
+ if (ndisAdap->PrivateSrbInProgress)
+ {
+ ndisAdap->PrivateSrbInProgress = FALSE;
+ }
+ else
+ {
+ ndisAdap->UsedInISR.SrbRequestStatus = (BOOLEAN) srb_completed_successfully;
+ ndisAdap->UsedInISR.SrbRequestCompleted = TRUE;
+ ndisAdap->DprRequired = TRUE;
+ }
+}
+
+
+/***************************************************************************
+*
+* Function - user_shedule_receive_process
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Arrange for our DPR to be scheduled so that we can deal
+* with received frames.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+
+void
+user_schedule_receive_process(ADAPTER_HANDLE adapter_handle)
+{
+ PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->DprRequired = TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - user_adapter_removed
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Arrange for our DPR to be scheduled so that we can deal
+* with a removed adapter.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+
+void
+user_adapter_removed(ADAPTER_HANDLE adapter_handle)
+{
+ PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->DprRequired = TRUE;
+ PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->AdapterRemoved = TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - user_handle_adapter_check
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Called on an adapter check. Not a lot we can do really!
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+
+void
+user_handle_adapter_check(ADAPTER_HANDLE adapter_handle)
+{
+ MadgePrint1("Adapter Check!!!!\n");
+}
+
+
+//
+// Currently we are not supporting transmit modes that require
+// user completion routine.
+//
+
+#if 0
+
+/***************************************************************************
+*
+* Function - user_transmit_completion
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* identifier -> NDIS packet handle.
+*
+* Purpose - To notify an upper protocol that a transmit has completed.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+
+void
+user_transmit_completion(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD identifier
+ )
+{
+}
+
+#endif
+
+
+/***************************************************************************
+*
+* Function - rxtx_adapter_removed
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+*
+* Purpose - Called to tidy up when we find out that the adapter has
+* been removed. All we do is tell the wrapper that we
+* have finished any submitted transmits.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+rxtx_adapter_removed(
+ ADAPTER_HANDLE adapter_handle
+ )
+{
+ ADAPTER * adapter;
+ PTX_SLOT_MGMNT tx_slot_mgmnt;
+ UINT tx_slots;
+ PMADGE_ADAPTER ndisAdap;
+
+ //
+ // Pre-calculate some commonly used values.
+ //
+
+ adapter = adapter_record[adapter_handle];
+ tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
+ tx_slots = adapter->init_block->fastmac_parms.tx_slots;
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // Note that the adapter has been removed.
+ //
+
+ ndisAdap->AdapterRemoved = TRUE;
+
+ //
+ // Iterate around the transmit slots that are in use and
+ // up call to indicate that the transmits are over.
+ //
+
+ while (tx_slot_mgmnt->number_tx_in_use > 0)
+ {
+ //
+ // Update the slot usage.
+ //
+
+ tx_slot_mgmnt->number_tx_in_use--;
+
+ if (++tx_slot_mgmnt->first_tx_in_use == tx_slots)
+ {
+ tx_slot_mgmnt->first_tx_in_use = 0;
+ }
+
+ //
+ // Tell the wrapper that there is a free slot.
+ //
+
+ NdisMSendResourcesAvailable(ndisAdap->UsedInISR.MiniportHandle);
+ }
+}
+
+
+/******** End of FTK_USER.C ***********************************************/
+
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_adap.h b/private/ntos/ndis/madge/driver/head_def/ftk_adap.h
new file mode 100644
index 000000000..b5f982bc7
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_adap.h
@@ -0,0 +1,280 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE ADAPTER DEFINITIONS */
+/* ======================= */
+/* */
+/* FTK_ADAP.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for the structure which is */
+/* used to maintain information on an adapter that is being used by the */
+/* FTK. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_ADAP.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_ADAP_H 221
+
+
+/****************************************************************************/
+/* */
+/* TYPEDEFs for all structures defined within this header file : */
+/* */
+
+typedef struct STRUCT_ADAPTER ADAPTER;
+
+
+/****************************************************************************/
+/* */
+/* Structure type : ADAPTER */
+/* */
+/* The adapter structure is used to maintain all the information for a */
+/* single adapter. This includes information on the Fastmac for the */
+/* adapter. Most of the fields are filled in from the user supplied adapter */
+/* information to driver_prepare_adapter and driver_start_adapter. */
+/* */
+
+struct STRUCT_ADAPTER
+ {
+ void (*set_dio_address) (struct STRUCT_ADAPTER*, DWORD);
+ void (*interrupt_handler) (struct STRUCT_ADAPTER*);
+ void (*remove_card) (struct STRUCT_ADAPTER*);
+ UINT adapter_card_bus_type;
+ UINT adapter_card_type;
+ UINT adapter_card_revision;
+ UINT adapter_ram_size; /* Depends on card type. */
+#ifdef PCMCIA_POINT_ENABLE
+ UINT socket; /* Socket passed to point
+ enabler. */
+ BOOLEAN drop_int; /* Flag used to stop a
+ spurious interrupt being
+ claimed. */
+#endif
+ WORD io_location;
+ WORD io_range;
+ WORD interrupt_number; /* 0 == Polling mode */
+ WBOOLEAN edge_triggered_ints;
+ WORD nselout_bits; /* IRQ select on Smart16 */
+ WORD dma_channel;
+ UINT transfer_mode; /* DMA/MMIO/PIO */
+ WBOOLEAN EaglePsDMA;
+ WORD mc32_config; /* special config info */
+ NODE_ADDRESS permanent_address; /* BIA PROM node address */
+ UINT ring_speed;
+ WBOOLEAN speed_detect; /* Card is capable of detecting ring speed */
+ WORD max_frame_size; /* determined by ring speed */
+ UINT set_ring_speed; /* Force ring speed to this */
+ DWORD mmio_base_address; /* MMIO base address */
+ DWORD pci_handle; /* PCI slot handle. */
+ WBOOLEAN use_32bit_pio;
+ WORD sif_dat; /* SIF register IO locations*/
+ WORD sif_datinc;
+ WORD sif_adr;
+ WORD sif_int;
+ WORD sif_acl;
+ WORD sif_adr2;
+ WORD sif_adx;
+ WORD sif_dmalen;
+ WORD sif_sdmadat;
+ WORD sif_sdmaadr;
+ WORD sif_sdmaadx;
+ WORD c46_bits; /* Bits we must remember in */
+ /* the AT93C46 control reg. */
+
+
+ WBOOLEAN set_irq; /* set IRQ if possible */
+ WBOOLEAN set_dma; /* set DMA if possible */
+
+ SRB_GENERAL srb_general; /* SRB for this adapter */
+ WORD size_of_srb; /* size of current SRB */
+
+ DOWNLOAD_IMAGE * download_image; /* ptr Fastmac binary image */
+ INITIALIZATION_BLOCK * init_block; /* ptr Fastmac init block */
+ SRB_HEADER * srb_dio_addr; /* addr of SRB in DIO space */
+ FASTMAC_STATUS_BLOCK * stb_dio_addr; /* addr of STB in DIO space */
+
+ WBOOLEAN interrupts_on; /* for this adapter */
+ WBOOLEAN dma_on; /* for this adapter */
+
+ UINT adapter_status; /* prepared or running */
+ UINT srb_status; /* free or in use */
+ ERROR_RECORD error_record; /* error type and value */
+ ERROR_MESSAGE error_message; /* error message string */
+
+ STATUS_INFORMATION * status_info; /* ptr adapter status info */
+
+ void * user_information; /* User's private data. */
+
+ ADAPTER_HANDLE adapter_handle;
+
+#ifdef FMPLUS
+
+ DWORD dma_test_buf_phys;
+ DWORD dma_test_buf_virt;
+
+
+ RX_SLOT * rx_slot_array[FMPLUS_MAX_RX_SLOTS];
+ /* Rx slot DIO addresses */
+ TX_SLOT * tx_slot_array[FMPLUS_MAX_TX_SLOTS];
+ /* Tx slot DIO addresses */
+
+ void * rx_slot_mgmnt; /* pointer to user slot */
+ void * tx_slot_mgmnt; /* management structures. */
+
+#else
+
+ DWORD rx_buffer_phys; /* RX buffer physical address*/
+ DWORD rx_buffer_virt; /* RX buffer virtual address */
+ DWORD tx_buffer_phys; /* TX buffer physical address*/
+ DWORD tx_buffer_virt; /* TX buffer virtual address */
+
+#endif
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : ADAPTER - WORD adapter_card_type */
+/* */
+/* The following are the different types of adapter cards supported by the */
+/* FTK (and their subtypes). */
+/* */
+
+#define ADAPTER_CARD_TYPE_16_4_AT 2
+
+#define ADAPTER_CARD_16_4_PC 0
+#define ADAPTER_CARD_16_4_MAXY 1
+#define ADAPTER_CARD_16_4_AT 2
+#define ADAPTER_CARD_16_4_FIBRE 3
+#define ADAPTER_CARD_16_4_BRIDGE 4
+#define ADAPTER_CARD_16_4_ISA_C 5
+#define ADAPTER_CARD_16_4_AT_P_REV 6
+#define ADAPTER_CARD_16_4_FIBRE_P 7
+#define ADAPTER_CARD_16_4_ISA_C_P 8
+#define ADAPTER_CARD_16_4_AT_P 9
+
+#define ADAPTER_CARD_TYPE_16_4_MC 3
+
+#define ADAPTER_CARD_TYPE_16_4_MC_32 4
+
+#define ADAPTER_CARD_TYPE_16_4_EISA 5
+
+#define ADAPTER_CARD_16_4_EISA_MK1 1
+#define ADAPTER_CARD_16_4_EISA_MK2 2
+#define ADAPTER_CARD_16_4_EISA_BRIDGE 3
+#define ADAPTER_CARD_16_4_EISA_MK3 4
+
+#define ADAPTER_CARD_TYPE_SMART_16 6
+#define ADAPTER_CARD_SMART_16 1
+
+#define ADAPTER_CARD_TYPE_16_4_PCI 7
+#define ADAPTER_CARD_16_4_PCI 0
+
+#define ADAPTER_CARD_TYPE_16_4_PCMCIA 8
+#define ADAPTER_CARD_16_4_PCMCIA 1
+
+#define ADAPTER_CARD_TYPE_16_4_PNP 9
+#define ADAPTER_CARD_PNP 0
+
+#define ADAPTER_CARD_TYPE_16_4_PCIT 10
+#define ADAPTER_CARD_16_4_PCIT 0
+
+#define ADAPTER_CARD_TYPE_16_4_PCI2 11
+#define ADAPTER_CARD_16_4_PCI2 0
+
+#define ADAPTER_CARD_UNKNOWN 255
+
+/****************************************************************************/
+/* */
+/* Values : ADAPTER - WORD adapter_status */
+/* */
+/* These values are for the different required states of the adapter when */
+/* using the FTK. */
+/* */
+
+#define ADAPTER_PREPARED_FOR_START 0
+#define ADAPTER_RUNNING 1
+
+
+/****************************************************************************/
+/* */
+/* Values : ADAPTER - WORD srb_status */
+/* */
+/* These values are for the different required states of the SRB, */
+/* associated with an adapter, when using the FTK. */
+/* */
+
+#define SRB_ANY_STATE 0
+#define SRB_FREE 1
+#define SRB_NOT_FREE 2
+
+
+/****************************************************************************/
+/* */
+/* Value : Number of Adapters supported */
+/* */
+/* The FTK supports a specified maximum number of adapters. The smaller */
+/* this value is, the less memory that is used. This is especially true */
+/* when considering system specific parts such as the DOS example code */
+/* within this FTK. It uses the maximum number of adapters value for */
+/* determining the size of static arrays of adapter structures and */
+/* initialization blocks. It also uses it for determining the number of */
+/* interrupt stubs required given that : */
+/* */
+/* NOTE : If using the DOS example system specific code, then it must be */
+/* the case that MAX_NUMBER_OF_ADAPTERS defined here equals */
+/* MAX_NUMBER_OF_ADAPTERS as defined in SYS_IRQ.ASM. */
+/* */
+
+#define MAX_NUMBER_OF_ADAPTERS 8
+
+
+#define ISA_IO_LOCATIONS 4
+#define MAX_ISA_ADAPATERS ISA_IO_LOCATIONS
+
+#define MC_IO_LOCATIONS 8
+#define MAX_MC_ADAPATERS MC_IO_LOCATIONS
+
+#define MC32_IO_LOCATIONS 8
+#define MAX_MC32_ADAPATERS MC32_IO_LOCATIONS
+
+
+/****************************************************************************/
+/* */
+/* Varaibles : adapter_record array */
+/* */
+/* The FTK maintains an array of pointers to the adapter structures used to */
+/* maintain information on the different adapters being used. This array is */
+/* exported by DRV_INIT.C. */
+/* */
+
+extern ADAPTER * adapter_record[MAX_NUMBER_OF_ADAPTERS];
+
+/****************************************************************************/
+/* */
+/* Macro: FTK_ADAPTER_USER_INFORMATION */
+/* */
+/* A macro to let FTK users get at their private adapter information from */
+/* an adapter handle. */
+/* */
+
+#define FTK_ADAPTER_USER_INFORMATION(adapter_handle) \
+ (adapter_record[(adapter_handle)]->user_information)
+
+
+/* */
+/* */
+/************** End of FTK_ADAP.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_at.h b/private/ntos/ndis/madge/driver/head_def/ftk_at.h
new file mode 100644
index 000000000..45d6c4345
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_at.h
@@ -0,0 +1,234 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (ATULA CARDS) */
+/* ================================================ */
+/* */
+/* FTK_AT.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge ATULA */
+/* adapter cards. Each adapter card has a number of control and status */
+/* registers. ALL bits in ALL registers are defined by Madge Networks Ltd, */
+/* however only a restricted number are defined below as used within the */
+/* FTK. All other bits must NOT be changed and no support will be offered */
+/* for any application that does so or uses the defined bits in any way */
+/* different to the FTK. */
+/* */
+/* Note: The ATULA is Madge Network's name for the ASIC on its 16/4 AT and */
+/* 16/4 PC adapter cards. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_AT.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_AT_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : ATULA REGISTER MAP */
+/* */
+/* Madge 16/4 AT and 16/4 PC adapter cards both use the ATULA and hence */
+/* have the following register map. By setting certain bits in the control */
+/* registers it is possible to page in a) the status register or the PIO */
+/* address registers, b) the BIA PROM (page 0 or page 1) or the EAGLE SIF */
+/* registers (normal or extended). */
+/* */
+/* NB. There is a lot of similarity between the ATULA and MC register maps. */
+/* */
+
+#define ATULA_IO_RANGE 32
+
+#define ATULA_CONTROL_REGISTER_1 1
+#define ATULA_CONTROL_REGISTER_2 2
+#define ATULA_STATUS_REGISTER 3
+#define ATULA_CONTROL_REGISTER_6 6
+#define ATULA_CONTROL_REGISTER_7 7
+
+#define ATULA_FIRST_SIF_REGISTER 8
+
+#define ATULA_BIA_PROM 8
+
+#define ATULA_PIO_ADDRESS_LOW_REGISTER 3
+#define ATULA_PIO_ADDRESS_MID_REGISTER 4
+#define ATULA_PIO_ADDRESS_HIGH_REGISTER 5
+
+#define AT_P_EISA_REV2_CTRL_REG 21
+#define AT_P_SW_CONFIG_REG 22
+
+/****************************************************************************/
+/* */
+/* Values : ATULA CONTROL_REGISTER_1 */
+/* */
+/* These are the bit definitions for control register 1 on ATULA cards. */
+/* */
+/* NB. The bit definitions are mostly the same as MC CONTROL_REGISTER_1. */
+/* */
+
+#define ATULA_CTRL1_SINTREN ((BYTE) 0x01) /* SIF interrupt enable */
+#define ATULA_CTRL1_NSRESET ((BYTE) 0x04) /* active low SIF reset */
+#define ATULA_CTRL1_SRSX ((BYTE) 0x40) /* SIF extended register select */
+#define ATULA_CTRL1_4_16_SEL ((BYTE) 0x80) /* Select 4 or 16 Mb/s */
+
+
+/****************************************************************************/
+/* */
+/* Values : ATULA CONTROL_REGISTER_2 BITS */
+/* */
+/* These are the bit definitions for control register 2 on ATULA cards. */
+/* */
+
+#define ATULA_CTRL2_CS16DLY ((BYTE) 0x01) /* 1=REV3, 0=REV4 bus timings */
+#define ATULA_CTRL2_ADDSEL ((BYTE) 0x04) /* page in PIO addr regs (PIO) */
+#define ATULA_CTRL2_SHRQEN ((BYTE) 0x10) /* SHRQ enable (PIO) */
+#define ATULA_CTRL2_INTEN ((BYTE) 0x20) /* overall interrupt enable */
+#define ATULA_CTRL2_SHRQ ((BYTE) 0x40) /* SHRQ pin status (PIO) */
+#define ATULA_CTRL2_SHLDA ((BYTE) 0x80) /* SHLDA pin status (PIO) */
+
+
+/****************************************************************************/
+/* */
+/* Values : ATULA CONTROL_REGISTER_6 BITS */
+/* */
+/* These are the bit definitions for control register 6 on ATULA cards. */
+/* */
+
+#define ATULA_CTRL6_MODES ((BYTE) 0x03) /* transfer mode (2 bits) */
+#define ATULA_CTRL6_UDRQ ((BYTE) 0x04) /* user generate DMA request */
+#define ATULA_CTRL6_DMAEN ((BYTE) 0x08) /* enable DMA */
+#define ATULA_CTRL6_CLKSEL ((BYTE) 0xC0) /* clock speed select (2 bits) */
+
+
+/****************************************************************************/
+/* */
+/* Values : ATULA CONTROL_REGISTER_7 */
+/* */
+/* These are the bit definitions for control register 7 on ATULA cards. */
+/* */
+/* NB. The bit definitions are mostly the same as MC CONTROL_REGISTER_0. */
+/* */
+
+#define ATULA_CTRL7_SIFSEL ((BYTE) 0x04) /* page in BIA PROM or SIF regs */
+#define ATULA_CTRL7_PAGE ((BYTE) 0x08) /* pages BIA PROM or EEPROM */
+#define ATULA_CTRL7_UINT ((BYTE) 0x10) /* user generate interrupt */
+#define ATULA_CTRL7_SINTR ((BYTE) 0x40) /* SIF interrupt pending */
+#define ATULA_CTRL7_REV_4 ((BYTE) 0x80) /* 1=REV4, 0=REV3 mode */
+
+
+/****************************************************************************/
+/* */
+/* Values : ATULA STATUS_REGISTER BITS */
+/* */
+/* These are the bit definitions for the status register on ATULA cards. */
+/* */
+
+#define ATULA_STATUS_SDDIR ((BYTE) 0x10) /* data xfer direction (PIO) */
+#define ATULA_STATUS_ASYN_BUS ((BYTE) 0x20) /* asynchronous bus */
+#define ATULA_STATUS_BUS8 ((BYTE) 0x40) /* 8 bit slot */
+
+
+/****************************************************************************/
+/* */
+/* Values : MODE IN ATULA CONTROL_REGISTER_6 */
+/* */
+/* The two mode select bits in control register 6 (ATULA_CTRL6_MODES) are */
+/* configured for the data transfer mode being used. */
+/* */
+
+#define ATULA_CTRL6_MODE_BUS_MASTER ((BYTE) 0x03) /* bus master DMA mode */
+#define ATULA_CTRL6_MODE_PIO ((BYTE) 0x00) /* PIO mode */
+
+
+/****************************************************************************/
+/* */
+/* Values : CLOCK SPEED IN ATULA CONTROL_REGISTER_6 */
+/* */
+/* The two SIF clock speed select bits in control register 6 */
+/* (ATULA_CTRL6_CLKSEL) are configured for either on-board (8MHz) or host */
+/* oscillator frequency. */
+/* */
+
+#define ATULA_CTRL6_CLKSEL_HOST ((BYTE) 0xC0) /* host bus */
+#define ATULA_CTRL6_CLKSEL_ON_BOARD ((BYTE) 0x00) /* 8Mhz on board */
+
+
+/****************************************************************************/
+/* */
+/* Values : FIELDS IN THE AT_P_EISA_REV2_CTRL REGISTER */
+/* */
+/* These bit masks define bit fields within the AT/P control register. */
+/* */
+
+#define ATP_RSCTRL ((BYTE) 0x08)
+#define ATP_CLKDIV ((BYTE) 0x10)
+
+
+/****************************************************************************/
+/* */
+/* Values : FIELDS IN THE AT_P_SW_CONFIG REGISTER */
+/* */
+/* These bit masks define bit fields within the AT/P control register. */
+/* */
+
+#define ATP_INTSEL0 ((BYTE) 0x01)
+#define ATP_INTSEL1 ((BYTE) 0x02)
+#define ATP_INTSEL2 ((BYTE) 0x04)
+#define ATP_INTSEL ((BYTE) 0x07)
+
+#define ATP_DMA0 ((BYTE) 0x08)
+#define ATP_DMA1 ((BYTE) 0x10)
+#define ATP_DMA ((BYTE) 0x18)
+
+#define ATP_S4N16 ((BYTE) 0x40)
+
+/****************************************************************************/
+/* */
+/* Value : PIO IO LOCATION */
+/* */
+/* The IO location used during PIO for reading/writing data from/to the */
+/* adapter card is mapped on top of the EAGLE SIFDAT register in the ATULA */
+/* card register map. */
+/* */
+
+#define ATULA_PIO_IO_LOC 0
+
+
+/****************************************************************************/
+/* */
+/* Values : ATULA EXTENDED EAGLE SIF REGISTERS */
+/* */
+/* The EAGLE SIF registers are in two groups - the normal SIF registers */
+/* (those from the old TI chipset) and the extended SIF registers (those */
+/* particular to the EAGLE). For Madge ATULA adapter cards, with */
+/* CTRL7_SIFSEL = 1 and CTRL1_NRESET = 1, having CTRL1_SRSX = 0 selects the */
+/* normal SIF registers and having CTRL1_SRSX = 1 selects the extended SIF */
+/* registers. */
+/* */
+/* The definitions for the normal SIF registers are in FTK_CARD.H because */
+/* they appear in the same relative IO locations for all adapter cards. The */
+/* extended SIF registers are here because they appear at different */
+/* relative IO locations for different types of adapter cards. For ATULA */
+/* and MC cards they are in fact identical. */
+/* */
+
+#define ATULA_EAGLE_SIFACL 0 /* adapter control */
+#define ATULA_EAGLE_SIFADR_2 2 /* copy of SIFADR */
+#define ATULA_EAGLE_SIFADX 4 /* DIO address (high) */
+#define ATULA_EAGLE_DMALEN 6 /* DMA length */
+
+
+/* */
+/* */
+/************** End of FTK_AT.H file ****************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_card.h b/private/ntos/ndis/madge/driver/head_def/ftk_card.h
new file mode 100644
index 000000000..02c4e4ef0
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_card.h
@@ -0,0 +1,341 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE ADAPTER CARD DEFINITIONS : EAGLE (TMS 380 2nd GEN) */
+/* ====================================================== */
+/* */
+/* FTK_CARD.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions specific to the TI EAGLE (TMS */
+/* 380 2nd generation) chipset and the bring-up, initialization and opening */
+/* of the adapter. It also contains the details of the BIA PROM on ATULA */
+/* and MC cards. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_CARD.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_CARD_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : EAGLE SIF REGISTERS */
+/* */
+/* The EAGLE SIF registers are in two groups - the normal SIF registers */
+/* (those from the old TI chipset) and the extended SIF registers (those */
+/* particular to the EAGLE). */
+/* */
+/* The definitions for the normal SIF registers are here because they */
+/* appear in the same relative IO locations for all adapter cards. The */
+/* definitions for the extended SIF registers are in the FTK_<card_type>.H */
+/* files. */
+/* */
+
+#define EAGLE_SIFDAT 0 /* DIO data */
+#define EAGLE_SIFDAT_INC 2 /* DIO data auto-increment */
+#define EAGLE_SIFADR 4 /* DIO address (low) */
+#define EAGLE_SIFINT 6 /* interrupt SIFCMD-SIFSTS */
+
+/* These definitions are for the case when the SIF registers are mapped */
+/* linearly. Otherwise, they will be at some extended location. */
+
+#define EAGLE_SIFACL 8
+#define EAGLE_SIFADX 12
+
+/* These definitions are for Eagle Pseudo DMA. Notice that they replace the */
+/* registers above - this is controlled by SIFACL. */
+
+#define EAGLE_SDMADAT 0
+#define EAGLE_DMALEN 2
+#define EAGLE_SDMAADR 4
+#define EAGLE_SDMAADX 6
+
+/****************************************************************************/
+/* */
+/* Value : Number of IO locations for SIF registers */
+/* */
+/* The number of SIF registers is only needed for enabling and disabling */
+/* ranges of IO ports. For the ATULA and MC cards the SIF registers are in */
+/* 2 pages only using 8 IO ports. However, for EISA cards, the SIF */
+/* registers are in a single page of 16 IO ports. Hence, 16 IO ports need */
+/* to be enabled whenever accessing SIF registers. */
+/* */
+
+#define SIF_IO_RANGE 16
+
+/****************************************************************************/
+/* */
+/* Value : Number of IO locations for adapter cards */
+/* */
+/* The maximum IO range required for the register map of any type of */
+/* adapter card is that used by the EISA card. The ATULA based cards have */
+/* the largest contiguous IO range, however. The EISA range is split into */
+/* two, the upper range only being used during installation. */
+/* */
+
+#define MAX_CARD_IO_RANGE ATULA_IO_RANGE
+
+
+/****************************************************************************/
+/* */
+/* Values : MAX FRAME SIZES SUPPORTED */
+/* */
+/* Depending on the ring speed (4 Mbit/s or 16 Mbit/s) different maximum */
+/* frame sizes are supported as defined in the ISO standards. The ISO */
+/* standards give the maximum size of the information field to which has to */
+/* added the MAC header, SR info fields etc. to give real maximum token */
+/* ring frame size. */
+/* */
+
+#define MAC_FRAME_SIZE 39
+
+#define MIN_FRAME_SIZE (256 + MAC_FRAME_SIZE)
+#define MAX_FRAME_SIZE_4_MBITS (4472 + MAC_FRAME_SIZE)
+#define MAX_FRAME_SIZE_16_MBITS (17800 + MAC_FRAME_SIZE)
+
+
+/****************************************************************************/
+/* */
+/* Values : EAGLE ADAPTER CONTROL (SIFACL) REGISTER BITS */
+/* */
+/* The bits in the EAGLE extended SIF register EAGLE_SIFACL can be used for */
+/* general controlling of the adapter card. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-18 4.3.1 SIFACL - SIF Adapter Control Register */
+/* */
+
+#define EAGLE_SIFACL_SWHLDA 0x0800 /* for EAGLE pseudo-DMA */
+#define EAGLE_SIFACL_SWDDIR 0x0400 /* data transfer direction */
+#define EAGLE_SIFACL_SWHRQ 0x0200 /* DMA pending */
+#define EAGLE_SIFACL_PSDMAEN 0x0100 /* for EAGLE pseudo-DMA */
+#define EAGLE_SIFACL_ARESET 0x0080 /* adapter reset */
+#define EAGLE_SIFACL_CPHALT 0x0040 /* halt EAGLE */
+#define EAGLE_SIFACL_BOOT 0x0020 /* bootstrap */
+#define EAGLE_SIFACL_RESERVED1 0x0010 /* reserved */
+#define EAGLE_SIFACL_SINTEN 0x0008 /* system interrupt enable */
+#define EAGLE_SIFACL_PARITY 0x0004 /* adapter parity enable */
+#define EAGLE_SIFACL_INPUT0 0x0002 /* reserved */
+#define EAGLE_SIFACL_RESERVED2 0x0001 /* reserved */
+
+
+/****************************************************************************/
+/* */
+/* Values : DIO LOCATIONS */
+/* */
+/* When initializing an adapter the initialization block must be downloaded */
+/* to location 0x00010A00L in DIO space. */
+/* */
+/* The ring speed, from which the maximum frame size is deduced, can be */
+/* determined by the value in the ring speed register at DIO address 0x0142 */
+/* in the EAGLE DATA page 0x00010000. */
+/* */
+
+#define DIO_LOCATION_INIT_BLOCK 0x00010A00L
+
+#define DIO_LOCATION_EAGLE_DATA_PAGE 0x00010000L
+#define DIO_LOCATION_RING_SPEED_REG 0x0142
+
+#define RING_SPEED_REG_4_MBITS_MASK 0x0400
+
+#define DIO_LOCATION_EXT_DMA_ADDR 0x010E
+#define DIO_LOCATION_DMA_ADDR 0x0110
+
+#define DIO_LOCATION_DMA_CONTROL 0x100A
+
+/****************************************************************************/
+/* */
+/* Values : EAGLE BRING UP INTERRUPT REGISTER VALUES */
+/* */
+/* The code produced at the SIFSTS part of the SIF interrupt register at */
+/* bring up time indicates the success or failure of the bring up. The */
+/* success or failure is determined by looking at the top nibble. On */
+/* success, the INITIALIZE bit is set. On failure, the TEST and ERROR bits */
+/* are set and the error code is in the bottom nibble. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-40 4.5 Bring-Up Diagnostics - BUD */
+/* */
+
+#define EAGLE_SIFINT_SYSTEM (UINT) 0x0080
+
+#define EAGLE_BRING_UP_TOP_NIBBLE (BYTE) 0xF0
+#define EAGLE_BRING_UP_BOTTOM_NIBBLE (BYTE) 0x0F
+
+#define EAGLE_BRING_UP_SUCCESS (BYTE) 0x40
+#define EAGLE_BRING_UP_FAILURE (BYTE) 0x30
+
+
+/****************************************************************************/
+/* */
+/* Values : EAGLE INITIALIZATION INTERRUPT REGISTER VALUES */
+/* */
+/* The code 0x9080 is output to the SIF interrupt register in order to */
+/* start the initialization process. The code produced at the SIFSTS part */
+/* of the SIF interrupt register at initialization time indicates the */
+/* success or failure of the initialization. On success, the INITIALIZE, */
+/* TEST and ERROR bits are all zero. On failure, the ERROR bit is set and */
+/* the error code is in the bottom nibble. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-46 4.6.2 Writing The Initialization Block */
+/* */
+
+#define EAGLE_INIT_START_CODE 0x9080
+
+#define EAGLE_INIT_TOP_NIBBLE (BYTE) 0xF0
+#define EAGLE_INIT_BOTTOM_NIBBLE (BYTE) 0x0F
+
+#define EAGLE_INIT_SUCCESS_MASK (BYTE) 0x70
+#define EAGLE_INIT_FAILURE_MASK (BYTE) 0x10
+
+
+/****************************************************************************/
+/* */
+/* Values : SCB and SSB test patterns */
+/* */
+/* As a result of initialization, certain test patterns should be left in */
+/* the SSB and SCB as pointed to by the TI initialization parameters. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-46 4.6.2 Writing The Initialization Block */
+/* */
+
+#define SSB_TEST_PATTERN_LENGTH 8
+#define SSB_TEST_PATTERN_DATA {0xFF,0xFF,0xD1,0xD7,0xC5,0xD9,0xC3,0xD4}
+
+#define SCB_TEST_PATTERN_LENGTH 6
+#define SCB_TEST_PATTERN_DATA {0x00,0x00,0xC1,0xE2,0xD4,0x8B}
+
+
+/****************************************************************************/
+/* */
+/* Value : EAGLE ARB FREE CODE - written to the EAGLE interrupt register to */
+/* indicate that the ARB is now free for use by the adapter. This */
+/* is of most use at start time when combined with the DELAY_RX */
+/* FEATURE FLAG. This code can be used to enable receives. */
+
+#define EAGLE_ARB_FREE_CODE 0x90FF
+
+
+/****************************************************************************/
+/* */
+/* Values : EAGLE OPENING ERRORS */
+/* */
+/* On opening the adapter, the success or failure is recorded in the */
+/* open_error field of the Fastmac status parameter block. The bottom byte */
+/* has the error value on failure. On success, the word is clear. The open */
+/* error is that which would be given by a MAC 0003 OPEN command. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-80 MAC 0003 OPEN command */
+/* */
+
+#define EAGLE_OPEN_ERROR_BOTTOM_BYTE 0x00FF
+
+#define EAGLE_OPEN_ERROR_SUCCESS 0x0000
+
+
+/****************************************************************************/
+/* */
+/* Values : BIA PROM FORMAT */
+/* */
+/* The BIA PROM is accessed in 2 pages. With CTRLn_SIFSEL = 0 (n=7 for */
+/* ATULA cards, n=0 for MC cards) or CTRL1_NRESET = 0, the bit CTRLn_PAGE */
+/* selects the different pages. With CTRLn_PAGE = 0, the id and board type */
+/* are available; with CTRLn_PAGE = 1, the node address is available. */
+/* */
+
+#define BIA_PROM_ID_BYTE 0
+#define BIA_PROM_ADAPTER_BYTE 1
+#define BIA_PROM_REVISION_BYTE 2
+#define BIA_PROM_FEATURES_BYTE 3
+#define BIA_PROM_HWF2 4
+#define BIA_PROM_HWF3 5
+
+#define BIA_PROM_NODE_ADDRESS 1
+
+/****************************************************************************/
+/* */
+/* Values : Bits defined in the HW flags */
+/* */
+/* HWF2 */
+#define C30 0x1
+
+/* HWF3 */
+#define RSPEED_DETECT 0x80
+
+
+/****************************************************************************/
+/* */
+/* Values : BIA PROM ADAPTER CARD TYPES */
+/* */
+/* The second byte in the first page of the BIA PROM contains an adapter */
+/* card type. */
+/* */
+
+#define BIA_PROM_TYPE_16_4_AT ((BYTE) 0x04)
+#define BIA_PROM_TYPE_16_4_MC ((BYTE) 0x08)
+#define BIA_PROM_TYPE_16_4_PC ((BYTE) 0x0B)
+#define BIA_PROM_TYPE_16_4_MAXY ((BYTE) 0x0C)
+#define BIA_PROM_TYPE_16_4_MC_32 ((BYTE) 0x0D)
+#define BIA_PROM_TYPE_16_4_AT_P ((BYTE) 0x0E)
+
+#define MAX_ADAPTER_CARD_AT_REV 6
+
+
+/****************************************************************************/
+/* */
+/* Values : BIA PROM FEATURES BYTE MASKS (and related values) */
+/* */
+/* The features byte in the BIA indicates certain hardware characteristics */
+/* of AT/P cards (and later cards). */
+/* Note that you can multiply the masked DRAM field by the DRAM_MULT value */
+/* to get the amount of RAM on the card (don't shift the field). */
+/* */
+
+#define BIA_PROM_FEATURE_SRA_MASK ((BYTE) 0x01)
+#define BIA_PROM_FEATURE_DRAM_MASK ((BYTE) 0x3E)
+#define BIA_PROM_FEATURE_CLKDIV_MASK ((BYTE) 0x40)
+
+#define DRAM_MULT 64
+
+
+/****************************************************************************/
+/* */
+/* Values : MADGE ADAPTER CARD NODE ADDRESSES */
+/* */
+/* The first 3 bytes of the permanent node address for Madge adapter cards */
+/* must have certain values. All Madge node addresses are of the form */
+/* 0000F6xxxxxx. */
+/* */
+
+#define MADGE_NODE_BYTE_0 ((BYTE) 0x00)
+#define MADGE_NODE_BYTE_1 ((BYTE) 0x00)
+#define MADGE_NODE_BYTE_2 ((BYTE) 0xF6)
+
+
+/* */
+/* */
+/************** End of FTK_CARD.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_defs.h b/private/ntos/ndis/madge/driver/head_def/ftk_defs.h
new file mode 100644
index 000000000..e5271ea61
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_defs.h
@@ -0,0 +1,52 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE FTK DEFINITIONS */
+/* =================== */
+/* */
+/* FTK_DEFS.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file includes all the definition header files used by the */
+/* FTK. The header files are included in an order such that all */
+/* dependenices between files are satisfied. */
+/* */
+/* IMPORTANT : All structures used within the FTK need to be packed in */
+/* order to work correctly. This means sizeof(STRUCTURE) will give the real */
+/* size in bytes, and if a structure contains sub-structures there will be */
+/* no spaces between the sub-structures. */
+/* */
+/****************************************************************************/
+
+#include "user.h"
+#include "ftk_user.h"
+#include "ftk_down.h"
+#include "ftk_init.h"
+#include "ftk_at.h"
+#include "ftk_sm16.h"
+#include "ftk_pci.h"
+#include "ftk_pcit.h"
+#include "ftk_pci2.h"
+#include "ftk_pcmc.h"
+#include "ftk_eisa.h"
+#include "ftk_mc.h"
+#include "ftk_pnp.h"
+#include "ftk_card.h"
+#include "ftk_fm.h"
+#include "ftk_err.h"
+#include "ftk_srb.h"
+#include "ftk_adap.h"
+#include "ftk_macr.h"
+#include "ftk_poke.h"
+
+/* */
+/* */
+/************** End of FTK_DEFS.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_down.h b/private/ntos/ndis/madge/driver/head_def/ftk_down.h
new file mode 100644
index 000000000..7ea825141
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_down.h
@@ -0,0 +1,128 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOWNLOAD DEFINITIONS */
+/* ======================== */
+/* */
+/* FTK_DOWN.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for the structure which is */
+/* used for downloading information on to an adapter that is being used by */
+/* the FTK. */
+/* */
+/* REFERENCE : The Madge Smart SRB Interface */
+/* - Downloading The Code */
+/* */
+/* IMPORTANT : All structures used within the FTK need to be packed in */
+/* order to work correctly. This means sizeof(STRUCTURE) will give the real */
+/* size in bytes, and if a structure contains sub-structures there will be */
+/* no spaces between the sub-structures. */
+/* */
+/****************************************************************************/
+
+#pragma pack(1)
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_DOWN.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_DOWN_H 221
+
+
+/****************************************************************************/
+/* */
+/* TYPEDEFs for all structures defined within this header file : */
+/* */
+
+typedef struct STRUCT_DOWNLOAD_RECORD DOWNLOAD_RECORD;
+
+/****************************************************************************/
+/* */
+/* Structure type : DOWNLOAD_RECORD */
+/* */
+/* This structure gives the format of the records that define how data is */
+/* downloaded into adapter DIO space. There are only 3 types of record that */
+/* are used on EAGLEs when downloading. These are MODULE - a special record */
+/* that starts a download image, DATA_32 - null terminated data with DIO */
+/* start address location, and FILL_32 - pattern with length to be filled */
+/* in starting at given DIO location. */
+/* */
+/* Each download record is an array of words in Intel byte ordering (ie. */
+/* least significant byte first). */
+/* */
+/* REFERENCE : The Madge Smart SRB Interface */
+/* - Downloading The Code */
+/* */
+
+struct STRUCT_DOWNLOAD_RECORD
+ {
+ WORD length; /* length of entire record */
+ WORD type; /* type of record */
+ union
+ {
+ struct /* MODULE */
+ {
+ WORD reserved_1;
+ WORD download_features;
+ WORD reserved_2;
+ WORD reserved_3;
+ WORD reserved_4;
+ BYTE name[1]; /* '\0' ending module name */
+ } module;
+
+ struct /* DATA_32 */
+ {
+ DWORD dio_addr; /* 32 bit EAGLE address */
+ WORD word_count; /* number of words */
+ WORD data[1]; /* null terminated data */
+ } data_32;
+
+ struct /* FILL_32 */
+ {
+ DWORD dio_addr; /* 32 bit EAGLE address */
+ WORD word_count; /* number of words */
+ WORD pattern; /* value to fill */
+ } fill_32;
+
+ } body;
+
+ };
+
+/****************************************************************************/
+/* */
+/* Values : DOWNLOAD_RECORD - WORD type */
+/* */
+/* These values are for the different types of download record. */
+/* */
+
+#define DOWNLOAD_RECORD_TYPE_DATA_32 0x04
+#define DOWNLOAD_RECORD_TYPE_FILL_32 0x05
+#define DOWNLOAD_RECORD_TYPE_MODULE 0x12
+
+
+/****************************************************************************/
+/* */
+/* Values : DOWNLOAD_RECORD - module. WORD download_features */
+/* */
+/* These specify some features of the module to be downloaded that may be */
+/* checked for. */
+/* */
+
+#define DOWNLOAD_FASTMAC_INTERFACE 0x0011
+#define DOWNLOAD_BMIC_SUPPORT 0x4000 /* required for EISA cards */
+
+#pragma pack()
+
+/* */
+/* */
+/************** End of FTK_DOWN.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_eisa.h b/private/ntos/ndis/madge/driver/head_def/ftk_eisa.h
new file mode 100644
index 000000000..8845363c5
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_eisa.h
@@ -0,0 +1,132 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (EISA CARDS) */
+/* =============================================== */
+/* */
+/* FTK_EISA.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge EISA */
+/* adapter cards. Each adapter card has a number of control and status */
+/* registers. ALL bits in ALL registers are defined by Madge Networks Ltd, */
+/* however only a restricted number are defined below as used within the */
+/* FTK. All other bits must NOT be changed and no support will be offered */
+/* for any application that does so or uses the defined bits in any way */
+/* different to the FTK. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_EISA.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_EISA_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : EISA REGISTER MAP */
+/* */
+/* Madge EISA cards have the following register map. All SIF registers are */
+/* always visible. */
+/* */
+/* NB. The IO registers are actually in two groups 0x0000-0x000F (the SIF */
+/* registers) and 0x0C80-0x00C9F (the control type registers). */
+/* */
+
+#define EISA_IO_RANGE 16
+
+#define EISA_FIRST_SIF_REGISTER 0x0000
+
+#define EISA_IO_RANGE2 32
+
+#define EISA_IO_RANGE2_BASE 0x0C80
+
+#define EISA_ID_REGISTER_0 0x0C80
+#define EISA_ID_REGISTER_1 0x0C82
+#define EISA_CONTROLX_REGISTER 0x0C84
+
+#define EISA_BMIC_REGISTER_3 0x0C90
+
+
+/****************************************************************************/
+/* */
+/* Values : MC POS_REGISTER_0 */
+/* */
+/* These are the required contents of the EISA ID registers for Madge 16/4 */
+/* EISA mk1 and mk2 cards. */
+/* */
+
+#define EISA_ID0_MDG_CODE 0x8734 /* 'MDG' encoded */
+
+#define EISA_ID1_MK1_MDG_CODE 0x0100 /* '0001' encoded */
+#define EISA_ID1_MK2_MDG_CODE 0x0200 /* '0002' encoded */
+#define EISA_ID1_BRIDGE_MDG_CODE 0x0300 /* '0003' encoded */
+#define EISA_ID1_MK3_MDG_CODE 0x0400 /* '0004' encoded */
+
+
+/****************************************************************************/
+/* */
+/* Values : EISA CONTROLX_REGISTER */
+/* */
+/* These are the bit definitions for the expansion board control register */
+/* on EISA cards. */
+/* */
+
+#define EISA_CTRLX_CDEN ((BYTE) 0x01) /* card enabled */
+
+
+/****************************************************************************/
+/* */
+/* Values : EISA BMIC_REGISTER_3 */
+/* */
+/* These are the bit definitions for BMIC register 3 on EISA cards. */
+/* */
+
+#define EISA_BMIC3_IRQSEL ((BYTE) 0x0F) /* interrupt number (4 bits) */
+#define EISA_BMIC3_EDGE ((BYTE) 0x10) /* edge\level triggered ints */
+#define EISA_BMIC3_SPD ((BYTE) 0x80) /* any speed selected */
+
+
+/****************************************************************************/
+/* */
+/* Values : EISA EXTENDED EAGLE SIF REGISTERS */
+/* */
+/* The EAGLE SIF registers are in two groups - the normal SIF registers */
+/* (those from the old TI chipset) and the extended SIF registers (those */
+/* particular to the EAGLE). For Madge EISA adapter cards, both normal and */
+/* extended SIF registers are always accessible. */
+/* */
+/* The definitions for the normal SIF registers are in FTK_CARD.H because */
+/* they appear in the same relative IO locations for all adapter cards. The */
+/* extended SIF registers are here because they appear at different */
+/* relative IO locations for different types of adapter cards. */
+/* */
+
+#define EISA_EAGLE_SIFACL 8 /* adapter control */
+#define EISA_EAGLE_SIFADR_2 10 /* copy of SIFADR */
+#define EISA_EAGLE_SIFADX 12 /* DIO address (high) */
+#define EISA_EAGLE_DMALEN 14 /* DMA length */
+
+
+/****************************************************************************/
+/* */
+/* Values : VRAM enable on EIDA Mk3 */
+/* */
+
+#define DIO_LOCATION_EISA_VRAM_ENABLE ((DWORD) 0xC0000L)
+#define EISA_VRAM_ENABLE_WORD ((WORD) 0xFFFF)
+
+/* */
+/* */
+/************** End of FTK_EISA.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_err.h b/private/ntos/ndis/madge/driver/head_def/ftk_err.h
new file mode 100644
index 000000000..595460bb5
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_err.h
@@ -0,0 +1,389 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE ERROR DEFINITIONS */
+/* ===================== */
+/* */
+/* FTK_ERR.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the structures associated with error handling */
+/* and all the possible error codes (types and values) produced by the FTK. */
+/* */
+/* A string of text describing each of the possible error codes (type and */
+/* value) can be found in the error tables in FTK_TAB.H. */
+/* */
+/* IMPORTANT : All structures used within the FTK need to be packed in */
+/* order to work correctly. This means sizeof(STRUCTURE) will give the real */
+/* size in bytes, and if a structure contains sub-structures there will be */
+/* no spaces between the sub-structures. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_ERR.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_ERR_H 221
+
+
+/****************************************************************************/
+/* */
+/* TYPEDEFs for all structures defined within this header file : */
+/* */
+
+typedef struct STRUCT_ERROR_RECORD ERROR_RECORD;
+typedef struct STRUCT_ERROR_MESSAGE ERROR_MESSAGE;
+typedef struct STRUCT_ERROR_MESSAGE_RECORD ERROR_MESSAGE_RECORD;
+
+
+/****************************************************************************/
+/* */
+/* Structure type : ERROR_MESSAGE_RECORD */
+/* */
+/* The error message tables (see FTK_TAB.H) are made up of elements of this */
+/* structure. Each error message string has associated with it an error */
+/* value of the type of error that the table is for. */
+/* */
+
+struct STRUCT_ERROR_MESSAGE_RECORD
+ {
+ BYTE value;
+ char * err_msg_string;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : ERROR_MESSAGE */
+/* */
+/* Associated with an adapter structure is an error message for the last */
+/* error to occur on the adapter. It is filled in by a call to */
+/* driver_explain_error and a pointer to it is returned to the user. */
+/* */
+
+#define MAX_ERROR_MESSAGE_LENGTH 600
+
+struct STRUCT_ERROR_MESSAGE
+ {
+ char string[MAX_ERROR_MESSAGE_LENGTH];
+ };
+
+/****************************************************************************/
+/* */
+/* Structure type : ERROR_RECORD */
+/* */
+/* This structure is used for recording error information. There is an */
+/* element of this structure, associated with every adapter, that is used */
+/* to record the current error status of the adapter. */
+/* */
+
+struct STRUCT_ERROR_RECORD
+ {
+ BYTE type;
+ BYTE value;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - BYTE type */
+/* */
+/* The following lists the type of errors that can occur. Some of these are */
+/* fatal in that an adapter for which they occur can not subsequently be */
+/* used. The value 0 (zero) is used to indicate no error has yet occured. */
+/* */
+
+#define ERROR_TYPE_NONE (BYTE) 0x00 /* no error */
+#define ERROR_TYPE_SRB (BYTE) 0x01 /* non-fatal error */
+#define ERROR_TYPE_OPEN (BYTE) 0x02 /* non-fatal error */
+#define ERROR_TYPE_DATA_XFER (BYTE) 0x03 /* non-fatal error */
+#define ERROR_TYPE_DRIVER (BYTE) 0x04 /* fatal error */
+#define ERROR_TYPE_HWI (BYTE) 0x05 /* fatal error */
+#define ERROR_TYPE_BRING_UP (BYTE) 0x06 /* fatal error */
+#define ERROR_TYPE_INIT (BYTE) 0x07 /* fatal error */
+#define ERROR_TYPE_AUTO_OPEN (BYTE) 0x08 /* fatal error */
+#define ERROR_TYPE_ADAPTER (BYTE) 0x09 /* fatal error */
+#define ERROR_TYPE_CS (BYTE) 0x0A /* fatal error */
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_SRB . BYTE value */
+/* SRB_HEADER - BYTE return_code */
+/* */
+/* The non-fatal SRB error type uses for error values the return codes in */
+/* the SRB header. For the SRBs that are supported by the FTK there are */
+/* only a limited number of possible error values that can occur. Note */
+/* however, that a failing open adapter SRB call may cause OPEN error type */
+/* errors and not just SRB error type errors (see ERROR_TYPE_OPEN below). */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface */
+/* */
+
+#define SRB_E_00_SUCCESS (BYTE) 0x00
+#define SRB_E_03_ADAPTER_OPEN (BYTE) 0x03
+#define SRB_E_04_ADAPTER_CLOSED (BYTE) 0x04
+#define SRB_E_06_INVALID_OPTIONS (BYTE) 0x06
+#define SRB_E_07_CMD_CANCELLED_FAIL (BYTE) 0x07
+#define SRB_E_32_INVALID_NODE_ADDRESS (BYTE) 0x32
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_OPEN . BYTE value */
+/* */
+/* Non-fatal open errors occur when an open adapter SRB returns with code */
+/* SRB_E_07_CMD_CANCELLED_FAILED. In this case the error type is changed to */
+/* ERROR_TYPE_OPEN and the error value is changed to show that an open */
+/* error has occured. The actual open error details are determined when the */
+/* user calls driver_explain_error (see TMS Open Error Codes below). */
+/* */
+
+#define OPEN_E_01_OPEN_ERROR (BYTE) 0x01
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_DATA_XFER . BYTE value */
+/* */
+/* There is only one possible non-fatal data transfer error. This occurs on */
+/* an attempted transmit when the Fastmac transmit buffer is full. */
+/* */
+
+#define DATA_XFER_E_01_BUFFER_FULL (BYTE) 0x01
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_DRIVER . BYTE value */
+/* */
+/* The DRIVER part of the FTK can generate the following fatal error */
+/* values. These can, for example, be caused by sys_alloc routines failing */
+/* or passing an illegal adapter handle to a driver routine. See FTK_TAB.H */
+/* for more details. */
+/* */
+
+#define DRIVER_E_01_INVALID_HANDLE (BYTE) 0x01
+#define DRIVER_E_02_NO_ADAP_STRUCT (BYTE) 0x02
+#define DRIVER_E_03_FAIL_ALLOC_STATUS (BYTE) 0x03
+#define DRIVER_E_04_FAIL_ALLOC_INIT (BYTE) 0x04
+#define DRIVER_E_05_FAIL_ALLOC_RX_BUF (BYTE) 0x05
+#define DRIVER_E_06_FAIL_ALLOC_TX_BUF (BYTE) 0x06
+#define DRIVER_E_07_NOT_PREPARED (BYTE) 0x07
+#define DRIVER_E_08_NOT_RUNNING (BYTE) 0x08
+#define DRIVER_E_09_SRB_NOT_FREE (BYTE) 0x09
+#define DRIVER_E_0A_RX_BUF_BAD_SIZE (BYTE) 0x0A
+#define DRIVER_E_0B_RX_BUF_NOT_DWORD (BYTE) 0x0B
+#define DRIVER_E_0C_TX_BUF_BAD_SIZE (BYTE) 0x0C
+#define DRIVER_E_0D_TX_BUF_NOT_DWORD (BYTE) 0x0D
+#define DRIVER_E_0E_BAD_RX_METHOD (BYTE) 0x0E
+#define DRIVER_E_0F_WRONG_RX_METHOD (BYTE) 0x0F
+
+#define DRIVER_E_10_BAD_RX_SLOT_NUMBER (BYTE) 0x10
+#define DRIVER_E_11_BAD_TX_SLOT_NUMBER (BYTE) 0x11
+#define DRIVER_E_12_FAIL_ALLOC_DMA_BUF (BYTE) 0x12
+#define DRIVER_E_13_BAD_FRAME_SIZE (BYTE) 0x13
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_HWI . BYTE value */
+/* */
+/* The HWI part of the FTK can generate the following fatal error values. */
+/* Most of these are caused by the user supplying illegal values to */
+/* driver_start_adapter. See FTK_TAB.H for more details. */
+/* */
+
+#define HWI_E_01_BAD_CARD_BUS_TYPE (BYTE) 0x01
+#define HWI_E_02_BAD_IO_LOCATION (BYTE) 0x02
+#define HWI_E_03_BAD_INTERRUPT_NUMBER (BYTE) 0x03
+#define HWI_E_04_BAD_DMA_CHANNEL (BYTE) 0x04
+#define HWI_E_05_ADAPTER_NOT_FOUND (BYTE) 0x05
+#define HWI_E_06_CANNOT_USE_DMA (BYTE) 0x06
+#define HWI_E_07_FAILED_TEST_DMA (BYTE) 0x07
+#define HWI_E_08_BAD_DOWNLOAD (BYTE) 0x08
+#define HWI_E_09_BAD_DOWNLOAD_IMAGE (BYTE) 0x09
+#define HWI_E_0A_NO_DOWNLOAD_IMAGE (BYTE) 0x0A
+#define HWI_E_0B_FAIL_IRQ_ENABLE (BYTE) 0x0B
+#define HWI_E_0C_FAIL_DMA_ENABLE (BYTE) 0x0C
+#define HWI_E_0D_CARD_NOT_ENABLED (BYTE) 0x0D
+#define HWI_E_0E_NO_SPEED_SELECTED (BYTE) 0x0E
+#define HWI_E_0F_BAD_FASTMAC_INIT (BYTE) 0x0F
+
+#define HWI_E_10_BAD_TX_RX_BUFF_SIZE (BYTE) 0x10
+#define HWI_E_11_TOO_MANY_TX_RX_BUFFS (BYTE) 0x11
+#define HWI_E_12_BAD_SCB_ALLOC (BYTE) 0x12
+#define HWI_E_13_BAD_SSB_ALLOC (BYTE) 0x13
+#define HWI_E_14_BAD_PCI_MACHINE (BYTE) 0x14
+#define HWI_E_15_BAD_PCI_MEMORY (BYTE) 0x15
+#define HWI_E_16_PCI_3BYTE_PROBLEM (BYTE) 0x16
+#define HWI_E_17_BAD_TRANSFER_MODE (BYTE) 0x17
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_BRING_UP . BYTE value */
+/* */
+/* During an attempt to perform bring-up of an adapter card, one of a */
+/* number of fatal error values may be produced. Bits 12-15 of the EAGLE */
+/* SIFINT register contain the error value. These codes are used by the FTK */
+/* to distinguish different bring-up errors. An extra error value is used */
+/* for the case when no bring up code is produced within a timeout period */
+/* (3 seconds). */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-40 4.5 Bring-Up Diagnostics - BUD */
+/* */
+
+#define BRING_UP_E_00_INITIAL_TEST (BYTE) 0x00
+#define BRING_UP_E_01_SOFTWARE_CHECKSUM (BYTE) 0x01
+#define BRING_UP_E_02_ADAPTER_RAM (BYTE) 0x02
+#define BRING_UP_E_03_INSTRUCTION_TEST (BYTE) 0x03
+#define BRING_UP_E_04_INTERRUPT_TEST (BYTE) 0x04
+#define BRING_UP_E_05_FRONT_END (BYTE) 0x05
+#define BRING_UP_E_06_SIF_REGISTERS (BYTE) 0x06
+
+#define BRING_UP_E_10_TIME_OUT (BYTE) 0x10
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_INIT . BYTE value */
+/* */
+/* During an attempt to perform adapter initialization, one of a number of */
+/* fatal error values may be produced. Bits 12-15 of the EAGLE SIFINT */
+/* regsiter contain the error value. These codes are used by the FTK to */
+/* distinguish different initialization errors. An extra error value is */
+/* used for the case when no initialization code is produced within a */
+/* timeout period (11 seconds). */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-47 4.6 Adapter Initialization */
+/* */
+
+#define INIT_E_01_INIT_BLOCK (BYTE) 0x01
+#define INIT_E_02_INIT_OPTIONS (BYTE) 0x02
+#define INIT_E_03_RX_BURST_SIZE (BYTE) 0x03
+#define INIT_E_04_TX_BURST_SIZE (BYTE) 0x04
+#define INIT_E_05_DMA_THRESHOLD (BYTE) 0x05
+#define INIT_E_06_ODD_SCB_ADDRESS (BYTE) 0x06
+#define INIT_E_07_ODD_SSB_ADDRESS (BYTE) 0x07
+#define INIT_E_08_DIO_PARITY (BYTE) 0x08
+#define INIT_E_09_DMA_TIMEOUT (BYTE) 0x09
+#define INIT_E_0A_DMA_PARITY (BYTE) 0x0A
+#define INIT_E_0B_DMA_BUS (BYTE) 0x0B
+#define INIT_E_0C_DMA_DATA (BYTE) 0x0C
+#define INIT_E_0D_ADAPTER_CHECK (BYTE) 0x0D
+#define INIT_E_0E_NOT_ENOUGH_MEMORY (BYTE) 0x0E
+
+#define INIT_E_10_TIME_OUT (BYTE) 0x10
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_AUTO_OPEN . BYTE value */
+/* */
+/* Auto-open errors are fatal - there is no chance to try to open the */
+/* adapter again. The error value is usually set to show that an open */
+/* adapter error has occured. The details of the open error are determined */
+/* when the user calls driver_explain_error (see TMS Open Error Codes */
+/* below). There is also an extra error value which is used for the case */
+/* when no open adapter error code is produced within a timeout period (40 */
+/* seconds). */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-79 MAC 0003 OPEN command */
+/* */
+
+#define AUTO_OPEN_E_01_OPEN_ERROR (BYTE) 0x01
+#define AUTO_OPEN_E_80_TIME_OUT (BYTE) 0x80
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_ADAPTER . BYTE value */
+/* */
+/* An adapter check interrupt causes an adapter check fatal error. */
+/* Different types of adapter checks are not distinguished by the FTK. */
+/* */
+
+#define ADAPTER_E_01_ADAPTER_CHECK (BYTE) 0x01
+
+
+/****************************************************************************/
+/* */
+/* Values : ERROR_RECORD - ERROR_TYPE_CS . BYTE value */
+/* */
+/* These are possible errors return from calling PCMCIA Card Services. */
+/* These errors can only occur on 16/4 PCMCIA ringnode. Other adapters do */
+/* not make calls to PCMCIA Card Services. To start up a 16/4 PCMCIA */
+/* Ringnode, the driver first registers with PCMCIA Card Services as a */
+/* client, gropes for the ringnode using Card Services calls, requests I/O */
+/* and interrupt resources from Card Services. If any of these operations */
+/* fails, the driver will return following errors. Note that these are */
+/* fatal errors. */
+/* */
+
+#define CS_E_01_NO_CARD_SERVICES (BYTE) 0x01
+#define CS_E_02_REGISTER_CLIENT_FAILED (BYTE) 0x02
+#define CS_E_03_REGISTRATION_TIMEOUT (BYTE) 0x03
+#define CS_E_04_NO_MADGE_ADAPTER_FOUND (BYTE) 0x04
+#define CS_E_05_ADAPTER_NOT_FOUND (BYTE) 0x05
+#define CS_E_06_SPECIFIED_SOCKET_IN_USE (BYTE) 0x06
+#define CS_E_07_IO_REQUEST_FAILED (BYTE) 0x07
+#define CS_E_08_BAD_IRQ_CHANNEL (BYTE) 0x08
+#define CS_E_09_IRQ_REQUEST_FAILED (BYTE) 0x09
+#define CS_E_0A_REQUEST_CONFIG_FAILED (BYTE) 0x0A
+
+
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* Values : TMS Open Error Codes */
+/* */
+/* When an E_01_OPEN_ERROR (either AUTO_OPEN or OPEN) occurs, more details */
+/* of the open adapter error are available by looking at the open_error */
+/* field in the Fastmac status block. This open error is the same as that */
+/* generated by a TI MAC 0003 OPEN command. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-79 MAC 0003 OPEN command */
+/* */
+
+#define TMS_OPEN_FAIL_E_40_OPEN_ADDR 0x4000
+#define TMS_OPEN_FAIL_E_02_FAIL_OPEN 0x0200
+#define TMS_OPEN_FAIL_E_01_OPEN_OPTS 0x0100
+
+#define TMS_OPEN_PHASE_E_01_LOBE_TEST 0x0010
+#define TMS_OPEN_PHASE_E_02_INSERTION 0x0020
+#define TMS_OPEN_PHASE_E_03_ADDR_VER 0x0030
+#define TMS_OPEN_PHASE_E_04_RING_POLL 0x0040
+#define TMS_OPEN_PHASE_E_05_REQ_INIT 0x0050
+
+#define TMS_OPEN_ERR_E_01_FUNC_FAIL 0x0001
+#define TMS_OPEN_ERR_E_02_SIGNAL_LOSS 0x0002
+#define TMS_OPEN_ERR_E_05_TIMEOUT 0x0005
+#define TMS_OPEN_ERR_E_06_RING_FAIL 0x0006
+#define TMS_OPEN_ERR_E_07_BEACONING 0x0007
+#define TMS_OPEN_ERR_E_08_DUPL_ADDR 0x0008
+#define TMS_OPEN_ERR_E_09_REQ_INIT 0x0009
+#define TMS_OPEN_ERR_E_0A_REMOVE 0x000A
+
+
+/* */
+/* */
+/************** End of FTK_ERR.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_fm.h b/private/ntos/ndis/madge/driver/head_def/ftk_fm.h
new file mode 100644
index 000000000..0d99596df
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_fm.h
@@ -0,0 +1,351 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE FASTMAC DEFINITIONS */
+/* ======================= */
+/* */
+/* FTK_FM.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the structures, constants etc., that are */
+/* relevant to Fastmac and its use by the FTK and are not included */
+/* elsewhere. This includes the Fastmac status block structure and the */
+/* Fastmac use of the EAGLE SIFINT register. */
+/* */
+/* IMPORTANT : All structures used within the FTK need to be packed in */
+/* order to work correctly. This means sizeof(STRUCTURE) will give the real */
+/* size in bytes, and if a structure contains sub-structures there will be */
+/* no spaces between the sub-structures. */
+/* */
+/****************************************************************************/
+
+#pragma pack(1)
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_FM.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_FM_H 221
+
+
+/****************************************************************************/
+/* */
+/* TYPEDEFs for all structures defined within this header file : */
+/* */
+
+typedef struct STRUCT_FASTMAC_STATUS_BLOCK FASTMAC_STATUS_BLOCK;
+#ifdef FMPLUS
+typedef struct STRUCT_RX_SLOT RX_SLOT;
+typedef struct STRUCT_TX_SLOT TX_SLOT;
+#endif
+
+/****************************************************************************/
+/* */
+/* Structure type : FASTMAC_STATUS_BLOCK */
+/* */
+/* Fastmac maintains a status block that includes the pointers to the */
+/* receive and transmit buffers, as well as the ring status and a boolean */
+/* flag to say if the adapter is open. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - Status Block */
+/* */
+
+struct STRUCT_FASTMAC_STATUS_BLOCK
+ {
+ WORD reserved_1;
+ WORD signature;
+ WBOOLEAN adapter_open; /* TRUE when open */
+ WORD open_error; /* open error code */
+ WORD tx_adap_ptr; /* transmit buffer pointers */
+ WORD tx_host_ptr;
+ WORD tx_wrap_ptr;
+ WORD rx_adap_ptr; /* receive buffer pointers */
+ WORD rx_wrap_ptr;
+ WORD rx_host_ptr;
+ NODE_ADDRESS permanent_address; /* BIA PROM node address */
+ NODE_ADDRESS open_address; /* opening node address */
+ WORD tx_dma_count;
+ WORD timestamp_ptr;
+ WORD rx_internal_buffer_size;
+ WORD rx_total_buffers_avail;
+ WORD rx_buffers_in_use;
+ WORD rx_frames_lost;
+ WORD watchdog_timer;
+ WORD ring_status; /* current ring status */
+ WORD tx_discarded;
+#ifdef FMPLUS
+ WORD rx_slot_start; /* where to find rx slots */
+ WORD tx_slot_start; /* where to find tx slots */
+#endif
+ WORD reserved_2[1];
+ WORD rxdesc_host_ptr;
+ DWORD rxdesc_queue[1];
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : Fastmac buffer sizes */
+/* */
+/* The Fastmac receive and transmit buffers have minimum and maximum */
+/* allowable sizes. The minimum size allows the buffer to contain a single */
+/* 1K frame. */
+/* */
+
+#define FASTMAC_MAXIMUM_BUFFER_SIZE 0xFF00
+#define FASTMAC_MINIMUM_BUFFER_SIZE 0x0404
+
+
+/****************************************************************************/
+/* */
+/* Values : FASTMAC SIF INTERRUPT (SIFCMD-SIFSTS) REGISTER BITS */
+/* */
+/* When Fastmac generates an interrupt (via the SIF interrupt register), */
+/* the value in the register will indicate the reason for the interrupt. */
+/* Also, when the user interrupts Fastmac (again via the SIF interrupt */
+/* register), the value in the register indicates the reason. */
+/* */
+/* REFERENCE : The Madge Smart SRB Interface */
+/* - The Interrupt Register */
+/* */
+
+#define DRIVER_SIFINT_IRQ_FASTMAC 0x8000 /* interrupt Fastmac */
+
+#define DRIVER_SIFINT_FASTMAC_IRQ_MASK 0x00FF
+
+#define DRIVER_SIFINT_SSB_FREE 0x4000
+#define DRIVER_SIFINT_SRB_COMMAND 0x2000
+#define DRIVER_SIFINT_ARB_FREE 0x1000
+
+#define DRIVER_SIFINT_ACK_SSB_RESPONSE 0x0400
+#define DRIVER_SIFINT_ACK_SRB_FREE 0x0200
+#define DRIVER_SIFINT_ACK_ARB_COMMAND 0x0100
+
+
+#define FASTMAC_SIFINT_IRQ_DRIVER 0x0080 /* interrupt driver */
+
+#define FASTMAC_SIFINT_ADAPTER_CHECK 0x0008
+#define FASTMAC_SIFINT_SSB_RESPONSE 0x0004
+#define FASTMAC_SIFINT_SRB_FREE 0x0002
+#define FASTMAC_SIFINT_ARB_COMMAND 0x0001
+
+#define FASTMAC_SIFINT_RECEIVE 0x0000
+
+
+/****************************************************************************/
+/* */
+/* Values : FASTMAC DIO LOCATIONS */
+/* */
+/* There are certain fixed locations in DIO space containing pointers that */
+/* are accessed by the driver to determine DIO locations where the driver */
+/* must read or store Fastmac information. These pointers identify the */
+/* location of such things as the SRB and status block (STB). The pointers */
+/* are at DIO locations 0x00011000 - 0x00011008. The values defined below */
+/* give the location of the pointers within the EAGLE DATA page 0x00010000. */
+/* */
+/* REFERENCE : The Madge Smart SRB Interface */
+/* - Shared RAM Format */
+/* */
+
+#define DIO_LOCATION_SSB_POINTER 0x1000
+#define DIO_LOCATION_SRB_POINTER 0x1002
+#define DIO_LOCATION_ARB_POINTER 0x1004
+#define DIO_LOCATION_STB_POINTER 0x1006 /* status block */
+#define DIO_LOCATION_IPB_POINTER 0x1008 /* init block */
+#define DIO_LOCATION_DMA_CONTROL 0x100A
+#define DIO_LOCATION_DMA_POINTER 0x100C
+
+
+/****************************************************************************/
+/* */
+/* Values : Fastmac product id string */
+/* */
+/* The product id string for Fastmac that is used by certain management MAC */
+/* frames. If the Fastmac auto-open feature is used then the product id is */
+/* always "THE MADGE FASTMAC". If an OPEN_ADAPTER SRB then the FTK product */
+/* id is "FTK MADGE FASTMAC". */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface : Open Adapter SRB */
+/* */
+
+#define SIZEOF_PRODUCT_ID 18
+#ifdef FMPLUS
+#define FASTMAC_PRODUCT_ID "FTK MADGE FM PLUS"
+#else
+#define FASTMAC_PRODUCT_ID "FTK MADGE FASTMAC"
+#endif
+
+/****************************************************************************/
+/* */
+/* Global variable : ftk_product_inst_id */
+/* */
+/* Value of the product ID strings set when an open adapter SRB */
+/* is generated. This is set to FASTMAC_PRODUCT_ID in DRV_SRB.C. */
+/* */
+
+extern char ftk_product_inst_id[SIZEOF_PRODUCT_ID];
+
+/****************************************************************************/
+/* */
+/* Values : Fastmac buffer format */
+/* */
+/* The format in which frames are kept in the Fastmac buffers includes a */
+/* header to the frame containing the length of the entire header and */
+/* frame, and a timestamp. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - The Fastmac Algorithm */
+/* */
+
+
+#define FASTMAC_BUFFER_HEADER_SIZE 4
+
+#define FASTMAC_HEADER_LENGTH_OFFSET 0
+#define FASTMAC_HEADER_STAMP_OFFSET 2
+
+
+#ifdef FMPLUS
+/****************************************************************************/
+/* */
+/* Structure type : RX_SLOT */
+/* */
+/* Fastmac Plus maintains a slot structure on the card for each receive */
+/* buffer on the host. These include the address of the buffer, the length */
+/* of any frame in it, and the receive status of any frame there. When a */
+/* frame is received, Fastmac Plus updates the length and status fields. */
+/* */
+/* REFERENCE : The Madge Fastmac Plus Programming Specification */
+/* - Receive Details: Slot Structure */
+/* */
+
+struct STRUCT_RX_SLOT
+ {
+ WORD buffer_len;
+ WORD reserved;
+ WORD buffer_hiw;
+ WORD buffer_low;
+ WORD rx_status;
+ WORD next_slot;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : TX_SLOT */
+/* */
+/* Fastmac Plus maintains a number of slot structures on the card, to allow */
+/* transmit pipelining. Each of these structures includes two fields for */
+/* host buffers and lengths - one is for a small buffer, less than the size */
+/* of a buffer on the adapter card, and the other is for a large buffer, up */
+/* to the maximum frame size. There is also a status field so that the host */
+/* transmit code can monitor the progress of the transmit. */
+/* */
+/* REFERENCE : The Madge Fastmac Plus Programming Specification */
+/* - Transmit Details: Slot Structure */
+/* */
+
+struct STRUCT_TX_SLOT
+ {
+ WORD tx_status;
+ WORD small_buffer_len;
+ WORD large_buffer_len;
+ WORD reserved[2];
+ WORD small_buffer_hiw;
+ WORD small_buffer_low;
+ WORD next_slot;
+ WORD large_buffer_hiw;
+ WORD large_buffer_low;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : Fastmac Plus min/max slot numbers */
+/* */
+/* Fastmac Plus places certain restrictions on the numbers of transmit and */
+/* receive slots that can be allocated. These constants specify the values. */
+/* */
+/* REFERENCE : The Madge Fastmac Plus Programming Specification */
+/* - Initialisation : TMS Load Parms */
+/* */
+
+#define FMPLUS_MAX_RX_SLOTS 32
+#define FMPLUS_MIN_RX_SLOTS 2
+
+#define FMPLUS_MAX_TX_SLOTS 32
+#define FMPLUS_MIN_TX_SLOTS 2
+
+
+/****************************************************************************/
+/* */
+/* Values : Fastmac Plus Receive Status Mask */
+/* */
+/* By bitwise AND-ing the mask here with the receive status read from the */
+/* receive slot, code can determine whether the received frame is good or */
+/* not. If the result is zero, the frame is good, otherwise it is a junk */
+/* frame. */
+/* */
+/* REFERENCE : The Madge Fastmac Plus Programming Specification */
+/* - Receive Status Processing */
+/* */
+
+#define GOOD_RX_FRAME_MASK ((WORD) 0x5E00)
+
+
+/****************************************************************************/
+/* */
+/* Values : Fastmac Plus Transmit Status Mask And Values */
+/* */
+/* By bitwise AND-ing the good frame mask with the transmit status read */
+/* from the receive slot, code can determine whether the frame was */
+/* transmitted properly or not. If more detail is required, the receive */
+/* status mask can be used to check various conditions in the transmitted */
+/* frame when it returned to the adapter. */
+/* */
+/* REFERENCE : The Madge Fastmac Plus Programming Specification */
+/* - Transmit Status Processing */
+/* */
+
+#define GOOD_TX_FRAME_MASK ((WORD) 0x5F00)
+#define GOOD_TX_FRAME_VALUE ((WORD) 0x0100)
+
+#define TX_RECEIVE_STATUS_MASK ((WORD) 0x0700)
+#define TX_RECEIVE_LOST_FRAME ((WORD) 0x0300)
+#define TX_RECEIVE_CORRUPT_TOKEN ((WORD) 0x0500)
+#define TX_RECEIVE_IMPLICIT_ABORT ((WORD) 0x0700)
+
+
+/****************************************************************************/
+/* */
+/* Values : Fastmac Plus Zero Length Small Buffer value */
+/* */
+/* When transmitting a frame that exists only in a large buffer, a special */
+/* non-zero value must be written to the small buffer length field of the */
+/* receive slot (this is because Fastmac Plus uses zero there to indicate */
+/* that a transmit has completed, and waits for it to change before trying */
+/* to transmit any more from that slot). This special value is defined here.*/
+/* */
+/* REFERENCE : The Madge Fastmac Plus Programming Specification */
+/* - Transmit Details */
+/* */
+
+#define FMPLUS_SBUFF_ZERO_LENGTH ((WORD)(0x8000))
+
+#endif
+
+
+#pragma pack()
+
+/* */
+/* */
+/************** End of FTK_FM.H file ****************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_init.h b/private/ntos/ndis/madge/driver/head_def/ftk_init.h
new file mode 100644
index 000000000..491df1e0a
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_init.h
@@ -0,0 +1,330 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE INITIALIZATION BLOCK DEFINITIONS */
+/* ==================================== */
+/* */
+/* FTK_INIT.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for the structures that go to */
+/* make the initialization block that is needed in order to initialize an */
+/* adapter card that is in use by the FTK. */
+/* */
+/* IMPORTANT : All structures used within the FTK need to be packed in */
+/* order to work correctly. This means sizeof(STRUCTURE) will give the real */
+/* size in bytes, and if a structure contains sub-structures there will be */
+/* no spaces between the sub-structures. */
+/* */
+/****************************************************************************/
+
+#pragma pack(1)
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_INIT.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_INIT_H 221
+
+
+/****************************************************************************/
+/* */
+/* TYPEDEFs for all structures defined within this header file : */
+/* */
+
+typedef struct STRUCT_INITIALIZATION_BLOCK INITIALIZATION_BLOCK;
+typedef struct STRUCT_TI_INIT_PARMS TI_INIT_PARMS;
+typedef struct STRUCT_MADGE_INIT_PARMS_HEADER MADGE_INIT_PARMS_HEADER;
+typedef struct STRUCT_SMART_INIT_PARMS SMART_INIT_PARMS;
+typedef struct STRUCT_FASTMAC_INIT_PARMS FASTMAC_INIT_PARMS;
+
+/****************************************************************************/
+/* */
+/* Structure type : TI_INIT_PARMS */
+/* */
+/* The TI initialization parameters are exactly those defined by TI for */
+/* initializing an adapter based on the EAGLE chipset except for a special */
+/* byte of 16/4 MC 32 configuration information. This byte overrides a TI */
+/* initialization block field not used by Madge adapter cards. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-42 4.6 Adapter Initialization */
+/* */
+
+struct STRUCT_TI_INIT_PARMS
+ {
+ WORD init_options;
+ WORD madge_mc32_config; /* special MC 32 data */
+ BYTE reserved[4]; /* ignored by Madge cards */
+ WORD rx_burst;
+ WORD tx_burst;
+ BYTE parity_retry;
+ BYTE dma_retry;
+ DWORD scb_addr; /* 32 bit phys host addr */
+ DWORD ssb_addr; /* 32 bit phys host addr */
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : TI_INIT_PARMS - WORD init_options */
+/* */
+/* The init_options are set up for burst mode DMA. */
+/* */
+
+#define TI_INIT_OPTIONS_BURST_DMA 0x9F00
+
+
+/****************************************************************************/
+/* */
+/* Values : TI_INIT_PARMS - WORD madge_mc32_config */
+/* */
+/* This value is used to configure MC and ISA CLIENT cards. */
+/* */
+
+#define MC_AND_ISACP_USE_PIO 0x0040
+
+
+/****************************************************************************/
+/* */
+/* Values : TI_INIT_PARMS - BYTE parity_retry, BYTE dma_retry */
+/* */
+/* A default value is used by the FTK for the parity and dma retry counts. */
+/* */
+
+#define TI_INIT_RETRY_DEFAULT 5
+
+
+/****************************************************************************/
+/* */
+/* Structure type : MADGE_INIT_PARMS_HEADER */
+/* */
+/* This is the common header to all Madge smart software initialization */
+/* parameter blocks - that is, in this case, the header for the general */
+/* smart software MAC level parameters and the Fastmac specific parameters. */
+/* */
+/* REFERENCE : The Madge Smart SRB Interface */
+/* - Bring-Up and Initialization */
+/* */
+
+
+struct STRUCT_MADGE_INIT_PARMS_HEADER
+ {
+ WORD length; /* byte length of parms */
+ WORD signature; /* parms specific */
+ WORD reserved; /* must be 0 */
+ WORD version; /* parms specific */
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : SMART_INIT_PARMS */
+/* */
+/* This structure contains general MAC level parameters for when */
+/* downloading any Madge smart software. */
+/* */
+/* REFERENCE : The Madge Smart SRB Interface */
+/* - Bring-Up and Initialization */
+/* */
+
+struct STRUCT_SMART_INIT_PARMS
+ {
+
+ MADGE_INIT_PARMS_HEADER header;
+
+ WORD reserved_1; /* must be 0 */
+ NODE_ADDRESS permanent_address; /* BIA PROM node address */
+ WORD rx_tx_buffer_size; /* 0 => default 1K-8 bytes */
+ DWORD reserved_2; /* must be 0 */
+ WORD dma_buffer_size; /* 0 => no limit */
+ WORD max_buffer_ram; /* 0 => default 2MB */
+ WORD min_buffer_ram; /* 0 => default 10K */
+ WORD sif_burst_size; /* 0 => no limit */
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : SMART_INIT_PARMS - header. WORD signature, WORD version */
+/* */
+/* The values for the header of the general smart software MAC level */
+/* paramters strcture. */
+/* */
+
+#define SMART_INIT_HEADER_SIGNATURE 0x0007
+#define SMART_INIT_HEADER_VERSION 0x0101
+#ifdef FMPLUS
+#define SMART_INIT_MIN_RAM_DEFAULT 0x0002
+#endif
+
+/****************************************************************************/
+/* */
+/* Structure type : SMART_FASTMAC_INIT_PARMS */
+/* */
+/* The Fastmac initialization parameters as specified in the Fastmac */
+/* documentation. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - Initialization */
+/* */
+
+
+struct STRUCT_FASTMAC_INIT_PARMS
+ {
+
+ MADGE_INIT_PARMS_HEADER header;
+
+ WORD feature_flags;
+ WORD int_flags;
+
+ WORD open_options; /* only for auto_open */
+ NODE_ADDRESS open_address; /* only for auto_open */
+ DWORD group_address; /* only for auto_open */
+ DWORD functional_address; /* only for auto_open */
+
+ DWORD rx_buf_physaddr; /* set to zero for FMPlus */
+ WORD rx_buf_size; /* (see rx_bufs/rx_slots) */
+ WORD rx_buf_space;
+
+ DWORD tx_buf_physaddr; /* set to zero for FMPlus */
+ WORD tx_buf_size; /* (see tx_bufs/tx_slots) */
+ WORD tx_buf_space;
+
+ WORD max_frame_size; /* for both rx and tx */
+ WORD size_rxdesc_queue; /* set to zero for FMPlus */
+ WORD max_rx_dma; /* set to zero for FMPlus */
+
+ WORD group_root_address; /* only for auto_open */
+#ifdef FMPLUS
+ WORD rx_bufs; /* # of internel rx buffers */
+ WORD tx_bufs; /* # of internal tx buffers */
+ WORD rx_slots; /* # of host rx buffers */
+ WORD tx_slots; /* # of host tx buffers */
+ WORD tx_ahead; /* Leave as zero */
+#endif
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : FASTMAC_INIT_PARMS - header. WORD signature, WORD version */
+/* */
+/* The values for the header of the Fastmac specific initialization */
+/* parameter block. */
+/* */
+
+#ifdef FMPLUS
+#define FMPLUS_INIT_HEADER_SIGNATURE 0x000E
+#define FMPLUS_INIT_HEADER_VERSION 0x0200 /* NOT Fastmac version! */
+#else
+#define FASTMAC_INIT_HEADER_SIGNATURE 0x0005
+#define FASTMAC_INIT_HEADER_VERSION 0x0405 /* NOT Fastmac version! */
+#endif
+
+/****************************************************************************/
+/* */
+/* Values : FASTMAC_INIT_PARMS - WORD feature_flags */
+/* */
+/* The feature flag bit signifcant values as described in the Fastmac */
+/* specification document. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - Initialization */
+/* */
+
+#define FEATURE_FLAG_AUTO_OPEN 0x0001
+#define FEATURE_FLAG_NOVELL 0x0002
+#define FEATURE_FLAG_SELL_BY_DATE 0x0004
+#define FEATURE_FLAG_PASS_RX_CRC 0x0008
+#define FEATURE_FLAG_WATCHDOG_TIMER 0x0020
+#define FEATURE_FLAG_DISCARD_BEACON_TX 0x0040
+#define FEATURE_FLAG_TRUNCATE_DMA 0x0080
+#define FEATURE_FLAG_DELAY_RX 0x0100
+#define FEATURE_FLAG_ONE_INT_PER_RX 0x0200
+#define FEATURE_FLAG_NEW_INIT_BLOCK 0x0400
+#define FEATURE_FLAG_AUTO_OPEN_ON_OPEN 0x0800
+#define FEATURE_FLAG_DISABLE_TX_FAIRNES 0x1000
+#ifdef FMPLUS
+#define FEATURE_FLAG_FMPLUS_ALWAYS_SET 0x0000
+#endif
+
+/* Yes, the FMPLUS_ALWAYS_SET bit is ZERO, because in fact it must NOT */
+/* always be set! This is an unfortunate historical legacy... */
+
+
+/****************************************************************************/
+/* */
+/* Values : FASTMAC_INIT_PARMS - WORD int_flags */
+/* */
+/* The interrupt flag bit significant values as described in the Fastmac */
+/* Plus specification document. */
+/* */
+/* REFERENCE : The Madge Fastmac Plus Programming Specification */
+/* - Initialization : TMS Load Parms */
+/* */
+
+#define INT_FLAG_TX_BUF_EMPTY 0x0001
+#define INT_FLAG_TIMER_TICK_ARB 0x0002
+#define INT_FLAG_RING_STATUS_ARB 0x0004
+#ifdef FMPLUS
+#define INT_FLAG_LARGE_DMA 0x0008
+#define INT_FLAG_RX 0x0010
+#endif
+
+#ifdef FMPLUS
+/****************************************************************************/
+/* */
+/* Values : Magic Fastmac Plus numbers to do with buffers on the adapter */
+/* */
+/* The size of buffers on the adapter card can be set with in the init. */
+/* block with the rx_tx_buffer_size field. The minimum value and default */
+/* values are specified here. Also, there are numbers giving the amount of */
+/* memory (in bytes) available for buffers on adapter cards of various RAM */
+/* sizes. */
+/* */
+/* REFERENCE : The Madge Fastmac Plus Programming Specification */
+/* - Initialization : SMTMAC Load Parms */
+/* */
+
+#define FMPLUS_MIN_TXRX_BUFF_SIZE 97
+
+#define FMPLUS_DEFAULT_BUFF_SIZE_SMALL 504 /* For EISA/MC32 cards */
+#define FMPLUS_DEFAULT_BUFF_SIZE_LARGE 1016 /* For all other cards */
+
+#define FMPLUS_MAX_BUFFMEM_IN_128K 63056 /* Bytes available for buffs*/
+#define FMPLUS_MAX_BUFFMEM_IN_256K 193104 /* on cards of 128K,256K, & */
+#define FMPLUS_MAX_BUFFMEM_IN_512K 453200 /* 512K RAM. */
+#endif
+
+/****************************************************************************/
+/* */
+/* Structure type : INITIALIZATION_BLOCK */
+/* */
+/* The initialization block consists of 3 parts - 22 bytes of TI */
+/* intialization parameters, general smart software MAC level parameters, */
+/* and the Fastmac specific parameters. */
+/* */
+
+struct STRUCT_INITIALIZATION_BLOCK
+ {
+ TI_INIT_PARMS ti_parms;
+ SMART_INIT_PARMS smart_parms;
+ FASTMAC_INIT_PARMS fastmac_parms;
+ };
+
+
+#pragma pack()
+
+/* */
+/* */
+/************** End of FTK_INIT.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_macr.h b/private/ntos/ndis/madge/driver/head_def/ftk_macr.h
new file mode 100644
index 000000000..d8bf16bec
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_macr.h
@@ -0,0 +1,157 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MACRO DEFINITIONS */
+/* ===================== */
+/* */
+/* FTK_MACR.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the macros that are used within the FTK. All */
+/* macros are included here for convenience, even though some are only used */
+/* in a single module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_MACR.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_MACR_H 221
+
+
+/****************************************************************************/
+/* */
+/* The macro_dword_align macro is used in DRV_TX.C to align Fastmac buffer */
+/* pointers on DWORD boundaries. */
+/* */
+
+#define macro_dword_align(p) (((p) + 0x0003) & 0xFFFC)
+
+
+/****************************************************************************/
+/* */
+/* The macro_word_swap_dword macro is used in DRV_INIT.C, DRV_SRB.C and */
+/* HWI_GEN.C to swap the WORDs within a DWORD in preparation for */
+/* downloading of the DWORD on to the adapter. */
+/* */
+
+#define macro_word_swap_dword(dw) dw = ((dw << 16) | (dw >> 16))
+
+
+/****************************************************************************/
+/* */
+/* The macro_byte_swap_word macro is used in DRV_RX.C and DRV_TX.C to swap */
+/* the BYTEs within a WORD because the length field in a Fastmac buffer is */
+/* in TMS ordering. */
+/* */
+
+#define macro_byte_swap_word(w) (((w) << 8) | ((w) >> 8))
+
+
+/****************************************************************************/
+/* */
+/* The macro_set<w/b>_bit macros are used in HWI_<card_type>.C to set */
+/* specific bits in control and other IO registers without affecting the */
+/* value of any other bits. */
+/* */
+/* The macro_setb_bit macro is for byte-size registers; the macro_setw_bit */
+/* macro is for word-size registers. */
+/* */
+
+#define macro_probe_setb_bit(io, b) \
+ sys_probe_outsb(io, (BYTE) (sys_probe_insb(io) | (b)))
+#define macro_setb_bit(hnd, io, b) \
+ sys_outsb( hnd, io, (BYTE) (sys_insb(hnd, io) | (b)))
+#define macro_setw_bit(hnd, io, b) \
+ sys_outsw( hnd, io, (WORD) (sys_insw(hnd, io) | (b)))
+
+
+/****************************************************************************/
+/* */
+/* The macro_clear<w/b>_bit macros are used in HWI_<card_type>.C to clear */
+/* specific bits in control and other IO registers without affecting the */
+/* value of any other bits. */
+/* */
+/* The macro_clearb_bit macro is for byte-size registers; the */
+/* macro_clearw_bit macro is for word-size registers. */
+/* */
+
+#define macro_probe_clearb_bit(io, b) \
+ sys_probe_outsb(io, (BYTE) (sys_probe_insb(io) & ~(b)))
+#define macro_clearb_bit(hnd, io, b) \
+ sys_outsb( hnd, io, (BYTE) (sys_insb(hnd, io) & ~(b)))
+#define macro_clearw_bit(hnd, io, b) \
+ sys_outsw( hnd, io, (WORD) (sys_insw(hnd, io) & ~(b)))
+
+
+/****************************************************************************/
+/* */
+/* The macro_fatal_error macro is used in DRV_ERR.C to distinguish fatal */
+/* from non-fatal errors. Fatal errors cause an adapter to no longer be */
+/* usable. */
+/* */
+
+#define macro_fatal_error(err) \
+ \
+ ( (err == ERROR_TYPE_HWI) || \
+ (err == ERROR_TYPE_DRIVER) || \
+ (err == ERROR_TYPE_INIT) || \
+ (err == ERROR_TYPE_BRING_UP) || \
+ (err == ERROR_TYPE_AUTO_OPEN) || \
+ (err == ERROR_TYPE_ADAPTER) )
+
+
+/****************************************************************************/
+/* */
+/* The macro_get_next_record macro is used in HWI_GEN.C to adjust a */
+/* pointer such that it points to the next download record in a list of */
+/* such records. */
+/* */
+
+#define macro_get_next_record(p) \
+ \
+ p = (DOWNLOAD_RECORD *) (((BYTE *) p) + p->length)
+
+
+/****************************************************************************/
+/* */
+/* The macro_enable_io and macro_disable_io macros are used throughout the */
+/* FTK for enabling/disabling access to specific IO locations. This is */
+/* required under certain operating systems, and the macros are implemented */
+/* by calls to system specific routines. */
+/* */
+/* Note on increasing speed: */
+/* */
+/* The reason for the macros is so that for systems where enabling and */
+/* disabling of IO locations is not required, the macros can just be */
+/* replaced by null code and there is no overhead of calling a system */
+/* routine that does nothing. */
+/* */
+
+#define macro_enable_io(adap) \
+ sys_enable_io((adap)->io_location, (adap)->io_range)
+
+#define macro_disable_io(adap) \
+ sys_disable_io((adap)->io_location, (adap)->io_range)
+
+#define macro_probe_enable_io(io_loc, io_range) \
+ sys_enable_io(io_loc, io_range)
+
+#define macro_probe_disable_io(io_loc, io_range) \
+ sys_disable_io(io_loc, io_range)
+
+
+
+/* */
+/* */
+/************** End of FTK_MACR.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_mc.h b/private/ntos/ndis/madge/driver/head_def/ftk_mc.h
new file mode 100644
index 000000000..07807d4e4
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_mc.h
@@ -0,0 +1,195 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (MICROCHANNEL CARDS) */
+/* ======================================================= */
+/* */
+/* FTK_MC.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge MC */
+/* adapter cards. Each adapter card has a number of control and status */
+/* registers. ALL bits in ALL registers are defined by Madge Networks Ltd, */
+/* however only a restricted number are defined below as used within the */
+/* FTK. All other bits must NOT be changed and no support will be offered */
+/* for any application that does so or uses the defined bits in any way */
+/* different to the FTK. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_MC.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_MC_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : MC REGISTER MAP */
+/* */
+/* Madge MC cards have the following register map. By setting certain bits */
+/* in the control registers it is possible to page in the BIA PROM (page 0 */
+/* or page 1) or the EAGLE SIF registers (normal or extended). */
+/* */
+/* NB. There is a lot of similarity between the MC and ATULA register maps. */
+/* */
+
+#define MC_IO_RANGE 16
+
+#define MC_CONTROL_REGISTER_0 0
+#define MC_CONTROL_REGISTER_1 1
+#define MC_POS_REGISTER_0 2
+#define MC_POS_REGISTER_1 3
+#define MC_POS_REGISTER_2 4
+#define MC_CONTROL_REGISTER_7 7
+
+#define MC_FIRST_SIF_REGISTER 8
+
+#define MC_BIA_PROM 8
+
+
+/****************************************************************************/
+/* */
+/* Values : MC CONTROL_REGISTER_0 */
+/* */
+/* These are the bit definitions for control register 0 on MC cards. */
+/* */
+/* NB. The bit definitions are mostly the same as ATULA CONTROL_REGISTER_7. */
+/* */
+
+#define MC_CTRL0_SIFSEL ((BYTE) 0x04) /* page in BIA PROM or SIF regs */
+#define MC_CTRL0_PAGE ((BYTE) 0x08) /* pages BIA PROM or EEPROM */
+#define MC_CTRL0_SINTR ((BYTE) 0x40) /* SIF interrupt pending */
+
+
+/****************************************************************************/
+/* */
+/* Values : MC CONTROL_REGISTER_1 */
+/* */
+/* These are the bit definitions for control register 1 on MC cards. */
+/* */
+/* NB. The bit definitions are mostly the same as ATULA CONTROL_REGISTER_1. */
+/* */
+
+#define MC_CTRL1_SINTREN ((BYTE) 0x01) /* SIF interrupt enable */
+#define MC_CTRL1_NSRESET ((BYTE) 0x04) /* active low SIF reset */
+#define MC_CTRL1_SRSX ((BYTE) 0x40) /* SIF extended register select */
+#define MC_CTRL1_16N4 ((BYTE) 0x80) /* ring speed select */
+
+
+/****************************************************************************/
+/* */
+/* Values : MC POS_REGISTER_0 */
+/* */
+/* These are the bit definitions for POS register 0 on MC cards. */
+/* */
+
+#define MC_POS0_CDEN ((BYTE) 0x01) /* card enabled */
+#define MC_POS0_DMAS ((BYTE) 0x1E) /* arbitration level (4 bits) */
+#define MC_POS0_IRQSEL ((BYTE) 0xC0) /* interrupt (2 bits encoded) */
+
+
+/****************************************************************************/
+/* */
+/* Values : MC POS_REGISTER_1 */
+/* */
+/* These are the bit definitions for POS register 1 on MC cards. */
+/* */
+
+#define MC_POS1_NOSPD ((BYTE) 0x04) /* any speed selected */
+#define MC_POS1_STYPE6 ((BYTE) 0x40) /* 16/4 MC media type */
+#define MC32_POS1_STYPE6 ((BYTE) 0x01) /* 16/4 MC 32 media type */
+
+
+/****************************************************************************/
+/* */
+/* Values : MC POS_REGISTER_2 */
+/* */
+/* These are the bit definitions for POS register 2 on MC cards. The */
+/* streaming bit is only applicable to 16/4 MC 32 cards. */
+/* */
+
+#define MC_POS2_FAIRNESS ((BYTE) 0x10) /* fair bus arbitration */
+#define MC_POS2_16N4 ((BYTE) 0x20) /* ring speed select */
+#define MC_POS2_STREAMING ((BYTE) 0x40) /* use streaming DMA */
+
+
+/****************************************************************************/
+/* */
+/* Values : MC CONTROL_REGISTER_7 */
+/* */
+/* These are the bit definitions for control register 7 on MC cards. */
+/* */
+
+#define MC_CTRL7_STYPE3 ((BYTE) 0x01) /* media type select */
+
+
+/****************************************************************************/
+/* */
+/* Values : IRQ SELECT IN MC POS_REGISTER_0 */
+/* */
+/* The two interrupt select bits in POS register 0 (MC_POS0_IRQSEL) */
+/* represent the interrupt number the card is on. */
+/* */
+
+#define MC_POS0_IRSEL_IRQ3 ((BYTE) 0x40) /* interrupt 3 encoding */
+#define MC_POS0_IRSEL_IRQ9 ((BYTE) 0x80) /* interrupt 9 encoding */
+#define MC_POS0_IRSEL_IRQ10 ((BYTE) 0xC0) /* interrupt 10 encoding */
+
+
+/****************************************************************************/
+/* */
+/* Values : MC EXTENDED EAGLE SIF REGISTERS */
+/* */
+/* The EAGLE SIF registers are in two groups - the normal SIF registers */
+/* (those from the old TI chipset) and the extended SIF registers (those */
+/* particular to the EAGLE). For Madge MC adapter cards, with CTRL0_SIFSEL */
+/* = 1 and CTRL1_NRESET = 1, having CTRL1_SRSX = 0 selects the normal SIF */
+/* registers and having CTRL1_SRSX = 1 selects the extended SIF registers. */
+/* */
+/* The definitions for the normal SIF registers are in FTK_CARD.H because */
+/* they appear in the same relative IO locations for all adapter cards. The */
+/* extended SIF registers are here because they appear at different */
+/* relative IO locations for different types of adapter cards. For ATULA */
+/* and MC cards they are in fact identical. */
+/* */
+
+#define MC_EAGLE_SIFACL 0 /* adapter control */
+#define MC_EAGLE_SIFADR_2 2 /* copy of SIFADR */
+#define MC_EAGLE_SIFADX 4 /* DIO address (high) */
+#define MC_EAGLE_DMALEN 6 /* DMA length */
+
+/****************************************************************************/
+/* */
+/* Values : ADAPTER - BYTE mc32_config */
+/* */
+/* The adapter structure field mc32_config is made up of streaming, */
+/* fairness and arbitration level information as follows : */
+/* */
+/* bits 0-3 MC_POS0_DMAS */
+/* bit 4 MC_POS2_FAIRNESS */
+/* bit 5 MC_POS2_STREAMING */
+/* */
+/* The POS register fields need to be shifted into the correct bit */
+/* positions for the mc32_config byte. The right shift values are given */
+/* below. */
+/* */
+
+#define MC32_CONFIG_DMA_SHIFT ((BYTE) 1)
+#define MC32_CONFIG_FAIRNESS_SHIFT ((BYTE) 0)
+#define MC32_CONFIG_STREAMING_SHIFT ((BYTE) 1)
+
+
+/* */
+/* */
+/************** End of FTK_MC.H file ****************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_pci.h b/private/ntos/ndis/madge/driver/head_def/ftk_pci.h
new file mode 100644
index 000000000..6c6a63ea6
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_pci.h
@@ -0,0 +1,150 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (PCI CARDS) */
+/* =================================================== */
+/* */
+/* FTK_PCI.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1994 */
+/* Developed by PRR */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge Smart */
+/* 16/4 PCI */
+/* adapter cards. These adapter cards have a couple of control registers, */
+/* in addition to the SIF registers. ALL bits in ALL control registers are */
+/* defined by Madge Networks Ltd */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_PCI.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_PCI_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : PCI REGISTER MAP */
+/* */
+/* The Madge PCI Ringnode uses the following register layout. */
+/* N.B. The SIF registers are mapped linearly, with no overlaying. */
+/* */
+
+#define PCI_GENERAL_CONTROL_REG 0
+#define PCI_INT_MASK_REG 4
+#define PCI_SEEPROM_CONTROL_REG 8
+#define PCI_FIRST_SIF_REGISTER 0x20
+
+#define PCI_IO_RANGE 256
+
+#define PCI1_SRESET 1 /* Bit 0 of General Control Register */
+#define PCI1_RSPEED_4MBPS 0x200 /* Bit 9 of General Control Register */
+#define PCI1_RSPEED_VALID 0x400 /* Bit 10 of General Control Register */
+
+#define PCI1_BIA_CLK 0x0001 /* Bit 0 of SEEPROM control word. */
+#define PCI1_BIA_DOUT 0x0002 /* Bit 1 of SEEPROM control word. */
+#define PCI1_BIA_ENA 0x0004 /* Bit 2 of SEEPROM control word. */
+#define PCI1_BIA_DIN 0x0008 /* Bit 3 of SEEPROM control word. */
+
+#define PCI1_ENABLE_MMIO 0x0080 /* MC32 config value to enable MMIO. */
+
+
+/****************************************************************************/
+/* */
+/* Values : AT93C46 Serial EEPROM control valuse */
+/* */
+
+#define PCI_C46_START_BIT 0x8000
+#define PCI_C46_READ_CMD 0x4000
+#define PCI_C46_ADDR_MASK 0x003f
+#define PCI_C46_ADDR_SHIFT 7
+#define PCI_C46_CMD_LENGTH 9
+
+
+/****************************************************************************/
+/* */
+/* Values : PCI SIF REGISTERS */
+/* */
+/* The EAGLE SIF registers are in two groups - the normal SIF registers */
+/* (those from the old TI chipset) and the extended SIF registers (those */
+/* particular to the EAGLE). */
+/* */
+/* The definitions for the normal SIF registers are here because they */
+/* appear in the same relative IO locations for all adapter cards. */
+/* */
+
+#define PCI_SIFDAT 0 /* DIO data */
+#define PCI_SIFDAT_INC 4 /* DIO data auto-increment */
+#define PCI_SIFADR 8 /* DIO address (low) */
+#define PCI_SIFINT 12 /* interrupt SIFCMD-SIFSTS */
+
+/* These definitions are for the case when the SIF registers are mapped */
+/* linearly. Otherwise, they will be at some extended location. */
+
+#define PCI_SIFACL 16
+#define PCI_SIFADX 24
+
+/* These definitions are for Eagle Pseudo DMA. Notice that they replace the */
+/* registers above - this is controlled by SIFACL. */
+
+#define PCI_SDMADAT 0
+#define PCI_DMALEN 4
+#define PCI_SDMAADR 8
+#define PCI_SDMAADX 12
+
+
+/****************************************************************************/
+/* */
+/* Value : Number of IO locations for SIF registers */
+/* */
+/* The number of SIF registers is only needed for enabling and disabling */
+/* ranges of IO ports. For the ATULA and MC cards the SIF registers are in */
+/* 2 pages only using 8 IO ports. However, for EISA cards, the SIF */
+/* registers are in a single page of 16 IO ports. Hence, 16 IO ports need */
+/* to be enabled whenever accessing SIF registers. */
+/* */
+
+#define PCI_SIF_IO_RANGE 32
+
+/****************************************************************************/
+/* */
+/* Values : Locations of data in the serial EEPROM (in words) */
+/* */
+/* */
+
+#define PCI_EEPROM_BIA_WORD0 0
+#define PCI_EEPROM_BIA_WORD1 1
+#define PCI_EEPROM_BIA_WORD2 2
+#define PCI_EEPROM_RING_SPEED 3
+#define PCI_EEPROM_RAM_SIZE 4
+
+
+
+/* */
+/* For some perverted reason it is not possible to read these bits back */
+/* from the SEEPROM control register once they have been written. */
+/* */
+
+#define BITS_TO_REMEMBER (PCI1_BIA_ENA | PCI1_BIA_DOUT | PCI1_BIA_CLK)
+
+/****************************************************************************/
+/* */
+/* Values : Ring speed values stored in the serial EEPROM */
+/* */
+/* */
+
+#define PCI_EEPROM_4MBS 1
+#define PCI_EEPROM_16MBPS 0
+
+/* */
+/* */
+/************** End of FTK_PCI.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_pci2.h b/private/ntos/ndis/madge/driver/head_def/ftk_pci2.h
new file mode 100644
index 000000000..4d488bd35
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_pci2.h
@@ -0,0 +1,122 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (PCI CARDS) */
+/* =================================================== */
+/* */
+/* FTK_PCI2.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1994 */
+/* Developed by PRR */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge Smart */
+/* 16/4 PCI (BM) adapter cards, ie based on the Madge bus interface ASIC. */
+/* */
+/* The SIF registers are WORD aligned and start at offset 0x10 from the IO */
+/* space */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_PCI.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_PCI_H 221
+
+/***************************************************************************/
+/* */
+/* PCI-2 IO Map */
+/* Offsets of register locations are from the start of the card's IO space.*/
+/* */
+
+#define PCI2_INTERRUPT_STATUS 0x01 /* One byte. */
+#define PCI2_DMAING 0x01 /* Bit 0 - Dma in progress */
+#define PCI2_SINTR 0x02 /* Bit 1 - SIF int */
+#define PCI2_SWINT 0x04 /* Bit 2 - Software int */
+#define PCI2_PCI_INT 0x80 /* Bit 8 - Catastrophic error */
+
+#define PCI2_INTERRUPT_CONTROL 0x02 /* One byte. */
+#define PCI2_SINTEN 0x02 /* Bit 1 - SIF int enable */
+#define PCI2_SWINTEN 0x04 /* Bit 2 - S/w int enable */
+#define PCI2_PCI_ERR_EN 0x80 /* Bit 9 - Catastrophic err en */
+
+#define PCI2_RESET 0x04 /* One byte. */
+#define PCI2_CHIP_NRES 0x01 /* Bit 0 - Reset chip if zero */
+#define PCI2_FIFO_NRES 0x02 /* Bit 2 - Fifo reset if zero */
+#define PCI2_SIF_NRES 0x04 /* Bit 3 - SIF reset if zero */
+
+#define PCI2_SEEPROM_CONTROL 0x07 /* One byte. */
+#define PCI2_SEESK 0x01 /* Bit 0 - Clock */
+#define PCI2_SEED 0x02 /* Bit 1 - Data */
+#define PCI2_SEEOE 0x04 /* Bit 2 - Output enable */
+
+#define PCI2_EEPROM_CONTROL 0x08 /* Dword - Low 19 bits are addr */
+#define PCI2_AUTOINC 0x80000000 /* Bit 31 - Does addr autoinc */
+
+#define PCI2_EEPROM_DATA 0x0C /* One byte. */
+
+#define PCI2_SIF_OFFSET 0x10
+
+/* Locations 0x22 onwards are for ASIC debugging only */
+#define PCI2_IO_RANGE 0x36
+
+
+
+/****************************************************************************/
+/* */
+/* Bits for programming the EEPROM */
+/* */
+/* */
+#define AT24_IO_CLOCK 1
+#define AT24_IO_DATA 2
+#define AT24_IO_ENABLE 4
+
+/****************************************************************************/
+/* */
+/* Usefule locations in the EEPROM */
+/* */
+/* */
+#define PCI2_EEPROM_BIA_WORD0 9
+#define PCI2_EEPROM_BIA_WORD1 10
+#define PCI2_EEPROM_BIA_WORD2 11
+#define PCI2_EEPROM_RING_SPEED 12
+#define PCI2_EEPROM_RAM_SIZE 13
+#define PCI2_HWF1 14
+#define PCI2_HWF2 15
+
+
+/****************************************************************************/
+/* */
+/* Useful values in the EEPROM */
+/* */
+#define PCI2_EEPROM_4MBITS 1
+#define PCI2_EEPROM_16MBITS 0
+
+
+#define PCI2_BUS_MASTER_ONLY 4
+#define PCI2_HW2_431_READY 0x10
+
+
+/****************************************************************************/
+/* */
+/* Useful locations in the PCI config space */
+/* */
+/* */
+#define PCI_CONFIG_COMMAND 0x4
+
+/****************************************************************************/
+/* */
+/* The BUS Master DMA Enable bit in the CONFIG_COMMAND register */
+#define PCI_CONFIG_BUS_MASTER_ENABLE 0x4
+
+
+/* */
+/* */
+/************** End of FTK_PCI.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_pcit.h b/private/ntos/ndis/madge/driver/head_def/ftk_pcit.h
new file mode 100644
index 000000000..9822c09ce
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_pcit.h
@@ -0,0 +1,109 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (PCI CARDS) */
+/* =================================================== */
+/* */
+/* FTK_PCIT.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1994 */
+/* Developed by PRR */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge Smart */
+/* 16/4 PCI (T) adapter cards, ie based on the Ti PCI bus interface ASIC */
+/* The only IO registers are the SIF registers, all other control is */
+/* through PCI config space */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_PCI.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_PCI_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : PCI REGISTER MAP */
+/* */
+/* The Madge PCI Ringnode uses the following register layout. */
+/* N.B. The SIF registers are mapped linearly, with no overlaying. */
+/* */
+#define PCIT_HANDSHAKE 0x100C
+#define PCIT_HANDSHAKE 0x100C
+
+
+/****************************************************************************/
+/* */
+/* Useful locations in the PCI config space */
+/* */
+/* */
+#define EEPROM_OFFSET 0x48
+#define MISC_CONT_REG 0x40
+#define PCI_CONFIG_COMMAND 0x4
+#define CACHE_LINE_SIZE 0xC
+
+/****************************************************************************/
+/* */
+/* The BUS Master DMA Enable bit in the CONFIG_COMMAND register */
+#define PCI_CONFIG_BUS_MASTER_ENABLE 0x4
+#define PCI_CONFIG_IO_ENABLE 0x2
+#define PCI_CONFIG_MEM_ENABLE 0x1
+
+/****************************************************************************/
+/* */
+/* Bits for programming the EEPROM */
+/* */
+/* */
+#define AT24_IO_CLOCK 1
+#define AT24_IO_DATA 2
+#define AT24_IO_ENABLE 4
+
+/****************************************************************************/
+/* */
+/* EEPROM commands */
+/* */
+#define AT24_WRITE_CMD 0xA0
+#define AT24_READ_CMD 0xA1
+
+/****************************************************************************/
+/* */
+/* Useful locations in the EEPROM */
+/* */
+/* */
+
+#define PCIT_EEPROM_BIA_WORD0 9
+#define PCIT_EEPROM_BIA_WORD1 10
+#define PCIT_EEPROM_BIA_WORD2 11
+#define PCIT_EEPROM_RING_SPEED 12
+#define PCIT_EEPROM_RAM_SIZE 13
+#define PCIT_EEPROM_HWF2 15
+
+#define NSEL_4MBITS 3
+#define NSEL_16MBITS 1
+
+/****************************************************************************/
+/* */
+/* Values in the EEPROM */
+/* */
+#define PCIT_EEPROM_4MBITS 1
+#define PCIT_EEPROM_16MBITS 0
+
+#define PCIT_BROKEN_DMA 0x20
+
+/*
+* Value passed to the adapter in the mc32 byte to tell it to use the FMPLUS
+* code which supports broken DMA.
+*/
+#define TRN_PCIT_BROKEN_DMA 0x200
+
+/* */
+/* */
+/************** End of FTK_PCI.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_pcmc.h b/private/ntos/ndis/madge/driver/head_def/ftk_pcmc.h
new file mode 100644
index 000000000..b229657ae
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_pcmc.h
@@ -0,0 +1,256 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (PCMCIA CARDS) */
+/* ================================================= */
+/* */
+/* FTK_PCMC.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by VL */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge PCMCIA */
+/* adapter cards. Each adapter card has a number of control and status */
+/* registers. ALL bits in ALL registers are defined by Madge Networks Ltd, */
+/* however only a restricted number are defined below as used within the */
+/* FTK. All other bits must NOT be changed and no support will be offered */
+/* for any application that does so or uses the defined bits in any way */
+/* different to the FTK. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_PCMC.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_PCMC_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : PCMCIA REGISTER MAP */
+/* */
+/* Madge PCMCIA cards have the following register map. All SIF registers */
+/* are always visible. */
+/* */
+
+#define PCMCIA_IO_RANGE 32
+
+#define PCMCIA_CONTROL_REGISTER_1 0x0000
+#define PCMCIA_CONTROL_REGISTER_2 0x0002
+
+#define PCMCIA_PIO_IO_LOC 0x0008
+
+#define PCMCIA_FIRST_SIF_REGISTER 0x0010
+
+
+/****************************************************************************/
+/* */
+/* Values : PCMCIA_CONTROL_REGISTER_1 */
+/* */
+/* These are bit definitions for control register 1 on PCMCIA adapters. */
+/* */
+
+#define PCMCIA_CTRL1_SINTREN ((BYTE) 0x01) /* SIF interrupt enable */
+#define PCMCIA_CTRL1_SRESET ((BYTE) 0x02) /* EAGLE SIF reset */
+#define PCMCIA_CTRL1_CISDIS ((BYTE) 0x04) /* CIS ROM / extern EEPROM */
+#define PCMCIA_CTRL1_SHLDA ((BYTE) 0x40) /* SHLDA pin status (PIO) */
+#define PCMCIA_CTRL1_SHRQ ((BYTE) 0x80) /* SHRQ pin status (PIO) */
+
+
+/****************************************************************************/
+/* */
+/* Values : PCMCIA_CONTROL_REGISTER_2 */
+/* */
+/* These are bit definitions for control register 2 on PCMCIA adapters. */
+/* */
+
+#define PCMCIA_CTRL2_SBCKSEL ((BYTE) 0x03) /* SIF clock frequency */
+#define PCMCIA_CTRL2_4N16 ((BYTE) 0x04) /* Ring speed 4/16 */
+#define PCMCIA_CTRL2_FLSHWREN ((BYTE) 0x08) /* EEPROM write enable */
+#define PCMCIA_CTRL2_E2SK ((BYTE) 0x10) /* SK (sync clk) pin of EEPROM */
+#define PCMCIA_CTRL2_E2CS ((BYTE) 0x20) /* CS (chip sel) pin of EEPROM */
+#define PCMCIA_CTRL2_E2DI ((BYTE) 0x40) /* DI (data in) pin of EEPROM */
+#define PCMCIA_CTRL2_E2DO ((BYTE) 0x80) /* Output statue of EEPROm */
+
+#define PCMCIA_CTRL2_4N16_4 ((BYTE) 0x04) /* ringspeed = 4MB/s */
+#define PCMCIA_CTRL2_4N16_16 ((BYTE) 0x00) /* ringspeed = 16MB/s */
+
+#define PCMCIA_CTRL2_SBCKSEL_2 ((BYTE) 0x00) /* sif clock frequency 2MHz */
+#define PCMCIA_CTRL2_SBCKSEL_8 ((BYTE) 0x01) /* sif clock frequency 8MHz */
+#define PCMCIA_CTRL2_SBCKSEL_16 ((BYTE) 0x02) /* sif clock frequency 16MHz */
+#define PCMCIA_CTRL2_SBCKSEL_32 ((BYTE) 0x03) /* sif clock frequency 32MHz */
+
+
+/****************************************************************************/
+/* */
+/* Values : PCMCIA EXTENDED EAGLE SIF REGISTERS */
+/* */
+/* The EAGLE SIF registers are in two groups - the normal SIF registers */
+/* (those from the old TI chipset) and the extended SIF registers (those */
+/* particular to the EAGLE). For Madge PCMCIA adapter cards, both normal */
+/* and extended SIF registers are always accessible. */
+/* */
+/* The definitions for the normal SIF registers are in FTK_CARD.H because */
+/* they appear in the same relative IO locations for all adapter cards. The */
+/* extended SIF registers are here because they appear at different */
+/* relative IO locations for different types of adapter cards. */
+/* */
+
+#define PCMCIA_EAGLE_SIFACL 8 /* adapter control */
+#define PCMCIA_EAGLE_SIFADR_2 10 /* copy of SIFADR */
+#define PCMCIA_EAGLE_SIFADX 12 /* DIO address (high) */
+#define PCMCIA_EAGLE_DMALEN 14 /* DMA length */
+
+
+/****************************************************************************/
+/* */
+/* Values : PCMCIA CARD CONFIGURATION REGISTER */
+/* */
+/* These are definition of PCMCIA card configuration register (CCR) which */
+/* are mapped into attribute memory space. They should only be accessed */
+/* through PCMCIA Card Services. */
+/* */
+
+#define PCMCIA_CONFIG_BASE 0x00000800 /* Offset from attribute memory space */
+
+/* SMART 16/4 PCMCIA ringnode only have Configuration Option Register and */
+/* Configuration Status Register. There are no Pin Register and Socket/Copy */
+/* Register. */
+
+#define PCMCIA_REGISTER_PRESENT RC_PRESENT_OPTION_REG | RC_PRESENT_STATUS_REG
+
+#define PCMCIA_OPTION_REG 0x00 /* configruation option register (COR) */
+#define PCMCIA_STATUS_REG 0x02 /* configuration status register (CSR) */
+
+
+/****************************************************************************/
+/* */
+/* Values : PCMCIA CARD CONFIGURATION OPTION REGISTER (COR) */
+/* */
+
+#define PCMCIA_COR_CNFGD_MASK ((BYTE) 0x3F) /* IO Config. Enable port */
+#define PCMCIA_COR_LEVLREQ ((BYTE) 0x40) /* Level/Edge IRQ mode select */
+#define PCMCIA_COR_SYSRESET ((BYTE) 0x80) /* soft reset (not sif reset) */
+
+
+/****************************************************************************/
+/* */
+/* Values : PCMCIA CARD CONFIGURATION STATUS REGISTER (CSR) */
+/* */
+
+#define PCMCIA_CSR_RSRVD2 ((BYTE) 0x01) /* Reserved */
+#define PCMCIA_CSR_INTR ((BYTE) 0x02) /* Interrupt request to host */
+#define PCMCIA_CSR_PWRDWN ((BYTE) 0x04) /* Power down bit. Not used */
+#define PCMCIA_CSR_AUDIO ((BYTE) 0x08) /* Audio. Not used */
+#define PCMCIA_CSR_RSRVD1 ((BYTE) 0x10) /* Reserved */
+#define PCMCIA_CSR_IOIS8 ((BYTE) 0x20) /* 8-bit/16-bit data path */
+#define PCMCIA_CSR_SIGCHG ((BYTE) 0x40) /* Status Change. Not used */
+#define PCMCIA_CSR_CHANGED ((BYTE) 0x80) /* Not used */
+
+
+/****************************************************************************/
+/* */
+/* Initial Setting of these register */
+/* */
+
+#define PCMCIA_STATUS_REG_SETTING ((BYTE) 0x00)
+#define PCMCIA_PIN_REG_SETTING ((BYTE) 0x00)
+#define PCMCIA_COPY_REG_SETTING ((BYTE) 0x00)
+#define PCMCIA_OPTION_REG_SETTING \
+ ( 0x01 & PCMCIA_COR_CNFGD_MASK ) | PCMCIA_COR_LEVLREQ
+
+
+/****************************************************************************/
+/* */
+/* Other Hardware specification related definitions */
+/* */
+
+
+/* */
+/* EEPROM */
+/* */
+
+#define C46_START_BIT 0x8000 /* start bit of command */
+#define C46_READ_CMD 0x4000 /* command to enable reading of EEPROM */
+#define C46_ADDR_MASK 0x003F /* Bottom 6 bits are the address */
+#define C46_ADDR_SHIFT 7 /* no. of bits to shift the address */
+#define C46_CMD_LENGTH 9 /* 1 start bit, 2 cmd bits, 6 adr bits */
+
+#define EEPROM_ADDR_NODEADDR1 0x0000 /* 1st word in EEPROM = Nodeaddress1 */
+#define EEPROM_ADDR_NODEADDR2 0x0001 /* 2nd word in EEPROM = Nodeaddress2 */
+#define EEPROM_ADDR_NODEADDR3 0x0002 /* 3rd word in EEPROM = Nodeaddress3 */
+#define EEPROM_ADDR_RINGSPEED 0x0003 /* 4th word in EEPROM = RingSpeed */
+#define EEPROM_ADDR_RAMSIZE 0x0004 /* 5th word in EEPROM = Ram size / 128 */
+#define EEPROM_ADDR_REVISION 0x0005 /* 6th word in EEPROM = Revsion */
+
+#define EEPROM_RINGSPEED_16 0x0000 /* The 4th word = 0 -> 16MB/s */
+#define EEPROM_RINGSPEED_4 0x0001 /* The 4th word = 1 -> 4MB/s */
+
+
+/* */
+/* Miscellaneous */
+/* */
+
+#define PCMCIA_RAM_SIZE 512 /* 512k RAM on adapter */
+
+#define PCMCIA_NUMBER_OF_ADDR_LINES 16 /* Number of address lines decoded */
+
+#define PCMCIA_VCC 50 /* Vcc in tenth of a volt */
+#define PCMCIA_VPP1 0 /* Vpp1 in tenth of a volt */
+#define PCMCIA_VPP2 0 /* Vpp2 in tenth of a volt */
+
+
+/****************************************************************************/
+/* */
+/* Madge Signature for tuple CISTPL_VERS_1 */
+/* */
+
+#define MADGE_TPLLV1_INFO_LEN 33 /* note that there is a '\0' in the string */
+ /* so strlen will not work. */
+
+ /* 123456 789012345678901234567890123 */
+
+#define MADGE_TPLLV1_INFO_STRING "MADGE\0SMART 16/4 PCMCIA RINGNODE"
+
+
+/****************************************************************************/
+/* */
+/* Data sturcture of tuple CISTPL_VERS_1 */
+/* */
+/* Note that CS Level 2.00 or below start with a byte of tpl_code and a */
+/* byte of tpl_link. They are removed in CS Level 2.01 */
+/* */
+
+struct STRUCT_CS200_CISTPL_VERS_1_DATA
+{
+ BYTE tpl_code;
+ BYTE tpl_link;
+ BYTE tpllv1_major;
+ BYTE tpllv1_minor;
+ BYTE info[MADGE_TPLLV1_INFO_LEN];
+ BYTE additional_info[1];
+};
+
+typedef struct STRUCT_CS200_CISTPL_VERS_1_DATA CS200_CISTPL_VERS_1_DATA;
+
+struct STRUCT_CS201_CISTPL_VERS_1_DATA
+{
+ BYTE tpllv1_major;
+ BYTE tpllv1_minor;
+ BYTE info[MADGE_TPLLV1_INFO_LEN];
+ BYTE additional_info[1];
+};
+
+typedef struct STRUCT_CS201_CISTPL_VERS_1_DATA CS201_CISTPL_VERS_1_DATA;
+
+/* */
+/* */
+/********************* End of FTK_PCMC.H file *****************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_pnp.h b/private/ntos/ndis/madge/driver/head_def/ftk_pnp.h
new file mode 100644
index 000000000..319a0c15d
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_pnp.h
@@ -0,0 +1,142 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (Plug aNd Play (PNP) CARDS) */
+/* ============================================================== */
+/* */
+/* FTK_PNP.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by AC */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge PNP */
+/* adapter cards. These adapter cards have a couple of control registers, */
+/* in addition to the SIF registers. ALL bits in ALL control registers are */
+/* defined by Madge Networks Ltd */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_PNP.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_PNP_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : PNP REGISTER MAP */
+/* */
+/* The Madge Smart 16 Ringnode uses the following register layout. */
+/* N.B. The SIF registers are mapped linearly, with no overlaying. */
+/* */
+
+#define PNP_IO_RANGE 32
+
+#define PNP_CONTROL_REGISTER_1 3
+#define PNP_ID_REGISTER 8
+
+#define PNP_FIRST_SIF_REGISTER 16
+
+
+/****************************************************************************/
+/* */
+/* Values : PNP CONFIGURATION REGISTERS */
+/* */
+/* These are the bit definitions for the PnP configuration registers. */
+/* */
+
+#define PNP_CONFIG_ADDRESS_REGISTER 1
+#define PNP_CONFIG_DATA_REGISTER 2
+
+#define PNP_VENDOR_CONFIG_BYTE ((BYTE) 0xf0)
+
+#define PNP_VENDOR_CONFIG_IRQ ((BYTE )0x70)
+#define PNP_VENDOR_CONFIG_4MBITS ((BYTE) 0x80)
+#define PNP_VENDOR_CONFIG_RSVALID ((BYTE) 0x02)
+#define PNP_VENDOR_CONFIG_PXTAL ((BYTE) 0x01)
+
+
+/****************************************************************************/
+/* */
+/* Values : PNP CONTROL_REGISTER_1 */
+/* */
+/* These are the bit definitions for control register 1 on Smart 16 cards. */
+/* */
+/* NB. The bit definitions are mostly the same as MC CONTROL_REGISTER_1. */
+/* */
+
+#define PNP_CTRL1_NSRESET ((BYTE) 0x80) /* SIF Reset signal */
+#define PNP_CTRL1_CHRDY_ACTIVE ((BYTE) 0x20) /* Active channel ready. */
+
+
+/****************************************************************************/
+/* */
+/* This defines the bits used to set the RING SPEED for PNP cards. */
+/* */
+/* The bit is SET/CLEARED in SIFACL via adapter->nselout_bits just before */
+/* taking the card out of the RESET state. */
+/* */
+/* NSELOUT1 is use to control the ring speed */
+/* NSELOUT0 should ALWAYS be left alone. */
+/* */
+
+#define PNP_RING_SPEED_4 1
+#define PNP_RING_SPEED_16 0
+
+/*
+*
+* Various definitions used to talk to EEPROM.
+*
+*/
+#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
+
+/*
+* Useful locations in the EEPROM
+*/
+#define PNP_HWARE_FEATURES1 0xEB
+#define PNP_HWARE_FEATURES3 0xED
+#define PNP_HWARE_PNP_FLAGS 0xEE
+
+/*
+*
+* This defines the bits in HWARE_FEATURES1 which give the DRAM size.
+*
+*/
+
+#define PNP_DRAM_SIZE_MASK 0x3E
+
+/*
+*
+* This defines the bits in HWARE_FEATURES3 which give the chip type.
+*
+*/
+
+#define PNP_C30_MASK 0x40
+#define PNP_C30 PNP_C30_MASK
+
+
+/*
+* This defines the bits in HWARE_PNP_FLAGS.
+*/
+
+#define PNP_ACTIVE_FLOAT_CHRDY 0x02
+
+/* */
+/* */
+/************** End of FTK_PNP.H file ***************************************/
+/* */
+/* */
+
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_poke.h b/private/ntos/ndis/madge/driver/head_def/ftk_poke.h
new file mode 100644
index 000000000..eb469ba9e
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_poke.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+*
+* FTK_POKE.H
+*
+* Part of the FastMAC Toolkit.
+* Copyright (c) Madge Networks Ltd 1995
+*
+* This module provides some functions that will send tracing information
+* to either serial port (COM1 or COM2) on a standard IBM PC clone.
+*
+*****************************************************************************/
+
+#ifdef FTK_POKEOUTS
+
+void _ftk_poke_char(int ch);
+void _ftk_poke_string(char *str);
+void _ftk_poke_byte(int byte);
+void _ftk_poke_word(int word);
+void _ftk_poke_dword(long dword);
+
+#define FTK_POKE_CHAR(x) _ftk_poke_char((int) (x))
+#define FTK_POKE_STRING(x) _ftk_poke_string(x)
+#define FTK_POKE_BYTE(x) _ftk_poke_byte((int) (x))
+#define FTK_POKE_WORD(x) _ftk_poke_word((int) (x))
+#define FTK_POKE_DWORD(x) _ftk_poke_dword((long) (x))
+
+/*
+ * Prototypes and macro definitions for comms primitives.
+ */
+
+int _inp(unsigned port);
+int _outp(unsigned port, int data_byte);
+
+#define OUTB(x, y) _outp(x, y)
+#define INB(x) _inp(x)
+
+/*
+ * Use the following definition to force pokeouts to COM2.
+ */
+
+/* #define USE_COM2 */
+
+#else
+
+#define FTK_POKE_CHAR(x)
+#define FTK_POKE_STRING(x)
+#define FTK_POKE_BYTE(x)
+#define FTK_POKE_WORD(x)
+#define FTK_POKE_DWORD(x)
+
+#endif
+
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_sm16.h b/private/ntos/ndis/madge/driver/head_def/ftk_sm16.h
new file mode 100644
index 000000000..3005e775d
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_sm16.h
@@ -0,0 +1,100 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MADGE ADAPTER CARD DEFINITIONS (SMART 16 CARDS) */
+/* ================================================ */
+/* */
+/* FTK_SM16.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by AC */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions for programming Madge Smart 16 */
+/* adapter cards. These adapter cards have a couple of control registers, */
+/* in addition to the SIF registers. ALL bits in ALL control registers are */
+/* defined by Madge Networks Ltd */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_SM16.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_SM16_H 221
+
+
+/****************************************************************************/
+/* */
+/* Values : SMART 16 REGISTER MAP */
+/* */
+/* The Madge Smart 16 Ringnode uses the following register layout. */
+/* N.B. The SIF registers are mapped linearly, with no overlaying. */
+/* */
+
+#define SMART16_IO_RANGE 32
+
+#define SMART16_DEFAULT_INTERRUPT 2
+
+#define SMART16_CONTROL_REGISTER_1 0
+#define SMART16_CONTROL_REGISTER_2 8
+
+#define SMART16_FIRST_SIF_REGISTER 16
+
+
+/****************************************************************************/
+/* */
+/* Values : SMART 16 CONTROL_REGISTER_1 */
+/* */
+/* These are the bit definitions for control register 1 on Smart 16 cards. */
+/* */
+/* NB. The bit definitions are mostly the same as MC CONTROL_REGISTER_1. */
+/* */
+
+#define SMART16_CTRL1_NSRESET ((BYTE) 0x01) /* SIF Reset signal */
+#define SMART16_CTRL1_SCS ((BYTE) 0x02) /* Chip select */
+
+
+/****************************************************************************/
+/* */
+/* Values : SMART 16 CONTROL_REGISTER_2 BITS */
+/* */
+/* These are the bit definitions for control register 2 on Smart 16 cards. */
+/* */
+
+#define SMART16_CTRL2_XTAL ((BYTE) 0x01) /* Used to decode BIA */
+#define SMART16_CTRL2_SCS ((BYTE) 0x02) /* Same as CTRL1_SCS */
+
+
+/****************************************************************************/
+/* */
+/* Values : SMART 16 SIFACL INTERRUPT SETTINGS */
+/* */
+/* These are the values to be written into the NSELOUT0/1 bits of SIFACL to */
+/* select the interrupt number on the adapter card. */
+/* */
+
+#define SMART16_IRQ_2 3
+#define SMART16_IRQ_3 0
+#define SMART16_IRQ_7 2
+
+
+/****************************************************************************/
+/* */
+/* Values : SMART 16 IO PORT MASK for revision type */
+/* */
+/* This bit in the IO address selects between rev3 and rev4 bus timings. */
+/* */
+
+#define SMART16_REV3 ((UINT) 0x1000)
+
+
+/* */
+/* */
+/************** End of FTK_SM16.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_srb.h b/private/ntos/ndis/madge/driver/head_def/ftk_srb.h
new file mode 100644
index 000000000..027611abd
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_srb.h
@@ -0,0 +1,279 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE SRB DEFINITIONS */
+/* =================== */
+/* */
+/* FTK_SRB.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains all the definitions and structures that are */
+/* required for the SRB interface. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface */
+/* */
+/* IMPORTANT : All structures used within the FTK need to be packed in */
+/* order to work correctly. This means sizeof(STRUCTURE) will give the real */
+/* size in bytes, and if a structure contains sub-structures there will be */
+/* no spaces between the sub-structures. */
+/* */
+/****************************************************************************/
+
+#pragma pack(1)
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_SRB.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_SRB_H 221
+
+
+/****************************************************************************/
+/* */
+/* TYPEDEFs for all structures defined within this header file : */
+/* */
+
+typedef struct STRUCT_SRB_HEADER SRB_HEADER;
+
+typedef union UNION_SRB_GENERAL SRB_GENERAL;
+
+typedef struct STRUCT_SRB_MODIFY_OPEN_PARMS SRB_MODIFY_OPEN_PARMS;
+
+typedef struct STRUCT_SRB_OPEN_ADAPTER SRB_OPEN_ADAPTER;
+
+typedef struct STRUCT_SRB_CLOSE_ADAPTER SRB_CLOSE_ADAPTER;
+
+typedef struct STRUCT_SRB_SET_MULTICAST_ADDR SRB_SET_GROUP_ADDRESS;
+typedef struct STRUCT_SRB_SET_MULTICAST_ADDR SRB_SET_FUNCTIONAL_ADDRESS;
+
+typedef struct STRUCT_SRB_READ_ERROR_LOG SRB_READ_ERROR_LOG;
+
+typedef struct STRUCT_SRB_SET_BRIDGE_PARMS SRB_SET_BRIDGE_PARMS;
+
+typedef struct STRUCT_SRB_SET_PROD_INST_ID SRB_SET_PROD_INST_ID;
+
+/****************************************************************************/
+/* */
+/* Structure type : SRB_HEADER */
+/* */
+/* All SRBs have a common header. With Fastmac all SRBs complete */
+/* synchronously, ie. the return code is never E_FF_COMMAND_NOT_COMPLETE */
+/* and the correlator field is not used. */
+/* */
+
+struct STRUCT_SRB_HEADER
+ {
+ BYTE function;
+ BYTE correlator;
+ BYTE return_code;
+ BYTE reserved;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : SRB_HEADER - BYTE function */
+/* */
+/* These are the SRBs currently supported by the FTK. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface */
+/* */
+
+#define MODIFY_OPEN_PARMS_SRB 0x01
+#define OPEN_ADAPTER_SRB 0x03
+#define CLOSE_ADAPTER_SRB 0x04
+#define SET_GROUP_ADDRESS_SRB 0x06
+#define SET_FUNCTIONAL_ADDRESS_SRB 0x07
+#define READ_ERROR_LOG_SRB 0x08
+#define SET_BRIDGE_PARMS_SRB 0x09
+#define FMPLUS_SPECIFIC_SRB 0xC3
+
+#define SET_PROD_INST_ID_SUBCODE 4
+
+/****************************************************************************/
+/* */
+/* Values : SRB_HEADER - BYTE return_code */
+/* */
+/* These are defined in FTK_ERR.H */
+/* */
+
+
+/****************************************************************************/
+/* */
+/* Structure type : SRB_MODIFY_OPEN_PARMS */
+/* */
+/* This SRB is issued to modify the open options for an adapter. The */
+/* adapter can be in auto-open mode or have been opened by an SRB (see */
+/* below). */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface : Modify Open Parms SRB */
+/* */
+
+struct STRUCT_SRB_MODIFY_OPEN_PARMS
+ {
+ SRB_HEADER header;
+ WORD open_options;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : SRB_OPEN_ADAPTER */
+/* */
+/* This SRB is issued to open the adapter with the given node address and */
+/* functional and group addresses. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface : Open Adapter SRB */
+/* */
+
+struct STRUCT_SRB_OPEN_ADAPTER
+ {
+ SRB_HEADER header;
+ BYTE reserved_1[2];
+ WORD open_error; /* secondary error code */
+ WORD open_options; /* see USER.H for options */
+ NODE_ADDRESS open_address;
+ DWORD group_address;
+ DWORD functional_address;
+ WORD reserved_2;
+ WORD reserved_3;
+ WORD reserved_4;
+ BYTE reserved_5;
+ BYTE reserved_6;
+ BYTE reserved_7[10];
+ char product_id[SIZEOF_PRODUCT_ID]; /* network managers */
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : SRB_CLOSE_ADAPTER */
+/* */
+/* The SRB for closing the adapter consists of just an SRB header. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface : Close Adapter SRB */
+/* */
+
+struct STRUCT_SRB_CLOSE_ADAPTER
+ {
+ SRB_HEADER header;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure types : SRB_SET_GROUP_ADDRESS */
+/* SRB_SET_FUNCTIONAL_ADDRESS */
+/* */
+/* This structure is used for SRBs for setting both the functional and */
+/* group addresses of an adapter. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface : Set Group/Functional Address SRB */
+/* */
+
+struct STRUCT_SRB_SET_MULTICAST_ADDR
+ {
+ SRB_HEADER header;
+ WORD reserved;
+ MULTI_ADDRESS multi_address;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : SRB_READ_ERROR_LOG */
+/* */
+/* This SRB is used to get MAC error log counter information from the */
+/* adapter. The counters are reset to zero as they are read. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface : Read Error Log SRB */
+/* */
+
+struct STRUCT_SRB_READ_ERROR_LOG
+ {
+ SRB_HEADER header;
+ WORD reserved;
+ ERROR_LOG error_log; /* defined in FTK_USER.H */
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : SRB_SET_BRIDGE_PARMS */
+/* */
+/* This SRB is used to configure the TI Source Routing Accelerator (SRA) */
+/* ASIC. The adapter must be open for this SRB to work. */
+/* The order for the fields in the options word is : */
+/* Bit 15 (MSB) : single-route-broadcast */
+/* Bit 14 - 10 : reserved (all zero) */
+/* Bit 9 - 4 : maximum route length */
+/* Bit 3 - 0 : number of bridge bits */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface : Set Bridge Parms SRB */
+/* */
+
+struct STRUCT_SRB_SET_BRIDGE_PARMS
+ {
+ SRB_HEADER header;
+ WORD options;
+ UINT this_ring;
+ UINT that_ring;
+ UINT bridge_num;
+ };
+
+#define SRB_SBP_DFLT_BRIDGE_BITS 4
+#define SRB_SBP_DFLT_ROUTE_LEN 18
+
+
+struct STRUCT_SRB_SET_PROD_INST_ID
+ {
+ SRB_HEADER header;
+ WORD subcode;
+ BYTE product_id[SIZEOF_PRODUCT_ID];
+ };
+
+/****************************************************************************/
+/* */
+/* Structure type : SRB_GENERAL */
+/* */
+/* This SRB structure is a union of all the possible SRB structures used by */
+/* the FTK. Included in the union is an SRB header structure so that the */
+/* header of an SRB can be accessed without knowing the type of SRB. */
+/* */
+
+union UNION_SRB_GENERAL
+ {
+ SRB_HEADER header;
+ SRB_MODIFY_OPEN_PARMS mod_parms;
+ SRB_OPEN_ADAPTER open_adap;
+ SRB_CLOSE_ADAPTER close_adap;
+ SRB_SET_GROUP_ADDRESS set_group;
+ SRB_SET_FUNCTIONAL_ADDRESS set_func;
+ SRB_READ_ERROR_LOG err_log;
+ SRB_SET_BRIDGE_PARMS set_bridge_parms;
+ SRB_SET_PROD_INST_ID set_prod_inst_id;
+ };
+
+#pragma pack()
+
+
+/* */
+/* */
+/************** End of FTK_SRB.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_tab.h b/private/ntos/ndis/madge/driver/head_def/ftk_tab.h
new file mode 100644
index 000000000..89ff399f9
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_tab.h
@@ -0,0 +1,1054 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE ERROR TABLES DEFINITIONS */
+/* ============================ */
+/* */
+/* FTK_TAB.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1993 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains the definitions and local variable */
+/* declarations that are required by the error handling part of the FTK. It */
+/* includes the error message text for all the possible errors that can */
+/* occur. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_TAB.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_TAB_H 221
+
+#ifndef FTK_NO_ERROR_MESSAGES
+
+/****************************************************************************/
+/* */
+/* Variables : error_msg_headers_table */
+/* */
+/* The error_msg_headers_table contains the text of the error message */
+/* header for each type of error. This header is combined with the main */
+/* body of the error message to produce the full error text which is put in */
+/* the adapter structure of the adapter on which the error occurred. */
+/* */
+
+local char * error_msg_headers_table[] =
+
+{
+ "\n SRB error :"
+ "\n -----------",
+
+ "\n Open adapter error :"
+ "\n --------------------",
+
+ "\n Data transfer error :"
+ "\n ---------------------",
+
+ "\n Driver error :"
+ "\n --------------",
+
+ "\n HWI error :"
+ "\n -----------",
+
+ "\n Bring up error :"
+ "\n ----------------",
+
+ "\n Initialization error :"
+ "\n ----------------------",
+
+ "\n Auto-open adapter error :"
+ "\n -------------------------",
+
+ "\n Adapter check error :"
+ "\n ---------------------",
+
+ "\n PCMCIA Card Services error :"
+ "\n ----------------------------"
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : special error messages */
+/* */
+/* Some error messages have to have the full text, header and body, */
+/* together. These include those error messages that can be produced when */
+/* there is no valid adapter structure into which to put the full message. */
+/* This is the case for drv_err_msg_1 and drv_err_msg_2. */
+/* */
+
+local char drv_err_msg_1[] =
+
+ "\n Driver error :"
+ "\n --------------"
+ "\n The adapter handle being used is invalid. It"
+ "\n has been corrupted by the user of the FTK.";
+
+local char drv_err_msg_2[] =
+
+ "\n Driver error :"
+ "\n --------------"
+ "\n Either the adapter handle is invalid or memory"
+ "\n for an adapter structure has not successfully"
+ "\n been allocated by a call to the system routine"
+ "\n sys_alloc_adapter_structure.";
+
+
+/****************************************************************************/
+/* */
+/* Value : Default marker */
+/* */
+/* Each table of error message texts, for a particular error type, needs a */
+/* final marker in case an unknown error value is encountered. This should */
+/* not occur within the FTK, but it may be that extra error values are */
+/* added by users incorrectly. */
+/* */
+
+
+#define ERR_MSG_UNKNOWN_END_MARKER 0xFF
+
+
+/****************************************************************************/
+/* */
+/* Variables : srb_error_msg_table */
+/* */
+/* The srb_error_msg_table contains the error message body texts for SRB */
+/* error type messages. These texts are combined with the error type header */
+/* messages to produce the full error message. */
+/* */
+
+
+local ERROR_MESSAGE_RECORD srb_error_msg_table[] =
+
+{
+ {
+ SRB_E_03_ADAPTER_OPEN,
+ "\n The adapter is open and should be closed for"
+ "\n the previous SRB to complete successfully."
+ },
+
+ {
+ SRB_E_04_ADAPTER_CLOSED,
+ "\n The adapter is closed and should be open for"
+ "\n the previous SRB to complete successfully."
+ },
+
+ {
+ SRB_E_06_INVALID_OPTIONS,
+ "\n The parameters used to configure the bridge are"
+ "\n invalid in some way."
+ },
+
+ {
+ SRB_E_07_CMD_CANCELLED_FAIL,
+ "\n The previous SRB command has been cancelled"
+ "\n because of an unrecoverable error when"
+ "\n attempting to complete it. A field in the SRB"
+ "\n is probably invalid."
+ },
+
+ {
+ SRB_E_32_INVALID_NODE_ADDRESS,
+ "\n The node address field in the previous SRB is"
+ "\n invalid. Either the BIA PROM on the card is"
+ "\n faulty or the user has supplied an invalid node"
+ "\n address to the appropriate driver routine."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : open_error_msg_table */
+/* */
+/* The open_error_msg_table contains the error message body texts for open */
+/* error type messages. These texts are combined with the error type header */
+/* messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD open_error_msg_table[] =
+
+{
+ {
+ OPEN_E_01_OPEN_ERROR,
+ "\n The adapter has failed to open onto the ring."
+ "\n This could be caused by one of the following -"
+ "\n"
+ "\n i) the lobe cable is not securely"
+ "\n attached to the adapter card or cabling"
+ "\n unit."
+ "\n"
+ "\n ii) the ring speed setting on the card"
+ "\n does not match the actual ring speed."
+ "\n"
+ "\n iii) insertion onto the ring has been"
+ "\n prevented by ring management software."
+ "\n"
+ "\n iv) the ring is beaconing."
+ "\n"
+ "\n v) there is a crashed ring parameter"
+ "\n server on the ring."
+ "\n"
+ "\n Check the above and then retry the operation."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : data_xfer_error_msg_table */
+/* */
+/* The data_xfer_error_msg_table contains the error message body texts for */
+/* data transfer error type messages. These texts are combined with the */
+/* error type header messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD data_xfer_error_msg_table[] =
+
+{
+ {
+ DATA_XFER_E_01_BUFFER_FULL,
+ "\n The Fastmac transmit buffer is full. This is"
+ "\n probably because it can be filled by the host"
+ "\n quicker than the adapter can put the frames"
+ "\n onto the ring. However, it could be because the"
+ "\n adapter has closed. Hence, check the ring"
+ "\n status if this error persists."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : driver_error_msg_table */
+/* */
+/* The driver_error_msg_table contains the error message body texts for */
+/* driver error type messages. These texts are combined with the error type */
+/* header messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD driver_error_msg_table[] =
+
+{
+ {
+ DRIVER_E_03_FAIL_ALLOC_STATUS,
+ "\n Memory for a status information structure has"
+ "\n not successfully been allocated by a call to"
+ "\n the system routine sys_alloc_status_structure."
+ },
+
+ {
+ DRIVER_E_04_FAIL_ALLOC_INIT,
+ "\n Memory for an initialization block has not"
+ "\n successfully been allocated by a call to the"
+ "\n system routine sys_alloc_init_block."
+ },
+
+ {
+ DRIVER_E_05_FAIL_ALLOC_RX_BUF,
+ "\n Memory for a Fastmac receive buffer has not"
+ "\n successfully been allocated by a call to the"
+ "\n system routine sys_alloc_receive_buffer."
+ },
+
+ {
+ DRIVER_E_06_FAIL_ALLOC_TX_BUF,
+ "\n Memory for a Fastmac transmit buffer has not"
+ "\n successfully been allocated by a call to the"
+ "\n system routine sys_alloc_transmit_buffer."
+ },
+
+ {
+ DRIVER_E_07_NOT_PREPARED,
+ "\n A call to driver_start_adapter has been made"
+ "\n without first calling driver_prepare_adapter."
+ },
+
+ {
+ DRIVER_E_08_NOT_RUNNING,
+ "\n A driver routine has been called without first"
+ "\n getting the adapter up an running (by first"
+ "\n calling driver_prepare_adapter and then calling"
+ "\n driver_start_adapter)."
+ },
+
+ {
+ DRIVER_E_09_SRB_NOT_FREE,
+ "\n The SRB for the adapter is not free and hence"
+ "\n the previously called driver routine can not"
+ "\n execute since it uses the SRB. After calling a"
+ "\n driver routine that uses the SRB, wait for the"
+ "\n user_completed_srb routine to be called before"
+ "\n calling such a driver routine again."
+ },
+
+ {
+ DRIVER_E_0A_RX_BUF_BAD_SIZE,
+ "\n The size of the Fastmac receive buffer is"
+ "\n either too big or too small. The maximum"
+ "\n allowable size is 0xFF00. The minimum allowable"
+ "\n size is 0x0404 which allows the buffer to hold"
+ "\n a single 1K frame."
+ },
+
+ {
+ DRIVER_E_0B_RX_BUF_NOT_DWORD,
+ "\n The physical address of the Fastmac receive"
+ "\n buffer must be on a DWORD boundary ie. the"
+ "\n bottom 2 bits of the address must be zero."
+ },
+
+ {
+ DRIVER_E_0C_TX_BUF_BAD_SIZE,
+ "\n The size of the Fastmac transmit buffer is"
+ "\n either too big or too small. The maximum"
+ "\n allowable size is 0xFF00. The minimum allowable"
+ "\n size is 0x0404 which allows the buffer to hold"
+ "\n a single 1K frame."
+ },
+
+ {
+ DRIVER_E_0D_TX_BUF_NOT_DWORD,
+ "\n The physical address of the Fastmac transmit"
+ "\n buffer must be on a DWORD boundary ie. the"
+ "\n bottom 2 bits of the address must be zero."
+ },
+
+ {
+ DRIVER_E_0E_BAD_RX_METHOD,
+ "\n The receive method value that has been supplied"
+ "\n to driver_prepare_adapter is invalid. A choice"
+ "\n of two values is possible; either"
+ "\n RX_OUT_OF_INTERRUPTS or RX_BY_SCHEDULED_PROCESS"
+ "\n is allowed."
+ },
+
+ {
+ DRIVER_E_0F_WRONG_RX_METHOD,
+ "\n The driver_get_outstanding_receive routine can"
+ "\n only be called if the receive method chosen is"
+ "\n RX_BY_SCHEDULED_PROCESS."
+ },
+
+ {
+ DRIVER_E_10_BAD_RX_SLOT_NUMBER,
+ "\n The number of receive slots requested from the"
+ "\n driver_prepare_adapter routine must lie within"
+ "\n the limits set in the FastMac Plus programming"
+ "\n specification (currently from 4 to 32)."
+ },
+
+ {
+ DRIVER_E_11_BAD_TX_SLOT_NUMBER,
+ "\n The number of transmit slots requested from"
+ "\n the driver_prepare_adapter routine must lie"
+ "\n within the limits set in the FastMac Plus pro-"
+ "\n gramming specification (currently 4 to 32)."
+ },
+
+ {
+ DRIVER_E_12_FAIL_ALLOC_DMA_BUF,
+ "\n Memory for a dma buffer has not successfully"
+ "\n been allocated by a call to the system routine"
+ "\n sys_alloc_dma_phys_buf."
+ },
+
+ {
+ DRIVER_E_13_BAD_FRAME_SIZE,
+ "\n The frame size specified is out of range."
+ "\n Please choose a smaller value."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : hwi_error_msg_table */
+/* */
+/* The hwi_error_msg_table contains the error message body texts for hwi */
+/* error type messages. These texts are combined with the error type header */
+/* messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD hwi_error_msg_table[] =
+
+{
+ {
+ HWI_E_01_BAD_CARD_BUS_TYPE,
+ "\n The adapter card bus type given is invalid. It"
+ "\n does not correspond to a valid Madge adapter"
+ "\n card bus type."
+ },
+
+ {
+ HWI_E_02_BAD_IO_LOCATION,
+ "\n The IO location given is not valid for the"
+ "\n adapter card being used."
+ },
+
+ {
+ HWI_E_03_BAD_INTERRUPT_NUMBER,
+ "\n The interrupt number given is not valid for the"
+ "\n adapter card being used."
+ },
+
+ {
+ HWI_E_04_BAD_DMA_CHANNEL,
+ "\n The DMA channel given is not valid for the"
+ "\n adapter card being used. Alternatively, a DMA"
+ "\n channel has been specified and the card is"
+ "\n configured for PIO mode. Note 16/4 PC cards do"
+ "\n not support DMA, and that EISA and MC cards do"
+ "\n not support PIO."
+ },
+
+ {
+ HWI_E_05_ADAPTER_NOT_FOUND,
+ "\n An adapter card of the given bus type has not"
+ "\n been found at the IO location specified. Check"
+ "\n that the adapter details are correct and that"
+ "\n the adapter card has been correctly installed"
+ "\n in the machine."
+ },
+
+ {
+ HWI_E_06_CANNOT_USE_DMA,
+ "\n It is not possible to use DMA when an adapter"
+ "\n card is in an 8-bit slot. Either select PIO"
+ "\n data transfer mode or put the adapter card in a"
+ "\n 16-bit slot. Note 16/4 PC cards do not support"
+ "\n DMA."
+ },
+
+ {
+ HWI_E_07_FAILED_TEST_DMA,
+ "\n The test DMAs that take place as part of the"
+ "\n adapter initialization have failed. The address"
+ "\n for the DMAs is probably not downloaded to the"
+ "\n adapter card correctly due to the byte ordering"
+ "\n of the host machine."
+ },
+
+ {
+ HWI_E_08_BAD_DOWNLOAD,
+ "\n Downloading the Fastmac binary image has"
+ "\n failed. When reading the downloaded data back"
+ "\n from the adapter, it does not equal the data"
+ "\n that was downloaded. There is probably a fault"
+ "\n with the adapter card - use a diagnostics"
+ "\n program to check it more thoroughly."
+ },
+
+ {
+ HWI_E_09_BAD_DOWNLOAD_IMAGE,
+ "\n The format of the Fastmac binary image that is"
+ "\n being downloaded is invalid. Check that the"
+ "\n data has not been corrupted and that the"
+ "\n pointer to the Fastmac download code (supplied"
+ "\n to driver_prepare_adapter) is correct."
+ },
+
+ {
+ HWI_E_0A_NO_DOWNLOAD_IMAGE,
+ "\n No download image has been provided. The"
+ "\n pointer to the Fastmac binary image supplied to"
+ "\n driver_prepare_adapter is NULL and hence"
+ "\n invalid."
+ },
+
+ {
+ HWI_E_0B_FAIL_IRQ_ENABLE,
+ "\n The required interrupt channel has not been"
+ "\n successfully enabled by a call to the system"
+ "\n routine sys_enable_irq_channel."
+ },
+
+ {
+ HWI_E_0C_FAIL_DMA_ENABLE,
+ "\n The required DMA channel has not been"
+ "\n successfully enabled by a call to the system"
+ "\n routine sys_enable_dma_channel."
+ },
+
+ {
+ HWI_E_0D_CARD_NOT_ENABLED,
+ "\n The card has not been enabled. Both EISA and MC"
+ "\n cards must be properly configured before use."
+ "\n Use the configuration utility provided with"
+ "\n your computer."
+ },
+
+ {
+ HWI_E_0E_NO_SPEED_SELECTED,
+ "\n A speed (16Mb/s or 4Mb/s) has not been selected"
+ "\n for the adapter card. Both EISA and MC cards"
+ "\n must be configured for a particular ring speed"
+ "\n before use. Use the configuration utility"
+ "\n provided with your computer."
+ },
+
+ {
+ HWI_E_0F_BAD_FASTMAC_INIT,
+ "\n The initialization of Fastmac has not completed"
+ "\n successfully. The node address field in the"
+ "\n Fastmac status block is not a Madge node"
+ "\n address. Either an attempt has been made to use"
+ "\n the FTK with a non-Madge card or there is a"
+ "\n problem with the adapter. Use a diagnostics"
+ "\n program to check the adapter card more"
+ "\n thoroughly."
+ },
+
+ {
+ HWI_E_10_BAD_TX_RX_BUFF_SIZE,
+ "\n The size of the buffers used by the code on the"
+ "\n adapter must exceed the minimum value specified"
+ "\n in the FastMac Plus programming specification,"
+ "\n which is currently 96 bytes."
+ },
+
+ {
+ HWI_E_11_TOO_MANY_TX_RX_BUFFS,
+ "\n There is not enough memory on the adapter to"
+ "\n accommodate the number of transmit and receive"
+ "\n buffers requested. Try reducing the number of"
+ "\n transmit slots requested, or reducing the allo-"
+ "\n cation of buffers to large frame transmits in"
+ "\n hwi_initialise_adapter."
+ },
+
+ {
+ HWI_E_12_BAD_SCB_ALLOC,
+ "\n Failed to allocate a block of memory suitable"
+ "\n for the DMA test into the SCB. This is a system"
+ "\n memory allocation failure, arising in the func-"
+ "\n tion sys_alloc_dma_buffer."
+ },
+
+ {
+ HWI_E_13_BAD_SSB_ALLOC,
+ "\n Failed to allocate a block of memory suitable"
+ "\n for the DMA test into the SSB. This is a system"
+ "\n memory allocation failure, arising in the func-"
+ "\n tion sys_alloc_dma_buffer."
+ },
+
+ {
+ HWI_E_14_BAD_PCI_MACHINE,
+ "\n This machine is either not a 386 (or higher) or"
+ "\n there is a problem with the PCI BIOS."
+ },
+
+ {
+ HWI_E_15_BAD_PCI_MEMORY,
+ "\n The PCI BIOS has failed to allocate any memory"
+ "\n to do memory mapped IO."
+ },
+
+ {
+ HWI_E_16_PCI_3BYTE_PROBLEM,
+ "\n Internal error &3800"
+ },
+
+ {
+ HWI_E_17_BAD_TRANSFER_MODE,
+ "\n The transfer mode specified is not supported by"
+ "\n this card."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : bring_up_error_msg_table */
+/* */
+/* The bring_up_error_msg_table contains the error message body texts for */
+/* bring up error type messages. These texts are combined with the error */
+/* type header messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD bring_up_error_msg_table[] =
+
+{
+ {
+ BRING_UP_E_00_INITIAL_TEST,
+ "\n The bring up diagnostics failed with an initial"
+ "\n test error. This is an unrecoverable hardware"
+ "\n error. There is probably a fault with the"
+ "\n adapter card - use a diagnostics program to"
+ "\n check it more thoroughly."
+ },
+
+ {
+ BRING_UP_E_01_SOFTWARE_CHECKSUM,
+ "\n The bring up diagnostics failed with an adapter"
+ "\n software checksum error. This is an"
+ "\n unrecoverable hardware error. There is probably"
+ "\n a fault with the adapter card - use a"
+ "\n diagnostics program to check it more"
+ "\n thoroughly."
+ },
+
+ {
+ BRING_UP_E_02_ADAPTER_RAM,
+ "\n The bring up diagnostics failed with an adapter"
+ "\n RAM error when checking the first 128Kbytes."
+ "\n This is an unrecoverable hardware error. There"
+ "\n is probably a fault with the adapter card - use"
+ "\n a diagnostics program to check it more"
+ "\n thoroughly."
+ },
+
+ {
+ BRING_UP_E_03_INSTRUCTION_TEST,
+ "\n The bring up diagonstics failed with an"
+ "\n instruction test error. This is an"
+ "\n unrecoverable hardware error. There is probably"
+ "\n a fault with the adapter card - use a"
+ "\n diagnostics program to check it more"
+ "\n thoroughly."
+ },
+
+ {
+ BRING_UP_E_04_INTERRUPT_TEST,
+ "\n The bring up diagonstics failed with a context"
+ "\n / interrupt test error. This is an"
+ "\n unrecoverable hardware error. There is probably"
+ "\n a fault with the adapter card - use a"
+ "\n diagnostics program to check it more"
+ "\n thoroughly."
+ },
+
+ {
+ BRING_UP_E_05_FRONT_END,
+ "\n The bring up diagonstics failed with a protocol"
+ "\n handler / ring interface hardware error. This"
+ "\n is an unrecoverable hardware error. There is"
+ "\n probably a fault with the adapter card - use a"
+ "\n diagnostics program to check it more"
+ "\n thoroughly."
+ },
+
+ {
+ BRING_UP_E_06_SIF_REGISTERS,
+ "\n The bring up diagonstics failed with a system"
+ "\n interface register error. This is an"
+ "\n unrecoverable hardware error. There is probably"
+ "\n a fault with the adapter card - use a"
+ "\n diagnostics program to check it more"
+ "\n thoroughly."
+ },
+
+ {
+ BRING_UP_E_10_TIME_OUT,
+ "\n The adapter failed to complete the bring up"
+ "\n diagnostics within the time out period. Check"
+ "\n that the system provided timer routines are"
+ "\n working correctly. Alternatively, there may be"
+ "\n a fault with the adapter card - use a"
+ "\n diagnostics program to check it more"
+ "\n thoroughly."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : init_error_msg_table */
+/* */
+/* The init_error_msg_table contains the error message body texts for init */
+/* error type messages. These texts are combined with the error type header */
+/* messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD init_error_msg_table[] =
+
+{
+ {
+ INIT_E_01_INIT_BLOCK,
+ "\n Adapter initialization has failed because the"
+ "\n TI initialization block has not been correctly"
+ "\n downloaded. There is probably a fault with the"
+ "\n adapter card - use a diagnostics program to"
+ "\n check it more thoroughly."
+ },
+
+ {
+ INIT_E_02_INIT_OPTIONS,
+ "\n Adapter initialization has failed because of"
+ "\n invalid options in the TI part of the"
+ "\n initialization block. This field is set"
+ "\n correctly by the FTK and should not be changed"
+ "\n elsewhere. One possible reason for this error"
+ "\n is if the structures used by the FTK are not"
+ "\n byte packed."
+ },
+
+ {
+ INIT_E_03_RX_BURST_SIZE,
+ "\n Adapter initialization has failed because of an"
+ "\n odd receive burst size being set in the TI part"
+ "\n of the initialization block. This field is set"
+ "\n correctly by the FTK and should not be changed"
+ "\n elsewhere. One possible reason for this error"
+ "\n is if the structures used by the FTK are not"
+ "\n byte packed."
+ },
+
+ {
+ INIT_E_04_TX_BURST_SIZE,
+ "\n Adapter initialization has failed because of an"
+ "\n odd transmit burst size being set in the TI"
+ "\n part of the initialization block. This field is"
+ "\n set correctly by the FTK and should not be"
+ "\n changed elsewhere. One possible reason for"
+ "\n this error is if the structures used by the FTK"
+ "\n are not byte packed."
+ },
+
+ {
+ INIT_E_05_DMA_THRESHOLD,
+ "\n Adapter initialization has failed because of an"
+ "\n invalid DMA abort threshold being set in the TI"
+ "\n part of the initialization block. This field is"
+ "\n set correctly by the FTK and should not be"
+ "\n changed elsewhere. One possible reason for"
+ "\n this error is if the structures used by the FTK"
+ "\n are not byte packed."
+ },
+
+ {
+ INIT_E_06_ODD_SCB_ADDRESS,
+ "\n Adapter initialization has failed because of an"
+ "\n odd SCB address being set in the TI part of the"
+ "\n initialization block. This field is set"
+ "\n correctly by the FTK and should not be changed"
+ "\n elsewhere. One possible reason for this error"
+ "\n is if the structures used by the FTK are not"
+ "\n byte packed."
+ },
+
+ {
+ INIT_E_07_ODD_SSB_ADDRESS,
+ "\n Adapter initialization has failed because of an"
+ "\n odd SSB address being set in the TI part of the"
+ "\n initialization block. This field is set"
+ "\n correctly by the FTK and should not be changed"
+ "\n elsewhere. One possible reason for this error"
+ "\n is if the structures used by the FTK are not"
+ "\n byte packed."
+ },
+
+ {
+ INIT_E_08_DIO_PARITY,
+ "\n Adapter initialization has failed because a"
+ "\n parity error occurred during a DIO write"
+ "\n operation. There is probably a fault with the"
+ "\n adapter card - use a diagnostics program to"
+ "\n check it more thoroughly."
+ },
+
+ {
+ INIT_E_09_DMA_TIMEOUT,
+ "\n Adapter initialization has failed because of a"
+ "\n DMA timeout error. The adapter timed out"
+ "\n waiting for a test DMA transfer to complete. If"
+ "\n PIO data transfer mode is being used then the"
+ "\n fault probably lies in the system routines"
+ "\n called by the PIO code."
+ },
+
+ {
+ INIT_E_0A_DMA_PARITY,
+ "\n Adapter initialization has failed because of a"
+ "\n DMA parity error. There is probably a fault"
+ "\n with the adapter card - use a diagnostics"
+ "\n program to check it more thoroughly."
+ },
+
+ {
+ INIT_E_0B_DMA_BUS,
+ "\n Adapter initialization has failed because of a"
+ "\n DMA bus error. There is probably a fault with"
+ "\n the adapter card - use a diagnostics program to"
+ "\n check it more thoroughly."
+ },
+
+ {
+ INIT_E_0C_DMA_DATA,
+ "\n Adapter initialization has failed because of a"
+ "\n DMA data error. On completing a test DMA,"
+ "\n comparing the final data to the initial data"
+ "\n showed an error. If PIO data transfer mode is"
+ "\n being used then the fault probably lies in the"
+ "\n system routines called by the PIO code."
+ },
+
+ {
+ INIT_E_0D_ADAPTER_CHECK,
+ "\n Adapter initialization has failed because of an"
+ "\n adapter check. An unrecoverable hardware error"
+ "\n occurred on the adapter. There is probably a"
+ "\n fault with the adapter card - use a diagnostics"
+ "\n program to check it more thoroughly."
+ },
+
+ {
+ INIT_E_0E_NOT_ENOUGH_MEMORY,
+ "\n Adapter initialization failed because there was"
+ "\n insufficient memory for the number of transmit"
+ "\n and receive buffers requested. Reduce either"
+ "\n the buffer allocation or the number of transmit"
+ "\n slots."
+ },
+
+ {
+ INIT_E_10_TIME_OUT,
+ "\n The adapter failed to complete initialization"
+ "\n within the time out period. Check that the"
+ "\n system provided timer routines are working"
+ "\n correctly. Another possible reason for this"
+ "\n error is if the structures used by the FTK are"
+ "\n not byte packed. Alternatively, there may be a"
+ "\n fault with the adapter card - use a diagnostics"
+ "\n program to check it more thoroughly."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : auto_open_error_msg_table */
+/* */
+/* The auto_open_error_msg_table contains the error message body texts for */
+/* auto open error type messages. These texts are combined with the error */
+/* type header messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD auto_open_error_msg_table[] =
+
+{
+ {
+ AUTO_OPEN_E_01_OPEN_ERROR,
+ "\n The adapter has failed to open onto the ring."
+ "\n This could be caused by one of the following -"
+ "\n"
+ "\n i) the lobe cable is not securely"
+ "\n attached to the adapter card or cabling"
+ "\n unit."
+ "\n"
+ "\n ii) insertion onto the ring has been"
+ "\n prevented by ring management software."
+ "\n"
+ "\n iii) there is a crashed ring parameter"
+ "\n server on the ring."
+ "\n"
+ "\n Check the above before retrying the operation."
+ },
+
+ {
+ AUTO_OPEN_E_80_TIME_OUT,
+ "\n The adapter has failed to open within a"
+ "\n substantial time out period (greater than 30"
+ "\n seconds). There is probably a fault with the"
+ "\n adapter card - use a diagnostics program to"
+ "\n check it more thoroughly."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : adapter_error_msg_table */
+/* */
+/* The adapter_error_msg_table contains the error message body texts for */
+/* adapter check error type messages. These texts are combined with the */
+/* error type header messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD adapter_error_msg_table[] =
+
+{
+ {
+ ADAPTER_E_01_ADAPTER_CHECK,
+ "\n An adapter check interrupt has occurred. An"
+ "\n unrecoverable hardware error has caused the"
+ "\n adapter to become inoperable. There is probably"
+ "\n a fault with the adapter card - use a"
+ "\n diagnostics program to check it more"
+ "\n thoroughly."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+/****************************************************************************/
+/* */
+/* Variables : pcmcia_cs_error_msg_table */
+/* */
+/* The pcmcia_cs_error_msg_table contains the error message body texts for */
+/* PCMCIA Card Services error type messages. These texts are combined with */
+/* the error type header messages to produce the full error message. */
+/* */
+
+local ERROR_MESSAGE_RECORD pcmcia_cs_error_msg_table[] =
+
+{
+ {
+ CS_E_01_NO_CARD_SERVICES,
+ "\n No PCMCIA Card Services installed. Madge Smart"
+ "\n 16/4 PCMCIA ringnode driver requires PCMCIA"
+ "\n Card Services. You can use Card Services which"
+ "\n come with your computer or Madge Card Services."
+ },
+
+ {
+ CS_E_02_REGISTER_CLIENT_FAILED,
+ "\n Failed to register with PCMCIA Card Services."
+ "\n Check that PCMCIA Card Services is properly"
+ "\n installed. Make sure there is no crashing of"
+ "\n memory usage with other TSR or memory manager."
+ },
+
+ {
+ CS_E_03_REGISTRATION_TIMEOUT,
+ "\n PCMCIA Card Services failed to response in time"
+ "\n Check that PCMCIA Card Services is properly"
+ "\n installed. Make sure there is no crashing of"
+ "\n memory usage with other TSR or memory manager."
+ },
+
+ {
+ CS_E_04_NO_MADGE_ADAPTER_FOUND,
+ "\n No Madge Smart 16/4 PCMCIA Ringnode found."
+ },
+
+ {
+ CS_E_05_ADAPTER_NOT_FOUND,
+ "\n Cannot find a Madge Smart 16/4 PCMCIA Ringnode"
+ "\n in the PCMCIA Socket specified. Check if the"
+ "\n adapter is properly fitted."
+ },
+
+ {
+ CS_E_06_SPECIFIED_SOCKET_IN_USE,
+ "\n The adapter in the PCMCIA socket specified is"
+ "\n in use."
+ },
+
+ {
+ CS_E_07_IO_REQUEST_FAILED,
+ "\n PCMCIA Card Services refused the request for IO"
+ "\n resource. The IO location specified is being"
+ "\n used by other devices."
+ },
+
+ {
+ CS_E_08_BAD_IRQ_CHANNEL,
+ "\n The interrupt number specified is not"
+ "\n supported."
+ },
+
+ {
+ CS_E_09_IRQ_REQUEST_FAILED,
+ "\n PCMCIA Card Services refused the request for"
+ "\n interupt channel resources. The interrupt"
+ "\n number specified is being used by other devices"
+ },
+
+ {
+ CS_E_0A_REQUEST_CONFIG_FAILED,
+ "\n PCMCIA Card Services refused the request for"
+ "\n resources."
+ },
+
+ {
+ ERR_MSG_UNKNOWN_END_MARKER,
+ "\n An unknown error has occurred."
+ }
+};
+
+
+/****************************************************************************/
+/* */
+/* Variables : list_of_error_msg_tables */
+/* */
+/* The list_of_error_msg_tables contains a list of pointers to the */
+/* different tables of error message body texts (one table per error type). */
+/* This variable is used to access the correct table for the error type */
+/* that has occurred. */
+/* */
+
+
+local ERROR_MESSAGE_RECORD * list_of_error_msg_tables[] =
+
+{
+ srb_error_msg_table ,
+ open_error_msg_table ,
+ data_xfer_error_msg_table ,
+ driver_error_msg_table ,
+ hwi_error_msg_table ,
+ bring_up_error_msg_table ,
+ init_error_msg_table ,
+ auto_open_error_msg_table ,
+ adapter_error_msg_table ,
+ pcmcia_cs_error_msg_table
+};
+
+#endif
+
+/* */
+/* */
+/************** End of FTK_TAB.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_def/ftk_user.h b/private/ntos/ndis/madge/driver/head_def/ftk_user.h
new file mode 100644
index 000000000..09f85c8b5
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_def/ftk_user.h
@@ -0,0 +1,666 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE USER DEFINITIONS */
+/* ==================== */
+/* */
+/* FTK_USER.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains ALL the definitions and structures required by */
+/* any user of the FTK driver. Any user of the FTK need only include this */
+/* definitions header file in order to use the FTK. */
+/* */
+/* IMPORTANT : Some structures used within the FTK need to be packed in */
+/* order to work correctly. This means sizeof(STRUCTURE) will give the real */
+/* size in bytes, and if a structure contains sub-structures there will be */
+/* no spaces between the sub-structures. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this FTK_USER.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_FTK_USER_H 221
+
+
+/****************************************************************************/
+/* */
+/* TYPEDEFs for all structures defined within this header file : */
+/* */
+
+typedef struct STRUCT_NODE_ADDRESS NODE_ADDRESS;
+typedef union UNION_MULTI_ADDRESS MULTI_ADDRESS;
+typedef struct STRUCT_STATUS_INFORMATION STATUS_INFORMATION;
+typedef struct STRUCT_ERROR_LOG ERROR_LOG;
+typedef struct STRUCT_PROBE PROBE;
+typedef struct STRUCT_PREPARE_ARGS PREPARE_ARGS, *PPREPARE_ARGS;
+typedef struct STRUCT_START_ARGS START_ARGS, *PSTART_ARGS;
+typedef struct STRUCT_TR_OPEN_DATA TR_OPEN_DATA, *PTR_OPEN_DATA;
+
+
+/****************************************************************************/
+/* */
+/* Function declarations */
+/* */
+/* Routines in the FTK are either local to a module, or they are exported. */
+/* Exported routines are entry points to the user of a module and the */
+/* routine has an 'extern' definition in an appropriate header file (see */
+/* FTK_INTR.H and FTK_EXTR.H). A user of the FTK may wish to follow this */
+/* method of function declarations using the following definitions. */
+/* */
+
+#define local static
+#define export
+
+
+/****************************************************************************/
+/* */
+/* Basic types : BYTE, WORD, DWORD and BOOLEAN */
+/* */
+/* The basic types used throughout the FTK, and for passing parameters to */
+/* it, are BYTE (8 bit unsigned), WORD (16 bit unsigned), DWORD (32 bit */
+/* unsigned) and BOOLEAN (16 bit unsigned). A BOOLEAN variable should take */
+/* the value TRUE or FALSE. */
+/* */
+/* Note that none of the FTK code makes an explicit check for the value */
+/* TRUE (it only checks for FALSE which must be zero) and hence TRUE can */
+/* have any non-zero value. */
+/* */
+
+typedef unsigned char BYTE; /* 8 bits */
+
+typedef unsigned short int WORD; /* 16 bits */
+
+typedef unsigned long int DWORD; /* 32 bits */
+
+typedef unsigned long int ULONG;
+
+typedef WORD WBOOLEAN;
+
+typedef unsigned int UINT;
+
+#define VOID void
+
+#define FALSE 0
+#define TRUE 1
+
+#if !defined(max)
+#define max(a,b) ((a) < (b) ? (b) : (a))
+#endif
+
+#if !defined(min)
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+#ifdef FMPLUS
+
+/****************************************************************************/
+/* */
+/* Variables : Fmplus download image */
+/* */
+/* The following variables are exported by FMPLUS.C which contains the */
+/* binary image for FastmacPlus in a 'C' format BYTE array. These variables */
+/* will be needed by a user of the FTK in order to download Fastmac */
+/* Plus (fmplus_image), display the Fastmac Plus version number and */
+/* copyright message (fmplus_version and fmplus_copyright_msg) and check */
+/* that the FTK version number is that required by Fastmac */
+/* (ftk_version_for_fmplus). The variables concerned with the size of the */
+/* Fastmac Plus binary (sizeof_fmplus_array and recorded_size_fmplus_array) */
+/* can be used to check for corruption of the Fasmtac image array. The */
+/* checksum byte (fmplus_checksum) can also be used for this purpose. */
+/* */
+
+extern BYTE fmplus_image[];
+
+extern char fmplus_version[];
+
+extern char fmplus_copyright_msg[];
+
+extern WORD ftk_version_for_fmplus;
+
+extern WORD sizeof_fmplus_array;
+
+extern WORD recorded_size_fmplus_array;
+
+extern BYTE fmplus_checksum;
+
+#else
+
+/****************************************************************************/
+/* */
+/* Variables : Fastmac download image */
+/* */
+/* The following variables are exported by FASTMAC.C which contains the */
+/* binary image for Fastmac in a 'C' format BYTE array. These variables */
+/* will be needed by a user of the FTK in order to download Fastmac */
+/* (fastmac_image), display the Fastmac version number and copyright */
+/* message (fastmac_version and fastmac_copyright_msg) and check that the */
+/* FTK version number is that required by Fastmac */
+/* (ftk_version_for_fastmac). The variables concerned with the size of the */
+/* Fastmac binary (sizeof_fastmac_array and recorded_size_fastmac_array) */
+/* can be used to check for corruption of the Fasmtac image array. The */
+/* checksum byte (fastmac_checksum) can also be used for this purpose. */
+/* */
+
+extern BYTE fastmac_image[];
+
+extern WORD fastmac_version;
+
+extern char fastmac_copyright_msg[];
+
+extern WORD ftk_version_for_fastmac;
+
+extern WORD sizeof_fastmac_array;
+
+extern WORD recorded_size_fastmac_array;
+
+extern BYTE fastmac_checksum;
+
+#endif
+
+/****************************************************************************/
+/* */
+/* Values : Pointers */
+/* */
+/* For a near pointer, (one that points to a location in DGROUP), the value */
+/* NULL (must equal 0) is used to specify that it is yet to be assigned or */
+/* an attempt to assign to it was unsuccessful. For example, an attempt to */
+/* allocate memory via a system specific call to which a near pointer is to */
+/* point, eg. sys_alloc_init_block, should return NULL if unsuccessful. */
+/* Similarly, when a DWORD is used as a pointer to a 32 bit physical */
+/* address pointer, the value NULL_PHYSADDR (must equal 0L) is used. It */
+/* should be returned by sys_alloc fastmac buffer routines if unsuccessful. */
+/* */
+
+#if !defined(NULL)
+#define NULL 0
+#endif
+
+#define NULL_PHYSADDR 0L
+
+
+/****************************************************************************/
+/* */
+/* Type : ADAPTER_HANDLE */
+/* */
+/* An element of this type is returned by driver_prepare_adapter in order */
+/* to identify a particular adapter for all subsequent calls to the driver */
+/* module of the FTK. */
+/* */
+
+typedef WORD ADAPTER_HANDLE;
+
+
+/****************************************************************************/
+/* */
+/* Type : DOWNLOAD_IMAGE */
+/* */
+/* A pointer to a download image must be supplied by the user to */
+/* driver_prepare_adapter. This download image should be Fastmac. */
+/* */
+
+typedef BYTE DOWNLOAD_IMAGE;
+
+
+/****************************************************************************/
+/* */
+/* The following structures represent data strcutures on the adapter and */
+/* must be byte packed. */
+/* */
+
+#pragma pack(1)
+
+
+/****************************************************************************/
+/* */
+/* Structure type : NODE_ADDRESS */
+/* */
+/* A node address may be supplied by the user to driver_prepare_adapter or */
+/* driver_open_adapter. The permanent node address of the adapter is */
+/* returned by driver_start_adapter. A node address is a 6 byte value. For */
+/* Madge adapters the bytes would be 0x00, 0x00, 0xF6, ... etc. */
+/* */
+
+struct STRUCT_NODE_ADDRESS
+ {
+ BYTE byte[6];
+ };
+
+
+/****************************************************************************/
+/* */
+/* Union type : MULTI_ADDRESS */
+/* */
+/* A multicast address may be supplied by the user to */
+/* driver_set_group_address or driver_set_functional_address. The */
+/* multicast address is the final 4 bytes of a 6 byte node address. The */
+/* first 2 bytes are determined by whether it is a group address or a */
+/* functional address. */
+/* */
+
+union UNION_MULTI_ADDRESS
+ {
+ DWORD all;
+ BYTE byte[4];
+ };
+
+
+/****************************************************************************/
+/* */
+/* Type : LONG_ADDRESS */
+/* */
+/* A LONG_ADDRESS is a 64 bit address. Some architectures (e.g. Alpha) use */
+/* 64 bit physical addresses. */
+/* */
+
+union STRUCT_LONG_ADDRESS
+ {
+ BYTE bytes[8];
+ WORD words[4];
+ DWORD dwords[2];
+ };
+
+typedef union STRUCT_LONG_ADDRESS LONG_ADDRESS;
+
+
+/****************************************************************************/
+/* */
+/* Structure type : TR_OPEN_DATA */
+/* */
+/* The TR_OPEN_DATA structure is used to pass to the Open SRB and to the */
+/* driver_start_adapter functions all the addressing details that could */
+/* usefully set. This is especially useful for restoring the card to a */
+/* prior state after a reset. */
+/* */
+
+typedef struct STRUCT_TR_OPEN_DATA
+ {
+ WORD open_options;
+ NODE_ADDRESS opening_node_address;
+ ULONG group_address;
+ ULONG functional_address;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : ERROR_LOG */
+/* */
+/* This is part of the information returned by a call to */
+/* driver_get_adapter_status. The error log contains the information from a */
+/* READ_ERROR_LOG SRB call. All the MAC level error counters are reset to */
+/* zero after they are read. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-112 MAC 000A READ.ERROR.LOG Command */
+/* */
+
+struct STRUCT_ERROR_LOG
+ {
+ BYTE line_errors;
+ BYTE reserved_1;
+ BYTE burst_errors;
+ BYTE ari_fci_errors;
+ BYTE reserved_2;
+ BYTE reserved_3;
+ BYTE lost_frame_errors;
+ BYTE congestion_errors;
+ BYTE frame_copied_errors;
+ BYTE reserved_4;
+ BYTE token_errors;
+ BYTE reserved_5;
+ BYTE dma_bus_errors;
+ BYTE dma_parity_errors;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Structure type : STATUS_INFORMATION */
+/* */
+/* The status information returned by a call to driver_get_status */
+/* includes whether the adapter is currently open, the current ring status */
+/* and the MAC level error log information. */
+/* */
+
+struct STRUCT_STATUS_INFORMATION
+ {
+ WBOOLEAN adapter_open;
+ WORD ring_status;
+ ERROR_LOG error_log;
+ };
+
+
+/****************************************************************************/
+/* */
+/* Values : STATUS_INFORMATION - WORD ring_status */
+/* */
+/* These are the possible ring status values returned by a call to */
+/* driver_get_adapter_status. */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-61 4.12.2 RING.STATUS */
+/* */
+
+#define RING_STATUS_SIGNAL_LOSS 0x8000
+#define RING_STATUS_HARD_ERROR 0x4000
+#define RING_STATUS_SOFT_ERROR 0x2000
+#define RING_STATUS_TRANSMIT_BEACON 0x1000
+#define RING_STATUS_LOBE_FAULT 0x0800
+#define RING_STATUS_AUTO_REMOVAL 0x0400
+#define RING_STATUS_REMOVE_RECEIVED 0x0100
+#define RING_STATUS_COUNTER_OVERFLOW 0x0080
+#define RING_STATUS_SINGLE_STATION 0x0040
+#define RING_STATUS_RING_RECOVERY 0x0020
+
+
+/****************************************************************************/
+/* */
+/* Values : WORD open_options */
+/* */
+/* The open_options parameter to driver_prepare_adapter and */
+/* driver_open_adapter has the following bit fields defined. */
+/* */
+/* WARNING : The FORCE_OPEN option is a special Fastmac option that will */
+/* open an adapter onto any ring - even if the adapter and ring speed do */
+/* not match! Use it with caution. */
+/* */
+/* REFERENCE : The Madge Fastmac Interface Specification */
+/* - SRB Interface : Open Adapter SRB */
+/* */
+/* REFERENCE : The TMS 380 Second-Generation Token_Ring User's Guide */
+/* by Texas Instruments */
+/* 4-71 MAC 0003 OPEN command */
+/* */
+
+#define OPEN_OPT_WRAP_INTERFACE 0x8000
+#define OPEN_OPT_DISABLE_SOFT_ERROR 0x4000
+#define OPEN_OPT_DISABLE_HARD_ERROR 0x2000
+#define OPEN_OPT_PASS_ADAPTER_MACS 0x1000
+#define OPEN_OPT_PASS_ATTENTION_MACS 0x0800
+#define OPEN_OPT_FORCE_OPEN 0x0400 /* Fastmac only */
+#define OPEN_OPT_CONTENDER 0x0100
+#define OPEN_OPT_PASS_BEACON_MACS 0x0080
+#define OPEN_OPT_EARLY_TOKEN_RELEASE 0x0010
+#define OPEN_OPT_COPY_ALL_MACS 0x0004
+#define OPEN_OPT_COPY_ALL_LLCS 0x0002
+
+
+/****************************************************************************/
+/* */
+/* Values : WORD adapter_card_bus_type */
+/* */
+/* The following adapter card bus types are defined and can be passed to */
+/* driver_start_adapter. Different adapter card bus types apply to */
+/* different adapter cards : */
+/* */
+/* ADAPTER_CARD_ISA_BUS_TYPE 16/4 PC or 16/4 AT */
+/* ADAPTER_CARD_MC_BUS_TYPE 16/4 MC or 16/4 MC 32 */
+/* ADAPTER_CARD_EISA_BUS_TYPE 16/4 EISA mk1 or mk2 */
+/* */
+
+#define ADAPTER_CARD_ATULA_BUS_TYPE 1
+#define ADAPTER_CARD_MC_BUS_TYPE 2
+#define ADAPTER_CARD_EISA_BUS_TYPE 3
+#define ADAPTER_CARD_PCI_BUS_TYPE 4
+#define ADAPTER_CARD_SMART16_BUS_TYPE 5
+#define ADAPTER_CARD_PCMCIA_BUS_TYPE 6
+#define ADAPTER_CARD_PNP_BUS_TYPE 7
+#define ADAPTER_CARD_TI_PCI_BUS_TYPE 8
+#define ADAPTER_CARD_PCI2_BUS_TYPE 9
+
+
+/****************************************************************************/
+/* */
+/* Values : WORD transfer_mode, WORD interrupt_number */
+/* */
+/* If POLLING_INTERRUPTS_MODE is given as the interrupt number to */
+/* driver_start_adapter, then polling is assumed to be used. */
+/* */
+/* NOTE : If using the DOS example system specific code, then note that */
+/* PIO_DATA_TRANSFER_MODE is defined in SYS_IRQ.ASM and SYS_DMA.ASM */
+/* resepctively. The value used here must be, and is, identical. */
+/* */
+
+#define PIO_DATA_TRANSFER_MODE 0
+#define DMA_DATA_TRANSFER_MODE 1
+#define MMIO_DATA_TRANSFER_MODE 2
+#define POLLING_INTERRUPTS_MODE 0
+
+
+/****************************************************************************/
+/* */
+/* Values : Returned from driver_transmit_frame (or some such) */
+/* */
+/* The value returned by driver_transmit_frame indicates how far the code */
+/* got with transmitting the frame. FAIL and SUCCEED are obvious, WAIT */
+/* means that the caller should not assume the frame has been transmitted */
+/* until some later indication. */
+/* */
+
+#define DRIVER_TRANSMIT_FAIL 0
+#define DRIVER_TRANSMIT_WAIT 1
+#define DRIVER_TRANSMIT_SUCCEED 2
+
+
+/****************************************************************************/
+/* */
+/* Values : Returned from user_receive_frame */
+/* */
+/* The value returned by a call to the user_receive_frame routine indicates */
+/* whether the user wishes to keep the frame in the Fastmac buffer or has */
+/* dealt with it (decided it can be thrown away or copied it elsewhere). In */
+/* the latter case the frame can be removed from the Fastmac receive */
+/* buffer. */
+/* */
+
+#define DO_NOT_KEEP_FRAME 0
+#define KEEP_FRAME 1
+
+
+/****************************************************************************/
+/* */
+/* Type : card_t */
+/* */
+/* To support large model compilation, certain type casts have to be made */
+/* to evade compilation errors. The card_t type is used to convert pointers */
+/* to structures on the adapter card into unsigned integers so that they */
+/* can be truncated to 16 bits without warnings. */
+/* */
+/* */
+
+typedef DWORD card_t;
+
+
+/****************************************************************************/
+/* */
+/* The following structures do not need to be byte packed. */
+/* */
+
+#pragma pack()
+
+
+/****************************************************************************/
+/* */
+/* Values : PROBE_FAILURE */
+/* */
+/* This value is returned by the driver_probe_adapter function if an error */
+/* occurs. */
+/* */
+
+#define PROBE_FAILURE 0xffff
+
+
+/****************************************************************************/
+/* */
+/* Values : FTK_UNDEFINED */
+/* */
+/* This value means that a value is not defined or not used. */
+/* */
+
+#define FTK_UNDEFINED 0xeeff
+
+
+/****************************************************************************/
+/* */
+/* Structure type : PROBE */
+/* */
+/* The probe structure can be filled in with card details by a call to */
+/* driver_probe_adapter. This is the way the user of the FTK should obtain */
+/* hardware resource information (DMA channel, IRQ number etc) about an */
+/* adapter before calling driver_prepare_adapter and driver_start_adapter. */
+/* */
+
+struct STRUCT_PROBE
+{
+ WORD socket;
+ UINT adapter_card_bus_type;
+ UINT adapter_card_type;
+ UINT adapter_card_revision;
+ UINT adapter_ram_size;
+ WORD io_location;
+ WORD interrupt_number;
+ WORD dma_channel;
+ UINT transfer_mode;
+ DWORD mmio_base_address;
+ DWORD pci_handle;
+};
+
+
+/****************************************************************************/
+/* */
+/* Types : PREPARE_ARGS */
+/* */
+/* The driver_prepare_adapter function takes a collection of arguments. An */
+/* instance of this structure is used to pass the arguments. */
+/* */
+
+typedef struct STRUCT_PREPARE_ARGS
+{
+ /* User's private information, not interpreted by the FTK. */
+
+ void * user_information;
+
+#ifdef FMPLUS
+
+ /* Number of FastMAC Plus receive and transmit slots. */
+
+ WORD number_of_rx_slots;
+ WORD number_of_tx_slots;
+
+#else
+
+ /* Size of the FastMAC receive and transmit buffers. */
+
+ WORD receive_buffer_byte_size;
+ WORD transmit_buffer_byte_size;
+
+#endif
+
+ /* Requested maximum frame size. */
+
+ WORD max_frame_size;
+
+};
+
+
+/****************************************************************************/
+/* */
+/* Types : START_ARGS */
+/* */
+/* The driver_start_adapter function takes a collection of arguments. An */
+/* instance of this structure is used to pass the arguments. Note that some */
+/* of the structure fields are filled in on return from */
+/* driver_start_adapter. */
+/* */
+
+typedef struct STRUCT_START_ARGS
+{
+ /* Adapter family. */
+
+ UINT adapter_card_bus_type;
+
+ /* Hardware resource details. */
+
+#ifdef PCMCIA_POINT_ENABLE
+ UINT socket;
+#endif
+ WORD io_location;
+ WORD dma_channel;
+ UINT transfer_mode;
+ WORD interrupt_number;
+
+ /* Override DMA/IRQ values on soft programmable adapters? */
+
+ WBOOLEAN set_dma_channel;
+ WBOOLEAN set_interrupt_number;
+
+ /* Force ring speed to this if possible. 4, 16 or 0 for default. */
+
+ UINT set_ring_speed;
+
+ /* Base Address for MMIO */
+
+ DWORD mmio_base_address;
+
+ /*
+ * Used for the Ti PCI ASIC which in hwi_install needs to access PCI
+ * Config space.
+ */
+
+ DWORD pci_handle;
+
+ /* Actual maximum frame size. Set on return. */
+
+ WORD max_frame_size;
+
+ /* Auto open the adapter? */
+
+ WBOOLEAN auto_open_option;
+
+ /* Open options and addresses for auto open mode. If
+ opening_node_address == 000000000000 the the BIA address
+ is used. */
+
+ WORD open_options;
+
+ NODE_ADDRESS opening_node_address;
+ ULONG opening_group_address;
+ ULONG opening_functional_address;
+
+ /* Pointer to the adapter download image. */
+
+ DOWNLOAD_IMAGE * code;
+
+ /* The open status of the adapter on return. */
+
+ UINT open_status;
+
+#ifdef FMPLUS
+
+ /* Size of the RX/TX buffers on the adapter. */
+
+ WORD rx_tx_buffer_size;
+
+#endif
+
+};
+
+
+/* */
+/* */
+/************** End of FTK_USER.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/drv_err.h b/private/ntos/ndis/madge/driver/head_mod/drv_err.h
new file mode 100644
index 000000000..c8e90ac6b
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/drv_err.h
@@ -0,0 +1,56 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE ERROR EXPLANATION MODULE */
+/* ============================ */
+/* */
+/* DRV_ERR.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The driver module provides a simple interface to allow the use of */
+/* Fastmac in as general a setting as possible. It handles the downloading */
+/* of the Fastmac code and the initialization of the adapter card. It */
+/* provides simple transmit and receive routines. It is desgined to */
+/* quickly allow the implementation of Fastmac applications. It is not */
+/* designed as the fastest or most memory efficient solution. */
+/* */
+/* The DRV_ERR.H file contains the exported function definitions for the */
+/* procedures in the DRV_ERR.C module that may be called by the user. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this DRV_ERR.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_DRV_ERR_H 221
+
+
+/****************************************************************************/
+
+extern WBOOLEAN driver_explain_error(
+
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * returned_error_type,
+ BYTE * returned_error_value,
+ char * * returned_error_message
+ );
+
+extern WBOOLEAN driver_check_version(
+
+ UINT * returned_version_number
+ );
+
+
+/* */
+/* */
+/************** End of DRV_ERR.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/drv_init.h b/private/ntos/ndis/madge/driver/head_mod/drv_init.h
new file mode 100644
index 000000000..0878e5cad
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/drv_init.h
@@ -0,0 +1,79 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DRIVER MODULE (INITIALIZE / REMOVE) */
+/* ======================================= */
+/* */
+/* DRV_INIT.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The driver module provides a simple interface to allow the use of */
+/* Fastmac in as general a setting as possible. It handles the downloading */
+/* of the Fastmac code and the initialization of the adapter card. It */
+/* provides simple transmit and receive routines. It is desgined to */
+/* quickly allow the implementation of Fastmac applications. It is not */
+/* designed as the fastest or most memory efficient solution. */
+/* */
+/* The DRV_INIT.H file contains the exported function definitions for the */
+/* procedures in the DRV_INIT.C module that may be called by the user. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this DRV_INIT.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_DRV_INIT_H 221
+
+/****************************************************************************/
+
+export UINT driver_probe_adapter(
+ WORD adapter_card_bus_type,
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ );
+
+export UINT driver_deprobe_adapter(
+ PROBE * resources,
+ UINT length
+ );
+
+export WBOOLEAN driver_prepare_adapter(
+
+ PPREPARE_ARGS arguments,
+ ADAPTER_HANDLE * returned_adapter_handle
+ );
+
+extern WBOOLEAN driver_start_adapter(
+
+ ADAPTER_HANDLE adapter_handle,
+ PSTART_ARGS arguments,
+ NODE_ADDRESS * returned_permanent_address
+ );
+
+#ifdef FMPLUS
+extern WBOOLEAN driver_start_receive_process(
+
+ ADAPTER_HANDLE adapter_handle
+ );
+#endif
+
+extern WBOOLEAN driver_remove_adapter(
+
+ ADAPTER_HANDLE adapter_handle
+ );
+
+
+/* */
+/* */
+/************** End of DRV_INIT.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/drv_irq.h b/private/ntos/ndis/madge/driver/head_mod/drv_irq.h
new file mode 100644
index 000000000..3582496d3
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/drv_irq.h
@@ -0,0 +1,48 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DRIVER MODULE (INTERRUPT HANDLER) */
+/* ===================================== */
+/* */
+/* DRV_IRQ.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The driver module provides a simple interface to allow the use of */
+/* Fastmac in as general a setting as possible. It handles the downloading */
+/* of the Fastmac code and the initialization of the adapter card. It */
+/* provides simple transmit and receive routines. It is desgined to */
+/* quickly allow the implementation of Fastmac applications. It is not */
+/* designed as the fastest or most memory efficient solution. */
+/* */
+/* The DRV_IRQ.H file contains the exported function definitions for the */
+/* procedures in the DRV_IRQ.C module that may be called by the user. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this DRV_IRQ.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_DRV_IRQ_H 221
+
+
+/****************************************************************************/
+
+extern WBOOLEAN driver_get_outstanding_receive(
+
+ ADAPTER_HANDLE adapter_handle
+ );
+
+
+/* */
+/* */
+/************** End of DRV_IRQ.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/drv_misc.h b/private/ntos/ndis/madge/driver/head_mod/drv_misc.h
new file mode 100644
index 000000000..41ba1683a
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/drv_misc.h
@@ -0,0 +1,81 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* MISCELLANEOUS DRIVER PROCEDURE DECLARATIONS */
+/* =========================================== */
+/* */
+/* DRV_MISC.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The driver module provides a simple interface to allow the use of */
+/* Fastmac in as general a setting as possible. It handles the downloading */
+/* of the Fastmac code and the initialization of the adapter card. It */
+/* provides simple transmit and receive routines. It is desgined to */
+/* quickly allow the implementation of Fastmac applications. It is not */
+/* designed as the fastest or most memory efficient solution. */
+/* */
+/* The DRV_MISC.H file contains the exported function definitions for the */
+/* those procedures that are exported by driver modules but are not */
+/* required by the user. Hence, for example, it includes the definitions */
+/* for those driver routines involved in handling interrupts. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this DRV_MISC.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_DRV_MISC_H 221
+
+
+/****************************************************************************/
+/* */
+/* From DRV_ERR.C ... */
+/* */
+
+extern WBOOLEAN driver_check_adapter(
+
+ ADAPTER_HANDLE adapter_handle,
+ UINT required_adapter_status,
+ UINT required_srb_status
+ );
+
+
+/****************************************************************************/
+/* */
+/* From DRV_SRB.C ... */
+/* */
+
+extern void driver_completing_srb(
+
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ );
+
+
+/****************************************************************************/
+/* */
+/* From DRV_IRQ.C ... */
+/* */
+
+extern void driver_interrupt_entry(
+
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter,
+ WORD sifint_actual
+ );
+
+
+
+/* */
+/* */
+/************** End of DRV_MISC.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/drv_rxtx.h b/private/ntos/ndis/madge/driver/head_mod/drv_rxtx.h
new file mode 100644
index 000000000..38576fb7b
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/drv_rxtx.h
@@ -0,0 +1,201 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* DRIVER/USER INTERFACE PROCEDURE DEFINITIONS */
+/* =========================================== */
+/* */
+/* DRV_RXTX.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The first section contains all the function definitions of routines that */
+/* must be supplied by the user to receive frames plus information on */
+/* completed SRBs. */
+/* */
+/* The next sections contain function prototypes for the transmit and */
+/* receive functions the user must provide. Eaxmples of these functions can */
+/* be found in the TRANSMIT.C and RECEIVE.C modules of the DOS demonstration*/
+/* programs. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this DRV_RXTX.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_DRV_RXTX_H 221
+
+/****************************************************************************/
+/* */
+/* FUNCTION PROTOTYPES */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* WARNING: Depending on the implementation, the receive side processing may*/
+/* require a USER_RECEIVE_FRAME routine, but this is implementation*/
+/* dependent. A fixed interface does not fit well with FastmacPlus.*/
+/* */
+
+extern void user_schedule_receive_process(
+
+ ADAPTER_HANDLE adapter_handle
+ );
+
+extern void user_handle_adapter_check(
+
+ ADAPTER_HANDLE adapter_handle
+ );
+
+extern void user_completed_srb(
+
+ ADAPTER_HANDLE adapter_handle,
+ WBOOLEAN srb_completed_successfully
+ );
+
+extern void user_transmit_completion(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD identifier
+ );
+
+extern WORD user_receive_frame(
+
+ ADAPTER_HANDLE adapter_handle,
+ BYTE FAR * rx_frame_addr,
+ WORD rx_frame_len
+ );
+
+extern void user_adapter_removed(
+
+ ADAPTER_HANDLE adapter_handle
+ );
+
+
+/****************************************************************************/
+/* */
+/* These are the function prototypes that the FastMAC Plus user must */
+/* provide to handle transmission. Note that rxtx_irq_completion_check */
+/* is only needed for the FTK_TX_WITH_COMPLETION transmit method. */
+/* */
+
+#ifdef FMPLUS
+
+extern WBOOLEAN rxtx_transmit_frame(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD tx_frame_identifier,
+ WORD tx_frame_length,
+ WORD tx_flags
+ );
+
+extern void rxtx_irq_tx_completion_check(
+
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ );
+
+extern WBOOLEAN rxtx_allocate_tx_buffers(
+
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ );
+
+extern void rxtx_setup_tx_buffers(
+
+ ADAPTER * adapter,
+ WBOOLEAN use_physical_addresses,
+ WORD number_of_slots
+ );
+
+extern void rxtx_free_tx_buffers(
+
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ );
+#endif
+
+
+/****************************************************************************/
+/* */
+/* These are the function prototypes that the FastMAC Plus user must */
+/* provide to handle receiving. */
+/* */
+
+#ifdef FMPLUS
+
+extern void rxtx_irq_rx_frame_handler(
+
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ );
+
+extern WBOOLEAN rxtx_allocate_rx_buffers(
+
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ );
+
+extern void rxtx_setup_rx_buffers(
+
+ ADAPTER * adapter,
+ WBOOLEAN use_physical_addresses,
+ WORD number_of_slots
+ );
+
+extern void rxtx_free_rx_buffers(
+
+ ADAPTER * adapter,
+ WORD max_frame_size,
+ WORD number_of_slots
+ );
+
+#endif
+
+
+/****************************************************************************/
+/* */
+/* These are the function prototypes that the FastMAC user must */
+/* provide to handle transmission. */
+/* */
+
+#ifndef FMPLUS
+
+extern WBOOLEAN rxtx_transmit_frame(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD tx_frame_identifier,
+ WORD tx_frame_length,
+ WORD tx_flags
+ );
+
+#endif
+
+
+/****************************************************************************/
+/* */
+/* These are the function prototypes that the FastMAC user must */
+/* provide to handle receiving. */
+/* */
+
+#ifndef FMPLUS
+
+extern void rxtx_irq_rx_frame_handler(
+
+ ADAPTER_HANDLE adapter_handle,
+ ADAPTER * adapter
+ );
+
+
+#endif
+
+/************** End of DRV_RXTX.H file **************************************/
diff --git a/private/ntos/ndis/madge/driver/head_mod/drv_srb.h b/private/ntos/ndis/madge/driver/head_mod/drv_srb.h
new file mode 100644
index 000000000..319e3c1c4
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/drv_srb.h
@@ -0,0 +1,110 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DRIVER MODULE (SRBs) */
+/* ======================== */
+/* */
+/* DRV_SRB.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The driver module provides a simple interface to allow the use of */
+/* Fastmac in as general a setting as possible. It handles the downloading */
+/* of the Fastmac code and the initialization of the adapter card. It */
+/* provides simple transmit and receive routines. It is desgined to */
+/* quickly allow the implementation of Fastmac applications. It is not */
+/* designed as the fastest or most memory efficient solution. */
+/* */
+/* The DRV_SRB.H file contains the exported function definitions for the */
+/* procedures in the DRV_SRB.C module that may be called by the user. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this DRV_SRB.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_DRV_SRB_H 221
+
+
+/****************************************************************************/
+
+extern UINT driver_ring_speed(
+
+ ADAPTER_HANDLE
+ );
+
+extern UINT driver_max_frame_size(
+
+ ADAPTER_HANDLE
+ );
+
+extern WBOOLEAN driver_modify_open_options(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD open_options
+ );
+
+extern WBOOLEAN driver_open_adapter(
+
+ ADAPTER_HANDLE adapter_handle,
+ PTR_OPEN_DATA open_data
+ );
+
+extern WBOOLEAN driver_close_adapter(
+
+ ADAPTER_HANDLE adapter_handle
+ );
+
+extern WBOOLEAN driver_set_group_address(
+
+ ADAPTER_HANDLE adapter_handle,
+ MULTI_ADDRESS * group_address
+ );
+
+
+extern WBOOLEAN driver_set_functional_address(
+
+ ADAPTER_HANDLE adapter_handle,
+ MULTI_ADDRESS * functional_address
+ );
+
+extern void driver_get_open_and_ring_status(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD * pwRingStatus,
+ WORD * pwOpenStatus
+ );
+
+extern WBOOLEAN driver_get_status(
+
+ ADAPTER_HANDLE adapter_handle
+ );
+
+extern WBOOLEAN driver_set_bridge_parms(
+
+ ADAPTER_HANDLE adapter_handle,
+ WBOOLEAN single_route_bcast,
+ UINT this_ring,
+ UINT that_ring,
+ UINT bridge_num
+ );
+
+extern WBOOLEAN driver_set_product_instance_id(
+
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * product_id
+ );
+
+
+/* */
+/* */
+/************** End of DRV_SRB.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/ftk_extr.h b/private/ntos/ndis/madge/driver/head_mod/ftk_extr.h
new file mode 100644
index 000000000..a35a46d39
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/ftk_extr.h
@@ -0,0 +1,67 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MODULE ENTRY POINTS DEFINITIONS (EXTERNAL) */
+/* ============================================== */
+/* */
+/* FTK_EXTR.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The FASTMAC TOOL-KIT consists of three parts - the DRIVER, the HWI and */
+/* the SYSTEM specific parts. These parts are further divided into a number */
+/* of modules. Each module has a number of exported procedures that are */
+/* the entry points to the users of that module. The definitions of these */
+/* entry points are maintained within header files using the same name as */
+/* the module itself. Each of these header files also contains a version */
+/* number of the FTK to which it belongs for consistency checking. */
+/* */
+/* There is also a header file for the utilities module that contains */
+/* useful routines used in different parts of the FTK. */
+/* */
+/* */
+/* The FTK_EXTR.H file contains the exported function definitions that are */
+/* required external to the FTK ie. by a user of the FTK. It includes the */
+/* definitions for the USER and SYSTEM functions that must be supplied by */
+/* any application. It also contains the definitions of those functions in */
+/* the DRIVER part that may be called by an FTK user. */
+/* */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* SYSTEM part : module header files */
+/* */
+
+#include "sys_allo.h"
+#include "sys_buff.h"
+#include "sys_dma.h"
+#include "sys_irq.h"
+#include "sys_mem.h"
+#include "sys_time.h"
+#include "sys_pci.h"
+#include "sys_cs.h"
+#include "sys_pcmc.h"
+
+/****************************************************************************/
+/* */
+/* DRIVER part : module header files */
+/* */
+
+#include "drv_err.h"
+#include "drv_srb.h"
+#include "drv_irq.h"
+#include "drv_init.h"
+#include "drv_rxtx.h"
+
+/* */
+/* */
+/************** End of FTK_EXTR.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/ftk_intr.h b/private/ntos/ndis/madge/driver/head_mod/ftk_intr.h
new file mode 100644
index 000000000..b112700a9
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/ftk_intr.h
@@ -0,0 +1,76 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE MODULE ENTRY POINTS DEFINITIONS (INTERNAL) */
+/* ============================================== */
+/* */
+/* FTK_INTR.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The FASTMAC TOOL-KIT consists of three parts - the DRIVER, the HWI and */
+/* the SYSTEM specific parts. These parts are further divided into a number */
+/* of modules. Each module has a number of exported procedures that are */
+/* the entry points to the users of that module. The definitions of these */
+/* entry points are maintained within header files using the same name as */
+/* the module itself. Each of these header files also contains a version */
+/* number of the FTK to which it belongs for consistency checking. */
+/* */
+/* Any application supplies a further fourth part to the FTK - the USER */
+/* part. Hence there is also a header file specifying the format of */
+/* procedures to be supplied by the user for the use of the FTK. */
+/* */
+/* There is also a header file for the utilities module that contains */
+/* useful routines used in different parts of the FTK. */
+/* */
+/* */
+/* The FTK_INTR.H file contains the exported function definitions that are */
+/* required internally by the FTK. It includes the definitions for the HWI */
+/* functions and for those DRIVER functions that are called from within the */
+/* FTK only. It also includes the utilities function definitions. */
+/* */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* HWI part : module header files */
+/* */
+
+#include "hwi_gen.h"
+#include "hwi_at.h"
+#include "hwi_sm16.h"
+#include "hwi_mc.h"
+#include "hwi_eisa.h"
+#include "hwi_pcmc.h"
+#include "hwi_pci.h"
+#include "hwi_pcit.h"
+#include "hwi_pci2.h"
+#include "hwi_pnp.h"
+
+/****************************************************************************/
+/* */
+/* DRIVER part : module header files */
+/* */
+
+#include "drv_misc.h"
+
+
+/****************************************************************************/
+/* */
+/* utilities module header file */
+/* */
+
+#include "util.h"
+
+
+/* */
+/* */
+/************** End of FTK_INTR.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_at.h b/private/ntos/ndis/madge/driver/head_mod/hwi_at.h
new file mode 100644
index 000000000..b8f884afd
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_at.h
@@ -0,0 +1,75 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (ATULA CARDS) */
+/* =========================================== */
+/* */
+/* HWI_AT.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1994 */
+/* Developed by MF */
+/* From code by NT */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_AT.H file contains the exported function definitions for the */
+/* HWI_AT.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this HWI_AT.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_HWI_AT_H 221
+
+
+/****************************************************************************/
+
+export UINT hwi_atula_probe_card(
+
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ );
+
+export WBOOLEAN hwi_atula_read_rate_error( ADAPTER * adapter
+ );
+
+extern WBOOLEAN hwi_atula_install_card(
+
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ );
+
+extern void hwi_atula_interrupt_handler(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_atula_remove_card(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_atula_set_dio_address(
+
+ ADAPTER * adapter,
+ DWORD dio_address
+ );
+
+
+/* */
+/* */
+/************** End of HWI_AT.H file ****************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_eisa.h b/private/ntos/ndis/madge/driver/head_mod/hwi_eisa.h
new file mode 100644
index 000000000..884e4f938
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_eisa.h
@@ -0,0 +1,72 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (EISA CARDS) */
+/* ========================================== */
+/* */
+/* HWI_EISA.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1994 */
+/* Developed by MF */
+/* From code by NT */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_EISA.H file contains the exported function definitions for the */
+/* HWI_EISA.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this HWI_EISA.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_HWI_EISA_H 221
+
+
+/****************************************************************************/
+
+export UINT hwi_eisa_probe_card(
+
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ );
+
+extern WBOOLEAN hwi_eisa_install_card(
+
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ );
+
+extern void hwi_eisa_interrupt_handler(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_eisa_remove_card(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_eisa_set_dio_address(
+
+ ADAPTER * adapter,
+ DWORD dio_address
+ );
+
+
+/* */
+/* */
+/************** End of HWI_EISA.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_gen.h b/private/ntos/ndis/madge/driver/head_mod/hwi_gen.h
new file mode 100644
index 000000000..da4cccad5
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_gen.h
@@ -0,0 +1,127 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (GENERAL) */
+/* ======================================= */
+/* */
+/* HWI_GEN.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1994 */
+/* Developed by MF */
+/* From code by NT */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_GEN.H file contains the exported function definitions for the */
+/* HWI_GEN.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this HWI_GEN.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_HWI_GEN_H 221
+
+
+/****************************************************************************/
+
+export WBOOLEAN
+hwi_read_rate_error(
+ ADAPTER * adapter
+ );
+
+/****************************************************************************/
+/* */
+/* Return codes hwi_read_rate_error. */
+/* */
+/****************************************************************************/
+#define RATE_ERROR 1
+#define NOT_SUPP 2
+
+export UINT hwi_probe_adapter(
+ WORD adapter_card_bus_type,
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ );
+
+export UINT hwi_deprobe_adapter(
+ PROBE * resources,
+ UINT length
+ );
+
+extern WBOOLEAN hwi_install_adapter(
+
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ );
+
+extern WBOOLEAN hwi_initialize_adapter(
+
+ ADAPTER * adapter,
+ INITIALIZATION_BLOCK * init_block
+ );
+
+extern WBOOLEAN hwi_get_node_address_check(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_interrupt_entry(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD interrupt_number
+ );
+
+extern void hwi_remove_adapter(
+
+ ADAPTER * adapter
+ );
+
+export void hwi_halt_eagle(
+
+ ADAPTER * adapter
+ );
+
+export WBOOLEAN hwi_download_code(
+
+ ADAPTER * adapter,
+ DOWNLOAD_RECORD * download_record,
+ void (*set_dio_address)(ADAPTER *, DWORD)
+ );
+
+export void hwi_start_eagle(
+
+ ADAPTER * adapter
+ );
+
+export WBOOLEAN hwi_get_bring_up_code(
+
+ ADAPTER * adapter
+ );
+
+export WORD hwi_get_max_frame_size(
+
+ ADAPTER * adapter
+ );
+
+export UINT hwi_get_ring_speed(
+
+ ADAPTER * adapter
+ );
+
+/* */
+/* */
+/************** End of HWI_GEN.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_mc.h b/private/ntos/ndis/madge/driver/head_mod/hwi_mc.h
new file mode 100644
index 000000000..ec5253223
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_mc.h
@@ -0,0 +1,72 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (MICROCHANNEL CARDS) */
+/* ================================================== */
+/* */
+/* HWI_MC.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1994 */
+/* Developed by MF */
+/* From code by NT */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_MC.H file contains the exported function definitions for the */
+/* HWI_MC.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this HWI_MC.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_HWI_MC_H 221
+
+
+/****************************************************************************/
+
+export UINT hwi_mc_probe_card(
+
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ );
+
+extern WBOOLEAN hwi_mc_install_card(
+
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ );
+
+extern void hwi_mc_interrupt_handler(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_mc_remove_card(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_mc_set_dio_address(
+
+ ADAPTER * adapter,
+ DWORD dio_address
+ );
+
+
+/* */
+/* */
+/************** End of HWI_MC.H file ****************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_pci.h b/private/ntos/ndis/madge/driver/head_mod/hwi_pci.h
new file mode 100644
index 000000000..933bed373
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_pci.h
@@ -0,0 +1,61 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (PCI CARDS) */
+/* ========================================= */
+/* */
+/* HWI_PCI.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1994 */
+/* Developed by PRR */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_PCI.H file contains the exported function definitions for the */
+/* HWI_PCI.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this HWI_EISA.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_HWI_PCI_H 221
+
+
+/****************************************************************************/
+
+export WBOOLEAN hwi_pci_install_card( ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image );
+
+export void hwi_pci_interrupt_handler( ADAPTER * adapter);
+
+export void hwi_pci_remove_card( ADAPTER * adapter );
+
+export void hwi_pci_set_dio_address( ADAPTER * adapter,
+ DWORD dio_address );
+
+export UINT hwi_pci_probe_card( PROBE * Resources,
+ UINT NumberOfResources,
+ WORD * IOMask,
+ UINT NumberIO
+ );
+
+export WBOOLEAN hwi_pci_deprobe_card(
+ PROBE resource
+ );
+
+
+/* */
+/* */
+/************** End of HWI_PCI.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_pci2.h b/private/ntos/ndis/madge/driver/head_mod/hwi_pci2.h
new file mode 100644
index 000000000..5ecd286ce
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_pci2.h
@@ -0,0 +1,56 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (PCI CARDS) */
+/* ========================================= */
+/* */
+/* HWI_PCI.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1994 */
+/* Developed by PRR */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_PCI2.H file contains the exported function definitions for the */
+/* HWI_PCI2.C module. */
+/* */
+/****************************************************************************/
+
+#define FTK_VERSION_NUMBER_hwi_pci2_H 221
+
+
+/****************************************************************************/
+
+export WBOOLEAN hwi_pci2_install_card( ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image );
+
+export void hwi_pci2_interrupt_handler( ADAPTER * adapter);
+
+export void hwi_pci2_remove_card( ADAPTER * adapter );
+
+export void hwi_pci2_set_dio_address( ADAPTER * adapter,
+ DWORD dio_address );
+
+export UINT hwi_pci2_probe_card( PROBE * Resources,
+ UINT NumberOfResources,
+ WORD * IOMask,
+ UINT NumberIO
+ );
+
+export WBOOLEAN hwi_pci2_deprobe_card(
+ PROBE resource
+ );
+
+
+/* */
+/* */
+/************** End of HWI_PCI.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_pcit.h b/private/ntos/ndis/madge/driver/head_mod/hwi_pcit.h
new file mode 100644
index 000000000..714e2b24a
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_pcit.h
@@ -0,0 +1,56 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (PCI CARDS) */
+/* ========================================= */
+/* */
+/* HWI_PCI.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1994 */
+/* Developed by PRR */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_PCI.H file contains the exported function definitions for the */
+/* HWI_PCI.C module. */
+/* */
+/****************************************************************************/
+
+#define FTK_VERSION_NUMBER_HWI_PCIT_H 221
+
+
+/****************************************************************************/
+
+export WBOOLEAN hwi_pcit_install_card( ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image );
+
+export void hwi_pcit_interrupt_handler( ADAPTER * adapter);
+
+export void hwi_pcit_remove_card( ADAPTER * adapter );
+
+export void hwi_pcit_set_dio_address( ADAPTER * adapter,
+ DWORD dio_address );
+
+export UINT hwi_pcit_probe_card( PROBE * Resources,
+ UINT NumberOfResources,
+ WORD * IOMask,
+ UINT NumberIO
+ );
+
+export WBOOLEAN hwi_pcit_deprobe_card(
+ PROBE resource
+ );
+
+
+/* */
+/* */
+/************** End of HWI_PCI.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_pcmc.h b/private/ntos/ndis/madge/driver/head_mod/hwi_pcmc.h
new file mode 100644
index 000000000..5ab0c7e13
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_pcmc.h
@@ -0,0 +1,77 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (PCMCIA CARDS) */
+/* ============================================ */
+/* */
+/* HWI_PCMC.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1993 */
+/* Developed by VL */
+/* From code by MF, NT */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_PCMC.H file contains the exported function definitions for the */
+/* HWI_PCMC.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this HWI_PCMC.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_HWI_PCMC_H 221
+
+
+/****************************************************************************/
+
+export UINT hwi_pcmcia_probe_card(
+
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ );
+
+export WBOOLEAN hwi_pcmcia_deprobe_card(
+
+ PROBE resource
+ );
+
+extern WBOOLEAN hwi_pcmcia_install_card(
+
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ );
+
+extern void hwi_pcmcia_interrupt_handler(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_pcmcia_remove_card(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_pcmcia_set_dio_address(
+
+ ADAPTER * adapter,
+ DWORD dio_address
+ );
+
+
+/* */
+/* */
+/************** End of HWI_PCMC.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_pnp.h b/private/ntos/ndis/madge/driver/head_mod/hwi_pnp.h
new file mode 100644
index 000000000..4bed4f1e9
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_pnp.h
@@ -0,0 +1,72 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (SMART 16 CARDS) */
+/* ============================================== */
+/* */
+/* HWI_PNP.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1990-1994 */
+/* Developed by AC */
+/* From code by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_PNP.H file contains the exported function definitions for the */
+/* HWI_PNP.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this HWI_PNP.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_HWI_PNP_H 221
+
+
+/****************************************************************************/
+
+extern WBOOLEAN hwi_pnp_install_card(
+
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ );
+
+extern void hwi_pnp_interrupt_handler(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_pnp_remove_card(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_pnp_set_dio_address(
+
+ ADAPTER * adapter,
+ DWORD dio_address
+ );
+#ifndef FTK_NO_PROBE
+export UINT
+hwi_pnp_probe_card(
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ );
+#endif
+
+/* */
+/* */
+/************** End of HWI_PNP.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/hwi_sm16.h b/private/ntos/ndis/madge/driver/head_mod/hwi_sm16.h
new file mode 100644
index 000000000..23a9df200
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/hwi_sm16.h
@@ -0,0 +1,70 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE HARDWARE INTERFACE MODULE (SMART 16 CARDS) */
+/* ============================================== */
+/* */
+/* HWI_SM16.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1994 */
+/* Developed by AC */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the Hardware Interface (HWI) is to supply an adapter card */
+/* independent interface to any driver. It performs nearly all of the */
+/* functions that involve affecting SIF registers on the adapter cards. */
+/* This includes downloading code to, initializing, and removing adapters. */
+/* */
+/* The HWI_SM16.H file contains the exported function definitions for the */
+/* HWI_SM16.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this HWI_SM16.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_HWI_SM16_H 221
+
+
+/****************************************************************************/
+
+export UINT hwi_smart16_probe_card(
+
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ );
+
+extern WBOOLEAN hwi_smart16_install_card(
+
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ );
+
+extern void hwi_smart16_interrupt_handler(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_smart16_remove_card(
+
+ ADAPTER * adapter
+ );
+
+extern void hwi_smart16_set_dio_address(
+
+ ADAPTER * adapter,
+ DWORD dio_address
+ );
+
+/* */
+/* */
+/************** End of HWI_SM16.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_allo.h b/private/ntos/ndis/madge/driver/head_mod/sys_allo.h
new file mode 100644
index 000000000..4a959b90f
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_allo.h
@@ -0,0 +1,95 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (ALLOCATE/FREE MEMORY) */
+/* ===================================================== */
+/* */
+/* SYS_ALLO.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* memory allocation routines, interrupt and DMA channel enabling/disabling */
+/* routines, and routines for accessing IO ports. */
+/* */
+/* The SYS_ALLO.H file contains the exported function definitions for the */
+/* SYS_ALLO.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_ALLO.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_ALLO_H 221
+
+
+/****************************************************************************/
+
+extern BYTE * sys_alloc_init_block(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD init_block_byte_size
+ );
+
+extern BYTE * sys_alloc_adapter_structure(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD adapter_structure_byte_size
+ );
+
+extern BYTE * sys_alloc_status_structure(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD status_structure_byte_size
+ );
+
+extern WBOOLEAN sys_alloc_dma_phys_buffer(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD buffer_byte_size,
+ DWORD * phys,
+ DWORD * virt
+ );
+
+extern void sys_free_init_block(
+
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * init_block_addr,
+ WORD init_block_byte_size
+ );
+
+extern void sys_free_adapter_structure(
+
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * adapter_structure_addr,
+ WORD adapter_structure_byte_size
+ );
+
+extern void sys_free_status_structure(
+
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * status_structure_addr,
+ WORD status_structure_byte_size
+ );
+
+extern void sys_free_dma_phys_buffer(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD buffer_byte_size,
+ DWORD phys,
+ DWORD virt
+ );
+
+/* */
+/* */
+/************** End of SYS_ALLO.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_buff.h b/private/ntos/ndis/madge/driver/head_mod/sys_buff.h
new file mode 100644
index 000000000..c708440ec
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_buff.h
@@ -0,0 +1,67 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (ALLOCATE/FREE BUFFERS) */
+/* ====================================================== */
+/* */
+/* SYS_BUFF.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* memory allocation routines, interrupt and DMA channel enabling/disabling */
+/* routines, and routines for accessing IO ports. */
+/* */
+/* The SYS_BUFF.H file contains the exported function definitions for the */
+/* SYS_BUFF.ASM module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_BUFF.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_BUFF_H 221
+
+
+/****************************************************************************/
+
+extern DWORD sys_alloc_transmit_buffer(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD transmit_buffer_byte_size
+ );
+
+extern DWORD sys_alloc_receive_buffer(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD receive_buffer_byte_size
+ );
+
+extern void sys_free_transmit_buffer(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD transmit_buffer_physaddr,
+ WORD transmit_buffer_byte_size
+ );
+
+extern void sys_free_receive_buffer(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD receive_buffer_physaddr,
+ WORD receive_buffer_byte_size
+ );
+
+/* */
+/* */
+/************** End of SYS_BUFF.H file **************************************/
+/* */
+/* */
+
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_cs.h b/private/ntos/ndis/madge/driver/head_mod/sys_cs.h
new file mode 100644
index 000000000..14ea4dfd9
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_cs.h
@@ -0,0 +1,651 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (INTERFACE TO PCMCIA CARD SERVICES) */
+/* ================================================================== */
+/* */
+/* SYS_CS.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by VL */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* memory allocation routines, interrupt and DMA channel enabling/disabling */
+/* routines, and routines for accessing IO ports. */
+/* */
+/* This SYS_CS.H file contains the exported function definitions for the */
+/* SYS_CS.ASM module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_CS.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_CS_H 221
+
+/****************************************************************************/
+/* */
+/* Routine to invoke PCMCIA Card Services. */
+/* */
+/* PCMCIA spec. defines card services as: */
+/* */
+/* Status = CardServices (Function, Handle, Pointer, ArgLength, ArgPointer) */
+/* */
+/* Note that Handle and Pointer can be both input and output argument. So */
+/* in our C function, the second and third argument are pointer to Handle */
+/* and pointer to Pointer respectively. */
+/* */
+/* NOTE THAT NO ARGUMENT CHECKING IS DONE HERE, MAKE SURE THAT YOU PASS IN */
+/* CORRECT ARGUMENTS. */
+/* */
+
+extern WORD CardServices (
+ BYTE Function,
+ WORD FAR * PHandle,
+ void * FAR * PPointer,
+ WORD ArgLength,
+ BYTE FAR * ArgPointer );
+
+
+/****************************************************************************/
+/* */
+/* This is the prototype of the Callback function. When user make */
+/* RegisterClient call to card services, pointer to callback function must */
+/* be supplied. Card Services will then notify the user of any event by */
+/* calling this Callback function. */
+/* */
+
+extern WORD Callback (
+ WORD Function,
+ WORD Socket,
+ WORD Info,
+ void FAR * MTDRequest,
+ void FAR * Buffer,
+ WORD Misc,
+ WORD ClientData1,
+ WORD ClientData2,
+ WORD ClientData3 );
+
+
+
+/****************************************************************************/
+/* */
+/* #DEFINES */
+/* ======== */
+
+
+/****************************************************************************/
+/* */
+/* This is the version number of the Card Services specification upon which */
+/* the following Card Services constants are based. It is stored in BCD */
+/* format. */
+
+#define CARD_SERVICES_VERSION 0x0201
+
+
+/****************************************************************************/
+/* */
+/* This is the version number of the Socket Services specification upon */
+/* which the following Socket Services constants are based. It is stored in */
+/* BCD format. */
+/* */
+
+#define SOCKET_SERVICES_VERSION 0x0210
+
+
+/****************************************************************************/
+/* */
+/* These are the Card Services Functions available through the CardServices */
+/* Function call to Socket Services. */
+/* */
+
+#define CS_GetCardServicesInfo 0x0B
+#define CS_RegisterClient 0x10
+#define CS_DeregisterClient 0x02
+#define CS_GetStatus 0x0C
+#define CS_ResetCard 0x11
+#define CS_SetEventMask 0x31
+#define CS_GetEventMask 0x2E
+
+#define CS_RequestIO 0x1F
+#define CS_ReleaseIO 0x1B
+#define CS_RequestIRQ 0x20
+#define CS_ReleaseIRQ 0x1C
+#define CS_RequestWindow 0x21
+#define CS_ModifyWindow 0x17
+#define CS_ReleaseWindow 0x1D
+#define CS_MapMemPage 0x14
+#define CS_RequestSocketMask 0x22
+#define CS_ReleaseSocketMask 0x2F
+#define CS_RequestConfiguration 0x30
+#define CS_GetConfiguration 0x04
+#define CS_ModifyConfiguration 0x27
+#define CS_ReleaseConfiguration 0x1E
+
+#define CS_OpenMemory 0x18
+#define CS_ReadMemory 0x19
+#define CS_WriteMemory 0x24
+#define CS_CopyMemory 0x01
+#define CS_RegisterEraseQueue 0x0F
+#define CS_CheckEraseQueue 0x26
+#define CS_DeregisterEraseQueue 0x25
+#define CS_CloseMemory 0x00
+
+#define CS_GetFirstTuple 0x07
+#define CS_GetNextTuple 0x0A
+#define CS_GetTupleData 0x0D
+#define CS_GetFirstRegion 0x06
+#define CS_GetNextRegion 0x09
+#define CS_GetFirstPartition 0x05
+#define CS_GetNextPartition 0x08
+
+#define CS_ReturnSSEntry 0x23
+#define CS_MapLogSocket 0x12
+#define CS_MapPhySocket 0x15
+#define CS_MapLogWindow 0x13
+#define CS_MapPhyWindow 0x16
+#define CS_RegisterMTD 0x1A
+#define CS_RegisterTimer 0x38
+#define CS_SetRegion 0x39
+#define CS_ValidateCIS 0x2B
+#define CS_RequestExclusive 0x2C
+#define CS_ReleaseExclusive 0x2D
+#define CS_GetFirstClient 0x0E
+#define CS_GetNextClient 0x2A
+#define CS_GetClientInfo 0x03
+#define CS_AddSocketServices 0x32
+#define CS_ReplaceSocketServices 0x33
+#define CS_VendorSpecific 0x34
+#define CS_AdjustResourceInfo 0x35
+
+#define CS_AccessConfigurationRegister 0x36
+
+
+/****************************************************************************/
+/* */
+/* These are the Card Services Callback Function codes */
+/* */
+
+#define BATTERY_DEAD 0x01
+#define BATTERY_LOW 0x02
+#define CARD_LOCK 0x03
+#define CARD_READY 0x04
+#define CARD_REMOVAL 0x05
+#define CARD_UNLOCK 0x06
+#define EJECTION_COMPLETE 0x07
+#define EJECTION_REQUEST 0x08
+#define INSERTION_COMPLETE 0x09
+#define INSERTION_REQUEST 0x0A
+#define EXCLUSIVE_COMPLETE 0x0D
+#define EXCLUSIVE_REQUEST 0x0E
+#define RESET_PHYSICAL 0x0F
+#define RESET_REQUEST 0x10
+#define CARD_RESET 0x11
+#define CLIENT_INFO 0x14
+#define TIMER_EXPIRED 0x15
+#define SS_UPDATED 0x16
+#define CARD_INSERTION 0x40
+#define RESET_COMPLETE 0x80
+#define REGISTRATION_COMPLETE 0x82
+
+
+/****************************************************************************/
+/* */
+/* These are the SocketServices/CardServices Return codes */
+/* */
+
+#define CMD_SUCCESS 0x00
+#define BAD_ADAPTER 0x01
+#define BAD_ATTRIBUTE 0x02
+#define BAD_BASE 0x03
+#define BAD_EDC 0x04
+#define BAD_IRQ 0x06
+#define BAD_OFFSET 0x07
+#define BAD_PAGE 0x08
+#define READ_FAILURE 0x09
+#define BAD_SIZE 0x0A
+#define BAD_SOCKET 0x0B
+#define BAD_TYPE 0x0D
+#define BAD_VCC 0x0E
+#define BAD_VPP 0x0F
+#define BAD_WINDOW 0x11
+#define WRITE_FAILURE 0x12
+#define NO_CARD 0x14
+#define BAD_FUNCTION 0x15
+#define BAD_MODE 0x16
+#define BAD_SPEED 0x17
+#define BUSY 0x18
+#define GENERAL_FAILURE 0x19
+#define WRITE_PROTECTED 0x1A
+#define BAD_ARG_LENGTH 0x1B
+#define BAD_ARGS 0x1C
+#define CONFIGURATION_LOCKED 0x1D
+#define IN_USE 0x1E
+#define NO_MORE_ITEMS 0x1F
+#define OUT_OF_RESOURCE 0x20
+#define BAD_HANDLE 0x21
+
+
+
+/****************************************************************************/
+/* */
+/* These are the bit definitions for Event Mask Functions */
+/* */
+
+#define MASK_WRITE_PROTECT 0x0001
+#define MASK_CARD_LOCK 0x0002
+#define MASK_EJECTION 0x0004
+#define MASK_INSERTION 0x0008
+#define MASK_BATTERY_DEAD 0x0010
+#define MASK_BATTERY_LOW 0x0020
+#define MASK_READY 0x0040
+#define MASK_CARD_DETECT 0x0080
+#define MASK_PM 0x0100
+#define MASK_RESET 0x0200
+#define MASK_SS_UPDATE 0x0400
+
+/****************************************************************************/
+/* */
+/* These are the bit definition for RegisterClient attribute */
+/* */
+
+#define RC_ATTR_MEMORY_CLIENT_DRIVER 0x0001
+#define RC_ATTR_MEMORY_TECH_DRIVER 0x0002
+#define RC_ATTR_IO_CLIENT_DEVICE_DRIVER 0x0004
+#define RC_ATTR_IO_INSERTION_SHARABLE 0x0008
+#define RC_ATTR_IO_INSERTION_EXCLUSIVE 0x0010
+
+/****************************************************************************/
+/* */
+/* These are definition for AdjustResourceInfo Action */
+/* */
+
+#define ARI_ACTION_REMOVE 0x00
+#define ARI_ACTION_ADD 0x01
+#define ARI_ACTION_GET_FIRST 0x02
+#define ARI_ACTION_GET_NEXT 0x03
+
+/****************************************************************************/
+/* */
+/* These are definition for AdjustResourceInfo Resource */
+/* */
+
+#define ARI_RESOURCE_MEMORY 0x00
+#define ARI_RESOURCE_IO 0x01
+#define ARI_RESOURCE_IRQ 0x02
+
+/****************************************************************************/
+/* */
+/* These are definition for RequestIO Attributes */
+/* */
+
+#define RIO_ATTR_SHARED 0x01
+#define RIO_ATTR_FIRST_SHARED 0x02
+#define RIO_ATTR_FORCE_ALIAS_ACCESS 0x04
+#define RIO_ATTR_16_BIT_DATA 0x08
+
+/****************************************************************************/
+/* */
+/* These are definition for RequestIRQ Attributes */
+/* */
+
+#define RIRQ_ATTR_TYPE_EXCLUSIVE 0x0000
+#define RIRQ_ATTR_TYPE_TIME_MULTIPLEX 0x0001
+#define RIRQ_ATTR_TYPE_DYMANIC_SHARE 0x0002
+#define RIRQ_ATTR_TYPE_RESERVED 0x0003
+
+
+/****************************************************************************/
+/* */
+/* These are definition for RequestIRQ IRQInfos */
+/* */
+
+
+#define IRQ_INFO1_INFO2_ENABLE 0x10
+
+#define IRQ_INFO1_LEVEL 0x20
+#define IRQ_INFO1_PULSE 0x40
+#define IRQ_INFO1_SHARE 0x80
+
+#define IRQ_0 0x0001
+#define IRQ_1 0x0002
+#define IRQ_2 0x0004
+#define IRQ_3 0x0008
+#define IRQ_4 0x0010
+#define IRQ_5 0x0020
+#define IRQ_6 0x0040
+#define IRQ_7 0x0080
+#define IRQ_8 0x0100
+#define IRQ_9 0x0200
+#define IRQ_10 0x0400
+#define IRQ_11 0x0800
+#define IRQ_12 0x1000
+#define IRQ_13 0x2000
+#define IRQ_14 0x4000
+#define IRQ_15 0x8000
+
+/****************************************************************************/
+/* */
+/* These are RequestConfiguration related things */
+/* */
+
+#define RC_ATTR_ENABLE_IRQ_STEERING 0x02
+
+
+#define RC_PRESENT_OPTION_REG 0x01
+#define RC_PRESENT_STATUS_REG 0x02
+#define RC_PRESENT_PIN_REPLACEMENT 0x04
+#define RC_PRESENT_COPY_REG 0x08
+
+#define RC_INTTYPE_MEMORY 0x01
+#define RC_INTTYPE_MEMORY_AND_IO 0x02
+
+
+/****************************************************************************/
+/* */
+/* These are AccessConfigurationRegister related things */
+/* */
+
+#define ACR_ACTION_READ 0x00
+#define ACR_ACTION_WRITE 0x01
+
+
+/****************************************************************************/
+/* */
+/* These are the codes for tuples within the CIS (Card Information */
+/* Structure) */
+/* */
+
+#define CISTPL_NULL 0x00
+#define CISTPL_DEVICE 0x01
+#define CISTPL_CHECKSUM 0x10
+#define CISTPL_LONGLINK_A 0x11
+#define CISTPL_LONGLINK_C 0x12
+#define CISTPL_LINKTARGET 0x13
+#define CISTPL_NO_LINK 0x14
+#define CISTPL_VERS_1 0x15
+#define CISTPL_ALTSTR 0x16
+#define CISTPL_DEVICE_A 0x17
+#define CISTPL_JEDEC_C 0x18
+#define CISTPL_JEDEC_A 0x19
+#define CISTPL_CONFIG 0x1A
+#define CISTPL_CFTABLE_ENTRY 0x1B
+#define CISTPL_DEVICE_OC 0x1C
+#define CISTPL_DEVICE_OA 0x1D
+#define CISTPL_DEVICE_GEO 0x1E
+#define CISTPL_DEVICE_GEO_A 0x1F
+
+#define CISTPL_MANFID 0x20
+#define CISTPL_FUNCID 0x21
+#define CISTPL_FUNCE 0x22
+#define CISTPL_SWIL 0x23
+#define CISTPL_VERS_2 0x40
+#define CISTPL_FORMAT 0x41
+#define CISTPL_GEOMETRY 0x42
+#define CISTPL_BYTEORDER 0x43
+#define CISTPL_DATE 0x44
+#define CISTPL_BATTERY 0x45
+
+
+/****************************************************************************/
+/* */
+/* These are argument block definitions for various card services functions */
+/* */
+/****************************************************************************/
+/* */
+
+/****************************************************************************/
+/* */
+/* Argument for GetCardServicesInfo */
+/* */
+
+struct STRUCT_CS_GET_CS_INFO_ARG
+{
+ WORD InfoLen;
+ BYTE Signature[2];
+ WORD Count;
+ WORD Revision;
+ WORD CSLevel;
+ WORD VStrOff;
+ WORD VStrLen;
+ BYTE VendorString[1];
+};
+
+typedef struct STRUCT_CS_GET_CS_INFO_ARG CS_GET_CS_INFO_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Argument for RegisterClient */
+/* */
+
+struct STRUCT_CS_REGISTER_CLIENT_ARG
+{
+ WORD Attributes;
+ WORD EventMask;
+ WORD ClientData[4];
+ WORD Version;
+};
+
+typedef struct STRUCT_CS_REGISTER_CLIENT_ARG CS_REGISTER_CLIENT_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Argument for GetFirstTuple */
+/* */
+
+struct STRUCT_CS_GET_FIRST_TUPLE_ARG
+{
+ WORD Socket;
+ WORD Attributes;
+ BYTE DesiredTuple;
+ BYTE Reserved;
+ WORD Flags;
+ DWORD LinkOffset;
+ DWORD CISOffset;
+ BYTE TupleCode;
+ BYTE TupleLink;
+};
+
+typedef struct STRUCT_CS_GET_FIRST_TUPLE_ARG CS_GET_FIRST_TUPLE_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Argument for GetTupleData */
+/* */
+
+struct STRUCT_CS_GET_TUPLE_DATA_ARG
+{
+ WORD Socket;
+ WORD Attributes;
+ BYTE DesiredTuples;
+ BYTE TupleOffset;
+ WORD Flags;
+ DWORD LinkOffset;
+ DWORD CISOffset;
+ WORD TupleDataMax;
+ WORD TupleDataLen;
+ BYTE TupleData[1];
+};
+
+typedef struct STRUCT_CS_GET_TUPLE_DATA_ARG CS_GET_TUPLE_DATA_ARG;
+
+
+
+/****************************************************************************/
+/* */
+/* Argument for AdjustResouceInfo ( IO resources ) */
+/* */
+
+struct STRUCT_CS_ADJ_IO_RESOURCE_ARG
+{
+ BYTE Action;
+ BYTE Resource;
+ WORD BasePort;
+ BYTE NumPorts;
+ BYTE Attributes;
+ BYTE IOAddrLines;
+};
+
+typedef struct STRUCT_CS_ADJ_IO_RESOURCE_ARG CS_ADJ_IO_RESOURCE_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Argument for RequestIO */
+/* */
+
+struct STRUCT_CS_REQUEST_IO_ARG
+{
+ WORD Socket;
+ WORD BasePort1;
+ BYTE NumPorts1;
+ BYTE Attributes1;
+ WORD BasePort2;
+ BYTE NumPorts2;
+ BYTE Attributes2;
+ BYTE IOAddrLines;
+
+};
+
+typedef struct STRUCT_CS_REQUEST_IO_ARG CS_REQUEST_IO_ARG;
+
+/****************************************************************************/
+/* */
+/* Argument for RequestIRQ */
+/* */
+
+struct STRUCT_CS_REQUEST_IRQ_ARG
+{
+ WORD Socket;
+ WORD Attributes;
+ BYTE AssignedIRQ;
+ BYTE IRQInfo1;
+ WORD IRQInfo2;
+};
+
+typedef struct STRUCT_CS_REQUEST_IRQ_ARG CS_REQUEST_IRQ_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Argument for RequestConfiguration */
+/* */
+
+struct STRUCT_CS_REQUEST_CONFIG_ARG
+{
+ WORD Socket;
+ WORD Attributes;
+ BYTE Vcc;
+ BYTE Vpp1;
+ BYTE Vpp2;
+ BYTE IntType;
+ DWORD ConfigBase;
+ BYTE Status;
+ BYTE Pin;
+ BYTE Copy;
+ BYTE ConfigIndex;
+ BYTE Present;
+};
+
+typedef struct STRUCT_CS_REQUEST_CONFIG_ARG CS_REQUEST_CONFIG_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Argument for AccessConfigurationRegister */
+/* */
+
+struct STRUCT_CS_ACCESS_CONFIG_REG_ARG
+{
+ WORD Socket;
+ BYTE Action;
+ BYTE Offset;
+ BYTE Value;
+};
+
+typedef struct STRUCT_CS_ACCESS_CONFIG_REG_ARG CS_ACCESS_CONFIG_REG_ARG;
+
+/****************************************************************************/
+/* */
+/* Argument for ReleaseIO */
+/* */
+
+struct STRUCT_CS_RELEASE_IO_ARG
+{
+ WORD Socket;
+ WORD BasePort1;
+ BYTE NumPorts1;
+ BYTE Attributes1;
+ WORD BasePort2;
+ BYTE NumPorts2;
+ BYTE Attributes2;
+ BYTE IOAddrLines;
+};
+
+typedef struct STRUCT_CS_RELEASE_IO_ARG CS_RELEASE_IO_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Argument for ReleaseIRQ */
+/* */
+
+struct STRUCT_CS_RELEASE_IRQ_ARG
+{
+ WORD Socket;
+ WORD Attributes;
+ BYTE AssignedIRQ;
+};
+
+typedef struct STRUCT_CS_RELEASE_IRQ_ARG CS_RELEASE_IRQ_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Argument for ReleaseConfiguration */
+/* */
+
+struct STRUCT_CS_RELEASE_CONFIG_ARG
+{
+ WORD Socket;
+};
+
+typedef struct STRUCT_CS_RELEASE_CONFIG_ARG CS_RELEASE_CONFIG_ARG;
+
+
+/****************************************************************************/
+/* */
+/* Client Information Structure */
+/* */
+
+struct STRUCT_CS_CLIENT_INFO
+{
+ WORD MaxLen;
+ WORD InfoLen;
+ WORD Atrributes;
+ WORD Revision;
+ WORD CSLevel;
+ WORD RevDate;
+ WORD NameOff;
+ WORD NameLen;
+ WORD VStringOff;
+ WORD VStringLen;
+};
+
+typedef struct STRUCT_CS_CLIENT_INFO CS_CLIENT_INFO;
+
+/* */
+/* */
+/************** End of SYS_CS.H file ****************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_dma.h b/private/ntos/ndis/madge/driver/head_mod/sys_dma.h
new file mode 100644
index 000000000..7e29b6315
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_dma.h
@@ -0,0 +1,60 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (DMA) */
+/* ==================================== */
+/* */
+/* SYS_DMA.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* DMAory allocation routines, interrupt and DMA channel enabling/disabling */
+/* routines, and routines for accessing IO ports. */
+/* */
+/* The SYS_DMA.H file contains the exported function definitions for the */
+/* SYS_DMA.ASM module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_DMA.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_DMA_H 221
+
+
+/****************************************************************************/
+
+extern WBOOLEAN sys_enable_dma_channel(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD dma_channel
+ );
+
+extern void sys_disable_dma_channel(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD dma_channel
+ );
+
+extern WORD sys_atula_find_dma_channel(
+
+ WORD io_on_off_location,
+ BYTE dma_on_byte,
+ BYTE dma_off_byte
+ );
+
+
+/* */
+/* */
+/************** End of SYS_DMA.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_irq.h b/private/ntos/ndis/madge/driver/head_mod/sys_irq.h
new file mode 100644
index 000000000..4e8db1d8f
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_irq.h
@@ -0,0 +1,65 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (INTERRUPT) */
+/* ========================================== */
+/* */
+/* SYS_IRQ.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* IRQory allocation routines, interrupt and DMA channel enabling/disabling */
+/* routines, and routines for accessing IO ports. */
+/* */
+/* The SYS_IRQ.H file contains the exported function definitions for the */
+/* SYS_IRQ.ASM module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_IRQ.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_IRQ_H 221
+
+
+/****************************************************************************/
+
+extern WBOOLEAN sys_enable_irq_channel(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD interrupt_number
+ );
+
+extern void sys_disable_irq_channel(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD interrupt_number
+ );
+
+extern void sys_clear_controller_interrupt(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD interrupt_number
+ );
+
+extern WORD sys_atula_find_irq_channel(
+
+ WORD io_on_off_location,
+ BYTE irq_on_byte,
+ BYTE irq_off_byte
+ );
+
+/* */
+/* */
+/************** End of SYS_IRQ.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_mem.h b/private/ntos/ndis/madge/driver/head_mod/sys_mem.h
new file mode 100644
index 000000000..ebcc6670b
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_mem.h
@@ -0,0 +1,206 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (MEMORY IO) */
+/* ========================================== */
+/* */
+/* SYS_MEM.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* memory allocation routines, interrupt and DMA channel enabling/disabling */
+/* routines, and routines for accessing IO ports. */
+/* */
+/* The SYS_MEM.H file contains the exported function definitions for the */
+/* SYS_MEM.ASM module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_MEM.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_MEM_H 221
+
+
+/****************************************************************************/
+
+extern void sys_enable_io(
+
+ WORD io_location,
+ WORD io_range
+ );
+
+extern void sys_disable_io(
+
+ WORD io_location,
+ WORD io_range
+ );
+
+extern WORD sys_insw(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location
+ );
+
+extern BYTE sys_insb(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location
+ );
+
+extern void sys_outsw(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD output_location,
+ WORD output_word
+ );
+
+extern void sys_outsb(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD output_location,
+ BYTE output_byte
+ );
+
+extern WORD sys_probe_insw(
+
+ WORD input_location
+ );
+
+extern BYTE sys_probe_insb(
+
+ WORD input_location
+ );
+
+extern void sys_probe_outsw(
+
+ WORD output_location,
+ WORD output_word
+ );
+
+extern void sys_probe_outsb(
+
+ WORD output_location,
+ BYTE output_byte
+ );
+
+extern void sys_rep_insw(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE FAR * destination_address,
+ WORD length_in_words
+ );
+
+extern void sys_rep_swap_insw(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE FAR * destination_address,
+ WORD length_in_words
+ );
+
+extern void sys_rep_outsw(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD output_location,
+ BYTE FAR * source_address,
+ WORD length_in_words
+ );
+
+extern void sys_rep_swap_outsw(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD output_location,
+ BYTE FAR * source_address,
+ WORD length_in_words
+ );
+
+extern void sys_rep_insd(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE FAR * destination_address,
+ WORD length_in_dwords
+ );
+
+extern void sys_rep_outsd(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD output_location,
+ BYTE FAR * source_address,
+ WORD length_in_dwords
+ );
+
+extern DWORD sys_phys_to_virt(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD physaddr
+ );
+
+
+extern DWORD sys_virt_to_phys(
+
+ ADAPTER_HANDLE adapter_handle,
+ void FAR * virtaddr
+ );
+
+export void sys_rep_movsd_to(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD SourcePtr,
+ DWORD DestPtr,
+ WORD TransferSize
+ );
+
+
+export void sys_rep_movsd_from(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD SourcePtr,
+ DWORD DestPtr,
+ WORD TransferSize
+ );
+
+export void sys_movsd_from(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD SourcePtr,
+ DWORD DestPtr
+ );
+
+export void sys_movsd_to(
+
+ ADAPTER_HANDLE adapter_handle,
+ DWORD SourcePtr,
+ DWORD DestPtr
+ );
+
+export void sys_mem_copy(
+
+ BYTE FAR * destination_ptr,
+ BYTE FAR * source_ptr,
+ WORD byte_count
+ );
+
+extern WBOOLEAN sys_sync_with_interrupt(
+
+ ADAPTER_HANDLE adapter_handle,
+ WBOOLEAN (*f)(void *),
+ void * ptr
+ );
+
+/* */
+/* */
+/************** End of SYS_MEM.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_pci.h b/private/ntos/ndis/madge/driver/head_mod/sys_pci.h
new file mode 100644
index 000000000..6b0faf0ba
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_pci.h
@@ -0,0 +1,93 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (PCI BIOS) */
+/* ========================================= */
+/* */
+/* SYS_PCI.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by PRR */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* routines for accessing PCI configuration info. */
+/* */
+/* The SYS_PCI.H file contains the exported function definitions for the */
+/* SYS_PCI.ASM module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_MEM.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_PCI_H 221
+
+export WBOOLEAN sys_pci_valid_machine( void );
+
+export WBOOLEAN sys_pci_read_config_dword(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ DWORD * dword_ptr
+ );
+
+export WBOOLEAN sys_pci_read_config_word(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ WORD * dword_ptr
+ );
+
+export WBOOLEAN sys_pci_read_config_byte(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ BYTE * byte_ptr
+ );
+
+export WBOOLEAN sys_pci_write_config_dword(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ DWORD dword
+ );
+
+export WBOOLEAN sys_pci_write_config_word(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ WORD word
+ );
+
+export WBOOLEAN sys_pci_write_config_byte(
+
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ BYTE byte
+ );
+
+export WBOOLEAN sys_pci_find_card( WORD FAR * PCIHandlePtr,
+ WORD Index,
+ WORD DeviceID);
+
+export WBOOLEAN sys_pci_get_io_base(WORD PCIHandle,
+ WORD FAR * BaseAddressPtr );
+
+export WBOOLEAN sys_pci_get_irq( WORD PCIHandle,
+ WORD FAR * IRQPtr );
+
+export WORD sys_pci_get_mem( WORD PCIHandle,
+ DWORD FAR * MemPtr);
+
+/* */
+/* */
+/************** End of SYS_PCI.H file ***************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_pcmc.h b/private/ntos/ndis/madge/driver/head_mod/sys_pcmc.h
new file mode 100644
index 000000000..9c16efca4
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_pcmc.h
@@ -0,0 +1,50 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (MEMORY IO) */
+/* ========================================== */
+/* */
+/* SYS_PCMC.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* memory allocation routines, interrupt and DMA channel enabling/disabling */
+/* routines, and routines for accessing IO ports. */
+/* */
+/* The SYS_PCMC.H file contains the exported function definitions for the */
+/* SYS_PCMC.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_MEM.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_PCMC_H 221
+
+
+/****************************************************************************/
+
+extern WBOOLEAN sys_pcmcia_point_enable(
+
+ ADAPTER* adapter
+ );
+
+extern void sys_pcmcia_point_disable(
+
+ ADAPTER* adapter
+ );
+
+/* */
+/* */
+/************** End of SYS_PCMC.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/sys_time.h b/private/ntos/ndis/madge/driver/head_mod/sys_time.h
new file mode 100644
index 000000000..b4a3932cd
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/sys_time.h
@@ -0,0 +1,52 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE DOS SYSTEM SPECIFIC MODULE (TIMERS) */
+/* ======================================= */
+/* */
+/* SYS_TIME.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The purpose of the DOS system specific module is to provide those */
+/* services that are influenced by the operating system. This includes */
+/* memory allocation routines, interrupt and DMA channel enabling/disabling */
+/* routines, and routines for accessing IO ports. */
+/* */
+/* The SYS_TIME.H file contains the exported function definitions for the */
+/* SYS_TIME.ASM module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this SYS_TIME.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_SYS_TIME_H 221
+
+
+/****************************************************************************/
+
+extern void sys_wait_at_least_milliseconds(
+
+ WORD number_of_milliseconds
+ );
+
+extern void sys_wait_at_least_microseconds(
+
+ WORD number_of_microseconds
+ );
+
+
+
+/* */
+/* */
+/************** End of SYS_TIME.H file **************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/head_mod/util.h b/private/ntos/ndis/madge/driver/head_mod/util.h
new file mode 100644
index 000000000..12d5c5ee1
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/head_mod/util.h
@@ -0,0 +1,80 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE UTILITIES MODULE */
+/* ==================== */
+/* */
+/* UTIL.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* Developed by MF */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* The UTIL.C utilities module provides a range of general purpose */
+/* utilities that are used throughout the FTK. These routines provide such */
+/* functions as the ability to copy strings, clear memory, byte swap node */
+/* addresses and caculate the minimum of three values. */
+/* */
+/* The UTIL.H file contains the exported function definitions for the */
+/* UTIL.C module. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this UTIL.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_UTIL_H 221
+
+
+/****************************************************************************/
+
+
+extern void util_string_copy(
+
+ char * copy_to_string,
+ char * copy_from_string
+ );
+
+extern void util_mem_copy(
+ BYTE * copy_to_string,
+ BYTE * copy_from_string,
+ UINT count
+ );
+
+
+extern void util_string_concatenate(
+
+ char * add_to_string,
+ char * string_to_add
+ );
+
+extern UINT util_minimum(
+
+ UINT val_1,
+ UINT val_2,
+ UINT val_3
+ );
+
+extern void util_zero_memory(
+
+ BYTE * memory,
+ UINT size_in_bytes
+ );
+
+extern void util_byte_swap_structure(
+
+ BYTE * byte_based_structure,
+ UINT size_of_structure
+ );
+
+
+/* */
+/* */
+/************** End of UTIL.H file ******************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/hwi_at.c b/private/ntos/ndis/madge/driver/hwi_at.c
new file mode 100644
index 000000000..fa9ed25dc
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_at.c
@@ -0,0 +1,2206 @@
+/****************************************************************************
+*
+* HWI_AT.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* HARDWARE INTERFACE MODULE FOR ATULA CARDS
+*
+* Copyright (c) Madge Networks Ltd. 1990-1994
+*
+* COMPANY CONFIDENTIAL
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_AT.C module contains the routines specific to 16/4 PC and 16/4
+* AT cards which are necessary to install an adapter, to initialize an
+* adapter, to remove an adapter and to handle interrupts on an adapter.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* Routines internal to FTK */
+#include "ftk_extr.h" /* Routines provided or used by external FTK user */
+
+#ifndef FTK_NO_ATULA
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local void
+hwi_atula_read_node_address(
+ ADAPTER * adapter
+ );
+
+local WBOOLEAN
+hwi_atula_valid_io_location(
+ WORD io_location
+ );
+
+#ifndef FTK_NO_PROBE
+
+local WORD
+hwi_atula_get_irq_channel(
+ WORD io_location,
+ UINT adapter_revision
+ );
+
+local WORD
+hwi_atula_get_dma_channel(
+ WORD io_location,
+ UINT adapter_revsion
+ );
+
+#endif
+
+local WORD
+hwi_atula_valid_transfer_mode(
+ ADAPTER * adapter
+ );
+
+local WORD
+hwi_atula_valid_irq_channel(
+ ADAPTER * adapter
+ );
+
+local WORD
+hwi_atula_valid_dma_channel(
+ ADAPTER * adapter
+ );
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL VARIABLES
+|
+---------------------------------------------------------------------------*/
+
+local BYTE atp_irq_select_table[16] =
+{
+ 0xff, /* 0 Unused */
+ 0xff, /* 1 Unused */
+ 0x07, /* 2 */
+ 0x06, /* 3 */
+ 0xff, /* 4 Unused */
+ 0x05, /* 5 */
+ 0xff, /* 6 Unused */
+ 0x04, /* 7 */
+ 0xff, /* 8 Unused */
+ 0x07, /* 9 */
+ 0x03, /* 10 */
+ 0x02, /* 11 */
+ 0x01, /* 12 */
+ 0xff, /* 13 Unused */
+ 0xff, /* 14 Unused */
+ 0x00 /* 15 */
+};
+
+local BYTE atp_dma_select_table[7] =
+{
+ 0xff, /* 0 Unused */
+ 0xff, /* 1 Unused */
+ 0xff, /* 2 Unused */
+ 0x08, /* 3 */
+ 0xff, /* 4 Unused */
+ 0x10, /* 5 */
+ 0x18 /* 6 */
+};
+
+local WORD adapter_card_at_rmsz_lut[7] =
+{
+ 128, /* 16/4 AT */
+ 128, /* 16/4 AT */
+ 256, /* 16/4 AT */
+ 256, /* 16/4 Fibre AT */
+ 256, /* 16/4 AT Bridgenode */
+ 128, /* 16/4 ISA Client */
+ 512 /* 16/4 AT Plus */
+};
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_atula_probe_card
+* ====================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is an array of IO locations to examine for the presence
+* of an adapter. For ATULA based adapters with should be a subset of
+* {0x0a20, 0x1a20, 0x2a20, 0x3a20}.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_atula_probe_card routine is called by hwi_probe_adapter. It
+* probes the adapter card for information such as DMA channel, IRQ number
+* etc. This information can then be supplied by the user when starting the
+* adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_probe_card)
+#endif
+
+export UINT
+hwi_atula_probe_card(
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ )
+{
+ WBOOLEAN card_found;
+ WORD control_1;
+ WORD control_2;
+ WORD status;
+ WORD control_6;
+ WORD control_7;
+ WORD bia_prom;
+ WORD bia_prom_id;
+ WORD bia_prom_adap;
+ WORD bia_prom_rev;
+ WORD bia_prom_hwf;
+ BYTE bia_temp_bd;
+ BYTE bia_temp_rev;
+ BYTE bia_temp_hwf;
+ UINT i;
+ UINT j;
+
+ /*
+ * Sanity check the bounds.
+ */
+
+ if (length <= 0 || number_locations <= 0)
+ {
+ return PROBE_FAILURE;
+ }
+
+ /*
+ * Validate the IO locations.
+ */
+
+ for (i = 0; i < number_locations; i++)
+ {
+ if (!hwi_atula_valid_io_location(valid_locations[i]))
+ {
+ return PROBE_FAILURE;
+ }
+ }
+
+ /*
+ * j is the number of adapters found.
+ */
+
+ j = 0;
+
+ for (i = 0; i < number_locations; i++)
+ {
+ /*
+ * Make sure that we haven't run out of PROBE structures.
+ */
+
+ if (j >= length)
+ {
+ return j;
+ }
+
+ /*
+ * Set up the ATULA control IO locations.
+ */
+
+ control_1 = valid_locations[i] + ATULA_CONTROL_REGISTER_1;
+ control_2 = valid_locations[i] + ATULA_CONTROL_REGISTER_2;
+ status = valid_locations[i] + ATULA_STATUS_REGISTER;
+ control_6 = valid_locations[i] + ATULA_CONTROL_REGISTER_6;
+ control_7 = valid_locations[i] + ATULA_CONTROL_REGISTER_7;
+ bia_prom = valid_locations[i] + ATULA_BIA_PROM;
+ bia_prom_id = bia_prom + BIA_PROM_ID_BYTE;
+ bia_prom_adap = bia_prom + BIA_PROM_ADAPTER_BYTE;
+ bia_prom_rev = bia_prom + BIA_PROM_REVISION_BYTE;
+ bia_prom_hwf = bia_prom + BIA_PROM_FEATURES_BYTE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_enable_io(valid_locations[i], ATULA_IO_RANGE);
+#endif
+
+ /*
+ * Reset adapter (ATULA_CTRL1_NRESET = 0).
+ */
+
+ sys_probe_outsb(control_1, 0);
+
+ /*
+ * Page in first page of BIA PROM.
+ * set ATULA_CTRL7_PAGE = 0 and ATULA_CTRL7_SIFSEL = 0.
+ */
+
+ sys_probe_outsb(control_7, 0);
+
+ /*
+ * Check we have a functioning adapter at the given IO location by
+ * checking the BIA PROM for an 'M' id byte and also by checking that
+ * the BIA adapter card byte is for a supported card type.
+ */
+
+ /*
+ * At the moment there are four major board types that are acceptable
+ * AT, PC, MAXY, and ATP.
+ */
+
+ card_found = FALSE;
+
+ if (sys_probe_insb(bia_prom_id) == 'M')
+ {
+ bia_temp_bd = sys_probe_insb(bia_prom_adap);
+ bia_temp_rev = sys_probe_insb(bia_prom_rev);
+ bia_temp_hwf = sys_probe_insb(bia_prom_hwf);
+
+ if (bia_temp_bd == BIA_PROM_TYPE_16_4_PC)
+ {
+ resources[j].adapter_card_revision = ADAPTER_CARD_16_4_PC;
+ resources[j].adapter_ram_size = 128;
+ card_found = TRUE;
+ }
+ else if (bia_temp_bd == BIA_PROM_TYPE_16_4_MAXY)
+ {
+ resources[j].adapter_card_revision = ADAPTER_CARD_16_4_MAXY;
+ resources[j].adapter_ram_size = 256;
+ card_found = TRUE;
+ }
+ else if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT)
+ {
+ if (bia_temp_rev <= MAX_ADAPTER_CARD_AT_REV)
+ {
+ resources[j].adapter_ram_size = adapter_card_at_rmsz_lut[bia_temp_rev];
+ }
+ else
+ {
+ resources[j].adapter_ram_size = 128;
+ }
+
+ if (bia_temp_rev < ADAPTER_CARD_16_4_AT)
+ {
+ resources[j].adapter_card_revision = ADAPTER_CARD_16_4_AT;
+ }
+ else
+ {
+ resources[j].adapter_card_revision = bia_temp_rev;
+ }
+ card_found = TRUE;
+ }
+ else if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT_P)
+ {
+ resources[j].adapter_ram_size = 512;
+
+ switch(bia_temp_rev)
+ {
+ case ADAPTER_CARD_16_4_FIBRE:
+ resources[j].adapter_card_revision = ADAPTER_CARD_16_4_FIBRE_P;
+ break;
+ case ADAPTER_CARD_16_4_ISA_C:
+ resources[j].adapter_card_revision = ADAPTER_CARD_16_4_ISA_C_P;
+ resources[j].adapter_ram_size = 128;
+ break;
+ case ADAPTER_CARD_16_4_AT_P_REV:
+ resources[j].adapter_card_revision = ADAPTER_CARD_16_4_AT_P;
+ break;
+ default:
+ resources[j].adapter_card_revision = ADAPTER_CARD_UNKNOWN;
+ break;
+ }
+
+ card_found = TRUE;
+ }
+ }
+
+ /*
+ * Check for the features byte - if it is non-zero, it may override our
+ * RAM size calculations.
+ */
+
+ if (bia_temp_hwf)
+ {
+ UINT dram = (bia_temp_hwf & BIA_PROM_FEATURE_DRAM_MASK) * DRAM_MULT;
+
+ if (dram)
+ {
+ resources[j].adapter_ram_size = dram;
+ }
+ }
+
+ /*
+ * If we've found an adapter then we need to make a note of
+ * the IO location and attempt to determine the interrupt
+ * number and DMA channel.
+ */
+
+ if (card_found)
+ {
+ resources[j].io_location = valid_locations[i];
+ resources[j].adapter_card_bus_type = ADAPTER_CARD_ATULA_BUS_TYPE;
+ resources[j].adapter_card_type = ADAPTER_CARD_TYPE_16_4_AT;
+
+ resources[j].dma_channel = hwi_atula_get_dma_channel(
+ valid_locations[i],
+ resources[j].adapter_card_revision
+ );
+
+ /*
+ * If we get a DMA channel of 0 back then we can't use DMA so
+ * default the transfer mode to PIO. Otherwise we'll set the
+ * transfer mode to DMA.
+ */
+
+ if (resources[j].dma_channel == 0)
+ {
+ resources[j].transfer_mode = PIO_DATA_TRANSFER_MODE;
+ }
+ else
+ {
+ resources[j].transfer_mode = DMA_DATA_TRANSFER_MODE;
+ }
+
+ resources[j].interrupt_number = hwi_atula_get_irq_channel(
+ valid_locations[i],
+ resources[j].adapter_card_revision
+ );
+
+ /*
+ * And note that we've found an adapter.
+ */
+
+ j++;
+ }
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_disable_io(valid_locations[i], ATULA_IO_RANGE);
+#endif
+ }
+
+ return j;
+}
+#endif /* FTK_NO_PROBE */
+
+#ifndef FTK_NO_DETECT
+/****************************************************************************/
+/* */
+/* hwi_atula_read_rate_error */
+/* ========================= */
+/* */
+/* */
+/* PARAMETERS : */
+/* ============ */
+/* */
+/* adapter : The ubiqitous adapter structure. */
+/* */
+/* BODY : */
+/* ====== */
+/* */
+/* The hwi_atula_read_rate_error reads the NRATE_ERR signal from the */
+/* adapter DIO space. This is read from chapter 0 address 0. */
+/* */
+/* RETURNS : */
+/* ========= */
+/* */
+/* The routine returns RATE_ERROR if there is a rate error, 0 if there is no*/
+/* error, and NOT_SUPP if the card doesn't support this. */
+/* */
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_read_rate_error)
+#endif
+
+export WORD hwi_atula_read_rate_error( ADAPTER * adapter
+ )
+{
+ WBOOLEAN ret_code;
+ WORD error_word;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter );
+#endif
+
+ if (adapter->speed_detect == TRUE)
+ {
+ hwi_atula_set_dio_address( adapter, 0x00000000L);
+
+ sys_outsw( adapter->adapter_handle, adapter->sif_adr, 0x0);
+
+
+ error_word = sys_insw( adapter->adapter_handle, adapter->sif_dat) & 0x0080;
+
+ hwi_atula_set_dio_address( adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ if (error_word & 0x0080)
+ {
+ ret_code = 0;
+ }
+ else
+ {
+ ret_code = RATE_ERROR;
+ }
+ }
+ else
+ {
+ ret_code = NOT_SUPP;
+ }
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter );
+#endif
+
+ return ret_code;
+}
+#endif /* FTK_NO_DETECT */
+
+/****************************************************************************
+*
+* hwi_atula_install_card
+* ======================
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+* BODY :
+* ======
+*
+* The hwi_atula_install_card routine is called by hwi_install_adapter. It
+* sets up the adapter card and downloads the required code to it. Firstly,
+* it checks there is a valid adapter at the required IO address. If so it
+* reads the node address from the BIA PROM and sets up and checks numerous
+* on-board registers for correct operation.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls.
+* Similarly, operating system calls are used to enable DMA if required. If
+* DMA is not used then the adapter is set up for PIO.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_install_card)
+#endif
+
+export WBOOLEAN
+hwi_atula_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ WBOOLEAN is_soft_prog = FALSE;
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location + ATULA_CONTROL_REGISTER_1;
+ WORD control_2 = adapter->io_location + ATULA_CONTROL_REGISTER_2;
+ WORD status = adapter->io_location + ATULA_STATUS_REGISTER;
+ WORD control_6 = adapter->io_location + ATULA_CONTROL_REGISTER_6;
+ WORD control_7 = adapter->io_location + ATULA_CONTROL_REGISTER_7;
+ WORD bia_prom = adapter->io_location + ATULA_BIA_PROM;
+ WORD bia_prom_id = bia_prom + BIA_PROM_ID_BYTE;
+ WORD bia_prom_adap = bia_prom + BIA_PROM_ADAPTER_BYTE;
+ WORD bia_prom_rev = bia_prom + BIA_PROM_REVISION_BYTE;
+ WORD bia_prom_hwf = bia_prom + BIA_PROM_FEATURES_BYTE;
+ WORD bia_prom_hwf2 = bia_prom + BIA_PROM_HWF2;
+ WORD bia_prom_hwf3 = bia_prom + BIA_PROM_HWF3;
+ BYTE control_6_out;
+ BYTE dummy_sifdat;
+ BYTE bia_temp_bd = 0;
+ BYTE bia_temp_rev = 0;
+ BYTE bia_temp_hwf = 0;
+ BYTE bia_temp_hwf2 = 0;
+ BYTE bia_temp_hwf3 = 0;
+ WBOOLEAN card_found;
+ WORD sif_base;
+
+ /*
+ * Check that the IO location is valid.
+ */
+
+ if (!hwi_atula_valid_io_location(adapter->io_location))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION;
+
+ return FALSE;
+ }
+
+ /*
+ * Record the locations of the SIF registers.
+ */
+
+ sif_base = adapter->io_location + ATULA_FIRST_SIF_REGISTER;
+
+ adapter->sif_dat = sif_base + EAGLE_SIFDAT;
+ adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC;
+ adapter->sif_adr = sif_base + EAGLE_SIFADR;
+ adapter->sif_int = sif_base + EAGLE_SIFINT;
+ adapter->sif_acl = sif_base + ATULA_EAGLE_SIFACL;
+ adapter->sif_adr2 = sif_base + ATULA_EAGLE_SIFADR_2;
+ adapter->sif_adx = sif_base + ATULA_EAGLE_SIFADX;
+ adapter->sif_dmalen = sif_base + ATULA_EAGLE_DMALEN;
+
+ adapter->io_range = ATULA_IO_RANGE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Enable adapter card interrupts.
+ */
+
+ sys_outsb(handle, control_2, ATULA_CTRL2_INTEN);
+
+ /*
+ * Reset adapter (ATULA_CTRL1_NRESET = 0).
+ */
+
+ sys_outsb(handle, control_1, 0);
+
+ /*
+ * Page in first page of BIA PROM.
+ * Set ATULA_CTRL7_PAGE = 0 and ATULA_CTRL7_SIFSEL = 0.
+ */
+
+ sys_outsb(handle, control_7, 0);
+
+ /*
+ * Check we have a functioning adapter at the given IO location by
+ * checking the BIA PROM for an 'M' id byte and also by checking that
+ * the BIA adapter card byte is for a supported card type.
+ */
+
+ /*
+ * At the moment there are four major board types that are acceptable
+ * AT, PC, MAXY, and ATP.
+ */
+
+ card_found = FALSE;
+
+ if (sys_insb(handle, bia_prom_id) == 'M')
+ {
+ bia_temp_bd = sys_insb(handle, bia_prom_adap);
+ bia_temp_rev = sys_insb(handle, bia_prom_rev);
+ bia_temp_hwf = sys_insb(handle, bia_prom_hwf);
+ bia_temp_hwf2 = sys_insb(handle, bia_prom_hwf2);
+ bia_temp_hwf3 = sys_insb(handle, bia_prom_hwf3);
+
+ if (bia_temp_bd == BIA_PROM_TYPE_16_4_PC)
+ {
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_PC;
+ adapter->adapter_ram_size = 128;
+ card_found = TRUE;
+ }
+ else if (bia_temp_bd == BIA_PROM_TYPE_16_4_MAXY)
+ {
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_MAXY;
+ adapter->adapter_ram_size = 256;
+ card_found = TRUE;
+ }
+ else if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT)
+ {
+ if (bia_temp_rev <= MAX_ADAPTER_CARD_AT_REV)
+ {
+ adapter->adapter_ram_size = adapter_card_at_rmsz_lut[bia_temp_rev];
+ }
+ else
+ {
+ adapter->adapter_ram_size = 128;
+ }
+
+ if (bia_temp_rev < ADAPTER_CARD_16_4_AT)
+ {
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_AT;
+ }
+ else
+ {
+ adapter->adapter_card_revision = bia_temp_rev;
+ }
+
+ card_found = TRUE;
+ }
+ else if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT_P)
+ {
+ adapter->adapter_ram_size = 512;
+
+ switch(bia_temp_rev)
+ {
+ case ADAPTER_CARD_16_4_FIBRE:
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_FIBRE_P;
+ break;
+ case ADAPTER_CARD_16_4_ISA_C:
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_ISA_C_P;
+ adapter->adapter_ram_size = 128;
+ adapter->mc32_config = MC_AND_ISACP_USE_PIO;
+ break;
+ case ADAPTER_CARD_16_4_AT_P_REV:
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_AT_P;
+ break;
+ default:
+ adapter->adapter_card_revision = ADAPTER_CARD_UNKNOWN;
+ break;
+ }
+
+ card_found = TRUE;
+ }
+ }
+
+ /*
+ * If no ATULA card found then fill in error record and return.
+ */
+
+ if (!card_found)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Sanity check the interrupt number and DMA channel. The checking
+ * routines fill in the error record in the adapter structure.
+ */
+
+ if (!hwi_atula_valid_irq_channel(adapter) ||
+ !hwi_atula_valid_transfer_mode(adapter) ||
+ !hwi_atula_valid_dma_channel(adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Note the major card type.
+ */
+
+ adapter->adapter_card_type = ADAPTER_CARD_TYPE_16_4_AT;
+
+ /*
+ * If this card has a C30 on board and the ring speed bit is set then
+ * we support ring speed detect.
+ */
+
+ if (((bia_temp_hwf2 & 0x3) == C30 ) && (bia_temp_hwf3 & RSPEED_DETECT))
+ {
+ adapter->speed_detect = TRUE;
+ }
+
+ /*
+ * Now we need to check for AT/P cards - these need special processing.
+ */
+
+ if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT_P ||
+ bia_temp_rev == ADAPTER_CARD_16_4_AT_P_REV)
+ {
+ WORD atp_eisa_rev2 = adapter->io_location + AT_P_EISA_REV2_CTRL_REG;
+ BYTE eisa_rev2_byte = 0;
+
+ if (bia_temp_bd == BIA_PROM_TYPE_16_4_AT_P)
+ {
+ eisa_rev2_byte |= ATP_RSCTRL;
+ }
+
+ if ((bia_temp_hwf & BIA_PROM_FEATURE_CLKDIV_MASK) ||
+ (bia_temp_rev == ADAPTER_CARD_16_4_ISA_C))
+ {
+ eisa_rev2_byte |= ATP_CLKDIV;
+ }
+
+ sys_outsb(handle, atp_eisa_rev2, eisa_rev2_byte);
+
+ is_soft_prog = TRUE;
+ }
+
+ /*
+ * Check for the features byte - if it is non-zero, it may override our
+ * RAM size calculations.
+ */
+
+ if (bia_temp_hwf)
+ {
+ UINT dram = (bia_temp_hwf & BIA_PROM_FEATURE_DRAM_MASK) * DRAM_MULT;
+
+ if (dram)
+ {
+ adapter->adapter_ram_size = dram;
+ }
+ }
+
+ /*
+ * The user might have asked to override the card configuration with
+ * the values supplied - this only works for ATPs and ISA/C/Ps.
+ */
+
+ if (is_soft_prog)
+ {
+ WORD atp_sw_config = adapter->io_location + AT_P_SW_CONFIG_REG;
+ BYTE config_byte;
+ UINT int_num = adapter->interrupt_number;
+ UINT dma_chan = adapter->dma_channel;
+
+ if (adapter->set_irq || adapter->set_dma || adapter->set_ring_speed)
+ {
+ config_byte = sys_insb(handle, atp_sw_config);
+
+ /*
+ * Override the interrupt number.
+ */
+
+ if (adapter->set_irq &&
+ int_num < sizeof(atp_irq_select_table) &&
+ atp_irq_select_table[int_num] != 0xff)
+ {
+ config_byte = (config_byte & ~ATP_INTSEL) |
+ atp_irq_select_table[int_num];
+ }
+
+ /*
+ * Override the DMA channel.
+ */
+
+ if (adapter->set_dma &&
+ dma_chan < sizeof(atp_dma_select_table) &&
+ atp_dma_select_table[dma_chan] != 0xff)
+ {
+ config_byte = (config_byte & ~ATP_DMA) |
+ atp_dma_select_table[dma_chan];
+ }
+
+ /*
+ * Set the ring speed.
+ */
+
+ if (adapter->set_ring_speed == 16)
+ {
+ config_byte = (config_byte & ~ATP_S4N16);
+ }
+ else if (adapter->set_ring_speed == 4)
+ {
+ config_byte = (config_byte | ATP_S4N16);
+ }
+
+ sys_outsb(handle, atp_sw_config, config_byte);
+ }
+ }
+
+ /*
+ * May have changed from software running in bus master to PIO.
+ * Hence get spurious data at ?a28 cos of DLATCH bug in ATULA hardware
+ * so get next read data as if doing PIO data transfer.
+ * Hence do extra read from ?a28 to fix bug.
+ */
+
+ dummy_sifdat = sys_insb(handle, adapter->sif_dat);
+
+ /*
+ * Check here to see if we have to force card to 16 Mb/s for a none
+ * soft programmable card.
+ */
+
+ if (!is_soft_prog && adapter->set_ring_speed == 16)
+ {
+ macro_setb_bit(handle, control_1, ATULA_CTRL1_4_16_SEL);
+ }
+
+ /*
+ * Interrupts for ATULA cards are always edge triggered.
+ */
+
+ adapter->edge_triggered_ints = TRUE;
+
+ /*
+ * Machine reset does not affect speed or media setting of ATULA cards.
+ */
+
+ /*
+ * Find the adapter card node address.
+ */
+
+ hwi_atula_read_node_address(adapter);
+
+ /*
+ * If have REV3 adapter type then must set up special bus timings
+ * must do this before any SIF register access
+ * on 16/4 PC doing this is not necessary but has no effect
+ */
+
+ if ((sys_insb(handle, control_7) & ATULA_CTRL7_REV_4) == 0)
+ {
+ /*
+ * Note that a sys_outsb here will clear the INTEN bit that was set
+ * earlier on. This does not matter, however, because we have found
+ * the interrupt vector by this stage. If this does become a problem,
+ * use macro_setb_bit().
+ */
+
+ sys_outsb(handle, control_2, ATULA_CTRL2_CS16DLY);
+ }
+
+ /*
+ * Set control register 6 for normal or synchronous bus operation.
+ * Use status register to get bus operation mode. On 16/4 PC will always
+ * in fact have normal bus operation.
+ */
+
+ control_6_out = 0;
+
+ if ((sys_insb(handle, status) & ATULA_STATUS_ASYN_BUS) != 0)
+ {
+ control_6_out |= ATULA_CTRL6_CLKSEL_ON_BOARD;
+ }
+ else
+ {
+ control_6_out |= ATULA_CTRL6_CLKSEL_HOST;
+ }
+
+ /*
+ * If want to use DMA, need a 16 bit slot.
+ * Note that 16/4 PC will always be in an 8 bit slot.
+ */
+
+ if ((adapter->transfer_mode == DMA_DATA_TRANSFER_MODE) &&
+ ((sys_insb(handle, status) & ATULA_STATUS_BUS8) != 0))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_06_CANNOT_USE_DMA;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Set up transfer mode now that we know we are in a valid slot.
+ */
+
+ if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
+ {
+ control_6_out |= ATULA_CTRL6_MODE_BUS_MASTER;
+ }
+ else
+ {
+ control_6_out |= ATULA_CTRL6_MODE_PIO;
+ }
+
+ /*
+ * Now output to control register 6 the required value we have set up.
+ */
+
+ sys_outsb(handle, control_6, control_6_out);
+
+ /*
+ * Wait at least 10 milliseconds and bring adapter out of reset state.
+ * 10ms is the minimum time must hold ATULA_CTRL1_NRESET low after
+ * changing ATULA_CTRL6_CLKSEL bits. Disable and re-enable accessing
+ * IO locations around wait so delay can reschedule this task and not
+ * effect others running.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ sys_wait_at_least_milliseconds(10);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ macro_setb_bit( handle, control_1, ATULA_CTRL1_NSRESET);
+
+ /*
+ * Get extended SIF registers, halt EAGLE, then get normal SIF regs.
+ */
+
+ macro_setb_bit(handle, control_7, ATULA_CTRL7_SIFSEL);
+ macro_setb_bit(handle, control_1, ATULA_CTRL1_SRSX);
+
+ hwi_halt_eagle(adapter);
+
+ macro_clearb_bit(handle, control_1, ATULA_CTRL1_SRSX);
+
+ /*
+ * Download code to adapter. View download image as a sequence of
+ * download records. Pass address of routine to set up DIO addresses
+ * on ATULA cards. If routine fails return failure (error record
+ * already filled in).
+ */
+
+ if (!hwi_download_code(
+ adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_atula_set_dio_address
+ ))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Get extended SIF registers, start EAGLE, then get normal SIF regs.
+ */
+
+ macro_setb_bit(handle, control_1, ATULA_CTRL1_SRSX);
+
+ hwi_start_eagle(adapter);
+
+ macro_clearb_bit(handle, control_1, ATULA_CTRL1_SRSX);
+
+ /*
+ * Wait for a valid bring up code, may wait 3 seconds.
+ * if routine fails return failure (error record already filled in).
+ */
+
+ if (!hwi_get_bring_up_code(adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Set DIO address to point to EAGLE DATA page 0x10000L.
+ */
+
+ hwi_atula_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * Set maximum frame size from the ring speed.
+ */
+
+ adapter->max_frame_size = hwi_get_max_frame_size(adapter);
+ adapter->ring_speed = hwi_get_ring_speed(adapter);
+
+ /*
+ * If not in polling mode then set up interrupts. Interrupts_on
+ * field is used when disabling interrupts for adapter.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on =
+ sys_enable_irq_channel(handle, adapter->interrupt_number);
+
+ /*
+ * If fail enable irq channel then fill in error record and return.
+ */
+
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+ /*
+ * Enable interrupts at adapter (do this even in polling mode).
+ * Hence when polling still 'using' interrupt channel.
+ * So do not use card interrupt switch setting shared by other devices.
+ */
+
+ macro_setb_bit( handle, control_1, ATULA_CTRL1_SINTREN);
+ macro_setb_bit( handle, control_2, ATULA_CTRL2_INTEN);
+
+ /*
+ * Set up PIO or DMA as required.
+ */
+
+ if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
+ {
+ /*
+ * Bus master DMA. This is not possible for 16/4 PC adapters.
+ * Enable DMA at adapter and then call system service routine.
+ * Must enable DMA at adapter before enable DMA channel
+ * otherwise machine will 'crash'. Also important that DMA
+ * channel is correct for same reason. dma_on field is used
+ * when disabling DMA for adapter.
+ */
+
+ macro_setb_bit(handle, control_6, ATULA_CTRL6_DMAEN);
+
+ adapter->dma_on = sys_enable_dma_channel(handle, adapter->dma_channel);
+
+ /*
+ * If we fail to enable dma channel then fill in error record
+ * and return also disable DMA at adapter because of failure.
+ */
+
+ if (!adapter->dma_on)
+ {
+ macro_clearb_bit(handle, control_6, ATULA_CTRL6_DMAEN);
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0C_FAIL_DMA_ENABLE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ /*
+ * PIO mode. This is only data transfer mode possible for
+ * 16/4 PC adapters. Enable PIO interrupt.
+ */
+
+ macro_setb_bit(handle, control_2, ATULA_CTRL2_SHRQEN);
+ }
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ /*
+ * Return successfully.
+ */
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* hwi_atula_interrupt_handler
+* ===========================
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* BODY :
+* ======
+*
+* The hwi_atula_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF or by the
+* ATULA in order to do a PIO data transfer. Note it could in fact be the
+* case that no interrupt has occured on the particular adapter being
+* checked.
+*
+* On SIF interrupts, the interrupt is acknowledged and cleared. The value
+* in the SIF interrupt register is recorded in order to pass it to the
+* driver_interrupt_entry routine (along with the adapter details).
+*
+* On PIO interrupts, the length, direction and physical address of the
+* transfer is determined. A system provided routine is called to do the
+* data transfer itself. Note the EAGLE thinks it is doing a DMA transfer
+* - it is the ATULA which allows us to do it via in/out instructions. Also
+* note that the IO location for the PIO is mapped onto the location of the
+* EAGLE SIFDAT register - the PIO does not actually use the SIFDAT
+* register so it's value is not effected by this routine.
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_atula_interrupt_handler)
+#endif
+
+export void
+hwi_atula_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location + ATULA_CONTROL_REGISTER_1;
+ WORD control_2 = adapter->io_location + ATULA_CONTROL_REGISTER_2;
+ WORD status = adapter->io_location + ATULA_STATUS_REGISTER;
+ WORD control_7 = adapter->io_location + ATULA_CONTROL_REGISTER_7;
+ WORD sifadr = adapter->sif_adr;
+ WORD sifdat = adapter->sif_dat;
+ WORD sifint = adapter->sif_int;
+ WORD sifint_value;
+ WORD sifint_tmp;
+ BYTE FAR * pio_virtaddr;
+ WORD pio_len_bytes;
+ WBOOLEAN pio_from_adapter;
+ WORD saved_sifadr;
+ UINT dummy;
+ DWORD dma_high_word;
+ WORD dma_low_word;
+
+ /*
+ * Inform system about the IO ports we are going to access.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Check for SIF interrupt or PIO interrupt.
+ */
+
+ if ((sys_insb(handle, control_7) & ATULA_CTRL7_SINTR) != 0)
+ {
+ /*
+ * SIF interrupt has occurred. SRB free, adapter check
+ * or received frame interrupt.
+ */
+
+ /*
+ * Toggle SIF interrupt enable to acknowledge interrupt at ATULA.
+ */
+
+ macro_clearb_bit(handle, control_1, ATULA_CTRL1_SINTREN);
+ macro_setb_bit(handle, control_1, ATULA_CTRL1_SINTREN);
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+ */
+
+ /*
+ * WARNING: Do NOT reorder the clearing of the SIFINT register with
+ * the reading of it. If SIFINT is cleared after reading it, any
+ * interrupts raised after reading it will be lost. Admittedly
+ * this is a small time frame, but it is important.
+ */
+
+ sys_outsw(handle, sifint, 0);
+
+ /*
+ * Record the EAGLE SIF interrupt register value.
+ */
+
+ /*
+ * WARNING: Continue to read the SIFINT register until it is stable
+ * because of a potential problem involving the host reading the
+ * register after the adapter has written the low byte of it, but
+ * before it has written the high byte. Failure to wait for the
+ * SIFINT register to settle can cause spurious interrupts.
+ */
+
+ sifint_value = sys_insw(handle, sifint);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(handle, sifint);
+ }
+ while (sifint_tmp != sifint_value);
+
+ /*
+ * Acknowledge/clear interrupt at interrupt controller.
+ */
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(handle, adapter->interrupt_number);
+#endif
+
+ /*
+ * Toggle interrupt enable bit to regenerate any lost interrupts.
+ * Need do this because using edge triggered interrupts.
+ */
+
+ macro_clearb_bit(handle, control_2, ATULA_CTRL2_INTEN);
+ macro_setb_bit(handle, control_2, ATULA_CTRL2_INTEN);
+
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+ driver_interrupt_entry(handle, adapter, sifint_value);
+ }
+ else if ((sys_insb(handle, control_2) & ATULA_CTRL2_SHRQ) != 0)
+ {
+ /*
+ * PIO interrupt has occurred. Data transfer to/from adapter
+ * interrupt.
+ */
+
+ /*
+ * Toggle PIO interrupt enable to acknowledge interrupt at ATULA.
+ */
+
+ macro_clearb_bit(handle, control_2, ATULA_CTRL2_SHRQEN);
+ macro_setb_bit(handle, control_2, ATULA_CTRL2_SHRQEN);
+
+ /*
+ * We must preserve the value of SIF address in case we have
+ * interrupted someone who relies on it not chaning.
+ */
+
+ saved_sifadr = sys_insw(handle, adapter->sif_adr);
+
+ /*
+ * Read the virtual address for the PIO through DIO space from the
+ * SIF registers. Because the SIF thinks that it is doing real DMA,
+ * the SDMAADR/SDMAADX registers cannot be paged in, so they must
+ * be read from their memory mapped locations in Eagle memory.
+ */
+
+ sys_outsw(handle, sifadr, DIO_LOCATION_EXT_DMA_ADDR);
+ dma_high_word = (DWORD) sys_insw(handle, sifdat);
+
+ sys_outsw(handle, sifadr, DIO_LOCATION_DMA_ADDR);
+ dma_low_word = sys_insw(handle, sifdat);
+
+ pio_virtaddr = (BYTE FAR *) ((dma_high_word << 16) | ((DWORD) dma_low_word));
+
+ /*
+ * Read the DMA length from the extended SIF register.
+ */
+
+ macro_setb_bit(handle, control_1, ATULA_CTRL1_SRSX);
+ pio_len_bytes = sys_insw(handle, adapter->sif_dmalen);
+ macro_clearb_bit( handle, control_1, ATULA_CTRL1_SRSX);
+
+ /*
+ * If we are talking to the ISA Client/P, we need to use software
+ * handshaking across the PIO. Start by writing zero to a magic
+ * location on the adapter.
+ */
+
+ if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P)
+ {
+ sys_outsw(handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(handle, sifdat, 0);
+ }
+
+ /*
+ * Start what the SIF thinks is a DMA but is PIO instead.
+ */
+
+ macro_setb_bit(handle, control_2, ATULA_CTRL2_SHLDA);
+
+ /*
+ * Determine what direction the data transfer is to take place in.
+ */
+
+ pio_from_adapter = sys_insb(handle, status) & ATULA_STATUS_SDDIR;
+
+ /*
+ * Do the actual data transfer. Note that Fastmac only copies whole
+ * WORDs to DWORD boundaries. FastmacPlus, however, can transfer
+ * any length to any address.
+ */
+
+ if (pio_from_adapter)
+ {
+ /*
+ * Transfer into host memory from adapter.
+ */
+
+ /*
+ * First, check if host address is on an odd byte boundary.
+ */
+
+ if ((card_t) pio_virtaddr % 2)
+ {
+ pio_len_bytes--;
+ *(pio_virtaddr++) =
+ sys_insb(handle, (WORD) (sifdat + ATULA_PIO_IO_LOC + 1));
+ }
+
+ /*
+ * Now transfer the bulk of the data.
+ */
+
+ sys_rep_insw(
+ handle,
+ (WORD) (sifdat + ATULA_PIO_IO_LOC),
+ pio_virtaddr,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ /*
+ * Finally transfer any trailing byte.
+ */
+
+ if (pio_len_bytes % 2)
+ {
+ *(pio_virtaddr + pio_len_bytes - 1) =
+ sys_insb(handle, (WORD) (sifdat + ATULA_PIO_IO_LOC));
+ }
+ }
+ else
+ {
+ /*
+ * Transfer into adapter memory from the host.
+ */
+
+ /*
+ * If we are talking to an ISA Client/P card, we need to assert
+ * the -CLKDIV signal to prevent dips in one of the signals to
+ * the ATULA. This is only needed for ISA/C/P transmits.
+ */
+
+ if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P &&
+ pio_len_bytes > 13)
+ {
+ /*
+ * Need to write ATP_RSCTRL to ATP_EISA_REV2_CTRL reg.
+ */
+
+ sys_outsb(
+ handle,
+ (WORD) (adapter->io_location + AT_P_EISA_REV2_CTRL_REG),
+ ATP_RSCTRL
+ );
+ }
+
+ /*
+ * First, check if host address is on an odd byte boundary.
+ */
+
+ if ((card_t) pio_virtaddr % 2)
+ {
+ pio_len_bytes--;
+ sys_outsb(
+ handle,
+ (WORD) (sifdat + ATULA_PIO_IO_LOC + 1),
+ *(pio_virtaddr++)
+ );
+ }
+
+ /*
+ * Now transfer the bulk of the data.
+ */
+
+ sys_rep_outsw(
+ handle,
+ (WORD) (sifdat + ATULA_PIO_IO_LOC),
+ pio_virtaddr,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ /*
+ * Finally transfer any trailing byte.
+ */
+
+ if (pio_len_bytes % 2)
+ {
+ sys_outsb(
+ handle,
+ (WORD) (sifdat + ATULA_PIO_IO_LOC),
+ *(pio_virtaddr + pio_len_bytes - 1)
+ );
+ }
+
+ /*
+ * If we are talking to an ISA Client/P card, we need to remove
+ * the -CLKDIV signal that we asserted above.
+ */
+
+ if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P &&
+ pio_len_bytes > 13)
+ {
+ /*
+ * Deassert the -CLKDIV signal that we asserted up above.
+ */
+
+ sys_outsb(
+ handle,
+ (WORD) (adapter->io_location + AT_P_EISA_REV2_CTRL_REG),
+ ATP_RSCTRL | ATP_CLKDIV
+ );
+ }
+ }
+
+ /*
+ * If we are talking to an ISA Client/P card, we now finish off the
+ * software handshake process that we started at the beginning.
+ */
+
+ if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P)
+ {
+ /*
+ * Do a read first - otherwise the write might fail.
+ */
+
+ sys_outsw(handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ dummy = sys_insw(handle, sifdat);
+
+ sys_outsw(handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(handle, sifdat, 0xFFFF);
+ }
+
+ /*
+ * Restore the SIF address.
+ */
+
+ sys_outsw(handle, adapter->sif_adr, saved_sifadr);
+
+ /*
+ * Acknowledge/clear interrupt at interrupt controller.
+ */
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(handle, adapter->interrupt_number);
+#endif
+
+ /*
+ * Toggle interrupt enable bit to regenerate any lost interrupts.
+ */
+
+ macro_clearb_bit(handle, control_2, ATULA_CTRL2_INTEN);
+ macro_setb_bit(handle, control_2, ATULA_CTRL2_INTEN);
+ }
+
+ /*
+ * Let system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_atula_remove_card
+* =====================
+*
+* PARAMETERS (passed by hwi_remove_adapter) :
+* ===========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* BODY :
+* ======
+*
+* The hwi_atula_remove_card routine is called by hwi_remove_adapter. It
+* disables DMA and interrupts if they are being used. It also resets the
+* adapter.
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_atula_remove_card)
+#endif
+
+export void
+hwi_atula_remove_card(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location + ATULA_CONTROL_REGISTER_1;
+ WORD control_2 = adapter->io_location + ATULA_CONTROL_REGISTER_2;
+ WORD control_6 = adapter->io_location + ATULA_CONTROL_REGISTER_6;
+
+ /*
+ * Disable DMA if successfully enabled. DMA will only be on if not
+ * in PIO mode. DMA channel must be disabled before disabling DMA
+ * at adapter otherwise machine will 'crash'.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ if (adapter->dma_on)
+ {
+ sys_disable_dma_channel(handle, adapter->dma_channel);
+
+ macro_clearb_bit(handle, control_6, ATULA_CTRL6_DMAEN);
+
+ adapter->dma_on = FALSE;
+ }
+
+ /*
+ * Disable interrupts being generated. Only need to do this if
+ * interrupts successfully enabled. Interrupt must be disabled at
+ * adapter before unpatching interrupt. Even in polling mode we
+ * must turn off interrupts at adapter.
+ */
+
+ if (adapter->interrupts_on)
+ {
+ macro_clearb_bit(handle, control_2, ATULA_CTRL2_INTEN);
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(handle, adapter->interrupt_number);
+ }
+
+ adapter->interrupts_on = FALSE;
+ }
+
+ /*
+ * Perform adapter reset, set ATULA_CTRL1_NSRESET low.
+ */
+
+ sys_outsb(handle, control_1, 0);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_atula_set_dio_address
+* =========================
+* PARAMETERS :
+* ============
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DWORD dio_address
+*
+* The 32 bit DIO address to select.
+*
+* BODY :
+* ======
+*
+* The hwi_atula_set_dio_address routine is used, with ATULA cards, for
+* putting a 32 bit DIO address into the SIF DIO address and extended DIO
+* address registers. Note that the extended address register should be
+* loaded first.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_set_dio_address)
+#endif
+
+export void
+hwi_atula_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location + ATULA_CONTROL_REGISTER_1;
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * Page in extended SIF registers.
+ */
+
+ macro_setb_bit(handle, control_1, ATULA_CTRL1_SRSX);
+
+ /*
+ * Load extended DIO address register with top 16 bits of address.
+ * Always load extended address register first.
+ */
+
+ sys_outsw(handle, sif_dio_adrx, (WORD) (dio_address >> 16));
+
+ /*
+ * Return to having normal SIF registers paged in.
+ */
+
+ macro_clearb_bit(handle, control_1, ATULA_CTRL1_SRSX);
+
+ /*
+ * Load DIO address register with low 16 bits of address.
+ */
+
+ sys_outsw(handle, sif_dio_adr, (WORD) (dio_address & 0x0000FFFF));
+}
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|
+| hwi_atula_valid_io_location
+| ===========================
+|
+| The hwi_atula_valid_io_location routine checks to see if the user has
+| supplied a valid IO location for an ATULA based adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_valid_io_location)
+#endif
+
+local WBOOLEAN
+hwi_atula_valid_io_location(
+ WORD io_location
+ )
+{
+ WBOOLEAN io_valid;
+
+ switch (io_location)
+ {
+ case 0x0A20 :
+ case 0x1A20 :
+ case 0x2A20 :
+ case 0x3A20 :
+
+ /*
+ * These are the valid user supplied io locations.
+ */
+
+ io_valid = TRUE;
+ break;
+
+
+ default :
+
+ /*
+ * Anything else is invalid.
+ */
+
+ io_valid = FALSE;
+ break;
+ }
+
+ return io_valid;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_atula_read_node_address
+| ===========================
+|
+| The hwi_atula_read_node_address routine reads in the node address that
+| is stored in the second page of the BIA PROM on ATULA cards.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_read_node_address)
+#endif
+
+local void
+hwi_atula_read_node_address(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_7 = adapter->io_location + ATULA_CONTROL_REGISTER_7;
+ WORD bia_prom = adapter->io_location + ATULA_BIA_PROM;
+ WORD bia_prom_address = bia_prom + BIA_PROM_NODE_ADDRESS;
+ WORD index;
+
+ /*
+ * Page in second page of BIA PROM containing node address.
+ */
+
+ macro_setb_bit(handle, control_7, ATULA_CTRL7_PAGE);
+
+ /*
+ * Read node address from BIA PROM.
+ */
+
+ for (index = 0; index < 6; index++)
+ {
+ adapter->permanent_address.byte[index] =
+ sys_insb(handle, (WORD) (bia_prom_address + index));
+ }
+
+ /*
+ * Restore first page of BIA PROM.
+ */
+
+ macro_clearb_bit(handle, control_7, ATULA_CTRL7_PAGE);
+}
+
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| hwi_atula_get_irq_channel
+| =========================
+|
+| The hwi_atula_get_irq_channel routine attempts to determine the
+| interrupt number that an ATULA card is using. It does this by calling
+| system provided routine. It does not always succeed in finding the
+| interrupt number being used.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_get_irq_channel)
+#endif
+
+local WORD
+hwi_atula_get_irq_channel(
+ WORD io_location,
+ UINT adapter_revision
+ )
+{
+ WORD control_2 = io_location + ATULA_CONTROL_REGISTER_2;
+ WORD control_7 = io_location + ATULA_CONTROL_REGISTER_7;
+ BYTE original_ctrl7;
+ BYTE irq_off;
+ BYTE irq_on;
+ WORD irq;
+
+ /*
+ * Enable interrupts at adapter card temporarily.
+ */
+
+ macro_probe_setb_bit(control_2, ATULA_CTRL2_INTEN);
+
+ /*
+ * Save contents of ATULA control register 7.
+ */
+
+ original_ctrl7 = sys_probe_insb(control_7);
+
+ /*
+ * Current contents of control register 7 does not generate interrupt.
+ */
+
+ irq_off = original_ctrl7;
+
+ /*
+ * If set user interrupt bit then will generate interrupt.
+ */
+
+ irq_on = irq_off | ATULA_CTRL7_UINT;
+
+ /*
+ * Call system provided routine to attempt to dicover interrupt number.
+ * Routine returns FTK_NOT_DETERMINED if not get interrupt number.
+ */
+
+ irq = sys_atula_find_irq_channel(control_7, irq_on, irq_off);
+
+ /*
+ * Restore original contents of ATULA control register 7.
+ */
+
+ sys_probe_outsb(control_7, original_ctrl7);
+
+ /*
+ * Disable interrupts at adapter card.
+ */
+
+ macro_probe_clearb_bit( control_2, ATULA_CTRL2_INTEN);
+
+ /*
+ * Return discovered interrupt number (could be FTK_NOT_DETERMINED).
+ */
+
+ return irq;
+}
+#endif
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| hwi_atula_get_dma_channel
+| =========================
+|
+| The hwi_atula_get_dma_channel routine attempts to determine the DMA
+| channel that an ATULA card is using. It does this by calling a system
+| provided routine.
+|
+| It may be that the system routine does not always succeed in finding the
+| DMA channel being used. However, if the provided system routine is used,
+| then PIO mode is chosen if the DMA channel can not be determined. Hence,
+| in this case, the value FTK_NOT_DETERMINED will never be returned by the
+| hwi_atula_get_dma_channel routine.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_get_dma_channel)
+#endif
+
+local WORD
+hwi_atula_get_dma_channel(
+ WORD io_location ,
+ UINT adapter_revision
+ )
+{
+ WORD control_6 = io_location + ATULA_CONTROL_REGISTER_6;
+ WORD bia_prom = io_location + ATULA_BIA_PROM;
+ WORD bia_prom_adap = bia_prom + BIA_PROM_ADAPTER_BYTE;
+ BYTE original_ctrl6;
+ BYTE dma_off;
+ BYTE dma_on;
+ WORD dma;
+
+ /*
+ * Check to see if an adapter that doesn't support DMA is being used.
+ */
+
+ if (adapter_revision == ADAPTER_CARD_16_4_PC ||
+ adapter_revision == ADAPTER_CARD_16_4_ISA_C ||
+ adapter_revision == ADAPTER_CARD_16_4_ISA_C_P)
+ {
+ dma = 0;
+ }
+ else
+ {
+ /*
+ * For the 16/4 AT card, save the contents of control register 6.
+ */
+
+ original_ctrl6 = sys_probe_insb(control_6);
+
+ /*
+ * Need to enable DMA for bus master.
+ */
+
+ dma_off = original_ctrl6 |
+ ATULA_CTRL6_MODE_BUS_MASTER |
+ ATULA_CTRL6_DMAEN;
+
+ /*
+ * Set user generate DMA request bit for turning DMA signal on.
+ */
+
+ dma_on = dma_off | ATULA_CTRL6_UDRQ;
+
+ /*
+ * Call system provided routine to attempt to dicover DMA channel.
+ * Provided routine returns PIO_DATA_TRANSFER_MODE if not find.
+ */
+
+ dma = sys_atula_find_dma_channel(control_6, dma_on, dma_off);
+
+ /*
+ * Restore original contents of ATULA control register 6.
+ */
+
+ sys_probe_outsb(control_6, original_ctrl6);
+ }
+
+ /*
+ * Return discovered DMA channel details.
+ */
+
+ return dma;
+}
+#endif
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_atula_valid_transfer_mode
+| =============================
+|
+| The hwi_atula_valid_transfer mode routine checks to see if the user has
+| supplied a valid transfer mode for an ATULA based adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_valid_transfer_mode)
+#endif
+
+local WBOOLEAN
+hwi_atula_valid_transfer_mode(
+ ADAPTER * adapter
+ )
+{
+ WBOOLEAN mode_valid;
+
+ /*
+ * Assume that transfer mode is valid.
+ */
+
+ mode_valid = TRUE;
+
+ /*
+ * MMIO is always invalid.
+ */
+
+ if (adapter->transfer_mode == MMIO_DATA_TRANSFER_MODE)
+ {
+ mode_valid = FALSE;
+ }
+
+ /*
+ * PIO is always valid but DMA may not be.
+ */
+
+ else if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
+ {
+ if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_PC ||
+ adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C ||
+ adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P)
+ {
+ mode_valid = FALSE;
+ }
+ }
+
+ if (!mode_valid)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_17_BAD_TRANSFER_MODE;
+ }
+
+ return mode_valid;
+}
+
+/*---------------------------------------------------------------------------
+|
+| hwi_atula_valid_irq_channel
+| ===========================
+|
+| The hwi_atula_valid_irq_channel routine checks to see if the user has
+| supplied a valid interrupt number for an ATULA based adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_valid_irq_channel)
+#endif
+
+local WBOOLEAN
+hwi_atula_valid_irq_channel(
+ ADAPTER * adapter
+ )
+{
+ WBOOLEAN int_valid;
+
+ /*
+ * Assume that interrupt number is valid.
+ */
+
+ int_valid = TRUE;
+
+ /*
+ * No need to do any check on interrupt number if in polling mode.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ /*
+ * Check the interrupt number based on adapter type.
+ */
+
+ if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_PC)
+ {
+ switch (adapter->interrupt_number)
+ {
+ case 2 :
+ case 3 :
+ case 5 :
+ case 7 :
+ case 9 :
+ break;
+
+ default :
+ int_valid = FALSE;
+ break;
+
+ }
+ }
+ else
+ {
+ switch (adapter->interrupt_number)
+ {
+ case 2 :
+ case 3 :
+ case 5 :
+ case 7 :
+ case 9 :
+ case 10 :
+ case 11 :
+ case 12 :
+ case 15 :
+ break;
+
+ default :
+ int_valid = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (!int_valid)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_03_BAD_INTERRUPT_NUMBER;
+ }
+
+ return int_valid;
+}
+
+/*---------------------------------------------------------------------------
+|
+| hwi_atula_valid_dma_channel
+| ===========================
+|
+| The hwi_atula_valid_dma_channel routine checks to see if the user has
+| supplied a valid DMA channel for an ATULA based adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_atula_valid_dma_channel)
+#endif
+
+local WBOOLEAN
+hwi_atula_valid_dma_channel(
+ ADAPTER * adapter
+ )
+{
+ WBOOLEAN dma_valid;
+
+ /*
+ * Assume that DMA channel is valid.
+ */
+
+ dma_valid = TRUE;
+
+ /*
+ * Only need to check on DMA channel in DMA mode.
+ */
+
+ if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
+ {
+ /*
+ * Some adapters do not support DMA.
+ */
+
+ if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_PC ||
+ adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C ||
+ adapter->adapter_card_revision == ADAPTER_CARD_16_4_ISA_C_P)
+ {
+ dma_valid = FALSE;
+ }
+ else if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_AT_P ||
+ adapter->adapter_card_revision == ADAPTER_CARD_16_4_FIBRE_P)
+ {
+ switch (adapter->dma_channel)
+ {
+ case 3 :
+ case 5 :
+ case 6 :
+ break;
+
+ default :
+ dma_valid = FALSE;
+ break;
+ }
+ }
+ else
+ {
+ switch (adapter->dma_channel)
+ {
+ case 1 :
+ case 3 :
+ case 5 :
+ case 6 :
+ break;
+
+ default :
+ dma_valid = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (!dma_valid)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_04_BAD_DMA_CHANNEL;
+ }
+
+ return dma_valid;
+}
+
+
+#endif
+
+/**** End of HWI_AT.C file *************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_eisa.c b/private/ntos/ndis/madge/driver/hwi_eisa.c
new file mode 100644
index 000000000..741a8dadf
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_eisa.c
@@ -0,0 +1,1054 @@
+/****************************************************************************
+*
+* HWI_EISA.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* HARDWARE INTERFACE MODULE FOR EISA CARDS
+*
+* Copyright (c) Madge Networks Ltd. 1990-1994
+*
+* COMPANY CONFIDENTIAL
+*
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_EISA.C module contains the routines specific to 16/4 EISA mk1
+* and mk2 cards which are necessary to install an adapter, to initialize
+* an adapter, to remove an adapter and to handle interrupts on an adapter.
+* Also supported are EISA Bridge nodes.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+#ifndef FTK_NO_EISA
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local WBOOLEAN
+hwi_eisa_valid_io_location(
+ WORD io_location
+ );
+
+#ifndef FTK_NO_PROBE
+
+local WORD
+hwi_eisa_get_irq_channel(
+ WORD io_location
+ );
+
+#endif
+
+local WBOOLEAN
+hwi_eisa_valid_dma_channel(
+ WORD dma_channel
+ );
+
+local WBOOLEAN
+hwi_eisa_valid_irq_channel(
+ WORD irq_channel
+ );
+
+local WBOOLEAN
+hwi_eisa_valid_transfer_mode(
+ UINT transfer_mode
+ );
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_eisa_probe_card
+* ===================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is an array of IO locations to examine for the presence
+* of an adapter. For EISA adapters with should be a subset of
+* {0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000, 0x9000}.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_eisa_probe_card routine is called by hwi_probe_adapter. It
+* reads the id registers to find the type of card and also reads the IRQ.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_eisa_probe_card)
+#endif
+
+export UINT
+hwi_eisa_probe_card(
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ )
+{
+ WBOOLEAN card_found;
+ WORD id_reg_0;
+ WORD id_reg_1;
+ WORD control_x;
+ WORD bmic_3;
+ UINT i;
+ UINT j;
+
+ /*
+ * Check the bounds are sensible.
+ */
+
+ if(length <= 0 || number_locations <= 0)
+ {
+ return PROBE_FAILURE;
+ }
+
+ for(i = 0; i < number_locations; i++)
+ {
+ if(!hwi_eisa_valid_io_location(valid_locations[i]))
+ {
+ return PROBE_FAILURE;
+ }
+ }
+
+ /*
+ * j is the number of adapters found. Unsurprisingly we zero it.
+ */
+
+ j = 0;
+
+ for(i = 0; i < number_locations; i++)
+ {
+ /*
+ * If we run out of PROBE structures then bomb out.
+ */
+
+ if(j >= length)
+ {
+ return(j);
+ }
+
+ /*
+ * Set up the EISA registers.
+ */
+
+ id_reg_0 = valid_locations[i] + EISA_ID_REGISTER_0;
+ id_reg_1 = valid_locations[i] + EISA_ID_REGISTER_1;
+ control_x = valid_locations[i] + EISA_CONTROLX_REGISTER;
+ bmic_3 = valid_locations[i] + EISA_BMIC_REGISTER_3;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_enable_io(valid_locations[i], EISA_IO_RANGE);
+#endif
+ card_found = FALSE;
+
+ /*
+ * Look for an EISA card.
+ */
+
+ if (sys_probe_insw(id_reg_0) == EISA_ID0_MDG_CODE)
+ {
+ if (sys_probe_insw(id_reg_1) == EISA_ID1_MK1_MDG_CODE)
+ {
+ resources[j].adapter_ram_size = 128;
+ card_found = TRUE;
+ }
+ else if (sys_probe_insw(id_reg_1) == EISA_ID1_MK2_MDG_CODE)
+ {
+ resources[j].adapter_ram_size = 256;
+ card_found = TRUE;
+ }
+ else if (sys_probe_insw(id_reg_1) == EISA_ID1_BRIDGE_MDG_CODE)
+ {
+ resources[j].adapter_ram_size = 256;
+ card_found = TRUE;
+ }
+ else if (sys_probe_insw(id_reg_1) == EISA_ID1_MK3_MDG_CODE)
+ {
+ resources[j].adapter_ram_size = 256;
+ card_found = TRUE;
+ }
+ }
+
+
+ if(card_found)
+ {
+ /*
+ * Wayhay! We found one. Let's set up some values.
+ */
+
+ resources[j].io_location = valid_locations[i];
+ resources[j].adapter_card_bus_type = ADAPTER_CARD_EISA_BUS_TYPE;
+ resources[j].adapter_card_type = ADAPTER_CARD_TYPE_16_4_EISA;
+ resources[j].interrupt_number = hwi_eisa_get_irq_channel(
+ valid_locations[i]);
+ resources[j].dma_channel = 0;
+ resources[j].transfer_mode = DMA_DATA_TRANSFER_MODE;
+
+ /*
+ * Increment j to point to the next structure and try again.
+ */
+
+ j++;
+ }
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_disable_io(resources->io_location, EISA_IO_RANGE);
+#endif
+ }
+
+ return(j);
+}
+#endif
+
+/****************************************************************************
+*
+* hwi_eisa_install_card
+* =====================
+*
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_eisa_install_card routine is called by hwi_install_adapter. It
+* sets up the adapter card and downloads the required code to it. Firstly,
+* it checks there is a valid adapter at the required IO address. If so it
+* sets up and checks numerous on-board registers for correct operation.
+* The node address can not be read from the BIA PROM at this stage.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls. There is
+* no need to explicitly enable DMA. Note PIO can not be used.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_eisa_install_card)
+#endif
+
+export WBOOLEAN
+hwi_eisa_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD id_reg_0 = adapter->io_location +
+ EISA_ID_REGISTER_0;
+ WORD id_reg_1 = adapter->io_location +
+ EISA_ID_REGISTER_1;
+ WORD control_x = adapter->io_location +
+ EISA_CONTROLX_REGISTER;
+ WORD bmic_3 = adapter->io_location +
+ EISA_BMIC_REGISTER_3;
+ WORD sif_base;
+
+ /*
+ * Check the IO location is valid.
+ */
+
+ if(!hwi_eisa_valid_io_location(adapter->io_location))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION;
+
+ return FALSE;
+ }
+
+ /*
+ * Check the transfer mode is valid.
+ */
+
+ if(!hwi_eisa_valid_transfer_mode(adapter->transfer_mode))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION;
+
+ return FALSE;
+ }
+
+ /*
+ * Check the DMA channel is valid.
+ */
+
+ if(!hwi_eisa_valid_dma_channel(adapter->dma_channel))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_04_BAD_DMA_CHANNEL;
+
+ return FALSE;
+ }
+
+ /*
+ * Check the IRQ is valid.
+ */
+
+ if(!hwi_eisa_valid_irq_channel(adapter->interrupt_number))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_03_BAD_INTERRUPT_NUMBER;
+
+ return FALSE;
+ }
+
+ /*
+ * Save IO locations of SIF registers.
+ */
+
+ sif_base = adapter->io_location + EISA_FIRST_SIF_REGISTER;
+
+ adapter->sif_dat = sif_base + EAGLE_SIFDAT;
+ adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC;
+ adapter->sif_adr = sif_base + EAGLE_SIFADR;
+ adapter->sif_int = sif_base + EAGLE_SIFINT;
+ adapter->sif_acl = sif_base + EISA_EAGLE_SIFACL;
+ adapter->sif_adr2 = sif_base + EISA_EAGLE_SIFADR_2;
+ adapter->sif_adx = sif_base + EISA_EAGLE_SIFADX;
+ adapter->sif_dmalen = sif_base + EISA_EAGLE_DMALEN;
+
+ adapter->io_range = EISA_IO_RANGE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ adapter->adapter_card_type = ADAPTER_CARD_TYPE_16_4_EISA;
+
+ if (sys_insw( handle, id_reg_0) == EISA_ID0_MDG_CODE)
+ {
+ if (sys_insw( handle, id_reg_1) == EISA_ID1_MK1_MDG_CODE)
+ {
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_EISA_MK1;
+ adapter->adapter_ram_size = 128;
+ }
+ else if (sys_insw( handle, id_reg_1) == EISA_ID1_MK2_MDG_CODE)
+ {
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_EISA_MK2;
+ adapter->adapter_ram_size = 256;
+ }
+ else if (sys_insw( handle, id_reg_1) == EISA_ID1_BRIDGE_MDG_CODE)
+ {
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_EISA_BRIDGE;
+ adapter->adapter_ram_size = 256;
+ }
+ else if (sys_insw( handle, id_reg_1) == EISA_ID1_MK3_MDG_CODE)
+ {
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_EISA_MK3;
+ adapter->adapter_ram_size = 256;
+ }
+ else
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+
+ /*
+ * Check that the adapter card is enabled.
+ * If not then fill in error record and return.
+ */
+
+ if ((sys_insb( handle, control_x) & EISA_CTRLX_CDEN) == 0)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0D_CARD_NOT_ENABLED;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Check that a speed has been selected for the card.
+ * If not then fill in error record and return.
+ */
+
+ if ((sys_insb( handle, bmic_3) & EISA_BMIC3_SPD) == 0)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0E_NO_SPEED_SELECTED;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Discover whether interrupts are edge or level triggered.
+ */
+
+ if ((sys_insb( handle, bmic_3) & EISA_BMIC3_EDGE) == 0)
+ {
+ adapter->edge_triggered_ints = TRUE;
+ }
+ else
+ {
+ adapter->edge_triggered_ints = FALSE;
+ }
+
+ /*
+ * Machine reset does not affect speed or media setting of EISA cards.
+ * Also we cannot find adapter node address at this stage for EISA cards.
+ * The adapter permanent address remains all zeroes.
+ *
+ * There are no other special control registers to set for EISA cards
+ * and no issue of bringing adapter out of reset state.
+ */
+
+ /*
+ * Halt the eagle. No need to page in extended SIF registers for
+ * EISA cards.
+ */
+
+ hwi_halt_eagle(adapter);
+
+ /*
+ * download code to adapter.
+ * View download image as a sequence of download records. Pass address
+ * of routine to set up DIO addresses on EISA cards. If routine fails
+ * return failure (error record already filled in).
+ */
+
+ if (!hwi_download_code(
+ adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_eisa_set_dio_address))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Start the eagle.
+ */
+
+ hwi_start_eagle(adapter);
+
+ /*
+ * Wait for a valid bring up code, may wait 3 seconds.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!hwi_get_bring_up_code( adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return(FALSE);
+ }
+
+ /*
+ * Set DIO address to point to EAGLE DATA page 0x10000L.
+ */
+
+ hwi_eisa_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * Set maximum frame size from the ring speed.
+ */
+
+ adapter->max_frame_size = hwi_get_max_frame_size(adapter);
+
+ /*
+ * Set the ring speed.
+ */
+
+ adapter->ring_speed = hwi_get_ring_speed(adapter);
+
+ /*
+ * If we have a mark 3 adapter then we need to initialise the
+ * VRAM by writing 0xffff to 0xc0000 in DIO space. Remember to
+ * to set the extended address register back to the Eagle
+ * data page.
+ */
+
+ if (adapter->adapter_card_revision == ADAPTER_CARD_16_4_EISA_MK3)
+ {
+ hwi_eisa_set_dio_address(adapter, DIO_LOCATION_EISA_VRAM_ENABLE);
+ sys_outsw(handle, adapter->sif_dat, EISA_VRAM_ENABLE_WORD);
+ hwi_eisa_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+ }
+
+ /*
+ * If not in polling mode then set up interrupts.
+ * interrupts_on field is used when disabling interrupts for adapter.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on =
+ sys_enable_irq_channel( handle, adapter->interrupt_number);
+
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+ /*
+ * No need to explicitly enable interrupts at adapter for EISA card
+ * and no need to explicitly set up DMA channel.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return TRUE;
+
+}
+
+
+/****************************************************************************
+*
+* hwi_eisa_interrupt_handler
+* ==========================
+*
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_eisa_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF only.
+* There are no PIO interupts on EISA cards. Note it could in fact be the
+* case that no interrupt has occured on the particular adapter being
+* checked.
+*
+* On SIF interrupts, the interrupt is acknowledged and cleared. The value
+* in the SIF interrupt register is recorded in order to pass it to the
+* driver_interrupt_entry routine (along with the adapter details).
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_eisa_interrupt_handler)
+#endif
+
+export void
+hwi_eisa_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_x = adapter->io_location +
+ EISA_CONTROLX_REGISTER;
+ WORD sifint_register = adapter->sif_int;
+ WORD sifint_value;
+ WORD sifint_tmp;
+
+ /*
+ * Inform system about the IO ports we are going to access.
+ * Enable maximum number of IO locations used by any adapter card.
+ * Do this so at driver level we can disable IO not knowing the adapter
+ * type.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Check for SIF interrupt. (We don't get PIO interrupts on EISA cards).
+ */
+
+ if ((sys_insw(handle, sifint_register) &
+ FASTMAC_SIFINT_IRQ_DRIVER) != 0)
+ {
+ /*
+ * A SIF interrupt has occurred. This could be an SRB free,
+ * an adapter check or a received frame interrupt
+
+ * No need to acknowledge interrupt at EISA card.
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+
+ * WARNING: Do NOT reorder the clearing of the SIFINT register with
+ * the reading of it. If SIFINT is cleared after reading it, any
+ * interrupts raised after reading it will be lost. Admittedly
+ * this is a small time frame, but it is important.
+ */
+
+ sys_outsw(handle, adapter->sif_int, 0);
+
+ /*
+ * Record the EAGLE SIF interrupt register value.
+
+ * WARNING: Continue to read the SIFINT register until it is stable
+ * because of a potential problem involving the host reading the
+ * register after the adapter has written the low byte of it, but
+ * before it has written the high byte. Failure to wait for the
+ * SIFINT register to settle can cause spurious interrupts.
+ */
+
+ sifint_value = sys_insw(handle, adapter->sif_int);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(
+ handle,
+ adapter->sif_int);
+ }
+ while (sifint_tmp != sifint_value);
+
+ /*
+ * Acknowledge/clear interrupt at interrupt controller.
+ */
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(handle, adapter->interrupt_number);
+#endif
+
+ /*
+ * No need regenerate any interrupts when using level sensitive.
+ * For edge triggered we need to disable\enable board to regenerate
+ * interrupts.
+ */
+
+ if (adapter->edge_triggered_ints)
+ {
+ macro_clearb_bit(handle, control_x, EISA_CTRLX_CDEN);
+ macro_setb_bit(handle, control_x, EISA_CTRLX_CDEN);
+ }
+
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+
+ driver_interrupt_entry(handle, adapter, sifint_value);
+
+ }
+
+ /*
+ * Let the system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+}
+
+
+/****************************************************************************
+*
+* hwi_eisa_remove_card
+* ====================
+*
+*
+* PARAMETERS (passed by hwi_remove_adapter) :
+* ===========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_eisa_remove_card routine is called by hwi_remove_adapter. It
+* disables interrupts if they are being used. It also resets the adapter.
+* Note there is no need to explicitly disable DMA channels.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_eisa_remove_card)
+#endif
+
+export void
+hwi_eisa_remove_card(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD sif_acontrol = adapter->sif_acl;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Disable interrupts. Only need to do this if interrupts successfully
+ * enabled.
+ * Interrupts must be disabled at adapter before unpatching interrupt.
+ * Even in polling mode we must turn off interrupts at adapter.
+ */
+
+ if (adapter->interrupts_on)
+ {
+ macro_clearw_bit( handle, sif_acontrol, EAGLE_SIFACL_SINTEN);
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(handle, adapter->interrupt_number);
+ }
+ adapter->interrupts_on = FALSE;
+
+ }
+
+ /*
+ * Perform adapter reset, set EAGLE_SIFACL_ARESET high.
+ */
+
+ macro_setw_bit( handle, sif_acontrol, EAGLE_SIFACL_ARESET);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_eisa_set_dio_address
+* ========================
+*
+* The hwi_eisa_set_dio_address routine is used, with EISA cards, for
+* putting a 32 bit DIO address into the SIF DIO address and extended DIO
+* address registers. Note that the extended address register should be
+* loaded first.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_eisa_set_dio_address)
+#endif
+
+export void
+hwi_eisa_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * Load extended DIO address register with top 16 bits of address.
+ * Always load extended address register first.
+ * Note EISA cards have single page of all SIF registers, hence do not
+ * need page in certain SIF registers.
+ */
+
+ sys_outsw(
+ handle,
+ sif_dio_adrx,
+ (WORD)(dio_address >> 16));
+
+ /*
+ * Load DIO address register with low 16 bits of address.
+ */
+
+ sys_outsw(
+ handle,
+ sif_dio_adr,
+ (WORD)(dio_address & 0x0000FFFF));
+
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|
+| hwi_eisa_valid_io_location
+| ==========================
+|
+| The hwi_eisa_valid_io_location routine checks to see if the user has
+| supplied a valid IO location for an EISA adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_eisa_valid_io_location)
+#endif
+
+export WBOOLEAN
+hwi_eisa_valid_io_location(
+ WORD io_location
+ )
+{
+ WBOOLEAN io_valid;
+
+ switch (io_location)
+ {
+ case 0x1000 :
+ case 0x2000 :
+ case 0x3000 :
+ case 0x4000 :
+ case 0x5000 :
+ case 0x6000 :
+ case 0x7000 :
+ case 0x8000 :
+ case 0x9000 :
+ case 0xA000 :
+ case 0xB000 :
+ case 0xC000 :
+ case 0xD000 :
+ case 0xE000 :
+ case 0xF000 :
+
+ io_valid = TRUE;
+ break;
+
+ default :
+
+ io_valid = FALSE;
+ break;
+
+ }
+
+ return(io_valid);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_eisa_valid_irq_channel
+| ==========================
+|
+| The hwi_eisa_valid_irq_channel routine checks to see if the user has
+| supplied a sensible IRQ for an EISA adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_eisa_valid_irq_channel)
+#endif
+
+export WBOOLEAN
+hwi_eisa_valid_irq_channel(
+ WORD irq_channel
+ )
+{
+ WBOOLEAN int_valid = TRUE;
+
+
+ if (irq_channel != POLLING_INTERRUPTS_MODE)
+ {
+ switch (irq_channel)
+ {
+ case 3:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ break;
+
+ default:
+ int_valid = FALSE;
+ }
+ }
+
+ return int_valid;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_eisa_valid_dma_channel
+| ==========================
+|
+| The hwi_eisa_valid_dma_channel routine checks to see if the user has
+| supplied a sensible dma channel for an EISA adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_eisa_valid_dma_channel)
+#endif
+
+export WBOOLEAN
+hwi_eisa_valid_dma_channel(
+ WORD dma_channel
+ )
+{
+ return (dma_channel == 0);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_eisa_valid_transfer_mode
+| ============================
+|
+| The hwi_eisa_valid_transfer_mode routine checks to see if the user has
+| supplied a sensible transfer mode for an EISA adapter card. That means DMA
+| at the moment.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_eisa_valid_transfer_mode)
+#endif
+
+export WBOOLEAN
+hwi_eisa_valid_transfer_mode(
+ UINT transfer_mode
+ )
+{
+ return (transfer_mode == DMA_DATA_TRANSFER_MODE);
+}
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| hwi_eisa_get_irq_channel
+| ========================
+|
+| The hwi_eisa_get_irq_channel routine determines the interrupt number
+| that an EISA card is using. It does this by looking at one of the BMIC
+| registers. It always succeeds in finding the interrupt number being
+| used.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_eisa_get_irq_channel)
+#endif
+
+local WORD
+hwi_eisa_get_irq_channel(
+ WORD io_location
+ )
+{
+ WORD bmic_3 = io_location + EISA_BMIC_REGISTER_3;
+ WORD irq;
+
+ /*
+ * The interrupt number is in four bits (3,2,1,0) in BMIC register 3.
+ */
+
+ irq = sys_probe_insb(bmic_3) & EISA_BMIC3_IRQSEL;
+
+ /*
+ * Interrupt 2 needs to be changed to 9 for system routines.
+ */
+
+ if (irq == 2)
+ {
+ irq = 9;
+ }
+
+ /*
+ * Return the discovered interrupt number.
+ */
+
+ return(irq);
+}
+#endif
+
+#endif
+
+/******** End of HWI_EISA.C ************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_gen.c b/private/ntos/ndis/madge/driver/hwi_gen.c
new file mode 100644
index 000000000..d0a2d7928
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_gen.c
@@ -0,0 +1,2077 @@
+/****************************************************************************
+*
+* HWI_GEN.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* THE GENERAL HARDWARE INTERFACE MODULE
+*
+* Copyright (c) Madge Networks Ltd. 1990-1994
+*
+* COMPANY CONFIDENTIAL
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_GEN.C module contains the general routines necessary to install
+* an adapter, to initialize an adapter, to remove an adapter and to handle
+* interrupts on an adapter. It does not contain the routines specific to a
+* particular card type involved in any of these processes. These are in
+* the relevant HWI_<card_type>.C modules.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+/*---------------------------------------------------------------------------
+|
+| GLOBAL VARIABLES
+|
+---------------------------------------------------------------------------*/
+
+local BYTE scb_test_pattern[] = SCB_TEST_PATTERN_DATA;
+local BYTE ssb_test_pattern[] = SSB_TEST_PATTERN_DATA;
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local void
+hwi_copy_to_dio_space(
+ ADAPTER * adapter,
+ DWORD dio_location,
+ BYTE * download_data,
+ WORD data_length_bytes
+ );
+
+local WBOOLEAN
+hwi_get_init_code(
+ ADAPTER * adapter
+ );
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_deprobe_adapter
+* ===================
+*
+*
+* PARAMETERS :
+* ============
+*
+* PROBE * probe_values
+*
+* This structure identifies cards that have been probed.
+*
+* UINT length
+*
+* The length of the above array.
+*
+* BODY :
+* ======
+*
+* The hwi_deprobe_adapter routine uses the card bus type to call the
+* correct hwi_<card_type>_deprobe_card routine.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_deprobe_adapter)
+#endif
+
+export WBOOLEAN
+hwi_deprobe_adapter(
+ PROBE * resources,
+ UINT length
+ )
+{
+ WBOOLEAN success = TRUE;
+ UINT i;
+
+ for(i = 0; i < length; i++)
+ {
+ switch(resources[i].adapter_card_bus_type)
+ {
+ /*
+ * As it stands the only adapter that needs to be deprobed is a
+ * PCMCIA, since it has to deregister with card services.
+ */
+
+#ifndef FTK_NO_PCMCIA
+ case ADAPTER_CARD_PCMCIA_BUS_TYPE :
+ success = success && hwi_pcmcia_deprobe_card(resources[i]);
+ break;
+#endif
+ default :
+ break;
+ }
+ }
+
+ return(success);
+}
+
+/****************************************************************************
+*
+* hwi_probe_adapter
+* =================
+*
+*
+* PARAMETERS (passed by driver_probe_adapter) :
+* =============================================
+*
+* WORD adapter_card_bus_type
+*
+* the bus type of the card, so we can switch to the correct hwi module.
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is an array of IO locations to examine for the presence
+* of an adapter.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_probe_adapter routine is called by driver_probe_adapter. It
+* switches to a hwi_<card type>_probe_card routine which does the work.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the value returned from below.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_probe_adapter)
+#endif
+
+export UINT
+hwi_probe_adapter(
+ WORD adapter_card_bus_type,
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ )
+{
+ UINT number_found;
+ UINT i;
+
+ /*
+ * Mark all resource entries as undefined to start off with.
+ */
+
+ for (i = 0; i < length; i++)
+ {
+ resources[i].socket = FTK_UNDEFINED;
+ resources[i].adapter_card_bus_type = FTK_UNDEFINED;
+ resources[i].adapter_card_type = FTK_UNDEFINED;
+ resources[i].adapter_card_revision = FTK_UNDEFINED;
+ resources[i].adapter_ram_size = FTK_UNDEFINED;
+ resources[i].io_location = FTK_UNDEFINED;
+ resources[i].interrupt_number = FTK_UNDEFINED;
+ resources[i].dma_channel = FTK_UNDEFINED;
+ resources[i].transfer_mode = FTK_UNDEFINED;
+ resources[i].mmio_base_address = FTK_UNDEFINED;
+ }
+
+ /*
+ * And call the appropriate probe routine.
+ */
+
+ switch(adapter_card_bus_type)
+ {
+#ifndef FTK_NO_ATULA
+ case ADAPTER_CARD_ATULA_BUS_TYPE :
+ number_found = hwi_atula_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+#ifndef FTK_NO_PNP
+ case ADAPTER_CARD_PNP_BUS_TYPE :
+ number_found = hwi_pnp_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+#ifndef FTK_NO_MC
+ case ADAPTER_CARD_MC_BUS_TYPE :
+ number_found = hwi_mc_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+#ifndef FTK_NO_EISA
+ case ADAPTER_CARD_EISA_BUS_TYPE :
+ number_found = hwi_eisa_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+#ifndef FTK_NO_SMART16
+ case ADAPTER_CARD_SMART16_BUS_TYPE :
+ number_found = hwi_smart16_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+#ifndef FTK_NO_PCI
+ case ADAPTER_CARD_PCI_BUS_TYPE :
+ number_found = hwi_pci_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+#ifndef FTK_NO_PCMCIA
+ case ADAPTER_CARD_PCMCIA_BUS_TYPE :
+ number_found = hwi_pcmcia_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+#ifndef FTK_NO_PCI_TI
+ case ADAPTER_CARD_TI_PCI_BUS_TYPE :
+ number_found = hwi_pcit_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+#ifndef FTK_NO_PCI2
+ case ADAPTER_CARD_PCI2_BUS_TYPE :
+ number_found = hwi_pci2_probe_card(resources,
+ length,
+ valid_locations,
+ number_locations);
+ break;
+#endif
+
+ default :
+
+ /*
+ * Bad adapter card bus type so fail.
+ */
+
+ number_found = 0;
+ break;
+ }
+
+ return number_found;
+}
+#endif
+
+
+#ifndef FTK_NO_DETECT
+/****************************************************************************
+*
+* hwi_read_rate_error
+* ===================
+*
+*
+* PARAMETERS (passed by driver_probe_adapter) :
+* =============================================
+*
+* ADAPTER * adapter
+*
+* The adapter structure
+*
+*
+* BODY :
+* ======
+*
+* The hwi_read_rate_error switches to a hwi_<card type>_read_rate_error
+* which reads the rate error bit of the C30. Normally this is visible in
+* the IO space of the bus interface chip, except for the AT space when we
+* read it through DIO.
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if there was a rate error.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_read_rate_error)
+#endif
+
+export WORD
+hwi_read_rate_error(
+ ADAPTER * adapter
+ )
+{
+ WBOOLEAN wrong_speed = FALSE;
+
+ switch (adapter->adapter_card_bus_type)
+ {
+
+#ifndef FTK_NO_ATULA
+ case ADAPTER_CARD_ATULA_BUS_TYPE :
+ wrong_speed = hwi_atula_read_rate_error(
+ adapter);
+
+ break;
+#endif
+ default:
+ {
+ wrong_speed = NOT_SUPP;
+ break;
+ }
+ }
+
+ return wrong_speed;
+}
+#endif /* FTK_NO_DETECT */
+
+
+/****************************************************************************
+*
+* hwi_install_adapter
+* ===================
+*
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_install_adapter routine uses the card bus type to call the
+* correct hwi_<card_type>_install_card routine.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_install_adapter)
+#endif
+
+export WBOOLEAN
+hwi_install_adapter(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WBOOLEAN install_success;
+
+ /*
+ * Record fact that adapter does not have interrupts or DMA enabled.
+ */
+
+ adapter->interrupts_on = FALSE;
+ adapter->dma_on = FALSE;
+
+ /*
+ * Cards do not support speed detect unless they have a C30.
+ */
+ adapter->speed_detect = FALSE;
+
+ /*
+ * Call correct install routine dependent on adapter card bus type.
+ */
+
+ switch (adapter->adapter_card_bus_type)
+ {
+#ifndef FTK_NO_ATULA
+ case ADAPTER_CARD_ATULA_BUS_TYPE :
+
+ /*
+ * Set up pointers to the functions we will need later.
+ */
+
+ adapter->interrupt_handler = hwi_atula_interrupt_handler;
+ adapter->remove_card = hwi_atula_remove_card;
+ adapter->set_dio_address = hwi_atula_set_dio_address;
+
+ /*
+ * Call the install routine.
+ */
+
+ install_success = hwi_atula_install_card(
+ adapter,
+ download_image);
+
+ break;
+#endif
+#ifndef FTK_NO_PNP
+ case ADAPTER_CARD_PNP_BUS_TYPE :
+
+ /*
+ * Set up pointers to the functions we will need later.
+ */
+
+ adapter->interrupt_handler = hwi_pnp_interrupt_handler;
+ adapter->remove_card = hwi_pnp_remove_card;
+ adapter->set_dio_address = hwi_pnp_set_dio_address;
+
+ /*
+ * Call the install routine.
+ */
+
+ install_success = hwi_pnp_install_card(
+ adapter,
+ download_image);
+
+ break;
+#endif
+#ifndef FTK_NO_MC
+ case ADAPTER_CARD_MC_BUS_TYPE :
+
+ adapter->interrupt_handler = hwi_mc_interrupt_handler;
+ adapter->remove_card = hwi_mc_remove_card;
+ adapter->set_dio_address = hwi_mc_set_dio_address;
+
+ install_success = hwi_mc_install_card(
+ adapter,
+ download_image);
+
+ break;
+#endif
+#ifndef FTK_NO_EISA
+ case ADAPTER_CARD_EISA_BUS_TYPE :
+
+ adapter->interrupt_handler = hwi_eisa_interrupt_handler;
+ adapter->remove_card = hwi_eisa_remove_card;
+ adapter->set_dio_address = hwi_eisa_set_dio_address;
+
+
+ install_success = hwi_eisa_install_card(
+ adapter,
+ download_image);
+
+ break;
+#endif
+#ifndef FTK_NO_SMART16
+ case ADAPTER_CARD_SMART16_BUS_TYPE :
+
+ adapter->interrupt_handler = hwi_smart16_interrupt_handler;
+ adapter->remove_card = hwi_smart16_remove_card;
+ adapter->set_dio_address = hwi_smart16_set_dio_address;
+
+ install_success = hwi_smart16_install_card(
+ adapter,
+ download_image);
+
+ break;
+#endif
+#ifndef FTK_NO_PCI
+ case ADAPTER_CARD_PCI_BUS_TYPE :
+
+ adapter->interrupt_handler = hwi_pci_interrupt_handler;
+ adapter->remove_card = hwi_pci_remove_card;
+ adapter->set_dio_address = hwi_pci_set_dio_address;
+
+
+ install_success = hwi_pci_install_card(
+ adapter,
+ download_image);
+
+ break;
+#endif
+#ifndef FTK_NO_PCMCIA
+ case ADAPTER_CARD_PCMCIA_BUS_TYPE :
+
+ adapter->interrupt_handler = hwi_pcmcia_interrupt_handler;
+ adapter->remove_card = hwi_pcmcia_remove_card;
+ adapter->set_dio_address = hwi_pcmcia_set_dio_address;
+
+ install_success = hwi_pcmcia_install_card(adapter, download_image);
+
+ break;
+#endif
+#ifndef FTK_NO_PCIT
+ case ADAPTER_CARD_TI_PCI_BUS_TYPE :
+
+ adapter->interrupt_handler = hwi_pcit_interrupt_handler;
+ adapter->remove_card = hwi_pcit_remove_card;
+ adapter->set_dio_address = hwi_pcit_set_dio_address;
+
+ install_success = hwi_pcit_install_card(
+ adapter,
+ download_image);
+
+ break;
+#endif
+
+#ifndef FTK_NO_PCI2
+ case ADAPTER_CARD_PCI2_BUS_TYPE :
+
+ adapter->interrupt_handler = hwi_pci2_interrupt_handler;
+ adapter->remove_card = hwi_pci2_remove_card;
+ adapter->set_dio_address = hwi_pci2_set_dio_address;
+
+ install_success = hwi_pci2_install_card(
+ adapter,
+ download_image);
+
+ break;
+#endif
+
+ default :
+
+ /*
+ * Bad adapter card bus type so fail.
+ */
+
+ install_success = FALSE;
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_01_BAD_CARD_BUS_TYPE;
+
+ break;
+ }
+
+ return install_success;
+}
+
+
+/****************************************************************************
+*
+* hwi_initialize_adapter
+* ======================
+*
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* INITIALIZATION_BLOCK * init_block
+*
+* This is the initialization block that is to be copied into DIO space
+* before performing the actual chipset initialization.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_initialize_adapter routine performs the initialization of the
+* chipset. It sets up the TI initialization block and the general MAC
+* level smart software initialization parameters and copies these into DIO
+* space at 0x10A00 on the EAGLE. These are followed in DIO space by the
+* Fastmac module specific initialization block details. The
+* initialization is started and then the routine waits up to 11 seconds
+* for success or failure to be registered by the SIF interrupt register.
+* The DMAs that occur during initialization are also checked for success.
+* Note these DMAs may actually be done by PIO transfers by the HWI itself
+* for ATULA cards.
+*
+* During downloading BYTE fields in structures need to be swapped and
+* DWORDs need to have the UINTs within swapped around. This is because of
+* the low-high byte ordering on Intel machines and the high-low ordering
+* of the EAGLE and the byte swapping that automatically occurs when
+* downloading through the SIF. Note that the automatic byte swapping
+* means UINTs do not themselves need any special treatment.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+* On success we also exit with 0x0001 in the EAGLE_SIDADRX register.
+* This should never need to be altered by any user. This means for example
+* that the FTK driver need only interest itself in the non-extended SIF
+* registers.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_initialize_adapter)
+#endif
+
+#if 1
+sys_int53( void);
+#endif
+
+export WBOOLEAN
+hwi_initialize_adapter(
+ ADAPTER * adapter,
+ INITIALIZATION_BLOCK * init_block
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ FASTMAC_INIT_PARMS * fastmac_parms = &init_block->fastmac_parms;
+ WBOOLEAN init_success;
+ UINT i;
+ BYTE FAR * dma_test_scb_buff;
+ BYTE FAR * dma_test_ssb_buff;
+ DWORD dma_test_scb_phys;
+ DWORD dma_test_ssb_phys;
+#ifdef FMPLUS
+ WORD fmplus_buffer_size;
+ DWORD fmplus_max_buffmem;
+ WORD fmplus_max_buffers;
+#endif
+
+ /*
+ * Set up the TI initialization parameters. Those fields not set up here
+ * must be zero. Set up for burst DMA.
+ */
+
+ init_block->ti_parms.init_options = TI_INIT_OPTIONS_BURST_DMA;
+
+ /*
+ * Copy in 16/4 MC 32 configuration information. This data is zero for
+ * non-16/4 MC 32 cards.
+ */
+
+ init_block->ti_parms.madge_mc32_config = adapter->mc32_config;
+
+ /*
+ * Set up retry counts.
+ */
+
+ init_block->ti_parms.parity_retry = TI_INIT_RETRY_DEFAULT;
+ init_block->ti_parms.dma_retry = TI_INIT_RETRY_DEFAULT;
+
+ /*
+ * NB It is not safe to use the Fastmac receive buffer for the DMA test
+ * because if auto-open is used, a frame could be received before we
+ * have a chance to test the contents of this memory. So put both SSB
+ * and SCB in the Tx buffer.
+ */
+
+#ifdef FMPLUS
+ /*
+ * FMPlus does not have a transmit buffer it can use for the test DMAs,
+ * so we use a buffer previously allocated in the drv_init module.
+ */
+
+ dma_test_scb_buff = (BYTE FAR *) adapter->dma_test_buf_virt;
+ dma_test_scb_phys = adapter->dma_test_buf_phys;
+
+ dma_test_ssb_phys = dma_test_scb_phys + SCB_TEST_PATTERN_LENGTH;
+ dma_test_ssb_buff = dma_test_scb_buff + SCB_TEST_PATTERN_LENGTH;
+
+#else
+ /*
+ * For Fastmac, we use the transmit buffer for the test DMAs.
+ */
+
+ dma_test_scb_buff = (BYTE FAR *) adapter->tx_buffer_virt;
+ dma_test_scb_phys = adapter->tx_buffer_phys;
+
+ dma_test_ssb_phys = dma_test_scb_phys + SCB_TEST_PATTERN_LENGTH;
+ dma_test_ssb_buff = dma_test_scb_buff + SCB_TEST_PATTERN_LENGTH;
+
+ if (adapter->transfer_mode != DMA_DATA_TRANSFER_MODE)
+ {
+ fastmac_parms->tx_buf_physaddr = adapter->tx_buffer_virt;
+
+ fastmac_parms->rx_buf_physaddr = adapter->rx_buffer_virt;
+ }
+
+#endif
+
+ if (adapter->transfer_mode != DMA_DATA_TRANSFER_MODE)
+ {
+ /*
+ * PIO uses virtual addresses to save having to perform Phys-to-Virt
+ * conversions in the interrupt service routine.
+ */
+
+ init_block->ti_parms.scb_addr = (DWORD)dma_test_scb_buff;
+ init_block->ti_parms.ssb_addr = (DWORD)dma_test_ssb_buff;
+ }
+ else
+ {
+ /*
+ * DMA must use physical addresses, however. We already have these
+ * saved.
+ */
+
+ init_block->ti_parms.scb_addr = dma_test_scb_phys;
+ init_block->ti_parms.ssb_addr = dma_test_ssb_phys;
+ }
+
+
+ macro_word_swap_dword(init_block->ti_parms.scb_addr);
+ macro_word_swap_dword(init_block->ti_parms.ssb_addr);
+
+ #if 0
+ /*
+ * TMSDebug support
+ */
+ printf("\nTMSDebug Enabled\n");
+ init_block->smart_parms.reserved_1 = 3;
+ sys_int53();
+ #endif
+
+ /*
+ * Set up the smart software initialization parameters. Those fields
+ * not set up here must be zero.
+ * Set up header to identify the smart software initialization parms.
+ */
+
+ init_block->smart_parms.header.length = sizeof(SMART_INIT_PARMS);
+ init_block->smart_parms.header.signature = SMART_INIT_HEADER_SIGNATURE;
+ init_block->smart_parms.header.version = SMART_INIT_HEADER_VERSION;
+
+ /*
+ * Byte swap the permanent node address when setting it up.
+ */
+
+ init_block->smart_parms.permanent_address = adapter->permanent_address;
+
+ util_byte_swap_structure(
+ (BYTE *) &init_block->smart_parms.permanent_address,
+ sizeof(NODE_ADDRESS));
+
+#ifdef FMPLUS
+ /*
+ * Must set min_buffer_ram field for backwards compatibility with other
+ * Madge code (see FMPlus programming spec.)
+ */
+
+ init_block->smart_parms.min_buffer_ram = SMART_INIT_MIN_RAM_DEFAULT;
+#endif
+
+ /*
+ * Need to byte swap fields in the Fastmac specific init parms.
+ * These fields are the opening node address and the buffer addresses.
+ */
+
+ util_byte_swap_structure(
+ (BYTE *)&fastmac_parms->open_address,
+ sizeof(NODE_ADDRESS));
+
+#ifdef FMPLUS
+ /*
+ * Now work out the number of transmit and receive buffers.
+ * The number of buffers allocated depends on the maximum frame size
+ * anticipated, and on the amount of memory on the card. Unfortunately,
+ * one cannot know the maximum possible frame size until after the mac
+ * code has started and worked out what the ring speed is. Thus it is
+ * necessary to make an assumption about what the largest frame size
+ * supported will be.
+ */
+
+ /*
+ * First, work out how big the buffers are. Unless a different size has
+ * been specified, use the default buffer size.
+ */
+
+ fmplus_buffer_size = init_block->smart_parms.rx_tx_buffer_size;
+
+ /*
+ * MC32, EISA and PCIx cards use a smaller default buffer size than other
+ * cards do (16/4 AT and 16/4 MC cards).
+ */
+
+ if (adapter->adapter_card_type == ADAPTER_CARD_TYPE_16_4_EISA ||
+ adapter->adapter_card_type == ADAPTER_CARD_TYPE_16_4_MC_32 ||
+ adapter->adapter_card_type == ADAPTER_CARD_TYPE_16_4_PCI ||
+ adapter->adapter_card_type == ADAPTER_CARD_TYPE_16_4_PCIT ||
+ adapter->adapter_card_type == ADAPTER_CARD_TYPE_16_4_PCI2)
+ {
+ if (fmplus_buffer_size)
+ {
+ fmplus_buffer_size =
+ max(FMPLUS_MIN_TXRX_BUFF_SIZE,
+ min(FMPLUS_DEFAULT_BUFF_SIZE_SMALL, fmplus_buffer_size)
+ );
+ }
+ else
+ {
+ fmplus_buffer_size = FMPLUS_DEFAULT_BUFF_SIZE_SMALL;
+ }
+ }
+ else
+ {
+ if (fmplus_buffer_size)
+ {
+ fmplus_buffer_size =
+ max(FMPLUS_MIN_TXRX_BUFF_SIZE, fmplus_buffer_size);
+ }
+ else
+ {
+ fmplus_buffer_size = FMPLUS_DEFAULT_BUFF_SIZE_LARGE;
+ }
+ }
+
+ init_block->smart_parms.rx_tx_buffer_size = fmplus_buffer_size;
+
+ if (fmplus_buffer_size < FMPLUS_MIN_TXRX_BUFF_SIZE)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_10_BAD_TX_RX_BUFF_SIZE;
+ return FALSE;
+ }
+
+ /*
+ * Next, work out how much memory on the card we can use for buffers.
+ */
+
+ if (adapter->adapter_ram_size == 128)
+ {
+ fmplus_max_buffmem = FMPLUS_MAX_BUFFMEM_IN_128K;
+ }
+ else if (adapter->adapter_ram_size == 256)
+ {
+ fmplus_max_buffmem = FMPLUS_MAX_BUFFMEM_IN_256K;
+ }
+ else if (adapter->adapter_ram_size == 512)
+ {
+ fmplus_max_buffmem = FMPLUS_MAX_BUFFMEM_IN_512K;
+ }
+ else
+ {
+ fmplus_max_buffmem = FMPLUS_MAX_BUFFMEM_IN_128K;
+ }
+
+ /*
+ * Use the two numbers worked out above to determine the maximum number
+ * of buffers we can fit on the card.
+ * The calculation is to round the buffer size up to the nearest 1K,
+ * and to divide that into the total amount of memory. The rounding up
+ * has to take account of the eight bytes buffer header that is added
+ * by FMP i.e. buffer_allocation = (buffer_size + 8 + 1023) 1024
+ * (there is also a "fudge-factor" of 5 buffers to allow the binary to
+ * grow a little from its current size!)
+ */
+
+ fmplus_max_buffers =
+ (WORD)(fmplus_max_buffmem / ((fmplus_buffer_size + 1031) & ~1023)) -
+ 5;
+
+ /*
+ * Finally, allocate the buffers between transmit and receive. Notice
+ * that we allow here for frames as big as they are ever going to get
+ * on token ring. For smaller frames and 4 Mbps rings, this will just
+ * have the effect of improving back-to-back transmit performance.
+ */
+
+ fastmac_parms->tx_bufs = 2 *
+ ((fastmac_parms->max_frame_size +
+ fmplus_buffer_size) /
+ fmplus_buffer_size);
+
+ fastmac_parms->rx_bufs = fmplus_max_buffers -
+ fastmac_parms->tx_slots -
+ fastmac_parms->tx_bufs;
+
+ /*
+ * When an error occurs is a little subjective at this point. It is, in
+ * fact, possible to receive a frame with only about three buffers, but
+ * for safety's sake, we demand that there be enough to receive a max.
+ * sized frame.
+ */
+
+ if (fastmac_parms->rx_bufs < fastmac_parms->tx_bufs)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_11_TOO_MANY_TX_RX_BUFFS;
+ return (FALSE);
+ }
+
+#else
+ macro_word_swap_dword(fastmac_parms->tx_buf_physaddr);
+ macro_word_swap_dword(fastmac_parms->rx_buf_physaddr);
+#endif
+
+ /*
+ * Inform the system about the IO ports we are going to access.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Download initialization block to required location in DIO space.
+ * Note routine leaves 0x0001 in EAGLE SIFADRX register.
+ */
+
+ hwi_copy_to_dio_space(
+ adapter,
+ DIO_LOCATION_INIT_BLOCK,
+ (BYTE *) init_block,
+ sizeof(INITIALIZATION_BLOCK));
+
+ /*
+ * After downloading byte swap back some Fastmac specific init parms.
+ * Fields are the opening node address and the Fastmac buffer addresses.
+ * This is especially important to do for the buffer addresses
+ * because they are used in transmit/receive routines.
+ */
+
+ util_byte_swap_structure(
+ (BYTE *)&fastmac_parms->open_address,
+ sizeof(NODE_ADDRESS));
+
+#ifndef FMPLUS
+ macro_word_swap_dword(fastmac_parms->tx_buf_physaddr);
+ macro_word_swap_dword(fastmac_parms->rx_buf_physaddr);
+
+ /*
+ * The mainline transmit receive code assumes that these values ar
+ * physical addresses, so we had better convert them back... The al-
+ * ternative would be to rewrite all the transmit and receive modules
+ * to note which transfer mode is in use.
+ */
+
+ if (adapter->transfer_mode != DMA_DATA_TRANSFER_MODE)
+ {
+ fastmac_parms->tx_buf_physaddr = adapter->tx_buffer_phys;
+
+ fastmac_parms->rx_buf_physaddr = adapter->rx_buffer_phys;
+ }
+
+#endif
+
+ /*
+ * Start initialization by output 0x9080 to SIF interrupt register.
+ */
+
+ sys_outsw(handle, adapter->sif_int, EAGLE_INIT_START_CODE);
+
+ /*
+ * Wait for a valid initialization code, may wait 11 seconds.
+ * During this process test DMAs need to occur, hence in PIO mode needs
+ * calls to hwi_interrupt_entry, hence need interrupts or polling active.
+ */
+
+ init_success = hwi_get_init_code(adapter);
+
+ /*
+ * Let the system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter );
+#endif
+
+ if (!init_success)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Check that test DMAs were successful.
+ */
+
+ /*
+ * First check SCB for correct test pattern. Remember used Fastmac
+ * transmit buffer address for SCB address.
+ */
+
+ for (i = 0; i < SCB_TEST_PATTERN_LENGTH; i++)
+ {
+ if (dma_test_scb_buff[i] != scb_test_pattern[i])
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_07_FAILED_TEST_DMA;
+ return FALSE;
+ }
+ }
+
+ /*
+ * Now check SSB for correct test pattern. Remember used Fastmac
+ * receive buffer address for SSB address.
+ */
+
+ for (i = 0; i < SSB_TEST_PATTERN_LENGTH; i++)
+ {
+ if (dma_test_ssb_buff[i] != ssb_test_pattern[i])
+ {
+ /* fill in error record and fail if pattern doesn't match */
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_07_FAILED_TEST_DMA;
+ return FALSE;
+ }
+ }
+
+ /*
+ * Successful completion of initialization.
+ */
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* hwi_get_node_address_check
+* ==========================
+*
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_get_node_address_check routine reads the adapter's permanent
+* node address from the Fastmac status block (STB) in DIO space. It then
+* checks to see if this node address is a valid Madge address. This
+* checks that Fastmac is correctly installed.
+*
+* For ATULA and MC cards, the adapter node address has actually been read
+* once already. There is no harm in getting it again, from Fastmac this
+* time; (previously it was read from the BIA PROM). For EISA cards, the
+* node address has not been read previously. This is the first time we can
+* get it. The node address is not readable from the host with EISA cards.
+* Only Fastmac can find it out for us.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_get_node_address_check)
+#endif
+
+export WBOOLEAN
+hwi_get_node_address_check(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Get the permanent node address from the STB in DIO space.
+ * Record address in adapter structure.
+ */
+
+ sys_outsw(
+ handle,
+ adapter->sif_adr,
+ (WORD)(card_t)&adapter->stb_dio_addr->permanent_address);
+
+ sys_rep_insw(
+ handle,
+ adapter->sif_datinc,
+ (BYTE *)&adapter->permanent_address,
+ (sizeof(NODE_ADDRESS) / 2));
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter );
+#endif
+
+ /*
+ * Byte swap node address after reading from adapter.
+ */
+
+ util_byte_swap_structure(
+ (BYTE *) &adapter->permanent_address,
+ sizeof(NODE_ADDRESS));
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* hwi_interrupt_entry
+* ===================
+*
+*
+* PARAMETERS :
+* ============
+*
+* UINT interrupt_number
+*
+* This is the interrupt number of the interrupting adapter card. If it is
+* zero (POLLING_INTERRUPTS_MODE) then all cards must be checked to see if
+* they require servicing.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_interrupt_entry routine is either called by an operating system
+* specific interrupt detection routine with an actual interrupt number as
+* the parameter or, at intervals, by a routine passing the
+* POLLING_INTERRUPTS_MODE parameter. In the former case all adapters using
+* the given interrupt number are checked for outstanding interrupts. In
+* the latter case, ALL adapters are checked for outstanding interrupts.
+*
+* It is important that hwi_interrupt_entry is not re-entered with a
+* subsequent interrupt on the same adapter. Hence, in the polling case,
+* the routine that called hwi_interrupt_entry must not call it again until
+* the hwi finishes it's current execution. If real interrupts are being
+* used, then care must be taken not to turn interrupts on and allow a
+* further interrupt to cause hwi_interrupt_entry to be re-entered.
+*
+* The details of interrupt handling are dealt with by card specific
+* interrupt handlers. In general, for SIF Fastmac interrupts, th
+* interrupt is acknowledged at the SIF. Driver_interrupt_entry is then
+* called with the interrupt number, details of the relevant adapter and
+* the contents of the EAGLE_SIFINT register. If instead a PIO transfer is
+* required, then the necessary data transfer is performed between the
+* adapter and host memory. PIO can only occur with ATULA adapter cards.
+*
+*
+* Note on increasing speed:
+*
+* One way of speeding up execution of the interrupt routine would be to
+* replace the sys_outsw and sys_insw routines by similar routines supplied
+* with your C compiler and have them compiled in-line. This would be
+* particularly advantageous when handling PIO data transfer.
+*
+*
+* RETURNS :
+* =========
+*
+* This routine always completes successfully.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_interrupt_entry)
+#endif
+
+export void
+hwi_interrupt_entry(
+ ADAPTER_HANDLE adapter_handle,
+ WORD interrupt_number
+ )
+{
+ ADAPTER * adapter;
+
+#ifndef FTK_NO_SHARED_IRQ_POLL
+ for (adapter_handle = 0;
+ adapter_handle < MAX_NUMBER_OF_ADAPTERS;
+ adapter_handle++)
+ {
+#endif
+
+ /*
+ * Get pointer to adapter structure.
+ */
+
+ adapter = adapter_record[adapter_handle];
+
+ /*
+ * In polling mode check ALL adapters.
+ * In interrupt mode check all adapters with correct int number.
+ * Only check actual running, working adapters.
+ */
+
+ if ((adapter != NULL) &&
+ (adapter->adapter_status == ADAPTER_RUNNING) &&
+ ((interrupt_number == POLLING_INTERRUPTS_MODE) ||
+ (adapter->interrupt_number == interrupt_number)))
+ {
+ /*
+ * Interrupts are handled by adapter modules.
+ */
+
+ (*(adapter->interrupt_handler))(adapter);
+ }
+
+#ifndef FTK_NO_SHARED_IRQ_POLL
+ }
+#endif
+
+ return;
+}
+
+
+/****************************************************************************
+*
+* hwi_remove_adapter
+* ==================
+*
+*
+* PARAMETERS :
+* ============
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_remove_adapter routine uses the card bus type to call the
+* correct hwi_<card_type>_remove_card routine.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_remove_adapter)
+#endif
+
+export void
+hwi_remove_adapter(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+
+ /*
+ * Call correct remove routine.
+ */
+
+ (*(adapter->remove_card))(adapter);
+
+ return;
+}
+
+/****************************************************************************
+*
+* UPCALL PROCEDURES - Used by hwi_<card type>.c modules
+*
+****************************************************************************/
+
+/****************************************************************************
+*
+* hwi_halt_eagle
+* ==============
+*
+* The hwi_halt_eagle routine halts the EAGLE. It does this by setting the
+* halt EAGLE bit in the SIF adapter control register. It also resets the
+* adapter by twiddling the adapter reset bit in the same register.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_halt_eagle)
+#endif
+
+export void
+hwi_halt_eagle(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD sif_adapter_control_register = adapter->sif_acl;
+ WORD acontrol_output;
+
+ /*
+ * Set output for SIF register EAGLE_ACONTROL.
+ * Maintain parity; set halt, reset, enable SIF interrupts.
+ */
+
+ acontrol_output = (sys_insw(handle, sif_adapter_control_register) &
+ EAGLE_SIFACL_PARITY) |
+ EAGLE_SIFACL_ARESET |
+ EAGLE_SIFACL_CPHALT |
+ EAGLE_SIFACL_BOOT |
+ EAGLE_SIFACL_SINTEN |
+ adapter->nselout_bits;
+
+ if (adapter->EaglePsDMA)
+ {
+ acontrol_output |= EAGLE_SIFACL_PSDMAEN;
+ }
+
+ /*
+ * Wait at least 14 microseconds before putting adapter in reset state.
+ * We may have just taken adapter out of reset state.
+ * 14us is the minimum time must hold ARESET low between resets.
+ * Disable and re-enable accessing IO locations around wait so
+ * OS can reschedule this task and not effect others running.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter );
+#endif
+
+ sys_wait_at_least_microseconds(14);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter );
+#endif
+
+ /*
+ * Output to SIF register EAGLE_ACONTROL to halt EAGLE.
+ */
+
+ sys_outsw(
+ handle,
+ sif_adapter_control_register,
+ acontrol_output);
+
+ /*
+ * Wait at least 14 microseconds before taking adapter out of reset
+ * state.
+ * 14us is the minimum time must hold ARESET low between resets.
+ * Disable and re-enable accessing IO locations around wait so
+ * OS can reschedule this task and not effect others running.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter );
+#endif
+
+ sys_wait_at_least_microseconds(14);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter );
+#endif
+
+ /*
+ * Bring EAGLE out of reset state, maintain halt status.
+ */
+
+ sys_outsw(
+ handle,
+ sif_adapter_control_register,
+ (WORD) (acontrol_output & ~EAGLE_SIFACL_ARESET));
+
+ return;
+}
+
+
+/****************************************************************************
+*
+* hwi_download_code
+* =================
+*
+* The hwi_download_code routine downloads the given data to the adapter.
+* This must be done with the EAGLE halted. Besides details of the adapter
+* and a pointer to the first download reocrd of the download image, the
+* routine is passed a helper routine for setting DIO addresses for the
+* actual downloading.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_download_code)
+#endif
+
+export WBOOLEAN
+hwi_download_code(
+ ADAPTER * adapter,
+ DOWNLOAD_RECORD * download_record,
+ void (*set_dio_address)(ADAPTER *, DWORD)
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD sif_data_inc_register = adapter->sif_datinc;
+ UINT i;
+
+ /*
+ * If there is no code to be downloaded then fail.
+ */
+
+ if (download_record == NULL)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0A_NO_DOWNLOAD_IMAGE;
+ return FALSE;
+ }
+
+ /*
+ * The first record in the image must be a MODULE type record.
+ */
+
+ if (download_record->type != DOWNLOAD_RECORD_TYPE_MODULE)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_09_BAD_DOWNLOAD_IMAGE;
+ return FALSE;
+ }
+
+ /*
+ * The code to be downloaded must be Fastmac (Plus).
+ */
+
+ if ((download_record->body.module.download_features &
+ DOWNLOAD_FASTMAC_INTERFACE) == 0)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_09_BAD_DOWNLOAD_IMAGE;
+ return FALSE;
+ }
+
+ /*
+ * Get the next download record.
+ */
+
+ macro_get_next_record(download_record);
+
+ /*
+ * Now download the data; a zero length record marks the end.
+ */
+
+ while (download_record->length != 0)
+ {
+ /*
+ * the action depends on type of record.
+ */
+
+ if (download_record->type == DOWNLOAD_RECORD_TYPE_DATA_32)
+ {
+ /*
+ * Set DIO address for downloading data to in SIF registers.
+ */
+
+ (*set_dio_address)(
+ adapter,
+ download_record->body.data_32.dio_addr);
+
+ /*
+ * Download data.
+ */
+
+ for (i = 0; i < download_record->body.data_32.word_count; i++)
+ {
+ sys_outsw(
+ handle,
+ sif_data_inc_register,
+ download_record->body.data_32.data[i]);
+ }
+
+ /*
+ * Check download worked by reading back and comparing.
+ */
+
+ (*set_dio_address)(
+ adapter,
+ download_record->body.data_32.dio_addr);
+
+ for (i = 0; i < download_record->body.data_32.word_count; i++)
+ {
+ if (sys_insw(handle, sif_data_inc_register) !=
+ download_record->body.data_32.data[i])
+ {
+ /*
+ * Fill in error record if read back not correct.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_08_BAD_DOWNLOAD;
+ return FALSE;
+ }
+ }
+ }
+ else if (download_record->type == DOWNLOAD_RECORD_TYPE_FILL_32)
+ {
+ /*
+ * Set DIO address for downloading to in SIF registers.
+ */
+
+ (*set_dio_address)(
+ adapter,
+ download_record->body.fill_32.dio_addr);
+
+ /*
+ * Fill EAGLE memory with required pattern.
+ */
+
+ for (i = 0; i < download_record->body.fill_32.word_count; i++)
+ {
+ sys_outsw(
+ handle,
+ sif_data_inc_register,
+ download_record->body.fill_32.pattern);
+ }
+
+ /*
+ * Check download worked by reading back and comparing.
+ */
+
+ (*set_dio_address)(
+ adapter,
+ download_record->body.fill_32.dio_addr);
+
+ for (i = 0; i < download_record->body.fill_32.word_count; i++)
+ {
+ WORD x;
+
+ if ((x = sys_insw(handle, sif_data_inc_register)) !=
+ download_record->body.fill_32.pattern)
+ {
+ /*
+ * Fill in error record if read back not correct.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_08_BAD_DOWNLOAD;
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Can only have DATA and FILL records after first MODULE.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_09_BAD_DOWNLOAD_IMAGE;
+ return FALSE;
+ }
+
+ /*
+ * Get the next download record.
+ */
+
+ macro_get_next_record(download_record);
+ }
+
+ /*
+ * Successful downloading complete.
+ */
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* hwi_start_eagle
+* ===============
+*
+* The hwi_start_eagle routine takes the EAGLE out of the halt state it is
+* in.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_start_eagle)
+#endif
+
+export void
+hwi_start_eagle(
+ ADAPTER * adapter
+ )
+{
+ WORD sif_adapter_control_register = adapter->sif_acl;
+
+ /*
+ * Only change the halt status in the SIF register EAGLE_ACONTROL.
+ */
+
+ sys_outsw(
+ adapter->adapter_handle,
+ sif_adapter_control_register,
+ (WORD) (sys_insw(
+ adapter->adapter_handle,
+ sif_adapter_control_register) & ~EAGLE_SIFACL_CPHALT));
+
+}
+
+
+/****************************************************************************
+*
+* hwi_get_bring_up_code
+* =====================
+*
+* The hwi_get_bring_up_code routine waits for at least 15 seconds for a
+* valid bring up code to appear in the SIF interrupt register. If bring up
+* fails then this routine will retry up to 10 times. If even this fails,
+* then an error record is filled in.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_get_bring_up_code)
+#endif
+
+export WBOOLEAN
+hwi_get_bring_up_code(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD sif_interrupt_register = adapter->sif_int;
+ UINT index;
+ BYTE bring_up_code;
+ BYTE bring_up_error;
+ UINT retry;
+
+ /*
+ * We'll retry 10 times and if we don't get any other error we'll
+ * return a timeout.
+ */
+
+ retry = 10;
+ bring_up_error = BRING_UP_E_10_TIME_OUT;
+
+ do
+ {
+ retry--;
+
+ for (index = 0; index < 60; index++)
+ {
+ /*
+ * No bring up code available yet. Wait at least a quarter of a
+ * second before trying again. Disable and re-enable accessing IO
+ * locations around wait so delay can reschedule this task and not
+ * effect others running.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter );
+#endif
+
+ sys_wait_at_least_milliseconds(250);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter );
+#endif
+
+ /*
+ * Get bring up code from SIFSTS register.
+ */
+
+ bring_up_code = sys_insb(handle, sif_interrupt_register);
+
+ /*
+ * Check for successful bring up in top nibble of SIFSTS register.
+ * Success is shown by INITIALIZE bit being set.
+ */
+
+ if ((bring_up_code & EAGLE_BRING_UP_TOP_NIBBLE) ==
+ EAGLE_BRING_UP_SUCCESS)
+ {
+ return TRUE;
+ }
+
+ /*
+ * Check for failed bring up in top nibble of SIFSTS register.
+ * Failure is shown by the TEST and ERROR bits being set.
+ */
+
+ if ((bring_up_code & EAGLE_BRING_UP_TOP_NIBBLE) ==
+ EAGLE_BRING_UP_FAILURE)
+ {
+ /*
+ * Get actual bring up error code from bottom nibble of
+ * SIFSTS.
+ */
+
+ bring_up_error = bring_up_code & EAGLE_BRING_UP_BOTTOM_NIBBLE;
+ break;
+ }
+ }
+
+ /*
+ * We have failed to do a bring up, if retry hasn't reached
+ * zero yet then write 0xff00 to SIFINT to reset the Eagle
+ * and start bring up again.
+ */
+
+ if (retry > 0)
+ {
+ sys_outsw(handle, sif_interrupt_register, (WORD) 0xff00);
+ }
+ }
+ while (retry > 0);
+
+ /*
+ * We have completely failed bring up so return an error.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_BRING_UP;
+ adapter->error_record.value = bring_up_error;
+
+ return FALSE;
+}
+
+
+/****************************************************************************
+*
+* hwi_get_max_frame_size
+* ======================
+*
+* The hwi_get_max_frame_size routine uses the ring speed register in DIO
+* space to find the ring speed and hence the maximum allowable frame size
+* set by the ISO standard.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_get_max_frame_size)
+#endif
+
+export WORD
+hwi_get_max_frame_size(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD sif_dio_address_register = adapter->sif_adr;
+ WORD sif_dio_data_register = adapter->sif_dat;
+
+ /*
+ * Set DIO address register to point to ring speed register.
+ * Note that SIFADRX already equals 0x0001 (for DATA page at 0x10000).
+ */
+
+ sys_outsw(
+ handle,
+ sif_dio_address_register,
+ DIO_LOCATION_RING_SPEED_REG);
+
+ /*
+ * Use the contents of the ring speed register to determine ring speed.
+ */
+
+ if (sys_insw(handle, sif_dio_data_register) & RING_SPEED_REG_4_MBITS_MASK)
+ {
+ return MAX_FRAME_SIZE_4_MBITS;
+ }
+ else
+ {
+ return MAX_FRAME_SIZE_16_MBITS;
+ }
+
+}
+
+
+/****************************************************************************
+*
+* hwi_get_ring_speed
+* ==================
+*
+* The hwi_get_ring_speed routine uses the ring speed register in DIO
+* space to find the ring speed.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_get_ring_speed)
+#endif
+
+export UINT
+hwi_get_ring_speed(
+ ADAPTER * adapter
+ )
+{
+ WORD sif_dio_address_register = adapter->sif_adr;
+ WORD sif_dio_data_register = adapter->sif_dat;
+ ADAPTER_HANDLE hnd = adapter->adapter_handle;
+
+ /*
+ * Set DIO address register to point to ring speed register.
+ * Note that SIFADRX already equals 0x0001 (for DATA page at 0x10000).
+ */
+
+ sys_outsw(
+ hnd,
+ sif_dio_address_register,
+ DIO_LOCATION_RING_SPEED_REG);
+
+ /*
+ * Use the contents of the ring speed register to determine ring speed.
+ */
+
+ if (sys_insw(hnd, sif_dio_data_register) & RING_SPEED_REG_4_MBITS_MASK)
+ {
+ return 4;
+ }
+ else
+ {
+ return 16;
+ }
+
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|
+| hwi_copy_to_dio_space
+| =====================
+|
+| The hwi_copy_to_dio_space routine copies the given amount of data into
+| DIO space at the specified location. The method of setting up the SIF
+| DIO address registers depends on the type of adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_copy_to_dio_space)
+#endif
+
+local void
+hwi_copy_to_dio_space(
+ ADAPTER * adapter,
+ DWORD dio_location,
+ BYTE * download_data,
+ WORD data_length_bytes
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+
+ /*
+ * Set up DIO address in SIF DIO address registers.
+ * This needs to be done differently depending on adapter card type.
+ */
+
+ (*(adapter->set_dio_address))(adapter, dio_location);
+
+ /*
+ * Copy data into DIO space.
+ */
+ sys_rep_outsw(
+ handle,
+ adapter->sif_datinc,
+ download_data,
+ (WORD) (data_length_bytes / 2));
+
+ if (data_length_bytes & 1)
+ {
+ /*
+ * Byte out instructions do not work on the Ti PCI card,
+ * as it is not definate whether we ship this card, the fix
+ * shall stay here for now. PRR
+ */
+ if (adapter->adapter_card_type != ADAPTER_CARD_TYPE_16_4_PCIT)
+ {
+ sys_outsb(
+ handle,
+ adapter->sif_datinc,
+ *(download_data + data_length_bytes - 1));
+ }
+ #ifndef FTK_NO_PCIT
+ else
+ {
+ WORD last_byte;
+ last_byte = *(download_data + data_length_bytes - 1);
+ last_byte <<= 8;
+ last_byte &= 0xFF00;
+ sys_outsw(
+ handle,
+ adapter->sif_datinc,
+ last_byte);
+
+ }
+ #endif
+ }
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_read_sifint
+| ===============
+|
+| Read the SIFINT register. This function is called via
+Ý sys_sych_with_interruptto avoid DMA/SIF problems on PciT adapters.
+---------------------------------------------------------------------------*/
+
+local WBOOLEAN
+hwi_read_sifint(
+ void * ptr
+ );
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_read_sifint)
+#endif
+
+local WBOOLEAN
+hwi_read_sifint(
+ void * ptr
+ )
+{
+ ADAPTER * adapter = (ADAPTER *) ptr;
+
+ return sys_insb(adapter->adapter_handle, adapter->sif_int);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_get_init_code
+| =================
+|
+| The hwi_get_init_code routine waits for at least 11 seconds for a valid
+| initialization code to appear in the SIF interrupt register. If
+| initialization fails then this routine fills in the adapter error
+| record.
+|
+---------------------------------------------------------------------------*/
+
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_get_init_code)
+#endif
+
+local WBOOLEAN
+hwi_get_init_code(
+ ADAPTER * adapter
+ )
+{
+ UINT index;
+ BYTE init_code;
+
+ for (index = 0; index < 100; index++)
+ {
+ /*
+ * Get initialization code from SIFSTS register.
+ */
+
+ init_code = (BYTE) sys_sync_with_interrupt(
+ adapter->adapter_handle,
+ hwi_read_sifint,
+ (void *) adapter
+ );
+
+ /*
+ * Check for successful initialization in top nibble of SIFSTS.
+ * Success is shown by INITIALIZE, TEST and ERROR bits being zero.
+ */
+
+ if ((init_code & EAGLE_INIT_SUCCESS_MASK) == 0)
+ {
+ return TRUE;
+ }
+
+ /*
+ * Check for failed initialization in top nibble of SIFSTS.
+ * Failure is shown by the ERROR bit being set.
+ */
+
+ if ((init_code & EAGLE_INIT_FAILURE_MASK) != 0)
+ {
+ /*
+ * Get actual init error code from bottom nibble of SIFSTS
+ */
+
+ init_code = init_code & EAGLE_INIT_BOTTOM_NIBBLE;
+
+ /*
+ * Fill in error record with actual initialization error code.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_INIT;
+ adapter->error_record.value = init_code;
+ return FALSE;
+ }
+
+ /*
+ * No initialization code available yet. Wait at least a quarter of
+ * a second before trying again. Disable and re-enable accessing IO
+ * locations around wait so OS can reschedule this task and not
+ * effect others running.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter );
+#endif
+
+ sys_wait_at_least_milliseconds(250);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter );
+#endif
+
+ }
+
+ /*
+ * At least 11 seconds have gone so return time out failure.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_INIT;
+ adapter->error_record.value = INIT_E_10_TIME_OUT;
+ return FALSE;
+
+}
+
+
+/******* End of HWI_GEN.C **************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_mc.c b/private/ntos/ndis/madge/driver/hwi_mc.c
new file mode 100644
index 000000000..eb67eb5eb
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_mc.c
@@ -0,0 +1,1326 @@
+/****************************************************************************
+*
+* HWI_MC.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* THE HARDWARE INTERFACE MODULE FOR MICROCHANNEL CARDS
+*
+* Copyright (c) Madge Networks Ltd. 1990-1994
+*
+* COMPANY CONFIDENTIAL
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_MC.C module contains the routines specific to 16/4 MC and 16/4
+* MC 32 cards which are necessary to install an adapter, to initialize an
+* adapter, to remove an adapter and to handle interrupts on an adapter.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+#ifndef FTK_NO_MC
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local void
+hwi_mc_read_node_address(
+ ADAPTER * adapter
+ );
+
+local WBOOLEAN
+hwi_mc_valid_io_location(
+ WORD io_location
+ );
+
+#ifndef FTK_NO_PROBE
+
+local WORD
+hwi_mc_get_irq_channel(
+ WORD io_location
+ );
+
+local WORD
+hwi_mc_get_dma_channel(
+ WORD io_location
+ );
+
+#endif
+
+local WBOOLEAN
+hwi_mc_valid_irq_channel(
+ WORD irq_channel
+ );
+
+local WBOOLEAN
+hwi_mc_valid_dma_channel(
+ WORD dma_channel
+ );
+
+local WBOOLEAN
+hwi_mc_valid_transfer_mode(
+ UINT transfer_mode
+ );
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_mc_probe_card
+* =================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is an array of IO locations to examine for the presence
+* of an adapter. For microchannel adapters with should be a subset of
+* {0x0a20, 0x1a20, 0x2a20, 0x3a20}.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_mc_probe_card routine is called by hwi_probe_adapter. It
+* reads the id registers to find the type of card and also reads the IRQ.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_probe_card)
+#endif
+
+export UINT
+hwi_mc_probe_card(
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ )
+{
+ WORD pos_0;
+ WORD pos_1;
+ WORD pos_2;
+ WORD control_0;
+ WORD control_1;
+ WORD control_7;
+ WORD bia_prom;
+ WORD bia_prom_id;
+ WORD bia_prom_adap;
+ WORD bia_prom_rev;
+ WBOOLEAN card_found;
+ UINT i;
+ UINT j;
+
+ /*
+ * Check the bounds.
+ */
+
+ if(length <= 0 || number_locations <= 0)
+ {
+ return PROBE_FAILURE;
+ }
+
+ /*
+ * Check we've been passed a valid set of IO locations.
+ */
+
+ for(i = 0; i < number_locations; i++)
+ {
+ if(!hwi_mc_valid_io_location(valid_locations[i]))
+ {
+ return PROBE_FAILURE;
+ }
+ }
+
+ /*
+ * j is the number of adapters found, so zero it.
+ */
+
+ j = 0;
+
+ for(i = 0; i < number_locations; i++)
+ {
+ /*
+ * If we've run out of PROBE structures, return.
+ */
+
+ if(j >= length)
+ {
+ return j;
+ }
+
+ /*
+ * Set up the MC control registers.
+ */
+
+ pos_0 = valid_locations[i] + MC_POS_REGISTER_0;
+ pos_1 = valid_locations[i] + MC_POS_REGISTER_1;
+ pos_2 = valid_locations[i] + MC_POS_REGISTER_2;
+ control_0 = valid_locations[i] + MC_CONTROL_REGISTER_0;
+ control_1 = valid_locations[i] + MC_CONTROL_REGISTER_1;
+ control_7 = valid_locations[i] + MC_CONTROL_REGISTER_7;
+ bia_prom = valid_locations[i] + MC_BIA_PROM;
+ bia_prom_id = bia_prom + BIA_PROM_ID_BYTE;
+ bia_prom_adap = bia_prom + BIA_PROM_ADAPTER_BYTE;
+ bia_prom_rev = bia_prom + BIA_PROM_REVISION_BYTE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_enable_io(valid_locations[i], MC_IO_RANGE);
+#endif
+ card_found = FALSE;
+
+ /*
+ * Reset the card.
+ */
+
+ sys_probe_outsb( control_1, 0);
+ sys_probe_outsb( control_0, 0);
+
+ if (sys_probe_insb(bia_prom_id) == 'M')
+ {
+ if (sys_probe_insb(bia_prom_adap) ==
+ BIA_PROM_TYPE_16_4_MC)
+ {
+ resources[j].adapter_card_type =
+ ADAPTER_CARD_TYPE_16_4_MC;
+
+ if(sys_probe_insb(bia_prom_rev) < 2)
+ {
+ resources[j].adapter_ram_size = 128;
+ }
+ else
+ {
+ resources[j].adapter_ram_size = 256;
+ }
+
+ card_found = TRUE;
+ }
+ else if (sys_probe_insb(bia_prom_adap) ==
+ BIA_PROM_TYPE_16_4_MC_32)
+ {
+ resources[j].adapter_card_type =
+ ADAPTER_CARD_TYPE_16_4_MC_32;
+
+ resources[j].adapter_ram_size = 256;
+
+ card_found = TRUE;
+ }
+ }
+
+ if(card_found)
+ {
+ resources[j].io_location = valid_locations[i];
+ resources[j].adapter_card_bus_type = ADAPTER_CARD_MC_BUS_TYPE;
+ resources[j].interrupt_number = hwi_mc_get_irq_channel(
+ valid_locations[i]);
+ resources[j].dma_channel = hwi_mc_get_dma_channel(
+ valid_locations[i]);
+ resources[j].transfer_mode = DMA_DATA_TRANSFER_MODE;
+
+ /*
+ * Increment j to point at the next PROBE structure.
+ */
+
+ j++;
+ }
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_disable_io(resources->io_location, MC_IO_RANGE);
+#endif
+ }
+
+ return j;
+}
+#endif
+
+/****************************************************************************
+*
+* hwi_mc_install_card
+* ===================
+*
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_mc_install_card routine is called by hwi_install_adapter. It
+* sets up the adapter card and downloads the required code to it. Firstly,
+* it checks there is a valid adapter at the required IO address. If so it
+* reads the node address from the BIA PROM and sets up and checks numerous
+* on-board registers for correct operation.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls. There is
+* no need to explicitly enable DMA. Note PIO can not be used.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_install_card)
+#endif
+
+export WBOOLEAN
+hwi_mc_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD pos_0 = adapter->io_location +
+ MC_POS_REGISTER_0;
+ WORD pos_1 = adapter->io_location +
+ MC_POS_REGISTER_1;
+ WORD pos_2 = adapter->io_location +
+ MC_POS_REGISTER_2;
+ WORD control_0 = adapter->io_location +
+ MC_CONTROL_REGISTER_0;
+ WORD control_1 = adapter->io_location +
+ MC_CONTROL_REGISTER_1;
+ WORD control_7 = adapter->io_location +
+ MC_CONTROL_REGISTER_7;
+ WORD bia_prom = adapter->io_location +
+ MC_BIA_PROM;
+ WORD bia_prom_id = bia_prom +
+ BIA_PROM_ID_BYTE;
+ WORD bia_prom_adap = bia_prom +
+ BIA_PROM_ADAPTER_BYTE;
+ WORD bia_prom_rev = bia_prom +
+ BIA_PROM_REVISION_BYTE;
+ BYTE streaming;
+ BYTE fairness;
+ BYTE arbitration;
+ WBOOLEAN card_found;
+ WORD sif_base;
+
+
+ /*
+ * Check the IO location is valid.
+ */
+
+ if(!hwi_mc_valid_io_location(adapter->io_location))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION;
+
+ return FALSE;
+ }
+
+ /*
+ * Check the transfer mode is valid.
+ */
+
+ if(!hwi_mc_valid_transfer_mode(adapter->transfer_mode))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION;
+
+ return FALSE;
+ }
+
+ /*
+ * Check the DMA channel is valid.
+ */
+
+ if(!hwi_mc_valid_dma_channel(adapter->dma_channel))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_04_BAD_DMA_CHANNEL;
+
+ return FALSE;
+ }
+
+ /*
+ * Check the IRQ is valid.
+ */
+
+ if(!hwi_mc_valid_irq_channel(adapter->interrupt_number))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_03_BAD_INTERRUPT_NUMBER;
+
+ return FALSE;
+ }
+
+ /*
+ * Save IO locations of SIF registers.
+ */
+
+ sif_base = adapter->io_location + MC_FIRST_SIF_REGISTER;
+
+ adapter->sif_dat = sif_base + EAGLE_SIFDAT;
+ adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC;
+ adapter->sif_adr = sif_base + EAGLE_SIFADR;
+ adapter->sif_int = sif_base + EAGLE_SIFINT;
+ adapter->sif_acl = sif_base + MC_EAGLE_SIFACL;
+ adapter->sif_adr2 = sif_base + MC_EAGLE_SIFADR_2;
+ adapter->sif_adx = sif_base + MC_EAGLE_SIFADX;
+ adapter->sif_dmalen = sif_base + MC_EAGLE_DMALEN;
+
+ adapter->io_range = MC_IO_RANGE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Reset adapter (MC_CTRL1_NSRESET = 0).
+ */
+
+ sys_outsb(handle, control_1, 0);
+
+ /*
+ * Page in the first page of BIA PROM and set MC_CTRL0_PAGE = 0
+ * and MC_CTRL0_SIFSEL = 0.
+ */
+
+ sys_outsb(handle, control_0, 0);
+
+ /*
+ * Check we have a functioning adapter at the given IO location by
+ * checking the BIA PROM for an 'M' id byte and also by checking that
+ * the BIA adapter card byte is for a supported card type
+ * While we are doing this, we might as well record the card revision
+ * type, and use it to work out how much memory is on the card.
+ */
+
+ card_found = FALSE;
+
+ if (sys_insb( handle, bia_prom_id) == 'M')
+ {
+ if (sys_insb( handle, bia_prom_adap) ==
+ BIA_PROM_TYPE_16_4_MC)
+ {
+ adapter->adapter_card_type =
+ ADAPTER_CARD_TYPE_16_4_MC;
+
+ adapter->adapter_card_revision =
+ sys_insb(handle, bia_prom_rev);
+
+ if (adapter->adapter_card_revision < 2)
+ {
+ adapter->adapter_ram_size = 128;
+ }
+ else
+ {
+ adapter->adapter_ram_size = 256;
+ }
+
+ card_found = TRUE;
+ }
+ else if (sys_insb(handle, bia_prom_adap) ==
+ BIA_PROM_TYPE_16_4_MC_32)
+ {
+ adapter->adapter_card_type =
+ ADAPTER_CARD_TYPE_16_4_MC_32;
+
+ adapter->adapter_card_revision =
+ sys_insb(handle, bia_prom_rev);
+
+ adapter->adapter_ram_size = 256;
+
+ card_found = TRUE;
+ }
+ }
+
+ /*
+ * If no MC card found then fill in error record and return.
+ */
+
+ if (!card_found)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Check that the adapter card is enabled. If not then fill in error
+ * record and return.
+ */
+
+ if ((sys_insb(handle, pos_0) & MC_POS0_CDEN) == 0)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0D_CARD_NOT_ENABLED;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Check that a speed has been selected for the card.
+ */
+
+ if ((sys_insb(handle, pos_1) & MC_POS1_NOSPD) != 0)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0E_NO_SPEED_SELECTED;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return(FALSE);
+ }
+
+ /*
+ * Interrupts for MC cards are always level triggered.
+ */
+
+ adapter->edge_triggered_ints = FALSE;
+
+ /*
+ * Card speed has been set to 4Mb/s by machine reset. Set card to 16Mb/s
+ * if necessary.
+ */
+
+ if ((sys_insb(handle, pos_2) & MC_POS2_16N4) != 0)
+ {
+ macro_setb_bit(handle, control_1, MC_CTRL1_16N4);
+ }
+
+ /*
+ * Find the adapter card node address.
+ */
+
+ hwi_mc_read_node_address(adapter);
+
+ /*
+ * There are no other special control registers to set up for MC cards.
+ */
+
+ /*
+ * Wait at least 14 microseconds and bring adapter out of reset state.
+ * 14us is the minimum time must hold MC_CTRL1_NSRESET low.
+ * There are no CLKSEL issues as with ATULA cards for MC cards.
+ * Disable and re-enable accessing IO locations around the wait
+ * so the OS can reschedule this task and not effect others running.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ sys_wait_at_least_microseconds(14);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ macro_setb_bit(handle, control_1, MC_CTRL1_NSRESET);
+
+ /*
+ * Media type set to STP (type 6) by machine reset on 16 4 MC
+ * and set to UTP (type 3) by MC_CTRL1_NSRESET on 16 4 MC 32.
+ * Change media type if necessary now that MC_CTRL1_NSRESET != 0.
+ * POS media type bit is in different place for 16/4 MC and 16/4 MC 32.
+ */
+
+ if (adapter->adapter_card_type == ADAPTER_CARD_TYPE_16_4_MC)
+ {
+ if ((sys_insb(handle, pos_1) & MC_POS1_STYPE6) == 0)
+ {
+ macro_setb_bit(handle, control_7, MC_CTRL7_STYPE3);
+ }
+ }
+ else
+ {
+ if ((sys_insb(handle, pos_1) & MC32_POS1_STYPE6) != 0)
+ {
+ macro_clearb_bit(handle, control_7, MC_CTRL7_STYPE3);
+ }
+ }
+
+ /*
+ * Get extended SIF registers, halt EAGLE, then get normal SIF regs.
+ */
+
+ macro_setb_bit(handle, control_0, MC_CTRL0_SIFSEL);
+ macro_setb_bit(handle, control_1, MC_CTRL1_SRSX);
+
+ hwi_halt_eagle(adapter);
+
+ macro_clearb_bit(handle, control_1, MC_CTRL1_SRSX);
+
+ /*
+ * Download code to the adapter. View download image as a sequence of
+ * download records. Pass address of routine to set up DIO addresses
+ * on MC cards.
+ */
+
+ if (!hwi_download_code(
+ adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_mc_set_dio_address))
+ {
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Get extended SIF registers, start EAGLE, then get normal SIF regs.
+ */
+
+ macro_setb_bit(handle, control_1, MC_CTRL1_SRSX);
+
+ hwi_start_eagle(adapter);
+
+ macro_clearb_bit(handle, control_1, MC_CTRL1_SRSX);
+
+ /*
+ * Wait for a valid bring up code, may wait 3 seconds.
+ */
+
+ if (!hwi_get_bring_up_code(adapter))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Set DIO address to point to EAGLE DATA page 0x10000L.
+ */
+
+ hwi_mc_set_dio_address(
+ adapter,
+ DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * Set maximum frame size from the ring speed.
+ */
+
+ adapter->max_frame_size = hwi_get_max_frame_size(adapter);
+
+ /*
+ * Set the ring speed.
+ */
+
+ adapter->ring_speed = hwi_get_ring_speed(adapter);
+
+ /* if not in polling mode then set up interrupts */
+ /* interrupts_on field is used when disabling interrupts for adapter */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on =
+ sys_enable_irq_channel(handle, adapter->interrupt_number);
+
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+ /*
+ * Enable interrupts at adapter (do this even in polling mode).
+ * Hence when polling still 'using' interrupt channel
+ * so do not use card interrupt switch setting shared by other devices.
+ */
+
+ macro_setb_bit(handle, control_1, MC_CTRL1_SINTREN);
+
+ /*
+ * No need to explicitly set up DMA channel for MC card.
+ */
+
+ /*
+ * Set up 16/4 MC 32 configuation information.
+ * This information is later placed in the TI initialization block.
+ * It includes streaming, fairness and aribtration level details.
+ */
+
+ if (adapter->adapter_card_type == ADAPTER_CARD_TYPE_16_4_MC_32)
+ {
+ /*
+ * Get streaming info, adjust bit position for mc32_config byte.
+ */
+
+ streaming = sys_insb(handle, pos_2) & MC_POS2_STREAMING;
+ streaming = (BYTE)(streaming >> MC32_CONFIG_STREAMING_SHIFT);
+
+ /*
+ * Get fairness info, adjust bit position for mc32_config byte.
+ */
+
+ fairness = sys_insb(handle, pos_2) & MC_POS2_FAIRNESS;
+ fairness = (BYTE)(fairness >> MC32_CONFIG_FAIRNESS_SHIFT);
+
+ /*
+ * Get arbitration info, adjust bit position for mc32_config byte.
+ */
+
+ arbitration = sys_insb(handle, pos_0) & MC_POS0_DMAS;
+ arbitration = (BYTE)(arbitration >> MC32_CONFIG_DMA_SHIFT);
+
+ /*
+ * Record mc32_config byte.
+ */
+
+ adapter->mc32_config = streaming | fairness | arbitration;
+ }
+
+ /*
+ * Return successfully.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ return(TRUE);
+
+}
+
+
+/****************************************************************************
+*
+* hwi_mc_interrupt_handler
+* ========================
+*
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_mc_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF only.
+* There are no PIO interupts on MC cards. Note it could in fact be the
+* case that no interrupt has occured on the particular adapter being
+* checked.
+*
+* On SIF interrupts, the interrupt is acknowledged and cleared. The value
+* in the SIF interrupt register is recorded in order to pass it to the
+* driver_interrupt_entry routine (along with the adapter details).
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_mc_interrupt_handler)
+#endif
+
+export void
+hwi_mc_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_0 = adapter->io_location +
+ MC_CONTROL_REGISTER_0;
+ WORD control_1 = adapter->io_location +
+ MC_CONTROL_REGISTER_1;
+ WORD sifint_value;
+ WORD sifint_tmp;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter);
+#endif
+
+ /*
+ * Check for SIF interrupt (do not get PIO interrupts on MC cards).
+ */
+
+ if ((sys_insb( handle, control_0) & MC_CTRL0_SINTR) != 0)
+ {
+ /*
+ * SIF interrupt has occurred. This could be an SRB free, an adapter
+ * check or a received frame interrupt.
+ */
+
+ /*
+ * Toggle SIF interrupt enable to acknowledge interrupt at MC card.
+ */
+
+ macro_clearb_bit(handle, control_1, MC_CTRL1_SINTREN);
+ macro_setb_bit(handle, control_1, MC_CTRL1_SINTREN);
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+ */
+
+ /*
+ * WARNING: Do NOT reorder the clearing of the SIFINT register with
+ * the reading of it. If SIFINT is cleared after reading it, any
+ * interrupts raised after reading it will be lost. Admittedly
+ * this is a small time frame, but it is important.
+ */
+
+ sys_outsw(handle, adapter->sif_int, 0);
+
+ /*
+ * Record the EAGLE SIF interrupt register value.
+ */
+
+ /*
+ * WARNING: Continue to read the SIFINT register until it is stable
+ * because of a potential problem involving the host reading the
+ * register after the adapter has written the low byte of it, but
+ * before it has written the high byte. Failure to wait for the
+ * SIFINT register to settle can cause spurious interrupts.
+ */
+
+ sifint_value = sys_insw(handle, adapter->sif_int);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(
+ handle,
+ adapter->sif_int );
+ } while (sifint_tmp != sifint_value);
+
+ /*
+ * Acknowledge/clear interrupt at interrupt controller.
+ */
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(handle, adapter->interrupt_number);
+#endif
+
+ /*
+ * No need regenerate any interrupts because using level sensitive.
+ */
+
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+
+ driver_interrupt_entry(handle, adapter, sifint_value);
+
+ }
+
+ /*
+ * Let system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+
+ return;
+}
+
+
+/****************************************************************************
+*
+* hwi_mc_remove_card
+* ==================
+*
+*
+* PARAMETERS (passed by hwi_remove_adapter) :
+* ===========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_mc_remove_card routine is called by hwi_remove_adapter. It
+* disables interrupts if they are being used. It also resets the adapter.
+* Note there is no need to explicitly disable DMA channels.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_mc_remove_card)
+#endif
+
+export void
+hwi_mc_remove_card(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location + MC_CONTROL_REGISTER_1;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Disable interrupts. Only need to do this if interrupts successfully
+ * enabled. Interrupt must be disabled at adapter before unpatching
+ * interrupt. Even in polling mode we must turn off interrupts at
+ * adapter.
+ */
+
+ if (adapter->interrupts_on)
+ {
+
+ macro_clearb_bit(handle, control_1, MC_CTRL1_SINTREN);
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(handle, adapter->interrupt_number);
+ }
+
+ adapter->interrupts_on = FALSE;
+
+ }
+
+ /*
+ * Perform adapter reset, set MC_CTRL1_NSRESET low.
+ */
+
+ sys_outsb(handle, control_1, 0);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+}
+
+
+/****************************************************************************
+*
+* hwi_mc_set_dio_address
+* ======================
+*
+* The hwi_mc_set_dio_address routine is used, with MC cards, for putting a
+* 32 bit DIO address into the SIF DIO address and extended DIO address
+* registers. Note that the extended address register should be loaded
+* first.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_set_dio_address)
+#endif
+
+export void
+hwi_mc_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location +
+ MC_CONTROL_REGISTER_1;
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * Page in extended SIF registers.
+ */
+
+ macro_setb_bit(handle, control_1, MC_CTRL1_SRSX);
+
+ /*
+ * Load extended DIO address register with top 16 bits of address.
+ * Always load extended address register first.
+ */
+
+ sys_outsw(handle, sif_dio_adrx, (WORD)(dio_address >> 16));
+
+ /*
+ * Return to having normal SIF registers paged in.
+ */
+
+ macro_clearb_bit(handle, control_1, MC_CTRL1_SRSX);
+
+ /*
+ * Load DIO address register with low 16 bits of address.
+ */
+
+ sys_outsw(handle, sif_dio_adr, (WORD)(dio_address & 0x0000FFFF));
+
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|
+| hwi_mc_read_node_address
+| ========================
+|
+| The hwi_mc_read_node_address routine reads in the node address that is
+| stored in the second page of the BIA PROM on MC cards.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_read_node_address)
+#endif
+
+local void
+hwi_mc_read_node_address(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE handle = adapter->adapter_handle;
+ WORD control_0 = adapter->io_location +
+ MC_CONTROL_REGISTER_0;
+ WORD bia_prom = adapter->io_location +
+ MC_BIA_PROM;
+ WORD bia_prom_address = bia_prom + BIA_PROM_NODE_ADDRESS;
+ WORD index;
+
+ /*
+ * Page in second page of BIA PROM containing node address.
+ */
+
+ macro_setb_bit(handle, control_0, MC_CTRL0_PAGE);
+
+ /*
+ * Read node address from BIA PROM.
+ */
+
+ for (index = 0; index < 6; index++)
+ {
+ adapter->permanent_address.byte[index] =
+ sys_insb(handle, (WORD) (bia_prom_address + index));
+ }
+
+ /*
+ * Restore first page of BIA PROM.
+ */
+
+ macro_clearb_bit(handle, control_0, MC_CTRL0_PAGE);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_mc_valid_io_location
+| ========================
+|
+| The hwi_mc_valid_io_location routine checks to see if the user has
+| supplied a valid IO location for an MC adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_valid_io_location)
+#endif
+
+local WBOOLEAN
+hwi_mc_valid_io_location(
+ WORD io_location
+ )
+{
+ WBOOLEAN io_valid;
+
+ switch (io_location)
+ {
+ case 0x0A20 :
+ case 0x1A20 :
+ case 0x2A20 :
+ case 0x3A20 :
+ case 0x0E20 :
+ case 0x1E20 :
+ case 0x2E20 :
+ case 0x3E20 :
+ /*
+ * These are the valid user supplied io locations.
+ */
+
+ io_valid = TRUE;
+ break;
+
+ default :
+ /*
+ * Anything else is invalid.
+ */
+
+ io_valid = FALSE;
+ break;
+ }
+
+ return(io_valid);
+}
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| hwi_mc_get_irq_channel
+| ======================
+|
+| The hwi_mc_get_irq_channel routine determines the interrupt number that
+| an MC card is using. It does this by looking at one of the POS
+| registers. It always succeeds in finding the interrupt number being
+| used.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_get_irq_channel)
+#endif
+
+local WORD
+hwi_mc_get_irq_channel(
+ WORD io_location
+ )
+{
+ WORD pos_0 = io_location + MC_POS_REGISTER_0;
+ WORD irq = 0;
+ WORD irq_coded;
+
+ /*
+ * The interrupt number is encoded in two bits (7,6) in POS register 0.
+ */
+
+ irq_coded = sys_probe_insb(pos_0) & MC_POS0_IRQSEL;
+
+ /*
+ * There are only 3 possible interrupt numbers that can be configured.
+ * One of these 3 cases will always be true.
+ */
+
+ switch (irq_coded)
+ {
+ case MC_POS0_IRSEL_IRQ3 :
+ irq = 3;
+ break;
+
+ case MC_POS0_IRSEL_IRQ9 :
+ irq = 9;
+ break;
+
+ case MC_POS0_IRSEL_IRQ10 :
+ irq = 10;
+ break;
+
+ default :
+ break;
+
+ }
+
+ /*
+ * Return the discovered interrupt number.
+ */
+
+ return(irq);
+}
+#endif
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| hwi_mc_get_dma_channel
+| ======================
+|
+| The hwi_mc_get_dma_channel routine determines the DMA channel
+| (arbitration level) that an MC card is using. It does this by looking at
+| one of the POS registers. It always succeeds in finding the DMA channel
+| being used.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_get_dma_channel)
+#endif
+
+local WORD
+hwi_mc_get_dma_channel(
+ WORD io_location
+ )
+{
+ WORD pos_0 = io_location + MC_POS_REGISTER_0;
+ WORD dma_coded;
+ WORD dma;
+
+ /*
+ * The DMA channel is encoded in 4 bits (4,3,2,1) in POS register 0.
+ */
+
+ dma_coded = sys_probe_insb(pos_0) & MC_POS0_DMAS;
+
+ /*
+ * In order to get the actual DMA channel, shift right by one bit.
+ */
+
+ dma = dma_coded >> 1;
+
+ /*
+ * Return the discovered DMA channel.
+ */
+
+ return(dma);
+}
+#endif
+
+/*---------------------------------------------------------------------------
+|
+| hwi_mc_valid_irq_channel
+| ========================
+|
+| The hwi_mc_valid_irq_channel routine checks to see if the user has
+| supplied a sensible IRQ for an MC adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_valid_irq_channel)
+#endif
+
+export WBOOLEAN
+hwi_mc_valid_irq_channel(
+ WORD irq_channel
+ )
+{
+ return (irq_channel == POLLING_INTERRUPTS_MODE ||
+ irq_channel == 3 ||
+ irq_channel == 9 ||
+ irq_channel == 10);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_mc_valid_dma_channel
+| ========================
+|
+| The hwi_mc_valid_dma_channel routine checks to see if the user has
+| supplied a sensible dma channel for an MC adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_valid_dma_channel)
+#endif
+
+export WBOOLEAN
+hwi_mc_valid_dma_channel(
+ WORD dma_channel
+ )
+{
+ return (dma_channel <= 14);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_mc_valid_transfer_mode
+| ============================
+|
+| The hwi_mc_valid_transfer_mode routine checks to see if the user has
+| supplied a sensible transfer mode for an MC adapter card. That means DMA
+| at the moment.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_mc_valid_transfer_mode)
+#endif
+
+export WBOOLEAN
+hwi_mc_valid_transfer_mode(
+ UINT transfer_mode
+ )
+{
+ return (transfer_mode == DMA_DATA_TRANSFER_MODE);
+}
+
+
+#endif
+
+/******** End of HWI_MC.C **************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_pci.c b/private/ntos/ndis/madge/driver/hwi_pci.c
new file mode 100644
index 000000000..7eb19fec0
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_pci.c
@@ -0,0 +1,1567 @@
+/****************************************************************************
+*
+* HWI_PCI.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* HARDWARE INTERFACE MODULE FOR PCI CARDS
+*
+* Copyright (c) Madge Networks Ltd. 1994
+*
+* COMPANY CONFIDENTIAL
+*
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_PCI.C module contains the routines specific to the Smart 16/4 PCI
+* card which supports MMIO and pseudo DMA.
+*
+*****************************************************************************
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#define PCI_PCI1_DEVICE_ID 1
+
+#define INT_PCIMMIO_RX 0x40
+#define INT_PCIMMIO_TX 0x20
+#define INT_PCIMMIO (INT_PCIMMIO_RX | INT_PCIMMIO_TX)
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+#ifndef FTK_NO_PCI
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local void
+pci_c46_write_bit(
+ ADAPTER * adapter,
+ WORD mask,
+ WBOOLEAN set_bit
+ );
+
+local void
+pci_c46_twitch_clock(
+ ADAPTER * adapter
+ );
+
+local WORD
+pci_c46_read_data(
+ ADAPTER * adapter
+ );
+
+local WBOOLEAN
+hwi_pci_read_node_address(
+ ADAPTER * adapter
+ );
+
+local WORD
+hwi_pci_read_eeprom_word(
+ ADAPTER * adapter,
+ WORD word_address
+ );
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_pci_probe_card
+* ==================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is normally an array of IO locations to examine for the
+* presence of an adapter. However for PCI adapters the io location is read
+* from the BIOS, so this array can remain empty.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_pci_probe_card routine is called by hwi_probe_adapter. It
+* reads the id registers to find the type of card and also reads the IRQ.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci_probe_card)
+#endif
+
+export UINT
+hwi_pci_probe_card(
+ PROBE * Resources,
+ UINT NumberOfResources,
+ WORD * IOMask,
+ UINT NumberIO
+ )
+{
+ WORD i;
+ WORD Handle;
+ DWORD MMIOAddress;
+
+ if (!sys_pci_valid_machine())
+ {
+ return 0;
+ }
+
+ for (i=0;i<NumberOfResources;i++)
+ {
+ if (!sys_pci_find_card(&Handle, i,PCI_PCI1_DEVICE_ID))
+ {
+ break;
+ }
+
+ Resources[i].adapter_card_bus_type = ADAPTER_CARD_PCI_BUS_TYPE;
+
+ if (!sys_pci_get_io_base(Handle, &(Resources[i].io_location)))
+ {
+ return PROBE_FAILURE;
+ }
+
+ if (!sys_pci_get_irq(Handle, &(Resources[i].interrupt_number)))
+ {
+ return PROBE_FAILURE;
+ }
+
+ if (!sys_pci_get_mem(Handle, &MMIOAddress))
+ {
+ /*
+ * The user wants MMIO and we weren't given any Memory
+ */
+
+ return PROBE_FAILURE;
+ }
+
+ /*
+ * Convert the address to virtual addressing.
+ */
+
+ Resources[i].mmio_base_address = sys_phys_to_virt(0, MMIOAddress);
+
+ /*
+ * We can't read the memory size from the serial EEPROM until the
+ * hwi_pci_install_card function is called.
+ */
+
+ Resources[i].adapter_ram_size = 512;
+
+ Resources[i].adapter_card_type = ADAPTER_CARD_TYPE_16_4_PCI;
+
+ Resources[i].transfer_mode = PIO_DATA_TRANSFER_MODE;
+
+ }
+
+ return i;
+}
+#endif
+
+/****************************************************************************
+*
+* hwi_pci_install_card
+* ====================
+*
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* hwi_pci_install_card is called by hwi_install_adapter. It sets up
+* the adapter card and downloads the required code to it. Firstly, it
+* checks there is a valid adapter at the required IO address by reading
+* the node address from the BIA PROM. It then sets up and checks various
+* on-board registers for correct operation.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls.
+* The adapter is set up for Eagle Pseudo-DMA, since real DMA is not used.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci_install_card)
+#endif
+
+export WBOOLEAN
+hwi_pci_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD control_reg;
+ WORD control_value;
+ WORD sif_base;
+ WORD ring_speed;
+
+ /*
+ * These things can all be assumed for the PCI Card.
+ */
+
+ adapter->adapter_card_type = ADAPTER_CARD_TYPE_16_4_PCI;
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_PCI;
+ adapter->edge_triggered_ints = FALSE;
+ adapter->mc32_config = 0;
+
+ /*
+ * Start off by assuming we will use pseudo DMA.
+ */
+
+ adapter->EaglePsDMA = TRUE;
+
+ /*
+ * If we are supposed to use MMIO then enable it.
+ */
+
+ if (adapter->transfer_mode == MMIO_DATA_TRANSFER_MODE)
+ {
+ adapter->mc32_config = PCI1_ENABLE_MMIO;
+ adapter->EaglePsDMA = FALSE;
+ }
+ else
+ {
+ /*
+ * If we've using pseudo DMA then we need a software handshake.
+ */
+ adapter->mc32_config = MC_AND_ISACP_USE_PIO;
+ }
+
+ /*
+ * Save IO locations of SIF registers.
+ */
+
+ sif_base = adapter->io_location + PCI_FIRST_SIF_REGISTER;
+
+ adapter->sif_dat = sif_base + PCI_SIFDAT;
+ adapter->sif_datinc = sif_base + PCI_SIFDAT_INC;
+ adapter->sif_adr = sif_base + PCI_SIFADR;
+ adapter->sif_int = sif_base + PCI_SIFINT;
+ adapter->sif_acl = sif_base + PCI_SIFACL;
+ adapter->sif_adx = sif_base + PCI_SIFADX;
+ adapter->sif_dmalen = sif_base + PCI_DMALEN;
+ adapter->sif_sdmadat = sif_base + PCI_SDMADAT;
+ adapter->sif_sdmaadr = sif_base + PCI_SDMAADR;
+ adapter->sif_sdmaadx = sif_base + PCI_SDMAADX;
+
+ adapter->io_range = PCI_IO_RANGE;
+
+ /*
+ * Set up a pointer to the general control register.
+ */
+
+ control_reg = adapter->io_location + PCI_GENERAL_CONTROL_REG;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Toggle the Reset bit to Reset the Eagle and take it out of reset
+ */
+
+ control_value = 0;
+ sys_outsw(
+ adapter_handle,
+ control_reg,
+ control_value);
+
+ sys_wait_at_least_microseconds(28);
+
+ control_value = PCI1_SRESET;
+ sys_outsw(
+ adapter_handle,
+ control_reg,
+ control_value);
+
+ /*
+ * Read the node address.
+ */
+
+ if (!hwi_pci_read_node_address(adapter))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ ring_speed = hwi_pci_read_eeprom_word(adapter, PCI_EEPROM_RING_SPEED);
+
+ /*
+ * Get the amount of RAM from the serial EEPROM (in units of 128k).
+ */
+
+ adapter->adapter_ram_size = hwi_pci_read_eeprom_word(
+ adapter,
+ PCI_EEPROM_RAM_SIZE) * 128;
+
+ /*
+ * Set the ring speed. If the user has specified a value then we will
+ * use that, otherwise we will use the value read from the EEPROM.
+ */
+
+ if (adapter->set_ring_speed == 16)
+ {
+ control_value &= ~PCI1_RSPEED_4MBPS;
+ }
+ else if (adapter->set_ring_speed == 4)
+ {
+ control_value |= PCI1_RSPEED_4MBPS;
+ }
+ else if (ring_speed == PCI_EEPROM_16MBPS)
+ {
+ control_value &= ~PCI1_RSPEED_4MBPS;
+ }
+ else
+ {
+ control_value |= PCI1_RSPEED_4MBPS;
+ }
+
+ control_value |= PCI1_RSPEED_VALID;
+ sys_outsw(
+ adapter_handle,
+ control_reg,
+ control_value);
+
+ /*
+ * Halt the Eagle prior to downloading the MAC code - this will also
+ * write the interrupt bits into the SIFACL register, where the MAC can
+ * find them.
+ */
+
+ hwi_halt_eagle(adapter);
+
+ /*
+ * Download code to adapter.
+ * View download image as a sequence of download records.
+ * Pass address of routine to set up DIO addresses on PCI cards.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!hwi_download_code(
+ adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_pci_set_dio_address))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Restart the Eagle to initiate bring up diagnostics.
+ */
+
+ hwi_start_eagle(adapter);
+
+ /*
+ * Wait for a valid bring up code, may wait 3 seconds.
+ */
+
+ if (!hwi_get_bring_up_code(adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Set DIO address to point to EAGLE DATA page 0x10000L.
+ */
+
+ hwi_pci_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * Get the ring speed, from the Eagle DIO space.
+ */
+
+ adapter->ring_speed = hwi_get_ring_speed(adapter);
+
+ /*
+ * Set maximum frame size from the ring speed.
+ */
+
+ adapter->max_frame_size = hwi_get_max_frame_size(adapter);
+
+ /*
+ * If not in polling mode then set up interrupts.
+ * interrupts_on field is used when disabling interrupts for adapter.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on = sys_enable_irq_channel(
+ adapter_handle,
+ adapter->interrupt_number);
+
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+ /*
+ * Return successfully.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* hwi_pci_interrupt_handler
+* =========================
+*
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ==========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pci_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF for either
+* a PIO data transfer or a normal condition (received frame, SRB complete,
+* ARB indication etc). Note it could in fact be the case that no interrupt
+* has occured on the particular adapter being checked.
+*
+* On normal SIF interrupts, the interrupt is acknowledged and cleared. The
+* value in the SIF interrupt register is recorded in order to pass it to
+* the driver_interrupt_entry routine (along with the adapter details).
+*
+* On PseudoDMA interrupts, the length, direction and physical address of
+* the transfer is determined. A system provided routine is called to do
+* the data transfer itself.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_pci_interrupt_handler)
+#endif
+
+export void
+hwi_pci_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sifacl;
+ WORD sifint_value;
+ WORD sifint_tmp;
+ WBOOLEAN sifint_occurred = FALSE;
+ WBOOLEAN pioint_occurred = FALSE;
+ WORD pio_addr_lo;
+ DWORD pio_addr_hi;
+ WORD pio_len_bytes;
+ WBOOLEAN pio_from_adapter;
+ UINT i;
+ BYTE FAR * pio_address;
+ WORD saved_sifadr;
+ WORD mmio_alignment;
+ BYTE FAR * mmio_addr;
+ DWORD mmio_dword;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Check for SIF interrupt or PIO interrupt.
+ */
+
+ /*
+ * Read SIFINT, and then re-read to make sure value is stable.
+ */
+
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ } while (sifint_tmp != sifint_value);
+
+ /*
+ * Given the SIFINT value, we can check one of the bits in it to see
+ * if that is what caused the interrupt.
+ */
+
+ if ((sifint_value & EAGLE_SIFINT_SYSTEM) != 0)
+ {
+ /*
+ * A SIF interrupt has occurred.
+ * This could be an SRB free, an adapter check or a received frame
+ * interrupt.
+ * Note that we do not process it yet - we wait until we have EOI'd
+ * the interrupt controller.
+ */
+
+ sifint_occurred = TRUE;
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_int, 0);
+ }
+
+ if (adapter->EaglePsDMA == TRUE)
+ {
+ /*
+ * Now read the SIFACL register to check for a PseudoDMA interrupt.
+ */
+
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+
+ if ((sifacl & EAGLE_SIFACL_SWHRQ) != 0)
+ {
+ /*
+ * PIO interrupt has occurred. Transfer data to/from adapter.
+ */
+
+ pioint_occurred = TRUE;
+
+ /*
+ * Using any PCI card, a software handshake must occur so that the MAC
+ * does not try to initiate another transfer until a point has been reached on
+ * the host at which the transfer has completed. If not, the following could
+ * happen:
+ *
+ * - The host requests the last word/byte of a receive from the card.
+ * - The SIF does not has the data ready.
+ * - Control of the bus is given to a SCSI card.
+ * - It bursts/does nothing in bus master mode for 16 microseconds.
+ * - The data becomes ready early on during these 16 microseconds and
+ * as a result the card software beleives that the transfer has completed.
+ * - The card software continues and sets up another PsDMA transfer.
+ * - The SCSI card finishes, but the PdDMA length is now incorrect and
+ * all is lost.
+ *
+ */
+
+ saved_sifadr = sys_insw(adapter_handle, adapter->sif_adr);
+
+ /*
+ * Set the PIO_HANDSHAKE word to 0
+ */
+ sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_DMA_CONTROL);
+
+ sys_outsw(adapter_handle, adapter->sif_dat, 0 );
+
+
+ /*
+ * By writing the SWHLDA bit, we "start" the transfer,
+ * causing the SDMA registers to mapped in.
+ */
+
+ macro_setw_bit(
+ adapter_handle,
+ adapter->sif_acl,
+ EAGLE_SIFACL_SWHLDA);
+
+ /*
+ * Determine what direction the data transfer is to take place in.
+ */
+
+ pio_from_adapter = sys_insw(
+ adapter_handle,
+ adapter->sif_acl) & EAGLE_SIFACL_SWDDIR;
+
+ pio_len_bytes = sys_insw(
+ adapter_handle,
+ adapter->sif_dmalen);
+
+ pio_addr_lo = sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadr);
+
+ pio_addr_hi = (DWORD) sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadx);
+
+ pio_address = (BYTE FAR *) ((pio_addr_hi << 16) |
+ ((DWORD) pio_addr_lo));
+
+
+ /*
+ * Do the actual data transfer.
+ */
+
+ /*
+ * Note that Fastmac only copies whole WORDs to DWORD boundaries.
+ * FastmacPlus, however, can transfer any length to any address.
+ */
+
+ if (pio_from_adapter)
+ {
+ /*
+ * Transfer into host memory from adapter.
+ */
+
+ /*
+ * First, check if host address is on an odd byte boundary.
+ */
+
+ if ((card_t)pio_address % 2)
+ {
+ pio_len_bytes--;
+ *(pio_address++) = sys_insb(
+ adapter_handle,
+ (WORD) (adapter->sif_sdmadat + 1));
+ }
+
+ /*
+ * Now transfer the bulk of the data.
+ */
+
+ sys_rep_insw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1));
+
+ /*
+ * Finally transfer any trailing byte.
+ */
+
+ if (pio_len_bytes % 2)
+ {
+ *(pio_address+pio_len_bytes - 1) =
+ sys_insb(
+ adapter_handle,
+ adapter->sif_sdmadat);
+ }
+ }
+ else
+ {
+ /*
+ * Transfer into adapter memory from the host.
+ */
+
+ if ((card_t)pio_address % 2)
+ {
+ pio_len_bytes--;
+ sys_outsb(
+ adapter_handle,
+ (WORD) (adapter->sif_sdmadat + 1),
+ *(pio_address++));
+ }
+
+ sys_rep_outsw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1));
+
+ if (pio_len_bytes % 2)
+ {
+ sys_outsb(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ *(pio_address+pio_len_bytes-1));
+ }
+ }
+ /*
+ * Wait for SWHLDA to go low, it is not safe to access normal SIF registers
+ * until this is the case.
+ */
+ do
+ {
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+ }
+ while (sifacl & EAGLE_SIFACL_SWHLDA);
+
+ /*
+ * Now output 0xFFFF to the PIO_HANDSHAKE word, to signal the DMA is complete.
+ */
+ sys_outsw(adapter_handle, adapter->sif_dat, 0xFFFF );
+
+ /*
+ * Restore the saved SIF address.
+ */
+ sys_outsw(adapter_handle, adapter->sif_adr, saved_sifadr);
+
+
+ }
+ }
+ else if ((sifint_value & INT_PCIMMIO) != 0 && sifint_occurred)
+ {
+ /*
+ * We have an MMIO interrupt so we can
+ * assume that we've not had an ordinary SIF interrupt.
+ */
+
+ sifint_occurred = FALSE;
+
+ /*
+ * PIO interrupt has occurred.Transfer data to/from adapter.
+ */
+
+ pioint_occurred = TRUE;
+
+ /*
+ * Preserve the contents of SIFADR.
+ */
+
+ saved_sifadr = sys_insw(adapter_handle,
+ adapter->sif_adr);
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ DIO_LOCATION_DMA_POINTER);
+
+ pio_addr_lo = sys_insw(
+ adapter_handle,
+ adapter->sif_datinc);
+
+ pio_addr_hi = sys_insw(
+ adapter_handle,
+ adapter->sif_datinc);
+
+ pio_address = (BYTE FAR *) ((((DWORD) pio_addr_hi) << 16) |
+ pio_addr_lo);
+
+ pio_len_bytes = sys_insw(
+ adapter_handle,
+ adapter->sif_datinc);
+
+ mmio_alignment = sys_insw(
+ adapter_handle,
+ adapter->sif_datinc);
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ DIO_LOCATION_DMA_CONTROL);
+
+ if (pio_len_bytes != 0)
+ {
+ mmio_addr = (BYTE FAR *) adapter->mmio_base_address;
+
+ if ((sifint_value & INT_PCIMMIO_RX) != 0)
+ {
+ /*
+ * Receive.
+ */
+
+ /*
+ * First off need to do a dummy read to initialise Hardware
+ * Read into a global variable to stop the optimiser from
+ * optimising out the statement.
+ */
+
+ sys_movsd_from(
+ adapter_handle,
+ (DWORD)mmio_addr,
+ (DWORD)(&mmio_dword));
+
+ /*
+ * Take care of the first DWORD, which may not all be valid
+ * data.
+ */
+
+ if (mmio_alignment != 0)
+ {
+ sys_movsd_from(
+ adapter_handle,
+ (DWORD)mmio_addr,
+ (DWORD)(&mmio_dword));
+
+ mmio_addr += 4;
+
+ for (i = mmio_alignment;
+ ((i < 4) && (pio_len_bytes > 0));
+ i++)
+ {
+ *pio_address = *(((BYTE FAR *) &mmio_dword) + i);
+ pio_address++;
+ pio_len_bytes--;
+ }
+ }
+
+ /*
+ * Transfer the bulk of the DWORDs.
+ */
+
+ if (pio_len_bytes >= 4)
+ {
+ sys_rep_movsd_from(
+ adapter_handle,
+ (DWORD)mmio_addr,
+ (DWORD)pio_address,
+ (WORD) (pio_len_bytes & 0xfffc));
+
+ pio_address += (pio_len_bytes & 0xfffc);
+ mmio_addr += (pio_len_bytes & 0xfffc);
+ pio_len_bytes &= 0x0003;
+ }
+
+ /*
+ * Deal with any trailing bytes in the last DWORD.
+ */
+
+ if (pio_len_bytes > 0)
+ {
+ sys_movsd_from(
+ adapter_handle,
+ (DWORD)mmio_addr,
+ (DWORD)(&mmio_dword));
+
+ for(i = 0; i < pio_len_bytes; i++)
+ {
+ *pio_address = *(((BYTE FAR *) &mmio_dword) + i);
+ pio_address++;
+ }
+ }
+
+ /*
+ * Write the handshake value.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_dat,
+ 0xffff);
+ }
+ else
+ {
+ /*
+ * Transmit.
+ */
+
+ switch (mmio_alignment)
+ {
+ /*
+ * If the alignment is 0 then there is a whole DWORD
+ * to copy so we don't do anything and let the following
+ * code handle it.
+ */
+
+ case 0:
+ break;
+
+ /*
+ * If the alignment is 1 then we can't do anything
+ * we cannot write 3 bytes in one go.
+ */
+
+ case 1:
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_16_PCI_3BYTE_PROBLEM;
+
+ return;
+
+ /*
+ * If the alignment is 2 then we must transfer a word
+ * unless there is only one byte of data.
+ */
+
+ case 2:
+ if (pio_len_bytes == 1)
+ {
+ *(mmio_addr + 2) = *pio_address;
+ pio_address++;
+ pio_len_bytes--;
+ }
+ else
+ {
+ *((WORD FAR *) (mmio_addr + 2)) =
+ *((WORD FAR *) pio_address);
+ pio_address += 2;
+ pio_len_bytes -= 2;
+ mmio_addr += 4;
+ }
+
+ break;
+
+ /*
+ * If the alignment is 3 then we must transfer a byte.
+ */
+
+ case 3:
+ *(mmio_addr + 3) = *pio_address;
+ pio_address++;
+ pio_len_bytes--;
+ mmio_addr += 4;
+
+ break;
+ }
+
+ /*
+ * Transfer the bulk of the DWORDs.
+ */
+
+ if (pio_len_bytes >= 4)
+ {
+ sys_rep_movsd_to(
+ adapter_handle,
+ (DWORD)pio_address,
+ (DWORD)mmio_addr,
+ (WORD) (pio_len_bytes & 0xfffc));
+
+ pio_address += (pio_len_bytes & 0xfffc);
+ mmio_addr += (pio_len_bytes & 0xfffc);
+ pio_len_bytes &= 0x0003;
+ }
+
+ /*
+ * Transfer the remainder of the data.
+ */
+
+ switch (pio_len_bytes)
+ {
+ /*
+ * There may be nothing left to do.
+ */
+
+ case 0:
+ break;
+
+ /*
+ * If there is 1 byte left the just do a single byte
+ * copy.
+ */
+
+ case 1:
+ *mmio_addr = *pio_address;
+
+ break;
+
+ /*
+ * If there are two bytes left then do a word copy.
+ */
+
+ case 2:
+ *((WORD FAR *) mmio_addr) = *((WORD FAR *) pio_address);
+
+ break;
+
+ /*
+ * If there are 3 bytes left then we have a slight
+ * problem as we cannot do a single write of 3 bytes.
+ * Fortunately there should always be some space left
+ * at the end of a buffer on the adapter.
+ */
+
+ case 3:
+ sys_movsd_to(
+ adapter_handle,
+ (DWORD)pio_address,
+ (DWORD)mmio_addr);
+
+ break;
+ }
+
+ /*
+ * There now follows an extended handshake, to
+ * workaround the SAM upload hardware bug on the PCI I. The
+ * host must not make any DIO access until the upload has
+ * finished. In order to achieve this we:
+ *
+ * a) write 05555h to the DMA_CONTROL, to indicate that we've
+ * completed the MMIO write.
+ *
+ * b) poll DMA_CONTROL until it becomes 0AAAAh, indicating
+ * that the adapter is now about to do the upload.
+ *
+ * c) write 0FFFFh to DMA_CONTROL, to indicate that we've
+ * completed reading from DIO space.
+ *
+ * d) wait 'x' microseconds while the adapter does
+ * the upload.
+ *
+ * We make sure that we're not reading any cached
+ * value from the data_reg by writing to the sifaddr
+ * beforehand.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_dat,
+ 0x5555);
+
+ do
+ {
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ DIO_LOCATION_DMA_CONTROL);
+ }
+ while (sys_insw(adapter_handle, adapter->sif_dat) != 0xaaaa);
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ DIO_LOCATION_DMA_CONTROL);
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_dat,
+ 0xffff);
+
+ sys_wait_at_least_microseconds(4);
+ }
+ }
+
+ /*
+ * Restore SIFADR.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ saved_sifadr);
+ }
+
+ /*
+ * Now that we have finished acknowledging the interrupt at the card,
+ * we acknowledge it at the interrupt controller.
+ */
+
+#ifndef FTK_NO_CLEAR_IRQ
+
+ if (sifint_occurred || pioint_occurred)
+ {
+ /*
+ * Acknowledge/clear interrupt at interrupt controller.
+ */
+
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+ }
+
+#endif
+
+ /*
+ * Only now do we do driver specific processing of SIF interrupts.
+ */
+
+ if (sifint_occurred)
+ {
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+
+ driver_interrupt_entry(adapter_handle, adapter, sifint_value);
+ }
+
+ /*
+ * Let system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_pci_remove_card
+* ===================
+*
+*
+* PARAMETERS (passed by hwi_remove_card)
+* ======================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_smart16_remove_card routine is called by hwi_remove_adapter. It
+* disables interrupts if they are being used. It also resets the adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pci_remove_card)
+#endif
+
+export void
+hwi_pci_remove_card(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD wGenConAddr = adapter->io_location +
+ PCI_GENERAL_CONTROL_REG;
+ WORD wControl;
+ WORD sifacl;
+
+ /*
+ * Interrupt must be disabled at adapter before unpatching interrupt.
+ * Even in polling mode we must turn off interrupts at adapter.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+ sifacl = (sifacl & ~(EAGLE_SIFACL_PSDMAEN | EAGLE_SIFACL_SINTEN));
+ sys_outsw(adapter_handle, adapter->sif_acl, sifacl);
+
+ if (adapter->interrupts_on)
+ {
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(
+ adapter_handle,
+ adapter->interrupt_number);
+ }
+
+ adapter->interrupts_on = FALSE;
+ }
+
+ /*
+ * Reset the Eagle
+ */
+
+ wControl = sys_insw(adapter_handle, wGenConAddr);
+ wControl &= ~PCI1_SRESET;
+ sys_outsw(adapter_handle, wGenConAddr, wControl);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_pci_set_dio_address
+* =======================
+*
+* The hwi_pci_set_dio_address routine is used, with PCI cards, for
+* putting a 32 bit DIO address into the SIF DIO address and extended DIO
+* address registers. Note that the extended address register should be
+* loaded first.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci_set_dio_address)
+#endif
+
+export void
+hwi_pci_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * Load extended DIO address register with top 16 bits of address.
+ * Always load extended address register first.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ sif_dio_adrx,
+ (WORD)(dio_address >> 16));
+
+ /*
+ * Load DIO address register with low 16 bits of address.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ sif_dio_adr,
+ (WORD)(dio_address & 0x0000FFFF));
+}
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------
+|
+| pci_c46_write_bit
+| ==================
+|
+| Write a bit to the SEEPROM control register.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pci_c46_write_bit)
+#endif
+
+local void
+pci_c46_write_bit(
+ ADAPTER * adapter,
+ WORD mask,
+ WBOOLEAN set_bit
+ )
+{
+ WORD ctrl_reg;
+
+ /*
+ * Get the current value of the SEEPROM control register.
+ */
+
+ ctrl_reg = sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCI_SEEPROM_CONTROL_REG));
+
+ /*
+ * Some bits cannot be read back from the SEEPROM control register once
+ * they have been written, so we must keep track of them ourself.
+ */
+
+ ctrl_reg |= adapter->c46_bits;
+
+ /*
+ * Clear or set the bit.
+ */
+
+ if (set_bit)
+ {
+ ctrl_reg |= mask;
+ }
+ else
+ {
+ ctrl_reg &= ~mask;
+ }
+
+ /*
+ * Write the data to the SEEPROM control register.
+ */
+
+ sys_outsb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCI_SEEPROM_CONTROL_REG),
+ (BYTE) ctrl_reg);
+
+ /*
+ * Remember the bits that we cannot read back.
+ */
+
+ adapter->c46_bits = ctrl_reg & BITS_TO_REMEMBER;
+
+ /*
+ * Wait for a bit.
+ */
+
+ sys_wait_at_least_microseconds(10);
+
+ /*
+ * And read the SEEPROM control register back so that the data gets
+ * latched properly.
+ */
+
+ sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCI_SEEPROM_CONTROL_REG));
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| pci_c46_twitch_clock
+| ====================
+|
+| Toggle the SEEPROM clock.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pci_c46_twitch_clock)
+#endif
+
+local void
+pci_c46_twitch_clock(
+ ADAPTER * adapter
+ )
+{
+ pci_c46_write_bit(adapter, PCI1_BIA_CLK, TRUE);
+ pci_c46_write_bit(adapter, PCI1_BIA_CLK, FALSE);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| pci_c46_read_data
+| =================
+|
+| Read a data bit from the SEEPROM control register
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pci_c46_read_data)
+#endif
+
+local WORD
+pci_c46_read_data(
+ ADAPTER * adapter
+ )
+{
+ return sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCI_SEEPROM_CONTROL_REG)
+ ) & PCI1_BIA_DIN;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pci_read_eeprom_word
+| ========================
+|
+| hwi_pci_read_eeprom_word takes the address of the word to be read
+| from the AT93C46 serial EEPROM, write to the IO ports a magic sequence
+| to switch the EEPROM to reading mode and finally read the required word
+| and return.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci_read_eeprom_word)
+#endif
+
+local WORD
+hwi_pci_read_eeprom_word(
+ ADAPTER * adapter,
+ WORD word_address
+ )
+{
+ WORD i;
+ WORD cmd_word = PCI_C46_START_BIT | PCI_C46_READ_CMD;
+ WORD tmp_word;
+
+ /*
+ * Concatenate the address to command word.
+ */
+
+ cmd_word |= (WORD)((word_address & PCI_C46_ADDR_MASK) <<
+ PCI_C46_ADDR_SHIFT);
+
+ /*
+ * Clear data in bit.
+ */
+
+ pci_c46_write_bit(
+ adapter,
+ PCI1_BIA_DOUT,
+ FALSE);
+
+ /*
+ * Assert chip select bit.
+ */
+
+ pci_c46_write_bit(
+ adapter,
+ PCI1_BIA_ENA,
+ TRUE);
+
+ /*
+ * Send read command and address.
+ */
+
+ pci_c46_twitch_clock(adapter);
+
+ tmp_word = cmd_word;
+
+ for (i = 0; i < PCI_C46_CMD_LENGTH; i++)
+ {
+ pci_c46_write_bit(
+ adapter,
+ PCI1_BIA_DOUT,
+ (WBOOLEAN) ((tmp_word & 0x8000) != 0));
+ pci_c46_twitch_clock(adapter);
+ tmp_word <<= 1;
+ }
+
+ /*
+ * Read data word.
+ */
+
+ tmp_word = 0x0000;
+
+ for (i = 0; i < 16; i++)
+ {
+ pci_c46_twitch_clock(adapter);
+
+ if (i > 0)
+ {
+ tmp_word <<= 1;
+ }
+
+ if (pci_c46_read_data(adapter) != 0)
+ {
+ tmp_word |= 0x0001;
+ }
+ }
+
+ /*
+ * Clear data in bit.
+ */
+
+ pci_c46_write_bit(adapter, PCI1_BIA_DOUT, FALSE);
+
+ /*
+ * Deselect chip.
+ */
+
+ pci_c46_write_bit(adapter, PCI1_BIA_ENA, FALSE);
+
+ /*
+ * Tick clock.
+ */
+
+ pci_c46_twitch_clock(adapter);
+
+ return tmp_word;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pci_read_node_address
+| =========================
+|
+| The hwi_pci_read_node_address routine reads in the node address from
+| the SEEPROM, and checks that it is a valid Madge node address.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci_read_node_address)
+#endif
+
+local WBOOLEAN
+hwi_pci_read_node_address(
+ ADAPTER * adapter
+ )
+{
+ WORD temp;
+
+ temp = hwi_pci_read_eeprom_word(adapter, PCI_EEPROM_BIA_WORD0);
+ adapter->permanent_address.byte[0] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[1] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ temp = hwi_pci_read_eeprom_word(adapter, PCI_EEPROM_BIA_WORD1);
+ adapter->permanent_address.byte[2] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[3] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ temp = hwi_pci_read_eeprom_word(adapter, PCI_EEPROM_BIA_WORD2);
+ adapter->permanent_address.byte[4] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[5] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ return TRUE;
+}
+
+#endif
+
+/******* End of HWI_PCI.C **************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_pci2.c b/private/ntos/ndis/madge/driver/hwi_pci2.c
new file mode 100644
index 000000000..40a5320ed
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_pci2.c
@@ -0,0 +1,1792 @@
+/****************************************************************************
+*
+* HWI_PCI2.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* HARDWARE INTERFACE MODULE FOR PCI CARDS
+*
+* Copyright (c) Madge Networks Ltd. 1994
+*
+* COMPANY CONFIDENTIAL
+*
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_PCIT.C module contains the routines specific to the Smart 16/4
+* PCI(BM) based on the Madge PCI ASIC, this card supports Pseudo DMA, and
+* bus master DMA.
+*
+*****************************************************************************
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#define PCI_PCI2_DEVICE_ID 2
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+BYTE bEepromByteStore;
+BYTE bLastDataBit;
+
+#ifndef FTK_NO_PCI2
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local WBOOLEAN
+hwi_pci2_read_node_address(
+ ADAPTER * adapter
+ );
+
+local WORD
+hwi_at24_read_a_word(
+ ADAPTER * adapter,
+ WORD word_address
+ );
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_pci2_probe_card
+* ==================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is normally an array of IO locations to examine for the
+* presence of an adapter. However for PCI adapters the io location is read
+* from the BIOS, so this array can remain empty.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_pci2_probe_card routine is called by hwi_probe_adapter. It
+* reads the id registers to find the type of card and also reads the IRQ.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci2_probe_card)
+#endif
+
+export UINT
+hwi_pci2_probe_card(
+ PROBE * Resources,
+ UINT NumberOfResources,
+ WORD * IOMask,
+ UINT NumberIO
+ )
+{
+ WORD i;
+ WORD Handle;
+
+ if (!sys_pci_valid_machine())
+ {
+ return 0;
+ }
+
+ for (i=0;i<NumberOfResources;i++)
+ {
+ if (!sys_pci_find_card(&Handle, i,PCI_PCI2_DEVICE_ID))
+ {
+ break;
+ }
+
+ Resources[i].pci_handle = Handle;
+ Resources[i].adapter_card_bus_type = ADAPTER_CARD_PCI2_BUS_TYPE;
+
+ if (!sys_pci_get_io_base(Handle, &(Resources[i].io_location)))
+ {
+ return PROBE_FAILURE;
+ }
+
+ if (!sys_pci_get_irq(Handle, &(Resources[i].interrupt_number)))
+ {
+ return PROBE_FAILURE;
+ }
+
+
+ /*
+ * We can't read the memory size from the serial EEPROM until the
+ * hwi_pci2_install_card function is called.
+ */
+
+ Resources[i].adapter_ram_size = 512;
+
+ Resources[i].adapter_card_type = ADAPTER_CARD_TYPE_16_4_PCI2;
+
+ Resources[i].transfer_mode = PIO_DATA_TRANSFER_MODE;
+
+ }
+
+ return i;
+}
+#endif
+
+/****************************************************************************
+*
+* hwi_pci2_install_card
+* ====================
+*
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* hwi_pci2_install_card is called by hwi_install_adapter. It sets up
+* the adapter card and downloads the required code to it. Firstly, it
+* checks there is a valid adapter at the required IO address by reading
+* the node address from the BIA PROM. It then sets up and checks various
+* on-board registers for correct operation.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls.
+* The adapter is set up for Eagle Pseudo-DMA, since real DMA is not used.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci2_install_card)
+#endif
+
+export WBOOLEAN
+hwi_pci2_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sif_base;
+ WORD ring_speed;
+ WORD wHardFeatures;
+ BYTE bTemp;
+
+ /*
+ * These things can all be assumed for the PCI2 Card.
+ */
+
+ adapter->adapter_card_type = ADAPTER_CARD_TYPE_16_4_PCI2;
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_PCI2;
+ adapter->edge_triggered_ints = FALSE;
+ adapter->mc32_config = 0;
+
+ /*
+ * Start off by assuming we will use pseudo DMA.
+ */
+
+ adapter->EaglePsDMA = TRUE;
+
+ /*
+ * Save IO locations of SIF registers.
+ */
+
+ sif_base = adapter->io_location + PCI2_SIF_OFFSET;
+
+ adapter->sif_dat = sif_base + EAGLE_SIFDAT;
+ adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC;
+ adapter->sif_adr = sif_base + EAGLE_SIFADR;
+ adapter->sif_int = sif_base + EAGLE_SIFINT;
+ adapter->sif_acl = sif_base + EAGLE_SIFACL;
+ adapter->sif_adx = sif_base + EAGLE_SIFADX;
+ adapter->sif_dmalen = sif_base + EAGLE_DMALEN;
+ adapter->sif_sdmadat = sif_base + EAGLE_SDMADAT;
+ adapter->sif_sdmaadr = sif_base + EAGLE_SDMAADR;
+ adapter->sif_sdmaadx = sif_base + EAGLE_SDMAADX;
+
+ adapter->io_range = PCI2_IO_RANGE;
+
+ /*
+ * RESET the Card
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Clear all the RESET bits, wait at least 14uS and then assert all three
+ * , turning on one at a time, in the following sequence
+ * - Set CHIP_NRES
+ * - Set SIF_NRES
+ * - Set FIFO_NRES
+ */
+
+ bTemp = sys_insb(
+ adapter_handle,
+ (WORD) (adapter->io_location + PCI2_RESET));
+
+ bTemp &= ~(PCI2_CHIP_NRES | PCI2_FIFO_NRES | PCI2_SIF_NRES);
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) (adapter->io_location + PCI2_RESET),
+ bTemp);
+
+ /*
+ * Wait 14 uS before taking it out of reset.
+ */
+
+ sys_wait_at_least_microseconds(14);
+
+ bTemp |= PCI2_CHIP_NRES;
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) (adapter->io_location + PCI2_RESET),
+ bTemp);
+
+ bTemp |= PCI2_SIF_NRES;
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) (adapter->io_location + PCI2_RESET),
+ bTemp);
+
+ bTemp |= PCI2_FIFO_NRES;
+
+ sys_outsb(adapter_handle,
+ (WORD) (adapter->io_location + PCI2_RESET),
+ bTemp);
+
+
+ if (!hwi_pci2_read_node_address(adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+ return FALSE;
+ }
+
+ /*
+ * If this is 1 the card is @ 4Mbit/s 0 16MBit/s.
+ */
+
+ ring_speed = hwi_at24_read_a_word(adapter, PCI2_EEPROM_RING_SPEED);
+
+ /*
+ * Get the amount of RAM from the serial EEPROM (in units of 128k).
+ */
+
+ adapter->adapter_ram_size = hwi_at24_read_a_word(
+ adapter,
+ PCI2_EEPROM_RAM_SIZE) * 128;
+
+
+ /*
+ * This flag tells us if the card supports DMA, and if it supports release
+ * 4.31 software.
+ */
+
+ wHardFeatures = hwi_at24_read_a_word(adapter, PCI2_HWF2);
+
+#define RELEASE_431 1
+#ifdef RELEASE_431
+
+ if (!(wHardFeatures & PCI2_HW2_431_READY))
+ {
+ /*
+ * This card does not support Release 4.31 software.
+ */
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+ return FALSE;
+ }
+
+#endif
+
+ if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
+ {
+ /*
+ * Does this card support DMA ???
+ */
+
+ if (wHardFeatures & PCI2_BUS_MASTER_ONLY)
+ {
+ adapter->EaglePsDMA = FALSE;
+
+ /*
+ * Need to set the MASTER ENABLE bit in the PCI Command register
+ * otherwise DMA will not work and will hang the machine.
+ * The BIOS should do this, but some don't.
+ */
+
+ sys_pci_read_config_byte(
+ adapter_handle,
+ PCI_CONFIG_COMMAND,
+ &bTemp);
+
+ bTemp |= PCI_CONFIG_BUS_MASTER_ENABLE;
+
+ sys_pci_write_config_byte(
+ adapter_handle,
+ PCI_CONFIG_COMMAND,
+ bTemp);
+ }
+ else
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_06_CANNOT_USE_DMA;
+ return FALSE;
+ }
+
+ }
+
+ /*
+ * If we've using pseudo DMA then we need a software handshake.
+ */
+
+ if (adapter->EaglePsDMA)
+ {
+ adapter->mc32_config = MC_AND_ISACP_USE_PIO;
+ }
+
+ /*
+ * Set the ring speed. If the user has specified a value then we will
+ * use that, otherwise we will use the value read from the EEPROM.
+ */
+
+ /*
+ * These NSEL bits are different to other cards, bit 0 must be ~bit1
+ * There is a missing NOT gate in the ASIC.
+ */
+
+ if (adapter->set_ring_speed == 16)
+ {
+ adapter->nselout_bits = 0;
+ }
+ else if (adapter->set_ring_speed == 4)
+ {
+ adapter->nselout_bits = 2;
+ }
+ else if (ring_speed == PCI2_EEPROM_4MBITS)
+ {
+ adapter->nselout_bits = 2;
+ }
+ else
+ {
+ adapter->nselout_bits = 0;
+ }
+
+ /*
+ * Set the interrupt control register to enable SIF interrupts and
+ * PCI Error interrupts, although the ISR does nowt about the latter
+ * at present.
+ */
+
+ sys_outsb( adapter->adapter_handle, (WORD) (adapter->io_location + PCI2_INTERRUPT_CONTROL), PCI2_SINTEN | PCI2_PCI_ERR_EN);
+
+ /*
+ * Halt the Eagle prior to downloading the MAC code - this will also
+ * write the interrupt bits into the SIFACL register, where the MAC can
+ * find them.
+ */
+
+ hwi_halt_eagle(adapter);
+
+ /*
+ * Download code to adapter.
+ * View download image as a sequence of download records.
+ * Pass address of routine to set up DIO addresses on PCI cards.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!hwi_download_code(
+ adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_pci2_set_dio_address))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Restart the Eagle to initiate bring up diagnostics.
+ */
+
+ hwi_start_eagle(adapter);
+
+ /*
+ * Wait for a valid bring up code, may wait 3 seconds.
+ */
+
+ if (!hwi_get_bring_up_code(adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Set DIO address to point to EAGLE DATA page 0x10000L.
+ */
+
+ hwi_pci2_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * Get the ring speed, from the Eagle DIO space.
+ */
+
+ adapter->ring_speed = hwi_get_ring_speed(adapter);
+
+ /*
+ * Set maximum frame size from the ring speed.
+ */
+
+ adapter->max_frame_size = hwi_get_max_frame_size(adapter);
+
+ /*
+ * If not in polling mode then set up interrupts.
+ * interrupts_on field is used when disabling interrupts for adapter.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on = sys_enable_irq_channel(
+ adapter_handle,
+ adapter->interrupt_number);
+
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+ /*
+ * Return successfully.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return TRUE;
+}
+
+/****************************************************************************
+*
+* hwi_pci2_interrupt_handler
+* =========================
+*
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ==========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pci2_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF for either
+* a PIO data transfer or a normal condition (received frame, SRB complete,
+* ARB indication etc). Note it could in fact be the case that no interrupt
+* has occured on the particular adapter being checked.
+*
+* On normal SIF interrupts, the interrupt is acknowledged and cleared. The
+* value in the SIF interrupt register is recorded in order to pass it to
+* the driver_interrupt_entry routine (along with the adapter details).
+*
+* On PseudoDMA interrupts, the length, direction and physical address of
+* the transfer is determined. A system provided routine is called to do
+* the data transfer itself.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_pci2_interrupt_handler)
+#endif
+
+export void
+hwi_pci2_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sifacl;
+ WORD sifint_value;
+ WORD sifint_tmp;
+ WORD pio_addr_lo;
+ WBOOLEAN sifint_occurred = FALSE;
+ WBOOLEAN pioint_occurred = FALSE;
+ DWORD pio_addr_hi;
+ WORD pio_len_bytes;
+ WBOOLEAN pio_from_adapter;
+ BYTE bInt;
+ BYTE FAR * pio_address;
+ WORD saved_sifadr;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Check for SIF interrupt or PIO interrupt.
+ */
+
+ /*
+ * Read SIFINT, and then re-read to make sure value is stable.
+ */
+
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ }
+ while (sifint_tmp != sifint_value);
+
+ /*
+ * Given the SIFINT value, we can check one of the bits in it to see
+ * if that is what caused the interrupt.
+ */
+
+ if ((sifint_value & EAGLE_SIFINT_SYSTEM) != 0)
+ {
+ /*
+ * A SIF interrupt has occurred.
+ * This could be an SRB free, an adapter check or a received frame
+ * interrupt.
+ * Note that we do not process it yet - we wait until we have EOI'd
+ * the interrupt controller.
+ */
+
+ sifint_occurred = TRUE;
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_int, 0);
+
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+
+ driver_interrupt_entry(adapter_handle, adapter, sifint_value);
+ }
+
+
+ /*
+ * Now read the SIFACL register to check for a PseudoDMA interrupt.
+ */
+
+ if (adapter->transfer_mode != DMA_DATA_TRANSFER_MODE)
+ {
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+
+ if ((sifacl & EAGLE_SIFACL_SWHRQ) != 0)
+ {
+ /*
+ * PIO interrupt has occurred. Transfer data to/from adapter.
+ */
+
+ pioint_occurred = TRUE;
+
+ /*
+ * Preserve SIFADR.
+ */
+
+ saved_sifadr = sys_insw(adapter_handle, adapter->sif_adr);
+
+ /*
+ * Start the software handshake.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(adapter_handle, adapter->sif_dat, 0);
+
+ /*
+ * By writing the SWHLDA bit, we "start" the transfer,
+ * causing the SDMA registers to mapped in.
+ */
+
+ macro_setw_bit(
+ adapter_handle,
+ adapter->sif_acl,
+ EAGLE_SIFACL_SWHLDA);
+
+ /*
+ * Determine what direction the data transfer is to take place in.
+ */
+
+ pio_from_adapter = sys_insw(
+ adapter_handle,
+ adapter->sif_acl) & EAGLE_SIFACL_SWDDIR;
+
+ pio_len_bytes = sys_insw(
+ adapter_handle,
+ adapter->sif_dmalen);
+
+ pio_addr_lo = sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadr);
+
+ pio_addr_hi = (DWORD) sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadx);
+
+ pio_address = (BYTE FAR *) ((pio_addr_hi << 16) |
+ ((DWORD) pio_addr_lo));
+
+
+ /*
+ * Do the actual data transfer.
+ */
+
+ /*
+ * Note that Fastmac only copies whole WORDs to DWORD boundaries.
+ * FastmacPlus, however, can transfer any length to any address.
+ */
+
+ if (pio_from_adapter)
+ {
+ /*
+ * Transfer into host memory from adapter.
+ */
+
+ /*
+ * First, check if host address is on an odd byte boundary.
+ */
+
+ if ((card_t)pio_address % 2)
+ {
+ pio_len_bytes--;
+ *(pio_address++) = sys_insb(
+ adapter_handle,
+ (WORD) (adapter->sif_sdmadat + 1));
+ }
+
+ /*
+ * Now transfer the bulk of the data.
+ */
+
+ sys_rep_insw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1));
+
+ /*
+ * Finally transfer any trailing byte.
+ */
+
+ if (pio_len_bytes % 2)
+ {
+ *(pio_address+pio_len_bytes - 1) =
+ sys_insb(adapter_handle, adapter->sif_sdmadat);
+ }
+ }
+ else
+ {
+ /*
+ * Transfer into adapter memory from the host.
+ */
+
+ if ((card_t)pio_address % 2)
+ {
+ pio_len_bytes--;
+ sys_outsb(
+ adapter_handle,
+ (WORD) (adapter->sif_sdmadat + 1),
+ *(pio_address++));
+ }
+
+ sys_rep_outsw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1));
+
+ if (pio_len_bytes % 2)
+ {
+ sys_outsb(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ *(pio_address+pio_len_bytes-1));
+ }
+ }
+
+ /*
+ * Wait for SWHLDA to go low, it is not safe to access
+ * normal SIF registers until this is the case.
+ */
+
+ do
+ {
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+ }
+ while (sifacl & EAGLE_SIFACL_SWHLDA);
+
+ /*
+ * Finish the software handshake. We need a dummy ready so that
+ * the SIF can stabalise.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_DMA_CONTROL);
+ sys_insw(adapter_handle, adapter->sif_dat);
+
+ sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(adapter_handle, adapter->sif_dat, 0xFFFF);
+
+ /*
+ * Restore SIFDR.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_adr, saved_sifadr);
+ }
+ }
+
+ if (pioint_occurred || sifint_occurred)
+ {
+#ifndef FTK_NO_CLEAR_IRQ
+
+ /*
+ * Acknowledge/clear interrupt at interrupt controller.
+ */
+
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+
+#endif
+ }
+ else
+ {
+ bInt = sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCI2_INTERRUPT_STATUS));
+
+ if (bInt & PCI2_PCI_INT)
+ {
+#ifndef FTK_NO_CLEAR_IRQ
+
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+
+#endif
+ }
+ }
+
+ /*
+ * Let system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+}
+
+
+/****************************************************************************
+*
+* hwi_pci2_remove_card
+* ===================
+*
+*
+* PARAMETERS (passed by hwi_remove_card)
+* ======================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_smart16_remove_card routine is called by hwi_remove_adapter. It
+* disables interrupts if they are being used. It also resets the adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pci2_remove_card)
+#endif
+
+export void
+hwi_pci2_remove_card(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD wGenConAddr = adapter->io_location +
+ PCI_GENERAL_CONTROL_REG;
+ WORD sifacl;
+ BYTE bTemp;
+
+ /*
+ * Interrupt must be disabled at adapter before unpatching interrupt.
+ * Even in polling mode we must turn off interrupts at adapter.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+ sifacl = (sifacl & ~(EAGLE_SIFACL_PSDMAEN | EAGLE_SIFACL_SINTEN));
+ sys_outsw(adapter_handle, adapter->sif_acl, sifacl);
+
+ if (adapter->interrupts_on)
+ {
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(
+ adapter_handle,
+ adapter->interrupt_number);
+ }
+
+ adapter->interrupts_on = FALSE;
+ }
+
+ /*
+ * RESET the Eagle
+ */
+
+ bTemp = sys_insb(
+ adapter_handle,
+ (WORD) (adapter->io_location + PCI2_RESET));
+
+ bTemp &= ~(PCI2_CHIP_NRES | PCI2_FIFO_NRES | PCI2_SIF_NRES);
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) (adapter->io_location + PCI2_RESET),
+ bTemp);
+
+ /*
+ * Wait 14 uS before taking it out of reset.
+ */
+
+ sys_wait_at_least_microseconds(14);
+
+ bTemp |= (PCI2_CHIP_NRES | PCI2_FIFO_NRES | PCI2_SIF_NRES);
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) (adapter->io_location + PCI2_RESET),
+ bTemp);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_pci2_set_dio_address
+* =======================
+*
+* The hwi_pci2_set_dio_address routine is used, with PCI cards, for
+* putting a 32 bit DIO address into the SIF DIO address and extended DIO
+* address registers. Note that the extended address register should be
+* loaded first.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci2_set_dio_address)
+#endif
+
+export void
+hwi_pci2_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * Load extended DIO address register with top 16 bits of address.
+ * Always load extended address register first.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ sif_dio_adrx,
+ (WORD)(dio_address >> 16));
+
+ /*
+ * Load DIO address register with low 16 bits of address.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ sif_dio_adr,
+ (WORD)(dio_address & 0x0000FFFF));
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pci2_read_node_address
+| ==========================
+|
+| The hwi_pci2_read_node_address routine reads in the node address from
+| the SEEPROM, and checks that it is a valid Madge node address.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pci2_read_node_address)
+#endif
+
+local WBOOLEAN
+hwi_pci2_read_node_address(
+ ADAPTER * adapter
+ )
+{
+ WORD temp;
+
+ temp = hwi_at24_read_a_word(adapter, PCIT_EEPROM_BIA_WORD0);
+ adapter->permanent_address.byte[0] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[1] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ temp = hwi_at24_read_a_word(adapter, PCIT_EEPROM_BIA_WORD1);
+ adapter->permanent_address.byte[2] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[3] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ temp = hwi_at24_read_a_word(adapter, PCIT_EEPROM_BIA_WORD2);
+ adapter->permanent_address.byte[4] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[5] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ return TRUE;
+}
+
+/***************************************************************************
+* *
+* Local routines for accessing the AT93AT24 Serial EEPROM, this is the same*
+* EEPROM fitted to the PNP card and the PCI 2 card. *
+* *
+* The routines are 'nicked' from the PCI-T card with just write_bits and *
+* input having been changed to reflect I/O through I/O space not PCI config*
+* space. *
+* *
+***************************************************************************/
+
+local void hwi_at24_delay( ADAPTER * adapter );
+local void hwi_at24_set_clk( ADAPTER * adapter );
+local void hwi_at24_clr_clk( ADAPTER * adapter );
+local void hwi_at24_twitch_clk( ADAPTER * adapter );
+local void hwi_at24_start_bit( ADAPTER * adapter );
+local void hwi_at24_stop_bit( ADAPTER * adapter );
+local WBOOLEAN hwi_at24_wait_ack( ADAPTER * adapter );
+local WBOOLEAN hwi_at24_dummy_wait_ack( ADAPTER * adapter );
+
+
+/************************************************************************
+ * Read the 3 EEPROM bits
+ *
+ * Inputs : Adapter structure.
+ *
+ * Outputs : Value read from control register.
+ ***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_input)
+#endif
+
+local BYTE hwi_at24_input(ADAPTER * adapter)
+{
+ BYTE bInput;
+
+ bInput = sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCI2_SEEPROM_CONTROL));
+
+ /*
+ * Store the 5 bits which don't interrest us
+ */
+
+ bEepromByteStore = bInput & (BYTE)0xF8;
+
+ return bInput;
+}
+
+
+/************************************************************************
+ * Write to the 3 EEPROM bits
+ *
+ * Inputs : Adapter structure.
+ * The data to be written.
+ *
+ * Outputs : None.
+ ***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_write_bits)
+#endif
+
+local void hwi_at24_write_bits(ADAPTER * adapter, BYTE bValue)
+{
+ BYTE bTemp;
+
+ /*
+ * Restore the 5 bits we were not interested in from the previous read
+ */
+
+ bTemp |= bEepromByteStore;
+
+ sys_outsb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCI2_SEEPROM_CONTROL),
+ bValue);
+}
+
+
+/************************************************************************
+ *
+ * Write to the three EEPROM bits.
+ *
+ * We have to store the DATA bit as we cannot definately read it back.
+ *
+ * Inputs : Adapter structure.
+ * The data to be written.
+ *
+ * Outputs : None.
+ ***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_output)
+#endif
+
+local void hwi_at24_output(ADAPTER * adapter, BYTE bValue)
+{
+ bLastDataBit = bValue & (BYTE)AT24_IO_DATA;
+
+ hwi_at24_write_bits(adapter, bValue);
+}
+
+
+/************************************************************************
+ *
+ * Write to the three EEPROM bits.
+ *
+ * Set the DATA bit to the most recent written bit.
+ *
+ * Inputs : Adapter structure.
+ * The data to be written.
+ *
+ * Outputs : None.
+ ***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_output_preserve_data)
+#endif
+
+local void hwi_at24_output_preserve_data(ADAPTER * adapter, BYTE bValue)
+{
+ bValue &= ~AT24_IO_DATA;
+
+ bValue |= bLastDataBit;
+
+ hwi_at24_write_bits(adapter, bValue);
+}
+
+
+/************************************************************************
+ * Delay to allow for serial device timing issues
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_delay)
+#endif
+
+local void hwi_at24_delay(ADAPTER * adapter)
+{
+ UINT i;
+
+ for (i = 0; i < 100; i++)
+ {
+ sys_insb(adapter->adapter_handle, adapter->io_location);
+ }
+}
+
+
+/************************************************************************
+ * Set the serial device clock bit
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_set_clk)
+#endif
+
+local void hwi_at24_set_clk(ADAPTER * adapter)
+{
+ BYTE temp;
+
+ temp = hwi_at24_input(adapter);
+ temp |= AT24_IO_CLOCK;
+
+ hwi_at24_output_preserve_data(adapter, temp);
+}
+
+
+/************************************************************************
+ *
+ * Clears the serial device clock bit
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_clr_clk)
+#endif
+
+local void hwi_at24_clr_clk(ADAPTER * adapter)
+{
+ BYTE temp;
+
+ temp = hwi_at24_input(adapter);
+ temp &= ~AT24_IO_CLOCK;
+
+ hwi_at24_output_preserve_data(adapter, temp);
+
+ return;
+}
+
+/************************************************************************
+*
+* hwi_at24_read_data
+* Read a data bit from the serial EEPROM. It is assumed that the clock is low
+* on entry to this routine. The data bit is forced high to allow access to
+* the data from the EEPROM, then the clock is toggled, with a read of the
+* data in the middle.
+*
+* Beware! The latched data bit will be set on exit.
+*
+************************************************************************/
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_read_data)
+#endif
+
+local BYTE hwi_at24_read_data(ADAPTER * adapter)
+{
+ BYTE bData;
+
+ /*
+ * Set the latched data bit to disconnect us from the data line.
+ */
+
+ bData = AT24_IO_ENABLE | AT24_IO_DATA;
+
+ hwi_at24_output(adapter, bData);
+
+ /*
+ * Set the clk bit to enable the data line.
+ */
+
+ hwi_at24_set_clk(adapter);
+
+ /*
+ * Read the data bit.
+ */
+
+ bData = hwi_at24_input(adapter);
+
+ /*
+ * Get the Data bit into bit 0.
+ */
+
+ bData &= AT24_IO_DATA;
+ bData >>= 1;
+
+ /*
+ * Clear clock again.
+ */
+
+ hwi_at24_clr_clk(adapter);
+
+ return bData;
+}
+
+/************************************************************************
+*
+* hwi_at24_write_data
+*
+* Write a data bit to the serial EEPROM. No clock toggle is performed.
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_write_data)
+#endif
+
+local void hwi_at24_write_data(ADAPTER * adapter, BYTE bData)
+{
+ BYTE bTemp;
+
+ /*
+ * The bit value is in position 0, get it into position 1
+ */
+
+ bData <<= 1;
+
+ /*
+ * Not strictly neccessary, but I'm paranoid.
+ */
+
+ bData &= AT24_IO_DATA;
+
+ bTemp = hwi_at24_input(adapter);
+ bTemp &= ~AT24_IO_DATA;
+
+ bTemp |= bData;
+ hwi_at24_output(adapter, bTemp);
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_enable_eeprom
+ *
+ * Must be called at the start of eeprom access to ensure we can pull low
+ * the data and clock pins on the EEPROM. Forces the clock signal low, as part
+ * of the strategy of routines assuming the clock is low on entry to them.
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_enable_eeprom)
+#endif
+
+local void hwi_at24_enable_eeprom(ADAPTER * adapter)
+{
+ BYTE temp;
+
+ temp = hwi_at24_input(adapter);
+ temp |= AT24_IO_ENABLE;
+
+ hwi_at24_output(adapter, temp);
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_start_bit
+ *
+ * Send a "START bit" to the serial EEPROM. This involves toggling the
+ * clock bit low to high, with data set on the rising edge and cleared on the
+ * falling edge. Assumes clock is low and EEPROM enabled on entry.
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_start_bit)
+#endif
+
+local void hwi_at24_start_bit(ADAPTER * adapter)
+{
+ BYTE bData;
+
+ bData = AT24_IO_ENABLE | AT24_IO_DATA;
+
+ /*
+ * Set the Data bit
+ */
+
+ hwi_at24_output(adapter, bData);
+ hwi_at24_set_clk(adapter);
+
+ /*
+ * Clear the Data bit.
+ */
+
+ bData = AT24_IO_ENABLE | AT24_IO_CLOCK;
+ hwi_at24_output(adapter, bData);
+ hwi_at24_clr_clk(adapter);
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_stop_bit
+ *
+ * Send a "STOP bit" to the serial EEPROM. This involves toggling the
+ * clock bit low to high, with data clear on the rising edge and set on the
+ * falling edge. Assumes clock is low and EEPROM enabled on entry.
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_stop_bit)
+#endif
+
+local void hwi_at24_stop_bit(ADAPTER * adapter)
+{
+ BYTE bData;
+
+ bData = AT24_IO_ENABLE;
+
+ /*
+ * Clear the Data Bit
+ */
+
+ hwi_at24_output(adapter, bData);
+ hwi_at24_set_clk(adapter);
+
+ /*
+ * Set the Data Bit.
+ */
+
+ bData |= (AT24_IO_DATA | AT24_IO_CLOCK);
+ hwi_at24_output(adapter, bData);
+ hwi_at24_clr_clk(adapter);
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_wait_ack
+ *
+ * Wait for an ack from the EEPROM.
+ * Outputs : TRUE or FALSE
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_wait_ack)
+#endif
+
+local WBOOLEAN hwi_at24_wait_ack(ADAPTER * adapter)
+{
+ WBOOLEAN Acked = FALSE;
+ UINT i;
+ BYTE bData;
+
+ for (i = 0; i < 10; i++)
+ {
+ bData = hwi_at24_read_data(adapter);
+ bData &= 1;
+
+ if (!bData)
+ {
+ Acked = TRUE;
+ break;
+ }
+ }
+
+ return Acked;
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_dummy_wait_ack
+ *
+ * Wait for a negative ack from the EEPROM.
+ *
+ * Outputs : TRUE or FALSE
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_dummy_wait_ack)
+#endif
+
+local WBOOLEAN hwi_at24_dummy_wait_ack(ADAPTER * adapter)
+{
+ WBOOLEAN Acked = FALSE;
+ UINT i;
+ BYTE bData;
+
+ for (i = 0; i < 10; i++)
+ {
+ bData = hwi_at24_read_data(adapter);
+
+ if (bData & 1)
+ {
+ Acked = TRUE;
+ break;
+ }
+ }
+
+ return Acked;
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_serial_read_bits
+ *
+ * Read a Byte from the serial EEPROM.
+ *
+ * NB This routine gets 8 bits from the EEPROM, but relies upon commands
+ * having been sent to the EEPROM 1st. In order to read a byte use
+ * hwi_at24_receive_data.
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_read_bits)
+#endif
+
+local BYTE hwi_at24_serial_read_bits(ADAPTER * adapter)
+{
+ BYTE bData = 0;
+ BYTE bBit;
+ UINT i;
+
+ for (i = 0; i < 8; i++)
+ {
+ /*
+ * The EEPROM clocks data out MSB first.
+ */
+
+ bBit = hwi_at24_read_data(adapter);
+ bData <<= 1;
+ bData |= bBit;
+ }
+
+ return bData;
+}
+
+/************************************************************************
+ *
+ * hwi_at24_serial_write_bits
+ *
+ * Send 8 bits to the serial EEPROM.
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_write_bits)
+#endif
+
+local void hwi_at24_serial_write_bits(ADAPTER * adapter, BYTE bData)
+{
+ BYTE bBit;
+ UINT i;
+
+ for (i = 0; i < 8; i++)
+ {
+ bBit = (BYTE)(bData >> (7-i));
+ bBit &= 1;
+ hwi_at24_write_data(adapter, bBit);
+
+ /*
+ * Toggle the clock line to pass the data to the device.
+ */
+
+ hwi_at24_set_clk(adapter);
+ hwi_at24_clr_clk(adapter);
+ }
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_serial_send_cmd
+ *
+ * Send a command to the serial EEPROM.
+ *
+ * Outputs : TRUE if sent OK
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_send_cmd)
+#endif
+
+local WBOOLEAN hwi_at24_serial_send_cmd(ADAPTER * adapter, BYTE bCommand)
+{
+ UINT i = 0;
+ WBOOLEAN Sent = FALSE;
+
+ while ((i < 40) && (Sent == FALSE))
+ {
+ i++;
+
+ /*
+ * Wake the device up.
+ */
+
+ hwi_at24_start_bit(adapter);
+ hwi_at24_serial_write_bits(adapter, bCommand);
+
+ Sent = hwi_at24_wait_ack(adapter);
+ }
+
+ return Sent;
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_serial_send_cmd_addr
+ *
+ * Send a command and address to the serial EEPROM.
+ *
+ * Outputs : TRUE if sent OK
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_send_cmd_addr)
+#endif
+
+local WBOOLEAN
+hwi_at24_serial_send_cmd_addr(ADAPTER * adapter, BYTE bCommand, BYTE bAddr)
+{
+ WBOOLEAN RetCode;
+
+ RetCode = hwi_at24_serial_send_cmd(adapter, bCommand);
+
+ if (RetCode)
+ {
+ hwi_at24_serial_write_bits(adapter, bAddr);
+
+ RetCode = hwi_at24_wait_ack(adapter);
+ }
+
+ return RetCode;
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_serial_receive_data
+ *
+ * Having set up the address we want to read from, read the data.
+ *
+ * Outputs : Data read back.
+ *
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_receive_data)
+#endif
+
+local BYTE hwi_at24_serial_receive_data(ADAPTER * adapter)
+{
+ BYTE bData;
+ WBOOLEAN Acked;
+
+ bData = hwi_at24_serial_read_bits(adapter);
+
+ Acked = hwi_at24_dummy_wait_ack(adapter);
+
+ if (!Acked)
+ {
+ bData = 0xFF;
+ }
+
+ return bData;
+
+}
+
+/************************************************************************
+ *
+ * hwi_at24_serial_read_byte
+ *
+ * Read a byte of data from the specified ROM address
+ *
+ * Outputs : Data read back.
+ *
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_read_byte)
+#endif
+
+local BYTE hwi_at24_serial_read_byte(ADAPTER * adapter, BYTE bAddr)
+{
+ BYTE bData;
+
+ hwi_at24_enable_eeprom(adapter);
+
+ /*
+ * Send the serial device a dummy WRITE command
+ * that contains the address of the byte we want to
+ * read !
+ */
+
+ hwi_at24_serial_send_cmd_addr(adapter, AT24_WRITE_CMD, bAddr);
+
+ /*
+ * Send the read command
+ */
+
+ hwi_at24_serial_send_cmd(adapter, AT24_READ_CMD);
+
+ /*
+ * Read the data
+ */
+
+ bData = hwi_at24_serial_receive_data(adapter);
+
+ /*
+ * Deselect the EEPROM
+ */
+
+ hwi_at24_stop_bit(adapter);
+
+ return bData;
+
+}
+
+
+/************************************************************************
+ *
+ * hwi_at24_read_a_word
+ *
+ * Read a word of data from the specified ROM address
+ *
+ * Outputs : Data read back.
+ *
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_read_a_word)
+#endif
+
+local WORD hwi_at24_read_a_word(ADAPTER * adapter, WORD word_address)
+{
+ WORD wData;
+ BYTE bLoByte;
+ BYTE bByteAddress = (BYTE)((word_address * 2)&0xFF);
+
+ bLoByte = hwi_at24_serial_read_byte(adapter, bByteAddress);
+
+ wData = (WORD) hwi_at24_serial_read_byte(
+ adapter,
+ (BYTE)(bByteAddress + 1));
+
+ wData <<= 8;
+ wData |= bLoByte;
+
+ return wData;
+}
+
+#endif
+
+
+/******* End of HWI_PCI2.C **************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_pcit.c b/private/ntos/ndis/madge/driver/hwi_pcit.c
new file mode 100644
index 000000000..fee338a22
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_pcit.c
@@ -0,0 +1,2028 @@
+/****************************************************************************
+*
+* HWI_PCIT.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* HARDWARE INTERFACE MODULE FOR PCI CARDS
+*
+* Copyright (c) Madge Networks Ltd. 1994
+*
+* COMPANY CONFIDENTIAL
+*
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_PCIT.C module contains the routines specific to the Smart 16/4 PCI(T)
+* based on the TI PCI ASIC, this card supports PSEUDO DMA, and BUs master DMA.
+*
+* The second spin of the Ti ASIC had a problem where it was not possible to do
+* DIO and DMA at the same time. Version 1.36 of FastMac plus had an interlock
+* put into it to prevent these happening @ the same time. FastMAC however
+* must be used in PIO mode. More details on the interlocking is found
+* at the top of hwi_pcit_interrupt
+*
+*****************************************************************************
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#define PCI_PCIT_DEVICE_ID 4
+
+#include "ftk_defs.h"
+
+#define COLOUR_BLACK 0x00
+#define COLOUR_BLUE 0x10
+#define COLOUR_GREEN 0x20
+#define COLOUR_CYAN 0x30
+#define COLOUR_RED 0x40
+#define COLOUR_MAGENTA 0x50
+#define COLOUR_YELLOW 0x60
+#define COLOUR_WHITE 0x70
+
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+BYTE bEepromByteStore;
+BYTE bLastDataBit;
+
+#ifndef FTK_NO_PCIT
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local WBOOLEAN
+hwi_pcit_read_node_address(
+ ADAPTER * adapter
+ );
+
+local WORD
+hwi_at24_read_a_word(
+ ADAPTER * adapter,
+ WORD word_address
+ );
+
+
+#ifndef FTK_NO_PROBE
+
+/****************************************************************************
+*
+* hwi_pcit_probe_card
+* ==================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is normally an array of IO locations to examine for the
+* presence of an adapter. However for PCI adapters the io location is read
+* from the BIOS, so this array can remain empty.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_pcit_probe_card routine is called by hwi_probe_adapter. It
+* reads the id registers to find the type of card and also reads the IRQ.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcit_probe_card)
+#endif
+
+export UINT
+hwi_pcit_probe_card(
+ PROBE * Resources,
+ UINT NumberOfResources,
+ WORD * IOMask,
+ UINT NumberIO
+ )
+{
+ WORD i;
+ WORD Handle;
+
+ if (!sys_pci_valid_machine())
+ {
+ return 0;
+ }
+
+ for (i=0;i<NumberOfResources;i++)
+ {
+ if (!sys_pci_find_card(&Handle, i,PCI_PCIT_DEVICE_ID))
+ {
+ break;
+ }
+
+ Resources[i].pci_handle = Handle;
+ Resources[i].adapter_card_bus_type = ADAPTER_CARD_TI_PCI_BUS_TYPE;
+
+ if (!sys_pci_get_io_base(Handle, &(Resources[i].io_location)))
+ {
+ return PROBE_FAILURE;
+ }
+
+ if (!sys_pci_get_irq(Handle, &(Resources[i].interrupt_number)))
+ {
+ return PROBE_FAILURE;
+ }
+
+ /*
+ * We can't read the memory size from the serial EEPROM until the
+ * hwi_pcit_install_card function is called.
+ */
+
+ Resources[i].adapter_ram_size = 512;
+
+ Resources[i].adapter_card_type = ADAPTER_CARD_TYPE_16_4_PCIT;
+
+#ifdef FMPLUS
+ Resources[i].transfer_mode = PIO_DATA_TRANSFER_MODE;
+/* Resources[i].transfer_mode = DMA_DATA_TRANSFER_MODE;*/
+#else
+ Resources[i].transfer_mode = PIO_DATA_TRANSFER_MODE;
+#endif
+
+ }
+
+ return i;
+}
+
+#endif
+
+
+/****************************************************************************
+*
+* hwi_pcit_install_card
+* ====================
+*
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* hwi_pcit_install_card is called by hwi_install_adapter. It sets up
+* the adapter card and downloads the required code to it. Firstly, it
+* checks there is a valid adapter at the required IO address by reading
+* the node address from the BIA PROM. It then sets up and checks various
+* on-board registers for correct operation.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls.
+* The adapter is set up for Eagle Pseudo-DMA, since real DMA is not used.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcit_install_card)
+#endif
+
+export WBOOLEAN
+hwi_pcit_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sif_base;
+ WORD ring_speed;
+ WORD wControlReg;
+ WORD wBrokenDMA;
+ BYTE bCache;
+#ifdef FMPLUS
+ DWORD dwHandShakeAddress;
+#endif
+
+ /*
+ * These things can all be assumed for the Ti PCI Card.
+ */
+
+ adapter->adapter_card_type = ADAPTER_CARD_TYPE_16_4_PCIT;
+ adapter->adapter_card_revision = ADAPTER_CARD_16_4_PCIT;
+ adapter->edge_triggered_ints = FALSE;
+
+ /*
+ * Start off by assuming we will use pseudo DMA.
+ */
+
+ adapter->EaglePsDMA = TRUE;
+
+ /*
+ * Save IO locations of SIF registers.
+ */
+
+ sif_base = adapter->io_location;
+
+ adapter->sif_dat = sif_base + EAGLE_SIFDAT;
+ adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC;
+ adapter->sif_adr = sif_base + EAGLE_SIFADR;
+ adapter->sif_int = sif_base + EAGLE_SIFINT;
+ adapter->sif_acl = sif_base + EAGLE_SIFACL;
+ adapter->sif_adx = sif_base + EAGLE_SIFADX;
+ adapter->sif_dmalen = sif_base + EAGLE_DMALEN;
+ adapter->sif_sdmadat = sif_base + EAGLE_SDMADAT;
+ adapter->sif_sdmaadr = sif_base + EAGLE_SDMAADR;
+ adapter->sif_sdmaadx = sif_base + EAGLE_SDMAADX;
+
+ adapter->io_range = SIF_IO_RANGE;
+
+ /*
+ * If we are supposed to use DMA then enable it.
+ */
+
+ if (adapter->transfer_mode == DMA_DATA_TRANSFER_MODE)
+ {
+ adapter->EaglePsDMA = FALSE;
+
+ /*
+ * Does this card have a 'broken' DMA ASIC ??
+ * Read the HW features 2 to find out.
+ */
+
+ wBrokenDMA = hwi_at24_read_a_word(adapter, PCIT_EEPROM_HWF2);
+ if (wBrokenDMA == PCIT_BROKEN_DMA)
+ {
+#ifdef FMPLUS
+ adapter->mc32_config = TRN_PCIT_BROKEN_DMA;
+#else
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_17_BAD_TRANSFER_MODE;
+ return FALSE;
+#endif
+ }
+ else
+ {
+ adapter->mc32_config = 0;
+ }
+ }
+ else
+ {
+ /*
+ * If we've using pseudo DMA then we need a software handshake.
+ */
+ adapter->mc32_config = MC_AND_ISACP_USE_PIO;
+ }
+
+ /*
+ * The Command word of the PCI config space must be set to 7 i.e.
+ * we support BUS MASTER DMA. Some BIOS' don't do this. The Ti ASIC
+ * refuses to let this field be set to 3 which some BIOS's do this is
+ * turned into 0 by the Ti ASIC.
+ */
+
+ sys_pci_write_config_byte(
+ adapter_handle,
+ PCI_CONFIG_COMMAND,
+ PCI_CONFIG_BUS_MASTER_ENABLE |
+ PCI_CONFIG_IO_ENABLE |
+ PCI_CONFIG_MEM_ENABLE);
+
+
+ /*
+ *
+ * Since the BIOS may have failed to set the card up correctly as a result of
+ * the above problem, it may have got the Latency timer (offset 0Dh) and
+ * cache line size (offset 0Ch) bytes wrong too. The only observed erroneous
+ * values (Compaq Deskpro XL 466) are F8h and FFh respectively (all bits set
+ * that can be set).
+ *
+ * The latency timer is not particularly important, and can safely be left at
+ * F8h.
+ *
+ * A cache line size of FFh causes DMA problems and is changed to 20h.
+ *
+ */
+
+ sys_pci_read_config_byte(adapter_handle, CACHE_LINE_SIZE, &bCache);
+
+ if (bCache == 0xFF)
+ {
+ sys_pci_write_config_byte(
+ adapter_handle,
+ CACHE_LINE_SIZE,
+ 0x20
+ );
+ }
+
+ /*
+ * Set up the Miscellanous Control Register, we only need to modify the
+ * top word.
+ */
+
+ sys_pci_read_config_word(
+ adapter_handle,
+ MISC_CONT_REG + 2,
+ &wControlReg);
+
+#if 0
+ wControlReg &= 0xE4;
+ wControlReg |= 0x4;
+#else
+ /*
+ * A fix to the DMA bug, we now clear bit 18 rather than setting it
+ * (Slight lie this was not really a fix, but J.M. thinks leave it
+ * in as it does no harm. M.D. & P.R. disagree )
+ */
+ wControlReg &= 0xE0;
+#endif
+
+ sys_pci_write_config_word(
+ adapter_handle,
+ MISC_CONT_REG + 2,
+ wControlReg);
+
+ /*
+ * Can't RESET the Eagle as this does not work
+ */
+
+ if (!hwi_pcit_read_node_address(adapter))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+ return FALSE;
+ }
+
+ ring_speed = hwi_at24_read_a_word(adapter, PCIT_EEPROM_RING_SPEED);
+
+ /*
+ * Get the amount of RAM from the serial EEPROM (in units of 128k).
+ */
+
+ adapter->adapter_ram_size = hwi_at24_read_a_word(
+ adapter,
+ PCIT_EEPROM_RAM_SIZE) * 128;
+
+ /*
+ * Set the ring speed. If the user has specified a value then we will
+ * use that, otherwise we will use the value read from the EEPROM.
+ */
+
+ if (adapter->set_ring_speed == 16)
+ {
+ adapter->nselout_bits = NSEL_16MBITS;
+ }
+ else if (adapter->set_ring_speed == 4)
+ {
+ adapter->nselout_bits = NSEL_4MBITS;
+ }
+ else if (ring_speed == PCIT_EEPROM_4MBITS)
+ {
+ adapter->nselout_bits = NSEL_4MBITS;
+ }
+ else
+ {
+ adapter->nselout_bits = NSEL_16MBITS;
+ }
+
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Halt the Eagle prior to downloading the MAC code - this will also
+ * write the interrupt bits into the SIFACL register, where the MAC can
+ * find them.
+ */
+
+ hwi_halt_eagle(adapter);
+
+ /*
+ * Download code to adapter.
+ * View download image as a sequence of download records.
+ * Pass address of routine to set up DIO addresses on PCI cards.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!hwi_download_code(
+ adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_pcit_set_dio_address))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+
+ /*
+ * Restart the Eagle to initiate bring up diagnostics.
+ */
+
+ hwi_start_eagle(adapter);
+
+ /*
+ * Wait for a valid bring up code, may wait 3 seconds.
+ */
+
+ if (!hwi_get_bring_up_code(adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Set DIO address to point to EAGLE DATA page 0x10000L.
+ */
+
+ hwi_pcit_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * Get the ring speed, from the Eagle DIO space.
+ */
+
+ adapter->ring_speed = hwi_get_ring_speed(adapter);
+
+ /*
+ * Set maximum frame size from the ring speed.
+ */
+
+ adapter->max_frame_size = hwi_get_max_frame_size(adapter);
+
+ /*
+ * If not in polling mode then set up interrupts.
+ * interrupts_on field is used when disabling interrupts for adapter.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on = sys_enable_irq_channel(
+ adapter_handle,
+ adapter->interrupt_number);
+
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+ /*
+ * Pass the address to be used for the 'broken' DMA handshake to the
+ * adapter.
+ */
+
+#ifdef FMPLUS
+
+ if (adapter->mc32_config == TRN_PCIT_BROKEN_DMA)
+ {
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ DIO_LOCATION_DMA_POINTER);
+
+ dwHandShakeAddress = adapter->dma_test_buf_phys
+ + SCB_TEST_PATTERN_LENGTH
+ + SSB_TEST_PATTERN_LENGTH;
+
+ /*
+ * We have to Output this address LSW first;
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_datinc,
+ (WORD) (dwHandShakeAddress & 0xFFFF));
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_datinc,
+ (WORD) ((dwHandShakeAddress & 0xFFFF0000) >> 16));
+
+
+ }
+
+#endif
+
+
+ /*
+ * Return successfully.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* hwi_pcit_interrupt_handler
+* =========================
+*
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ==========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pcit_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF for either
+* a PIO data transfer or a normal condition (received frame, SRB complete,
+* ARB indication etc). Note it could in fact be the case that no interrupt
+* has occured on the particular adapter being checked.
+*
+* On normal SIF interrupts, the interrupt is acknowledged and cleared. The
+* value in the SIF interrupt register is recorded in order to pass it to
+* the driver_interrupt_entry routine (along with the adapter details).
+*
+* On PseudoDMA interrupts, the length, direction and physical address of
+* the transfer is determined. A system provided routine is called to do
+* the data transfer itself.
+*
+* The Second spin of the Ti ASIC has some problems such that no access to SIF
+* registers can occur safely during a DMA.
+*
+* If the Broken DMA bit was set in the HW features 2 the we need the following
+* mechanism.
+*
+* - The card wishes to do a DMA
+* - The card sets the handshake word to 1111h
+* - The card sets the SIF interrupt bit in the SIFINT register
+* - The host interrupt routine is entered
+* - The host notices it is a SIF interrupt and it is a special SIF
+* interrupt since the handshake word is 1111h
+* - The host clears the handshake word
+* - ... which the card has been waiting for
+* - The card performs the DMA transfer
+* - The card does an extra, single byte, DMA transfer to a flag in
+* the adapter structure on the host, of data 11h
+* - ... which the host has been waiting for
+* - The host resets the transfer flag to its previous value
+* - The host EOIs the interrupt and leaves the interrupt routine
+*
+* The handshake word off the adapter which tells us the following:
+*
+* 0000 => Normal SIF interrupt.
+* 1111 => Spin whilst DMA completes.
+* 2222 => As for 1111 but this hints that a SIF interrupt may follow very soon
+* after the DMA, hence poll for this.
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+local BYTE
+hwi_pcit_read_byte(
+ BYTE FAR * ptr
+ );
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_pcit_read_byte)
+#endif
+
+local BYTE
+hwi_pcit_read_byte(
+ BYTE FAR * ptr
+ )
+{
+ return *ptr;
+}
+
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_pcit_interrupt_handler)
+#endif
+
+export void
+hwi_pcit_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sifacl;
+ WORD sifint_value;
+ WORD sifint_tmp;
+ WORD pio_addr_lo;
+ DWORD pio_addr_hi;
+ WORD pio_len_bytes;
+ WORD last_byte;
+ WBOOLEAN pio_from_adapter;
+ WBOOLEAN our_interrupt = FALSE;
+ WBOOLEAN proper_sif_int = FALSE;
+ BYTE FAR * pio_address;
+ WORD saved_sifadr;
+#ifdef FMPLUS
+ BYTE FAR * dma_handshake_addr;
+ WORD dodgy_dma;
+ WORD timeout;
+#endif
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Check for SIF interrupt or PIO interrupt.
+ */
+
+ /*
+ * Read SIFINT, and then re-read to make sure value is stable.
+ */
+
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ }
+ while (sifint_tmp != sifint_value);
+
+ /*
+ * Given the SIFINT value, we can check one of the bits in it to see
+ * if that is what caused the interrupt.
+ */
+
+ if ((sifint_value & EAGLE_SIFINT_SYSTEM) != 0)
+ {
+
+ /*
+ * It's our interrupt and as far as we can tell it's a real
+ * SIF interrupt.
+ */
+
+ proper_sif_int = TRUE;
+ our_interrupt = TRUE;
+
+#ifdef FMPLUS
+
+ if (adapter->mc32_config == TRN_PCIT_BROKEN_DMA)
+ {
+
+ /*
+ * Preserve SIFADR.
+ */
+
+ saved_sifadr = sys_insw(adapter_handle, adapter->sif_adr);
+
+ /*
+ * Broken DMA is enabled so check if this was a broken
+ * DMA interrupt.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ DIO_LOCATION_DMA_CONTROL
+ );
+
+ dodgy_dma = sys_insw(adapter_handle, adapter->sif_dat);
+
+ /*
+ * If there is a DMA pending then do some DMA processing.
+ */
+
+ if (dodgy_dma != 0)
+ {
+ /*
+ * This is not a proper SIF interrupt so note the fact.
+ */
+
+ proper_sif_int = FALSE;
+
+ /*
+ * Work out where the handshake byte will be in host
+ * memory.
+ */
+
+ dma_handshake_addr = (BYTE FAR *)
+ adapter->dma_test_buf_virt +
+ SCB_TEST_PATTERN_LENGTH +
+ SSB_TEST_PATTERN_LENGTH;
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge
+ * interrupt at SIF.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_int, 0);
+
+ /*
+ * Set the host flag to zero.
+ */
+
+ *dma_handshake_addr = 0;
+
+ /*
+ * Clear the flag on the adapter i.e. start DMA.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_dat, 0);
+
+ /*
+ * Wait until the adapter puts 0x11 in our flag.
+ */
+
+ while (hwi_pcit_read_byte(dma_handshake_addr) != 0x11)
+ NdisStallExecution(10);
+ }
+
+ /*
+ * Now did the adapter hint that a SIF interrupt will follow
+ * presently.
+ */
+
+ if (dodgy_dma == 0x2222)
+ {
+ /*
+ * Poll For a SIF interrupt - wait for it to stabalise at the
+ * same time.
+ */
+
+ timeout = 0;
+
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+
+ if (sifint_value == sifint_tmp &&
+ (sifint_value & EAGLE_SIFINT_SYSTEM) != 0);
+ {
+ proper_sif_int = TRUE;
+ }
+ timeout++;
+ }
+ while (!proper_sif_int && timeout < 40);
+ }
+
+ /*
+ * Restore SIFADR.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_adr,
+ saved_sifadr);
+
+ }
+#endif
+ }
+
+ /*
+ * Now read the SIFACL register to check for a PseudoDMA interrupt.
+ */
+
+ if (adapter->transfer_mode != DMA_DATA_TRANSFER_MODE)
+ {
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+
+ if ((sifacl & EAGLE_SIFACL_SWHRQ) != 0)
+ {
+ our_interrupt = TRUE;
+
+ /*
+ * Using any PCI card, a software handshake must occur so that the MAC
+ * does not try to initiate another transfer until a point has been reached on
+ * the host at which the transfer has completed. If not, the following could
+ * happen:
+ *
+ * - The host requests the last word/byte of a receive from the card.
+ * - The SIF does not has the data ready.
+ * - Control of the bus is given to a SCSI card.
+ * - It bursts/does nothing in bus master mode for 16 microseconds.
+ * - The data becomes ready early on during these 16 microseconds and
+ * as a result the card software beleives that the transfer has completed.
+ * - The card software continues and sets up another PsDMA transfer.
+ * - The SCSI card finishes, but the PdDMA length is now incorrect and
+ * all is lost.
+ *
+ */
+
+ saved_sifadr = sys_insw(adapter_handle, adapter->sif_adr);
+
+ /*
+ * Set the PIO_HANDSHAKE word to 0
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_adr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(adapter_handle, adapter->sif_dat, 0 );
+
+ /*
+ * NB Words must be byte swapped, this is done in the SIF and
+ * then Ti kindly byte swap in their ASIC, so we have to do it again.
+ * Also beacause of a bug in the ASIC byte read/writes don't work
+ * so if the buffer is odd aligned the rep insw/outsw must
+ * mis-aligned on the host. Apparently this causes no performance
+ * loss on the 486 or above.
+ */
+
+ /*
+ * PIO interrupt has occurred. Transfer data to/from adapter.
+ */
+
+ /*
+ * By writing the SWHLDA bit, we "start" the transfer,
+ * causing the SDMA registers to mapped in.
+ */
+
+ macro_setw_bit(
+ adapter_handle,
+ adapter->sif_acl,
+ EAGLE_SIFACL_SWHLDA);
+
+ /*
+ * Determine what direction the data transfer is to take place in.
+ */
+
+ pio_from_adapter = sys_insw(
+ adapter_handle,
+ adapter->sif_acl) & EAGLE_SIFACL_SWDDIR;
+
+ pio_len_bytes = sys_insw(
+ adapter_handle,
+ adapter->sif_dmalen);
+
+ pio_addr_lo = sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadr);
+
+ pio_addr_hi = (DWORD) sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadx);
+
+ pio_address = (BYTE FAR *) ((pio_addr_hi << 16) |
+ ((DWORD) pio_addr_lo));
+
+
+ /*
+ * Do the actual data transfer.
+ */
+
+ /*
+ * Note that Fastmac only copies whole WORDs to DWORD boundaries.
+ * FastmacPlus, however, can transfer any length to any address.
+ */
+
+ if (pio_from_adapter)
+ {
+ /*
+ * Transfer into host memory from adapter.
+ */
+
+ sys_rep_swap_insw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1));
+
+
+ if (pio_len_bytes % 2)
+ {
+ /*
+ * Odd length transfer, need to get the last byte, this
+ * is done using an in ax, dx, and the byte is in the top
+ * byte due to byte swapping issues.
+ */
+
+ last_byte = sys_insw(
+ adapter_handle,
+ adapter->sif_sdmadat);
+
+ *(pio_address + pio_len_bytes - 1) = (BYTE)
+ ((last_byte & 0xFF00) >> 8);
+
+ }
+ }
+ else
+ {
+ /*
+ * Transfer into adapter memory from the host.
+ */
+
+ sys_rep_swap_outsw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1));
+
+ if (pio_len_bytes % 2)
+ {
+ /*
+ * Odd length transfer, need to send the last byte, this
+ * is done using by writing a word, with the byte is in
+ * the top byte due to byte swapping issues.
+ */
+
+ last_byte = (WORD) *(pio_address + pio_len_bytes - 1);
+ last_byte <<= 8;
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ last_byte);
+ }
+ }
+
+ /*
+ * Wait for SWHLDA to go low, it is not safe to access normal
+ * SIF registers until this is the case.
+ */
+
+ do
+ {
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+ }
+ while (sifacl & EAGLE_SIFACL_SWHLDA);
+
+ /*
+ * Now output 0xFFFF to the PIO_HANDSHAKE word, to signal
+ * the DMA is complete.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_dat, 0xFFFF );
+
+ /*
+ * Restore the saved SIF address.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_adr, saved_sifadr);
+ }
+ }
+
+ /*
+ * Does a normal sif_int need processing as opposed to a 'dodgy' DMA
+ * interrupt.
+ */
+
+ if (proper_sif_int)
+ {
+ /*
+ * A SIF interrupt has occurred.
+ * This could be an SRB free, an adapter check or a received
+ * frame interrupt.
+ */
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_int, 0);
+
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+
+ driver_interrupt_entry(adapter_handle, adapter, sifint_value);
+ }
+
+ if (our_interrupt)
+ {
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+#endif
+
+ }
+
+ /*
+ * Let system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_pcit_remove_card
+* ====================
+*
+*
+* PARAMETERS (passed by hwi_remove_card)
+* ======================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_smart16_remove_card routine is called by hwi_remove_adapter. It
+* disables interrupts if they are being used. It also resets the adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pcit_remove_card)
+#endif
+
+export void
+hwi_pcit_remove_card(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD wGenConAddr = adapter->io_location +
+ PCI_GENERAL_CONTROL_REG;
+ WORD sifacl;
+
+ /*
+ * Interrupt must be disabled at adapter before unpatching interrupt.
+ * Even in polling mode we must turn off interrupts at adapter.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+ sifacl = (sifacl & ~(EAGLE_SIFACL_PSDMAEN | EAGLE_SIFACL_SINTEN));
+ sys_outsw(adapter_handle, adapter->sif_acl, sifacl);
+
+ if (adapter->interrupts_on)
+ {
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(
+ adapter_handle,
+ adapter->interrupt_number);
+ }
+
+ adapter->interrupts_on = FALSE;
+ }
+
+ /*
+ * Can't reset the Eagle as the reset line does not work, lets try
+ * hwi_halt_eagle.
+ */
+
+ hwi_halt_eagle( adapter );
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_pcit_set_dio_address
+* =======================
+*
+* The hwi_pcit_set_dio_address routine is used, with PCI cards, for
+* putting a 32 bit DIO address into the SIF DIO address and extended DIO
+* address registers. Note that the extended address register should be
+* loaded first.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcit_set_dio_address)
+#endif
+
+export void
+hwi_pcit_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * Load extended DIO address register with top 16 bits of address.
+ * Always load extended address register first.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ sif_dio_adrx,
+ (WORD)(dio_address >> 16));
+
+ /*
+ * Load DIO address register with low 16 bits of address.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ sif_dio_adr,
+ (WORD)(dio_address & 0x0000FFFF));
+}
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pcit_read_node_address
+| ==========================
+|
+| The hwi_pcit_read_node_address routine reads in the node address from
+| the SEEPROM, and checks that it is a valid Madge node address.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcit_read_node_address)
+#endif
+
+local WBOOLEAN
+hwi_pcit_read_node_address(
+ ADAPTER * adapter
+ )
+{
+ WORD temp;
+ temp = hwi_at24_read_a_word(adapter, PCIT_EEPROM_BIA_WORD0);
+ adapter->permanent_address.byte[0] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[1] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ temp = hwi_at24_read_a_word(adapter, PCIT_EEPROM_BIA_WORD1);
+ adapter->permanent_address.byte[2] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[3] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ temp = hwi_at24_read_a_word(adapter, PCIT_EEPROM_BIA_WORD2);
+ adapter->permanent_address.byte[4] = (BYTE) ((temp ) & 0x00ff);
+ adapter->permanent_address.byte[5] = (BYTE) ((temp >> 8) & 0x00ff);
+
+ return TRUE;
+}
+
+/***************************************************************************
+* *
+* Local routines for accessing the AT93AT24 Serial EEPROM, this is the same*
+* EEPROM fitted to the PNP card and the PCI 2 card. The only difference, is*
+* that for this card the I/O is done through the PCI config space. *
+* *
+***************************************************************************/
+
+local void hwi_at24_delay( ADAPTER * adapter );
+local void hwi_at24_set_clk( ADAPTER * adapter );
+local void hwi_at24_clr_clk( ADAPTER * adapter );
+local void hwi_at24_twitch_clk( ADAPTER * adapter );
+local void hwi_at24_start_bit( ADAPTER * adapter );
+local void hwi_at24_stop_bit( ADAPTER * adapter );
+local WBOOLEAN hwi_at24_wait_ack( ADAPTER * adapter );
+local WBOOLEAN hwi_at24_dummy_wait_ack( ADAPTER * adapter );
+
+
+/************************************************************************
+*
+* Read the EEPROM bits
+*
+* The Data Bit does not always match the previously ouptut value.
+*
+* Inputs : Adapter structure.
+*
+* Outputs : Value read from control register.
+*
+***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_input)
+#endif
+
+local BYTE hwi_at24_input( ADAPTER * adapter )
+{
+ BYTE bInput;
+ BYTE bStore;
+
+ sys_pci_read_config_byte(adapter->adapter_handle, EEPROM_OFFSET, &bInput);
+
+ /*
+ * Store the 5 bits which don't interrest us.
+ */
+
+ bEepromByteStore = bInput & (BYTE) 0x8F;
+
+ /*
+ * The bits are arranged as follows
+ * 0ZXY0000,
+ * all the above routines are generic and expect
+ * 00000XYZ
+ */
+
+ bStore = bInput;
+ bInput &= 0x40;
+ bInput >>= 6;
+ bStore &= 0x30;
+ bStore >>= 3;
+ bInput |= bStore;
+
+ return bInput;
+}
+
+
+/************************************************************************
+*
+* Write to the three EEPROM bits.
+*
+* Inputs : Adapter structure.
+* The data to be written.
+*
+* Outputs : None.
+*
+***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_write_bits)
+#endif
+
+local void hwi_at24_write_bits(ADAPTER * adapter, BYTE bValue)
+{
+ BYTE bTemp;
+
+ bTemp = (BYTE)((bValue & 0x6) << 3);
+ bTemp |= (BYTE)((bValue & 0x1) << 6);
+
+ /*
+ * Restore the 5 bits we were not interested in from the previous read.
+ */
+
+ bTemp |= bEepromByteStore;
+
+ sys_pci_write_config_byte(adapter->adapter_handle, EEPROM_OFFSET, bTemp);
+
+
+ return;
+}
+
+
+/************************************************************************
+*
+* Write to the three EEPROM bits.
+*
+* We have to store the DATA bit as we cannot definately read it back.
+*
+* Inputs : Adapter structure.
+* The data to be written.
+*
+* Outputs : None.
+*
+***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_output)
+#endif
+
+local void hwi_at24_output(ADAPTER * adapter, BYTE bValue)
+{
+ bLastDataBit = bValue & (BYTE) AT24_IO_DATA;
+
+ hwi_at24_write_bits(adapter, bValue);
+
+ return;
+}
+
+
+/************************************************************************
+*
+* Write to the three EEPROM bits.
+*
+* Set the DATA bit to the most recent written bit.
+*
+* Inputs : Adapter structure.
+* The data to be written.
+*
+* Outputs : None.
+*
+***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_output_preserve_data)
+#endif
+
+local void hwi_at24_output_preserve_data( ADAPTER * adapter, BYTE bValue)
+{
+ bValue &= ~AT24_IO_DATA;
+ bValue |= bLastDataBit;
+
+ hwi_at24_write_bits(adapter, bValue);
+
+ return;
+}
+
+
+/************************************************************************
+*
+* Delay to allow for serial device timing issues
+*
+* Inputs : Adapter structure
+*
+* Outputs : None
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_delay)
+#endif
+
+local void hwi_at24_delay(ADAPTER * adapter)
+{
+ UINT i;
+
+ for (i = 0; i < 100; i++)
+ {
+ sys_insb(adapter->adapter_handle, adapter->io_location);
+ }
+}
+
+
+/************************************************************************
+*
+* Set the serial device clock bit
+*
+* Inputs : Adapter structure
+*
+* Outputs : None
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_set_clk)
+#endif
+
+local void hwi_at24_set_clk(ADAPTER * adapter )
+{
+ BYTE temp;
+
+ temp = hwi_at24_input(adapter );
+ temp |= AT24_IO_CLOCK;
+
+ hwi_at24_output_preserve_data(adapter, temp);
+
+ return;
+}
+
+
+/************************************************************************
+*
+* Clears the serial device clock bit
+*
+* Inputs : Adapter structure
+*
+* Outputs : None
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_clr_clk)
+#endif
+
+local void hwi_at24_clr_clk(ADAPTER * adapter )
+{
+ BYTE temp;
+
+ temp = hwi_at24_input(adapter );
+ temp &= ~AT24_IO_CLOCK;
+
+ hwi_at24_output_preserve_data(adapter, temp);
+
+ return;
+}
+
+/************************************************************************
+*
+* hwi_at24_read_data
+* Read a data bit from the serial EEPROM. It is assumed that the clock is low
+* on entry to this routine. The data bit is forced high to allow access to
+* the data from the EEPROM, then the clock is toggled, with a read of the
+* data in the middle.
+*
+* Beware! The latched data bit will be set on exit.
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_read_data)
+#endif
+
+local BYTE hwi_at24_read_data(ADAPTER * adapter)
+{
+ BYTE bData;
+
+ /*
+ * Set the latched data bit to disconnect us from the data line.
+ */
+
+ bData = AT24_IO_ENABLE | AT24_IO_DATA;
+
+ hwi_at24_output(adapter, bData);
+
+ /*
+ * Set the clk bit to enable the data line.
+ */
+
+ hwi_at24_set_clk(adapter);
+
+ /*
+ * Read the data bit.
+ */
+
+ bData = hwi_at24_input(adapter);
+
+ /*
+ * Get the Data bit into bit 0.
+ */
+
+ bData &= AT24_IO_DATA;
+ bData >>= 1;
+
+ /*
+ * Clear clock again.
+ */
+
+ hwi_at24_clr_clk(adapter);
+
+ return bData;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_write_data
+*
+* Write a data bit to the serial EEPROM. No clock toggle is performed.
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_write_data)
+#endif
+
+local void hwi_at24_write_data(ADAPTER * adapter, BYTE bData)
+{
+ BYTE bTemp;
+
+ /*
+ * The bit value is in position 0, get it into position 1.
+ */
+
+ bData <<= 1;
+
+ /*
+ * Not strictly neccessary, but I'm paranoid.
+ */
+
+ bData &= AT24_IO_DATA;
+ bTemp = hwi_at24_input(adapter);
+ bTemp &= ~AT24_IO_DATA;
+
+ bTemp |= bData;
+ hwi_at24_output(adapter, bTemp);
+
+ return;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_enable_eeprom
+*
+* Must be called at the start of eeprom access to ensure we can pull low
+* the data and clock pins on the EEPROM. Forces the clock signal low, as part
+* of the strategy of routines assuming the clock is low on entry to them.
+*
+* Inputs : Adapter structure
+*
+* Outputs : None
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_enable_eeprom)
+#endif
+
+local void hwi_at24_enable_eeprom(ADAPTER * adapter)
+{
+ BYTE temp;
+
+ temp = hwi_at24_input(adapter);
+ temp |= AT24_IO_ENABLE;
+
+ hwi_at24_output(adapter, temp);
+
+ return;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_start_bit
+*
+* Send a "START bit" to the serial EEPROM. This involves toggling the
+* clock bit low to high, with data set on the rising edge and cleared on the
+* falling edge. Assumes clock is low and EEPROM enabled on entry.
+*
+* Inputs : Adapter structure
+*
+* Outputs : None
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_start_bit)
+#endif
+
+local void hwi_at24_start_bit(ADAPTER * adapter)
+{
+ BYTE bData;
+
+ bData = AT24_IO_ENABLE | AT24_IO_DATA;
+
+ /*
+ * Set the Data bit.
+ */
+
+ hwi_at24_output(adapter, bData);
+
+ hwi_at24_set_clk(adapter);
+
+ /*
+ * Clear the Data bit
+ */
+
+ bData = AT24_IO_ENABLE | AT24_IO_CLOCK;
+ hwi_at24_output(adapter, bData);
+
+ hwi_at24_clr_clk(adapter);
+
+ return;
+
+}
+
+
+/************************************************************************
+*
+* hwi_at24_stop_bit
+*
+* Send a "STOP bit" to the serial EEPROM. This involves toggling the
+* clock bit low to high, with data clear on the rising edge and set on the
+* falling edge. Assumes clock is low and EEPROM enabled on entry.
+* Inputs : Adapter structure
+*
+* Outputs : None
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_stop_bit)
+#endif
+
+local void hwi_at24_stop_bit(ADAPTER * adapter)
+{
+ BYTE bData;
+
+ bData = AT24_IO_ENABLE;
+
+ /*
+ * Clear the Data Bit.
+ */
+
+ hwi_at24_output(adapter, bData);
+
+ hwi_at24_set_clk(adapter);
+
+ /*
+ * Set the Data Bit.
+ */
+
+ bData |= (AT24_IO_DATA | AT24_IO_CLOCK);
+ hwi_at24_output(adapter, bData);
+
+ hwi_at24_clr_clk(adapter);
+
+ return;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_wait_ack
+*
+* Wait for an ack from the EEPROM.
+* Outputs : TRUE or FALSE
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_wait_ack)
+#endif
+
+local WBOOLEAN hwi_at24_wait_ack(ADAPTER * adapter)
+{
+ WBOOLEAN Acked = FALSE;
+ UINT i;
+ BYTE bData;
+
+ for (i = 0; i < 10; i++)
+ {
+ bData = hwi_at24_read_data(adapter);
+ bData &= 1;
+
+ if (!bData)
+ {
+ Acked = TRUE;
+ break;
+ }
+ }
+
+ return Acked;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_dummy_wait_ack
+*
+* Wait for a negative ack from the EEPROM.
+*
+* Outputs : TRUE or FALSE
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_dummy_wait_ack)
+#endif
+
+local WBOOLEAN hwi_at24_dummy_wait_ack(ADAPTER * adapter)
+{
+ WBOOLEAN Acked = FALSE;
+ UINT i;
+ BYTE bData;
+
+ for (i = 0; i < 10; i++)
+ {
+ bData = hwi_at24_read_data(adapter);
+
+ if (bData & 1)
+ {
+ Acked = TRUE;
+ break;
+ }
+ }
+
+ return Acked;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_serial_read_bits
+*
+* Read a Byte from the serial EEPROM.
+*
+* NB This routine gets 8 bits from the EEPROM, but relies upon commands
+* having been sent to the EEPROM 1st. In order to read a byte use
+* hwi_at24_receive_data.
+*
+* Outputs : None
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_read_bits)
+#endif
+
+local BYTE hwi_at24_serial_read_bits(ADAPTER * adapter)
+{
+ BYTE bData = 0;
+ BYTE bBit;
+ UINT i;
+
+ for (i = 0; i < 8; i++)
+ {
+ /*
+ * The EEPROM clocks data out MSB first.
+ */
+
+ bBit = hwi_at24_read_data( adapter );
+ bData <<= 1;
+ bData |= bBit;
+ }
+
+ return bData;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_serial_write_bits
+*
+* Send 8 bits to the serial EEPROM.
+*
+* Outputs : None
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_write_bits)
+#endif
+
+local void hwi_at24_serial_write_bits(ADAPTER * adapter, BYTE bData)
+{
+ BYTE bBit;
+ UINT i;
+
+ for ( i = 0; i < 8; i++)
+ {
+ bBit = (BYTE)(bData >> (7-i));
+ bBit &= 1;
+ hwi_at24_write_data(adapter, bBit);
+
+ /*
+ * Toggle the clock line to pass the data to the device.
+ */
+
+ hwi_at24_set_clk(adapter);
+ hwi_at24_clr_clk(adapter);
+ }
+
+ return;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_serial_send_cmd
+*
+* Send a command to the serial EEPROM.
+*
+* Outputs : TRUE if sent OK
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_send_cmd)
+#endif
+
+local WBOOLEAN hwi_at24_serial_send_cmd( ADAPTER * adapter, BYTE bCommand )
+{
+ UINT i = 0;
+ WBOOLEAN Sent = FALSE;
+
+ while ((i < 40) && (Sent == FALSE))
+ {
+ i++;
+
+ /*
+ * Wake the device up.
+ */
+
+ hwi_at24_start_bit(adapter);
+
+ hwi_at24_serial_write_bits( adapter, bCommand);
+
+ Sent = hwi_at24_wait_ack(adapter);
+ }
+
+ return Sent;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_serial_send_cmd_addr
+*
+* Send a command and address to the serial EEPROM.
+*
+* Outputs : TRUE if sent OK
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_send_cmd_addr)
+#endif
+
+local WBOOLEAN hwi_at24_serial_send_cmd_addr(
+ ADAPTER * adapter,
+ BYTE bCommand,
+ BYTE bAddr
+ )
+{
+ WBOOLEAN RetCode;
+
+ RetCode = hwi_at24_serial_send_cmd(adapter, bCommand);
+
+ if (RetCode)
+ {
+ hwi_at24_serial_write_bits(adapter, bAddr);
+
+ RetCode = hwi_at24_wait_ack(adapter);
+ }
+
+ return RetCode;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_serial_receive_data
+*
+* Having set up the address we want to read from, read the data.
+*
+* Outputs : Data read back.
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_receive_data)
+#endif
+
+local BYTE hwi_at24_serial_receive_data(ADAPTER * adapter)
+{
+ BYTE bData;
+ WBOOLEAN Acked;
+
+ bData = hwi_at24_serial_read_bits(adapter);
+
+ Acked = hwi_at24_dummy_wait_ack(adapter);
+
+ if (!Acked)
+ {
+ bData = 0xFF;
+ }
+
+ return bData;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_serial_read_byte
+*
+* Read a byte of data from the specified ROM address
+*
+* Outputs : Data read back.
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_serial_read_byte)
+#endif
+
+local BYTE hwi_at24_serial_read_byte(ADAPTER * adapter, BYTE bAddr)
+{
+ BYTE bData;
+
+ hwi_at24_enable_eeprom(adapter);
+
+ /*
+ * Send the serial device a dummy WRITE command
+ * that contains the address of the byte we want to
+ * read !
+ */
+
+ hwi_at24_serial_send_cmd_addr(adapter, AT24_WRITE_CMD, bAddr);
+
+ /*
+ * Send the read command.
+ */
+
+ hwi_at24_serial_send_cmd(adapter, AT24_READ_CMD);
+
+ /*
+ * Read the data.
+ */
+
+ bData = hwi_at24_serial_receive_data(adapter);
+
+ /*
+ * Deselect the EEPROM.
+ */
+
+ hwi_at24_stop_bit( adapter );
+
+ return bData;
+}
+
+
+/************************************************************************
+*
+* hwi_at24_read_a_word
+*
+* Read a word of data from the specified ROM address
+*
+* Outputs : Data read back.
+*
+************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_at24_read_a_word)
+#endif
+
+local WORD hwi_at24_read_a_word(ADAPTER * adapter, WORD word_address)
+{
+ WORD wData;
+ BYTE bLoByte;
+ BYTE bByteAddress = (BYTE) ((word_address * 2) & 0xFF);
+
+ bLoByte = hwi_at24_serial_read_byte(adapter, bByteAddress);
+
+ wData = (WORD) hwi_at24_serial_read_byte(
+ adapter,
+ (BYTE) (bByteAddress + 1));
+
+ wData <<= 8;
+ wData |= bLoByte;
+
+ return wData;
+}
+
+#endif
+
+
+/******* End of HWI_PCIT.C **************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_pcmc.c b/private/ntos/ndis/madge/driver/hwi_pcmc.c
new file mode 100644
index 000000000..f5aa76c3a
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_pcmc.c
@@ -0,0 +1,3366 @@
+/****************************************************************************
+*
+* HWI_PCMC.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* THE HARDWARE INTERFACE MODULE FOR PCMCIA CARDS
+*
+* Copyright (c) Madge Networks Ltd. 1990-1994
+*
+* COMPANY CONFIDENTIAL
+*
+****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_PCMC.C module contains the routines specific to PCMCIA cards
+* which are necessary to install an adapter, to initialize an adapter, to
+* remove an adapter and to handle interrupts on an adapter.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+#ifndef FTK_NO_PCMCIA
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| Card Services related defines and globals. Used only in this module.
+|
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|
+| #defines
+|
+---------------------------------------------------------------------------*/
+
+#define DETERMINED_BY_CARD_SERVICES 0x00FF
+
+#define MAX_PCMCIA_SOCKETS 0x08
+
+#define PCMCIA_CS_REGISTRATION_TIMEOUT 0xF0000 /* Not real time. Just a */
+ /* for loop counting so */
+ /* 0xF0000 times. */
+
+/*---------------------------------------------------------------------------
+|
+| These are hardware related defines. These are not put in ftk_pcmc.h
+| because: 1. they are only used here and not by ftk user. 2. they are
+| defined using #defines in sys_cs.h which is only included internally.
+|
+---------------------------------------------------------------------------*/
+
+/*
+ * Interrupt channels supported in form of bit mask.
+ */
+
+#define PCMCIA_AVAILABLE_IRQ_MASK \
+ \
+ (IRQ_2|IRQ_3|IRQ_5|IRQ_6|IRQ_7|IRQ_8|IRQ_10|IRQ_11|IRQ_12|IRQ_13|IRQ_14|IRQ_15)
+
+/*
+ * This is the value of IRQInfo1 used in RequestConfiguration. Note that
+ * only level triggered interupt is supported.
+ */
+
+/*
+ * User has specified an interrupt channel.
+ */
+
+#define PCMCIA_IRQINFO1_SPECIFIED IRQ_INFO1_LEVEL
+
+/*
+ * User has not specified an interrupt channel, will be allocated by PCMCIA
+ * card services.
+ */
+
+#define PCMCIA_IRQINFO1_NOT_SPECIFIED \
+ \
+ (IRQ_INFO1_LEVEL | IRQ_INFO1_INFO2_ENABLE)
+
+
+/*---------------------------------------------------------------------------
+|
+| PCMCIA client information
+|
+---------------------------------------------------------------------------*/
+
+#define PCMCIA_VENDOR_NAME "MADGE"
+#define PCMCIA_VENDOR_NAME_LEN 6
+
+ /* 1234567890123456789012345678901 */
+#define PCMCIA_CLIENT_NAME "SMART 16/4 PCMCIA RINGNODE HWI"
+#define PCMCIA_CLIENT_NAME_LEN 31
+
+#define PCMCIA_VENDOR_REVISION 0x0001
+
+#define PCMCIA_VENDOR_REVISION_DATE 0x1C2D /* 13/01/94 in dos format */
+
+struct STRUCT_MADGE_CLIENT_INFODD
+{
+ CS_CLIENT_INFO info;
+ BYTE NameString[PCMCIA_CLIENT_NAME_LEN];
+ BYTE VendorString[PCMCIA_VENDOR_NAME_LEN];
+};
+
+typedef struct STRUCT_MADGE_CLIENT_INFODD MADGE_CLIENT_INFO;
+
+#define DEFAULT_CLIENT_INFO \
+{ \
+ { \
+ 0x0000, \
+ sizeof(MADGE_CLIENT_INFO), \
+ RC_ATTR_IO_CLIENT_DEVICE_DRIVER | RC_ATTR_IO_INSERTION_SHARABLE, \
+ PCMCIA_VENDOR_REVISION, \
+ CARD_SERVICES_VERSION, \
+ PCMCIA_VENDOR_REVISION_DATE, \
+ 20, \
+ PCMCIA_CLIENT_NAME_LEN, \
+ 20+PCMCIA_CLIENT_NAME_LEN, \
+ PCMCIA_VENDOR_NAME_LEN, \
+ }, \
+ PCMCIA_CLIENT_NAME, \
+ PCMCIA_VENDOR_NAME, \
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| PCMCIA sockets record structures
+|
+---------------------------------------------------------------------------*/
+
+enum ENUM_SOCKET_STATUS
+{
+ SOCKET_NOT_INITIALIZED = 0,
+ SOCKET_READY,
+ SOCKET_IN_USE,
+};
+
+typedef enum ENUM_SOCKET_STATUS SOCKET_STATUS;
+
+struct STRUCT_PCMCIA_SOCKET_RECORD
+{
+ WORD ClientHandle;
+ WORD io_location;
+ WORD irq_number;
+ SOCKET_STATUS status;
+ ADAPTER_HANDLE adapter_handle;
+};
+
+typedef struct STRUCT_PCMCIA_SOCKET_RECORD PCMCIA_SOCKET_RECORD;
+
+
+/*---------------------------------------------------------------------------
+|
+| Things use to set up argument buffer
+|
+---------------------------------------------------------------------------*/
+
+/*
+ * Default arg buffer length.
+ */
+
+#define MAX_PCMCIA_ARG_BUFFER_LEN 100
+
+/*
+ * Arg buffer structure.
+ */
+
+/*
+ * Madge Card Services expects the string "Madge" prepended to the argument
+ * buffer.
+ */
+
+struct STRUCT_PCMCIA_ARG_BUFFER
+{
+ BYTE Madge[5];
+ BYTE Buf[MAX_PCMCIA_ARG_BUFFER_LEN];
+};
+
+typedef struct STRUCT_PCMCIA_ARG_BUFFER PCMCIA_ARG_BUFFER;
+
+/*
+ * A macro which creates a new argument buffer and initializes it.
+ */
+
+#define NEW_PCMCIA_ARG_BUFFER(Fp) \
+ \
+ PCMCIA_ARG_BUFFER _xXx_arg_buf_##Fp = {{'M','a','d','g','e'}, {0x00}}; \
+ BYTE FAR * ##Fp = (BYTE FAR *)(_xXx_arg_buf_##Fp.Buf)
+
+
+/*---------------------------------------------------------------------------
+|
+| Global variables Used by Card Services related routines
+|
+---------------------------------------------------------------------------*/
+
+/*
+ * PCMCIA Socket Record. One for each socket. Index by socket no. i.e. 0 to
+ * MAX_PCMCIA_SOCKETS-1
+ */
+
+PCMCIA_SOCKET_RECORD pcmcia_socket_table[MAX_PCMCIA_SOCKETS] =
+{
+ {0x0000, 0x0000, 0x0000, SOCKET_NOT_INITIALIZED, 0x0000},
+};
+
+WORD CardServicesVersion; /* Version of Card Services found */
+
+/*
+ * A flag set by callback to signal of registration completion
+ */
+
+WBOOLEAN RegisterClientCompleted = FALSE;
+
+/*
+ * A signature string found on Madge 16 4 PCMCIA Ringnode. Use in adapter
+ * groping.
+ */
+
+BYTE MADGE_TPLLV1_INFO[] = MADGE_TPLLV1_INFO_STRING;
+
+/*
+ * A bit mask of interrupt channel current used by active ringnode.
+ */
+
+WORD UsedIrqChannelsMask = 0x0000;
+
+/*
+ * The default client information. Reply with this for CLIENT_INFO callback.
+ */
+
+MADGE_CLIENT_INFO default_client_info = DEFAULT_CLIENT_INFO;
+
+#endif
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local WORD
+hwi_pcmcia_read_eeprom_word(
+ ADAPTER * adapter,
+ WORD word_address);
+
+local WORD
+pcmcia_c46_read_data(
+ ADAPTER * adapter);
+
+local void
+pcmcia_c46_write_bit(
+ ADAPTER * adapter,
+ WORD mask,
+ WBOOLEAN set_bit);
+
+local void
+pcmcia_c46_twitch_clock(
+ ADAPTER * adapter);
+
+#ifndef FTK_NO_PROBE
+
+local WBOOLEAN
+hwi_pcmcia_card_services_setup(
+ PROBE * resource
+ );
+
+local WORD
+hwi_pcmcia_cs_release_config(
+ WORD ClientHandle,
+ WORD Socket
+ );
+
+local WORD
+hwi_pcmcia_cs_release_io(
+ WORD ClientHandle,
+ WORD Socket,
+ WORD IoLocation
+ );
+
+local WORD
+hwi_pcmcia_cs_release_irq(
+ WORD ClientHandle,
+ WORD Socket,
+ WORD IRQChannel
+ );
+
+local WORD
+hwi_pcmcia_cs_deregister_client(
+ WORD ClientHandle
+ );
+
+local WBOOLEAN
+hwi_pcmcia_tear_down_cs(
+ PROBE resource
+ );
+
+#endif
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_pcmcia_probe_card
+* =====================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is an array of IO locations to examine for the presence
+* of an adapter. For PCMCIA adapters with should be a subset of
+* {0x0a20, 0x1a20, 0x2a20, 0x3a20}.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_pcmcia_probe_card routine is called by hwi_probe_adapter. It
+* reads the id registers to find the type of card and also reads the IRQ.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcmcia_probe_card)
+#endif
+
+export UINT
+hwi_pcmcia_probe_card(
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ )
+{
+ UINT i;
+ UINT j;
+
+ /*
+ * Check the bounds to make sure they're sensible
+ */
+
+ if(length <= 0 || number_locations <= 0)
+ {
+ return PROBE_FAILURE;
+ }
+
+ /*
+ * j is the number of adapters found.
+ */
+
+ j = 0;
+
+ for(i = 0; i < number_locations; i++)
+ {
+ /*
+ * If we've run out of PROBE structures then return.
+ */
+
+ if(j >= length)
+ {
+ return(j);
+ }
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_enable_io(valid_locations[i], PCMCIA_IO_RANGE);
+#endif
+
+ resources[j].io_location = valid_locations[i];
+
+ if ( hwi_pcmcia_card_services_setup(&resources[j]) )
+ {
+ resources[j].adapter_card_type =
+ ADAPTER_CARD_TYPE_16_4_PCMCIA;
+ resources[j].adapter_ram_size =
+ PCMCIA_RAM_SIZE;
+ resources[j].adapter_card_bus_type =
+ ADAPTER_CARD_PCMCIA_BUS_TYPE;
+ resources[j].dma_channel =
+ 0;
+ resources[j].transfer_mode =
+ PIO_DATA_TRANSFER_MODE;
+
+ /*
+ * Increment j to point at the next PROBE structure.
+ */
+
+ j++;
+
+ /*
+ * HACK!! Card Services doesn't seem to be re-entrant so quit
+ * straight away.
+ */
+
+ return j;
+ }
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_disable_io(resources->io_location, PCMCIA_IO_RANGE);
+#endif
+ }
+
+ return(j);
+}
+
+
+/****************************************************************************
+*
+* hwi_pcmcia_deprobe_card
+* =======================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE resource
+*
+* This structure is used to identify and record specific information about
+* the adapter.
+*
+* BODY :
+* ======
+*
+* The hwi_smart16_probe_card routine is called by hwi_probe_adapter. It
+* probes the adapter card for information such as DMA channel, IRQ number
+* etc. This information can then be supplied by the user when starting the
+* adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or zero if there's a
+* problem
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pcmcia_deprobe_card)
+#endif
+
+export WBOOLEAN
+hwi_pcmcia_deprobe_card(
+ PROBE resource
+ )
+{
+ WBOOLEAN success;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_enable_io(resource.io_location, PCMCIA_IO_RANGE);
+#endif
+
+ /*
+ * Release resources requested from card services and deregister.
+ */
+
+ success = hwi_pcmcia_tear_down_cs(resource);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_disable_io(resource.io_location, PCMCIA_IO_RANGE);
+#endif
+
+ return(success);
+}
+#endif
+
+/****************************************************************************
+*
+* hwi_pcmcia_install_card
+* =======================
+*
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pcmcia_install_card routine is called by hwi_install_adapter.
+* It sets up the adapter card and downloads the required code to it.
+*
+* Firstly, it checks if the I O location and interrupt channel are valid
+* Then it registers with PCMCIA card services, and checks if the required
+* Madge PCMCIA ringnode exists. If so it requests interrrupt and I
+* resources from PCMCIA card services, sets up and checks numerous
+* on-board registers for correct operation. Burnt in address and default
+* ring speed are read from EEPROM.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+void hlpr_unmap_PCMCIA_irq(WORD irq);
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcmcia_install_card)
+#endif
+
+export WBOOLEAN
+hwi_pcmcia_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ WORD control_1 = adapter->io_location +
+ PCMCIA_CONTROL_REGISTER_1;
+ WORD control_2 = adapter->io_location +
+ PCMCIA_CONTROL_REGISTER_2;
+ WORD eeprom_word;
+ WORD ring_speed;
+ WORD sif_base;
+ BYTE tmp_byte;
+
+#ifdef PCMCIA_POINT_ENABLE
+ /*
+ * Make sure we don't lose any interrupts.
+ */
+
+ adapter->drop_int = FALSE;
+
+ /*
+ * Enable the card.
+ */
+
+ if(!sys_pcmcia_point_enable(adapter))
+ {
+ /*
+ * Error record already filled in.
+ */
+
+ return(FALSE);
+ }
+#endif
+
+ /*
+ * We don't do any validation on the user supplied adapter details
+ * since the user has to obtain the values from card services in the
+ * first place! (Or did they?)
+ */
+
+ /*
+ * Save IO location of the SIF registers.
+ */
+
+ sif_base = adapter->io_location + PCMCIA_FIRST_SIF_REGISTER;
+
+ adapter->sif_dat = sif_base + EAGLE_SIFDAT;
+ adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC;
+ adapter->sif_adr = sif_base + EAGLE_SIFADR;
+ adapter->sif_int = sif_base + EAGLE_SIFINT;
+ adapter->sif_acl = sif_base + PCMCIA_EAGLE_SIFACL;
+ adapter->sif_adr2 = sif_base + PCMCIA_EAGLE_SIFADR_2;
+ adapter->sif_adx = sif_base + PCMCIA_EAGLE_SIFADX;
+ adapter->sif_dmalen = sif_base + PCMCIA_EAGLE_DMALEN;
+
+ adapter->io_range = PCMCIA_IO_RANGE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Can be assumed for a PCMCIA adapter.
+ */
+
+ adapter->adapter_card_type = ADAPTER_CARD_TYPE_16_4_PCMCIA;
+
+#if 0
+
+ adapter->adapter_card_revision = 0x0000;
+ adapter->adapter_ram_size = PCMCIA_RAM_SIZE;
+
+#endif
+
+ /*
+ * Interrupts are always level triggered.
+ */
+
+ adapter->edge_triggered_ints = FALSE;
+
+ /*
+ * To get the software handeshake to work properly on PIO
+ * we need to set the MC_AND_ISACP_USE_PIO bit in the
+ * mc32_config byte.
+ */
+
+ adapter->mc32_config = MC_AND_ISACP_USE_PIO;
+
+ /*
+ * Read node address from serial EEPROM.
+ */
+
+ eeprom_word = hwi_pcmcia_read_eeprom_word(
+ adapter,
+ EEPROM_ADDR_NODEADDR1);
+ adapter->permanent_address.byte[0] = (BYTE)(eeprom_word & 0x00FF);
+ adapter->permanent_address.byte[1] = (BYTE)(eeprom_word >> 8);
+
+ eeprom_word = hwi_pcmcia_read_eeprom_word(
+ adapter,
+ EEPROM_ADDR_NODEADDR2);
+ adapter->permanent_address.byte[2] = (BYTE)(eeprom_word & 0x00FF);
+ adapter->permanent_address.byte[3] = (BYTE)(eeprom_word >> 8);
+
+ eeprom_word = hwi_pcmcia_read_eeprom_word(
+ adapter,
+ EEPROM_ADDR_NODEADDR3);
+ adapter->permanent_address.byte[4] = (BYTE)(eeprom_word & 0x00FF);
+ adapter->permanent_address.byte[5] = (BYTE)(eeprom_word >> 8);
+
+ /*
+ * Read ring speed from serial EEPROM.
+ */
+
+ ring_speed = hwi_pcmcia_read_eeprom_word(
+ adapter,
+ EEPROM_ADDR_RINGSPEED);
+
+ /*
+ * Read RAM size from serial EEPROM. Use 512k default if nothing
+ * specified.
+ */
+
+ adapter->adapter_ram_size = hwi_pcmcia_read_eeprom_word(
+ adapter,
+ EEPROM_ADDR_RAMSIZE
+ ) * 128;
+
+ if (adapter->adapter_ram_size == 0)
+ {
+ adapter->adapter_ram_size = PCMCIA_RAM_SIZE;
+ }
+
+ /*
+ * Read hardware revision from serial EEPROM.
+ */
+
+ adapter->adapter_card_revision = hwi_pcmcia_read_eeprom_word(
+ adapter,
+ EEPROM_ADDR_REVISION);
+
+ adapter->use_32bit_pio = FALSE;
+
+#ifdef FTK_PCMCIA_32BIT_PIO
+
+ if (adapter->adapter_card_revision != 0)
+ {
+ adapter->use_32bit_pio = TRUE;
+ }
+
+#endif
+
+ /*
+ * Set all the EEPROM related bits in control register 2 to zero.
+ */
+
+ tmp_byte = 0x00;
+
+ tmp_byte &= ~( PCMCIA_CTRL2_E2DO | PCMCIA_CTRL2_E2DI |
+ PCMCIA_CTRL2_E2CS | PCMCIA_CTRL2_E2SK |
+ PCMCIA_CTRL2_FLSHWREN );
+
+ /*
+ * Set SIF clock frequency to 16MHz.
+ */
+
+ tmp_byte |= PCMCIA_CTRL2_SBCKSEL_16;
+
+ /*
+ * Ring Speed is read from EEPROM, now program it to the front
+ * end chip.
+ */
+
+ if (adapter->set_ring_speed == 16)
+ {
+ tmp_byte |= ( PCMCIA_CTRL2_4N16 & PCMCIA_CTRL2_4N16_16 );
+ }
+ else if (adapter->set_ring_speed == 4)
+ {
+ tmp_byte |= ( PCMCIA_CTRL2_4N16 & PCMCIA_CTRL2_4N16_4 );
+ }
+ else if ( ring_speed == EEPROM_RINGSPEED_4 )
+ {
+ tmp_byte |= ( PCMCIA_CTRL2_4N16 & PCMCIA_CTRL2_4N16_4 );
+ }
+ else
+ {
+ tmp_byte |= ( PCMCIA_CTRL2_4N16 & PCMCIA_CTRL2_4N16_16 );
+ }
+
+ /*
+ * Write all these setting to control register 2 all in one go.
+ */
+
+ sys_outsb(adapter->adapter_handle, control_2, tmp_byte);
+
+
+ /*
+ * Bring EAGLE out of reset.
+ */
+
+ macro_setb_bit(
+ adapter->adapter_handle,
+ control_1,
+ PCMCIA_CTRL1_SRESET);
+
+ /*
+ * Halt EAGLE, no need to page in extended SIF registers for pcmcia.
+ */
+
+ hwi_halt_eagle(adapter);
+
+ /*
+ * Download code to adapter. View download image as a sequence of
+ * download records.
+ * Pass address of routine to set up DIO addresses on pcmcia cards. If
+ * routine fails return failure (error record already filled in).
+ */
+
+ if (!hwi_download_code(
+ adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_pcmcia_set_dio_address))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Start EAGLE, no need page in extended SIF registers for pcmcia cards.
+ */
+
+ hwi_start_eagle(adapter);
+
+ /*
+ * Wait for a valid bring up code, may wait 3 seconds. If routine fails
+ * return failure (error record already filled in).
+ */
+
+
+ if (!hwi_get_bring_up_code(adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Set DIO address to point to EAGLE DATA page 0x10000L.
+ */
+
+ hwi_pcmcia_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * Set maximum frame size from the ring speed.
+ */
+
+ adapter->max_frame_size = hwi_get_max_frame_size(adapter);
+
+ /*
+ * Get the ring speed.
+ */
+
+ adapter->ring_speed = hwi_get_ring_speed(adapter);
+
+ /*
+ * If not in polling mode then set up interrupts interrupts_on field
+ * is used when disabling interrupts for adapter.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on = sys_enable_irq_channel(
+ adapter->adapter_handle,
+ adapter->interrupt_number);
+
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+
+ /*
+ * Enable interrupts at adapter GCR1 SINTREN.
+ */
+
+ macro_setb_bit(
+ adapter->adapter_handle,
+ control_1,
+ PCMCIA_CTRL1_SINTREN);
+
+ /*
+ * PCMCIA adapters do not have DMA channel to setup.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* hwi_pcmcia_interrupt_handler
+* ============================
+*
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ============================================
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* The adapter handle for the adapter so it can later be passed to the user
+* supplied user_receive_frame or user_completed_srb routine.
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pcmcia_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF or a PIO
+* data transfer. Note it could in fact be the case that no interrupt has
+* occured on the particular adapter being checked.
+*
+* On SIF interrupts, the interrupt is acknowledged and cleared. The value
+* in the SIF interrupt register is recorded in order to pass it to the
+* driver_interrupt_entry routine (along with the adapter details).
+*
+* On PIO interrupts, the length, direction and physical address of the
+* transfer is determined. A system provided routine is called to do the
+* data transfer itself. Note the EAGLE thinks it is doing a DMA transfer.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_pcmcia_interrupt_handler)
+#endif
+
+#ifndef WIN_BOOK_FIX
+
+/*---------------------------------------------------------------------------
+Ý This is the ordinary, none WinBook, interrupt handler.
+Ý--------------------------------------------------------------------------*/
+
+export void
+hwi_pcmcia_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location +
+ PCMCIA_CONTROL_REGISTER_1;
+ WORD control_2 = adapter->io_location +
+ PCMCIA_CONTROL_REGISTER_2;
+ WORD pio_location = adapter->io_location +
+ PCMCIA_PIO_IO_LOC;
+ WORD sifint_register = adapter->sif_int;
+ WORD sifadr = adapter->sif_adr;
+ WORD sifdat = adapter->sif_dat;
+ WORD sifacl = adapter->sif_acl;
+ WORD sifint_value;
+ WORD sifint_tmp;
+ BYTE FAR * pio_address;
+ WORD pio_len_bytes;
+ WORD pio_from_adapter;
+
+ WORD saved_sifadr;
+ WORD dummy;
+
+ DWORD dma_high_word;
+ WORD dma_low_word;
+
+ WORD temp_word;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter);
+#endif
+
+ /*
+ * Check for SIF interrupt or PIO interrupt.
+ */
+
+ if ((sys_insw(adapter_handle, sifint_register) &
+ FASTMAC_SIFINT_IRQ_DRIVER) != 0)
+ {
+ /*
+ * A SIF interrupt has occurred. Thsi could be an SRB free,
+ * an adapter check or a received frame interrupt.
+ */
+
+ /*
+ * Clear SIF interrupt enable bit in control register.
+ */
+
+ macro_clearb_bit(adapter_handle, control_1, PCMCIA_CTRL1_SINTREN);
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+ */
+
+ /*
+ * WARNING: Do NOT reorder the clearing of the SIFINT register with
+ * the reading of it. If SIFINT is cleared after reading it, any
+ * interrupts raised after reading it will be lost. Admittedly
+ * this is a small time frame, but it is important.
+ */
+
+ sys_outsw(adapter_handle, sifint_register, 0);
+
+ /*
+ * Record the EAGLE SIF interrupt register value.
+ */
+
+ /*
+ * WARNING: Continue to read the SIFINT register until it is stable
+ * because of a potential problem involving the host reading the
+ * register after the adapter has written the low byte of it, but
+ * before it has written the high byte. Failure to wait for the
+ * SIFINT register to settle can cause spurious interrupts.
+ */
+
+ sifint_value = sys_insw(adapter_handle, sifint_register);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(adapter_handle, sifint_register);
+ }
+ while (sifint_tmp != sifint_value);
+
+ /*
+ * Acknowledge clear interrupt at interrupt controller.
+ */
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number
+ );
+#endif
+
+ /*
+ * Set interrupt enable bit to regenerate any lost interrupts.
+ */
+
+ macro_setb_bit(adapter_handle, control_1, PCMCIA_CTRL1_SINTREN);
+
+ /*
+ * It is possible that the PCMCIA adapter may have been removed. In
+ * which case we would expect to get 0xffff from an IO location
+ * occupied by the adapter. We will check the value of SIFADR since
+ * this should never be 0xffff.
+ */
+
+ if (sys_insw(adapter_handle, sifadr) == 0xffff)
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+
+#ifdef FTK_ADAPTER_REMOVED_NOTIFY
+ user_adapter_removed(adapter_handle);
+#endif
+ return;
+ }
+
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+
+ driver_interrupt_entry(adapter_handle, adapter, sifint_value);
+
+ }
+ else if ((sys_insb(adapter_handle, control_1) & PCMCIA_CTRL1_SHRQ) != 0)
+ {
+ /*
+ * A PIO interrupt has occurred. Transfer data to/from adapter.
+ */
+
+ saved_sifadr = sys_insw(adapter_handle, sifadr);
+
+ /*
+ * Read the physical address for the PIO through DIO space from the
+ * SIF registers. Because the SIF thinks that it is doing real DMA,
+ * the SDMAADR SDMAADX registers cannot be paged in, so they must
+ * be read from their memory mapped locations in Eagle memory.
+ */
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_EXT_DMA_ADDR);
+ dma_high_word = (DWORD)sys_insw(adapter_handle, sifdat);
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_DMA_ADDR);
+ dma_low_word = sys_insw(adapter_handle, sifdat);
+
+ pio_address = (BYTE FAR *) ((dma_high_word << 16) |
+ ((DWORD) dma_low_word));
+
+ /*
+ * Read the PIO length from SIF register.
+ */
+
+ pio_len_bytes = sys_insw(adapter_handle, adapter->sif_dmalen);
+
+ /*
+ * Determine what direction the data transfer is to take place in.
+ */
+
+ pio_from_adapter = sys_insw(
+ adapter_handle,
+ sifacl) & EAGLE_SIFACL_SWDDIR;
+
+
+ /*
+ * It is possible that the PCMCIA adapter may have been removed. In
+ * which case we would expect to get 0xffff from an IO location
+ * occupied by the adapter. We will check the value of pio_len_bytes
+ * since this should never be 0xffff. We do this test here as we have
+ * read what we think are the DMA location and length. The following
+ * code may DMA rubbish if the adapter goes away after this test
+ * but at least we know it will happen to/from a valid host buffer.
+ */
+
+ if (pio_len_bytes == 0xffff)
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number
+ );
+#endif
+
+#ifdef FTK_ADAPTER_REMOVED_NOTIFY
+ user_adapter_removed(adapter_handle);
+#endif
+
+ return;
+ }
+
+ /*
+ * We need to use software handshaking across the PIO.
+ * Start by writing zero to a magic location on the adapter.
+ */
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(adapter_handle, sifdat, 0);
+
+ /*
+ * Start what the SIF thinks is a DMA but is PIO instead. This
+ * involves clearing the SINTREN bit and setting SHLDA bit on
+ * control register 1. Note that we have to keep SRESET bit set
+ * otherwise we will reset the EAGLE.
+ */
+
+ sys_outsb(
+ adapter_handle,
+ control_1,
+ PCMCIA_CTRL1_SHLDA | PCMCIA_CTRL1_SRESET);
+
+ /*
+ * Do the actual data transfer.
+ */
+
+ /*
+ * Note that Fastmac only copies whole WORDs to DWORD boundaries
+ * FastmacPlus, however, can transfer any length to any address.
+ */
+
+ if (pio_from_adapter)
+ {
+ /*
+ *
+ *
+ * Transfer into host memory from adapter.
+ *
+ *
+ */
+
+ /*
+ * Deal with an odd leading byte.
+ */
+
+ if (((card_t) pio_address & 0x01) != 0)
+ {
+ /*
+ * Read a WORD, the top byte is data.
+ */
+
+ temp_word = sys_insw(adapter_handle, pio_location);
+ pio_len_bytes--;
+ *(pio_address++) = (BYTE) (temp_word >> 8);
+ }
+
+ /*
+ * We might be able to do 32 bit PIO.
+ */
+
+ if (adapter->use_32bit_pio)
+ {
+ /*
+ * Deal with an odd leading word.
+ */
+
+ if (((card_t) pio_address & 0x02) != 0 && pio_len_bytes > 0)
+ {
+ /*
+ * There could be one or two bytes of data.
+ */
+
+ if (pio_len_bytes == 1)
+ {
+ pio_len_bytes--;
+ *(pio_address) =
+ sys_insb(adapter_handle, pio_location);
+ }
+ else
+ {
+ pio_len_bytes -= 2;
+ *((WORD *) pio_address) =
+ sys_insw(adapter_handle, pio_location);
+ pio_address += 2;
+ }
+ }
+
+ /*
+ * Deal with the bulk of the dwords.
+ */
+
+ sys_rep_insd(
+ adapter_handle,
+ pio_location,
+ pio_address,
+ (WORD) (pio_len_bytes >> 2)
+ );
+
+ pio_address += (pio_len_bytes & 0xfffc);
+
+ /*
+ * Deal with a trailing word.
+ */
+
+ if ((pio_len_bytes & 0x02) != 0)
+ {
+ /*
+ * Read a word.
+ */
+
+ *((WORD *) pio_address) =
+ sys_insw(adapter_handle, pio_location);
+ pio_address += 2;
+ }
+ }
+
+ /*
+ * Otherwise use 16 bit PIO.
+ */
+
+ else
+ {
+ /*
+ * Transfer the bulk of the data.
+ */
+
+ sys_rep_insw(
+ adapter_handle,
+ pio_location,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ pio_address += (pio_len_bytes & 0xfffe);
+
+ }
+
+ /*
+ * Finally transfer any trailing byte.
+ */
+
+ if ((pio_len_bytes & 0x01) != 0)
+ {
+ *(pio_address) = sys_insb(adapter_handle, pio_location);
+ }
+ }
+
+ else
+ {
+ /*
+ *
+ *
+ * Transfer into adapter memory from the host.
+ *
+ *
+ */
+
+ /*
+ * Deal with a leading odd byte.
+ */
+
+ if (((card_t) pio_address & 0x01) != 0)
+ {
+ /*
+ * Write a WORD with data in top byte.
+ */
+
+ temp_word = ((WORD) *(pio_address++)) << 8;
+ pio_len_bytes--;
+ sys_outsw(adapter_handle, pio_location, temp_word);
+ }
+
+ /*
+ * We might be able to do 32 bit PIO.
+ */
+
+ if (adapter->use_32bit_pio)
+ {
+ /*
+ * Deal with an odd leading word.
+ */
+
+ if (((card_t) pio_address & 0x02) != 0 && pio_len_bytes > 0)
+ {
+ /*
+ * There could be one or two bytes of data. If there
+ * is only one byte it goes in the high word.
+ */
+
+ if (pio_len_bytes == 1)
+ {
+ pio_len_bytes--;
+ sys_outsb(
+ adapter_handle,
+ pio_location,
+ *(pio_address)
+ );
+ }
+ else
+ {
+ pio_len_bytes -= 2;
+ sys_outsw(
+ adapter_handle,
+ pio_location,
+ *((WORD *) pio_address)
+ );
+ pio_address += 2;
+ }
+ }
+
+ /*
+ * Deal with the bulk of the dwords.
+ */
+
+ sys_rep_outsd(
+ adapter_handle,
+ pio_location,
+ pio_address,
+ (WORD) (pio_len_bytes >> 2)
+ );
+
+ pio_address += (pio_len_bytes & 0xfffc);
+
+ /*
+ * Deal with a trailing word.
+ */
+
+ if ((pio_len_bytes & 0x02) != 0)
+ {
+ /*
+ * Write a word.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ pio_location,
+ *((WORD *) pio_address)
+ );
+ pio_address += 2;
+ }
+ }
+
+ /*
+ * Otherwise use 16 bit PIO.
+ */
+
+ else
+ {
+ sys_rep_outsw(
+ adapter_handle,
+ pio_location,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ pio_address += (pio_len_bytes & 0xfffe);
+ }
+
+ /*
+ * Deal with a trailing byte.
+ */
+
+ if ((pio_len_bytes & 0x01) != 0)
+ {
+ sys_outsb(
+ adapter_handle,
+ pio_location,
+ *(pio_address)
+ );
+ }
+ }
+
+ /*
+ * Transfer done. We have to tell the hardware we have finished.
+ * This involves clearing the SHLDA bit to signal the end of PIO.
+ * Note that the SRESET bit is kept set otherwise we will reset the
+ * EAGLE.
+ */
+
+ sys_outsb(
+ adapter_handle,
+ control_1,
+ PCMCIA_CTRL1_SRESET);
+
+
+ /*
+ * Poll until SHLAD clears.
+ */
+
+ /*
+ * Now wait until SHLDA clears. This is needed since while SHLDA is
+ * set the EAGLE still believes it is in bus master mode; and any
+ * attempt to access the SIF will fail.
+ */
+
+ do
+ {
+ dummy = sys_insb(adapter_handle, control_1);
+
+ /*
+ * It is possible that the adapter was removed during the
+ * transfer. If it was we could spin forever. We will test
+ * the value read from control_1, if it is 0xff then we
+ * assume that the adapter has been removed.
+ */
+
+ if (dummy == 0xff)
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+#endif
+
+#ifdef FTK_ADAPTER_REMOVED_NOTIFY
+ user_adapter_removed(adapter_handle);
+#endif
+
+ return;
+ }
+ }
+ while ((dummy & PCMCIA_CTRL1_SHLDA) != 0);
+
+ /*
+ * Finish off the software handshake process that we started at the
+ * beginning. This time we have to write 0xFFFF to
+ * DIO_LOCATION_DMA_CONTROL
+
+ * Do a read first - otherwise the write might fail
+ */
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ dummy = sys_insw(adapter_handle, sifdat);
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(adapter_handle, sifdat, 0xFFFF);
+
+ sys_outsw(adapter_handle, sifadr, saved_sifadr);
+
+ /*
+ * acknowledge/clear interrupt at interrupt controller.
+ */
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+#endif
+
+ /*
+ * Set interrupt enable bit to regenerate any lost interrupts.
+ */
+
+ macro_setb_bit(adapter_handle, control_1, PCMCIA_CTRL1_SINTREN);
+ }
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+}
+
+#else
+
+/*---------------------------------------------------------------------------
+Ý This is the special interrupt handler for WinBooks.
+Ý On a WinBook there is a 120us window after an interrupt has been
+Ý signalled before the interrupt line floats up to a high enough
+Ý level that another interrupt can be generated. To avoid loosing
+Ý an interrupt in this window we must hold either not allow another
+Ý interrupt to be generated in the windows or poll the adapter for
+Ý interrupt causes for the duration of the window. Since on some
+Ý OSs we cannot spend very long in our interrupt handler we cannot
+Ý just poll (which is the fastest scheme) so we use a mixture. We
+Ý use the PIO handshake to delay a second PIO interrupt and poll
+Ý for SIF interrupts - which are much rarer.
+---------------------------------------------------------------------------*/
+
+export void
+hwi_pcmcia_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location +
+ PCMCIA_CONTROL_REGISTER_1;
+ WORD control_2 = adapter->io_location +
+ PCMCIA_CONTROL_REGISTER_2;
+ WORD pio_location = adapter->io_location +
+ PCMCIA_PIO_IO_LOC;
+ WORD sifint_register = adapter->sif_int;
+ WORD sifadr = adapter->sif_adr;
+ WORD sifdat = adapter->sif_dat;
+ WORD sifacl = adapter->sif_acl;
+ WORD sifint_value;
+ WORD sifint_tmp;
+ BYTE FAR * pio_address;
+ WORD pio_len_bytes;
+ WORD pio_from_adapter;
+
+ WORD saved_sifadr;
+ WORD dummy;
+
+ DWORD dma_high_word;
+ WORD dma_low_word;
+
+ WORD temp_word;
+ UINT i;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io( adapter);
+#endif
+
+ /*
+ * Clear SIF interrupt enable bit in control register.
+ */
+
+ macro_clearb_bit(adapter_handle, control_1, PCMCIA_CTRL1_SINTREN);
+
+ /*
+ * Check for SIF interrupt or PIO interrupt. We do this 80 times
+ * as this has been empirically shown to result in a delay of
+ * 120us since we cleared SINTREN above.
+ */
+
+ for (i = 0; i < 80; i++)
+ {
+ if ((sys_insw(adapter_handle, sifint_register) &
+ FASTMAC_SIFINT_IRQ_DRIVER) != 0)
+ {
+ /*
+ * A SIF interrupt has occurred. This could be an SRB free,
+ * an adapter check or a received frame interrupt.
+ */
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+ */
+
+ /*
+ * WARNING: Do NOT reorder the clearing of the SIFINT register with
+ * the reading of it. If SIFINT is cleared after reading it, any
+ * interrupts raised after reading it will be lost. Admittedly
+ * this is a small time frame, but it is important.
+ */
+
+ sys_outsw(adapter_handle, sifint_register, 0);
+
+ /*
+ * Record the EAGLE SIF interrupt register value.
+ */
+
+ /*
+ * WARNING: Continue to read the SIFINT register until it is stable
+ * because of a potential problem involving the host reading the
+ * register after the adapter has written the low byte of it, but
+ * before it has written the high byte. Failure to wait for the
+ * SIFINT register to settle can cause spurious interrupts.
+ */
+
+ sifint_value = sys_insw(adapter_handle, sifint_register);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(adapter_handle, sifint_register);
+ }
+ while (sifint_tmp != sifint_value);
+
+ /*
+ * It is possible that the PCMCIA adapter may have been removed. In
+ * which case we would expect to get 0xffff from an IO location
+ * occupied by the adapter. We will check the value of SIFADR since
+ * this should never be 0xffff.
+ */
+
+ if (sys_insw(adapter_handle, sifadr) == 0xffff)
+ {
+ #ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+ #endif
+
+ #ifdef FTK_ADAPTER_REMOVED_NOTIFY
+ user_adapter_removed(adapter_handle);
+ #endif
+ return;
+ }
+
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+
+ driver_interrupt_entry(adapter_handle, adapter, sifint_value);
+ }
+ else if ((sys_insb(adapter_handle, control_1) & PCMCIA_CTRL1_SHRQ) != 0)
+ {
+ /*
+ * A PIO interrupt has occurred. Transfer data to/from adapter.
+ */
+
+ saved_sifadr = sys_insw(adapter_handle, sifadr);
+
+ /*
+ * Read the physical address for the PIO through DIO space from the
+ * SIF registers. Because the SIF thinks that it is doing real DMA,
+ * the SDMAADR SDMAADX registers cannot be paged in, so they must
+ * be read from their memory mapped locations in Eagle memory.
+ */
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_EXT_DMA_ADDR);
+ dma_high_word = (DWORD)sys_insw(adapter_handle, sifdat);
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_DMA_ADDR);
+ dma_low_word = sys_insw(adapter_handle, sifdat);
+
+ pio_address = (BYTE FAR *) ((dma_high_word << 16) |
+ ((DWORD) dma_low_word));
+
+ /*
+ * Read the PIO length from SIF register.
+ */
+
+ pio_len_bytes = sys_insw(adapter_handle, adapter->sif_dmalen);
+
+ /*
+ * Determine what direction the data transfer is to take place in.
+ */
+
+ pio_from_adapter = sys_insw(
+ adapter_handle,
+ sifacl) & EAGLE_SIFACL_SWDDIR;
+
+
+ /*
+ * It is possible that the PCMCIA adapter may have been removed. In
+ * which case we would expect to get 0xffff from an IO location
+ * occupied by the adapter. We will check the value of pio_len_bytes
+ * since this should never be 0xffff. We do this test here as we have
+ * read what we think are the DMA location and length. The following
+ * code may DMA rubbish if the adapter goes away after this test
+ * but at least we know it will happen to/from a valid host buffer.
+ */
+
+ if (pio_len_bytes == 0xffff)
+ {
+ #ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+ #endif
+ #ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number
+ );
+ #endif
+
+ #ifdef FTK_ADAPTER_REMOVED_NOTIFY
+ user_adapter_removed(adapter_handle);
+ #endif
+
+ return;
+ }
+
+ /*
+ * We need to use software handshaking across the PIO.
+ * Start by writing zero to a magic location on the adapter.
+ */
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(adapter_handle, sifdat, 0);
+
+ /*
+ * Start what the SIF thinks is a DMA but is PIO instead. This
+ * involves clearing the SINTREN bit and setting SHLDA bit on
+ * control register 1. Note that we have to keep SRESET bit set
+ * otherwise we will reset the EAGLE.
+ */
+
+ macro_setb_bit(adapter_handle, control_1, PCMCIA_CTRL1_SHLDA);
+
+ /*
+ * Do the actual data transfer.
+ */
+
+ /*
+ * Note that Fastmac only copies whole WORDs to DWORD boundaries
+ * FastmacPlus, however, can transfer any length to any address.
+ */
+
+ if (pio_from_adapter)
+ {
+ /*
+ *
+ *
+ * Transfer into host memory from adapter.
+ *
+ *
+ */
+
+ /*
+ * Deal with an odd leading byte.
+ */
+
+ if (((card_t) pio_address & 0x01) != 0)
+ {
+ /*
+ * Read a WORD, the top byte is data.
+ */
+
+ temp_word = sys_insw(adapter_handle, pio_location);
+ pio_len_bytes--;
+ *(pio_address++) = (BYTE) (temp_word >> 8);
+ }
+
+ /*
+ * We might be able to do 32 bit PIO.
+ */
+
+ if (adapter->use_32bit_pio)
+ {
+ /*
+ * Deal with an odd leading word.
+ */
+
+ if (((card_t) pio_address & 0x02) != 0 && pio_len_bytes > 0)
+ {
+ /*
+ * There could be one or two bytes of data.
+ */
+
+ if (pio_len_bytes == 1)
+ {
+ pio_len_bytes--;
+ *(pio_address) =
+ sys_insb(adapter_handle, pio_location);
+ }
+ else
+ {
+ pio_len_bytes -= 2;
+ *((WORD *) pio_address) =
+ sys_insw(adapter_handle, pio_location);
+ pio_address += 2;
+ }
+ }
+
+ /*
+ * Deal with the bulk of the dwords.
+ */
+
+ sys_rep_insd(
+ adapter_handle,
+ pio_location,
+ pio_address,
+ (WORD) (pio_len_bytes >> 2)
+ );
+
+ pio_address += (pio_len_bytes & 0xfffc);
+
+ /*
+ * Deal with a trailing word.
+ */
+
+ if ((pio_len_bytes & 0x02) != 0)
+ {
+ /*
+ * Read a word.
+ */
+
+ *((WORD *) pio_address) =
+ sys_insw(adapter_handle, pio_location);
+ pio_address += 2;
+ }
+ }
+
+ /*
+ * Otherwise use 16 bit PIO.
+ */
+
+ else
+ {
+ /*
+ * Transfer the bulk of the data.
+ */
+
+ sys_rep_insw(
+ adapter_handle,
+ pio_location,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ pio_address += (pio_len_bytes & 0xfffe);
+
+ }
+
+ /*
+ * Finally transfer any trailing byte.
+ */
+
+ if ((pio_len_bytes & 0x01) != 0)
+ {
+ *(pio_address) = sys_insb(adapter_handle, pio_location);
+ }
+ }
+
+ else
+ {
+ /*
+ *
+ *
+ * Transfer into adapter memory from the host.
+ *
+ *
+ */
+
+ /*
+ * Deal with a leading odd byte.
+ */
+
+ if (((card_t) pio_address & 0x01) != 0)
+ {
+ /*
+ * Write a WORD with data in top byte.
+ */
+
+ temp_word = ((WORD) *(pio_address++)) << 8;
+ pio_len_bytes--;
+ sys_outsw(adapter_handle, pio_location, temp_word);
+ }
+
+ /*
+ * We might be able to do 32 bit PIO.
+ */
+
+ if (adapter->use_32bit_pio)
+ {
+ /*
+ * Deal with an odd leading word.
+ */
+
+ if (((card_t) pio_address & 0x02) != 0 && pio_len_bytes > 0)
+ {
+ /*
+ * There could be one or two bytes of data. If there
+ * is only one byte it goes in the high word.
+ */
+
+ if (pio_len_bytes == 1)
+ {
+ pio_len_bytes--;
+ sys_outsb(
+ adapter_handle,
+ pio_location,
+ *(pio_address)
+ );
+ }
+ else
+ {
+ pio_len_bytes -= 2;
+ sys_outsw(
+ adapter_handle,
+ pio_location,
+ *((WORD *) pio_address)
+ );
+ pio_address += 2;
+ }
+ }
+
+ /*
+ * Deal with the bulk of the dwords.
+ */
+
+ sys_rep_outsd(
+ adapter_handle,
+ pio_location,
+ pio_address,
+ (WORD) (pio_len_bytes >> 2)
+ );
+
+ pio_address += (pio_len_bytes & 0xfffc);
+
+ /*
+ * Deal with a trailing word.
+ */
+
+ if ((pio_len_bytes & 0x02) != 0)
+ {
+ /*
+ * Write a word.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ pio_location,
+ *((WORD *) pio_address)
+ );
+ pio_address += 2;
+ }
+ }
+
+ /*
+ * Otherwise use 16 bit PIO.
+ */
+
+ else
+ {
+ sys_rep_outsw(
+ adapter_handle,
+ pio_location,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ pio_address += (pio_len_bytes & 0xfffe);
+ }
+
+ /*
+ * Deal with a trailing byte.
+ */
+
+ if ((pio_len_bytes & 0x01) != 0)
+ {
+ sys_outsb(
+ adapter_handle,
+ pio_location,
+ *(pio_address)
+ );
+ }
+ }
+
+ /*
+ * Transfer done. We have to tell the hardware we have finished.
+ * This involves clearing the SHLDA bit to signal the end of PIO.
+ * Note that the SRESET bit is kept set otherwise we will reset the
+ * EAGLE.
+ */
+
+ macro_clearb_bit(adapter_handle, control_1, PCMCIA_CTRL1_SHLDA);
+
+ /*
+ * Poll until SHLDA clears.
+ */
+
+ /*
+ * Now wait until SHLDA clears. This is needed since while SHLDA is
+ * set the EAGLE still believes it is in bus master mode; and any
+ * attempt to access the SIF will fail.
+ */
+
+ do
+ {
+ dummy = sys_insb(adapter_handle, control_1);
+
+ /*
+ * It is possible that the adapter was removed during the
+ * transfer. If it was we could spin forever. We will test
+ * the value read from control_1, if it is 0xff then we
+ * assume that the adapter has been removed.
+ */
+
+ if (dummy == 0xff)
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+#endif
+
+#ifdef FTK_ADAPTER_REMOVED_NOTIFY
+ user_adapter_removed(adapter_handle);
+#endif
+
+ return;
+ }
+ }
+ while ((dummy & PCMCIA_CTRL1_SHLDA) != 0);
+
+ /*
+ * We don't clear the handshake here to stop another
+ * PIO interrupt being generated for at least 120us
+ */
+ }
+ }
+
+
+ /*
+ * Finish off the software handshake process that we started at the
+ * beginning. This time we have to write 0xFFFF to
+ * DIO_LOCATION_DMA_CONTROL
+ *
+ * Do a read first - otherwise the write might fail
+ */
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ dummy = sys_insw(adapter_handle, sifdat);
+
+ sys_outsw(adapter_handle, sifadr, DIO_LOCATION_DMA_CONTROL);
+ sys_outsw(adapter_handle, sifdat, 0xFFFF);
+
+ sys_outsw(adapter_handle, sifadr, saved_sifadr);
+
+ /*
+ * acknowledge/clear interrupt at interrupt controller.
+ */
+
+#ifndef FTK_NO_CLEAR_IRQ
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+#endif
+
+ /*
+ * Set interrupt enable bit to regenerate any lost interrupts.
+ */
+
+ macro_setb_bit(adapter_handle, control_1, PCMCIA_CTRL1_SINTREN);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+#endif
+
+
+/****************************************************************************
+*
+* hwi_pcmcia_remove_card
+* ======================
+*
+*
+* PARAMETERS (passed by hwi_remove_adapter) :
+* ===========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pcmcia_remove_card routine is called by hwi_remove_adapter. It
+* disables interrupts if they are being used. It also resets the adapter.
+* Note there is no need to explicitly disable DMA channels.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pcmcia_remove_card)
+#endif
+
+export void
+hwi_pcmcia_remove_card(
+ ADAPTER * adapter
+ )
+{
+ WORD sif_acontrol = adapter->sif_acl;
+ WORD control_1 = adapter->io_location +
+ PCMCIA_CONTROL_REGISTER_1;
+
+ /*
+ * Disable interrupts. Only need to do this if interrupts successfully
+ * enabled.
+ * Interrupts must be disabled at adapter before unpatching interrupts.
+ * Even in polling mode we must turn off interrupts at adapter.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ if (adapter->interrupts_on)
+ {
+ macro_clearw_bit(
+ adapter->adapter_handle,
+ sif_acontrol,
+ EAGLE_SIFACL_SINTEN);
+
+#ifdef PCMCIA_POINT_ENABLE
+ /* Deconfigure and power down the card before disabling host
+ * interrupt handler in case of spurious interrupts from the
+ * PCMCIA controller.
+ */
+
+ /*
+ * Warn our handler of the likelihood of a spurious interrupt.
+ */
+
+ adapter->drop_int = TRUE;
+ sys_pcmcia_point_disable(adapter);
+#endif
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(
+ adapter->adapter_handle,
+ adapter->interrupt_number);
+ }
+
+ adapter->interrupts_on = FALSE;
+ }
+
+ /*
+ * Perform adapter reset, and set EAGLE_SIFACL_ARESET high.
+ */
+
+ macro_clearb_bit(
+ adapter->adapter_handle,
+ control_1,
+ PCMCIA_CTRL1_SRESET);
+
+ macro_setw_bit(
+ adapter->adapter_handle,
+ sif_acontrol,
+ EAGLE_SIFACL_ARESET);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+}
+
+
+/****************************************************************************
+*
+* hwi_pcmcia_set_dio_address
+* ==========================
+*
+* The hwi_pcmcia_set_dio_address routine is used, with pcmcia cards, for
+* putting a 32 bit DIO address into the SIF DIO address and extended DIO
+* address registers.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcmcia_set_dio_address)
+#endif
+
+export void
+hwi_pcmcia_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address
+ )
+{
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * Load extended DIO address register with top 16 bits of address.
+ * Always load extended address register first.
+ * Note pcmcia cards have single page of all SIF registers hence do not
+ * need page in certain SIF registers.
+ */
+
+ sys_outsw(
+ adapter->adapter_handle,
+ sif_dio_adrx,
+ (WORD)(dio_address >> 16));
+
+ /*
+ * Load DIO address register with low 16 bits of address.
+ */
+
+ sys_outsw(
+ adapter->adapter_handle,
+ sif_dio_adr,
+ (WORD)(dio_address & 0x0000FFFF));
+
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|
+| pcmcia_c46_write_bit
+| ====================
+|
+| Write a bit to the SEEPROM control register.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pcmcia_c46_write_bit)
+#endif
+
+local void
+pcmcia_c46_write_bit(
+ ADAPTER * adapter,
+ WORD mask,
+ WBOOLEAN set_bit)
+{
+ WORD ctrl_reg;
+
+ /*
+ * Get the current value of the SEEPROM control register.
+ */
+
+ ctrl_reg = sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCMCIA_CONTROL_REGISTER_2)
+ );
+
+ /*
+ * Clear or set the bit.
+ */
+
+ if (set_bit)
+ {
+ ctrl_reg |= mask;
+ }
+ else
+ {
+ ctrl_reg &= ~mask;
+ }
+
+ /*
+ * Write the data to the SEEPROM control register.
+ */
+
+ sys_outsb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCMCIA_CONTROL_REGISTER_2),
+ (BYTE) ctrl_reg);
+
+ /*
+ * Wait for a bit.
+ */
+
+ sys_wait_at_least_microseconds(10);
+
+ /*
+ * And read the SEEPROM control register back so that the data gets
+ * latched properly.
+ */
+
+ sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCMCIA_CONTROL_REGISTER_2));
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| pcmcia_c46_twitch_clock
+| =======================
+|
+| Toggle the SEEPROM clock.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pcmcia_c46_twitch_clock)
+#endif
+
+local void
+pcmcia_c46_twitch_clock(
+ ADAPTER * adapter
+ )
+{
+ pcmcia_c46_write_bit(adapter, PCMCIA_CTRL2_E2SK, TRUE);
+ pcmcia_c46_write_bit(adapter, PCMCIA_CTRL2_E2SK, FALSE);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| pcmcia_c46_read_data
+| ====================
+|
+| Read a data bit from the SEEPROM control register
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pcmcia_c46_read_data)
+#endif
+
+local WORD
+pcmcia_c46_read_data(
+ ADAPTER * adapter
+ )
+{
+ return sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PCMCIA_CONTROL_REGISTER_2)
+ ) & PCMCIA_CTRL2_E2DO;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pcmcia_read_eeprom_word
+| ===========================
+|
+| hwi_pcmcia_read_eeprom_word takes the address of the word to be read
+| from the AT93C46 serial EEPROM, write to the IO ports a magic sequence
+| to switch the EEPROM to reading mode and finally read the required word
+| and return.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcmcia_read_eeprom_word)
+#endif
+
+local WORD
+hwi_pcmcia_read_eeprom_word(
+ ADAPTER * adapter,
+ WORD word_address
+ )
+{
+ WORD i;
+ WORD cmd_word = C46_START_BIT | C46_READ_CMD;
+ WORD tmp_word;
+
+ /*
+ * Concatenate the address to command word.
+ */
+
+ cmd_word |= (WORD)((word_address & C46_ADDR_MASK) << C46_ADDR_SHIFT);
+
+ /*
+ * Clear data in bit.
+ */
+
+ pcmcia_c46_write_bit(
+ adapter,
+ PCMCIA_CTRL2_E2DI,
+ FALSE);
+
+ /*
+ * Assert chip select bit.
+ */
+
+ pcmcia_c46_write_bit(
+ adapter,
+ PCMCIA_CTRL2_E2CS,
+ TRUE);
+
+ /*
+ * Send read command and address.
+ */
+
+ pcmcia_c46_twitch_clock(
+ adapter);
+
+ tmp_word = cmd_word;
+
+ for (i = 0; i < C46_CMD_LENGTH; i++)
+ {
+ pcmcia_c46_write_bit(
+ adapter,
+ PCMCIA_CTRL2_E2DI,
+ (WBOOLEAN) ((tmp_word & 0x8000) != 0));
+ pcmcia_c46_twitch_clock(adapter);
+ tmp_word <<= 1;
+ }
+
+ /*
+ * Read data word.
+ */
+
+ tmp_word = 0x0000;
+
+ for (i = 0; i < 16; i++)
+ {
+ pcmcia_c46_twitch_clock(adapter);
+
+ if (i > 0)
+ {
+ tmp_word <<= 1;
+ }
+
+ if (pcmcia_c46_read_data(adapter) != 0)
+ {
+ tmp_word |= 0x0001;
+ }
+ }
+
+ /*
+ * Clear data in bit.
+ */
+
+ pcmcia_c46_write_bit(
+ adapter,
+ PCMCIA_CTRL2_E2DI,
+ FALSE);
+
+ /*
+ * Deselect chip.
+ */
+
+ pcmcia_c46_write_bit(
+ adapter,
+ PCMCIA_CTRL2_E2CS,
+ FALSE);
+
+ /*
+ * Tick clock.
+ */
+
+ pcmcia_c46_twitch_clock(adapter);
+
+ return tmp_word;
+}
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| hwi_pcmcia_card_services_setup
+| ==============================
+|
+| hwi_pcmcia_card_services_setup is called by hwi_pcmcia_install_card. It
+| handles all the procedures required to register with PCMCIA Card
+| Serivces and request I O and interrupt resources.
+|
+| The caller must fill in interrupt_number and io_location field of the
+| input adapter structure. Interrupt number can be any number supported by
+| the 16 4 PCMCIA ringnode or DETERMINED_BY_CS. A valid io_location mus
+| be supplied.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pcmcia_card_services_setup)
+#endif
+
+local WBOOLEAN
+hwi_pcmcia_card_services_setup(
+ PROBE * resource
+ )
+{
+ NEW_PCMCIA_ARG_BUFFER(fp);
+
+ WORD rc;
+ WORD ClientHandle;
+ DWORD i = 0;
+ WORD j;
+ void FAR * CallBackPtr = (void FAR *) Callback;
+ WORD socket = DETERMINED_BY_CARD_SERVICES;
+ WORD irq = DETERMINED_BY_CARD_SERVICES;
+ WORD io_location = resource->io_location;
+
+ rc = CardServices(
+ CS_GetCardServicesInfo, /* Function */
+ NULL, /* Handle not used */
+ NULL, /* Pointer not used */
+ MAX_PCMCIA_ARG_BUFFER_LEN, /* argbuffer length */
+ fp ); /* argbuffer */
+
+ if (rc == CMD_SUCCESS)
+ {
+ CS_GET_CS_INFO_ARG FAR * ptr = (CS_GET_CS_INFO_ARG FAR *)fp;
+
+ if ((ptr->Signature[0] == 'C') &&
+ (ptr->Signature[1] == 'S'))
+ {
+ CardServicesVersion = ptr->CSLevel;
+ }
+ else if ((ptr->Signature[0] == 'M') &&
+ (ptr->Signature[1] == 'N'))
+ {
+ CardServicesVersion = ptr->CSLevel;
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ {
+ CS_REGISTER_CLIENT_ARG FAR * ptr =
+ (CS_REGISTER_CLIENT_ARG FAR *)fp;
+
+ ptr->Attributes = RC_ATTR_IO_CLIENT_DEVICE_DRIVER |
+ RC_ATTR_IO_INSERTION_SHARABLE;
+
+ ptr->EventMask = MASK_CARD_DETECT;
+
+ ptr->ClientData[0] = 0x00; /* Not used */
+ ptr->ClientData[1] = 0x00; /* CardServices will put DS here. */
+ ptr->ClientData[2] = 0x00; /* Not used */
+ ptr->ClientData[3] = 0x00; /* Not used */
+ ptr->Version = 0x0201;
+ }
+
+ /*
+ * Set RegisterClientCompleted flag to FALSE. When registration
+ * complete event occur, call back function will set this flag to TRUE.
+ */
+
+ RegisterClientCompleted = FALSE;
+
+ rc = CardServices(
+ CS_RegisterClient,
+ (WORD FAR *)&ClientHandle,
+ (void * FAR *)&CallBackPtr,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp );
+
+ if (CMD_SUCCESS != rc)
+ {
+ return FALSE;
+ }
+
+ while (!RegisterClientCompleted)
+ {
+ /*
+ * Wait for card insertion event to complete, timeout if waiting
+ * for too long.
+ */
+
+ i++;
+
+ if (i == PCMCIA_CS_REGISTRATION_TIMEOUT)
+ {
+ return FALSE;
+ }
+ }
+
+ /*
+ * Check if there is a least one socket ready for use. Return false if
+ * none is found. Remember we have registered with card services, so
+ * deregister before returning.
+ */
+
+ for (j = 0; j < MAX_PCMCIA_SOCKETS; j++)
+ {
+ if (SOCKET_READY == pcmcia_socket_table[j].status)
+ {
+ break;
+ }
+ }
+
+ if (MAX_PCMCIA_SOCKETS == j)
+ {
+ /*
+ * No socket available. Either no Madge card installed or they are
+ * already in use. Report error here. Must deregister before
+ * returning.
+ */
+
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ return FALSE;
+ }
+
+ if (socket != DETERMINED_BY_CARD_SERVICES)
+ {
+ /*
+ * User specified a socket number to use. Check if it is available.
+ */
+
+ if (pcmcia_socket_table[socket].status == SOCKET_NOT_INITIALIZED)
+ {
+ /*
+ * No Madge Card found in PCMCIA socket specified, deregister
+ * and report error.
+ */
+
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ return FALSE;
+ }
+ else if (pcmcia_socket_table[socket].status == SOCKET_IN_USE)
+ {
+ /*
+ * Card in socket number specified is currently in use,
+ * deregister and report error.
+ */
+
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ return FALSE;
+ }
+ else
+ {
+ /*
+ * Socket number specified has a Madge Card in it and it is
+ * available.
+ */
+ ;
+ }
+
+ }
+ else
+ {
+ /*
+ * User asked Card Services to choose which socket to use.
+ * Use the first available one.
+ */
+ socket = j;
+ }
+
+ /*
+ * Call CS AdjustResourceInfo.
+ */
+
+ {
+ CS_ADJ_IO_RESOURCE_ARG FAR * ptr =
+ (CS_ADJ_IO_RESOURCE_ARG FAR *)fp;
+
+ ptr->Action = ARI_ACTION_ADD;
+ ptr->Resource = ARI_RESOURCE_IO;
+ ptr->BasePort = io_location;
+ ptr->NumPorts = PCMCIA_IO_RANGE;
+ ptr->Attributes = 0x00;
+ ptr->IOAddrLines = PCMCIA_NUMBER_OF_ADDR_LINES;
+ }
+
+ rc = CardServices(CS_AdjustResourceInfo,
+ NULL,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp );
+
+ if (CMD_SUCCESS != rc)
+ {
+ /*
+ * Requested IO location is not available, deregister and report
+ * error.
+ */
+
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ return FALSE;
+ }
+
+ /*
+ * AdjustResourceInfo does not exist for CS V2.00 on the IBM ThinkPad.
+ * Assume it is ok. Do not bother to check the return code here.
+ */
+
+ /*
+ * Call CS RequestIO to ask for IO resources.
+ */
+
+ {
+ CS_REQUEST_IO_ARG FAR * ptr = (CS_REQUEST_IO_ARG FAR *) fp;
+
+ ptr->Socket = socket;
+ ptr->BasePort1 = io_location;
+ ptr->NumPorts1 = PCMCIA_IO_RANGE;
+ ptr->Attributes1 = RIO_ATTR_16_BIT_DATA;
+ ptr->BasePort2 = 0x0000;
+ ptr->NumPorts2 = 0x00;
+ ptr->Attributes2 = 0x00;
+ ptr->IOAddrLines = PCMCIA_NUMBER_OF_ADDR_LINES;
+
+ }
+
+ rc = CardServices(CS_RequestIO,
+ (WORD FAR *)&ClientHandle,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp );
+
+
+ if (CMD_SUCCESS != rc)
+ {
+ /*
+ * Requested IO location is not available, deregister and report
+ * error.
+ */
+
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ return FALSE;
+ }
+
+ /*
+ * Call CS RequestIRQ to ask for interrupt resources.
+ */
+
+ {
+ CS_REQUEST_IRQ_ARG FAR * ptr = (CS_REQUEST_IRQ_ARG FAR *)fp;
+
+ if (DETERMINED_BY_CARD_SERVICES == irq)
+ {
+ /*
+ * User asked card services to choose any interrupt channel
+ * available.
+ */
+
+ ptr->IRQInfo1 = PCMCIA_IRQINFO1_NOT_SPECIFIED;
+
+ /*
+ * List of IRQ channel available (in form of bit mask) for card
+ * services to choose from. Exclude those already in use.
+ */
+
+ ptr->IRQInfo2 = PCMCIA_AVAILABLE_IRQ_MASK & ~UsedIrqChannelsMask;
+ }
+ else if ((0x0001 << irq) & PCMCIA_AVAILABLE_IRQ_MASK)
+ {
+ /*
+ * Use the interrupt channel the user supplied.
+ */
+
+ ptr->IRQInfo1 = (BYTE)((irq & 0x00FF) |
+ PCMCIA_IRQINFO1_SPECIFIED);
+ ptr->IRQInfo2 = 0x0000;
+ }
+ else
+ {
+ /*
+ * An invalid interrupt channel is specified.
+ * We have already requested for an IO resource, we must
+ * release it and deregister with card services before
+ * returning.
+ */
+
+ hwi_pcmcia_cs_release_io(ClientHandle, socket, io_location);
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ return FALSE;
+ }
+
+ ptr->Socket = socket;
+ ptr->Attributes = 0x0000;
+
+ rc = CardServices(
+ CS_RequestIRQ,
+ (WORD FAR *)&ClientHandle,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp );
+
+ if (CMD_SUCCESS == rc)
+ {
+ /*
+ * Card Services successfully allocated us an interrupt
+ * channel, record it for later use.
+ */
+
+ irq = (WORD)ptr->AssignedIRQ;
+ }
+ else
+ { /*
+ * Failed to obtain an interrupt channel. Release the IO
+ * allocated and deregister with card services.
+ */
+
+ hwi_pcmcia_cs_release_io(ClientHandle, socket, io_location);
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ return FALSE;
+ }
+ }
+
+ /*
+ * Call CS RequestConfiguration.
+ */
+
+ {
+ CS_REQUEST_CONFIG_ARG FAR * ptr = (CS_REQUEST_CONFIG_ARG FAR *)fp;
+
+ ptr->Socket = socket;
+ ptr->Attributes = RC_ATTR_ENABLE_IRQ_STEERING;
+ ptr->Vcc = PCMCIA_VCC;
+ ptr->Vpp1 = PCMCIA_VPP1;
+ ptr->Vpp2 = PCMCIA_VPP2;
+ ptr->IntType = RC_INTTYPE_MEMORY_AND_IO;
+ ptr->ConfigBase = PCMCIA_CONFIG_BASE;
+ ptr->Status = PCMCIA_STATUS_REG_SETTING;
+ ptr->Pin = PCMCIA_PIN_REG_SETTING;
+ ptr->Copy = PCMCIA_COPY_REG_SETTING;
+ ptr->ConfigIndex = PCMCIA_OPTION_REG_SETTING;
+ ptr->Present = PCMCIA_REGISTER_PRESENT;
+
+ }
+
+ rc = CardServices(
+ CS_RequestConfiguration,
+ (WORD FAR *)&ClientHandle,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp );
+
+ if (CMD_SUCCESS != rc)
+ {
+ /*
+ * RequestConfiguration failed. Release all resources and return
+ * error.
+ */
+
+ hwi_pcmcia_cs_release_io(ClientHandle, socket, io_location);
+ hwi_pcmcia_cs_release_irq(ClientHandle, socket, irq);
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ return FALSE;
+
+ }
+
+ /*
+ * We successfully made all the card services call. Update our local
+ * sockets record here.
+ */
+
+ pcmcia_socket_table[socket].status = SOCKET_IN_USE;
+ pcmcia_socket_table[socket].irq_number = irq;
+ pcmcia_socket_table[socket].io_location = io_location;
+ pcmcia_socket_table[socket].ClientHandle = ClientHandle;
+
+ /*
+ * Record interrupt channel used.
+ */
+
+ UsedIrqChannelsMask |= ( 0x0001 << irq );
+
+ /*
+ * Fill adapter sturcture with resources allocated.
+ */
+
+ resource->interrupt_number = irq;
+ resource->io_location = io_location;
+ resource->socket = socket;
+
+ /*
+ * Toggle the top bit of Configuration Option Register to reset card.
+ */
+
+ /*
+ * Note that this is not necessary for later cards.
+ * CS 2.00 may not have this function, so just do it but don't bother
+ * to check return code.
+ */
+
+ {
+ CS_ACCESS_CONFIG_REG_ARG FAR * ptr =
+ (CS_ACCESS_CONFIG_REG_ARG FAR *) fp;
+
+ ptr->Socket = socket;
+ ptr->Action = ACR_ACTION_WRITE;
+ ptr->Offset = PCMCIA_OPTION_REG;
+ ptr->Value = PCMCIA_COR_SYSRESET;
+
+ CardServices(
+ CS_AccessConfigurationRegister,
+ NULL,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp );
+
+ ptr->Value = 0x00;
+
+ CardServices(
+ CS_AccessConfigurationRegister,
+ NULL,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp );
+
+ ptr->Value = PCMCIA_OPTION_REG_SETTING;
+
+ CardServices(
+ CS_AccessConfigurationRegister,
+ NULL,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp );
+ }
+
+ return TRUE;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pcmcia_cs_release_config
+| ============================
+|
+| hwi_pcmcia_cs_release_config releases resources requested earlier from
+| Card Services. This is part of the shut down procedure.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pcmcia_cs_release_config)
+#endif
+
+local WORD
+hwi_pcmcia_cs_release_config(
+ WORD ClientHandle,
+ WORD Socket)
+{
+ NEW_PCMCIA_ARG_BUFFER(fp);
+ WORD chandle = ClientHandle;
+ CS_RELEASE_CONFIG_ARG FAR * ptr = (CS_RELEASE_CONFIG_ARG FAR *)fp;
+
+ ptr->Socket = Socket;
+
+ return CardServices(
+ CS_ReleaseConfiguration,
+ &chandle,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pcmcia_cs_release_io
+| ========================
+|
+| hwi_pcmcia_cs_release_io releases the IO resources requested earlier
+| from Card Services.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pcmcia_cs_release_io)
+#endif
+
+local WORD
+hwi_pcmcia_cs_release_io(
+ WORD ClientHandle,
+ WORD Socket,
+ WORD IoLocation
+ )
+{
+ NEW_PCMCIA_ARG_BUFFER(fp);
+ WORD chandle = ClientHandle;
+ CS_RELEASE_IO_ARG FAR * ptr = (CS_RELEASE_IO_ARG FAR *)fp;
+
+
+ ptr->Socket = Socket;
+ ptr->BasePort1 = IoLocation;
+ ptr->NumPorts1 = PCMCIA_IO_RANGE;
+ ptr->Attributes1 = RIO_ATTR_16_BIT_DATA;
+ ptr->BasePort2 = 0x0000;
+ ptr->NumPorts2 = 0x00;
+ ptr->Attributes2 = 0x00;
+ ptr->IOAddrLines = PCMCIA_NUMBER_OF_ADDR_LINES;
+
+ return CardServices(
+ CS_ReleaseIO,
+ (WORD FAR *)&chandle,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pcmcia_cs_release_irq
+| =========================
+|
+| hwi_pcmcia_cs_release_irq release the IRQ resources requested earlier
+| from Card Services.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pcmcia_cs_release_irq)
+#endif
+
+local WORD
+hwi_pcmcia_cs_release_irq(
+ WORD ClientHandle,
+ WORD Socket,
+ WORD IRQChannel)
+{
+ NEW_PCMCIA_ARG_BUFFER(fp);
+ WORD chandle = ClientHandle;
+ CS_RELEASE_IRQ_ARG FAR * ptr = (CS_RELEASE_IRQ_ARG FAR *)fp;
+
+
+ ptr->Socket = Socket;
+ ptr->Attributes = 0x0000;
+ ptr->AssignedIRQ = (BYTE)IRQChannel;
+
+ return CardServices(
+ CS_ReleaseIRQ,
+ (WORD FAR *)&chandle,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp);
+}
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pcmcia_cs_deregister_client
+| ===============================
+|
+| hwi_pcmcia_cs_deregister_client informs PCMCIA card services that we are
+| not longer interest in any PCMCIA event and/or resources. It is called
+| in shut down or failure in invoking other card services related
+| function.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pcmcia_cs_deregister_client)
+#endif
+
+local WORD
+hwi_pcmcia_cs_deregister_client(
+ WORD ClientHandle
+ )
+{
+ NEW_PCMCIA_ARG_BUFFER(fp);
+ WORD chandle = ClientHandle;
+
+ return CardServices(
+ CS_DeregisterClient,
+ (WORD FAR *)&chandle,
+ NULL,
+ 0,
+ fp);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pcmcia_tear_down_cs
+| =======================
+|
+| hwi_pcmcia_tear_down_cs is called by hwi_pcmcia_remove card to release
+| all the resources allocated by PCMCIA card services and deregister with
+| card services
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pcmcia_tear_down_cs)
+#endif
+
+local WBOOLEAN
+hwi_pcmcia_tear_down_cs(
+ PROBE resource
+ )
+{
+
+ WORD socket = resource.socket;
+ WORD ClientHandle;
+ WORD io_location;
+ WORD irq_number;
+ WBOOLEAN rc1;
+ WBOOLEAN rc2;
+ WBOOLEAN rc3;
+ WBOOLEAN rc4;
+
+
+ if (pcmcia_socket_table[socket].status != SOCKET_IN_USE)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Socket number found. retrieve clienthandle, irq, iolocation from our
+ * local socket record.
+ */
+
+ ClientHandle = pcmcia_socket_table[socket].ClientHandle;
+ io_location = pcmcia_socket_table[socket].io_location;
+ irq_number = pcmcia_socket_table[socket].irq_number;
+
+ /*
+ * Call the PCMCIA card services routine to bring it down.
+ */
+
+ rc1 = hwi_pcmcia_cs_release_config(ClientHandle, socket);
+ rc2 = hwi_pcmcia_cs_release_io(ClientHandle, socket, io_location);
+ rc3 = hwi_pcmcia_cs_release_irq(ClientHandle, socket, irq_number);
+ rc4 = hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ /*
+ * Update local record.
+ */
+
+ pcmcia_socket_table[socket].ClientHandle = 0x0000;
+ pcmcia_socket_table[socket].io_location = 0x0000;
+ pcmcia_socket_table[socket].irq_number = 0x0000;
+ pcmcia_socket_table[socket].status = SOCKET_NOT_INITIALIZED;
+
+ return (rc1 && rc2 && rc3 && rc4);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| This is the callback function used by Card Services to notify client any
+| event changes. Its prototype is defined in sys_cs.h module.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(Callback)
+#endif
+
+WORD FAR
+Callback(
+ WORD Function,
+ WORD Socket,
+ WORD Info,
+ void FAR * MTDRequest,
+ void FAR * Buffer,
+ WORD Misc,
+ WORD ClientData1,
+ WORD ClientData2,
+ WORD ClientData3
+ )
+{
+ NEW_PCMCIA_ARG_BUFFER(fp);
+ WORD rc;
+
+ switch (Function)
+ {
+ case REGISTRATION_COMPLETE :
+ RegisterClientCompleted = TRUE;
+ break;
+
+ case CARD_INSERTION :
+ /*
+ * Call GetFistTuple of card services.
+ */
+
+ {
+ CS_GET_FIRST_TUPLE_ARG FAR * ptr =
+ (CS_GET_FIRST_TUPLE_ARG FAR *)fp;
+
+ ptr->Socket = Socket;
+ ptr->Attributes = 0x0000;
+ ptr->DesiredTuple = CISTPL_VERS_1;
+ ptr->Reserved = 0x00;
+ }
+
+ rc = CardServices(
+ CS_GetFirstTuple,
+ NULL,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp);
+
+ if (rc != CMD_SUCCESS)
+ {
+ break;
+ }
+
+ /*
+ * Call GetTupleData of card services.
+ */
+
+ {
+ CS_GET_TUPLE_DATA_ARG FAR * ptr =
+ (CS_GET_TUPLE_DATA_ARG FAR *)fp;
+
+ ptr->TupleOffset = 0x00;
+ ptr->TupleDataMax = MAX_PCMCIA_ARG_BUFFER_LEN;
+ }
+
+ rc = CardServices(
+ CS_GetTupleData,
+ NULL,
+ NULL,
+ MAX_PCMCIA_ARG_BUFFER_LEN,
+ fp);
+
+ if (rc != CMD_SUCCESS)
+ {
+ break;
+ }
+
+ /*
+ * Is it a Madge Smart 16/4 PCMCIA Ringnode?
+ */
+
+ {
+ CS_GET_TUPLE_DATA_ARG FAR * ptr =
+ (CS_GET_TUPLE_DATA_ARG FAR *)fp;
+ BYTE FAR * info_ptr;
+ WORD i;
+
+ /*
+ * Find the signature strings in the tuple.
+ * Allow for CS version 2.00 or below. See the TupleData
+ * union in the header file.
+ */
+
+ if (CardServicesVersion <= 0x0200)
+ {
+ info_ptr = ((CS200_CISTPL_VERS_1_DATA FAR *)
+ (ptr->TupleData) )->info;
+ }
+ else
+ {
+ info_ptr = ((CS201_CISTPL_VERS_1_DATA FAR *)
+ (ptr->TupleData) )->info;
+ }
+
+ /*
+ * Compare signature strings. Avoid strcmp, _fstrcmp,
+ * memcmp, _fmemcmp, etc. to make it model independent.
+ */
+
+ for (i = 0; i < MADGE_TPLLV1_INFO_LEN; i++)
+ {
+ if (*(MADGE_TPLLV1_INFO+i) != *(info_ptr+i))
+ {
+ break;
+ }
+ }
+
+
+ if (MADGE_TPLLV1_INFO_LEN == i) /* yes, a madge card. */
+ {
+ if (pcmcia_socket_table[Socket].status ==
+ SOCKET_NOT_INITIALIZED)
+ {
+ pcmcia_socket_table[Socket].status = SOCKET_READY;
+ }
+
+ /*
+ * do nothing if status is SOCKET_READY or
+ * SOCKET_IN_USE.
+ */
+ }
+ }
+
+ break;
+
+ case CLIENT_INFO :
+ {
+ WORD buffer_size =
+ ((CS_CLIENT_INFO FAR *)Buffer)->MaxLen;
+ WORD len_to_copy;
+ WORD i;
+ WORD madge_info_size = sizeof(MADGE_CLIENT_INFO);
+ BYTE FAR * src;
+ BYTE FAR * dest;
+
+ /*
+ * Copy whole client info structure if there is space,
+ * otherwise just fill the buffer supplied.
+ */
+
+ len_to_copy =
+ (buffer_size > madge_info_size) ? madge_info_size :
+ buffer_size;
+
+ src = (BYTE FAR *)&default_client_info;
+ dest = (BYTE FAR *)Buffer;
+
+ for (i = 0; i < len_to_copy; i++)
+ {
+ if (i > 1) /* Skip MaxLen field which is preserved. */
+ {
+ *(dest+i) = *(src+1);
+ }
+ }
+ }
+
+ break;
+
+ case CARD_REMOVAL:
+ /*
+ * Only remove card in use.
+ * Check Socket < MAX_PCMCIA_SOCKETS to prevent access
+ * to out-of-bound array element.
+ */
+
+ if ((Socket < MAX_PCMCIA_SOCKETS) &&
+ (pcmcia_socket_table[Socket].status == SOCKET_IN_USE))
+ {
+ WORD ClientHandle = pcmcia_socket_table[Socket].ClientHandle;
+ WORD io_location = pcmcia_socket_table[Socket].io_location;
+ WORD irq_number = pcmcia_socket_table[Socket].irq_number;
+
+ /*
+ * Call the PCMCIA card services routine to bring it down.
+ */
+
+ hwi_pcmcia_cs_release_config(ClientHandle, Socket);
+ hwi_pcmcia_cs_release_io(ClientHandle, Socket, io_location);
+ hwi_pcmcia_cs_release_irq(ClientHandle, Socket, irq_number);
+ hwi_pcmcia_cs_deregister_client(ClientHandle);
+
+ /*
+ * Update local record.
+ */
+
+ pcmcia_socket_table[Socket].ClientHandle = 0x0000;
+ pcmcia_socket_table[Socket].io_location = 0x0000;
+ pcmcia_socket_table[Socket].irq_number = 0x0000;
+ pcmcia_socket_table[Socket].status =
+ SOCKET_NOT_INITIALIZED;
+ pcmcia_socket_table[Socket].adapter_handle = 0x0000;
+ }
+
+ break;
+
+ default :
+
+ break;
+ }
+
+ return CMD_SUCCESS;
+}
+
+#endif
+
+#endif
+
+/******** End of HWI_PCMC.C ************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_pnp.c b/private/ntos/ndis/madge/driver/hwi_pnp.c
new file mode 100644
index 000000000..29e9821db
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_pnp.c
@@ -0,0 +1,2490 @@
+/****************************************************************************
+*
+* THE HARDWARE INTERFACE MODULE (SMART PNP RINGNODES)
+* ===================================================
+*
+* HWI_PNP.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* Copyright (c) Madge Networks Ltd. 1990-1994
+* Developed by AC
+* From code by MF
+* CONFIDENTIAL
+*
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_PNP.C module contains the routines specific to the PnP card
+* which are necessary to install an adapter, to initialize an adapter, to
+* remove an adapter, and to handle interrupts on an adapter.
+*
+*****************************************************************************
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+#ifndef FTK_NO_PNP
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local WBOOLEAN
+hwi_pnp_valid_io_location(
+ WORD io_location
+ );
+
+local WBOOLEAN
+hwi_pnp_read_node_address(
+ ADAPTER * adapter
+ );
+
+local WBOOLEAN
+hwi_pnp_valid_irq_channel(
+ ADAPTER * adapter
+ );
+
+local WBOOLEAN
+hwi_pnp_test_for_id(
+ ADAPTER * adapter
+ );
+
+local WORD
+pnp_read_a_word(
+ ADAPTER * adapter,
+ WORD index
+ );
+
+#ifndef FTK_NO_PROBE
+
+local WBOOLEAN
+hwi_pnp_probe_find_card(
+ WORD io_location
+ );
+
+local WORD
+hwi_pnp_probe_get_irq(
+ WORD io_location
+ );
+
+local WORD
+pnp_probe_read_a_word(
+ WORD io_location,
+ WORD index
+ );
+
+#endif
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_pnp_probe_card
+* ==================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is an array of IO locations to examine for the presence
+* of an adapter. For PNP based adapters this should be a subset of
+* {0x3a20, 0x920, 0x940, 0x960, 0x980, 0xa20, 0xa40, 0xa60, 0xa80, 0xb20,
+* 0xb40, 0xb60, 0xb80}.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_pnp_probe_card routine is called by hwi_probe_adapter. It
+* probes the adapter card for information such as DMA channel, IRQ number
+* etc. This information can then be supplied by the user when starting the
+* adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_probe_card)
+#endif
+
+export UINT
+hwi_pnp_probe_card(
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ )
+{
+ WORD temp_word;
+ UINT adapters_found;
+ UINT i;
+
+ /*
+ * Sanity check the bounds.
+ */
+
+ if (length <= 0 || number_locations <= 0)
+ {
+ return PROBE_FAILURE;
+ }
+
+ /*
+ * Validate the IO locations.
+ */
+
+ for (i = 0; i < number_locations; i++)
+ {
+ if (!hwi_pnp_valid_io_location(valid_locations[i]))
+ {
+ return PROBE_FAILURE;
+ }
+ }
+
+ adapters_found = 0;
+
+ for (i = 0; i < number_locations; i++)
+ {
+ /*
+ * Make sure that we haven't run out of PROBE structures.
+ */
+ if (adapters_found >= length)
+ {
+ return adapters_found;
+ }
+
+ if (hwi_pnp_probe_find_card(valid_locations[i]))
+ {
+
+ /*
+ * Found a card! Now fill out the probe structure.
+ */
+
+ resources[adapters_found].io_location = valid_locations[i];
+ resources[adapters_found].adapter_card_bus_type = ADAPTER_CARD_PNP_BUS_TYPE;
+ resources[adapters_found].adapter_card_type = ADAPTER_CARD_TYPE_16_4_PNP;
+ resources[adapters_found].adapter_card_revision = ADAPTER_CARD_PNP;
+ resources[adapters_found].transfer_mode = PIO_DATA_TRANSFER_MODE;
+
+ /*
+ * Now find out how much RAM we have.
+ */
+
+ temp_word = pnp_probe_read_a_word(
+ valid_locations[i],
+ PNP_HWARE_FEATURES1);
+
+ temp_word &= PNP_DRAM_SIZE_MASK;
+
+ /*
+ * Convert the DRAM size to multiples of bytes.
+ */
+
+ resources[adapters_found].adapter_ram_size = temp_word * 64;
+
+ /*
+ * Now find out what IRQ we are using.
+ */
+
+ resources[adapters_found].interrupt_number = hwi_pnp_probe_get_irq( valid_locations[i]);
+
+ adapters_found++;
+ }
+ }
+
+ return adapters_found;
+
+}
+#endif
+
+/****************************************************************************
+*
+* hwi_pnp_install_card
+* =====================
+*
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pnp_install_card routine is called by hwi_install_adapter. It
+* sets up the adapter card and downloads the required code to it. Firstly,
+* it checks there is a valid adapter at the required IO address. If so it
+* reads the node address from the BIA PROM and sets up and checks numerous
+* on-board registers for correct operation.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls.
+* Similarly, operating system calls are used to enable DMA if required. If
+* DMA is not used then the adapter is set up for PIO.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_install_card)
+#endif
+
+export WBOOLEAN
+hwi_pnp_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location +
+ PNP_CONTROL_REGISTER_1;
+ WORD config_addr = adapter->io_location +
+ PNP_CONFIG_ADDRESS_REGISTER;
+ WORD config_data = adapter->io_location +
+ PNP_CONFIG_DATA_REGISTER;
+ WORD chip_type;
+ WORD ram_size;
+ BYTE byte;
+ WORD sif_base;
+
+
+ /*
+ * Firstly do some validation on the user supplied adapter details
+ * check that the IO location is valid
+ * if routine fails return failure (error record already filled in)
+ * In theory we shouldnt have to do this - but Chicago has been known
+ * to pass out junk !!
+ */
+
+ if (!hwi_pnp_valid_io_location(adapter->io_location))
+ {
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION;
+ return FALSE;
+ }
+
+ /*
+ * save IO locations of the SIF registers
+ */
+
+ sif_base = adapter->io_location + PNP_FIRST_SIF_REGISTER;
+
+ adapter->sif_dat = sif_base + EAGLE_SIFDAT;
+ adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC;
+ adapter->sif_adr = sif_base + EAGLE_SIFADR;
+ adapter->sif_int = sif_base + EAGLE_SIFINT;
+ adapter->sif_acl = sif_base + EAGLE_SIFACL;
+ adapter->sif_adr2 = sif_base + EAGLE_SIFADR;
+ adapter->sif_adx = sif_base + EAGLE_SIFADX;
+ adapter->sif_dmalen = sif_base + EAGLE_DMALEN;
+ adapter->sif_sdmadat = sif_base + EAGLE_SDMADAT;
+ adapter->sif_sdmaadr = sif_base + EAGLE_SDMAADR;
+ adapter->sif_sdmaadx = sif_base + EAGLE_SDMAADX;
+
+ adapter->io_range = PNP_IO_RANGE;
+
+ /*
+ * Make sure this is a real PNP card by reading the ID register
+ */
+
+ if(!hwi_pnp_test_for_id(adapter))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+ return FALSE;
+ }
+
+ /*
+ * You might want to check that we have not already checked for a card
+ * at this address (or its rev3/4 equivalent).
+ * Read the node address for the specified IO location.
+ */
+
+ if (!hwi_pnp_read_node_address(adapter))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+ return FALSE;
+ }
+
+ /*
+ * Check the transfer mode - this is very easy as we only do PIO
+ * (albeit EAGLE PseudoDMA).
+ */
+
+ if (adapter->transfer_mode != PIO_DATA_TRANSFER_MODE)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Check the IRQ channel supplied.
+ * In theory we shouldnt have to do this - but Chicago has been known
+ * to pass out junk !!
+ */
+
+ if (!hwi_pnp_valid_irq_channel(adapter))
+ {
+ /*
+ * Fill in error record and return
+ */
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_03_BAD_INTERRUPT_NUMBER;
+ return FALSE;
+ }
+
+ /*
+ * These things can all be assumed for the pnp.
+ */
+
+ adapter->adapter_card_type = ADAPTER_CARD_TYPE_16_4_PNP;
+ adapter->adapter_card_revision = ADAPTER_CARD_PNP;
+
+ /*
+ * Now find out how much RAM we have.
+ */
+
+ ram_size = pnp_read_a_word(adapter,
+ PNP_HWARE_FEATURES1);
+
+ ram_size &= PNP_DRAM_SIZE_MASK;
+
+ /*
+ * Convert the DRAM size to multiples of bytes.
+ */
+
+ adapter->adapter_ram_size = ram_size * 64;
+ adapter->edge_triggered_ints = TRUE;
+ adapter->EaglePsDMA = TRUE;
+
+ /*
+ * Set the ring speed if required.
+ */
+
+ /*
+ * RCS 2/11/94 Added code to set the adapter->nselout bits so that
+ * the ring speed is fully adopted by the adapter when "hwi_halt_eagle()"
+ * is called.
+ *
+ * Also set the "ringspeed configured" bit if the "set_ring_speed"
+ * feature is specified so that we will use the value.
+ *
+ * Also return an error if the ringspeed hasnt been configured and
+ * the user hasnt specified "set_ring_speed".
+ */
+
+ /*
+ * Is this a C30 based card???
+ * If it is then we can't drive the lowest bit of the vendor config
+ * register as this gives an indication of ring_speed error (Potentially).
+ *
+ */
+
+ chip_type = pnp_read_a_word(
+ adapter,
+ PNP_HWARE_FEATURES3);
+ chip_type &= PNP_C30_MASK;
+
+ /*
+ * First read the current settings
+ */
+
+ sys_outsb(
+ adapter_handle,
+ config_addr,
+ PNP_VENDOR_CONFIG_BYTE);
+
+ byte = sys_insb(
+ adapter_handle,
+ config_data);
+
+ if (adapter->set_ring_speed != 0)
+ {
+ if (adapter->set_ring_speed == 4)
+ {
+ if ( chip_type != PNP_C30 )
+ {
+ /*
+ * Set bits to select 4mbits as the ring speed
+ */
+ byte |= (PNP_VENDOR_CONFIG_4MBITS + PNP_VENDOR_CONFIG_PXTAL);
+ }
+ else
+ {
+ byte |= PNP_VENDOR_CONFIG_4MBITS;
+ }
+ }
+ else if (adapter->set_ring_speed == 16)
+ {
+ if ( chip_type != PNP_C30 )
+ {
+ /*
+ * Clear bits to select 16mbits as the ring speed
+ */
+
+ byte &= ~(PNP_VENDOR_CONFIG_4MBITS +
+ PNP_VENDOR_CONFIG_PXTAL);
+ }
+ else
+ {
+ byte &= ~(PNP_VENDOR_CONFIG_4MBITS);
+ }
+ }
+
+ /*
+ * Show ring speed as having been configured
+ */
+
+ byte |= PNP_VENDOR_CONFIG_RSVALID;
+
+ /*
+ * and write it back to the card
+ */
+
+ sys_outsb(
+ adapter_handle,
+ config_data,
+ byte);
+ }
+
+ /*
+ * Use the value in "byte" to set the NSELOUT bits or it will still
+ * only run at 16 !!
+ */
+
+ if (byte & PNP_VENDOR_CONFIG_RSVALID)
+ {
+ if (byte & PNP_VENDOR_CONFIG_4MBITS)
+ {
+ adapter->nselout_bits = PNP_RING_SPEED_4;
+ }
+ else
+ {
+ adapter->nselout_bits = PNP_RING_SPEED_16;
+ }
+ }
+ else
+ {
+ /*
+ * The user MUST configure the RING SPEED before we will let him use
+ * the card.
+ * He can either run the CONFIG util or use the FORCE4/FORCE16
+ * mechanism.
+ * Fill in error record and return
+ */
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0E_NO_SPEED_SELECTED;
+
+ return FALSE;
+ }
+
+ /*
+ * Bring adapter out of reset state (ensure that SCS is zero before
+ * doing this). If active float channel ready is set in the Plug and
+ * Play hardware flags then set the PNP_CHRDY_ACTIVE bit.
+ */
+
+ byte = PNP_CTRL1_NSRESET;
+
+ if ((pnp_read_a_word(
+ adapter,
+ PNP_HWARE_PNP_FLAGS) & PNP_ACTIVE_FLOAT_CHRDY) != 0)
+ {
+ byte |= PNP_CTRL1_CHRDY_ACTIVE;
+ }
+
+ sys_outsb(
+ adapter_handle,
+ control_1,
+ byte);
+
+ /*
+ * Halt the Eagle prior to downloading the MAC code - this will also
+ * write the ringspeed bits into the SIFACL register.
+ */
+
+ hwi_halt_eagle(adapter);
+
+ /*
+ * download code to adapter
+ * view download image as a sequence of download records
+ * pass address of routine to set up DIO addresses on ATULA cards
+ * if routine fails return failure (error record already filled in)
+ */
+
+ if (!hwi_download_code(
+ adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_pnp_set_dio_address))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Restart the Eagle to initiate bring up diagnostics.
+ */
+
+ hwi_start_eagle(adapter);
+
+ /*
+ * wait for a valid bring up code, may wait 3 seconds
+ * if routine fails return failure (error record already filled in)
+ */
+
+ if (!hwi_get_bring_up_code(adapter))
+ {
+ return FALSE;
+ }
+
+ /*
+ * set DIO address to point to EAGLE DATA page 0x10000L
+ */
+
+ hwi_pnp_set_dio_address(
+ adapter,
+ DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * set maximum frame size from the ring speed
+ */
+
+ adapter->max_frame_size = hwi_get_max_frame_size(adapter);
+
+ /*
+ * Get the ring speed.
+ */
+
+ adapter->ring_speed = hwi_get_ring_speed(adapter);
+
+ /*
+ * if not in polling mode then set up interrupts
+ * interrupts_on field is used when disabling interrupts for adapter
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on =
+ sys_enable_irq_channel(adapter_handle,
+ adapter->interrupt_number);
+
+ /*
+ * if fail enable irq channel then fill in error record and return
+ */
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+ /*
+ * return successfully
+ */
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* hwi_pnp_interrupt_handler
+* ==========================
+*
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ============================================
+*
+* ADAPTER_HANDLE adapter_handle
+*
+* The adapter handle for the adapter so it can later be passed to the user
+* supplied user_receive_frame or user_completed_srb routine.
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pnp_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF or by the
+* ATULA in order to do a PIO data transfer. Note it could in fact be the
+* case that no interrupt has occured on the particular adapter being
+* checked.
+*
+* On SIF interrupts, the interrupt is acknowledged and cleared. The value
+* in the SIF interrupt register is recorded in order to pass it to the
+* driver_interrupt_entry routine (along with the adapter details).
+*
+* On PIO interrupts, the length, direction and physical address of the
+* transfer is determined. A system provided routine is called to do the
+* data transfer itself. Note the EAGLE thinks it is doing a DMA transfer
+* - it is the ATULA which allows us to do it via in/out instructions. Also
+* note that the IO location for the PIO is mapped onto the location of the
+* EAGLE SIFDAT register - the PIO does not actually use the SIFDAT
+* register so it's value is not effected by this routine.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_pnp_interrupt_handler)
+#endif
+
+export void
+hwi_pnp_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ WORD sifacl;
+ WORD sifint_value;
+ WORD sifint_tmp;
+ WBOOLEAN sifint_occurred = FALSE;
+ WBOOLEAN pioint_occurred = FALSE;
+ BYTE FAR * pio_virtaddr;
+ WORD lo_word;
+ DWORD hi_word;
+ WORD pio_len_bytes;
+ WBOOLEAN pio_from_adapter;
+ ADAPTER_HANDLE adapter_handle;
+
+ adapter_handle = adapter->adapter_handle;
+
+ /*
+ * inform system about the IO ports we are going to access
+ * eanble maximum number of IO locations used by any adapter card
+ * do this so at driver level can disable IO not knowing adapter type
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * check for SIF interrupt or PIO interrupt
+ */
+
+ /*
+ * Mask off any further interrupts while we read SIFINT (note that this
+ * does not mask off Pseudo DMA interrupts)
+ */
+
+ macro_clearw_bit(
+ adapter_handle,
+ adapter->sif_acl,
+ EAGLE_SIFACL_SINTEN
+ );
+
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ }
+ while (sifint_tmp != sifint_value);
+
+ if ((sifint_value & EAGLE_SIFINT_SYSTEM) != 0)
+ {
+ /*
+ * SIF interrupt has occurred
+ * SRB free, adapter check or received frame interrupt
+ */
+
+ sifint_occurred = TRUE;
+
+ /*
+ * clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF
+ */
+
+ sys_outsw(adapter_handle, adapter->sif_int, 0);
+ }
+
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+
+ if ((sifacl & EAGLE_SIFACL_SWHRQ) != 0)
+ {
+ /*
+ * PIO interrupt has occurred
+ * data transfer to/from adapter interrupt
+ */
+
+ pioint_occurred = TRUE;
+
+ macro_setw_bit(
+ adapter_handle,
+ adapter->sif_acl,
+ EAGLE_SIFACL_SWHLDA
+ );
+
+ /*
+ * determine what direction the data transfer is to take place in
+ */
+
+ pio_from_adapter = sys_insw(
+ adapter_handle,
+ adapter->sif_acl
+ ) & EAGLE_SIFACL_SWDDIR;
+
+ pio_len_bytes = sys_insw(
+ adapter_handle,
+ adapter->sif_dmalen
+ );
+
+ lo_word = sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadr
+ );
+
+ hi_word = (DWORD) sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadx
+ );
+
+ pio_virtaddr = (BYTE FAR *) ((hi_word << 16) | ((DWORD) lo_word));
+
+ /*
+ * do the actual data transfer
+ * note that Fastmac only copies whole WORDs to DWORD boundaries
+ * FastmacPlus, however, can transfer any length to any address.
+ */
+
+ if (pio_from_adapter)
+ {
+ /*
+ * transfer into host memory from adapter
+ */
+
+ /*
+ * transfer whole WORDs to Fastmac receive buffer
+ * NOT FORGETTING the possibility of a trailing byte.
+ */
+
+ sys_rep_insw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_virtaddr,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ if (pio_len_bytes % 2)
+ {
+ /*
+ * Finally transfer any trailing byte.
+ */
+
+ *(pio_virtaddr + pio_len_bytes - 1) =
+ sys_insb(adapter_handle, adapter->sif_sdmadat);
+ }
+ }
+ else
+ {
+ /*
+ * transfer into adapter memory from the host
+ */
+
+ sys_rep_outsw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_virtaddr,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ if (pio_len_bytes % 2)
+ {
+ sys_outsb(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ *(pio_virtaddr+pio_len_bytes-1)
+ );
+ }
+ }
+ }
+
+#ifndef FTK_NO_CLEAR_IRQ
+
+ if (sifint_occurred || pioint_occurred)
+ {
+ /*
+ * acknowledge/clear interrupt at interrupt controller
+ */
+
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+ }
+
+#endif
+
+ if (sifint_occurred)
+ {
+ /*
+ * call driver with details of SIF interrupt
+ */
+
+ driver_interrupt_entry(adapter_handle, adapter, sifint_value);
+ }
+
+ /*
+ * Read SIFACL until the SWHLDA bit has cleared.
+ */
+
+ do
+ {
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+ }
+ while ((sifacl & EAGLE_SIFACL_SWHLDA) != 0);
+
+ /*
+ * Now set SINTEN in SIFACL to regenerate interrupts.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_acl,
+ (WORD) (sifacl | EAGLE_SIFACL_SINTEN)
+ );
+
+ /*
+ * let system know we have finished accessing the IO ports
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter );
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_pnp_remove_card
+* ====================
+*
+*
+* PARAMETERS (passed by hwi_remove_adapter) :
+* ===========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_pnp_remove_card routine is called by hwi_remove_adapter. It
+* disables interrupts if they are being used. It also resets the adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_pnp_remove_card)
+#endif
+
+export void
+hwi_pnp_remove_card(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location +
+ PNP_CONTROL_REGISTER_1;
+ WORD sifacl;
+
+ /*
+ * interrupt must be disabled at adapter before unpatching interrupt
+ * even in polling mode we must turn off interrupts at adapter
+ */
+
+ sifacl = sys_insw(adapter_handle, adapter->sif_acl);
+ sifacl = (sifacl & ~(EAGLE_SIFACL_PSDMAEN | EAGLE_SIFACL_SINTEN));
+
+ sys_outsw(adapter_handle,
+ adapter->sif_acl,
+ sifacl);
+
+ if (adapter->interrupts_on)
+ {
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(
+ adapter_handle,
+ adapter->interrupt_number);
+ }
+
+ adapter->interrupts_on = FALSE;
+ }
+
+
+ /*
+ * perform adapter reset, set PNP_CTRL1_NSRESET low
+ */
+
+ sys_outsb(adapter_handle, control_1, !PNP_CTRL1_NSRESET);
+}
+
+
+/****************************************************************************
+*
+* hwi_atula_set_dio_address
+* =========================
+*
+* The hwi_atula_set_dio_address routine is used, with ATULA cards, for
+* putting a 32 bit DIO address into the SIF DIO address and extended DIO
+* address registers. Note that the extended address register should be
+* loaded first.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_set_dio_address)
+#endif
+
+export void
+hwi_pnp_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * load extended DIO address register with top 16 bits of address
+ * always load extended address register first
+ */
+
+ sys_outsw(adapter_handle, sif_dio_adrx, (WORD)(dio_address >> 16));
+
+ /*
+ * load DIO address register with low 16 bits of address
+ */
+
+ sys_outsw(adapter_handle, sif_dio_adr, (WORD)(dio_address & 0x0000FFFF));
+
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pnp_read_node_address
+| ==========================
+|
+| The hwi_pnp_read_node_address routine reads in the node address from
+| the BIA, and checks that it is a valid Madge node address.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_read_node_address)
+#endif
+
+local WBOOLEAN
+hwi_pnp_read_node_address(
+ ADAPTER * adapter
+ )
+{
+ WORD ioport = adapter->io_location;
+
+ adapter->permanent_address.byte[0] = 0;
+ adapter->permanent_address.byte[1] = 0;
+ adapter->permanent_address.byte[2] = (BYTE) pnp_read_a_word(adapter, 15);
+ adapter->permanent_address.byte[3] = (BYTE) pnp_read_a_word(adapter, 14);
+ adapter->permanent_address.byte[4] = (BYTE) pnp_read_a_word(adapter, 13);
+ adapter->permanent_address.byte[5] = (BYTE) pnp_read_a_word(adapter, 12);
+
+ return (adapter->permanent_address.byte[2] == MADGE_NODE_BYTE_2);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pnp_valid_io_location
+| ==========================
+|
+| The hwi_pnp_valid_io_location routine checks to see if the user has
+| supplied a valid IO location for a PNP adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_valid_io_location)
+#endif
+
+local WBOOLEAN
+hwi_pnp_valid_io_location(
+ WORD io_location
+ )
+{
+ WBOOLEAN io_valid;
+
+ switch (io_location)
+ {
+
+ case 0x1A20 :
+ case 0x2A20 :
+ case 0x3A20 :
+
+ /*
+ * The following are needed coz Chicago won't configure our
+ * PNP card at xA20 (a problem with Chicago !??)
+ */
+
+ case 0x0140 : /* In case CHICAGO cant find a free one */
+
+ /*
+ * It (Chicago) also wont allow cards to be at a 10 bit alias
+ * of each other ! (despite the fact we set the bit that says
+ * we fully decode all sixteen bits of the address !!)
+ */
+
+ case 0x0920 :
+ case 0x0940 :
+ case 0x0960 :
+ case 0x0980 :
+
+ case 0x0A20 :
+ case 0x0A40 :
+ case 0x0A60 :
+ case 0x0A80 :
+ case 0x0AA0 :
+
+ case 0x0B20 :
+ case 0x0B40 :
+ case 0x0B60 :
+ case 0x0B80 :
+
+ /*
+ * These are the valid user supplied io locations
+ */
+ io_valid = TRUE;
+ break;
+
+
+ default :
+
+ /*
+ * Anything else is invalid
+ */
+ io_valid = FALSE;
+ break;
+ }
+
+ return io_valid;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pnp_valid_irq_channel
+| ==========================
+|
+| The hwi_pnp_valid_irq_channel routine checks to see if the user has
+| supplied a valid interrupt number for a PNP
+|
+| If the user has stated that polling mode is to be used, then this is
+| always okay. If not, then a check is made that the user given interrupt
+| number is a valid number for the card type.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_valid_irq_channel)
+#endif
+
+local WBOOLEAN
+hwi_pnp_valid_irq_channel(
+ ADAPTER * adapter
+ )
+{
+ WBOOLEAN int_valid;
+
+ /*
+ * assume that interrupt number is valid
+ */
+
+ int_valid = TRUE;
+
+ /*
+ * no need to do any check on interrupt number if in polling mode
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ /*
+ * Can only check that the interrupt number given is valid
+ */
+
+ switch (adapter->interrupt_number)
+ {
+ case 2 :
+ case 3 :
+ case 7 :
+ case 9 :
+ case 10 :
+ case 11 :
+ case 15 :
+ break;
+
+ default :
+ int_valid = FALSE;
+ break;
+
+ }
+ }
+
+ if (!int_valid)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_03_BAD_INTERRUPT_NUMBER;
+ }
+
+ return int_valid;
+}
+
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| hwi_pnp_probe_find_card
+| =======================
+|
+| The hwi_pnp_find_card checks if a PNP card is at a particular location.
+| This is called by the probe routines.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_probe_find_card)
+#endif
+
+local WBOOLEAN
+hwi_pnp_probe_find_card(
+ WORD io_location
+ )
+{
+ WORD id_reg = io_location + PNP_ID_REGISTER;
+ WORD i;
+
+ /*
+ * Search for leading 'm'
+ */
+
+ for (i = 0; i < 4; i++)
+ {
+ if (sys_insb(0 , id_reg) == 'm')
+ {
+ /*
+ * Next byte must be 'd'.
+ */
+
+ if (sys_insb(0 , id_reg) == 'd')
+ {
+ return TRUE;
+ }
+ }
+ }
+
+ /*
+ * PNP ID not seen, or incorrect!
+ */
+
+ return FALSE;
+}
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pnp_probe_get_irq
+| =====================
+|
+| The hwi_pnp_gwt_irq gets the Interrupt used by a plug and play card.
+| This is called by the probe routines.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_probe_get_irq)
+#endif
+
+local WORD
+hwi_pnp_probe_get_irq(
+ WORD io_location
+ )
+{
+ WORD interrupt;
+
+ sys_probe_outsb(
+ (io_location + PNP_CONFIG_ADDRESS_REGISTER),
+ PNP_VENDOR_CONFIG_IRQ);
+
+ interrupt = (WORD)sys_probe_insb(
+ (io_location+PNP_CONFIG_DATA_REGISTER));
+
+ return interrupt;
+}
+
+
+
+#endif
+
+/*---------------------------------------------------------------------------
+|
+| hwi_pnp_test_for_id
+| ===================
+|
+| The hwi_pnp_test_for_id routine confirms that a real PNP card exists
+| at the supplied addreess by checking the contents of the ID register.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_pnp_test_for_id)
+#endif
+
+local WBOOLEAN
+hwi_pnp_test_for_id(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD id_reg = adapter->io_location + PNP_ID_REGISTER;
+ WORD i;
+
+ /*
+ * Search for leading 'm'
+ */
+ for (i = 0; i < 4; i++)
+ {
+ if (sys_insb(adapter_handle, id_reg) == 'm')
+ {
+ /*
+ * Next byte must be 'd'
+ */
+ if (sys_insb(adapter_handle, id_reg) == 'd')
+ {
+ return TRUE;
+ }
+ break;
+ }
+ }
+
+ /*
+ * PNP ID not seen, or incorrect.
+ */
+ return FALSE;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifndef FTK_NO_PROBE
+
+/************************************************************************
+ *
+ * Support routines for the serial device fitted to the Plug aNd Play
+ * cards. To be used by the probe functions.
+ *
+ ************************************************************************/
+
+local void pnp_probe_delay( WORD io_location );
+local void pnp_probe_set_clk( WORD io_location );
+local void pnp_probe_clr_clk( WORD io_location );
+local void pnp_probe_twitch_clk( WORD io_location );
+local void pnp_probe_start_bit( WORD io_location );
+local void pnp_probe_stop_bit( WORD io_location );
+local WBOOLEAN pnp_probe_wait_ack( WORD io_location );
+local WBOOLEAN pnp_probe_dummy_wait_ack(WORD io_location );
+
+
+/************************************************************************
+ * Read a byte from the control register for the specified adapter.
+ *
+ * Inputs : Adapter structure.
+ *
+ * Outputs : Value read from control register.
+ ***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_read_ctrl)
+#endif
+
+local WORD pnp_probe_read_ctrl( WORD io_location )
+{
+ return sys_probe_insb( io_location + PNP_CON_REG_OFFSET );
+}
+
+
+/************************************************************************
+ * Write a byte to the control register for the specified adapter.
+ *
+ * Inputs : Adapter structure.
+ * The data to be written.
+ *
+ * Outputs : None.
+ ***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_write_ctrl)
+#endif
+
+local void pnp_probe_write_ctrl( WORD io_location, WORD data)
+{
+ sys_probe_outsb( io_location + PNP_CON_REG_OFFSET, (BYTE)data );
+}
+
+
+/************************************************************************
+ * Delay to allow for serial device timing issues
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_delay)
+#endif
+
+local void pnp_probe_delay( WORD io_location )
+{
+ UINT i;
+
+ for (i = 0; i < PNP_DELAY_CNT; i++)
+ {
+ sys_probe_insb( io_location );
+ }
+}
+
+/************************************************************************
+ * Set the serial device clock bit
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_set_clk)
+#endif
+
+local void pnp_probe_set_clk( WORD io_location )
+{
+ WORD temp;
+
+ temp = pnp_probe_read_ctrl( io_location );
+ temp |= PNP_SSK;
+
+ pnp_probe_write_ctrl( io_location, temp);
+
+ pnp_probe_delay( io_location );
+}
+
+
+/************************************************************************
+ * Clears the serial device clock bit
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_clr_clk)
+#endif
+
+local void pnp_probe_clr_clk( WORD io_location )
+{
+ WORD temp;
+
+ temp = pnp_probe_read_ctrl( io_location );
+ temp &= ~PNP_SSK;
+
+ pnp_probe_write_ctrl( io_location, temp);
+
+ pnp_probe_delay( io_location );
+}
+
+
+/************************************************************************
+ * Puts the serial device data port into OUTPUT mode
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_set_eeden)
+#endif
+
+local void pnp_probe_set_eeden( WORD io_location )
+{
+ WORD temp;
+
+ temp = pnp_probe_read_ctrl( io_location );
+ temp |= PNP_EEDEN;
+
+ pnp_probe_write_ctrl( io_location , temp);
+
+ pnp_probe_delay( io_location );
+}
+
+
+/************************************************************************
+ * Puts the serial device data port into INPUT mode
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_clr_eeden)
+#endif
+
+local void pnp_probe_clr_eeden( WORD io_location )
+{
+ WORD temp;
+
+ temp = pnp_probe_read_ctrl( io_location );
+ temp &= ~PNP_EEDEN;
+
+ pnp_probe_write_ctrl( io_location, temp);
+
+ pnp_probe_delay( io_location );
+}
+
+
+/************************************************************************
+ * Sets the clears the serial device clock bit to strobe data into device
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_twitch_clk)
+#endif
+
+local void pnp_probe_twitch_clk( WORD io_location )
+{
+ pnp_probe_set_clk( io_location );
+ pnp_probe_clr_clk( io_location );
+}
+
+
+/************************************************************************
+ * Sends a start bit to the serial device.
+ *
+ * This is done by a 1 to 0 transition of the data bit while the clock
+ * bit it 1.
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_start_bit)
+#endif
+
+local void pnp_probe_start_bit( WORD io_location )
+{
+ WORD temp;
+
+ temp = pnp_probe_read_ctrl( io_location );
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+ temp |= (PNP_EEDO + PNP_EEDEN);
+
+ pnp_probe_write_ctrl( io_location, temp);
+
+ pnp_probe_delay( io_location );
+
+ temp |= PNP_SSK;
+
+ pnp_probe_write_ctrl( io_location, temp);
+
+ pnp_probe_delay( io_location );
+
+ temp &= ~PNP_EEDO;
+
+ pnp_probe_write_ctrl( io_location , temp);
+
+ pnp_probe_delay( io_location );
+
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+
+ pnp_probe_write_ctrl( io_location , temp);
+
+ pnp_probe_delay( io_location );
+}
+
+
+/************************************************************************
+ * Sends a stop bit to the serial device.
+ *
+ * This is done by a 0 to 1 transition of the data bit while the clock
+ * bit it 1.
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_stop_bit)
+#endif
+
+local void pnp_probe_stop_bit( WORD io_location )
+{
+ WORD temp;
+
+ temp = pnp_probe_read_ctrl( io_location );
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+ temp |= (PNP_EEDEN);
+
+ pnp_probe_write_ctrl( io_location, temp);
+
+ pnp_probe_delay( io_location );
+
+ temp |= PNP_SSK;
+
+ pnp_probe_write_ctrl(io_location, temp);
+
+ pnp_probe_delay(io_location);
+
+ temp |= PNP_EEDO;
+
+ pnp_probe_write_ctrl(io_location, temp);
+
+ pnp_probe_delay(io_location);
+
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+
+ pnp_probe_write_ctrl(io_location, temp);
+
+ pnp_probe_delay(io_location);
+}
+
+
+/************************************************************************
+ * Waits for the serial device to say its accepted the last cmd/data
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : TRUE if OK, FALSE if it timed out
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_wait_ack)
+#endif
+
+local WBOOLEAN pnp_probe_wait_ack(WORD io_location)
+{
+ WORD temp;
+ WORD i;
+
+ temp = pnp_probe_read_ctrl(io_location);
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+
+ pnp_probe_write_ctrl(io_location, temp);
+
+ pnp_probe_delay(io_location);
+
+ for (i = 0; i < PNP_WAIT_CNT; i++)
+ {
+ pnp_probe_set_clk(io_location);
+
+ temp = pnp_probe_read_ctrl(io_location);
+
+ pnp_probe_clr_clk(io_location);
+
+ if (!(temp & PNP_EEDO))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/************************************************************************
+ * Waits for the serial device to say its passed the last of the data to
+ * be read.
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : TRUE if OK, FALSE if it timed out
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_dummy_wait_ack)
+#endif
+
+local WBOOLEAN pnp_probe_dummy_wait_ack(WORD io_location)
+{
+ WORD temp;
+ WORD i;
+
+ temp = pnp_probe_read_ctrl(io_location);
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+
+ pnp_probe_write_ctrl(io_location, temp);
+
+ pnp_probe_delay(io_location);
+
+ for (i = 0; i < PNP_WAIT_CNT ; i++)
+ {
+ pnp_probe_set_clk(io_location);
+
+ temp = pnp_probe_read_ctrl(io_location);
+
+ pnp_probe_clr_clk(io_location);
+
+ if (temp & PNP_EEDO)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/************************************************************************
+ * Writes a bit to the serial device
+ * be read.
+ *
+ * Inputs : Adapter structure
+ * The data bit to be written
+ *
+ * Outputs : TRUE if OK, FALSE if it timed out
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_write_data)
+#endif
+
+local void pnp_probe_write_data(WORD io_location, WORD data)
+{
+ WORD temp;
+
+ temp = pnp_probe_read_ctrl(io_location);
+ temp &= ~(PNP_EEDO);
+ temp |= (data & 0x0080) >> 6;
+
+ pnp_probe_write_ctrl(io_location, temp);
+
+ pnp_probe_delay(io_location);
+}
+
+
+/************************************************************************
+ *
+ * Routine to read a byte from the serial device fitted to the Plug aNd Play
+ * cards.
+ *
+ * Inputs : Adapter structure.
+ * Offset (address) in the serial device to read
+ *
+ * Outputs : A word with the interstng byte in the LSB
+ *
+ * RCS 22/07/94
+ *
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_probe_read_a_word)
+#endif
+
+local WORD pnp_probe_read_a_word(WORD io_location, WORD index)
+{
+ WORD temp;
+ WORD data_byte = 0;
+ WORD i;
+
+ /*
+ * Wake up the device
+ */
+ pnp_probe_start_bit(io_location);
+
+ /*
+ * Set data 'OUTPUT' mode
+ */
+ pnp_probe_set_eeden(io_location);
+
+ /*
+ * 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++)
+ {
+ pnp_probe_write_data(io_location, temp);
+ pnp_probe_twitch_clk(io_location);
+ temp = temp << 1;
+ }
+
+ if (!pnp_probe_wait_ack(io_location))
+ {
+ /*
+ * Return sommat invalid if it timed out !
+ */
+ return 0xffff;
+ }
+
+ /*
+ * Set data 'OUTPUT' mode
+ */
+ pnp_probe_set_eeden(io_location);
+
+ /*
+ * Send Address in ROM
+ */
+ temp = index;
+
+ /*
+ * MSB first !
+ */
+ for (i = 0; i < 8; i++)
+ {
+ pnp_probe_write_data(io_location, temp);
+ pnp_probe_twitch_clk(io_location);
+ temp = temp << 1;
+ }
+
+ if (!pnp_probe_wait_ack(io_location))
+ {
+ /*
+ * Return sommat invalid if it timed out !
+ */
+ return 0xffff;
+ }
+
+ pnp_probe_start_bit(io_location);
+
+ /*
+ * Set data 'OUTPUT' mode
+ */
+ pnp_probe_set_eeden(io_location);
+
+ /*
+ * Send READ CMD
+ */
+ temp = PNP_READ_CMD;
+
+ /*
+ * MSB first !
+ */
+ for (i = 0; i < 8 ;i++)
+ {
+ pnp_probe_write_data(io_location, temp);
+ pnp_probe_twitch_clk(io_location);
+ temp = temp << 1;
+ }
+
+ if (!pnp_probe_wait_ack(io_location))
+ {
+ /*
+ * Return sommat invalid if it timed out !
+ */
+ return 0xffff;
+ }
+
+ /*
+ * Set data 'INPUT' mode
+ */
+ pnp_probe_clr_eeden(io_location);
+
+ /*
+ * Now read the serial data - MSB first !
+ */
+ for (i = 0; i < 8 ;i++)
+ {
+ pnp_probe_set_clk(io_location);
+
+ temp = pnp_probe_read_ctrl(io_location);
+
+ pnp_probe_clr_clk(io_location);
+
+ temp &= PNP_EEDO;
+ temp = temp >> 1;
+ data_byte = data_byte << 1;
+ data_byte &= 0xfffe;
+ data_byte |= temp;
+ }
+
+ if (!pnp_probe_dummy_wait_ack(io_location))
+ {
+ /*
+ * Return sommat invalid if it timed out !
+ */
+
+ return 0xffff;
+ }
+
+ pnp_probe_stop_bit(io_location);
+
+ return data_byte;
+}
+
+#endif
+
+/************************************************************************
+ *
+ * Support routines for the serial device fitted to the Plug aNd Play
+ * cards.
+ *
+ * RCS 22/07/94
+ *
+ ************************************************************************/
+
+
+local void pnp_delay(ADAPTER *);
+local void pnp_set_clk(ADAPTER *);
+local void pnp_clr_clk(ADAPTER *);
+local void pnp_twitch_clk(ADAPTER *);
+local void pnp_start_bit(ADAPTER *);
+local void pnp_stop_bit(ADAPTER *);
+local WBOOLEAN pnp_wait_ack(ADAPTER *);
+local WBOOLEAN pnp_dummy_wait_ack(ADAPTER *);
+local void pnp_write_data(ADAPTER *, WORD);
+
+
+/************************************************************************
+ * Read a byte from the control register for the specified adapter.
+ *
+ * Inputs : Adapter structure.
+ *
+ * Outputs : Value read from control register.
+ ***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_read_ctrl)
+#endif
+
+local WORD pnp_read_ctrl(ADAPTER * adapter)
+{
+ return sys_insb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PNP_CON_REG_OFFSET)
+ );
+}
+
+
+/************************************************************************
+ * Write a byte to the control register for the specified adapter.
+ *
+ * Inputs : Adapter structure.
+ * The data to be written.
+ *
+ * Outputs : None.
+ ***********************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_write_ctrl)
+#endif
+
+local void pnp_write_ctrl(ADAPTER * adapter, WORD data)
+{
+ sys_outsb(
+ adapter->adapter_handle,
+ (WORD) (adapter->io_location + PNP_CON_REG_OFFSET),
+ (BYTE) data
+ );
+}
+
+
+/************************************************************************
+ * Delay to allow for serial device timing issues
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_delay)
+#endif
+
+local void pnp_delay(ADAPTER * adapter)
+{
+ WORD i;
+
+ for (i = 0; i < PNP_DELAY_CNT; i++)
+ {
+ sys_insb(adapter->adapter_handle, adapter->io_location);
+ }
+}
+
+
+/************************************************************************
+ * Set the serial device clock bit
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_set_clk)
+#endif
+
+local void pnp_set_clk(ADAPTER * adapter)
+{
+ WORD temp;
+
+ temp = pnp_read_ctrl(adapter);
+ temp |= PNP_SSK;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+}
+
+
+/************************************************************************
+ * Clears the serial device clock bit
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_clr_clk)
+#endif
+
+local void pnp_clr_clk(ADAPTER * adapter)
+{
+ WORD temp;
+
+ temp = pnp_read_ctrl(adapter);
+ temp &= ~PNP_SSK;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+}
+
+
+/************************************************************************
+ * Puts the serial device data port into OUTPUT mode
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_set_eeden)
+#endif
+
+local void pnp_set_eeden(ADAPTER * adapter)
+{
+ WORD temp;
+
+ temp = pnp_read_ctrl(adapter);
+ temp |= PNP_EEDEN;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+}
+
+
+/************************************************************************
+ * Puts the serial device data port into INPUT mode
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_clr_eeden)
+#endif
+
+local void pnp_clr_eeden(ADAPTER * adapter)
+{
+ WORD temp;
+
+ temp = pnp_read_ctrl(adapter);
+ temp &= ~PNP_EEDEN;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+}
+
+
+/************************************************************************
+ * Sets the clears the serial device clock bit to strobe data into device
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_twitch_clk)
+#endif
+
+local void pnp_twitch_clk(ADAPTER * adapter)
+{
+ pnp_set_clk(adapter);
+ pnp_clr_clk(adapter);
+}
+
+
+/************************************************************************
+ * Sends a start bit to the serial device.
+ *
+ * This is done by a 1 to 0 transition of the data bit while the clock
+ * bit it 1.
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_start_bit)
+#endif
+
+local void pnp_start_bit(ADAPTER * adapter)
+{
+ WORD temp;
+
+ temp = pnp_read_ctrl(adapter);
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+ temp |= (PNP_EEDO + PNP_EEDEN);
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+
+ temp |= PNP_SSK;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+
+ temp &= ~PNP_EEDO;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+}
+
+
+/************************************************************************
+ * Sends a stop bit to the serial device.
+ *
+ * This is done by a 0 to 1 transition of the data bit while the clock
+ * bit it 1.
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : None
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_stop_bit)
+#endif
+
+local void pnp_stop_bit(ADAPTER * adapter)
+{
+ WORD temp;
+
+ temp = pnp_read_ctrl(adapter);
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+ temp |= (PNP_EEDEN);
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+
+ temp |= PNP_SSK;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+
+ temp |= PNP_EEDO;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+}
+
+
+/************************************************************************
+ * Waits for the serial device to say its accepted the last cmd/data
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : TRUE if OK, FALSE if it timed out
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_wait_ack)
+#endif
+
+local WBOOLEAN pnp_wait_ack(ADAPTER * adapter)
+{
+ WORD temp;
+ WORD i;
+
+ temp = pnp_read_ctrl(adapter);
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+
+ for (i = 0; i < PNP_WAIT_CNT; i++)
+ {
+ pnp_set_clk(adapter);
+
+ temp = pnp_read_ctrl(adapter);
+
+ pnp_clr_clk(adapter);
+
+ if (!(temp & PNP_EEDO))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/************************************************************************
+ * Waits for the serial device to say its passed the last of the data to
+ * be read.
+ *
+ * Inputs : Adapter structure
+ *
+ * Outputs : TRUE if OK, FALSE if it timed out
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_dummy_wait_ack)
+#endif
+
+local WBOOLEAN pnp_dummy_wait_ack(ADAPTER * adapter)
+{
+ WORD temp;
+ WORD i;
+
+ temp = pnp_read_ctrl(adapter);
+ temp &= ~(PNP_EEDO + PNP_EEDEN + PNP_SSK);
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+
+ for (i = 0; i < PNP_WAIT_CNT ; i++)
+ {
+ pnp_set_clk(adapter);
+
+ temp = pnp_read_ctrl(adapter);
+
+ pnp_clr_clk(adapter);
+
+ if (temp & PNP_EEDO)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/************************************************************************
+ * Writes a bit to the serial device
+ * be read.
+ *
+ * Inputs : Adapter structure
+ * The data bit to be written
+ *
+ * Outputs : TRUE if OK, FALSE if it timed out
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_write_data)
+#endif
+
+local void pnp_write_data(ADAPTER * adapter, WORD data)
+{
+ WORD temp;
+
+ temp = pnp_read_ctrl(adapter);
+ temp &= ~(PNP_EEDO);
+ temp |= (data & 0x0080) >> 6;
+
+ pnp_write_ctrl(adapter, temp);
+
+ pnp_delay(adapter);
+}
+
+
+/************************************************************************
+ *
+ * Routine to read a byte from the serial device fitted to the Plug aNd Play
+ * cards.
+ *
+ * Inputs : Adapter structure.
+ * Offset (address) in the serial device to read
+ *
+ * Outputs : A word with the interstng byte in the LSB
+ *
+ * RCS 22/07/94
+ *
+ ************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(pnp_read_a_word)
+#endif
+
+local WORD pnp_read_a_word(ADAPTER * adapter, WORD index)
+{
+ WORD temp;
+ WORD data_byte = 0;
+ WORD i;
+
+ /*
+ * Wake up the device
+ */
+ pnp_start_bit(adapter);
+
+ /*
+ * Set data 'OUTPUT' mode
+ */
+ pnp_set_eeden(adapter);
+
+ /*
+ * 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++)
+ {
+ pnp_write_data(adapter, temp);
+ pnp_twitch_clk(adapter);
+ temp = temp << 1;
+ }
+
+ if (!pnp_wait_ack(adapter))
+ {
+ /*
+ * Return sommat invalid if it timed out !
+ */
+ return 0xffff;
+ }
+
+ /*
+ * Set data 'OUTPUT' mode
+ */
+ pnp_set_eeden(adapter);
+
+ /*
+ * Send Address in ROM
+ */
+ temp = index;
+
+ /*
+ * MSB first !
+ */
+ for (i = 0; i < 8; i++)
+ {
+ pnp_write_data(adapter, temp);
+ pnp_twitch_clk(adapter);
+ temp = temp << 1;
+ }
+
+ if (!pnp_wait_ack(adapter))
+ {
+ /*
+ * Return sommat invalid if it timed out !
+ */
+ return 0xffff;
+ }
+
+ pnp_start_bit(adapter);
+
+ /*
+ * Set data 'OUTPUT' mode
+ */
+ pnp_set_eeden(adapter);
+
+ /*
+ * Send READ CMD
+ */
+ temp = PNP_READ_CMD;
+
+ /*
+ * MSB first !
+ */
+ for (i = 0; i < 8 ;i++)
+ {
+ pnp_write_data(adapter, temp);
+ pnp_twitch_clk(adapter);
+ temp = temp << 1;
+ }
+
+ if (!pnp_wait_ack(adapter))
+ {
+ /*
+ * Return sommat invalid if it timed out !
+ */
+ return 0xffff;
+ }
+
+ /*
+ * Set data 'INPUT' mode
+ */
+ pnp_clr_eeden(adapter);
+
+ /*
+ * Now read the serial data - MSB first !
+ */
+ for (i = 0; i < 8 ;i++)
+ {
+ pnp_set_clk(adapter);
+
+ temp = pnp_read_ctrl(adapter);
+
+ pnp_clr_clk(adapter);
+
+ temp &= PNP_EEDO;
+ temp = temp >> 1;
+ data_byte = data_byte << 1;
+ data_byte &= 0xfffe;
+ data_byte |= temp;
+ }
+
+ if (!pnp_dummy_wait_ack(adapter))
+ {
+ /*
+ * Return sommat invalid if it timed out !
+ */
+ return 0xffff;
+ }
+
+ pnp_stop_bit(adapter);
+
+ return data_byte;
+}
+
+#endif
+
+/******** End of HWI_PNP.C *************************************************/
diff --git a/private/ntos/ndis/madge/driver/hwi_sm16.c b/private/ntos/ndis/madge/driver/hwi_sm16.c
new file mode 100644
index 000000000..75c637c21
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/hwi_sm16.c
@@ -0,0 +1,1191 @@
+/****************************************************************************
+*
+* HWI_SM16.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* HARDWARE INTERFACE MODULE FOR SMART 16 CARDS
+*
+* Copyright (c) Madge Networks Ltd. 1994
+*
+* COMPANY CONFIDENTIAL
+*
+*
+*****************************************************************************
+*
+* The purpose of the Hardware Interface (HWI) is to supply an adapter card
+* independent interface to any driver. It performs nearly all of the
+* functions that involve affecting SIF registers on the adapter cards.
+* This includes downloading code to, initializing, and removing adapters.
+*
+* The HWI_SM16.C module contains the routines specific to the Smart16 card
+* which are necessary to install an adapter, to initialize an adapter, to
+* remove an adapter, and to handle interrupts on an adapter.
+*
+/***************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+#ifndef FTK_NO_SMART16
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+local WBOOLEAN
+hwi_smart16_read_node_address(
+ ADAPTER * adapter
+ );
+
+local WBOOLEAN
+hwi_smart16_valid_io_location(
+ WORD io_location
+ );
+
+local WBOOLEAN
+hwi_smart16_valid_transfer_mode(
+ UINT transfer_mode
+ );
+
+#ifndef FTK_NO_PROBE
+
+local WBOOLEAN
+hwi_smart16_check_for_card(
+ WORD io_location
+ );
+
+#endif
+
+local WBOOLEAN
+hwi_smart16_valid_irq_channel(
+ ADAPTER * adapter
+ );
+
+#ifndef FTK_NO_PROBE
+/****************************************************************************
+*
+* hwi_smart16_probe_card
+* ======================
+*
+*
+* PARAMETERS (passed by hwi_probe_adapter) :
+* ==========================================
+*
+* PROBE * resources
+*
+* resources is an array structures used to identify and record specific
+* information about adapters found.
+*
+* UINT length
+*
+* length is the number of structures pointed to by reources.
+*
+* WORD * valid_locations
+*
+* valid_locations is an array of IO locations to examine for the presence
+* of an adapter. For smart 16 adapters with should be a subset of
+* {0x4a20, 0x4e20, 0x6a20, 0x6e20}.
+*
+* UINT number_locations
+*
+* This is the number of IO locations in the above list.
+*
+* BODY :
+* ======
+*
+* The hwi_smart16_probe_card routine is called by hwi_probe_adapter. It
+* checks for the existence of a card by reading its node address. This is
+* about all we can do for a smart 16.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns the number of adapters found, or PROBE_FAILURE if
+* there's a problem.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_smart16_probe_card)
+#endif
+
+export UINT
+hwi_smart16_probe_card(
+ PROBE * resources,
+ UINT length,
+ WORD * valid_locations,
+ UINT number_locations
+ )
+{
+ WORD control_1;
+ WORD control_2;
+ UINT i;
+ UINT j;
+
+ /*
+ * Check the bounds are sensible.
+ */
+
+ if(length <= 0 || number_locations <= 0)
+ {
+ return PROBE_FAILURE;
+ }
+
+ /*
+ * Range check the IO locations.
+ */
+
+ for(i = 0; i < number_locations; i++)
+ {
+ if(!hwi_smart16_valid_io_location(valid_locations[i]))
+ {
+ return PROBE_FAILURE;
+ }
+ }
+
+ /*
+ * j is the number of adapters found.
+ */
+
+ j = 0;
+
+ for(i = 0; i < number_locations; i++)
+ {
+ /*
+ * Check we aren't out of PROBE structures.
+ */
+
+ if(j >= length)
+ {
+ return j;
+ }
+
+ /*
+ * Set up the control register locations.
+ */
+
+ control_1 = valid_locations[i] + SMART16_CONTROL_REGISTER_1;
+ control_2 = valid_locations[i] + SMART16_CONTROL_REGISTER_2;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_enable_io(valid_locations[i], SMART16_IO_RANGE);
+#endif
+ /*
+ * Reset the card.
+ */
+
+ sys_probe_outsb(control_1, 0);
+
+ if (hwi_smart16_check_for_card(valid_locations[i]))
+ {
+
+ /*
+ * We have obviously found a valid smart 16 by this point so
+ * set up some values.
+ */
+
+ resources[j].adapter_card_bus_type = ADAPTER_CARD_SMART16_BUS_TYPE;
+ resources[j].adapter_card_type = ADAPTER_CARD_TYPE_SMART_16;
+ resources[j].adapter_card_revision = ADAPTER_CARD_SMART_16;
+ resources[j].adapter_ram_size = 128;
+ resources[j].io_location = valid_locations[i];
+ resources[j].interrupt_number = SMART16_DEFAULT_INTERRUPT;
+ resources[j].dma_channel = 0;
+ resources[j].transfer_mode = PIO_DATA_TRANSFER_MODE;
+
+ /*
+ * And increment j to point at the next free PROBE structure.
+ */
+
+ j++;
+ }
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_probe_disable_io(resources->io_location, SMART16_IO_RANGE);
+#endif
+
+ }
+
+ return j;
+}
+#endif
+
+/****************************************************************************
+*
+* hwi_smart16_install_card
+* ========================
+*
+*
+* PARAMETERS (passed by hwi_install_adapter) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+* DOWNLOAD_IMAGE * download_image
+*
+* This is the code to be downloaded to the adapter. The image must be of
+* the correct type i.e. must be downloadable into the adapter. If the
+* pointer is 0 downloading is not done.
+*
+*
+* BODY :
+* ======
+*
+* hwi_smart16_install_card is called by hwi_install_adapter. It sets up
+* the adapter card and downloads the required code to it. Firstly, it
+* checks there is a valid adapter at the required IO address by reading
+* the node address from the BIA PROM. It then sets up and checks various
+* on-board registers for correct operation.
+*
+* Then, it halts the EAGLE, downloads the code, restarts the EAGLE and
+* waits up to 3 seconds for a valid bring-up code. If interrupts are
+* required, these are enabled by operating system specific calls.
+* The adapter is set up for Eagle Pseudo-DMA, since real DMA is not used.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine returns TRUE if it succeeds. If this routine fails (returns
+* FALSE) then a subsequent call to driver_explain_error, with the adapter
+* handle corresponding to the adapter parameter used here, will give an
+* explanation.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_smart16_install_card)
+#endif
+
+export WBOOLEAN
+hwi_smart16_install_card(
+ ADAPTER * adapter,
+ DOWNLOAD_IMAGE * download_image
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location +
+ SMART16_CONTROL_REGISTER_1;
+ WORD control_2 = adapter->io_location +
+ SMART16_CONTROL_REGISTER_2;
+ WORD sif_base;
+
+ /*
+ * Check the IO location is valid.
+ */
+
+ if(!hwi_smart16_valid_io_location(adapter->io_location))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION;
+
+ return FALSE;
+ }
+
+ /*
+ * Check the transfer mode is valid.
+ */
+
+ if(!hwi_smart16_valid_transfer_mode(adapter->transfer_mode))
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_02_BAD_IO_LOCATION;
+
+ return FALSE;
+ }
+
+ if (!hwi_smart16_valid_irq_channel(adapter))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Record the locations of the SIF registers.
+ */
+
+ sif_base = adapter->io_location + SMART16_FIRST_SIF_REGISTER;
+
+ adapter->sif_dat = sif_base + EAGLE_SIFDAT;
+ adapter->sif_datinc = sif_base + EAGLE_SIFDAT_INC;
+ adapter->sif_adr = sif_base + EAGLE_SIFADR;
+ adapter->sif_int = sif_base + EAGLE_SIFINT;
+ adapter->sif_acl = sif_base + EAGLE_SIFACL;
+ adapter->sif_adr2 = sif_base + EAGLE_SIFADR;
+ adapter->sif_adx = sif_base + EAGLE_SIFADX;
+ adapter->sif_dmalen = sif_base + EAGLE_DMALEN;
+ adapter->sif_sdmadat = sif_base + EAGLE_SDMADAT;
+ adapter->sif_sdmaadr = sif_base + EAGLE_SDMAADR;
+ adapter->sif_sdmaadx = sif_base + EAGLE_SDMAADX;
+
+ adapter->io_range = SMART16_IO_RANGE;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * You might want to check that we have not already checked for a card
+ * at this address (or its rev3/4 equivalent).
+ */
+
+ /*
+ * Reset adapter (SMART16_CTRL1_SRESET = 0). This is necessary for
+ * reading the BIA.
+ */
+
+ sys_outsb(adapter_handle, control_1, 0);
+
+ /*
+ * Read the node address for the specified IO location. This will check
+ * that it is a valid Madge address, which is the only way we have of
+ * identifying the card.
+ */
+
+ if (!hwi_smart16_read_node_address(adapter))
+ {
+ /*
+ * Fill in error record and return
+ */
+
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_05_ADAPTER_NOT_FOUND;
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+
+ return FALSE;
+ }
+
+ /*
+ * Make sure that SCS bit is zero (see below where we bring card out of
+ * reset).
+ */
+
+ sys_outsb(adapter_handle, control_1, 0);
+
+ /*
+ * nselout_bits are needed to select the IRQ on the card.
+ */
+
+ switch (adapter->interrupt_number)
+ {
+ case 2 :
+ adapter->nselout_bits = SMART16_IRQ_2;
+ break;
+ case 3 :
+ adapter->nselout_bits = SMART16_IRQ_3;
+ break;
+ case 7 :
+ adapter->nselout_bits = SMART16_IRQ_7;
+ break;
+ default :
+ break;
+
+ }
+
+ /*
+ * These things can all be assumed for the smart16.
+ */
+
+ adapter->adapter_card_type = ADAPTER_CARD_TYPE_SMART_16;
+ adapter->adapter_card_revision = ADAPTER_CARD_SMART_16;
+ adapter->adapter_ram_size = 128;
+ adapter->edge_triggered_ints = TRUE;
+ adapter->EaglePsDMA = TRUE;
+ adapter->max_frame_size = MAX_FRAME_SIZE_16_MBITS;
+ adapter->ring_speed = 16;
+
+ /*
+ * Bring adapter out of reset state (ensure that SCS is zero before
+ * doing this).
+ */
+
+ sys_outsb(adapter_handle, control_1, 1);
+
+ /*
+ * Halt the Eagle prior to downloading the MAC code - this will also
+ * write the interrupt bits into the SIFACL register, where the MAC can
+ * find them.
+ */
+
+ hwi_halt_eagle(adapter);
+
+ /*
+ * Download code to adapter.
+ * View download image as a sequence of download records. Pass address
+ * of routine to set up DIO addresses on ATULA cards.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!hwi_download_code(adapter,
+ (DOWNLOAD_RECORD *) download_image,
+ hwi_smart16_set_dio_address))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Restart the Eagle to initiate bring up diagnostics.
+ */
+
+ hwi_start_eagle(adapter);
+
+ /*
+ * Wait for a valid bring up code, may wait 3 seconds.
+ * If routine fails return failure (error record already filled in).
+ */
+
+ if (!hwi_get_bring_up_code(adapter))
+ {
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+
+ /*
+ * Set DIO address to point to EAGLE DATA page 0x10000L.
+ */
+
+ hwi_smart16_set_dio_address(adapter, DIO_LOCATION_EAGLE_DATA_PAGE);
+
+ /*
+ * If not in polling mode then set up interrupts.
+ * Interrupts_on field is used when disabling interrupts for adapter.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ adapter->interrupts_on =
+ sys_enable_irq_channel(adapter_handle, adapter->interrupt_number);
+
+ /*
+ * If fail enable irq channel then fill in error record and return.
+ */
+
+ if (!adapter->interrupts_on)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_0B_FAIL_IRQ_ENABLE;
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return FALSE;
+ }
+ }
+ else
+ {
+ adapter->interrupts_on = TRUE;
+ }
+
+ /* return successfully */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+ return TRUE;
+
+}
+
+
+/****************************************************************************
+*
+* hwi_smart16_interrupt_handler
+* =============================
+*
+*
+* PARAMETERS (passed by hwi_interrupt_entry) :
+* ============================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_smart16_interrupt_handler routine is called, when an interrupt
+* occurs, by hwi_interrupt_entry. It checks to see if a particular card
+* has interrupted. The interrupt could be generated by the SIF for either
+* a PIO data transfer or a normal condition (received frame, SRB complete,
+* ARB indication etc). Note it could in fact be the case that no interrupt
+* has occured on the particular adapter being checked.
+*
+* On normal SIF interrupts, the interrupt is acknowledged and cleared. The
+* value in the SIF interrupt register is recorded in order to pass it to
+* the driver_interrupt_entry routine (along with the adapter details).
+*
+* On PseudoDMA interrupts, the length, direction and physical address of
+* the transfer is determined. A system provided routine is called to do
+* the data transfer itself.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_IRQ_FUNCTION
+#pragma FTK_IRQ_FUNCTION(hwi_smart16_interrupt_handler)
+#endif
+
+export void
+hwi_smart16_interrupt_handler(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sifacl_value;
+ WORD sifint_value;
+ WORD sifint_tmp;
+ WBOOLEAN sifint_occurred = FALSE;
+ WBOOLEAN pioint_occurred = FALSE;
+ WORD pio_len_bytes;
+ WBOOLEAN pio_from_adapter;
+ BYTE FAR * pio_address;
+ WORD lo_word;
+ DWORD hi_word;
+
+ /*
+ * Inform system about the IO ports we are going to access.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ /*
+ * Check for SIF interrupt or PIO interrupt.
+ */
+
+ /*
+ * Mask off any further interrupts while we read SIFINT (note that this
+ * does not mask off Pseudo DMA interrupts).
+ */
+
+ macro_clearw_bit(
+ adapter_handle,
+ adapter->sif_acl,
+ EAGLE_SIFACL_SINTEN
+ );
+
+ sifint_value = sys_insw(adapter_handle, adapter->sif_int);
+ do
+ {
+ sifint_tmp = sifint_value;
+ sifint_value = sys_insw(
+ adapter_handle,
+ adapter->sif_int
+ );
+ }
+ while (sifint_tmp != sifint_value);
+
+ if ((sifint_value & EAGLE_SIFINT_SYSTEM) != 0)
+ {
+ /*
+ * SIF interrupt has occurred.
+ * SRB free, adapter check or received frame interrupt.
+ */
+
+ sifint_occurred = TRUE;
+
+ /*
+ * Clear EAGLE_SIFINT_HOST_IRQ to acknowledge interrupt at SIF.
+ */
+
+ sys_outsw( adapter_handle, adapter->sif_int, 0);
+
+ }
+
+ sifacl_value = sys_insw(adapter_handle, adapter->sif_acl);
+
+ if ((sifacl_value & EAGLE_SIFACL_SWHRQ) != 0)
+ {
+ /*
+ * PIO interrupt has occurred.
+ * Data transfer to/from adapter interrupt.
+ */
+
+ pioint_occurred = TRUE;
+
+ macro_setw_bit(
+ adapter_handle,
+ adapter->sif_acl,
+ EAGLE_SIFACL_SWHLDA
+ );
+
+ /*
+ * Determine what direction the data transfer is to take place in.
+ */
+
+ pio_from_adapter = sys_insw(
+ adapter_handle,
+ adapter->sif_acl
+ ) & EAGLE_SIFACL_SWDDIR;
+
+ pio_len_bytes = sys_insw(
+ adapter_handle,
+ adapter->sif_dmalen
+ );
+
+ lo_word = sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadr
+ );
+
+ hi_word = (DWORD) sys_insw(
+ adapter_handle,
+ adapter->sif_sdmaadx
+ );
+
+ pio_address = (BYTE FAR *) ((hi_word << 16) | ((DWORD) lo_word));
+
+ /*
+ * Do the actual data transfer.
+ * Note that Fastmac only copies whole UINTs to DWORD boundaries.
+ * FastmacPlus, however, can transfer any length to any address.
+ */
+
+ if (pio_from_adapter)
+ {
+ /*
+ * Transfer into host memory from adapter.
+ * First, check if host address is on an odd byte boundary.
+ */
+
+ if ((card_t)pio_address % 2)
+ {
+ pio_len_bytes--;
+ *(pio_address++) =
+ sys_insb(adapter_handle,
+ (WORD) (adapter->sif_sdmadat + 1));
+ }
+
+ /*
+ * Now transfer the bulk of the data.
+ */
+
+ sys_rep_insw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1));
+
+ /*
+ * Finally transfer any trailing byte.
+ */
+
+ if (pio_len_bytes % 2)
+ {
+ *(pio_address+pio_len_bytes-1) =
+ sys_insb(adapter_handle,
+ adapter->sif_sdmadat);
+ }
+ }
+ else
+ {
+ /*
+ * Transfer into adapter memory from the host.
+ */
+
+ if ((card_t)pio_address % 2)
+ {
+ pio_len_bytes--;
+ sys_outsb(
+ adapter_handle,
+ (WORD) (adapter->sif_sdmadat + 1),
+ *(pio_address++)
+ );
+ }
+
+ sys_rep_outsw(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ pio_address,
+ (WORD) (pio_len_bytes >> 1)
+ );
+
+ if (pio_len_bytes % 2)
+ {
+ sys_outsb(
+ adapter_handle,
+ adapter->sif_sdmadat,
+ *(pio_address+pio_len_bytes-1)
+ );
+ }
+ }
+ }
+
+#ifndef FTK_NO_CLEAR_IRQ
+
+ if (sifint_occurred || pioint_occurred)
+ {
+ /*
+ * Acknowledge/clear interrupt at interrupt controller.
+ */
+ sys_clear_controller_interrupt(
+ adapter_handle,
+ adapter->interrupt_number);
+ }
+
+#endif
+
+ if (sifint_occurred)
+ {
+ /*
+ * Call driver with details of SIF interrupt.
+ */
+
+ driver_interrupt_entry(
+ adapter_handle,
+ adapter,
+ sifint_value);
+ }
+
+ /*
+ * Read SIFACL until the SWHLDA bit has cleared.
+ */
+
+ do
+ {
+ sifacl_value = sys_insw(adapter_handle, adapter->sif_acl);
+ }
+ while ((sifacl_value & EAGLE_SIFACL_SWHLDA) != 0);
+
+ /*
+ * Now set SINTEN in SIFACL to regenerate interrupts.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_acl,
+ (WORD) (sifacl_value | EAGLE_SIFACL_SINTEN)
+ );
+
+ /*
+ * Let system know we have finished accessing the IO ports.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io( adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_smart16_remove_card
+* =======================
+*
+*
+* PARAMETERS (passed by hwi_remove_adapter) :
+* ===========================================
+*
+* ADAPTER * adapter
+*
+* This structure is used to identify and record specific information about
+* the required adapter.
+*
+*
+* BODY :
+* ======
+*
+* The hwi_smart16_remove_card routine is called by hwi_remove_adapter. It
+* disables interrupts if they are being used. It also resets the adapter.
+*
+*
+* RETURNS :
+* =========
+*
+* The routine always successfully completes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(hwi_smart16_remove_card)
+#endif
+
+export void
+hwi_smart16_remove_card(
+ ADAPTER * adapter
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD control_1 = adapter->io_location +
+ SMART16_CONTROL_REGISTER_1;
+ WORD sifacl_value;
+
+ /*
+ * Interrupt must be disabled at adapter before unpatching interrupt.
+ * Even in polling mode we must turn off interrupts at adapter.
+ */
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_enable_io(adapter);
+#endif
+
+ sifacl_value = sys_insw(adapter_handle, adapter->sif_acl);
+ sifacl_value = (sifacl_value & ~(EAGLE_SIFACL_PSDMAEN | EAGLE_SIFACL_SINTEN));
+ sys_outsw(
+ adapter_handle,
+ adapter->sif_acl,
+ sifacl_value);
+
+ if (adapter->interrupts_on)
+ {
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ sys_disable_irq_channel(
+ adapter_handle,
+ adapter->interrupt_number);
+ }
+
+ adapter->interrupts_on = FALSE;
+ }
+
+ /*
+ * perform adapter reset, set BALD_EAGLE_CTRL1_NSRESET low
+ */
+
+ sys_outsb(adapter_handle, control_1, 0);
+
+#ifndef FTK_NO_IO_ENABLE
+ macro_disable_io(adapter);
+#endif
+}
+
+
+/****************************************************************************
+*
+* hwi_smart16_set_dio_address
+* ===========================
+*
+* The hwi_smart16_set_dio_address routine is used, with Smart16 cards, for
+* putting a 32 bit DIO address into the SIF DIO address and extended DIO
+* address registers. Note that the extended address register should be
+* loaded first.
+*
+****************************************************************************/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_smart16_set_dio_address)
+#endif
+
+export void
+hwi_smart16_set_dio_address(
+ ADAPTER * adapter,
+ DWORD dio_address
+ )
+{
+ ADAPTER_HANDLE adapter_handle = adapter->adapter_handle;
+ WORD sif_dio_adr = adapter->sif_adr;
+ WORD sif_dio_adrx = adapter->sif_adx;
+
+ /*
+ * Load extended DIO address register with top 16 bits of address.
+ * Always load extended address register first.
+ */
+ sys_outsw(
+ adapter_handle,
+ sif_dio_adrx,
+ (WORD)(dio_address >> 16));
+
+ /*
+ * Load DIO address register with low 16 bits of address.
+ */
+
+ sys_outsw(
+ adapter_handle,
+ sif_dio_adr,
+ (WORD)(dio_address & 0x0000FFFF));
+
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| LOCAL PROCEDURES
+|
+---------------------------------------------------------------------------*/
+
+#ifndef FTK_NO_PROBE
+/*---------------------------------------------------------------------------
+|
+| hwi_smart16_check_for_card
+| ==========================
+|
+| The hwi_smart16_check_for_card routine reads in the node address from
+| the BIA, and checks that it is a valid Madge node address. Basically
+| it's just the same as hwi_smart16_read_node_address.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_smart16_check_for_card)
+#endif
+
+local WBOOLEAN
+hwi_smart16_check_for_card(
+ WORD io_location
+ )
+{
+ WORD control_2 = io_location + SMART16_CONTROL_REGISTER_2;
+ WORD port;
+ BYTE i;
+ BYTE j;
+ BYTE two_bits;
+ DWORD node_address = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ sys_probe_outsb(control_2, i);
+
+ /*
+ * Read the 8 bit node address 2 bits at a time.
+ */
+
+ port = io_location;
+
+ for (j = 0; j < 4; j++)
+ {
+ two_bits = (BYTE)(sys_probe_insb(port) & 3);
+ node_address = (node_address << 2) | two_bits;
+ port += 8;
+ }
+ }
+
+ /*
+ * If we find that the high byte is not f6 then we know we haven't
+ * got a valid card so we fail.
+ */
+
+ return (((node_address >> 24) & 0x000000ffL) == 0x000000f6L &&
+ (node_address & 0x00ffffffL) != 0x00ffffffL &&
+ (node_address & 0x00ffffffL) != 0x00000000L);
+}
+#endif
+
+/*---------------------------------------------------------------------------
+|
+| hwi_smart16_read_node_address
+| =============================
+|
+| The hwi_smart16_read_node_address routine reads in the node address from
+| the BIA, and checks that it is a valid Madge node address.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_smart16_read_node_address)
+#endif
+
+local WBOOLEAN
+hwi_smart16_read_node_address(
+ ADAPTER * adapter
+ )
+{
+ WORD control_2 = adapter->io_location +
+ SMART16_CONTROL_REGISTER_2;
+ WORD port;
+ BYTE i;
+ BYTE j;
+ BYTE two_bits;
+ DWORD node_address = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ sys_outsb(
+ adapter->adapter_handle,
+ control_2,
+ i);
+
+ /*
+ * Read the 8 bit node address 2 bits at a time.
+ */
+
+ port = adapter->io_location;
+
+ for (j = 0; j < 4; j++)
+ {
+ two_bits = (BYTE)(sys_insb(adapter->adapter_handle, port) & 3);
+ node_address = (node_address << 2) | two_bits;
+ port += 8;
+ }
+ }
+
+ adapter->permanent_address.byte[0] = 0;
+ adapter->permanent_address.byte[1] = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ adapter->permanent_address.byte[5-i]
+ = (BYTE)((node_address >> (8 * i)) & 0x0ff);
+ }
+
+ return (adapter->permanent_address.byte[2] == MADGE_NODE_BYTE_2);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_smart16_valid_io_location
+| =============================
+|
+| The hwi_smart16_valid_io_location routine checks to see if the user has
+| supplied a valid IO location for a smart 16 adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_smart16_valid_io_location)
+#endif
+
+local WBOOLEAN
+hwi_smart16_valid_io_location(
+ WORD io_location
+ )
+{
+ WBOOLEAN io_valid;
+
+ switch (io_location & ~SMART16_REV3)
+ {
+
+ case 0x4A20 :
+ case 0x4E20 :
+ case 0x6A20 :
+ case 0x6E20 :
+
+ /*
+ * These are the valid user supplied io locations.
+ */
+
+ io_valid = TRUE;
+ break;
+
+
+ default :
+
+ /*
+ * Anything else is invalid.
+ */
+
+ io_valid = FALSE;
+
+ break;
+ }
+
+ return(io_valid);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_smart16_valid_transfer_mode
+| ===============================
+|
+| The hwi_smart16_valid_transfer_mode routine checks to see if the user has
+| supplied a valid transfer mode for a smart 16 adapter card (that's PIO to
+| you and me).
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_smart16_valid_transfer_mode)
+#endif
+
+local WBOOLEAN
+hwi_smart16_valid_transfer_mode(
+ UINT transfer_mode
+ )
+{
+ return(transfer_mode == PIO_DATA_TRANSFER_MODE);
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| hwi_smart16_valid_irq_channel
+| =============================
+|
+| The hwi_smart16_valid_irq_channel routine checks to see if the user has
+| supplied a valid interrupt number for a Smart16 adapter card.
+|
+---------------------------------------------------------------------------*/
+
+#ifdef FTK_INIT_FUNCTION
+#pragma FTK_INIT_FUNCTION(hwi_smart16_valid_irq_channel)
+#endif
+
+local WBOOLEAN
+hwi_smart16_valid_irq_channel(
+ ADAPTER * adapter
+ )
+{
+ WBOOLEAN int_valid;
+
+ /*
+ * Assume that interrupt number is valid.
+ */
+
+ int_valid = TRUE;
+
+ /*
+ * No need to do any check on interrupt number if in polling mode.
+ */
+
+ if (adapter->interrupt_number != POLLING_INTERRUPTS_MODE)
+ {
+ switch (adapter->interrupt_number)
+ {
+ case 2 :
+ case 3 :
+ case 7 :
+ break;
+
+ default :
+ int_valid = FALSE;
+ break;
+
+ }
+ }
+
+ if (!int_valid)
+ {
+ adapter->error_record.type = ERROR_TYPE_HWI;
+ adapter->error_record.value = HWI_E_03_BAD_INTERRUPT_NUMBER;
+ }
+
+ return int_valid;
+}
+
+#endif
+
+/******** End of HWI_SM16.C file *******************************************/
+
diff --git a/private/ntos/ndis/madge/driver/inc/ndismod.h b/private/ntos/ndis/madge/driver/inc/ndismod.h
new file mode 100644
index 000000000..d7aab4d6c
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/inc/ndismod.h
@@ -0,0 +1,792 @@
+/***************************************************************************
+*
+* NDISMOD.H
+*
+* NDIS3 miniport driver main header file.
+*
+* Copyright (c) Madge Networks Ltd 1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: PBA 21/06/1994
+*
+****************************************************************************/
+
+#ifndef _NDIS_
+#include <ndis.h>
+#endif
+
+/*---------------------------------------------------------------------------
+|
+| General Constants
+|
+|--------------------------------------------------------------------------*/
+
+#define MADGE_NDIS_MAJOR_VERSION 3
+#define MADGE_NDIS_MINOR_VERSION 0
+
+#define EVERY_2_SECONDS 2000
+
+#define MADGE_MINIMUM_LOOKAHEAD (64)
+
+//
+// Keep this OID if we are gathering performance statistics
+//
+// #define OID_MADGE_MONITOR 0x0303028e
+
+#define OID_TYPE_MASK 0xffff0000
+#define OID_TYPE_GENERAL_OPERATIONAL 0x00010000
+#define OID_TYPE_GENERAL_STATISTICS 0x00020000
+#define OID_TYPE_802_5_OPERATIONAL 0x02010000
+#define OID_TYPE_802_5_STATISTICS 0x02020000
+
+#define MADGE_ERRMSG_INIT_INTERRUPT (ULONG)0x01
+#define MADGE_ERRMSG_CREATE_FILTER (ULONG)0x02
+#define MADGE_ERRMSG_ALLOC_MEMORY (ULONG)0x03
+#define MADGE_ERRMSG_REGISTER_ADAPTER (ULONG)0x04
+#define MADGE_ERRMSG_ALLOC_DEVICE_NAME (ULONG)0x05
+#define MADGE_ERRMSG_ALLOC_ADAPTER (ULONG)0x06
+#define MADGE_ERRMSG_INITIAL_INIT (ULONG)0x07
+#define MADGE_ERRMSG_OPEN_DB (ULONG)0x08
+#define MADGE_ERRMSG_ALLOC_OPEN (ULONG)0x09
+#define MADGE_ERRMSG_HARDWARE_ADDRESS (ULONG)0x0A
+#define MADGE_ERRMSG_WRONG_RBA (ULONG)0x0B
+#define MADGE_ERRMSG_REDUCE_MAX_FSIZE (ULONG)0x0C
+#define MADGE_ERRMSG_OPEN_IMAGE_FILE (ULONG)0x0D
+#define MADGE_ERRMSG_MAP_IMAGE_FILE (ULONG)0x0E
+#define MADGE_ERRMSG_BAD_IMAGE_FILE (ULONG)0x0F
+#define MADGE_ERRMSG_NO_BUS_TYPE (ULONG)0x10
+#define MADGE_ERRMSG_NO_MCA_POS (ULONG)0x11
+#define MADGE_ERRMSG_NO_EISA_CONFIG (ULONG)0x12
+#define MADGE_ERRMSG_NO_ISA_IO (ULONG)0x13
+#define MADGE_ERRMSG_NO_ISA_IRQ (ULONG)0x14
+#define MADGE_ERRMSG_NO_ISA_DMA (ULONG)0x15
+#define MADGE_ERRMSG_BAD_PARAMETER (ULONG)0x16
+#define MADGE_ERRMSG_NO_PCI_SLOTNUMBER (ULONG)0x17
+#define MADGE_ERRMSG_BAD_PCI_SLOTNUMBER (ULONG)0x18
+#define MADGE_ERRMSG_BAD_PCI_MMIO (ULONG)0x19
+#define MADGE_ERRMSG_MAPPING_PCI_MMIO (ULONG)0x1a
+#define MADGE_ERRMSG_NO_PCI_IO (ULONG)0x1b
+#define MADGE_ERRMSG_NO_PCI_IRQ (ULONG)0x1c
+
+//
+// Number of bytes in a minimum length token ring frame (MAC not
+// LLC so just FC, AC and addresses).
+//
+
+#define FRAME_HEADER_SIZE 14
+
+
+/*---------------------------------------------------------------------------
+|
+| Optional Parameter Definition Structure.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ NDIS_STRING Keyword;
+ DWORD Minimum;
+ DWORD Maximum;
+ NDIS_CONFIGURATION_PARAMETER DefaultValue;
+ NDIS_CONFIGURATION_PARAMETER ActualValue;
+}
+MADGE_PARM_DEFINITION;
+
+
+/*---------------------------------------------------------------------------
+|
+| ISR Information Structure.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ NDIS_HANDLE MiniportHandle;
+ ULONG InterruptNumber;
+ BOOLEAN InterruptShared;
+ NDIS_INTERRUPT_MODE InterruptMode;
+ BOOLEAN SrbRequestCompleted;
+ BOOLEAN SrbRequestStatus;
+}
+USED_IN_ISR, *PUSED_IN_ISR;
+
+#ifdef OID_MADGE_MONITOR
+/*---------------------------------------------------------------------------
+|
+| Monitor Structure
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ UINT TransmitFrames;
+ UINT ReceiveFrames;
+ UINT TransferFrames;
+ UINT TransmitFrameSize[65];
+ UINT ReceiveFrameSize[65];
+ UINT TransferFrameSize[65];
+ UINT ReceiveFlag;
+ UINT CurrentFrameSize;
+ UINT NumberOfPFrags[65];
+ UINT NumberOfVFrags[65];
+ UINT FailedToTransmit;
+}
+MADGE_MONITOR, *PMADGE_MONITOR;
+#endif
+
+/*---------------------------------------------------------------------------
+|
+| Adapter Structure.
+|
+| We actually have two adapter structures for each adapter. One of the type
+| described below for NDIS3 level information and one maintained by the
+| FTK for lower level adapter specific information.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ //
+ // Card configuration options.
+ //
+
+ UINT BusType;
+ UINT IoLocation1;
+ UINT IoLocation2;
+ UINT InterruptLevel;
+ UINT DmaChannel;
+ UINT TransferMode;
+ UINT SlotNumber;
+ UINT FastmacTxSlots;
+ UINT FastmacRxSlots;
+ UINT MaxFrameSize;
+ UINT CardBufferSize;
+ BOOLEAN PromiscuousMode;
+ BOOLEAN AlternateIo;
+ BOOLEAN TestAndXIDEnabled;
+ BOOLEAN ForceOpen;
+ BOOLEAN Force4;
+ BOOLEAN Force16;
+ BOOLEAN Multiprocessor;
+
+ UINT MapRegistersAllocated;
+
+ //
+ // Card dependent parameters.
+ //
+
+ WORD FTKCardBusType;
+ NDIS_INTERFACE_TYPE NTCardBusType;
+
+ //
+ // Handle for communicating with the FTK.
+ //
+
+ ADAPTER_HANDLE FtkAdapterHandle;
+
+ //
+ // Kernel resources allocated for the adapter.
+ //
+
+ NDIS_MINIPORT_INTERRUPT Interrupt;
+ NDIS_MINIPORT_TIMER WakeUpTimer;
+ NDIS_MINIPORT_TIMER CompletionTimer;
+
+ //
+ // Flags to indicate the current state of the driver/card.
+ //
+
+ BOOLEAN TimerInitialized;
+ BOOLEAN FtkInitialized;
+ BOOLEAN IORange1Initialized;
+ BOOLEAN IORange2Initialized;
+ BOOLEAN DprInProgress;
+
+ UINT RxTxBufferState;
+
+ BOOLEAN UseMPSafePIO;
+
+ BOOLEAN AdapterRemoved;
+
+ BOOLEAN ShutdownHandlerRegistered;
+
+ //
+ // Details of I/O ports used.
+ //
+
+ UINT IoLocationBase;
+
+ WORD IORange1;
+ WORD IORange2;
+ UINT IORange1End;
+
+ PVOID MappedIOLocation1;
+ PVOID MappedIOLocation2;
+
+ //
+ // Memory usage for PCI.
+ //
+
+ DWORD MmioRawAddress;
+ VOID * MmioVirtualAddress;
+ BOOLEAN MmioMapped;
+
+ //
+ // Interrupt related details.
+ //
+
+ USED_IN_ISR UsedInISR;
+ BOOLEAN SrbRequestStatus;
+ BOOLEAN DprRequired;
+
+ //
+ // Flag set if we are waiting for a private SRB to complete.
+ //
+
+ BOOLEAN PrivateSrbInProgress;
+
+ //
+ // General Mandatory Operational Characteristics.
+ //
+
+ NDIS_HARDWARE_STATUS HardwareStatus;
+ UINT CurrentPacketFilter;
+ ULONG CurrentLookahead;
+
+ //
+ // Counters for the General Mandatory Statistics.
+ //
+
+ UINT FramesTransmitted;
+ UINT FramesReceived;
+ UINT FrameTransmitErrors;
+ UINT FrameReceiveErrors;
+ UINT ReceiveCongestionCount;
+
+ //
+ // Token Ring Mandatory Operational Characteristics.
+ //
+
+ NODE_ADDRESS OpeningNodeAddress;
+ NODE_ADDRESS PermanentNodeAddress;
+ ULONG GroupAddress;
+ ULONG FunctionalAddress;
+ WORD OpenOptions;
+ WORD LastOpenStatus;
+ WORD CurrentRingStatus;
+ NDIS_802_5_RING_STATE CurrentRingState;
+
+ //
+ // Counters for the Token Ring Mandatory Statistics.
+ //
+
+ UINT LineErrors;
+ UINT LostFrames;
+
+ //
+ // Counters for the Token Ring Optional Statistics.
+ //
+
+ UINT BurstErrors;
+ UINT AcErrors;
+ UINT FrameCopiedErrors;
+ UINT TokenErrors;
+
+ NDIS_OID JustReadErrorLog;
+
+ //
+ // Status of a pended request.
+ //
+
+ NDIS_REQUEST_TYPE RequestType;
+ NDIS_OID RequestOid;
+ PVOID InformationBuffer;
+
+#ifdef OID_MADGE_MONITOR
+ MADGE_MONITOR MonitorInfo;
+#endif
+
+}
+MADGE_ADAPTER, *PMADGE_ADAPTER;
+
+
+/*---------------------------------------------------------------------------
+|
+| Adapter types.
+|
+---------------------------------------------------------------------------*/
+
+#define MADGE_ADAPTER_ATULA 100
+
+#define MADGE_ADAPTER_PCMCIA 200
+
+#define MADGE_ADAPTER_PNP 300
+
+#define MADGE_ADAPTER_SMART16 400
+
+#define MADGE_ADAPTER_EISA 500
+
+#define MADGE_ADAPTER_MC 600
+
+#define MADGE_ADAPTER_PCI 700
+
+#define MADGE_ADAPTER_UNKNOWN 9999
+
+
+/*---------------------------------------------------------------------------
+|
+| Transfer modes.
+|
+---------------------------------------------------------------------------*/
+
+#define MADGE_PIO_MODE 0
+#define MADGE_DMA_MODE 1
+#define MADGE_MMIO_MODE 2
+
+
+/*---------------------------------------------------------------------------
+|
+| OS types.
+|
+---------------------------------------------------------------------------*/
+
+#define MADGE_OS_NT 100
+#define MADGE_OS_WIN95 200
+
+
+/*---------------------------------------------------------------------------
+|
+| Rx and Tx Buffer Initialization Flags.
+|
+---------------------------------------------------------------------------*/
+
+#define MADGE_RX_INITIALIZED 0x0001
+#define MADGE_TX_INITIALIZED 0x0002
+
+#define MADGE_RXTX_INITIALIZED (MADGE_RX_INITIALIZED | MADGE_TX_INITIALIZED)
+
+
+/*---------------------------------------------------------------------------
+|
+| Definition of a token ring frame MAC header.
+|
+|--------------------------------------------------------------------------*/
+
+typedef struct
+{
+ BYTE AC;
+ BYTE FC;
+ UCHAR DestAddress[6];
+ UCHAR SrcAddress[6];
+}
+TOKENRING, *PTOKENRING;
+
+
+/*---------------------------------------------------------------------------
+|
+| Procedure Identifiers for Logging.
+|
+|--------------------------------------------------------------------------*/
+
+typedef enum
+{
+ readRegistry,
+ registerAdapter,
+ initAdapter,
+ madgeInitialize,
+ inFtk
+}
+MADGE_PROC_ID;
+
+
+/*---------------------------------------------------------------------------
+|
+| Structure of the FastMAC Plus download file header.
+|
+|--------------------------------------------------------------------------*/
+
+#define DOWNLOAD_CHECKSUM_SKIP (sizeof(DWORD) * 2)
+
+#define DOWNLOAD_CHECKSUM_BYTE(chk, byte) \
+ (chk) = \
+ (((DWORD) (chk) >> 30) ^ ((DWORD) (chk) << 1)) + (UCHAR) (byte)
+
+
+#define BUILD_DWORD(a, b, c, d) \
+ ((((DWORD) (a)) << 24) + \
+ (((DWORD) (b)) << 16) + \
+ (((DWORD) (c)) << 8 ) + \
+ (((DWORD) (d)) ))
+
+#define DOWNLOAD_SIGNATURE BUILD_DWORD(26, 'G', 'D', 'M')
+
+typedef
+struct
+{
+ DWORD signature;
+ DWORD chkSum;
+ DWORD version;
+ char mVer[32];
+}
+DOWNLOAD_FILE_HEADER;
+
+
+/*---------------------------------------------------------------------------
+|
+| Macro to check that a download file is cosha.
+|
+|--------------------------------------------------------------------------*/
+
+#define IS_DOWNLOAD_OK(downHdr, checkSum) \
+ ((downHdr)->signature == DOWNLOAD_SIGNATURE && \
+ (((downHdr)->version & 0xffff0000L) == \
+ (MADGE_NT_VERSION_DWORD & 0xffff0000L) || \
+ (downHdr)->version == 0) && \
+ (downHdr)->chkSum == (checkSum))
+
+
+/*---------------------------------------------------------------------------
+|
+| Details of PCI configuration memory.
+|
+| We don't define a structure for this to avoid byte alignment problems on
+| none x86 machines.
+|
+---------------------------------------------------------------------------*/
+
+#define PCI_CONFIG_SIZE 64
+#define PCI_MMIO_SIZE 4096
+
+#define PCI_VENDOR_ID(buff) (((DWORD *) (buff))[0] & 0x0000ffffL)
+#define PCI_REVISION(buff) ((((DWORD *) (buff))[0] & 0xffff0000L) >> 16)
+#define PCI_IO_BASE(buff) (((DWORD *) (buff))[4] & 0xfffffffeL)
+#define PCI_MMIO_BASE(buff) (((DWORD *) (buff))[5] & 0xfffffff0L)
+#define PCI_IRQ_NUMBER(buff) (((DWORD *) (buff))[15] & 0x000000ffL)
+
+#define MAX_PCI_SLOTS 32 // There are 5 bits of device ID which
+ // is what NT uses as the slot number.
+
+#define PCI_FIND_ADAPTER 0xffff
+
+
+#define MADGE_PCI_VENDOR_ID 0x10b6
+
+#define MADGE_PCI_RAP1B_REVISION 0x0001
+#define MADGE_PCI_PCI2_REVISION 0x0002
+#define MADGE_PCI_PCIT_REVISION 0x0004
+
+
+/*---------------------------------------------------------------------------
+|
+| Table to Map FTK Adapter Handles to NDIS3 Level Adapter Structures.
+|
+|--------------------------------------------------------------------------*/
+
+// extern PMADGE_ADAPTER MadgeAdapterRecord[MAX_NUMBER_OF_ADAPTERS];
+
+
+/*---------------------------------------------------------------------------
+|
+| Macros to Map Between Objects.
+|
+|--------------------------------------------------------------------------*/
+
+//
+// Get an NDIS3 level adapter structure pointer from an FTK adapter handle.
+//
+
+#define PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(handle) \
+ ((PMADGE_ADAPTER) FTK_ADAPTER_USER_INFORMATION(handle))
+
+//
+// Get an NDIS3 level adapter structure pointer from an NDIS adapter
+// adapter context handle.
+//
+
+#define PMADGE_ADAPTER_FROM_CONTEXT(handle) \
+ ((PMADGE_ADAPTER) ((PVOID) (handle)))
+
+
+/*---------------------------------------------------------------------------
+|
+| Memory Manipulation Macros.
+|
+|--------------------------------------------------------------------------*/
+
+//
+// Allocate ordinary memory.
+//
+
+#define MADGE_ALLOC_MEMORY(status, address, length) \
+{ \
+ NDIS_PHYSICAL_ADDRESS temp = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); \
+ *(status) = NdisAllocateMemory( \
+ (PVOID) (address), \
+ (length), \
+ 0, \
+ temp \
+ ); \
+}
+
+//
+// Free ordinary memory.
+//
+
+#define MADGE_FREE_MEMORY(address, length) \
+ NdisFreeMemory( \
+ (PVOID)(address), \
+ (length), \
+ 0 \
+ )
+
+
+//
+// Copy memory.
+//
+
+#define MADGE_MOVE_MEMORY(destination, source, length) \
+ NdisMoveMemory((PVOID) (destination), (PVOID) (source), (ULONG) (length))
+
+//
+// Zero memory.
+//
+
+#define MADGE_ZERO_MEMORY(destination, length) \
+ NdisZeroMemory((PVOID) (destination), (ULONG) (length))
+
+
+/*---------------------------------------------------------------------------
+|
+| Tokening Ring Address Testing Macros.
+|
+|--------------------------------------------------------------------------*/
+
+//
+// Compare two token ring MAC addresses pointed to by addPtr0 and
+// addrPtr1. Return TRUE if they are the same.
+//
+
+#define MADGE_ADDRESS_SAME(addrPtr0, addrPtr1) \
+ (((WORD *) (addrPtr0))[2] == ((WORD *) (addrPtr1))[2] && \
+ ((WORD *) (addrPtr0))[1] == ((WORD *) (addrPtr1))[1] && \
+ ((WORD *) (addrPtr0))[0] == ((WORD *) (addrPtr1))[0])
+
+
+//
+// Return TRUE if the frame pointer to by framePtr is source routed.
+//
+
+#define FRAME_IS_SOURCE_ROUTED(framePtr) \
+ ((((UCHAR *) (framePtr))[8] & 0x80) != 0)
+
+//
+// Return the number of bytes of source routing information in
+// a frame.
+//
+
+#define FRAME_SOURCE_ROUTING_BYTES(framePtr) \
+ (((UCHAR *) (framePtr))[14] & 0x1f)
+
+
+/*---------------------------------------------------------------------------
+|
+| Utility Macros.
+|
+|--------------------------------------------------------------------------*/
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions Exported by MADGE.C
+|
+|--------------------------------------------------------------------------*/
+
+NDIS_STATUS
+DriverEntry(PDRIVER_OBJECT driverObject, PUNICODE_STRING registryPath);
+
+NDIS_STATUS
+MadgeInitialize(
+ PNDIS_STATUS openErrorStatus,
+ PUINT selectedMediumIndex,
+ PNDIS_MEDIUM mediumArray,
+ UINT mediumArraySize,
+ NDIS_HANDLE miniportHandle,
+ NDIS_HANDLE wrapperConfigContext
+ );
+
+VOID
+MadgeHalt(NDIS_HANDLE adapterContext);
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions Exported by DISPATCH.C
+|
+|--------------------------------------------------------------------------*/
+
+VOID
+MadgeGetAdapterStatus(
+ PVOID systemSpecific1,
+ PVOID context,
+ PVOID systemSpecific2,
+ PVOID systemSpecific3
+ );
+
+BOOLEAN
+MadgeCheckForHang(NDIS_HANDLE adapterContext);
+
+NDIS_STATUS
+MadgeReset(PBOOLEAN addressReset, NDIS_HANDLE adapterContext);
+
+VOID
+MadgeDisableInterrupts(NDIS_HANDLE adapterContext);
+
+VOID
+MadgeEnableInterrupts(NDIS_HANDLE adapterContext);
+
+NDIS_STATUS
+MadgeSend(NDIS_HANDLE adapterContext, PNDIS_PACKET packet, UINT flags);
+
+VOID
+MadgeCopyFromPacketToBuffer(
+ PNDIS_PACKET packet,
+ UINT offset,
+ UINT bytesToCopy,
+ PCHAR destPtr,
+ PUINT bytesCopied
+ );
+
+NDIS_STATUS
+MadgeTransferData(
+ PNDIS_PACKET packet,
+ PUINT bytesTransferred,
+ NDIS_HANDLE adapterContext,
+ NDIS_HANDLE receiveContext,
+ UINT byteOffset,
+ UINT bytesToTransfer
+ );
+
+VOID
+MadgeCopyFromBufferToPacket(
+ PCHAR srcPtr,
+ UINT bytesToCopy,
+ PNDIS_PACKET packet,
+ UINT offset,
+ PUINT bytesCopied
+ );
+
+VOID
+MadgeISR(
+ PBOOLEAN interruptRecognised,
+ PBOOLEAN queueDPR,
+ NDIS_HANDLE adapterContext
+ );
+
+VOID
+MadgeHandleInterrupt(NDIS_HANDLE adapterContext);
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions Exported by REQUEST.C
+|
+|--------------------------------------------------------------------------*/
+
+VOID
+MadgeCompletePendingRequest(PMADGE_ADAPTER ndisAdap);
+
+NDIS_STATUS
+MadgeQueryInformation(
+ NDIS_HANDLE adapterContext,
+ NDIS_OID oid,
+ PVOID infoBuffer,
+ ULONG infoLength,
+ PULONG bytesRead,
+ PULONG bytesNeeded
+ );
+
+NDIS_STATUS
+MadgeSetInformation(
+ NDIS_HANDLE adapterContext,
+ NDIS_OID oid,
+ PVOID infoBuffer,
+ ULONG infoLength,
+ PULONG bytesRead,
+ PULONG bytesNeeded
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Functions Exported by FTK_USER.C
+|
+|--------------------------------------------------------------------------*/
+
+void
+rxtx_await_empty_tx_slots(
+ ADAPTER_HANDLE adapter_handle
+ );
+
+void
+rxtx_adapter_removed(
+ ADAPTER_HANDLE adapter_handle
+ );
+
+
+/*---------------------------------------------------------------------------
+|
+| Debugging Macros.
+|
+|--------------------------------------------------------------------------*/
+
+#if DBG
+
+#define MadgePrint1(fmt) \
+ DbgPrint("MdgMPort: "##fmt)
+#define MadgePrint2(fmt, v1) \
+ DbgPrint("MdgMPort: "##fmt, v1)
+#define MadgePrint3(fmt, v1, v2) \
+ DbgPrint("MdgMPort: "##fmt, v1, v2)
+#define MadgePrint4(fmt, v1, v2, v3) \
+ DbgPrint("MdgMPort: "##fmt, v1, v2, v3)
+#define MadgePrint5(fmt, v1, v2, v3, v4) \
+ DbgPrint("MdgMPort: "##fmt, v1, v2, v3, v4)
+
+#define STATIC
+
+#else
+
+#define MadgePrint1(fmt)
+#define MadgePrint2(fmt, v1)
+#define MadgePrint3(fmt, v1, v2)
+#define MadgePrint4(fmt, v1, v2, v3)
+#define MadgePrint5(fmt, v1, v2, v3, v4)
+
+#define STATIC
+
+#endif
+
+
+/*---------------------------------------------------------------------------
+|
+| These event codes aren't mapped to NDIS error codes in the release DDK.
+|
+---------------------------------------------------------------------------*/
+
+#ifndef NDIS_ERROR_CODE_MEMORY_CONFLICT
+#define NDIS_ERROR_CODE_MEMORY_CONFLICT \
+ EVENT_NDIS_MEMORY_CONFLICT
+#endif
+
+#ifndef NDIS_ERROR_CODE_INVALID_DOWNLOAD_FILE_ERROR
+#define NDIS_ERROR_CODE_INVALID_DOWNLOAD_FILE_ERROR \
+ EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR
+#endif
+
+
+/**** End of NDISMOD.H *****************************************************/
+
diff --git a/private/ntos/ndis/madge/driver/inc/user.h b/private/ntos/ndis/madge/driver/inc/user.h
new file mode 100644
index 000000000..933ac4473
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/inc/user.h
@@ -0,0 +1,235 @@
+/****************************************************************************/
+/****************************************************************************/
+/* */
+/* THE USER OPTIONS */
+/* ================ */
+/* */
+/* USER.H : Part of the FASTMAC TOOL-KIT (FTK) */
+/* */
+/* Copyright (c) Madge Networks Ltd. 1991-1994 */
+/* CONFIDENTIAL */
+/* */
+/* */
+/****************************************************************************/
+/* */
+/* This header file contains option settings that the user may configure. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* VERSION_NUMBER of FTK to which this USER.H belongs : */
+/* */
+
+#define FTK_VERSION_NUMBER_USER_H 221
+
+
+/****************************************************************************/
+/* */
+/* ADAPTER DOWNLOAD */
+/* */
+/* Define if you with to use FastMAC Plus. Leave undefined to use FastMAC. */
+/* */
+
+#define FMPLUS
+
+
+/****************************************************************************/
+/* */
+/* RECEIVE METHOD */
+/* */
+/* Define one method only. */
+/* */
+/* FTK_RX_OUT_OF_INTERRUPTS means that the rxtx_irq_rx_frame_handler will */
+/* be called out of the interrupt handler. This will call */
+/* user_receive_frame if there is a frame to be received. */
+/* */
+/* FTK_RX_BY_SCHEDULED_PROCESS means that the user_schedule_receive_process */
+/* is called out of the interrupt handler. The user should note that this */
+/* has happened and at his/her convenience call */
+/* driver_get_outstanding_receives which will call user_receive_frame for */
+/* each received frame. */
+/* */
+/* FTK_RX_BY_POLLING means the user should repeatedly call */
+/* driver_get_outstanding_receives to collect any received frames. */
+/* */
+
+#define FTK_RX_BY_SCHEDULED_PROCESS
+/* #define FTK_RX_BY_POLLING */
+/* #define FTK_RX_OUT_OF_INTERRUPTS */
+
+
+/****************************************************************************/
+/* */
+/* TRANSMIT METHOD */
+/* */
+/* Define only one method. These options are only relevant to FastMAC Plus. */
+/* */
+/* FTK_TX_WITH_COMPLETION means that the adapter will generate an interrupt */
+/* when it has finished with a host transmit slot buffer. The */
+/* rxtx_irq_tx_completion_check function will be called out of the interrupt*/
+/* handler so that the user can deal with the freed buffer. */
+/* */
+/* FTK_TX_WITH_POLLING means the user must poll the FastMAC Plus transmit */
+/* status values on the adapter to determine if a host transmit slot buffer */
+/* is no longer in use. */
+/* */
+
+#define FTK_TX_WITH_COMPLETION
+/* #define FTK_TX_WITH_POLLING */
+
+
+/****************************************************************************/
+/* */
+/* TRANSMIT METHOD 2 */
+/* */
+/* If FTK_TX_WITH_COMPLETION is defined then the adapter will generate */
+/* an interrupt each time its has transfered a frame from host to adapter. */
+/* Normally the user supplied routine rxtx_irq_tx_completion_check is called*/
+/* as a result. If the completion interrupt should be enabled but */
+/* rxtx_irq_tx_completion_check should not be called then define */
+/* FTK_NO_TX_COMPLETION_CALL. */
+/* */
+
+#define FTK_NO_TX_COMPLETION_CALL
+
+
+/****************************************************************************/
+/* */
+/* ADAPTER TYPE EXCLUSION */
+/* */
+/* Define one or more of these flags to disable support for adapter types. */
+/* */
+
+/* #define FTK_NO_PCMCIA */
+/* #define FTK_NO_PCI */
+/* #define FTK_NO_EISA */
+/* #define FTK_NO_ATULA */
+/* #define FTK_NO_MC */
+/* #define FTK_NO_SMART16 */
+/* #define FTK_NO_PNP */
+/* #define FTK_NO_PCIT */
+/* #define FTK_NO_PCI2 */
+
+
+/****************************************************************************/
+/* */
+/* REMOVAL OF ADAPTER PROBE SUPPORT */
+/* */
+/* Define this flags to disable support for adapter probing. */
+/* */
+
+#define FTK_NO_PROBE
+
+
+/****************************************************************************/
+/* */
+/* REMOVAL OF ERROR MESSAGES */
+/* */
+/* Define this flags to disable support for textual explinations of errors. */
+/* */
+
+#define FTK_NO_ERROR_MESSAGES
+
+
+/****************************************************************************/
+/* */
+/* SPEED ABOVE TESTING */
+/* */
+/* Define this flags to improve performance but reduce error checking. */
+/* */
+
+#define SPEED_ABOVE_TESTING
+
+
+/****************************************************************************/
+/* */
+/* CLEARING INTERRUPT CONTROLLER */
+/* */
+/* Define this flags if the interrupt routines should not call */
+/* sys_clear_controller_interrupt to clear an interrupt at the machine's */
+/* interrupt controller. */
+/* */
+
+#define FTK_NO_CLEAR_IRQ
+
+
+/****************************************************************************/
+/* */
+/* ENABLING/DISABLING IO ACCESS */
+/* */
+/* Define this flag if the macros macro_enable_io and macro_disable_io */
+/* should not be called to enable IO access and disable IO access. */
+/* */
+
+#define FTK_NO_IO_ENABLE
+
+
+/****************************************************************************/
+/* */
+/* SHARED INTERRUPTS */
+/* */
+/* Define this flag if the FTK should not poll every adapter on an */
+/* interrupt. */
+/* */
+
+#define FTK_NO_SHARED_IRQ_POLL
+
+
+/****************************************************************************/
+/* */
+/* ADAPTER REMOVAL NOTOFICATION */
+/* */
+/* Define this flag if the PCMCIA interrupt handler should call */
+/* user_adapter_removed if it detects that the PCMCIA adapter has been */
+/* removed. */
+/* */
+
+#define FTK_ADAPTER_REMOVED_NOTIFY
+
+
+/****************************************************************************/
+/* */
+/* PCMCIA 32 BIT PIO SUPPORT */
+/* */
+/* Define this flag if 32 bit PIO should be used with PCMCIA adapters that */
+/* support it. */
+/* */
+
+#define FTK_PCMCIA_32BIT_PIO
+
+
+/****************************************************************************/
+/* */
+/* POINTER SIZES */
+/* */
+/* Most of the FTK can be compiled in any memory model. However some parts */
+/* need to be able to access all of memory with a pointer (e.g. PIO and */
+/* MMIO transfer routines). These pointers are all marked with a FAR */
+/* modifier. If you are using a DOS compiler then this should be defined */
+/* to the appropriate value to mark a pointer as being 32 bit. If you are */
+/* compiling for a flat memory model then defien FAR to be nothing. */
+/* */
+
+#define FAR
+
+
+/*---------------------------------------------------------------------------
+Ý NDIS 3 Specific function memory occupancy.
+----------------------------------------------------------------------------*/
+
+#ifndef _NDIS_
+#include <ndis.h>
+#endif
+
+// #define FTK_INIT_FUNCTION(_F) NDIS_PAGABLE_FUNCTION(_F)
+#define FTK_INIT_FUNCTION(_F)
+
+
+/* */
+/* */
+/************** End of USER.H file ******************************************/
+/* */
+/* */
diff --git a/private/ntos/ndis/madge/driver/madge.c b/private/ntos/ndis/madge/driver/madge.c
new file mode 100644
index 000000000..9e3e22dda
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/madge.c
@@ -0,0 +1,3393 @@
+/***************************************************************************
+*
+* MADGE.C
+*
+* FastMAC Plus based NDIS3 miniport driver entry, initialisation and
+* closedown module.
+*
+* Copyright (c) Madge Networks Ltd 1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_extr.h"
+#include "ftk_intr.h"
+
+#include "mdgmport.upd"
+#include "ndismod.h"
+
+/*---------------------------------------------------------------------------
+|
+| Identification string for MVER.
+|
+---------------------------------------------------------------------------*/
+
+char MVerString[] = MVER_STRING;
+
+
+/*---------------------------------------------------------------------------
+|
+| Option strings for registry queries.
+|
+| There is a lot of fuss here to get the various strings defined in the
+| correct way - those that are optional need to be defined in the parm.
+| table as string constants, while those that are passed directly to the
+| registry query functions need to be explicitly defined outside any
+| structures.
+|
+|--------------------------------------------------------------------------*/
+
+#define HIDDEN_OFFS 0x80
+
+#define EmptyString NDIS_STRING_CONST("")
+
+//
+// These are the NT versions of the option strings.
+//
+
+#define IOAddrString NDIS_STRING_CONST("IoLocation")
+#define IOBaseString NDIS_STRING_CONST("IoBaseAddress")
+#define InterruptNumString NDIS_STRING_CONST("InterruptNumber")
+#define DMAChanString NDIS_STRING_CONST("DmaChannel")
+#define TxSlotNumString NDIS_STRING_CONST("TxSlots")
+#define RxSlotNumString NDIS_STRING_CONST("RxSlots")
+#define MaxFrameSizeString NDIS_STRING_CONST("MaxFrameSize")
+#define CardBuffSizeString NDIS_STRING_CONST("CardBufferSize")
+#define AlternateIoString NDIS_STRING_CONST("Alternate")
+#define TestAndXIDString NDIS_STRING_CONST("TestAndXIDEnabled")
+#define RxTxSlotsString NDIS_STRING_CONST("RxTxSlots")
+#define ForceOpenString NDIS_STRING_CONST("ForceOpen")
+#define Force4String NDIS_STRING_CONST("Force4")
+#define Force16String NDIS_STRING_CONST("Force16")
+#define SlotNumString NDIS_STRING_CONST("SlotNumber")
+#define NoPciMmioString NDIS_STRING_CONST("NoMmio")
+#define RingSpeedString NDIS_STRING_CONST("RingSpeed")
+#define AdapterTypeString NDIS_STRING_CONST("AdapterType")
+#define MmioAddrString NDIS_STRING_CONST("MemBase")
+#define PlatformTypeString NDIS_STRING_CONST("PlatformType")
+#define TransferTypeString NDIS_STRING_CONST("TransferType")
+
+WCHAR PromModeString[] =
+ { L'P' + HIDDEN_OFFS, L'r' + HIDDEN_OFFS, L'o' + HIDDEN_OFFS,
+ L'm' + HIDDEN_OFFS, L'i' + HIDDEN_OFFS, L's' + HIDDEN_OFFS,
+ L'c' + HIDDEN_OFFS, L'u' + HIDDEN_OFFS, L'o' + HIDDEN_OFFS,
+ L'u' + HIDDEN_OFFS, L's' + HIDDEN_OFFS, L'M' + HIDDEN_OFFS,
+ L'o' + HIDDEN_OFFS, L'd' + HIDDEN_OFFS, L'e' + HIDDEN_OFFS,
+ L'X' + HIDDEN_OFFS, 000 };
+
+#define PromiscuousString { sizeof(PromModeString) - 2, \
+ sizeof(PromModeString), \
+ PromModeString }
+
+//
+// These strings are passed direct to NdisReadConfiguration.
+//
+
+STATIC NDIS_STRING BusTypeString = NDIS_STRING_CONST("BusType");
+STATIC NDIS_STRING BusNumberString = NDIS_STRING_CONST("BusNumber");
+STATIC NDIS_STRING IOAddressString = IOAddrString;
+STATIC NDIS_STRING IOBaseAddrString = IOBaseString;
+STATIC NDIS_STRING InterruptNumberString = InterruptNumString;
+STATIC NDIS_STRING DMAChannelString = DMAChanString;
+STATIC NDIS_STRING SlotNumberString = SlotNumString;
+STATIC NDIS_STRING NoMmioString = NoPciMmioString;
+STATIC NDIS_STRING AdapterString = AdapterTypeString;
+STATIC NDIS_STRING MmioAddressString = MmioAddrString;
+STATIC NDIS_STRING PlatformString = PlatformTypeString;
+STATIC NDIS_STRING TransferModeString = TransferTypeString;
+
+STATIC NDIS_STRING NullString = EmptyString;
+
+
+/*---------------------------------------------------------------------------
+|
+| Optional parameter structure.
+|
+|--------------------------------------------------------------------------*/
+
+//
+// The Keyword parameters here use the #define's above, so the compiler is
+// kept happy about string initialisers.
+//
+
+STATIC struct
+{
+ MADGE_PARM_DEFINITION TxSlots;
+ MADGE_PARM_DEFINITION RxSlots;
+ MADGE_PARM_DEFINITION MaxFrameSize;
+ MADGE_PARM_DEFINITION CardBufferSize;
+ MADGE_PARM_DEFINITION PromiscuousMode;
+ MADGE_PARM_DEFINITION AlternateIo;
+ MADGE_PARM_DEFINITION TestAndXIDEnabled;
+ MADGE_PARM_DEFINITION RxTxSlots;
+ MADGE_PARM_DEFINITION ForceOpen;
+ MADGE_PARM_DEFINITION Force4;
+ MADGE_PARM_DEFINITION Force16;
+ MADGE_PARM_DEFINITION RingSpeed;
+ MADGE_PARM_DEFINITION NullParm;
+}
+MadgeParmTable =
+{
+ {TxSlotNumString, 2, 32, {NdisParameterInteger, 0}},
+ {RxSlotNumString, 2, 32, {NdisParameterInteger, 0}},
+ {MaxFrameSizeString, 1024, 17839, {NdisParameterInteger, 4096}},
+ {CardBuffSizeString, 0, 0xFFFF, {NdisParameterInteger, 0}},
+ {PromiscuousString, 0, 1, {NdisParameterInteger, 0}},
+ {AlternateIoString, 0, 1, {NdisParameterInteger, 0}},
+ {TestAndXIDString, 0, 1, {NdisParameterInteger, 0}},
+ {RxTxSlotsString, 0, 5, {NdisParameterInteger, 2}},
+ {ForceOpenString, 0, 1, {NdisParameterInteger, 0}},
+ {Force4String, 0, 1, {NdisParameterInteger, 0}},
+ {Force16String, 0, 1, {NdisParameterInteger, 0}},
+ {RingSpeedString, 0, 2, {NdisParameterInteger, 0}},
+ {EmptyString}
+};
+
+
+/*---------------------------------------------------------------------------
+|
+| Name of the FastMAC Plus image file.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STRING FmpImageFileName = MADGE_FMP_NAME;
+
+
+/*---------------------------------------------------------------------------
+|
+| List of PCI adapters in use.
+|
+---------------------------------------------------------------------------*/
+
+STATIC struct
+{
+ UINT BusNumber;
+ UINT SlotNumber;
+}
+PciSlotsUsedList[MAX_NUMBER_OF_ADAPTERS];
+
+STATIC int
+PciSlotsUsedCount = 0;
+
+
+/****************************************************************************
+*
+* NDIS3 level adapter structure pointer table.
+*
+****************************************************************************/
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeReadRegistryForMC
+|
+| Parameters - wrapperConfigHandle -> Wrapper context handle.
+| registryConfigHandle -> Already open registry query handle.
+| ndisAdap -> Pointer to an NDIS3 level adapter
+| structure.
+|
+| Purpose - Read configuration information for MC adapters out of
+Ý the registry.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeReadRegistryForMC(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeReadRegistryForMC)
+
+STATIC NDIS_STATUS
+MadgeReadRegistryForMC(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap
+ )
+{
+ static WORD mcaIrqMap[4] = { 0, 3, 9, 10};
+ static WORD mcaIoMap[8] = {0x0a20, 0x1a20, 0x2a20, 0x3a20,
+ 0x0e20, 0x1e20, 0x2e20, 0x3e20};
+
+ NDIS_STATUS status;
+ PNDIS_CONFIGURATION_PARAMETER configParam;
+ UINT slotNumber;
+ NDIS_MCA_POS_DATA mcaData;
+ BYTE iOSelect;
+
+ //
+ // Note the information that is always true for MC adapters.
+ //
+
+ ndisAdap->NTCardBusType = NdisInterfaceMca;
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_MC_BUS_TYPE;
+ ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
+
+ //
+ // MicroChannel is easy - the POS registers contain all the info
+ // we need, so read those and save the information.
+ //
+
+ NdisReadMcaPosInformation(
+ &status,
+ wrapperConfigHandle,
+ &slotNumber,
+ &mcaData
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_NO_MCA_POS
+ );
+
+ return status;
+ }
+
+ //
+ // Decode the Interrupt Number. Note: the FTK will throw
+ // IRQ 0 out as invalid.
+ //
+
+ ndisAdap->UsedInISR.InterruptNumber = mcaIrqMap[mcaData.PosData1 >> 6];
+
+ //
+ // NB: Arbitration Level 15 => PIO, which we do not allow -
+ // the FTK will throw this out as an invalid DMA channel.
+ // NB: We call it DmaChannel to be compatible with ISA cards.
+ //
+
+ ndisAdap->DmaChannel = (mcaData.PosData1 >> 1) & 0x0F;
+
+ //
+ // Build the IO Location select value from several sources.
+ //
+
+ iOSelect = (mcaData.PosData1 >> 5) & 0x01;
+ iOSelect |= (mcaData.PosData4 >> 4) & 0x02;
+ iOSelect |= (mcaData.PosData3 >> 0) & 0x04;
+
+ //
+ // NB: IO locations 0x2e20 and 0x3e20 are only valid for
+ // MC32 cards, but the .ADF file will have prevented them
+ // being set for MC16s.
+ //
+
+ ndisAdap->IoLocation1 = mcaIoMap[iOSelect];
+ ndisAdap->UsedInISR.InterruptMode = NdisInterruptLevelSensitive;
+ ndisAdap->UsedInISR.InterruptShared = TRUE;
+ ndisAdap->IORange1 = MC_IO_RANGE;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeReadRegistryForEISA
+|
+| Parameters - wrapperConfigHandle -> Wrapper context handle.
+| registryConfigHandle -> Already open registry query handle.
+| ndisAdap -> Pointer to an NDIS3 level adapter
+| structure.
+|
+| Purpose - Read configuration information for an EISA adapter
+Ý out of the registry.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeReadRegistryForEISA(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeReadRegistryForEISA)
+
+STATIC NDIS_STATUS
+MadgeReadRegistryForEISA(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap
+ )
+{
+ NDIS_STATUS status;
+ PNDIS_CONFIGURATION_PARAMETER configParam;
+ UINT slotNumber;
+ NDIS_EISA_FUNCTION_INFORMATION eisaData;
+
+ //
+ // For Eisa bus systems, we could have an Isa card or an Eisa
+ // card - try to read the Eisa information, and if that fails
+ // MadgeReadRegistry will assume it is an Isa card instead.
+ //
+
+ NdisReadEisaSlotInformation(
+ &status,
+ wrapperConfigHandle,
+ &slotNumber,
+ &eisaData
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return status;
+ }
+
+ //
+ // Note the information that is always true for EISA
+ // adapters.
+ //
+
+ ndisAdap->NTCardBusType = NdisInterfaceEisa;
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_EISA_BUS_TYPE;
+ ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
+
+ //
+ // Got EISA configuration data - decode the relevant bits.
+ //
+
+ ndisAdap->IoLocation1 = slotNumber << 12;
+
+ //
+ // Get the Interrupt number from the NVRAM data - we know it
+ // is going to be the first Irq element in the Irq array
+ // because the card only uses one interrupt.
+ //
+
+ ndisAdap->UsedInISR.InterruptNumber =
+ eisaData.EisaIrq[0].ConfigurationByte.Interrupt;
+
+ ndisAdap->UsedInISR.InterruptMode = (NDIS_INTERRUPT_MODE)
+ (eisaData.EisaIrq[0].ConfigurationByte.LevelTriggered
+ ? NdisInterruptLevelSensitive
+ : NdisInterruptLatched);
+
+ ndisAdap->UsedInISR.InterruptShared = (BOOLEAN)
+ eisaData.EisaIrq[0].ConfigurationByte.Shared;
+
+ //
+ // For EISA cards we don't care what the DMA setting is. So
+ // we leave it set to 0 forget about it.
+ //
+
+ ndisAdap->IORange1 = EISA_IO_RANGE;
+ ndisAdap->IoLocation2 = ndisAdap->IoLocation1 + EISA_IO_RANGE2_BASE;
+ ndisAdap->IORange2 = EISA_IO_RANGE2;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeReadRegistryForISA
+|
+| Parameters - wrapperConfigHandle -> Wrapper context handle.
+| registryConfigHandle -> Already open registry query handle.
+| ndisAdap -> Pointer to an NDIS3 level adapter
+| structure.
+Ý adapterType -> Adapter type.
+|
+| Purpose - Read configuration information for ISA adapters out
+Ý of the registry.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeReadRegistryForISA(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap,
+ ULONG adapterType
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeReadRegistryForISA)
+
+STATIC NDIS_STATUS
+MadgeReadRegistryForISA(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap,
+ ULONG adapterType
+ )
+{
+ NDIS_STATUS status;
+ PNDIS_CONFIGURATION_PARAMETER configParam;
+
+ //
+ // Note the information that is always TRUE for ISA adapters.
+ //
+
+ ndisAdap->NTCardBusType = NdisInterfaceIsa;
+
+ //
+ // Do some adapter type specific setup. If we don't
+ // know what sort of adapter it is we'll assume it's
+ // an ATULA adapter so we are backwards compatible.
+ //
+
+ switch (adapterType)
+ {
+ case MADGE_ADAPTER_UNKNOWN:
+ case MADGE_ADAPTER_ATULA:
+
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_ATULA_BUS_TYPE;
+ ndisAdap->IORange1 = ATULA_IO_RANGE;
+ ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
+ break;
+
+ case MADGE_ADAPTER_SMART16:
+
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_SMART16_BUS_TYPE;
+ ndisAdap->IORange1 = SMART16_IO_RANGE;
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ break;
+
+ case MADGE_ADAPTER_PCMCIA:
+
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_PCMCIA_BUS_TYPE;
+ ndisAdap->IORange1 = PCMCIA_IO_RANGE;
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ break;
+
+ case MADGE_ADAPTER_PNP:
+
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_PNP_BUS_TYPE;
+ ndisAdap->IORange1 = PNP_IO_RANGE;
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ break;
+
+ default:
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // Get the IO location - must have this. First try
+ // "IoLocation" and then "IoBaseAddress".
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &IOAddressString,
+ NdisParameterHexInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &IOBaseAddrString,
+ NdisParameterHexInteger
+ );
+ }
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_NO_ISA_IO
+ );
+
+ return status;
+ }
+
+ ndisAdap->IoLocation1 = configParam->ParameterData.IntegerData;
+
+ //
+ // Er, slight hack here. We used to pretend that Smart16
+ // adapters were ATULA adapters. We now don't. So to
+ // be backwards compatible, if we have an unknown adapter
+ // with an IO base >= 0x4a20 and <= 0x6e20 we'll assume it's
+ // really a Smart16.
+ //
+
+ if (adapterType == MADGE_ADAPTER_UNKNOWN &&
+ ndisAdap->IoLocation1 >= 0x4a20 &&
+ ndisAdap->IoLocation1 <= 0x6e20)
+ {
+ adapterType = MADGE_ADAPTER_SMART16;
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_SMART16_BUS_TYPE;
+ ndisAdap->IORange1 = SMART16_IO_RANGE;
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ }
+
+ //
+ // Get the IRQ number - we must have this.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &InterruptNumberString,
+ NdisParameterInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_NO_ISA_IRQ
+ );
+
+ return status;
+ }
+
+ ndisAdap->UsedInISR.InterruptNumber =
+ configParam->ParameterData.IntegerData;
+
+ ndisAdap->UsedInISR.InterruptMode = NdisInterruptLatched;
+ ndisAdap->UsedInISR.InterruptShared = FALSE;
+
+ //
+ // Read the TransferType parameter and switch into PIO
+ // mode if specified.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &TransferModeString,
+ NdisParameterInteger
+ );
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if (configParam->ParameterData.IntegerData == MADGE_PIO_MODE)
+ {
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ }
+ }
+
+ //
+ // Get the DMA channel (PIO is specified as channel 0,
+ // multiprocessor safe PIO is specified as 0x8000). We
+ // don't need a DMA channel if the adapter isn't an ATULA so
+ // the only reason for reading the DMA channel for none
+ // ATULA adapters is to allow backwards compatability with old
+ // registry set ups that specify multiprocessor safe PIO
+ // with the DmaChannel == 0x8000. Using the DMA channel
+ // to specify PIO is retained for backwards compatibility
+ // the correct way is to set the TransferType parameter.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &DMAChannelString,
+ NdisParameterInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ ndisAdap->DmaChannel = 0;
+ }
+ else
+ {
+ ndisAdap->DmaChannel = configParam->ParameterData.IntegerData;
+ }
+
+ //
+ // Note if we should be using multiprocessor safe PIO.
+ //
+
+ if (ndisAdap->DmaChannel == 0x8000)
+ {
+ ndisAdap->DmaChannel = 0;
+ ndisAdap->UseMPSafePIO = TRUE;
+ }
+
+ //
+ // If we did not get a DMA channel then we must use PIO.
+ //
+
+ if (ndisAdap->DmaChannel == 0)
+ {
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeFindPciInfoForWin95
+|
+| Parameters - wrapperConfigHandle -> Wrapper context handle.
+| registryConfigHandle -> Already open registry query handle.
+| ndisAdap -> Pointer to an NDIS3 level adapter
+| structure.
+Ý pciSlotInfo -> Pointer to a buffer that will
+Ý be filled with the configuration
+Ý data for the adapter.
+|
+| Purpose - Read configuration information for PCI adapters out
+Ý of the registry when running on Windows95. The slot
+Ý containing the adapter is also found and the configuration
+Ý data from the slot returned in the pciSlotInfo buffer.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeFindPciInfoForWin95(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap,
+ BYTE * pciSlotInfo
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeFindPciInfoForWin95)
+
+STATIC NDIS_STATUS
+MadgeFindPciInfoForWin95(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap,
+ BYTE * pciSlotInfo
+
+ )
+{
+ NDIS_STATUS status;
+ PNDIS_CONFIGURATION_PARAMETER configParam;
+ UINT i;
+
+ //
+ // Unfortunately Windows95 (M7) and NT handle PCI configuration
+ // in different ways. Under NT one has to read the slot
+ // configuration. Under Windows95 the resource information
+ // is faked up by the configuration manager and can be read
+ // directly from the wrapper.
+ //
+
+ //
+ // Get the IO location - must have this. First try
+ // "IoLocation" and then "IoBaseAddress".
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &IOAddressString,
+ NdisParameterHexInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &IOBaseAddrString,
+ NdisParameterHexInteger
+ );
+ }
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_NO_PCI_IO
+ );
+
+ return status;
+ }
+
+ ndisAdap->IoLocation1 = configParam->ParameterData.IntegerData;
+
+ //
+ // Get the IRQ number - we must have this.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &InterruptNumberString,
+ NdisParameterInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_NO_PCI_IRQ
+ );
+
+ return status;
+ }
+
+ ndisAdap->UsedInISR.InterruptNumber =
+ configParam->ParameterData.IntegerData;
+
+ //
+ // Get the MMIO base address - optional.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &MmioAddressString,
+ NdisParameterInteger
+ );
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ ndisAdap->MmioRawAddress =
+ configParam->ParameterData.IntegerData;
+ }
+
+ //
+ // We also need to know which slot the adapter is in so we can
+ // read and write configuration space directly. We'll search for
+ // a slot which contains a Madge adapter which the correct I/O
+ // location. As a side effect we'll store the configuration data
+ // for the slot in pciSlotInfo. Note: Under Windows 95 (build 490)
+ // NdisReadPciSlotInformation does appear to return the number
+ // of bytes read as it does under NT - not sure what it returns ...
+ //
+
+ ndisAdap->SlotNumber = PCI_FIND_ADAPTER;
+
+ for (i = 0; i < MAX_PCI_SLOTS; i++)
+ {
+ NdisReadPciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ i,
+ 0,
+ (VOID *) pciSlotInfo,
+ PCI_CONFIG_SIZE
+ );
+
+ if (PCI_VENDOR_ID(pciSlotInfo) == MADGE_PCI_VENDOR_ID &&
+ PCI_IO_BASE(pciSlotInfo) == ndisAdap->IoLocation1)
+ {
+ ndisAdap->SlotNumber = i;
+ break;
+ }
+ }
+
+ if (ndisAdap->SlotNumber == PCI_FIND_ADAPTER)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_BAD_PCI_SLOTNUMBER
+ );
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+Ý Function - MadgePciSlotUsed
+Ý Parameters - busNumber -> Bus number containing the adapter.
+Ý slotNumber -> Slot number containing the adapter.
+Ý Purpose - Check if a PCI slot is already in use.
+Ý Returns - TRUE if the slot is in use or FALSE if not.
+Ý--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+MadgePciSlotUsed(
+ UINT busNumber,
+ UINT slotNumber
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgePciSlotUsed)
+
+STATIC BOOLEAN
+MadgePciSlotUsed(
+ UINT busNumber,
+ UINT slotNumber
+ )
+{
+ int i;
+
+ for (i = 0; i < PciSlotsUsedCount; i++)
+ {
+ if (PciSlotsUsedList[i].BusNumber == busNumber &&
+ PciSlotsUsedList[i].SlotNumber == slotNumber)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeFindPciInfoForNt
+|
+| Parameters - wrapperConfigHandle -> Wrapper context handle.
+| registryConfigHandle -> Already open registry query handle.
+| ndisAdap -> Pointer to an NDIS3 level adapter
+| structure.
+Ý pciSlotInfo -> Pointer to a buffer that will
+Ý be filled with the configuration
+Ý data for the adapter.
+|
+| Purpose - Read configuration information for PCI adapters out
+Ý of the registry when running on Windows95. The slot
+Ý containing the adapter is also found and the configuration
+Ý data from the slot returned in the pciSlotInfo buffer.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeFindPciInfoForNt(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap,
+ BYTE * pciSlotInfo
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeFindPciInfoForNt)
+
+STATIC NDIS_STATUS
+MadgeFindPciInfoForNt(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap,
+ BYTE * pciSlotInfo
+ )
+{
+ NDIS_STATUS status;
+ PNDIS_CONFIGURATION_PARAMETER configParam;
+ UINT slotNumber;
+ BOOLEAN pciSlotRead;
+ BOOLEAN useMmio;
+ UINT i;
+ PNDIS_RESOURCE_LIST pciResources;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR resDesc;
+ UINT busNumber;
+
+ //
+ // Unfortunately Windows95 (M7) and NT handle PCI configuration
+ // in different ways. Under NT one has to read the slot
+ // configuration. Under Windows95 the resource information
+ // is faked up by the configuration manager and can be read
+ // directly from the wrapper.
+ //
+
+ //
+ // Find out what the slot number is. This is in fact the
+ // PCI device number. Values 0 through 31 represent real
+ // slot numbers. 0xffff means we should search for the
+ // first unused Madge PCI adapter.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &SlotNumberString,
+ NdisParameterInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_NO_PCI_SLOTNUMBER
+ );
+
+ return status;
+ }
+
+ slotNumber = configParam->ParameterData.IntegerData;
+ pciSlotRead = FALSE;
+
+ //
+ // Read the bus number.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &BusNumberString,
+ NdisParameterInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_NO_PCI_SLOTNUMBER
+ );
+
+ return status;
+ }
+
+ busNumber = configParam->ParameterData.IntegerData;
+
+ //
+ // If the slot number is PCI_FIND_ADAPTER (0xffff) then we
+ // will attempt to search for the first Madge PCI adapter
+ // that is not already in use.
+ //
+
+ if (slotNumber == PCI_FIND_ADAPTER)
+ {
+ for (i = 0; !pciSlotRead && i < MAX_PCI_SLOTS; i++)
+ {
+ if (!MadgePciSlotUsed(busNumber, i))
+ {
+ //
+ // Extract the PCI configuration information from
+ // the slot.
+ //
+
+ status = NdisReadPciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ i,
+ 0,
+ (VOID *) pciSlotInfo,
+ PCI_CONFIG_SIZE
+ );
+ //
+ // Check if the slot contains a Madge adapter and
+ // break out of the loop if it does.
+ //
+
+ if (status == PCI_CONFIG_SIZE &&
+ PCI_VENDOR_ID(pciSlotInfo) == MADGE_PCI_VENDOR_ID)
+ {
+ slotNumber = i;
+ pciSlotRead = TRUE;
+ }
+ }
+ }
+ }
+
+ //
+ // Check if the slotNumber is valid. This will fail if the
+ // above adapter search failed.
+ //
+
+ if (slotNumber < 0 ||
+ slotNumber >= MAX_PCI_SLOTS ||
+ MadgePciSlotUsed(busNumber, slotNumber))
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_BAD_PCI_SLOTNUMBER
+ );
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // Note that the PCI slot is in use.
+ //
+
+ PciSlotsUsedList[PciSlotsUsedCount].BusNumber = busNumber;
+ PciSlotsUsedList[PciSlotsUsedCount].SlotNumber = slotNumber;
+ PciSlotsUsedCount++;
+
+ ndisAdap->SlotNumber = slotNumber;
+
+ //
+ // There two methods for getting the PCI configuration. One is
+ // to read it directly from the PCI configuration space. This
+ // works for Intel patforms where a PCI BIOS has configured
+ // all of the adapters at boot time. It does not work for
+ // none Intel platforms where the PCI devices are not
+ // configured at boot time. Unfortunately the call which
+ // provokes NT to configure a PCI device, NdisMPciAssignResources
+ // is not available in the NT 3.5 wrapper. So, until NT 3.51
+ // becomes dominant we must support both configuration methods.
+ //
+
+ //
+ // If we haven't already extracted the PCI configuration
+ // information from the slot and check that it is valid.
+ //
+
+ if (!pciSlotRead)
+ {
+ status = NdisReadPciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ slotNumber,
+ 0,
+ (VOID *) pciSlotInfo,
+ PCI_CONFIG_SIZE
+ );
+
+ if (status != PCI_CONFIG_SIZE ||
+ PCI_VENDOR_ID(pciSlotInfo) != MADGE_PCI_VENDOR_ID)
+ {
+ MadgePrint1("No Madge adapter in slot\n");
+
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_BAD_PCI_SLOTNUMBER
+ );
+
+ return NDIS_STATUS_FAILURE;
+ }
+ }
+
+ //
+ // Call NdisMPciAssignResources for the specified slot to
+ // get the adapter configuration.
+ //
+
+ status = NdisMPciAssignResources(
+ ndisAdap->UsedInISR.MiniportHandle,
+ slotNumber,
+ &pciResources
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_BAD_PCI_SLOTNUMBER
+ );
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // Iterate through the returned resource list recording the values
+ // in the PCI configuration
+ //
+
+ for (i = 0; i < pciResources->Count; i++)
+ {
+ resDesc = &pciResources->PartialDescriptors[i];
+
+ switch (resDesc->Type)
+ {
+ case CmResourceTypeInterrupt:
+
+ ndisAdap->UsedInISR.InterruptNumber =
+ (ULONG) resDesc->u.Interrupt.Vector;
+ break;
+
+ case CmResourceTypePort:
+
+ ndisAdap->IoLocation1 =
+ (UINT) NdisGetPhysicalAddressLow(resDesc->u.Port.Start);
+ break;
+
+ case CmResourceTypeMemory:
+
+ ndisAdap->MmioRawAddress =
+ (DWORD) NdisGetPhysicalAddressLow(resDesc->u.Memory.Start);
+ break;
+ }
+ }
+
+
+ //
+ // On none-Intel platforms it's possible for the PCI adapter's I/O
+ // base to be greater than 0xffff. Since the FTK uses 16bit
+ // I/O locations we make a note of the I/O base in a 32bit cell
+ // that we can add in inside the I/O functions in sys_mem.c
+ //
+
+#ifndef _M_IX86
+
+ ndisAdap->IoLocationBase = ndisAdap->IoLocation1;
+ ndisAdap->IoLocation1 = 0;
+
+#endif
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeReadRegistryForPCI
+|
+| Parameters - wrapperConfigHandle -> Wrapper context handle.
+| registryConfigHandle -> Already open registry query handle.
+| ndisAdap -> Pointer to an NDIS3 level adapter
+| structure.
+Ý platformType -> Type of platform: NT or Win95.
+|
+| Purpose - Read configuration information for PCI.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeReadRegistryForPCI(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap,
+ UINT platformType
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeReadRegistryForPCI)
+
+STATIC NDIS_STATUS
+MadgeReadRegistryForPCI(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap,
+ UINT platformType
+ )
+{
+ NDIS_STATUS status;
+ PNDIS_CONFIGURATION_PARAMETER configParam;
+ BYTE pciSlotInfo[PCI_CONFIG_SIZE];
+ BOOLEAN useMmio;
+
+ //
+ // Note the information that is always true for PCI adapters.
+ //
+
+ ndisAdap->NTCardBusType = NdisInterfacePci;
+
+ //
+ // Set up the fixed configuration information.
+ //
+
+ ndisAdap->UsedInISR.InterruptMode = NdisInterruptLevelSensitive;
+ ndisAdap->UsedInISR.InterruptShared = TRUE;
+
+ //
+ // We know need to find the PCI adapter and read in the configuration
+ // information for the slot. Unfortunatetly the method we have to use
+ // is different for NT and Win95.
+ //
+
+ if (platformType == MADGE_OS_WIN95)
+ {
+ status = MadgeFindPciInfoForWin95(
+ wrapperConfigHandle,
+ registryConfigHandle,
+ ndisAdap,
+ pciSlotInfo
+ );
+ }
+ else
+ {
+ status = MadgeFindPciInfoForNt(
+ wrapperConfigHandle,
+ registryConfigHandle,
+ ndisAdap,
+ pciSlotInfo
+ );
+ }
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return status;
+ }
+
+ //
+ // Now we know we have a Madge PCI adapter of some sort but
+ // as yet we don't know what type. We'll work this out by
+ // looking at the device/revision ID in the slot's configuration
+ // data. At the same time we'll note the default transfer type
+ // for the adapter.
+ //
+
+ switch (PCI_REVISION(pciSlotInfo))
+ {
+ case MADGE_PCI_RAP1B_REVISION:
+
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_PCI_BUS_TYPE;
+ ndisAdap->TransferMode = MMIO_DATA_TRANSFER_MODE;
+ ndisAdap->IORange1 = PCI_IO_RANGE;
+ break;
+
+ case MADGE_PCI_PCI2_REVISION:
+
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_PCI2_BUS_TYPE;
+ ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
+ ndisAdap->IORange1 = PCI2_IO_RANGE;
+ break;
+
+ case MADGE_PCI_PCIT_REVISION:
+
+ ndisAdap->FTKCardBusType = ADAPTER_CARD_TI_PCI_BUS_TYPE;
+ ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
+ ndisAdap->IORange1 = SIF_IO_RANGE;
+ break;
+
+ default:
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // Now we need to work out the transfer type. There are three
+ // things that affect the transfer type: the setting of
+ // the TransferType registry parameter, the setting of the
+ // NoMmio registry flag and whether we have been allocated any
+ // MMIO memory. Ideally we would just use the TransferType flag.
+ // The NoMmio flag is to preserve backwards compatibility with old
+ // registry set ups.
+ //
+
+ //
+ // Read the transfer type flag if possible.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &TransferModeString,
+ NdisParameterInteger
+ );
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Set the transfer type depending on the TransferType parameter
+ // and the adapter type.
+ //
+
+ if (configParam->ParameterData.IntegerData == MADGE_DMA_MODE)
+ {
+ if (ndisAdap->FTKCardBusType == ADAPTER_CARD_PCI2_BUS_TYPE ||
+ ndisAdap->FTKCardBusType == ADAPTER_CARD_TI_PCI_BUS_TYPE)
+ {
+ ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
+ }
+ }
+
+ if (configParam->ParameterData.IntegerData == MADGE_PIO_MODE)
+ {
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ }
+
+ if (configParam->ParameterData.IntegerData == MADGE_MMIO_MODE)
+ {
+ if (ndisAdap->FTKCardBusType == ADAPTER_CARD_PCI_BUS_TYPE)
+ {
+ ndisAdap->TransferMode = MMIO_DATA_TRANSFER_MODE;
+ }
+ }
+ }
+
+ //
+ // To preserve backwards compatibility if we find the NoMmio flag
+ // set then switch to PIO mode.
+ //
+
+ if (ndisAdap->TransferMode == MMIO_DATA_TRANSFER_MODE)
+ {
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &NoMmioString,
+ NdisParameterInteger
+ );
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ if (configParam->ParameterData.IntegerData != 0)
+ {
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ }
+ }
+ }
+
+ //
+ // If we are in MMIO mode then check that we were allocated some MMIO
+ // memory. If not switch to PIO mode.
+ //
+
+ if (ndisAdap->TransferMode == MMIO_DATA_TRANSFER_MODE)
+ {
+ if (ndisAdap->MmioRawAddress == 0)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MEMORY_CONFLICT,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_BAD_PCI_MMIO
+ );
+
+ ndisAdap->TransferMode == PIO_DATA_TRANSFER_MODE;
+
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeReadRegistry
+|
+| Parameters - wrapperConfigHandle -> Wrapper context handle.
+| registryConfigHandle -> Already open registry query handle.
+| ndisAdap -> Pointer to an NDIS3 level adapter
+| structure.
+|
+| Purpose - Read configuration information out of the registry.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeReadRegistry(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeReadRegistry)
+
+STATIC NDIS_STATUS
+MadgeReadRegistry(
+ NDIS_HANDLE wrapperConfigHandle,
+ NDIS_HANDLE registryConfigHandle,
+ PMADGE_ADAPTER ndisAdap
+ )
+{
+ NDIS_STATUS status;
+ PNDIS_CONFIGURATION_PARAMETER configParam;
+ MADGE_PARM_DEFINITION * pMadgeParmTable;
+ PVOID networkAddress;
+ ULONG networkAddressLength;
+ UINT adapterType;
+ UINT platformType;
+
+ //
+ // Try to read the OS platform type. If we don't find one then
+ // assume we are running on NT.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &PlatformString,
+ NdisParameterInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ platformType = MADGE_OS_NT;
+ }
+ else
+ {
+ platformType = configParam->ParameterData.IntegerData;
+ }
+
+ //
+ // Read the system bus type - that will give us a direction
+ // in which to search for further details.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &BusTypeString,
+ NdisParameterInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_NO_BUS_TYPE
+ );
+
+ return status;
+ }
+
+ ndisAdap->BusType = configParam->ParameterData.IntegerData;
+
+ //
+ // Originally we determined what sort of adapter we had based
+ // on the bus type returned by the configuration call to the
+ // wrapper. This works for NT but doesn't for Windows95 (M7)
+ // which seems to fail to identify a card as being in a PCI
+ // bus. We also cannot tell between the various sorts of ISA
+ // adapter now available. To fix this we look in the registry
+ // for an adapter type parameter. We use this and the bus type
+ // returned by the wrapper to work out where to start. We don't
+ // fail if we can't read an adapter type so that we will work with
+ // old registry set ups.
+ //
+ // Build 310 of Windows95 seems to return the native bus type of the
+ // PC. This means on a PCI machine we always get NdisInterfacePci.
+ // To get around this problem we will work out the bus type from
+ // the adapter type parameter if one is present.
+ //
+ // Unfortunately we can't just abandon the bus type de-multiplexing
+ // if we are to work with old NT registry set ups.
+ //
+
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &AdapterString,
+ NdisParameterInteger
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ adapterType = MADGE_ADAPTER_UNKNOWN;
+ }
+ else
+ {
+ adapterType = configParam->ParameterData.IntegerData;
+ }
+
+ switch (adapterType)
+ {
+ case MADGE_ADAPTER_ATULA:
+ case MADGE_ADAPTER_PCMCIA:
+ case MADGE_ADAPTER_PNP:
+ case MADGE_ADAPTER_SMART16:
+
+ ndisAdap->BusType = NdisInterfaceIsa;
+ break;
+
+ case MADGE_ADAPTER_EISA:
+
+ ndisAdap->BusType = NdisInterfaceEisa;
+ break;
+
+ case MADGE_ADAPTER_MC:
+
+ ndisAdap->BusType = NdisInterfaceMca;
+ break;
+
+ case MADGE_ADAPTER_PCI:
+
+ ndisAdap->BusType = NdisInterfacePci;
+ break;
+
+ default:
+
+ //
+ // We don't have a valid adapter type parameter so we'll
+ // just have to beleive the bus type the wrapper passed
+ // us.
+ //
+
+ break;
+ }
+
+ //
+ // Based on the determined Bus Type, try to find details of the card.
+ //
+
+ //
+ // Remember, all fields of the MADGE_ADAPTER structure were zeroed
+ // after the structure's allocation.
+ //
+
+ switch (ndisAdap->BusType)
+ {
+ case NdisInterfaceMca:
+
+ status = MadgeReadRegistryForMC(
+ wrapperConfigHandle,
+ registryConfigHandle,
+ ndisAdap
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return status;
+ }
+
+ break;
+
+ case NdisInterfaceEisa:
+
+ //
+ // For Eisa bus systems, we could have an Isa card or an Eisa
+ // card - try to read the Eisa information, and if that fails
+ // assume it is an Isa card instead.
+ //
+
+ status = MadgeReadRegistryForEISA(
+ wrapperConfigHandle,
+ registryConfigHandle,
+ ndisAdap
+ );
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ break;
+ }
+
+ //
+ // Failed to read EISA data for this card, so it is unlikely
+ // to be one - try ISA instead - fall through.
+ //
+
+ case NdisInterfaceIsa:
+
+ status = MadgeReadRegistryForISA(
+ wrapperConfigHandle,
+ registryConfigHandle,
+ ndisAdap,
+ adapterType
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return status;
+ }
+
+ break;
+
+ case NdisInterfacePci:
+
+ status = MadgeReadRegistryForPCI(
+ wrapperConfigHandle,
+ registryConfigHandle,
+ ndisAdap,
+ platformType
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return status;
+ }
+
+ break;
+
+
+ default:
+
+ //
+ // Unsupported Bus Type, so return failure - no point being more
+ // explicit than that at the moment since any of the bits above
+ // could have failed too, and they do not return anything more
+ // meaningful either.
+ //
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ MadgePrint2("FTKCardBusType = %d\n", ndisAdap->FTKCardBusType);
+ MadgePrint2("SlotNumber = %d\n", ndisAdap->SlotNumber);
+ MadgePrint2("IoLocation1 = %lx\n", ndisAdap->IoLocation1);
+ MadgePrint2("MmioAddress = %lx\n", ndisAdap->MmioRawAddress);
+ MadgePrint2("InterruptNumber = %lx\n", ndisAdap->UsedInISR.InterruptNumber);
+ MadgePrint2("TransferMode = %d\n", ndisAdap->TransferMode);
+ MadgePrint2("DmaChannel = %d\n", ndisAdap->DmaChannel);
+
+ //
+ // To get here, we must have worked out the IO Address, IRQ number, DMA
+ // channel/arbitration level, and all the interrupt details. This just
+ // leaves the optional parameters for tuning the performance of the MAC
+ // code.
+ //
+
+ pMadgeParmTable = (MADGE_PARM_DEFINITION *) &MadgeParmTable;
+
+ while (!NdisEqualString(&pMadgeParmTable->Keyword, &NullString, TRUE))
+ {
+ NdisReadConfiguration(
+ &status,
+ &configParam,
+ registryConfigHandle,
+ &pMadgeParmTable->Keyword,
+ pMadgeParmTable->DefaultValue.ParameterType
+ );
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Did read something. Check bounds. We assume all are Integers.
+ //
+
+ if (configParam->ParameterData.IntegerData <
+ pMadgeParmTable->Minimum ||
+ configParam->ParameterData.IntegerData >
+ pMadgeParmTable->Maximum)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_DRIVER_FAILURE,
+ 2,
+ readRegistry,
+ MADGE_ERRMSG_BAD_PARAMETER
+ );
+
+ pMadgeParmTable->ActualValue = pMadgeParmTable->DefaultValue;
+ }
+ else
+ {
+ pMadgeParmTable->ActualValue = *configParam;
+ }
+ }
+ else
+ {
+ //
+ // We didn't read anything, so use the default value.
+ //
+
+ pMadgeParmTable->ActualValue = pMadgeParmTable->DefaultValue;
+ }
+
+ pMadgeParmTable++;
+ }
+
+ //
+ // We have successfully read any optional keywords and none of them is
+ // too small or big. The other thing we need the registry for is the
+ // locally administered address, for which there is a specific NDIS call
+ //
+
+ NdisReadNetworkAddress(
+ &status,
+ &networkAddress,
+ &networkAddressLength,
+ registryConfigHandle
+ );
+
+ if (status == NDIS_STATUS_SUCCESS &&
+ networkAddressLength == TR_LENGTH_OF_ADDRESS)
+ {
+ //
+ // We read a valid length TR address, but if the
+ // top two bits are not "01", it is not legal.
+ //
+
+ if ((((BYTE *) networkAddress)[0] & 0xc0) == 0x40)
+ {
+ ndisAdap->OpeningNodeAddress =
+ *((NODE_ADDRESS *) networkAddress);
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeShutdown
+*
+* Parameters - context -> Adapter context.
+*
+* Purpose - Quickly shutdown the adapter.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeShutdown(
+ NDIS_HANDLE context
+ )
+{
+ MADGE_ADAPTER * ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(context);
+
+ MadgePrint1("MadgeShutdown called\n");
+
+ if (ndisAdap->TimerInitialized)
+ {
+ BOOLEAN timerOutstanding;
+
+ NdisMCancelTimer(&ndisAdap->WakeUpTimer, &timerOutstanding);
+ NdisMCancelTimer(&ndisAdap->CompletionTimer, &timerOutstanding);
+
+ ndisAdap->TimerInitialized = FALSE;
+ }
+
+ //
+ // Just call the FTK to shutdown the adapter.
+ //
+
+ if (ndisAdap->FtkInitialized)
+ {
+ rxtx_await_empty_tx_slots(ndisAdap->FtkAdapterHandle);
+ driver_remove_adapter(ndisAdap->FtkAdapterHandle);
+ ndisAdap->FtkInitialized = FALSE;
+ ndisAdap->AdapterRemoved = TRUE;
+ }
+
+ MadgePrint1("MadgeShutdown ended\n");
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeRegisterAdapter
+|
+| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter
+| structure.
+| wrapperConfigHandle -> Wrapper context handle.
+|
+| Purpose - Register an adapter instance with the NDIS3 wrapper.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeRegisterAdapter(
+ PMADGE_ADAPTER ndisAdap,
+ NDIS_HANDLE wrapperConfigHandle
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeRegisterAdapter)
+
+STATIC NDIS_STATUS
+MadgeRegisterAdapter(
+ PMADGE_ADAPTER ndisAdap,
+ NDIS_HANDLE wrapperConfigHandle
+ )
+{
+ NDIS_STATUS status;
+ BOOLEAN busMaster;
+
+ MadgePrint1("MadgeRegisterAdapter started\n");
+
+ //
+ // Register a shutdown handler with the wrapper.
+ //
+
+ NdisMRegisterAdapterShutdownHandler(
+ ndisAdap->UsedInISR.MiniportHandle,
+ ndisAdap,
+ MadgeShutdown
+ );
+
+ ndisAdap->ShutdownHandlerRegistered = TRUE;
+
+ //
+ // Register our attributes with the wrapper. These are our adapter
+ // context (i.e. a pointer to our adapter structure), whether we
+ // are a bus master device and our bus type.
+ //
+
+ busMaster = (ndisAdap->TransferMode == DMA_DATA_TRANSFER_MODE);
+
+ MadgePrint1("NdisMSetAttributes called\n");
+ MadgePrint2("busMaster = %d\n", (UINT) busMaster);
+
+ NdisMSetAttributes(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (NDIS_HANDLE) ndisAdap,
+ busMaster,
+ ndisAdap->NTCardBusType
+ );
+
+ MadgePrint1("NdisMSetAttributes returned\n");
+
+ //
+ // Register our IO port usage.
+ //
+
+ MadgePrint1("NdisMRegisterIoPortRange called\n");
+
+ status = NdisMRegisterIoPortRange(
+ &ndisAdap->MappedIOLocation1,
+ ndisAdap->UsedInISR.MiniportHandle,
+ ndisAdap->IoLocation1 + ndisAdap->IoLocationBase,
+ ndisAdap->IORange1
+ );
+
+ MadgePrint1("NdisMRegisterIoPortRange returned\n");
+ MadgePrint2("MappedIORange1 = %x\n", (UINT) ndisAdap->MappedIOLocation1);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ MadgePrint2("NdisMRegisterIoPortRange failed rc = %x\n", status);
+ return status;
+ }
+
+ ndisAdap->IORange1Initialized = TRUE;
+
+ //
+ // If we are using an EISA card then we have a second range of IO
+ // locations.
+ //
+
+ if (ndisAdap->IORange2 > 0)
+ {
+ MadgePrint1("NdisMRegisterIoPortRange called\n");
+
+ status = NdisMRegisterIoPortRange(
+ &ndisAdap->MappedIOLocation2,
+ ndisAdap->UsedInISR.MiniportHandle,
+ ndisAdap->IoLocation2 + ndisAdap->IoLocationBase,
+ ndisAdap->IORange2
+ );
+
+ MadgePrint1("NdisMRegisterIoPortRange returned\n");
+ MadgePrint2("MappedIORange2 = %x\n", (UINT) ndisAdap->MappedIOLocation2);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ MadgePrint2("NdisMRegisterIoPortRange failed rc = %x\n", status);
+ return status;
+ }
+
+ ndisAdap->IORange2Initialized = TRUE;
+ }
+
+ MadgePrint1("MadgeRegisterAdapter finished\n");
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - FlagIsTrue
+|
+| Parameters - flag -> Pointer to a flag to find the value of.
+|
+| Purpose - Return the value of a flag. Can be called by a function
+Ý that polls a flag to avoid the compiler optimising out
+Ý the test of the flag.
+|
+| Returns - The value of the flag.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC BOOLEAN
+FlagIsTrue(BOOLEAN * flag);
+
+#pragma FTK_INIT_FUNCTION(FlagIsTrue)
+
+STATIC BOOLEAN
+FlagIsTrue(BOOLEAN * flag)
+{
+ MadgePrint1("FlagIsTrue\n");
+
+ return *flag;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeMapMmioMemory
+|
+| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
+|
+| Purpose - Attempt to map in our MMIO memory.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeMapMmioMemory(PMADGE_ADAPTER ndisAdap);
+
+#pragma FTK_INIT_FUNCTION(MadgeMapMmioMemory)
+
+STATIC NDIS_STATUS
+MadgeMapMmioMemory(PMADGE_ADAPTER ndisAdap)
+{
+ NDIS_PHYSICAL_ADDRESS mmioPhysAddr = NDIS_PHYSICAL_ADDRESS_CONST(0, 0);
+ UINT status;
+
+ NdisSetPhysicalAddressLow(
+ mmioPhysAddr,
+ ndisAdap->MmioRawAddress
+ );
+
+ status = NdisMMapIoSpace(
+ &ndisAdap->MmioVirtualAddress,
+ ndisAdap->UsedInISR.MiniportHandle,
+ mmioPhysAddr,
+ PCI_MMIO_SIZE
+ );
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_MEMORY_CONFLICT,
+ 2,
+ initAdapter,
+ MADGE_ERRMSG_MAPPING_PCI_MMIO
+ );
+ }
+ else
+ {
+ ndisAdap->MmioMapped = TRUE;
+ }
+
+ return status;
+}
+
+
+#ifndef LINK_FMPLUS
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeReadDownload
+|
+| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
+Ý downloadFile -> Pointer to as handle for the download file.
+| download -> Pointer to a holder for a pointer to the
+Ý download image read into memory.
+| Purpose - Read the download into memory. If the function returns
+Ý success then must unmap and close *downloadFile.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeReadDownload(
+ PMADGE_ADAPTER ndisAdap,
+ NDIS_HANDLE * downloadFile,
+ void * * download
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeReadDownload)
+
+STATIC NDIS_STATUS
+MadgeReadDownload(
+ PMADGE_ADAPTER ndisAdap,
+ NDIS_HANDLE * downloadFile,
+ void * * download
+ )
+{
+ NDIS_STATUS status;
+ NDIS_HANDLE imageFile;
+ UINT imageLength;
+ PVOID imagePtr;
+ NDIS_PHYSICAL_ADDRESS highestAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+ DOWNLOAD_FILE_HEADER * downHdrPtr;
+ UCHAR * chkPtr;
+ ULONG chkSum;
+ UINT i;
+
+ //
+ // Open the FastMAC Plus image file.
+ //
+
+ MadgePrint1("NdisOpenFile called\n");
+
+ NdisOpenFile(
+ &status,
+ &imageFile,
+ &imageLength,
+ &FmpImageFileName,
+ highestAddress
+ );
+
+ MadgePrint1("NdisOpenFile returned\n");
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ MadgePrint2("NdisOpenFile failed rc= %x\n", status);
+
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_INVALID_DOWNLOAD_FILE_ERROR,
+ 2,
+ initAdapter,
+ MADGE_ERRMSG_OPEN_IMAGE_FILE
+ );
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Map in the FastMAC Plus image file.
+ //
+
+ NdisMapFile(&status, &imagePtr, imageFile);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 2,
+ initAdapter,
+ MADGE_ERRMSG_MAP_IMAGE_FILE
+ );
+
+ NdisCloseFile(imageFile);
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ //
+ // Make sure that the image file is valid by checking its checksum,
+ // version number and signature.
+ //
+
+ downHdrPtr = (DOWNLOAD_FILE_HEADER *) imagePtr;
+ chkPtr = ((UCHAR *) imagePtr) + DOWNLOAD_CHECKSUM_SKIP;
+ chkSum = 0;
+
+ for (i = DOWNLOAD_CHECKSUM_SKIP; i < imageLength; i++)
+ {
+ DOWNLOAD_CHECKSUM_BYTE(chkSum, *chkPtr);
+ chkPtr++;
+ }
+
+ if (!IS_DOWNLOAD_OK(downHdrPtr, chkSum))
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_INVALID_DOWNLOAD_FILE_ERROR,
+ 2,
+ initAdapter,
+ MADGE_ERRMSG_BAD_IMAGE_FILE
+ );
+
+ NdisUnmapFile(imageFile);
+ NdisCloseFile(imageFile);
+
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ *downloadFile = imageFile;
+ *download = imagePtr;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+#else
+
+#include "fmplus.c"
+
+#endif
+
+#ifdef _M_IX86
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeArbitrateBufferMemory
+|
+| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
+|
+| Purpose - Determine if we can allocate all the shared memory
+Ý we need for DMA buffer space and if we can't then
+Ý reduce our requirements until we can or we reach
+Ý our minimum requirements. If the buffer space cannot
+Ý be aribtrated then the requirements are left as is and
+Ý it is assumed that the FTK initialisation will fail
+Ý and generate an out of memory error.
+|
+| Returns - Nothing.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC VOID
+MadgeArbitrateBufferMemory(PMADGE_ADAPTER ndisAdap);
+
+#pragma FTK_INIT_FUNCTION(MadgeArbitrateBufferMemory)
+
+STATIC VOID
+MadgeArbitrateBufferMemory(PMADGE_ADAPTER ndisAdap)
+{
+ VOID * testVirt;
+ VOID * rxVirt;
+ VOID * txVirt;
+ NDIS_PHYSICAL_ADDRESS testPhys;
+ NDIS_PHYSICAL_ADDRESS rxPhys;
+ NDIS_PHYSICAL_ADDRESS txPhys;
+ ULONG rxBufferSize;
+ ULONG txBufferSize;
+ UINT maxFrameSize;
+ UINT rxSlots;
+ UINT txSlots;
+ BOOLEAN succeeded;
+ BOOLEAN failed;
+ BOOLEAN arbitrated;
+
+ //
+ // There doesn't seem to be a problem allocating none
+ // shared memory so if we aren't in DMA mode then
+ // don't do anything.
+ //
+
+ if (ndisAdap->TransferMode != DMA_DATA_TRANSFER_MODE)
+ {
+ return;
+ }
+
+ //
+ // The first bit of shared memory we must have is for the DMA
+ // test buffers.
+ //
+
+ testVirt = NULL;
+
+ NdisMAllocateSharedMemory(
+ ndisAdap->UsedInISR.MiniportHandle,
+ SCB_TEST_PATTERN_LENGTH + SSB_TEST_PATTERN_LENGTH,
+ FALSE,
+ &testVirt,
+ &testPhys
+ );
+
+ //
+ // If we can't allocate the test buffer then just give up.
+ //
+
+ if (testVirt == NULL)
+ {
+ return;
+ }
+
+ //
+ // We've got the test buffer memory so now arbitrate the
+ // RX/TX buffers. Note: the buffer allocation MUST MATCH
+ // THAT IN FTK_USER.C.
+ //
+
+ maxFrameSize = ndisAdap->MaxFrameSize;
+ rxSlots = ndisAdap->FastmacRxSlots;
+ txSlots = ndisAdap->FastmacTxSlots;
+
+ failed = FALSE;
+ succeeded = FALSE;
+ arbitrated = FALSE;
+
+ while (!failed && !succeeded)
+ {
+ rxVirt = NULL;
+ txVirt = NULL;
+
+ //
+ // Try to allocate the receive buffer.
+ //
+
+ rxBufferSize = ((maxFrameSize + 4 + 32 + 3) & ~3) * rxSlots;
+
+ NdisMAllocateSharedMemory(
+ ndisAdap->UsedInISR.MiniportHandle,
+ rxBufferSize,
+ FALSE,
+ &rxVirt,
+ &rxPhys
+ );
+
+ //
+ // If we allocated the RX buffer space then try to allocate
+ // the TX buffer space.
+ //
+
+ if (rxVirt != NULL)
+ {
+ txBufferSize = ((maxFrameSize + 3) & ~3) * txSlots;
+
+ NdisMAllocateSharedMemory(
+ ndisAdap->UsedInISR.MiniportHandle,
+ txBufferSize,
+ FALSE,
+ &txVirt,
+ &txPhys
+ );
+ }
+
+ //
+ // Free any buffers we managed to allocate.
+ //
+
+ if (rxVirt != NULL)
+ {
+ NdisMFreeSharedMemory(
+ ndisAdap->UsedInISR.MiniportHandle,
+ rxBufferSize,
+ FALSE,
+ rxVirt,
+ rxPhys
+ );
+ }
+
+ if (txVirt != NULL)
+ {
+ NdisMFreeSharedMemory(
+ ndisAdap->UsedInISR.MiniportHandle,
+ txBufferSize,
+ FALSE,
+ txVirt,
+ txPhys
+ );
+ }
+
+ //
+ // If we managed to allocate both buffers then we have
+ // succeeded.
+ //
+
+ if (rxVirt != NULL && txVirt != NULL)
+ {
+ succeeded = TRUE;
+ }
+
+ //
+ // Otherwise we must reduce our memory requirements.
+ //
+
+ else
+ {
+ arbitrated = TRUE;
+
+ //
+ // First try reducing the number of transmit slots.
+ //
+
+ if (txSlots > FMPLUS_MIN_TX_SLOTS)
+ {
+ txSlots--;
+ }
+
+ //
+ // Next try reducing the number of receive slots.
+ //
+
+ else if (rxSlots > FMPLUS_MIN_RX_SLOTS)
+ {
+ rxSlots--;
+ }
+
+ //
+ // Finally try reducing the frame size. 1800 bytes has
+ // empirically shown to be the minimum value required
+ // for the DOMAIN server startup to work at NT installation.
+ //
+
+ else if (maxFrameSize > 1800)
+ {
+ maxFrameSize -= 512;
+
+ if (maxFrameSize < 1800)
+ {
+ maxFrameSize = 1800;
+ }
+ }
+
+ //
+ // If we can't reduce our buffer requirements any further
+ // then fail.
+ //
+
+ else
+ {
+ failed = TRUE;
+ }
+ }
+ }
+
+ //
+ // Free the memory for the DMA test buffer.
+ //
+
+ NdisMFreeSharedMemory(
+ ndisAdap->UsedInISR.MiniportHandle,
+ SCB_TEST_PATTERN_LENGTH + SSB_TEST_PATTERN_LENGTH,
+ FALSE,
+ testVirt,
+ testPhys
+ );
+
+ //
+ // If we have succeded then we must update the requirements in
+ // adapter structure and if we have changed any values we must
+ // write a message to the event log.
+ //
+
+ if (succeeded && arbitrated)
+ {
+ ndisAdap->MaxFrameSize = maxFrameSize;
+ ndisAdap->FastmacRxSlots = rxSlots;
+ ndisAdap->FastmacTxSlots = txSlots;
+
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
+ 1,
+ initAdapter
+ );
+ }
+}
+
+#endif
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeInitAdapter
+|
+| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
+|
+| Purpose - Initialise an adapter.
+|
+| Returns - An NDIS3 status code.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC NDIS_STATUS
+MadgeInitAdapter(PMADGE_ADAPTER ndisAdap);
+
+#pragma FTK_INIT_FUNCTION(MadgeInitAdapter)
+
+STATIC NDIS_STATUS
+MadgeInitAdapter(PMADGE_ADAPTER ndisAdap)
+{
+ WORD ftkStatus;
+ NDIS_STATUS status;
+ PREPARE_ARGS prepare;
+ START_ARGS start;
+
+#ifndef LINK_FMPLUS
+
+ NDIS_HANDLE imageFile;
+ PVOID imagePtr;
+
+#endif
+
+ MadgePrint1("MadgeInitAdapter started\n");
+
+ //
+ // If we are doing MMIO then we need to map in the MMIO memory.
+ // If we fail to map in the memory then default ti PIO.
+ //
+
+ if (ndisAdap->TransferMode == MMIO_DATA_TRANSFER_MODE)
+ {
+ if (MadgeMapMmioMemory(ndisAdap) != NDIS_STATUS_SUCCESS)
+ {
+ ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
+ }
+ }
+
+#ifdef _M_IX86
+
+ //
+ // Arbitrate "DMA" buffer memory.
+ //
+
+ MadgeArbitrateBufferMemory(ndisAdap);
+
+#endif
+
+ //
+ // Set up the arguments to pass to driver_prepare_adapter.
+ //
+
+ MADGE_ZERO_MEMORY(&prepare, sizeof(PREPARE_ARGS));
+
+ prepare.user_information = (void *) ndisAdap;
+ prepare.number_of_rx_slots = (WORD) ndisAdap->FastmacRxSlots;
+ prepare.number_of_tx_slots = (WORD) ndisAdap->FastmacTxSlots;
+ prepare.max_frame_size = (WORD) ndisAdap->MaxFrameSize;
+
+ //
+ // Try to prepare the adapter for use.
+ //
+
+ //
+ // Mark the fact that the FTK has been called, so that we know if we
+ // have to call driver_remove_adapter() when doing clean up.
+ //
+
+ ndisAdap->FtkInitialized = TRUE;
+
+ MadgePrint1("driver_prepare_adapter called\n");
+
+ if (!driver_prepare_adapter(&prepare, &(ndisAdap->FtkAdapterHandle)))
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ MadgePrint1("driver_prepare_adapter returned\n");
+ MadgePrint2("adapter_handle = %d\n", ndisAdap->FtkAdapterHandle);
+
+#ifndef LINK_FMPLUS
+
+ //
+ // Read in the download file.
+ //
+
+ status = MadgeReadDownload(ndisAdap, &imageFile, &imagePtr);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ return status;
+ }
+
+#endif
+
+ //
+ // Set up the arguments to driver_start_adapter.
+ //
+
+ MADGE_ZERO_MEMORY(&start, sizeof(START_ARGS));
+
+ start.adapter_card_bus_type = (UINT) ndisAdap->FTKCardBusType;
+
+ start.io_location = (WORD) ndisAdap->IoLocation1;
+ start.transfer_mode = (UINT) ndisAdap->TransferMode;
+ start.dma_channel = (WORD) ndisAdap->DmaChannel;
+ start.interrupt_number = (WORD) ndisAdap->UsedInISR.InterruptNumber;
+ start.set_dma_channel = TRUE;
+ start.set_interrupt_number = TRUE;
+ start.mmio_base_address = (DWORD) ndisAdap->MmioVirtualAddress;
+ start.pci_handle = (DWORD) ndisAdap->SlotNumber;
+
+ if (ndisAdap->Force16)
+ {
+ start.set_ring_speed = 16;
+ }
+ else if (ndisAdap->Force4)
+ {
+ start.set_ring_speed = 4;
+ }
+
+ start.opening_node_address = ndisAdap->OpeningNodeAddress;
+ start.auto_open_option = TRUE;
+
+ if (ndisAdap->ForceOpen)
+ {
+ ndisAdap->OpenOptions |= OPEN_OPT_FORCE_OPEN;
+ }
+
+ start.open_options = (WORD) ndisAdap->OpenOptions;
+
+ start.rx_tx_buffer_size = (WORD) ndisAdap->CardBufferSize;
+
+#ifndef LINK_FMPLUS
+
+ start.code = (DOWNLOAD_IMAGE *)
+ (((UCHAR *) imagePtr) + sizeof(DOWNLOAD_FILE_HEADER));
+
+#else
+
+ start.code = (DOWNLOAD_IMAGE *) fmplus_image;
+
+#endif
+
+ MadgePrint1("driver_start_adapter called\n");
+
+ ftkStatus = driver_start_adapter(
+ ndisAdap->FtkAdapterHandle,
+ &start,
+ &ndisAdap->PermanentNodeAddress
+ );
+
+ MadgePrint1("driver_start_adapter returned\n");
+ MadgePrint2("MAC buffer size = %d\n",
+ adapter_record[ndisAdap->FtkAdapterHandle
+ ]->init_block->smart_parms.rx_tx_buffer_size
+ );
+
+#ifndef LINK_FMPLUS
+
+ //
+ // No matter what we have finished with the FastMAC Plus image file.
+ //
+
+ NdisUnmapFile(imageFile);
+ NdisCloseFile(imageFile);
+
+#endif
+
+ if (!ftkStatus)
+ {
+ MadgePrint1("driver_start_adapter failed\n");
+
+ //
+ // Were it not for the fact that we are going to clean up and fail
+ // as soon as we return, we ought to set the CurrentRingState to
+ // NdisRingStateOpenFailure here if AutoOpen was selected.
+ //
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // Warn the user if FastMAC Plus had to reduce the frame size.
+ //
+
+ if (ndisAdap->MaxFrameSize > start.max_frame_size)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
+ 3,
+ initAdapter,
+ MADGE_ERRMSG_REDUCE_MAX_FSIZE,
+ ndisAdap->MaxFrameSize
+ );
+ }
+
+ ndisAdap->MaxFrameSize = start.max_frame_size;
+
+ //
+ // If we did not specify a locally administered address then copy the
+ // permanent one across to the local one.
+ //
+
+ if (ndisAdap->OpeningNodeAddress.byte[0] == 0)
+ {
+ MADGE_MOVE_MEMORY(
+ &ndisAdap->OpeningNodeAddress,
+ &ndisAdap->PermanentNodeAddress,
+ sizeof(ndisAdap->PermanentNodeAddress)
+ );
+ }
+
+ //
+ // Note that the adapter is open.
+ //
+
+ ndisAdap->CurrentRingState = NdisRingStateOpened;
+ ndisAdap->LastOpenStatus = start.open_status;
+
+ //
+ // Nasty hack. If we have a PciT atapter with broken dma and we are
+ // running on a multiprocessor we need set the multiprocessor safe
+ // PIO flag to make sure that we don't do DIO whilst our interrupt
+ // hander is running. Unfortunately we don't know if we have
+ // broken DMA until after we've started the adapter.
+ //
+
+ if (ndisAdap->Multiprocessor &&
+ adapter_record[ndisAdap->FtkAdapterHandle]->mc32_config ==
+ TRN_PCIT_BROKEN_DMA)
+ {
+ MadgePrint1("Using MP sfae PIO because of PCIT DMA.\n");
+ ndisAdap->UseMPSafePIO = TRUE;
+ }
+
+ //
+ // Note that we MUST start the receive process, even if we are NOT using
+ // auto-open, because FastmacPlus ignores SRBs (including OPEN SRBs) if
+ // this has not been done.
+ //
+
+ driver_start_receive_process(ndisAdap->FtkAdapterHandle);
+
+ //
+ // We now need to set the product instance ID. The product instance
+ // ID will be set to the contents of ftk_product_inst_id[] if we
+ // issue an open SRB, but since Miniports always auto-open we
+ // need to generate a set product instance SRB to set it.
+ //
+
+ //
+ // Note that we are generating a private SRB (not to be treated
+ // as a normal NDIS request), generate the SRB and then wait
+ // for it to finish.
+ //
+
+ ndisAdap->PrivateSrbInProgress = TRUE;
+
+ MadgePrint1("Calling driver_set_product_instance_id\n");
+
+ driver_set_product_instance_id(
+ ndisAdap->FtkAdapterHandle,
+ NT_PRODUCT_INSTANCE_ID
+ );
+
+ MadgePrint1("Waiting for SRB to complete\n");
+
+ while (FlagIsTrue(&ndisAdap->PrivateSrbInProgress))
+ NdisMSleep(100);
+
+ MadgePrint1("MadgeInitAdapter finished\n");
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeCleanupAdapter
+|
+| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
+|
+| Purpose - Deallocate the resources associated with an adapter.
+|
+| Returns - Nothing.
+|
+|--------------------------------------------------------------------------*/
+
+STATIC VOID
+MadgeCleanupAdapter(PMADGE_ADAPTER ndisAdap)
+{
+ BOOLEAN timerOutstanding;
+
+ MadgePrint1("MadgeCleanupAdapter 1\n");
+
+ if (ndisAdap->TimerInitialized)
+ {
+ NdisMCancelTimer(&ndisAdap->WakeUpTimer, &timerOutstanding);
+ NdisMCancelTimer(&ndisAdap->CompletionTimer, &timerOutstanding);
+ ndisAdap->TimerInitialized = FALSE;
+ }
+
+ MadgePrint1("MadgeCleanupAdapter 2\n");
+
+ if (ndisAdap->FtkInitialized)
+ {
+ rxtx_await_empty_tx_slots(ndisAdap->FtkAdapterHandle);
+ driver_remove_adapter(ndisAdap->FtkAdapterHandle);
+ ndisAdap->FtkInitialized = FALSE;
+ }
+
+ if (ndisAdap->MapRegistersAllocated > 0)
+ {
+ NdisMFreeMapRegisters(ndisAdap->UsedInISR.MiniportHandle);
+ ndisAdap->MapRegistersAllocated = 0;
+ }
+
+ MadgePrint1("MadgeCleanupAdapter 3\n");
+
+ if (ndisAdap->MmioMapped)
+ {
+ NdisMUnmapIoSpace(
+ ndisAdap->UsedInISR.MiniportHandle,
+ ndisAdap->MmioVirtualAddress,
+ PCI_MMIO_SIZE
+ );
+ ndisAdap->MmioMapped = FALSE;
+ }
+
+ MadgePrint1("MadgeCleanupAdapter 4\n");
+
+ if (ndisAdap->IORange1Initialized)
+ {
+ NdisMDeregisterIoPortRange(
+ ndisAdap->UsedInISR.MiniportHandle,
+ ndisAdap->IoLocation1 + ndisAdap->IoLocationBase,
+ ndisAdap->IORange1,
+ ndisAdap->MappedIOLocation1
+ );
+ ndisAdap->IORange1Initialized = FALSE;
+ }
+
+ MadgePrint1("MadgeCleanupAdapter 5\n");
+
+ if (ndisAdap->IORange2Initialized)
+ {
+ NdisMDeregisterIoPortRange(
+ ndisAdap->UsedInISR.MiniportHandle,
+ ndisAdap->IoLocation2 + ndisAdap->IoLocationBase,
+ ndisAdap->IORange2,
+ ndisAdap->MappedIOLocation2
+ );
+ ndisAdap->IORange2Initialized = FALSE;
+ }
+
+ MadgePrint1("MadgeCleanupAdapter 6\n");
+
+ if (ndisAdap->ShutdownHandlerRegistered)
+ {
+ NdisMDeregisterAdapterShutdownHandler(
+ ndisAdap->UsedInISR.MiniportHandle
+ );
+ ndisAdap->ShutdownHandlerRegistered = FALSE;
+
+ MadgePrint1("De-registered shutdown handler\n");
+ }
+
+ MADGE_FREE_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
+}
+
+
+/***************************************************************************
+*
+* Function - MadgeHalt
+*
+* Parameters - adapterContext -> Pointer to our NDIS level adapter
+* structure.
+*
+* Purpose - Process a call from the NDIS3 wrapper to remove an
+* adapter instance.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeHalt(NDIS_HANDLE adapterContext)
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ MadgePrint1("MadgeHalt started\n");
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
+
+ //
+ // The NDIS interface guarantees that all bindings are closed, i.e. all
+ // MadgeCloseAdapter calls have completed successfully.
+ //
+
+ ndisAdap->HardwareStatus = NdisHardwareStatusClosing;
+
+ MadgeCleanupAdapter(ndisAdap);
+
+ MadgePrint1("MadgeHalt finished\n");
+}
+
+
+/****************************************************************************
+*
+* Function - MadgeTxCompletion
+*
+* Parameters - systemSpecific1 -> Unused.
+* context -> Actually a pointer to our NDIS3 level
+* adapter structure.
+* systemSpecific2 -> Unused.
+* systemSpecific3 -> Unused.
+*
+* Purpose - Call our TX competion routine as a result of a timer.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+VOID
+MadgeTxCompletion(
+ PVOID systemSpecific1,
+ PVOID context,
+ PVOID systemSpecific2,
+ PVOID systemSpecific3
+ )
+{
+ PMADGE_ADAPTER ndisAdap = (PMADGE_ADAPTER) context;
+
+ //
+ // Call the TX completion function.
+ //
+
+ rxtx_irq_tx_completion_check(
+ ndisAdap->FtkAdapterHandle,
+ adapter_record[ndisAdap->FtkAdapterHandle]
+ );
+}
+
+
+/***************************************************************************
+*
+* Function - MadgeInitialise
+*
+* Parameters - openErrorStatus -> Pointer to a holder for an open
+* error status.
+* selectedMediumIndex -> Pointer to a holder for the index
+* of the medium selected.
+* mediumArray -> Array of media types.
+* mediumArraySize -> Size of the media array.
+* miniportHandle -> Miniport adapter handle.
+* wrapperConfigContext -> Handle used when querying the
+* registry.
+*
+* Purpose - Carry out adapter instance initialisation.
+*
+* Returns - An NDIS3 status code.
+*
+***************************************************************************/
+
+NDIS_STATUS
+MadgeInitialize(
+ PNDIS_STATUS openErrorStatus,
+ PUINT selectedMediumIndex,
+ PNDIS_MEDIUM mediumArray,
+ UINT mediumArraySize,
+ NDIS_HANDLE miniportHandle,
+ NDIS_HANDLE wrapperConfigContext
+ );
+
+#pragma FTK_INIT_FUNCTION(MadgeInitialize)
+
+NDIS_STATUS
+MadgeInitialize(
+ PNDIS_STATUS openErrorStatus,
+ PUINT selectedMediumIndex,
+ PNDIS_MEDIUM mediumArray,
+ UINT mediumArraySize,
+ NDIS_HANDLE miniportHandle,
+ NDIS_HANDLE wrapperConfigContext
+ )
+{
+ NDIS_STATUS status;
+ PMADGE_ADAPTER ndisAdap;
+ NDIS_HANDLE configHandle;
+ UINT i;
+
+ MadgePrint1("MadgeInitialize started\n");
+
+ //
+ // ---------------------------------------------------------------------
+ // Check that the upper protocol knows about token ring and if
+ // it does set the index.
+ //
+
+ for (i = 0; i < mediumArraySize; i++)
+ {
+ if (mediumArray[i] == NdisMedium802_5)
+ {
+ break;
+ }
+ }
+
+ if (i == mediumArraySize)
+ {
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;
+ }
+
+ *selectedMediumIndex = i;
+
+ //
+ // ---------------------------------------------------------------------
+ // Doing basic sanity checks and allocating some memory for our
+ // per-adapter structure.
+ //
+
+ if (wrapperConfigContext == NULL)
+ {
+ //
+ // No registry config. information found by NDIS library for us.
+ // We cannot proceed without it.
+ //
+
+ return NDIS_STATUS_FAILURE;
+ }
+
+ //
+ // Allocate memory for the adapter structure.
+ //
+
+ MADGE_ALLOC_MEMORY(&status, &ndisAdap, sizeof(MADGE_ADAPTER));
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Failed to allocate adapter structure. Can't go on without it.
+ //
+
+ return status;
+ }
+
+ MADGE_ZERO_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
+
+ MadgePrint2("ndisAdap = %x\n", ndisAdap);
+
+ //
+ // We need the mini port handle early on.
+ //
+
+ ndisAdap->UsedInISR.MiniportHandle = miniportHandle;
+
+ //
+ // ---------------------------------------------------------------------
+ // Read the registry: open the registry, read the contents, and close it
+ // again. This will handle adapter parameters and LAAs, and also working
+ // out various values to do with interrupt modes.
+ //
+
+ MadgePrint1("NdisOpenConfiguration called\n");
+
+ NdisOpenConfiguration(
+ &status,
+ &configHandle,
+ wrapperConfigContext
+ );
+
+ MadgePrint1("NdisOpenConfiguration returned\n");
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ MadgePrint2("NdisOpenConfiguration failed rc=%x\n", status);
+ MADGE_FREE_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
+ return status;
+ }
+
+ status = MadgeReadRegistry(
+ wrapperConfigContext,
+ configHandle,
+ ndisAdap
+ );
+
+ NdisCloseConfiguration(configHandle);
+
+ //
+ // We have gleaned all we can from the registry - was it all OK?
+ //
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // If Status is not success, it will be either NDIS_STATUS_FAILURE
+ // if a parameter was out of range, or it will be the error code
+ // returned by NdisReadConfiguration().
+ //
+
+ MadgePrint2("MadgeReadRegistry failed rc = %x\n", status);
+ MADGE_FREE_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
+ return status;
+ }
+
+ //
+ // ---------------------------------------------------------------------
+ // Having read the registry, we can initialize the rest of the fields in
+ // the adapter structure.
+ //
+
+ #define I_DATA ActualValue.ParameterData.IntegerData
+
+ //
+ // Copy the values from the Parameter table into the per-adapter struct.
+ // This is necessary because the Parameter table will be used again for
+ // the next card that is added.
+ //
+ // Note that we handle the rx/tx slots configuration in a special way.
+ // The value of rx/tx slots is set by indexing into a table with the
+ // single paramter RxTxSlots, unless RxSlots or TxSlots have been set in
+ // which case these values override the values derived from RxTxSlots.
+ //
+
+ switch (MadgeParmTable.RxTxSlots.I_DATA)
+ {
+ case 0:
+ ndisAdap->FastmacTxSlots = 2;
+ ndisAdap->FastmacRxSlots = 2;
+ break;
+ case 1:
+ ndisAdap->FastmacTxSlots = 3;
+ ndisAdap->FastmacRxSlots = 3;
+ break;
+ case 2:
+ ndisAdap->FastmacTxSlots = 4;
+ ndisAdap->FastmacRxSlots = 4;
+ break;
+ case 3:
+ ndisAdap->FastmacTxSlots = 6;
+ ndisAdap->FastmacRxSlots = 6;
+ break;
+ case 4:
+ ndisAdap->FastmacTxSlots = 8;
+ ndisAdap->FastmacRxSlots = 8;
+ break;
+ case 5:
+ ndisAdap->FastmacTxSlots = 10;
+ ndisAdap->FastmacRxSlots = 10;
+ break;
+ default:
+ ndisAdap->FastmacTxSlots = 4;
+ ndisAdap->FastmacRxSlots = 4;
+ break;
+ }
+
+ if (MadgeParmTable.TxSlots.I_DATA != 0)
+ {
+ ndisAdap->FastmacTxSlots = MadgeParmTable.TxSlots.I_DATA;
+ }
+
+ if (MadgeParmTable.RxSlots.I_DATA != 0)
+ {
+ ndisAdap->FastmacRxSlots = MadgeParmTable.RxSlots.I_DATA;
+ }
+
+ MadgePrint3("TX slots = %d RX slots = %d\n",
+ ndisAdap->FastmacTxSlots,
+ ndisAdap->FastmacRxSlots
+ );
+
+ ndisAdap->MaxFrameSize = MadgeParmTable.MaxFrameSize.I_DATA;
+ ndisAdap->CardBufferSize = MadgeParmTable.CardBufferSize.I_DATA;
+ ndisAdap->PromiscuousMode = (MadgeParmTable.PromiscuousMode.I_DATA == 1);
+ ndisAdap->AlternateIo = (MadgeParmTable.AlternateIo.I_DATA == 1);
+ ndisAdap->TestAndXIDEnabled = (MadgeParmTable.TestAndXIDEnabled.I_DATA == 1);
+ ndisAdap->ForceOpen = (MadgeParmTable.ForceOpen.I_DATA == 1);
+ ndisAdap->Force4 = (MadgeParmTable.Force4.I_DATA == 1);
+ ndisAdap->Force16 = (MadgeParmTable.Force16.I_DATA == 1);
+ ndisAdap->Multiprocessor = (NdisSystemProcessorCount() > 1);
+
+ if (ndisAdap->TransferMode != DMA_DATA_TRANSFER_MODE &&
+ ndisAdap->Multiprocessor)
+ {
+ ndisAdap->UseMPSafePIO = TRUE;
+ }
+
+ //
+ // If the RingSpeed parameter is present then this overrides the
+ // Force4 and Force16 parameters. RingSpeed == 0 means either not
+ // present or don't care. RingSpeed == 1 means 4MBits. RingSpeed == 2
+ // means 16MBits.
+ //
+
+ switch (MadgeParmTable.RingSpeed.I_DATA)
+ {
+ case 1:
+ ndisAdap->Force4 = TRUE;
+ ndisAdap->Force16 = FALSE;
+ break;
+
+ case 2:
+ ndisAdap->Force4 = FALSE;
+ ndisAdap->Force16 = TRUE;
+
+ default:
+ break;
+ }
+
+ //
+ // Initialize the rest of the Adapter structure.
+ //
+
+ ndisAdap->UsedInISR.MiniportHandle = miniportHandle;
+ ndisAdap->CurrentLookahead = ndisAdap->MaxFrameSize - FRAME_HEADER_SIZE;
+ ndisAdap->CurrentRingState = NdisRingStateClosed;
+ ndisAdap->HardwareStatus = NdisHardwareStatusNotReady;
+
+ //
+ // These next few lines are strictly unnecessary because their fields in
+ // the structure are already zero from our earlier ZERO_MEMORY() call.
+ //
+
+ ndisAdap->UsedInISR.SrbRequestCompleted = FALSE;
+ ndisAdap->UsedInISR.SrbRequestStatus = FALSE;
+ ndisAdap->DprInProgress = FALSE;
+
+ //
+ // One nasty piece of hackery for Smart16 cards, whereby we must add to
+ // the IoLocation 0x1000 if the Alternate switch is true.
+ //
+
+ if (ndisAdap->NTCardBusType == NdisInterfaceIsa &&
+ ndisAdap->IoLocation1 > 0x3a20 &&
+ ndisAdap->AlternateIo)
+ {
+ ndisAdap->IoLocation1 += 0x1000;
+ }
+
+ //
+ // We need to know where the end of the first range of IO locations
+ // we use is.
+ //
+
+ ndisAdap->IORange1End = ndisAdap->IoLocation1 + ndisAdap->IORange1 - 1;
+
+ //
+ // ---------------------------------------------------------------------
+ // We can now try to register the adapter. This involves filling in the
+ // AdapterInformation structure and calling NdisRegisterAdapter(). See
+ // the function MadgeRegisterAdapter for details.
+ //
+
+ if ((status = MadgeRegisterAdapter(
+ ndisAdap,
+ wrapperConfigContext
+ )) != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Either we failed to allocate memory for the adapter information
+ // structure, or the NdisRegisterAdapter() call failed.
+ //
+
+ MadgePrint2("MadgeRegisterAdapter failed rc = %x\n", status);
+ MADGE_FREE_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
+ return status;
+ }
+
+ //
+ // ---------------------------------------------------------------------
+ // We are now into the last stages of initialization. This is going to
+ // cause to be allocated several more resources (in the form of kernel
+ // objects, filter databases, FTK structures, interrupt channels, ...)
+ // so from here on we have to be a lot more careful about cleaning up.
+ //
+
+ ndisAdap->HardwareStatus = NdisHardwareStatusInitializing;
+
+ //
+ // Call the FTK to download the MAC code to the card and initialize it.
+ //
+
+ status = MadgeInitAdapter(ndisAdap);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // If it was an FTK generated error then log an appropriate event.
+ //
+
+ if (status == NDIS_STATUS_FAILURE)
+ {
+ BYTE error_type;
+ BYTE error_value;
+ char * error_message;
+
+ driver_explain_error(
+ ndisAdap->FtkAdapterHandle,
+ &error_type,
+ &error_value,
+ &error_message
+ );
+
+ MadgePrint3("FTK error %02x, %02x\n", error_type, error_value);
+
+ //
+ // To keep Microsoft happy we will generate special error
+ // messages for some of the more common error conditions.
+ //
+
+ //
+ // An open error is probably because the cable isn't plugged in.
+ //
+
+ if (error_type == ERROR_TYPE_OPEN ||
+ error_type == ERROR_TYPE_AUTO_OPEN)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
+ 4,
+ madgeInitialize,
+ MADGE_ERRMSG_INITIAL_INIT,
+ (ULONG) error_type,
+ (ULONG) error_value
+ );
+ }
+ else
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_HARDWARE_FAILURE,
+ 4,
+ madgeInitialize,
+ MADGE_ERRMSG_INITIAL_INIT,
+ (ULONG) error_type,
+ (ULONG) error_value
+ );
+ }
+ }
+
+ //
+ // In any case, tidy up the adapter and abort.
+ //
+
+ MadgeCleanupAdapter(ndisAdap);
+ return status;
+ }
+
+ ndisAdap->HardwareStatus = NdisHardwareStatusReady;
+
+ //
+ // Set up the ring status monitor function.
+ //
+
+ NdisMInitializeTimer(
+ &ndisAdap->WakeUpTimer,
+ ndisAdap->UsedInISR.MiniportHandle,
+ (PVOID) MadgeGetAdapterStatus,
+ ndisAdap
+ );
+
+ NdisMSetTimer(&ndisAdap->WakeUpTimer, EVERY_2_SECONDS);
+
+ NdisMInitializeTimer(
+ &ndisAdap->CompletionTimer,
+ ndisAdap->UsedInISR.MiniportHandle,
+ (PVOID) MadgeTxCompletion,
+ ndisAdap
+ );
+
+ ndisAdap->TimerInitialized = TRUE;
+
+ MadgePrint1("MadgeInitialize finished\n");
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/***************************************************************************
+*
+* Function - DriverEntry
+*
+* Parameters - driverObject -> Pointer to a driver object.
+* registryPath -> Path to our configuration information in
+* the registry.
+*
+* Purpose - Carry out the driver (as opposed to adapter instance)
+* initialisation. This is the main entry point.
+*
+* Returns - An NDIS3 status code.
+*
+***************************************************************************/
+
+NDIS_STATUS
+DriverEntry(PDRIVER_OBJECT driverObject, PUNICODE_STRING registryPath);
+
+#pragma FTK_INIT_FUNCTION(DriverEntry)
+
+NDIS_STATUS
+DriverEntry(PDRIVER_OBJECT driverObject, PUNICODE_STRING registryPath)
+{
+ NDIS_HANDLE ndisWrapperHandle;
+ NDIS_STATUS status;
+ NDIS_MINIPORT_CHARACTERISTICS madgeChar;
+ UINT i;
+
+ MadgePrint1("DriverEntry starting\n");
+
+ //
+ // We are obliged first of all to initialize the NDIS wrapper.
+ //
+
+ MadgePrint1("NdisMInitializeWrapper called\n");
+
+ NdisMInitializeWrapper(
+ &ndisWrapperHandle,
+ driverObject,
+ registryPath,
+ NULL
+ );
+
+ MadgePrint1("NdisMInitializeWrapper returned\n");
+
+ //
+ // Decode any hidden strings here, for use later in MacAddAdapter. This
+ // only applies to PromiscuousMode support at the moment.
+ //
+
+ for (i = 0;
+ i < MadgeParmTable.PromiscuousMode.Keyword.Length /
+ sizeof(*(MadgeParmTable.PromiscuousMode.Keyword.Buffer));
+ i++)
+ {
+ MadgeParmTable.PromiscuousMode.Keyword.Buffer[i] -= HIDDEN_OFFS;
+ }
+
+ //
+ // Fill in the characteristics table - this lists all the driver entry
+ // points that may be called by the NDIS wrapper.
+ //
+
+ madgeChar.MajorNdisVersion = MADGE_NDIS_MAJOR_VERSION;
+ madgeChar.MinorNdisVersion = MADGE_NDIS_MINOR_VERSION;
+ madgeChar.CheckForHangHandler = MadgeCheckForHang;
+ madgeChar.DisableInterruptHandler = MadgeDisableInterrupts;
+ madgeChar.EnableInterruptHandler = MadgeEnableInterrupts;
+ madgeChar.HaltHandler = MadgeHalt;
+ madgeChar.HandleInterruptHandler = MadgeHandleInterrupt;
+ madgeChar.InitializeHandler = MadgeInitialize;
+ madgeChar.ISRHandler = MadgeISR;
+ madgeChar.QueryInformationHandler = MadgeQueryInformation;
+ madgeChar.ReconfigureHandler = NULL;
+ madgeChar.ResetHandler = MadgeReset;
+ madgeChar.SendHandler = MadgeSend;
+ madgeChar.SetInformationHandler = MadgeSetInformation;
+ madgeChar.TransferDataHandler = MadgeTransferData;
+
+ //
+ // Register the miniport driver with NDIS library.
+ //
+
+ MadgePrint1("NdisMRegisterMiniport called\n");
+
+ status = NdisMRegisterMiniport(
+ ndisWrapperHandle,
+ &madgeChar,
+ sizeof(madgeChar)
+ );
+
+ MadgePrint1("NdisMRegisterMiniport returned\n");
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ MadgePrint2("NdisMRegisterMiniport failed rc=%x\n", status);
+ NdisTerminateWrapper(ndisWrapperHandle, NULL);
+ return NDIS_STATUS_FAILURE;
+ }
+
+ MadgePrint1("DriverEntry finished\n");
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/******** End of MADGE.C ***************************************************/
+
diff --git a/private/ntos/ndis/madge/driver/makefile b/private/ntos/ndis/madge/driver/makefile
new file mode 100644
index 000000000..9481f22cd
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/madge/driver/makefile.inc b/private/ntos/ndis/madge/driver/makefile.inc
new file mode 100644
index 000000000..6eba30160
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/makefile.inc
@@ -0,0 +1,5 @@
+mdgmport.bin: $(TARGETEXEFILES)
+ chmode -r mdgmport.bin
+ binplace mdgmport.bin
+ touch mdgmport.bin
+ chmode +r mdgmport.bin
diff --git a/private/ntos/ndis/madge/driver/mdgerrs.h b/private/ntos/ndis/madge/driver/mdgerrs.h
new file mode 100644
index 000000000..af2e4b3d3
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/mdgerrs.h
@@ -0,0 +1,154 @@
+//
+// Values are 32 bit values layed out as follows:
+//
+// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +---+-+-+-----------------------+-------------------------------+
+// |Sev|C|R| Facility | Code |
+// +---+-+-+-----------------------+-------------------------------+
+//
+// where
+//
+// Sev - is the severity code
+//
+// 00 - Success
+// 01 - Informational
+// 10 - Warning
+// 11 - Error
+//
+// C - is the Customer code flag
+//
+// R - is a reserved bit
+//
+// Facility - is the facility code
+//
+// Code - is the facility's status code
+//
+//
+// Define the facility codes
+//
+
+
+//
+// Define the severity codes
+//
+
+
+//
+// MessageId: NDIS_ERROR_CODE_OUT_OF_RESOURCE
+//
+// MessageText:
+//
+// Adapter %2 : Insufficient memory or system resources was available
+// for the netcard driver to initialize. (The last DWORD of the data section
+// below contains a detailed error code.)
+//
+#define NDIS_ERROR_CODE_OUT_OF_RESOURCE ((NDIS_ERROR_CODE)0xC0001389L)
+
+//
+// MessageId: NDIS_ERROR_CODE_HARDWARE_FAILURE
+//
+// MessageText:
+//
+// Adapter %2 : The adapter hardware failed to initialize. Please
+// check that the adapter card is properly inserted into its slot and that the
+// network cable is connected. If its is an ISA adapter check that the interrupt
+// number, DMA channel and IO location in the adapter configuration match the
+// settings on the adapter card. (The data section below includes a driver
+// specific error code of 0x07 and the last two DWORDS give a detailed error
+// code.)
+//
+#define NDIS_ERROR_CODE_HARDWARE_FAILURE ((NDIS_ERROR_CODE)0xC000138AL)
+
+//
+// MessageId: NDIS_ERROR_CODE_ADAPTER_NOT_FOUND
+//
+// MessageText:
+//
+// Adapter %2 : The netcard driver could not allocate sufficient memory
+// for transmit and recive buffers. The number of RX and TX slots and
+// the maximum frame size may have been reduced to reduce the amount
+// of memory required.
+//
+#define NDIS_ERROR_CODE_ADAPTER_NOT_FOUND ((NDIS_ERROR_CODE)0xC000138BL)
+
+//
+// MessageId: NDIS_ERROR_CODE_INTERRUPT_CONNECT
+//
+// MessageText:
+//
+// Adapter %2 : The netcard driver was not able to connect the
+// adapter card's interrupt. Please ensure that the adapter card is properly
+// inserted into its slot. If it is an ISA adapter then check that the
+// interrupt number specified in the adapter configuration matches that
+// set on the adapter card.
+//
+#define NDIS_ERROR_CODE_INTERRUPT_CONNECT ((NDIS_ERROR_CODE)0xC000138CL)
+
+//
+// MessageId: NDIS_ERROR_CODE_DRIVER_FAILURE
+//
+// MessageText:
+//
+// Adapter %2 : One of the paramters in the registry entry for this adapter
+// is invalid. If possible a default value will have been used.
+//
+#define NDIS_ERROR_CODE_DRIVER_FAILURE ((NDIS_ERROR_CODE)0xC000138DL)
+
+//
+// MessageId: NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION
+//
+// MessageText:
+//
+// Adapter %2 : The maximum frame size setting in the registry is too
+// large. The driver has trimmed it down to the maximum allowable setting. (The
+// data section below includes a driver specific error code of 0xC, followed by
+// the actual maximum frame size used in the last DWORD. Replace the value in the
+// registry with this).
+//
+#define NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION ((NDIS_ERROR_CODE)0xC0001391L)
+
+//
+// MessageId: NDIS_ERROR_CODE_INAVLID_VALUE_FROM_ADAPTER
+//
+// MessageText:
+//
+// Adapter %2 : The adapter could not be opened onto the ring. Please ensure
+// that the network cable is connected to the adapter and that the token
+// ring is fully connected. Also ensure that all the nodes on your ring
+// are set to the same speed and that all nodes have different addresses.
+//
+#define NDIS_ERROR_CODE_INAVLID_VALUE_FROM_ADAPTER ((NDIS_ERROR_CODE)0xC0001392L)
+
+//
+// MessageId: NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER
+//
+// MessageText:
+//
+// Adapter %2 : An essential registry parameter is missing for this adapter.
+// For MCA and EISA adapters the registry must contain BusType and SlotNumber
+// parameters. For ISA adapters the registry must contain IoLocation,
+// InterruptNumber and DmaChannel parameters.
+//
+#define NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER ((NDIS_ERROR_CODE)0xC0001393L)
+
+//
+// MessageId: NDIS_ERROR_CODE_INVALID_DOWNLOAD_FILE_ERROR
+//
+// MessageText:
+//
+// Adapter %2 : Either the file MDGMPORT.BIN is not present in the device drivers
+// directory, the file is of the wrong version or the file is corrupt.
+//
+#define NDIS_ERROR_CODE_INVALID_DOWNLOAD_FILE_ERROR ((NDIS_ERROR_CODE)0xC000139CL)
+
+//
+// MessageId: NDIS_ERROR_CODE_MEMORY_CONFLICT
+//
+// MessageText:
+//
+// Adapter %2 : Either MMIO memory was not assigned or could not be mapped into
+// virtual memory. PIO transfer method is being used instead of MMIO.
+//
+#define NDIS_ERROR_CODE_MEMORY_CONFLICT ((NDIS_ERROR_CODE)0x80001399L)
+
diff --git a/private/ntos/ndis/madge/driver/mdgerrs.rc b/private/ntos/ndis/madge/driver/mdgerrs.rc
new file mode 100644
index 000000000..0885a897e
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/mdgerrs.rc
@@ -0,0 +1,2 @@
+LANGUAGE 0x9,0x1
+1 11 MSG00001.bin
diff --git a/private/ntos/ndis/madge/driver/mdgmport.bin b/private/ntos/ndis/madge/driver/mdgmport.bin
new file mode 100644
index 000000000..cfb369d88
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/mdgmport.bin
Binary files differ
diff --git a/private/ntos/ndis/madge/driver/mdgmport.rc b/private/ntos/ndis/madge/driver/mdgmport.rc
new file mode 100644
index 000000000..a445b6bbe
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/mdgmport.rc
@@ -0,0 +1,26 @@
+#include <windows.h>
+
+#include "mdgerrs.rc"
+
+#include "mdgmport.upd"
+
+#include <ntverp.h>
+
+#undef VER_COMPANYNAME_STR
+#undef VER_PRODUCTNAME_STR
+#undef VER_PRODUCTVERSION
+#undef VER_PRODUCTVERSION_STR
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+#define VER_COMPANYNAME_STR "Madge Networks Ltd"
+#define VER_PRODUCTNAME_STR "Madge Networks Smart 16/4 Ringnode Driver"
+#define VER_FILEDESCRIPTION_STR "Madge Smart 16/4 Ringnode Driver"
+#define VER_INTERNALNAME_STR "MdgNT.SYS"
+
+#define VER_LEGALCOPYRIGHT_YEARS "1994"
+#define VER_LEGALCOPYRIGHT_STR "Copyright (C) Madge Networks Ltd " VER_LEGALCOPYRIGHT_YEARS
+#define VER_PRODUCTVERSION MADGE_NT_VERSION
+#define VER_PRODUCTVERSION_STR MADGE_NT_VERSION_STR
+
+#include "common.ver"
diff --git a/private/ntos/ndis/madge/driver/mdgmport.upd b/private/ntos/ndis/madge/driver/mdgmport.upd
new file mode 100644
index 000000000..62ca51952
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/mdgmport.upd
@@ -0,0 +1,553 @@
+/***************************************************************************
+*
+* MDGMPORT.UPD
+*
+* Update log and version information for FastMAC Plus based NDIS 3.0
+* miniport driver.
+*
+* Copyright (c) Madge Networks Ltd 1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: 20/06/1994
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| Helper macro to make a DWORD.
+|
+---------------------------------------------------------------------------*/
+
+#define MAKE_DWORD(a, b, c, d) \
+ ((((DWORD) (a)) << 24) + \
+ (((DWORD) (b)) << 16) + \
+ (((DWORD) (c)) << 8 ) + \
+ (((DWORD) (d)) ))
+
+
+/*---------------------------------------------------------------------------
+|
+| Version number.
+|
+---------------------------------------------------------------------------*/
+
+//
+// Define both a string and a comma separated list of numbers. These will be
+// used by the resource compiler when version stamping the driver file.
+//
+
+#define MADGE_NT_VERSION 2,04,30,00
+#define MADGE_NT_VERSION_STR "2.04.30"
+#define MADGE_NT_VERSION_DWORD MAKE_DWORD(2, 4, 30, 0)
+
+#define _IS_ALPHA // Define if alpha version.
+
+
+/*---------------------------------------------------------------------------
+|
+| Compile time string definitions identifying driver type. Used in one of
+| the request calls (OID_GEN_VENDOR_DESCRIPTION).
+|
+|--------------------------------------------------------------------------*/
+
+#if NDIS_NT
+#define MADGE_NT_NAME "MdgMPort"
+#define MADGE_DRIVER_NAME NDIS_STRING_CONST("MdgMPort");
+#define MADGE_FMP_NAME NDIS_STRING_CONST("MDGMPORT.BIN");
+#endif
+
+#if DBG
+#define _DRIVER_PREFIX "DEBUG_MADGE_NDIS3_DRIVER:"
+#else
+#define _DRIVER_PREFIX "MADGE_NDIS3_DRIVER:"
+#endif
+
+#define DRIVER_VERSION \
+ _DRIVER_PREFIX##" "##MADGE_NT_NAME##" "##MADGE_NT_VERSION_STR
+
+
+/*---------------------------------------------------------------------------
+Ý Product instance identification string.
+---------------------------------------------------------------------------*/
+
+#ifdef _IS_ALPHA
+#define NT_PRODUCT_INSTANCE_ID "MDGMPORT v"##MADGE_NT_VERSION_STR
+#else
+#define NT_PRODUCT_INSTANCE_ID "MDGMPORT.SYS v"##MADGE_NT_VERSION_STR
+#endif
+
+
+/*---------------------------------------------------------------------------
+|
+| String for identification by MVER.
+|
+|--------------------------------------------------------------------------*/
+
+#define MVER_STRING \
+ "VeRsIoN="##MADGE_NT_NAME##" "##MADGE_NT_VERSION_STR
+
+
+/*---------------------------------------------------------------------------
+|
+| Update history.
+|
+|----------------------------------------------------------------------------
+
+ 2.04.30 10/10/1995 PBA
+
+ Source to be shipped to Microsoft. This is the LSS 4.31
+ build with support added for non-intel platforms.
+
+ 2.04.01-.29 Reserved for 4.3(1) maintanance.
+
+ 2.04 21/07/1995 PBA
+
+ Re-released for 4.3(1) with PCI-TI DMA/DIO fix.
+
+ 2.03.01-.49 Reserved for 4.3(1) maintanance.
+
+ 2.03.01 14/07/1995 PBA
+
+ Now uses FTK 2.21.11 which has software handshakes
+ for all PCI cards in pseduo DMA mode. There is a race
+ condition on a PCI bus whereby SWHLDA gets "stuck" and
+ a pending pseudo DMA starts before the host tells
+ the adapter to start it.
+
+ FTK 2.21.11 also fixes a bug in the RAP 1B MMIO code
+ where we could erroneously do an MMIO transfer if
+ we were on a shared interrupt.
+
+ FTK 2.21.11 also fixes a PCI-IT DMA problem. We were
+ not checking if pseudo DMA was enabled in the
+ interrupt handler and because the interrupt handler
+ is called for real DMA should SWHRQ be set we would
+ do some erroneous pseudo DMA processing.
+
+ 2.03 30/06/1995 PBA
+
+ Hardware thread released for LSS 4.3(1) with support
+ for PCI-TI adapters and untested support for PCI-Abyss
+ adapters. Uses FTK 2.21.07 and FMPLUS 1.36.
+
+ 2.02 Used for non-intel thread drivied from LSS 4.30.
+
+ 2.01.03 12/05/1995 PBA
+
+ Now uses FTK 2.21.02 that can cope with the stray
+ initialisation interrupt generated by some
+ socket controllers.
+
+ 2.01.02 07/04/1995 PBA
+
+ Now uses FTK 2.21.01 and FastMAC Plus 1.34.10 which
+ have an extended handshake on transmit MMIO to
+ avoid a SAM upload/DIO race condition.
+
+ 2.01.01 05/04/1995 PBA
+
+ Power PC build. Only tested on ISA and PCI adapters.
+ Only works in PIO mode.
+
+
+ 2.02.01 - .49 Reserved for 4.3(0 and/or PnP) maintenance.
+
+ 2.01 02/02/1995 PBA
+
+ Released for 4.3(0 and/or PnP). Any previous 4.3(x)
+ threads are now dead.
+
+ 2.00.61 02/02/1995 PBA
+
+ Now uses FastMAC Plus 1.28. Given to DaveF for Chicago
+ testing and possible shipping to Microsoft for M8
+ and/or NT 3.51.
+
+ 2.00.60 01/02/1995 PBA
+
+ Windows95 build 310 always returns the native bus type
+ of the PC rather than the type of the bus the adapter
+ is in. To get around the problem we now read the bus
+ type from the wrapper and then override the value if
+ we find an adapter type parameter in the registry.
+
+ 2.00.59 31/01/1995 PBA
+
+ The Windows95 wrapper now supports the
+ NdisReadPciSlotInformation so we can now have a binary
+ compatible build. The register parameter "PlatformType"
+ is used to determine the OS type the driver is running on.
+
+ Also allowed "IoBaseAddress" to be used instead of
+ "IoLocation" for forwards compatibility with NT 3.51.
+
+ 2.00.58 24/01/1995 PBA
+
+ Uses FTK 2.20.26 that fixes a problem where the software
+ handshake was not being enabled properly for PCMCIA
+ adapters.
+
+ 2.00.57 12/01/1995 PBA
+
+ Given to central support to fix PRF 2841.
+ Uses FastMAC Plus 1.20.
+
+ 2.00.56 12/01/1995 PBA
+
+ Now uses FTK 2.20.25 that has a fix to avoid
+ driver_remove_adapter deallocating the FastMAC Plus
+ dma test buffer when it has not been allocated.
+
+ 2.00.55 12/01/1995 PBA
+
+ Now deregister shutdown handler in MadgeCleanupAdapter
+ to avoid the odd blue screen when MadgeShutdown was
+ called after we had freed the adapter structure.
+
+ 2.00.54 12/01/1995 PBA
+
+ Now uses FTK 2.20.24 that allows the driver to run
+ on none Madge adapters if #define MADGIC_BIT 0x8000
+ is present in user.h.
+
+ 2.00.53 11/01/1995 PBA
+
+ Given to central support. Uses FastMAC Plus 1.25.
+
+ 2.00.52 11/01/1995 PBA
+
+ Given to central support to fix PRF 2841.
+ i.e. Insufficient shared memory available when the
+ driver is installed while NT is being installed to
+ start the adapter during the NT installation. The solution
+ is to add a shared memory aribitration routine which
+ attempts to reduce the number of RX/TX slots and the
+ maxiumum frame size until there is enough shared memory
+ left. Uses FastMAC Plus 1.20.
+
+ 2.00.51 06/01/1995 PBA
+
+ Shipped source to FrancisT so he could build it on
+ a MIPs. Uses FastMAC Plus 1.25.
+
+ 2.00.50 03/01/1995 PBA
+
+ Changed so that TX/RX buffers on use shared memory in DMA
+ mode. PIO and MMIO use ordinary memory.
+
+ Version numbers 1.50.01 to 1.99.99 are used for a FastMAC version.
+
+ 1.07.52 13/12/1994 PBA
+
+ No longer sets monitor contender in the open options.
+
+ 1.07.51 09/12/1994 PBA
+
+ Changed so that if we are compiling for a none Intel
+ platform we allocate map registers properly. For Intel
+ platforms we still use the cludge where we allocate
+ the adapter block ourselves. This should solve the
+ DEC AXP 2100 problem.
+
+ 1.07.50 09/12/1994 PBA
+
+ Revised to use the new FTK (2.20.xx).
+
+ 1.07.01 - .49 Reserved for release 4.3(1) maintenance.
+
+ 1.07 Reserved for release 4.3(1).
+
+ Screwed up the versions numbers. Live development jumps to 1.07.50
+
+ 1.06.52 29/11/1994 PBA
+
+ Gave source to FrancisF to try and track down the
+ DEC 2100 shared memory allocation problem.
+
+ 1.06.51 24/11/1994 PBA
+
+ Moved the clearing of the private SRB in progress flag
+ out of the DPR and into the ISR as the DPR doesn't
+ get called during the initialisation code under Chicago.
+ Doing it this way avoids the nasty delay loop in the
+ initialisation code when setting the product instance id.
+
+ ---- Special ---------------------------------------------------------------
+
+ 1.06.81 - Microsoft thread based on 1.06.80 splits here.
+
+ 1.06.80 11/01/1994 PBA
+
+ Same as 1.06.50 but accepts IoBaseAddress for the I/O
+ location as well as IoLocation. Uses FastMAC Plus 1.20.
+ Shipped to Jameel Hyder at Microsoft for NT 3.51 beta.
+
+ ---- Special ---------------------------------------------------------------
+
+ 1.06.70 13/12/1994 PBA
+
+ This is an alpha for FrancisT derived directly from
+ 1.06. The only differences are that it does not open in
+ monitor contention mode, it uses map registers rather
+ than the "horrible hack" and it is an NT only build.
+
+ ---- Special ---------------------------------------------------------------
+
+ 1.06.60 05/11/1994 PBA
+
+ Same as 1.06.50 but with FastMAC Plus 1.24.
+
+ ---- Special ---------------------------------------------------------------
+
+ 1.06.50 23/11/1994 PBA
+
+ Shipped to Microsoft for possible inclusion in the next
+ NT and Chicago (M8) releases. Uses FastMAC Plus v1.20.
+ This is based on 1.05.04.
+
+ ----------------------------------------------------------------------------
+
+ 1.06.01 - .49 Reserved for release 4.3(0) maintenance.
+
+ 1.06 Reserved for release 4.3(0).
+
+ Source used for 4.3(1) split from the main thread here.
+
+ 1.05.04 22/11/1994 PBA
+
+ Changed the initialisation code to allow as few as
+ 2 RX and 2 TX slots. Hopefully this will keep
+ Microsoft quiet about shared memory allocation.
+
+ 1.05.03 22/11/1994 PBA
+
+ Added a shutdown handler. Note there is no documentation
+ for this, just an example in the IBMTOK2i source.
+
+ 1.05.02 21/11/1994 PBA
+
+ Now re-tries bring-up up to 10 times.
+
+ 1.05.01 18/11/1994 PBA
+
+ Added code to set a product instance id in FastMAC plus.
+
+ 1.05 18/11/1994 PBA
+
+ Windows95 build for PnP field trials. Uses FastMAC Plus
+ v1.20.
+
+ 1.04.54 17/11/1994 PBA
+
+ Modified the PnP HWI to set the channel ready bit
+ if the active float channel ready bit is set in the
+ PnP hardware features byte.
+
+ 1.04.53 17/11/1994 PBA
+
+ Added support for PCI under Chicago. This has to be
+ done with a compile time switch because the
+ NdisReadPciSlotInformation functions is not in the
+ Chicago (M7) Ndis wrapper. If this function call
+ is present then Chicago refuses to load the driver.
+ We get the PCI configuration in Chicago by just reading
+ from the registry.
+
+ 1.04.52 16/11/1994 PBA
+
+ Changed PnP HWI so that it knows about C30s.
+
+ 1.04.51 07/11/1994 PBA
+
+ Added PnP support. Chicago only at the moment.
+
+ 1.04.50 04/11/1994 PBA
+
+ Added PCMCIA support. Chicago only at the moment.
+
+ Version numbers 1.04.01 to 1.04.49 are reserved for maintenance fixes
+ to version 1.04. Live development continues at 1.04.50.
+
+ 1.04 08/11/1994 PBA
+
+ Cludged version use for PCI Releases. Uses FastMAC Plus v1.21
+ and hwi_pci.c from v1.03 archive. This means that the
+ driver does MMIO on RX only (pseudo DMA on transmit).
+
+ 1.03.07 07/11/1994 PBA
+
+ Alpha version shipped to Gordon Cairns.
+ Uses FastMAC Plus alpha v1.23.01
+
+ 1.03.06 03/11/1994 PBA
+
+ Now supports transmit and receive PCI MMIO.
+
+ 1.03.05 02/11/1994 PBA
+
+ Now sets the FTK error code if RX or TX buffers cannot
+ be allocaed.
+
+ 1.03.04 01/11/1994 PBA
+
+ Arranged for the PCI cards to be defaulted to pseudo DMA
+ if MMIO memory is not allocated or cannot be mapped into
+ virtual memory.
+
+ 1.03.03 01/11/1994 PBA
+
+ Tidied up the error messages written to the event long
+ as the new DDK has a better range of error codes.
+
+ 1.03.02 11/10/1994 PBA
+
+ Added a RingSpeed parameter to set the ringspeed(!).
+ RingSpeed == 0 means don't care about the ring speed;
+ use the default or use Force4/Force16. 1 means 4MBits.
+ 2 means 16 MBits. RingSpeed overrides Force4/Force16.
+
+ 1.03.01 7/10/1994 PD
+
+ Added traffic monitoring code enabled by uncommenting
+ line defining OID_MADGE_MONITOR in NDISMOD.H.
+
+
+ 1.03 28/09/1994 PBA
+
+ Released for PCI release 4.2(3).
+
+ 1.02.53 28/09/1994 PBA
+
+ Now uses FastMAC Plus 1.21.
+
+ 1.02.52 28/09/1994 PBA
+
+ Added PCI support. There is a new registry parameter
+ called "NoMmio". By default MMIO is used as the PCI
+ transfer method. If NoMmio is 1 then pseudo DMA is used.
+ PCI adapters are identified by the "SlotNumber" parameter
+ in the registry. This is actually set to the logical
+ device number of the PCI adapter. If SlotNumber is set
+ to 0xffff then the PCI bus is searched for the first
+ unused Madge PCI adapter.
+
+ 1.02.51 21/09/1994 PBA
+
+ Added a Multiprocessor parameter. If this parameter is
+ non-zero and the DMA channel is zero then multiprocessor
+ safe PIO is used. The code which enabled multiprocessor
+ safe PIO by when the DMA channel was set to 0x8000 has
+ been left in for backwards compatibility.
+
+ 1.02.50 12/09/1994 PBA
+
+ The I/O location of the SIF registers is now recorded in
+ the adapter structure at initialisation time by the
+ hwi_xxx.c routines. Previously the SIF registers were
+ assumed to be at fixed offsets from a SIF base address.
+ This change is needed to support PCI adapters.
+
+ Due to the problems with FastMAC Plus a re-release with a new FastMAC
+ plus image will be needed for LSS 4.30. This release will be based on
+ 1.02.xx which is the same as the earlier LSS 4.30 with some minor bug
+ fixes. Live development continues with 1.02.50.
+
+ 1.02.04 12/09/1994 PBA
+
+ Now sets the "Madgic" bits in the FMP dowload header so
+ that we will run on none Madge adapters.
+
+ 1.02.03 12/09/1994 PBA
+
+ Fixed a bug where we didn't check if the tx buffer memory
+ allocation had succeeded.
+
+ 1.02.02 31/08/1994 PBA
+
+ Source shipped to Microsoft.
+
+ 1.02.01 31/08/1994 PBA
+
+ Noew only checks the major and minor version numbers
+ of the download.
+
+ 1.02 24/08/1994 PBA
+
+ Re-released for 4.3.
+
+ 1.01.03 16/08/1994 PBA
+
+ Added comments about ring speed and duplicate addresses
+ to the cannot open error message.
+
+ 1.01.02 11/08/1994 PBA
+
+ At the recommendation of Kevin Martin (Microsoft) the
+ NDIS_MAC_OPTIONS_NO_LOOPBACK bit is no-longer set and we
+ just allow the hardware to do loopback.
+
+ 1.01.01 10/08/1994 PBA
+
+ Added a flag to the adapter structure called UseMPSafePIO.
+ If this flag is set then all of the DIO on the transmit
+ and receive paths is encapsulated in functions invoked
+ by NdisMSynchronizeWithInterrupt to protect the DIO
+ from PIO interrupts happening on another processor in
+ a multiprocessor machine. This flag is set if the DMA
+ channel is specified as 0x8000 - see MadgeReadRegstry().
+
+ 1.01 22/07/1994 PBA
+
+ Released for 4.30.
+
+ 1.00.08 20/07/1994 PBA
+
+ Added support for a Force16 option for ATULA adapters
+ and Force16 and Force4 options for AT/P and ISA/C/P
+ adapters.
+
+ 1.00.07 19/07/1994 PBA
+
+ Added an option to allow the adapter to be forced open
+ (it was always done before, which is wrong).
+
+ 1.00.06 04/07/1994 PBA
+
+ Found a race condition with ATULA cards in PIO mode. We
+ MUST claim interrupts (even if they are just for PIO)
+ until the "DMA" initialisation test is over or sometimes
+ WFWG (and possibly NT) permanently masks out our interrupts.
+
+ 1.00.05 01/07/1994 PBA
+
+ Alpha version for Gordon Cairns to test.
+
+ 1.00.04 29/06/1994 PBA
+
+ Used conditional assembly in sys_mem.c so that the
+ I/O on Intel platforms does not involve any mapping
+ (since the mapping always results in the port address
+ anyway).
+
+ 1.00.03 28/06/1994 PBA
+
+ Now uses FTK common to all of the NDIS3 drivers.
+
+ 1.00.02 28/06/1994 PBA
+
+ Fixed a bug in the ChangeFilter function. We were carefully
+ working out the new open options and passing the old options
+ in the SRB.
+
+ 1.00.01 21/06/1994 PBA
+
+ First instance for MdgMPort. Derived from MdgNT v1.01.12
+
+---------------------------------------------------------------------------*/
+
+
+/******** End of MDGMPORT.UPD **********************************************/
+ \ No newline at end of file
diff --git a/private/ntos/ndis/madge/driver/msg00001.bin b/private/ntos/ndis/madge/driver/msg00001.bin
new file mode 100644
index 000000000..7e2f93fb0
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/msg00001.bin
Binary files differ
diff --git a/private/ntos/ndis/madge/driver/request.c b/private/ntos/ndis/madge/driver/request.c
new file mode 100644
index 000000000..21172e71b
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/request.c
@@ -0,0 +1,1158 @@
+/***************************************************************************
+*
+* REQUEST.C
+*
+* FastMAC Plus based NDIS3 miniport driver routines for handling SRB
+* requests and ODI_ requsts.
+*
+* Copyright (c) Madge Networks Ltd 1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_extr.h"
+
+#include "mdgmport.upd"
+#include "ndismod.h"
+
+
+/*---------------------------------------------------------------------------
+|
+| Global OIDs that we will support queries on.
+|
+---------------------------------------------------------------------------*/
+
+NDIS_OID MadgeGlobalSupportedOids[] =
+{
+ //
+ // General, Operational, Mandatory.
+ //
+
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_MAC_OPTIONS,
+
+ //
+ // General, Statistical, Mandatory.
+ //
+
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+
+ //
+ // Token Ring, Operational, Mandatory.
+ //
+
+ OID_802_5_PERMANENT_ADDRESS,
+ OID_802_5_CURRENT_ADDRESS,
+ OID_802_5_CURRENT_FUNCTIONAL,
+ OID_802_5_CURRENT_GROUP,
+ OID_802_5_LAST_OPEN_STATUS,
+ OID_802_5_CURRENT_RING_STATUS,
+ OID_802_5_CURRENT_RING_STATE,
+
+ //
+ // Token Ring, Statistical, Mandatory.
+ //
+
+ OID_802_5_LINE_ERRORS,
+ OID_802_5_LOST_FRAMES,
+
+ //
+ // Token Ring Statistical, Optional.
+ //
+
+ OID_802_5_BURST_ERRORS,
+ OID_802_5_AC_ERRORS,
+ OID_802_5_FRAME_COPIED_ERRORS,
+ OID_802_5_TOKEN_ERRORS
+
+ //
+ // There are three more Token Ring error stat's but TI MAC code does not
+ // support them, so we go without! (ABORT_DELIMITERS, FREQUENCY_ERRORS,
+ // and INTERNAL_ERRORS).
+ //
+};
+
+
+/**************************************************************************
+*
+* Function - MadgeCompletePendingRequest
+*
+* Parameters - ndisAdap -> Pointer NDIS3 level adapter structure.
+*
+* Purpose - Complete a pending request on the adapter specified.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+VOID
+MadgeCompletePendingRequest(PMADGE_ADAPTER ndisAdap)
+{
+ BOOLEAN success;
+ ADAPTER * ftkAdapter;
+ ULONG * infoBuffer;
+
+// MadgePrint1("MadgeCompletePendingRequest started\n");
+
+ success = ndisAdap->SrbRequestStatus;
+
+ switch(ndisAdap->RequestType)
+ {
+ case NdisRequestQueryInformation:
+
+ infoBuffer = (ULONG *) ndisAdap->InformationBuffer;
+
+ if (success)
+ {
+ ftkAdapter = adapter_record[ndisAdap->FtkAdapterHandle];
+
+ ndisAdap->ReceiveCongestionCount +=
+ ftkAdapter->status_info->error_log.congestion_errors;
+ ndisAdap->LineErrors +=
+ ftkAdapter->status_info->error_log.line_errors;
+ ndisAdap->BurstErrors +=
+ ftkAdapter->status_info->error_log.burst_errors;
+ ndisAdap->AcErrors +=
+ ftkAdapter->status_info->error_log.ari_fci_errors;
+ ndisAdap->TokenErrors +=
+ ftkAdapter->status_info->error_log.token_errors;
+
+ switch(ndisAdap->RequestOid)
+ {
+ case OID_GEN_RCV_NO_BUFFER:
+
+ *infoBuffer = ndisAdap->ReceiveCongestionCount;
+ break;
+
+ case OID_802_5_LINE_ERRORS:
+
+ *infoBuffer = ndisAdap->LineErrors;
+ break;
+
+ case OID_802_5_BURST_ERRORS:
+
+ *infoBuffer = ndisAdap->BurstErrors;
+ break;
+
+ case OID_802_5_AC_ERRORS:
+
+ *infoBuffer = ndisAdap->AcErrors;
+ break;
+
+ case OID_802_5_TOKEN_ERRORS:
+
+ *infoBuffer = ndisAdap->TokenErrors;
+ break;
+ }
+
+ ndisAdap->JustReadErrorLog = ndisAdap->RequestOid;
+ }
+
+ //
+ // And complete the request.
+ //
+
+ NdisMQueryInformationComplete(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (success) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE
+ );
+
+ break;
+
+ case NdisRequestSetInformation:
+
+ //
+ // All we need to do is complete the request.
+ //
+
+ NdisMSetInformationComplete(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (success) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE
+ );
+
+ break;
+ }
+
+// MadgePrint1("MadgeCompletePendingRequest finished\n");
+}
+
+
+/***************************************************************************
+*
+* Function - MadgeQueryInformation
+*
+* Parameters - adapterContext -> Pointer NDIS3 level adapter structure.
+* oid -> The OID.
+* infoBuffer -> Pointer to the information buffer.
+* infoLength -> Length of the information buffer.
+* bytesWritten -> Pointer to a holder for the number of
+* bytes we've written.
+* bytesNeeded -> Pointer to a holder for the number of
+* bytes we need.
+*
+* Purpose - Set adapter information.
+*
+* Returns - An NDIS3 status code.
+*
+***************************************************************************/
+
+NDIS_STATUS
+MadgeQueryInformation(
+ NDIS_HANDLE adapterContext,
+ NDIS_OID oid,
+ PVOID infoBuffer,
+ ULONG infoLength,
+ PULONG bytesWritten,
+ PULONG bytesNeeded
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ UINT supportedOids;
+ UINT i;
+ ULONG genericULong;
+ USHORT genericUShort;
+ UCHAR genericArray[6];
+ PVOID sourceBuffer;
+ ULONG sourceLength;
+ UCHAR * vendorID;
+
+
+ static UCHAR VendorDescription[] = DRIVER_VERSION;
+
+// MadgePrint2("MadgeQueryInformation Oid = %08x\n", (UINT) oid);
+
+ //
+ // Do some pre-calculation.
+ //
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
+ sourceBuffer = (PVOID) &genericULong;
+ sourceLength = (ULONG) sizeof(ULONG);
+ vendorID = (UCHAR *) &genericULong;
+ supportedOids = sizeof(MadgeGlobalSupportedOids) / sizeof(NDIS_OID);
+
+ //
+ // Check that we recognise the OID.
+ //
+
+#ifdef OID_MADGE_MONITOR
+
+ if (oid == OID_MADGE_MONITOR)
+ {
+ if (sizeof(MADGE_MONITOR) > infoLength)
+ {
+ *bytesNeeded = sizeof(MADGE_MONITOR);
+ return NDIS_STATUS_BUFFER_TOO_SHORT;
+ }
+
+ MADGE_MOVE_MEMORY(
+ infoBuffer,
+ &(ndisAdap->MonitorInfo),
+ sizeof(MADGE_MONITOR)
+ );
+
+ *bytesWritten = sizeof(MADGE_MONITOR);
+
+ // Clear out the Monitor Structure
+ for (i = 0; i < sizeof(MADGE_MONITOR); i++)
+ {
+ ((UCHAR *) &(ndisAdap->MonitorInfo))[i] = (UCHAR) 0;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+ }
+
+#endif
+
+ for (i = 0; i < supportedOids; i++)
+ {
+ if (oid == MadgeGlobalSupportedOids[i])
+ {
+ break;
+ }
+ }
+
+ if (i == supportedOids)
+ {
+ *bytesWritten = 0;
+ MadgePrint1("OID not supported\n");
+ return NDIS_STATUS_INVALID_OID;
+ }
+
+ //
+ // Now decode the OID based on the component bytes - this should make
+ // the switch statement slightly quicker than a simple linear list.
+ //
+ // The OIDs are classed by category (General or Media Specific) and type
+ // (Operational or Statistical), so we'll deal with them thus :
+ // General Operational
+ // General Statistical
+ // Media Specific Operational
+ // Media Specific Statistical
+ //
+
+ switch (oid & OID_TYPE_MASK)
+ {
+ /*-----------------------------------------------------------------*/
+
+ case OID_TYPE_GENERAL_OPERATIONAL:
+
+ switch (oid)
+ {
+ case OID_GEN_SUPPORTED_LIST:
+
+ sourceBuffer = MadgeGlobalSupportedOids;
+ sourceLength = sizeof(MadgeGlobalSupportedOids);
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+
+ genericULong = ndisAdap->HardwareStatus;
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+
+ genericULong = NdisMedium802_5;
+ break;
+
+ case OID_GEN_MEDIA_IN_USE:
+
+ genericULong = NdisMedium802_5;
+ break;
+
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+
+ //
+ // The maximum lookahead size is the size of the whole
+ // frame, less the MAC header. It is NOT the maximum
+ // frame size according to the ring speed.
+ //
+
+ genericULong = ndisAdap->MaxFrameSize - FRAME_HEADER_SIZE;
+
+ //
+ // WARNING: What about Source Routing in the header?
+ //
+
+// MadgePrint2("OID_GEN_MAXIMUM_LOOKAHEAD = %ld\n",
+// genericULong);
+
+ break;
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+
+ //
+ // Note that the MAXIMUM_FRAME_SIZE is the largest frame
+ // supported, not including any MAC header, while the
+ // MAXIMUM_TOTAL_SIZE does include the MAC header.
+ //
+
+ genericULong = ndisAdap->MaxFrameSize;
+
+ if (oid == OID_GEN_MAXIMUM_FRAME_SIZE)
+ {
+ genericULong -= FRAME_HEADER_SIZE;
+ }
+
+// MadgePrint2("OID_GEN_MAXIMUM_FRAME_SIZE = %ld\n",
+// genericULong);
+
+ break;
+
+ case OID_GEN_LINK_SPEED:
+
+ //
+ // Is this right? Shouldn't it be 16000000 and 4000000?
+ //
+
+ genericULong =
+ (driver_ring_speed(ndisAdap->FtkAdapterHandle) == 16)
+ ? 160000
+ : 40000;
+ break;
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+
+ genericULong =
+ ndisAdap->MaxFrameSize * ndisAdap->FastmacTxSlots;
+ break;
+
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+
+ genericULong =
+ ndisAdap->MaxFrameSize * ndisAdap->FastmacRxSlots;
+ break;
+
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+
+ genericULong = ndisAdap->MaxFrameSize;
+ break;
+
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+
+ genericULong = ndisAdap->MaxFrameSize;
+ break;
+
+ case OID_GEN_VENDOR_ID:
+
+ MADGE_MOVE_MEMORY(
+ vendorID,
+ &ndisAdap->PermanentNodeAddress,
+ 3
+ );
+ vendorID[3] = 0x00;
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+
+ sourceBuffer = VendorDescription;
+ sourceLength = sizeof(VendorDescription);
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ genericULong = (ULONG) ndisAdap->CurrentPacketFilter;
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ genericULong = (ULONG) ndisAdap->CurrentLookahead;
+
+// MadgePrint2("OID_GEN_CURRENT_LOOKAHEAD = %ld\n",
+// genericULong);
+
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+
+ genericUShort = (MADGE_NDIS_MAJOR_VERSION << 8) +
+ MADGE_NDIS_MINOR_VERSION;
+ sourceBuffer = &genericUShort;
+ sourceLength = sizeof(USHORT);
+ break;
+
+ case OID_GEN_MAC_OPTIONS:
+
+ genericULong = (ULONG)
+ (NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED);
+ break;
+
+ default:
+
+ MadgePrint2("OID %x not recognised\n", oid);
+ return NDIS_STATUS_INVALID_OID;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+
+ case OID_TYPE_GENERAL_STATISTICS:
+
+ //
+ // Might need these later.
+ //
+
+ *bytesWritten = sourceLength;
+ ndisAdap->RequestType = NdisRequestQueryInformation;
+ ndisAdap->RequestOid = oid;
+ ndisAdap->InformationBuffer = infoBuffer;
+
+ switch (oid)
+ {
+ case OID_GEN_XMIT_OK:
+
+ genericULong = (ULONG) ndisAdap->FramesTransmitted;
+ break;
+
+ case OID_GEN_RCV_OK:
+
+ genericULong = (ULONG) ndisAdap->FramesReceived;
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+
+ genericULong = (ULONG) ndisAdap->FrameTransmitErrors;
+ break;
+
+ case OID_GEN_RCV_ERROR:
+
+ genericULong = (ULONG) ndisAdap->FrameReceiveErrors;
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+
+ //
+ // We need to issue a READ_ERROR_LOG SRB to recover an
+ // up to date value for this counter.
+ //
+
+ if (ndisAdap->JustReadErrorLog != 0 &&
+ ndisAdap->JustReadErrorLog != oid)
+ {
+ genericULong = (ULONG)
+ ndisAdap->ReceiveCongestionCount;
+ }
+ else if (infoLength >= sourceLength)
+ {
+ driver_get_status(ndisAdap->FtkAdapterHandle);
+ return NDIS_STATUS_PENDING;
+ }
+ break;
+
+ default:
+
+ MadgePrint2("OID %x not recognised\n", oid);
+ return NDIS_STATUS_INVALID_OID;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+
+ case OID_TYPE_802_5_OPERATIONAL:
+
+ switch (oid)
+ {
+ case OID_802_5_PERMANENT_ADDRESS:
+
+ sourceBuffer = &genericArray;
+ sourceLength = sizeof(ndisAdap->PermanentNodeAddress);
+
+ MADGE_MOVE_MEMORY(
+ sourceBuffer,
+ &ndisAdap->PermanentNodeAddress,
+ sizeof(ndisAdap->PermanentNodeAddress)
+ );
+ break;
+
+ case OID_802_5_CURRENT_ADDRESS:
+
+ sourceBuffer = &genericArray;
+ sourceLength =
+ sizeof(ndisAdap->OpeningNodeAddress);
+
+ MADGE_MOVE_MEMORY(
+ sourceBuffer,
+ &ndisAdap->OpeningNodeAddress,
+ sizeof(ndisAdap->OpeningNodeAddress)
+ );
+ break;
+
+ case OID_802_5_CURRENT_FUNCTIONAL:
+
+ genericULong =
+ ndisAdap->FunctionalAddress & 0xffffffff;
+ break;
+
+ case OID_802_5_CURRENT_GROUP:
+
+ genericULong =
+ ndisAdap->GroupAddress & 0xffffffff;
+ break;
+
+ case OID_802_5_LAST_OPEN_STATUS:
+
+ genericULong = ndisAdap->LastOpenStatus;
+ break;
+
+ case OID_802_5_CURRENT_RING_STATUS:
+
+ genericULong = ndisAdap->CurrentRingStatus;
+ break;
+
+ case OID_802_5_CURRENT_RING_STATE:
+
+ genericULong = NdisRingStateOpened;
+ break;
+
+ default:
+
+ MadgePrint2("OID %x not recognised\n", oid);
+ return NDIS_STATUS_INVALID_OID;
+ }
+ break;
+
+ /*-----------------------------------------------------------------*/
+
+ case OID_TYPE_802_5_STATISTICS:
+
+ //
+ // We do a bit of pre-processing here in case we have to queue
+ // an SRB request. In this instance we want everything ready bar
+ // the actual data.
+ //
+
+ if (sourceLength > infoLength)
+ {
+ break;
+ }
+
+ *bytesWritten = sourceLength;
+ ndisAdap->RequestType = NdisRequestQueryInformation;
+ ndisAdap->RequestOid = oid;
+ ndisAdap->InformationBuffer = infoBuffer;
+
+ //
+ // Now get on with working out the data.
+ //
+
+ switch (oid)
+ {
+ case OID_802_5_LINE_ERRORS:
+
+ //
+ // We need to issue a READ_ERROR_LOG SRB to recover an
+ // up to date value for this counter.
+ //
+
+ if (ndisAdap->JustReadErrorLog != 0 &&
+ ndisAdap->JustReadErrorLog != oid)
+ {
+ genericULong = (ULONG) ndisAdap->LineErrors;
+ }
+ else
+ {
+ driver_get_status(ndisAdap->FtkAdapterHandle);
+ return NDIS_STATUS_PENDING;
+ }
+ break;
+
+ case OID_802_5_LOST_FRAMES:
+
+ //
+ // This counter is managed by the transmit process using
+ // the transmit status returned by FastmacPlus.
+ //
+
+ genericULong = (ULONG) ndisAdap->LostFrames;
+ break;
+
+ case OID_802_5_BURST_ERRORS:
+
+ if (ndisAdap->JustReadErrorLog != 0 &&
+ ndisAdap->JustReadErrorLog != oid)
+ {
+ genericULong= (ULONG) ndisAdap->BurstErrors;
+ }
+ else
+ {
+ driver_get_status(ndisAdap->FtkAdapterHandle);
+ return NDIS_STATUS_PENDING;
+ }
+ break;
+
+ case OID_802_5_AC_ERRORS:
+
+ if (ndisAdap->JustReadErrorLog != 0 &&
+ ndisAdap->JustReadErrorLog != oid)
+ {
+ genericULong= (ULONG) ndisAdap->AcErrors;
+ }
+ else
+ {
+ driver_get_status(ndisAdap->FtkAdapterHandle);
+ return NDIS_STATUS_PENDING;
+ }
+ break;
+
+ case OID_802_5_FRAME_COPIED_ERRORS:
+
+ //
+ // This counter is managed by the receive process using
+ // the receive status returned by FastmacPlus.
+ //
+
+ genericULong = (ULONG) ndisAdap->FrameCopiedErrors;
+ break;
+
+ case OID_802_5_TOKEN_ERRORS:
+
+ if (ndisAdap->JustReadErrorLog != 0 &&
+ ndisAdap->JustReadErrorLog != oid)
+ {
+ genericULong = (ULONG) ndisAdap->TokenErrors;
+ }
+ else
+ {
+ driver_get_status(ndisAdap->FtkAdapterHandle);
+ return NDIS_STATUS_PENDING;
+ }
+ break;
+
+ default:
+
+ MadgePrint2("OID %x not recognised\n", oid);
+ return NDIS_STATUS_INVALID_OID;
+ }
+ break;
+ }
+
+ //
+ // Check memory allocation provided by caller - report required amount
+ // if we haven't got enough.
+ //
+
+ if (sourceLength > infoLength)
+ {
+ *bytesNeeded = sourceLength;
+ return NDIS_STATUS_BUFFER_TOO_SHORT;
+ }
+
+ MADGE_MOVE_MEMORY(
+ infoBuffer,
+ sourceBuffer,
+ sourceLength
+ );
+
+ *bytesWritten = sourceLength;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeChangeGroupAddress
+|
+| Parameters - ndisAdap -> Pointer to our NDIS level adapter structure.
+| newAddress -> The new group address.
+|
+| Purpose - Queue an SRB to change the group address.
+|
+| Returns - Nothing.
+|
+---------------------------------------------------------------------------*/
+
+STATIC VOID
+MadgeChangeGroupAddress(
+ PMADGE_ADAPTER ndisAdap,
+ TR_FUNCTIONAL_ADDRESS newAddress
+ )
+{
+ MULTI_ADDRESS multiAddress;
+
+// MadgePrint1("MadgeChangeGroupAddress started\n");
+
+ ndisAdap->GroupAddress = newAddress;
+ multiAddress.all = (DWORD) newAddress;
+
+ ndisAdap->RequestType = NdisRequestSetInformation;
+
+ //
+ // And call the FTK to change the address.
+ //
+
+ driver_set_group_address(ndisAdap->FtkAdapterHandle, &multiAddress);
+
+// MadgePrint1("MadgeChangeGroupAddress finished\n");
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeChangeFunctionalAddress
+|
+| Parameters - ndisAdap -> Pointer to our NDIS level adapter structure.
+| newAddress -> The new functional address.
+|
+| Purpose - Queue an SRB to change the functional address.
+|
+| Returns - Nothing.
+|
+---------------------------------------------------------------------------*/
+
+STATIC VOID
+MadgeChangeFunctionalAddress(
+ PMADGE_ADAPTER ndisAdap,
+ TR_FUNCTIONAL_ADDRESS newAddress
+ )
+{
+ MULTI_ADDRESS multiAddress;
+
+// MadgePrint2("MadgeChangeFunctionalAddress started %08x\n",
+// (UINT) newAddress);
+
+ ndisAdap->FunctionalAddress = newAddress;
+ multiAddress.all = (DWORD) newAddress;
+
+ ndisAdap->RequestType = NdisRequestSetInformation;
+
+ //
+ // And call the FTK to change the address.
+ //
+
+ driver_set_functional_address(ndisAdap->FtkAdapterHandle, &multiAddress);
+
+// MadgePrint1("MadgeChangeFunctionalAddress finished\n");
+}
+
+
+/*---------------------------------------------------------------------------
+|
+| Function - MadgeChangeFilter
+|
+| Parameters - ndisAdap -> Pointer to our NDIS level adapter structure.
+| newFilter -> The new packet filter.
+|
+| Purpose - Change the packet filter.
+|
+| Returns - NDIS_STATUS_PENDING if an SRB is required,
+| NDIS_STATUS_NOT_SUPPORTED if we don't support the filter
+| types, otherwise NDIS_STATUS_SUCCESS.
+|
+---------------------------------------------------------------------------*/
+
+NDIS_STATUS
+MadgeChangeFilter(
+ PMADGE_ADAPTER ndisAdap,
+ UINT newFilter
+ )
+{
+ UINT index;
+ UINT modifyOpenOptions;
+ UINT oldFilter;
+
+ //
+ // Lookup table for the various ways we might want to modify the open
+ // options of the adapter.
+ //
+
+#define MOO_NO_CHANGE (0xffff)
+#define MOO_MASK ((WORD) (~(OPEN_OPT_COPY_ALL_MACS | OPEN_OPT_COPY_ALL_LLCS)))
+
+WORD MooLookupTable[] = {
+ MOO_NO_CHANGE,
+ OPEN_OPT_COPY_ALL_MACS | OPEN_OPT_COPY_ALL_LLCS,
+ OPEN_OPT_COPY_ALL_MACS,
+ OPEN_OPT_COPY_ALL_MACS | OPEN_OPT_COPY_ALL_LLCS,
+ 0,
+ MOO_NO_CHANGE,
+ OPEN_OPT_COPY_ALL_MACS,
+ MOO_NO_CHANGE,
+ 0,
+ OPEN_OPT_COPY_ALL_MACS | OPEN_OPT_COPY_ALL_LLCS,
+ MOO_NO_CHANGE,
+ OPEN_OPT_COPY_ALL_MACS | OPEN_OPT_COPY_ALL_LLCS,
+ 0,
+ MOO_NO_CHANGE,
+ OPEN_OPT_COPY_ALL_MACS,
+ MOO_NO_CHANGE
+ };
+
+// MadgePrint2("MadgeChangeFilter started filter = %04x\n",
+// (UINT) newFilter);
+
+ //
+ // Do some pre-calculation.
+ //
+
+ modifyOpenOptions = 0;
+ index = 0;
+ oldFilter = ndisAdap->CurrentPacketFilter;
+
+// MadgePrint2("Old filter = %04x\n", oldFilter);
+
+ //
+ // By default, the card will receive directed frames, broadcast frames,
+ // and matching functional and group address frames. Thus the following
+ // filter types are handled automatically, whether we want them or not:
+ // NDIS_PACKET_TYPE_DIRECTED NDIS_PACKET_TYPE_BROADCAST
+ // NDIS_PACKET_TYPE_FUNCTIONAL NDIS_PACKET_TYPE_GROUP
+ //
+ // Of the remaining filters, the following are not supported (see below)
+ // NDIS_PACKET_TYPE_MULTICAST NDIS_PACKET_TYPE_ALL_FUNCTIONAL
+ // NDIS_PACKET_TYPE_ALL_MULTICAST NDIS_PACKET_TYPE_SOURCE_ROUTING
+ //
+ // This leaves NDIS_PACKET_TYPE_PROMISCUOUS and NDIS_PACKET_TYPE_MAC,
+ // which we can handle if we want to.
+ //
+
+ if ((newFilter & (NDIS_PACKET_TYPE_MULTICAST |
+ NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
+ NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_MAC_FRAME |
+ NDIS_PACKET_TYPE_SOURCE_ROUTING)) != 0)
+
+ {
+ //
+ // These filters are not supported - there is no way our MAC/hw can
+ // be this selective, although the host software could do its own
+ // filtering i.e. enable promiscuous mode, and then throw away all
+ // frames except those indicated above. At some stage it might be
+ // an idea to do this anyway, together with a caveat that it is not
+ // going to be a high performance solution.
+ //
+ // Anyway, in the mean time, return NDIS_STATUS_NOT_SUPPORTED.
+ //
+
+ return NDIS_STATUS_NOT_SUPPORTED;
+ }
+
+ //
+ // Only allow promiscuous mode if it has been enabled.
+ //
+
+ if ((newFilter & (NDIS_PACKET_TYPE_PROMISCUOUS |
+ NDIS_PACKET_TYPE_MAC_FRAME)) != 0)
+ {
+ if (!ndisAdap->PromiscuousMode)
+ {
+ return NDIS_STATUS_NOT_SUPPORTED;
+ }
+ }
+
+ //
+ // We've weeded out the illegal ones now - note that no change has been
+ // made to the current filter - this is as specified in the paperwork!
+ //
+ // Make a note of the _adapter_ notion of the filter. Each
+ // binding will have its own idea of what it wants, but this is
+ // the Filter Database's problem, not ours!
+ //
+
+ ndisAdap->CurrentPacketFilter = newFilter;
+
+ //
+ // Now we have to work out which bits need setting in the Modify Open
+ // Options SRB - when I looked at this there didn't appear to be any
+ // obvious way of simplifying the logic, so I use a look up table to do
+ // the decoding instead. You'll just have to take my word for it that I
+ // worked all the permutations out correctly!
+ //
+
+ if (oldFilter & NDIS_PACKET_TYPE_MAC_FRAME)
+ {
+ index |= 8;
+ }
+ if (oldFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
+ {
+ index |= 4;
+ }
+ if (newFilter & NDIS_PACKET_TYPE_MAC_FRAME)
+ {
+ index |= 2;
+ }
+ if (newFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
+ {
+ index |= 1;
+ }
+
+// MadgePrint2("index = %d\n", index);
+
+ modifyOpenOptions =
+ (ndisAdap->OpenOptions & MOO_MASK) | MooLookupTable[index];
+
+// MadgePrint2("modifyOpenOptions = %04x\n", modifyOpenOptions);
+
+ //
+ // Now see if we need to issue an SRB - note that MOO_NO_CHANGE is not
+ // zero, to distinguish from the case when we actually want to write out
+ // zero to turn all the options off.
+ //
+
+ if (modifyOpenOptions != MOO_NO_CHANGE)
+ {
+ //
+ // We have to issue a ModifyOpenOptions SRB.
+ //
+
+ ndisAdap->RequestType = NdisRequestSetInformation;
+ ndisAdap->OpenOptions = (WORD) modifyOpenOptions;
+
+ driver_modify_open_options(
+ ndisAdap->FtkAdapterHandle,
+ ndisAdap->OpenOptions
+ );
+
+// MadgePrint1("MadgeChangeFilter pended\n");
+
+ return NDIS_STATUS_PENDING;
+ }
+
+// MadgePrint1("MadgeChangeFilter finished\n");
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+
+/***************************************************************************
+*
+* Function - MadgeSetInformation
+*
+* Parameters - adapterContext -> Pointer NDIS3 level adapter structure.
+* oid -> The OID.
+* infoBuffer -> Pointer to the information buffer.
+* infoLength -> Length of the information buffer.
+* bytesRead -> Pointer to a holder for the number of
+* bytes we've read.
+* bytesNeeded -> Pointer to a holder for the number of
+* bytes we need.
+*
+* Purpose - Set adapter information.
+*
+* Returns - An NDIS3 status code.
+*
+***************************************************************************/
+
+NDIS_STATUS
+MadgeSetInformation(
+ NDIS_HANDLE adapterContext,
+ NDIS_OID oid,
+ PVOID infoBuffer,
+ ULONG infoLength,
+ PULONG bytesRead,
+ PULONG bytesNeeded
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ NDIS_STATUS retCode;
+
+// MadgePrint2("MadgeSetInformation Oid = %08x\n", (UINT) oid);
+
+ //
+ // Do some pre-calculation.
+ //
+
+ ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
+
+ //
+ // Process the request.
+ //
+
+ switch (oid)
+ {
+ case OID_802_5_CURRENT_FUNCTIONAL:
+
+ if (infoLength != TR_LENGTH_OF_FUNCTIONAL)
+ {
+ *bytesNeeded = TR_LENGTH_OF_FUNCTIONAL;
+ retCode = NDIS_STATUS_INVALID_LENGTH;
+ }
+ else
+ {
+ MadgeChangeFunctionalAddress(
+ ndisAdap,
+ *((TR_FUNCTIONAL_ADDRESS *) infoBuffer)
+ );
+ *bytesRead = TR_LENGTH_OF_FUNCTIONAL;
+ retCode = NDIS_STATUS_PENDING;
+ }
+ break;
+
+ case OID_802_5_CURRENT_GROUP:
+
+ if (infoLength != TR_LENGTH_OF_FUNCTIONAL)
+ {
+ *bytesNeeded = TR_LENGTH_OF_FUNCTIONAL;
+ retCode = NDIS_STATUS_INVALID_LENGTH;
+ }
+ else
+ {
+ MadgeChangeGroupAddress(
+ ndisAdap,
+ *((TR_FUNCTIONAL_ADDRESS *) infoBuffer)
+ );
+ *bytesRead = TR_LENGTH_OF_FUNCTIONAL;
+ retCode = NDIS_STATUS_PENDING;
+ }
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ if (infoLength != sizeof(UINT))
+ {
+ *bytesNeeded = sizeof(UINT);
+ retCode = NDIS_STATUS_INVALID_LENGTH;
+ }
+ else
+ {
+ retCode = MadgeChangeFilter(
+ ndisAdap,
+ *((UINT *) infoBuffer)
+ );
+ *bytesRead = sizeof(UINT);
+ }
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ //
+ // It IS important to record the current lookahead. On WFWG
+ // machines it is not possible to indicate the whole frame
+ // as lookahead, so take a note of it here.
+ //
+
+// MadgePrint3("Set lookahead infoLength = %d (%d)\n", infoLength, sizeof(ULONG));
+
+ if (infoLength != sizeof(ULONG))
+ {
+ *bytesNeeded = sizeof(ULONG);
+ retCode = NDIS_STATUS_INVALID_LENGTH;
+ }
+ else
+ {
+ ndisAdap->CurrentLookahead =
+ MIN(
+ ndisAdap->MaxFrameSize - FRAME_HEADER_SIZE,
+ MAX(
+ *((ULONG *) infoBuffer),
+ MADGE_MINIMUM_LOOKAHEAD
+ )
+ );
+ *bytesRead = sizeof(ULONG);
+ retCode = NDIS_STATUS_SUCCESS;
+ }
+ break;
+
+ case OID_GEN_PROTOCOL_OPTIONS:
+
+ //
+ // This does nothing - we really don't care about the protocol
+ // options at the moment since we are too stupid to make use of
+ // them anyway.
+ //
+
+ *bytesRead = 4;
+ retCode = NDIS_STATUS_SUCCESS;
+ break;
+
+ default:
+
+ MadgePrint1("Invalid OID\n");
+ retCode = NDIS_STATUS_INVALID_OID;
+ break;
+ }
+
+ return retCode;
+}
+
+/******** End of REQUEST.C ************************************************/
diff --git a/private/ntos/ndis/madge/driver/sources b/private/ntos/ndis/madge/driver/sources
new file mode 100644
index 000000000..23e95be6c
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/sources
@@ -0,0 +1,56 @@
+!if 0
+
+ Copyright (C) 1992-1995 by Digital Equipment Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the MADGE NDIS3 miniport driver being built
+ and the list of sources files needed to build it.
+ It specifies also the compiler switches specific to this driver
+
+Author:
+
+!endif
+
+TARGETNAME=MDGMPORT
+TARGETTYPE=DRIVER
+
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib
+INCLUDES=.;..\..\..\inc;HEAD_DEF;HEAD_MOD;INC
+
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=madge.c \
+ dispatch.c \
+ request.c \
+ ftk_user.c \
+ mdgmport.rc \
+ sys_allo.c \
+ sys_dma.c \
+ sys_irq.c \
+ sys_mem.c \
+ sys_time.c \
+ hwi_gen.c \
+ hwi_at.c \
+ hwi_sm16.c \
+ hwi_eisa.c \
+ hwi_mc.c \
+ hwi_pci.c \
+ hwi_pcmc.c \
+ hwi_pnp.c \
+ hwi_pcit.c \
+ hwi_pci2.c \
+ drv_err.c \
+ drv_srb.c \
+ drv_irq.c \
+ drv_init.c \
+ util.c
+
+NTTARGETFILES=mdgmport.bin
diff --git a/private/ntos/ndis/madge/driver/sys_allo.c b/private/ntos/ndis/madge/driver/sys_allo.c
new file mode 100644
index 000000000..d643826c8
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/sys_allo.c
@@ -0,0 +1,492 @@
+/****************************************************************************
+*
+* SYS_ALLO.C
+*
+* FastMAC Plus based NDIS3 miniport driver. This module contains helper
+* routines used by the FTK to allocate resources.
+*
+* Copyright (c) Madge Networks Ltd 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: MF
+* Major modifications: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_extr.h"
+
+#include "ndismod.h"
+
+
+/***************************************************************************
+*
+* Function - sys_allocate_adapter_structure
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* adapter_structure_byte_size -> Size of the adapter structure.
+*
+* Purpose - Allocate an FTK adapter structure.
+*
+* Returns - A pointer to the structure on success or NULL on failure.
+*
+***************************************************************************/
+
+BYTE *
+sys_alloc_adapter_structure(
+ ADAPTER_HANDLE adapter_handle,
+ WORD adapter_structure_byte_size
+ );
+
+#pragma FTK_INIT_FUNCTION(sys_alloc_adapter_structure)
+
+BYTE *
+sys_alloc_adapter_structure(
+ ADAPTER_HANDLE adapter_handle,
+ WORD adapter_structure_byte_size
+ )
+{
+ PVOID ptr;
+ NDIS_STATUS status;
+
+ MADGE_ALLOC_MEMORY(&status, &ptr, (UINT) adapter_structure_byte_size);
+
+ return (status == NDIS_STATUS_SUCCESS)
+ ? (BYTE *) ptr
+ : NULL;
+
+}
+
+/***************************************************************************
+*
+* Function - sys_allocate_dma_phys_buffer
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* buffer_byte_size -> Size of the DMA buffer.
+* buf_phys -> Pointer to a holder for the DMA
+* buffer's physical address.
+* buf_virt -> Pointer to a holder for the DMA
+* buffer's virtual address.
+*
+* Purpose - Allocate a DMA buffer.
+*
+* Returns - TRUE on success or FALSE on failure.
+*
+***************************************************************************/
+
+WBOOLEAN
+sys_alloc_dma_phys_buffer(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD buffer_byte_size,
+ DWORD * buf_phys,
+ DWORD * buf_virt
+ );
+
+#pragma FTK_INIT_FUNCTION(sys_alloc_dma_phys_buffer)
+
+WBOOLEAN
+sys_alloc_dma_phys_buffer(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD buffer_byte_size,
+ DWORD * buf_phys,
+ DWORD * buf_virt
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ VOID * virt;
+ NDIS_PHYSICAL_ADDRESS phys;
+ NDIS_STATUS status;
+
+ *buf_virt = 0;
+ *buf_phys = 0;
+ ndisAdap = (PMADGE_ADAPTER) FTK_ADAPTER_USER_INFORMATION(adapter_handle);
+
+ //
+ // If we are in DMA mode then we must use shared memory. If we are
+ // not in DMA mode then we can use ordinary memory.
+ //
+
+ if (ndisAdap->TransferMode == DMA_DATA_TRANSFER_MODE)
+ {
+#ifdef _ALPHA_
+
+ //
+ // If we are running on an Alpha platform then we need
+ // to allocate map registers. This allocation scheme was
+ // recommended to FrancisT by DEC.
+ //
+
+ if (NdisMAllocateMapRegisters(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ndisAdap->DmaChannel == 0) ? 255 : ndisAdap->DmaChannel,
+ (BOOLEAN) (ndisAdap->NTCardBusType != NdisInterfaceIsa),
+ BYTES_TO_PAGES(buffer_byte_size),
+ buffer_byte_size
+ ) != NDIS_STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ //
+ // Note that we have allocated some map registers.
+ //
+
+ ndisAdap->MapRegistersAllocated += BYTES_TO_PAGES(buffer_byte_size);
+
+#endif
+
+#ifdef _MIPS_
+
+ //
+ // If we are running on a MIPs platform then we only
+ // seem to need one map register.
+ //
+
+ if (ndisAdap->MapRegistersAllocated == 0)
+ {
+ if (NdisMAllocateMapRegisters(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ndisAdap->DmaChannel == 0) ? 255 : ndisAdap->DmaChannel,
+ (BOOLEAN) (ndisAdap->NTCardBusType != NdisInterfaceIsa),
+ 1,
+ buffer_byte_size
+ ) != NDIS_STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ //
+ // Note that we have allocated some map registers.
+ //
+
+ ndisAdap->MapRegistersAllocated++;
+ }
+
+#endif
+
+#ifdef _PPC_
+
+ //
+ // If we are running on a PPC platform then we only
+ // seem to need one map register.
+ //
+
+ if (ndisAdap->MapRegistersAllocated == 0)
+ {
+ if (NdisMAllocateMapRegisters(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ndisAdap->DmaChannel == 0) ? 255 : ndisAdap->DmaChannel,
+ (BOOLEAN) (ndisAdap->NTCardBusType != NdisInterfaceIsa),
+ 1,
+ buffer_byte_size
+ ) != NDIS_STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ //
+ // Note that we have allocated some map registers.
+ //
+
+ ndisAdap->MapRegistersAllocated++;
+ }
+
+#endif
+
+#ifdef _M_IX86
+
+ //
+ // If we are running on an Intel platform then we only
+ // seem to need one map register.
+ //
+
+ if (ndisAdap->MapRegistersAllocated == 0)
+ {
+ if (NdisMAllocateMapRegisters(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ndisAdap->DmaChannel == 0) ? 255 : ndisAdap->DmaChannel,
+ (BOOLEAN) (ndisAdap->NTCardBusType != NdisInterfaceIsa),
+ 1,
+ buffer_byte_size
+ ) != NDIS_STATUS_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ //
+ // Note that we have allocated some map registers.
+ //
+
+ ndisAdap->MapRegistersAllocated++;
+ }
+
+#endif
+
+ MadgePrint1("sys_alloc_dma_phys_buffer: allocating SHARED memory\n");
+
+ NdisMAllocateSharedMemory(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ULONG) buffer_byte_size,
+ FALSE,
+ &virt,
+ &phys
+ );
+
+ if (virt != NULL)
+ {
+ *buf_virt = (DWORD) virt;
+ *buf_phys = (DWORD) NdisGetPhysicalAddressLow(phys);
+ }
+
+ MadgePrint3(
+ "sys_alloc_dma_phys_buffer physical low = %lx high = %lx\n",
+ (DWORD) NdisGetPhysicalAddressLow(phys),
+ (DWORD) NdisGetPhysicalAddressHigh(phys)
+ );
+ }
+
+ else
+ {
+ MadgePrint1("sys_alloc_dma_phys_buffer: allocating NORMAL memory\n");
+
+ MADGE_ALLOC_MEMORY(&status, &virt, buffer_byte_size);
+
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ *buf_virt = (DWORD) virt;
+ }
+ else
+ {
+ virt = NULL;
+ }
+ }
+
+
+ MadgePrint2("sys_alloc_dma_phys_buffer virtual = %lx\n", (DWORD) virt);
+
+ return virt != NULL;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_allocate_status_structure
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* status_structure_byte_size -> Size of the status structure.
+*
+* Purpose - Allocate an FTK status structure.
+*
+* Returns - A pointer to the structure on success or NULL on failure.
+*
+***************************************************************************/
+
+BYTE *
+sys_alloc_status_structure(
+ ADAPTER_HANDLE adapter_handle,
+ WORD status_structure_byte_size
+ );
+
+#pragma FTK_INIT_FUNCTION(sys_alloc_status_structure)
+
+BYTE *
+sys_alloc_status_structure(
+ ADAPTER_HANDLE adapter_handle,
+ WORD status_structure_byte_size
+ )
+{
+ PVOID ptr;
+ NDIS_STATUS status;
+
+ MADGE_ALLOC_MEMORY(&status, &ptr, (UINT) status_structure_byte_size);
+
+ return (status == NDIS_STATUS_SUCCESS)
+ ? (BYTE *) ptr
+ : NULL;
+
+}
+
+
+/***************************************************************************
+*
+* Function - sys_allocate_init_block
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* init_block_byte_size -> Size of the adapter structure.
+*
+* Purpose - Allocate an FTK initialisation block.
+*
+* Returns - A pointer to the block on success or NULL on failure.
+*
+***************************************************************************/
+
+BYTE *
+sys_alloc_init_block(
+ ADAPTER_HANDLE adapter_handle,
+ WORD init_block_byte_size
+ );
+
+#pragma FTK_INIT_FUNCTION(sys_alloc_init_block)
+
+BYTE *
+sys_alloc_init_block(
+ ADAPTER_HANDLE adapter_handle,
+ WORD init_block_byte_size
+ )
+{
+ PVOID ptr;
+ NDIS_STATUS status;
+
+ MADGE_ALLOC_MEMORY(&status, &ptr, (UINT) init_block_byte_size);
+
+ return (status == NDIS_STATUS_SUCCESS)
+ ? (BYTE *) ptr
+ : NULL;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_free_adapter_structure
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* adapter_structure_addr -> Pointer to the adapter
+* structure.
+* adapter_structure_byte_size -> Size of the adapter structure.
+*
+* Purpose - Deallocate an FTK adapter structure.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_free_adapter_structure(
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * adapter_structure_addr,
+ WORD adapter_structure_byte_size
+ )
+{
+ MADGE_FREE_MEMORY(
+ (PVOID) adapter_structure_addr,
+ (UINT) adapter_structure_byte_size
+ );
+}
+
+
+/***************************************************************************
+*
+* Function - sys_free_dma_phys_buffer
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* buffer_byte_size -> Size of the DMA buffer.
+* buf_phys -> The DMA buffer's physical address.
+* buf_virt -> The DMA buffer's virtual address.
+*
+* Purpose - Free a DMA buffer.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_free_dma_phys_buffer(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD buffer_byte_size,
+ DWORD buf_phys,
+ DWORD buf_virt
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ VOID * virt;
+ NDIS_PHYSICAL_ADDRESS phys;
+
+ ndisAdap = (PMADGE_ADAPTER) FTK_ADAPTER_USER_INFORMATION(adapter_handle);
+ virt = (VOID *) buf_virt;
+
+ //
+ // If we are in DMA mode then we must free shared memory, otherwise we
+ // must free ordinary memory.
+ //
+
+ if (ndisAdap->TransferMode == DMA_DATA_TRANSFER_MODE)
+ {
+ NdisSetPhysicalAddressHigh(phys, 0);
+ NdisSetPhysicalAddressLow(phys, buf_phys);
+
+ NdisMFreeSharedMemory(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ULONG) buffer_byte_size,
+ FALSE,
+ virt,
+ phys
+ );
+ }
+
+ else
+ {
+ MADGE_FREE_MEMORY(virt, buffer_byte_size);
+ }
+}
+
+/***************************************************************************
+*
+* Function - sys_free_status_structure
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* status_structure_addr -> Pointer to the status structure.
+* status_structure_byte_size -> Size of the status structure.
+*
+* Purpose - Deallocate an FTK status structure.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+export void
+sys_free_status_structure(
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * status_structure_addr,
+ WORD status_structure_byte_size
+ )
+{
+ MADGE_FREE_MEMORY(
+ (PVOID) status_structure_addr,
+ (UINT) status_structure_byte_size
+ );
+}
+
+
+/***************************************************************************
+*
+* Function - sys_free_init_block
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* init_block_addr -> Pointer to the initialisation block.
+* init_block_byte_size -> Size of the initialisation block.
+*
+* Purpose - Deallocate an FTK initialisation block.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+export void
+sys_free_init_block(
+ ADAPTER_HANDLE adapter_handle,
+ BYTE * init_block_addr,
+ WORD init_block_byte_size
+ )
+{
+ MADGE_FREE_MEMORY(
+ (PVOID) init_block_addr,
+ (UINT) init_block_byte_size
+ );
+}
+
+
+/******** End of SYS_ALLO.C ***********************************************/
+
diff --git a/private/ntos/ndis/madge/driver/sys_dma.c b/private/ntos/ndis/madge/driver/sys_dma.c
new file mode 100644
index 000000000..42d5b5244
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/sys_dma.c
@@ -0,0 +1,233 @@
+/****************************************************************************
+*
+* SYS_DMA.C
+*
+* This module contains helper routines used by the FTK to initialise
+* DMA access to adapters.
+*
+* Copyright (c) Madge Networks Ltd 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: MF
+* Major modifications: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_extr.h"
+
+#include "ndismod.h"
+
+/*---------------------------------------------------------------------------
+|
+| DMA General Note
+| ----------------
+|
+| On an IBM compatible PC/AT machine, DMA is controlled by Programmable
+| DMA Controller 8237 chips. On AT machines there are two 8237 DMA
+| controllers. The primary controller handles DMA channels 0-3, the
+| secondary controller handles channels 4-7.
+|
+| The FTK is interested in three registers on each controller. These are
+| the mode register for setting the DMA mode for a given channel, the
+| mask register used for enabling/disabling a DMA channel, and the status
+| register for seeing what DMA channel requests have been generated.
+|
+---------------------------------------------------------------------------*/
+
+//
+// IO ports for status, mask and mode registers on primary DMA controller
+//
+
+#define DMA_STATUS_PRIMARY_8237 0x08
+#define DMA_MASK_PRIMARY_8237 0x0A
+#define DMA_MODE_PRIMARY_8237 0x0B
+
+//
+// IO ports for status, mask and mode registers on secondary DMA controller
+//
+
+#define DMA_STATUS_SECONDARY_8237 0x0D0
+#define DMA_MASK_SECONDARY_8237 0x0D4
+#define DMA_MODE_SECONDARY_8237 0x0D6
+
+//
+// Set cascade mode code (sent to mode register along with DMA channel)
+//
+
+#define DMA_CASCADE_MODE_8237 0x0C0
+
+//
+// Disable DMA channel code (sent to mask register along with DMA channel)
+//
+
+#define DMA_DISABLE_MASK_8237 0x04
+
+
+/****************************************************************************
+*
+* Function - sys_enable_dma_channel
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* dma_channel -> The DMA channel number.
+*
+* Purpose - Initialise a DMA channel.
+*
+* Returns - TRUE on success or FALSE on failure.
+*
+* Notes:
+*
+* With the NDIS3 driver the dma channel is enabled by the underlying
+* operating system. We pass information about our adapter in the
+* NDIS_ADAPTER_INFORMATION structure, including whether its a
+* BusMasterDma card --- by setting the AdapterInformation.Master flag
+* in MDGNT.c.
+*
+* So eventually this routine should be null and just return TRUE.
+*
+* Upto NT build 438, there is a problem with the AdapterInformation.Master
+* flag. Setting it does not enable the DMA channel on certain ISA/AT
+* platforms. Therefore the following code has been included such that we
+* explicitly enable the DMA channel.
+*
+* The DMA channel has been specified in the AdapterInformation structure
+* passed by the MAC driver to NdisRegisterAdapter()
+*
+****************************************************************************/
+
+WBOOLEAN
+sys_enable_dma_channel(ADAPTER_HANDLE adapter_handle, WORD dma_channel);
+
+#pragma FTK_INIT_FUNCTION(sys_enable_dma_channel)
+
+WBOOLEAN
+sys_enable_dma_channel(ADAPTER_HANDLE adapter_handle, WORD dma_channel)
+{
+#ifdef _M_IX86
+
+ if (dma_channel < 4)
+ {
+ //
+ // Program up primary 8237. Write local DMA channel with cascade
+ // mode to mode register. Write local DMA channel to mask register
+ // to enable it.
+ //
+
+ //
+ // (dma_channel + DMA_CASCADE_MODE_8237) -> DMA_MODE_PRIMARY_8237
+ //
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) DMA_MODE_PRIMARY_8237,
+ (BYTE) (dma_channel + DMA_CASCADE_MODE_8237)
+ );
+
+ //
+ // (dma_channel) -> DMA_MASK_PRIMARY_8237
+ //
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) DMA_MASK_PRIMARY_8237,
+ (BYTE) dma_channel
+ );
+
+ }
+ else
+ {
+ //
+ // Program up secondary 8237. Get local DMA channel by DMA-4.
+ // Write local DMA channel with cascade mode to mode register.
+ // Write local DMA channel to mask register to enable it.
+ //
+
+ dma_channel = dma_channel - 4;
+
+ //
+ // (dma_channel + DMA_CASCADE_MODE_8237) -> DMA_MODE_SECONDARY_8237
+ //
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) DMA_MODE_SECONDARY_8237,
+ (BYTE)(dma_channel + DMA_CASCADE_MODE_8237)
+ );
+
+
+ //
+ // (dma_channel) -> DMA_MASK_SECONDARY_8237
+ //
+
+ sys_outsb(
+ adapter_handle,
+ (WORD) DMA_MASK_SECONDARY_8237,
+ (BYTE) dma_channel
+ );
+ }
+
+#endif
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* Function - sys_disable_dma_channel
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* dma_channel -> The DMA channel number.
+*
+* Purpose - De-initialise a DMA channel.
+*
+* Returns - Nothing.
+*
+* Notes:
+*
+* Upto NT build 438, there is a problem with the AdapterInformation.Master
+* flag. Setting it does not enable the DMA channel on certain ISA/AT
+* platforms. Therefore the code in sys_enable_dma_channel() above, has been
+* included such that we explicitly enable the DMA channel.
+*
+* Eventually, the Operating system will do this for us. And will also disable
+* the DMA channel when the driver is unloaded.
+*
+* Therefore, I have not added code to explicitly disable DMA channel.
+*
+*
+* However, if we do not disable the channel certain ISA platforms hang
+* on shutdown. (pba 25/5/1994)
+*
+***************************************************************************/
+
+void
+sys_disable_dma_channel(ADAPTER_HANDLE adapter_handle, WORD dma_channel)
+{
+#ifdef _M_IX86
+
+ if (dma_channel < 4)
+ {
+ sys_outsb(
+ adapter_handle,
+ (WORD) DMA_MASK_PRIMARY_8237,
+ (BYTE) (DMA_DISABLE_MASK_8237 + dma_channel)
+ );
+ }
+ else
+ {
+ sys_outsb(
+ adapter_handle,
+ (WORD)DMA_MASK_SECONDARY_8237,
+ (BYTE)(DMA_DISABLE_MASK_8237 + (dma_channel - 4))
+ );
+ }
+
+#endif
+}
+
+
+/******** End of SYS_DMA.C *************************************************/
diff --git a/private/ntos/ndis/madge/driver/sys_irq.c b/private/ntos/ndis/madge/driver/sys_irq.c
new file mode 100644
index 000000000..a056ffab0
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/sys_irq.c
@@ -0,0 +1,119 @@
+/****************************************************************************
+*
+* SYS_IRQ.C
+*
+* FastMAC Plus based NDIS3 miniport driver. This module contains helper
+* routines used by the FTK to handle interrupts.
+*
+* Copyright (c) Madge Networks Ltd 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: MF
+* Major modifications: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_intr.h"
+#include "ftk_extr.h"
+
+#include "ndismod.h"
+
+
+/****************************************************************************
+*
+* Function - sys_enable_irq_channel
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* interrupt_number -> Interrupt number to enable (unused).
+*
+* Purpose - Register an IRQ with the NDIS3 wrapper so that
+* MadgeInterruptServiceRoutine() gets called on the
+* IRQ and MadgeDeferredProcessingRoutine() as the DPR.
+*
+* Returns - TRUE on success or FALSE on failure.
+*
+****************************************************************************/
+
+WBOOLEAN
+sys_enable_irq_channel(ADAPTER_HANDLE adapter_handle, WORD interrupt_number);
+
+#pragma FTK_INIT_FUNCTION(sys_enable_irq_channel)
+
+WBOOLEAN
+sys_enable_irq_channel(ADAPTER_HANDLE adapter_handle, WORD interrupt_number)
+{
+ PMADGE_ADAPTER ndisAdap;
+ NDIS_STATUS status;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // Register with the NDIS3 wrapper.
+ //
+
+ status = NdisMRegisterInterrupt(
+ &ndisAdap->Interrupt,
+ ndisAdap->UsedInISR.MiniportHandle,
+ (UINT) ndisAdap->UsedInISR.InterruptNumber,
+ (UINT) ndisAdap->UsedInISR.InterruptNumber,
+ TRUE, // We want ISRs.
+ ndisAdap->UsedInISR.InterruptShared,
+ ndisAdap->UsedInISR.InterruptMode
+ );
+
+ //
+ // If it didn't work then write an entry to the event log.
+ //
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisWriteErrorLogEntry(
+ ndisAdap->UsedInISR.MiniportHandle,
+ NDIS_ERROR_CODE_INTERRUPT_CONNECT,
+ 2,
+ inFtk,
+ MADGE_ERRMSG_INIT_INTERRUPT
+ );
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/****************************************************************************
+*
+* Function - sys_disable_irq_channel
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* interrupt_number -> Interrupt number to disable (unused).
+*
+* Purpose - De-register an IRQ with the NDIS3 wrapper.
+*
+* Returns - Nothing.
+*
+****************************************************************************/
+
+void
+sys_disable_irq_channel(ADAPTER_HANDLE adapter_handle, WORD interrupt_number)
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ //
+ // De-register with the NDIS3 wrapper.
+ //
+
+ NdisMDeregisterInterrupt(&ndisAdap->Interrupt);
+}
+
+
+
+/******** End of SYS_IRQ.C ************************************************/
+
diff --git a/private/ntos/ndis/madge/driver/sys_mem.c b/private/ntos/ndis/madge/driver/sys_mem.c
new file mode 100644
index 000000000..f72beb7bc
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/sys_mem.c
@@ -0,0 +1,925 @@
+/****************************************************************************
+*
+* SYS_MEM.C
+*
+* FastMAC Plus based NDIS3 miniport driver. This module contains helper
+* routines used by the FTK to perform I/O access to adapters.
+*
+* Copyright (c) Madge Networks Ltd 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: MF
+* Major modifications: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_extr.h"
+
+#include "ndismod.h"
+
+/*--------------------------------------------------------------------------
+|
+| Note: These I/O routines are more involved that I would have liked for
+| two reasons. We cannot use uncooked raw I/O routines because our
+| EISA adapters use two ranges of I/O locations which could have some
+| other device in between them. Also we cannot turn these functions into
+| macros because the FTK expects sys_ins{b|w} to return a value but the
+| Ndis take a pointer to a memory cell for the value read.
+|
+--------------------------------------------------------------------------*/
+
+/***************************************************************************
+*
+* Function - sys_insw
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* input_location -> I/O location to be read.
+*
+* Purpose - Read a word from an I/O location.
+*
+* Returns - The word read.
+*
+***************************************************************************/
+
+WORD
+sys_insw(
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+ WORD word_data;
+
+#ifdef _M_IX86
+
+ NdisRawReadPortUshort((ULONG) input_location, &word_data);
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) input_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) input_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) input_location - ndisAdap->IoLocation2);
+
+ NdisRawReadPortUshort(port, &word_data);
+
+#endif
+
+ return word_data;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_insb
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* input_location -> I/O location to be read.
+*
+* Purpose - Read a byte from an I/O location.
+*
+* Returns - The byte read.
+*
+***************************************************************************/
+
+BYTE
+sys_insb(
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+ BYTE byte_data;
+
+#ifdef _M_IX86
+
+ NdisRawReadPortUchar((ULONG) input_location, &byte_data);
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) input_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) input_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) input_location - ndisAdap->IoLocation2);
+
+ NdisRawReadPortUchar(port, &byte_data);
+
+#endif
+
+ return byte_data;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_outsw
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* output_location -> I/O location to be written.
+* output_word -> The word to be written.
+*
+* Purpose - Write a word to an I/O location.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_outsw(
+ ADAPTER_HANDLE adapter_handle,
+ WORD output_location,
+ WORD output_word
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+
+#ifdef _M_IX86
+
+ NdisRawWritePortUshort((ULONG) output_location, output_word);
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) output_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) output_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) output_location - ndisAdap->IoLocation2);
+
+ NdisRawWritePortUshort(port, output_word);
+
+#endif
+}
+
+
+/***************************************************************************
+*
+* Function - sys_outsb
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* output_location -> I/O location to be written.
+* output_byte -> The byte to be written.
+*
+* Purpose - Write a byte to an I/O location.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_outsb(
+ ADAPTER_HANDLE adapter_handle,
+ WORD output_location,
+ BYTE output_byte
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+
+#ifdef _M_IX86
+
+ NdisRawWritePortUchar((ULONG) output_location, output_byte);
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) output_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) output_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) output_location - ndisAdap->IoLocation2);
+
+ NdisRawWritePortUchar(port, output_byte);
+
+#endif
+}
+
+
+/***************************************************************************
+*
+* Function - sys_rep_insw
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* output_location -> I/O location to be read.
+* destination_address -> Destination for the data read.
+* length_in_words -> Number of words to read.
+*
+* Purpose - Read a number of words from an I/O location.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_rep_insw(
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE * destination_address,
+ WORD length_in_words
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+
+#ifdef _M_IX86
+
+ NdisRawReadPortBufferUshort(
+ (ULONG) input_location,
+ (USHORT *) destination_address,
+ (ULONG) length_in_words
+ );
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) input_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) input_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) input_location - ndisAdap->IoLocation2);
+
+ NdisRawReadPortBufferUshort(
+ port,
+ (USHORT *) destination_address,
+ (ULONG) length_in_words
+ );
+
+#endif
+}
+
+
+/***************************************************************************
+*
+* Function - sys_rep_outsw
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* output_location -> I/O location to be written.
+* source_address -> Address of the data to be written.
+* length_in_words -> Number of words to read.
+*
+* Purpose - Write a number of words to an I/O location.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_rep_outsw(
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE * source_address,
+ WORD length_in_words
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+
+#ifdef _M_IX86
+
+ NdisRawWritePortBufferUshort(
+ (ULONG) input_location,
+ (USHORT *) source_address,
+ (ULONG) length_in_words
+ );
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) input_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) input_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) input_location - ndisAdap->IoLocation2);
+
+ NdisRawWritePortBufferUshort(
+ port,
+ (USHORT *) source_address,
+ (ULONG) length_in_words
+ );
+
+#endif
+}
+
+
+/***************************************************************************
+*
+* Function - sys_rep_swap_insw
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* output_location -> I/O location to be read.
+* destination_address -> Destination for the data read.
+* length_in_words -> Number of words to read.
+*
+* Purpose - Read a number of byte swapped words from an I/O location.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_rep_swap_insw(
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE * destination_address,
+ WORD length_in_words
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+ USHORT word_data;
+ WORD * ptr;
+
+ ptr = (WORD *) destination_address;
+
+#ifdef _M_IX86
+
+ while (length_in_words > 0)
+ {
+ NdisRawReadPortUshort((ULONG) input_location, &word_data);
+ *ptr = ((WORD) word_data << 8) | ((WORD) word_data >> 8);
+
+ ptr++;
+ length_in_words--;
+ }
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) input_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) input_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) input_location - ndisAdap->IoLocation2);
+
+ while (length_in_words > 0)
+ {
+ NdisRawReadPortUshort(port, &word_data);
+ *ptr = ((WORD) word_data << 8) | ((WORD) word_data >> 8);
+
+ ptr++;
+ length_in_words--;
+ }
+
+
+#endif
+}
+
+
+/***************************************************************************
+*
+* Function - sys_rep_swap_outsw
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* output_location -> I/O location to be written.
+* source_address -> Address of the data to be written.
+* length_in_words -> Number of words to read.
+*
+* Purpose - Write a number of byte swapped words to an I/O location.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_rep_swap_outsw(
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE * source_address,
+ WORD length_in_words
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+ USHORT word_data;
+ WORD * ptr;
+
+ ptr = (WORD *) source_address;
+
+#ifdef _M_IX86
+
+ while (length_in_words > 0)
+ {
+ word_data = (USHORT) (*ptr << 8) | (*ptr >> 8);
+ NdisRawWritePortUshort((ULONG) input_location, word_data);
+
+ ptr++;
+ length_in_words--;
+ }
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) input_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) input_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) input_location - ndisAdap->IoLocation2);
+
+ while (length_in_words > 0)
+ {
+ word_data = (USHORT) (*ptr << 8) | (*ptr >> 8);
+ NdisRawWritePortUshort(port, word_data);
+
+ ptr++;
+ length_in_words--;
+ }
+
+#endif
+}
+
+
+/***************************************************************************
+*
+* Function - sys_rep_insd
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* output_location -> I/O location to be read.
+* destination_address -> Destination for the data read.
+* length_in_dwords -> Number of dwords to read.
+*
+* Purpose - Read a number of dwords from an I/O location.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_rep_insd(
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE * destination_address,
+ WORD length_in_dwords
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+
+#ifdef _M_IX86
+
+ NdisRawReadPortBufferUlong(
+ (ULONG) input_location,
+ (USHORT *) destination_address,
+ (ULONG) length_in_dwords
+ );
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) input_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) input_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) input_location - ndisAdap->IoLocation2);
+
+ NdisRawReadPortBufferUlong(
+ port,
+ (ULONG *) destination_address,
+ (ULONG) length_in_dwords
+ );
+
+#endif
+}
+
+
+/***************************************************************************
+*
+* Function - sys_rep_outsd
+*
+* Parameters - adapter_handle -> FTK adapter handle.
+* output_location -> I/O location to be written.
+* source_address -> Address of the data to be written.
+* length_in_dwords -> Number of dwords to read.
+*
+* Purpose - Write a number of dwords to an I/O location.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_rep_outsd(
+ ADAPTER_HANDLE adapter_handle,
+ WORD input_location,
+ BYTE * source_address,
+ WORD length_in_dwords
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+ ULONG port;
+
+#ifdef _M_IX86
+
+ NdisRawWritePortBufferUlong(
+ (ULONG) input_location,
+ (USHORT *) source_address,
+ (ULONG) length_in_dwords
+ );
+
+#else
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+ port = ((UINT) input_location <= ndisAdap->IORange1End)
+ ? (ULONG) ndisAdap->MappedIOLocation1 +
+ ((UINT) input_location - ndisAdap->IoLocation1)
+ : (ULONG) ndisAdap->MappedIOLocation2 +
+ ((UINT) input_location - ndisAdap->IoLocation2);
+
+ NdisRawWritePortBufferUlong(
+ port,
+ (ULONG *) source_address,
+ (ULONG) length_in_dwords
+ );
+
+#endif
+}
+
+/***************************************************************************
+*
+* Function - sys_sync_with_interrupt
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* f -> Function to call.
+* ptr -> Argument for f.
+*
+* Purpose - Call a function in such as way that its execution will
+* never overlap with the ISR.
+*
+* Returns - The return value from *f.
+*
+***************************************************************************/
+
+WBOOLEAN
+sys_sync_with_interrupt(
+ ADAPTER_HANDLE adapter_handle,
+ WBOOLEAN (*f)(void *),
+ void * ptr
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ return NdisMSynchronizeWithInterrupt(
+ &ndisAdap->Interrupt,
+ (void *) f,
+ ptr
+ );
+}
+
+
+/***************************************************************************
+*
+* Function - sys_rep_movsd_to
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* SourcePtr -> Pointer to the source data.
+* DestPtr -> pointer to the destination.
+* TransferSize -> Number of bytes to transfer.
+*
+* Purpose - Transfer data to a memory mapped device. Although bytes
+* are given as the transfer size a whole number of
+* DWORDS are transferred.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_rep_movsd_to(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD SourcePtr,
+ DWORD DestPtr,
+ WORD TransferSize
+ )
+{
+ NdisMoveToMappedMemory(
+ (VOID *) DestPtr,
+ (VOID *) SourcePtr,
+ (ULONG) TransferSize
+ );
+}
+
+
+/***************************************************************************
+*
+* Function - sys_rep_movsd_from
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* SourcePtr -> Pointer to the source data.
+* DestPtr -> pointer to the destination.
+* TransferSize -> Number of bytes to transfer.
+*
+* Purpose - Transfer data from a memory mapped device. Although bytes
+* are given as the transfer size a whole number of
+* DWORDS are transferred.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_rep_movsd_from(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD SourcePtr,
+ DWORD DestPtr,
+ WORD TransferSize
+ )
+{
+ NdisMoveFromMappedMemory(
+ (VOID *) DestPtr,
+ (VOID *) SourcePtr,
+ (ULONG) TransferSize
+ );
+}
+
+
+/***************************************************************************
+*
+* Function - sys_movsd_to
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* SourcePtr -> Pointer to the source data.
+* DestPtr -> pointer to the destination.
+*
+* Purpose - Transfer a DWORD of data to a memory mapped device.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_movsd_to(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD SourcePtr,
+ DWORD DestPtr
+ )
+{
+ *((DWORD *) DestPtr) = *((DWORD *) SourcePtr);
+}
+
+
+/***************************************************************************
+*
+* Function - sys_movsd_from
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* SourcePtr -> Pointer to the source data.
+* DestPtr -> pointer to the destination.
+*
+* Purpose - Transfer a DWORD of data from a memory mapped device.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_movsd_from(
+ ADAPTER_HANDLE adapter_handle,
+ DWORD SourcePtr,
+ DWORD DestPtr
+ )
+{
+ *((DWORD *) DestPtr) = *((DWORD *) SourcePtr);
+}
+
+
+/***************************************************************************
+*
+* Function - sys_pci_read_config_dword
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* index -> Offset into the configuration space from
+* which to read.
+* dword_ptr -> Buffer for the data read.
+*
+* Purpose - Read a DWORD from PCI configuration space.
+*
+* Returns - TRUE on success.
+*
+***************************************************************************/
+
+WBOOLEAN
+sys_pci_read_config_dword(
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ DWORD * dword_ptr
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ NdisReadPciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ULONG) adapter_record[adapter_handle]->pci_handle,
+ index,
+ (void *) dword_ptr,
+ 4
+ );
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_pci_read_config_word
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* index -> Offset into the configuration space from
+* which to read.
+* word_ptr -> Buffer for the data read.
+*
+* Purpose - Read a WORD from PCI configuration space.
+*
+* Returns - TRUE on success.
+*
+***************************************************************************/
+
+WBOOLEAN
+sys_pci_read_config_word(
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ WORD * word_ptr
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ NdisReadPciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ULONG) adapter_record[adapter_handle]->pci_handle,
+ index,
+ (void *) word_ptr,
+ 2
+ );
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_pci_read_config_byte
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* index -> Offset into the configuration space from
+* which to read.
+* byte_ptr -> Buffer for the data read.
+*
+* Purpose - Read a BYTE from PCI configuration space.
+*
+* Returns - TRUE on success.
+*
+***************************************************************************/
+
+WBOOLEAN
+sys_pci_read_config_byte(
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ BYTE * byte_ptr
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ NdisReadPciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ULONG) adapter_record[adapter_handle]->pci_handle,
+ index,
+ (void *) byte_ptr,
+ 1
+ );
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_pci_write_config_dword
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* index -> Offset into the configuration space to
+* which to write.
+* dword -> Data to write.
+*
+* Purpose - Write a DWORD to PCI configuration space.
+*
+* Returns - TRUE on success.
+*
+***************************************************************************/
+
+WBOOLEAN
+sys_pci_write_config_dword(
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ DWORD dword
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ NdisWritePciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ULONG) adapter_record[adapter_handle]->pci_handle,
+ index,
+ (void *) &dword,
+ 4
+ );
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_pci_write_config_word
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* index -> Offset into the configuration space to
+* which to write.
+* word -> Data to write.
+*
+* Purpose - Write a WORD to PCI configuration space.
+*
+* Returns - TRUE on success.
+*
+***************************************************************************/
+
+WBOOLEAN
+sys_pci_write_config_word(
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ WORD word
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ NdisWritePciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ULONG) adapter_record[adapter_handle]->pci_handle,
+ index,
+ (void *) &word,
+ 2
+ );
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+*
+* Function - sys_pci_write_config_byte
+*
+* Parameter - adapter_handle -> FTK adapter handle.
+* index -> Offset into the configuration space to
+* which to write.
+* byte -> Data to write.
+*
+* Purpose - Write a BYTE to PCI configuration space.
+*
+* Returns - TRUE on success.
+*
+***************************************************************************/
+
+WBOOLEAN
+sys_pci_write_config_byte(
+ ADAPTER_HANDLE adapter_handle,
+ WORD index,
+ BYTE byte
+ )
+{
+ PMADGE_ADAPTER ndisAdap;
+
+ ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
+
+ NdisWritePciSlotInformation(
+ ndisAdap->UsedInISR.MiniportHandle,
+ (ULONG) adapter_record[adapter_handle]->pci_handle,
+ index,
+ (void *) &byte,
+ 1
+ );
+
+ return TRUE;
+}
+
+/******** End of SYS_MEM.C ************************************************/
+
diff --git a/private/ntos/ndis/madge/driver/sys_time.c b/private/ntos/ndis/madge/driver/sys_time.c
new file mode 100644
index 000000000..6376c2d75
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/sys_time.c
@@ -0,0 +1,80 @@
+/****************************************************************************
+*
+* SYS_TIME.C
+*
+* This module contains helper routines used by the FTK to handle timers.
+*
+* Copyright (c) Madge Networks Ltd 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+* Created: MF
+* Major modifications: PBA 21/06/1994
+*
+****************************************************************************/
+
+#include <ndis.h>
+
+#include "ftk_defs.h"
+#include "ftk_extr.h"
+
+#include "ndismod.h"
+
+
+/***************************************************************************
+*
+* Function - sys_wait_for_at_least_milliseconds
+*
+* Parameters - number_of_milliseconds -> Number of milliseconds for which
+* to wait.
+*
+* Purpose - Wait for at least a given number of milliseconds.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_wait_at_least_milliseconds(WORD number_of_milliseconds)
+{
+ DWORD number_of_microseconds;
+
+ //
+ // Note: During a call to NdisStallExecution(), all other system
+ // activity is stopped. For this reason stalls of more than 10 ms
+ // are strongly discouraged.
+ //
+
+ number_of_microseconds = (DWORD) number_of_milliseconds * 1000;
+
+ NdisStallExecution((UINT) number_of_microseconds);
+}
+
+
+/***************************************************************************
+*
+* Function - sys_wait_for_at_least_microseconds
+*
+* Parameters - number_of_microseconds -> number of microseconds for which
+* to wait.
+*
+* Purpose - Wait for at least a given number of milliseconds.
+*
+* Returns - Nothing.
+*
+***************************************************************************/
+
+void
+sys_wait_at_least_microseconds(WORD number_of_microseconds)
+{
+ //
+ // Note: During a call to NdisStallExecution(), all other system
+ // activity is stopped. For this reason stalls of more than 10 ms
+ // are strongly discouraged.
+ //
+
+ NdisStallExecution((UINT) number_of_microseconds);
+}
+
+/******** End of SYS_TIME.C ***********************************************/
+
diff --git a/private/ntos/ndis/madge/driver/util.c b/private/ntos/ndis/madge/driver/util.c
new file mode 100644
index 000000000..ef458cad4
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/util.c
@@ -0,0 +1,252 @@
+/****************************************************************************
+*
+* UTIL.C : Part of the FASTMAC TOOL-KIT (FTK)
+*
+* THE UTILITIES MODULE
+*
+* Copyright (c) Madge Networks Ltd. 1991-1994
+*
+* COMPANY CONFIDENTIAL
+*
+*****************************************************************************
+*
+* The UTIL.C utilities module provides a range of general purpose
+* utilities that are used throughout the FTK. These routines provide such
+* functions as the ability to copy strings, clear memory, byte swap node
+* addresses and caculate the minimum of three values.
+*
+****************************************************************************/
+
+/*---------------------------------------------------------------------------
+|
+| DEFINITIONS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_defs.h"
+
+/*---------------------------------------------------------------------------
+|
+| MODULE ENTRY POINTS
+|
+---------------------------------------------------------------------------*/
+
+#include "ftk_intr.h" /* routines internal to FTK */
+#include "ftk_extr.h" /* routines provided or used by external FTK user */
+
+/****************************************************************************
+*
+* util_string_copy
+* ================
+*
+* The util_string_copy routine copies a null terminated string from source
+* to destination.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(util_string_copy)
+#endif
+
+export void
+util_string_copy(
+ char * copy_to_string,
+ char * copy_from_string
+ )
+{
+
+ while (*copy_from_string != '\0')
+ {
+ *copy_to_string++ = *copy_from_string++;
+ }
+
+ *copy_to_string = '\0';
+
+ return;
+}
+
+
+/****************************************************************************
+*
+* util_mem_copy
+* =============
+*
+* The util_mem_copy routine copies max_copy_len bytes from the source
+* address to the destination address (both are virtual addresses).
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(util_mem_copy)
+#endif
+
+export void
+util_mem_copy(
+ BYTE * copy_to_mem,
+ BYTE * copy_from_mem,
+ UINT max_copy_len
+ )
+{
+ while (max_copy_len > 0)
+ {
+ *copy_to_mem = *copy_from_mem;
+
+ copy_to_mem++;
+ copy_from_mem++;
+ max_copy_len--;
+ }
+}
+
+
+/****************************************************************************
+*
+* util_string_concatenate
+* =======================
+*
+* The util_string_concatenate routine adds one null terminated string onto
+* the end of another, creating a new null terminated string.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(util_string_concatenate)
+#endif
+
+export void
+util_string_concatenate(
+ char * add_to_string,
+ char * string_to_add
+ )
+{
+
+ while (*add_to_string != '\0')
+ {
+ add_to_string++;
+ }
+
+ while (*string_to_add != '\0')
+ {
+ *add_to_string++ = *string_to_add++;
+ }
+
+ *add_to_string = '\0';
+
+ return;
+}
+
+
+/****************************************************************************
+*
+* util_minimum
+* ============
+*
+* The util_minimum routine returns the minimum of three values that are
+* passed to it.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(util_minimum)
+#endif
+
+export UINT
+util_minimum(
+ UINT val_1,
+ UINT val_2,
+ UINT val_3
+ )
+{
+ if (val_1 > val_2)
+ {
+ if (val_2 > val_3)
+ {
+ return val_3;
+ }
+ else
+ {
+ return val_2;
+ }
+ }
+ else
+ {
+ if (val_1 > val_3)
+ {
+ return val_3;
+ }
+ else
+ {
+ return val_1;
+ }
+ }
+}
+
+
+/****************************************************************************
+*
+* util_zero_memory
+* ================
+*
+* The util_zero_memory routine clears an area of memory of a given size in
+* bytes.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(util_zero_memory)
+#endif
+
+export void
+util_zero_memory(
+ BYTE * memory,
+ UINT size_in_bytes
+ )
+{
+ while (size_in_bytes--)
+ {
+ *memory++ = 0;
+ }
+
+ return;
+}
+
+
+/****************************************************************************
+*
+* util_byte_swap_structure
+* ========================
+*
+* The util_byte_swap_structure routine swaps adjacent bytes in a structure
+* so that it can be correctly downloaded onto an adapter card. It is used
+* for byte swapping a node address, a multicast address and a product id
+* string.
+*
+****************************************************************************/
+
+#ifdef FTK_RES_FUNCTION
+#pragma FTK_RES_FUNCTION(util_byte_swap_structure)
+#endif
+
+export void
+util_byte_swap_structure(
+ BYTE * byte_based_structure,
+ UINT size_of_structure
+ )
+{
+ UINT i;
+ BYTE temp;
+
+ for ( i = 0; i < size_of_structure; i = i+2)
+ {
+ temp = *byte_based_structure;
+ *byte_based_structure = *(byte_based_structure + 1);
+ *(byte_based_structure + 1) = temp;
+ byte_based_structure += 2;
+ }
+
+ return;
+}
+
+
+/******** End of UTIL.C ****************************************************/
+
+