mirror of
https://github.com/elliotnunn/boot3.git
synced 2024-05-28 15:41:27 +00:00
5b0f0cc134
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
1716 lines
56 KiB
Plaintext
1716 lines
56 KiB
Plaintext
;
|
|
; File: PDMMace.a
|
|
;
|
|
; Contains: routines to support MACE when coupled with a AMIC-style DMA model
|
|
;
|
|
; Written by: Sean Findley, Mark A. Law, Gary Rensberger
|
|
;
|
|
; Copyright: © 1990-1993 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM25> 10/6/93 RC Took out PDM EVT1 support
|
|
; <SM24> 9/20/93 GMR Fixed a bug where we might count a xmit frame twice, if we got
|
|
; an underflow interrupt in the middle of transmission.
|
|
; <SM23> 9/9/93 pdw Changed installation of MACE int to maceVector in
|
|
; DMADispatchGlobals instead of ddMACEÉ.
|
|
; <SMG3> 9/2/93 chp Change MaceVarPtr from DC.L 1 to DC.L 0 so that the MACE
|
|
; variables are initialized to Ònone.Ó
|
|
; <SMG2> 8/30/93 chp InterruptHandlers.a now supports MACE interrupts on PDM.
|
|
; Modified the MACEInterrupt exception handler to run as a
|
|
; subroutine to the system interrupt dispatcher, so deferred tasks
|
|
; can now run following a MACE interrupt. Modified MACE and Enet
|
|
; DMA interrupt routines to save and restore only those registers
|
|
; not saved by the interrupt dispatcher. Modified the install code
|
|
; to install interrupt handlers into the AMIC dispatch table
|
|
; rather than AutoInt3, and to do so directly rather than calling
|
|
; _DMAIntInstall.
|
|
; <SM21> 8/20/93 GMR Added AMIC4 support (don't apply AMIC headPtr hack if on AMIC4).
|
|
; <SM20> 8/4/93 GMR Fixed a bug that caused the xmit routine to count a packet as
|
|
; going out, but which didn't go out because of a bad length.
|
|
; <SM19> 7/1/93 GMR Backed out a couple of the changes in <SM18> which were
|
|
; unnecessary; the branch to the wrong label was the only change
|
|
; needed to fix the problem.
|
|
; <SM18> 7/1/93 pdw Fixed the "Blowed up after Macsbug" bug which was due to not
|
|
; handling MACE Overflow problems correctly which were due to AMIC
|
|
; overflows caused by the deferred task processing of packets
|
|
; which was not happening because Macsbug turns off the Deferred
|
|
; Task Manager which was... It was late one night... Actually we
|
|
; just moved the @done label up one line.
|
|
; <SM17> 6/28/93 GMR Made receive handling use deferred tasks now, instead of
|
|
; processing at level 4.
|
|
; <SM16> 6/10/93 GMR Fixed a couple bugs (found by test tool) in the level 3 Mace
|
|
; handler, and in handling transmit completions.
|
|
; <SM15> 6/8/93 GMR Added support for EVT1. Temporarily fixed privilage violation
|
|
; when running VM; the level 3 handler installation really needs
|
|
; support from Inthandlers.a.
|
|
; <SM14> 6/3/93 GMR Remove debugger on receive overflow.
|
|
; <SM13> 6/2/93 GMR Now, defer transmits until we get a MACE interrupt indicating
|
|
; the previous packet went out.
|
|
; <SM12> 6/2/93 GMR Rewrote the interrupt handlers and cleaned up parts of the code.
|
|
; <SM11> 6/1/93 dwc Fix init code, add code to wait for MACE transmit status valid
|
|
; to work around MACE's not returning it in a timely manner.
|
|
; <SM10> 5/27/93 dwc Added work-around code to wait for AMIC to finish writing a
|
|
; packet into the receive DMA buffer before handling it.
|
|
; <SM9> 5/25/93 dwc Cleaned uo for Alpha. Removed some more debug code and hardware
|
|
; patches. Added simple work around for AMICs' incrementing the
|
|
; head pointer before it has finished writing the packet into the
|
|
; DMA buffer. This is a kluge, but it is the fastest one I
|
|
; tried, and throws away the fewest packets.
|
|
; <SM8> 5/4/93 dwc Added debug code to work around AMIC's returning FF's on the
|
|
; first read. Added test for EVT1/EVT2.
|
|
; <SM7> 4/6/93 dwc Updated for level #4 DMA interrupts.
|
|
; <SM6> 3/24/93 dwc Remove obsolete code and added code to try to recover from
|
|
; lowered interrupt level during packet handling.
|
|
; <SM5> 3/5/93 dwc Removed some more debugging and obsolete code and comments.
|
|
; <SM3> 2/25/93 dwc Enabled receive, removed some debug code and obsolete routines.
|
|
; <SM2> 2/24/93 dwc Cleaned up transmit, disabled receive for PDM D5 ROM build.
|
|
; 11/30/92 dwc Moved INTLockOut, DMALockOut to PDMMaceEqu.a.
|
|
; 11/20/92 dwc Convert to PDM.
|
|
;
|
|
; To Do: Look into AMIC not properly detecting receive overflow (head continues to wrap past
|
|
; the tail without error).
|
|
;
|
|
; Notes: This version supports EVT2 and later machines.
|
|
;
|
|
;
|
|
|
|
|
|
|
|
PRINT OFF
|
|
INCLUDE 'SysEqu.a' ; System definitions
|
|
INCLUDE 'SysErr.a' ; System errors
|
|
INCLUDE 'Traps.a' ; Traps definitions
|
|
INCLUDE 'GestaltEqu.a'
|
|
INCLUDE 'InternalOnlyEqu.a' ; lowmem globals
|
|
INCLUDE 'HardwarePrivateEqu.a'
|
|
INCLUDE 'UniversalEqu.a' ; lowmem global records
|
|
INCLUDE 'ATalkMacros.a' ; Nifty Macros
|
|
INCLUDE 'SysPrivateEqu.a' ; ExpandMem defs
|
|
|
|
; Conditional compile equates
|
|
BUFDEBUG EQU 0
|
|
DEBUG EQU 0
|
|
PROM EQU 0
|
|
Logging EQU 1
|
|
SUPPORTS_OLD_HW EQU 1
|
|
USEDEFERREDTASK 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
|
|
|
|
|
|
|
|
|
|
;_______________________________________
|
|
;
|
|
; Misc definitions
|
|
;_______________________________________
|
|
|
|
OneWdsSz EQU 8 ; single fragment wds size
|
|
INTLockOut EQU $0700 ; SR value to disable ALL interrupts
|
|
DMALockOut EQU $0400 ; SR value to disable AMIC DMA interrupts
|
|
NeedDefer EQU 5 ; bit indicates VM is running
|
|
|
|
MACERevA2 EQU $0941
|
|
MACERevB0 EQU $0940
|
|
|
|
MAX_STAT_PEND EQU 1
|
|
|
|
|
|
MaceVars RECORD 0 ; our variables
|
|
MACEmem DS.l 1 ; ptr to memory block with recv & xmit buffers
|
|
MACEmemSz DS.l 1 ; need size if need to free it
|
|
XmitBuffMem DS.l 1 ; xmit buffer mem
|
|
DMAPacketPtr DS.l 1 ; ptr to active receive packet in DMA buffer
|
|
MACEBase DS.l 1 ; MACE base address
|
|
AMICDMABase DS.l 1 ; AMIC DMA base address
|
|
DTQE DS.b dtQElSize ; Deferred task queue element
|
|
MACEChipID DS.w 1 ; MACE revision
|
|
ALIGN 4
|
|
|
|
; ¥¥¥ parms saved from MaceInit call
|
|
RcvRtn DS.l 1 ; users recv rtn
|
|
RcvParm DS.l 1 ; users recv rtn parm
|
|
XmtDnRtn DS.l 1 ; users xmit completion rtn
|
|
XmtDnParm DS.l 1 ; users xmit completion rtn parm
|
|
MCfg DS.l 1 ; ptr to MACE config record
|
|
Dot3StatPtr DS.l 1 ; ptr to 802.3 statistics counters
|
|
LAPMIBStatPtr DS.l 1 ; ptr to LAP MIB statistics counters
|
|
OurAddrPtr DS.l 1 ; ptr to ethernet address
|
|
MemMove DS.l 1 ; ptr to fast memory move rtn
|
|
; ¥¥¥ end parms
|
|
|
|
DeferFlag ds.b 1 ; bit 0 = deferred task installed.
|
|
XmitPend ds.b 1 ; <> 0 = # xmits pending
|
|
XmitStat ds.b 1 ; <> 0 = # xmit status's pending from mace
|
|
|
|
IF SUPPORTS_OLD_HW THEN
|
|
BoardFlag ds.b 1 ; 00 = AMIC1-3
|
|
; 01 = AMIC4
|
|
ENDIF
|
|
|
|
ALIGN 4
|
|
DMABufStart DS.l 1 ; logical addr of start of DMA recv buffer
|
|
TxBuffPtr0 DS.l 1 ; logical addr of start of DMA xmit buffer0
|
|
TxBuffPtr1 DS.l 1 ; logical addr of start of DMA xmit buffer1
|
|
|
|
XmitRegSet ds.w 1 ; 0 or 1
|
|
ByteCount ds.w 1 ; bytes in current xmit packet
|
|
|
|
COLLCnt DS.l 1 ; recv frames with collision error
|
|
|
|
; Transmit Frame Status Register counters
|
|
XmtStatINV DS.l 1 ; xmit ints with xmit status invalid
|
|
XmtLCOL DS.l 1 ; late collision
|
|
XmtRTRYCnt DS.l 1 ; total number of retries
|
|
|
|
; Interrupt Register counter
|
|
RCVCOCnt DS.l 1 ; *256 to get # collisions on net
|
|
MPCOCnt DS.l 1 ; *256 to get # of missed packets due to
|
|
; RcvOFLO, receiver disabled, or excessive
|
|
; receive frame count (RcvFC)
|
|
|
|
LogAddrFltr DS.b 8 ; Copy of MACE Logical Address Filter
|
|
; bit order 63-56, 55-48, ... 7-0
|
|
LAFHashTbl DS.b 64 ; Tbl of counts of number multicasts addresses
|
|
|
|
RcvBuffer ds.b 6*256 ; Receive buffer (transfered to from DMA buffer)
|
|
|
|
IF Logging THEN
|
|
LogPtr ds.l 1
|
|
LogEndPtr ds.l 1 ; ptr to end of log
|
|
LogStart ds.l 512*4 ; room for 512 log entries
|
|
LogEnd
|
|
ENDIF
|
|
|
|
MaceVarSz EQU * ; End of variables
|
|
ENDR
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
; Receive Buffer template
|
|
; -ensure 1st one is quad-aligned and all the rest will be
|
|
;-----------------------------------------------------------------
|
|
RecvBuff Record 0
|
|
MaceStat DS.b 4 ; Recv'd pkt status from Mace
|
|
DS.b 4 ; Garbage bytes
|
|
Packet DS.b Max_Pkt_Size ; packet data area
|
|
EndR
|
|
|
|
|
|
|
|
|
|
EJECT
|
|
|
|
STRING PASCAL
|
|
MACHINE MC68020
|
|
|
|
MaceData PROC
|
|
ENTRY MaceVarPtr
|
|
MaceVarPtr DC.L 0 ; Contains ptr to my variables
|
|
ENDP
|
|
|
|
|
|
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; ResetMACE - Reset AMIC & MACE FIFOs and disable recv & xmit paths and reset MACE
|
|
;
|
|
; Call: A2 - drvr vars
|
|
;
|
|
; Return: none
|
|
;
|
|
; Destroys: A1,D0,D1
|
|
;
|
|
;________________________________________________________________________
|
|
|
|
ResetMACE PROC EXPORT
|
|
WITH MACERegs,MaceVars
|
|
|
|
; reset & disable MACE -> AMIC receive path
|
|
MoveA.l MACEBase(A2), A0 ; A0-> base address of MACE regs
|
|
MoveA.l AMICDMABase(A2), A1 ; A1-> base address of AMIC regs
|
|
|
|
Move.b #0, MACE_MAC_CNFG(A0) ; Disable MACE recv, xmit, et. al.
|
|
nop
|
|
Move.b MACE_FIFO_CNFG(A0), D0 ; Get current FIFO config
|
|
OrI.b #(1<<RCVFWR), D0 ; Keep current FIFO's watermarks
|
|
Move.b D0, MACE_FIFO_CNFG(A0) ; Reset MACE recv FIFO
|
|
nop
|
|
|
|
Move.b #(1<<DMARST), AMIC_DMA_RECV_CNTL(A1)
|
|
nop ; Allow it to complete
|
|
Move.b #(1<<DMAIF), AMIC_DMA_RECV_CNTL(A1) ; Clear interrupt flag
|
|
nop ; Allow it to complete
|
|
Move.b #(1<<DMARST), AMIC_DMA_XMIT_CNTL(A1) ; Reset xmit chnl
|
|
nop ; Allow it to complete
|
|
Move.b #(1<<DMAIF), AMIC_DMA_XMIT_CNTL(A1) ; Clear interrupt flag
|
|
nop ; Allow it to complete
|
|
|
|
|
|
Move.b MACE_FIFO_CNFG(A0), D0 ; Get current FIFO config
|
|
OrI.b #(1<<XMTFWR), D0 ; Keep current FIFO's watermarks
|
|
Move.b D0, MACE_FIFO_CNFG(A0) ; Reset MACE xmit FIFO
|
|
nop
|
|
; Reset MACE
|
|
Move.b #(1<<MACERESET), MACE_BIU_CNFG(A0) ; reset MACE
|
|
nop
|
|
@wait Move.b MACE_BIU_CNFG(A0), D0
|
|
BTst #MACERESET, D0
|
|
Bne.s @wait ; loop until reset complete
|
|
|
|
Move.b #0, MACE_MAC_CNFG(A0) ; make sure MACE disabled
|
|
nop
|
|
Move.b #MaceIntMask, MACE_INT_MSK(A0) ; Disable all MACE ints.
|
|
nop
|
|
|
|
Rts
|
|
|
|
ENDP
|
|
EJECT
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; FreeMACEMem - free all memory
|
|
;
|
|
; Call: A2 - our globals
|
|
;
|
|
; Return: none
|
|
;
|
|
; Destroys: A0
|
|
;
|
|
;________________________________________________________________________
|
|
|
|
FreeMACEMem PROC
|
|
|
|
IMPORT FreeMemory
|
|
WITH MaceVars
|
|
|
|
Tst.l MaceVarPtr ; Mace var pointer
|
|
Beq.s @57 ; no mem allocated
|
|
|
|
Move.l #0, -(SP) ; size not needed
|
|
Move.l A2, -(SP) ; ptr to mem to free
|
|
Move #0, -(SP) ; no options
|
|
Lea FreeMemory, A0
|
|
Jsr (A0) ; free MACE var memory
|
|
Lea 10(SP), SP ; strip parms
|
|
Lea MaceVarPtr, A0
|
|
Clr.l (A0) ; Clear MaceVarPtr contents
|
|
@57
|
|
Rts
|
|
|
|
ENDWITH
|
|
ENDP
|
|
EJECT
|
|
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; MACEHalt - HALT the MACE, remove interrupt handlers, free all memory
|
|
;
|
|
; Call: none
|
|
;
|
|
; Return: none
|
|
;
|
|
; Destroys: A1,D0,D1
|
|
;
|
|
;________________________________________________________________________
|
|
|
|
MACEHalt PROC EXPORT
|
|
|
|
WITH MACERegs,MaceVars
|
|
|
|
Move.l A2, -(SP) ; save regs
|
|
MoveA.l MaceVarPtr, A2 ; Get ptr to my vars
|
|
|
|
Move SR,-(SP) ; Save interrupt mask level
|
|
OrI #DMALockOut, SR ; Disable DMA ints.
|
|
|
|
Bsr ResetMACE
|
|
|
|
Move.l AMICDMABase(A2), A1 ; Base address of AMIC
|
|
Move.b #(1<<DMAIF), AMIC_DMA_XMIT_CNTL(A1) ; Clear IF & disable xmit DMA
|
|
nop ; Allow it to complete
|
|
Move.b #(1<<DMAIF), AMIC_DMA_RECV_CNTL(A1) ; Clear IF & disable xmit DMA
|
|
nop ; Allow it to complete
|
|
|
|
MoveA.l MACEBase(A2), A3
|
|
Move.b #MaceIntMask, MACE_INT_MSK(A3) ; Disable all MACE interrupts
|
|
nop ; Allow it to complete
|
|
|
|
|
|
OrI #INTLockOut, SR ; Disable ALL ints.
|
|
|
|
IF USEDEFERREDTASK THEN
|
|
bclr.b #0,DeferFlag(A2) ; is Deferred Task installed?
|
|
Beq.s @nodq ; nope
|
|
IF DEBUG THEN
|
|
_Debugger
|
|
ENDIF
|
|
Lea DTQE(A2), A0 ; get ptr to queue entry
|
|
LEA DTQueue, A1 ; get ptr to queue
|
|
_Dequeue ; remove from deferred task queue
|
|
|
|
@nodq
|
|
ENDIF
|
|
|
|
Move (SP)+, SR ; Restore SR
|
|
|
|
; Free MACE buffer and var memory
|
|
; ¥¥¥¥
|
|
; ¥¥¥¥ WARNING: upper layer handlers better be done with packets cause we're
|
|
; ¥¥¥¥ freeing the mem the packets are in!
|
|
; ¥¥¥¥
|
|
Bsr FreeMACEMem ; Free, and unlock if needed, all mem blks
|
|
|
|
Move.l (SP)+, A2 ; restore regs
|
|
Rts
|
|
|
|
ENDP
|
|
EJECT
|
|
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; NormAddr - convert IEEE address to normal format
|
|
;
|
|
; Call: D0 bit-inverted address byte from Address Prom
|
|
;
|
|
; Return: D0 bit-inverted address byte
|
|
;
|
|
; Destroys: D1
|
|
;
|
|
;________________________________________________________________________
|
|
|
|
NormAddr PROC EXPORT
|
|
MoveM.l D2,-(SP)
|
|
Clr.b D1
|
|
MoveQ #7,D2
|
|
@loop
|
|
Lsl.b #1,D1 ; get ready for next bit
|
|
Lsr.b #1,D0 ; get a bit from source
|
|
Bcc.s @lb ; non there
|
|
AddQ.b #1,D1
|
|
@lb
|
|
DBra D2,@loop
|
|
Move.b D1,D0 ; D0=converted value
|
|
MoveM.l (SP)+,D2
|
|
Rts
|
|
|
|
ENDP
|
|
EJECT
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; DoCRC - compute Ethernet CRC on address field
|
|
;
|
|
; Call:
|
|
; D1 = first two bytes of address
|
|
; D3 = last four bytes of address
|
|
;
|
|
; Return:
|
|
; D0 = 6 bit hash into Logical Address Filter
|
|
;
|
|
; Uses: D0,D1
|
|
;
|
|
; The CRC-32 of a sequence of bits views that sequence as the co-efficients of a (long!)
|
|
; polynomial. This polynomial is multiplied by x^32, then divided by the CRC polynomial
|
|
; x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 +x+1.
|
|
; It is the remainder of this division (of degree <= x^31), considered as a 32 bit sequence,
|
|
; that is the CRC. In the calculation, the initial value of the "remainder" is all 1's.
|
|
;
|
|
;________________________________________________________________________
|
|
|
|
CRCPoly EQU %00000100110000010001110110110111
|
|
; Co-efficients after a shift left
|
|
|
|
DoCRC PROC
|
|
Move.l D2, -(SP)
|
|
MoveQ #-1,D2 ; D2 = current value of CRC
|
|
Bsr.s @10 ; Compute over D1, address bits 47-32
|
|
Move.l D3,D1 ; D1 = rest to do
|
|
Swap D1 ; Get high word of D3 into D1
|
|
Bsr.s @10 ; Compute over D1, address bits 31-16
|
|
Swap D1 ; Get low word of D3 into D1
|
|
Bsr.s @10 ; Compute over D1, address bits 15-0
|
|
|
|
And #%111111, D2 ; Get six hash bits in low byte
|
|
|
|
Move D2, D0
|
|
Bsr NormAddr ; D0 = bit inverted hash
|
|
Lsr.b #2, D0 ; Move 6 msb's to 6 lsb's
|
|
Move.l (SP)+, D2
|
|
Rts ; Exit DoCRC
|
|
|
|
;
|
|
; Accumulate the CRC over the low 16 bits of D1 (starting with high byte bit 0!)
|
|
;
|
|
@10 MoveQ #16,D0 ; D0 = no. of bits to do
|
|
Ror #8,D1 ; Do high byte first
|
|
@15 Lsl.L #1,D2 ; Shift CRC, clear low bit, old hi bit in C
|
|
;
|
|
; If (CRC-hi-bit XOR D1-current-bit) = 1, we complement bits specified by the CRC polynomial
|
|
; (this is the equivalent of a subtract operation in the long division process, I think)
|
|
;
|
|
Bcc.s @30 ; Branch if CRC hi bit clear
|
|
Ror #1,D1 ; Shift D1, low bit in C
|
|
Bcs.s @50 ; (1 XOR 1) = 0: don't compl; low bit = 0
|
|
Bra.s @40 ; Go complement
|
|
|
|
@30 Ror #1,D1 ; Shift D1, high bit in C
|
|
Bcc.s @50 ; (0 XOR 0) = 0: don't compl; low bit = 0
|
|
@40 Eor.l #CRCPoly,D2 ; Complement some bits; set low bit
|
|
@50 SubQ #1,D0 ; Decrement count of bits to do
|
|
Bne.s @15 ; Do all 16 bits
|
|
Rts ; That's it if done them all
|
|
|
|
ENDP
|
|
EJECT
|
|
|
|
;________________________________________________________________________
|
|
;
|
|
; WriteLAF - update MACE Logical Address Filter (LAF) from copy in drvr globals
|
|
;
|
|
; Call:
|
|
; A2 -> my variables
|
|
;
|
|
; Return:
|
|
; none
|
|
;
|
|
; Uses:
|
|
; A1, D0
|
|
;
|
|
; The LAF can not be updated while MACE recv is enabled. Disable MACE pkt
|
|
; reception. If frames in MACE Recv FIFO, reset MACE Recv FIFO (possible pkt
|
|
; loss), flush AMIC recv FIFO, and reprime affected DMA Reg. Set. Finally,
|
|
; update the LAF.
|
|
;________________________________________________________________________
|
|
|
|
WriteLAF PROC
|
|
WITH MACERegs,MaceVars
|
|
MoveA.l MACEBase(A2), A1
|
|
|
|
Move.b MACE_MAC_CNFG(A1), -(SP) ; Save current config
|
|
|
|
Move.b #(1<<ADDRCHG), MACE_ADDR_CNFG(A1) ; Set address change bit
|
|
nop
|
|
@wait1 Move.b MACE_ADDR_CNFG(A1), D0 ; wait for MACE to clear it
|
|
BTst #ADDRCHG, D0
|
|
Bne.s @wait1
|
|
|
|
Lea LogAddrFltr(A2), A0 ; A0-> copy of logical address filter
|
|
Move.b #(1<<LOGADDR), MACE_ADDR_CNFG(A1) ; Select logical address
|
|
nop
|
|
MoveQ #7, D0
|
|
@laf Move.b (A0,D0.w), MACE_LOG_ADDR(A1) ; Set appropriate bits in Log. Addr Filter
|
|
nop
|
|
DBra D0, @laf
|
|
|
|
Move.b (SP)+, MACE_MAC_CNFG(A1) ; restore MACE mac config
|
|
nop
|
|
RTS
|
|
|
|
ENDP
|
|
EJECT
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; MaceAddMulti - add a multicast address to the list
|
|
;
|
|
; Call:
|
|
; D1 = first two bytes of address
|
|
; D3 = last four bytes of address
|
|
;
|
|
; Return:
|
|
; none
|
|
;
|
|
; Computes the hash for this multicast address and increments hash count in
|
|
; the Logical Address Filter (LAF) Table. If hash count now = 1, sets
|
|
; appropriate bit in the MACE LAF.
|
|
;___________________________________________________________________________
|
|
|
|
MaceAddMulti PROC EXPORT
|
|
WITH MACERegs,MaceVars
|
|
|
|
Move.l A2, -(SP) ; Save used C regs
|
|
MoveA.l MaceVarPtr, A2 ; Get ptr to my vars
|
|
|
|
Bsr DoCRC ; D0-> 6 bit hash into LAF
|
|
AddQ.b #1, (LAFHashTbl,A2,D0) ; Inc. # of multi's with this hash
|
|
CmpI.b #1, (LAFHashTbl,A2,D0) ; Multiaddr hash bit already in LAF?
|
|
Bhi @bye ; yes, do nothing
|
|
|
|
Lea LogAddrFltr(A2), A0 ; A0-> copy of log. addr. filter
|
|
Cmp.b #31, D0 ; Hash > 31?
|
|
Bhi.s @b63to32 ; yes
|
|
Move.l 4(A0), D1 ; no, get LAF bits 31-0
|
|
BSet.l D0, D1 ; Is this hash bit already set?
|
|
Bne @bye ; yes, nothing to do
|
|
Move.l D1, 4(A0) ; Save modified LAF bits 31-0
|
|
Bra.s @doit
|
|
|
|
@b63to32 Sub.b #32, D0 ; Convert hash for use on LAF bits 63-32
|
|
Move.l (A0), D1 ; Get LAF bits 63-32
|
|
BSet.l D0, D1 ; Is this hash bit already set?
|
|
Bne @bye ; yes, nothing to do
|
|
Move.l D1, (A0) ; Save modified LAF bits 63-32
|
|
|
|
@doit Bsr WriteLAF ; Write the new LAF
|
|
|
|
@bye Move.l (SP)+, A2 ; Restore used C regs
|
|
Rts
|
|
ENDP
|
|
EJECT
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; MaceDelMulti - Delete a multicast address HASH from the LAF
|
|
;
|
|
; Call:
|
|
; D1 = first two bytes of address
|
|
; D3 = last four bytes of address
|
|
;
|
|
; Return:
|
|
; none
|
|
;
|
|
; Computes the hash for this multicast address and decrements the LAF
|
|
; Table hash count for the given Multicast address. If new hash count = 0,
|
|
; clears appropriate bit in MACE LAF.
|
|
; Depends on caller to ensure not called for a multicast's hash that hasn't
|
|
; already been inc'd in LAFHashTbl.
|
|
;___________________________________________________________________________
|
|
|
|
MaceDelMulti PROC EXPORT
|
|
WITH MACERegs,MaceVars
|
|
|
|
Move.l A2, -(SP) ; Save used C regs
|
|
MoveA.l MaceVarPtr, A2 ; Get ptr to my vars
|
|
|
|
Bsr DoCRC ; D0-> 6 bit hash into LAF
|
|
SubQ.b #1, (LAFHashTbl,A2,D0) ; Dec. # of multi's with this hash
|
|
Bne @bye ; Do nothing if hash table cnt non-zero
|
|
|
|
; Clear this bit in LAF since no other
|
|
; multiaddr's hash to this bit
|
|
Lea LogAddrFltr(A2), A0 ; A0-> copy of log. addr. filter
|
|
Cmp.b #31, D0 ; Hash > 31?
|
|
Bhi.s @b63to32 ; yes
|
|
Move.l 4(A0), D1 ; no, get LAF bits 31-0
|
|
BClr.l D0, D1 ; Clear this hash bit
|
|
IF DEBUG THEN
|
|
Beq @huh ; if LAFHashTbl correct, D1 should
|
|
ELSE ; have D0 bit set!
|
|
Beq @bye ; do nothing hash bit already clear!
|
|
ENDIF
|
|
Move.l D1, 4(A0) ; Save modified LAF bits 31-0
|
|
Bra.s @doit
|
|
|
|
@b63to32 Sub.b #32, D0 ; Convert hash for use on LAF bits 63-32
|
|
Move.l (A0), D1 ; Get LAF bits 63-32
|
|
BClr.l D0, D1 ; Clear this hash bit
|
|
IF DEBUG THEN
|
|
Beq @huh ; if LAFHashTbl correct, D1 should
|
|
ELSE ; have D0 bit set!
|
|
Beq @bye ; do nothing hash bit already clear!
|
|
ENDIF
|
|
Move.l D1, (A0) ; Save modified LAF bits 63-32
|
|
|
|
@doit Bsr WriteLAF ; Write the new LAF
|
|
|
|
@bye Move.l (SP)+, A2 ; Restore used C regs
|
|
Rts
|
|
|
|
IF DEBUG THEN
|
|
@huh _Debugger ; nothing to do 'cause hash bit
|
|
Bra.s @bye ; was already clear
|
|
ENDIF
|
|
|
|
ENDP
|
|
EJECT
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; PrimeXmitRS - Prime Reg Set with transmit packet info.
|
|
;
|
|
; Call:
|
|
; 4(SP) - xmit buffer ptr
|
|
; A2 - our vars
|
|
;
|
|
; Return:
|
|
; If xmit register sets are full, return CC==NE; else, CC==EQ.
|
|
; Notes:
|
|
; Called both on normal writes AND write completion (interrupt level 4)
|
|
;___________________________________________________________________________
|
|
|
|
PrimeXmitRS PROC
|
|
IMPORT AddToLog
|
|
|
|
XmitPrm RECORD 4
|
|
XmitPtr DS.l 1 ; Transmit buffer ptr
|
|
ParmSz EQU *
|
|
ENDR
|
|
|
|
WITH MACERegs,MaceVars,LAPMIBStats
|
|
|
|
addq.b #1,XmitStat(a2) ; count this packet as waiting to go out <SM20>
|
|
|
|
move.l AMICDMABase(A2),A3 ; Get AMIC DMA base addr
|
|
|
|
Move.b AMIC_DMA_XMIT_CNTL(A3), D1 ; get xmit status
|
|
BTst #DMARUN, D1 ; DMA enabled already?
|
|
Beq @noten ; No, don't reset it
|
|
|
|
move.b #XMTMSK, AMIC_DMA_XMIT_CNTL(A3) ; Clear IF & DMARUN
|
|
nop
|
|
|
|
|
|
@noten moveq #0, D0
|
|
Move.w ByteCount(A2), D0 ; Get DMA byte count (word)
|
|
move.w XmitRegSet(a2),d1 ; get register set
|
|
lsl #4,d1 ; * 16 for proper reg offset
|
|
|
|
IF Logging THEN
|
|
move.l #'DMA ',-(sp)
|
|
move.l #'SEND',-(sp)
|
|
move.l d0,-(sp)
|
|
move.w XmitPend(a2),(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
|
|
Move.b D0, (AMIC_DMA_XMIT_CNT0L,A3,d1.w) ; Set DMA byte count (LOW)
|
|
nop ; Allow it to complete
|
|
ror.w #8,D0 ; Get HIGH count into lower byte
|
|
Move.b D0, (AMIC_DMA_XMIT_CNT0H,A3,d1.w) ; Set DMA byte count (HIGH)
|
|
nop ; Allow it to complete
|
|
|
|
|
|
@aroundone rol.w #8,D0 ; Get HIGH count back into upper byte
|
|
|
|
Move.l XmitPrm.XmitPtr(SP),a1 ; a1 - xmit buffer ptr
|
|
BTst #0,(A1) ; xmiting a multi/bcast?
|
|
MoveA.l LAPMIBStatPtr(A2), A1
|
|
Bne.s @30
|
|
AddQ.l #1, ifOutUcastPkts(A1) ; inc. non-multi/bcast cntr
|
|
Bra.s @31
|
|
@30 AddQ.l #1, ifOutNUcastPkts(A1) ; inc. multi/bcast cntr
|
|
@31 Add.l D0, ifOutOctets(A1) ; inc. sent octet cntr
|
|
|
|
|
|
Move.b #XMTDMA, AMIC_DMA_XMIT_CNTL(A3) ; Clear IF & enable xmit DMA
|
|
nop ; Allow it to complete
|
|
|
|
MoveQ #0, D0 ; Set CC's
|
|
Rts ; Return
|
|
|
|
ENDP
|
|
EJECT
|
|
|
|
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; MaceXmit - Calls PrimeXmitRS to prime Reg Set with transmit packet info.
|
|
; If xmit register sets are full, put xmit buffer ptr on tail
|
|
; of xmit InUse queue.
|
|
;
|
|
; Call:
|
|
; 4(SP) - WDS ptr
|
|
;
|
|
; Return:
|
|
; D0 = error code; nobuff - temporarily out of xmit buffers
|
|
; eLenErr - sum of data in WDS > max. pkt size
|
|
; noErr - primed reg set with xmit pkt or put pkt
|
|
; on xmit InUse queue
|
|
; Notes:
|
|
; Called both on normal writes AND write completion (interrupt level 4). Due to
|
|
; a hardware problem in Curio (it seems), you cannot DMA another packet into
|
|
; MACE before a pending Xmit status is read, or the transmitter locks up. Hence
|
|
; the code below will return a 'nobuff' error if there is an outstanding status.
|
|
; If the part is fixed, then by modifying a constant, the code will allow 2 or more
|
|
; packets to go out before returning the error.
|
|
;___________________________________________________________________________
|
|
|
|
MaceXmit PROC EXPORT
|
|
|
|
WDSPrm RECORD 4 ; Return address
|
|
WDSPtr DS.l 1 ; Write Data Structure ptr
|
|
ParmSz EQU *
|
|
ENDR
|
|
|
|
IMPORT AddToLog
|
|
WITH MACERegs,MaceVars
|
|
|
|
Move.l WDSPrm.WDSPtr(SP), D2 ; Get WDS ptr
|
|
movem.l A0-A4/D1-D4,-(SP) ; save non-scratch regs
|
|
|
|
MoveA.l MaceVarPtr, A2 ; Get ptr to my vars
|
|
|
|
Move SR,-(SP) ; ¥¥`Save interrupt mask level
|
|
OrI #DMALockOut, SR ; Disable DMA ints.
|
|
|
|
move.l AMICDMABase(A2),a0 ; Get AMIC DMA base addr
|
|
Move.b AMIC_DMA_XMIT_CNTL(A0),d0 ; Which reg set is available?
|
|
andi.b #(1<<SET0)+(1<<SET1),d0 ; We're only interested in these 2
|
|
Bne.s @haveBuff
|
|
|
|
_debugger ; something's really screwed...
|
|
move (sp)+,sr ; ¥¥Restore int. mask level
|
|
movem.l (sp)+,a0-a4/d1-d4 ; Restore C regs
|
|
moveq #nobuff,d0 ; Set no xmit buff available error
|
|
rts ; return to caller
|
|
|
|
@haveBuff
|
|
;------------------------------------------
|
|
; first make sure we don't have any status's pending before sending the packet.
|
|
;------------------------------------------
|
|
|
|
move.b XmitStat(a2),d0 ; see how many packets outstanding
|
|
cmpi.b #MAX_STAT_PEND,d0 ; MACE can only buffer 1 status (bug)
|
|
blo.s @gotit ; 0 outstanding, send another
|
|
|
|
addq.b #1,XmitPend(a2) ; else, count pending packet
|
|
move (sp)+,sr ; ¥¥Restore int. mask level
|
|
movem.l (sp)+,a0-a4/d1-d4 ; Restore C regs
|
|
moveq #nobuff,d0 ; Set no xmit buff available error
|
|
rts ; return to caller
|
|
|
|
|
|
@gotit
|
|
;------------------------------------------
|
|
; Total the length and make sure it's valid
|
|
;------------------------------------------
|
|
move.w #0,XmitRegSet(a2) ;
|
|
move.l TxBuffPtr0(a2),a1 ; assume DMA set 0 for now
|
|
|
|
; addq.w #1,XmitRegSet(a2) ; ¥¥ no need for the 2nd DMA channel due to MACE bug
|
|
; move.l TxBuffPtr1(a2),a1 ; use set 1
|
|
|
|
move.l a1,-(sp) ; ¥¥save buffer pointer for later
|
|
|
|
Clr.w ByteCount(A2) ; init len
|
|
Move.l D2, A4 ; A4-> WDS
|
|
@1
|
|
MoveQ #0,D0
|
|
Move.w (A4), D0 ; get this wds entry length
|
|
Beq.s @2 ; all done
|
|
AddQ.w #6, A4 ; inc to next wds entry length
|
|
Add.w D0,ByteCount(A2) ; sum the length
|
|
Bra.s @1 ; look for more
|
|
@2
|
|
Move.w ByteCount(A2),D1 ; get single fragment length
|
|
Sub.w #EHdrSize,D1 ; Subtract out header bytes
|
|
Cmp.w #EMaxDataSz,D1 ; Check the data's length
|
|
Bls.s @cont ; Branch if ok
|
|
|
|
;------------------------------------------
|
|
; Length error, relink buffer onto free list and return error
|
|
;------------------------------------------
|
|
MoveA.l (SP)+,A1 ; ¥¥Pop buff ptr
|
|
|
|
Move (SP)+,sr ; ¥¥Restore int. mask level
|
|
Movem.l (SP)+,A0-A4/D1-D4 ; Restore C regs
|
|
MoveQ #eLenErr,D0 ; Set length error
|
|
Rts ; Return it
|
|
|
|
|
|
;------------------------------------------
|
|
; Copy WDS data to our Xmit buffer
|
|
;------------------------------------------
|
|
@cont MoveA.l (SP),A1 ;
|
|
MoveA.l D2,A4 ; A4-> WDS
|
|
@3
|
|
Move.w (A4)+,D0 ; last WDS entry?
|
|
Beq.s @4 ; yes, all done
|
|
MoveA.l (A4)+,A0 ; get pointer to the data
|
|
; A0->source, A1->dest, D0=len
|
|
MoveM.l A1/D0,-(SP) ; save buff ptr and len
|
|
Jsr ([MemMove,A2]) ; move the data
|
|
MoveM.l (SP)+,A1/D0
|
|
AddA.l D0, A1 ; update buff ptr
|
|
Bra.s @3 ; look for more
|
|
@4 ; (SP) -> Xmit buffer ptr pushed earlier
|
|
Jsr PrimeXmitRS
|
|
|
|
AddQ #4,sp ; ¥¥Pop buff ptr
|
|
Move (SP)+,SR ; ¥¥Restore int. mask level
|
|
Movem.l (SP)+,A0-A4/D1-D4 ; Restore C regs
|
|
MoveQ #0, D0 ; Set return code & CC's
|
|
Rts ; Return
|
|
|
|
ENDP
|
|
EJECT
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; MaceRecv - Deferred Task Packet receive routine
|
|
;
|
|
; Call: a1 - our variables
|
|
;
|
|
; Return:
|
|
;
|
|
; Destroys: a0-a1,d0-d1
|
|
;
|
|
; Calls:
|
|
; Calls user's handler to receive packet.
|
|
;
|
|
; Notes:
|
|
; Installed via DMAInterrupt, called via Deferred Task Mgr.
|
|
;___________________________________________________________________________
|
|
|
|
MaceRecv PROC
|
|
IMPORT AddToLog,CopyRcvBuffer,InitStatBuf
|
|
WITH MACERegs,MaceVars,RecvBuff
|
|
WITH Dot3StatsEntry,LAPMIBStats
|
|
|
|
|
|
movem.l A2-A6/D2-D4,-(SP) ; save non-scratch regs
|
|
move.l a1,a2 ; get ptr to our globals
|
|
|
|
@ChkRecv movea.l AMICDMABase(a2),a3 ; get ptr to AMIC
|
|
|
|
move.w sr,-(sp) ; ¥¥ save sr
|
|
ori.w #DMALockOut,sr ; ¥ mask out DMA ints
|
|
|
|
;--------------------------------------
|
|
; Here we check for a valid packet in the circular buffer...
|
|
;--------------------------------------
|
|
@rcvPcktLoop
|
|
moveq #0,d0
|
|
move.b AMIC_DMA_RECV_TAIL(A3),D0 ; Are there packets to process? (should be)
|
|
cmp.b AMIC_DMA_RECV_HEAD(A3),D0 ; Get the Head Ptr
|
|
bne @gotData
|
|
|
|
btst.b #6,AMIC_DMA_RECV_CNTL(a3) ; overrun?
|
|
beq @exit
|
|
IF Logging THEN
|
|
move.b AMIC_DMA_RECV_HEAD(A3),d0
|
|
move.l #'McRv',-(sp) ; push string
|
|
move.l #'OVER',-(sp) ; push string
|
|
move.l #'RUN ',-(sp) ; push string
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
@gotData
|
|
tst.l DMAPacketPtr(a2) ; did we re-enter??
|
|
bne @exit ; yes, exit for now
|
|
|
|
|
|
IF Logging THEN
|
|
move.l d0,-(sp)
|
|
swap d0
|
|
move.b AMIC_DMA_RECV_HEAD(A3),d0
|
|
move.l #'DMAr',-(sp) ; push string
|
|
move.l d0,-(sp) ; push tail/head
|
|
|
|
move.l DMABufStart(A2),a0 ; Recv buffer ptr
|
|
clr.w d0
|
|
swap d0
|
|
lsl.w #8,d0
|
|
adda.l d0,a0 ; point to start of packet
|
|
move.l (a0),-(sp) ; push status/length
|
|
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
move.l (sp)+,d0
|
|
ENDIF
|
|
|
|
move.l DMABufStart(A2),a0 ; Recv buffer ptr
|
|
lsl.w #8,d0 ; convert to offset
|
|
add.l d0,a0 ; a0=addr of packet
|
|
IF SUPPORTS_OLD_HW THEN
|
|
tst.b BoardFlag(a2) ; AMIC4?
|
|
bgt.s @skipStat ; yes, don't bother with the hack
|
|
tst.l (a0) ; ¥ has status been updated?
|
|
beq @exit ; ¥ no, not full packet, exit
|
|
@skipStat
|
|
ENDIF
|
|
move.l a0,DMAPacketPtr(a2) ; save ptr, flag we're in use
|
|
|
|
move.w (sp)+,sr ; ¥¥ restore interrupts
|
|
|
|
;--------------------------------------
|
|
; we seem to have a complete packet, get it's status,
|
|
; copy DMA buffer to our receive buffer (if status valid),
|
|
; and call user with data
|
|
;--------------------------------------
|
|
|
|
moveq #0,d1
|
|
move.w (a0),d1 ; Get Status(15-12) & Byte Cnt(11-8,7-0)
|
|
move.w d1,d2 ; want Status later
|
|
lsr.w #8,d2 ; d2.w=00ss
|
|
andi.b #$f0,d2 ; d2.w=00s0
|
|
swap d2 ; d2.l=s000
|
|
move.w 2(a0),d2 ; d2.l=s0cr (Get the Collision & Runt cnts)
|
|
swap d2 ; d2.l=crs0 (Coll,Runt,Stat,Null)
|
|
andi.w #$0fff,d1 ; remove status bits from byte cnt
|
|
|
|
bsr CopyRcvBuffer ; copy the DMA buffer into our receive buffer
|
|
|
|
btst.b #6,AMIC_DMA_RECV_CNTL(a3) ; are we in an overrun condition?
|
|
beq.s @notOverrun
|
|
IF Logging THEN
|
|
move.b AMIC_DMA_RECV_HEAD(A3),d0
|
|
move.l #'McR2',-(sp) ; push string
|
|
move.l #'OVER',-(sp) ; push string
|
|
move.l #'RUN ',-(sp) ; push string
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
move.b #$4a,AMIC_DMA_RECV_CNTL(a3) ; yes, clear the overrun and turn on DMA
|
|
@notOverrun
|
|
|
|
MoveA.l LAPMIBStatPtr(A2),A5 ; pt to LAP stats
|
|
MoveA.l Dot3StatPtr(A2),A6 ; pt to DOT3 stats
|
|
|
|
;-----------------------------------------------------------------
|
|
; Retrieve status bytes from beginning of buffer. Each status byte is present in
|
|
; the high and low bytes of a word. There are 4 status bytes, so there are 8 bytes
|
|
; of status.
|
|
;-----------------------------------------------------------------
|
|
Add.l d1,ifInOctets(a5)
|
|
|
|
Btst #RcvOFLO,d2 ; Overflow Error?
|
|
Beq.s @s1
|
|
AddQ.l #1,dot3StatsInternalMacReceiveErrors(a6)
|
|
Bra.s @s4 ;
|
|
|
|
@s1 AndI.b #(1<<RcvCLSN)+(1<<RcvFRAM)+\
|
|
(1<<RcvFCS),d2 ; Receive Status Error?
|
|
Beq.s @s4 ; Note: only lower status/len byte trashed
|
|
|
|
AddQ.l #1,ifInErrors(a5)
|
|
Btst #RcvFCS,d2 ; FCS Error?
|
|
Beq.s @s2
|
|
AddQ.l #1, dot3StatsFCSErrors(A6)
|
|
@s2 Btst #RcvFRAM, d2 ; Framing Error?
|
|
Beq.s @s3
|
|
AddQ.l #1, dot3StatsAlignmentErrors(A6)
|
|
@s3 Btst #RcvCLSN, d2 ; Collsion Error?
|
|
Beq.s @s4
|
|
AddQ.l #1, COLLCnt(A2) ; Yes
|
|
AddQ.l #1, dot3StatsLateCollisions(A6) ; xmit & recv cntr
|
|
@s4
|
|
|
|
;-----------------------------------------------------------------
|
|
; Call user's receive routine
|
|
;-----------------------------------------------------------------
|
|
move.w sr,-(sp) ; ¥¥ save sr
|
|
movem.l a2-a3/d1-d2,-(sp) ; ¥¥ save non-scratch regs
|
|
lea RcvBuffer(a2),a0 ; get ptr to our receive buffer
|
|
Pea Packet(a0) ; Pass recv packet ptr
|
|
Move.l d2,-(sp) ; pass recv packet status word
|
|
move.l d1,-(sp) ; pass recv packet length
|
|
Move.l RcvParm(a2),-(sp) ; Pass user's rcv rtn parm
|
|
MoveA.l RcvRtn(a2),a0 ; User's rcv rtn
|
|
Jsr (a0) ; Call user's rcv rtn
|
|
Add #RcvParms.ParmsSz,sp ; strip parms
|
|
movem.l (sp)+,a2-a3/d1-d2 ; ¥¥ restore non-scratch regs
|
|
|
|
ori.w #DMALockOut,sr ; ¥ mask interrupts
|
|
clr.l DMAPacketPtr(a2) ; local buffer not in use now
|
|
|
|
;--------------------------------------
|
|
; Now see if length valid by checking error status (bits 4-7)
|
|
; If invalid, we must reset the receiver and receive DMA channels,
|
|
; since the length might be incorrect. If the HeadPtr (hardware bug)
|
|
; didn't move during a packet, we wouldn't have to to this.
|
|
;--------------------------------------
|
|
tst.b d2 ; status bits zero?
|
|
beq.s @rcvPcktLoop ; length correct, check for another packet
|
|
|
|
move.l MACEBase(a2),a1 ; Base address of Mace
|
|
move.b #(1<<ENXMT)+(0<<ENRCV),\
|
|
MACE_MAC_CNFG(a1) ; disable receiver
|
|
nop
|
|
move.b #(1<<DMARST),AMIC_DMA_RECV_CNTL(a3) ; turn off receive DMA
|
|
nop
|
|
move.b #TFW16+RFW64+(1<<RCVFWR),\ ; reset MACE's receive fifo
|
|
MACE_FIFO_CNFG(a1)
|
|
nop
|
|
|
|
IF SUPPORTS_OLD_HW THEN
|
|
tst.b BoardFlag(a2) ; AMIC4?
|
|
bgt.s @skipStatInit ; yes, don't bother with the hack
|
|
bsr InitStatBuf ; init status/length words in DMA buff
|
|
@skipStatInit
|
|
ENDIF
|
|
move.b #RCVMSK, AMIC_DMA_RECV_CNTL(A3) ; Clear IF & enable recv DMA
|
|
move.b #(1<<ENXMT)+(1<<ENRCV),\
|
|
MACE_MAC_CNFG(a1) ; re-enable receiver
|
|
nop
|
|
|
|
@exit bclr #0,DeferFlag(a2) ; deferred task complete
|
|
move.w (sp)+,sr ; ¥¥ restore interrupts
|
|
movem.l (sp)+,d2-d4/a2-a6 ; ¥¥ restore registers
|
|
rts
|
|
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
EJECT
|
|
;___________________________________________________________________________
|
|
;
|
|
; MaceInterrupt - Process interrupts from MACE
|
|
;
|
|
; Calls: none
|
|
;
|
|
; Notes: Mace interrupts at Level 3
|
|
;
|
|
; Primary function is to read the MACE transmit status upon receipt of the
|
|
; Transmit Completion interrupt. Also, reads and processes interrupts for
|
|
; error conditions.
|
|
;___________________________________________________________________________
|
|
|
|
MaceInterrupt PROC
|
|
IMPORT AddToLog
|
|
WITH MACERegs,MaceVars,Dot3StatsEntry,LAPMIBStats
|
|
|
|
MoveA.l MaceVarPtr,A1 ; Get ptr to my vars
|
|
|
|
@more Move.l MACEBase(A1), A0 ; Base address of Mace
|
|
Move.b MACE_INT(A0), D0 ; Get Mace Interrupt Status
|
|
AndI.b #~OurIntsMask, D0 ; Process only the ones we want
|
|
Bne @goOn ; no ints we care about, leave
|
|
rts ; Return from MaceInterrupt
|
|
|
|
@goOn MoveA.l LAPMIBStatPtr(A1), A2
|
|
MoveA.l Dot3StatPtr(A1), A3
|
|
|
|
;--------------------------------------
|
|
; Process Transmit Completion Interrupt
|
|
;--------------------------------------
|
|
BTst #XMTINT, D0 ; Xmit done int?
|
|
Beq @rcvco ; no, check for err int.
|
|
|
|
;--------------------------------------
|
|
; Read Mace Transmit Status
|
|
;--------------------------------------
|
|
MoveQ #0, D1
|
|
Move.b MACE_TX_RETRY_CNT(A0), D1 ; Read Xmit Retry Count
|
|
Add.l D1, XmtRTRYCnt(A1)
|
|
Move.b MACE_TX_FRM_STAT(A0), D1 ; Read Xmit Frame Status
|
|
|
|
tst.b XmitStat(a1) ; make sure there's an outstanding frame <SM24>
|
|
beq.s @skipCnt ; no, don't count it <SM24>
|
|
subq.b #1,XmitStat(a1) ; else, count this frame status as read
|
|
@skipCnt
|
|
IF Logging THEN
|
|
move.l #'MACE',-(sp)
|
|
move.l d0,-(sp) ; log interrupt reg
|
|
move.b d1,1(sp) ; and frame status
|
|
move.l XmitPend(a1),-(sp)
|
|
move.b MACE_FIFO_FRM_CNT(A0),2(sp) ; and frame counts
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
BTst #XMTSV, D1 ; Is status valid?
|
|
Bne.s @10 ; yes, continue
|
|
AddQ.l #1, XmtStatINV(A1)
|
|
Bra @xmit
|
|
|
|
@10 Move.b D1, -(SP) ; save D1
|
|
AndI.b #(1<<UFLO)+(1<<LCOL)+(1<<RTRY), D1
|
|
Beq.s @1
|
|
AddQ.l #1, ifOutErrors(A2)
|
|
@1 Move.b (SP)+, D1 ; restore D1
|
|
beq.s @xmit ; There's no other status
|
|
|
|
BTst #UFLO, D1 ; Underflow?
|
|
Beq.s @2 ; no
|
|
AddQ.l #1, dot3StatsInternalMacTransmitErrors(A3)
|
|
|
|
@2 BTst #LCOL, D1 ; Late Collision?
|
|
Beq.s @3 ; no
|
|
AddQ.l #1, XmtLCOL(A1)
|
|
AddQ.l #1, dot3StatsLateCollisions(A3)
|
|
|
|
@3 BTst #LCAR, D1 ; Loss of Carrier?
|
|
Beq.s @4 ; no
|
|
AddQ.l #1, dot3StatsCarrierSenseErrors(A3)
|
|
|
|
@4 BTst #DEFER, D1 ; deferred?
|
|
Beq.s @5 ; no
|
|
AddQ.l #1, dot3StatsDeferredTransmissions(A3)
|
|
|
|
@5 BTst #RTRY, D1 ; 15 retries?
|
|
Beq.s @6 ; no
|
|
AddQ.l #1, dot3StatsExcessiveCollisions(A3)
|
|
Bra.s @xmit ; Chk err since remaining
|
|
; bits can't be set
|
|
@6 BTst #MORE, D1 ; More than 1 retry?
|
|
Beq.s @7 ; no
|
|
AddQ.l #1, dot3StatsMultipleCollisionFrames(A3)
|
|
Bra.s @xmit ; Chk err since remaining
|
|
; bits can't be set
|
|
@7 BTst #ONE, D1 ; Exactly 1 retry?
|
|
Beq.s @xmit ; no
|
|
AddQ.l #1, dot3StatsSingleCollisionFrames(A3)
|
|
|
|
|
|
@xmit movem.l d0-d1/a1-a3,-(sp)
|
|
move.w sr,-(sp) ; ¥¥
|
|
Move.l XmtDnRtn(a1),d0
|
|
Beq.s @8 ; no xmit completion rtn
|
|
Move.l XmtDnParm(a1),-(sp) ; Push user parm
|
|
MoveA.l d0,a0
|
|
move.b XmitPend(a1),d0 ; pass our 'xmit waiting' flag
|
|
beq.s @7a
|
|
subq.b #1,XmitPend(a1)
|
|
@7a Jsr (a0) ; Call user xmit completion rtn
|
|
addq #4,sp ; Strip parms
|
|
@8 move.w (sp)+,sr ; ¥¥
|
|
movem.l (sp)+,d0-d1/a1-a3
|
|
|
|
|
|
;--------------------------------------
|
|
; Process Error Interrupts
|
|
;--------------------------------------
|
|
@rcvco
|
|
BTst #RCVCO, D0 ; Recv Collision Overflow count interrupt?
|
|
; Indicates RCV coll cntr rolled over from 255->0
|
|
Beq.s @mpci ; no
|
|
AddQ.l #1, RCVCOCnt(A1)
|
|
|
|
@mpci BTst #MPCO, D0 ; Missed packet count interrupt? This int.
|
|
; indicates MPC reg. rolled over from 255->0
|
|
Beq.s @cerr ; no
|
|
AddQ.l #1, MPCOCnt(A1)
|
|
Add.l #256, ifInErrors(A2)
|
|
|
|
|
|
@cerr BTst #CERR, D0 ; Collision error interrupt?
|
|
Beq.s @babl ; no
|
|
AddQ.l #1, dot3StatsSQETestErrors(A3)
|
|
AddQ.l #1, ifOutErrors(A2)
|
|
|
|
@babl BTst #BABL, D0 ; Babble error interrupt?
|
|
Beq.s @chkAgain ; no
|
|
AddQ.l #1, dot3StatsFrameTooLongs(A3)
|
|
AddQ.l #1, ifOutErrors(A2)
|
|
|
|
@chkAgain bra @more
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; Routine: CopyRcvBuffer
|
|
;
|
|
; Inputs: d1 - packet length
|
|
; d2 - packet status
|
|
; a0 - ptr to start of packet in DMA buffer
|
|
; a2 - globals
|
|
; a2 - AMIC base
|
|
; Outputs: RcvBuffer - contains the received packet
|
|
; Destroys: a1,d3
|
|
;
|
|
; Calls:
|
|
;
|
|
; Function: Copyies the packet in DMA buffer to our receive buffer, bumping
|
|
; the tail pointer as we go.
|
|
;___________________________________________________________________________
|
|
CopyRcvBuffer PROC EXPORT
|
|
WITH MACERegs,MaceVars
|
|
|
|
move.l d1,-(sp) ; save length
|
|
tst.b d2 ; check status, is length valid?
|
|
bne.s @copyExit
|
|
|
|
add.w #$00ff+8,d1 ; compute the rounded up length in pages
|
|
andi.w #$ff00,d1
|
|
lsr.w #8,d1 ; # of pages (256 bytes)
|
|
subq.w #1,d1 ; adjust for dbra
|
|
blt.s @copyExit
|
|
|
|
moveq #0,d3
|
|
move.b AMIC_DMA_RECV_TAIL(a3),d3 ; get tail ptr
|
|
move.l DMAPacketPtr(a2),a0 ; get buf ptr
|
|
lea RcvBuffer(a2),a1 ; get ptr to our receive buffer
|
|
|
|
@clrLoop move.l #$0100,d0
|
|
_BlockMove ; copy next page to user buffer
|
|
add.w #$0100,a1 ; point to next page
|
|
clr.l (a0) ; clear out it's length/status ¥¥hardware fix
|
|
add.w #$0100,a0 ; point to next status
|
|
addq.b #1,d3 ; bump tail ptr
|
|
cmpi.b #$c0,d3 ; at end of buffer?
|
|
blo.s @update ; no, continue
|
|
moveq #0,d3 ; yes, reset to starting page
|
|
move.l DMABufStart(a2),a0 ; wrap length/status ptr to start
|
|
@update move.b d3,AMIC_DMA_RECV_TAIL(a3) ; update tail ptr
|
|
nop
|
|
cmp.b AMIC_DMA_RECV_HEAD(a3),d3 ; have we caught up with head (bad length)?
|
|
dbeq d1,@clrLoop ; and repeat for next page
|
|
|
|
@copyExit move.l (sp)+,d1
|
|
rts
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
EJECT
|
|
;___________________________________________________________________________
|
|
;
|
|
; DMAIntHandler - Process DMA Interrupt from AMIC
|
|
;
|
|
; Call: A1 - our variables (reference constant from dispatcher)
|
|
;
|
|
; Regs: A2 - our variables
|
|
; A3 - Receive or Transmit DMA Channel base address
|
|
; D4.B - Register Set offset, 0 or $10
|
|
;
|
|
; Calls: PrimeRecv - reprime a Recv DMA reg set
|
|
; MaceXmitDone - read Xmit status and reprime Xmit DMA regs if needed
|
|
;
|
|
; RePrime Receive and Transmit Register Sets. Install Deferred Task to
|
|
; process Received Packets and Transmit Completions.
|
|
;___________________________________________________________________________
|
|
|
|
DMAIntHandler PROC
|
|
IMPORT AddToLog,InitStatBuf,CopyRcvBuffer
|
|
WITH MACERegs,MaceVars
|
|
|
|
Move.l D4, -(SP) ; Save non-interrupt regs used
|
|
Move.l A1,A2 ; A2 -> our variables
|
|
|
|
;--------------------------------------
|
|
; Check for packet in Receive DMA Channel
|
|
;--------------------------------------
|
|
ChkRecv MoveA.l AMICDMABase(a2),a3
|
|
Move.b AMIC_DMA_RECV_CNTL(a3),d0 ; Get receive status, int pending?
|
|
bpl @ChkXmitDone ; no, check xmit channel
|
|
|
|
btst #6,d0 ; is this an overrun?
|
|
beq.s @notOVRN ; no, continue
|
|
IF Logging THEN
|
|
move.b AMIC_DMA_RECV_HEAD(A3),d0
|
|
move.l #'RECV',-(sp) ; push string
|
|
move.l #'OVER',-(sp) ; push string
|
|
move.l #'RUN ',-(sp) ; push string
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
|
|
IF DEBUG THEN
|
|
_debugger
|
|
ENDIF
|
|
Move.b #$80, AMIC_DMA_RECV_CNTL(A3) ; Clear the interrupt
|
|
bra.s @2
|
|
@notOVRN Move.b #RCVMSK, AMIC_DMA_RECV_CNTL(A3) ; Clear the interrupt and turn on DMA
|
|
@2
|
|
nop
|
|
|
|
IF Logging THEN
|
|
move.b AMIC_DMA_RECV_HEAD(A3),d0
|
|
move.l #'DMAr',-(sp) ; push string
|
|
move.l #'Int ',-(sp) ; push string
|
|
move.l DeferFlag(a2),-(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
|
|
bset #0,DeferFlag(a2) ; we're installing deferred task
|
|
bne.s @ChkXmitDone ; skip if already installed
|
|
|
|
IF USEDEFERREDTASK THEN
|
|
lea DTQE(a2),a0 ; A0->deferred task queue element
|
|
movea.l JDTInstall,a1
|
|
jsr (a1) ; install deferred task
|
|
ELSE
|
|
move.l a2,a1 ; a1 = globals for deferred tasks
|
|
bsr MaceRecv
|
|
ENDIF
|
|
|
|
;---------------------------------------------------------------
|
|
; Check for Transmit Completion Interrupt
|
|
;---------------------------------------------------------------
|
|
@ChkXmitDone
|
|
move.b AMIC_DMA_XMIT_CNTL(a3),d0 ; AMIC xmit control/status
|
|
bpl @doneAMICInt ; exit if no xmit DMA int
|
|
|
|
IF Logging THEN
|
|
move.l #'DMA ',-(sp)
|
|
move.l #'DONE',-(sp)
|
|
move.l d0,-(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
|
|
Move.b #XMTMSK, AMIC_DMA_XMIT_CNTL(A3) ; clear the interrupt
|
|
nop
|
|
|
|
@doneAMICInt
|
|
Move.l (SP)+, D4
|
|
|
|
rts ; Return from DMAInterrupt
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
|
|
|
|
EJECT
|
|
;___________________________________________________________________________
|
|
;
|
|
; MaceInit - Get var and DMA memory, then initialize DMA Register Sets and
|
|
; MACE chip
|
|
;
|
|
; Call: following record on stack:
|
|
;
|
|
; MACEInitParms RECORD 0
|
|
; RecvRtn DS.l 1 ; address of Ethernet receive routine
|
|
; RecvPrms DS.l 1 ; parms to pass @ receive
|
|
; XmitRtn DS.l 1 ; address of Ethernet xmit complete routine
|
|
; XmitPrms DS.l 1 ; parms to pass @ xmit complete
|
|
; MACECfgPtr DS.l 1 ; ptr to MACE config record
|
|
; Dot3NetStats DS.l 1 ; ptr to 802.3 statistics array
|
|
; LAPMIBNetStats DS.l 1 ; ptr to LAP MIB statistics array
|
|
; EnetAddr DS.l 1 ; ptr to ethernet address
|
|
; FastMoveRtn DS.l 1 ; ->proc to move memory FAST
|
|
; IPSize EQU *
|
|
;
|
|
; Return:
|
|
; D0 = openErr (-23) or mFulErr (-41)
|
|
;___________________________________________________________________________
|
|
|
|
MaceInit PROC EXPORT
|
|
|
|
parms RECORD {A6Link}
|
|
LocalSize EQU *
|
|
A6Link DS.l 2 ; link and return address
|
|
initp DS MACEInitParms ; parameters passed to us
|
|
ENDR
|
|
|
|
IMPORT TranslateAddress, GetMemory, FreeMemory, AddToLog, InitStatBuf
|
|
WITH parms,initp,MACERegs,MaceVars
|
|
|
|
Link A6,#LocalSize ; Save A6
|
|
MoveM.l A2-A4/D3-D5,-(SP) ; Save regs
|
|
|
|
Move.l #MaceVarSz, -(SP) ; requested memory size
|
|
Move #0, -(SP) ; do NOT want memory locked,
|
|
; contiguous, and non-cacheable
|
|
Lea GetMemory, A0
|
|
Jsr (A0) ; get memory in D0
|
|
AddQ #6, SP ; pop parms
|
|
Blt @InitError ; bra if CC indicate error
|
|
|
|
Lea MaceVarPtr, A3
|
|
Move.l A0, (A3) ; Save ptr to my vars
|
|
MoveA.l A0, A2
|
|
|
|
|
|
IF SUPPORTS_OLD_HW THEN
|
|
clr.b BoardFlag(a2) ; init to AMIC1-3
|
|
move.w sr,-(sp) ;¥¥
|
|
ori.w #$0700,sr ; mask ints during this
|
|
lea $50f14010,a0
|
|
move.b (a0),d1
|
|
move.b d1,-(sp) ;¥¥ read AMIC, save old value
|
|
btst.l #3,d1 ; check bit 3
|
|
bne.s @amic4 ; if set, must be amic4
|
|
ori.b #(1<<3),d1 ; clear, get set mask
|
|
move.b d1,(a0) ; try setting bit 3
|
|
nop
|
|
btst.b #3,(a0) ; did it set?
|
|
beq.s @hwChkDone ; no, must be AMIC1-3
|
|
@amic4 addq.b #1,BoardFlag(a2) ; yes, 01=AMIC4
|
|
@hwChkDone move.b (sp)+,(a0) ; ¥¥ restore AMIC
|
|
move.w (sp)+,sr ; ¥¥ restore SR
|
|
ENDIF
|
|
|
|
IF Logging THEN
|
|
lea LogStart(a2),a0
|
|
move.l a0,LogPtr(a2)
|
|
lea LogEnd(a2),a0
|
|
move.l a0,LogEndPtr(a2)
|
|
|
|
move.l #'STRT',-(sp)
|
|
move.l #'ENET',-(sp)
|
|
clr.l -(sp)
|
|
bsr AddToLog
|
|
add.w #12,sp
|
|
ENDIF
|
|
|
|
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 the MACE base address
|
|
Move.l DecoderInfo.AMICAddr(A0), AMICDMABase(A2) ; Save the AMIC base address
|
|
|
|
Move.l RecvRtn(A6), RcvRtn(A2) ; save addr of recv rtn
|
|
Move.l RecvPrms(A6), RcvParm(A2) ; save parm for recv rtn
|
|
|
|
Move.l XmitRtn(A6), XmtDnRtn(A2) ; save addr of xmit compl rtn
|
|
Move.l XmitPrms(A6), XmtDnParm(A2) ; save parm for xmit compl rtn
|
|
|
|
Move.l Dot3NetStats(A6), Dot3StatPtr(A2)
|
|
Move.l LAPMIBNetStats(A6), LAPMIBStatPtr(A2)
|
|
|
|
Move.l EnetAddr(A6), OurAddrPtr(A2) ; save ptr to our Ethernet address
|
|
Move.l FastMoveRtn(A6), MemMove(A2) ; save addr of fast mem move rtn
|
|
|
|
|
|
;-------------------------------------------------------------------------------------
|
|
; Get the buffer addresses from the AMIC base address register + offsets
|
|
;-------------------------------------------------------------------------------------
|
|
lea $61000000,a1 ; Get the buffer base address
|
|
Move.l a1,DMABufStart(A2) ; Set Recv buffer pointer
|
|
|
|
adda.l #XMIT_BUFF0,a1 ; D0 = Recv ptr + xmit buff offset
|
|
Move.l a1,TxBuffPtr0(A2) ; Set 1st Xmit buffer pointer
|
|
adda.w #2048,a1
|
|
Move.l a1,TxBuffPtr1(A2) ; Set 2nd Xmit buffer pointer
|
|
|
|
IF SUPPORTS_OLD_HW THEN
|
|
tst.b BoardFlag(a2) ; AMIC4?
|
|
bgt.s @skipStat ; yes, don't bother with the hack
|
|
bsr InitStatBuf ; ¥¥ hack to init status words at each page boundary
|
|
@skipStat
|
|
ENDIF
|
|
;-------------------------------------------------------------------------------------
|
|
; Install MACE Recv DMA channel Deferred Task, called by MACE_RECVhndlr
|
|
;-------------------------------------------------------------------------------------
|
|
Move.w #dtQType, DTQE+qType(A2) ; Set Deferred Task queue type
|
|
Lea MaceRecv,A1
|
|
Move.l A1, DTQE+dtAddr(A2) ; Set address of DT, called by slot int. hndlr.
|
|
Move.l A2, DTQE+dtParm(A2) ; Set variable pointer to MACE vars
|
|
|
|
;-------------------------------------------------------------------------------------
|
|
; MACE Chip initialization
|
|
;-------------------------------------------------------------------------------------
|
|
MoveA.l MACEBase(A2), A0 ; A0-> base address of Mace regs
|
|
|
|
Bsr ResetMACE ; Reset MACE chip and AMIC DMA chnls
|
|
|
|
Move.b #(1<<RTRD), MACE_USER_TEST_REG(A0) ; Disable access to Reserved Test Regs
|
|
Move.b #MaceIntMask, MACE_INT_MSK(A0) ; Disable all ints.
|
|
nop
|
|
Move.b #XMTS64, MACE_BIU_CNFG(A0) ; Xmit start after 64 bytes, Intel Bus Mode
|
|
Move.b #(1<<APADXMT), MACE_TX_FRM_CNTRL(A0) ; ¥¥¥Xmit Control ->
|
|
; Enable Retry, FCS, Auto Padding
|
|
Move.b #$00, MACE_RX_FRM_CNTRL(A0) ; ¥¥¥Recv Control ->
|
|
; Disable Auto Pad Stripping
|
|
; Set up FIFOs' configuration
|
|
Move.b #TFW16+(1<<XMTFWR)+RFW64+(1<<RCVFWR),\ ; ¥¥¥
|
|
MACE_FIFO_CNFG(A0)
|
|
Move.b #0, MACE_PLS_CNFG(A0) ; Set up for normal transmit
|
|
nop
|
|
|
|
Move.b MACE_CHIP_ID_HIGH(A0), D0
|
|
Lsl #8, D0
|
|
Move.b MACE_CHIP_ID_LOW(A0), D0
|
|
Move D0, MACEChipID(A2)
|
|
|
|
|
|
CmpI #MACERevA2, MACEChipID(A2) ;???? temp code to check MACE chip id
|
|
Beq.s @skip1 ; MACE in Rev B0 Curio has new bit in IAC!
|
|
|
|
Move.b #(1<<ADDRCHG), MACE_ADDR_CNFG(A0) ; Set address change bit
|
|
nop ; Allow it to complete
|
|
@wait1 Move.b MACE_ADDR_CNFG(A0), D0 ; wait for MACE to clear it
|
|
Bne.s @wait1
|
|
@skip1
|
|
|
|
|
|
Move.b #(1<<PHYADDR), MACE_ADDR_CNFG(A0) ; Select physical address
|
|
nop ; Allow it to complete
|
|
Lea MACE_PHY_ADDR(A0), A0 ; A0-> Mace Phy Address Reg
|
|
MoveA.l OurAddrPtr(A2), A1 ; A1-> Our node address
|
|
Move.b (A1)+, (A0) ; Move addr byte0 to Mace reg
|
|
nop ; Allow it to complete
|
|
Move.b (A1)+, (A0) ; Move addr byte1 to Mace reg
|
|
nop ; Allow it to complete
|
|
Move.b (A1)+, (A0) ; Move addr byte2 to Mace reg
|
|
nop ; Allow it to complete
|
|
Move.b (A1)+, (A0) ; Move addr byte3 to Mace reg
|
|
nop ; Allow it to complete
|
|
Move.b (A1)+, (A0) ; Move addr byte4 to Mace reg
|
|
nop ; Allow it to complete
|
|
Move.b (A1), (A0) ; Move addr byte5 to Mace reg
|
|
nop ; Allow it to complete
|
|
MoveA.l MACEBase(A2), A0 ; Get back base address of Mace regs
|
|
|
|
CmpI #MACERevA2, MACEChipID(A2) ;???? temp code to check MACE chip id
|
|
Beq.s @skip2 ; MACE in Rev B0 Curio has new bit in IAC!
|
|
Move.b #(1<<ADDRCHG), MACE_ADDR_CNFG(A0) ; Set address change bit
|
|
nop ; Allow it to complete
|
|
@wait2 Move.b MACE_ADDR_CNFG(A0), D0 ; wait for MACE to clear it
|
|
Bne.s @wait2
|
|
@skip2
|
|
|
|
Move.b #(1<<LOGADDR), MACE_ADDR_CNFG(A0) ; Select logical address
|
|
nop ; Allow it to complete
|
|
Lea MACE_LOG_ADDR(A0), A1 ; A1-> Mace Phy Address Reg
|
|
MoveQ #7, D0
|
|
@laf Move.b #0, (A1) ; CLEAR all bits in Log Addr Filter
|
|
nop ; Allow it to complete
|
|
DBra D0, @laf
|
|
|
|
|
|
MoveA.l AMICDMABase(A2), A3 ; Get the AMIC base address
|
|
Move.b #(1<<DMAIF), AMIC_DMA_RECV_CNTL(A3) ; Clear recv DMA IF, disable DMA
|
|
nop ; Allow it to complete
|
|
|
|
|
|
; Install MACE Recv DMA channel Deferred Task, called by MACE_RECVhndlr
|
|
Move.w #dtQType, DTQE+qType(A2) ; Set Deferred Task queue type
|
|
Lea MaceRecv, A1
|
|
Move.l A1, DTQE+dtAddr(A2) ; Set address of DT, called by slot int. hndlr.
|
|
Move.l A2, DTQE+dtParm(A2) ; Set variable pointer to MACE vars
|
|
|
|
|
|
; Initialize Recv & Xmit DMA Channel Control Registers
|
|
MoveA.l AMICDMABase(A2), A3 ; <!>Get the AMIC base address
|
|
Move.b #XMTMSK, AMIC_DMA_XMIT_CNTL(A3) ; Clear IF to be safe
|
|
nop ; Allow it to complete
|
|
Move.b #RCVMSK, AMIC_DMA_RECV_CNTL(A3) ; Clear IF & enable recv DMA
|
|
nop ; Allow it to complete
|
|
|
|
; Be sure the Tail Pointer starts out a 0
|
|
Move.b #0, AMIC_DMA_RECV_TAIL(A3) ; Start at the beginning
|
|
nop ; Allow it to complete
|
|
|
|
;------------------------------------------------------------
|
|
; Install Enet interrupt handlers
|
|
;------------------------------------------------------------
|
|
|
|
with ExpandMemRec, DMADispGlobals
|
|
|
|
movea.l ([ExpandMem],emDMADispatchGlobals), A0
|
|
|
|
; Install MACE (level 3) interrupt handler
|
|
|
|
lea MaceInterrupt, A1
|
|
move.l A1, maceVector(A0) ; register the handler in its designated entry
|
|
|
|
; Install AMIC DMA (level 4) interrupt handlers
|
|
|
|
lea DMAIntHandler, A1
|
|
moveq #hwAmicETX, D0
|
|
move.l A1, ddVector0(A0,D0.l*8) ; register transmit DMA handler
|
|
move.l A2, ddRefCon0(A0,D0.l*8) ; register globals pointer as reference constant
|
|
|
|
moveq #hwAmicERX, D0
|
|
move.l A1, ddVector0(A0,D0.l*8) ; register receive DMA handler
|
|
move.l A2, ddRefCon0(A0,D0.l*8) ; register globals pointer as reference constant
|
|
|
|
endwith
|
|
|
|
;------------------------------------------------------------
|
|
; Enable MACE
|
|
;------------------------------------------------------------
|
|
Move.l MACEBase(A2), A0 ; Base address of Mace
|
|
Move.b #(1<<ENXMT)+(1<<ENRCV),\
|
|
MACE_MAC_CNFG(A0) ; Enable xmit and recv
|
|
nop
|
|
Move.b #OurIntsMask, MACE_INT_MSK(A0) ; Enable ints. we care about
|
|
nop
|
|
|
|
MoveQ #0, D0
|
|
Bra.s @60
|
|
|
|
;------------------------------------------------------------
|
|
; Init error - clear out variable pointer for next try
|
|
;------------------------------------------------------------
|
|
@InitError
|
|
Move D0,D3 ; Save error code
|
|
Bsr FreeMACEMem ; Free, and unlock if needed, all mem blks
|
|
|
|
Move D3,D0
|
|
CmpI #-1,D0 ; Translate generic error
|
|
Bne.s @60
|
|
MoveQ #openErr,D0
|
|
@60
|
|
Tst D0
|
|
MoveM.l (SP)+, A2-A4/D3-D5 ; Restore regs
|
|
Unlk A6
|
|
Rts ; Return with error
|
|
|
|
ENDP
|
|
|
|
|
|
|
|
;___________________________________________________________________________
|
|
;
|
|
; Fuctions: InitStatBuf
|
|
; Inputs: a2 - ptr to globals
|
|
; Destroys: d0,a0
|
|
; Return:
|
|
;___________________________________________________________________________
|
|
|
|
InitStatBuf PROC EXPORT
|
|
IF SUPPORTS_OLD_HW THEN
|
|
WITH MaceVars
|
|
|
|
Move.l DMABufStart(a2),a0 ; Set Recv buffer pointer
|
|
move.w #$c0-1,d0
|
|
@clrLp clr.l (a0) ; clear length/status ¥¥hardware fix
|
|
add.w #$0100,a0 ; point to next possible status field
|
|
dbra d0,@clrLp
|
|
rts
|
|
ENDIF
|
|
ENDP
|
|
|
|
|
|
|
|
|
|
EJECT
|
|
IF Logging THEN
|
|
;___________________________________________________________________________
|
|
;
|
|
; Fuctions: AddToLog
|
|
; Inputs: a2 - ptr to globals
|
|
; 4-16(sp) - params to log
|
|
; Return:
|
|
;___________________________________________________________________________
|
|
|
|
AddToLog PROC EXPORT
|
|
|
|
WITH MaceVars
|
|
|
|
movem.l a0-a1,-(sp) ; save regs
|
|
move.w sr,-(sp)
|
|
ori.w #$0700,sr
|
|
Lea MaceVarPtr, a1
|
|
move.l (a1),a1
|
|
move.l LogPtr(a1),a0 ; get current ptr into log buffer
|
|
move.l 22(sp),(a0)+ ; log user data
|
|
move.l 18(sp),(a0)+
|
|
move.l 14(sp),(a0)+
|
|
move.l Ticks,-(sp) ; and time stamp
|
|
move.w 4(sp),(sp) ; and saved SR
|
|
move.l (sp)+,(a0)+ ; stuff them
|
|
cmpa.l LogEndPtr(a1),a0 ; are we at end?
|
|
blo.s @ok
|
|
lea LogStart(a1),a0
|
|
@ok move.l a0,LogPtr(a1) ; update log ptr
|
|
move.w (sp)+,sr
|
|
movem.l (sp)+,a0-a1
|
|
rts
|
|
|
|
ENDP
|
|
ENDIF
|
|
END
|