.TITLE LAB5
;+
;
; 35.477 COMPUTER HARDWARE DESIGN LAB #5.
;
; I/O ROUTINES FOR Q-BUS FLOPPY CONTROLLER.
;
; WRITTEN SPRING 1992 BY NIMAL RATNAYAKE, DOUG SHOAF, JOHN WILSON.
;
;-
.PSECT ABS,LONG ;ADDRESSES ARE ABSOLUTE
.DSABL GBL ;UNDEFINED SYMBOLS CAUSE ERROR
;
; DEFINE THE SYMBOLS
;
NTRK= 35 ;NUMBER OF TRACKS PER DISK
NSEC= 16 ;NUMBER OF SECTORS PER TRACK
SECLEN= 128 ;SECTORS ARE 128 BYTES (SINGLE DENSITY)
;
; DEVICE REGISTERS.
;
FDCSR= ^X20001E78 ;COMMAND/STATUS REGISTER
FDCSRH= FDCSR+1 ;HIGH BYTE OF CSR
FDTRK= FDCSR+2 ;WD 1771 TRACK REGISTER (BYTE)
FDSEC= FDCSR+4 ;WD 1771 SECTOR REGISTER (BYTE)
FDDAT= FDCSR+6 ;WD 1771 DATA REGISTER (BYTE)
;
; INTERRUPT VECTOR LOCATIONS.
;
; VECTORS ARE .LONG'S CONTAINING THE LONGWORD-ALIGNED (MULTIPLE OF 4)
; ADDRESS OF THE INTERRUPT SERVICE ROUTINE IN BITS <31:2>. THE LOW 2 BITS MUST
; BE 00 TO USE THE KERNEL STACK; OTHER VALUES DO OTHER THINGS, IN PARTICULAR
; 10 WILL CAUSE A JUMP TO USER MICROCODE, SO MAKE SURE THE SERVICE ROUTINE
; STARTS ON A LONGWORD BOUNDARY (ADDRESS=MULTIPLE OF 4)!
;
VEC$A= ^X2B0 ;INTERRUPT A VECTOR
VEC$B= ^X2B4 ;INTERRUPT B VECTOR
;
; INTERNAL PROCESSOR REGISTER NUMBERS, ACCESSED WITH MTPR INSTRUCTION
; (N.B. SECOND OPERAND IS POINTER TO REG SO MUST BE IMMEDIATE!).
; THESE MUST BE INITIALIZED BEFORE INTERRUPTS WILL WORK.
PR$_SCBB=^X11 ;SYSTEM CONTROL BLOCK BASE (INIT TO 0)
PR$_IPL=^X12 ;INTR PRIORITY LEVEL (INIT TO 13 TO ALLOW FLOPPY INTRS)
;
; THE NEXT FOUR PROCESSOR REGISTERS CONTROL THE CONSOLE TERMINAL INTERFACE.
; (NOT ALL VAXEN IMPLEMENT THESE BUT THE KA640 DOES)
;
RXCS= ^X20 ;UART RECEIVER CONTROL/STATUS REG (BIT 7 = READY)
RXDB= ^X21 ;UART RECEIVER DATA BUFFER REG (LOW BYTE = CHAR)
TXCS= ^X22 ;UART TRANSMITTER CONTROL/STATUS REG (BIT 7 = READY)
TXDB= ^X23 ;UART TRANSMITTER DATA BUFFER REG (LOW BYTE = CHAR)
;
; ASCII CHARACTERS
;
CTRLC= ^O3 ;CONTROL/C (ABORT FROM PROMPT)
BEL= ^O7 ;BELL (7 OCTAL)
BS= ^O10 ;BACKSPACE
LF= ^O12 ;LINE FEED
CR= ^O15 ;CARRIAGE RETURN
RUB= ^O177 ;RUBOUT
;
STACK= ^X1000 ;STACK BUILDS DOWN BELOW FIRST ROUTINE
;
; ROUTINE TO SEEK TO TRACK 34 USING POLLED I/O (NO INTERRUPTS).
;
.=^X1000 ;START WITH "S 1000"
SEEK: ; WAIT UNTIL 1771 IS READY (SHOULD BE READY ALREADY)
CLRB @#FDCSRH ;CLEAR THE CSR/FIFO SETTINGS
10$: MOVB @#FDCSR,R0 ;READ STATUS
BLBS R0,10$ ;IF BIT 0 IS 1 (BUSY) WAIT
MOVB #34,@#FDDAT ;LOAD TRACK NUMBER
MOVB #^X13,@#FDCSR ;SEEK COMMAND
; BRIEF DELAY TO GIVE THE "BUSY" BIT TIME TO TURN ON
MOVL #20,R0 ;WAIT LOOP COUNT
20$: SOBGTR R0,20$ ;SIT 'N SPIN
; WAIT FOR THE "BUSY" BIT TO TURN OFF
30$: MOVB @#FDCSR,R0 ;READ STATUS
BLBS R0,30$ ;IF LOW BIT SET (BUSY) WAIT
HALT
;
; ROUTINE TO SEEK TO TRACK 0 USING POLLED I/O (NO INTERRUPTS).
;
.=^X2000 ;START WITH "S 2000"
RECAL: ; WAIT UNTIL 1771 IS READY (SHOULD BE READY ALREADY)
CLRB @#FDCSRH ;CLEAR THE CSR/FIFO SETTINGS
10$: MOVB @#FDCSR,R0 ;READ STATUS
BLBS R0,10$ ;IF BIT 0 IS 1 (BUSY) WAIT
MOVB #^X03,@#FDCSR ;RECALIBRATE COMMAND
; BRIEF DELAY TO GIVE THE "BUSY" BIT TIME TO TURN ON
MOVL #20,R0 ;WAIT LOOP COUNT
20$: SOBGTR R0,20$ ;SIT 'N SPIN
; WAIT FOR THE "BUSY" BIT TO TURN OFF
30$: MOVB @#FDCSR,R0 ;READ STATUS
BLBS R0,30$ ;IF LOW BIT SET (BUSY) WAIT
HALT
;
; SAME AS ABOVE ONLY USES INTERRUPT "A" TO DETECT COMPLETION.
;
; IF INTERRUPT "A" NEVER HAPPENS THIS ROUTINE WILL SPIN FOREVER,
; TYPE "BREAK" TO HALT.
;
.=^X3000 ;START WITH "S 3000"
RECAL1: ; INIT INTERRUPT SYSTEM
MOVL #STACK,SP ;SET STACK POINTER
CLRB @#FDCSRH ;CLEAR THE CSR/FIFO SETTINGS
MTPR #^X0,#PR$_SCBB ;SET SYS CTRL BLK BASE ADDRESS TO 0
MTPR #^X13,#PR$_IPL ;SET INTR PRIORITY LEVEL TO 13
MOVL #INTA,@#VEC$A ;SET INTERRUPT VECTOR A
CLRB @#DONE ;INTA HASN'T RUN YET
MOVW #^X1003,@#FDCSR ;INTR ENA=1,RECALIBRATE
10$: TSTB @#DONE ;HAS INTR A TRIGGERED?
BEQL 10$ ;LOOP IF NOT
HALT
;
; FILL SECTOR BUFFER FROM KEYBOARD.
;
.=^X4000 ;START WITH "S 4000"
FILL: MOVL #FILLPR,R0 ;POINT AT PROMPT
MOVL #6,R1 ;LENGTH=6 CHARS
JSB @#PRINT ;PRINT THE PROMPT
MOVL #BUFFER,R3 ;POINT AT BUFFER
MOVL #SECLEN,R4 ;BYTE COUNT
10$: JSB @#GETC ;GET A CHARACTER
CMPB R0,#RUB ;RUBOUT?
BEQL 30$ ;YES
CMPB R0,#CR ;CR?
BEQL 40$
MOVB R0,(R3)+ ;WRITE IT
JSB @#PUTC ;ECHO THE CHARACTER
SOBGTR R4,10$ ;LOOP FOR EACH BYTE
20$: MOVL #CRLF,R0 ;POINT AT CR+LF
MOVL #2,R1 ;LENGTH=2
JSB @#PRINT ;ECHO A CRLF
HALT ;AND HALT
30$: ; THEY TYPED RUBOUT -- DELETE PREVIOUS CHARACTER
CMPL R4,#SECLEN ;AT BEGINNING OF LINE ALREADY?
BEQL 10$ ;YES, IGNORE
MOVL #BKSPBK,R0 ;POINT AT BACKSPACE-SPACE-BACKSPACE
MOVL #3,R1 ;LENGTH=3 CHARS
JSB @#PRINT ;WIPE OUT PREVIOUS CHARACTER
DECL R3 ;BACK UP POINTER
INCL R4 ;BUMP FREE COUNTER
BRB 10$ ;AROUND FOR MORE
40$: ; THEY TYPED CR -- PAD REST OF BUFFER WITH BLANKS
MOVC5 #0,(R3),#^A' ',R4,(R3) ;OH BABY (SEE MANUAL FOR INFO ON MOVC5)
BRB 20$ ;ECHO CR+LF AND HALT
FILLPR: .ASCII /DATA? /
;
; ROUTINE TO READ/WRITE THE FIFO USING INTERRUPT "B".
;
; WRITES THE FIRST 64 BYTES OF BUFFER (LOADED BY FILL) INTO THE FIFO'S,
; THEN HALTS; WHEN THE USER TYPES "C" (CONTINUE), READS THE FIFO'S BACK
; INTO THE SECOND 64 BYTES OF BUFFER AND PRINTS THE DATA READ.
;
.=^X5000 ;START WITH "S 5000"
RWFIFO: ; INIT INTERRUPT SYSTEM
MOVL #STACK,SP ;SET STACK POINTER
CLRB @#FDCSRH ;DISABLE INTERRUPTS
MOVL #INTB$W,@#VEC$B ;SET INTERRUPT VECTOR B (WRITE ROUTINE)
MTPR #^X0,#PR$_SCBB ;SET SYS CTRL BLK BASE ADDRESS TO 0
MTPR #^X13,#PR$_IPL ;SET INTR PRIORITY LEVEL TO 13
MOVL #BUFFER,@#POINTR ;ADDRESS OF BEGINNING OF BLOCK
MOVL #64,@#COUNTR ;BYTE COUNT
MOVB #^XE8,@#FDCSRH ;SET FIFO=1, FFD=1, FIFO-RESET=1, INTR ENB=1
10$: TSTL @#COUNTR ;TRANSFERRED ALL BYTES?
BNEQ 10$ ;LOOP IF NOT
HALT ;;; USER MAY EXAMINE REGISTERS AND <C>ONTINUE
MOVL #INTB$R,@#VEC$B ;SET INTERRUPT VECTOR B
MOVL #BUFFER+64,@#POINTR ;ADDRESS OF BUFFER INTO WHICH TO READ
MOVL #64,@#COUNTR ;BYTE COUNT
MOVB #^X88,@#FDCSRH ;SET FIFO=1,FFD=0,INTR ENB=1
20$: TSTL @#COUNTR ;TRANSFERRED ALL BYTES?
BNEQ 20$ ;SPIN UNTIL DONE
; PRINT OUT THE DATA READ
MOVL #BUFFER+64,R0 ;POINT AT THE PART WE JUST READ
MOVL #64,R1 ;LENGTH
JSB @#PRINT
MOVL #CRLF,R0 ;CR+LF
MOVL #2,R1 ;LENGTH=2 CHARS
JSB @#PRINT
HALT
;
; READ A SECTOR FROM THE DISK. USES INTERRUPTS A AND B.
;
; USER IS PROMPTED FOR TRACK AND SECTOR (IN DECIMAL), AND THE DATA READ
; ARE PRINTED ON THE CONSOLE TERMINAL. IF THERE IS A READ ERROR THEN
; PRINT "ERR"; TYPE ^C TO HALT AND THEN EXAMINE THE DEVICE REGISTERS
; TO FIND OUT WHAT KIND OF ERROR IT WAS.
;
; THE DATA READ OVERWRITE WHATEVER WAS IN THE SECTOR BUFFER.
;
.=^X6000 ;START WITH "S 6000"
RDSEC: JSB @#TRKSEC ;GET TRACK, SECTOR FROM USER INTO R1, R2
MOVL #BUFFER,@#POINTR ;SET POINTER TO START OF BUFFER
; INITIALIZE THE INTERRUPT SYSTEM
MOVL #STACK,SP ;INIT STACK POINTER
MOVL #INTA,@#VEC$A ;INTERRUPT "A" SERVICE ROUTINE (SET DONE=1)
MOVL #INTB$R,@#VEC$B ;INTERRUPT "B" SERVICE ROUTINE (READ FIFO)
MTPR #^X0,#PR$_SCBB ;SET SYS CTRL BLK BASE ADDRESS TO 0
MTPR #^X13,#PR$_IPL ;SET INTR PRIORITY LEVEL TO 13
; TELL 1771 TO SEEK TO THE SPECIFIED TRACK
CLRB @#FDCSRH ;CLEAR FIFO CONTROL BITS
MOVB R1,@#FDDAT ;GIVE TRACK NUMBER TO 1771
MOVB #^X13,@#FDCSR ;SEEK COMMAND (TO THAT TRACK)
; BRIEF DELAY TO ALLOW "BUSY" BIT TO COME ON
MOVL #20,R0 ;WAIT LOOP COUNT
20$: SOBGTR R0,20$ ;SIT 'N SPIN
; SPIN UNTIL "BUSY" BIT CLEARS AGAIN
30$: MOVB @#FDCSR,R0 ;READ STATUS
BLBS R0,30$ ;IF LSB IS 1 (BUSY) WAIT
; TELL 1771 TO READ THE SPECIFIED SECTOR
MOVL #SECLEN,@#COUNTR ;SET COUNTER TO NUMBER OF BYTES TO TRANSFER
CLRB @#DONE ;CLEAR "DONE" SEMAPHORE
MOVB R2,@#FDSEC ;LOAD SECTOR REGISTER
MOVW #^XB88C,@#FDCSR ;FIFO=1,FFD=0,ENA=1,ENB=1,FIFO-RESET=1,READ
40$: TSTB @#DONE ;HAS INTR A OCCURRED YET?
BEQL 40$ ;IF NOT LOOP
BITB #^X9C,@#FDCSR ;CHECK STATUS: NOT RDY, REC NOT FND, CRC, LOST
BNEQ 50$ ;ERROR IF ANY ERROR BITS SET
; PRINT THE DATA FROM THE SECTOR
MOVL #BUFFER,R0 ;ADDRESS
MOVL #SECLEN,R1 ;LENGTH
BRB 60$ ;SKIP
50$: MOVL #ERR,R0 ;PRINT ERROR MESSAGE
MOVL #3,R1 ;LENGTH
60$: JSB @#PRINT ;PRINT IT
MOVL #CRLF,R0 ;POINT AT CR+LF
MOVL #2,R1 ;LENGTH=2 CHARACTERS
JSB @#PRINT ;SKIP A LINE
BRW RDSEC ;AROUND FOR MORE
ERR: .ASCII /ERR/
;
; WRITE A SECTOR TO THE DISK. USES INTERRUPTS A AND B.
;
; ANALOGOUS TO RDSEC; THE USER IS PROMPTED FOR TRACK AND SECTOR, AND
; THE CONTENTS OF THE SECTOR BUFFER ARE WRITTEN TO THAT SECTOR.
; ERRORS DETECTED AS ABOVE.
;
.=^X7000 ;START WITH "S 7000"
WRSEC: JSB @#TRKSEC ;GET TRACK, SECTOR FROM USER INTO R1, R2
MOVL #BUFFER,@#POINTR ;SET POINTER TO START OF BUFFER
; INITIALIZE THE INTERRUPT SYSTEM
MOVL #STACK,SP ;INIT STACK POINTER
MOVL #INTA,@#VEC$A ;INTERRUPT "A" SERVICE ROUTINE (SET DONE=1)
MOVL #INTB$W,@#VEC$B ;INTERRUPT "B" SERVICE ROUTINE (WRITE FIFO)
MTPR #^X0,#PR$_SCBB ;SET SYS CTRL BLK BASE ADDRESS TO 0
MTPR #^X13,#PR$_IPL ;SET INTR PRIORITY LEVEL TO 13
; TELL 1771 TO SEEK TO THE SPECIFIED TRACK
CLRB @#FDCSRH ;CLEAR FIFO CONTROL BITS
MOVB R1,@#FDDAT ;GIVE TRACK NUMBER TO 1771
MOVB #^X13,@#FDCSR ;SEEK COMMAND (TO THAT TRACK)
; BRIEF DELAY TO ALLOW "BUSY" BIT TO COME ON
MOVL #20,R0 ;WAIT LOOP COUNT
20$: SOBGTR R0,20$ ;SIT 'N SPIN
; SPIN UNTIL "BUSY" BIT CLEARS AGAIN
30$: MOVB @#FDCSR,R0 ;READ STATUS
BLBS R0,30$ ;IF LSB IS 1 (BUSY) WAIT
; TELL 1771 TO WRITE THE SPECIFIED SECTOR
MOVL #SECLEN,@#COUNTR ;SET COUNTER TO NUMBER OF BYTES TO TRANSFER
CLRB @#DONE ;CLEAR "DONE" SEMAPHORE
MOVB R2,@#FDSEC ;LOAD SECTOR REGISTER
MOVW #^XF8AC,@#FDCSR ;FIFO=1,FFD=1,ENA=1,ENB=1,FIFO-RESET=1,WRITE
40$: TSTB @#DONE ;HAS INTR A OCCURRED YET?
BEQL 40$ ;IF NOT LOOP
BITB #^XFC,@#FDCSR ;CHECK STATUS BITS: NOT RDY, WRT PROT, WRT FLT,
; REC NOT FND, CRC, LOST DATA
BNEQ 50$ ;ERROR IF ANY ERROR BITS SET
; PRINT THE DATA WRITTEN FOR CONFIRMATION
MOVL #BUFFER,R0 ;ADDRESS
MOVL #SECLEN,R1 ;LENGTH
BRB 60$ ;SKIP
50$: MOVL #ERR,R0 ;ERROR MESSAGE
MOVL #3,R1 ;LENGTH
60$: JSB @#PRINT ;PRINT IT
MOVL #CRLF,R0 ;POINT AT CR+LF
MOVL #2,R1 ;LENGTH
JSB @#PRINT ;SKIP A LINE
BRW WRSEC ;AROUND FOR MORE
;
; INTR A ("OPERATION COMPLETE") INTERRUPT SERVICE ROUTINE.
;
; SET "DONE" NON-ZERO AND TURN OFF INTR ENA
; (MAINLINE POLLS "DONE" TO SEE WHEN WE HAVE BEEN CALLED).
;
.ALIGN LONG
INTA: MOVB #1,@#DONE ;;SET "DONE" FLAG
BICB #^X10,@#FDCSRH ;;DISABLE FURTHER "A" INTERRUPTS
REI
;
; INTR B ("FIFO READY") ISR FOR READING FROM FIFO.
;
; READ THE NEXT BYTE FROM THE FIFO, OR DISABLE FIFO INTERRUPTS
; IF ALL BYTES HAVE BEEN TRANSFERRED.
;
.ALIGN LONG
INTB$R: MOVL R0,-(SP) ;;SAVE R0
MOVL @#POINTR,R0 ;;FETCH POINTER
MOVB @#FDDAT,(R0)+ ;;READ A BYTE (ADDRESS IS IN POINTR)
MOVL R0,@#POINTR ;;POINT AT NEXT BYTE
MOVL (SP)+,R0 ;;RESTORE
DECL @#COUNTR ;;DECREMENT COUNT
BEQL NOMORE ;;0, NO MORE INTS
REI
;
; INTR B ("FIFO READY") ISR FOR WRITING TO FIFO.
;
; WRITE THE NEXT BYTE TO THE FIFO, OR DISABLE FIFO INTERRUPTS
; IF ALL BYTES HAVE BEEN TRANSFERRED.
;
.ALIGN LONG
INTB$W: MOVL R0,-(SP) ;;SAVE R0
MOVL @#POINTR,R0 ;;FETCH POINTER
MOVB (R0)+,@#FDDAT ;;WRITE A BYTE (ADDRESS IS IN POINTR)
MOVL R0,@#POINTR ;;POINT AT NEXT BYTE
MOVL (SP)+,R0 ;;RESTORE
DECL @#COUNTR ;;DECREMENT COUNT
BEQL NOMORE ;;0, NO MORE INTS
; CUTENESS -- HANDLE NEXT BYTE NOW IF THERE IS ONE
; INSTEAD OF WAITING FOR THE NEXT INTERRUPT
BITB #1,@#FDCSRH ;;"FIFO IR" BIT SET?
BNEQ INTB$W ;;YES, WRITE ANOTHER BYTE
REI
;
NOMORE: ; BYTE COUNT EXHAUSTED, NO MORE INTS NEEDED (FROM INTB$R OR INTB$W)
BICB #8,@#FDCSRH ;;CLEAR "INTR ENB" BIT
REI
;
; GET TRACK AND SECTOR FROM TERMINAL.
;
; RETURNS TRACK IN R1, SECTOR IN R2. HALTS IF USER TYPES ^C.
;
TRKSEC: ; GET TRACK NUMBER
MOVL #TRKPRM,R0 ;TRACK PROMPT
MOVL #TRKPRL,R1 ;LENGTH
JSB @#PRINT ;DISPLAY PROMPT
JSB @#GETNUM ;GET NUMBER FROM USER
CMPL R0,#NTRK ;LESS THAN # OF TRACKS?
BGEQU TRKSEC ;RE-PROMPT IF NOT
MOVL R0,R6 ;SAVE IF SO
10$: ; GET SECTOR NUMBER
MOVL #SECPRM,R0 ;SECTOR PROMPT
MOVL #SECPRL,R1 ;LENGTH
JSB @#PRINT ;DISPLAY PROMPT
JSB @#GETNUM ;GET NUMBER
TSTL R0 ;0 NOT ALLOWED
BEQL 10$
CMPL R0,#NSEC ;.LE. # OF SECTORS?
BGTRU 10$ ;RE-PROMPT IF NOT
MOVL R6,R1 ;GET TRACK INTO R1
MOVL R0,R2 ;SECTOR INTO R0
RSB
;
; GET A NUMBER FROM THE KEYBOARD.
;
; RETURNED IN R0, R1-R4 TRASHED.
;
GETNUM: CLRL R4 ;TOTAL SO FAR=0
CLRL R5 ;# OF CHARACTERS DISPLAYED
10$: JSB @#GETC ;GET A CHARACTER
CMPB R0,#CR ;CR?
BEQL 40$
CMPB R0,#RUB ;RUBOUT?
BEQL 30$
CMPB R0,#^A'0' ;DIGIT, RIGHT?
BLSSU 20$
CMPB R0,#^A'9'
BGTRU 20$
JSB @#PUTC ;ECHO IT
SUBB #^A'0',R0 ;CONVERT TO BINARY
MULL #10,R4 ;TOTAL *10
ADDL R0,R4 ;ADD IN THE NEW DIGIT
INCL R5 ;CHAR COUNT *2
BRB 10$ ;LOOP
20$: ; IT WASN'T A DIGIT, CR OR RUBOUT
MOVB #BEL,R0 ;RING BELL
JSB @#PUTC
BRB 10$ ;TRY AGAIN
30$: ; RUBOUT - DELETE PREVIOUS CHARACTER
TSTL R5 ;IS THERE ONE?
BEQL 10$ ;NO
DECL R5 ;YES, -1
DIVL #10,R4 ;LOSE LAST DIGIT
MOVL #BKSPBK,R0 ;BACKSPACE-SPACE-BACKSPACE
MOVL #3,R1 ;LENGTH
BSB PRINT ;WIPE OUT THE CHAR
BRB 10$ ;AROUND FOR MORE
40$: ; END OF STRING
MOVL #CRLF,R0 ;POINT AT CR+LF
MOVL #2,R1 ;2 CHARACTERS
BSB PRINT ;ECHO IT
MOVL R4,R0 ;COPY NUMBER TO R0
RSB
;
; PRINT A STRING ON THE CONSOLE TERMINAL.
;
; R0 ADDRESS OF STRING
; R1 NUMBER OF CHARACTERS IN STRING
;
PRINT: MFPR #TXCS,R2 ;GET CSR
TSTB R2 ;"READY" BIT (BIT 7) SET YET?
BGEQ PRINT ;WAIT IF NOT
MOVZBL (R0)+,R2 ;GET NEXT CHARACTER
MTPR R2,#TXDB ;WRITE IT
SOBGTR R1,PRINT ;LOOP
RSB
;
; WAIT AND GET A CHARACTER FROM THE CONSOLE TERMINAL.
;
; IF THE CHARACTER IS CTRL/C THEN HALT.
;
; R0 RETURNS CHARACTER
;
GETC: MFPR #RXCS,R0 ;GET CSR
TSTB R0 ;CHAR READY?
BGEQ GETC ;NO
MFPR #RXDB,R0 ;YES, GET IT
MOVZBL R0,R0 ;CLEAR HIGH 24 BITS
CMPB R0,#CTRLC ;^C?
BEQL 10$ ;YES, HALT
RSB
10$: HALT
;
; WRITE A CHARACTER TO THE CONSOLE TERMINAL.
;
; R0 CHARACTER TO WRITE
;
PUTC: MFPR #TXCS,R1 ;GET CSR
TSTB R1 ;PORT READY FOR THE CHAR?
BGEQ PUTC ;NO
MTPR R0,#TXDB ;YES, PUT IT INTO THE TRANSMIT DATA BUFFER
RSB
;
BKSPBK: .BYTE BS,^A' ',BS
CRLF: .BYTE CR,LF
TRKPRM: .ASCII /TRACK? /
TRKPRL= .-TRKPRM
SECPRM: .ASCII /SECTOR? /
SECPRL= .-SECPRM
;
.=^X8000 ;EXAMINE THESE LOCATIONS WITH "E/P/L <ADDR>"
POINTR: .LONG ;POINTER TO NEXT BYTE TO READ OR WRITE "E/P/L 8000"
COUNTR: .LONG ;COUNTER OF BYTES REMAINING TO TRANSFER "E/P/L 8004"
DONE: .BYTE ;FLAG - NON-ZERO => DONE WITH OPERATION "E/P/B 8008"
;
.=^X9000 ;BUFFER LOCATION
BUFFER: .BLKB SECLEN ;HOLDS ONE SECTOR "E/P/B/N:7F 9000"
;
.END