	.TITLE	YMDRIVER	:	RK11/RK05 HANDLER FOR THE VAX

	.IDENT	/MIT IV/

	.LIST	MEB

	.SBTTL	TITLE PAGE


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	AUTHOR : A. HERMES. III    MIT BATES LINEAR ACCELERATOR
;
;	DATE   : X/XX/MCMLXXVIII
;
;	
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.PAGE
	.SBTTL	RK11/RK05  SYSGEN INPUTS FOR INSTALLING HANDLER

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	INTERRUPT VECTOR FOR THE YM:  %O220
;	CSR ADDRESS FOR THE YM:       %O17404
;
;	SYSGEN COMMAND FILE :
;
;	$ RUN SYS$SYSTEM:SYSGEN
;	 LOAD DM0:YMDRIVER.EXE
;	 CONNECT YMA0/ADAPTER=3/VECTOR=%O220/CSR=%O17400
;	CONNECT YMA1/ADAPTER=3/VECTOR=%O220/CSR=%O17400
;	 SHOW /DEVICE
;	 EXIT
;
;	TYPE TO THE MONITOR :
;
;	$ @SYSGEN   <CR>
;
;	THIS WILL FACILITATE THE IMPLEMENTING OF THE DRIVER WITHOUT
;	UNDUE TYPING ERRORS.
;
;
;	THE DRIVER MAY ALSO BE INSTALLED IN THE [10,40]STARTUP.COM,
;	AFTER THE RUN SYS$SYSTEM:SYSGEN, SO THAT IT IS AUTOMATICALLY
;	INSTALLED AFTER EACH REBOOT.
;
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.PAGE
	.SBTTL RK11/RK05  DISK DRIVE TYPE AND CONTROLLER

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;									
;	THE DISK DRIVE IS A PERTEC RK11 DRIVE THAT IS COMPATABLE WITH THE 
;	DEC RK11 DISK DRIVES.
;
;
;	THE DRIVES AND CONTROLLER WERE OBTAINED FROM:
;
;		XYLOGIC, INC
;		BURLINGTON,MASS
;
;	THERE ARE SOME DIFFERENCES :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


.PAGE
	.SBTTL	RK11/RK05  SYSTEM MACRO LIBRARY CALLS

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; MACRO LIBRARY CALLS : SYSTEM DEFINITIONS
;
;	THESE DEFINITIONS ARE FOUND IN THE LIBRARY [1,1]LIB.MLB
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
	$DCDEF				;DEFINE DEVICE TYPES AND CLASSES
	$ADPDEF				;DEFINE ADP OFFSETS
	$CRBDEF				;DEFINE CRB OFFSETS
	$DDBDEF				;DEFINE DDB OFFSETS
	$DPTDEF				;DEFINE DPT OFFSETS
	$EMBDEF				;DEFINE EMB OFFSETS
	$IDBDEF				;DEFINE IDB OFFSETS
	$IODEF				;DEFINE I/O FUNCTION CODES
	$IRPDEF				;DEFINE IRP OFFSETS
	$UBADEF				;DEFINE UBA REGISTER OFFSETS
	$UCBDEF				;DEFINE UCB OFFSETS
	$VECDEF				;DEFINE INTERRUPT DISPATCH VECTOR OFFSETS
.PAGE
	.SBTTL	RK11/RK05  EXECUTE MACRO FOR THE RK05
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;
; EXECUTE FUNCTION AND BRANCH ON RETRIABLE ERROR CONDITION : 
;
;	THIS MACRO IS USED IN CONJUNCTION WITH THE HARDWARE FUNCTION
;	CODES OF THE RK11/RK05.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
	.MACRO	EXFUNCH BDST,FCODE
		.IF NB	FCODE
		MOVZBL	#CD'FCODE,R3
		.ENDC
		BSBW	FEXH
		.BYTE	BDST-.-1
	.ENDM
 
	.MACRO	EXFUNCL BDST,FCODE
		.IF NB	FCODE
 		MOVZBL	#CD'FCODE,R3
		.ENDC
		BSBW	FEXL
		.BYTE	BDST-.-1
	.ENDM
.PAGE
	.SBTTL	RK11/RK05  FUNCTION TABLE ( FTAB ) ENTRY MACRO
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; GENERATE FUNCTION TABLE ENTRY :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


 
	.MACRO	GENF FCODE
		CD'FCODE=.-FTAB/2
		.WORD	FCODE!YM_CS_M_GO!YM_CS_M_IDE
	.ENDM
.PAGE
	.SBTTL	RK11/RK05  REGISTER DEFINITIONS

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; REFERENCES : 
;
; RK11/RK05 REGISTER OFFSETS :
;
;	1]  PERIPHERALS HANDBOOD FOR THE PDP-11 : PAGES 4-314, 4-325
;
;	2]  RK11-D AND RK11-E MOVING HEAD DISK DRIVE CONTROLLER MANUAL :
;		   CHAPTER 3 : PAGES 3-1, 3-10
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	BIT POSITIONS FOR THE RK11/RK05 DEVICE REGISTERS :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
	$DEFINI	YM			;RK05 IS A YM ON THE VAX

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;
;DS	DRIVE STATUS REGISTER (RKDS)  :  R/O  :  ADDRESS = 777400
;
;	CONTAINS THE CURRENT SELECTED DRIVE STATUS AND THE CURRENT
;	SECTOR ADDRESS :
;
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

$DEF	YM_DS		.BLKW	1	; DRIVE STATUS REGISTER
	_VIELD	YM_DS,0,<-		; DRIVE STATUS REGISTER FIELD DEFINITIONS
		<SC,4>,-		; [0-3]    SECTOR COUNTER: 4 BITS WIDE
		<SCSA,,M>,-		; [4]      SECTOR ADDRESS FROM RKDA
		<WPS,,M>,-		; [5]      WRITE PROTECT STATUS
		<RWSR,,M>,-		; [6]      R/W/SEEK READY
		<DRY,,M>,-		; [7]      DRIVE READY
		<SOK,,M>,-		; [8]      SECTOR COUNTER OK
		<SIN,,M>,-		; [9]      SEEK INCOMPLETE
		<DRU,,M>,-		; [10]     DRIVE UNSAFE
		<RK05,,M>,-		; [11]     ID BIT : ALWAYS SET
		<DPL,,M>,-		; [12]     DRIVE POWER LOW
		<ID,3>,-		; [13-15]  ID OF DRV THAT SET INT
	>				;

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;ER	RK ERROR REGISTER (RKER) : R/O ALL BITS : ADDRESS = 777402
;
;	NOTE :  BITS 5 THRU 15 ARE ALL HARD ERRORS.
;		THEY ARE CLEARED ONLY BY A BUS INIT OR A CONTROL
;		CLEAR FUNCTION.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


$DEF	YM_ER		.BLKW	1	;ERROR REGISTER
	_VIELD	YM_ER,0,<-		; ERROR REGISTER BIT DEFINITIONS
		<WCE,,M>,-		; [0]      WRITE CHECK ERROR
		<CSE,,M>,-		; [1]      CHECKSUM ERROR
		<UNU,,M>,-		; [2]      UNUSED
		<SWPV,,M>,-		; [3]	   SEC WRT PROT VIO
		<SPR,,M>,-		; [4]	   SPARE BIT
		<NXS,,M>,-		; [5]      NONEXISTENT SECTOR
		<NXC,,M>,-		; [6]      NONEXISTENT CYCLINDER
		<NXD,,M>,-		; [7]      NONEXISTENT DISK
		<TE,,M>,-		; [8]      READ TIMING ERROR
		<DLT,,M>,-		; [9]      DATA LATE
		<NXM,,M>,-		; [10]     NONEXISTENT MEMORY
		<PGE,,M>,-		; [11]     PROGAMMING ERROR
		<SKE,,M>,-		; [12]     SEEK ERROR
		<WLO,,M>,-		; [13]     WRITE LOCK OUT VIOLATION
		<OVR,,M>,-		; [14]     OVERRUN
		<DRE,,M>,-		; [15]     DRIVE ERROR
	>				;

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;CS	CONTROL AND STATUS REGISTER (RKCS) :  ADDRESS = 777404
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
$DEF	YM_CS		.BLKW	1	;CONTROL STATUS REGISTER
	_VIELD	YM_CS,0,<-		; CONTROL STATUS REGISTER FIELD DEFINITIONS
		<GO,,M>,-		; [0]      GO BIT : WRITE ONLY BIT
		<FCODE,3>,-		; [1-3]    FUNCTION CODE :
		<MEX,2>,-		; [4-5]    MEM EXTEN BITS : R/W
		<IDE,,M>,-		; [6]      INTERRUPT ON DONE ENABLE
		<RDY,,M>,-		; [7]      CONTROLLER READY : R/O
		<SSE,,M>,-		; [8]      STOP ON SOFT ERROR : R/W
		<SPC,,M>,-		; [9]      SECTOR WRITE PROTECT CNTL
		<FMT,,M>,-		; [10]     FORMAT : R/W
		<IBA,,M>,-		; [11]     INH INC OF RKBA : R/W
		<MAI,,M>,-		; [12]     MAINTENANCE MODE : R/W
		<SCP,,M>,-		; [13]     SEARCH COMPLETE : R/O
		<HE,,M>,-		; [14]     HARD ERROR : R/O
		<ERR,,M>,-		; [15]     ERROR : RKER : R/O
	>				;


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;WC	WORD COUNT REGISTER (RKWC) :  ADDRESS = 777406
;
;	CONTAINS THE TWO'S COMPLEMENT OF THE TOTAL NUMBER OF 
;	WORDS TO BE AFFECTED BY A GIVEN FUNCTION.
;	IT INCREMENTS BY ONE AFTER EACH WORD TRANSFER.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


$DEF	YM_WC		.BLKW	1	;WORD COUNT REGISTER


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;BA	CURRENT BUS ADDRESS REGISTER (RKBA) :  ADDRESS = 777410
;
;	CONTAINS THE BUS ADDRESS TO OR FROM WHICH DATA WILL BE 
;	TRANSFERRED.
;	THE REGISTER IS INCREMENTED BY TWO AT THE END OF EACH
;	TRANSFER.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


$DEF	YM_BA		.BLKW	1	;BUS ADDRESS REGISTER


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;DA	DISK ADDRESS REGISTER (RKDA) :  ADDRESS = 777412
;
;	ALL RKDA BITS ARE LOADED FROM THE BUS DATA LINES ONLY IN
;	RK11 READY STATE, AND CLEARED BY BUS INIT AND CONTROL RESET.
;	THE RKDA IS INCREMENTED AUTOMATICALLY AT THE END OF EACH 
;	DISK SECTOR.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


$DEF	YM_DA		.BLKW	1	;DESIRED SECTOR/TRACK ADDRESS REGISTER
	_VIELD	YM_DA,0,<-		; DESIRED ADDRESS FIELD DEFINITIONS
		<SA,4>,-		; [0-3]    DESIRED SECTOR ADDRESS
		<SUR,,M>,-		; [4]      SURFACE
		<CYLADR,8>,-		; [5-12]   CYLINDER ADDRESS
		<DRSEL,3>-		; [13-15]  DRIVE SELECT
	>				;


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;DB	DATA BUFFER REGISTER (RKDB) :  ADDRESS = 777416
;
;	THIS REGISTER IS THE GENERAL DATA HANDLER.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


