	.TITLE	DXPDRIVER - STAR CONSOLE FLOPPY DISK DRIVER
	.IDENT	/00/
 
;
; COPYRIGHT (C) 1977
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER  A LICENSE FOR USE ONLY  ON  A
; SINGLE COMPUTER SYSTEM AND MAY BE  COPIED ONLY WITH  THE INCLU-
; SION OF  THE  ABOVE  COPYRIGHT NOTICE.  THIS SOFTWARE,  OR  ANY
; OTHER COPIES THEREOF, MAY NOT BE  PROVIDED  OR  OTHERWISE  MADE
; AVAILABLE TO ANY OTHER PERSON EXCEPT  FOR  USE  ON  SUCH SYSTEM
; AND TO  ONE WHO AGREES  TO  THESE LICENSE  TERMS.  TITLE TO AND
; OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC.
;
; THE INFORMATION IN THIS SOFTWARE  IS  SUBJECT TO CHANGE WITHOUT
; NOTICE AND SHOULD NOT BE CONSTRUED  AS  A COMMITMENT BY DIGITAL
; EQUIPMENT CORPORATION.
;
; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
; SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
;
; C. A. MONIA 13-JUL-77
;
; STAR CONSOLE FLOPPY DISK DRIVER
;
; MACRO LIBRARY CALLS
;
 
	$ADPDEF				;DEFINE ADP OFFSETS
	$CRBDEF				;DEFINE CRB OFFSETS
	$DDBDEF				;DEFINE DDB OFFSETS
	$DDTDEF				;DEFINE DDT OFFSETS
	$EMBDEF				;DEFINE EMB OFFSETS
	$IDBDEF				;DEFINE IDB OFFSETS
	$IODEF				;DEFINE I/O FUNCTION CODES
	$IRPDEF				;DEFINE IRP OFFSETS
	$PRDEF				;DEFINE PROCESSOR REGISTERS
	$SSDEF				;DEFINE SYSTEM STATUS VALUES
	$UBADEF				;DEFINE UBA REGISTER OFFSETS
	$UCBDEF				;DEFINE UCB OFFSETS
	$VECDEF				;DEFINE INTERRUPT DISPATCH VECTOR OFFSETS
 
;
; LOCAL SYMBOLS
;
; CONSOLE FLOPPY STATUS BIT DEFINITIONS
;
 
	_VIELD	DXP_RXDB,0,<-		;RECEIVER DATA BUFFER FIELD DEFINITIONS
	<CRC,,M>,-			;CRC ERROR
	<PAR,,M>,-			;PARITY
	<INI,,M>-			;INIT. COMPLETE
>					;
	_VIELD	DXP_RXDB,6,<-		;
	<DEL,,M>,-			;DELETED DATA MARK READ
	<ERR,,M>-			;ERROR DETECTED
>					;
 
;
; CONSOLE COMMAND FIELD DEFINITION
;
 
DXP_M_CMD = 8@8				;COMMAND BIT
 
;
; CONSOLE DATA BUFFER VALUES
;
 
DXP_RXDB_K_CMD = 9@8			;INITIATE FLOPPY FUNCTION
DXP_RXDB_K_FCMP = 2@8			;FLOPPY FUNCTION COMPLETE
DXP_RXDB_K_PRTC = 5			;PROTOCOL ERROR STATUS
 
;
; HARDWARE FUNCTION CODES
;
 
F_READSECTOR=8@8!0			;READ SECTOR
F_WRITESECTOR=8@8!1			;WRITE SECTOR
F_READSTATUS=8@8!2			;READ STATUS
F_WRITEDELDATA=8@8!3			;WRITE DELETED DATA SECTOR
F_CANCEL=8@8!4				;CANCEL FLOPPY FUNCTION
 
;
; LOCAL DATA
;
; DRIVER DISPATCH TABLE
;
;
 
	.PSECT	WIONONPAGED
 
DXP$DDT::				;ADDRESS OF DRIVER DISPATCH TABLE
	.LONG	STARTIO			;INITIATE I/O OPERATION
	.LONG	UNSOLNT			;UNSOLICITED INTERRUPT
	.LONG	DX$FUNCTABLE		;FUNCTION DECISION TABLE
	.LONG	UNSOLNT			;DEASSIGN PROCESSING ROUTINE
	.LONG	REGDUMP			;REGISTER DUMP ROUTINE
	.WORD	<6>*4+<3>*4		;SIZE OF DIAGNOSTIC BUFFER
	.WORD	0			;SIZE OF ERROR BUFFER (0=NONE)
 
	.SBTTL	START I/O OPERATION
 
