xref: /original-bsd/sys/vax/mdec/tuboot.c (revision 23a40993)
1 /*	tuboot.c	4.5	83/06/29	*/
2 
3 /*
4  * VAX tu58 console cassette boot block
5  *
6  * Helge Skrivervik CSRG/UCB 18jun83
7  *
8  * Reads a program from a rt-11 directory on tape
9  * and executes it.  Programs must be stripped of
10  * the header and is loaded ``bits as is''.
11  * You can return to this loader via ``ret'' as
12  * you are called ``calls $0,ent''.
13  * Error checking and recovery is almost nonexistant
14  * due to the severe space constraints.
15  *
16  * NOTE: Any changes to this program are likely to
17  *	 bring the size over 512 bytes ....
18  *
19  * Based on tp format bootstrap originally written by Thomas Ferrin.
20  *
21  */
22 	.set	CTABLE,0x400	/* where to load the rad50 cnv table */
23 	.set	RELOC,0x70000
24 /* rt-11 directory definitions */
25 	.set	DIRBLK,6	/* rt-11 directory starts at block 6 */
26 	.set	FILSIZ,8	/* rt-11 direc entry offset for file size */
27 	.set	ENTSIZ,14	/* size of 1 rt-11 dir entry, bytes */
28 	.set	BLKSIZ,512	/* tape block size, bytes */
29 	.set	NUMDIR,2	/* no. of dir blocks on tape */
30 	.set	FNSIZ,8		/* size of rad50 filename + 2 */
31 	.set	NAME,2		/* direc entry offset for filename */
32 	.set	STATUS,1	/* direc entry offset for entry status */
33 /* rt-11 directory entry status */
34 	.set	RT_ESEG,8	/* end of directory segment */
35 	.set	RT_NULL,2	/* empty entry */
36 	.set	RT_FILE,4	/* valid file entry */
37 /* processor registers and bits */
38 	.set	RXCS,32
39 	.set	RXDB,33
40 	.set	TXCS,34
41 	.set	TXDB,35
42 	.set	RXCS_DONE,0x80
43 	.set	TXCS_RDY,0x80
44 	.set	TXCS_pr,7	/* bit position of TXCS ready bit */
45 	.set	RXCS_pd,7	/* bit position of RXCS done bit */
46 /* console storage registers and bits */
47 	.set	CSRS,0x1c
48 	.set	CSRD,0x1d
49 	.set	CSTS,0x1e
50 	.set	CSTD,0x1f
51 /* TU commands and bits */
52 	.set	TU_BREAK,1
53 	.set	TU_INIT,4
54 	.set	TU_CONTINUE,16
55 	.set	TU_READY,7	/* bit position of CSRS ready bit */
56 	.set	TU_PACKETLEN,8	/* length of readcom block */
57 /* local stack variables */
58 	.set	ext,-4				/* file ext. */
59 	.set	name,-20			/* 12 bytes for full name */
60 	.set	rt_name,-20-FNSIZ		/* rad50 file name */
61 
62 /*
63  * Initialization.
64  */
65 init:
66 	.word	0 		/* entry mask for dec monitor */
67 	nop;nop;nop;nop;nop	/* some no-ops for 750 boot rom to skip */
68 	nop;nop;nop;nop;nop
69 	movl	$RELOC,fp	/* core loc to which to move this program */
70 	addl3	$rt_name,fp,sp	/* set stack pointer; leave room for locals */
71 	clrl	r0
72 1:
73 	movc3	$end,(r0),(fp)	/* move boot up to relocated position */
74 	jmp	start+RELOC
75 
76 start:
77 	mtpr	$TU_BREAK,$CSTS		/* set break condition */
78 	clrl	r2			/* nulls */
79 	bsbw	xmit2			/* wait 2 character times */
80 	mfpr	$CSRD,r2		/* clear receive buffer */
81 	movzwl	$TU_INIT|(TU_INIT<<8),r2	/* load 2 INIT opcodes */
82 	bsbw	xmit2			/* xmit 'em */
83 1:
84 	mfpr	$CSRD,r7		/* get recv data */
85 	cmpb	r7,$TU_CONTINUE		/* is it a continue flag? */
86 	bneq	1b			/* nope, look more */
87 
88 	movab	name(fp),r4		/* start of filename storage */
89 	clrq	(r4)			/* init name field */
90 	clrq	name+8(fp)
91 	clrq	rt_name(fp)		/* init rad50 filename */
92 	movzbl	$'=,r0			/* prompt character */
93 	bsbw	putc			/* output char to main console */
94 
95 /*
96  * Read in a file name from console.
97  */
98 	movl	r4,r1			/* loc at which to store file name */
99 nxtc:
100 	bsbw	getc			/* get input char's in file name */
101 	cmpb	r0,$012			/* terminator ? */
102 	beql	nullc
103 	movb	r0,(r1)+
104 	brb	nxtc
105 nullc:
106 	cmpl	r4,r1
107 	beql	start			/* restart if empty string */
108 	clrb	(r1)			/* add null byte at end */
109 
110 /*
111  * User-specified filename has been stored at name(fp),
112  * read the entire directory contents into low core.
113  */
114 dirred:
115 	movl	$DIRBLK,r10		/* directory starts at block DIRBLK */
116 	movl	$(NUMDIR*BLKSIZ),r6	/* no. bytes in total dir */
117 	clrl	r11			/* start address */
118 	bsbw	taper			/* read no. bytes indicated */
119 /*
120  * Read in the character conversion table which reside in block 1
121  * (the second block) on the cassette. Place it after the directory
122  * on low core (from 0x400).
123  */
124 	movl	$1,r10			/* block number */
125 	movl	$BLKSIZ,r6		/* read one block */
126 	bsbw	taper
127 
128 /*
129  * Convert the ascii filename to rad50.
130  * R4 still points to name(fp)
131  */
132 	movl	$6,r3			/* max length of filename */
133 1:
134 	cmpb	$'.,(r4)+		/* look for '.' */
135 	beql	1f
136 	sobgtr	r3,1b
137 	incl	r4			/* point past '.' if ext is present */
138 1:
139 	clrb	-1(r4)			/* end name with null */
140 	movl	$3,r3			/* max length of extension */
141 	movab	ext(fp),r5		/* place extension here */
142 1:
143 	movb	(r4)+,(r5)+
144 	beql	1f			/* the string is null terminated */
145 	sobgtr	r3,1b
146 1:
147 	movab	name(fp),r4
148 	movab	rt_name(fp),r5		/* ptr to rad50 name */
149 	bsbw	rad50			/* convert filename */
150 	movab	ext(fp),r4
151 	movab	rt_name+4(fp),r5
152 	bsbw	rad50			/* convert extension */
153 
154 /*
155  * Search entire directory for user-specified file name.
156  */
157 
158 	movab	rt_name(fp),r4		/* search for this file */
159 	movl	$10,r5			/* point to first file entry */
160 	movzwl	-2(r5),r10		/* r10 = block # where files begin */
161 2:
162 	cmpc3	$6,NAME(r5),(r4)	/* see if dir entry matches filename */
163 	beql	fndfil			/* found match */
164 1:
165 	addw2	FILSIZ(r5),r10		/* add file length to block pointer */
166 	addl2	$ENTSIZ,r5		/* move to next entry */
167 #	cpmb	STATUS(r5),$RT_NULL	/* check if deleted file */
168 #	beql	1b /* not really necessary since deleted entries will fail */
169 		   /* to compare anyway */
170 	cmpb	STATUS(r5),$RT_ESEG	/* check if end of segment */
171 	bneq	2b
172 	brw	start			/* entry not in directory; start over */
173 
174 /*
175  * Found desired directory entry
176  */
177 fndfil:
178 					/* start block no., 2 bytes in r10 */
179 	movzwl	FILSIZ(r5),r6		/* file size (blocks) */
180 	mull2	$BLKSIZ,r6		/* file size (bytes) */
181 	cmpl	r6,$RELOC-512		/* check if file fits below stack */
182 	blss	filok
183 	brw	start			/* file too large */
184 
185 /*
186  * Read in desired file from tape.
187  */
188 filok:
189 	movl	r6,r5			/* start of bss space */
190 	clrl	r11			/* start address */
191 	bsbb	taper
192 
193 /*
194  * Clear core.
195  */
196 	subl3	r5,$RELOC-4,r0		/* no. bytes to clear */
197 1:
198 	clrb	(r5)+
199 	sobgtr	r0,1b
200 
201 /*
202  * Jump to start of file & execute.
203  */
204 	addl3	$20,fp,ap		/* ?? */
205 	clrl	r5
206 	calls	$0,(r5)
207 bad:
208 	brw	start
209 
210 /*
211  * Read (r6) bytes from block (r10)
212  * into loc (r11).
213  */
214 taper:
215 	clrl	r8			/* initialize checksum */
216 	movab	readcom,r0		/* read command packet addr */
217 	movzbl	$TU_PACKETLEN/2,r1	/* size of readcom block */
218 1:
219 	movzwl	(r0)+,r2		/* get 2 chars from block */
220 	bsbb	xmit			/* xmit and update ckecksum */
221 	sobgtr	r1,1b			/* loop if more */
222 
223 /*
224  * Now do variable part of packet.
225  */
226 	movl	r6,r2			/* byte count */
227 	bsbb	xmit
228 	movl	r10,r2			/* starting block number */
229 	bsbb	xmit
230 	movzwl	r8,r2			/* accumulated ckecksum */
231 	bsbb	xmit
232 
233 /*
234  * Collect read packet from device.
235  */
236 1:
237 	bsbb	recv2			/* get 2 packet characters */
238 	decb	r2			/* data packet? */
239 	bneq	1f			/* branch on end of data */
240 	movzbl	r1,r8			/* get byte count of packet */
241 
242 /*
243  * Read data into memory.
244  */
245 2:
246 	bsbb	recv1			/* get a char */
247 	movb	r1,(r11)+		/* stuff into memory */
248 	sobgtr	r8,2b			/* loop if more */
249 	bsbb	recv2			/* skip checksum */
250 	brb	1b			/* read next packet */
251 
252 /*
253  * End of data xfer; check for errors.
254  */
255 1:
256 	bsbb	recv2			/* get success code */
257 	tstl	r1			/* error in read? */
258 	blss	9f			/* branch if status error */
259 	movl	$5,r0
260 1:
261 	bsbb	recv2			/* discard 10 bytes */
262 	sobgtr	r0,1b
263 	rsb
264 
265 /* Fatal error */
266 9:
267 	movab	ermsg,r1
268 1:
269 	movb	(r1)+,r0
270 	beql	bad
271 	bsbb	putc
272 	brb	1b
273 
274 /*
275  * Update checksum in r8 and xmit 2 characters.
276  */
277 xmit:
278 	addw2	r2,r8			/* update checksum */
279 	adwc	$0,r8			/* add  in carry */
280 
281 /* send the 2 characters contained in r2 */
282 xmit2:
283 	bsbb	1f			/* xmit one of 'em */
284 	ashl	$-8,r2,r2		/* get next char */
285 					/* fall into... */
286 1:
287 	mfpr	$CSTS,r7		/* get xmit status */
288 	bbc	$TU_READY,r7,1b		/* loop until ready */
289 	mtpr	r2,$CSTD		/* send char */
290 	rsb
291 
292 /*
293  * Receive 2 characters, return in r2 and r1.
294  */
295 recv2:
296 	bsbb	recv1			/* recv one of 'em */
297 					/* fall into... */
298 
299 /*
300  * Receive 1 character.
301  */
302 recv1:
303 	movzbl	r1,r2			/* save previous byte */
304 1:
305 	mfpr	$CSRS,r7		/* get recv status */
306 	bbc	$TU_READY,r7,1b		/* loop until ready */
307 	mfpr	$CSRD,r1		/* get char */
308 	blss	9b			/* branch on recv error */
309 	rsb
310 
311 getc:
312 	mfpr	$RXCS,r0
313 	bbc	$RXCS_pd,r0,getc	/* receiver ready ? */
314 	mfpr	$RXDB,r0
315 	extzv	$0,$7,r0,r0
316 	cmpb	r0,$015
317 	bneq	putc			/* echo and return */
318 	bsbb	putc			/* carriage return */
319 #	movb	$0,r0
320 #	bsbb	putc			/* delay */
321 	movb	$012,r0			/* send line feed and return */
322 putc:
323 	mfpr	$TXCS,r2
324 	bbc	$TXCS_pr,r2,putc	/* transmitter ready ? */
325 	mtpr	r0,$TXDB
326 	rsb
327 
328 /*
329  * Convert the filename given from the console
330  * to radix 50 (rt-11) format.
331  */
332 rad50:
333 	clrw	r1
334 	bsbb	getb50			/* get next ascii byte, exit if null */
335 	mull3	$03100,r0,r1
336 	bsbb	getb50
337 	mull3	$050,r0,r2
338 	addl2	r2,r1
339 	bsbb	getb50
340 	addl2	r0,r1			/* last byte, just add it in */
341 	movw	r1,(r5)+		/* save result */
342 	brb	rad50
343 
344 getb50:
345 	movzbl	(r4)+,r0		/* get next ascii byte */
346 	beql	1f			/* if zero: end of string */
347 	movzbl	CTABLE(r0),r0		/* and get the r50 byte from the table*/
348 	rsb
349 1:
350 	tstl	(sp)+			/* we're through, get back to where */
351 					/* rad50 was called */
352 	movw	r1,(r5)			/* but first save the result */
353 	rsb
354 
355 	.align	2
356 readcom:
357 	.byte	2			/* command packet flag */
358 	.byte	10			/* number of bytes in message */
359 	.byte	2			/* tu read opcode */
360 	.byte	0			/* modifier */
361 	.byte	0			/* unit number */
362 	.byte	0			/* switches */
363 	.word	0			/* sequence number */
364 					/* byte count and block number follow */
365 
366 ermsg:
367 	.asciz	"tu err\r\n"
368 end:
369 
370 /*
371  * Ascii to rad 50 conversion table,
372  * stored on the second block on the cassette
373  *
374  * NOTE: Always make sure this table ends up
375  * starting at byte 512!!!!
376  */
377 	.align	2
378 	.data	2
379 	.long	0x1d1d1d1d
380 	.long	0x1d1d1d1d
381 	.long	0x1d1d1d1d
382 	.long	0x1d1d1d1d
383 	.long	0x1d1d1d1d
384 	.long	0x1d1d1d1d
385 	.long	0x1d1d1d1d
386 	.long	0x1d1d1d1d
387 	.long	0x1d1d1d00
388 	.long	0x1d1d1d1b
389 	.long	0x1d1d1d1d
390 	.long	0x1d1c1d1d
391 	.long	0x21201f1e
392 	.long	0x25242322
393 	.long	0x1d1d2726
394 	.long	0x1d1d1d1d
395 	.long	0x302011d
396 	.long	0x7060504
397 	.long	0xb0a0908
398 	.long	0xf0e0d0c
399 	.long	0x13121110
400 	.long	0x17161514
401 	.long	0x1d1a1918
402 	.long	0x1d1d1d1d
403 	.long	0x302011d
404 	.long	0x7060504
405 	.long	0xb0a0908
406 	.long	0xf0e0d0c
407 	.long	0x13121110
408 	.long	0x17161514
409 	.long	0x1d1a1918
410 	.long	0x1d1d1d1d
411 	.long	0x1d1d1d1d
412 	.long	0x1d1d1d1d
413 	.long	0x1d1d1d1d
414 	.long	0x1d1d1d1d
415 	.long	0x1d1d1d1d
416 	.long	0x1d1d1d1d
417 	.long	0x1d1d1d1d
418 	.long	0x1d1d1d1d
419 	.long	0x1d1d1d00
420 	.long	0x1d1d1d1b
421 	.long	0x1d1d1d1d
422 	.long	0x1d1c1d1d
423 	.long	0x21201f1e
424 	.long	0x25242322
425 	.long	0x1d1d2726
426 	.long	0x1d1d1d1d
427 	.long	0x302011d
428 	.long	0x7060504
429 	.long	0xb0a0908
430 	.long	0xf0e0d0c
431 	.long	0x13121110
432 	.long	0x17161514
433 	.long	0x1d1a1918
434 	.long	0x1d1d1d1d
435 	.long	0x302011d
436 	.long	0x7060504
437 	.long	0xb0a0908
438 	.long	0xf0e0d0c
439 	.long	0x13121110
440 	.long	0x17161514
441 	.long	0x1d1a1918
442 	.long	0x1d1d1d
443 	.data
444