; ; 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): ; ; 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