$DEF	YM_DB		.BLKW	1	; DATA BUFFER REGISTER
;
;
	$DEFEND	YM

;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	THERE ARE NO OFFSETS OR ECC IN THE RK05 DISK DRIVE :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;


; SOFTWARE STATUS IN UPPER BYTE OF OFFSET WORD
;

	_VIELD	YM,0,<-			;SOFTWARE STATUS BIT DEFINITIONS
		<ECI,,M>,-		; ECC INHIBIT
		<DCK,,M>-		; DATACHECK IN PROGRESS
		>

.PAGE
	.SBTTL RK11/RK05  DEFINE DEVICE DEPENDENT UCB OFFSETS
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	DEFINE DEVICE DEPENDENT UCB OFFSETS :
;
;	UNIT CONTROL BLOCK ( UCB ) : DEFINES THE CHARACTERISTICS AND CURRENT
;				     STATE OF AN INDIVIDUAL DEVICE UNIT.
;
;	THE UCB BLOCK DESCRIBES OR PROVIDES POINTERS TO THE DEVICE TYPE,
;	CONTROLLER, DRIVER, DEVICE STATUS, AND CURRENT I/O ACTIVITY.
;
;	THE CONNECT COMMAND TO SYSGEN CREATES UCB'S OF THE LENGTH SPEC-
;	IFIED IN THE DRIVER PROLOGUE TABLE OF THE DEVICE'S DRIVER.
;
;
;	THE DRIVER USES UCB STORAGE LOCATED BEYOND THE STANDARD UCB FIELDS
;	FOR THE DEVICE SPECIFIC DATA AND TEMPORARY STORAGE.  THIS DRIVER
;	USES STORAGE BEGINNING AT UCB$W_BCR+2.
;
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 
	$DEFINI	UCB
 
.=UCB$W_BCR+2				;
 
$DEF	UCB$W_YM_DS	.BLKW	1	;DRIVE STATUS REGISTER
$DEF	UCB$W_YM_ER	.BLKW	1	;ERROR REGISTER
$DEF	UCB$W_YM_CS	.BLKW	1	;CONTROL STATUS REGISTER
$DEF	UCB$W_YM_WC	.BLKW	1	;WORD COUNT REGISTER
$DEF	UCB$W_YM_BA	.BLKW	1	;BUS ADDRESS REGISTER
$DEF	UCB$W_YM_DA	.BLKW	1	;DISK ADDRESS REGISTER
$DEF	UCB$W_YM_DB	.BLKW	1	;DATA BUFFER REGISTER
$DEF	UCB$W_YM_DPN	.BLKW	1	;DATAPATH NUMBER
$DEF	UCB$L_YM_DPR	.BLKL	1	;DATAPATH REGISTER
$DEF	UCB$L_YM_FMPR	.BLKL	1	;FINAL MAP REGISTER
$DEF	UCB$L_YM_PMPR	.BLKL	1	;PREVIOUS MAP REGISTER
;			.BLKW	1	;SPARE USED WORD
 
	$DEFEND	UCB

.PAGE
	.SBTTL	RK11/RK05  HARDWARE FUNCTION CODES FOR THE RK05
 

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	HARDWARE FUNCTION CODES :
;
;
;	THE RK11/RK05 HAS ONLY 8 FUNCTION CODES :
;
;	THE FOLLOWING FUNCTIONS ARE THE CODES FOR BITS 0-3 OF THE CSR,
;	AND ARE THE ONLY FUNCTION CODES FOR THE RK05 DEVICE.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	BIT3	BIT2	BIT1	OPERATION
;
;	 0	 0	 0	 CONTROL RESET
;	 0	 0	 1	 WRITE
;	 0	 1	 0	 READ
;	 0	 1	 1	 WRITE CHECK
;	 1	 0	 0	 SEEK
;	 1	 0	 1	 READ CHECK
;	 1	 1	 0	 DRIVE RESET
;	 1	 1	 1	 WRITE LOCK
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	HARDWARE FUNCTION CODES DEFINED AND RENAMED FOR THE VAX :
;
;	CONTROL RESET = INITIALIZES ALL INTERNAL REGISTERS AND FLIP-
;	FLOPS, AND CLEARS ALL OF THE BITS OF THE SEVEN PROGRAMMABLE
;	REGISTERS, EXCEPT RKCS 07 (READY) WHICH IT SETS, AND RKDS
;	01 THRU 11, WHICH ARE NOT AFFECTED.
;
;	CONTROL RESET = DRIVE CLEAR ( FOR THE VAX )
;
;	DRIVE RESET = FOR A DRIVE RESET FUNCTION, THE CONTROLLER DIRECTS
;	THE SELECTED DISK DRIVE TO MOVE ITS HEAD MECHANISM TO CYLINDER
;	000 AND RESET ALL ACTIVE ERROR STATUS LINES.
;
;	DRIVE RESET = RECALIBRATE DRIVE ( FOR THE VAX )
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	FUTURE IMPLEMENTATION : TO ALLOW THE RK11/RK05 TO READ AND WRITE
;				HEADERS.
;
;	WRITEHEAD = FORMAT BIT (CSR 10) + WRITE BIT (CSR 1) OR'D WITH THE
;	GO, SSE  AND IE FROM THE GENF MACRO : ^X443
;
;	MOVW	#CDF_WRITEHEAD!YM_CS_M_FMT,YM_CS	;WRITE HEADER FUNCTION
;
;OR     MOVW	#^X443,YM_CS(R4)
;
;	READHEAD = FORMAT BIT (CSR 10) + READ BIT (CSR 2) OR'D WITH THE
;	GO, SSE  AND IE FROM THE GENF MACRO : ^X445
;
;	MOVW	#CDF_READHEAD!YM_CS_M_FMT,YM_CS		;READ HEADER FUNCTION
;
;OR	MOVW	#^X445,YM_CS(R4)				;
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	HARDWARE FUNCTION CODES DEFINED :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
F_WRTLOC = ^X7*2			; WRITE LOCK
F_SEEK = ^X4*2				; SEEK CYLINDER
F_RECAL = ^X6*2				; RECAL DRIVE = DRIVE RESET
F_DRVCLR = ^X0*2			; DRIVE CLEAR = CONTROL RESET
F_WRITECHECK = ^X3*2			; WRITE CHECK DATA
F_WRITEDATA = ^X1*2			; WRITE DATA
F_READCHECK = ^X5*2			; READ CHECK
F_READDATA = ^X2*2			; READ DATA
F_WRITEHEAD = ^X1*2!YM_CS_M_FMT		; WRITE HEADER FUNCTION
F_READHEAD = ^X2*2!YM_CS_M_FMT		; READ HEADER FUNCTION

.PAGE
	.SBTTL	RK11/RK05  DRIVER PROLOGUE TABLE FOR THE RK05
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; DRIVER PROLOGUE TABLE : ( DPT )
;
;	THE DPT DESCRIBES THE DEVICE TYPE, DRIVER NAME, AND FIELDS IN THE
;	I/O DATA BASE THAT ARE TO BE INITIALIZED DURING DRIVER LOADING
;	AND RELOADING.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	SINCE THERE IS NO DEVICE TYPE FOR THE RK05 IN THE $DCDEF MACRO
;	THE RK05 IS DEFINED TO BE A SUPPORTED DEVICE ON THE VAX.
;

	DT$_RK05=DT$_RP04		;VMS THINKS YM IS AN RP04

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
	DPTAB	-			;DEFINE DPT

		END=YM_END,-		;END OF DRIVER
		ADAPTER=UBA,-		;ADAPTER TYPE
		FLAGS=DPT$M_SVP,-	;SYSTEM PAGE TABLE ENTRY REQUIRED
		UCBSIZE=200,-		;UCB SIZE
		NAME=RKDRIVER		;DRIVER NAME

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	DPT_STORE INIT			;CONTROL BLOCK INIT VALUES
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	DPT_STORE DDB,DDB$L_ACPD,L,<^A\F11\> 	   ;DEFAULT ACP NAME
	DPT_STORE DDB,DDB$L_ACPD+3,B,3		   ;ACP CLASS
	DPT_STORE UCB,UCB$B_FIPL,B,8		   ;FORK IPL
	DPT_STORE UCB,UCB$L_DEVCHAR,L,-		   ;DEVICE CHARACTERISTICS
		<DEV$M_FOD-			   ; FILES ORIENTED
		!DEV$M_DIR-			   ; DIRECTORY STRUCTURED
		!DEV$M_AVL-			   ; AVAILABLE
		!DEV$M_ELG-			   ; ERROR LOGGING ENABLED
		!DEV$M_SHR-			   ; SHAREABLE
		!DEV$M_IDV-			   ; INPUT DEVICE
		!DEV$M_ODV-			   ; OUTPUT DEVICE
		!DEV$M_RND>			   ; RANDOM ACCESS
	DPT_STORE UCB,UCB$B_DEVCLASS,B,DC$_DISK    ;DEVICE CLASS
	DPT_STORE UCB,UCB$W_DEVBUFSIZ,W,512 	   ;DEFAULT BUFFER SIZE
	DPT_STORE UCB,UCB$B_SECTORS,B,12 	   ;NUMBER OF SECTORS PER TRACK
	DPT_STORE UCB,UCB$B_TRACKS,B,2		   ;NUMBER OF TRACKS PER CYLINDER
	DPT_STORE UCB,UCB$W_CYLINDERS,W,200	   ;NUMBER OF CYLINDERS : RK05
	DPT_STORE UCB,UCB$L_MAXBLOCK,L,<200*2*12>  ;MAXIMUM BLOCK NUMBER : RK05
	DPT_STORE UCB,UCB$B_DEVTYPE,B,DT$_RK05	   ;TENTATIVE DEVICE TYPE
	DPT_STORE UCB,UCB$B_DIPL,B,21		   ;DEVICE IPL
	DPT_STORE UCB,UCB$B_ERTCNT,B,8		   ;ERROR RETRY COUNT
	DPT_STORE UCB,UCB$B_ERTMAX,B,8		   ;MAX ERROR RETRY COUNT

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	DPT_STORE REINIT		;CONTROL BLOCK RE-INIT VALUES
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	DPT_STORE CRB,CRB$L_INTD+4,D,YM$INT 			;ISR ADDRESS
	DPT_STORE CRB,CRB$L_INTD+VEC$L_INITIAL,D,YM_RK11_INIT   ;CONTROLLER INIT
	DPT_STORE CRB,CRB$L_INTD+VEC$L_UNITINIT,D,YM_RK05_INIT  ;UNIT INIT
	DPT_STORE DDB,DDB$L_DDT,D,RK$DDT 			;DDT ADDRESS
	DPT_STORE END						;