;+
; STARTIO - START I/O OPERATION ON DEVICE UNIT
;
; THIS ENTRY POINT IS ENTERED TO START AN I/O OPERATION ON THE CONSOLE
; FLOPPY. CONTROL ALTERNATES BETWEEN THE FLOPPY DRIVER AND THE FLOPPY
; UTILITY ROUTINES IN DXUTILITY THAT ARE SHARED BY ALL FLOPPY DEVICES.
; THE DRIVER PERFORMS ALL DEVICE-DEPENDANT PROCESSING WHILE THE UTILI-
; TY ROUTINES HANDLE THE INTERFACE BETWEEN THE DRIVE AND THE SYSTEM OR
; USER. THE PROTOCOL FOR EACH DATA TRANSFER IS AS FOLLOWS:
;
;	1. THE SYSTEM DETERMINES THE LEGALITY OF A FUNCTION AND ANY PRE-
;	   PROCESSING TO BE PERFORMED BY SCANNING THE COMMON FUNCTION DE-
;	   CISION TABLE.
;
;	2. A REQUEST IS DEQUEUED AND THE DRIVER IS ENTERED AT ITS START-I/O
;	   ENTRY POINT.
;
;	3. A SUBROUTINE CALL TO COMMON CODE IS EXECUTED TO COMPUTE THE INI-
;	   TIAL MEDIA ADDRESS AND SETUP THE I/O DATA BASE FOR THE TRANSFER.
;
;	4. A CO-ROUTINE CALL TO THE DRIVER IS EXECUTED TO POSITION THE MEDIA
;
;	5. A CO-ROUTINE CALL TO THE DRIVER IS PERFORMED TO TRANSFER ONE BYTE
;	   OF DATA
;
;	6. A CO-ROUTINE CALL TO THE COMMON PROCESSOR IS PERFORMED TO UPDATE
;	   THE ADDRESS AND BYTE COUNT AND CHECK FOR ENDPOINT CONDITIONS
;
; STEPS 4 - 6 ARE EXECUTED AT HARDWARE IPL LEVEL. A TRANSFER TO FORK LEVEL
; MUST BE EXECUTED WHENEVER:
;
;	. ONE SECTOR OF DATA HAS BEEN TRANSFERRED
;
;	. AN ERROR CONDITION IS DETECTED.
;
; ON OCCURANCE OF AN ERROR, THE DRIVER PERFORMS ANY HARDWARE DEPENDANT
; FUNCTIONS THEN TRANSFERS CONTROL TO THE COMMON EXCEPTION ENTRY POINT
; TO RESET MEDIA AND USER ADDRESSES AND REISSUE THE REQUEST.
;
; THE FLAGS DESCRIBED BELOW ARE USED TO SIGNAL EXCEPTION CONDITIONS:
;
;	FLAGS SET BY DRIVER:
;
;		WHEN EXCEPTION RETURN IS TAKEN:
;
;			R3 LBS = RETRIABLE HARDWARE ERROR
;			R3 LBC = FATAL HARDWARE ERROR
;
;			R0 CONTAINS THE STATUS CODE REFLECTING THE TYPE OF ERROR
;			DETECTED.
;
;	FLAGS SET BY UTILITY:
;
;		R3 LBC = TRANSFER OF ONE SECTOR COMPLETED
;
;		R3 LBS = PERFORM NORMAL DRIVER FUNCTION
;
;
; INPUTS:
;
;	R3 = ADDRESS OF I/O PACKET.
;	R5 = ADDRESS OF DEVICE UNIT CONTROL BLOCK
;
; OUTPUTS:
;
;	********OUTPUTS********
;-
 
	.ENABL	LSB
 
STARTIO:				;
	BSBW	DX$STARTIO		;CALL UTILITY ROUTINE TO SETUP PHYSICAL ADDRESS
