xref: /csrg-svn/sys/vax/mdec/tuboot.c (revision 13237)
1*13237Shelge /*	tuboot.c	4.4	83/06/22	*/
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 */
308*13237Shelge 	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:
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:
369*13237Shelge 
370*13237Shelge /*
371*13237Shelge  * Ascii to rad 50 conversion table,
372*13237Shelge  * stored on the second block on the cassette
373*13237Shelge  *
374*13237Shelge  * NOTE: Always make sure this table ends up
375*13237Shelge  * starting at byte 512!!!!
376*13237Shelge  */
377*13237Shelge 	.align	2
378*13237Shelge 	.data	2
379*13237Shelge 	.long	0x1d1d1d1d
380*13237Shelge 	.long	0x1d1d1d1d
381*13237Shelge 	.long	0x1d1d1d1d
382*13237Shelge 	.long	0x1d1d1d1d
383*13237Shelge 	.long	0x1d1d1d1d
384*13237Shelge 	.long	0x1d1d1d1d
385*13237Shelge 	.long	0x1d1d1d1d
386*13237Shelge 	.long	0x1d1d1d1d
387*13237Shelge 	.long	0x1d1d1d00
388*13237Shelge 	.long	0x1d1d1d1b
389*13237Shelge 	.long	0x1d1d1d1d
390*13237Shelge 	.long	0x1d1c1d1d
391*13237Shelge 	.long	0x21201f1e
392*13237Shelge 	.long	0x25242322
393*13237Shelge 	.long	0x1d1d2726
394*13237Shelge 	.long	0x1d1d1d1d
395*13237Shelge 	.long	0x302011d
396*13237Shelge 	.long	0x7060504
397*13237Shelge 	.long	0xb0a0908
398*13237Shelge 	.long	0xf0e0d0c
399*13237Shelge 	.long	0x13121110
400*13237Shelge 	.long	0x17161514
401*13237Shelge 	.long	0x1d1a1918
402*13237Shelge 	.long	0x1d1d1d1d
403*13237Shelge 	.long	0x302011d
404*13237Shelge 	.long	0x7060504
405*13237Shelge 	.long	0xb0a0908
406*13237Shelge 	.long	0xf0e0d0c
407*13237Shelge 	.long	0x13121110
408*13237Shelge 	.long	0x17161514
409*13237Shelge 	.long	0x1d1a1918
410*13237Shelge 	.long	0x1d1d1d1d
411*13237Shelge 	.long	0x1d1d1d1d
412*13237Shelge 	.long	0x1d1d1d1d
413*13237Shelge 	.long	0x1d1d1d1d
414*13237Shelge 	.long	0x1d1d1d1d
415*13237Shelge 	.long	0x1d1d1d1d
416*13237Shelge 	.long	0x1d1d1d1d
417*13237Shelge 	.long	0x1d1d1d1d
418*13237Shelge 	.long	0x1d1d1d1d
419*13237Shelge 	.long	0x1d1d1d00
420*13237Shelge 	.long	0x1d1d1d1b
421*13237Shelge 	.long	0x1d1d1d1d
422*13237Shelge 	.long	0x1d1c1d1d
423*13237Shelge 	.long	0x21201f1e
424*13237Shelge 	.long	0x25242322
425*13237Shelge 	.long	0x1d1d2726
426*13237Shelge 	.long	0x1d1d1d1d
427*13237Shelge 	.long	0x302011d
428*13237Shelge 	.long	0x7060504
429*13237Shelge 	.long	0xb0a0908
430*13237Shelge 	.long	0xf0e0d0c
431*13237Shelge 	.long	0x13121110
432*13237Shelge 	.long	0x17161514
433*13237Shelge 	.long	0x1d1a1918
434*13237Shelge 	.long	0x1d1d1d1d
435*13237Shelge 	.long	0x302011d
436*13237Shelge 	.long	0x7060504
437*13237Shelge 	.long	0xb0a0908
438*13237Shelge 	.long	0xf0e0d0c
439*13237Shelge 	.long	0x13121110
440*13237Shelge 	.long	0x17161514
441*13237Shelge 	.long	0x1d1a1918
442*13237Shelge 	.long	0x1d1d1d
443*13237Shelge 	.data
444