.Title AlvEnable Alvin Device Enable .Psect Alvin,Gbl,Con .Ident /LVL51C/ .Globl LDevice, GetDDA .Mcall $Alvin, $RTdef, $IfTSX, $TSXjob .Mcall .Print, .SCCA, .Gval, .Lookup .Mcall .Serr, .RctrlO, .Protect ;+ ;;**************************************************************************** ;; AlvEnable - Subroutine to Enable an Alvin controlled device. ;; ;; Version 5.1c - Support for connection to a TSX CL controlled channel. ;; ;; Expects calls of the form: ;; Jsr Pc,AlvEnable ; With the logical unit number ;; ; to be enabled in reg 3. ;; < Aleda error codes return in register 0 > ;;**************************************************************************** ;; Last Modified: 4-Oct-85 DVJensen ;; 30-Oct-85 DVJ changed so only the unit number is passed in R3. This ;; is the standard way (and the only way) to communicate to ;; AlvEnable which device is to be enabled. ;- $RTdef ; Define the RT-11 offsets needed to get at the configuration. $Alvin ; Define Alvin structure offsets and status bits. BR4=200 ; Interrupt level 4. BR7=340 ; Interrupt level 7 - Used for RT interrupt convention. INTENABLE=100 ;Bit in DL-11 status word to enable interrupts. ;; AlvEnable:: Mov R4,-(SP) ;Save Registers Used. Mov R3,-(SP) Mov R2,-(SP) Mov R1,-(SP) ; Enter with logical unit number to be enabled ; in register 3. Alve15: Jsr R5,GetDDA ; Get the device descriptor base address. .Word -1 ; Use the unit number in R3. Bcc Alve20 ; Branch if the control block was found. Mov #-40.,R0 ; No, return error code- "UNIT OUT OF RANGE". Br AlvERX Alve20: ; Currently it is required that the control block is in the device ; descriptor table before it is enabled. This means that if a ; device descriptor is dynamically generated, it must be inserted ; into the table prior to the enable. ; If a redirected descriptor was enabled, Mov R0,R2 ; we now have actual device to be enabled. Bit #Disable,(R2) ; Is the device actually disabled? Bne Alve16 ; Yes, branch, it's OK to enable it. Mov #-22.,R0 ; No, then return error "DEV ALREADY ENA". Br AlvERX Alve16: Mov BDefault(R2),PDBadr(R2) ; Save the previous default buffer. Mov Lctl(R2),R4 ; Get the logical control word. $IfTSX ,TryRT ; Branch if not running under TSX-Plus. ;; TSX: Bit #RTctl,R4 ; Is this the console being enabled? Beq TryCL ; No, branch to check for CL support. .Gval #EMTWORK,#-4 ; Get TSX-Plus lead-in character. Mov R0,TSXLead ; Save the leadin character in the root. Movb #200,TSXLead+1 ; Force Bit 15 (negative) and clear rest of ; high byte. Let this hang around. Movb R0,SETtt ; Set the correct lead-in character Movb R0,SETtt+2 ; for all sequences. .Print #SETtt ; Allow JSW bits to be honored. Br RTconsole ; The rest is the same as RT. ;;******** ;; TryCL: ; This is TSX. Try for CL support. Bit #CLctl,R4 ; Is the descriptor typed for CL? Bne DoCL ; Yes, branch to do it. Mov #-41.,R0 ; No, then error "TSX ENABLE NOT ALLOWED". Br AlvERX DoCL: $TSXJOB TSXjob(R2) ; Get the TSX+ job number and save it. Movb CLunit(R2),R3 ; Yes, get the CL unit number and line number. Bit #177770,R3 ; Is this between 1 and 7? Bne CLfail ; No, error in CL unit number. Mov R3,Attunit ; Set the CL unit number for the attach. Add #^rCL0,R3 ; Add the unit to the device name. Mov R3,CLname ; Set the device name for allocate. Mov R3,CLookup ; Set the Device name for lookup. Mov #ChkAlloc,R0 ; Check if device is already allocated. EMT 375 Bcc ChkJob ; If carry is clear, it appears we are OK. CLfail: Mov #-38.,R0 ; Else error, "FAILED TO CONNECT TO CL". Br AlvERX ChkJob: Cmp R0,TSXjob(R2) ; Is the job with the allocation this job? Beq CLopen ; Yes, then presume we already have it setup. ;;******** Movb TSXLine(R2),AttLine ; Attach CL to a line? Beq CLalloc ; No, branch - presume CLx is setup. Mov #Attach,R0 ; Point R0 to the arg block. EMT 375 Bcs CLfail ; CLx attachment to TSX line failed - Branch. CLalloc: Mov #Allocate,R0 ; Now try to allocate CLx. EMT 375 Bcs NoAllocate ; Oops, we didn't get the allocation. Movb R0,AllocJob(R2) ; Yes, this is the unit which owns the alloc. Bne NoAllocate ; If non-zero someone else has it. Movb TSXjob(R2),AllocJob(R2) ; If zero we own the allocation. NoAllocate: CLopen: .Lookup #EMTwork,Lunit(R2),#CLookup ; Logical unit number = channel. Bcc EnaOK ; Branch if lookup succeeded. Mov #-42.,R0 ; Error code "FAILED TO OPEN CHANNEL". AlvERX: Sec ; Set carry if error. Br AlvEnx ; Exit with error code in R0. ;;******************************* TryRT: Bit #RTctl,R4 ; Is this console enable under RT? Beq NotConsole ; No, branch. RTConsole: ; Yes, then do the generic console setup. Bit #NoAbort,R4 ; Should we disallow Control-C to Abort? Beq DIEasy ; No, branch. .SCCA #EMTWORK,#RTTCC ;Disallow control-C abort. .Serr ; And also do soft error reporting. DIEasy: Bis #TTNoWait,@#RTJSW ; Set for non-block TTout. Bit #Output,R4 ; Should we also set for transparent input? Beq Forcit ; No, branch. Bis #TTspecial+TTuplow,@#RTJSW ; Yes, do this also. ForcIt: .RCtrlO ; Listen up to the change. EnaOK: Mov #Ignore,(R2) ; Setup the enabled status. Br AlveDone ; and Exit. ;;******** ;; NotConsole: Mov #Ldevice,R3 ; Get the Device Table Descriptor address. Mov DTDItable(R3),R3 ; Get the address of ITable for the desc. Bne RTDIcheck ; Branch if it is included. RTDIerr: Mov #-39.,R0 ; Cannot setup pseudo-CL under RT. Br AlvERX ;;******** RTDIcheck: Bit #CLctl,R4 ; Is this pseudo-CL under RT? Beq JustDI ; No, branch. Mov DITDin(R3),R0 ; Get adr of default input interrupt handler. Bit #Output,R4 ; Input or Output device? Beq RTDIset ; Branch for the input device. Mov DITDout(R3),R0 ; Get the default output interrupt handler. RTDIset: Tst R0 ; Is there such a default? Beq RTDIerror ; No, branch to return error code. Mov R0,Hndler(R2) ; Yes, override the CL handler with this one. Bic #RTctl!CLctl,Lctl(R2) ; It is a direct interrupt handler now. JustDI: ; Process Direct Interrupt Handler linkage: Mov (R3),R1 ; Get beginning address of interrupt table. DIfind: Tst DDAstore(R1) ; Is this one available? Beq DIgo ; Yes, go set it up. Add DITsize(R3),R1 ; Increment to next vector element. Cmp R1,DITend(R3) ; Past end of the table? Blo DIfind ; No, check next one. Br RTDIerror ; Yes, no room for this one - ERROR. DIgo: Mov Vector(R2),R3 ; The the vector from the desc. .Protect #EMTwork,R3 ; Protect the vector. Bcc DIconnect ; Branch if successfull. Mov #-44.,R0 ; Error "VECTOR IS SEIZED". Br AlvERX DIconnect: Mov #IGNORE,(R2) ; Initialize logical status to ignore. Mov DevAdr(R2),R0 ; Get the CSR address of the port. Mov (R0),PDSTAT(R2) ; Save actual device status Clr (R0) ; Disable interrupts Mov (R3),PENTRY(R2) ; Save previous entry address from vector Mov R1,(R3)+ ; This unit's interrupt entry adr to vector Mov (R3),PENTPS(R2) ; Save prev processor status from vector Mov R2,DDASTORE(R1) ; Store device desc in intrpt entry element Mov #BR7,(R3) ; Set up initial interrupt level. Mov #INTENABLE,(R0) ; Enable interrupts... AlvEdone: Clr R0 ; Return Code = 0 = OK. This also clears carry. AlvEnx: Mov (SP)+,R1 Mov (SP)+,R2 Mov (SP)+,R3 Mov (SP)+,R4 Rts Pc ; Return. ;;******************************* EMTWORK: .Word 0,0,0,0 ; Working location for EMT's. SetTT: .Byte 35,'S,35,'U,200 ; Tell TSX to do non-blocking TTin's and .Even ; single char activation - honor the JSW bits. Allocate: .Byte 0,156 ; TSX device ALLOCATE EMT arg block. .Word CLname ; Pointer to CLx device name. ChkAlloc: .Byte 2,156 ; TSX check if device allocated EMT arg block. .Word CLname ; Pointer to CLx device name. CLookup: .Rad50 'CL0' ; Device name for the lookup (unit filled in). CLname: .Rad50 'CL0' ; (unit number is filled in here and above) .Word 0,0,0 ; (the rest of the file spec must be zero) .RAD50 /CL1/ Attach: .Byte 0,155 ; Attach a CL unit to a line - EMT arg block. Attunit: .Word 0 ; CL unit number (filled in above). Attline: .Word 0 ; TSX line number (filled in above). ;;******************************* .Psect LRTTSX,Gbl,Con TSXLEAD:: .Word 0 ;TSX lead-in character ( in low byte ). ; High byte is TSX/RT Status: Negative = TSX. RTTCC:: .Word 0 ;Double control-C status word. ;;**************************************************************************** .END