Commit | Line | Data |
---|---|---|
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 */ | |
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: | |
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 | |
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 | |
ff906971 KB |
270 | #ifdef DEBUG |
271 | movzbl $'1,r0 | |
272 | bsbw putc | |
273 | #endif | |
86448185 KB |
274 | init2: movw $TMSCP_ERR,TMSCPsa(%rCSR) # start step 2 |
275 | 2: bitw $TMSCP_STEP2,TMSCPsa(%rCSR) | |
276 | beql 2b | |
ff906971 KB |
277 | #ifdef DEBUG |
278 | movzbl $'2,r0 | |
279 | bsbw putc | |
280 | #endif | |
86448185 KB |
281 | init3: addl3 $8,%rUBADDR,r0 # start step 3 |
282 | cvtlw r0,TMSCPsa(%rCSR) | |
283 | 3: bitw $TMSCP_STEP3,TMSCPsa(%rCSR) | |
284 | beql 3b | |
ff906971 KB |
285 | #ifdef DEBUG |
286 | movzbl $'3,r0 | |
287 | bsbw putc | |
288 | #endif | |
86448185 KB |
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 | |
ff906971 KB |
294 | #ifdef DEBUG |
295 | movzbl $'4,r0 | |
296 | bsbw putc | |
297 | #endif | |
86448185 KB |
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) | |
ff906971 KB |
311 | bsbw tmscpcmd |
312 | #ifdef DEBUG | |
313 | movzbl $'S,r0 | |
314 | bsbw putc | |
315 | #endif | |
86448185 KB |
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 | |
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 |
358 | onlin: 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. | |
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 | |
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 | |
402 | end: |