From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/ndis/madge/driver/dispatch.c | 919 ++++++ private/ntos/ndis/madge/driver/drv_err.c | 555 ++++ private/ntos/ndis/madge/driver/drv_init.c | 1656 ++++++++++ private/ntos/ndis/madge/driver/drv_irq.c | 413 +++ private/ntos/ndis/madge/driver/drv_srb.c | 1849 +++++++++++ private/ntos/ndis/madge/driver/ftk.upd | 279 ++ private/ntos/ndis/madge/driver/ftk_poke.c | 267 ++ private/ntos/ndis/madge/driver/ftk_user.c | 2187 +++++++++++++ private/ntos/ndis/madge/driver/head_def/ftk_adap.h | 280 ++ private/ntos/ndis/madge/driver/head_def/ftk_at.h | 234 ++ private/ntos/ndis/madge/driver/head_def/ftk_card.h | 341 ++ private/ntos/ndis/madge/driver/head_def/ftk_defs.h | 52 + private/ntos/ndis/madge/driver/head_def/ftk_down.h | 128 + private/ntos/ndis/madge/driver/head_def/ftk_eisa.h | 132 + private/ntos/ndis/madge/driver/head_def/ftk_err.h | 389 +++ private/ntos/ndis/madge/driver/head_def/ftk_fm.h | 351 ++ private/ntos/ndis/madge/driver/head_def/ftk_init.h | 330 ++ private/ntos/ndis/madge/driver/head_def/ftk_macr.h | 157 + private/ntos/ndis/madge/driver/head_def/ftk_mc.h | 195 ++ private/ntos/ndis/madge/driver/head_def/ftk_pci.h | 150 + private/ntos/ndis/madge/driver/head_def/ftk_pci2.h | 122 + private/ntos/ndis/madge/driver/head_def/ftk_pcit.h | 109 + private/ntos/ndis/madge/driver/head_def/ftk_pcmc.h | 256 ++ private/ntos/ndis/madge/driver/head_def/ftk_pnp.h | 142 + private/ntos/ndis/madge/driver/head_def/ftk_poke.h | 52 + private/ntos/ndis/madge/driver/head_def/ftk_sm16.h | 100 + private/ntos/ndis/madge/driver/head_def/ftk_srb.h | 279 ++ private/ntos/ndis/madge/driver/head_def/ftk_tab.h | 1054 ++++++ private/ntos/ndis/madge/driver/head_def/ftk_user.h | 666 ++++ private/ntos/ndis/madge/driver/head_mod/drv_err.h | 56 + private/ntos/ndis/madge/driver/head_mod/drv_init.h | 79 + private/ntos/ndis/madge/driver/head_mod/drv_irq.h | 48 + private/ntos/ndis/madge/driver/head_mod/drv_misc.h | 81 + private/ntos/ndis/madge/driver/head_mod/drv_rxtx.h | 201 ++ private/ntos/ndis/madge/driver/head_mod/drv_srb.h | 110 + private/ntos/ndis/madge/driver/head_mod/ftk_extr.h | 67 + private/ntos/ndis/madge/driver/head_mod/ftk_intr.h | 76 + private/ntos/ndis/madge/driver/head_mod/hwi_at.h | 75 + private/ntos/ndis/madge/driver/head_mod/hwi_eisa.h | 72 + private/ntos/ndis/madge/driver/head_mod/hwi_gen.h | 127 + private/ntos/ndis/madge/driver/head_mod/hwi_mc.h | 72 + private/ntos/ndis/madge/driver/head_mod/hwi_pci.h | 61 + private/ntos/ndis/madge/driver/head_mod/hwi_pci2.h | 56 + private/ntos/ndis/madge/driver/head_mod/hwi_pcit.h | 56 + private/ntos/ndis/madge/driver/head_mod/hwi_pcmc.h | 77 + private/ntos/ndis/madge/driver/head_mod/hwi_pnp.h | 72 + private/ntos/ndis/madge/driver/head_mod/hwi_sm16.h | 70 + private/ntos/ndis/madge/driver/head_mod/sys_allo.h | 95 + private/ntos/ndis/madge/driver/head_mod/sys_buff.h | 67 + private/ntos/ndis/madge/driver/head_mod/sys_cs.h | 651 ++++ private/ntos/ndis/madge/driver/head_mod/sys_dma.h | 60 + private/ntos/ndis/madge/driver/head_mod/sys_irq.h | 65 + private/ntos/ndis/madge/driver/head_mod/sys_mem.h | 206 ++ private/ntos/ndis/madge/driver/head_mod/sys_pci.h | 93 + private/ntos/ndis/madge/driver/head_mod/sys_pcmc.h | 50 + private/ntos/ndis/madge/driver/head_mod/sys_time.h | 52 + private/ntos/ndis/madge/driver/head_mod/util.h | 80 + private/ntos/ndis/madge/driver/hwi_at.c | 2206 +++++++++++++ private/ntos/ndis/madge/driver/hwi_eisa.c | 1054 ++++++ private/ntos/ndis/madge/driver/hwi_gen.c | 2077 ++++++++++++ private/ntos/ndis/madge/driver/hwi_mc.c | 1326 ++++++++ private/ntos/ndis/madge/driver/hwi_pci.c | 1567 +++++++++ private/ntos/ndis/madge/driver/hwi_pci2.c | 1792 +++++++++++ private/ntos/ndis/madge/driver/hwi_pcit.c | 2028 ++++++++++++ private/ntos/ndis/madge/driver/hwi_pcmc.c | 3366 +++++++++++++++++++ private/ntos/ndis/madge/driver/hwi_pnp.c | 2490 ++++++++++++++ private/ntos/ndis/madge/driver/hwi_sm16.c | 1191 +++++++ private/ntos/ndis/madge/driver/inc/ndismod.h | 792 +++++ private/ntos/ndis/madge/driver/inc/user.h | 235 ++ private/ntos/ndis/madge/driver/madge.c | 3393 ++++++++++++++++++++ private/ntos/ndis/madge/driver/makefile | 7 + private/ntos/ndis/madge/driver/makefile.inc | 5 + private/ntos/ndis/madge/driver/mdgerrs.h | 154 + private/ntos/ndis/madge/driver/mdgerrs.rc | 2 + private/ntos/ndis/madge/driver/mdgmport.bin | Bin 0 -> 57142 bytes private/ntos/ndis/madge/driver/mdgmport.rc | 26 + private/ntos/ndis/madge/driver/mdgmport.upd | 553 ++++ private/ntos/ndis/madge/driver/msg00001.bin | Bin 0 -> 2744 bytes private/ntos/ndis/madge/driver/request.c | 1158 +++++++ private/ntos/ndis/madge/driver/sources | 56 + private/ntos/ndis/madge/driver/sys_allo.c | 492 +++ private/ntos/ndis/madge/driver/sys_dma.c | 233 ++ private/ntos/ndis/madge/driver/sys_irq.c | 119 + private/ntos/ndis/madge/driver/sys_mem.c | 925 ++++++ private/ntos/ndis/madge/driver/sys_time.c | 80 + private/ntos/ndis/madge/driver/util.c | 252 ++ 86 files changed, 44098 insertions(+) create mode 100644 private/ntos/ndis/madge/driver/dispatch.c create mode 100644 private/ntos/ndis/madge/driver/drv_err.c create mode 100644 private/ntos/ndis/madge/driver/drv_init.c create mode 100644 private/ntos/ndis/madge/driver/drv_irq.c create mode 100644 private/ntos/ndis/madge/driver/drv_srb.c create mode 100644 private/ntos/ndis/madge/driver/ftk.upd create mode 100644 private/ntos/ndis/madge/driver/ftk_poke.c create mode 100644 private/ntos/ndis/madge/driver/ftk_user.c create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_adap.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_at.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_card.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_defs.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_down.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_eisa.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_err.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_fm.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_init.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_macr.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_mc.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_pci.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_pci2.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_pcit.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_pcmc.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_pnp.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_poke.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_sm16.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_srb.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_tab.h create mode 100644 private/ntos/ndis/madge/driver/head_def/ftk_user.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/drv_err.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/drv_init.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/drv_irq.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/drv_misc.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/drv_rxtx.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/drv_srb.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/ftk_extr.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/ftk_intr.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_at.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_eisa.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_gen.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_mc.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_pci.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_pci2.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_pcit.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_pcmc.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_pnp.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/hwi_sm16.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_allo.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_buff.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_cs.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_dma.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_irq.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_mem.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_pci.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_pcmc.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/sys_time.h create mode 100644 private/ntos/ndis/madge/driver/head_mod/util.h create mode 100644 private/ntos/ndis/madge/driver/hwi_at.c create mode 100644 private/ntos/ndis/madge/driver/hwi_eisa.c create mode 100644 private/ntos/ndis/madge/driver/hwi_gen.c create mode 100644 private/ntos/ndis/madge/driver/hwi_mc.c create mode 100644 private/ntos/ndis/madge/driver/hwi_pci.c create mode 100644 private/ntos/ndis/madge/driver/hwi_pci2.c create mode 100644 private/ntos/ndis/madge/driver/hwi_pcit.c create mode 100644 private/ntos/ndis/madge/driver/hwi_pcmc.c create mode 100644 private/ntos/ndis/madge/driver/hwi_pnp.c create mode 100644 private/ntos/ndis/madge/driver/hwi_sm16.c create mode 100644 private/ntos/ndis/madge/driver/inc/ndismod.h create mode 100644 private/ntos/ndis/madge/driver/inc/user.h create mode 100644 private/ntos/ndis/madge/driver/madge.c create mode 100644 private/ntos/ndis/madge/driver/makefile create mode 100644 private/ntos/ndis/madge/driver/makefile.inc create mode 100644 private/ntos/ndis/madge/driver/mdgerrs.h create mode 100644 private/ntos/ndis/madge/driver/mdgerrs.rc create mode 100644 private/ntos/ndis/madge/driver/mdgmport.bin create mode 100644 private/ntos/ndis/madge/driver/mdgmport.rc create mode 100644 private/ntos/ndis/madge/driver/mdgmport.upd create mode 100644 private/ntos/ndis/madge/driver/msg00001.bin create mode 100644 private/ntos/ndis/madge/driver/request.c create mode 100644 private/ntos/ndis/madge/driver/sources create mode 100644 private/ntos/ndis/madge/driver/sys_allo.c create mode 100644 private/ntos/ndis/madge/driver/sys_dma.c create mode 100644 private/ntos/ndis/madge/driver/sys_irq.c create mode 100644 private/ntos/ndis/madge/driver/sys_mem.c create mode 100644 private/ntos/ndis/madge/driver/sys_time.c create mode 100644 private/ntos/ndis/madge/driver/util.c (limited to 'private/ntos/ndis/madge/driver') 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 + +#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) ¬ifyStatus, + 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, ¤tBuffer, NULL); + if (bufferCount == 0) + { + return; + } + + NdisQueryBuffer(currentBuffer, ¤tPtr, ¤tLength); + + while (localBytesCopied < bytesToCopy) + { + if (currentLength == 0) + { + NdisGetNextBuffer(currentBuffer, ¤tBuffer); + if (currentBuffer == 0) + { + break; + } + + NdisQueryBuffer(currentBuffer, ¤tPtr, ¤tLength); + 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, ¤tBuffer, NULL); + if (bufferCount == 0) + { + return; + } + + NdisQueryBuffer(currentBuffer, &virtualAddress, ¤tLength); + + while (localBytesCopied < bytesToCopy) + { + if (currentLength == 0) + { + NdisGetNextBuffer(currentBuffer, ¤tBuffer); + if (currentBuffer == NULL) + { + break; + } + + NdisQueryBuffer(currentBuffer, &virtualAddress, ¤tLength); + 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__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__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 + +#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_.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_bit macros are used in HWI_.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_bit macros are used in HWI_.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_.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__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__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__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__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__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_.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;iadapter_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;iadapter_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;iadapter_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 +#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 +#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 + +#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 Binary files /dev/null and b/private/ntos/ndis/madge/driver/mdgmport.bin 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 + +#include "mdgerrs.rc" + +#include "mdgmport.upd" + +#include + +#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 Binary files /dev/null and b/private/ntos/ndis/madge/driver/msg00001.bin 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 + +#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 + +#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 + +#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 + +#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 + +#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 + +#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 ****************************************************/ + + -- cgit v1.2.3