xref: /csrg-svn/sys/vax/mdec/tmscpboot.c (revision 33388)
1*33388Sbostic /*
2*33388Sbostic  *	@(#)tmscpboot.c	7.2 (Berkeley) 01/22/88
3*33388Sbostic  *
4*33388Sbostic  * TK50 tape boot block for distribution tapes
5*33388Sbostic  * works on Q-bus tk50 drive on uVaxen
6*33388Sbostic  *
7*33388Sbostic  * Rick Lindsley
8*33388Sbostic  * richl@tektronix.tek.com
9*33388Sbostic  *
10*33388Sbostic  * reads a program from a tp directory on a tape and executes it
11*33388Sbostic  * program must be stripped of the header and is loaded ``bits as is''
12*33388Sbostic  * you can return to this loader via ``ret'' as you are called ``calls $0,ent''
13*33388Sbostic  */
1433387Sbostic 	.set	RELOC,0x70000
15*33388Sbostic /* tp directory definitions */
1633387Sbostic 	.set	FILSIZ,38	# tp direc offset for file size
1733387Sbostic 	.set	BNUM,44		# tp dir offset for start block no.
1833387Sbostic 	.set	ENTSIZ,64	# size of 1 TP dir entry, bytes
1933387Sbostic 	.set	PTHSIZ,32	# size of TP path name, bytes
2033387Sbostic 	.set	BLKSIZ,512	# tape block size, bytes
2133387Sbostic 	.set	NUMDIR,24	# no. of dir blocks on tape
2233387Sbostic 	.set	ENTBLK,8	# no. of dir entries per tape block
2333387Sbostic /* processor registers and bits */
2433387Sbostic 	.set	RXCS,32
2533387Sbostic 	.set	RXDB,33
2633387Sbostic 	.set	TXCS,34
2733387Sbostic 	.set	TXDB,35
2833387Sbostic 	.set	RXCS_DONE,0x80
2933387Sbostic 	.set	TXCS_RDY,0x80
3033387Sbostic 	.set	TXCS_pr,7	/* bit position of TXCS ready bit */
3133387Sbostic 	.set	RXCS_pd,7	/* bit position of RXCS done bit */
3233387Sbostic /* UBA registers */
3333387Sbostic 	.set	MAPSTART,0x20088000	# for a uVax, anyway
3433387Sbostic 	.set	UBAMEM,0x1ffc2000	# again, for a uVax
3533387Sbostic 	.set	MRV,0x80000000		# map register valid bit
3633387Sbostic /* TMSCP UBA registers */
3733387Sbostic 	.set	TMSCP_CSR, 0774500	# CSR of tk50
3833387Sbostic 	.set	TMSCPip,0		# initialization and polling
3933387Sbostic 	.set	TMSCPsa,2		# status and address
4033387Sbostic /* handy values for tmscp communication area */
4133387Sbostic 	.set	TMSCP_OWN,0x80000000
4233387Sbostic 	.set	TMSCP_ERR,0x8000
4333387Sbostic 	.set	TMSCP_STEP4,0x4000
4433387Sbostic 	.set	TMSCP_STEP3,0x2000
4533387Sbostic 	.set	TMSCP_STEP2,0x1000
4633387Sbostic 	.set	TMSCP_STEP1,0x800
4733387Sbostic 	.set	TMSCP_IE,0x80
4833387Sbostic 	.set	TMSCP_GO,1
4933387Sbostic /* handy offsets into tmscp communication area (from tmscpca) */
5033387Sbostic 	.set	cmdint,4
5133387Sbostic 	.set	rspint,6
5233387Sbostic 	.set	rspdsc,8
5333387Sbostic 	.set	cmddsc,12
5433387Sbostic /* handy offsets into mscp packets (from %rCMD or %rRSP) */
5533387Sbostic 	.set	msglen,0
5633387Sbostic 	.set	vcid,3
5733387Sbostic 	.set	unit,8
5833387Sbostic 	.set	op,12
5933387Sbostic 	.set	status,14
6033387Sbostic 	.set	modifier,14
6133387Sbostic 	.set	bytecnt,16
6233387Sbostic 	.set	cntflgs,18
6333387Sbostic 	.set	buffer,20
6433387Sbostic 	.set	tmkcnt,20
6533387Sbostic 	.set	lbn,32
6633387Sbostic 	.set	dscptr,40
6733387Sbostic /* TMSCP commands and modifiers */
6833387Sbostic 	.set	M_OP_STCON,4
6933387Sbostic 	.set	M_OP_ONLIN,9
7033387Sbostic 	.set	M_OP_READ,33
7133387Sbostic 	.set	M_OP_REPOS,37
7233387Sbostic 	.set	M_MD_REWND,2
7333387Sbostic 	.set	M_MD_IMMED,0x80
7433387Sbostic 	.set	M_MD_CLSEX,0x200
7533387Sbostic 	.set	M_ST_MASK,0x1f
7633387Sbostic 	.set	M_ST_TAPEM,14
7733387Sbostic /* miscellaneous */
7833387Sbostic 	.set	IUR, 0x37
7933387Sbostic 	.set	SID, 0x3e
8033387Sbostic 	.set	VAX_630,8
8133387Sbostic /* local stack variables */
8233387Sbostic 	.set	tmscpca,-240-PTHSIZ-26	# struct tmscpca (see tmscpreg.h)
8333387Sbostic 	.set	rsp,-240-PTHSIZ-10	# tmscp response area
8433387Sbostic 	.set	cmd,-120-PTHSIZ-10	# tmscp command area
8533387Sbostic 	.set	name,-PTHSIZ-10		# operator-typed file name
8633387Sbostic 	.set	dirread,-10		# is the tape directory incore already?
8733387Sbostic 	.set	mtapa,-8		# cur tape addr (last blk we read)
8833387Sbostic 	.set	tapa,-4			# desired tape addr (inclusive)
8933387Sbostic /* register usage */
9033387Sbostic 	.set	rCMD,r7
9133387Sbostic 	.set	rRSP,r8
9233387Sbostic 	.set	rUBADDR,r9
9333387Sbostic 	.set	rMAPREGS,r10
9433387Sbostic 	.set	rCSR,r11
9533387Sbostic /* ===== */
9633387Sbostic 
9733387Sbostic /* initialization */
9833387Sbostic init:
9933387Sbostic 	#
10033387Sbostic 	# if on a uVax, we were loaded by VMB from tape. We also have
10133387Sbostic 	# only one unibus, at 0x1fffc2000 (see above). Elstwise, this
10233387Sbostic 	# boot program will almost certainly need help.
10333387Sbostic 	#
10433387Sbostic 	mfpr	$SID,r0
10533387Sbostic 	cmpzv	$24,$8,r0,$VAX_630
10633387Sbostic 	beql	1f
10733387Sbostic 	halt
10833387Sbostic 	#
10933387Sbostic 	# We must have been loaded by VMB, and thus we are at a non-zero
11033387Sbostic 	# location.  sp will contain the base address of the area at which
11133387Sbostic 	# we were loaded. So we add sp to $end to get the true end-of-program
11233387Sbostic 	# address.
11333387Sbostic 	#
11433387Sbostic 1:	movl	sp,r6		# r6 - beginning of program
11533387Sbostic 	movl	$RELOC,fp	# core loc to which to move this program
11633387Sbostic 	addl3	$-512,fp,sp	# set stack pointer; leave room for locals
11733387Sbostic 	addl3	$-512,fp,r0	# zero our destination mem .. we start here
11833387Sbostic 	addl3	$end,fp,r1	# and end here
11933387Sbostic clr:	clrl	(r0)+
12033387Sbostic 	cmpl	r0,r1
12133387Sbostic 	jlss	clr
12233387Sbostic 
12333387Sbostic 	movc3	$end,(r6),(fp)	# copy to relocated position
12433387Sbostic 	addl3	$reginit,$RELOC,r0
12533387Sbostic 	jmp	(r0)		# and go there
12633387Sbostic reginit:
12733387Sbostic 	/* initialize our registers. Should need to do this only once */
12833387Sbostic 	addl3	$UBAMEM, $TMSCP_CSR, %rCSR	# set up CSR register
12933387Sbostic 	movl	$MAPSTART, %rMAPREGS	# locate map registers
13033387Sbostic 
13133387Sbostic 	moval	tmscpca(fp), %rUBADDR	# set unibus address for comm area
13233387Sbostic 	extzv	$0,$9,%rUBADDR,%rUBADDR	# format: (MR# << 9) | (&comm & 0x1ff)
13333387Sbostic 	ashl	$-9,$RELOC-512,r0	# setting up map register for our stack
13433387Sbostic 	bisl3	$MRV,r0,(%rMAPREGS)	# mark our stack valid (MR #0)
13533387Sbostic 
13633387Sbostic 	moval	cmd(fp),%rCMD		# location of cmd mscp packet
13733387Sbostic 	moval	rsp(fp),%rRSP		# location of rsp mscp packet
13833387Sbostic 	bsbw	inittmscp		# init the unit
13933387Sbostic 	bsbw	onlin			# set tape online
14033387Sbostic 	bsbw	rew			# rewind tape
14133387Sbostic 
14233387Sbostic start:
143*33388Sbostic #ifdef DEBUG
144*33388Sbostic 	movzbl	$11,r0			# newline
145*33388Sbostic 	bsbw	putc
146*33388Sbostic 	movzbl	$13,r0			# return
147*33388Sbostic 	bsbw	putc
148*33388Sbostic #endif
14933387Sbostic 	movzbl	$'=,r0			# prompt
150*33388Sbostic 	bsbw	putc
15133387Sbostic 	bsbw	getname
15233387Sbostic 
15333387Sbostic 	# desired TP filename is in name(fp).  Now read in entire tp directory
15433387Sbostic 	# contents into low core, starting at loc 0. Because tk50's are slow,
15533387Sbostic 	# and because we are going to go over 512 bytes anyway, and because
15633387Sbostic 	# it requires so little effort, we'll keep track of whether the data
15733387Sbostic 	# at location 0 is the tape directory.
15833387Sbostic 
15933387Sbostic 	tstw	dirread(fp)	# if directory needs to be read in, do so
16033387Sbostic 	bneq	1f
16133387Sbostic 	bsbw	readdir
16233387Sbostic 1:
16333387Sbostic 	#
16433387Sbostic 	# all of directory is now in locore, @ 0.
16533387Sbostic 	# search for filename; return to start if it isn't there.
16633387Sbostic 	#
16733387Sbostic 	clrl	r0			# start at location 0
16833387Sbostic nxtdir:	moval	name(fp),r2
16933387Sbostic 	movl	r0,r1
17033387Sbostic 1:	cmpb	(r1),(r2)
17133387Sbostic 	bneq	2f
17233387Sbostic 	tstb	(r1)
17333387Sbostic 	beql	found
17433387Sbostic 	incl	r1
17533387Sbostic 	incl	r2
17633387Sbostic 	brb	1b
17733387Sbostic 2:	acbl	$NUMDIR*BLKSIZ-1,$ENTSIZ,r0,nxtdir
17833387Sbostic 	brw	start			# entry not in directory; start over
17933387Sbostic 
18033387Sbostic 	# entry IS here; read it in from tape
18133387Sbostic 
18233387Sbostic found:	movzwl	BNUM(r0),tapa(fp)	# start block no., 2 bytes
18333387Sbostic 	addl2	$2-1,tapa(fp)		# skip over this program (2 blocks)
18433387Sbostic 					# minus 1 because we will read THROUGH
18533387Sbostic 					# this block; so we want to stop just
18633387Sbostic 					# before it
18733387Sbostic 	movzwl	FILSIZ(r0),r4		# low 2 bytes file size
18833387Sbostic 	insv	FILSIZ-1(r0),$16,$8,r4  # file size, high byte
18933387Sbostic 	cmpl	r4,$RELOC-512		# check if file fits below stack
19033387Sbostic 	bgeq	start 			# file too large
19133387Sbostic 
19233387Sbostic 	# Now advance to proper place on tape. tapa has our
19333387Sbostic 	# desired address
19433387Sbostic 
19533387Sbostic 	clrw	dirread(fp)	# we are about to obliterate our incore copy
19633387Sbostic 				# of the directory
19733387Sbostic 2:	clrl	r3	# rrec expects r3 to point to a buffer. 0 will do ...
19833387Sbostic 	bsbw	rrec
19933387Sbostic 	cmpl	mtapa(fp),tapa(fp)
20033387Sbostic 	blss	2b
20133387Sbostic 
20233387Sbostic 	# tape now positioned correctly. Read in program. Number of bytes
20333387Sbostic 	# to read is in r4. We must round up to an even BLKSIZ boundary.
20433387Sbostic 	# Clear the area we are putting it at; unix expects zeroes in its
20533387Sbostic 	# data and bss section.
20633387Sbostic 
20733387Sbostic 	addl2	$BLKSIZ-1,r4		# round up
20833387Sbostic 	bicl2	$BLKSIZ-1,r4		# mask out
20933387Sbostic 	movl	r4,r5			# use r5; need to save r4 for later
21033387Sbostic 1:	clrl	(r5)
21133387Sbostic 	sobgtr	r5,1b
21233387Sbostic 
21333387Sbostic 	# now read in file.
21433387Sbostic 
21533387Sbostic 	clrl	r3			# read into page 0 (incremented by rrec)
21633387Sbostic 	ashl	$-9,r4,r5		# r5 now holds # blks to read
21733387Sbostic 	addl2	r5,tapa(fp)		# compute desired tape blk #
21833387Sbostic 1:	bsbw	rrec
21933387Sbostic 	cmpl	mtapa(fp),tapa(fp)	# got it yet?
22033387Sbostic 	blss	1b
22133387Sbostic 
22233387Sbostic 	# begin execution. Call as a function.
22333387Sbostic 	clrl	r5
22433387Sbostic 	calls	$0,(r5)
22533387Sbostic 
22633387Sbostic 	# now, since the called function has reset the tape drive for
22733387Sbostic 	# us (!) we must reinit it again ourselves.
22833387Sbostic 
22933387Sbostic 	ashl	$-9,$RELOC-512,r0	# set up map register for our stack
23033387Sbostic 	bisl3	$MRV,r0,(%rMAPREGS)	# mark our stack valid (MR #0)
23133387Sbostic 	bsbw	inittmscp		# re-init drive
23233387Sbostic 	bsbw	onlin			# re-online it
23333387Sbostic 	brw	start
23433387Sbostic 
23533387Sbostic 	# getname will set name(fp) and leave len(name(fp)) in r6
23633387Sbostic getname:moval	name(fp),r1		# mov to register for ease of access
23733387Sbostic nxtc:	bsbw	getc
23833387Sbostic 	cmpb	r0,$012			# end of line?
23933387Sbostic 	beql	nullc
24033387Sbostic 	movb	r0,(r1)+
24133387Sbostic 	brb	nxtc
24233387Sbostic nullc:	moval	name(fp),r0
24333387Sbostic 	subl3	r0,r1,r6		# length of path name
24433387Sbostic 	jeql	start			# just hit return; nothing useful here
24533387Sbostic 	clrb	(r1)+			# add null at end
24633387Sbostic 	incl	r6			# add null to length
24733387Sbostic 	rsb
24833387Sbostic 
24933387Sbostic getc:	mfpr	$RXCS,r0
25033387Sbostic 	bbc	$RXCS_pd,r0,getc	/* receiver ready ? */
25133387Sbostic 	mfpr	$RXDB,r0
25233387Sbostic 	extzv	$0,$7,r0,r0
25333387Sbostic 	cmpb	r0,$015
25433387Sbostic 	bneq	putc
25533387Sbostic 	bsbw	putc
25633387Sbostic 	movb	$0,r0
25733387Sbostic 	bsbw	putc
25833387Sbostic 	movb	$012,r0
25933387Sbostic 
26033387Sbostic putc:	mfpr	$TXCS,r2
26133387Sbostic 	bbc	$TXCS_pr,r2,putc	/* transmitter ready ? */
26233387Sbostic 	extzv	$0,$7,r0,r0
26333387Sbostic 	mtpr	r0,$TXDB
26433387Sbostic 	rsb
26533387Sbostic 
26633387Sbostic inittmscp:
26733387Sbostic 	movw	$0,TMSCPip(%rCSR)		# start step 1
26833387Sbostic 1:	bitw	$TMSCP_STEP1,TMSCPsa(%rCSR)
26933387Sbostic 	beql	1b
270*33388Sbostic #ifdef DEBUG
271*33388Sbostic 	movzbl	$'1,r0
272*33388Sbostic 	bsbw	putc
273*33388Sbostic #endif
27433387Sbostic init2:	movw	$TMSCP_ERR,TMSCPsa(%rCSR)	# start step 2
27533387Sbostic 2:	bitw	$TMSCP_STEP2,TMSCPsa(%rCSR)
27633387Sbostic 	beql	2b
277*33388Sbostic #ifdef DEBUG
278*33388Sbostic 	movzbl	$'2,r0
279*33388Sbostic 	bsbw	putc
280*33388Sbostic #endif
28133387Sbostic init3:	addl3	$8,%rUBADDR,r0			# start step 3
28233387Sbostic 	cvtlw	r0,TMSCPsa(%rCSR)
28333387Sbostic 3:	bitw	$TMSCP_STEP3,TMSCPsa(%rCSR)
28433387Sbostic 	beql	3b
285*33388Sbostic #ifdef DEBUG
286*33388Sbostic 	movzbl	$'3,r0
287*33388Sbostic 	bsbw	putc
288*33388Sbostic #endif
28933387Sbostic init4:	addl3	$8,%rUBADDR,r0			# start step 4
29033387Sbostic 	ashl	$-16,r0,r0
29133387Sbostic 	cvtlw	r0,TMSCPsa(%rCSR)
29233387Sbostic 4:	bitw	$TMSCP_STEP4,TMSCPsa(%rCSR)
29333387Sbostic 	beql	4b
294*33388Sbostic #ifdef DEBUG
295*33388Sbostic 	movzbl	$'4,r0
296*33388Sbostic 	bsbw	putc
297*33388Sbostic #endif
29833387Sbostic setchar:
29933387Sbostic 	movw	$TMSCP_GO,TMSCPsa(%rCSR)
30033387Sbostic 	moval	140(%rUBADDR),tmscpca+cmddsc(fp)
30133387Sbostic 	moval	tmscpca+cmddsc(fp),dscptr(%rCMD)
30233387Sbostic 	movb	$1,vcid(%rCMD)
30333387Sbostic 	moval	20(%rUBADDR),tmscpca+rspdsc(fp)
30433387Sbostic 	moval	tmscpca+rspdsc(fp),dscptr(%rRSP)
30533387Sbostic 	clrw	cntflgs(%rCMD)
30633387Sbostic 
30733387Sbostic 	movb	$M_OP_STCON,op(%rCMD)
30833387Sbostic 	clrw	modifier(%rCMD)
30933387Sbostic 	clrl	buffer(%rCMD)
31033387Sbostic 	clrl	bytecnt(%rCMD)
311*33388Sbostic 	bsbw	tmscpcmd
312*33388Sbostic #ifdef DEBUG
313*33388Sbostic 	movzbl	$'S,r0
314*33388Sbostic 	bsbw	putc
315*33388Sbostic #endif
31633387Sbostic 	rsb
31733387Sbostic 
31833387Sbostic tmscpcmd:
31933387Sbostic 	movw	$116,msglen(%rCMD)		# 116 -- size of an mscp packet
32033387Sbostic 	bisl2	$TMSCP_OWN,tmscpca+cmddsc(fp)
32133387Sbostic 	movw	$116,msglen(%rRSP)
32233387Sbostic 	bisl2	$TMSCP_OWN,tmscpca+rspdsc(fp)
32333387Sbostic 	movw	TMSCPip(%rCSR),r0		# start polling
32433387Sbostic wait:	cvtwl	TMSCPsa(%rCSR),r0
32533387Sbostic 	bitl	$TMSCP_ERR,r0
32633387Sbostic 	beql	1f
32733387Sbostic 	movw	modifier(%rRSP),r1	# so we can read status easily
32833387Sbostic 	halt				# some error or other
32933387Sbostic 1:	tstl	tmscpca+4(fp)
33033387Sbostic 	beql	2f
33133387Sbostic 	clrw	tmscpca+4(fp)
33233387Sbostic 2:	bitl	$TMSCP_OWN,tmscpca+rspdsc(fp)
33333387Sbostic 	bneq	wait
33433387Sbostic 
33533387Sbostic 	# cmd done
33633387Sbostic 
33733387Sbostic 	clrw	tmscpca+rspint(fp)
33833387Sbostic 	extzv	$0,$5,status(%rRSP),r0
33933387Sbostic 	tstl	r0
34033387Sbostic 	beql	ok			# no errors
34133387Sbostic 	cmpl	$M_ST_TAPEM, r0
34233387Sbostic 	beql	ok			# not an error, just a tape mark
34333387Sbostic 	halt				# some unknown error
34433387Sbostic ok:	rsb
34533387Sbostic 
34633387Sbostic rew:	movb	$M_OP_REPOS,op(%rCMD)
34733387Sbostic 	movw	$M_MD_REWND|M_MD_IMMED,modifier(%rCMD)
34833387Sbostic 	clrl	buffer(%rCMD)
34933387Sbostic 	clrl	bytecnt(%rCMD)
35033387Sbostic 	bsbw	tmscpcmd
351*33388Sbostic #ifdef DEBUG
352*33388Sbostic 	movzbl	$'r,r0			# to indicate r)ewind
353*33388Sbostic 	bsbw	putc
354*33388Sbostic #endif
35533387Sbostic 	movl	$-1,mtapa(fp)		# no blocks read yet
35633387Sbostic 	rsb
357*33388Sbostic 
35833387Sbostic onlin:	movb	$M_OP_ONLIN,op(%rCMD)
35933387Sbostic 	clrw	modifier(%rCMD)
36033387Sbostic 	clrl	buffer(%rCMD)
36133387Sbostic 	clrl	bytecnt(%rCMD)
36233387Sbostic 	bsbw	tmscpcmd
363*33388Sbostic #ifdef DEBUG
364*33388Sbostic 	movzbl	$'O,r0			# to indicate O)nline
365*33388Sbostic 	bsbw	putc
366*33388Sbostic #endif
36733387Sbostic 	rsb
368*33388Sbostic 
36933387Sbostic 	# Read the tp directory. Number of blocks to read is in tapa(fp),
37033387Sbostic 	# and will be read into memory starting at location 0.
37133387Sbostic readdir:bsbw	rew			# beginning of tape
37233387Sbostic 	addl3	$2,$NUMDIR,tapa(fp)	# blocks to read (skip this 1k program)
37333387Sbostic 	clrl	r3			# using mem starting at 0 as free space
37433387Sbostic 	bsbw	rrec; bsbw rrec		# read and discard first two blocks --
37533387Sbostic 					# those are this program
37633387Sbostic 	bsbw	rrec			# read and discard first tp block
37733387Sbostic 	clrl	r3			# reset starting place
37833387Sbostic 	incw	dirread(fp)		# show that directory is incore
37933387Sbostic 1:	bsbw	rrec
38033387Sbostic 	cmpl	mtapa(fp),tapa(fp)	# done yet?
38133387Sbostic 	blss	1b
38233387Sbostic 	rsb
38333387Sbostic 
38433387Sbostic 	# read 1 block from mag tape into page indicated by r3, which will
38533387Sbostic 	# automatically be incremented here. mtapa is also advanced.
38633387Sbostic 
38733387Sbostic rrec:	bisl3	$MRV,r3,4(%rMAPREGS)	# using map register #1
38833387Sbostic 	movl	$BLKSIZ,bytecnt(%rCMD)	# how much to read
38933387Sbostic 	ashl	$9,$1,buffer(%rCMD)	# indicating mr #1. We just happen to
39033387Sbostic 					# be on a page boundary, so filling in
39133387Sbostic 					# the low 9 bits is not necessary.
39233387Sbostic 	movb	$M_OP_READ,op(%rCMD)
39333387Sbostic 	clrw	modifier(%rCMD)
39433387Sbostic 	bsbw	tmscpcmd
395*33388Sbostic #ifdef DEBUG
396*33388Sbostic 	movzbl	$'R,r0			# to indicate R)ead a record
397*33388Sbostic 	bsbw	putc
398*33388Sbostic #endif
39933387Sbostic 	incl	mtapa(fp)
40033387Sbostic 	incl	r3
40133387Sbostic 	rsb
40233387Sbostic end:
403