xref: /csrg-svn/sys/vax/mdec/tuboot.c (revision 13194)
1*13194Shelge /*	tuboot.s	4.1	83/02/16	*/
211099Ssam 
311099Ssam /*
411099Ssam  * VAX tu58 console cassette boot block
511099Ssam  *
611099Ssam  * Thomas Ferrin  27oct82
711099Ssam  *
811099Ssam  * Reads a program from a tp directory on tape
911099Ssam  * and executes it.  Program 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*13194Shelge  *
14*13194Shelge  * Helge Skrivervik CSRG/UCB 18jun83
15*13194Shelge  * 	Changed to use rt-11 format directory & files
16*13194Shelge  *	instead of tp format
1711099Ssam  */
1811099Ssam 	.set	RELOC,0x70000
1911099Ssam /* a.out defines */
2011099Ssam 	.set	HDRSIZ,040	/* size of file header for VAX */
2111099Ssam 	.set	MAGIC,0410	/* file type id in header */
2211099Ssam 	.set	TSIZ,4		/* text size */
2311099Ssam 	.set	DSIZ,8		/* data size */
2411099Ssam 	.set	BSIZ,12		/* bss size */
2511099Ssam 	.set	TENT,024	/* task header entry loc */
26*13194Shelge /* rt-11 directory definitions */
27*13194Shelge 	.set	DIRBLK,6	/* rt-11 directory starts at block 6 */
28*13194Shelge 	.set	FILSIZ,8	/* rt-11 direc entry offset for file size */
29*13194Shelge 	.set	ENTSIZ,14	/* size of 1 rt-11 dir entry, bytes */
3011099Ssam 	.set	BLKSIZ,512	/* tape block size, bytes */
31*13194Shelge 	.set	NUMDIR,2	/* no. of dir blocks on tape */
32*13194Shelge 	.set	RT_FNSIZ,8	/* size of rad50 filename + 2 */
33*13194Shelge 	.set	NAME,2		/* direc entry offset for filename */
34*13194Shelge 	.set	RT_STAT,1	/* direc entry offset for entry status */
35*13194Shelge /* rt-11 directory entry status */
36*13194Shelge 	.set	RT_ESEG,8	/* end of directory segment */
37*13194Shelge 	.set	RT_NULL,2	/* empty entry */
38*13194Shelge 	.set	RT_FILE,4	/* valid file entry */
3911099Ssam /* processor registers and bits */
4011099Ssam 	.set	RXCS,32
4111099Ssam 	.set	RXDB,33
4211099Ssam 	.set	TXCS,34
4311099Ssam 	.set	TXDB,35
4411099Ssam 	.set	RXCS_DONE,0x80
4511099Ssam 	.set	TXCS_RDY,0x80
4611099Ssam 	.set	TXCS_pr,7	/* bit position of TXCS ready bit */
4711099Ssam 	.set	RXCS_pd,7	/* bit position of RXCS done bit */
4811099Ssam /* console storage registers and bits */
4911099Ssam 	.set	CSRS,0x1c
5011099Ssam 	.set	CSRD,0x1d
5111099Ssam 	.set	CSTS,0x1e
5211099Ssam 	.set	CSTD,0x1f
5311099Ssam /* TU commands and bits */
5411099Ssam 	.set	TU_BREAK,1
5511099Ssam 	.set	TU_INIT,4
5611099Ssam 	.set	TU_CONTINUE,16
5711099Ssam 	.set	TU_READY,7	/* bit position of CSRS ready bit */
5811099Ssam 	.set	TU_PACKETLEN,8	/* length of readcom block */
5911099Ssam /* local stack variables */
60*13194Shelge 	.set	ext,-4				/* file ext. */
61*13194Shelge 	.set	name,-20			/* 12 bytes for full name */
62*13194Shelge 	.set	rt_name,-20-RT_FNSIZ		/* rad50 file name */
6311099Ssam 
64*13194Shelge /*
65*13194Shelge  * Initialization.
66*13194Shelge  */
6711099Ssam init:
6811099Ssam 	.word	0 		/* entry mask for dec monitor */
6911099Ssam 	nop;nop;nop;nop;nop	/* some no-ops for 750 boot rom to skip */
7011099Ssam 	nop;nop;nop;nop;nop
7111099Ssam 	movl	$RELOC,fp	/* core loc to which to move this program */
7211099Ssam 	addl3	$name,fp,sp	/* set stack pointer; leave room for locals */
7311099Ssam 	clrl	r0
7411099Ssam 1:
7511099Ssam 	movc3	$end,(r0),(fp)	/* move boot up to relocated position */
7611099Ssam 	jmp	start+RELOC
7711099Ssam 
7811099Ssam start:
7911099Ssam /* init tu58 */
8011099Ssam 	mtpr	$TU_BREAK,$CSTS		/* set break condition */
81*13194Shelge 	clrl	r2			/* nulls */
82*13194Shelge 	bsbw	xmit2			/* wait 2 character times */
83*13194Shelge 	mfpr	$CSRD,r2		/* clear receive buffer */
8411099Ssam 	movzwl	$TU_INIT|(TU_INIT<<8),r2	/* load 2 INIT opcodes */
85*13194Shelge 	bsbw	xmit2			/* xmit 'em */
8611099Ssam 1:
87*13194Shelge 	mfpr	$CSRD,r7		/* get recv data */
8811099Ssam 	cmpb	r7,$TU_CONTINUE		/* is it a continue flag? */
89*13194Shelge 	bneq	1b			/* nope, look more */
9011099Ssam 
91*13194Shelge 	clrq	rt_name(fp)		/* init rad50 filename */
9211099Ssam 	movab	name(fp),r4		/* start of filename storage */
9311099Ssam 	movzbl	$'=,r0			/* prompt character */
9411099Ssam 	bsbw	putc			/* output char to main console */
9511099Ssam 
9611099Ssam /* read in a file name */
9711099Ssam 	movl	r4,r1			/* loc at which to store file name */
9811099Ssam nxtc:
9911099Ssam 	bsbw	getc			/* get input char's in file name */
10011099Ssam 	cmpb	r0,$012			/* terminator ? */
10111099Ssam 	beql	nullc
10211099Ssam 	movb	r0,(r1)+
10311099Ssam 	brb	nxtc
10411099Ssam nullc:
10511099Ssam 	subl3	r4,r1,r9		/* size of path name */
106*13194Shelge 	beql	start			/* restart if empty string */
107*13194Shelge 	clrb	(r1)			/* add null byte at end */
108*13194Shelge 	incl	r9			/* and fix length */
10911099Ssam 
110*13194Shelge /*
111*13194Shelge  * user-specified filename has been stored at name(fp)
112*13194Shelge  * read in entire directory contents into low core
113*13194Shelge  */
11411099Ssam dirred:
115*13194Shelge 	movl	$DIRBLK,r10		/* directory starts at block DIRBLK */
11611099Ssam 	movl	$(NUMDIR*BLKSIZ),r6	/* no. bytes in total dir */
117*13194Shelge 	clrl	r11			/* start address */
11811099Ssam 	bsbw	taper			/* read no. bytes indicated */
119*13194Shelge /*
120*13194Shelge  * Read in the character conversion table which reside in block 1
121*13194Shelge  * (the second block) on the cassette.
122*13194Shelge  */
123*13194Shelge 	movl	$1,r10			/* start block */
124*13194Shelge 	movl	$BLKSIZ,r6		/* read one block */
125*13194Shelge 	movl	0x400,r11		/* place it after the directory */
126*13194Shelge 	bsbw	taper
12711099Ssam 
128*13194Shelge /*
129*13194Shelge  * Convert the ascii filename to rad50.
130*13194Shelge  */
131*13194Shelge 	movab	name(fp),r4		/* ptr to ascii name */
132*13194Shelge 	movl	$6,r3			/* max length of filename */
133*13194Shelge 1:
134*13194Shelge 	cmpb	$'.,(r4)+		/* look for '.' */
135*13194Shelge 	sobgtr	r3,1b
136*13194Shelge 	clrb	-1(r4)			/* end name with null */
137*13194Shelge 	movl	$3,r3			/* max length of extension */
138*13194Shelge 	movab	ext(fp),r5		/* place extension here */
139*13194Shelge 1:
140*13194Shelge 	movb	(r4)+,(r5)+
141*13194Shelge 	beql	1f			/* the string is null terminated */
142*13194Shelge 	sobgtr	r3,1b
143*13194Shelge 1:
144*13194Shelge 	movab	name(fp),r4
145*13194Shelge 	movab	rt_name(fp),r5		/* ptr to rad50 name */
146*13194Shelge 	bsbw	rad50			/* convert filename */
147*13194Shelge 	movab	ext(fp),r4
148*13194Shelge 	movab	rt_name+4(fp),r5
149*13194Shelge 	bsbw	rad50			/* convert extension */
150*13194Shelge 
151*13194Shelge /*
152*13194Shelge  * Search entire directory for user-specified file name.
153*13194Shelge  */
154*13194Shelge 
155*13194Shelge 	movab	rt_name(fp),r4		/* search for this file */
156*13194Shelge 	movl	$10,r5			/* dir buff loc = 0, point to first */
157*13194Shelge 					/* file entry */
158*13194Shelge 	movzwl	-2(r5),r3		/* r3 = block # where files begin */
159*13194Shelge 2:
160*13194Shelge 	cmpc3	$6,NAME(r5),(r4)	/* see if dir entry matches filename */
16111099Ssam 	beql	fndfil			/* found match */
162*13194Shelge 1:
163*13194Shelge 	addw2	FILSIZ(r5),r3		/* add file length to block pointer */
164*13194Shelge 	addl2	$ENTSIZ,r5		/* move to next entry */
165*13194Shelge #	cpmb	RT_STAT(r5),$RT_NULL	/* check if deleted file */
166*13194Shelge #	beql	1b
167*13194Shelge 	cmpb	RT_STAT(r5),$RT_ESEG	/* check if end of segment */
168*13194Shelge 	bneq	2b
16911099Ssam 	brw	start			/* entry not in directory; start over */
17011099Ssam 
171*13194Shelge /*
172*13194Shelge  * Found desired directory entry
173*13194Shelge  */
17411099Ssam fndfil:
175*13194Shelge 	movl	r3,r10			/* start block no., 2 bytes */
176*13194Shelge 	movzwl	FILSIZ(r5),r6		/* file size (blocks) */
177*13194Shelge 	mull2	$BLKSIZ,r6		/* file size (bytes) */
178*13194Shelge #	cmpl	r6,$RELOC-512		/* check if file fits below stack */
179*13194Shelge #	blss	filok
180*13194Shelge #	brw	start			/* file too large */
18111099Ssam 
182*13194Shelge /*
183*13194Shelge  * Read in desired file from tape.
184*13194Shelge  */
18511099Ssam filok:
18611099Ssam 	movl	r6,r5			/* start of bss space */
187*13194Shelge 	clrl	r11			/* start address */
18811099Ssam 	bsbb	taper
189*13194Shelge #	bsbb	rew
19011099Ssam 
191*13194Shelge /*
192*13194Shelge  * Clear core.
193*13194Shelge  */
19411099Ssam 	subl3	r5,$RELOC-4,r0		/* no. bytes to clear */
19511099Ssam 1:
19611099Ssam 	clrb	(r5)+
19711099Ssam 	sobgtr	r0,1b
19811099Ssam 
199*13194Shelge /*
200*13194Shelge  * Jump to start of file & execute.
201*13194Shelge  */
20211099Ssam 	addl3	$20,fp,ap
20311099Ssam 	clrl	r5
20411099Ssam 	calls	$0,(r5)
20511099Ssam bad:
20611099Ssam 	brw	start
20711099Ssam 
20811099Ssam /* rewind tape */
209*13194Shelge #ifdef notdef
21011099Ssam rew:
211*13194Shelge 	movb	$5,readcom+2		/* position opcode */
212*13194Shelge 	clrl	r10			/* block 0 */
213*13194Shelge 	clrl	r6			/* 0 bytes */
21411099Ssam 	bsbb	taper
215*13194Shelge 	movb	$2,readcom+2		/* read opcode */
21611099Ssam 	rsb
217*13194Shelge #endif
21811099Ssam 
219*13194Shelge /* read (r6) bytes from (r10) into loc (r11) */
22011099Ssam taper:
221*13194Shelge 	clrl	r8			/* initialize checksum */
222*13194Shelge 	movab	readcom,r0		/* read command packet addr */
22311099Ssam 	movzbl	$TU_PACKETLEN/2,r1	/* size of readcom block */
22411099Ssam 1:
225*13194Shelge 	movzwl	(r0)+,r2		/* get 2 chars from block */
226*13194Shelge 	bsbb	xmit			/* xmit and update ckecksum */
227*13194Shelge 	sobgtr	r1,1b			/* loop if more */
22811099Ssam 
22911099Ssam 	/* now do variable part of packet */
230*13194Shelge 	movl	r6,r2			/* byte count */
23111099Ssam 	bsbb	xmit
232*13194Shelge 	movl	r10,r2			/* starting block number */
23311099Ssam 	bsbb	xmit
234*13194Shelge 	movzwl	r8,r2			/* accumulated ckecksum */
23511099Ssam 	bsbb	xmit
23611099Ssam 
23711099Ssam 	/* collect read packet from device */
238*13194Shelge 	movl	r11,r0			/* starting addr */
23911099Ssam 1:
240*13194Shelge 	bsbb	recv2			/* get 2 packet characters */
241*13194Shelge 	decb	r2			/* data packet? */
242*13194Shelge 	bneq	1f			/* branch on end of data */
243*13194Shelge 	movzbl	r1,r8			/* get byte count of packet */
24411099Ssam 
24511099Ssam 	/* read data into memory */
24611099Ssam 2:
247*13194Shelge 	bsbb	recv1			/* get a char */
248*13194Shelge 	movb	r1,(r0)+		/* stuff into memory */
249*13194Shelge 	sobgtr	r8,2b			/* loop if more */
250*13194Shelge 	bsbb	recv2			/* skip checksum */
251*13194Shelge 	brb	1b			/* read next packet */
25211099Ssam 
25311099Ssam 	/* end of data xfer; check for errors */
25411099Ssam 1:
255*13194Shelge 	subl2	r6,r0			/* all bytes xfered? */
256*13194Shelge 	bneq	9f			/* nope, error */
257*13194Shelge 	bsbb	recv2			/* get success code */
258*13194Shelge 	tstl	r1			/* error in read? */
259*13194Shelge 	blss	9f			/* branch if status error */
26011099Ssam 	movl	$5,r0
26111099Ssam 1:
262*13194Shelge 	bsbb	recv2			/* discard 10 bytes */
26311099Ssam 	sobgtr	r0,1b
26411099Ssam 	rsb
26511099Ssam 
26611099Ssam 	/* fatal error */
26711099Ssam 9:
26811099Ssam 	movab	ermsg,r1
26911099Ssam 1:
27011099Ssam 	movb	(r1)+,r0
27111099Ssam 	beql	bad
27211099Ssam 	bsbb	putc
27311099Ssam 	brb	1b
27411099Ssam 
27511099Ssam 	/* update checksum in r8 and xmit 2 characters */
27611099Ssam xmit:
277*13194Shelge 	addw2	r2,r8			/* update checksum */
278*13194Shelge 	bcc	xmit2			/* branch if no overflow */
279*13194Shelge 	incw	r8			/* add  in carry */
28011099Ssam 
28111099Ssam 	/* send the 2 characters contained in r2 */
28211099Ssam xmit2:
283*13194Shelge 	bsbb	1f			/* xmit one of 'em */
284*13194Shelge 	ashl	$-8,r2,r2		/* get next char */
285*13194Shelge 					/* fall into... */
28611099Ssam 1:
287*13194Shelge 	mfpr	$CSTS,r7		/* get xmit status */
288*13194Shelge 	bbc	$TU_READY,r7,1b		/* loop until ready */
289*13194Shelge 	mtpr	r2,$CSTD		/* send char */
29011099Ssam 	rsb
29111099Ssam 
29211099Ssam 	/* receive 2 characters, return in r2 and r1 */
29311099Ssam recv2:
294*13194Shelge 	bsbb	recv1			/* recv one of 'em */
295*13194Shelge 					/* fall into... */
29611099Ssam 
29711099Ssam 	/* receive 1 character */
29811099Ssam recv1:
299*13194Shelge 	movzbl	r1,r2			/* save previous byte */
30011099Ssam 1:
301*13194Shelge 	mfpr	$CSRS,r7		/* get recv status */
302*13194Shelge 	bbc	$TU_READY,r7,1b		/* loop until ready */
303*13194Shelge 	mfpr	$CSRD,r1		/* get char */
304*13194Shelge #	blss	9b			/* branch on recv error */
30511099Ssam 	rsb
30611099Ssam 
30711099Ssam getc:
30811099Ssam 	mfpr	$RXCS,r0
30911099Ssam 	bbc	$RXCS_pd,r0,getc	/* receiver ready ? */
31011099Ssam 	mfpr	$RXDB,r0
311*13194Shelge 	movzbl	r0,r0
31211099Ssam 	cmpb	r0,$015
31311099Ssam 	bneq	putc			/* echo and return */
31411099Ssam 	bsbb	putc			/* carriage return */
315*13194Shelge #	movb	$0,r0
316*13194Shelge #	bsbb	putc			/* delay */
31711099Ssam 	movb	$012,r0			/* send line feed and return */
31811099Ssam putc:
31911099Ssam 	mfpr	$TXCS,r2
32011099Ssam 	bbc	$TXCS_pr,r2,putc	/* transmitter ready ? */
32111099Ssam 	mtpr	r0,$TXDB
32211099Ssam 	rsb
32311099Ssam 
324*13194Shelge /*
325*13194Shelge  * Convert the filename given from the console
326*13194Shelge  * to radix 50 (rt-11) format.
327*13194Shelge  */
328*13194Shelge rad50:
329*13194Shelge 	movl	$0x400,r6		/* address of conversion table */
330*13194Shelge 1:
331*13194Shelge 	bsbb	getb50			/* get next ascii byte, exit if null */
332*13194Shelge 	mull3	$03100,r0,r1
333*13194Shelge 	bsbb	getb50
334*13194Shelge 	mull3	$050,r0,r2
335*13194Shelge 	addl2	r2,r1
336*13194Shelge 	bsbb	getb50
337*13194Shelge 	addl2	r0,r1			/* last byte, just add it in */
338*13194Shelge 	movw	r1,(r5)+		/* save result */
339*13194Shelge 	brb	1b
340*13194Shelge 
341*13194Shelge getb50:
342*13194Shelge 	movzbl	(r4)+,r0		/* get next ascii byte */
343*13194Shelge 	beql	1f			/* if zero: end of string */
344*13194Shelge 	addl2	r6,r0			/* calculate conversion table address */
345*13194Shelge 	movzbl	(r0),r0			/* and get the r50 byte from the table*/
346*13194Shelge 	rsb
347*13194Shelge 1:
348*13194Shelge 	tstl	(sp)+			/* we're through, get back to where */
349*13194Shelge 					/* rad50 was called */
350*13194Shelge 	movw	r1,(r5)			/* but first save the result */
351*13194Shelge 	rsb
352*13194Shelge 
35311099Ssam 	.align	2
35411099Ssam readcom:
355*13194Shelge 	.byte	2			/* command packet flag */
356*13194Shelge 	.byte	10			/* number of bytes in message */
357*13194Shelge 	.byte	2			/* tu read opcode */
358*13194Shelge 	.byte	0			/* modifier */
359*13194Shelge 	.byte	0			/* unit number */
360*13194Shelge 	.byte	0			/* switches */
361*13194Shelge 	.word	0			/* sequence number */
362*13194Shelge 					/* byte count and block number follow */
36311099Ssam 
36411099Ssam ermsg:
36511099Ssam 	.asciz	"tu58 err\r\n"
36611099Ssam end:
367