|
|
1.1 root 1: /*
2: * @(#)tmscpboot.c 7.2 (Berkeley) 1/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: * [email protected]
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.