RESTART:				;
	MOVZWL	#F_READSECTOR,R3	;ASSUME READ PHYSICAL SECTOR
	BBC	#UCB$V_DX_WRITE,UCB$W_DEVSTS(R5),20$ ;BRANCH IF READ
	ADDB2	#<F_WRITESECTOR-F_READSECTOR>,R3 ;CONVERT FUNCTION CODE TO WRITE SECTOR
20$:					;
	BSBB	DXPOUT			;SEND COMMAND TO FLOPPY
	MOVZBL	UCB$L_MEDIA(R5),R3	;GET SECTOR NUMBER
	BSBB	DXPOUT			;OUTPUT SECTOR
	MOVZBL	UCB$L_MEDIA+2(R5),R3	;GET CYLINDER NUMBER
	BSBB	DXPOUT			;SEND CYLINDER NUMBER
	BBS	#UCB$V_DX_WRITE,UCB$W_DEVSTS(R5),DXPWRITE ;BRANCH IF WRITE
	BSBB	DXPINP			;WAIT FOR FLOPPY TO FINISH
30$:					;
	BSBB	DXPINP			;WAIT FOR INPUT DATA
	MOVB	R3,@UCB$L_DX_BFPNT(R5)	;STORE BYTE
	JSB	@(SP)+			;RETURN TO CALLER
	BLBS	R3,30$			;IF LBS CONTINUE TRANSFER
	BRB	40$			;NO MORE DATA
 
;+
; DXPWRITE - OUTPUT TO CONSOLE FLOPPY
;
; THIS ROUTINE IS ENTERED TO WRITE ONE BYTE OF DATA ON THE CONSOLE FLOPPY.
; IF AN ERROR OCCURS, A COROUTINE CALL IS MADE TO THE EXCEPTION ENTRY POINT
; SPECIFIED BY CALLER'S CALLER. THE STACK CONTAINS THE RETURN TO IN-LINE DRIVER
; CODE. IN THIS CASE, R3 INDICATES ERROR SEVERITY AS FOLLOWS:
;
;	R3 LBS = RETRIABLE ERROR
;	R3 LBC = FATAL ERROR
;
; THE ERROR CODE IS IN R0.
;
; IF NO ERROR OCCURS, A RETURN TO THE DRIVER IS EXECUTED.
;
; INPUTS:
;
;	R3 LBS = REQUEST TO WRITE ONE BYTE OF DATA
;	R5 = ADDRESS OF UCB
;	(SP) = RETURN ADDRESS
;
;	R3 LBC = SECTOR TRANSFER COMPLETE
;
; OUTPUTS:
;
;	A RETURN TO INLINE CODE IS EXECUTED FOR A SUCCESFUL TRANSFER.
;	IF SECTOR TRANSFER IS COMPLETE, A FORK IS EXECUTED BEFORE CALLING
;	THE CALLER.
;
;	A RETURN TO THE EXCEPTION ENTRY POINT IS TAKEN IF AN ERROR OCCURS.
;	IN THIS CASE, R3 INDICATES THE SEVERITY AND R0 CONTAINS THE ERROR
;	CODE.
;
;-
 
DXPWRITE:				;
	MOVZBL	@UCB$L_DX_BFPNT(R5),R3	;GET OUTPUT DATA
	BSBB	DXPOUT			;SEND TO DEVICE
	JSB	@(SP)+			;CALL THE CALLER
	BLBS	R3,DXPWRITE		;IF LBS WRITE ANOTHER BYTE
	BSBB	DXPINP			;WAIT FOR FLOPPY FUNCTION COMPLETE
40$:					;
	MOVL	(SP)+,R4		;RETRIEVE RETURN ADDRESS
	IOFORK				;DROP TO FORK LEVEL
	JSB	(R4)			;CALL THE CALLER
	BRB	RESTART			;GO AGAIN
 
	.DSABL	LSB
 