.PAGE
	.SBTTL	RK11/RK05  DRIVER DISPATCH TABLE FOR THE RK05
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; DRIVER DISPATCH TABLE : ( DDT )
;
;	THE DDT LISTS THE ENTRY POINTS FOR DRIVER SUBROUTINES TO BE CALLED
;	BY THE OPERATING SYSTEM TO PROCESS I/O.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
	DDTAB	RK,-				;DRIVER DISPATCH TABLE
		YM_STARTIO,-			;START I/O OPERATION
		YM_UNSOLNT,-			;UNSOLICITED INTERRUPT
		YM_FUNCTABLE,-			;FUNCTION DECISION TABLE
		0,-				;CANCEL I/O ENTRY POINT
		YM_REGDUMP,-			;REGISTER DUMP ROUTINE
		<11*4>,-			;DIAGNOSTIC BUFFER SIZE
		<<11*4>+<EMB$L_DV_REGSAV>>	;SIZE OF ERROR BUFFER

.PAGE
	.SBTTL	RK11/RK05  HARDWARE I/O FUNCTION CODE TABLE
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; HARDWARE I/O FUNCTION CODE TABLE :
;
;	THIS TABLE IS GENERATED VIA THE GENF MACRO.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
FTAB:						; DEFINE FNCT TBLE

	GENF	F_WRTLOC			; WRITE LOCK
	GENF	F_SEEK				; SEEK CYLINDER
	GENF	F_RECAL				; RECALIBRATE
	GENF	F_DRVCLR			; DRIVE CLEAR
	GENF	F_WRITECHECK			; WRITE CHECK
	GENF	F_WRITEDATA			; WRITE DATA
	GENF	F_READCHECK			; READ CHECK
	GENF	F_READDATA			; READ DATA
	GENF	F_WRITEHEAD			; WRITE HEADERS
	GENF	F_READHEAD			; READ HEADER
.PAGE
 	.SBTTL	RK11/RK05  FUNCTION DECISION TABLE
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; RK11/RK05  FUNCTION DECISION TABLE ( FDT ) : VAX RK05 DRIVER
;
;	THE FDT LISTS CODES FOR I/O FUNCTIONS THAT ARE VALID FOR THE DEVICE,
;	AND INDICATES WHETHER THE FUNCTIONS ARE BUFFERED AND SPECIFIES SUB-
;	ROUTINES TO PREFORM PREPROCESSING FOR PARTICULAR FUNCTIONS.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	IO$_WRTLOC	=IO$_REWIND
 
YM_FUNCTABLE:				;FUNCTION DECISION TABLE
	FUNCTAB	,-			;LEGAL FUNCTIONS
		<WRTLOC,-		;WRITE LOCK FUNCTION
		SEEK,-			;SEEK CYLINDER
		 RECAL,-		;RECALIBRATE
		 DRVCLR,-		;DRIVE CLEAR
		 SENSECHAR,-		;SENSE CHARACTERISTICS
		 SETCHAR,-		;SET CHARACTERISITCS
		 SENSEMODE,-		;SENSE MODE
		 SETMODE,-		;SET MODE
		 WRITECHECK,-		;WRITE CHECK
		 WRITEHEAD,-		;WRITE HEADERS
		 READHEAD,-		;READ HEADER
		 READLBLK,-		;READ LOGICAL BLOCK
		 WRITELBLK,-		;WRITE LOGICAL BLOCK
		 READPBLK,-		;READ PHYSICAL BLOCK
		 WRITEPBLK,-		;WRITE PHYSICAL BLOCK
		 READVBLK,-		;READ VIRTUAL BLOCK
		 WRITEVBLK,-		;WRITE VIRTUAL BLOCK
		 ACCESS,-		;ACCESS FILE AND/OR FIND DIRECTORY ENTRY
		 ACPCONTROL,-		;ACP CONTROL FUNCTION
		 CREATE,-		;CREATE FILE AND/OR CREATE DIRECTORY ENTRY
		 DEACCESS,-		;DEACCESS FILE
		 DELETE,-		;DELETE FILE AND/OR DIRECTORY ENTRY
		 MODIFY,-		;MODIFY FILE ATTRIBUTES
		 MOUNT>			;MOUNT VOLUME
	FUNCTAB	,-			;BUFFERED I/O FUNCTIONS
		<WRTLOC,-		;WRITE LOCK FUNCTION
		 SEEK,-			; SEEK CYLINDER
		 RECAL,-		; RECALIBRATE
		 DRVCLR,-		; DRIVE CLEAR
		 SENSECHAR,-		;SENSE CHARACTERISTICS
		 SETCHAR,-		;SET CHARACTERISITCS
		 SENSEMODE,-		;SENSE MODE
		 SETMODE,-		;SET MODE
		 ACCESS,-		;ACCESS FILE AND/OR FIND DIRECTORY ENTRY
		 ACPCONTROL,-		;ACP CONTROL FUNCTION
		 CREATE,-		;CREATE FILE AND/OR CREATE DIRECTORY ENTRY
		 DEACCESS,-		;DEACCESS FILE
		 DELETE,-		;DELETE FILE AND/OR DIRECTORY ENTRY
 		 MODIFY,-		;MODIFY FILE ATTRIBUTES
		 MOUNT>			;MOUNT VOLUME
	FUNCTAB	YM_ALIGN,-		;TEST ALIGNMENT FUNCTIONS
		<READHEAD,-		;READ HEADER
		 READLBLK,-		;READ LOGICAL BLOCK
		 READPBLK,-		;READ PHYSICAL BLOCK
		 READVBLK,-		;READ VIRTUAL BLOCK
		 WRITECHECK,-		;WRITE CHECK
		 WRITEHEAD,-		;WRITE HEADERS
		 WRITELBLK,-		;WRITE LOGICAL BLOCK
		 WRITEPBLK,-		;WRITE PHYSICAL BLOCK
		 WRITEVBLK>		;WRITE VIRTUAL BLOCK
	FUNCTAB	+ACP$READBLK,-		;READ FUNCTIONS
		<READHEAD,-		;READ HEADER
		 READLBLK,-		;READ LOGICAL BLOCK
		 READPBLK,-		;READ PHYSICAL BLOCK
		 READVBLK>		;READ VIRTUAL BLOCK
	FUNCTAB	+ACP$WRITEBLK,-		;WRITE FUNCTIONS
		<WRITECHECK,-		;WRITE CHECK
		 WRITEHEAD,-		;WRITE HEADERS
		 WRITELBLK,-		;WRITE LOGICAL BLOCK
		 WRITEPBLK,-		;WRITE PHYSICAL BLOCK
		 WRITEVBLK>		;WRITE VIRTUAL BLOCK
	FUNCTAB	+ACP$ACCESS,<ACCESS,CREATE> ;ACCESS AND CREATE FILE OR DIRECTORY
	FUNCTAB	+ACP$DEACCESS,<DEACCESS> ;DEACCESS FILE
	FUNCTAB	+ACP$MODIFY,-		;
		<ACPCONTROL,-		;ACP CONTROL FUNCTION
		 DELETE,-		;DELETE FILE OR DIRECTORY ENTRY
		 MODIFY>		;MODIFY FILE ATTRIBUTES
	FUNCTAB	+ACP$MOUNT,<MOUNT>	;MOUNT VOLUME
	FUNCTAB	+EXE$ZEROPARM,-		;ZERO PARAMETER FUNCTIONS
		 <RECAL,-		; RECALIBRATE
		 DRVCLR>		; DRIVE CLEAR
	FUNCTAB	+EXE$ONEPARM,-		;ONE PARAMETER FUNCTIONS
		<SEEK,-			;SEEK CYLINDER
		 RECAL>			;RECALIBRATE
	FUNCTAB	+EXE$SENSEMODE,-		;
		<SENSECHAR,-		;SENSE CHARACTERISTICS
		 SENSEMODE>		;SENSE MODE
	FUNCTAB	+EXE$SETCHAR,-		;
		<SETCHAR,-		;SET CHARACTERISTICS
		 SETMODE>		;SET MODE


.PAGE
 	.SBTTL	RK11/RK05  TEST ALIGNMENT OF BUFFER

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;
; YM_ALIGN - TEST CONDITION OF ODD/EVEN TRANSFER BYTE COUNT
;
; THIS ROUTINE IS CALLED FROM THE FUNCTION DECISION TABLE ( FDT ) DISPATCHER TO
; DETERMINE IF THE SPECIFIED TRANSFER COUNT IS ODD OR EVEN, WITH THE RESULT
; OF ACCEPTING ONLY THOSE QIO'S WITH AN EVEN TRANSFER BYTE COUNT.
;
; INPUTS:
;
;	R0 = SCRATCH.
;	R1 = SCRATCH.
;	R2 = SCRATCH.
;	R3 = ADDRESS OF I/O REQUEST PACKET (IRP)
;	R4 = CURRENT PROCESS PCB ADDRESS.
;	R5 = ASSIGNED DEVICE UCB ADDRESS.
;	R6 = ADDRESS OF CCB.
;	R7 = BIT NUMBER OF THE I/O FUNCTION CODE
;	R8 = FUNCTION DECISION TABLE ( FDT ) DISPATCH ADDRESS.
;	R9 = SCRATCH.
;	R10 = SCRATCH.
;	R11 = SCRATCH.
;	AP = ADDRESS OF FIRST FUNCTION DEPENDENT PARAMETER.
;
; OUTPUTS:
;
;	IF THE BYTE COUNT FOR THE TRANSFER IS NOT EVEN, THEN THE I/O OPER-
;	ATION IS ABORTED WITH AN ERROR.
;
;	OTHERWISE, A RETURN TO THE FDT DISPATCHER IS EXECUTED.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 

YM_ALIGN:				; CHECK IF BYTE COUNT IS EVEN

	BBS	#0,4(AP),10$		;IF SET, ODD BYTE COUNT

	RSB				; RETURN TO FDT DISPATCHER

10$:	MOVZWL	#SS$_BUFBYTALI,R0	;SET BUFFER ALIGNMENT STATUS

	JMP	G^EXE$ABORTIO		; ABORT I/O


.PAGE
 	.SBTTL	RK11/RK05  START I/O OPERATION ON THE RK05


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; YM_STARTIO - START I/O OPERATION ON DEVICE UNIT
;
; THIS ENTRY POINT IS ENTERED TO START AN I/O OPERATION ON A DEVICE UNIT.
;
; INPUTS:
;
;	R3 = ADDRESS OF I/O PACKET. ( IRP )
;	R5 = UCB ADDRESS OF DEVICE UNIT.
;
; OUTPUTS:
;
;	FUNCTION DEPENDENT PARAMETERS ARE STORED IN THE DEVICE UCB, THE ERROR
;	RETRY COUNT IS RESET, AND THE FUNCTION IS EXECUTED. AT FUNCTION COMPLETION
;	THE OPERATION IS TERMINATED THROUGH REQUEST COMPLETE.
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
YM_STARTIO:					  ;START I/O OPERATION

	MOVB	UCB$B_ERTMAX(R5),UCB$B_ERTCNT(R5) ;INIT ERR RTRY CNT
	MOVW	IRP$W_FUNC(R3),UCB$W_FUNC(R5) 	  ;SAVE FUNCTION CODE
	MOVL	IRP$L_MEDIA(R3),R0		  ;GET PARAMETER LONGWORD
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; MOVE FUNCTION DEPENDENT PARAMETERS TO UCB
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
10$:	EXTZV	#IRP$V_FCODE,#IRP$S_FCODE,- 	  ;EXTRACT I/O FUNCTION CODE
		IRP$W_FUNC(R3),R1		  ; FUNCTION CODE IN R1

	CMPB	#IO$_SEEK,R1 			  ;SEEK FUNCTION?
	BEQL	20$				  ;IF EQL YES
	MOVL	R0,UCB$W_DA(R5)			  ;STORE PARAMETER LONGWORD
	BRB	50$				  ;
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; SEEK FUNCTION - SET CYLINDER ADDRESS
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
20$:	MOVW	R0,UCB$W_DC(R5)			  ;SET CYLINDER ADDRESS
 
