mac-rom/Libs/InterfaceSrcs/piLAP.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
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.
2017-12-26 09:52:23 +08:00

766 lines
27 KiB
Plaintext

;
; File: piLAP.a
;
; Contains: xxx put contents here xxx
;
; Written by: xxx put writers here xxx
;
; Copyright: © 1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM2> 1/29/93 RB Do not move the SCCLockout value to the status register, always
; do an ORI.W with it so that NuKernel works and the stack is not
; changed.
;
;
BLANKS ON
STRING ASIS
EJECT
;_______________________________________________________________________
;
; LAP Routines
;_______________________________________________________________________
;
;_______________________________________________________________________
;
; LAPOpenProtocol
;
; Installs a protocol handler into MPP protocol table. There are
; two protocol handler tables used in ABPasIntf; one is kept in .MPP
; containing the protocol's type number and the address of the protocol's
; handler; and another is kept here in the interface for use by the
; LAPRead call. It contains an async flag, and a pointer to a readBlock
; structure. (defined in LAPRead)
;
; A NIL value in protoPtr will automatically install this interfaces
; built-in protocol handler. My protocol table will only include types
; that use the default protocol handler.
;
; FUNCTION LAPOpenProtocol(theLAPType : HalfByte; protoPtr : Ptr): INTEGER;
;
; Stack upon entry:
;
; TOS => .LONG Return address
; .LONG Pointer to protocol handler (see above)
; .BYTE LAP type field (only 1..127 is valid)
; .BYTE pascal filler
; .WORD function result code
;
; Returns: .WORD Result code
;
; Possible errors:
; Invalid protocol type (must be 1..127)
; Protocol type already in table
; No room in protocol table
;
; Register usage: D0-D2/A0-A1
; D3 is saved/restored
;
; The IO queue element is allocated on the stack for the control call
;
; Modification History:
; 8/24/84 GRT Ready for alpha release
; 8/28/84 GRT general code crunching pass
; 1/9/85 GRT Error 'AttErr' changed to 'LAPProtErr'
;
;_______________________________________________________________________
LAPOpenProtocol PROC EXPORT
IMPORT LAPProtoHdlr
JSR RemoveHdlBlks ; check for disposable handles
MOVE.L (SP)+,D2 ; save return address
MOVE.L (SP)+,A1 ; get protocol handler ptr
LEA tmpHandler,A0
MOVE.L A1,(A0) ; save for later
MOVE.L A1,D1 ; is it zero??
BNE.S @10 ; if not then branch and continue
LEA LAPProtoHdlr,A1 ; get address of built-in hdlr
@10 MOVE.B (SP)+,D1 ; lap type field
MOVE.L D3,-(SP) ; save D3 register
MOVE #LAPProtErr,D0 ; assume error
MOVE.B D1,D3 ; transfer register over
BEQ.S @90 ; check for a zero
SUB #IOQElSize,SP ; allocate space for the IOQEl
MOVE.L SP,A0 ; A0 -> IO queue element block
MOVE.B D3,ProtType(A0) ; lap type
MOVE.L A1,Handler(A0) ; protocol handler
MOVE #AttachPH,CSCode(A0) ; code for attach proto hndlr
MOVE #MPPRefNum,IORefNum(A0) ; set refnum up
_Control
ADD #IOQElSize,SP ; deallocate the queue element
BNE.S @90 ; check to see if control call had error
; store the protocol address and type in my own table for use by the READ op,
; but only if the proto address passed to us was zero.
MOVE.L tmpHandler,D1 ; was the proto handler for us?
BNE.S @90
LEA myHndlrTable,A1 ; A1 -> table of pr handlers
MOVE #(maxHndlr-1)*entrySize,D1 ; start at the end of the list
@20 TST.B theHndlr(A1,D1) ; is there a free entry (zero?)
BEQ.S @30 ; if zero then free so branch
SUBQ #entrySize,D1 ; change index number
BPL.S @20 ; check again
MOVE #LAPProtErr,D0 ; no free entry in table (ERROR)
BRA.S @90
@30 CLR.L thePtr(A1,D1) ; no read blocks linked in yet
MOVE.B D3,theHndlr(A1,D1) ; store the LAP type
CLR.B theRcvFlag(A1,D1) ; zero out the pkt rcvd flag
@90 JMP ExitD3 ; restore D3, set func result and exit
ENDPROC
EJECT
;_______________________________________________________________________
;
; LAPCloseProtocol
;
; Detaches the protocol handler from the table(s). Error is returned if
; the LAP type was not found in the MPP table. My protocol table is also
; scanned to remove the protocol type, but if it's not found, it is
; ignored. It is then assumed that the protocol type was for a protocol
; handler other than mine and therefore it was never installed in my
; table in the first place.
;
; FUNCTION LAPCloseProtocol(theLAPType : HalfByte): INTEGER;
;
; Stack upon entry:
;
; TOS => .LONG Return address
; .BYTE LAP type
; .BYTE pascal filler
; .WORD function result code
;
; Returns: .WORD Result code
;
; Possible errors:
; Protocol type not found in table.
;
; The IO queue element is allocated on the stack for the control call
;
; Modification History:
; 8/24/84 GRT Ready for alpha release
; 8/28/84 GRT no longer using D3
; 10/1/84 RFA,GRT register fun (changing register usage)
;
;_______________________________________________________________________
LAPCloseProtocol PROC EXPORT
JSR RemoveHdlBlks ; check to see if handles need to be disposed
MOVE.L (SP)+,D2 ; save return address
MOVE.B (SP)+,D1 ; get LAP type
SUB #IOQElSize,SP ; allocate IOQElement
MOVE.L SP,A0 ; A0 -> IOQEl
MOVE.B D1,ProtType(A0) ; pass parameter to IOQ
MOVE #DetachPH,CSCode(A0) ; control code
MOVE #MPPRefNum,IORefNum(A0) ; set refnum up
_Control ; make the call
ADD #IOQElSize,SP ; deallocate the IOQ element
BNE.S @20 ; check for error in control call
; Scan through table until either an matched entry is found, or until
; the end of the table is reached.
; Note#1: At this point we have successfully removed it from MPP's variable
; area. If we can't find the type in our local table, we ignore the error
; since we accomplished what we wanted anyways. (Why it's not there is beyond
; me)
LEA myHndlrTable,A1 ; A1 -> table of pr handlers
MOVE #(maxHndlr-1)*entrySize,D0 ; start at the end of the list
@05 CMP.B theHndlr(A1,D0),D1 ; do they match?
BEQ.S @10 ; OK so exit
SUBQ #entrySize,D0 ; down one entry
BPL.S @05
BRA.S @15 ; not here, so just exit (see note#1)
@10 CLR.B theHndlr(A1,D0) ; zero out the field to nullify it
@15 CLR D0 ; no errors
@20 JMP ExitD0 ; set func result and exit
ENDPROC
EJECT
;_______________________________________________________________________
;
; LAPWrite
;
; Write a packet out to the cable either synchronously or asynchronously.
; If sync, do the operation and return when completed. If async, pass
; control back after queueing the call, and when completed, post a network
; event (currently eventCode #10) back to the application.
;
; The ABRecHandle is locked down during most of the call. As for all async
; calls, abResult will contain a 1 in it as long as the operation is still
; in progress.
;
; The WDS used by MPP for writing is allocated under the IOQ element block.
;
; FUNCTION LAPWrite(abRecord : ABRecHandle; async : BOOLEAN): INTEGER;
;
; Stack upon entry:
;
; TOS => .LONG Return address
; .BYTE async flag
; .BYTE pascal filler
; .LONG handle to record data structure
; .WORD function result code
;
; Returns: .WORD Result code
; Additional data in record structure
;
; Possible errors:
;
;
; Upon allocation of the IOQElement block, an additional n bytes are
; allocated at the end. The data structure looks like this:
;
; |=========================|
; : :
; : IOQElement blk : 50 bytes
; : :
; : :
; |=========================|
; : AB record handle : 4 byte handle to AB record
; |-------------------------|
; : Q Element handle : 4 byte handle to this queue element
; |-------------------------|
; : WDS element1 (hdr info) : 6 bytes (2 byte length, 4 byte ptr)
; |-------------------------|
; : WDS element2 (write) : 6 bytes (points to data to write)
; |-------------------------|
; |_ WDS Termination _| 2 bytes
; | Word |
; |-------------------------|
; | async flag | 1 byte
; |=========================|
; | WDS dest node address | 1 byte (WDS element1 data; odd aligned)
; |-------------------------|
; | unused | 1 byte (LAP src address goes here)
; |-------------------------|
; | WDS lap type field | 1 byte
; |=========================|
;
; The pointer in WDS element1 will always point to the data portion of the
; element (stored under the async flag). This data is always 3 bytes long.
;
; Modification History:
; 8/24/84 GRT Ready for alpha release
; 8/29/84 GRT Code crunching
; 10/1/84 RFA GetHdlAndLock needs long word parameter instead of word
; 12/17/84 GRT CmpEventPost changed to Cmp1EventPost
; 2/7/85 GRT LAPProtType byte moved incorrectly into WDS header
; 4/30/86 GRT Saving queue element handle in the queue element
;_______________________________________________________________________
LAPWrite PROC EXPORT
JSR RemoveHdlBlks ; check to see if handles need to be disposed
MOVE.L (SP)+,D2 ; save return address
MOVE.B (SP)+,D1 ; save async flag
MOVE.L (SP),A0 ; copy of record handle
MOVE.L (SP)+,A1 ; another record handle copy made
MOVEM.L A2-A3,-(SP) ; save A2-A3
_HLock ; lock abRecord down
BNE @30 ; if not zero return an error
MOVE.L (A1),A2 ; A2 -> Ptr to ABRecord
MOVE #1,abResult(A2) ; 1 means we are currently in execution
MOVE.B #tLAPWrite,abOpCode(A2) ; put call type in record
; We are allocating an extra 22 bytes at the end of the IOQElement for storage
; of the misc data (see diagram)
MOVE.L #IOQElSize+WDSXtraLAPSize,D0 ; number of bytes to allocate
JSR GetHdlAndLock ; allocate the memory A0->IOQElement Hdl
BNE.S @30 ; error if didn't work
MOVE.L A0,D0 ; save handle
MOVE.L (A0),A0 ; A0 -> IOQElement blk (dereferenced)
MOVE.L D0,qElHdl(A0) ; save handle in the queue element
; A2 points to ABRecord. A0 points to IOQElement
MOVE.B D1,ABAsyncFlag(A0) ; async flag stored in IOQELBlk+18
MOVE.L A1,ABRecHdl(A0) ; save handle in IOQElement blk
LEA WDS1stEntry(A0),A3 ; address of the WDS header entry
; currently A3 is ODD aligned
; Fill up the WDS data at the end of the IOQ element block
LEA WDS1Start(A0),A1 ; start of WDS stuff
MOVE.L A1,WDSPointer(A0) ; move it into the IOQEl param area
MOVE #LAPHdSz,(A1)+ ; length is always 3 for the addr block
MOVE.L A3,(A1)+ ; stuff dest add ptr
MOVE lapReqCount(A2),(A1)+ ; buffer size to write out
MOVE.L lapDataPtr(A2),(A1)+ ; buffer data pointer
CLR (A1) ; zero means end of WDS
LEA lapAddress(A2),A1 ; address of the addr block
MOVE.B (A1),(A3) ; dest node into WDS header
MOVE.B 2(A1),2(A3) ; move proto type into WDS header
MOVE #WriteLAP,CSCode(A0) ; set control code
LEA WriteCompletion,A2 ; A2 -> our IO completion routine
JSR DoControlCall ; make the control call
@30 MOVEM.L (SP)+,A2-A3 ; restore A2-A3
JMP ExitD0 ; set func result and exit
;_______________________________________________________________________
; This routine is called when the IO has been completed
; A0 -> IOQElBlk
;_______________________________________________________________________
WriteCompletion
; on entry, A0 -> IOQElement block
MOVEM.L D0/A0-A2,-(SP) ; save registers
JSR CmpEntrance ; set up registers and unlock ab record hdl
JSR Cmp1EventPost ; post event if needed
MOVEM.L (SP)+,D0/A0-A2 ; restore registers
RTS
ENDPROC
EJECT
;_______________________________________________________________________
;
; LAPRead
;
; Read a packet coming in from the cable. If the call is sync, it will
; wait in a loop until a packet is recieved in its buffer. If made
; async, an event will be posted upon reception. Note that if two async
; calls are made and then a sync call is made, 3 packets must be received
; before control will return to the user! The sync call will only return
; when a packet has been recieved in the buffer that was used for the sync
; call.
;
; IMPORTANT: The LAPRead call can only be used with the built in protocol
; handler.
;
; The ABRecHandle is locked down until the call completes. The protocol
; handler is responsible for unlocking it. (unless an error occurs in the
; read queueing)
;
; FUNCTION LAPRead(abRecord : ABRecHandle; async : BOOLEAN): INTEGER;
;
; Stack upon entry:
;
; TOS => .LONG Return address
; .BYTE async flag
; .BYTE pascal filler
; .LONG handle to record data structure
; .WORD function result code
;
; Returns: .WORD Result code
; Additional data in record structure
;
; Possible errors:
;
;
; A 14 byte read block is allocated dynamically for every read call. This
; block is linked in a FIFO queue for every handler type. When a pkt is
; received, the first read block is taken and the packets data is put where
; the ptr points to. If the buffer is not big enough, the remaining part of
; the packet is discarded and an error is returned to the application. The
; packet up to the point of the end of the buffer, however, is returned intact.
;
; |=========================|
; | |
; | Link to next read blk | 4 byte pointer link
; | |
; | |
; |-------------------------|
; : AB record handle | 4 byte hdl to AB record
; |-------------------------|
; : Q element handle | 4 byte hdl to this queue element
; |-------------------------|
; | async flag | 1 byte
; |-------------------------|
; | unused | 1 byte
; |=========================|
;
; Modification History:
; 8/24/84 Ready for alpha release (GRT)
; 10/1/84 RFA GetHdlAndLock needs long word parameter
; 3/15/85 GRT Added RecoverHandle call
; 4/30/86 GRT Saving queue element handle in the queue element
;_______________________________________________________________________
LAPRead PROC EXPORT
ENTRY LAPProtoHdlr
JSR RemoveHdlBlks ; any handles to dispose of?
MOVE.L (SP)+,D2 ; save return address
MOVE.B (SP)+,D1 ; save async flag
MOVE.L (SP),A0 ; record handle copy made
MOVE.L (SP)+,A1 ; and another in A1
MOVEM.L A2-A4,-(SP) ; save A2-4 for later
_HLock ; lock it down
BNE ReadLExit ; if error then exit
MOVE.L A0,A4 ; save temporarily
MOVE.L (A4),A2 ; A2 -> Ptr to ABRecord
MOVE #1,abResult(A2) ; 1 means we are currently in execution
MOVE.B #tLAPRead,abOpCode(A2) ; put call type in
MOVEQ #rdBlkSize,D0 ; size of a read blk entry
JSR GetHdlAndLock ; get a handle to the memory
; A0 has handle to new memory block (to be used for the read block)
BNE.S ReadL1Exit ; exit if error (must clean up)
MOVE.L A0,D0 ; save handle in D0
MOVE.L (A0),A0 ; A0 -> my read block (dereference)
MOVE.L D0,rbHdl(A0) ; move handle to queue element
; A0 -> my read block A2 -> AB record
; first stuff the read blk full of data
CLR.L rbNxPtr(A0) ; zero out ptr to next element
MOVE.L A1,rbABHdl(A0) ; copy the AB rec hdl into it
MOVE.B D1,rbAFlag(A0) ; save the aysnc byte flag
; now check the hndlr table for the matching type field
MOVE.B lapAType(A2),D0 ; get the lap type
BEQ.S @06 ; zero type is invalid
LEA myHndlrTable,A1 ; A1 -> table of prot handlers
MOVE #(maxHndlr-1)*entrySize,D1 ; start at the end of the table
@05 CMP.B theHndlr(A1,D1),D0 ; do they match?
BEQ.S @10 ; OK so exit
SUBQ #entrySize,D1 ; down one entry
BPL.S @05
@06 MOVE.L A4,A0 ; recover the handle
JSR UnlockAndLinkHdl ; get rid of the read blk
MOVE #readQErr,D0 ; set error code
BRA.S ReadL1Exit
; must reset the pkt recvd flag before the read buffer is linked in
; SCC interrupts are being turned off while linking the block in
; A0 -> read blk
@10 CLR.B theRcvFlag(A1,D1) ; zero out the pkt recvd flag if sync
MOVE SR,-(SP) ; save status register on stack
ORI.W #SCCLockOut,SR ; lock out the SCC interrupts <SM2> rb
LEA thePtr(A1,D1),A4 ; A4 -> read element entry link
MOVE.L (A4),A3 ; A3 -> next read element
@15 MOVE.L A3,D0 ; is it the end of the link?
BEQ.S @20 ; if so, then we found the end
MOVE.L A3,A4 ; save previous ptr
MOVE.L (A3),A3 ; get next ptr in link
BRA.S @15 ; back and check
@20 MOVE.L A0,0(A4) ; put the read blk into link
MOVE (SP)+,SR ; restore interrupt status
CLR D0 ; no errors if we got here!
TST.B rbAFlag(A0) ; is this an async call?
BNE.S ReadLExit ; if so exit (don't unlock the handle)
; Since the call is sync, we wait until the pkt recvd flag says one has come in
; The result code will have been put in the record by the protocol handler.
@25 TST.B theRcvFlag(A1,D1) ; has a packet been received?
BEQ.S @25 ; if not, then wait
MOVE abResult(A2),D0 ; get result of operation into D0
BRA.S ReadLExit
; If an error occurred, but we have already locked memory blk, unlock blk
ReadL1Exit MOVE D0,D1 ; save error code
MOVE.L A2,A0 ; get the abRecHandle
_RecoverHandle
_HUnlock ; unlock the handle if no call was made
MOVE D1,D0 ; recover error code
ReadLExit MOVEM.L (SP)+,A2-A4 ; restore registers
JMP ExitD0 ; set func result (D0) and exit
; The table entries in memory are organized by entries and not by types.
;
; ENTRY 1: | protoHdlr Type (1)| Pkt rcvd flag (1)| read block link ptr (4)|
; ENTRY 2: | protoHdlr Type (1)| Pkt rcvd flag (1)| read block link ptr (4)|
; ENTRY 3: | protoHdlr Type (1)| Pkt rcvd flag (1)| read block link ptr (4)|
; ENTRY 4: | protoHdlr Type (1)| Pkt rcvd flag (1)| read block link ptr (4)|
EJECT
;_______________________________________________________________________
;
; LAPProtoHdlr
;
; This is the LAP protocol handler used in reading straight LAP packets.
; It is called by the MPP driver when a packet has been received if the
; type field has been installed by the AttachPH routine.
;
; The first two data bytes of the LAP packet have already been read into
; the RHA. (actually the RHA also has the 3 byte LAP hdr in it too)
;
; If you didn't already know it, the first two bytes of the data field of
; the LAP packet must be the length bytes in order for this to work!!
;
; Call:
; A0,A1 .LONG SCC read/write addresses (preserve)
; A2 .LONG local vars (preserve)
; A3 .LONG ptr into the RHA (5 bytes already loaded in)
; A4 .LONG address of the ReadPacket routine
; A5 .LONG useable until ReadRest is called
; D1 .WORD length still left to read (preserve)
;
; Return:
; D0 .WORD error result
;
; Possible errors:
;
; Modification History:
; 8/24/84 Ready for alpha release (GRT)
; 10/1/84 RFA,GRT Code crunching pass made
; 3/15/85 GRT RecoverHandle call added
; 4/30/86 GRT Getting rid of the _RecoverHandle traps
;_______________________________________________________________________
LAPProtoHdlr
; MPP subtracts two from the length bytes of the packet. We have to make sure
; that D1 contains at least one byte to read, else we skip this section
MOVEQ #4,D3 ; we want to read in at most 4 bytes
CMP D3,D1 ; check to see how many bytes are left
BHS.S @02 ; if more then just use the 4 bytes
MOVE D1,D3 ; else its less, so read however many left
@02 LEA myRHALen,A5 ; address of storage area
MOVE D3,(A5) ; save 'bytes to read'
BEQ.S @03 ; dont read if zero bytes left
JSR (A4) ; read the bytes into the RHA and adjust
BNE.S @08 ; if error then exit
; now that we've bought some time, scan through the table to find a buffer
; A2 -> MPP vars
; A3 -> modified RHA ptr
; D1 = number of bytes left to read in
@03 MOVE.L A3,-(SP) ; save RHA ptr
MOVEM.L A0-A1,-(SP) ; save other registers
LEA myHndlrTable,A5 ; A5 -> table of pr handlers
MOVE #(maxHndlr-1)*entrySize,D2 ; start at the end of the list
LEA ToRHA(A2),A0 ; address of top of RHA
MOVE.B LAPType(A0),D3 ; get lap type of packet from RHA
; D2 = entry number in PHT
@05 CMP.B theHndlr(A5,D2),D3 ; do they match?
BEQ.S @10
SUBQ #entrySize,D2 ; next entry
BPL.S @05 ; go back and check the next one
; No valid type in table. Ignore packet
@07 MOVEM.L (SP)+,A0-A1 ; restore the registers back
MOVE.L (SP)+,A3 ; restore RHA ptr
MOVEQ #0,D3 ; tells MPP we don't want the pkt
JMP 2(A4) ; read in the rest of the packet; exit
; Exit point - it's here because we want short branches!
@08 RTS
; We have found the entry so get how many bytes to read and read them into buf
@10 LEA tmpHndlrEntry,A1
MOVE D2,(A1) ; save the entry offset in the table
MOVE.L thePtr(A5,D2),A0 ; A0 -> read block structure
CMP #0,A0 ; is there a buffer there?
BEQ.S @07 ; if not, ignore the pkt
MOVE.L rbABHdl(A0),A0 ; A1 -> AB record ptr
MOVE.L (A0),A1 ; dereference handle
MOVE.L lapDataPtr(A1),A3 ; A3 -> data buffer
MOVE myRHALen,D2 ; get length saved up
ADDQ #2,D2 ; add the length bytes
ADD D2,A3 ; modify ptr
MOVE lapReqCount(A1),D3 ; D3 = number of bytes want to read
SUB D2,D3 ; D3 = bytes to read - what I've already read
MOVEM.L (SP)+,A0-A1 ; restore them back
JSR 2(A4) ; read in rest of packet
; D3 = number of bytes read compared to the buffer length (if less than zero, the
; buffer was not big enough!
; after call 2(A4) [ReadRest], we are able to use all conventional registers again
MOVE.L (SP)+,A3 ; restore RHA ptr (CCs not affected)
BNE @40 ; if error, branch
TST D3 ; check length info
BGE.S @13 ; if buffer is OK then branch
MOVE #buf2SmallErr,D0 ; buffer was not big enough
; copy bytes from the RHA into the users buffer
@13 MOVE myRHALen,D2 ; get length of rha
ADDQ #2,D2 ; add length bytes
SUB D2,A3 ; point to beginning of RHA data (not lap hdr)
MOVE tmpHndlrEntry,D1 ; get offset
LEA myHndlrTable,A1 ; address of my prot handler table
MOVE.L thePtr(A1,D1),A1 ; get the read block ptr
MOVE.L rbABHdl(A1),A0 ; get the ab record handle
MOVE.L (A0),A0 ; and dereference
CMP lapReqCount(A0),D2 ; is buffer big enough to hold RHA?
BLE.S @14 ; yes, proceed
MOVE lapReqCount(A0),D2 ; no, only copy bufSize bytes
@14 MOVE (A3),lapActCount(A0) ; actual bytes read in
MOVE.L lapDataPtr(A0),A2 ; A2 -> input data buffer
@15 SUBQ #1,D2 ; dec counter
BLT.S @18 ; if neg then exit
MOVE.B 0(A3,D2),0(A2,D2) ; copy RHA bytes into buffer
BRA.S @15 ; do it again until done
; move any pertinant data to the AB record to send back to the caller
; A0 -> ABrecord
@18 LEA myHndlrTable,A2 ; "wheres the table?"
MOVE D0,abResult(A0) ; set return result code
SUB #3,A3 ; A3 -> beginning of RHA!
MOVE.B (A3)+,lapADest(A0) ; move dst byte to record
MOVE.B (A3),lapASource(A0) ; move src node ID to record
MOVE.L rbABHdl(A1),A0 ; A0 = handle to AB record
_HUnlock ; unlock the ABRecord handle
TST.B rbAFlag(A1) ; test async flag
BEQ.S @20 ; if false branch
; it's async so post the event
MOVE.L A0,D0 ; event message (ABRecHandle)
MOVE #networkEvt,A0 ; event code
_PostEvent ; post event to caller; D0=err code
BRA.S @30
; it's sync so set the packet recvd flag
@20 ST theRcvFlag(A2,D1) ; set the pkt recvd flag to true
; unlink and unlock read block from the queue (has to be at the beginning)
@30 MOVE.L 0(A1),thePtr(A2,D1) ; unlink read blk
MOVE.L rbHdl(A1),A0 ; A0 = handle to read block
JSR UnlockAndLinkHdl ; dispose of the handle
@40 RTS
ENDPROC
EJECT
;_______________________________________________________________________
;
; LAPRdCancel
;
; Cancel a pending asynchronous LAPRead and free its associated data structures.
;
; IMPORTANT: The LAPRdCancel call can only be used with asynchronous LAPRead
; calls on a protocol type whose protocol handler is the default.
;
; The ABRecord is unlocked, and the associated Read Block is dequeued from
; the list of pending Read requests and marked for disposal. This call can
; only be made synchronously.
;
; FUNCTION LAPRdCancel(abRecord : ABRecHandle): INTEGER;
;
; Stack upon entry:
;
; TOS => .LONG Return address
; .LONG handle to record data structure
; .WORD function result code
;
; Returns: .WORD Result code
; The abResult field of the abRecord is set to zero
;
; Possible errors: Bad Protocol Type (zero or not open)
; abRecord not found
;
; Note that by the time the Read request queue is searched for the Read Block
; pointing to the specified abRecord, a packet may arrive and satisfy the
; request. An "abRecord not found" error will then be returned. In such a
; case, the caller should check the abResult field of the abRecord to see
; if it indeed has completed. If it did, it will contain zero or a negative
; error indication. If it is equal to 1, then something is seriously wrong.
;
; Modification History:
;
; 12/20/84 GRT New today from code originally written by RFA for DDP
; 3/15/85 GRT RecoverHandle call added
;
;_______________________________________________________________________
LAPRdCancel PROC EXPORT
JSR RemoveHdlBlks ; check disposable handles
MOVEM.L (SP)+, D2/A0 ; D2 = return adr, A0 = abRec hdl
MOVEM.L D3/A2-A3, -(SP) ; save some registers
; first check my protocol handler table for the matching protocol type
MOVE #readQErr,D0 ; assume an error
MOVE.L (A0),A2 ; A2 -> ABRecord
MOVE.B lapAType(A2),D3 ; get the lap type
BEQ.S LRdCnclExit ; zero is invalid
; scan table: D3 = lap type; A2 = abRecord ptr
LEA myHndlrTable,A1 ; A1 -> table of pr handlers
MOVE #(maxHndlr-1)*entrySize,D1 ; start at the end of the list
@05 CMP.B theHndlr(A1,D1),D3 ; do they match?
BEQ.S @07 ; OK so exit
SUBQ #entrySize,D1 ; down one entry
BPL.S @05
BRA.S LRdCnclExit ; if not found then leave
; we found the type, so search list of Read Blocks for one that points to abRec
; A1 -> protocol handler table
@07 MOVE #recNotFnd, D0 ; assume an error
LEA thePtr(A1,D1), A1 ; A1 = head of Read Block queue
MOVE SR, -(SP) ; save old status
ORI.W #SCCLockout, SR ; disable interrupts <SM2> rb
; the first time through, the check for the next element is made in the table;
; from then on, the check is made through the queue
@10 MOVE.L rbNxPtr(A1), A3 ; check next element
MOVE.L A3,D3 ; is there a next element?
; check A3 for zero (in SR)
BNE.S @20 ; yes, continue checks
MOVE (SP)+, SR ; no, we're at the end & no match!
BRA.S LRdCnclExit ; restore interrupt state & return
@20 CMPA.L rbABHdl(A3), A0 ; is this the RdBlk for our abRec?
BEQ.S FoundLIt ; yes!
MOVE.L A3, A1 ; no, skip down to next Read Block
BRA.S @10 ; and check it
; we found the right Read Block, so dequeue it and dispose of it
FoundLIt MOVE.L (A3), (A1) ; dequeue the Read Block
MOVE (SP)+, SR ; safe now to re-enable interrupts
CLR abResult(A2) ; clear result field in abRecord
; A0 still contains the abRecHandle to remove; A3 -> read block to dispose of
_HUnlock ; unlock the abRecord
MOVE.L A3,A0
_RecoverHandle ; recover handle to Read Block
_HUnlock ; unlock it and dispose of it
_DisposHandle ; (hopefully clears D0 as well)
LRdCnclExit MOVEM.L (SP)+, D3/A2-A3 ; restore registers
JSR ExitD0
ENDPROC