;+
; DXPINP - WAIT FOR FLOPPY INPUT INTERRUPT
;
; THIS ROUTINE IS ENTERED VIA A BSB TO WAIT FOR AN INPUT INTERRUPT.
; IT ENTERS COMMON CODE TO EXECUTE A WAIT FOR INTERRUPT. ON RECEIPT
; OF THE INTERRUPT A RETURN TO THE CALLER IS EXECUTED AT ISR LEVEL.
;
; INPUTS:
;
;	(SP) = RETURN TO CALLER
;	4(SP) = RETURN TO CALLERS CALLER (DXUTILITY CO-ROUTINE)
;	8(SP) = RETURN TO EXECUTIVE
;
; OUTPUTS:
;
;	R3 = INPUT DATA
;	R5 = UCB ADDRESS
;
;	(SP) = RETURN TO CO-ROUTINE IN DXUTILITY
;
;-
 
	.ENABL	LSB
 
DXPINP:					;
	DSBINT	#31			;DISABLE ALL INTERRUPTS
	BBS	#UCB$V_POWER,UCB$W_STS(R5),5$ ;BRANCH IF POWER FAILURE
	POPR	#^M<R2,R3,R4>		;GET IPL IN R2, RETURNS IN R3, R4
	PUSHL	R2			;RESTORE IPL TO TOP OF STACK
	WFIKPCH	40$,#10			;WAIT FOR INTERRUPT
	BBSC	#UCB$V_INTTYPE,UCB$W_STS(R5),25$ ;IF SET, RECEIVED INPUT INT.
	BBCS	#UCB$V_INT,UCB$W_STS(R5),2$	;ENABLE INTERRUPTS, DISMISS INTERRUPT
2$:						;
	BRW	UNSOLNT				;
 
;+
; DXPOUT - PERFORM OUTPUT TO THE CONSOLE FLOPPY DISK
;
; THIS ROUTINE IS ENTERED VIA A BSB TO SEND DATA TO THE CONSOLE FLOPPY.
; IT ENTERS THE COMMON CONSOLE INTERRUPT HANDLER TO TRANSFER THE DATA.
;
; INPUTS:
;
;	R3 = FLOPPY DATA (BIT 11 MUST BE SET FOR A FLOPPY CONSOLE COMMAND).
;	R5 = ADDRESS OF UCB
;	(SP) = RETURN TO CALLER
;	4(SP) = RETURN TO CALLERS CALLER (DXUTILITY CO-ROUTINE)
;	8(SP) = RETURN TO EXECUTIVE
;
; OUTPUTS:
;
;	R5 = UCB ADDRESS
;
;	(SP) = RETURN TO CO-ROUTINE IN DXUTILITY
;
;-
 
DXPOUT:					;
	DSBINT	#31			;DISABLE ALL DEVICE INTERRUPTS
	BBC	#UCB$V_POWER,UCB$W_STS(R5),10$ ;BRANCH IF NO POWER FAILURE
5$:					;
	ENBINT				;ENABLE INTERRUPTS
	POPR	#^M<R3,R4>		;REMOVE RETURNS FROM STACK
	CLRL	R3			;SET TO FLAG NONFATAL ERROR
	BRB	50$			;
10$:					;
	BSBW	CON$STARTIO		;STARTUP THE DEVICE
20$:					;
	POPR	#^M<R2,R3,R4>		;GET IPL IN R2, RETURNS IN R3, R4
	PUSHL	R2			;RESTORE IPL TO TOP OF STACK
	WFIKPCH	40$,#10			;WAIT FOR INTERRUPT, KEEP CHANNEL
	BBCC	#UCB$V_INTTYPE,UCB$W_STS(R5),30$ ;IF CLEAR, RECEIVED OUTPUT INTERRUPT
25$:					;
	MOVL	R3,UCB$L_DX_RXDB(R5)	;SAVE CONTENTS OF RXDB
	EXTZV	#8,#4,R3,-(SP)		;EXTRACT COMMAND FIELD
	CMPL	(SP)+,#<DXP_RXDB_K_FCMP@-8>;TEST COMPLETION CODE
	BLSS	30$			;IF LSS PROCESS NEXT CHARACTER
	BNEQ	DXPERR			;IF NEQ, ERROR
	TSTB	R3			;TEST STATUS
	BNEQ	DXPERR			;IF NEQ, EXCEPTION CONDITION
30$:					;
	PUSHL	R4			;SET RETURN TO CALLER
	JMP	@UCB$L_FR3(R5)		;RETURN TO CALLER
40$:					;
	CLRL	R3			;SET TO FLAG FATAL ERROR
	BRB	47$			;FLAG FATAL CONTROLLER ERROR
 
