mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-12-13 11:29:15 +00:00
1749 lines
56 KiB
Plaintext
1749 lines
56 KiB
Plaintext
;
|
|
; File: PDMMaceEnet.a
|
|
;
|
|
; Contains: Ethernet Data Link level driver for builtin MACE Ethernet on PDM.
|
|
;
|
|
; Converted for PDM
|
|
; by Dave Calvert November 18,1992
|
|
;
|
|
; Based on the Cyclone ENET driver
|
|
; Written by: Mark A. Law ,3-March-92
|
|
;
|
|
; Copyright: © 1991-1993 by Apple Computer, Inc. All rights reserved.
|
|
;
|
|
; This file is used in these builds: Mac32
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM12> 7/1/93 GMR Make the receive handler ignore the packet if there was a Mace
|
|
; overrun error.
|
|
; <SM11> 6/10/93 GMR Changed the handling transmit deferrals.
|
|
; <SM10> 6/2/93 GMR Minor changes to the receive handler.
|
|
; <SM9> 5/27/93 dwc Added support for AMIC work-around code.
|
|
; <SM8> 5/25/93 dwc Clean up for Alpha.
|
|
; <SM7> 5/4/93 dwc Added debug code to work around AMIC's returning FF's on the
|
|
; first read and removed some obsolete code and equates.
|
|
; <SM6> 4/6/93 dwc Updated for level #4 DMA interrupts.
|
|
; <SM5> 3/24/93 dwc Remove obsolete code and added code to try to recover from
|
|
; lowered interrupt level during packet handling.
|
|
; <SM4> 3/5/93 dwc Removed some obsolete code and comments.
|
|
; <SM3> 2/25/93 dwc Enabled receive and loopbacktests.
|
|
; <SM2> 2/24/93 dwc Removed some debug code and checked in for the PDM D5 ROM build.
|
|
; <SM1> 2/4/93 dwc first checked in
|
|
;
|
|
; To Do:
|
|
;
|
|
; Replace BIT24 with Supports24Bit
|
|
; Remove some unused equates
|
|
;
|
|
|
|
|
|
PRINT OFF
|
|
LOAD 'StandardEqu.d'
|
|
INCLUDE 'Slots.a' ; Slot interrupt equates
|
|
INCLUDE 'GestaltEqu.a'
|
|
INCLUDE 'HardwarePrivateEqu.a'
|
|
INCLUDE 'UniversalEqu.a' ; lowmem global records
|
|
INCLUDE 'ATalkMacros.a' ; Nifty Macros
|
|
|
|
; Conditional compile equates
|
|
COUNTERS EQU 0
|
|
BUFDEBUG EQU 0
|
|
BIT24 EQU 0 ; SuperMario always 32-bit
|
|
DEBUG EQU 0
|
|
PROM EQU 0 ; Promiscous mode support
|
|
Logging EQU 1 ;
|
|
|
|
PRINT NOGEN,NOMDIR,ON
|
|
INCLUDE 'PDMMaceEqu.a' ; Mace definitions
|
|
INCLUDE 'AMICEqu.a' ; AMIC definitions
|
|
INCLUDE 'ENETEqu.a' ; Driver definitions
|
|
INCLUDE 'SNMPLAP.a' ; SNMP definitions
|
|
EJECT
|
|
|
|
NumTxBuffers EQU 8 ; "optimal" number of xmit buffers
|
|
NumRxBuffers EQU 16 ; "optimal" number of recv buffers
|
|
NumRxChains EQU 4 ; "optimal" number of recv buffer chains
|
|
|
|
OurV RECORD 0 ; our variables
|
|
OurDCE DS.l 1 ; Offset to our DCE pointer in variables
|
|
MACEBase DS.l 1 ; MACE base address
|
|
IF PROM THEN
|
|
PromiscRHA DS.l 1 ; Contains status lw when in promiscuous mode
|
|
; ••• WARNING: do not separate from RHA!
|
|
ENDIF
|
|
RHA DS.b EHdrSize ; Read Header Area
|
|
;___________________________________________________________________________
|
|
;
|
|
; The LAP protocol handler table starts here. Format:
|
|
; .BYTE InUseFlag1,..., InUseFlagN ; Entry in use flag
|
|
; .wORD ProtCode1, ..., ProtCodeN ; Protocol type codes
|
|
; .lONG PHAddr1, ..., PHAddrN ; Protocol handler addresses
|
|
; .lONG RdQueueHd1, ..., RdQueueHdN ; Read queue heads
|
|
;___________________________________________________________________________
|
|
LAPTblSz EQU 16 ; Size of LAP protocol handler table (even)
|
|
InUseFlag DS.b LAPTblSz ; Entry in use flag
|
|
Protocols DS.w LAPTblSz ; List of active protocols
|
|
Handlers DS.l LAPTblSz ; List of handler addresses
|
|
RdQueueHd DS.l LAPTblSz ; Read queue heads
|
|
LAPTblEnd EQU * ; End of LAP table
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; Multicast address table. Entry format:
|
|
; Ethernet address (6 bytes)
|
|
; Use count (1 byte). Zero means entry free.
|
|
; Unused (1 byte)
|
|
;___________________________________________________________________________
|
|
|
|
MTblSz EQU 16 ; Size (in entries) of multicast address table
|
|
MEntrySz EQU 8 ; Size of an entry (power of 2)
|
|
MUseCount EQU EAddrSz ; Offset to use count in entry
|
|
|
|
ALIGN 4
|
|
MultiCTbl DS.b MTblSz*MEntrySz ; A list of valid addresses
|
|
ALIGN 4
|
|
XmitWait DS.b 1 ; non-zero = DoWrite waiting for buffers
|
|
IF PROM THEN
|
|
Promiscflg DS.b 1 ; non-zero = Promiscuous operation mode
|
|
ENDIF
|
|
deferCtl DS.b 1 ; non-zero = deferring control call
|
|
ALIGN 2
|
|
VBLQEL DS.b 14 ; VBL for control call deferrals
|
|
ALIGN 4
|
|
IF BIT24 THEN
|
|
AddrMask DS.l 1 ; 32 bit mask for addresses
|
|
ENDIF
|
|
MemMove DS.l 1 ; trap address of block move
|
|
IF COUNTERS THEN
|
|
EtherRcvCnt DS.l 1 ; # of times Deferred Recv Task called
|
|
XmitPend DS.l 1 ; Cnt of DoWrite calls from TimeMgr task
|
|
ENDIF
|
|
IF BUFDEBUG THEN
|
|
XmtDnActive DS.l 1
|
|
ENDIF
|
|
MCfg DS MACECfg ; MACE config data from config rsrc
|
|
ALIGN 4
|
|
InfoStart EQU * ; Old "GetInfo" network statistics start
|
|
OurAddr DS.b EAddrSz ; Our Ethernet address
|
|
DS.l 3 ; fill for compatibility with old getinfo
|
|
EtherStats DS NetStats
|
|
InfoEnd EQU * ; End of returned info
|
|
MultiRecvd DS.l 1 ; # of multicast pkts received
|
|
BcastRecvd DS.l 1 ; # of broadcast pkts received
|
|
; SNMP vars
|
|
LAPStats DS LAPMIBStats ; SNMP MIB stats for any link access protocol
|
|
Dt3Entry DS Dot3Entry ; SNMP status info and control vars
|
|
Dt3Stats DS Dot3StatsEntry ; SNMP stats for an 802.3 link
|
|
OurVarSz EQU * ; End of variables
|
|
ENDR
|
|
|
|
;_______________________________________
|
|
;
|
|
; Other definitions
|
|
;_______________________________________
|
|
|
|
AMaxDataSz EQU 768-EHdrSize ; Maximum data size for AppleTalk mode
|
|
|
|
INTLockOut EQU $0700 ; SR value to disable ALL interrupts
|
|
DMALockOut EQU $0400 ; SR value to disable PSC DMA interrupts
|
|
|
|
BlockMoveTrap EQU $A02E ; trap value for _BlockMove
|
|
|
|
ORBuffrsrc EQU 'ebfr' ; res type for buffer count override
|
|
|
|
IF PROM THEN
|
|
Promiscuous EQU 1 ; Bit #1 of Open()'s paramblk->ioFlags
|
|
ENDIF
|
|
EJECT
|
|
|
|
EJECT
|
|
|
|
ENETDriver MAIN EXPORT
|
|
STRING PASCAL
|
|
MACHINE MC68020
|
|
|
|
EXPORT TranslateAddress, GetMemory, FreeMemory
|
|
IMPORT MACEInit,MACEXmit,MACEAddMulti,MACEDelMulti,MACEHalt,NormAddr
|
|
IMPORT LOOPBACKTEST,MACESetProm,MACEXmitProm, AddToLog
|
|
|
|
WITH MACERegs,OurV
|
|
WITH LAPMIBStats,Dot3StatsEntry,Dot3Entry
|
|
|
|
; *****************************************
|
|
; * *
|
|
; * Start of ENET driver *
|
|
; * *
|
|
; *****************************************
|
|
ENET
|
|
;
|
|
; Driver header
|
|
;
|
|
DC.w $4400 ; Control, Locked, no Goodbye
|
|
DC.w 0,0 ; No time, no events
|
|
DC.w 0 ; No menu
|
|
|
|
;
|
|
; Entry points offset table
|
|
;
|
|
DC.w Open-ENET
|
|
DC.w AnRts-ENET
|
|
DC.w Control-ENET
|
|
DC.w AnRts-ENET
|
|
DC.w Close-ENET
|
|
|
|
DC.w '.ENET' ; Driver name
|
|
ALIGN 2
|
|
|
|
INCLUDE 'VersionPDMMaceEnet.a'
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; Open - initialize the ENET driver
|
|
;
|
|
; Call:
|
|
; D0 = 0
|
|
; A0 -> queue element
|
|
; A1 -> DCE
|
|
;
|
|
; Return:
|
|
; D0 = 0, no error
|
|
; D0 != 0, if error
|
|
;________________________________________________________________________
|
|
|
|
OpenRec RECORD {A6Link}
|
|
LinkSz EQU *
|
|
pbblkptr DS.l 1 ; copy of parameter block ptr
|
|
A6Link DS.l 2 ; link and return addr
|
|
ENDR
|
|
Open
|
|
|
|
Link A6,#OpenRec.LinkSz ; mark the stack for easy exit
|
|
|
|
Move.l A0,OpenRec.pbblkptr(A6) ; Save paramblock ptr for later access
|
|
|
|
Move.l #gestaltVMAttr,D0 ; see if VM is running
|
|
_Gestalt
|
|
Bne.s @noVM ; it is'nt if call failed
|
|
Move.l A0,D0
|
|
Btst #gestaltVMPresent,D0
|
|
Beq.s @noVM ; zero result means no VM running
|
|
BSet #VMImmuneBit,dCtlFlags+1(A1) ; tell VM to leave our calls alone
|
|
@noVM
|
|
Lea OurVarPtr,A3 ; A3 -> variable pointer
|
|
;
|
|
; Allocate our variables
|
|
;
|
|
Move.l #OurVarSz,D0 ; variables size
|
|
_NewPtr ,SYS,CLEAR ; get memory for our variables
|
|
Bne OpenError
|
|
|
|
Move.l A0,(A3) ; save variable pointer
|
|
MoveA.l A0, A2 ; A2 -> our vars
|
|
|
|
Move.b MaceEnet,DCtlQueue+1(A1) ; Version number goes here
|
|
Move.l A1,OurDCE(A2) ; Save our DCE address
|
|
|
|
Move.w #BlockMoveTrap,D0
|
|
_GetTrapAddress
|
|
Move.l A0,MemMove(A2) ; save trap address in our vars
|
|
|
|
;
|
|
; Look for an alternate address resource for this slot
|
|
;
|
|
SubQ #4,SP ; Make room for handle
|
|
Move.l #EAddrRType,-(SP) ; Push resource type
|
|
MoveQ #0,D0 ; Clear out D0
|
|
Move.b dCtlSlot(A1),D0 ; Get the slot number
|
|
Move D0,-(SP) ; Set slot number as resource ID
|
|
_GetResource ; Get it
|
|
MoveQ #-1, D0 ; Assume error
|
|
Move.l (SP)+,D1 ; D1 = handle to resource
|
|
Beq @30 ; Do nothing, if not there
|
|
Move.l D1,A0 ; A0 = handle to resource
|
|
Move.l (A0),A0 ; A0 = pointer to resource
|
|
BTst #0,(A0) ; Make sure it's not a multicast addr
|
|
Bne OpenError ; EXIT, if it is
|
|
Move.l (A0)+,OurAddr(A2) ; Move four bytes to our address
|
|
Move (A0)+,OurAddr+4(A2) ; Move the last two bytes
|
|
@30
|
|
|
|
Clr.l -(SP) ; room for result
|
|
Move.l #ORBuffrsrc,-(SP)
|
|
MoveQ #0,D0 ; Clear out D0
|
|
Move.b dCtlSlot(A1),D0
|
|
Move D0,-(SP) ; Set slot number as resource ID
|
|
_GetResource
|
|
Move.l (SP)+,D0
|
|
Beq.s @31 ; no buff override rsrc, branch
|
|
MoveA.l D0,A0
|
|
MoveA.l (A0),A0
|
|
|
|
@31
|
|
|
|
;
|
|
; Determine our Ethernet Address from Address Prom, if address not provided
|
|
; via EAddrRType resource
|
|
;
|
|
Lea OurAddr(A2),A1
|
|
Tst.l (A1)
|
|
Bne.s @45 ; already have an address
|
|
Tst.w 4(A1)
|
|
Bne.s @45 ; already have an address
|
|
|
|
Move.l D3, -(SP)
|
|
Lea AddrPROM, A0 ; Address of Ethernet Address PROM
|
|
MoveQ #0, D1 ; Setup to checksum the PROM address
|
|
MoveQ #7, D0 ; Do 8 bytes
|
|
MoveQ #1, D3 ; Offset to address byte
|
|
; Checksum the addresss PROM
|
|
@Xor Move.b (A0,D3.w), D2 ; get byte to XOR
|
|
Eor.b D2, D1
|
|
AddI #$10, D3 ; Inc offset to next byte
|
|
DBra D0, @Xor ; do them all
|
|
Move.l (SP)+, D3
|
|
CmpI.b #$FF, D1 ; end result should be $FF
|
|
Bne OpenError ; return with generic error (D0=-1)
|
|
; Get our Ethernet addresss from the PROM
|
|
AddQ #EAddrSz, A1 ; go from last to first
|
|
MoveQ #EAddrSz-1, D2 ; Get 6 addr bytes
|
|
Move.l D3, -(SP)
|
|
MoveQ #$51, D3 ; Offset to last address byte
|
|
|
|
@35 Move.b (A0,D3.w), D0 ; D0=inverted address
|
|
Bsr NormAddr ; Normalize it
|
|
Move.b D0, -(A1) ; Store in our vars
|
|
SubI #$10, D3 ; Dec offset to previous byte
|
|
DBra D2, @35
|
|
Move.l (SP)+, D3
|
|
@45
|
|
|
|
WITH MACEInitParms
|
|
SubA #IPSize, SP ; make room for parms
|
|
|
|
Move.l UnivInfoPtr, A0 ; Get ptr to ProductInfo
|
|
Add.l ProductInfo.DecoderInfoPtr(A0), A0 ; Point to the base address table
|
|
Move.l DecoderInfo.MACEAddr(A0), MACEBase(A2) ; Save base address of Mace
|
|
|
|
Pea EtherRecv ; addr of packet reception rtn
|
|
Move.l (SP)+, RecvRtn(SP)
|
|
Move.l A2, RecvPrms(SP)
|
|
Lea XmitBuffAvail, A0 ; xmit completion rtn
|
|
Move.l A0, XmitRtn(SP)
|
|
Move.l A2, XmitPrms(SP)
|
|
clr.l MACECfgPtr(SP) ; ptr to MACE config record (none)
|
|
Pea Dt3Stats(A2)
|
|
Move.l (SP)+, Dot3NetStats(SP) ; where to store 802.3 stats
|
|
Pea LAPStats(A2)
|
|
Move.l (SP)+, LAPMIBNetStats(SP) ; where to store LAP MIB stats
|
|
Pea OurAddr(A2)
|
|
Move.l (SP)+, EnetAddr(SP) ; ptr to our Ethernet address
|
|
Move.l MemMove(A2), FastMoveRtn(SP) ; addr of fast move memory rtn
|
|
|
|
Bsr MACEInit
|
|
Bne OpenError
|
|
|
|
AddA #IPSize, SP ; Strip parms
|
|
ENDWITH
|
|
|
|
Lea VBLQEL(A2),A0
|
|
Move #vType,vblType(A0)
|
|
Pea ControlDefer
|
|
Move.l (SP)+,vblAddr(A0)
|
|
Move #32767,vblCount(A0) ; setup control call deferral timer
|
|
_VInstall
|
|
|
|
;
|
|
; Perform 3 MACE loopback tests, if any fails, return an open error
|
|
;
|
|
Move.l #MaceEnetLongStrEnd-MaceEnetLongStr-1, -(SP) ; pass size of loopback
|
|
; data, minus 1 since pascal string
|
|
Pea MaceEnetLongStr+1 ; pass ptr to loopback data
|
|
Pea OurAddr(A2) ; pass ptr to our address
|
|
MoveA.l OurDCE(A2),A1 ; get ptr to DCE
|
|
Move dCtlRefNum(A1),D0
|
|
Move.l D0,-(SP) ; pass our refnum for ctl calls
|
|
|
|
MoveA.l MACEBase(A2),A3 ; MACE base address
|
|
|
|
; Perform Internal, no MENDEC, Lpbk
|
|
; Note: network packet reception disabled
|
|
Move.b #INTLPB, MACE_USER_TEST_REG(A3) ; set user test reg
|
|
nop
|
|
Bsr LOOPBACKTEST ; D0 ≠ 0 if passed
|
|
Beq LoopError ; failed
|
|
|
|
; Perform Internal, with MENDEC, Lpbk
|
|
; Note: network packet reception disabled
|
|
Move.b #MENDECLPB, MACE_USER_TEST_REG(A3) ; set user test reg
|
|
nop ; Allow write to complete
|
|
Bsr LOOPBACKTEST ; D0 ≠ 0 if passed
|
|
Beq LoopError ; failed
|
|
|
|
Move.b #EXTLPB, MACE_USER_TEST_REG(A3) ; perform external loopback
|
|
nop ; Allow write to complete
|
|
Bsr LOOPBACKTEST ; D0 ≠ 0 if passed
|
|
Beq LoopError ; failed
|
|
|
|
Move.b #NOLPB, MACE_USER_TEST_REG(A3) ; disable loopback
|
|
|
|
Bsr.s InitSNMP
|
|
IF PROM THEN
|
|
;
|
|
; Check if we're opened in promiscuous mode
|
|
;
|
|
Move.l OpenRec.pbblkptr(A6), A0 ; Restore paramblock ptr
|
|
BTst.b #Promiscuous, ioFlags+1(A0) ; Are we being opened in Promiscuous mode?
|
|
Beq.s @notprm
|
|
ST Promiscflg(A2) ; Yes, indicate we're in promiscuous mode
|
|
Move.b MACE_MAC_CNFG(A3), D0 ; get current config
|
|
OrI.b #(1<<PROMISC), D0
|
|
Move.b D0, MACE_MAC_CNFG(A3) ; enable MACE promiscous mode
|
|
nop ; Allow write to complete
|
|
AddQ #4, SP ; clean up parms
|
|
@notprm
|
|
ENDIF
|
|
MoveQ #noErr,D0 ; Indicate no error
|
|
Unlk A6
|
|
Rts ; And return
|
|
|
|
;
|
|
; Loopback test error - 1 of 3 loopback tests failed
|
|
;
|
|
LoopError
|
|
AddQ #8,SP ; strip loopback test parms
|
|
Bsr Close ; shut down MACE
|
|
MoveQ #-1,D0
|
|
Bra.s OpenErrDone ; return with open error
|
|
;
|
|
; Open error - clear out variable pointer for next try
|
|
;
|
|
OpenError
|
|
Move.w D0,D3 ; Save error code
|
|
|
|
Lea OurVarPtr, A3
|
|
Tst.l (A3) ; Our variable pointer
|
|
Beq.s @56 ; Mem not allocated
|
|
MoveA.l (A3), A0
|
|
_DisposPtr ; Free it up
|
|
Clr.l (A3) ; Clear it out
|
|
@56
|
|
Move.w D3,D0
|
|
OpenErrDone
|
|
CmpI.w #-1,D0 ; Translate generic error
|
|
Bne.s @60
|
|
MoveQ #openErr,D0
|
|
@60
|
|
Tst.w D0
|
|
Unlk A6
|
|
Rts ; Return with error
|
|
|
|
Align 2
|
|
; Strings used when building LAPStats.ifdescr string
|
|
RevStrStart Equ *
|
|
RevStr DC.B '. Hardware Revision: '
|
|
RevStrEnd Equ *
|
|
RevStrLen Equ RevStrEnd-(RevStrStart+1) ; str length, minus length byte
|
|
Align 2
|
|
;________________________________________________________________________
|
|
;
|
|
; Initialize SNMP statistic arrays
|
|
;
|
|
; Call: A2 - globals
|
|
;
|
|
; Return: none
|
|
;
|
|
; Destroys: A0,A1,D0,D3
|
|
;________________________________________________________________________
|
|
|
|
InitSNMP
|
|
|
|
; Initialize LAPStats
|
|
; Copy Pascal String MaceEnetLongStr
|
|
Lea LAPStats.ifDescr(A2), A1 ; A1 -> ifDescr
|
|
Lea MaceEnetLongStr, A0 ; A0 -> where to move from
|
|
MoveQ #0, D3 ; Init for BlockMove
|
|
Move.b (A0), D3 ; D0.B = strlen of MaceEnetLongStr
|
|
Cmp #255, D3 ; is str be greater than 255?
|
|
Bls @doit ; no
|
|
Move #255, D3 ; yes, move what we can
|
|
@doit AddQ #1, D3 ; move len byte too
|
|
Move.l D3, D0
|
|
_BlockMove ; Move it
|
|
Add.l D3, A1 ; A1 -> new end of ifDescr
|
|
|
|
Add.l #RevStrLen, D3 ; ifDescr + RevStr
|
|
Cmp #255, D3 ; would new str be greater than 255?
|
|
Bgt.s @cont ; yes, done with ifDescr
|
|
|
|
; get MACE Chip ID and convert to ascii
|
|
Lea RevStrEnd, A0
|
|
MoveA.l MACEBase(A2), A3 ; MACE base address
|
|
MoveQ #0, D0
|
|
Move.b MACE_CHIP_ID_HIGH(A3), D0 ; get high byte MACE Chip ID
|
|
Ror.l #4, D0 ; get high nibble
|
|
Add.b #$30, D0 ; convert to ascii
|
|
Move.b D0, -4(A0) ; save it in RevStr
|
|
Clr.b D0
|
|
Rol.l #4, D0 ; get low nibble
|
|
Add.b #$30, D0 ; convert to ascii
|
|
Move.b D0, -3(A0) ; save it in RevStr
|
|
Move.b MACE_CHIP_ID_LOW(A3), D0 ; get low byte MACE Chip ID
|
|
Ror.l #4, D0 ; get high nibble
|
|
Add.b #$30, D0 ; convert to ascii
|
|
Move.b D0, -2(A0) ; save it in RevStr
|
|
Clr.b D0
|
|
Rol.l #4, D0 ; get low nibble
|
|
Add.b #$30, D0 ; convert to ascii
|
|
Move.b D0, -1(A0) ; save it in RevStr
|
|
|
|
; Append RevStr, minus len byte, to ifDescr
|
|
Lea RevStrStart+1, A0 ; A0 -> where to move from, will skip length byte
|
|
; A1 -> current end of ifDescr
|
|
Move.l #RevStrLen, D0 ; D0.l = strlen of RevStr
|
|
_BlockMove ; Move it
|
|
|
|
Lea LAPStats.ifDescr(A2), A1 ; A1 -> ifDescr
|
|
Add.b #RevStrLen, (A1) ; Set final string length
|
|
@cont
|
|
|
|
Move.l #SNMPVersion, LAPStats.ifVersion(A2) ; Set version to 1.0.0
|
|
Move.l #iso88023_csmacd, LAPStats.ifType(A2) ; indicate we're an 802.3 link
|
|
Move.l #EMaxDataSz, LAPStats.ifMaxMTU(A2)
|
|
Move.l #ESpeed, LAPStats.ifSpeed(A2)
|
|
|
|
Move.b #EAddrSz, LAPStats.ifPhysAddress(A2) ; set len of ifPhyAddr to #6
|
|
Move.l OurAddr(A2), LAPStats.ifPhysAddress+1(A2) ; copy first 4 bytes of address
|
|
Move OurAddr+4(A2), LAPStats.ifPhysAddress+5(A2) ; copy last 2 bytes of address
|
|
Move.l #ifStatusUp, LAPStats.ifAdminStatus(A2)
|
|
Move.l #ifStatusUp, LAPStats.ifOperStatus(A2)
|
|
Move.l Ticks, LAPStats.ifLastChange(A2)
|
|
|
|
; Initialize Dt3Stats
|
|
|
|
Move.l #SNMPVersion, Dt3Stats.dot3StatsVersion(A2) ; Set version to 1.0.0
|
|
Move.l #0, Dt3Stats.dot3StatsIndex(A2) ; Set index to 0
|
|
|
|
; Initialize Dt3Entry
|
|
|
|
Move.l #SNMPVersion, Dt3Entry.dot3Version(A2) ; Set version = 1.0.0
|
|
Move.l #$0, Dt3Entry.dot3Index(A2)
|
|
Move.l #2, Dt3Entry.dot3InitializeMac(A2)
|
|
Move.l #1, Dt3Entry.dot3SubLayerStatus(A2)
|
|
Move.l #1, Dt3Entry.dot3MulticastReceiveStatus(A2)
|
|
Move.l #1, Dt3Entry.dot3TxEnabled(A2)
|
|
Move.l #0, Dt3Entry.dot3TestTdrValue(A2)
|
|
|
|
Rts
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; Translate Logical to Physical Address Routine
|
|
;
|
|
; Call:
|
|
; 8(A6).l -> logical address
|
|
; 12(A6).l -> logical size
|
|
;
|
|
; Return:
|
|
; D0.w < 0 -> ERROR
|
|
; D0.l = physical address
|
|
; CC's are set
|
|
;________________________________________________________________________
|
|
|
|
; Ptr TranslateAddress(laddr,lsize) ; translate logical to physical addrs
|
|
MemBlk RECORD 0
|
|
address DS.l 1
|
|
count DS.l 1
|
|
ENDR
|
|
|
|
TraAdd RECORD {A6Link}
|
|
LinkSz EQU *
|
|
logical DS MemBlk
|
|
physical DS MemBlk
|
|
A6Link DS.l 2 ; link and return addr
|
|
laddr DS.l 1 ; logical address
|
|
lsize DS.l 1 ; logical size
|
|
ENDR
|
|
|
|
TranslateAddress
|
|
|
|
WITH TraAdd
|
|
Link A6,#LinkSz
|
|
Move.l laddr(A6),logical.address(A6)
|
|
Move.l lsize(A6),logical.count(A6)
|
|
Lea logical(A6),A0 ; A0->translation table
|
|
Lea 1,A1 ; A1=count to translate
|
|
MoveQ #5,D0 ; GetPhysical
|
|
|
|
_MemoryDispatch
|
|
IF BUFDEBUG THEN
|
|
Beq.s @cont ; success
|
|
_Debugger ; failure ?!?
|
|
@cont
|
|
ELSE
|
|
Blt.s @exit ; error, exit
|
|
ENDIF
|
|
|
|
Move.l physical.Address(A6),D0 ; return lowest physical address
|
|
@exit Unlk A6
|
|
Rts
|
|
|
|
ENDWITH
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; GetMemory - Get mem and then, optionally, make it contiguous & locked &
|
|
; non-cacheable
|
|
;
|
|
; Call:
|
|
; 8(A6).w -> mem options requested
|
|
; 10(A6).l -> mem size requested
|
|
;
|
|
; Return:
|
|
; D0.w < 0 -> ERROR, couldn't get mem or couldn't lockmemcontig it
|
|
; D0.l = Ptr to locked, contig, non-cacheable mem
|
|
; CC's are set
|
|
;___________________________________________________________________________
|
|
|
|
GetMem RECORD {A6Link}
|
|
LinkSz EQU *
|
|
A6Link DS.l 2 ; link and return addr
|
|
memoptions DS.w 1 ; requested options
|
|
memsize DS.l 1 ; requested size
|
|
ENDR
|
|
|
|
GetMemory
|
|
WITH GetMem
|
|
Link A6,#LinkSz
|
|
Move.l memsize(A6), D0
|
|
_NewPtr ,SYS,CLEAR ; get the memory
|
|
Blt.s @exit ; error, exit
|
|
|
|
Move.l A0, -(SP) ; save ptr to new mem
|
|
Move memoptions(A6), D1
|
|
; want mem locked, contiguous, or non-cacheable?
|
|
AndI #(1<<Locked)+(1<<Contig)+(1<<CacheOff), D1
|
|
Beq.s @cont ; no
|
|
; yes, fall thru
|
|
;
|
|
; Should align memsize(A6) to a pageboundary via get/setptrsz so we can
|
|
; save some mem here cause once we lockmemcontig it, we've potentially locked
|
|
; more than we want 'cause lockmemcontig rounds down the start and up the end
|
|
; to page boundaries.
|
|
;
|
|
@doit Move.l memsize(A6), A1 ; length of buffer
|
|
MoveQ #4, D0 ; LockMemoryContiguous
|
|
_MemoryDispatch
|
|
Beq.s @cont ; success
|
|
IF BUFDEBUG THEN
|
|
_Debugger ; failure ?!?
|
|
ENDIF
|
|
Move.l (SP), A0 ; get mem ptr
|
|
Move D0, (SP) ; save err code
|
|
_DisposPtr ; failure, get rid of mem
|
|
IF BUFDEBUG THEN
|
|
Beq.s @ok1 ; success
|
|
_Debugger ; failure ?!?
|
|
@ok1
|
|
ENDIF
|
|
Move (SP), D0 ; restore err code
|
|
Bra.s @exit ; couldn't get mem
|
|
|
|
@cont Move.l A0, D0 ; setup return value
|
|
@exit Unlk A6
|
|
Rts
|
|
|
|
ENDWITH
|
|
|
|
EJECT
|
|
;___________________________________________________________________________
|
|
;
|
|
; FreeMemory - Free mem and then, optionally, UN-make it contiguous & locked &
|
|
; non-cacheable
|
|
;
|
|
; Call:
|
|
; 8(A6).w -> mem options
|
|
; 10(A6).l -> mem address to free
|
|
; 14(A6).l -> mem size to free
|
|
;
|
|
; Return:
|
|
; D0 = noErr
|
|
; CC's are set
|
|
;___________________________________________________________________________
|
|
|
|
FreeMem RECORD {A6Link}
|
|
LinkSz EQU *
|
|
A6Link DS.l 2 ; link and return addr
|
|
memoptions DS.w 1 ; requested options
|
|
memaddr DS.l 1 ; address of mem to free
|
|
memsize DS.l 1 ; size of mem to UN-(lock,contig,noncache)
|
|
ENDR
|
|
|
|
FreeMemory
|
|
WITH FreeMem
|
|
Link A6,#LinkSz
|
|
|
|
Move memoptions(A6), D1 ; get mem options
|
|
; was mem locked,contiguous,or non-cacheable?
|
|
AndI #(1<<Locked)+(1<<Contig)+(1<<CacheOff), D1
|
|
Beq.s @free ; no
|
|
|
|
Move.l memaddr(A6), A0 ; address of buffer
|
|
Move.l memsize(A6), A1 ; length of buffer
|
|
MoveQ #3, D0 ; UnLockMemory
|
|
_MemoryDispatch
|
|
IF BUFDEBUG THEN
|
|
Beq @ok ; success
|
|
_Debugger ; failure ?!?
|
|
@ok
|
|
ENDIF
|
|
@free Move.l memaddr(A6), A0 ; address of buffer
|
|
_DisposPtr ; free the memory
|
|
IF BUFDEBUG THEN
|
|
Tst D0
|
|
Beq @ok1 ; success
|
|
_Debugger ; failure ?!?
|
|
@ok1
|
|
ENDIF
|
|
MoveQ #0, D0 ; no error
|
|
Unlk A6
|
|
Rts
|
|
ENDWITH
|
|
|
|
EJECT
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; Control - control requests to driver - all ENET calls come in here.
|
|
;
|
|
; Call:
|
|
; A0 -> I/O queue element
|
|
; A1 -> device control entry
|
|
;________________________________________________________________________
|
|
|
|
ControlDefer ; task to complete a deferred control call
|
|
Move.w #32767,vblCount(A0) ; next task is a long time maybe
|
|
_StackSpace ; D0 = avail. stack space
|
|
Tst.l D0
|
|
Bmi.s @defer ; defer if negative space
|
|
CmpI.l #512,D0 ; is there a little room?
|
|
Bhs.s @doControl ; yes
|
|
@defer
|
|
Move.w #1,VBLCount(A0) ; restart fast timer
|
|
@exit
|
|
Rts ; and get out
|
|
@doControl
|
|
Lea -VBLQEL(A0),A2 ; A2->our vars
|
|
BClr #0,deferCtl(A2)
|
|
Beq.s @exit ; return to VBL if not really deferring
|
|
|
|
MoveA.l OurDCE(A2),A1 ; A1->our DCE
|
|
MoveA.l dCtlQHead(A1),A0 ; A0->param block in use
|
|
Bra.s doControl
|
|
Control
|
|
Move.w ioTrap(A0),D0 ; get trap word that called us
|
|
|
|
BTst #asyncTrpBit,D0 ; is this a synchronous call?
|
|
Beq.s doControl ; yes, bypass stack check
|
|
|
|
_StackSpace ; D0 = avail. stack space
|
|
Tst.l D0
|
|
Bmi.s @defer ; defer if negative space
|
|
CmpI.l #512,D0 ; is there a little room?
|
|
Bhs.s doControl ; yes
|
|
@defer
|
|
MoveA.l OurVarPtr,A2 ; A2->our vars
|
|
BSet #0,deferCtl(A2) ; indicate we are deferring
|
|
Move.w #1,vblCount+VBLQEL(A2) ; set next vbl to tick fast
|
|
CRts
|
|
MoveQ #noErr,D0 ; good return for now
|
|
Rts ; get out and get stack back
|
|
doControl
|
|
Move.l OurVarPtr,A2 ; A2 -> our variables
|
|
Move.w CSCode(A0),D2 ; Pickup control code
|
|
SubQ #KillCode,D2 ; Check for OS kill I/O call
|
|
Beq.s CRts ; return if so
|
|
|
|
MoveQ #ControlErr,D0 ; Assume a control error
|
|
Move.l OurVarPtr,A2 ; A2 -> our variables
|
|
Sub #FirstENET-KillCode,D2 ; Subtract off lowest command
|
|
Blt ENETDone ; Return error if too low
|
|
Cmp #LastENET-FirstENET,D2 ; Make sure not too high
|
|
Bgt ENETDone ; Return error if too high
|
|
Move CSParam(A0),D1 ; D1 = 1st parameter word
|
|
Move.l CSParam+2(A0),D3 ; D3 = 1st parameter longword
|
|
;
|
|
; Pick up routine address for this command and jump to routine
|
|
;
|
|
Move.w (ControlTable,D2.w*2),D2 ; get offset of routine
|
|
Jmp (ControlTable,D2.w) ; go do the call
|
|
|
|
;_________________________________________________________________________
|
|
;
|
|
; Control dispatch table - must be in the same order as the ENET commands.
|
|
; Specifies offsets to the command-handling routines.
|
|
;_________________________________________________________________________
|
|
|
|
ControlTable
|
|
DC.w LapGetDot3Entry-ControlTable ; 238
|
|
DC.w ENETDONE-ControlTable ; 239 LapSetDot3Entry
|
|
DC.w LapDot3Stats-ControlTable ; 240
|
|
DC.w ENETDONE-ControlTable ; 241 LapDot3CollStats
|
|
DC.w LapGetLinkStatus-ControlTable ; 242
|
|
DC.w ENETOK-ControlTable ; 243 CloseSAP
|
|
DC.w ENETOK-ControlTable ; 244 OpenSAP
|
|
DC.w DoDelMulti-ControlTable ; 245
|
|
DC.w DoAddMulti-ControlTable ; 246
|
|
DC.w DoAttachPH-ControlTable ; 247
|
|
DC.w DoDetachPH-ControlTable ; 248
|
|
DC.w DoWrite-ControlTable ; 249
|
|
DC.w DoRead-ControlTable ; 250
|
|
DC.w DoRdCancel-ControlTable ; 251
|
|
DC.w DoGetInfo-ControlTable ; 252
|
|
DC.w ENETOK-ControlTable ; 253 DoSetGeneral
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; LapGetDot3Entry - Get Dt3Entry
|
|
;
|
|
; Call:
|
|
; A0 -> queue element
|
|
; A2 -> our variables
|
|
; D3 = Link Stats Pointer
|
|
;
|
|
; Return:
|
|
; D0 = noErr
|
|
; EBuffSize(A0) = bytes returned
|
|
;___________________________________________________________________________
|
|
|
|
LapGetDot3Entry
|
|
Move.l #0, D0 ; Clear out D0
|
|
Move EBuffSize(A0), D0 ; D0 = # of bytes to move
|
|
Cmp #Dot3EntrySz, D0 ; Asking for more than we have?
|
|
Bls.s @OKsize ; no
|
|
Move #Dot3EntrySz, D0 ; yes, just return what we have
|
|
@OKsize
|
|
Move D0, EDataSize(A0) ; Return eDataSize
|
|
Move.l D3, A1 ; A1 -> user's Dot3Entry buffer
|
|
LEA Dt3Entry(A2), A0
|
|
_BlockMove
|
|
|
|
Bra ENETOK
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; LapGetLinkStatus - Return LAPMIBStats record info
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D3 = Link Stats Pointer
|
|
;
|
|
; Return:
|
|
; D0 = noErr
|
|
; EBuffSize(A0) = bytes returned
|
|
;___________________________________________________________________________
|
|
|
|
LapGetLinkStatus
|
|
Move.l MultiRecvd(A2), D0
|
|
Add.l BcastRecvd(A2), D0
|
|
Move.l D0, LAPStats.ifInNUcastPkts(A2) ; update non-unicast cnt
|
|
|
|
Move.l #0, D0 ; Clear out D0
|
|
Move EBuffSize(A0), D0 ; D0 = # of bytes to move
|
|
Cmp #LAPMIBStatsSz, D0 ; Asking for more than we have?
|
|
Bls.s @OKsize ; no
|
|
Move #LAPMIBStatsSz, D0 ; yes, just return what we have
|
|
@OKsize
|
|
Move D0, EDataSize(A0) ; Return eDataSize
|
|
MoveA.l D3, A1 ; A1 -> user's LAPMIBStats buffer
|
|
Lea LAPStats(A2), A0
|
|
_BlockMove
|
|
|
|
Bra ENETOK
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; LapDot3Stats - return Dot3Stats record info
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D3 = 802.3 Stats Pointer
|
|
;
|
|
; Return:
|
|
; D0 = noErr
|
|
; EBuffSize(A0) = bytes returned
|
|
;___________________________________________________________________________
|
|
|
|
LapDot3Stats
|
|
Move.l #0, D0 ; Clear out D0
|
|
Move EBuffSize(A0), D0 ; D0 = # of bytes to move
|
|
Cmp #Dot3StatsEntrySz, D0 ; Asking for more than we have?
|
|
Bls.s @OKsize ; no
|
|
Move #Dot3StatsEntrySz, D0 ; yes, just return what we have
|
|
@OKsize
|
|
Move D0, EDataSize(A0) ; Return eDataSize
|
|
MoveA.l D3, A1 ; A1 -> user's Dot3Stats buffer
|
|
Lea Dt3Stats(A2), A0
|
|
_BlockMove
|
|
|
|
Bra ENETOK
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; DoAddMulti - add a multicast address to the list
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D1 = first two bytes of address
|
|
; D3 = last four bytes of address
|
|
;
|
|
; Return:
|
|
; D0 = error code
|
|
;
|
|
; Finds a free entry in the Multicast Table, stores the multicast address,
|
|
; and increments the use count. Calls Mace rtn to update Mace Logical
|
|
; Address Filter (LAF).
|
|
;___________________________________________________________________________
|
|
|
|
DoAddMulti
|
|
MoveQ #eMultiErr,D0 ; Assume invalid address or table full
|
|
BTst #8,D1 ; Make sure multicast bit is set
|
|
Beq ENETDone ; Return error if invalid multicast address
|
|
Bsr FindMEntry ; D2 = entry number for this address
|
|
Bpl.s @40 ; Branch if found it
|
|
;
|
|
; Look for the first free one
|
|
;
|
|
MoveQ #MTblSz-1,D2 ; D2 = no. of entries in multicast table
|
|
@30 Tst.b (MultiCTbl+MUseCount,A2,D2*MEntrySz)
|
|
; This one free?
|
|
DBeq D2,@30 ; Loop until checked them all or got one
|
|
@35 Bne ENETDone ; Error if none free
|
|
|
|
;
|
|
; Set in table, then compute and set hash bit in Logical Address Filter (LAF)
|
|
;
|
|
@40 Move.l D3,(MultiCTbl+2,A2,D2*MEntrySz)
|
|
; Set second part of address
|
|
Move D1,(MultiCTbl,A2,D2*MEntrySz)
|
|
; Set first part of address
|
|
AddQ.b #1,(MultiCTbl+MUseCount,A2,D2*MEntrySz)
|
|
|
|
Bsr.l MACEAddMulti ; Let Mace update LAF
|
|
|
|
Bra ENETOK
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; DoDelMulti - delete a multicast address from the list
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D1 = first two bytes of address
|
|
; D3 = last four bytes of address
|
|
;
|
|
; Return:
|
|
; D0 = error code
|
|
;
|
|
; Finds the multicast address in the Multicast Table and decrements the use
|
|
; count. Calls Mace rtn to update Mace Logical Address Filter (LAF).
|
|
;___________________________________________________________________________
|
|
|
|
DoDelMulti MoveQ #eMultiErr,D0 ; Assume address not found
|
|
Bsr.s FindMEntry ; D2 = entry number in table
|
|
Bmi ENETDone ; Return error if not found
|
|
SubQ.b #1,(MultiCTbl+MUseCount,A2,D2*MEntrySz) ; Decrement use count
|
|
|
|
Bsr.l MACEDelMulti ; Let Mace update LAF
|
|
|
|
Bra ENETOK
|
|
|
|
;
|
|
; FindMEntry - find this address's entry in the multicast table
|
|
;
|
|
; Call:
|
|
; D1 = high two bytes of address
|
|
; D3 = low four bytes of address
|
|
; A2 -> our variables
|
|
;
|
|
; Return:
|
|
; D2 = entry number within table (minus if not found). CCR set.
|
|
;
|
|
|
|
FindMEntry MoveQ #MTblSz-1,D2 ; D2 = no. of entries in multicast table
|
|
@10 Tst.b (MultiCTbl+MUseCount,A2,D2*MEntrySz)
|
|
; Is this entry in use?
|
|
Beq.s @20 ; Branch if not
|
|
Cmp (MultiCTbl,A2,D2*MEntrySz),D1
|
|
; This it?
|
|
Bne.s @20 ; Branch if not
|
|
Cmp.l (MultiCTbl+2,A2,D2*MEntrySz),D3
|
|
; Is it?
|
|
Beq.s @30 ; Branch if got it
|
|
@20 DBra D2,@10 ; Loop until checked them all
|
|
@30 Tst D2 ; Set CCR
|
|
Rts ; And return
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; DoAttachPH - attach protocol handler control call
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D3.l = address of protocol handler's packet-receive code or zero
|
|
; D1.w = protocol type code
|
|
;
|
|
; Return:
|
|
; D0 = error code
|
|
;___________________________________________________________________________
|
|
|
|
DoAttachPH
|
|
IF BIT24 THEN
|
|
And.l AddrMask(A2),D3 ; 32 bit clean
|
|
ENDIF
|
|
MoveQ #LAPProtErr,D0 ; Assume an invalid protocol error
|
|
|
|
IF PROM THEN
|
|
Tst.B Promiscflg(A2) ; Are we in Promiscuous mode?
|
|
Beq.S @10 ; No, Note: not set until pass lpbk test
|
|
Tst.w D1
|
|
Bne.s ENETDone ; Force attach to ONLY prot type 0
|
|
@10
|
|
ENDIF
|
|
;
|
|
; Read down the active protocol table, searching for a match
|
|
;
|
|
Bsr.s GetProt ; See if it's there
|
|
Bpl.s ENETDone ; Return error if protocol already active
|
|
;
|
|
; Now scan for the first free one . . .
|
|
;
|
|
MoveQ #LAPTblSz-1,D2 ; Index into active protocols list
|
|
@20 Tst.b InUseFlag(A2,D2) ; Check this entry
|
|
DBeq D2,@20 ; Loop until get one or end
|
|
Bne.s ENETDone ; Error if none
|
|
Move.l D3,(Handlers,A2,D2*4) ; Fill Handlers in first (in case of interrupt)
|
|
Clr.l (RdQueueHd,A2,D2*4) ; Clear out read queue head
|
|
Move D1,Protocols(A2,D2*2)
|
|
; Fill protocol type in
|
|
ST InUseFlag(A2,D2) ; Indicate in use
|
|
ENETOK Clr D0 ; Indicate no error
|
|
ENETDone
|
|
Move.l OurDCE(A2),A1 ; Make sure A1 has DCE address
|
|
MoveA.l JIODone,A0
|
|
Jmp (A0) ; all done now
|
|
|
|
;
|
|
; Lookup D1 in the protocol table. Return D2 = index to protocol (negative = error).
|
|
;
|
|
GetProt MoveQ #LAPTblSz-1,D2 ; Index into active protocols list
|
|
@10 Tst.b InUseFlag(A2,D2) ; In use?
|
|
Beq.s @20 ; Branch if not
|
|
Cmp Protocols(A2,D2*2),D1 ; Match?
|
|
Beq.s @30 ; Branch if so
|
|
@20 DBra D2,@10 ; Keep going until got one
|
|
@30 Tst D2 ; Set CCR to D2
|
|
Rts ; Return (BPL for match)
|
|
;___________________________________________________________________________
|
|
;
|
|
; DoDetachPH - detach protocol handler control call
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D1.w = protocol type code
|
|
;
|
|
; Return:
|
|
; D0 = error code
|
|
;___________________________________________________________________________
|
|
|
|
DoDetachPH
|
|
MoveQ #LAPProtErr,D0 ; Assume no such protocol active
|
|
|
|
IF PROM THEN
|
|
Tst.B Promiscflg(A2) ; Are we in Promiscuous mode?
|
|
Beq.S @5 ; No, Note: not set until pass lpbk test
|
|
Tst.w D1
|
|
Bne.s ENETDone ; Force deattach to ONLY prot type 0
|
|
@5
|
|
ENDIF
|
|
Bsr.s GetProt ; D2 = index to protocol
|
|
Bmi.s ENETDone ; Return error if at end of table
|
|
Clr.b InUseFlag(A2,D2) ; Indicate entry free
|
|
Tst.l (Handlers,A2,D2*4) ; Default handler?
|
|
Bne.s @10 ; All done if not
|
|
Bsr.s AbortAll ; Abort all active reads
|
|
@10 Bra.s ENETOK ; Complete this call
|
|
|
|
|
|
;
|
|
; AbortAll - abort all active read requests.
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D2 = flag offset into protocol table
|
|
; Uses D1,A0
|
|
;
|
|
; Assumes InUseFlag(A2,D2) cleared out already so no interrupts
|
|
;
|
|
|
|
AbortAll Move.l (RdQueueHd,A2,D2*4),D1 ; D1 -> first read, if any
|
|
Beq.s @10 ; Branch if none
|
|
Move.l D1,A0 ; A0 -> queue element
|
|
Move.l (A0),(RdQueueHd,A2,D2*4) ; Remove from queue
|
|
Move #reqAborted,D0 ; Set error code
|
|
Bsr CompleteReq ; Return error
|
|
Bra.s AbortAll ; And loop
|
|
|
|
@10 Rts
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; DoWrite - write out a packet on Ethernet
|
|
;
|
|
; Called:
|
|
; A2 -> our variables
|
|
; D3 = WDS pointer
|
|
;
|
|
; Return:
|
|
; D0 = error code; nobuff => chip drvr out of xmit buffers
|
|
; eLenErr => sum of data in WDS > max. pkt size
|
|
; noErr => chip drvr gave pkt to chip or put pkt
|
|
; in xmit queue for transmission
|
|
;
|
|
; Notes: Depends on MACEXmit to check maximum WDS length
|
|
;
|
|
;___________________________________________________________________________
|
|
|
|
DoWrite
|
|
MoveQ #eLenErr, D0 ; Assume length error
|
|
Move.l D3,A0 ; A0 -> WDS
|
|
Cmp #EHdrSize,(A0) ; First entry must have whole header
|
|
Blo ENETDone ; Error if not
|
|
|
|
Move.l 2(A0),A0 ; A0 -> first WDS entry
|
|
Move.l OurAddr(A2),ESrcAddr(A0) ; Set our address in it
|
|
Move OurAddr+4(A2),ESrcAddr+4(A0)
|
|
|
|
IF Logging THEN
|
|
move.l #'DoWr',-(sp)
|
|
move.l ESrcAddr(A0),-(sp)
|
|
move.l ESrcAddr+4(A0),-(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
|
|
Move.l D3, -(SP) ; Push WDS ptr
|
|
Bsr MACEXmit ; send the packet
|
|
AddQ #4, SP ; Strip parms
|
|
Tst.l D0 ; Error?
|
|
Bne.s @xmitfail ; yes, check it
|
|
Bra ENETDone ; no, complete write req. w/no error
|
|
|
|
@xmitfail Cmp.l #nobuff, D0 ; temporarily out of xmit buffs?
|
|
IF BUFDEBUG THEN
|
|
Bne.s @chklenerr ; no, it must be a len err; lets chk
|
|
ELSE
|
|
Bne ENETDone ; no, its a len err; return err
|
|
ENDIF
|
|
|
|
MoveQ #noErr,D0
|
|
Rts ; Return, don't complete write yet
|
|
|
|
IF BUFDEBUG THEN
|
|
@chklenerr Cmp.l #eLenErr, D0 ; WDS length error?
|
|
Beq.s @ok ; yes
|
|
_Debugger ; no, what the heck?
|
|
@ok Bra ENETDone ; complete write req. w/error
|
|
ENDIF
|
|
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; XmitBuffAvail - xmit completion routine
|
|
;
|
|
; Call:
|
|
; d0 - transmit waiting flag (!=0 means a write is pending)
|
|
;
|
|
; Return:
|
|
; no return value/status
|
|
;
|
|
; Notes: called via time manager after DoWrite gets no buff available error
|
|
; from MACEXmit call.
|
|
;___________________________________________________________________________
|
|
TxPrm RECORD 4
|
|
TxParm DS.l 1 ; my xmitdone parm
|
|
TxPrmSz EQU *
|
|
ENDR
|
|
|
|
XmitBuffAvail
|
|
|
|
IF Logging THEN
|
|
move.l #'WrDn',-(sp)
|
|
clr.l -(sp)
|
|
clr.l -(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
|
|
MoveA.l OurVarPtr,A0 ; get ptr to our vars
|
|
|
|
IF BUFDEBUG THEN
|
|
AddQ.l #1, XmtDnActive(A0)
|
|
CmpI.l #1, XmtDnActive(A0)
|
|
Beq.s @ok
|
|
_Debugger ; oooppppsss!
|
|
@ok
|
|
ENDIF
|
|
|
|
Tst.b d0 ; waiting for xmit buffs?
|
|
Beq.s @exit ; no
|
|
|
|
IF COUNTERS THEN
|
|
AddQ.l #1, XmitPend(A0)
|
|
ENDIF
|
|
|
|
MoveM.l A0/A2/A3/D3, -(SP) ; save C regs
|
|
MoveA.l A0, A2 ; A2->our vars
|
|
MoveA.l OurDCE(A2), A1 ; A1->our DCE
|
|
Move.l dCtlQHead(A1),d0
|
|
beq.s @done
|
|
move.l d0,A0 ; A0->waiting write param blk
|
|
Move.l CSParam+2(A0), D3 ; D3 = 1st parameter longword (e.g. WDSP)
|
|
Bsr DoWrite ; process the write
|
|
@done MoveM.l (SP)+, A0/A2/A3/D3 ; restore C regs
|
|
|
|
IF BUFDEBUG THEN
|
|
SubQ.l #1, XmtDnActive(A0)
|
|
ENDIF
|
|
@exit Rts
|
|
|
|
EJECT
|
|
;___________________________________________________________________________
|
|
;
|
|
; DoRead - read a packet off the Ethernet
|
|
;
|
|
; Call:
|
|
; A0 -> queue element
|
|
; A1 -> our DCE
|
|
; A2 -> our variables
|
|
; D1 = protocol type code
|
|
;
|
|
; Return:
|
|
; D0 = error code
|
|
;___________________________________________________________________________
|
|
|
|
DoRead MoveQ #LAPProtErr,D0 ; Assume an error
|
|
Bsr GetProt ; D2 = index into PH table
|
|
Bmi ENETDone ; Error if not there
|
|
Tst.l (Handlers,A2,D2*4) ; Is it the default?
|
|
Bne ENETDone ; Error if not
|
|
Move #buf2SmallErr,D0 ; Assume buffer not big enough
|
|
Cmp #EHdrSize,EBuffSize(A0) ; Must hold at least header
|
|
Blo ENETDone ; Return error if not
|
|
;
|
|
; Dequeue the request from the system queue and queue it on ours (in order)
|
|
;
|
|
Lea (RdQueueHd,A2,D2*4),A3 ; A3 -> queue head
|
|
Move SR,-(SP) ; Save interrupt status
|
|
Move #DMALockOut, D1
|
|
_SETINTMASK D1
|
|
@10 Tst.l (A3) ; Is there a next element?
|
|
Beq.s @20 ; Branch if not
|
|
Move.l (A3),A3 ; Point to it if so
|
|
Bra.s @10 ; And keep going until end
|
|
|
|
@20
|
|
IF BIT24 THEN
|
|
Exg D0,A0
|
|
And.l AddrMask(A2),D0
|
|
Exg D0,A0 ; 32 bit clean
|
|
ENDIF
|
|
Move.l A0,(A3) ; Put queue element on our queue
|
|
BClr #DrvrActive,DCtlFlags+1(A1)
|
|
; Clear driver active flag
|
|
Move.l IOLink(A0),DCtlQHead(A1) ; Set next element addr in head
|
|
Bne.s @30 ; Branch if there is none
|
|
Clr.l DCtlQTail(A1) ; Clear tail if not
|
|
@30 Clr.l IOLink(A0) ; Indicate it's last one on our queue
|
|
Move.l DCtlQHead(A1),D0 ; Any more requests?
|
|
Beq.s @40 ; Branch if not
|
|
BSet #DrvrActive,DCtlFlags+1(A1)
|
|
; We're active again
|
|
Move (SP)+,SR ; Restore interrupt state
|
|
Move.l D0,A0 ; A0 -> new queue element
|
|
MoveQ #0,D0 ; D0 should be clear
|
|
IF Logging THEN
|
|
move.l #'DoRd',-(sp)
|
|
move.l a0,-(sp)
|
|
clr.l -(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
Bsr Control ; Call ourselves
|
|
MoveQ #0,D0 ; Return no error for previous call
|
|
Rts ; Return
|
|
|
|
@40 Move (SP)+,SR ; Restore interrupt state
|
|
Rts ; Return
|
|
;___________________________________________________________________________
|
|
;
|
|
; DoRdCancel - abort a pending read call
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D3 = pointer to queue element to abort
|
|
;
|
|
; Return:
|
|
; D0 = error code
|
|
;___________________________________________________________________________
|
|
|
|
DoRdCancel Move #CBNotFound,D0 ; Assume an error
|
|
IF BIT24 THEN
|
|
And.l AddrMask(A2),D3 ; 32 bit clean
|
|
ENDIF
|
|
Move.l D3,A1 ; A1 -> queue element
|
|
Move EProtType(A1),D1 ; D1 = protocol type
|
|
Bsr GetProt ; D2 = index into PH table
|
|
Bmi.s @60 ; Error if not there
|
|
Tst.l (Handlers,A2,D2*4) ; Is it the default?
|
|
Bne.s @60 ; Error if not
|
|
Lea (RdQueueHd,A2,D2*4),A3 ; A3 -> queue head
|
|
Move SR,-(SP) ; Save interrupt status
|
|
Move #DMALockOut, D1
|
|
_SETINTMASK D1
|
|
@30 Move.l (A3),D3 ; D3 -> next element in queue
|
|
IF BIT24 THEN
|
|
And.l AddrMask(A2),D3 ; 32 bit clean
|
|
ENDIF
|
|
Beq.s @50 ; Error if no more
|
|
Sub.l A1,D3 ; Subtract out desired one
|
|
Beq.s @40 ; Branch if it's the one
|
|
Move.l (A3),A3 ; A3 -> next in queue
|
|
Bra.s @30 ; Keep looking
|
|
|
|
@40 Move.l (A1),(A3) ; Point previous to next
|
|
Move (SP)+,SR ; Restore interrupts
|
|
;
|
|
; Complete the ERead with an error, then the ERdCancel
|
|
;
|
|
Move.l A1,A0 ; A0 -> ERead queue element
|
|
Move #ReqAborted,D0 ; D0 = aborted error
|
|
Bsr.s CompleteReq ; Complete it with error
|
|
Bra ENETOk ; Return no error for RdCancel
|
|
|
|
@50 Move (SP)+,SR ; Restore interrupt state
|
|
@60 Bra ENETDone ; Return not found error
|
|
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; CompleteReq - this code basically executes the parts of IODone necessary to
|
|
; complete the user's request (sets result code and executes the user's
|
|
; completion routine)
|
|
;
|
|
; Call:
|
|
; D0 = result code
|
|
; A0 -> I/O queue element
|
|
;________________________________________________________________________
|
|
|
|
CompleteReq Move.w D0,IOResult(A0) ; Set the result code
|
|
MoveM.l D1-D3/A0-A3,-(SP) ; Save registers
|
|
|
|
IF Logging THEN
|
|
move.l #'COMP',-(sp)
|
|
move.l a0,-(sp)
|
|
clr.l -(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
Move.l IOCompletion(A0),D1 ; Check if there's a completion routine
|
|
Beq.s @10 ; Branch if not - just return
|
|
Move.l D1,A1 ; Get it if so
|
|
Tst.w D0 ; IODone does this
|
|
Jsr (A1) ; Call completion routine
|
|
@10 MoveM.l (SP)+,D1-D3/A0-A3 ; Restore registers
|
|
Rts ; Return
|
|
;___________________________________________________________________________
|
|
;
|
|
; DoGetInfo - return stats in the following form:
|
|
; Our address, 3 lw's of 0's, Netstats record
|
|
;
|
|
; Call:
|
|
; A0 -> queue element
|
|
; A2 -> our variables
|
|
; D3 -> buffer for response
|
|
;
|
|
; Return:
|
|
; D0 = error code
|
|
;___________________________________________________________________________
|
|
|
|
DoGetInfo
|
|
IF BIT24 THEN
|
|
And.l AddrMask(A2),D3 ; 32 bit clean
|
|
ENDIF
|
|
Move #buf2SmallErr,D0 ; Assume buffer not big enough
|
|
Cmp #6,EBuffSize(A0) ; Must hold at least address
|
|
Blo ENETDone ; Return error if not
|
|
|
|
MoveQ #0, D0
|
|
Move EBuffSize(A0),D0 ; D0 = buffer size
|
|
Cmp #InfoEnd-InfoStart,D0 ; Asking for more than we have?
|
|
Bls.s @10 ; no, branch
|
|
MoveQ #InfoEnd-InfoStart,D0 ; yes, just return what we have
|
|
@10 Move.l D3,A1 ; A1 -> where to move to
|
|
Lea InfoStart(A2),A0 ; A0 -> where to move from
|
|
|
|
;
|
|
; Copy netstat info from Dot2stat and LAPMIBstat areas to "old" getinfo area
|
|
;
|
|
Move.l (LAPStats.ifOutUcastPkts,A2), D1
|
|
Add.l (LAPStats.ifOutNUcastPkts,A2), D1
|
|
Move.l D1, (EtherStats.TxOK,A2)
|
|
Move.l (Dt3Stats.dot3StatsSingleCollisionFrames,A2), (EtherStats.sCollFrame,A2)
|
|
Move.l (Dt3Stats.dot3StatsMultipleCollisionFrames,A2), (EtherStats.mCollFrame,A2)
|
|
; EtherStats.CollFrame doesn't make sense and is left 0
|
|
Move.l (Dt3Stats.dot3StatsDeferredTransmissions,A2), (EtherStats.DefTx,A2)
|
|
Move.l (Dt3Stats.dot3StatsLateCollisions,A2), (EtherStats.LateColl,A2)
|
|
Move.l (Dt3Stats.dot3StatsExcessiveCollisions,A2), (EtherStats.ExcessColl,A2)
|
|
Move.l (Dt3Stats.dot3StatsExcessiveDeferrals,A2), (EtherStats.ExcessDef,A2)
|
|
Move.l (Dt3Stats.dot3StatsInternalMacTransmitErrors,A2), (EtherStats.InMACTxErr,A2)
|
|
Move.l (LAPStats.ifInUcastPkts,A2), (EtherStats.RxOK,A2)
|
|
Move.l MultiRecvd(A2), (EtherStats.MultiRxOK,A2)
|
|
Move.l BcastRecvd(A2), (EtherStats.BroadRxOK,A2)
|
|
Move.l (Dt3Stats.dot3StatsFCSErrors,A2), (EtherStats.FCSerr,A2)
|
|
Move.l (Dt3Stats.dot3StatsAlignmentErrors,A2), (EtherStats.FAerr,A2)
|
|
Move.l (LAPStats.ifInErrors,A2), (EtherStats.MPerr,A2)
|
|
|
|
_BlockMove ; Move it
|
|
Bra ENETOK ; Return no error
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; EtherRecv - .ENET packet receive routine
|
|
;
|
|
; Call:
|
|
; Received packet(s) pointed to by buffer(s) on InUse Queue
|
|
;
|
|
; Return:
|
|
; Empty InUse Queue
|
|
;
|
|
; Destroys:
|
|
; Notes:
|
|
; EtherRecv is called by the MACE since we passed a ptr to EtherRecv
|
|
; as the RecvRtn in the MACEInit call.
|
|
;
|
|
; Calls:
|
|
; Upper layer handler, or Default Handler, to receive packet.
|
|
;___________________________________________________________________________
|
|
|
|
EtherRecv
|
|
WITH RcvParms
|
|
Link A6, #Size
|
|
|
|
IF Logging THEN
|
|
move.l #'Ethr',-(sp)
|
|
move.l #'Recv',-(sp)
|
|
move.l PktStat(A6),-(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
Move.l PktStat(A6), D0 ; get packet status
|
|
AndI.w #(1<<RcvOFLO)+(1<<RcvCLSN)+\
|
|
(1<<RcvFRAM)+(1<<RcvFCS),D0 ; packet with error?
|
|
Bne @86 ; ignore packet with error
|
|
|
|
MoveM.l A2-A5/D3,-(SP) ; save used C regs
|
|
|
|
MoveA.l Parm(A6), A2 ; Our variables
|
|
IF COUNTERS THEN
|
|
AddQ.l #1, EtherRcvCnt(A2)
|
|
ENDIF
|
|
move.l PktLen(A6),D1 ; D1=size of packet, including FCS
|
|
Sub #EHdrSize+4,D1 ; Subtract out header & FCS bytes from total
|
|
;
|
|
; Copy the Ethernet header from the packet into the RHA
|
|
;
|
|
Lea RHA(A2), A3 ; A3 -> RHA
|
|
MoveA.l PktData(A6), A0 ; A0 -> packet data
|
|
Move.l (A0)+, (A3)+ ; Move header into buffer
|
|
Move.l (A0)+, (A3)+ ; Hard code for speed
|
|
Move.l (A0)+, (A3)+
|
|
Move (A0)+, (A3)+ ; A3 -> buffer after header
|
|
|
|
;
|
|
; Check if dest. addr. a broadcast or one of our multicasts
|
|
;
|
|
Move RHA(A2), D3 ; D3 = first 2 bytes of dest address
|
|
BTst #8, D3 ; Is it a broadcast or multicast?
|
|
Beq.s @45 ; Branch if not, it must be our physical address
|
|
MoveQ #-1, D2 ; D2 = $FFFFFFFF
|
|
Cmp D2, D3 ; Is packet a broadcast?
|
|
Beq.s @last4 ; Maybe, check last 4 bytes of dest address
|
|
Move.l RHA+2(A2), D3 ; No, D3 = last 4 bytes of dest address
|
|
Bra @120 ; Go check if one of our registered multicasts
|
|
@last4 Move.l RHA+2(A2), D3 ; D3 = last 4 bytes of dest address
|
|
Cmp.l D2, D3 ; Is packet a broadcast?
|
|
Bne @120 ; No, go check if one of our registered multicasts
|
|
AddQ.l #1, BcastRecvd(A2) ; Yes, inc. broadcast pkt cntr
|
|
Bra.s @50
|
|
|
|
@45 AddQ.l #1, (LAPStats.ifInUcastPkts,A2) ; inc. non-multi/bcast pkt cntr
|
|
|
|
;
|
|
; Search the protocol handler table for this protocol
|
|
;
|
|
|
|
@50 Move EType-EHdrSize(A3),D0 ; D0 = protocol type or 802.3 length
|
|
Cmp.w #EMaxDataSz,D0 ; is it an 802.3?
|
|
Bhi @110 ; if not, try other protocols
|
|
|
|
Clr D0 ; Handler will be for type zero
|
|
Exg D0,D1 ; D1 = protocol type, D0 = old D1
|
|
Bsr GetProt ; D2 = offset in table
|
|
Exg D0,D1 ; Restore D0, D1
|
|
Bmi.s @90 ; Branch if not found
|
|
; Move EType-EHdrSize(A3),D0 ; D0 = protocol type
|
|
|
|
@70 Lea EReadPacket,A4 ; A4 -> our ReadPacket routine
|
|
Lea DefaultPH,A5 ; use default maybe
|
|
Move.l (Handlers,A2,D2*4),D3 ; get the protocol handler
|
|
Beq.s @80 ; use default
|
|
MoveA.l D3,A5 ; use table entry's protocol handler
|
|
|
|
@80
|
|
Jsr (A5) ; Call protocol handler
|
|
|
|
@85 MoveM.l (SP)+, A2-A5/D3 ; Restore registers
|
|
@86 Unlk A6
|
|
Rts ; That's it
|
|
|
|
@90 AddQ.l #1, LAPStats.ifInUnknownProtos(A2)
|
|
Bra.s @85
|
|
;
|
|
; Find Protocol handler for non 802.3 packet
|
|
;
|
|
@110
|
|
Exg D0,D1 ; D1 = protocol type, D0 = old D1
|
|
Bsr GetProt ; D2 = offset in table
|
|
Exg D0,D1 ; Restore D0, D1
|
|
Bmi.s @90 ; Branch if not found
|
|
|
|
Bra.s @70 ; Process it
|
|
|
|
;
|
|
; Packet is a multicast. Check if it matches one of our multicast addresses.
|
|
;
|
|
; Call:
|
|
; A2 -> our variables
|
|
; D3 = last 4 bytes of destination address
|
|
;
|
|
@120 Move D1,D0 ; Save length in case packet's for us
|
|
Move RHA(A2),D1 ; D1 = high two bytes of address
|
|
Bsr FindMEntry ; D2 = entry within multicast table
|
|
Bmi.s @150 ; Ignore it if not found
|
|
AddQ.l #1, MultiRecvd(A2) ; Inc count of multicast pkts recv'd
|
|
Move D0,D1 ; Restore packet length
|
|
Bra @50 ; And process packet
|
|
|
|
@150 AddQ.l #1, LAPStats.ifInDiscards(A2) ; Increment count of packets not for us
|
|
Bra.s @85 ; Ignore this packet
|
|
|
|
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; EReadPacket - read in the specified number of bytes into the specified
|
|
; buffer. Asking for more than there is is an error.
|
|
;
|
|
; EReadRest - read in the rest of the packet, putting the specified number
|
|
; of bytes into the specified buffer, and ignoring the rest.
|
|
;
|
|
; Call:
|
|
; A0 -> current location in card memory
|
|
; A1 -> card registers
|
|
; A3 -> buffer to read into
|
|
; A4 -> start of ReadPacket
|
|
; D1 = number of bytes left to come in (caller may decrease)
|
|
; D3 = byte count to read
|
|
;
|
|
; Return:
|
|
; D0 = error byte (Z bit set in CCR)
|
|
; D1 updated (ReadPacket)
|
|
; D2 saved
|
|
; D3 = 0 if exact number of bytes requested were read
|
|
; > 0 indicates number of bytes requested but not read
|
|
; (packet smaller than requested maximum)
|
|
; < 0 indicates number of extra bytes read but not returned
|
|
; (packet larger than requested maximum)
|
|
; A0,A1 preserved by ReadPacket, modified by ReadRest
|
|
; A2 saved
|
|
; A3 -> one past where last character went
|
|
; A4,A5 saved (until packet's all in or error)
|
|
;___________________________________________________________________________
|
|
|
|
EReadPacket Bra.s EDoRP ; Need this for two entry points
|
|
|
|
EReadRest Move D3,D0 ; D0 = number of bytes to return
|
|
Sub D1,D0 ; D0 = remainder count
|
|
Tst D3 ; Check for zero
|
|
Beq.s @10 ; If so, don't waste our time
|
|
Bsr.s MoveBytes ; Move the bytes in
|
|
@10 Move D0,D3 ; D3 = remainder count
|
|
MoveQ #0,D0 ; No error no matter what
|
|
Rts
|
|
EDoRP
|
|
Cmp.w D3,D1
|
|
Blo.s @5 ; error in request
|
|
Bsr.s MoveBytes ; Move in the bytes
|
|
Tst D3 ; Moved them all?
|
|
Beq.s @10 ; Branch if moved all ok
|
|
@5 MoveQ #eLenErr,D0 ; Set length error
|
|
@10 Rts ; Return
|
|
;___________________________________________________________________________
|
|
;
|
|
; DefaultPH - default protocol handler - complete an ERead call if there
|
|
;
|
|
; Call:
|
|
; A0,A1: preserve until ReadRest
|
|
; A2 -> local variables
|
|
; A4 -> EReadPacket
|
|
; A5 usable until ReadRest
|
|
; D0 = protocol type
|
|
; D2 = index into protocol table
|
|
;
|
|
; Notes: Interrupts are off
|
|
;
|
|
;___________________________________________________________________________
|
|
|
|
DefaultPH
|
|
Move.l (RdQueueHd,A2,D2*4),D0 ; D0 -> first ERead on queue
|
|
Beq.s @20 ; Skip packet if none
|
|
Move.l D0,A5 ; A5 -> ERead queue element
|
|
Move.l (A5),(RdQueueHd,A2,D2*4) ; Remove from queue
|
|
Move.l D0,D2 ; D2 = queue element pointer
|
|
Move.l EBuffPtr(A5),A3 ; A3 -> buffer to read into
|
|
Move EBuffSize(A5),D3 ; D3 = maximum size to read
|
|
Sub #EHdrSize,D3 ; Adjust for header
|
|
IF PROM THEN
|
|
Tst.B Promiscflg(A2) ; Are we in Promiscuous mode?
|
|
Beq.S @5 ; No, Note: not set until pass lpbk test
|
|
Lea PromiscRHA(A2), A5 ; A5 -> header info including pkt status lw
|
|
Move.l (A5)+,(A3)+ ; Move pkt status into buffer
|
|
Bra.s @6
|
|
@5 Lea RHA(A2),A5 ; A5 -> header info
|
|
@6
|
|
ELSE
|
|
Lea RHA(A2),A5 ; A5 -> header info
|
|
ENDIF
|
|
Move.l (A5)+,(A3)+ ; Move header into buffer
|
|
Move.l (A5)+,(A3)+ ; Hard code for speed
|
|
Move.l (A5)+,(A3)+ ; (AssumeEq?)
|
|
Move (A5)+,(A3)+ ; A3 -> buffer after header
|
|
Jsr 2(A4) ; Read in the whole thing (D0=0)
|
|
Move.l D2,A0 ; A0 -> queue element again
|
|
Move EBuffSize(A0),D1 ; D1 = original request size
|
|
Sub D3,D1 ; D1 = total packet size
|
|
Move D1,EDataSize(A0) ; Set in queue element
|
|
Tst D3 ; Check for buffer overflow
|
|
Bpl.s @10 ; Branch if no overflow
|
|
Move #buf2SmallErr,D0 ; Set error
|
|
@10 Bra CompleteReq ; Complete request and return
|
|
|
|
@20 MoveQ #0,D3 ; Indicate no buffer
|
|
Jmp 2(A4) ; Ignore packet and return
|
|
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; MoveBytes - move bytes from card memory to desired place
|
|
;
|
|
; Call:
|
|
; A0 -> current location in card memory
|
|
; A3 -> place to move bytes to
|
|
; D1 = number of bytes left in packet
|
|
; D3 = number of bytes to move
|
|
;
|
|
; Return:
|
|
; A0 adjusted
|
|
; A3 adjusted past bytes moved in
|
|
; D1 adjusted
|
|
; D3 = zero if all could be moved, remainder otherwise
|
|
;___________________________________________________________________________
|
|
|
|
MoveBytes
|
|
|
|
MoveM.l D0/D2/A1/A2,-(SP) ; Save registers
|
|
Move.l OurVarPtr,A2 ; A2 -> our variables
|
|
IF BIT24 THEN
|
|
Exg D0,A3
|
|
And.l AddrMask(A2),D0
|
|
Exg D0,A3 ; 32 bit clean
|
|
ENDIF
|
|
Move.l A3,A1 ; A1 -> where to move to
|
|
MoveQ #0,D0 ; D0 = number of bytes to move
|
|
Move D3,D0 ; Assume we can move all asked for
|
|
Cmp D1,D3 ; Can we move all asked for?
|
|
Bls.s @10 ; Branch if so
|
|
Move D1,D0 ; Else move all we can
|
|
@10 Sub D0,D1 ; Adjust count left to come in
|
|
Sub D0,D3 ; D3 = bytes not moved
|
|
AddA.w D0,A3
|
|
|
|
Move.l D1,-(SP) ; save this one
|
|
Move.l A0,-(SP)
|
|
Move.l D0,-(SP)
|
|
Jsr ([MemMove,A2]) ; call block move routine
|
|
MoveA.l (SP)+,A0
|
|
AddA.l (SP)+,A0 ; adjust pointer
|
|
Move.l (SP)+,D1
|
|
|
|
@30 MoveM.l (SP)+,D0/D2/A1/A2 ; Restore registers
|
|
Rts ; That's it
|
|
;________________________________________________________________________
|
|
;
|
|
; Close - close the ENET driver.
|
|
;
|
|
; Call:
|
|
; A1 -> DCE
|
|
;________________________________________________________________________
|
|
|
|
Close
|
|
; This code is only called if one of the LoopBack tests failed. Closing is
|
|
; not a supported function since there is no way for me to know how many
|
|
; clients are using the driver; ie. AppleTalk using 802.3 and MacTCP using
|
|
; Ethernet. If the Device Manager passed all open calls to the driver a
|
|
; use-count could be implemented and I could truely support Close.
|
|
MoveA.l OurVarPtr, A2 ; A2 -> our variables
|
|
|
|
Bsr MACEHalt ; stop MACE
|
|
|
|
MoveQ #LAPTblSz-1,D2 ; D2 = Index into active protocols list
|
|
@10 Tst.b InUseFlag(A2,D2) ; Active?
|
|
Beq.s @20 ; Branch if not
|
|
Tst.l (Handlers,A2,D2*4) ; Default handler
|
|
Bne.s @20 ; Branch if not
|
|
Bsr AbortAll ; Abort all requests
|
|
@20 DBra D2,@10 ; On to next
|
|
|
|
Lea VBLQEL(A2),A0
|
|
Tst.l vblAddr(A0) ; did we launch ctl call VBL?
|
|
Beq.s @50
|
|
_VRemove ; remove VBL task if so
|
|
@50
|
|
MoveA.L OurVarPtr,A0
|
|
_DisPosPtr ; free our var mem
|
|
|
|
Lea OurVarPtr,A2 ; A2 -> variable pointer
|
|
Clr.l (A2) ; Clear it out (no variables)
|
|
MoveQ #0,D0 ; Indicate no error
|
|
AnRts Rts ; And return
|
|
|
|
;
|
|
; Variable storage
|
|
;
|
|
OurVarPtr DC.l 0 ; Pointer to our variables
|
|
END
|
|
|
|
|
|
|