kernel reorg
[unix-history] / usr / src / sys / vax / mdec / tmscpboot.c
CommitLineData
ff906971
KB
1/*
2 * @(#)tmscpboot.c 7.2 (Berkeley) %G%
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 */
86448185 14 .set RELOC,0x70000
ff906971 15/* tp directory definitions */
86448185
KB
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 */
98init:
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 #
1141: 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
119clr: 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
126reginit:
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
142start:
ff906971
KB
143#ifdef DEBUG
144 movzbl $11,r0 # newline
145 bsbw putc
146 movzbl $13,r0 # return
147 bsbw putc
148#endif
86448185 149 movzbl $'=,r0 # prompt
ff906971 150 bsbw putc
86448185
KB
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
1621:
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
168nxtdir: moval name(fp),r2
169 movl r0,r1
1701: cmpb (r1),(r2)
171 bneq 2f
172 tstb (r1)
173 beql found
174 incl r1
175 incl r2
176 brb 1b
1772: 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
182found: 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
1972: 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
2101: 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 #
2181: 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
236getname:moval name(fp),r1 # mov to register for ease of access
237nxtc: bsbw getc
238 cmpb r0,$012 # end of line?
239 beql nullc
240 movb r0,(r1)+
241 brb nxtc
242nullc: 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
249getc: 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
260putc: mfpr $TXCS,r2
261 bbc $TXCS_pr,r2,putc /* transmitter ready ? */
262 extzv $0,$7,r0,r0
263 mtpr r0,$TXDB
264 rsb
265
266inittmscp:
267 movw $0,TMSCPip(%rCSR) # start step 1
2681: bitw $TMSCP_STEP1,TMSCPsa(%rCSR)
269 beql 1b
ff906971
KB
270#ifdef DEBUG
271 movzbl $'1,r0
272 bsbw putc
273#endif
86448185
KB
274init2: movw $TMSCP_ERR,TMSCPsa(%rCSR) # start step 2
2752: bitw $TMSCP_STEP2,TMSCPsa(%rCSR)
276 beql 2b
ff906971
KB
277#ifdef DEBUG
278 movzbl $'2,r0
279 bsbw putc
280#endif
86448185
KB
281init3: addl3 $8,%rUBADDR,r0 # start step 3
282 cvtlw r0,TMSCPsa(%rCSR)
2833: bitw $TMSCP_STEP3,TMSCPsa(%rCSR)
284 beql 3b
ff906971
KB
285#ifdef DEBUG
286 movzbl $'3,r0
287 bsbw putc
288#endif
86448185
KB
289init4: addl3 $8,%rUBADDR,r0 # start step 4
290 ashl $-16,r0,r0
291 cvtlw r0,TMSCPsa(%rCSR)
2924: bitw $TMSCP_STEP4,TMSCPsa(%rCSR)
293 beql 4b
ff906971
KB
294#ifdef DEBUG
295 movzbl $'4,r0
296 bsbw putc
297#endif
86448185
KB
298setchar:
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)
ff906971
KB
311 bsbw tmscpcmd
312#ifdef DEBUG
313 movzbl $'S,r0
314 bsbw putc
315#endif
86448185
KB
316 rsb
317
318tmscpcmd:
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
324wait: 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
3291: tstl tmscpca+4(fp)
330 beql 2f
331 clrw tmscpca+4(fp)
3322: 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
344ok: rsb
345
346rew: 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
ff906971
KB
351#ifdef DEBUG
352 movzbl $'r,r0 # to indicate r)ewind
353 bsbw putc
354#endif
86448185
KB
355 movl $-1,mtapa(fp) # no blocks read yet
356 rsb
ff906971 357
86448185
KB
358onlin: movb $M_OP_ONLIN,op(%rCMD)
359 clrw modifier(%rCMD)
360 clrl buffer(%rCMD)
361 clrl bytecnt(%rCMD)
362 bsbw tmscpcmd
ff906971
KB
363#ifdef DEBUG
364 movzbl $'O,r0 # to indicate O)nline
365 bsbw putc
366#endif
86448185 367 rsb
ff906971 368
86448185
KB
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.
371readdir: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
3791: 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
387rrec: 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
ff906971
KB
395#ifdef DEBUG
396 movzbl $'R,r0 # to indicate R)ead a record
397 bsbw putc
398#endif
86448185
KB
399 incl mtapa(fp)
400 incl r3
401 rsb
402end: