xref: /csrg-svn/sys/vax/mdec/tuboot.c (revision 13210)
1*13210Shelge /*	tuboot.c	4.3	83/06/19	*/
211099Ssam 
311099Ssam /*
411099Ssam  * VAX tu58 console cassette boot block
511099Ssam  *
6*13210Shelge  * Helge Skrivervik CSRG/UCB 18jun83
711099Ssam  *
8*13210Shelge  * Reads a program from a rt-11 directory on tape
9*13210Shelge  * 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''.
13*13210Shelge  * Error checking and recovery is almost nonexistant
14*13210Shelge  * due to the severe space constraints.
15*13210Shelge  *
16*13210Shelge  * NOTE: Any changes to this program are likely to
17*13210Shelge  *	 bring the size over 512 bytes ....
18*13210Shelge  *
19*13210Shelge  * Based on tp format bootstrap originally written by Thomas Ferrin.
20*13210Shelge  *
2111099Ssam  */
22*13210Shelge 	.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 */
30*13210Shelge 	.set	FNSIZ,8		/* size of rad50 filename + 2 */
3113194Shelge 	.set	NAME,2		/* direc entry offset for filename */
32*13210Shelge 	.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 */
60*13210Shelge 	.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 */
70*13210Shelge 	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 
88*13210Shelge 	movab	name(fp),r4		/* start of filename storage */
89*13210Shelge 	clrq	(r4)			/* init name field */
90*13210Shelge 	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 
95*13210Shelge /*
96*13210Shelge  * Read in a file name from console.
97*13210Shelge  */
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:
106*13210Shelge 	cmpl	r4,r1
10713194Shelge 	beql	start			/* restart if empty string */
10813194Shelge 	clrb	(r1)			/* add null byte at end */
10911099Ssam 
11013194Shelge /*
111*13210Shelge  * User-specified filename has been stored at name(fp),
112*13210Shelge  * 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
121*13210Shelge  * (the second block) on the cassette. Place it after the directory
122*13210Shelge  * on low core (from 0x400).
12313194Shelge  */
124*13210Shelge 	movl	$1,r10			/* block number */
12513194Shelge 	movl	$BLKSIZ,r6		/* read one block */
12613194Shelge 	bsbw	taper
12711099Ssam 
12813194Shelge /*
12913194Shelge  * Convert the ascii filename to rad50.
130*13210Shelge  * R4 still points to name(fp)
13113194Shelge  */
13213194Shelge 	movl	$6,r3			/* max length of filename */
13313194Shelge 1:
13413194Shelge 	cmpb	$'.,(r4)+		/* look for '.' */
135*13210Shelge 	beql	1f
13613194Shelge 	sobgtr	r3,1b
137*13210Shelge 	incl	r4			/* point past '.' if ext is present */
138*13210Shelge 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 */
159*13210Shelge 	movl	$10,r5			/* point to first file entry */
160*13210Shelge 	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:
165*13210Shelge 	addw2	FILSIZ(r5),r10		/* add file length to block pointer */
16613194Shelge 	addl2	$ENTSIZ,r5		/* move to next entry */
167*13210Shelge #	cpmb	STATUS(r5),$RT_NULL	/* check if deleted file */
168*13210Shelge #	beql	1b /* not really necessary since deleted entries will fail */
169*13210Shelge 		   /* to compare anyway */
170*13210Shelge 	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:
178*13210Shelge 					/* start block no., 2 bytes in r10 */
17913194Shelge 	movzwl	FILSIZ(r5),r6		/* file size (blocks) */
18013194Shelge 	mull2	$BLKSIZ,r6		/* file size (bytes) */
181*13210Shelge 	cmpl	r6,$RELOC-512		/* check if file fits below stack */
182*13210Shelge 	blss	filok
183*13210Shelge 	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  */
204*13210Shelge 	addl3	$20,fp,ap		/* ?? */
20511099Ssam 	clrl	r5
20611099Ssam 	calls	$0,(r5)
20711099Ssam bad:
20811099Ssam 	brw	start
20911099Ssam 
210*13210Shelge /*
211*13210Shelge  * Read (r6) bytes from block (r10)
212*13210Shelge  * into loc (r11).
213*13210Shelge  */
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 
223*13210Shelge /*
224*13210Shelge  * Now do variable part of packet.
225*13210Shelge  */
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 
233*13210Shelge /*
234*13210Shelge  * Collect read packet from device.
235*13210Shelge  */
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 
242*13210Shelge /*
243*13210Shelge  * Read data into memory.
244*13210Shelge  */
24511099Ssam 2:
24613194Shelge 	bsbb	recv1			/* get a char */
247*13210Shelge 	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 
252*13210Shelge /*
253*13210Shelge  * End of data xfer; check for errors.
254*13210Shelge  */
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 
265*13210Shelge /* Fatal error */
26611099Ssam 9:
26711099Ssam 	movab	ermsg,r1
26811099Ssam 1:
26911099Ssam 	movb	(r1)+,r0
27011099Ssam 	beql	bad
27111099Ssam 	bsbb	putc
27211099Ssam 	brb	1b
27311099Ssam 
274*13210Shelge /*
275*13210Shelge  * Update checksum in r8 and xmit 2 characters.
276*13210Shelge  */
27711099Ssam xmit:
27813194Shelge 	addw2	r2,r8			/* update checksum */
279*13210Shelge 	adwc	$0,r8			/* add  in carry */
28011099Ssam 
281*13210Shelge /* 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 
292*13210Shelge /*
293*13210Shelge  * Receive 2 characters, return in r2 and r1.
294*13210Shelge  */
29511099Ssam recv2:
29613194Shelge 	bsbb	recv1			/* recv one of 'em */
29713194Shelge 					/* fall into... */
29811099Ssam 
299*13210Shelge /*
300*13210Shelge  * Receive 1 character.
301*13210Shelge  */
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 */
30813194Shelge #	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
31513194Shelge 	movzbl	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:
333*13210Shelge 	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 */
342*13210Shelge 	brb	rad50
34313194Shelge 
34413194Shelge getb50:
34513194Shelge 	movzbl	(r4)+,r0		/* get next ascii byte */
34613194Shelge 	beql	1f			/* if zero: end of string */
347*13210Shelge 	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:
367*13210Shelge 	.asciz	"tu err\r\n"
36811099Ssam end:
369