xref: /csrg-svn/sys/vax/mdec/tuboot.c (revision 13439)
1*13439Ssam /*	tuboot.c	4.5	83/06/29	*/
211099Ssam 
311099Ssam /*
411099Ssam  * VAX tu58 console cassette boot block
511099Ssam  *
613210Shelge  * Helge Skrivervik CSRG/UCB 18jun83
711099Ssam  *
813210Shelge  * Reads a program from a rt-11 directory on tape
913210Shelge  * and executes it.  Programs must be stripped of
1011099Ssam  * the header and is loaded ``bits as is''.
1111099Ssam  * You can return to this loader via ``ret'' as
1211099Ssam  * you are called ``calls $0,ent''.
1313210Shelge  * Error checking and recovery is almost nonexistant
1413210Shelge  * due to the severe space constraints.
1513210Shelge  *
1613210Shelge  * NOTE: Any changes to this program are likely to
1713210Shelge  *	 bring the size over 512 bytes ....
1813210Shelge  *
1913210Shelge  * Based on tp format bootstrap originally written by Thomas Ferrin.
2013210Shelge  *
2111099Ssam  */
2213210Shelge 	.set	CTABLE,0x400	/* where to load the rad50 cnv table */
2311099Ssam 	.set	RELOC,0x70000
2413194Shelge /* rt-11 directory definitions */
2513194Shelge 	.set	DIRBLK,6	/* rt-11 directory starts at block 6 */
2613194Shelge 	.set	FILSIZ,8	/* rt-11 direc entry offset for file size */
2713194Shelge 	.set	ENTSIZ,14	/* size of 1 rt-11 dir entry, bytes */
2811099Ssam 	.set	BLKSIZ,512	/* tape block size, bytes */
2913194Shelge 	.set	NUMDIR,2	/* no. of dir blocks on tape */
3013210Shelge 	.set	FNSIZ,8		/* size of rad50 filename + 2 */
3113194Shelge 	.set	NAME,2		/* direc entry offset for filename */
3213210Shelge 	.set	STATUS,1	/* direc entry offset for entry status */
3313194Shelge /* rt-11 directory entry status */
3413194Shelge 	.set	RT_ESEG,8	/* end of directory segment */
3513194Shelge 	.set	RT_NULL,2	/* empty entry */
3613194Shelge 	.set	RT_FILE,4	/* valid file entry */
3711099Ssam /* processor registers and bits */
3811099Ssam 	.set	RXCS,32
3911099Ssam 	.set	RXDB,33
4011099Ssam 	.set	TXCS,34
4111099Ssam 	.set	TXDB,35
4211099Ssam 	.set	RXCS_DONE,0x80
4311099Ssam 	.set	TXCS_RDY,0x80
4411099Ssam 	.set	TXCS_pr,7	/* bit position of TXCS ready bit */
4511099Ssam 	.set	RXCS_pd,7	/* bit position of RXCS done bit */
4611099Ssam /* console storage registers and bits */
4711099Ssam 	.set	CSRS,0x1c
4811099Ssam 	.set	CSRD,0x1d
4911099Ssam 	.set	CSTS,0x1e
5011099Ssam 	.set	CSTD,0x1f
5111099Ssam /* TU commands and bits */
5211099Ssam 	.set	TU_BREAK,1
5311099Ssam 	.set	TU_INIT,4
5411099Ssam 	.set	TU_CONTINUE,16
5511099Ssam 	.set	TU_READY,7	/* bit position of CSRS ready bit */
5611099Ssam 	.set	TU_PACKETLEN,8	/* length of readcom block */
5711099Ssam /* local stack variables */
5813194Shelge 	.set	ext,-4				/* file ext. */
5913194Shelge 	.set	name,-20			/* 12 bytes for full name */
6013210Shelge 	.set	rt_name,-20-FNSIZ		/* rad50 file name */
6111099Ssam 
6213194Shelge /*
6313194Shelge  * Initialization.
6413194Shelge  */
6511099Ssam init:
6611099Ssam 	.word	0 		/* entry mask for dec monitor */
6711099Ssam 	nop;nop;nop;nop;nop	/* some no-ops for 750 boot rom to skip */
6811099Ssam 	nop;nop;nop;nop;nop
6911099Ssam 	movl	$RELOC,fp	/* core loc to which to move this program */
7013210Shelge 	addl3	$rt_name,fp,sp	/* set stack pointer; leave room for locals */
7111099Ssam 	clrl	r0
7211099Ssam 1:
7311099Ssam 	movc3	$end,(r0),(fp)	/* move boot up to relocated position */
7411099Ssam 	jmp	start+RELOC
7511099Ssam 
7611099Ssam start:
7711099Ssam 	mtpr	$TU_BREAK,$CSTS		/* set break condition */
7813194Shelge 	clrl	r2			/* nulls */
7913194Shelge 	bsbw	xmit2			/* wait 2 character times */
8013194Shelge 	mfpr	$CSRD,r2		/* clear receive buffer */
8111099Ssam 	movzwl	$TU_INIT|(TU_INIT<<8),r2	/* load 2 INIT opcodes */
8213194Shelge 	bsbw	xmit2			/* xmit 'em */
8311099Ssam 1:
8413194Shelge 	mfpr	$CSRD,r7		/* get recv data */
8511099Ssam 	cmpb	r7,$TU_CONTINUE		/* is it a continue flag? */
8613194Shelge 	bneq	1b			/* nope, look more */
8711099Ssam 
8813210Shelge 	movab	name(fp),r4		/* start of filename storage */
8913210Shelge 	clrq	(r4)			/* init name field */
9013210Shelge 	clrq	name+8(fp)
9113194Shelge 	clrq	rt_name(fp)		/* init rad50 filename */
9211099Ssam 	movzbl	$'=,r0			/* prompt character */
9311099Ssam 	bsbw	putc			/* output char to main console */
9411099Ssam 
9513210Shelge /*
9613210Shelge  * Read in a file name from console.
9713210Shelge  */
9811099Ssam 	movl	r4,r1			/* loc at which to store file name */
9911099Ssam nxtc:
10011099Ssam 	bsbw	getc			/* get input char's in file name */
10111099Ssam 	cmpb	r0,$012			/* terminator ? */
10211099Ssam 	beql	nullc
10311099Ssam 	movb	r0,(r1)+
10411099Ssam 	brb	nxtc
10511099Ssam nullc:
10613210Shelge 	cmpl	r4,r1
10713194Shelge 	beql	start			/* restart if empty string */
10813194Shelge 	clrb	(r1)			/* add null byte at end */
10911099Ssam 
11013194Shelge /*
11113210Shelge  * User-specified filename has been stored at name(fp),
11213210Shelge  * read the entire directory contents into low core.
11313194Shelge  */
11411099Ssam dirred:
11513194Shelge 	movl	$DIRBLK,r10		/* directory starts at block DIRBLK */
11611099Ssam 	movl	$(NUMDIR*BLKSIZ),r6	/* no. bytes in total dir */
11713194Shelge 	clrl	r11			/* start address */
11811099Ssam 	bsbw	taper			/* read no. bytes indicated */
11913194Shelge /*
12013194Shelge  * Read in the character conversion table which reside in block 1
12113210Shelge  * (the second block) on the cassette. Place it after the directory
12213210Shelge  * on low core (from 0x400).
12313194Shelge  */
12413210Shelge 	movl	$1,r10			/* block number */
12513194Shelge 	movl	$BLKSIZ,r6		/* read one block */
12613194Shelge 	bsbw	taper
12711099Ssam 
12813194Shelge /*
12913194Shelge  * Convert the ascii filename to rad50.
13013210Shelge  * R4 still points to name(fp)
13113194Shelge  */
13213194Shelge 	movl	$6,r3			/* max length of filename */
13313194Shelge 1:
13413194Shelge 	cmpb	$'.,(r4)+		/* look for '.' */
13513210Shelge 	beql	1f
13613194Shelge 	sobgtr	r3,1b
13713210Shelge 	incl	r4			/* point past '.' if ext is present */
13813210Shelge 1:
13913194Shelge 	clrb	-1(r4)			/* end name with null */
14013194Shelge 	movl	$3,r3			/* max length of extension */
14113194Shelge 	movab	ext(fp),r5		/* place extension here */
14213194Shelge 1:
14313194Shelge 	movb	(r4)+,(r5)+
14413194Shelge 	beql	1f			/* the string is null terminated */
14513194Shelge 	sobgtr	r3,1b
14613194Shelge 1:
14713194Shelge 	movab	name(fp),r4
14813194Shelge 	movab	rt_name(fp),r5		/* ptr to rad50 name */
14913194Shelge 	bsbw	rad50			/* convert filename */
15013194Shelge 	movab	ext(fp),r4
15113194Shelge 	movab	rt_name+4(fp),r5
15213194Shelge 	bsbw	rad50			/* convert extension */
15313194Shelge 
15413194Shelge /*
15513194Shelge  * Search entire directory for user-specified file name.
15613194Shelge  */
15713194Shelge 
15813194Shelge 	movab	rt_name(fp),r4		/* search for this file */
15913210Shelge 	movl	$10,r5			/* point to first file entry */
16013210Shelge 	movzwl	-2(r5),r10		/* r10 = block # where files begin */
16113194Shelge 2:
16213194Shelge 	cmpc3	$6,NAME(r5),(r4)	/* see if dir entry matches filename */
16311099Ssam 	beql	fndfil			/* found match */
16413194Shelge 1:
16513210Shelge 	addw2	FILSIZ(r5),r10		/* add file length to block pointer */
16613194Shelge 	addl2	$ENTSIZ,r5		/* move to next entry */
16713210Shelge #	cpmb	STATUS(r5),$RT_NULL	/* check if deleted file */
16813210Shelge #	beql	1b /* not really necessary since deleted entries will fail */
16913210Shelge 		   /* to compare anyway */
17013210Shelge 	cmpb	STATUS(r5),$RT_ESEG	/* check if end of segment */
17113194Shelge 	bneq	2b
17211099Ssam 	brw	start			/* entry not in directory; start over */
17311099Ssam 
17413194Shelge /*
17513194Shelge  * Found desired directory entry
17613194Shelge  */
17711099Ssam fndfil:
17813210Shelge 					/* start block no., 2 bytes in r10 */
17913194Shelge 	movzwl	FILSIZ(r5),r6		/* file size (blocks) */
18013194Shelge 	mull2	$BLKSIZ,r6		/* file size (bytes) */
18113210Shelge 	cmpl	r6,$RELOC-512		/* check if file fits below stack */
18213210Shelge 	blss	filok
18313210Shelge 	brw	start			/* file too large */
18411099Ssam 
18513194Shelge /*
18613194Shelge  * Read in desired file from tape.
18713194Shelge  */
18811099Ssam filok:
18911099Ssam 	movl	r6,r5			/* start of bss space */
19013194Shelge 	clrl	r11			/* start address */
19111099Ssam 	bsbb	taper
19211099Ssam 
19313194Shelge /*
19413194Shelge  * Clear core.
19513194Shelge  */
19611099Ssam 	subl3	r5,$RELOC-4,r0		/* no. bytes to clear */
19711099Ssam 1:
19811099Ssam 	clrb	(r5)+
19911099Ssam 	sobgtr	r0,1b
20011099Ssam 
20113194Shelge /*
20213194Shelge  * Jump to start of file & execute.
20313194Shelge  */
20413210Shelge 	addl3	$20,fp,ap		/* ?? */
20511099Ssam 	clrl	r5
20611099Ssam 	calls	$0,(r5)
20711099Ssam bad:
20811099Ssam 	brw	start
20911099Ssam 
21013210Shelge /*
21113210Shelge  * Read (r6) bytes from block (r10)
21213210Shelge  * into loc (r11).
21313210Shelge  */
21411099Ssam taper:
21513194Shelge 	clrl	r8			/* initialize checksum */
21613194Shelge 	movab	readcom,r0		/* read command packet addr */
21711099Ssam 	movzbl	$TU_PACKETLEN/2,r1	/* size of readcom block */
21811099Ssam 1:
21913194Shelge 	movzwl	(r0)+,r2		/* get 2 chars from block */
22013194Shelge 	bsbb	xmit			/* xmit and update ckecksum */
22113194Shelge 	sobgtr	r1,1b			/* loop if more */
22211099Ssam 
22313210Shelge /*
22413210Shelge  * Now do variable part of packet.
22513210Shelge  */
22613194Shelge 	movl	r6,r2			/* byte count */
22711099Ssam 	bsbb	xmit
22813194Shelge 	movl	r10,r2			/* starting block number */
22911099Ssam 	bsbb	xmit
23013194Shelge 	movzwl	r8,r2			/* accumulated ckecksum */
23111099Ssam 	bsbb	xmit
23211099Ssam 
23313210Shelge /*
23413210Shelge  * Collect read packet from device.
23513210Shelge  */
23611099Ssam 1:
23713194Shelge 	bsbb	recv2			/* get 2 packet characters */
23813194Shelge 	decb	r2			/* data packet? */
23913194Shelge 	bneq	1f			/* branch on end of data */
24013194Shelge 	movzbl	r1,r8			/* get byte count of packet */
24111099Ssam 
24213210Shelge /*
24313210Shelge  * Read data into memory.
24413210Shelge  */
24511099Ssam 2:
24613194Shelge 	bsbb	recv1			/* get a char */
24713210Shelge 	movb	r1,(r11)+		/* stuff into memory */
24813194Shelge 	sobgtr	r8,2b			/* loop if more */
24913194Shelge 	bsbb	recv2			/* skip checksum */
25013194Shelge 	brb	1b			/* read next packet */
25111099Ssam 
25213210Shelge /*
25313210Shelge  * End of data xfer; check for errors.
25413210Shelge  */
25511099Ssam 1:
25613194Shelge 	bsbb	recv2			/* get success code */
25713194Shelge 	tstl	r1			/* error in read? */
25813194Shelge 	blss	9f			/* branch if status error */
25911099Ssam 	movl	$5,r0
26011099Ssam 1:
26113194Shelge 	bsbb	recv2			/* discard 10 bytes */
26211099Ssam 	sobgtr	r0,1b
26311099Ssam 	rsb
26411099Ssam 
26513210Shelge /* Fatal error */
26611099Ssam 9:
26711099Ssam 	movab	ermsg,r1
26811099Ssam 1:
26911099Ssam 	movb	(r1)+,r0
27011099Ssam 	beql	bad
27111099Ssam 	bsbb	putc
27211099Ssam 	brb	1b
27311099Ssam 
27413210Shelge /*
27513210Shelge  * Update checksum in r8 and xmit 2 characters.
27613210Shelge  */
27711099Ssam xmit:
27813194Shelge 	addw2	r2,r8			/* update checksum */
27913210Shelge 	adwc	$0,r8			/* add  in carry */
28011099Ssam 
28113210Shelge /* send the 2 characters contained in r2 */
28211099Ssam xmit2:
28313194Shelge 	bsbb	1f			/* xmit one of 'em */
28413194Shelge 	ashl	$-8,r2,r2		/* get next char */
28513194Shelge 					/* fall into... */
28611099Ssam 1:
28713194Shelge 	mfpr	$CSTS,r7		/* get xmit status */
28813194Shelge 	bbc	$TU_READY,r7,1b		/* loop until ready */
28913194Shelge 	mtpr	r2,$CSTD		/* send char */
29011099Ssam 	rsb
29111099Ssam 
29213210Shelge /*
29313210Shelge  * Receive 2 characters, return in r2 and r1.
29413210Shelge  */
29511099Ssam recv2:
29613194Shelge 	bsbb	recv1			/* recv one of 'em */
29713194Shelge 					/* fall into... */
29811099Ssam 
29913210Shelge /*
30013210Shelge  * Receive 1 character.
30113210Shelge  */
30211099Ssam recv1:
30313194Shelge 	movzbl	r1,r2			/* save previous byte */
30411099Ssam 1:
30513194Shelge 	mfpr	$CSRS,r7		/* get recv status */
30613194Shelge 	bbc	$TU_READY,r7,1b		/* loop until ready */
30713194Shelge 	mfpr	$CSRD,r1		/* get char */
30813237Shelge 	blss	9b			/* branch on recv error */
30911099Ssam 	rsb
31011099Ssam 
31111099Ssam getc:
31211099Ssam 	mfpr	$RXCS,r0
31311099Ssam 	bbc	$RXCS_pd,r0,getc	/* receiver ready ? */
31411099Ssam 	mfpr	$RXDB,r0
315*13439Ssam 	extzv	$0,$7,r0,r0
31611099Ssam 	cmpb	r0,$015
31711099Ssam 	bneq	putc			/* echo and return */
31811099Ssam 	bsbb	putc			/* carriage return */
31913194Shelge #	movb	$0,r0
32013194Shelge #	bsbb	putc			/* delay */
32111099Ssam 	movb	$012,r0			/* send line feed and return */
32211099Ssam putc:
32311099Ssam 	mfpr	$TXCS,r2
32411099Ssam 	bbc	$TXCS_pr,r2,putc	/* transmitter ready ? */
32511099Ssam 	mtpr	r0,$TXDB
32611099Ssam 	rsb
32711099Ssam 
32813194Shelge /*
32913194Shelge  * Convert the filename given from the console
33013194Shelge  * to radix 50 (rt-11) format.
33113194Shelge  */
33213194Shelge rad50:
33313210Shelge 	clrw	r1
33413194Shelge 	bsbb	getb50			/* get next ascii byte, exit if null */
33513194Shelge 	mull3	$03100,r0,r1
33613194Shelge 	bsbb	getb50
33713194Shelge 	mull3	$050,r0,r2
33813194Shelge 	addl2	r2,r1
33913194Shelge 	bsbb	getb50
34013194Shelge 	addl2	r0,r1			/* last byte, just add it in */
34113194Shelge 	movw	r1,(r5)+		/* save result */
34213210Shelge 	brb	rad50
34313194Shelge 
34413194Shelge getb50:
34513194Shelge 	movzbl	(r4)+,r0		/* get next ascii byte */
34613194Shelge 	beql	1f			/* if zero: end of string */
34713210Shelge 	movzbl	CTABLE(r0),r0		/* and get the r50 byte from the table*/
34813194Shelge 	rsb
34913194Shelge 1:
35013194Shelge 	tstl	(sp)+			/* we're through, get back to where */
35113194Shelge 					/* rad50 was called */
35213194Shelge 	movw	r1,(r5)			/* but first save the result */
35313194Shelge 	rsb
35413194Shelge 
35511099Ssam 	.align	2
35611099Ssam readcom:
35713194Shelge 	.byte	2			/* command packet flag */
35813194Shelge 	.byte	10			/* number of bytes in message */
35913194Shelge 	.byte	2			/* tu read opcode */
36013194Shelge 	.byte	0			/* modifier */
36113194Shelge 	.byte	0			/* unit number */
36213194Shelge 	.byte	0			/* switches */
36313194Shelge 	.word	0			/* sequence number */
36413194Shelge 					/* byte count and block number follow */
36511099Ssam 
36611099Ssam ermsg:
36713210Shelge 	.asciz	"tu err\r\n"
36811099Ssam end:
36913237Shelge 
37013237Shelge /*
37113237Shelge  * Ascii to rad 50 conversion table,
37213237Shelge  * stored on the second block on the cassette
37313237Shelge  *
37413237Shelge  * NOTE: Always make sure this table ends up
37513237Shelge  * starting at byte 512!!!!
37613237Shelge  */
37713237Shelge 	.align	2
37813237Shelge 	.data	2
37913237Shelge 	.long	0x1d1d1d1d
38013237Shelge 	.long	0x1d1d1d1d
38113237Shelge 	.long	0x1d1d1d1d
38213237Shelge 	.long	0x1d1d1d1d
38313237Shelge 	.long	0x1d1d1d1d
38413237Shelge 	.long	0x1d1d1d1d
38513237Shelge 	.long	0x1d1d1d1d
38613237Shelge 	.long	0x1d1d1d1d
38713237Shelge 	.long	0x1d1d1d00
38813237Shelge 	.long	0x1d1d1d1b
38913237Shelge 	.long	0x1d1d1d1d
39013237Shelge 	.long	0x1d1c1d1d
39113237Shelge 	.long	0x21201f1e
39213237Shelge 	.long	0x25242322
39313237Shelge 	.long	0x1d1d2726
39413237Shelge 	.long	0x1d1d1d1d
39513237Shelge 	.long	0x302011d
39613237Shelge 	.long	0x7060504
39713237Shelge 	.long	0xb0a0908
39813237Shelge 	.long	0xf0e0d0c
39913237Shelge 	.long	0x13121110
40013237Shelge 	.long	0x17161514
40113237Shelge 	.long	0x1d1a1918
40213237Shelge 	.long	0x1d1d1d1d
40313237Shelge 	.long	0x302011d
40413237Shelge 	.long	0x7060504
40513237Shelge 	.long	0xb0a0908
40613237Shelge 	.long	0xf0e0d0c
40713237Shelge 	.long	0x13121110
40813237Shelge 	.long	0x17161514
40913237Shelge 	.long	0x1d1a1918
41013237Shelge 	.long	0x1d1d1d1d
41113237Shelge 	.long	0x1d1d1d1d
41213237Shelge 	.long	0x1d1d1d1d
41313237Shelge 	.long	0x1d1d1d1d
41413237Shelge 	.long	0x1d1d1d1d
41513237Shelge 	.long	0x1d1d1d1d
41613237Shelge 	.long	0x1d1d1d1d
41713237Shelge 	.long	0x1d1d1d1d
41813237Shelge 	.long	0x1d1d1d1d
41913237Shelge 	.long	0x1d1d1d00
42013237Shelge 	.long	0x1d1d1d1b
42113237Shelge 	.long	0x1d1d1d1d
42213237Shelge 	.long	0x1d1c1d1d
42313237Shelge 	.long	0x21201f1e
42413237Shelge 	.long	0x25242322
42513237Shelge 	.long	0x1d1d2726
42613237Shelge 	.long	0x1d1d1d1d
42713237Shelge 	.long	0x302011d
42813237Shelge 	.long	0x7060504
42913237Shelge 	.long	0xb0a0908
43013237Shelge 	.long	0xf0e0d0c
43113237Shelge 	.long	0x13121110
43213237Shelge 	.long	0x17161514
43313237Shelge 	.long	0x1d1a1918
43413237Shelge 	.long	0x1d1d1d1d
43513237Shelge 	.long	0x302011d
43613237Shelge 	.long	0x7060504
43713237Shelge 	.long	0xb0a0908
43813237Shelge 	.long	0xf0e0d0c
43913237Shelge 	.long	0x13121110
44013237Shelge 	.long	0x17161514
44113237Shelge 	.long	0x1d1a1918
44213237Shelge 	.long	0x1d1d1d
44313237Shelge 	.data
444