50$:	MOVB	R1,UCB$B_FEX(R5)		  ;SAVE FUNCTION DISPATCH INDEX

	BICW	#UCB$M_ECC!-			  ;NO ECC, BUT CLEAR
		UCB$M_DIAGBUF,UCB$W_DEVSTS(R5) 	  ;DIAGNOSTIC BUFFER PRESENT
	BBC	#IRP$V_DIAGBUF,IRP$W_STS(R3),FDISPATCH ;IF CLR, NO BUFFER

	BISW	#UCB$M_DIAGBUF,UCB$W_DEVSTS(R5)	  ;SET DIAGNOSTIC BUFF PRESENT
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;  FDISPATCH:  FUNCTION DISPATCHING DONE HERE :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
FDISPATCH:				  	  ;FUNCTION DISPATCHING

	MOVL	UCB$L_IRP(R5),R3	  	  ;RETRIEVE IRP ADDRESS
	BBS	#IRP$V_PHYSIO,IRP$W_STS(R3),10$   ;IF SET, PHYSICAL I/O FUNCTION

	BBS	#UCB$V_VALID,UCB$W_STS(R5),10$    ;IF SET, VOLUME SOFTWARE VALID

	MOVZWL	#SS$_VOLINV,R0			  ;SET VOLUME INVALID STATUS
	BRW	RESETXFR			  ;
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;  CHECK FOR IDENTITY OF FUNCTION :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
10$:	MOVZBL	UCB$B_FEX(R5),R3		  ;GET FUNCTION CODE

	CMPB	#IO$_SEEK,R3			  ;A SEEK FUNCTION?
	BNEQ	20$				  ;IF NEQ, IT'S NOT A SEEK

	EXFUNCH	RETRY,F_SEEK			  ;OTHERWISE, GO AND DO THE SEEK
	BRW	NORMAL				  ;IF HERE, NORMAL SUCCESS

20$:	CMPB	#IO$_RECAL,R3			  ;A RECAL FUNCTION = DRV RESET?
	BNEQ	30$				  ;IF NEQ, NO RECAL.

	EXFUNCH	RETRY,F_RECAL			  ;OTHERWISE, RECALIBRATE DRIVE
	BRW	NORMAL				  ;HERE FOR, NORMAL SUCCESS

30$:	CMPB	#IO$_DRVCLR,R3			  ;A DRV CLR FUNC = DRV RESET?
	BNEQ	40$				  ;IF NEQ, IT'S NOT A DVRCLR

	EXFUNCH	RETRY,F_DRVCLR			  ;OTHERWISE, DRV CLR=CNTL RESET
	BRW	NORMAL				  ;HERE FOR, NORMAL SUCCESS

40$:	CMPB	#IO$_REWIND,R3			  ;A REWIND FNC = WRTLOC
	BNEQ	50$				  ;IF NEQ, NO WRTLOC.

	EXFUNCH	RETRY,F_WRTLOC			  ;OTHERWISE, EXE WRITE LOC FNC
	BRW	NORMAL				  ;HERE FOR, NORMAL SUCCESS

50$:	MOVB	#CDF_WRITEDATA,UCB$B_CEX(R5)	  ;SET UP UCB
	CMPB	#IO$_WRITEPBLK,R3		  ;WRITE PHYSICAL?
	BEQL	WRITEDATA			  ;WRITE THE DATA.

	MOVB	#CDF_READDATA,UCB$B_CEX(R5)	  ;SET UP UCB
	CMPB	#IO$_READPBLK,R3		  ;READ PHYSICAL?
	BEQL	READDATA			  ;READ THE DATA

	MOVB	#CDF_WRITECHECK,UCB$B_CEX(R5)	  ;SET UP UCB
	CMPB	#IO$_WRITECHECK,R3		  ;WRITE CHECK?
	BEQL	CLRDATCHK			  ;

	MOVB	#CDF_WRITEHEAD,UCB$B_CEX(R5)	  ;SET UP UCB
	CMPB	#IO$_WRITEHEAD,R3		  ;WRITE HEADER FNC?
	BEQL	CLRDATCHK			  ;

	MOVB	#CDF_READHEAD,UCB$B_CEX(R5)	  ;SET UP UCB
	CMPB	#IO$_READHEAD,R3		  ;READ HEADER FNC
	BEQL	CLRDATCHK			  ;

CLRDATCHK:					  ;CLEAR DATA CHECK

	BICW	#IO$M_DATACHECK,UCB$W_FUNC(R5)	;CLR DATA CHK RQST
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;  WRITE DATA, WRITE CHECK DATA
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
WRITEDATA:					  ;WRITE DATA
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;  READ DATA, WRITE DATA, WRITE CHECK DATA
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
READDATA:					 ;READ DATA

	MOVB	UCB$B_CEX(R5),UCB$B_FEX(R5)	 ;SAVE CEX FOR RECOVERY
	BBS	#IO$V_INHSEEK,UCB$W_FUNC(R5),TRANSFR ;IF SET, NO EXPLICIT SEEK

	EXFUNCH	RETRY,F_SEEK			  ;SEEK DESIRED CYLINDER
 
;
; DATA TRANSFER
;
 
TRANSFR:				;DATA TRANSFER REQUEST CHANNEL
	MOVZBL	UCB$B_FEX(R5),R3	;GET FUNCTION DISPATCH INDEX
	EXFUNCL	TRANXT			;EXECUTE TRANSFER FUNCTION
 
;
; DATA CHECK
;
 
DATACHECK:				;DATA CHECK
	BBC	#IO$V_DATACHECK,UCB$W_FUNC(R5),NORMAL ;IF CLR, NO DATA CHECK

	MOVL	UCB$L_IRP(R5),R2	;GET ADDRESS OF IRP
	MOVQ	IRP$L_SVAPTE(R2),UCB$L_SVAPTE(R5) ;RESET TRANSFER PARAMETERS
	MOVL	IRP$L_MEDIA(R2),UCB$W_DA(R5) ;
 
;
 ; DATA CHECK RETRY
;
 
CHECKRETRY:				;DATA CHECK RETRY
	EXFUNCL	TRANXT,F_WRITECHECK	;EXECUTE WRITECHECK FUNCTION
 
;
; SUCCESSFUL OPERATION COMPLETION
;
 
NORMAL:					;
	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION STATUS
CHECKXT:				;
	BRW	FUNCXT			;
 
;
; TRANSFER ENDED WITH A RETRIABLE ERROR
;
 
TRANXT:					;TRANSFER EXIT
	CMPB	#CDF_WRITEDATA,UCB$B_CEX(R5) ;WRITE DATA FUNCTION?
	BEQL	RETRY			;IF EQL YES
	CMPB	#CDF_WRITEHEAD,UCB$B_CEX(R5) ;WRITE HEADER FUNCTION?
	BEQL	RETRY			;IF EQL YES
	BITW	#YM_ER_M_DLT!-		;DATA LATE OR,
		YM_ER_M_CSE!-		;CHECKSUM ERROR OR,
		YM_ER_M_WCE,R3		;WRITE CHECK ERROR?
	BEQL	DRVR			;IF EQL YES
RETRY:					;
	BRW	RETRYERR		;RETRIABLE ERROR
 

;
;  DRVR, DRIVE RESET OR RECAL ON ERRORS FROM TRANXT: FOR DPL!SIN
;


DRVR:					;DRIVE RESET FOR SEEK INCOMPLETE
	MOVZWL	UCB$W_BCR(R5),R0	;GET NEGATIVE NUMBER OF BYTES REMAINING
	ADDW	UCB$W_BCNT(R5),R0	;CALCULATE NUMBER OF BYTES TRANSFERED
	MOVL	R0,R1			;COPY NUMBER OF BYTES TRANSFERED
	BEQL	AXE			;IF EQL NONE - PERFORM OFFSET RECOVERY

	DECL	R0			;SET TO TRUNCATE LAST BLOCK TRANSFERED
10$:	BICW	#^X1FF,R0		;TRUNCATE RESIDUAL BYTES TRANSFERED


AXE:					;CHECK GOOD DATA TRANSFERRED
	TSTL	R0			;ANY GOOD DATA TRANSFERED?
	BEQL	40$			;IF EQL NO
; 
;
; THE TRANSFER ENDED IN AN ERROR BUT THERE WERE SECTORS TRANSFERED THAT
; CONTAINED GOOD DATA. SINCE THE ERROR COULD HAVE BEEN CAUSED BY A CYLIN-
; DER CROSSING, THE GOOD DATA IS SAVED AND THE TRANSFER IS RETRIED FROM THE
; POINT OF ERROR.
;
; 
	JSB	G^IOC$UPDATRANSP	;UPDATE TRANSFER PARAMETERS

40$:	DECB	UCB$B_ERTCNT(R5)	;A RETRIABLE ERROR?
	BEQL	FATALERR		;ANY RETRIES LEFT?
	BBS	#YM_V_DCK,UCB$W_OFFSET+1(R5),50$ ;IF SET, DATA CHECK FUNCTION

	BRW	TRANSFR			;TRY FUNCTION AGAIN
50$:	BRW	CHECKRETRY		;TRY DATA CHECK AGAIN
; 
;
; RETRIABLE ERROR
;
 
 RETRYERR:				;RETRIABLE ERROR
	DECB	UCB$B_ERTCNT(R5)	;ANY RETRIES LEFT?
	BEQL	FATALERR		;IF EQL NO
	BITW	#YM_DS_M_SIN,R2 		;SEEK INCOMPLETE  
	BEQL	10$			;IF EQL NO
	EXFUNCH	FATALERR,F_RECAL	;RECALIBRATE DRIVE
10$:	BRW	FDISPATCH		;
 
 
;
; FATAL CONTROLLER/DRIVE ERROR, ERROR RETRY COUNT EXHAUSTED, ERROR RETRY
; INHIBITED. :
;
 
