.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 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 " 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