|
|
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.