mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-01 11:29:27 +00:00
0ba83392d4
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.
766 lines
27 KiB
Plaintext
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 |