FATALERR:				;FATAL ERROR - SET STATUS

	MOVZWL	#SS$_UNSAFE,R0		;SET DRIVE UNSAFE STATUS
	BBS	#YM_DS_V_DRU,R2,FUNCXT	;IF SET, DRIVE UNSAFE

	MOVZWL	#SS$_DRVERR,R0		;DRIVE ERROR STATUS
	BBS	#YM_DS_V_SIN,R2,FUNCXT	;IF SET, SEEK INCOMPLETE

	MOVZWL	#SS$_FORMAT,R0		;SET FORMAT ERROR STATUS
	BITW	#YM_ER_M_PGE,R3		;PROGRAMMING ERROR
	BNEQ	FUNCXT			;IF NEQ YES

	MOVZWL	#SS$_WRITLCK,R0		;SET WRITE LOCK ERROR
	BBS	#YM_ER_V_WLO,R3,FUNCXT	;IF SET, WRITE LOCK ERROR


	MOVZWL	#SS$_IVADDR,R0		;SET INVALID DISK ADDRESS STATUS
	BITW	#YM_ER_M_NXS!-		;INVALID SECTOR ADR OR,
		YM_ER_M_NXC,R3		;INVALID CYL ADR ERROR?
	BNEQ	FUNCXT			;IF NEQ YES

	MOVZWL	#SS$_DATAOVERUN,R0	;SET DATAOVERRUN ADR STATUS
	BBS	#YM_ER_V_OVR,R3,FUNCXT		;DATA OVER RUN?

	MOVZWL	#SS$_BADCHKSUM,R0	;SET CHECKSUM ADR STATUS
	BBS	#YM_ER_V_CSE,R3,FUNCXT	;IF SET CHKSUM ERROR

	MOVZWL	#SS$_ILLCNTRFUNC,R0		;SET SEEK ERROR STATUS
	BBS	#YM_ER_V_SKE,R3,FUNCXT		;IF SET A SEEK ERROR

	MOVZWL	#SS$_BADPARAM,R0		;SET DRIVE TIMING ERROR 
	BBS	#YM_ER_V_TE,R3,FUNCXT	;IF SET A TIMING ERROR

	MOVZWL	#SS$_DATACHECK,R0	;SET DATA CHECK DSROR STATUS
	BBS	#YM_ER_V_WCE,R3,FUNCXT	;IF SET, WRITE CHECK ERROR

	MOVZWL	#SS$_NONEXDRV,R0	;SET NONEXISTENT DRIVE STATUS
	BBS	#YM_ER_V_NXD,R3,FUNCXT	;IF SET, NONEXISTENT DRIVE

	MOVZWL	#SS$_CTRLERR,R0		;SET CONTROLLER ERROR STATUS
 
;
; FUNCTION COMPLETION COMMON EXIT
;
 
FUNCXT:					;FUNCTION EXIT
	PUSHL	R0			;SAVE FINAL REQUEST STATUS
	JSB	G^IOC$DIAGBUFILL	;FILL DIAGNOSTIC BUFFER IF PRESENT
	CMPB	#CDF_WRITECHECK,UCB$B_FEX(R5) ;DRIVE RELATED FUNCTION?
	BGTRU	10$			;IF GTRU YES
	MOVL	UCB$L_IRP(R5),R3	;RETRIEVE ADDRESS OF IRP
	ADDW3	UCB$W_BCR(R5),IRP$W_BCNT(R3),2(SP) ;CALCULATE BYTES TRANSFERED

10$:	CLRL	R1			;CLEAR SECOND STATUS LONGWORD
	POPL	R0			;RETRIEVE FINAL REQUEST STATUS
	REQCOM				;COMPLETE REQUEST

.PAGE
 	.SBTTL	RK11/RK05  HARDWARE FUNCTION EXECUTION

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; FEXH - RK11/RK05 HARDWARE FUNCTION EXECUTION (HIGH PRIORITY)
; FEXL - RK11/RK05 HARDWARE FUNCTION EXECUTION (LOW PRIORITY)
;
; THIS ROUTINE IS CALLED VIA A BSB WITH A BYTE IMMEDIATELY FOLLOWING THAT
; SPECIFIES THE ADDRESS OF AN ERROR ROUTINE. ALL DATA IS ASSUMED TO HAVE BEEN
; SET UP IN THE UCB BEFORE THE CALL. THE APPROPRIATE PARAMETERS ARE LOADED
; INTO DEVICE REGISTERS AND THE FUNCTION IS INITIATED. THE RETURN ADDRESS
; IS STORED IN THE UCB AND A WAITFOR INTERRUPT IS EXECUTED. WHEN THE INTER-
; RUPT OCCURS, CONTROL IS RETURNED TO THE CALLER.
;
; INPUTS:
;
;	R3 = FUNCTION TABLE DISPATCH INDEX.
;	R4 = ADDRESS OF RK11 CSR.
;	R5 = DEVICE UNIT UCB ADDRESS.
;
;	00(SP) = RETURN ADDRESS OF CALLER.
;	04(SP) = RETURN ADDRESS OF CALLER'S CALLER.
;
;	IMMEDIATELY FOLLOWING INLINE AT THE CALL SITE IS A BYTE WHICH CONTAINS
;	A BRANCH DESTINATION TO AN ERROR RETRY ROUTINE.
;
; OUTPUTS:
;
;	THERE ARE FOUR EXITS FROM THIS ROUTINE:
;
;	1. SPECIAL CONDITION - THIS EXIT IS TAKEN IF A POWER FAILURE OCCURS
;		OR THE OPERATION TIMES OUT. IT IS A JUMP TO THE APPROPRIATE
;		ERROR ROUTINE.
;
;	2. FATAL ERROR - THIS EXIT IS TAKEN IF A FATAL CONTROLLER OR DRIVE
;		ERROR OCCURS OR IF ANY ERROR OCCURS AND ERROR RETRY IS
;		INHIBITED. IT IS A JUMP TO THE FATAL ERROR EXIT ROUTINE.
;
;	3. RETRIABLE ERROR - THIS EXIT IS TAKEN IF A RETRIABLE CONTROLLER
;		OR DRIVE ERROR OCCURS AND ERROR RETRY IS NOT INHIBITED.
;		IT CONSISTS OF TAKING THE ERROR BRANCH EXIT.
;
;	4. SUCCESSFUL OPERATION - THIS EXIT IS TAKEN IF NO ERROR OCCURS
;		DURING THE OPERATION. IT CONSISTS OF A RETURN INLINE.
;
;	IN ALL CASES IF AN ERROR OCCURS, AN ATTEMPT IS MADE TO LOG THE ERROR.
;
;	IN ALL CASES FINAL DRIVE AND CONTROLLER REGISTERS ARE RETURNED VIA
;	THE GENERAL REGISTERS R1, R2, AND R3, AND THE UCB.
;
;	R1 = DISK STATUS REGISTER.
;	R2 = ERROR REGISTER.
;	R3 = YM CSR
;
;	UCB$W_BCR(R5) = BYTE COUNT REGISTER.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 	.ENABL	LSB
FEXH:					;FUNCTION EXECUTOR (HIGH PRIORITY)
	MOVAB	G^IOC$REQPCHANH,R2	;SET ADDRESS OF REQUEST CHANNEL ROUTINE
	BRB	10$			;
FEXL:					;FUNCTION EXECUTOR (LOW PRIORITY)
	MOVAB	G^IOC$REQPCHANL,R2	;SET ADDRESS OF REQUEST CHANNEL ROUTINE
10$:	POPL	UCB$L_DPC(R5)		;SAVE DRIVER PC VALUE
	JSB	(R2)			;REQUEST CHANNEL


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	DEVICE UNIT FROM THE UCB MUST BE HANDLED IN A DIFFERENT WAY WITH
;	THE RK11/RK05, THE ACTUAL UNIT MUST BE INSERTED VIA THE INSV 
;	INSTRUCTION IN THE XFER ROUTINE.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	MOVZWL	UCB$W_UNIT(R5),R2	;GET DEVICE UNIT NUMBER

	CMPB	#CDF_SEEK,R3		;A SEEK?
	BEQL	POSIT			;SET POSITION

	CMPB	#CDF_RECAL,R3		;RECAL = DRIVE RESET?
	BEQL	POSIT			;RECAL DRIVE


	CMPB	#CDF_DRVCLR,R3		;A CONTROLLER RESET?
	BEQL	IMMED			;RESET CONTROLLER

	BRW	XFER			;OTHERWISE A TRANSFER FUNCTION

	.DSABL	LSB
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; IMMED: - IMMEDIATE FUNCTION EXECUTION
;
;	FUNCTION FOR IMMEDIATE EXECUTION IS:
;
;		DRIVE CLEAR = CONTROL RESET
;
;
;	1]  INTERRUPTS ARE DISABLED
;	2]  CHECK FOR POWER FAIL
;	3]  GET THE UNIT THAT SET THE INTERRUPT FROM R2
;	4]  PUT SELECTED UNIT INTO THE DISK ADDRESS REGISTER
;	5]  EXECUTE THE DRIVE CLEAR FUNCTION
;	6]  WAIT FOR INTERRUPT AND KEEP CHANNEL OR TIMEOUT
;		A)  IF TIMEOUT :
;		    LOWER TO FORK IPL AND RELEASE CHANNEL
;		B)  IF INTERRUPT:
;		    EXECUTE AN IOFORK AND RELEASE CHANNEL
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
IMMED:					;IMMEDIATE FUNCTION EXECUTION

	DSBINT				;DISABLE INTERRUPTS
	BBC	#UCB$V_POWER,UCB$W_STS(R5),5$ ;IF CLR, POWER HAS NOT FAILED
	BRW	ENBXIT			;EXIT

5$:	CLRL	R1			;CLEAR R1 FOR UNIT SEL INSV

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	GET THE UNIT THAT SET THE INTERRUPT :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	INSV	R2,-			; R2 HAS UNIT NUMBER
		#YM_DA_V_DRSEL,-
		#YM_DA_S_DRSEL,-
		R1			;FEED R1 TO YM_DA

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	GIVE SELECTED UNIT TO YM_DA :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	MOVW	R1,YM_DA(R4)		;SET UNIT NUMBER

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	NOW EXECUTE THE FUNCTION :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	MOVW	FTAB[R3],YM_CS(R4)	;EXECUTE FUNCTION

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	WAIT FOR INTERRUPT OR TIME OUT AND KEEP CHANNEL :
;		1]  IF TIMEOUT :  RESTORE IPL TO FORK IPL
;				  AND RELEASE CHANNEL
;		2]  IF INTERRUPT :   BRW TO IOFORK
;				     AND RELEASE CHANNEL
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	WFIKPCH	11$,#6		;WAITFOR INTERRUPT

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	IF INTERRUPT OCCURRED BEFORE TIMEOUT :
;
;	JUMP TO INTERRUPT RESPONSE ROUNTINE :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	BRW	9$

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	IF DEVICE TIMES OUT :  LOWER IPL TO FORK IPL
;			       AND RELEASE CHANNEL
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

11$:	SETIPL	UCB$B_FIPL		;ON TIMEOUT, LOWER IPL
	BRW	RLSCHN			;NOW GO AND RELEASE CHANNEL

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	DO THE IOFORK AFTER RETURN FROM THE ISR :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

9$:	IOFORK				;CREATE FORK PROCESS
	BRW	RLSCHN			; RELEASE CHANNEL
  

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; POSIT: - POSITIONING FUNCTION EXECUTION
;
;	FUNCTIONS INCLUDE:
;
;		SEEK CYLINDER,
;		RECALIBRATE DRIVE = DRIVE RESET
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
POSIT:					;POSITIONING FUNCTION
	DSBINT				;DISABLE INTERRUPTS
	BBS	#UCB$V_POWER,UCB$W_STS(R5),ENBXIT ;IF SET, POWER HAS FAILED


;
;	CLEAR R1 FOR THE SEEK FUNCTION INSV :
;
	CLRL	R1			;CLR R1 FOR INSV

;
;	GET DESIRED CYLINDER FROM THE UCB AND INSV INTO R1 :
;
	INSV	UCB$W_DC(R5),-
		#YM_DA_V_CYLADR,-
		#YM_DA_S_CYLADR,-
		R1

