.INCLUDE "SY0:[1,2]COMMON.MAC" TITLE ASYIO,,00,26-May-87,MEM .SBTTL .SBTTL +------------------------------------------------------------------+ .SBTTL | Copyright (C) 1987, Michael Mayfield, dba Mayfield International | .SBTTL | | .SBTTL | This software may be copied and distributed without restriction | .SBTTL | with the inclusion of this notice. This software is provided | .SBTTL | AS-IS, with no warranty, expressed or implied. | .SBTTL +------------------------------------------------------------------+ .SBTTL .LIST MEB .ENABL AMA ;+ ; ASYIO is a collection of subroutines callable from BP2 that perform asynchronous ; I/O. After posting a read or write with ASYGET or ASYPUT, the calling program ; continues execution during the I/O processing. ASYDON is used to check for I/O ; completion. ; ; Author: ; Michael Mayfield ; ; Assembly Procedure: ; $MAC ASYIO ; ; Taskbuild Procedure (ODL file): ; .ROOT USER ; USER: .FCTR bp2objs-ASYIO-LIBR ; LIBR: .FCTR LB:BP2OTS/LB ; .END ; ; Modification History: ; 00 26-May-87 MEM Original version ;- .SBTTL ASYGET Asynchronous read subroutine ;+ ; ASYGET is an external subroutine callable from BP2 that reads asynchronously ; from a device open on a specified channel. The routine returns immediately, ; without waiting for the read to complete. ; ; Input: ; R5 ->Parameter list, as follows: ; 0: Argument count. Always 5 ; 1: ->Channel number (INTEGER:CHANNEL) ; 2: ->Byte count (INTEGER:BYTCNT) ; 3: ->Buffer offset (INTEGER:BUFOFF) ; 4: ->Block number (LONG:BLOCK) ; 5: ->Parameter to pass in ASYDON on completion (INTEGER:PARAMETER) ; ; Output: ; ASYBUF Receives buffer of data at specified offset on I/O completion ; ; Call: ; EXTERNAL SUB ASYGET (INTEGER,INTEGER,INTEGER,LONG,INTEGER) ; CALL ASYGET(CHANNEL,BYTCNT,BUFOFF,BLOCK,PARAMETER) ; ; Note: ; String header format: ; Word 0 ->String data ; 1 Length of string ;- .PSECT ASYIO,I,RO,OVR,GBL .ENABL LSB ASYGET::CALL IOPREP ;Do common I/O preparation CLR @#XRB+XRBC ;Pass byte count as 0 for read .READA ;Post the read request 10$: TSTB @#FIRQB ;Did we get an error BEQ 20$ ;No CALL STOXRB ;Yes- Pretend I/O completed 20$: RETURN .SBTTL ASYPUT Asynchronous write subroutine ;+ ; ASYPUT is an external subroutine callable from BP2 that writes asynchronously ; to a device open on a specified channel. The routine returns immediately, ; without waiting for the write to complete. ; ; Input: ; R5 ->Parameter list, as follows: ; 0: Argument count. Always 5 ; 1: ->Channel number (INTEGER:CHANNEL) ; 2: ->Byte count (INTEGER:BYTCNT) ; 3: ->Buffer offset (INTEGER:BUFOFF) ; 4: ->Block number (LONG:BLOCK) ; 5: ->Parameter to pass in ASYDON on completion (INTEGER:PARAMETER) ; ; Output: ; ASYBUF Buffer of data at specified offset written to output device ; ; Call: ; EXTERNAL SUB ASYPUT (INTEGER,INTEGER,INTEGER,LONG,INTEGER) ; CALL ASYPUT(CHANNEL,BYTCNT,BUFOFF,BLOCK,PARAMETER) ; ; Note: ; String header format: ; Word 0 ->String data ; 1 Length of string ;- ASYPUT::CALL IOPREP ;Do common I/O preparation .WRITA ;Post the write request BR 10$ ;Check for errors and exit .DSABL LSB .SBTTL ASYDON Check for I/O completion ;+ ; ASYDON is an external subroutine callable from BP2 that checks for completion ; of a previously issued .READA or .WRITA request on a specified channel. If the ; I/O has completed, the I/O results (XRB) are returned to the caller. Otherwise ; a flag is returned specifying that no I/O completion is pending for the ; specified channel. ; ; Note that issuing a SLEEP -32767% will sleep until an asynchronous I/O request ; completes (on any channel). ; ; Input: ; R5 ->Parameter list, as follows: ; 0: Argument count. Always 5 ; 1: ->Channel number (INTEGER:CHANNEL) ; 2: ->Number of bytes transferred (INTEGER:IORECOUNT) ; 3: ->Returned buffer offset (INTEGER:BUFOFF) ; 4: ->Returned user's parameter (INTEGER:PARAMETER) ; 5: ->Returned completion status (INTEGER:ERRSTS) ; ; Output: ; BUFOFF Offset from start of ASYBUF buffer to start of data ; PARAMETER Parameter value passed by user on ASYGET or ASYPUT call ; ERRSTS Completion error status. ; 0 = No error ; -1 = No I/O completion pending for this channel ; >0 = Error number ; ; Call: ; EXTERNAL SUB ASYDON (INTEGER,INTEGER,INTEGER,INTEGER,INTEGER) ; CALL ASYDON(CHANNEL,IORECOUNT,BUFOFF,PARAMETER,ERRSTS) ;- ASYDON::TST (R5)+ ;Skip argument count MOV @(R5)+,R1 ;Get channel number ASL R1 ;Now channel number *2 ADD #DONTBL,R1 ;->DONTBL entry for this channel MOV (R1),R0 ;->Completion entry (or 0 if none pending) BEQ 20$ ;No completion entries pending for this channel MOV (R0),(R1) ;Dequeue completion entry MOV #DONTBL,R1 ;First entry in DONTBL is root of free list CALL QUEUER ;Queue completion entry onto free list CALLX $CLXRB ;Clear the XRB. R3->XRB+XRLEN TST (R0)+ ;Skip past link word in completion entry MOV (R0),@(R5)+ ;Return byte count in IORECOUNT MOV (R0),(R3)+ ;Return byte count as XRLOC MOV (R0)+,(R3)+ ;Return byte count as XRBC MOV (R0)+,R1 ;Get address of I/O buffer MOV R1,(R3)+ ;Return address of I/O buffer in XRLOC SUB #ASYBUF,R1 ;Compute offset from ASYBUF to I/O buffer MOV R1,@(R5)+ ;Return it in BUFOFF MOV (R0)+,(R3)+ ;Return channel & <23:16> of starting block number MOV (R0)+,(R3) ;Return <15:0> of starting block number MOV (R0)+,@(R5)+ ;Return user's parameter word in PARAMETER MOV (R0)+,@(R5)+ ;Return error code in ERRSTS 10$: RETURN ; No completion entries pending on specified channel 20$: MOV #-1,@6(R5) ;Return error status as -1 to show nothing pending BR 10$ ;Exit .SBTTL IOPREP Common I/O preparation ;+ ; IOPREP sets up the XRB and FIRQB for a .READA or .WRITA request. The completion ; address is set to IOAST. ; ; Input: ; R5 ->Parameter list, as follows: ; 0: Argument count. Always 5 ; 1: ->Channel number (INTEGER:CHANNEL) ; 2: ->Byte count (INTEGER:BYTCNT) ; 3: ->Buffer offset (INTEGER:BUFOFF) ; 4: ->Block number (LONG:BLOCK) ; 5: ->Parameter to pass in ASYDON on completion (INTEGER:PARAMETER) ; ; Output: ; XRLEN Size of buffer in bytes (size of BUFFER string) ; XRBC =XRLEN (Note: Must be cleared before issuing .READA) ; XRLOC Address of buffer (Base of BUFFER string) ; XRCI Channel number (value of CHANNEL) ; XRBLK <15:0> of block number (BLOCK) ; XRBLKM <23:16> of block number ; FQFIL =IOAST ; FQPPN Parameter to pass to ASYDON (value of PARAMETER) ; ; Call: ; JSR PC,IOPREP ;- IOPREP: CALLX $CLXRB ;Clear XRB. R3->XRB+XRLEN TST (R5)+ ;Skip argument count MOV @(R5)+,R2 ;Get channel number ASL R2 ;Now its channel number *2 MOV @(R5)+,(R3) ;Put buffer size in XRLEN MOV (R3)+,(R3)+ ;Same with XRBC MOV @(R5)+,(R3) ;Put offset in XRLOC ADD #ASYBUF,(R3)+ ;Now buffer address is in XRLOC MOVB R2,(R3)+ ;Store channel *2 in XRCI MOV (R5)+,R1 ;Get ->block number longword MOVB 2(R1),(R3)+ ;<23:16> of longword is MSB of block number MOV (R1),(R3) ;<15:0> of longword is LSB of block number CALLX $CLFQB ;Clear the FIRQB MOV #IOAST,@#FIRQB+FQFIL ;Completion routine is IOAST MOV @(R5)+,@#FIRQB+FQPPN ;Pass caller's parameter in asynch call RETURN .SBTTL IOAST I/O completion AST handler ;+ ; IOAST is entered as an AST on completion of a .READA or .WRITA from ASYGET or ; ASYPUT. ; ; Input: ; XRB Results of corresponding I/O request ; FIRQB+0 Error status ; FQPPN Parameter passed on I/O request ; ; Output: ; R0-R6 Preserved ; FIRQB Preserved ; DONTBL Completion entry linked onto end of completion queue for channel ; ; Call: ; AST entry ;- IOAST: CALL STOXRB ;Copy XRB and FIRQB info to completion entry .ASTX ;Exit from AST .SBTTL STOXRB Store XRB and FIRQB info in completion entry ;+ ; Allocates a completion entry and copies the XRB, error status, and user's ; parameter into it. The completion entry is linked onto the completion list ; for the channel specified in XRCI. ; ; Input: ; XRB Completion information on I/O request to save ; XRCI Channel *2 of I/O request channel ; FIRQB+0 Error status ; FQPPN User's parameter ; DONTBL Linked list of free and pending completion entries ; ; Output: ; DONTBL Completion entry removed from free list and queued onto ; completion queue for specified channel ; DONENT XRB copied to free completion entry. User's parameter is at ; XRTIME. Error status (FIRQB+0) is at XRMOD. ; R0-R6 Preserved ; ; Call: ; JSR PC,STOXRB ; ; Note: ; The XRB is not saved if no completion entries are available. It is the ; responsibility of the caller to ensure that no more than FREMAX ASTs ; are posted simultaneously. ;- STOXRB: PUSH ;Don't let any registers change MOV DONTBL,R0 ;Get ->free completion entry BEQ 10$ ;No free entries- Junk the request PUSH R0 ;Save ->completion entry MOV @DONTBL,DONTBL ;Delink completion entry from free list CLR (R0)+ ;Zero forward link in XRLEN MOV #XRB+XRBC,R1 ;->XRB @XRBC MOV (R1)+,(R0)+ ;Store XRBC in completion entry MOV (R1)+,(R0)+ ;Store XRLOC in completion entry PUSH (R1) ;Save XRCI MOV (R1)+,(R0)+ ;Store XRCI and XRBLKM in completion entry MOV (R1)+,(R0)+ ;Store XRBLK in completion entry MOV @#FIRQB+FQPPN,(R0)+ ;Store user's parameter in completion entry MOV @#FIRQB,(R0) ;Store error status in completion entry MOVB (SP)+,R1 ;Restore channel *2 ADD #DONTBL,R1 ;Now pointer to DONTBL entry for channel POP R0 ;Restore pointer to completion entry CALL QUEUER ;Queue completion entry onto DONTBL queue 10$: POP ;Restore all registers RETURN .SBTTL QUEUER Add entry to queue ;+ ; QUEUER links an entry onto a specified queue. ; ; Input: ; R0 ->Link word of entry to be added to specified queue ; R1 ->Base of queue to link entry onto ; ; Output: ; (R0) 0 ; (R1).. Entry added to end of linked list pointed to by R1 ; ; Call: ; JSR PC,QUEUER ;- ; Enqueue completion entry onto completion queue QUEUER: CLR (R0) ;Ensure 0 forward link 10$: TST (R1) ;Is this the end of the queue BEQ 20$ ;Yes MOV (R1),R1 ;Follow link to next entry in queue BR 10$ ;Loop until the end is found 20$: MOV R0,(R1) ;Link completion entry onto end of queue RETURN .SBTTL Data structures .PSECT ASYIOD,D,RW,OVR,GBL ; Constants FREMAX= 16. ;Maximum number of simultaneously pending ; completion entries ; Variables: ; Table of completion lists. Indexed by channel #*2. Channel 0 is used ; for a list of free entries. DONTBL: .WORD DONENT ;Link to first free entry, or 0 .BLKW 15. ;Link to first completion entry for channel*2, or 0 ; Linked list of free completion entries DONENT: .REPT FREMAX ;Repeat for all completion entries .WORD .+XRBSIZ ;Link to next entry .BLKB XRBSIZ-2 ;Saved XRB value plus error code and parameter .ENDR .= .- ;Point back to link word of last entry .WORD 0 ;Last link word is 0 .= .+ ;Point back after last completion entry ; I/O buffer shared with BP2 program. The size of the buffer is allocated ; by the calling program. .PSECT ASYBUF,D,RW,OVR,GBL ASYBUF: .END