AUSAM/sys/conf/powerf.s-new

/******		AT LAST FOLKS AN ALL SINGING ALL DANCING
/******		POWERFAIL RECOVERY ROUTINE.
/******
/******					ian johnstone
/******					MAY 78

/////////////////////////////////////////////////////////////////////////////////
/	certain options are necessary !!

.TTYCONNECT	= 1	/ set to one if tty connect mod is in the system
.PDP70		= 1	/ set to one for 11/70
.PDP45		= 0	/ set to one for 11/45
.PDP40		= 0	/ set to one for 11/40
			/ used by trap to print power fail recovery message
.if	.PDP70
.UNIBUSMAP	= 0	/ set to one if unibus map relevant
.endif
.SLR		= 1	/ set to one if stack limit exists
.if  .UNIBUSMAP - 1
.START		= 1	/ set to one if 134 bytes beyond 'start' (m70.s)
			/ can be clobbered as a power fail save area
			/ not the case if UNIBUSMAP defined ( 252. > 208. > 134. )
.endif

/	NON-UNIX instructions

reset	=	5
halt	=	0
mfpd	=	106500 ^ tst
mtpd	=	106600 ^ tst
rti	=	2

/	the move instructions that 'copiee' is to use

save	=	12321		/ mov (r3)+,(r1)+
rest	=	12123		/ mov (r1)+,(r3)+

/	Defines to describe cdevsw & bdevsw

.if	.TTYCONNECT
cdlen	=	14.		/ length of character device entry
cdpow	=	12.		/ offset in char device entry of powerfail routine
.endif
.if	.TTYCONNECT - 1
cdlen	=	12.		/ length of character device entry
cdpow	=	10.		/ offset in char device entry of powerfail routine
.endif
bdlen	=	10.		/ length of block device entry
bdpow	=	8.		/ offset in block device entry of powerfail routine

/	Some useful defines

CPUERR	=	177766		/ Cpu error register
PS	=	177776		/ Processor Status
MEMERR	=	177744		/ Memory system error register
.if	.SLR
SLR	=	177774		/ stack limit register
.endif
MMR0	=	177572		/ Memory Management register 0

/////////////////////////////////////////////////////////////////////////////////

	.data	/ this code must reside in bottom 8Kb of memory
		/ that is in lowest 8Kb of kernal i and kernal d space

	.globl	powfail, powvect, _savfp, loadfp
	.globl	_lks, _bdevsw, _cdevsw, csv
	.globl	nofault, _trap, _powflag, _uuerror
.if	.START
	.globl	start
.endif

/////////////////////////////////////////////////////////////////////////////////
/	power-down sequence
/	===================

powfail:				/ entry at priority level 7
	mov	$powtimout,*$powvect	/ in the event that 2ms is not long
					/ enough, halt on power-up
	mov	$1,_powflag		/ indicate powerfail in progress
					/ to other trap routines and printf.
	mov	r0,-(sp)
	mov	nofault,-(sp)		/ save nofault - want to process them
	clr	nofault			/ skip error catching ..
	mov	r1,-(sp)
	mov	$30340,PS		/ prior was user - 'mfpd sp' to work
	mfpd	sp			/ stack USER SP
	jsr	r5,csv			/ save r5,r4,r3,r2 and allow traceback
	jsr	pc,_savfp		/ save floating point registers
	mov	$save,mover		/ select desired mov for copiee
	jsr	pc,copiee		/ save volatile locations in core
.if	.SLR
	mov	*$SLR,-(sp)		/ save stack limit
.endif
	mov	sp,spsave		/ save Kernal SP
	mov	$powup,*$powvect	/ when power is restored powerup
					/ is the routine to use.

/////////////////////////////////////////////////////////////////////////////////
/	do nothing routine
/	==================
/
/	either waiting for the final curtain or
/	during last powerfail the powerwent before
/	saving could complete.

powtimout:
	halt				/ the inevitable will come soon enough
	br	powtimout		/ never ever want to continue.

/////////////////////////////////////////////////////////////////////////////////
/	power-up sequence
/	=================

powup:
	reset
	mov	$30340,PS		/ previous mode was user - want 'mtpd sp' to work
.if	.PDP70
	clr	*$CPUERR		/ it is not clear what initial value is
	mov	$-1,*$MEMERR		/ it is not clear what initial value is
.endif
	mov	$tmpstck+2,sp		/ get a one word temp stack
/
	mov	$rest,mover		/ select desired mov for copiee
	jsr	pc,copiee		/ restore volatile locattions
/
	mov	spsave,sp		/ use real stack
.if	.SLR
	mov	(sp)+,*$SLR		/ and protect it by restoring stack limit reg
.endif
	inc	*$MMR0			/ start mem mngmt
	jsr	pc,loadfp		/ restore floating point registers
/
	mov	$115,*_lks		/ restart the clock
/
	movb	*_uuerror,r4		/ save u.u_error dont want it inadvertantly changed
	mov	$1,(sp)			/ load a one to indicate "rootdev"
	mov	$_bdevsw,r2		/ start with block device recovery
0:	tst	(r2)			/ end of block table ??
	beq	1f			/ --> yes
	jsr	pc,*bdpow(r2)		/ call device power fail routine.
	add	$bdlen,r2		/ step to next entry
	clr	(sp)			/ no more root devices.
	br	0b
/
1:	mov	$_cdevsw,r2		/ now for the character devices
2:	tst	(r2)			/ end of cahracter table ??
	beq	3f			/ --> yes
	jsr	pc,*cdpow(r2)		/ call device power fail routine.
	add	$cdlen,r2		/ step to next entry
	br	2b
/
3:	tst	(sp)+			/ discard arg for device powerfail routines
	movb	r4,*_uuerror		/ restore u.u_error - ignore possible errors !!
					/ as left by csv
/
/
	mov	(sp)+,r2		/ restore registers as save by csv
	mov	(sp)+,r3		/ restore registers as save by csv
	mov	(sp)+,r4		/ restore registers as save by csv
	mov	(sp)+,r5		/ restore registers as save by csv
/
	mov	$16,-(sp)		/ power fail error code
	jsr	pc,_trap		/ let trap do its thing
	tst	(sp)+			/ pop error code
/
	mtpd	sp			/ restore USER SP
	mov	(sp)+,r1
	mov	(sp)+,nofault		/ well made it with out error !!
	mov	(sp)+,r0
	clr	_powflag		/ tell the world that power fail is over
	mov	$powfail,*$powvect	/ restore powerfail vector
	mov	$115,*_lks		/ restart the clock (i'm paranoid)
	rti				/ let it rip baby

/ temp stack area only used for restore
/ placed here so if anything goes wrong
/ code will be clobbered and no recover
/ will occur ( well maybe ).

tmpstck: . = . + 2

/////////////////////////////////////////////////////////////////////////////////
/	routine to save/load volatile locations described by 'tosave'

copiee:
.if	.START - 1
	mov	$savearea,r1		/ save area to be used
.endif
.if	.START
	mov	$start,r1		/ save area to be used
.endif
	mov	$tosave,r2		/ table of locations to save.
1:	mov	(r2)+,r3		/ address of next location.
	beq	3f			/ --> all done.
	mov	(r2)+,r4		/ number of words this location.
mover:	0				/ caller decides which mov.
	sob	r4,mover		/ copy all the words this location
	br	1b			/ go for more
3:
	rts	pc

/////////////////////////////////////////////////////////////////////////////////
/	the following table describes what is be be saved
/	in addition general register set 0 and user SP are saved

tosave:
	777772;   1.	/ PIR
	777744;   1.	/ Memory Control
	777600;  32.	/ user i PDR, d PDR, i PAR, d PAR
	772300;  32.	/ kernal i PDR, d PDR, i PAR, d PAR
.if .UNIBUSMAP
	770200;  59.	/ UNIBUSMAP
.endif
.if	.PDP40 - 1
	772516;   1.	/ MMR3
.endif
	0

.if	.START - 1
savearea:
	. = . + 4. + 64. + 64. + 2.
.if .UNIBUSMAP
	. = . + 118
.endif

.endif
/	miscellaneous locations

spsave:	.=.+2		/ save area for kernal sp.
_powflag:.=.+2		/ if ==1 then power fail in progress
			/ if ==2 then trap during powerfail
			/ if ==0 then nothing dto do with power fail