;
;	GET UNIT THAT SET INTERRUPT FROM R2 INTO R1 :
;
	INSV	R2,-			; R2 HAS THE UNIT NUMBER
		#YM_DA_V_DRSEL,-
		#YM_DA_S_DRSEL,-
		R1

;
;	GIVE RK11 THE DISK ADDRESS :
;
	MOVW	R1,YM_DA(R4)		;MOVE TO DISK ADR REG

;
;	NOW EXECUTE THE FUNCTION : SEEK OR RECAL :
;
	MOVW	FTAB[R3],YM_CS(R4)	;EXECUTE FUNCTION

	WFIRLCH	13$,#6		;WAITFOR INTERRUPT

	BRW	19$		;IF NOT TIMEOUT

13$:	SETIPL	UCB$B_FIPL		;ON TIMEOUT, LOWER TO FORK IPL
	BRW	RETREG			;THEN GO TO RETREG

;	IF INTERRUPT, CONTINUE
19$:	DSBINT				;DISABLE INTERRUPTS
	BBS	#UCB$V_POWER,UCB$W_STS(R5),10$ ;IF SET, POWER FAILURE

	BITW	#YM_DS_M_DRY,YM_DS(R4)	;DRIVE READY?


	BNEQ	10$			;IF NEQ YES


	WFIKPCH	17$,#6			;WAITFOR INTERRUPT

	BRW	23$			;IF NOT TIMEOUT

17$:	SETIPL	UCB$B_FIPL		;IF TIMEOUT,LOWER IPL
	BRW	RETREG			;AND GO TO RETREG

23$:	BRB	20$			;
10$:	ENBINT				;ENABLE INTERRUPTS
20$:	IOFORK				;CREATE FORK PROCESS
	BRW	RETREG			;
ENBXIT:					;
	ENBINT				;
	BRW	RLSCHN			;
 
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; XFER: - TRANSFER FUNCTION EXECUTION
;
;	FUNCTIONS INCLUDE:
;
;		WRITE CHECK,
;		WRITE DATA,
;		WRITE HEADERS,
;		READ DATA, AND
;		READ HEADER.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
XFER:					;TRANSFER FUNCTION EXECUTION

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	SET SBI = UNIBUS		;SET UP UNIBUS 
;
;	SET UP I/O TRANSFER BY REQUESTING A DATAPATH AND UBA MAP
;	REGISTERS AND LOADING THE UBA MAP REGISTERS.
;	
;	THE ABOVE ACTIONS CLOBBER R2, SO THAT, THE UNIT NUMBER
;	HAS TO BE GOTTEN FROM THE UCB IN SETTING UP THE DISK
;	ADDRESS REGISTER.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	REQDPR				;REQUEST DATAPATH
	REQMPR				;REQUEST MAP REGISTERS
	LOADUBA				;LOAD UNIBUS MAP REGISTERS



;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	SET UP YM_WC :
;
;
;	CALCULATE THE WORD COUNT OF THE TRANSFER :
;
;
;	1]  GET TRANSFER BYTE COUNT FROM UCB
;	2]  CONVERT TRANSFER BYTE COUNT TO WORDS
;	3]  DISABLE INTERRUPTS BY SETTING DEVICE IPL
;	4]  LOAD NEGATIVE TRANSFER COUNT INTO THE WORD COUNT REGISTER
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	MOVZWL	UCB$W_BCNT(R5),R0	;SET TRANSFER BYTE COUNT
	DIVL	#2,R0			;CONVERT TO WORDS
	DSBINT	UCB$B_DIPL(R5)		;SET DEVICE IPL
	MNEGW	R0,YM_WC(R4)		;SET TRANSFER WORD COUNT

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	SET UP YM_BA :
;
;
;	CALCULATE UNIBUS START ADDRESS OF THE TRANSFER :
;
;	1]  PUT BYTE OFFSET OF THE TRANSFER, FROM THE UCB, INTO 
;	    FIRST PAGE OF THE TRANSFER BUFFER
;	2]  GET ADDRESS OF CRB TO GET INTERRUPT TRANSFER VECTOR,
;	    WHICH IS THE ADDRESS OF THE YM INTERRUPT SERVICE
;	    ROUTINE.
;	3]  PUT STARTING MAP REGISTER NUMBER INTO HIGH BITS OF
;	    UNIBUS START ADDRESS : 
;			 CRB$L_INTD = INTERRUPT TRANSFER VECTOR
;			 VEC$W_MAPREG = NUMBER OF THE FIRST UBA
;	MAP REGISTER ALLOCATED TO THE DRIVER THAT OWNS THE CONTROL-
;	LER DATA CHANNEL.
;	4]  STORE LOW 16 BITS IN THE YM_BA REGISTER
;	5]  GET MEMORY EXTENSION BITS FROM THE CRB
;	6]  SHIFT LEFT 4 BITS TO POSITION MEMORY EXTENSION BITS
;	7]  SET FUNCTION CODE WITH MEMORY EXTENSION BITS
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	MOVZWL	UCB$W_BOFF(R5),R0	;GET BYTE OFFSET IN PAGE
	MOVL	UCB$L_CRB(R5),R1	;GET ADDRESS OF CRB
	INSV	CRB$L_INTD+VEC$W_MAPREG(R1),#9,#7,R0 ;INSERT HIGH 7 BITS OF ADDRESS

	MOVW	R0,YM_BA(R4)		;SET BUFFER ADDRESS
	EXTZV	#7,#2,CRB$L_INTD+VEC$W_MAPREG(R1),R0 ;GET MEMORY EXTENSION BITS

	ASHL	#4,R0,R0		;SHIFT LEFT ONE BYTE

	BISW	FTAB[R3],R0		;MERGE FUNCTION CODE


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	SET UP YM_DA :
;
;	1]  CLEAR R3 FOR INSV OF DISK ADDRESS
;	2]  GET SECTOR ADDRESS FROM THE UCB AND PUT INTO R3
;	3]  GET SURFACE TO R3 FROM UCB OR BIT SET SURFACE
;	4]  GET CYLINDER NUMBER FROM UCB AND INSV IT INTO R3
;	5]  GET UNIT NUMBER FROM THE UCB AND INSV IT INTO R3
;	6]  LOAD R3 INTO YM DISK ADDRESS REGISTER
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


	CLRL	R3				;CLR R3 FOR INSV
	MOVZBL	UCB$W_DA(R5),R3		;MOVE SECTOR ADR INTO PLACE
	TSTB	UCB$W_DA+1(R5)		;WHAT SURFACE?
	BEQL	11$

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;SURFACE NUMBER :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	BISW	#YM_DA_M_SUR,R3		;OTHERWISE, SET SURFACE NUMBER


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;CYLINDER NUMBER :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

11$:	INSV	UCB$W_DC(R5),-
		#YM_DA_V_CYLADR,-
		#YM_DA_S_CYLADR,-
		R3


;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;DRIVE THAT SET INTERRUPT :
;
;	REQUEST DATAPATH REGISTERS CLOBBERS R2.  THE DRIVE UNIT THAT
;	SET THE INTERRUPT MUST BE OBTAINED FROM THE UCB FOR THE INSV.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	INSV	UCB$W_UNIT(R5),-	;UCB HAS UNIT NUMBER
		#YM_DA_V_DRSEL,-
		#YM_DA_S_DRSEL,-
		R3

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;MOVE INTO DISK ADDRESS REGISTER :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	MOVW	R3,YM_DA(R4)		;SET DA REG

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	RAISE IPL :  CHECK FOR POWERFAIL BEFORE EXECUTING FUNCTION
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	SETIPL	#31			;DISABLE INTERRUPTS

	BBC	#UCB$V_POWER,UCB$W_STS(R5),10$ ;IF CLR, NO POWER FAILURE

	ENBINT				;ENABLE INTERRUPTS

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	IF NO POWER FAIL, FALL THRU : OTHERWISE RELEASE MAPPING REGS AND CHAN
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	BRW	60$			;

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	EXECUTE FUNCTION IN R0 BY PLACING IT INTO RK11 CSR :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

10$:	MOVW	R0,YM_CS(R4)		;EXECUTE FUNCTION

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	WAIT FOR INTERRUPT OR TIME OUT AND KEEP CHANNEL :
;		1]  IF TIMEOUT :  SAVE REGISTERS
;				  ENABLE INTERRUPTS
;				  FALL THROUGH TO IOFORK
;		2]  IF INTERRUPT :  BRW TO IOFORK
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	WFIKPCH	61$,#6			;WAITFOR INTERRUPT AND KEEP CHANNEL

	BRW	62$			;IF NO TIMEOUT, CREATE FORK PROCESS

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	IF DEVICE TIMES OUT :  SAVE REGISTERS
;			       CLEAR CONTROLLER
;			       RECAL DRIVE
;			       ENABLE INTERRUPTS
;			       FALL THRU TO IOFORK
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

61$:	BISW3	#YM_CS_M_ERR,YM_CS(R4),UCB$W_YM_CS(R5)	;SAVE CSR

	MOVAB	YM_DS(R4),R2		;GET ADR. OF DS REG
	MOVAB	UCB$W_YM_DS(R5),R3	;GET ADR OF DS SAVE AREA
	MOVW	(R2)+,(R3)+		;SAVE YM_DS
	MOVW	(R2)+,(R3)+		;SAVE YM_ER
	MOVW	(R2)+,(R3)+		;SAVE YM_CS
	MOVW	(R2)+,(R3)+		;SAVE YM_WC
	MOVW	(R2)+,(R3)+		;SAVE YM_BA
	MOVW	(R2)+,(R3)+		;SAVE YM_DA
	MOVW	(R2)+,(R3)+		;SAVE YM_DB

	MOVW	#^X1,YM_CS(R4)		;ISSUE CONTROL RESET
;	MOVW	#^XD,YM_CS(R4)		;ISSUE DRIVE RESET
	MOVZBW	#YM_CS_M_IDE,YM_CS(R4)	;ENABLE DEVICE INTERRUPTS


62$:	IOFORK				;CREATE FORK PROCESS

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	PURGE THE DATA PATH :
;
;	   THE CONFIGURATION REGISTER OBTAINED FROM THE CRB IS USED AS
;	   THE BASE OF THE OFFSETS TO THE DATA PATH REGISTERS ( DPR ).
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

;P_DP:						; PURGE DATA PATH

	MOVL	UCB$L_CRB(R5),R3		;GET ADDRESS OF CRB
	MOVL	@CRB$L_INTD+VEC$L_ADP(R3),R2    ;GET ADR OF CONFIGURATION REG
	EXTZV	#VEC$V_DATAPATH,#VEC$S_DATAPATH,- ;EXTRACT DATAPATH NUMBER
		CRB$L_INTD+VEC$B_DATAPATH(R3),R1 ;

	ASHL	#UBA$V_DPR_BNE,#1,UBA$L_DPR(R2)[R1] ;PURGE DATAPATH

	ASHL	#31-UBA$V_DPR_XMTER,UBA$L_DPR(R2)[R1],R0 ;ANY TRANSMISSION ERROR?

	BGEQ	20$			;IF GEQ NO

