xref: /csrg-svn/sys/vax/mdec/tuboot.c (revision 23153)
1*23153Smckusick /*
2*23153Smckusick  * Copyright (c) 1980 Regents of the University of California.
3*23153Smckusick  * All rights reserved.  The Berkeley software License Agreement
4*23153Smckusick  * specifies the terms and conditions for redistribution.
5*23153Smckusick  */
611099Ssam 
7*23153Smckusick #ifndef lint
8*23153Smckusick _sccsid:.asciz	"@(#)tuboot.c	6.2 (Berkeley) 06/08/85"
9*23153Smckusick #endif not lint
10*23153Smckusick 
1111099Ssam /*
1211099Ssam  * VAX tu58 console cassette boot block
1311099Ssam  *
1413210Shelge  * Helge Skrivervik CSRG/UCB 18jun83
1511099Ssam  *
1613210Shelge  * Reads a program from a rt-11 directory on tape
1713210Shelge  * and executes it.  Programs must be stripped of
1811099Ssam  * the header and is loaded ``bits as is''.
1911099Ssam  * You can return to this loader via ``ret'' as
2011099Ssam  * you are called ``calls $0,ent''.
2113210Shelge  * Error checking and recovery is almost nonexistant
2213210Shelge  * due to the severe space constraints.
2313210Shelge  *
2413210Shelge  * NOTE: Any changes to this program are likely to
2513210Shelge  *	 bring the size over 512 bytes ....
2613210Shelge  *
2713210Shelge  * Based on tp format bootstrap originally written by Thomas Ferrin.
2813210Shelge  *
2911099Ssam  */
3013210Shelge 	.set	CTABLE,0x400	/* where to load the rad50 cnv table */
3111099Ssam 	.set	RELOC,0x70000
3213194Shelge /* rt-11 directory definitions */
3313194Shelge 	.set	DIRBLK,6	/* rt-11 directory starts at block 6 */
3413194Shelge 	.set	FILSIZ,8	/* rt-11 direc entry offset for file size */
3513194Shelge 	.set	ENTSIZ,14	/* size of 1 rt-11 dir entry, bytes */
3611099Ssam 	.set	BLKSIZ,512	/* tape block size, bytes */
3713194Shelge 	.set	NUMDIR,2	/* no. of dir blocks on tape */
3813210Shelge 	.set	FNSIZ,8		/* size of rad50 filename + 2 */
3913194Shelge 	.set	NAME,2		/* direc entry offset for filename */
4013210Shelge 	.set	STATUS,1	/* direc entry offset for entry status */
4113194Shelge /* rt-11 directory entry status */
4213194Shelge 	.set	RT_ESEG,8	/* end of directory segment */
4313194Shelge 	.set	RT_NULL,2	/* empty entry */
4413194Shelge 	.set	RT_FILE,4	/* valid file entry */
4511099Ssam /* processor registers and bits */
4611099Ssam 	.set	RXCS,32
4711099Ssam 	.set	RXDB,33
4811099Ssam 	.set	TXCS,34
4911099Ssam 	.set	TXDB,35
5011099Ssam 	.set	RXCS_DONE,0x80
5111099Ssam 	.set	TXCS_RDY,0x80
5211099Ssam 	.set	TXCS_pr,7	/* bit position of TXCS ready bit */
5311099Ssam 	.set	RXCS_pd,7	/* bit position of RXCS done bit */
5411099Ssam /* console storage registers and bits */
5511099Ssam 	.set	CSRS,0x1c
5611099Ssam 	.set	CSRD,0x1d
5711099Ssam 	.set	CSTS,0x1e
5811099Ssam 	.set	CSTD,0x1f
5911099Ssam /* TU commands and bits */
6011099Ssam 	.set	TU_BREAK,1
6111099Ssam 	.set	TU_INIT,4
6211099Ssam 	.set	TU_CONTINUE,16
6311099Ssam 	.set	TU_READY,7	/* bit position of CSRS ready bit */
6411099Ssam 	.set	TU_PACKETLEN,8	/* length of readcom block */
6511099Ssam /* local stack variables */
6614312Ssam 	.set	ext,-4			/* file ext. */
6714312Ssam 	.set	name,-20		/* 12 bytes for full name */
6814312Ssam 	.set	rt_name,-20-FNSIZ	/* rad50 file name */
6914312Ssam /* reboot flags for boot */
7014312Ssam 	.set	RB_ASK,3		/* ask name and come up single user */
7111099Ssam 
7213194Shelge /*
7313194Shelge  * Initialization.
7413194Shelge  */
7511099Ssam init:
7611099Ssam 	.word	0 		/* entry mask for dec monitor */
7711099Ssam 	nop;nop;nop;nop;nop	/* some no-ops for 750 boot rom to skip */
7811099Ssam 	nop;nop;nop;nop;nop
7911099Ssam 	movl	$RELOC,fp	/* core loc to which to move this program */
8013210Shelge 	addl3	$rt_name,fp,sp	/* set stack pointer; leave room for locals */
8111099Ssam 	clrl	r0
8211099Ssam 1:
8311099Ssam 	movc3	$end,(r0),(fp)	/* move boot up to relocated position */
8411099Ssam 	jmp	start+RELOC
8511099Ssam 
8611099Ssam start:
8711099Ssam 	mtpr	$TU_BREAK,$CSTS		/* set break condition */
8813194Shelge 	clrl	r2			/* nulls */
8913194Shelge 	bsbw	xmit2			/* wait 2 character times */
9013194Shelge 	mfpr	$CSRD,r2		/* clear receive buffer */
9111099Ssam 	movzwl	$TU_INIT|(TU_INIT<<8),r2	/* load 2 INIT opcodes */
9213194Shelge 	bsbw	xmit2			/* xmit 'em */
9311099Ssam 1:
9413194Shelge 	mfpr	$CSRD,r7		/* get recv data */
9511099Ssam 	cmpb	r7,$TU_CONTINUE		/* is it a continue flag? */
9613194Shelge 	bneq	1b			/* nope, look more */
9711099Ssam 
9813210Shelge 	movab	name(fp),r4		/* start of filename storage */
9913210Shelge 	clrq	(r4)			/* init name field */
10013210Shelge 	clrq	name+8(fp)
10113194Shelge 	clrq	rt_name(fp)		/* init rad50 filename */
10211099Ssam 	movzbl	$'=,r0			/* prompt character */
10311099Ssam 	bsbw	putc			/* output char to main console */
10411099Ssam 
10513210Shelge /*
10613210Shelge  * Read in a file name from console.
10713210Shelge  */
10811099Ssam 	movl	r4,r1			/* loc at which to store file name */
10911099Ssam nxtc:
11011099Ssam 	bsbw	getc			/* get input char's in file name */
11111099Ssam 	cmpb	r0,$012			/* terminator ? */
11211099Ssam 	beql	nullc
11311099Ssam 	movb	r0,(r1)+
11411099Ssam 	brb	nxtc
11511099Ssam nullc:
11613210Shelge 	cmpl	r4,r1
11713194Shelge 	beql	start			/* restart if empty string */
11813194Shelge 	clrb	(r1)			/* add null byte at end */
11911099Ssam 
12013194Shelge /*
12113210Shelge  * User-specified filename has been stored at name(fp),
12213210Shelge  * read the entire directory contents into low core.
12313194Shelge  */
12411099Ssam dirred:
12513194Shelge 	movl	$DIRBLK,r10		/* directory starts at block DIRBLK */
12611099Ssam 	movl	$(NUMDIR*BLKSIZ),r6	/* no. bytes in total dir */
12713194Shelge 	clrl	r11			/* start address */
12811099Ssam 	bsbw	taper			/* read no. bytes indicated */
12913194Shelge /*
13013194Shelge  * Read in the character conversion table which reside in block 1
13113210Shelge  * (the second block) on the cassette. Place it after the directory
13213210Shelge  * on low core (from 0x400).
13313194Shelge  */
13413210Shelge 	movl	$1,r10			/* block number */
13513194Shelge 	movl	$BLKSIZ,r6		/* read one block */
13613194Shelge 	bsbw	taper
13711099Ssam 
13813194Shelge /*
13913194Shelge  * Convert the ascii filename to rad50.
14013210Shelge  * R4 still points to name(fp)
14113194Shelge  */
14213194Shelge 	movl	$6,r3			/* max length of filename */
14313194Shelge 1:
14413194Shelge 	cmpb	$'.,(r4)+		/* look for '.' */
14513210Shelge 	beql	1f
14613194Shelge 	sobgtr	r3,1b
14713210Shelge 	incl	r4			/* point past '.' if ext is present */
14813210Shelge 1:
14913194Shelge 	clrb	-1(r4)			/* end name with null */
15013194Shelge 	movl	$3,r3			/* max length of extension */
15113194Shelge 	movab	ext(fp),r5		/* place extension here */
15213194Shelge 1:
15313194Shelge 	movb	(r4)+,(r5)+
15413194Shelge 	beql	1f			/* the string is null terminated */
15513194Shelge 	sobgtr	r3,1b
15613194Shelge 1:
15713194Shelge 	movab	name(fp),r4
15813194Shelge 	movab	rt_name(fp),r5		/* ptr to rad50 name */
15913194Shelge 	bsbw	rad50			/* convert filename */
16013194Shelge 	movab	ext(fp),r4
16113194Shelge 	movab	rt_name+4(fp),r5
16213194Shelge 	bsbw	rad50			/* convert extension */
16313194Shelge 
16413194Shelge /*
16513194Shelge  * Search entire directory for user-specified file name.
16613194Shelge  */
16713194Shelge 
16813194Shelge 	movab	rt_name(fp),r4		/* search for this file */
16913210Shelge 	movl	$10,r5			/* point to first file entry */
17013210Shelge 	movzwl	-2(r5),r10		/* r10 = block # where files begin */
17113194Shelge 2:
17213194Shelge 	cmpc3	$6,NAME(r5),(r4)	/* see if dir entry matches filename */
17311099Ssam 	beql	fndfil			/* found match */
17413194Shelge 1:
17513210Shelge 	addw2	FILSIZ(r5),r10		/* add file length to block pointer */
17613194Shelge 	addl2	$ENTSIZ,r5		/* move to next entry */
17713210Shelge #	cpmb	STATUS(r5),$RT_NULL	/* check if deleted file */
17813210Shelge #	beql	1b /* not really necessary since deleted entries will fail */
17913210Shelge 		   /* to compare anyway */
18013210Shelge 	cmpb	STATUS(r5),$RT_ESEG	/* check if end of segment */
18113194Shelge 	bneq	2b
18211099Ssam 	brw	start			/* entry not in directory; start over */
18311099Ssam 
18413194Shelge /*
18513194Shelge  * Found desired directory entry
18613194Shelge  */
18711099Ssam fndfil:
18813210Shelge 					/* start block no., 2 bytes in r10 */
18913194Shelge 	movzwl	FILSIZ(r5),r6		/* file size (blocks) */
19013194Shelge 	mull2	$BLKSIZ,r6		/* file size (bytes) */
19113210Shelge 	cmpl	r6,$RELOC-512		/* check if file fits below stack */
19213210Shelge 	blss	filok
19313210Shelge 	brw	start			/* file too large */
19411099Ssam 
19513194Shelge /*
19613194Shelge  * Read in desired file from tape.
19713194Shelge  */
19811099Ssam filok:
19911099Ssam 	movl	r6,r5			/* start of bss space */
20013194Shelge 	clrl	r11			/* start address */
20111099Ssam 	bsbb	taper
20211099Ssam 
20313194Shelge /*
20413194Shelge  * Clear core.
20513194Shelge  */
20611099Ssam 	subl3	r5,$RELOC-4,r0		/* no. bytes to clear */
20711099Ssam 1:
20811099Ssam 	clrb	(r5)+
20911099Ssam 	sobgtr	r0,1b
21011099Ssam 
21113194Shelge /*
21213194Shelge  * Jump to start of file & execute.
21313194Shelge  */
21413210Shelge 	addl3	$20,fp,ap		/* ?? */
21511099Ssam 	clrl	r5
21614312Ssam 	movl	$RB_ASK,r11
21711099Ssam 	calls	$0,(r5)
21811099Ssam bad:
21911099Ssam 	brw	start
22011099Ssam 
22113210Shelge /*
22213210Shelge  * Read (r6) bytes from block (r10)
22313210Shelge  * into loc (r11).
22413210Shelge  */
22511099Ssam taper:
22613194Shelge 	clrl	r8			/* initialize checksum */
22713194Shelge 	movab	readcom,r0		/* read command packet addr */
22811099Ssam 	movzbl	$TU_PACKETLEN/2,r1	/* size of readcom block */
22911099Ssam 1:
23013194Shelge 	movzwl	(r0)+,r2		/* get 2 chars from block */
23113194Shelge 	bsbb	xmit			/* xmit and update ckecksum */
23213194Shelge 	sobgtr	r1,1b			/* loop if more */
23311099Ssam 
23413210Shelge /*
23513210Shelge  * Now do variable part of packet.
23613210Shelge  */
23713194Shelge 	movl	r6,r2			/* byte count */
23811099Ssam 	bsbb	xmit
23913194Shelge 	movl	r10,r2			/* starting block number */
24011099Ssam 	bsbb	xmit
24113194Shelge 	movzwl	r8,r2			/* accumulated ckecksum */
24211099Ssam 	bsbb	xmit
24311099Ssam 
24413210Shelge /*
24513210Shelge  * Collect read packet from device.
24613210Shelge  */
24711099Ssam 1:
24813194Shelge 	bsbb	recv2			/* get 2 packet characters */
24913194Shelge 	decb	r2			/* data packet? */
25013194Shelge 	bneq	1f			/* branch on end of data */
25113194Shelge 	movzbl	r1,r8			/* get byte count of packet */
25211099Ssam 
25313210Shelge /*
25413210Shelge  * Read data into memory.
25513210Shelge  */
25611099Ssam 2:
25713194Shelge 	bsbb	recv1			/* get a char */
25813210Shelge 	movb	r1,(r11)+		/* stuff into memory */
25913194Shelge 	sobgtr	r8,2b			/* loop if more */
26013194Shelge 	bsbb	recv2			/* skip checksum */
26113194Shelge 	brb	1b			/* read next packet */
26211099Ssam 
26313210Shelge /*
26413210Shelge  * End of data xfer; check for errors.
26513210Shelge  */
26611099Ssam 1:
26713194Shelge 	bsbb	recv2			/* get success code */
26813194Shelge 	tstl	r1			/* error in read? */
26913194Shelge 	blss	9f			/* branch if status error */
27011099Ssam 	movl	$5,r0
27111099Ssam 1:
27213194Shelge 	bsbb	recv2			/* discard 10 bytes */
27311099Ssam 	sobgtr	r0,1b
27411099Ssam 	rsb
27511099Ssam 
27613210Shelge /* Fatal error */
27711099Ssam 9:
27811099Ssam 	movab	ermsg,r1
27911099Ssam 1:
28011099Ssam 	movb	(r1)+,r0
28111099Ssam 	beql	bad
28211099Ssam 	bsbb	putc
28311099Ssam 	brb	1b
28411099Ssam 
28513210Shelge /*
28613210Shelge  * Update checksum in r8 and xmit 2 characters.
28713210Shelge  */
28811099Ssam xmit:
28913194Shelge 	addw2	r2,r8			/* update checksum */
29013210Shelge 	adwc	$0,r8			/* add  in carry */
29111099Ssam 
29213210Shelge /* send the 2 characters contained in r2 */
29311099Ssam xmit2:
29413194Shelge 	bsbb	1f			/* xmit one of 'em */
29513194Shelge 	ashl	$-8,r2,r2		/* get next char */
29613194Shelge 					/* fall into... */
29711099Ssam 1:
29813194Shelge 	mfpr	$CSTS,r7		/* get xmit status */
29913194Shelge 	bbc	$TU_READY,r7,1b		/* loop until ready */
30013194Shelge 	mtpr	r2,$CSTD		/* send char */
30111099Ssam 	rsb
30211099Ssam 
30313210Shelge /*
30413210Shelge  * Receive 2 characters, return in r2 and r1.
30513210Shelge  */
30611099Ssam recv2:
30713194Shelge 	bsbb	recv1			/* recv one of 'em */
30813194Shelge 					/* fall into... */
30911099Ssam 
31013210Shelge /*
31113210Shelge  * Receive 1 character.
31213210Shelge  */
31311099Ssam recv1:
31413194Shelge 	movzbl	r1,r2			/* save previous byte */
31511099Ssam 1:
31613194Shelge 	mfpr	$CSRS,r7		/* get recv status */
31713194Shelge 	bbc	$TU_READY,r7,1b		/* loop until ready */
31813194Shelge 	mfpr	$CSRD,r1		/* get char */
31913237Shelge 	blss	9b			/* branch on recv error */
32011099Ssam 	rsb
32111099Ssam 
32211099Ssam getc:
32311099Ssam 	mfpr	$RXCS,r0
32411099Ssam 	bbc	$RXCS_pd,r0,getc	/* receiver ready ? */
32511099Ssam 	mfpr	$RXDB,r0
32613439Ssam 	extzv	$0,$7,r0,r0
32711099Ssam 	cmpb	r0,$015
32811099Ssam 	bneq	putc			/* echo and return */
32911099Ssam 	bsbb	putc			/* carriage return */
33013194Shelge #	movb	$0,r0
33113194Shelge #	bsbb	putc			/* delay */
33211099Ssam 	movb	$012,r0			/* send line feed and return */
33311099Ssam putc:
33411099Ssam 	mfpr	$TXCS,r2
33511099Ssam 	bbc	$TXCS_pr,r2,putc	/* transmitter ready ? */
33611099Ssam 	mtpr	r0,$TXDB
33711099Ssam 	rsb
33811099Ssam 
33913194Shelge /*
34013194Shelge  * Convert the filename given from the console
34113194Shelge  * to radix 50 (rt-11) format.
34213194Shelge  */
34313194Shelge rad50:
34413210Shelge 	clrw	r1
34513194Shelge 	bsbb	getb50			/* get next ascii byte, exit if null */
34613194Shelge 	mull3	$03100,r0,r1
34713194Shelge 	bsbb	getb50
34813194Shelge 	mull3	$050,r0,r2
34913194Shelge 	addl2	r2,r1
35013194Shelge 	bsbb	getb50
35113194Shelge 	addl2	r0,r1			/* last byte, just add it in */
35213194Shelge 	movw	r1,(r5)+		/* save result */
35313210Shelge 	brb	rad50
35413194Shelge 
35513194Shelge getb50:
35613194Shelge 	movzbl	(r4)+,r0		/* get next ascii byte */
35713194Shelge 	beql	1f			/* if zero: end of string */
35813210Shelge 	movzbl	CTABLE(r0),r0		/* and get the r50 byte from the table*/
35913194Shelge 	rsb
36013194Shelge 1:
36113194Shelge 	tstl	(sp)+			/* we're through, get back to where */
36213194Shelge 					/* rad50 was called */
36313194Shelge 	movw	r1,(r5)			/* but first save the result */
36413194Shelge 	rsb
36513194Shelge 
36611099Ssam 	.align	2
36711099Ssam readcom:
36813194Shelge 	.byte	2			/* command packet flag */
36913194Shelge 	.byte	10			/* number of bytes in message */
37013194Shelge 	.byte	2			/* tu read opcode */
37113194Shelge 	.byte	0			/* modifier */
37213194Shelge 	.byte	0			/* unit number */
37313194Shelge 	.byte	0			/* switches */
37413194Shelge 	.word	0			/* sequence number */
37513194Shelge 					/* byte count and block number follow */
37611099Ssam 
37711099Ssam ermsg:
37814312Ssam 	.asciz	"tuerr\r\n"
37911099Ssam end:
38013237Shelge 
38113237Shelge /*
38213237Shelge  * Ascii to rad 50 conversion table,
38313237Shelge  * stored on the second block on the cassette
38413237Shelge  *
38513237Shelge  * NOTE: Always make sure this table ends up
38613237Shelge  * starting at byte 512!!!!
38713237Shelge  */
38813237Shelge 	.align	2
38913237Shelge 	.data	2
39013237Shelge 	.long	0x1d1d1d1d
39113237Shelge 	.long	0x1d1d1d1d
39213237Shelge 	.long	0x1d1d1d1d
39313237Shelge 	.long	0x1d1d1d1d
39413237Shelge 	.long	0x1d1d1d1d
39513237Shelge 	.long	0x1d1d1d1d
39613237Shelge 	.long	0x1d1d1d1d
39713237Shelge 	.long	0x1d1d1d1d
39813237Shelge 	.long	0x1d1d1d00
39913237Shelge 	.long	0x1d1d1d1b
40013237Shelge 	.long	0x1d1d1d1d
40113237Shelge 	.long	0x1d1c1d1d
40213237Shelge 	.long	0x21201f1e
40313237Shelge 	.long	0x25242322
40413237Shelge 	.long	0x1d1d2726
40513237Shelge 	.long	0x1d1d1d1d
40613237Shelge 	.long	0x302011d
40713237Shelge 	.long	0x7060504
40813237Shelge 	.long	0xb0a0908
40913237Shelge 	.long	0xf0e0d0c
41013237Shelge 	.long	0x13121110
41113237Shelge 	.long	0x17161514
41213237Shelge 	.long	0x1d1a1918
41313237Shelge 	.long	0x1d1d1d1d
41413237Shelge 	.long	0x302011d
41513237Shelge 	.long	0x7060504
41613237Shelge 	.long	0xb0a0908
41713237Shelge 	.long	0xf0e0d0c
41813237Shelge 	.long	0x13121110
41913237Shelge 	.long	0x17161514
42013237Shelge 	.long	0x1d1a1918
42113237Shelge 	.long	0x1d1d1d1d
42213237Shelge 	.long	0x1d1d1d1d
42313237Shelge 	.long	0x1d1d1d1d
42413237Shelge 	.long	0x1d1d1d1d
42513237Shelge 	.long	0x1d1d1d1d
42613237Shelge 	.long	0x1d1d1d1d
42713237Shelge 	.long	0x1d1d1d1d
42813237Shelge 	.long	0x1d1d1d1d
42913237Shelge 	.long	0x1d1d1d1d
43013237Shelge 	.long	0x1d1d1d00
43113237Shelge 	.long	0x1d1d1d1b
43213237Shelge 	.long	0x1d1d1d1d
43313237Shelge 	.long	0x1d1c1d1d
43413237Shelge 	.long	0x21201f1e
43513237Shelge 	.long	0x25242322
43613237Shelge 	.long	0x1d1d2726
43713237Shelge 	.long	0x1d1d1d1d
43813237Shelge 	.long	0x302011d
43913237Shelge 	.long	0x7060504
44013237Shelge 	.long	0xb0a0908
44113237Shelge 	.long	0xf0e0d0c
44213237Shelge 	.long	0x13121110
44313237Shelge 	.long	0x17161514
44413237Shelge 	.long	0x1d1a1918
44513237Shelge 	.long	0x1d1d1d1d
44613237Shelge 	.long	0x302011d
44713237Shelge 	.long	0x7060504
44813237Shelge 	.long	0xb0a0908
44913237Shelge 	.long	0xf0e0d0c
45013237Shelge 	.long	0x13121110
45113237Shelge 	.long	0x17161514
45213237Shelge 	.long	0x1d1a1918
45313237Shelge 	.long	0x1d1d1d
45413237Shelge 	.data
455