;+
; DXPERR - HARDWARE DEPENDANT ERROR PROCESSING
;
; THIS ROUTINE IS ENTERED WHENEVER AN ERROR INDICATION IS RECEIVED FROM
; THE FLOPPY INTERFACE. IF THE PROBLEM WAS NOT CAUSED BY DEVICE TIMEOUT
; OR POWER FAIL THEN THE DEVICE REGISTERS ARE SAVED AND A FORK IS EXE-
; CUTED TO PERFORM ERROR ANALYSES.
;
; IF THE ERROR IS CAUSED BY HARDWARE, THE SEVERITY (FATAL OR NON-FATAL)
; AND STANDARD ERROR CODE ARE SETUP.
;
; INPUTS:
;
;	R3 = CONTENTS OF RXDB (IF ENTRY IS FROM CONSOLE INTERRUPT DISPATCHER)
;	R4 = CO-ROUTINE ENTRY POINT
;	R5 = ADDRESS OF UCB
;
; OUTPUTS:
;
;	R0 CONTAINS ERROR CODE
;	R3 LSB = 1, RETRIABLE ERROR
;	R3 LSB = 0, FATAL ERROR
;
;-
 
DXPERR:					;
	IOFORK				;FORK
	MOVZWL	#SS$_CTRLERR,R0		;ASSUME CONTROLLER ERROR
	MOVL	R3,R1			;COPY RXDB CONTENTS
	CLRL	R3			;ASSUME ERROR IS FATAL
	EXTZV	#8,#4,R1,R2		;EXTRACT COMMAND FIELD
	CMPB	R2,#<DXP_RXDB_K_FCMP@-8> ;FUNCTION COMPLETE?
	BEQL	45$			;IF EQL YES, CHECK ERRORS
	CMPB	R2,#<DXP_RXDB_K_CMD@-8>	;PROTOCOL ERROR?
	BNEQ	60$			;IF NEQ GARBAGE IN SELECT FIELD
	CMPB	R1,#DXP_RXDB_K_PRTC	;CHECK DATA BYTE
	BEQL	50$			;IF EQL, PROTOCOL ERROR
	BRB	60$			;ELSE GARBAGE IN DATA BYTE
45$:					;
	MOVZWL	#SS$_PARITY,R0		;ASSUME DATA ERROR
	TSTB	R1			;TEST FOR DATA ERROR
	BLSS	50$			;IF LSS DATA ERROR
	MOVZWL	#SS$_FORMAT,R0		;ASSUME READ DELETED DATA
	BBS	#DXP_RXDB_V_DEL,R1,60$	;IF BIT SET, FATAL FORMAT ERROR
47$:					;
	MOVZWL	#SS$_CTRLERR,R0		;ELSE GARBAGE IN BYTE
	BRB	60$			;FATAL CONTROLLER ERROR
50$:					;
	INCL	R3			;NONFATAL ERROR
60$:					;
	BSBW	DX$ERR			;CALL COMMON EXCEPTION CODE
	BRW	RESTART			;RESTART TRANSFER
 
	.DSABL	LSB
 
;+
; REGDUMP - CONSOLE FLOPPY REGISTER DUMP ROUTINE
;
; THIS ROUTINE IS ENTERED TO COPY THE CONSOLE FLOPPY STATUS REGISTER
; CONTENTS (RXDB) TO THE SPECIFIED BUFFER. IT IS CALLED FROM THE DE-
; VICE ERROR LOGGING ROUTINE AND FROM THE DIAGNOSTIC BUFFER FILL ROU-
; TINE.
;
; INPUTS:
;
;	R0 = ADDRESS OF REGISTER SAVE BUFFER
;	R5 = ADDRESS OF UCB
;
; OUTPUTS:
;
;	THE COPY OF RXDB RECORDED IN THE UCB IS SAVED IN THE SPECIFIED BUFFER.
;
;-
 
REGDUMP:				;
	MOVL	#2,(R0)+		;SET NUMBER OF DEVICE REGISTERS
	MOVL	UCB$L_DX_RXDB(R5),(R0)+	;COPY DEVICE REGISTER
	MOVL	UCB$L_MEDIA(R5),(R0)	;COPY LAST DISK ADDRESS
UNSOLNT:				;
	RSB				;
 
	.END