;
;	IS THERE AN ERROR :
;

	MOVL	UBA$L_DPR(R2)[R1],UBA$L_DPR(R2)[R1]	;CLEAR DPPE
	BISW	#YM_CS_M_ERR!-		;SET CONTROLLER ERROR AND,
		YM_CS_M_HE,UCB$W_YM_CS(R5) ;HARD ERROR ERROR

	CLRW	UCB$W_YM_ER(R5)		;CLEAR ERROR REGISTER

	BICW	#^C<YM_DS_M_DRY>,UCB$W_YM_DS(R5) ;CLEAR ALL BUT DRIVE READY

20$:	BBS	#YM_CS_V_ERR,UCB$W_YM_CS(R5),30$ ;IF SET , DEVICE ERRORS

	BBC	#UCB$V_DIAGBUF,UCB$W_DEVSTS(R5),40$ ;IF CLR, NO DIAGNOSTIC BUFFER

30$:	MOVW	R1,UCB$W_YM_DPN(R5)	;SAVE DATAPATH NUMBER
	MOVL	UBA$L_DPR(R2)[R1],UCB$L_YM_DPR(R5) ;SAVE DATAPATH REGISTER
	EXTZV	#9,#7,UCB$W_YM_BA(R5),R0 ;GET LOW BITS OF FINAL MAP REGISTER NUMBER

;
;	GET MEMORY EXTENSION BITS :
;

	EXTZV	#YM_CS_V_MEX,-		;HIGH BITS OF FINAL MAP REG
		#YM_CS_S_MEX,-
		UCB$W_YM_CS(R5),R1	;PUT INTO R1


	INSV	R1,#7,#2,R0 ;INSERT HIGH BITS OF FINAL MAP REGISTER
  
	CMPW	#495,R0			;LEGAL MAP REGISTER NUMBER?
	BGEQ	35$			;IF GEQ YES
	MOVZWL	#495,R0			;RESTRICT MAP REGISTER NUMBER

35$:	MOVL	UBA$L_MAP(R2)[R0],UCB$L_YM_FMPR(R5) ;SAVE FINAL MAP REGISTER
	CLRL	UCB$L_YM_PMPR(R5)	;CLEAR PREVIOUS MAP REGISTER CONTENTS
	DECL	R0			;CALCULATE PREVIOUS MAP REGISTER NUMBER
	CMPV	#VEC$V_MAPREG,#VEC$S_MAPREG,- ;ANY PREVIOUS MAP REGISTER?
		CRB$L_INTD+VEC$W_MAPREG(R3),R0 ;

	BGTR	40$			;IF GTR NO

	MOVL	UBA$L_MAP(R2)[R0],UCB$L_YM_PMPR(R5) ;SAVE PREVIOUS MAP REGISTER
40$:	MULW3	#2,UCB$W_YM_WC(R5),UCB$W_BCR(R5) ;CONVERT WORD COUNT TO BYTE COUNT

	BBS	#YM_CS_V_ERR,UCB$W_YM_CS(R5),60$ ;IF SET, DEVICE ERRORS

	CMPB	#CDF_READHEAD,UCB$B_CEX(R5) ;READ HEADER FUNCTION?
	BRB	60$			;BRANCH TO EXIT, IF HERE

60$:	RELDPR				;RELEASE DATA PATH
	RELMPR				;RELEASE MAP REGISTERS
RLSCHN:					;
	RELCHAN				;RELEASE CHANNEL
 
;
; RETURN REGISTERS
;
 
	.ENABL	LSB
RETREG:					;RETURN FINAL DEVICE REGISTERS

;
;	PUT CS,DS,ER RK11 REGISTERS INTO R1,R2, AND R3 :
;
	MOVZWL	UCB$W_YM_CS(R5),R1	;RETRIEVE YM CSR
	MOVZWL	UCB$W_YM_DS(R5),R2	;RETREIVE DISK STATUS REG
	MOVZWL	UCB$W_YM_ER(R5),R3	;RETRIEVE ERROR REGISTER


	BITW	#UCB$M_POWER!-		;POWER FAIL OR DEVICE TIMEOUT?
		UCB$M_TIMOUT,UCB$W_STS(R5) ;
	BNEQ	30$			;IF NEQ YES - SPECIAL CONDITION

	BBC	#YM_CS_V_ERR,R1,10$	;IF CLR, NO ERRORS


;
;	CALL ERROR LOGGER :
;
	JSB	G^ERL$DEVICERR		;ALLOCATE AND FILL ERROR MESSAGE BUFFER

	BBS	#IO$V_INHRETRY,UCB$W_FUNC(R5),20$ ;IF SET, RETRY INHIBITED

	BITW	#YM_ER_M_OVR!-		;CYLINDER ADDRESS OVERFLOW,
		YM_ER_M_NXD!-		;NONEXISTENT DISK OR,
		YM_ER_M_PGE!-		;PROGRAMMING ERROR OR,
		YM_ER_M_NXM!-		;NON-EXISTENT MEMORY?
 		YM_ER_M_DRE!-		;DRIVE TYPE ERROR OR,
		YM_ER_M_NXC!-		;INVALID DISK ADDRESS ERROR OR,
		YM_ER_M_NXS!-		;NON-EXISTENT SECTOR OR,
		YM_ER_M_WLO,R3		;WRITE LOCK ERROR?
	BNEQ	20$			;IF NEQ YES

 
;
; RETRIABLE ERROR EXIT
;
 
	CVTBL	@UCB$L_DPC(R5),-(SP)	;GET BRANCH DISPLACEMENT
	ADDL	(SP)+,UCB$L_DPC(R5)	;CALCULATE RETURN ADDRESS - 1
10$:	INCL	UCB$L_DPC(R5)		;ADJUST TO CORRECT RETURN ADDRESS
	JMP	@UCB$L_DPC(R5)		;RETURN TO DRIVER
 
;
; FATAL CONTROLLER OR DRIVE ERROR EXIT
;
 
20$:	BRW	FATALERR		;
 
;
; SPECIAL CONDITION (POWER FAILURE OR DEVICE TIME OUT)
;
 
30$:	BBSC	#UCB$V_POWER,UCB$W_STS(R5),50$ ;IF SET, POWER FAILURE

 
;
; DEVICE TIME OUT
;
 
	JSB	G^ERL$DEVICTMO		;LOG DEVICE TIME OUT

	MOVL	UCB$L_CRB(R5),R3	;GET ADDRESS OF CRB
	MOVL	CRB$L_INTD+VEC$L_IDB(R3),R3 ;GET ADDRESS OF IDB
	CMPL	R5,IDB$L_OWNER(R3)	;DEVICE OWN CONTROLLER?
	BNEQ	40$			;IF NEQ NO


	MOVW	#F_DRVCLR!1,YM_CS(R4) ;CLEAR ENTIRE RK11/RK05 SUBSYSTEM
	MOVZBW	#YM_CS_M_IDE,YM_CS(R4)	;ENABLE DEVICE INTERRUPTS

40$:	SETIPL	UCB$B_FIPL(R5)		;LOWER TO FORK LEVEL
	MOVZWL	#SS$_TIMEOUT,R0		;SET DEVICE TIMEOUT STATUS
	DECB	UCB$B_ERTCNT(R5)	;ANY ERROR RETRIES REMAINING?
	BEQL	RESETXFR		;IF EQL NO
	RELCHAN				;RELEASE CHANNEL IF OWNED
	BICW	#UCB$M_TIMOUT,UCB$W_STS(R5) ;CLEAR TIME OUT STATUS
	BRW	FDISPATCH		;
 
;
; RESET TRANSFER BYTE COUNT TO ZERO
;
 
RESETXFR:				;
 	MOVL	UCB$L_IRP(R5),R3	;RETRIEVE ADDRESS OF I/O PACKET
	MNEGW	IRP$W_BCNT(R3),UCB$W_BCR(R5) ;RESET TRANSFER BYTE COUNT
	BRW	FUNCXT			;
 
;
; POWER FAILURE
;
 
50$:	RELCHAN				;RELEASE CHANNEL IF OWNED
	MOVL	UCB$L_IRP(R5),R3	;RETRIEVE ADDRESS OF I/O PACKET
	MOVQ	IRP$L_SVAPTE(R3),UCB$L_SVAPTE(R5) ;RESTORE TRANSFER PARAMETERS
	BRW	YM_STARTIO		;
	.DSABL	LSB
.PAGE
 	.SBTTL	RK11/RK05  REGISTER DUMP ROUTINE

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; YM_REGDUMP - RK11/RK05 REGISTER DUMP ROUTINE
;
; THIS ROUTINE IS CALLED TO SAVE THE CONTROLLER AND DRIVE REGISTERS IN A
; SPECIFIED BUFFER. IT IS CALLED FROM THE DEVICE ERROR LOGGING ROUTINE AND
; FROM THE DIAGNOSTIC BUFFER FILL ROUTINE.
;
; INPUTS:
;
;	R0 = ADDRESS OF REGISTER SAVE BUFFER.
;	R4 = ADDRESS OF YM CSR
;	R5 = DEVICE UNIT UCB ADDRESS.
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
YM_REGDUMP:				;RK11/RK05 REGISTER DUMP ROUTINE
	MOVL	#11,(R0)+		;INSERT NUMBER OF DEVICE REGISTERS
	MOVAL	UCB$W_YM_DS(R5),R1	;GET ADDRESS OF SAVED DEVICE REGISTERS
	MOVL	#7,R2			;SET NUMBER OF REGISTERS TO MOVE
10$:	MOVZWL	(R1)+,(R0)+		;MOVE REGISTER TO BUFFER
	SOBGTR	R2,10$			;ANY MORE TO MOVE?
	MOVZWL	(R1)+,(R0)+		;INSERT DATAPATH NUMBER
	MOVL	(R1)+,(R0)+		;INSERT DATAPATH REGISTER
	MOVL	(R1)+,(R0)+		;INSERT FINAL MAP REGISTER
	MOVL	(R1),(R0)+		;INSERT PREVIOUS MAP REGISTER
	RSB				;

.PAGE
 	.SBTTL	RK11/RK05  DISK DRIVE INITIALIZATION

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; YM_RK05_INIT: - RK11/RK05 DISK DRIVE INITIALIZATION
;
;	THIS ROUTINE IS CALLED,  VIA A JSB INSTRUCTION, AFTER CALLING THE 
;	CONTROLLER INITIALIZATION ROUTINE,  AND UNDER THE FOLLOWING  
;	CIRCUMSTANCES :
;
;		1]  AT SYSTEM INITIALIZATION ( STARTUP )
;		2]  IN ORDER TO LOAD AND/OR RELOAD THE DRIVER
;		3]  AT POWER FAIL ( A POWER RECOVERY RESTART )
;
;
; INPUTS:
;
;	R4 = ADDRESS OF YM CSR ( CONTROL AND STATUS REGISTER )
;	R5 = DEVICE UNIT UCB ADDRESS ( UNIT CONTROL BLOCK )
;
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
YM_RK05_INIT:				;RK11/RK05 UNIT INITIALIZATION


	MOVB	S^#DT$_RK05,UCB$B_DEVTYPE(R5)	;SET YM DEVTYP
	MOVW	#200,UCB$W_CYLINDERS(R5)	;SET # OF CYLS
	MOVL	#200*2*12,UCB$L_MAXBLOCK(R5)	;SET MAXBLK
	TSTW	UCB$W_UNIT(R5)			;UNIT = ?
	BEQL	10$				;MAYBE A SECOND UNIT
