.title DUSTAT.MAC .list me ; DUSTAT V2.00 ; Tim Shoppa (shoppa@triumf.ca), 28-Jan-1998 ; At the CSI prompt, DUSTAT takes a single device name. ; ; If the device is not a (T)MSCP device, the .DSTATUS information about ; the device is displayed, and an attempt is made to size the device ; with .SPFUN #373 if this is applicable. ; ; If the device is a (T)MSCP device, the .DSTATUS information normally ; isn't displayed (though the /D switch can be used to force its display.) ; MSCP devices are sized with .SPFUN #373, (T)MSCP partition information ; is displayed, and the (T)MSCP information available about the device's ; controller and unit information is displayed. If the /S (scan) switch ; is given, all the (T)MSCP units attached at that device's CSR are ; also probed and displayed. ; ; Revision history ; 1.00 10-Jan-1998 TDS Original working version ; 1.01 15-Jan-1998 TDS Add probing of TMSCP controllers, too. ; 1.02 28-Jan-1998 TDS Fix bugs in TMSCP logic, add .CSTAT ; and .DSTAT error messages, fix bit ; list for .DSTAT flags, small ; changes in controller list. ; 2.00 04-Mar-1998 TDS TMSCP devices have correct display, ; including density support. ; New (T)MSCP controllers in list, new ; .DSTAT devices, too. More detailed ; interpretation of unit and controller flags, ; status codes interpreted and displayed. ; New output buffering routine allows for ; cleaner displays. Output can be sent to ; LP, LS, or a file. .mcall .CSISPC,.DSTAT,.FETCH,.SPFUN,.EXIT,.CLOSE,.SRESET,.PRINT .mcall .LOOKUP,.CSTAT,.ENTER,.WRITW,.ASSUME ; Macros for output formatting ; example usage for left-justified string: ; CLRBUF ; TEXT ; NUMBER DEC1,R3 ; OUTBUF ; output from above will look like ; "This probram is brought to you by the number 6." ; (note that 3 characters are reserved for a decimal byte output, and that ; decimal values end with a decimal point.) ; ; example usage for left-right column format ; CLRBUF ; TEXTL ; NUML DEC1,R3 ; TEXTR ; STRR R0 ;R0 points to string "RQDX3", null terminated ; OUTBUF ; output from above will look like ; Left text 6. Right text RQDX3 ;12345678901234567890123456789012345678901234567890123456789012345678901234567 ; 1 2 3 4 5 6 7 .MACRO CLRBUF ;clear output buffer CALL CLRBUF .ENDM .MACRO OUTBUF ;output the buffer CALL OUTBUF .ENDM .MACRO TEXTL STR ;left-hand side text .SAVE .PSECT STRING $ = . .ASCIZ "STR" .RESTORE JSR R5,MOVSTR .WORD $ .WORD LINBUF+4. .ENDM .MACRO TEXTR STR ;right-hand side text .SAVE .PSECT STRING $ = . .ASCIZ "STR" .RESTORE JSR R5,MOVSTR .WORD $ .WORD LINBUF+40. .ENDM .MACRO TEXT STR ;output left-justified text .SAVE .PSECT STRING ;with word breaks as necessary $ = . .ASCIZ "STR" .RESTORE JSR R5,TEXT .WORD $ .ENDM .MACRO TEXTR0 ;output left-justified text pointed at by R0 CALL TEXTR0 .ENDM ;legal values for TYPE are OCT1, OCT2, DEC1, DEC2, DEC4. Numeral ;indicates number of bytes in the type. .MACRO NUMBER TYPE,N ;Display number as type. Default N=R1 .IF NB .IF EQ SZ'TYPE-1 CLR R1 BISB N,R1 .ENDC .IF EQ SZ'TYPE-2 MOV N,R1 .ENDC .IF EQ SZ'TYPE-4 MOV N+2,R1 MOV N,R2 .ENDC .ENDC CALL PR'TYPE .ENDM DGDEC1= 3. DGDEC2= 5. DGDEC4=10. DGOCT1= 3. DGOCT2= 6. SZDEC1= 1. SZDEC2= 2. SZDEC4= 4. SZOCT1= 1. SZOCT2= 2. .MACRO NUMG TAB,TYPE,N MOV #LINBUF+TAB-DG'TYPE,LINPTR NUMBER TYPE,N .ENDM .MACRO NUML TYPE,N NUMG 35.,TYPE,N .ENDM .MACRO NUMR TYPE,N NUMG 77.,TYPE,N .ENDM ;Macro for handling fatal errors .MACRO FATALE STR .SAVE .PSECT STRING $ = . .ASCIZ "STR" .RESTORE BCC .+12 MOV #$,R5 JMP FATAL .ENDM ;Macro for handling fatal errors without flushing output file .MACRO FATAL2 STR .SAVE .PSECT STRING $ = . .ASCIZ "STR" .RESTORE BCC .+12 MOV #$,R5 JMP FATAL2 .ENDM START: MOV #HANLOD,HANPTR ;Where to load handlers .CSISPC #OUTSP,#DEXT;,,#LINBUF ;Get device spec CLR DFLAG CLR SFLAG MOV (SP)+,R0 BEQ NOOPT 4$: MOV (SP)+,R1 ;Get next option BMI 10$ ;Did we have a value MOV #32.,-(SP) ;If not, default one! 10$: CMPB #'D,R1 ;D option to display .DSTAT info BEQ 12$ ;for MSCP devices CMPB #'d,R1 BNE 14$ 12$: MOV (SP)+,DFLAG BR 20$ 14$: CMPB #'S,R1 ;S option to scan other MSCP units BEQ 16$ ;default to first 32 units CMPB #'s,R1 ;but numeric value will set limit BNE 20$ 16$: MOV (SP)+,SFLAG 20$: SOB R0,4$ NOOPT: 2$: MOV #OUTSP+<5*2>,R2 ;User was only supposed to specify ;one input device and up to one output ;device:filename. MOV #<5*2>,R3 ;If anything 3$: TST (R2)+ ;else has been specified, complain. BNE 10$ SOB R3,3$ TST (R2)+ MOV #<6*4-1>,R3 4$: TST (R2)+ BNE 10$ SOB R3,4$ BR NGRIPE 10$: .PRINT #GRIPE BR START NGRIPE: TST INSPEC ;If no input file specified, BNE 1$ .PRINT #VERSON ;display version information BR START ;and get a new CSI line 1$: CALL BLKOPE ;open the output file, if there ;is one 70$: CLRBUF .DSTAT #STAT,#INSPEC ;Do a .DSTAT on the specified device FATALE MOV STAT,R1 ;If the device is number 50 BIC #177400,R1 ;(a MSCP device), or 60 (TMSCP) CLR MSCP ;set special flags CLR TMSCP CMP R1,#50 ;MSCP? BNE 3$ DEC MSCP BR 4$ 3$: CMP R1,#60 ;TMSCP? BNE 7$ DEC TMSCP ;Fill TMSCP with minus 1 4$: TST DFLAG ;unless /D was specified BEQ VARSIZ ;we don't display .DSTAT info 7$: MOV SP,DFLAG ;we definitely are displaying .DSTAT MOV #DEVTBL,R2 10$: CMP (R2)+,R1 ;Find the controller name in table BEQ 40$ ;found it! TST (R2)+ ;a zero here means end of table BNE 10$ ;if not end, check next entry 40$: MOV (R2),R0 TEXTR0 OUTBUF CLRBUF OUTBUF CLRBUF DBITS: CLR COMMA9 MOV #8.,R3 ;8 status bits to be checked MOV #BITTAB,R2 MOV STAT,R1 SWAB R1 2$: ROR R1 BCS 10$ MOV (R2)+,R0 ;here if bit is clear TST (R2)+ BR 20$ 10$: TST (R2)+ ;here if bit is set MOV (R2)+,R0 20$: CALL COMR0N SOB R3,2$ OUTBUF CLRBUF OUTBUF CLRBUF TEXTL NUML OCT2,STAT TEXTR NUMR DEC2,STAT+2 OUTBUF CLRBUF MOV STAT,R1 BPL SEQDEV ;is it a sequential device? SWAB R1 ;is it a variable-size device? ROR R1 BCS VARSIZ TEXTL <.DSTAT device size> ;if here, it's a fixed-size device NUML DEC2,STAT+6 SEQDEV: OUTBUF CLRBUF TST TMSCP ;Is it TMSCP? BNE VARSIZ JMP START VARSIZ: TST STAT+4 BNE NOLOAD .FETCH HANPTR,#INSPEC FATALE NOLOAD: .LOOKUP #AREA,#3,#INSPEC,TMSCP ;If a tape device, the -1 in ;TMSCP is a *no rewind* FATALE TST TMSCP BNE ISTMSC TST DFLAG BEQ NO373 .SPFUN #AREA,#3,#373,#BUFF,#1,#0,#0 ;Look up device size BCC LUWORK TEXTR <.SPFUN #373 device size unavailable> BR LUFAIL m1: .asciz /m1/ m2: .asciz /m2/ m3: .asciz /m3/ m4: .asciz /m4/ ;Note we do not regard a .SPFUN #373 failure as fatal. It may be, for ;example, that an existing floppy drive is not mounted. LUWORK: TEXTL <.DSTAT minimum device size> NUML DEC2,STAT+6 TEXTR <.SPFUN #373 device size> NUMR DEC2,BUFF LUFAIL: OUTBUF CLRBUF OUTBUF CLRBUF TST MSCP ;Is it MSCP? BNE ISMSCP JMP AGAIN NO373: ISMSCP: ;It is MSCP device MOV #372,R3 ;Table lookup is .SPFUN 372 for disk BR DOCST ISTMSC: MOV #352,R3 ;or .SPFUN 373 for tape ; Get DU unit number into R4 DOCST: MOV #CSTATD,R2 .CSTAT #AREA,#3,R2 ;CSTAT seems to be the clever way FATALE <.CSTAT failure> MOV 10(R2),R4 ;Unit number is 5th word MOV #BUFF,R2 DUTTSZ=<<64.+1>*2> ;DU translation table size (words) .SPFUN #AREA,#3,R3,R2,#DUTTSZ;Read translation table into buffer FATALE TST (R2)+ ;Get the number of translations into R3 ; The number of MSCP translations is a byte, the number of TMSCP ; translations is a word. Confusing, eh? TST TMSCP BNE 14$ CLR R3 ;Fetch just a byte if MSCP BISB (R2)+,R3 TSTB (R2)+ BR 16$ 14$: MOV (R2)+,R3 ;Fetch a whole word if TMSCP 16$: CMP R4,R3 BLO ISTRAN SEC FATALE ISTRAN: ADD R4,R2 ;Go to the R4th entry in the table ADD R4,R2 ADD R4,R2 ADD R4,R2 TEXT CLR R1 BISB 3(R2),R1 MOV R1,PORT NUMBER DEC1 TEXT < UNIT=> MOV (R2),R1 MOV R1,UNIT NUMBER DEC2 ;if TMSCP, this byte is a user job flag. If MSCP, it is partition number TST TMSCP BNE UJFLG TEXT < PART=> NUMBER DEC1,2(R2) BR TT3ENT UJFLG: TEXT < owner job# flag=> NUMBER OCT1,2(R2) TT3ENT: CALL OUTBUF CALL CLRBUF CALL OUTBUF CALL CLRBUF P.CRF= 0 ; 4 Command reference number P.UNIT= 4 ; 2 Unit number P.OPCD= 10 ; 1 Opcode ; MSCP OPCODES OP.SCC= 04 ; SET CONTROLLER CHARACTERISTICS Command OP.ONL= 11 ; ONLINE Command OP.GUS= 03 ; GET UNIT STATUS Command OP.AVL= 10 ; AVAILABLE Command OP.FMT= 24. ; FORMAT Command ;RQZX1 OP.SP8= 47. ; FORMAT Command for the RQDX3 ;RQZX1 P.MOD= 12 ; 2 Modifiers P.BCNT= 14 ; 4 Byte count P.BUFF= 20 ; 12 Buffer descriptor P.LBN= 34 ; 4 Logical block number ; ONLINE Command Message Offsets P.UNFL= 16 ; 2 Unit flags P.DVPM= 34 ; 4 Device dependent parameters P.SHUN= 40 ; 2 Shadow unit P.CPSP= 42 ; 2 Copy speed ; ONLINE Command Modifiers MD.IFM= 02 ; Ignore Media Format Errors ;RQZX1 ; SET CONTROLLER CHARACTERISTICS Command Message Offsets P.VRSN= 14 ; 2 MSCP version P.CNTF= 16 ; 2 Controller flags P.HTMO= 20 ; 2 Host timeout P.TIME= 24 ; 8 Quad-word time and date ; FORMAT Command Message Offsets P.FMTI= 34 ; 4 Format information ; END MESSAGE OFFSETS P.CRF= 0 ; 4 Command reference number P.UNIT= 4 ; 2 Unit number P.OPCD= 10 ; 1 Opcode ; MSCP OPCODES OP.END= 200 ; End message flag P.FLGS= 11 ; 1 End message flags P.STS= 12 ; 2 Status ; MSCP STATUS CODES ST.MSK= 37 ; Status / event code mask ST.SUC= 0 ; Success ST.OFL= 3 ; Unit-Offline NOVOLM= 40 ; No volume mounted ST.MFE= 5 ; Media Format Error ST.WPR= 6 ; Write protected P.BCNT= 14 ; 4 Byte count P.FBBK= 34 ; 4 First bad block ; GET UNIT STATUS End Message Offsets P.MLUN= 14 ; 2 Multi-unit code P.UNFL= 16 ; 2 Unit flags ; Unit flags UF.RMV= 00200 ; Bit - Removable UF.WPH= 20000 ; Bit - Write protect (hardware) UF.WPS= 10000 ; Bit - Write protect (software or volume) P.UNTI= 24 ; 8 Unit identifier P.MEDI= 34 ; 4 Media type identifier P.SHUN= 40 ; 2 Shadow unit (disk) density (tape) P.SHST= 42 ; 2 Shadow status (disk) speed (ips*bpi/1000) (tape) P.TRCK= 44 ; 2 Track size (disk) format menu (tape) P.GRP= 46 ; 2 Group size (disk) max write byte count (tape) P.CYL= 50 ; 2 Cylinder size (disk) max noise rec size (tape) P.USVR= 52 ; 1 Unit software version P.UHVR= 53 ; 1 Unit hardware version P.RCTS= 54 ; 2 RCT table size P.RBNS= 56 ; 1 RBNs / track P.RCTC= 57 ; 1 RCT copies ; ONLINE End Message Offsets P.MLUN= 14 ; 2 Multi-unit code P.UNFL= 16 ; 2 Unit flags ; Unit flags UF.WPH= 20000 ; Bit - Write protect (hardware) UF.WPS= 10000 ; Bit - Write protect (software or volume) P.UNTI= 24 ; 8 Unit identifier P.MEDI= 34 ; 4 Media type identifier P.SHUN= 40 ; 2 Shadow unit P.SHST= 42 ; 2 Shadow status P.UNSZ= 44 ; 4 Unit size P.VSER= 50 ; 4 Volume serial number ; SET CONTROLLER CHARACTERISTICS End Message Offsets P.VRSN= 14 ; 2 MSCP version P.CNTF= 16 ; 2 controller flags P.CTMO= 20 ; 2 controller timeout P.CSVR= 22 ; 1 controller software version P.CHVR= 23 ; 1 controller hardware version P.CNTI= 24 ; 8 controller ID CF.RPL=100000 ;Bit - controller-initiated BBR CLR CMDBUF+P.UNIT ;Clear the physical unit number JSR R5,BYPASS ;and set controller characteristics .WORD OP.SCC FATALE TEXT NUMBER DEC1,PORT TEXT < is a > TABLK: CLR R0 BISB RSPBUF+P.CNTI+6,R0 ;Get the controller ID byte MOV #MSCTBL,R2 10$: CMP (R2)+,R0 ;look up the numeric value in BEQ 32$ ;table of translations TST (R2)+ BNE 10$ ;a zero here means end of table 32$: MOV (R2),R0 ;the string to print TEXTR0 CONDIS: MOV SP,COMMA9 ;we will print commas MOV RSPBUF+P.CNTF,R1 ;test controller bits MOV #16.,R3 ;16. status bits to be checked MOV #CONBIT,R2 2$: MOV (R2)+,R0 ROR R1 BCC 10$ ;is bit set? CALL COMR0N ;if set, print meaning 10$: SOB R3,2$ TEXT <.> OUTBUF CLRBUF OUTBUF CLRBUF TEXTL NUML OCT2,RSPBUF+P.CNTF TEXTR NUMR DEC2,RSPBUF+P.VRSN OUTBUF CLRBUF TEXTL NUML DEC1,RSPBUF+P.CSVR TEXTR NUMR DEC1,RSPBUF+P.CHVR OUTBUF CLRBUF TEXTL MOV #RSPBUF+P.CNTI,R2 MOV #4,R3 MOV #LINBUF+35.-<4*DGOCT1>-3,LINPTR 20$: NUMBER OCT1,(R2)+ INC LINPTR SOB R3,20$ TEXTR MOV #4,R3 MOV #LINBUF+77.-<4*DGOCT1>-3,LINPTR 30$: NUMBER OCT1,(R2)+ INC LINPTR SOB R3,30$ OUTBUF CLRBUF OUTBUF CLRBUF TST SFLAG BEQ 70$ CLR UNIT BR AUNIT 70$: MOV UNIT,SFLAG AUNIT: CALL CLRUNI ;clear flags for bit interp MOV UNIT,CMDBUF+P.UNIT ;Set unit number we want JSR R5,BYPASS ;And put device available .WORD OP.AVL FATALE CALL SETUNI ;set interp of P.STS JSR R5,BYPASS ;Now try to put device online .WORD OP.ONL BCC TRANCOD CMP #ST.OFL!NOVOLM,RSPBUF+P.STS ;Is there a volume mounted? BNE TRANCOD ;Yes, continue SEC FATALE TRANCOD:CALL SETUNI ;set interp of P.STS MOV #RSPBUF,R0 MOV #ONLBUF,R1 MOV #RSPLEN,R2 1$: MOVB (R0)+,(R1)+ SOB R2,1$ JSR R5,BYPASS ;Now try to get unit status .WORD OP.GUS FATALE CALL SETUNI ;set interp of P.STS MOV ONLBUF+P.MEDI,R0 BNE 1$ JMP NUNIT ;If this field blank, no unit there 1$: TEXT NUMBER DEC1,UNIT TEXT < is a > ;Translate the media type code. Rightmost 7 bits indicates a decimal ;number, presumably in range 00-99; Each group of 5 bits remaining is ;a letter, encoded as 1=A, 26=Z, 0=nothing. 4$: MOV ONLBUF+P.MEDI,R0 BIC #177600,R0 MOV #MEDTRD,R1 MOVB #'0,(R1) ;Clear tens digit 10$: CMP R0,#10. BLO 12$ SUB #10.,R0 INCB (R1) ;Bump tens digit BR 10$ 12$: ADD #'0,R0 MOVB R0,1(R1) ;set ones digit MOV ONLBUF+P.MEDI,R2 MOV ONLBUF+P.MEDI+2,R3 MOV #5,R5 ;up to 5 chars MOV #7,R4 ;initial shift is 7 (to clear out digits) BR 40$ 30$: MOV #5,R4 ;usual shift is 5 (per letter) 40$: CLC ROR R3 ROR R2 SOB R4,40$ MOV R2,R0 BIC #^C<37>,R0 BEQ 50$ ;If a zero, then no letter here ADD #<'A-1>,R0 MOVB R0,-(R1) 50$: SOB R5,30$ 56$: MOV R1,R0 CALL TEXTR0 MOV SP,COMMA9 ;we will print commas ;Translate the status bits from AVL, GUS, and ONL CALL DISUNI ;Translate the unit flag bits into human-readable form MOV ONLBUF+P.UNFL,R1 ;test controller bits MOV #16.,R3 ;16. status bits to be checked MOV #UNIBIT,R2 60$: MOV (R2)+,R0 ROR R1 BCC 70$ ;is bit set? CALL COMR0N ;if set, print meaning 70$: SOB R3,60$ TST TMSCP BEQ NODENS CALL COMMA TEXT MOV RSPBUF+P.SHUN,R1 ;get current density CMP R1,RSPBUF+P.TRCK ;compare to format menu BNE MANDEN TEXT <(and only) > MANDEN: TEXT MOV #DENTBL,R2 10$: CMP (R2)+,R1 ;Find the controller name in table BEQ 40$ ;found it! TST (R2)+ ;a zero here means end of table BNE 10$ ;if not end, check next entry 40$: MOV (R2),R0 TEXTR0 NODENS: TEXT <.> OUTBUF CLRBUF OUTBUF CLRBUF TEXTL NUML OCT2,ONLBUF+P.UNFL TEXTR NUMR OCT2,ONLBUF+P.MLUN OUTBUF CLRBUF TEXTL MOV #ONLBUF+P.UNTI,R2 MOV #4,R3 MOV #LINBUF+35.-<4*DGOCT1>-3,LINPTR 20$: NUMBER OCT1,(R2)+ INC LINPTR SOB R3,20$ TEXTR MOV #4,R3 MOV #LINBUF+77.-<4*DGOCT1>-3,LINPTR 30$: NUMBER OCT1,(R2)+ INC LINPTR SOB R3,30$ OUTBUF CLRBUF TST TMSCP ;If it's TMSCP BNE NOTDSK ;then we don't print disk-spec stuff TEXTL <65535 block partitions> NUML DEC2,ONLBUF+P.UNSZ+2 TEXTR NUMR DEC2,ONLBUF+P.UNSZ OUTBUF CLRBUF TEXTL NUML DEC4,ONLBUF+P.UNSZ TEXTR NUMR DEC4,ONLBUF+P.VSER OUTBUF CLRBUF NOTDSK: TEXTL NUML DEC1,RSPBUF+P.USVR TEXTR NUMR DEC1,RSPBUF+P.UHVR OUTBUF CLRBUF TST TMSCP ;if it's a tape BEQ DSKGUS JMP TAPGUS ;then we have different output DSKGUS: ;Here we calculate number of blocks/cylinder and number of cylinders CLR R4 MOV RSPBUF+P.TRCK,R0 ;Blocks/Trk in R0 BEQ 66$ ;was a zero MOV RSPBUF+P.GRP,R2 ;Trk/Cylinder in R2 BEQ 66$ ;was a zero CLR R1 62$: ADD R0,R1 ;Poor man's multiply SOB R2,62$ ;Product in R1 MOV ONLBUF+P.UNSZ+2,R2 ;High byte MOV ONLBUF+P.UNSZ,R3 ;Low byte SUB #1,R3 ;drop by one SBC R2 ;for rounding BMI 66$ ;if it becomes -1, bug out 64$: SUB R1,R3 ;Subtract R1 SBC R2 BMI 65$ ;Loop until underflow INC R4 BR 64$ 65$: INC R4 ;we round up 66$: MOV R4,TOTCYL ;the total cylinder number TEXTL NUML OCT2,RSPBUF+P.SHUN TEXTR NUMR OCT2,RSPBUF+P.SHST OUTBUF CLRBUF TEXTL NUML DEC2,RSPBUF+P.CYL TEXTR NUMR DEC2,RSPBUF+P.TRCK OUTBUF CLRBUF TEXTL NUML DEC2,TOTCYL TEXTR NUMR DEC2,RSPBUF+P.GRP OUTBUF CLRBUF TEXTL NUML DEC2,RSPBUF+P.RCTS TEXTR NUMR DEC1,RSPBUF+P.RBNS OUTBUF CLRBUF TEXTL NUML DEC1,RSPBUF+P.RCTC BR COMGUS TAPGUS: TEXTL NUML DEC2,RSPBUF+P.GRP TEXTR NUMR DEC2,RSPBUF+P.CYL OUTBUF CLRBUF TEXTL NUML DEC2,RSPBUF+P.SHST COMGUS: OUTBUF CLRBUF OUTBUF CLRBUF NUNIT: CMP UNIT,SFLAG BEQ 74$ INC UNIT JMP AUNIT 74$: AGAIN: CALL BLKCLO ;close the output file .CLOSE #3 ;close the input file .SRESET JMP START ;CLRUNI, SETUNI, DISUNI handle the display of info from P.STS results CLRUNI: CLR STSOFF CLR STSAVL CLR STSMFE CLR STSNOV RETURN SETUNI: MOV RSPBUF+P.STS,R4 BIT R4,#40 ;no media mounted? BEQ 10$ BIC #40,R4 MOV SP,STSNOV 10$: CMP R4,#3 ;offline? BNE 20$ MOV SP,STSOFF RETURN 20$: CMP R4,#4 ;available? BNE 30$ MOV SP,STSAVL RETURN 30$: CMP R4,#5 ;media format error? BNE 40$ MOV SP,STSMFE 40$: RETURN DISUNI: CALL COMMA TST STSOFF BEQ DISUN1 TEXT BR DISUN2 DISUN1: TEXT DISUN2: TST STSMFE BEQ DISUN3 CALL COMMA TEXT DISUN3: TST STSNOV BEQ DISUN4 CALL COMMA TEXT DISUN4: TST STSAVL BEQ DISUN5 CALL COMMA TEXT DISUN5: RETURN PROCT1: ;Print an octal byte in R1 MOV R0,-(SP) ;Save registers MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #OCT1TAB,R3 ;Point to table of octal digits CLR ZEROSP JMP PRCOMM ;and go to common output routine PROCT2: ;Print an octal word in R1 MOV R0,-(SP) ;Save registers MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #OCT2TAB,R3 ;Point to table of octal digits CLR ZEROSP JMP PRCOMM ;and go to common output routine PRDEC1: ;Print a decimal byte in R1 MOV R0,-(SP) ;Save registers MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #DEC1TAB,R3 ;Point to table of octal digits MOV #2,ZEROSP JMP PRCOMM ;and go to common output routine PRDEC2: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #4,ZEROSP ;Now print the 16-bit value in R1 in decimal MOV #DECTAB,R3 ; List of decades ;PRCOMM is an alternate entry point for other number bases PRCOMM: MOV LINPTR,R0 MOV R0,R2 10$: MOVB #'0,(R2) ; Start with zero 20$: CMP R1,(R3) BLO 40$ SUB (R3),R1 INCB (R2) ; And bump it up in current place BR 20$ 40$: INC R2 ; Do next digit CMP #1,(R3)+ ; Unless we just did ones place BNE 10$ MOV R2,LINPTR MOV ZEROSP,R1 ; Do we want a leading zero suppress? BEQ 60$ ; not if ZEROSP=0 MOVB #'.,(R2)+ MOV R2,LINPTR MOV R0,R2 ; do a leading-zero suppress 50$: CMPB #'0,(R2) BNE 60$ MOVB #' ,(R2)+ SOB R1,50$ 60$: MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN PRDEC4: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) ;Now print the 32-bit value in R1 (hi)/R2 (lo) in decimal MOV #DECT32,R3 ; List of decades MOV LINPTR,R0 ; Where to store the digits MOV R0,R4 10$: MOVB #'0,(R4) ; Start with zero 20$: CMP R1,(R3) ; Compare high words BLO 40$ BHI 30$ CMP R2,2(R3) ;They were the same, compare lo words BLO 40$ 30$: SUB 2(R3),R2 ;Subtract lo words SBC R1 SUB (R3),R1 ;Subtract hi words INCB (R4) ; And bump it up to decimal value BR 20$ 40$: INC R4 ; Do next digit TST (R3)+ CMP #1,(R3)+ ; Unless we just did ones place BNE 10$ MOVB #'.,(R4)+ MOV R4,LINPTR MOV R0,R4 ; do a leading-zero suppress MOV #9.,R1 ; for up to first four digits 50$: CMPB #'0,(R4) BNE 60$ MOVB #' ,(R4)+ SOB R1,50$ 60$: MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN COMR0N: TSTB (R0) ;No comma if string is blank BEQ 10$ CALL COMMA TEXTR0 10$: RETURN COMMA: TST COMMA9 ;Print comma if flagged for BEQ COMMA0 TEXT <, > COMMA0: INC COMMA9 RETURN ; SUBROUTINE TO PERFORM MSCP BYPASS COMMAND ; ; INPUT VARIABLES: ; THE MSCP COMMAND PACKET MUST BE PREVIOUSLY SETUP IN CMDBUF ; R5 => MSCP OPCODE ; ; OUTPUT VARIABLES: ; CARRY SET IF SPFUN RETURNED ERROR OR INVALID COMMAND ; OTHERWISE, CARRY CLEAR ; ; CALLING SEQUENCE: ; JSR R5,BYPASS ; .WORD (MSCP OPCODE) ; BYPASS: MOV #RSPPKT,R2 ; POINTER TO MSCP AREA MOV #RSPLEN,(R2)+ ; RESPONSE PACKET LENGTH CLR (R2)+ ; VIRTUAL CIRCUIT ID ADD #RSPLEN,R2 ; POINT TO START OF COMMAND PACKET MOV #CMDLEN,(R2)+ ; COMMAND PACKET LENGTH CLR (R2)+ ; VIRTUAL CIRCUIT ID MOV (R5)+,P.OPCD(R2) ; OPCODE - FROM CALLER .SPFUN #AREA,#3,#360,#RSPPKT,#0,#0 ; ISSUE MSCP-BYPASS COMMAND BCS 1$ ; - BRANCH IF UNSUCCESSFUL MOVB RSPBUF+P.STS,-(SP) ; GET RETURNED STATUS BIC #^C,(SP) ; CLEAR SUBCODE CMP #1,(SP)+ ; WAS THE COMMAND INVALID? CLC ; ASSUME 'NO' BNE 1$ ; NO, RETURN SEC ; YES, SET CARRY THEN RETURN 1$: RTS R5 ; RETURN TO CALLER FATAL: CALL BLKCLO ;Close the output file FATAL2: .PRINT #FATALM ;Print the error message .PRINT R5 .EXIT ; BLKOPE opens the output file, if necessary BLKOPE: TST OUTSP ;If no output file, nothing to do BEQ BLKOP9 .DSTAT #STAT2,#OUTSP ;Do we need to .FETCH? TST STAT2+4 BNE BLKOP1 .FETCH HANPTR,#OUTSP FATALE BLKOP1: .ENTER #AREA,#1,#OUTSP,#OUTSP+8. ;Create output file FATALE MOV #BLKBUF,BLKPTR CLR BLKNUM BLKOP9: RETURN ; BLKCLO closes the output file, if necessary, after flushes the buffer. BLKCLO: TST OUTSP BEQ 70$ CALL BLKFLU .CLOSE #1 70$: RETURN ; BLKFLU flushes the output buffer to the output file. Don't call it ; unless you've already tested that output is going to a file. ; It writes zeroes from BLKPTR to the end of the block. On return, ; BLKPTR is pointing back to BLKBUF, and BLKNUM has been incremented. BLKFLU: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV BLKPTR,R1 CMP #BLKBUF,R1 ;is there anything in this block? BEQ BLKFL9 MOV #BLKBUF+512.,R2 SUB R1,R2 BEQ 10$ 4$: CLRB (R1)+ SOB R2,4$ 10$: .WRITW #AREA,#1,#BLKBUF,#256.,BLKNUM ; check for error in .WRITE using FATAL2, because FATALE attempts to ; do the write as part of the closing process. Messy, huh? FATAL2 MOV #BLKBUF,BLKPTR INC BLKNUM BLKFL9: MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN ; CLRBUF clears the output buffer and points LINPTR to the start of it. CLRBUF: MOV R0,-(SP) MOV R1,-(SP) MOV #LINBUF,R0 MOV R0,LINPTR MOV #LINBUZ-LINBUF,R1 1$: MOVB #' ,(R0)+ ;FILL WITH SPACES SOB R1,1$ MOV (SP)+,R1 MOV (SP)+,R0 RETURN ; OUTBUF prints the output buffer as a line. It suppresses trailing spaces. ; it sends the output to the file buffer if output is being redirected. OUTBUF: MOV R0,-(SP) MOV R1,-(SP) MOV #LINBUZ,R1 MOV #LINBUF,R0 1$: CMPB #' ,-(R1) BNE 10$ CMP R1,R0 BNE 1$ 10$: INC R1 CLRB (R1) TST OUTSP ;send output to console or to file? BEQ 50$ ; here we send output buffer to the block buffer. ; first terminate line with CRLF MOVB #13.,(R1)+ MOVB #10.,(R1)+ MOV R2,-(SP) 12$: MOV BLKPTR,R2 MOVB (R0)+,(R2)+ MOV R2,BLKPTR CMP #BLKBUF+512.,R2 BNE 14$ CALL BLKFLU 14$: CMP R0,R1 BNE 12$ MOV (SP)+,R2 BR 60$ ; here we send output buffer to the console. 50$: .PRINT 60$: MOV (SP)+,R1 MOV (SP)+,R0 RETURN MOVSTR: MOV R0,-(SP) MOV R1,-(SP) MOV (R5)+,R0 ;source string MOV (R5)+,R1 ;destination string BR 20$ 10$: MOVB (R0)+,(R1)+ 20$: TSTB (R0) ;we don't move the trailing null BNE 10$ 70$: MOV (SP)+,R1 MOV (SP)+,R0 RTS R5 TEXTR0: MOV R0,$1 JSR R5,TEXT $1: .WORD 0 RETURN TEXT: MOV R0,-(SP) MOV R1,-(SP) MOV (R5)+,R0 ;source string MOV LINPTR,R1 ;destination position BR 20$ 10$: MOVB (R0)+,(R1)+ CMP R1,#LINBUZ-2. ;did we hit the margin? BEQ 100$ 20$: TSTB (R0) ;we don't move the trailing null BNE 10$ 70$: MOV R1,LINPTR MOV (SP)+,R1 MOV (SP)+,R0 RTS R5 100$: MOV R0,-(SP) MOV #LINB2Z,R0 ; temporary buffer for overflow filled backwrd 101$: CMPB #' ,-(R1) ;we backtrack until we hit a space BEQ 102$ ;(trust that we don't have a spaceless buf!) MOVB (R1),-(R0) ;save stuff we back over MOVB #' ,(R1) ;filling with spaces as we go back BR 101$ 102$: CALL OUTBUF MOV #LINBUF,R1 ;move saved stuff to beginning of line MOVB #' ,(R1)+ ;clear the indent MOVB #' ,(R1)+ ;clear the indent MOVB #' ,(R1)+ ;clear the indent MOVB #' ,(R1)+ ;clear the indent 106$: CMP R0,#LINB2Z ;are we already at end of old line? BEQ 114$ ;if so, no more moving 110$: MOVB (R0)+,(R1)+ BR 106$ 114$: MOV R1,R0 120$: MOVB #' ,(R0)+ ;clear out rest of new line CMP R0,#LINBUZ BNE 120$ MOV (SP)+,R0 BR 10$ DEXT: .WORD 0,0,0,0 FATALM: .ASCII /?DUSTAT-F-/<200> .EVEN ZERO: .WORD 0 .MACRO TBLENT NUM,NAME .SAVE .PSECT STRINGS $ = . .ASCIZ "NAME" .RESTORE .WORD NUM,$ .ENDM .MACRO TBLEND NUM,NAME ;"NUM" should be impossible value .SAVE .PSECT STRINGS $ = . .ASCIZ "NAME" .RESTORE .WORD NUM,0,$ .ENDM DEVTBL: TBLENT 0 , TBLENT 1 , TBLENT 2 , TBLENT 3 , TBLENT 4 , TBLENT 5 , TBLENT 6 , TBLENT 7 , TBLENT 10 , TBLENT 11 , TBLENT 12 , TBLENT 13 , TBLENT 14 , TBLENT 15 , TBLENT 16 , TBLENT 17 , TBLENT 20 , TBLENT 21 , TBLENT 22 , TBLENT 23 , TBLENT 24 , TBLENT 25 , TBLENT 26 , TBLENT 27 , TBLENT 30 , TBLENT 31 , TBLENT 32 , TBLENT 33 , TBLENT 34 , TBLENT 35 , TBLENT 36 , TBLENT 37 , TBLENT 40 , TBLENT 41 , TBLENT 42 , TBLENT 43 , TBLENT 44 , TBLENT 45 , TBLENT 46 , TBLENT 47 , TBLENT 50 , TBLENT 51 , TBLENT 52 , TBLENT 53 , TBLENT 54 , TBLENT 55 , TBLENT 56 , ;future TBLENT 57 , TBLENT 60 , TBLENT 61 , TBLENT 62 , TBLENT 63 , TBLENT 64 , TBLENT 65 , TBLENT 66 , ;future TBLENT 67 , ;future TBLENT 70 , ;future TBLENT 71 , ;future TBLENT 72 , ;future TBLENT 73 , ;future TBLENT 74 , ;future TBLENT 75 ,;future TBLENT 76 , ;future TBLENT 77 , ;future TBLENT 100 , ;future TBLENT 101 , TBLENT 102 , TBLENT 105 , ; 200-377 are supposedly reserved to customers, but uPower Pascal ; uses the following TBLENT 376 , TBLENT 377 , TBLEND 177777 , MSCTBL: TBLENT 1. , TBLENT 2. , TBLENT 3. , TBLENT 4. , TBLENT 5. , TBLENT 6. , TBLENT 7. , TBLENT 8. , TBLENT 9. ,;Actually, ancient TUK50's use this too. TBLENT 10. , ;11. is unassigned TBLENT 12. , TBLENT 13. , TBLENT 14. , TBLENT 15. , TBLENT 16. , ;17. is unassigned TBLENT 18. , TBLENT 19. , TBLENT 20. , ; KFQSAs are an unusual beast. While the "disk" controller will report 21. ; at the end of step 4, it might report 96., 97., or some other ID later on ; since the controller ID actually depends on what type of disk it is. This ; also goes for the tape connections. So, this is why KFQSA devices appear ; to be listed twice; once under KFQSA, and once under the disk type itself. ; I've never seen a RT-11 system with a KFQSA, but I think it should work! TDS TBLENT 21. , TBLENT 22. , TBLENT 23. , TBLENT 24. , TBLENT 25. , ;26. is unassigned TBLENT 27. , ;28. is reserved TBLENT 29. , TBLENT 30. , TBLENT 31. , TBLENT 32. , TBLENT 33. , TBLENT 34. , TBLENT 35. , ;36. - 38. are unassigned TBLENT 39. , TBLENT 40. , TBLENT 41. , TBLENT 42. , ;43. - 44. are unassigned TBLENT 45. , ;46. - 64. are unassigned TBLENT 65., TBLENT 66., ;67. - 95. are unassigned TBLENT 96. , TBLENT 97. , TBLENT 98. , TBLENT 99. , TBLENT 100. , TBLENT 101. , TBLENT 102. , TBLENT 103. , ;RSTS/E sources say this is a TF70L TBLENT 104. , TBLENT 105. , TBLENT 106. , ;107.is unannounced TBLENT 108. , TBLENT 109. , TBLENT 110. , ;111. is unannounced TBLENT 112. , ;113. is unassigned TBLENT 114. , ;115. - 116. are unassigned TBLENT 117. , TBLENT 118. , ;119. - 127. are unassigned ;128. - 159. are reserved ;160. - 165. are unannounced ;166. - 191. are unassigned ;192. - 247. are reserved TBLENT 248. , ;249. - 250. are unannounced ;251. - 255. are unassigned TBLEND 177777 ,<(Unidentified)> DENTBL: TBLENT 1 , TBLENT 2 , TBLENT 4 , TBLENT 10 , TBLENT 401 , TBLENT 402 , TBLENT 404 , TBLENT 420 ,;according to RSTS/E TBLENT 1001 , TBLENT 1002 , ; 20xx entries are supposed to be RV80, whatever that is, ; according to RSTS/E sources. TBLEND 177777 , ;Macro for true/false text messages .MACRO TRUE STR .SAVE .PSECT STRING $ = . .ASCIZ "STR" .RESTORE .WORD $ .ENDM .MACRO FALSE STR .SAVE .PSECT STRING $ = . .ASCIZ "STR" .RESTORE .WORD $ .ENDM .MACRO BLANK .WORD ZERO .ENDM BITTAB: ;bit 8 FALSE TRUE ;bit 9 FALSE TRUE ;bit 10 FALSE TRUE ;bit 11 - only important if bit 9 is false FALSE TRUE ;bit 12 FALSE TRUE ;bit 13 BLANK TRUE ;bit 14 BLANK TRUE ;bit 15 FALSE TRUE ; These are the bits in the controller flags CONBIT: TRUE TRUE TRUE .REPT 12. BLANK .ENDR TRUE ; ; These are the bits in the unit flag word UNIBIT: TRUE TRUE TRUE TRUE BLANK BLANK TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE GRIPE: .ASCII /?DUSTAT-W-Illegal command/<15><12><15><12> VERSON: .ASCII /DUSTAT 2.00/<15><12><15><12> .ASCII "Usage: RUN DUSTAT [OUT=]DEV:[/S][/D]"<15><12> .ASCII " where OUT is an optional device (i.e. LP:) or file to send the output"<15><12> .ASCII " and DEV: is the device to be queried."<15><12><15><12> .ASCII " /S does a scan of all [T]MSCP units connected to DEV:"<15><12> .ASCIZ " /D shows .DSTATUS information for MSCP devices" .EVEN DECTAB: .WORD 10000.,1000. DEC1TAB:.WORD 100.,10.,1. OCT2TAB:.WORD 100000, 10000, 1000 OCT1TAB:.WORD 100, 10, 1 DECT32: .WORD 15258.,51712. .WORD 1525.,57600. .WORD 152.,38528. .WORD 15.,16960. .WORD 1.,34464. .WORD 0.,10000. .WORD 0., 1000. .WORD 0., 100. .WORD 0., 10. .WORD 0., 1. ;Here we build the MSCP command/response packet for .SPFUN #360 RSPPKT: .WORD 0,0 ;Response packet length,virtual circuit ID RSPBUF: .BLKW 24. ;Response buffer RSPLEN= .-RSPBUF ;Length of response buffer CMDPKT: .WORD 0,0 ;Command packet length,virtual circuit ID CMDBUF: .REPT 24. ;Zeroed command buffer .WORD 0 .ENDR CMDLEN= .-CMDBUF ;Length of command buffer .ASCII /?????/ ;stores translation of media ID MEDTRD: .ASCII /??/ .BYTE 0 ;unitialized storage follows .SAVE .PSECT STRING LINBUF: .BLKB 78. ;output line buffer LINBUZ: .BLKB 1. ;to contain a possible trailing null LINB2F: .BLKB 78. ;overflow buffer LINB2Z: .EVEN AREA: .BLKW 6. CSTATD: .BLKW 6. STAT: .BLKW 4. ;STAT buffer for device we're displaying STAT2: .BLKW 4. ;STAT buffer for output devicee ZEROSP: .BLKW 1 LINPTR: .BLKW 1 OUTSP: .BLKW 5*3 INSPEC: .BLKW 4*6 UNIT: .BLKW 1 PORT: .BLKW 1 TOTCYL: .BLKW 1 COMMA9: .BLKW 1 DFLAG: .BLKW 1 SFLAG: .BLKW 1 MSCP: .BLKW 1 TMSCP: .BLKW 1 STSAVL: .BLKW 1 STSMFE: .BLKW 1 STSNOV: .BLKW 1 STSOFF: .BLKW 1 BUFF: .BLKW DUTTSZ BLKBUF: .BLKB 512. BLKNUM: .BLKW 1 BLKPTR: .BLKW 1 ONLBUF: .BLKB RSPLEN .EVEN HANPTR: .BLKW 1 HANLOD: .END START