.TITLE DCJB50 Datacommunication JOB ; Multiprocessor V5 ;*********************************************************************** ; *** SYSTEM-JOB for Datacommunication using modified RSP *** ; ; Handler: * QNJ50.MAC (Qnector) ; * PDJ50.MAC (DR(V)-11 C/K, WB(V)-11) ; * Logical assignment should be JOB: ; Terminate job: 2 * ^C ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++; ; COPYRIGHT (c) 1985 by ; ; H.H. Klin. Neuro. AZG ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++; SPDIR = 0 ;Special Directory (e.g. Magtape) support enabled for SPDIR=1 BSTRP = 1 ;1=generate code for simple(i.e. Toggle-in) boot. TEST = 0 ;1=enable test printout: ; 'C' = Command received 'S' = Data packet send ; 'R' = Data packet received 'H' = Hard error: no device ; 'O' = Device I/O error 'P' = Protection violation ; 'F' = Special Function req. 'D' = Special Directory req. ;*************************** End User Edit ******************************* BOOT = 10 ;8. NDEV = 16. ;Total nr. of devices to OPEN. .MCALL .PRINT,.SERR, .SPFUN, .EXIT, .SETTOP,.DSTAT .MCALL .ENTER,.LOOKUP,.READW, .WRITW,.CLOSE, .HERR .MCALL .GVAL, .SAVEST,.REOPEN,.DATE, .GTIM .MCALL .TWAIT .ENABL LC .PSECT RUNJB START:: CALL BUFFER ;Execute initialisation code in BUFFER AGAIN:: .READW #AREA,#15.,#CMDPKT,#5,#ERROR ;Wait for next command. ; 5 = MESSAGE packet SIZE ADD #1,IONRLO ;Count the IO's. ADC IONRHI MOVB #'C,COND .iif NE,TEST .PRINT #COND ;-----------------------IO: command received----------------------------; .IF NE,BSTRP ; ; See if we have to BOOT ; CMP #BOOT,OPCODE BNE CMGO ;No boot. MOV #"BT,TEXT CLR R3 BISB JBSTAT,R3 ;R3 = JOBNUM INC R3 ;R3 = Blockno. (skip 0 in JBINFO) INC R3 ;R3 = Blockno. (skip 1 in JBINFO) MOV #256.,R4 ;1 Block = 512. BYTES! .READW #AREA,MESSAG,#BUFFER,R4,R3 ;Get bootblock BCS 1$ TST BUFFER ;1st word may not be 0 BEQ 1$ .WRITW #AREA,#15.,#BUFFER,R4,#-1 ;Boot stores this in low mem. TST ERROR BEQ 2$ 1$: MOV #"BF,TEXT 2$: CALL PSTAT BR AGAIN CMGO: .ENDC ;BSTRP ; ; Command received: Analyse and setup IO ; CALL ERRTST CMPB #NDEV,UNIT ;Check RSP unit no. in range. BHI GOON OPCERR: ;OPCODE ERROR UNIERR: JMP HRDERR ;UNIT ERROR GOON: MOV WRDCNT,R5 MOV R5,R1 CLRB R1 ;MULTIPLE OF 256. SUB R1,R5 ;WORD REST SWAB R1 ;NR. OF BLOCKS TST R5 ;REMAINING WORDS? BEQ NOWRDR ;NO INC R1 ;YES, 1 BLOCK MORE TO DO NOWRDR: MOV BLCKNR,R3 ;R3=Block start nr.! MOV #1,R0 ;Construct ASH UNIT,R0 ; prot. bit mask ; R1 => Nr. of IO blocks ; R3 => Block address ; R5 => Remaining words CLRB ENDMOD ;Set error return code to SUCCES TSTB SPFCOD ;SPDIR ? (Channel not necessarily open) BNE 5$ BIT R0,CHSTAT ;Check channel open. BEQ NODEV 5$: CMPB #2,OPCODE ;Read ? BEQ READST CMPB #3,OPCODE ;Write? BNE 10$ JMP WRITE ;Write to device. 10$: JMP SPFREQ ;Must be SPF request with zero WCNT ;-----------------------IO: read from device---------------------------; READST: TSTB SPFCOD ;If SPF with DATA READ, execute BEQ 1$ ; SPF first. Then branch to SEND JMP SPFREQ ; entry after setting up BUFDAT, 1$: ; R1,R4,R5. BIT R0,RDSTAT ;Check read prot. BNE PRDOK NODEV: JMP PRTERR PRDOK: MOVB #'S,COND READ: MOV #BUFFER,BUFDAT MOV BUFBLK,R4 ;R4=Nr. blocks available in buffer CMP R4,R1 ;All? BLOS 1$ MOV R1,R4 ;No, less. 1$: MOV R4,R2 SWAB R2 ;R2=Nr. words to read. CMP #1,R1 ;Last block? BNE 10$ TST R5 ;Remaining words? BEQ 10$ MOV R5,R2 ;Remaining words! 10$: .READW #AREA,UNIT,#BUFFER,R2,R3 BCC SEND JMP IOERR SEND: CMPB UNIT,MESSAG ;Mailbox data? BNE NOMAIL ; ; COPY JOB info into block requested by HELLO ; As HELLO requests always 1 block at a time, R3 is free to be used! ; MOV #IONRHI,R0 ;ADD MOV #BUFFER+480.,R2 ; JOB MOV #10.,R3 ; INFO 1$: MOV (R0)+,(R2)+ SOB R3,1$ .DATE MOV R0,(R2)+ ;System date .GTIM #AREA,R2 ;System time, 2 words! NOMAIL: ;-------------------------Send DATA packet(s)---------------------------; .iif NE,TEST .PRINT #COND ; ; Send data within packet through JOB Handler ; SDATA: MOV #256.,R2 ;Words/packet DEC R1 ;Last block? BNE 1$ TST R5 ;Remaining words? BEQ 1$ MOV R5,R2 ;Remaining words! 1$: .WRITW #AREA,#15.,BUFDAT,R2,#0 ;Wait for contents send. CALL ERRTST ADD #512.,BUFDAT ;POINT TO NEXT DATA INC R3 ;NEXT BLOCK TST R1 BEQ RDSUC ;Done with succes! DEC R4 ;Buffer exhausted? BNE SEND JMP READ RDSUC: JMP SNDEND ;-----------------------IO: write to device---------------------------; WRITE: BIT R0,WTSTAT ;Check write prot. BNE 1$ JMP PRTERR ;Write protect error. 1$: MOVB #'R,COND WRIT: MOV BUFBLK,R4 ;R4=Nr. blocks available in buffer CMP R4,R1 ;All? BLOS 1$ MOV R1,R4 ;No, less. 1$: MOV R4,R2 SWAB R2 ;R2=Nr. words to write. MOV #BUFFER,BUFDAT ;-----------------------Receive DATA packet(s)---------------------------; RCVDAT: .iif NE,TEST .PRINT #COND .READW #AREA,#15.,BUFDAT,#1,#0 CALL ERRTST ;Error test. 2$: DEC R1 ;One block less to receive ADD #512.,BUFDAT DEC R4 ;Buffer full? BNE RCVDAT TSTB SPFCOD ;If this is SPF with DATA WRITE, data BNE SPFREQ ; are now in buffer. Execute SPF CMPB MESSAG,UNIT ;Outp. for MAILBOX? BNE 3$ .PRINT #BUFFER ;Yes, print it also. ; ; WRITE to device, check wordcount for last block: ; 3$: TST R1 ;Last block received? BNE 4$ TST R5 ;Word rest? BEQ 4$ SUB #256.,R2 ;One block of words less ADD R5,R2 ; but add remaining words. ; 4$: .WRITW #AREA,UNIT,#BUFFER,R2,R3 BCS IOERR 6$: SWAB R2 ;Make nr. blocks ADD R2,R3 ;Next blockaddres for write. TST R1 ;All blocks done? BEQ SUCCES ;Done with succes JMP WRIT ;-------------------------I/O succes+errors---------------------------; ERRBYT=52 IOERR: TSTB @#ERRBYT ;EOF or HARD error? BNE ERR .iif NE,TEST MOVB #'O,COND MOVB #-2,ENDMOD ;EOF error! ERREND: .iif NE,TEST .PRINT #COND SUCCES: JMP SNDEND PRTERR: ;Protected device violated. .if NE,TEST MOVB #'P,COND BR ERR .endc HRDERR: .iif NE,TEST MOVB #'H,COND ERR: MOVB #-1,ENDMOD ;Hard error BR ERREND ;---------SPFUN requests + SPECIAL DIRECTORY device support-----------; ; R3 => Block address ; R5 => Remaining words ; Read/Spfun with zero wordcount: ; R1 => Nr. of IO blocks ; Write: ; R1 => R1=R4=0 (On return from receive data part=write processing) FILST$ = 100000 SPFREQ: MOVB #'F,COND .iif NE,TEST .PRINT #COND MOV #BUFFER,R4 MOV R4,BUFDAT ;Set up for possible SEND CMPB MTCHAN,UNIT BEQ 1$ CMPB SPFCOD,#373 ;Random access-size request? BNE 1$ .READW #AREA,MESSAG,R4,#32.,#1 ;Get Size table BCS HRDERR MOVB UNIT,R0 ASL R0 ; *2 ASL R0 ; *4 ADD R4,R0 ;Add #BUFFER offset BIT #FILST$,(R0)+ ;Check random access and skip DEVICE STATUS BEQ 1$ MOV @R0,@R4 ;Get size! BEQ HRDERR ;0 = No size DEC @R0 BNE 30$ ;1 = Variable volume, 30$ = SEND ; ; Variable volume: do SPFUN #373 request ; 1$: MOV #ENDINF,R0 MOV R0,R2 ;Error return block 4 words. CLR (R0)+ ;Initialize first two. CLR (R0)+ TSTB SPFCOD ;Positive means Special Directory req. BEQ HRDERR BGT SPDIRC TST R3 ;Blockno: if non 0, assume error return block BNE 4$ ; (e.g. MAGTAPE, RK06/07 etc.) CLR R2 4$: MOV R1,R4 ;Setup R4 also for code in SEND. CMP R4,BUFBLK ;Data buffer for SPFUN must be contiguous! BHI SPFMEM ;Not enough memory to execute this SPF. .SPFUN #AREA,UNIT,SPFCOD,#BUFFER,SPDATA,R2 BCC 20$ ; ; SPFUN ERROR! Still send the data in case of SPFUN read request! MOVB #-1,ENDMOD ;Init with HARD error! 10$: CMPB #2,OPCODE ;also DATA READ? BEQ 30$ ;No -> all done. Yes -> SPFUN REQ. with DATA- BR IOERR ;read; R1=Nr. IO blks, R5=wordrest, R4=R1 20$: CMPB #2,OPCODE ;Succesfull SPFUN: also DATA READ? BNE SUCCES ;No -> all done. Yes -> SPFUN REQ. with DATA- 30$: JMP SEND ;read; R1=Nr. IO blks, R5=wordrest, R4=R1 SPFMEM: MOV #"NB,TEXT ;Inform that there is No Buffer room! CALL PSTAT SPFERR: BR HRDERR ; ; SPECIAL DIRECTORY Device Requests: ; ================================== ; SPDIRC: .IF EQ,SPDIR MOV #"SP,TEXT ;Inform that there is No SPDIR support! CALL PSTAT BR SPFERR ;Error .IFF ; else generate special dir. code. MOVB #'D,COND .iif NE,TEST .PRINT #COND ; ASYREQ=-20. LOOKUP =3 ENTER =4 CLOSE =1 FNF =1 ; CONFIG=300 ;RT-11 CONFIGURATION word. USR$=1000 ;USR bit in CONFIG. word. MOV #1,R4 ASH UNIT,R4 .GVAL #AREA,#CONFIG ;The USR must be available! BIT #USR$,R0 BNE USROK MOV #"NU,TEXT ;Inform that there is No Usr! CALL PSTAT BR HRDR USROK: CMPB SPFCOD,#CLOSE BNE SPDIRO SPCLOS: BIT R4,CHSTAT ;Channel open? BEQ HRDR ;No -> hard error .CLOSE UNIT BIC R4,CHSTAT ;Set channel no open. SUCC: JMP SNDEND NFSMT: .RAD50 /MT / .WORD 0 SPDIRO: CMPB MTCHAN,UNIT BNE OTHERS ; ; MT: perform ASYNCHRONOUS DIRECTORY OPERATION! ; BIT R4,CHSTAT BNE 1$ .LOOKUP #AREA,UNIT,#NFSMT,R3 BCS HRDR 1$: BIS R4,CHSTAT MOV #BUFFER+6,R2 ;BUFF word 1,2,3 ; contains RAD50 filename TST BUFFER ;Hardware LOOKUP?. BEQ SUCC ;Yes, then we are ready. CMPB #LOOKUP,SPFCOD BNE 2$ MOV #LOOKUP,(R2)+ BR 3$ 2$: CMPB #ENTER,SPFCOD BNE HRDR MOV #ENTER,(R2)+ 3$: MOV R3,(R2)+ ;Enter sequence number(BLCKNR). CLR (R2)+ ;DEC reserved CLR (R2)+ ;DEC reserved ; .SPFUN #AREA,UNIT,#ASYREQ,#BUFFER,,#ENDINF BCC SUCC ;CC =file found! CMP #FNF,ENDINF ;File not found? BEQ SUCC ;Yes! OK! .CLOSE UNIT BIC R4,CHSTAT ;Set channel no open. HRDR: JMP HRDERR OTHERS: .READW #AREA,MESSAG,#BUFFER+100.,#32.,#0 ;16 Device/file names CLR R2 BISB UNIT,R2 ASL R2 ;Make bytes. ASL R2 ;*2. ASL R2 ;*4. (full filespec.=4 words) ADD #BUFFER+100.,R2 MOV #BUFFER+6.,R5 ;Shift filename MOV #BUFFER+8.,R1 ; 1 word MOV -(R5),-(R1) ; upwards MOV -(R5),-(R1) ; in BUFFER. MOV -(R5),-(R1) MOV @R2,@R5 ;Copy device name. CMPB SPFCOD,#LOOKUP ;Lookup support. BNE 3$ .LOOKUP #AREA,UNIT,R5,R3 BCS HRDR BR 4$ 3$: CMPB SPFCOD,#ENTER ;Enter support. BNE HRDR .ENTER #AREA,UNIT,R5,,R3 BCS HRDR 4$: BIS R4,CHSTAT .ENDC ;SUCCES: send END packet ;-------------------------Send END packet-----------------------------; SNDEND: MOVB #'E,COND .WRITW #AREA,#15.,#ENDOPC,#5,#1 .if NE,TEST .PRINT #COND .PRINT #CRLF .endc CALL ERRTST JMP AGAIN ;Go listening. ;------------------------Error processing-----------------------------; CHKERR: MOV #"CK,TEXT ;Indicate. MOVB #-1.,ENDMOD INC HERROR ;Checksum error ! Count it. CALL PSTAT BR SNDEND RETRN: RETURN ERRTST: MOV ERROR,R0 ;Error? BEQ RETRN TST (SP)+ ;Pop off ERRTST caller. CLR ERROR ;Reset error code DEC R0 ;Positive? BMI CHKERR ; MOV #"HD,TEXT ;Hard error TST R0 ;INIT? (= 1) BNE COMERR MOV #"IN,TEXT ;Init! COMERR: CFATAL: INC CERROR ;Count communications errors CALL PSTAT JMP AGAIN ;-------------------------------------------------------------------------; ; Table for accounting information: ERROR: .WORD 0 ; + 0 Error code from JOB: handler IONRHI: .WORD 0 ; + 2 Nr IO's High word. IONRLO: .WORD 0 ; + 4 Nr IO's Low word. HERROR: .WORD 0 ; + 6 CHECKSUM ERROR COUNT. CERROR: .WORD 0 ; + 10 COMMUNIC. ERROR COUNT. BFSIZE: .WORD 0 ; + 12 Data buffer size in words. BUFBLK: .WORD 0 ; + 14 Nr. of available 256. word buffers ;-------------------------Utilities service-----------------------------; CHSTAT: .WORD 0 ; + 16 Status "channels" open. RDSTAT: .WORD 177777 ; + 20 READ PROTECT. status WTSTAT: .WORD 100000 ; + 22 WRITE PROTECT. status. JBSTAT: .BYTE 0,0 ; + 24 Job/SPDIR/Boot indentifiers./JBNUM ; ^ ^^-> offset from handler pointer ;-----------------------------Packets-------------------------------; ; 1. COMMAND PACKET: CMDPKT:: ; Flag ... 5 words ... Checksum OPCODE: .BYTE 0 MODIF: .BYTE 0 UNIT: .BYTE 0 SPFCOD: .BYTE 0 SPDATA: .WORD 0 WRDCNT: .WORD 0 BLCKNR: .WORD 0 ; 2. END PACKET: ENDPKT:: ; Flag ... 5 words ... Checksum ENDOPC: .BYTE 64. ;=64.,100 for ENDPKT ENDMOD: .BYTE 0 ;=SUCCES CODE for ENDPKT ENDINF: .WORD 0 ;SPFUN/SPDIR 1 error return .WORD 0 ; 2 .WORD 0 ; 3 .WORD 0 ; 4 ;----------------------Miccellaneous Storage-----------------------------; BUFDAT: .WORD 0 ;Buffer Pointer to DATA to SEND/RECEIVE AREA: .BLKW 6 MESSAG: .BYTE 0 MTCHAN: .BYTE 0 ;-------------------------- Status Reporting ----------------------------; PSTAT: .if EQ,TEST .PRINT #TEXT .iff MOV #TEXT,R0 MOVB #'-, COND+1 .PRINT MOVB #200,COND+1 .endc RETURN TEXT: .ASCII /ST-/ .if EQ,TEST COND: .ASCII /I-/ .iff COND: .ASCII /I/<200> .endc .ASCII /DCJOB/ JBNUM: .BYTE 60 CRLF: .BYTE 0 ;CR, LF, Terminator. .EVEN ;---------------------- Initialization / buffer -------------------------; .PSECT INITJB FILST$ = 100000 BUFFER::.SERR .PRINT #PINIT ; ; Get JOB NUMber: ; MOV #AREA,R5 MOV #DVLIST,R1 .DSTAT R1,#JOB ;DVLIST receives 4 word status! BCS NOJHND TST DVLIST+4 BEQ NOJHND CLR R4 BISB @R1,R4 SUB #300,R4 ;R4 = job number MOV R4,R0 ADD #60,R0 .IIF NE,SPDIR BIS #100000,R4 .IIF NE,BSTRP BIS #40000,R4 MOV R4,JBSTAT MOVB R0,JBNUM CALL PSTAT ;Print startup status ; ; Get RW protection & device list: ; MOV #15.,R3 ;JOB channelno in R3 to save space .LOOKUP R5,R3,#JOBFIL BCS NOJFIL .READW R5,R3,#DVLIST,#46.,#1 ; Read RW-table(=14.w + SIZTAB=32.w) BCS NOJFIL ; ; First set RW protection for this JOB ; MOVB R4,R0 ASL R0 ;*2 ASL R0 ;*4 ADD #RWTABL,R0 MOV (R0)+,RDSTAT ;Default Read Access MOV (R0)+,WTSTAT ;Default Write Access ; ; Now get device list: ; .READW R5,R3,R1,#65.,#0 ;16 Device/file+messag+mtchan BCC GETDEV NOJFIL: .PRINT #NOJOBF .EXIT NOJHND: .PRINT #NOJOBH .EXIT GETDEV: .CLOSE R3 MOV MESS,MESSAG ;MOV also copies MTCH to MTCHAN ! ; Open channels on devices (R1 = #DVLIST, R5 = #AREA) : ; R3 = channel#, R4 = mask, R2 = total no. devices to open MOV #NDEV,R2 CLR R3 ;Channel nr. to open MOV #1,R4 ;Channel Bit OPENCH: CMPB R3,MTCHAN BNE 1$ .LOOKUP R5,R3,R1,#0 BR 2$ 1$: .LOOKUP R5,R3,R1 2$: BCS NEXTCH ; ; NO further examination of the device: dummy read on potentially ; available random access devices is done by JSHOW. This assures ; that drives with removable disks remain available when the drive ; is OFF at startup of DCJOB! ; SETCH: BIS R4,CHSTAT ;Channel open! NEXTCH: ASL R4 ADD #8.,R1 ;Point to next device INC R3 SOB R2,OPENCH ; ; Set up DATA & I/O buffer: ; ------------------------- MOV #-2,R0 .SETTOP SUB #BUFFER,R0 ;R0 = top of program TST (R0)+ ;R0 = available memory in bytes CLC ;Cannot use ASR (SIGNED division,/2) ROR R0 ;R0 = available memory in words MOV R0,BFSIZE CLRB R0 ;Multiple of 256. SWAB R0 MOV R0,BUFBLK ;No. of 256. word data buffers. ;;.iif NE,TEST .HERR RETURN ;Go running!! ; Buffer for list of devices & status & sizes & RW ; ------------------------------------------------ DVLIST: .BLKW 8.*4 RWTABL: .BLKW 7.*2 JOBDEF: PINIT: .ASCIZ /After startup: "Run JSHOW" ..../ ; 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 = 16. words .WORD 0,0 MESS: .BYTE 0 MTCH: .BYTE 0 ; ------------------------------------------------ JOB: .RAD50 /JOB / JOBFIL: .RAD50 /SY JBINFODAT/ NOJOBH: .ASCIZ \?No JOB: handler\ NOJOBF: .ASCIZ \?No SY:JBINFO.DAT\ .EVEN .=BUFFER+512. ;Get space for 256. WORD BUFFER! ;--------------End of initializing code / buffer area-----------------; .END START