xref: /original-bsd/sys/vax/mdec/tmscpboot.c (revision f1656be1)
1 /*
2  *	@(#)tmscpboot.c	7.2 (Berkeley) 01/22/88
3  *
4  * TK50 tape boot block for distribution tapes
5  * works on Q-bus tk50 drive on uVaxen
6  *
7  * Rick Lindsley
8  * richl@tektronix.tek.com
9  *
10  * reads a program from a tp directory on a tape and executes it
11  * program must be stripped of the header and is loaded ``bits as is''
12  * you can return to this loader via ``ret'' as you are called ``calls $0,ent''
13  */
14 	.set	RELOC,0x70000
15 /* tp directory definitions */
16 	.set	FILSIZ,38	# tp direc offset for file size
17 	.set	BNUM,44		# tp dir offset for start block no.
18 	.set	ENTSIZ,64	# size of 1 TP dir entry, bytes
19 	.set	PTHSIZ,32	# size of TP path name, bytes
20 	.set	BLKSIZ,512	# tape block size, bytes
21 	.set	NUMDIR,24	# no. of dir blocks on tape
22 	.set	ENTBLK,8	# no. of dir entries per tape block
23 /* processor registers and bits */
24 	.set	RXCS,32
25 	.set	RXDB,33
26 	.set	TXCS,34
27 	.set	TXDB,35
28 	.set	RXCS_DONE,0x80
29 	.set	TXCS_RDY,0x80
30 	.set	TXCS_pr,7	/* bit position of TXCS ready bit */
31 	.set	RXCS_pd,7	/* bit position of RXCS done bit */
32 /* UBA registers */
33 	.set	MAPSTART,0x20088000	# for a uVax, anyway
34 	.set	UBAMEM,0x1ffc2000	# again, for a uVax
35 	.set	MRV,0x80000000		# map register valid bit
36 /* TMSCP UBA registers */
37 	.set	TMSCP_CSR, 0774500	# CSR of tk50
38 	.set	TMSCPip,0		# initialization and polling
39 	.set	TMSCPsa,2		# status and address
40 /* handy values for tmscp communication area */
41 	.set	TMSCP_OWN,0x80000000
42 	.set	TMSCP_ERR,0x8000
43 	.set	TMSCP_STEP4,0x4000
44 	.set	TMSCP_STEP3,0x2000
45 	.set	TMSCP_STEP2,0x1000
46 	.set	TMSCP_STEP1,0x800
47 	.set	TMSCP_IE,0x80
48 	.set	TMSCP_GO,1
49 /* handy offsets into tmscp communication area (from tmscpca) */
50 	.set	cmdint,4
51 	.set	rspint,6
52 	.set	rspdsc,8
53 	.set	cmddsc,12
54 /* handy offsets into mscp packets (from %rCMD or %rRSP) */
55 	.set	msglen,0
56 	.set	vcid,3
57 	.set	unit,8
58 	.set	op,12
59 	.set	status,14
60 	.set	modifier,14
61 	.set	bytecnt,16
62 	.set	cntflgs,18
63 	.set	buffer,20
64 	.set	tmkcnt,20
65 	.set	lbn,32
66 	.set	dscptr,40
67 /* TMSCP commands and modifiers */
68 	.set	M_OP_STCON,4
69 	.set	M_OP_ONLIN,9
70 	.set	M_OP_READ,33
71 	.set	M_OP_REPOS,37
72 	.set	M_MD_REWND,2
73 	.set	M_MD_IMMED,0x80
74 	.set	M_MD_CLSEX,0x200
75 	.set	M_ST_MASK,0x1f
76 	.set	M_ST_TAPEM,14
77 /* miscellaneous */
78 	.set	IUR, 0x37
79 	.set	SID, 0x3e
80 	.set	VAX_630,8
81 /* local stack variables */
82 	.set	tmscpca,-240-PTHSIZ-26	# struct tmscpca (see tmscpreg.h)
83 	.set	rsp,-240-PTHSIZ-10	# tmscp response area
84 	.set	cmd,-120-PTHSIZ-10	# tmscp command area
85 	.set	name,-PTHSIZ-10		# operator-typed file name
86 	.set	dirread,-10		# is the tape directory incore already?
87 	.set	mtapa,-8		# cur tape addr (last blk we read)
88 	.set	tapa,-4			# desired tape addr (inclusive)
89 /* register usage */
90 	.set	rCMD,r7
91 	.set	rRSP,r8
92 	.set	rUBADDR,r9
93 	.set	rMAPREGS,r10
94 	.set	rCSR,r11
95 /* ===== */
96 
97 /* initialization */
98 init:
99 	#
100 	# if on a uVax, we were loaded by VMB from tape. We also have
101 	# only one unibus, at 0x1fffc2000 (see above). Elstwise, this
102 	# boot program will almost certainly need help.
103 	#
104 	mfpr	$SID,r0
105 	cmpzv	$24,$8,r0,$VAX_630
106 	beql	1f
107 	halt
108 	#
109 	# We must have been loaded by VMB, and thus we are at a non-zero
110 	# location.  sp will contain the base address of the area at which
111 	# we were loaded. So we add sp to $end to get the true end-of-program
112 	# address.
113 	#
114 1:	movl	sp,r6		# r6 - beginning of program
115 	movl	$RELOC,fp	# core loc to which to move this program
116 	addl3	$-512,fp,sp	# set stack pointer; leave room for locals
117 	addl3	$-512,fp,r0	# zero our destination mem .. we start here
118 	addl3	$end,fp,r1	# and end here
119 clr:	clrl	(r0)+
120 	cmpl	r0,r1
121 	jlss	clr
122 
123 	movc3	$end,(r6),(fp)	# copy to relocated position
124 	addl3	$reginit,$RELOC,r0
125 	jmp	(r0)		# and go there
126 reginit:
127 	/* initialize our registers. Should need to do this only once */
128 	addl3	$UBAMEM, $TMSCP_CSR, %rCSR	# set up CSR register
129 	movl	$MAPSTART, %rMAPREGS	# locate map registers
130 
131 	moval	tmscpca(fp), %rUBADDR	# set unibus address for comm area
132 	extzv	$0,$9,%rUBADDR,%rUBADDR	# format: (MR# << 9) | (&comm & 0x1ff)
133 	ashl	$-9,$RELOC-512,r0	# setting up map register for our stack
134 	bisl3	$MRV,r0,(%rMAPREGS)	# mark our stack valid (MR #0)
135 
136 	moval	cmd(fp),%rCMD		# location of cmd mscp packet
137 	moval	rsp(fp),%rRSP		# location of rsp mscp packet
138 	bsbw	inittmscp		# init the unit
139 	bsbw	onlin			# set tape online
140 	bsbw	rew			# rewind tape
141 
142 start:
143 #ifdef DEBUG
144 	movzbl	$11,r0			# newline
145 	bsbw	putc
146 	movzbl	$13,r0			# return
147 	bsbw	putc
148 #endif
149 	movzbl	$'=,r0			# prompt
150 	bsbw	putc
151 	bsbw	getname
152 
153 	# desired TP filename is in name(fp).  Now read in entire tp directory
154 	# contents into low core, starting at loc 0. Because tk50's are slow,
155 	# and because we are going to go over 512 bytes anyway, and because
156 	# it requires so little effort, we'll keep track of whether the data
157 	# at location 0 is the tape directory.
158 
159 	tstw	dirread(fp)	# if directory needs to be read in, do so
160 	bneq	1f
161 	bsbw	readdir
162 1:
163 	#
164 	# all of directory is now in locore, @ 0.
165 	# search for filename; return to start if it isn't there.
166 	#
167 	clrl	r0			# start at location 0
168 nxtdir:	moval	name(fp),r2
169 	movl	r0,r1
170 1:	cmpb	(r1),(r2)
171 	bneq	2f
172 	tstb	(r1)
173 	beql	found
174 	incl	r1
175 	incl	r2
176 	brb	1b
177 2:	acbl	$NUMDIR*BLKSIZ-1,$ENTSIZ,r0,nxtdir
178 	brw	start			# entry not in directory; start over
179 
180 	# entry IS here; read it in from tape
181 
182 found:	movzwl	BNUM(r0),tapa(fp)	# start block no., 2 bytes
183 	addl2	$2-1,tapa(fp)		# skip over this program (2 blocks)
184 					# minus 1 because we will read THROUGH
185 					# this block; so we want to stop just
186 					# before it
187 	movzwl	FILSIZ(r0),r4		# low 2 bytes file size
188 	insv	FILSIZ-1(r0),$16,$8,r4  # file size, high byte
189 	cmpl	r4,$RELOC-512		# check if file fits below stack
190 	bgeq	start 			# file too large
191 
192 	# Now advance to proper place on tape. tapa has our
193 	# desired address
194 
195 	clrw	dirread(fp)	# we are about to obliterate our incore copy
196 				# of the directory
197 2:	clrl	r3	# rrec expects r3 to point to a buffer. 0 will do ...
198 	bsbw	rrec
199 	cmpl	mtapa(fp),tapa(fp)
200 	blss	2b
201 
202 	# tape now positioned correctly. Read in program. Number of bytes
203 	# to read is in r4. We must round up to an even BLKSIZ boundary.
204 	# Clear the area we are putting it at; unix expects zeroes in its
205 	# data and bss section.
206 
207 	addl2	$BLKSIZ-1,r4		# round up
208 	bicl2	$BLKSIZ-1,r4		# mask out
209 	movl	r4,r5			# use r5; need to save r4 for later
210 1:	clrl	(r5)
211 	sobgtr	r5,1b
212 
213 	# now read in file.
214 
215 	clrl	r3			# read into page 0 (incremented by rrec)
216 	ashl	$-9,r4,r5		# r5 now holds # blks to read
217 	addl2	r5,tapa(fp)		# compute desired tape blk #
218 1:	bsbw	rrec
219 	cmpl	mtapa(fp),tapa(fp)	# got it yet?
220 	blss	1b
221 
222 	# begin execution. Call as a function.
223 	clrl	r5
224 	calls	$0,(r5)
225 
226 	# now, since the called function has reset the tape drive for
227 	# us (!) we must reinit it again ourselves.
228 
229 	ashl	$-9,$RELOC-512,r0	# set up map register for our stack
230 	bisl3	$MRV,r0,(%rMAPREGS)	# mark our stack valid (MR #0)
231 	bsbw	inittmscp		# re-init drive
232 	bsbw	onlin			# re-online it
233 	brw	start
234 
235 	# getname will set name(fp) and leave len(name(fp)) in r6
236 getname:moval	name(fp),r1		# mov to register for ease of access
237 nxtc:	bsbw	getc
238 	cmpb	r0,$012			# end of line?
239 	beql	nullc
240 	movb	r0,(r1)+
241 	brb	nxtc
242 nullc:	moval	name(fp),r0
243 	subl3	r0,r1,r6		# length of path name
244 	jeql	start			# just hit return; nothing useful here
245 	clrb	(r1)+			# add null at end
246 	incl	r6			# add null to length
247 	rsb
248 
249 getc:	mfpr	$RXCS,r0
250 	bbc	$RXCS_pd,r0,getc	/* receiver ready ? */
251 	mfpr	$RXDB,r0
252 	extzv	$0,$7,r0,r0
253 	cmpb	r0,$015
254 	bneq	putc
255 	bsbw	putc
256 	movb	$0,r0
257 	bsbw	putc
258 	movb	$012,r0
259 
260 putc:	mfpr	$TXCS,r2
261 	bbc	$TXCS_pr,r2,putc	/* transmitter ready ? */
262 	extzv	$0,$7,r0,r0
263 	mtpr	r0,$TXDB
264 	rsb
265 
266 inittmscp:
267 	movw	$0,TMSCPip(%rCSR)		# start step 1
268 1:	bitw	$TMSCP_STEP1,TMSCPsa(%rCSR)
269 	beql	1b
270 #ifdef DEBUG
271 	movzbl	$'1,r0
272 	bsbw	putc
273 #endif
274 init2:	movw	$TMSCP_ERR,TMSCPsa(%rCSR)	# start step 2
275 2:	bitw	$TMSCP_STEP2,TMSCPsa(%rCSR)
276 	beql	2b
277 #ifdef DEBUG
278 	movzbl	$'2,r0
279 	bsbw	putc
280 #endif
281 init3:	addl3	$8,%rUBADDR,r0			# start step 3
282 	cvtlw	r0,TMSCPsa(%rCSR)
283 3:	bitw	$TMSCP_STEP3,TMSCPsa(%rCSR)
284 	beql	3b
285 #ifdef DEBUG
286 	movzbl	$'3,r0
287 	bsbw	putc
288 #endif
289 init4:	addl3	$8,%rUBADDR,r0			# start step 4
290 	ashl	$-16,r0,r0
291 	cvtlw	r0,TMSCPsa(%rCSR)
292 4:	bitw	$TMSCP_STEP4,TMSCPsa(%rCSR)
293 	beql	4b
294 #ifdef DEBUG
295 	movzbl	$'4,r0
296 	bsbw	putc
297 #endif
298 setchar:
299 	movw	$TMSCP_GO,TMSCPsa(%rCSR)
300 	moval	140(%rUBADDR),tmscpca+cmddsc(fp)
301 	moval	tmscpca+cmddsc(fp),dscptr(%rCMD)
302 	movb	$1,vcid(%rCMD)
303 	moval	20(%rUBADDR),tmscpca+rspdsc(fp)
304 	moval	tmscpca+rspdsc(fp),dscptr(%rRSP)
305 	clrw	cntflgs(%rCMD)
306 
307 	movb	$M_OP_STCON,op(%rCMD)
308 	clrw	modifier(%rCMD)
309 	clrl	buffer(%rCMD)
310 	clrl	bytecnt(%rCMD)
311 	bsbw	tmscpcmd
312 #ifdef DEBUG
313 	movzbl	$'S,r0
314 	bsbw	putc
315 #endif
316 	rsb
317 
318 tmscpcmd:
319 	movw	$116,msglen(%rCMD)		# 116 -- size of an mscp packet
320 	bisl2	$TMSCP_OWN,tmscpca+cmddsc(fp)
321 	movw	$116,msglen(%rRSP)
322 	bisl2	$TMSCP_OWN,tmscpca+rspdsc(fp)
323 	movw	TMSCPip(%rCSR),r0		# start polling
324 wait:	cvtwl	TMSCPsa(%rCSR),r0
325 	bitl	$TMSCP_ERR,r0
326 	beql	1f
327 	movw	modifier(%rRSP),r1	# so we can read status easily
328 	halt				# some error or other
329 1:	tstl	tmscpca+4(fp)
330 	beql	2f
331 	clrw	tmscpca+4(fp)
332 2:	bitl	$TMSCP_OWN,tmscpca+rspdsc(fp)
333 	bneq	wait
334 
335 	# cmd done
336 
337 	clrw	tmscpca+rspint(fp)
338 	extzv	$0,$5,status(%rRSP),r0
339 	tstl	r0
340 	beql	ok			# no errors
341 	cmpl	$M_ST_TAPEM, r0
342 	beql	ok			# not an error, just a tape mark
343 	halt				# some unknown error
344 ok:	rsb
345 
346 rew:	movb	$M_OP_REPOS,op(%rCMD)
347 	movw	$M_MD_REWND|M_MD_IMMED,modifier(%rCMD)
348 	clrl	buffer(%rCMD)
349 	clrl	bytecnt(%rCMD)
350 	bsbw	tmscpcmd
351 #ifdef DEBUG
352 	movzbl	$'r,r0			# to indicate r)ewind
353 	bsbw	putc
354 #endif
355 	movl	$-1,mtapa(fp)		# no blocks read yet
356 	rsb
357 
358 onlin:	movb	$M_OP_ONLIN,op(%rCMD)
359 	clrw	modifier(%rCMD)
360 	clrl	buffer(%rCMD)
361 	clrl	bytecnt(%rCMD)
362 	bsbw	tmscpcmd
363 #ifdef DEBUG
364 	movzbl	$'O,r0			# to indicate O)nline
365 	bsbw	putc
366 #endif
367 	rsb
368 
369 	# Read the tp directory. Number of blocks to read is in tapa(fp),
370 	# and will be read into memory starting at location 0.
371 readdir:bsbw	rew			# beginning of tape
372 	addl3	$2,$NUMDIR,tapa(fp)	# blocks to read (skip this 1k program)
373 	clrl	r3			# using mem starting at 0 as free space
374 	bsbw	rrec; bsbw rrec		# read and discard first two blocks --
375 					# those are this program
376 	bsbw	rrec			# read and discard first tp block
377 	clrl	r3			# reset starting place
378 	incw	dirread(fp)		# show that directory is incore
379 1:	bsbw	rrec
380 	cmpl	mtapa(fp),tapa(fp)	# done yet?
381 	blss	1b
382 	rsb
383 
384 	# read 1 block from mag tape into page indicated by r3, which will
385 	# automatically be incremented here. mtapa is also advanced.
386 
387 rrec:	bisl3	$MRV,r3,4(%rMAPREGS)	# using map register #1
388 	movl	$BLKSIZ,bytecnt(%rCMD)	# how much to read
389 	ashl	$9,$1,buffer(%rCMD)	# indicating mr #1. We just happen to
390 					# be on a page boundary, so filling in
391 					# the low 9 bits is not necessary.
392 	movb	$M_OP_READ,op(%rCMD)
393 	clrw	modifier(%rCMD)
394 	bsbw	tmscpcmd
395 #ifdef DEBUG
396 	movzbl	$'R,r0			# to indicate R)ead a record
397 	bsbw	putc
398 #endif
399 	incl	mtapa(fp)
400 	incl	r3
401 	rsb
402 end:
403