sys7.1-doc-wip/Libs/InterfaceSrcs/nAppleTalk.a
2019-07-27 22:37:48 +08:00

728 lines
22 KiB
Plaintext

;
; File: nAppleTalk.a
;
; Copyright: © 1986-1992 by Apple Computer, Inc. All rights reserved.
;
; This file is used in these builds: ROM System
;
; Change History (most recent first):
;
; <SM2> 10/28/92 SWC Changed INCLUDEs to a LOAD of StandardEqu.d.
; <10> 6/27/91 JL Fixing GetLocalZones and GetZoneList calls. There was a residule
; line of code left in from an old implementation which had the
; potential to be a random stomper bug. The line was MOVE.W
; #zipGetZoneList,xppSubCode(A0) where A0 hasn't been set up yet.
; <9> 1/19/91 mbs (jg) Add ATEvent and ATPreflightEvent glue. Remove
; CancelAtalkClosePrep; nobody uses it. Change name of
; ATPKillAllGetReq to match inside Mac volume 6.
; <8> 1/7/91 JH (JDR) really JDR on JH's machine, put CancelAtalkClosePrep in
; here since the glue is not using the private AppleTalk
; interfaces. I'm only hacking this definition in for the moment
; because all of the AppleTalk interfaces need to be corrected.
; This is a temporary measure to make the build work.
; <7> 11/12/90 JL Fixing GetZone calls because A0 wasn't set up properly.
; <6> 10/16/90 JL Fixing the GetZone calls: didn't have the iorefnum
; <5> 10/16/90 JL Writing GetZone calls.
; <4> 10/16/90 JL Aligning LAPDispatch to correct word boundry
; <3> 10/1/90 JAL allowed new Phase II AppleTalk to build. Changed back from
; short branches (out of range).
; <2> 9/27/90 dba check in new version that has AppleTalk phase II glue (got from
; Jim Lord)
;
; *** MPW 3.1 ***
; 7 Dec 89 JAL Removed old rom (64K) code.
; Removed from: OpenXPP
; *** MPW 3.2 ***
; 16 Jul 90 JAL Added Phase II glue.
;
STRING ASIS
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'AppleTalk.a'
INCLUDE 'LAPEqu.a'
PRINT ON
nATPasCalls PROC EXPORT
EXPORT OpenXPP, ASPOpenSession, ASPCloseSession, ASPAbortOS
EXPORT ASPGetParms, ASPCloseAll, ASPUserWrite, ASPUserCommand
EXPORT ASPGetStatus, AFPCommand
EXPORT PAttachPH,PDetachPH,PWriteLAP
EXPORT POpenSkt,PCloseSkt,PWriteDDP
EXPORT PRegisterName,PLookupName,PConfirmName,PRemoveName
EXPORT POpenATPSkt,PCloseATPSkt,PSendRequest,PGetRequest
EXPORT PSendResponse,PAddResponse,PRelTCB,PRelRspCB
EXPORT PSetSelfSend,PNSendRequest,PKillSendReq,PKillGetReq,PKillNBP
EXPORT GetLocalZones, GetZoneList, GetMyZone
EXPORT PGetAppleTalkInfo, PATalkClosePrep
EXPORT ATPKillAllGetReq, LAPAddATQ, LAPRmvATQ
;-------------------------------------------------------------------------------
;
; All calls use D0-D1, A0-A1 and do not preserve results
;
; FUNCTION OpenXPP(VAR XPPRefnum: INTEGER): OSErr;
;
xppTfRNum EQU -(xppUnitNum+1)
OpenXPP
; XPP driver not open. Make an _Open call to it. If using a 128K ROM
; machine and the driver is already open, we will make another Open call to
; it just so we get the correct driver refNum.
;
@10 SUB #ioQElSize,SP ; allocate temporary param block.
MOVE.L SP,A0 ; A0 -> param block.
LEA XPPName, A1 ; A1 -> XPP (ASP/AFP) driver name.
MOVE.L A1,ioFileName(A0) ; driver name into param block.
CLR.B ioPermssn(A0) ; clear permissions byte
_Open
MOVE ioRefNum(A0),D1 ; D1 = driver refNum (may be invalid if error)
ADD #ioQElSize,SP ; deallocate temp param block.
@90 MOVE.L (SP)+,A0 ; get return address
MOVE.L (SP)+,A1 ; get VAR pointer.
MOVE.W D1,(A1) ; save driver refNum in program memory.
MOVE.W D0,(SP) ; save OSErr (space reserved previously)
JMP (A0) ; return to caller
; FUNCTION ASPOpenSession(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION ASPCloseSession(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION ASPAbortOS(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION ASPGetParms(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION ASPCloseAll(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION ASPUserWrite(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION ASPUserCommand(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION ASPGetStatus(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION AFPCommand(xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
; FUNCTION PAttachPH(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION PDetachPH(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION PWriteLAP(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION POpenSkt(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION PCloseSkt(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION PWriteDDP(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION PRegisterName(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION PLookupName(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION PConfirmName(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION PRemoveName(thePBptr:mppPBptr; async: BOOLEAN): OSErr;
; FUNCTION POpenATPSkt(thePBptr:atpPBptr; async: BOOLEAN): OSErr;
; FUNCTION PCloseATPSkt(thePBptr:atpPBptr; async: BOOLEAN): OSErr;
; FUNCTION PSendRequest(thePBptr:atpPBptr; async: BOOLEAN): OSErr;
; FUNCTION PGetRequest(thePBptr:atpPBptr; async: BOOLEAN): OSErr;
; FUNCTION PSendResponse(thePBptr:atpPBptr; async: BOOLEAN): OSErr;
; FUNCTION PAddResponse(thePBptr:atpPBptr; async: BOOLEAN): OSErr;
; FUNCTION PRelTCB(thePBptr:atpPBptr; async: BOOLEAN): OSErr;
; FUNCTION PRelRspCB(thePBptr:atpPBptr; async: BOOLEAN): OSErr;
; FUNCTION PSetSelfSend(thePBptr:mppPBptr;asyncflag:BOOLEAN): OSErr;
; FUNCTION PNSendRequest(thePBptr:atpPBptr;asyncflag:BOOLEAN): OSErr;
; FUNCTION PKillSendReq(thePBptr:atpPBptr;asyncflag:BOOLEAN): OSErr;
; FUNCTION PKillGetReq(thePBptr:atpPBptr;asyncflag:BOOLEAN): OSErr;
; FUNCTION PKillNBP(thePBptr:mppPBptr;asyncflag:BOOLEAN): OSErr;
; FUNCTION GetLocalZones(thePBptr: XPPParmBlkPtr;async: BOOLEAN): OSErr;
; FUNCTION GetZoneList(thePBptr: XPPParmBlkPtr;async: BOOLEAN): OSErr;
; FUNCTION GetMyZone(thePBptr: XPPParmBlkPtr;async: BOOLEAN): OSErr;
; FUNCTION PGetAppleTalkInfo(thePBptr: MPPPBPtr;async: BOOLEAN): OSErr;
; FUNCTION PATalkClosePrep(thePBptr: MPPPBPtr;async: BOOLEAN): OSErr;
; FUNCTION ATPKillAllGetReq(thePBptr: ATPPBPtr;async: BOOLEAN): OSErr;
; FUNCTION LAPAddATQ(theATQEntry: ATQEntryPtr): OSErr;
; FUNCTION LAPRmvATQ(theATQEntry: ATQEntryPtr): OSErr;
;-------------------- .MPP Calls ----------------------
LAPAddATQ
MOVE.W #LAddAEQ,D0
BRA LAPDispatch
LAPRmvATQ
MOVE.W #LRmvAEQ,D0
BRA LAPDispatch
LAPGetATQ
MOVE.W #LGetAEQ,D0
BRA LAPDispatch
PAttachPH
MOVE.W #AttachPH,D0
BRA MPPCtlCall
PDetachPH
MOVE.W #DetachPH,D0
BRA MPPCtlCall
PWriteLAP
MOVE.W #WriteLAP,D0
BRA MPPCtlCall
POpenSkt
MOVE.W #OpenSkt,D0
BRA MPPCtlCall
PCloseSkt
MOVE.W #CloseSkt,D0
BRA MPPCtlCall
PWriteDDP
MOVE.W #WriteDDP,D0
BRA MPPCtlCall
PRegisterName
MOVE.W #RegisterName,D0
BRA.S MPPCtlCall
PLookupName
MOVE.W #LookupName,D0
BRA.s MPPCtlCall
PConfirmName
MOVE.W #ConfirmName,D0
BRA.s MPPCtlCall
PRemoveName
MOVE.W #RemoveName,D0
BRA.S MPPCtlCall
PSetSelfSend
MOVE.W #SetSelfSend,D0
BRA.S MPPCtlCall
PKillNBP
MOVE.W #KillNBP,D0
BRA.S MPPCtlCall
PGetAppleTalkInfo
MOVE.W #GetATalkInfo,D0
BRA.S MPPCtlCall
PATalkClosePrep
MOVE.W #ATalkClosePrep,D0
BRA.S MPPCtlCall
;-------------------- .ATP Calls ----------------------
POpenATPSkt
MOVE.W #OpenATPSkt,D0
BRA.s ATPCtlCall
PCloseATPSkt
MOVE.W #CloseATPSkt,D0
BRA.S ATPCtlCall
PSendRequest
MOVE.W #SendRequest,D0
BRA.S ATPCtlCall
PGetRequest
MOVE.W #GetRequest,D0
BRA.S ATPCtlCall
PSendResponse
MOVE.W #SendResponse,D0
BRA.S ATPCtlCall
PAddResponse
MOVE.W #AddResponse,D0
BRA.S ATPCtlCall
PRelTCB
MOVE.W #RelTCB,D0
BRA.S ATPCtlCall
PRelRspCB
MOVE.W #RelRspCB,D0
BRA.S ATPCtlCall
PNSendRequest
MOVE.W #NSendRequest,D0
BRA.S ATPCtlCall
PKillSendReq
MOVE.W #KillSendReq,D0
BRA.S ATPCtlCall
PKillGetReq
MOVE.W #KillGetReq,D0
BRA.S ATPCtlCall
ATPKillAllGetReq
MOVE.W #KillAllGetReq,D0
ATPCtlCall
MOVEA.L 6(SP),A0 ;need ptr to param block
MOVE.W #-(atpUnitNum+1),ioRefNum(A0)
BRA.S CtlCall
MPPCtlCall
MOVEA.L 6(SP),A0 ;need ptr to param block
MOVE.W #-(mppUnitNum+1),ioRefNum(A0)
BRA.S CtlCall
;-------------------- .XPP Calls ----------------------
ASPOpenSession
MOVE.W #OpenSess,D0
BRA.S CtlCall
ASPCloseSession
MOVE.W #CloseSess,D0
BRA.S CtlCall
ASPAbortOS
MOVE.W #AbortOS,D0
BRA.S CtlCall
ASPGetParms
MOVE.W #GetParms,D0
BRA.S CtlCall
ASPCloseAll
MOVE.W #CloseAll,D0
BRA.S CtlCall
ASPUserWrite
MOVE.W #UserWrite,D0
BRA.S CtlCall
ASPUserCommand
MOVE.W #UserCommand,D0
BRA.S CtlCall
ASPGetStatus
MOVE.W #GetStatus,D0
BRA.S CtlCall
AFPCommand
MOVE.W #AFPCall,D0
BRA.S CtlCall
GetLocalZones
MOVE.W #xCall,D0
MOVE.W #zipGetLocalZones,D2
BRA.S GZCtlCall
GetZoneList
MOVE.W #xCall,D0
MOVE.W #zipGetZoneList,D2
BRA.S GZCtlCall
GetMyZone
MOVE.W #xCall,D0
MOVE.W #zipGetMyZone,D2
BRA.S GZCtlCall
CtlCall
Move.L (SP)+,A1 ;return address (Reg call preserves A1)
Move.B (SP)+,D1 ;Get ASync flag.
Move.L (SP)+,A0 ;get param pointer.
MOVE.W D0,CSCode(A0) ;csCode in param block to do right call.
TST.B D1 ;test ASync flag.
BNE.S @1
_Control ;tell OS to do it Synchronously
BrA.S @2
@1 _Control ,ASYNC ;Tell OS to do it Asynchronously
@2 Move.W D0,(SP) ;set function result
Jmp (A1) ;return to caller
GZCtlCall
Move.L (SP)+,A1 ;return address (Reg call preserves A1)
Move.B (SP)+,D1 ;Get ASync flag.
Move.L (SP)+,A0 ;get param pointer.
MOVE.W D2,xppSubCode(A0)
MOVE.W #-(xppUnitNum+1),ioRefNum(A0)
MOVE.W D0,CSCode(A0) ;csCode in param block to do right call.
TST.B D1 ;test ASync flag.
BNE.S @1
_Control ;tell OS to do it Synchronously
BrA.S @2
@1 _Control ,ASYNC ;Tell OS to do it Asynchronously
@2 Move.W D0,(SP) ;set function result
Jmp (A1) ;return to caller
XPPName DC.B 4 ; length of string.
DC.B '.XPP' ; driver name.
ALIGN 2
; Dispatch for new LAP Calls ATalk Phase II
LAPDispatch
MOVE.L 4(SP),A0
MOVE.L LAPMgrPtr,A1
MOVE.L (SP)+,(SP)
JSR LAPMgrCall(A1)
MOVE.L (SP)+,A0
MOVE.W D0,-(SP)
JMP (A0)
ENDPROC
; PROCEDURE BuildLAPwds(wdsptr,dataptr:Ptr;desthost,prototype,framelen:INTEGER);
; Fills in the dest., proto type, and length fields of an ALAP frame at dataptr and
; creates an appropriate SINGLE FRAME wds at wdsptr. The Length field is the length of the
; data portion of the ALAP frame. Note only the LSB 8 bits of desthost,prototype are used.
BuildLAPwds PROC EXPORT
MOVEM.L A0/A1/D0/D1,-(SP) ;save regs.
MOVE.W 20(SP),D0 ;D0=framlen
MOVEM.L 22(SP),D1/A0/A1 ;D1(H)=prototype, D1(L)=desthost
;(A0)->data, (A1)->wds
MOVE.B D1,(A0)+ ;set dest host
CLR.B (A0)+
SWAP D1
MOVE.B D1,(A0)+ ;set prototype
ADDQ.W #2,D0 ;adjust for length field
ROR.W #8,D0 ;access msb
MOVE.B D0,(A0)+ ;insert length in frame
ROR.W #8,D0 ;access lsb
MOVE.B D0,(A0)
MOVE.W D0,(A1) ;insert length in wds
ADDQ.W #lapHdSz,(A1)+ ;adjust for length and header fields
MOVE.L 26(SP),(A1)+ ;insert frame ptr
CLR.W (A1) ;mark end of wds
MOVEM.L (SP)+,A0/A1/D0/D1 ;restore regs.
MOVE.L (SP),14(SP) ;fix return addr.
ADDA.L #14,SP ;adjust stack ptr
RTS
ENDPROC
; PROCEDURE BuildDDPwds(wdsptr,headerptr,dataptr:Ptr;
; destaddress:AddrBlock,DDPtype,datalen:INTEGER)
; Builds a DDP write data structure using the supplied parameters. A single data block
; is assumed. NOTE: The headerptr points to a block of at least 17 bytes and the 1st byte
; is NOT used as DDP write likes this structure to begin on an odd address.
; Note only the LSB 8 bits of destnode,destsocket,DDPtype are used.
BuildDDPwds PROC EXPORT
MOVEM.L D1-D2/A0-A2,-(SP)
MOVEM.L 24(SP),D1-D2/A0-A2 ;D1(H)=datalen,D1(L)=DDPType
;D2(H)=destnet,D2(L)=destnode/destskt
;A0->data,A1->header,A2->wds
PEA 1(A1)
MOVE.L (SP)+,2(A2) ;set 1st ptr in wds
MOVE.L A0,WDSEntrySz+2(A2) ;set data ptr in wds
CLR.W WDSEntrySz*2(A2) ;set end of wds
SWAP D2
MOVE.W D2,1+lapHdSz+ddpDstNet(A1) ;set dest net number
SWAP D2
MOVE.B D2,1+lapHdSz+ddpDstSkt(A1) ;set dest socket
ASR.W #8,D2
MOVE.B D2,1+lapHdSz+ddpDstNode(A1) ;set dest node
MOVE.B D1,1+lapHdSz+ddpType(A1) ;set DDP type
SWAP D1
MOVE.W D1,WDSEntrySz(A2) ;set data len in wds
MOVEM.L (SP)+,D1-D2/A0-A2
MOVE.L (SP),20(SP) ;adj. rtn addr
ADDA.L #20,SP ;strip parms
RTS
ENDPROC
; PROCEDURE NBPSetEntity(Buffer:Ptr;NBPObject,NBPType,NBPZone:STRING[32])
; Concatenates the strings Object,Type, & Zone in Buffer
NBPSetEntity PROC EXPORT
MOVEM.L A0/A1/D0,-(SP)
MOVEQ #28,D0
BSR.S MoveAstring ;move the Object
MOVE.W #24,D0
BSR.S MoveAstring ;move the Type
MOVE.W #20,D0
BSR.S MoveAstring ;move the Zone
MOVEM.L (SP)+,A0/A1/D0
MOVE.L (SP),16(SP)
ADDA.L #16,SP
RTS
MoveAstring
MOVEA.L (SP,D0.W),A0 ;get source string addr
CLR.L D0
MOVE.B (A0),D0 ;setup len and adjust source addr
ADDQ.L #1,D0 ;adj for str len byte
MOVEA.L 32(SP),A1 ;setup dest addr
ADD.L D0,32(SP) ;update dest addr
_BlockMove
RTS
ENDPROC
; PROCEDURE NBPSetNTE( NTEptr:Ptr;NBPObject,NBPType,NBPZone:STRING[32];Socket:INTEGER);
; Builds an Names Table Entry using the parms. Calls NBPSetEntity to fill in the strings.
; This clears the next entry pointer in the NTE. Only LSB 8 bits of Socket are used.
NBPSetNTE PROC EXPORT
MOVEM.L A0-A3/D0,-(SP)
MOVE.W 24(SP),D0 ;D0=Socket
MOVEM.L 26(SP),A0-A3 ;A0->Zone,A1->Type,A2->Object,A3->NTE
CLR.L (A3)+ ;clear next ptr
MOVE.B D0,TupleSkt(A3) ;set socket
PEA TupleName(A3) ;set Buffer ptr
PEA (A2) ;Object
PEA (A1) ;Type
PEA (A0) ;Zone
JSR NBPSetEntity ;fill in the strings
MOVEM.L (SP)+,A0-A3/D0
MOVE.L (SP),18(SP)
ADDA.L #18,SP
RTS
ENDPROC
; FUNCTION GetBridgeAddress:INTEGER;
; Returns Abridge node number.
GetBridgeAddress PROC EXPORT
MOVE.L A0,-(SP)
CLR.W 8(SP)
MOVE.L ABusVars,D0 ;D0->AbusVars
CMPI.L #$FFFFFFFF,D0 ;no bridge if <= 0
BEQ.S @5
TST.L D0
BEQ.S @5
MOVEA.L D0,A0 ;A0->AbufVars
MOVE.B SysABridge(A0),9(SP) ;set bridge
@5 MOVE.L (SP)+,A0
RTS
ENDPROC
; FUNTION BuildBDS(BuffPtr,BDSptr:Ptr;BuffSize:INTEGER;):INTEGER;
; Builds a response BDS using a single buffer pointer and size. The BDS elements
; are used up until the BuffSize is expired.
BuildBDS PROC EXPORT
MOVEM.L A0-A1/D0-D2,-(SP)
MOVE.W 24(SP),D0 ;D0=BuffSize
MOVEM.L 26(SP),A0-A1 ;A0->BDS,A1->Buff
MOVEQ #7,D2 ;D2=#BDSelements (base zero)
CLR.W 34(SP) ;init function rslt
Do1element
TST.W D0
BEQ.S @1
ADDQ.W #1,34(SP) ;inc. function rslt
@1
MOVE.W #atpMaxData,-(SP) ;init size
CMPI.W #atpMaxData,D0
BGE.S @5 ;use max. size
MOVE.W D0,(SP) ;partial segment
@5 MOVE.W (SP),BDSBuffSz(A0) ;set size
MOVE.L A1,BDSBuffAdr(A0) ;set address
CLR.W BDSDataSz(A0) ;clear data size
ADDA.W (SP)+,A1 ;bump BuffPtr
LEA BDSEntrySz(A0),A0 ;bump BDSptr
SUBI.W #atpMaxData,D0 ;adjust size
BLE.S @15
DBRA D2,Do1element
@15 MOVEM.L (SP)+,A0-A1/D0-D2
MOVE.L (SP),10(SP)
ADDA.L #10,SP
RTS
ENDPROC
; FUNCTION ATPreFlightEvent(event, cancel: Longint; infoPtr: Ptr): OSErr;
; Walk the AppleTalk Event Queue (formerly the AppleTalk Transition Queue), passing
; event code to each element. If any event handler returns an error code, walk the queue
; again with the cancel code.
ATPreFlightEvent proc export
StackFrame record {A6Link}, increment
LocalStart equ * ; start of local vars
; This section is the stack frame used
; when calling the AEQ procedure
aeqEvent ds.l 1 ; AT event code
aeqPtr ds.l 1 ; ->AEQElem
aeqInfoPtr ds.l 1 ; ->event info (client use)
; These are true local variables
pfErr ds.w 1 ; preflight error code
lastQElem ds.l 1 ; last qElem called
nextQElem ds.l 1 ; next qElem to call
LocalSize equ LocalStart-* ; size of local vars
A6Link ds.l 1 ; saved A6
returnAddr ds.l 1 ; return addr for caller
ParmStart equ *
infoPtr ds.l 1 ; ->event info (client use)
cancel ds.l 1 ; cancel code
event ds.l 1 ; event code
ParmSize equ *-ParmStart ; size of parameters
result ds.w 1 ; result code (OSErr)
endr
; the stack on entry:
; sp -> return address [caller]
; infoPtr
; cancel (long)
; event (long)
; result (word)
; [previous contents]
with StackFrame, ATQel
link a6, #LocalSize ; set up stack frame
clr.w pfErr(a6) ; pfErr = noErr
; get access to the AppleTalk Event Queue
moveq #LGetAEQ, d0 ; d0 = LAPGetAEQ
move.l LAPMgrPtr, a0 ; a0 -> LAPMgr
jsr LAPMgrCall(a0) ; call Mr. LAP Manager
movea.l qHead(a1), a1 ; a1 -> first element in queue
@PFCkQElem
; check to see if we have come to the end of the queue
cmpa.l #0, a1 ; is it nil?
beq.s @PFExit ; yes, we're set
; remember who's next, and who we are about to call
move.l a1, lastQElem(a6) ; save ->this qElem
move.l AeQQLink(a1), nextQElem(a6) ; save ->next qElem
; set up the stack for the ATEvent handler
; the stack, as seen by the ATEvent handler procedure:
; sp -> return address
; event (long)
; ->aeq
; infoPtr
; [previous contents]
; must clear the namePtr each time to avoid returning the wrong name
move.l infoPtr(a6), aeqInfoPtr(a6) ; push infoPtr
move.l a1, aeqPtr(a6) ; push ->qElem
move.l event(a6), aeqEvent(a6) ; push event code
; call the aeqElem procedure
movea.l AeQCallAddr(a1), a0 ; a0 -> procedure address
jsr (a0) ; call it
tst.w d0 ; d0 == noErr?
bne.s @PFErr ; nope, have to cancel
; Pre-flight for that qElem was successful. get a pointer to the next qElem
; and see what he has to say about all this...
movea.l nextQElem(a6), a1 ; a1 -> next qElem
bra.s @PFCkQElem ; loop back
@PFErr
; someone barfed on the event.
; remember what they claimed was wrong, and walk the queue using the cancel code.
move.w d0, pfErr(a6) ; save error code
; get access to the AppleTalk Event Queue
moveq #LGetAEQ, d0 ; d0 = LAPGetAEQ
move.l LAPMgrPtr, a0 ; a0 -> LAPMgr
jsr LAPMgrCall(a0) ; call Mr. LAP Manager
movea.l qHead(a1), a1 ; a1 -> first element in queue
@PFCkDone
; check to see if we have come to the guy who barfed
cmpa.l lastQElem(a6), a1 ; are we done?
beq.s @PFExit ; yes, clear out
; remember who's next
move.l AeQQLink(a1), nextQElem(a6) ; save ->next qElem
; set up the stack
; the stack, as seen by the ATEvent handler procedure:
; sp -> return address
; cancel (long)
; ->aeq
; infoPtr
; [previous contents]
move.l infoPtr(a6), aeqInfoPtr(a6) ; push infoPtr
move.l a1, aeqPtr(a6) ; push ->qElem
move.l cancel(a6), aeqEvent(a6) ; push cancel event code
; call the aeqElem procedure
movea.l AeQCallAddr(a1), a0 ; a0 -> procedure address
jsr (a0) ; call it
; Get a pointer to the next qElem and let him in on the secret
movea.l nextQElem(a6), a1 ; a1 -> next qElem
bra.s @PFCkDone ; loop back
@PFExit
; restore the stack, set the return code, and get motivated...
move.w pfErr(a6), d0 ; get result code
unlk a6 ; blow away stack frame
movea.l (sp)+, a0 ; pop return address
adda.l #ParmSize, sp ; pop parameters
move.w d0, (sp) ; push result
jmp (a0) ; and return
endproc
; PROCEDURE ATEvent(event: Longint; infoPtr: Ptr);
; Walk the AppleTalk Event Queue (formerly the AppleTalk Transition Queue), passing
; event code to each element.
ATEvent proc export
StackFrame record {A6Link}, increment
LocalStart equ * ; start of local vars
; This section is the stack frame used
; when calling the AEQ procedure
aeqEvent ds.l 1 ; AT event code
aeqPtr ds.l 1 ; ->AEQElem
aeqInfoPtr ds.l 1 ; ->event info (client use)
; These are true local variables
nextQElem ds.l 1 ; next qElem to call
LocalSize equ LocalStart-* ; size of local vars
A6Link ds.l 1 ; saved A6
returnAddr ds.l 1 ; return addr for caller
ParmStart equ * ; start of parameters
infoPtr ds.l 1 ; ->event info (client use)
event ds.l 1 ; event code
ParmSize equ *-ParmStart ; size of parameters
endr
; the stack on entry:
; sp -> return address [caller]
; infoPtr
; event (long)
; [previous contents]
with StackFrame, ATQel
link a6, #LocalSize ; set up stack frame
; get access to the AppleTalk Event Queue
moveq #LGetAEQ, d0 ; d0 = LAPGetAEQ
move.l LAPMgrPtr, a0 ; a0 -> LAPMgr
jsr LAPMgrCall(a0) ; call Mr. LAP Manager
movea.l qHead(a1), a1 ; a1 -> first element in queue
@WkCkQElem
; check to see if we have come to the end of the queue
cmpa.l #0, a1 ; is it nil?
beq.s @WkExit ; yes, we're set
; remember who's next
move.l AeQQLink(a1), nextQElem(a6) ; save ->next qElem
; set up the stack
; the stack, as seen by the ATEvent handler procedure:
; sp -> return address
; event (long)
; ->aeq
; infoPtr
; [previous contents]
move.l infoPtr(a6), aeqInfoPtr(a6) ; push infoPtr
move.l a1, aeqPtr(a6) ; push ->qElem
move.l event(a6), aeqEvent(a6) ; push event code
; call the aeqElem procedure
movea.l AeQCallAddr(a1), a0 ; a0 -> procedure address
jsr (a0) ; call it
; get a pointer to the next qElem and let him in on the secret...
movea.l nextQElem(a6), a1 ; a1 -> next qElem
bra.s @WkCkQElem ; loop back
@WkExit
; restore the stack, and get motivated...
unlk a6 ; blow away stack frame
movea.l (sp)+, a0 ; pop return address
adda.l #ParmSize, sp ; pop parameters
jmp (a0) ; and return
endproc
END