10$:	BISW	#UCB$M_ONLINE!UCB$M_VALID,UCB$W_STS(R5)	;SET UNIT ONLINE
	RSB

.PAGE
 	.SBTTL	RK11/RK05  UNSOLICITED INTERRUPT ROUTINE

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; YM_UNSOLNT - RK11/RK05 UNSOLICITED INTERRUPT ROUTINE
;
;
; INPUTS:
;
;	R4 = ADDRESS OF YM CSR
;	R5 = DEVICE UNIT UCB ADDRESS.
;
; OUTPUTS:
;
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
YM_UNSOLNT:				;RK11/RK05 UNSOLICITED INTERRUPT

	MOVB	S^#DT$_RK05,UCB$B_DEVTYPE(R5)	;SET YM DEVTYP
	MOVW	#200,UCB$W_CYLINDERS(R5)	;SET # OF CYLS
	MOVL	#200*2*12,UCB$L_MAXBLOCK(R5)	;SET MAXBLK
	TSTW	UCB$W_UNIT(R5)			;UNIT = ?
	BEQL	11$				;MAYBE A SECOND UNIT
11$:	BISW	#UCB$M_ONLINE,UCB$W_STS(R5) ;SET UNIT ONLINE
10$:	RSB				;

.PAGE
 	.SBTTL	RK11/RK05  WAIT FOR CONTROLLER READY

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; YM_WAIT - WAIT FOR CONTROLLER READY
;
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
YM_WAIT:					;WAIT FOR CONTROLLER READY
	PUSHL	R2			;SAVE REGISTER
	DSBINT				;DISABLE INTERRUPTS
	MFPR	S^#PR$_ICR,R2		;READ INTERVAL COUNT REGISTER
	ADDL	#20,R2			;CALCULATE EXPIRATION TIME
	BLSS	20$			;IF LSS NO WRAP AROUND
	MOVAW	-10000(R2),R2		;CALCULATE WRAP AROUND VALUE
10$:	TSTB	YM_CS(R4)		;CONTROLLER READY?
	BLSS	30$			;IF LSS YES
	MFPR	S^#PR$_ICR,-(SP)	;READ INTERVAL COUNT REGISTER
	CMPL	(SP)+,R2		;TIME TO WRAP AROUND?
	BGTR	10$			;IF GTR NO
20$:	TSTB	YM_CS(R4)		;CONTROL READY?
	BLSS	30$			;IF LSS YES
	MFPR	S^#PR$_ICR,-(SP)	;READ INTERVAL COUNT REGISTER
	CMPL	(SP)+,R2		;TIME EXPIRE YET?
	BLSS	20$			;IF LSS NO
30$:	ENBINT				;ENABLE INTERRUPTS
	POPL	R2			;RESTORE REGISTER
	RSB				;

.PAGE
 	.SBTTL	RK11/RK05  DISK CONTROLLER INTERRUPT DISPATCHER

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
; YM$INT: - RK11/RK05 DISK CONTROLLER INTERRUPT DISPATCHER
;
; THIS ROUTINE IS ENTERED VIA A JSB INSTRUCTION WHEN AN INTERRUPT OCCURS
; ON AN RK11 DISK CONTROLLER. THE STATE OF THE STACK ON ENTRY IS:
;
;	00(SP) = POINTER TO THE ADDRESS OF THE IDB ( INTERRUPT DATA BLOCK )
;	02(SP) = SAVED R0
;	08(SP) = SAVED R1
;	12(SP) = SAVED R2
;	16(SP) = SAVED R3
;	20(SP) = SAVED R4
;	24(SP) = SAVED R5
;	28(SP) = SAVED PSL ( PROCESSOR STATUS LONGWORD )
;	32(SP) = SAVED PC
;
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
YM$INT::					;YM INTERRUPT DISPATCHER

	MOVL	@(SP),R3			;GET ADDRESS OF IDB
	MOVL	IDB$L_CSR(R3),R4		;GET ADDRESS OF YM_CS
	MOVL	IDB$L_OWNER(R3),R5		;GET OWNER UNIT UCB ADDRESS
	BEQL	10$				;IF EQL NO OWNER
	BBSC	#UCB$V_INT,UCB$W_STS(R5),30$ 	;IF SET, INTERRUPT EXPECTED

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	NO INTERRUPT EXPECTED :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

10$:	MOVW	YM_DS(R4),R1			;GET DISK STATUS

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	CLEAR R2 FOR EXTZV :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	CLRL	R2				;CLEAR R2 FOR EXTZV

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	GET ID OF DRIVE THAT SET INTERRUPT :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	EXTZV	#YM_DS_V_ID,-
		#YM_DS_S_ID,-
		R1,-				;GET DRV THAT SET INTERRUPT
		R2				;INTO R2

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	CHECK IF THE SEEK IS COMPLETE :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	BITW	#YM_CS_M_SCP,YM_CS(R4)		;IS SEEK COMPLETE?
	BNEQ	20$				;NEQ : DRIVE FOUND

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	MUST GO THRU HERE TO EXIT INTERRUPT :
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	MOVZBW	#YM_CS_M_IDE,YM_CS(R4)		;ENABLE DEVICE INTERRUPTS
	ADDL	#4,SP				;CLEAN STACK
	MOVQ	(SP)+,R0			;RESTORE REGISTERS
	MOVQ	(SP)+,R2			;
	MOVQ	(SP)+,R4			;
	REI					;


20$:	CLRL	R5				;CLEAR R5 FOR INSV

	INSV	R2,-				; R2 HAS THE UNIT NUMBER
		#YM_DA_V_DRSEL,-
		#YM_DA_S_DRSEL,-
		R5				;SELECT DRIVE IN R5
	MOVW	R5,YM_DA(R4)			;SELECT UNIT
	MOVL	IDB$L_UCBLST(R3)[R2],R5		;GET ADDRESS OF UCB
	BEQL	80$				;IF EQL NO CORRESPONDING UNIT
	BBCC	#UCB$V_INT,UCB$W_STS(R5),70$	;IF CLR,INTERR NOT EXPECTED

30$:	
40$:
	MOVW	YM_CS(R4),UCB$W_YM_CS(R5)	; SAVE CSR
	BLSS	100$				;IF LSS ERROR
	BBS	#UCB$V_DIAGBUF,UCB$W_DEVSTS(R5),100$ ;IF SET, DIAGNOSTIC BUFFER
	MOVW	YM_WC(R4),UCB$W_YM_WC(R5)	; SAVE WC REGISTER
	MOVW	YM_BA(R4),UCB$W_YM_BA(R5)	; SAVE BA REGISTER


;	CALL DRIVER AT STARTIO :

50$:	MOVQ	UCB$L_FR3(R5),R3		;RESTORE DRIVER CONTEXT
	JSB	@UCB$L_FPC(R5)			;CALL DRIVER AT INTERRUPT RETURN ADDRESS
	MOVL	@(SP),R3			;GET ADDRESS OF IDB
	MOVL	IDB$L_CSR(R3),R4		;GET ADDRESS OF YM_CS
60$:	MOVW	#^X1,YM_CS(R4)			;CLEAR CONTROLLER

	BSBW	YM_WAIT				;WAIT FOR CONTROLLER READY
	BRW	10$				;
70$:	BSBW	YM_UNSOLNT			;CALL UNSOLICITED INTERRUPT ROUTINE
	MOVL	@(SP),R3			;GET ADDRESS OF IDB
	MOVL	IDB$L_CSR(R3),R4		;GET ADDRESS OF YM_CS
	BEQL	60$				;IF EQL NO
	MOVW	#^X1,YM_CS(R4)			;ISSUE CONTROL RESET
	BRW	10$				;
80$:	BSBW	YM_WAIT				;WAIT FOR FUNCTION TO COMPLETE
	TSTW	YM_CS(R4)			;SUCCESSFUL COMPLETION?
	BGEQ	90$				;IF GEQ YES
	MOVW	#F_DRVCLR!1,YM_CS(R4)		;CLEAR RK05 DRIVE
	BSBW	YM_WAIT				;WAIT FOR FUNCTION TO COMPLETE
90$:	BRW	10$				;
100$:	MOVAB	YM_DS(R4),R2			;GET ADDRESS OF DEVICE REGISTERS
	MOVAB	UCB$W_YM_DS(R5),R3		; ADR OF DEVICE REG SAV AREA
	MOVW	(R2)+,(R3)+			;SAVE DS REGISTER
	MOVW	(R2)+,(R3)+			;SAVE ER REGISTER
	MOVW	(R2)+,(R3)+			;SAVE CONTROL STATUS REGISTER
	MOVW	(R2)+,(R3)+			;SAVE WORD COUNT REGISTER
	MOVW	(R2)+,(R3)+			;SAVE BUS ADDRESS REGISTER
	MOVW	(R2)+,(R3)+			;SAVE DISK ADDRESS REGISTER
	MOVW	(R2),(R3)			;SAVE DATA BUFFER REGISTER

	MOVW	#^X1,YM_CS(R4)		;SET CONTROL RESET
	MOVW	#^XD,YM_CS(R4)		;SET DRIVE RESET
110$:	BRW	50$				;

.PAGE
 	.SBTTL	RK11/RK05  DISK CONTROLLER INITIALIZATION

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;  YM_RK11_INIT: - RK11/RK05  DISK CONTROLLER INITIALIZATION
;
;	THIS ROUTINE IS CALLED, VIA A JSB INSTRUCTION, BEFORE CALLING THE 
;	DISK DRIVE ( UNIT ) INITIALIZATION ROUTINE, AND UNDER THE FOLLOW-
;	ING CIRCUMSTANCES :
;
;		1]  AT SYSTEM INITIALIZATION ( STARTUP )
;		2]  IN ORDER TO LOAD AND/OR RELOAD THE DRIVER
;		3]  AT POWER FAIL ( A POWER RECOVERY RESTART )
;
; INPUTS:
;
;	R0 = SCRATCH.
;	R1 = SCRATCH.
;	R2 = SCRATCH.
;	R3 = SCRATCH.
;	R4 = ADDRESS OF YM CSR ( CONTROL AND STATUS REGISTER )
;	R5 = ADDRESS OF CONTROLLER IDB ( INTERRUPT DATA BLOCK )
;	R6 = ADDRESS OF DDB
;	R8 = ADDRESS OF CRB
;
;
;
;	
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;
;	SYMBOLIC OFFSETS ARE NOT USED BUT THE HEX INPUTS ARE AS BELOW:
;
;	^X1 = _G0!FCODE	;FCODE = 000  CONTROL RESET
;	^XD = _GO!FCODE	;FCODE = 110  DRIVE RESET
;	THEN ENABLE INTERRUPTS
;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
YM_RK11_INIT:				;RK11/RK05 DISK CONTROLLER INITIALIZATION
	MOVW	#^X1,YM_CS(R4)		;ISSUE CONTROL RESET
	MOVW	#^XD,YM_CS(R4)		;ISSUE DRIVE RESET
	MOVZBW	#YM_CS_M_IDE,YM_CS(R4)	;ENABLE DEVICE INTERRUPTS
	RSB				;RETURN


YM_END:					;ADDRESS OF LAST LOCATION IN DRIVER
 
	.END
