.TITLE ALVIN Control Nucleus V5.1c .PSECT ALV51C,Gbl,Con .Ident /LVL51C/ .MCALL $Alv51 ;;********************************************************************** ;; ALVIN 7-01-77 BY DVJENSEN, AMES LAB COMPUTER SERVICES 50011 ;; VERSION ;; 28-JAN-82 5.0 - REVISED ALVIN NUCLEUS ;; 4-May-84 5.1 - Addition of Default buffer descriptor to Dev Desc. ;; - AlvEnable and AlvDisable written for Aleda. ;; 7-May-84 - Multiple Psects and some modules made separate. ;; 20-Jun-84 - Automatic Xon when buffer reduced within MARGIN ;; initiated by an output process - Subroutine UNSTALL. ;; 12-Jul-84 5.1A - DVJ added Send/Receive Function, UseDB, for using ;; the default buffer descriptor in the Dev Desc. ;; - Send and Receive now use GetDDA for accessing the ;; device descriptor address. ;; - A Send or Receive will not return an error if the ;; activation is for a Seized device which is active ;; on the same buffer as specified in the current Call. ;; 4-Sep-84 5.1B - FlowInput interrupt handler for serial flow control only ;; - Line Out interrupt handler will observe Offline as setup ;; by FlowIn. ;; 17-Jul-85 - Receive will process the function bits (complete the ;; receive setup) for a Seized device using same buffer. ;; 24-Jul-85 To avoid possible buffer pointer conflicts, A RECEIVE RESET ;; will not reset to the start of the buffer, but rather will ;; simply set the output pointer = input pointer. ;; 17-Sep-85 Version 5.1c includes support for TSX-Plus 5.1c CL ports. ;; - The direct interrupt handler code has been removed to a ;; separate psect module allowing for its exclusion if un-needed. ;; - RECEIVE nolonger will do the RTTon. This occurs at LENABLe. ;; - A fix to BUFSPACE. ;; - The ALV51C psect begins with the device table descriptor. ;; The address of ITable, the direct interrupt vector table, ;; is now accessed from the device table descriptor word 4. ;; This allows for the elimination of ITable by defining it zero. ;; 4-Oct-85 - The upper limit on number of devices is set to 16. ;; 6-May-86 - The upper limit on number of devices is set to 24. ;; - The RECEIVE RESET function will occur if the device is seized ;; and the request is for the same buffer. ;;********************************************************************** ;;********************************************************************** ;; NOTE: the following definition of the device control table descriptor ;; assumes that the user provides the DevTable and DevTEnd symbols. ;; This sets the actual limit to the number of devices. An upper limit ;; (which is more or less arbitrary) is set by the DEVICES definition. ;; .Globl DevTable, DevTEnd, ITable DEVICES==24. ;; LDevice:: .Word DevTable ; Base address of the Device Table. .Word DevTEnd ; Last address of the user's Table. .Word Devices ; The number of devices supported by Alvin. .Word ITable ; The address of the direct interrupt table. .Word DevDend ; Size in bytes of a device desc entry. ;;********************************************************************** ;; ALVIN Version Identification message: ;; ALVMSG:: .WORD INTRO1 ;TOP .WORD INTRO3 ;BOTTOM ;; INTRO1: .BYTE CR,LF,LF .ASCII '*** ALVIN ***' .BYTE CR,LF .ASCII 'Version 5.1c' .Byte Cr,Lf .Ascii '* 6-May-86 *' .BYTE CR,LF INTRO3: .BYTE LF .EVEN ;;********************************************************************** $Alv51 ;Define Alvin Version 5.1c constants. ;+ ;;********************************************************************** ;; G E N E R A L S U B R O U T I N E S ;;********************************************************************** .Psect Alvin,Gbl,Con .Sbttl Send Routine to initiate output to an Alvin device. ;;************** ;; SEND - An Alvin subroutine to initiate a transfer to an output device. ;; On return, R0 will be zero if an invalid device was specified; ;; otherwise, it will contain the address of the device control ;; block used for this output operation. ;; ;; Expects calls of the form: ;; JSR R5,SEND ;Initiate an output transfer. ;; .WORD (Function+Unit#) ;Function is optional (see below) ;; ;Unit# is the even byte. ;; .WORD (Buffer Descriptor address) ;; BR UNITSZD ;Invalid unit # or unit active exit. ;; ;; Note 1: The "STRING" control bit specified as a function will cause ;; the buffer descriptor parameter to be interpreted as a ;; static string descriptor, in which case the dynamic buffer ;; descriptor in the device control block is configured as the ;; buffer descriptor to send from. ;; Note 2: If the buffer descriptor parm is zero, then this parm is ;; assumed to already be in register 4. ;; Note 3: If the unit# is negative (bit 200 set), then ;; the unit#/function is assumed to be in register 3. ;; .Globl GetDDA ;- SEND:: MOV R4,-(SP) ;SAVE REGISTERS USED MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV (R5)+,R1 ;Get unit number and function. TSTB R1 ;Is the unit # negative? BMI SEND05 ;Yes, then unit#/control is already in reg 3. MOV R1,R3 ;Put parm in work register Send05: MOV (R5)+,R1 ;Get the Buffer Descriptor Address. BEQ SEND10 ;If zero then buf desc adr already in reg 4. MOV R1,R4 ;Put Parm where it belongs. SEND10: Jsr R5,GetDDA ;Get the Device Descriptor Address of the unit. .Word -1 ;Use the Unit number in R3 Mov R0,R2 ;Move the Dev Desc Adr to Reg 2. Beq SendUP ;If zero, then no Desc - invalid unit# Exit. Bit #Output,Lctl(R2) ;Is this an output device? Beq SendUP ;No, branch - invalid unit exit. Bit #UseDB,R3 ;Did user request to use the default buffer? Beq Send13 ;No, Branch. Mov BDefault(R2),R4 ;Yes, use the default buf desc adr. Beq SendUP ;If zero, it is not defined - error exit. Send13: Bit #Request!Disable,(R2) ;Is there a request pending? Bne SendUP ;Yes, must exit. Bis #Request,(R2) ;Lock out other requests for the device. Bit #Seized,(R2) ;Is device available? Beq Send15 ;Yes, branch. Br SendNO ; Debug - force this to be an error. Cmp R4,BDAdr(R2) ;Trying to initiate for the active buffer? Beq SendOK ;Already active - return no error indication. Br SendNO ;Busy with something else - return error exit. Send15: Bit #STRING,R3 ;Is a static string desc function bit set? Beq SENDBD ;No, proceed presuming a buffer desc. Mov R4,R0 ;Move string desc to work reg Cmp (R0),2(R0) ;Is this a valid static string desc? Bhi SENDNO ;No, cannot send Mov R2,R4 ;Get base address of device desc Add #BDESC0,R4 ;Calculate address of dynamic buf desc MOV R4,R1 ;Put in work reg MOV (R0),(R1)+ ;Set up the buf desc MOV (R0),(R1)+ ;As full buffer MOV (R0)+,(R1)+ MOV (R0),(R1) BR SENDGO ;Proceed normally now. SENDBD: CMP BIN(R4),BOUT(R4) ;Is INPUT PTR=OUTPUT PTR? Beq SendOK ;Yes, nothing to send but not an error. SENDGO: MOV R4,BDADR(R2) ;Put buffer desc adr in device ctl block MOV #SEIZED!Request,R0 ; Build the new logical status. MOV R3,R1 ;Get the send function BIS LCTL(R2),R1 ;Merge with permanent device characteristics BIT #PAROFF,R1 ;Is parity bit removal (zero) requested? BEQ SEND20 ;No, branch BIS #CLRPARITY,R0 ;Yes, mark the logical (temporary) status SEND20: BIT #PARON,R1 ;Is parity bit addition (one) requested? BEQ SENDIT ;No, branch BIS #SETPARITY,R0 ;Yes, mark the logical (temporary) status SENDIT: Mov R0,(R2) ; Set the device status. BIT #RTctl!CLctl,LCTL(R2) ;Is this an RT or CL controlled device? Bne SENDOK ;Yes, then let Alvupd do the rest. ;; SENDALV: ; Alvin controlled direct DL(v)-11 output: MovB @BOUT(R4),R0 ;Get the first character to be sent. Jsr PC,Parit ;Set the parity bit per request. MOV DEVADR(R2),R1 ;Get the actual device status adr. MOVB R0,2(R1) ;Send the character. SendOK: Tst (R5)+ ;Increment return address past error exit. SENDNO: BIC #REQUEST,(R2) ;Clear request indicator. SendUP: Jsr Pc,AlvUpdate ;Do transfers for Control'd devices & Flowctl. Mov R2,R0 ;Return the Device Descriptor Adr to User. MOV (SP)+,R1 ;Restore other registers. MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 RTS R5 ;RETURN TO CALLING ROUTINE ;+ ;;********************************************************************** .Sbttl Receive Routine to initiate input from an Alvin device. ;;************** ;; RECEIVE - Alvin subroutine to initiate a transfer from an input device. ;; On return R0 will contain zero if an invalid unit was specified; ;; otherwise it will contain the address of the control block used. ;; ;; Expects calls of the form: ;; JSR R5,RECEIVE ;; .WORD (FUNCTION+UNIT #) ;The unit number is in the even byte. ;; ;Function optional (see below). ;; .WORD (Buffer Descriptor address) ;; BR UNITSZD ;Invalid unit # or unit seized exit. ;; ;; ;; Note 1: If the buffer descriptor parm is zero, then this parm is ;; assumed to already be in register 4. ;; Note 2: If the unit# is negative, then the unit#/function is assumed ;; to be in register 3. ;; ;;;;;;;;;;;;;;;;;; ;; Unit logical control word bit definitions, for reference only, ;; actually defined by the $AlvXX Macro. ;; ; ATACHD=100000 ;UNIT IS ATTACHED (not used - but reserved) ; SNDBRK=010000 ;Unit is allowed to send breaks (OUTPUT only) ; SILENT=010000 ;Initiate receive with NOECHO enabled (INPUT only) ; PARON= 004000 ;PARITY IS BY DEFAULT TO BE FORCED ON (OUTPUT ONLY) ; PAROFF=002000 ;PARITY IS BY DEFAULT TO BE FORCED OFF (OUTPUT ONLY) ; (Someday ... SETTING BOTH PARON & PAROFF WILL RESULT IN EVEN PARITY) ; STREAM=000001 ;UNIT HAS STREAM LIST ENABLED (PRINTED OUTPUT ONLY) ; PAGE= 000002 ;UNIT HAS PAGE FORMATING ENABLED (PRINTED OUTPUT ONLY) ; OUTPUT=000004 ;Unit is enabled for output - absence indicates input. ; RTCTL= 000010 ;UNIT IS AN RT-11 CONTROLLED DEVICE (CONSOLE ONLY) ; ECHO= 000020 ;Unit is to echo chars thru ASOCDEVICE (INPUT only) ; FLOWCTL=00040 ;Unit enabled for flow control (ie,Xon/Xoff Input stream) ;; ADDITIONAL SEND & RECEIVE CONTROL BIT DEFINITIONS ; RESET= 001000 ;RECIEVE FUNCTION FOR RESETTING BUFFER POINTERS ; STRING=020000 ;SEND FUNCTION INDICATING STRING DESCRIPTOR PROVIDED ; UseDB= 40000 ;Function indicating the Default Buffer is to be used. ;; (Bit 400 is reserved as a control word continuation indicator ;; for Send/Receive calls.) ;; (All high-byte control word bits can be also be used as ;; Send/Receive functions at the time of the call. ;;::::::::::::::::::: ;; .Globl AlvUpdate,GetDDA ;- RECEIVE:: MOV R4,-(SP) ;SAVE REGISTERS USED MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV (R5)+,R2 ;GET UNIT NUMBER AND FUNCTION OPTIONS TSTB R2 ;IS THE UNIT NUMBER NEGATIVE? BMI RECV10 ;YES, BRANCH - UNIT/FUNCTION IS IN REG 3 MOV R2,R3 ;PUT UNIT/FUNCTION INTO CORRECT REG RECV10: MOV (R5)+,R2 ;GET BUFFER DESC PARM BEQ RECV20 ;IF ZERO, THEN BUF DESC IS ALREADY IN R4 MOV R2,R4 ;ELSE PUT IT WHERE IT BELONGS RECV20: Jsr R5,GetDDA ;Get the Device Descriptor Address .Word -1 ; of the unit specified in Register 3. Mov R0,R2 ;Put the Dev Desc where it belongs. Beq RecvUP ;If zero, then invalid - take the error exit. Bit #Output,Lctl(R2) ;Is this an input device? Bne RecvUP ;No, branch to the error exit. Bit #UseDB,R3 ;Did user specify to use the default buf? Beq Recv23 ;No, branch. Mov BDefault(R2),R4 ;Yes, Get the correct buffer descriptor. Beq RecvUP ;If zero, it is not defined - error exit. Recv23: BIT #REQUEST!DISABLE,(R2) ;Is the device available? BNE RecvUP ;No, must exit. BIS #REQUEST,(R2) ;Set request indicator to lockout others. BIT #SEIZED,(R2) ;Is the device seized? Beq Recv25 ;No, branch. Cmp R4,BDadr(R2) ;Is the an activation on the current buffer? Bne RecvNO ;No, then return an error - device active. ; Yes, then no error - Proceed with functions. ; Bic #NoEcho,(R2) ; Set for a change in echo mode. Br Recv45 ; Skip over reset in status, just reset buf. Recv25: MOV #SEIZED!REQUEST,(R2) ; Build new status - seize & retain MOV R4,BDADR(R2) ; Move buf desc adr to device desc. RECV30: CLRB R3 ;GET RID OF THE UNIT NUMBER BIS LCTL(R2),R3 ;MERGE FUNCTION WITH PERMANENT BIT #FLOWCTL,R3 ;Is flow to be controlled? BEQ RECV40 ;No, branch JSR PC,BUFSIZE ;Calculate the size of this buffer. ASR R0 ;Count returned in r0 - divide by 8 ASR R0 ; for the margin point to Xoff/Xon. ASR R0 MOV R0,BUFMARGIN(R2) ;Put buffer margin into Dev Desc RECV40: BIT #SILENT,R3 ; Should noecho (silent) be enabled? BEQ Recv45 ; No, branch BIS #NOECHO,(R2) ; Yes, set noecho in device status Recv45: BIT #RESET,R3 ; Are the buffer pointers to be RESET? BEQ RECVOK ; No, branch. Mov (R4),Bout(R4) ; Flush any characters in buffer. RecvSeize: RecvOK: TST (R5)+ ;Incr return adr - success. RecvNO: Bic #Request,(R2) ;Activity on device desc done RecvUP: Jsr PC,AlvUpdate ;See if transfers can be done. Mov R2,R0 ;Return the Device Desc Adr to the user. MOV (SP)+,R1 ;Restore Registers. MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 RTS R5 ;RETURN VIA REGISTER 5 ;+ ;;********************************************************************** .Sbttl ResetBufferPointers of an Alvin buffer. ;;************** ;; RESETBUF - Alvin subroutine to reset the input and output pointers ;; of an Alvin buffer descriptor to the start of the buffer. ;; Expects calls of the form: ;; JSR PC,RESETBUF ;; NOTE: The buffer descriptor address is assumed to be in register 4. ;- RESETBUF:: MOV BSTART(R4),BIN(R4) ;SET INPUT PTR TO START OF BUFFER MOV BSTART(R4),BOUT(R4) ;SET OUTPUT PTR TO START OF BUFFER RTS PC ;RETURN ;+ ;;********************************************************************** .Sbttl Bufin Register based circular buffer input. ;;************** ;; BUFIN - Alvin device handler subroutine to move a character in ;; register 0 into an Alvin buffer. ;; Assumes the buffer descriptor address is in register 4. ;; Assumes the device descriptor address is in register 2. ;; The RESPONSE status bit is always set indicating activity. ;; The buffer-full (BUFULL) status bit is conditionally set ;; if the input pointer catches up with the output pointer, ;; in which case the input pointer is not updated. ;; ;; Expects calls of the form: JSR PC,BUFIN ;w/ R2 and R4 setup. ;- BUFIN:: MOV R3,-(SP) ;Save work register MOV BIN(R4),R3 ;BRING BUF INPUT PTR LOCAL MOVB R0,(R3)+ ;MOVE CHAR TO BUFFER & INCREMENT BY 1 CMP BEND(R4),R3 ;AT END OF BUFFER? BHIS BUFINS ;NO, JUMP MOV BSTART(R4),R3 ;YES, WRAP AROUND BUFINS: CMP R3,BOUT(R4) ;BUFFER NOW FULL? (INPUT PTR=OUTPUT PTR?) BNE BUFINU ;NO, BRANCH TO UPDATE THE INPUT POINTER BIS #BUFULL!RESPONSE,(R2) ;STATUS BUFFER FULL & RESPONSE BR BUFINX ;AND EXIT BUFINU: MOV R3,BIN(R4) ;UPDATE THE BUFFER INPUT POINTER BIS #RESPONSE,(R2) ;SET RESPONSE IF CHAR ENTERED INTO BUF BUFINX: MOV (SP)+,R3 ;Restore work register RTS PC ;RETURN ;+ ;;********************************************************************** .Sbttl Bufout Register based circular buffer output. ;;************** ;; BUFOUT - Alvin device handler subroutine to update the output ;; buffer pointer in the buffer descriptor by one. ;; Assumes the buffer descriptor address is in register 4. ;; Register 0 is modified and on return will contain the updated ;; value of the output pointer (i.e, point to the next char). ;; ;; Expects calls of the form: JSR PC,BUFOUT ;w/ R4 setup. ;; ; Return with R0 = new Output Pointer. ;- BUFOUT:: MOV BOUT(R4),R0 ;Get output pointer from buffer descriptor INC R0 ;Increment by one CMP BEND(R4),R0 ;Exceeded buffer end - need to wrap? BHIS BUFOUP ;No, branch MOV BSTART(R4),R0 ;Yes, wrap around back to the start BUFOUP: MOV R0,BOUT(R4) ;Update output pointer in buf desc RTS PC ;And return with R0 pointing to next char ;+ ;;********************************************************************** .Sbttl Parit Register Based parity insertion/deletion. ;;************** ;; PARIT - Alvin subroutine to set or clear the parity bit of the ;; character is register 0 dependent on the status of the device ;; whose descriptor address is in register 2. ;; ;; Expects calls of the form: JSR PC,PARIT ;w/ R2 & R0 Setup. ;- PARIT:: BIT #SETPARITY,(R2) ;SHOULD PARITY BIT BE FORCED ON? BEQ PARITC ;NO, BRANCH BIS #200,R0 ;YES, TURN PARITY BIT ON BR PARITX ;GO SEND IT PARITC: BIT #CLRPARITY,(R2) ;SHOULD PARITY BIT BE FORCED OFF? BEQ PARITX ;NO, BRANCH BIC #200,R0 ;YES, CLEAR THE BIT PARITX: RTS PC ;RETURN ;+ ;;********************************************************************** .Sbttl BufCount Routine to count number of chars in cir buffer. ;;************** ;; BUFCOUNT - Subroutine to calculate the number of characters ;; in a buffer whose descriptor address is in register 4. ;; The resultant count will be returned in register 0. ;; ;; Expects calls of the form: JSR PC,BUFCOUNT ;w/ R4 Setup. ;- BUFCOUNT:: MOV BIN(R4),R0 ;Get the buffer input pointer SUB BOUT(R4),R0 ;Subtract the output pointer BCC BUFCEXIT ;If carry clear, then done ADD BEND(R4),R0 ;Add end address of buffer (END-OUT+IN) INC R0 ;Add one (END-OUT+IN+1) SUB BSTART(R4),R0 ;Remove starting address (IN-BEGIN+END-OUT+1) BUFCEXIT: RTS PC ;Return ;+ ;;********************************************************************** .Sbttl BufSize Routine to return size of a circular buffer. ;;************** ;; BUFSIZE - Subroutine to calculate the size (in bytes) ;; of a buffer whose descriptor address is in register 4. ;; The resultant count will be returned in register 0. ;; ;; Expects calls of the form: JSR PC,BUFSIZE ;w/ R4 setup. ;- BUFSIZE:: MOV BEND(R4),R0 ;Get ending address of buffer SUB BSTART(R4),R0 ;Subtract start address RTS PC ;Done (one byte is always wasted) ;+ ;;********************************************************************** .Sbttl BufSpace Calculate available space in a circular buffer. ;;************** ;; BUFSPACE - Subroutine to calculate the available space (in bytes) ;; of a buffer whose descriptor address is in register 4. ;; The resultant count will be returned in register 0. ;; ;; Expects calls of the form: JSR PC,BUFSPACE ; w/ R4 setup. ;- BUFSPACE:: MOV BOUT(R4),R0 ; Get the output pointer SUB BIN(R4),R0 ; Subtract the input pointer value BCC BUFSP2 ; If carry clear, decrement by one. ADD BEND(R4),R0 ; Else, add end address of buffer less SUB BSTART(R4),R0 ; start of buffer (size of buffer) RTS PC ; Return with space calculated in REG 0. BufSP2: Dec R0 ; One location is wasted: Output pointer is Rts Pc ; a used location and Input Ptr cannot ; catchup and equal it (or buffer is empty). ;;**************************************************************************** ;;**************************************************************************** ;; .END