1*11099Ssam /* tuboot.c 4.1 83/02/16 */ 2*11099Ssam 3*11099Ssam /* 4*11099Ssam * VAX tu58 console cassette boot block 5*11099Ssam * 6*11099Ssam * Thomas Ferrin 27oct82 7*11099Ssam * 8*11099Ssam * Reads a program from a tp directory on tape 9*11099Ssam * and executes it. Program must be stripped of 10*11099Ssam * the header and is loaded ``bits as is''. 11*11099Ssam * You can return to this loader via ``ret'' as 12*11099Ssam * you are called ``calls $0,ent''. 13*11099Ssam */ 14*11099Ssam .set RELOC,0x70000 15*11099Ssam /* a.out defines */ 16*11099Ssam .set HDRSIZ,040 /* size of file header for VAX */ 17*11099Ssam .set MAGIC,0410 /* file type id in header */ 18*11099Ssam .set TSIZ,4 /* text size */ 19*11099Ssam .set DSIZ,8 /* data size */ 20*11099Ssam .set BSIZ,12 /* bss size */ 21*11099Ssam .set TENT,024 /* task header entry loc */ 22*11099Ssam /* tp directory definitions */ 23*11099Ssam /* .set DIRBLK,8 /* tp directory starts at block 8 */ 24*11099Ssam .set DIRBLK,1 /* tp directory starts at block 1 */ 25*11099Ssam .set FILSIZ,38 /* tp direc offset for file size */ 26*11099Ssam .set BNUM,44 /* tp dir offset for start block no. */ 27*11099Ssam .set ENTSIZ,64 /* size of 1 TP dir entry, bytes */ 28*11099Ssam .set PTHSIZ,32 /* size of TP path name, bytes */ 29*11099Ssam .set BLKSIZ,512 /* tape block size, bytes */ 30*11099Ssam .set NUMDIR,24 /* no. of dir blocks on tape */ 31*11099Ssam .set ENTBLK,8 /* no. of dir entries per tape block */ 32*11099Ssam /* processor registers and bits */ 33*11099Ssam .set RXCS,32 34*11099Ssam .set RXDB,33 35*11099Ssam .set TXCS,34 36*11099Ssam .set TXDB,35 37*11099Ssam .set RXCS_DONE,0x80 38*11099Ssam .set TXCS_RDY,0x80 39*11099Ssam .set TXCS_pr,7 /* bit position of TXCS ready bit */ 40*11099Ssam .set RXCS_pd,7 /* bit position of RXCS done bit */ 41*11099Ssam /* console storage registers and bits */ 42*11099Ssam .set CSRS,0x1c 43*11099Ssam .set CSRD,0x1d 44*11099Ssam .set CSTS,0x1e 45*11099Ssam .set CSTD,0x1f 46*11099Ssam /* TU commands and bits */ 47*11099Ssam .set TU_BREAK,1 48*11099Ssam .set TU_INIT,4 49*11099Ssam .set TU_CONTINUE,16 50*11099Ssam .set TU_READY,7 /* bit position of CSRS ready bit */ 51*11099Ssam .set TU_PACKETLEN,8 /* length of readcom block */ 52*11099Ssam /* local stack variables */ 53*11099Ssam .set tapa,-4 /* desired tape addr */ 54*11099Ssam .set name,-8-PTHSIZ /* operator-typed file name */ 55*11099Ssam /* ===== */ 56*11099Ssam 57*11099Ssam /* initialization */ 58*11099Ssam init: 59*11099Ssam .word 0 /* entry mask for dec monitor */ 60*11099Ssam nop;nop;nop;nop;nop /* some no-ops for 750 boot rom to skip */ 61*11099Ssam nop;nop;nop;nop;nop 62*11099Ssam movl $RELOC,fp /* core loc to which to move this program */ 63*11099Ssam addl3 $name,fp,sp /* set stack pointer; leave room for locals */ 64*11099Ssam clrl r0 65*11099Ssam 1: 66*11099Ssam movc3 $end,(r0),(fp) /* move boot up to relocated position */ 67*11099Ssam jmp start+RELOC 68*11099Ssam 69*11099Ssam start: 70*11099Ssam /* init tu58 */ 71*11099Ssam mtpr $TU_BREAK,$CSTS /* set break condition */ 72*11099Ssam clrl r2 /* nulls */ 73*11099Ssam bsbw xmit2 /* wait 2 character times */ 74*11099Ssam mfpr $CSRD,r2 /* clear receive buffer */ 75*11099Ssam movzwl $TU_INIT|(TU_INIT<<8),r2 /* load 2 INIT opcodes */ 76*11099Ssam bsbw xmit2 /* xmit 'em */ 77*11099Ssam 1: 78*11099Ssam mfpr $CSRD,r7 /* get recv data */ 79*11099Ssam cmpb r7,$TU_CONTINUE /* is it a continue flag? */ 80*11099Ssam bneq 1b /* nope, look more */ 81*11099Ssam 82*11099Ssam movab name(fp),r4 /* start of filename storage */ 83*11099Ssam movzbl $'=,r0 /* prompt character */ 84*11099Ssam bsbw putc /* output char to main console */ 85*11099Ssam 86*11099Ssam /* read in a file name */ 87*11099Ssam movl r4,r1 /* loc at which to store file name */ 88*11099Ssam nxtc: 89*11099Ssam bsbw getc /* get input char's in file name */ 90*11099Ssam cmpb r0,$012 /* terminator ? */ 91*11099Ssam beql nullc 92*11099Ssam movb r0,(r1)+ 93*11099Ssam brb nxtc 94*11099Ssam nullc: 95*11099Ssam subl3 r4,r1,r9 /* size of path name */ 96*11099Ssam beql start /* dumb operator */ 97*11099Ssam clrb (r1)+ 98*11099Ssam incl r9 99*11099Ssam 100*11099Ssam /* user-specified tp filename has been stored at name(fp) */ 101*11099Ssam /* read in entire tp directory contents into low core */ 102*11099Ssam dirred: 103*11099Ssam movl $DIRBLK,tapa(fp) /* tp directory starts at block DIRBLK */ 104*11099Ssam movl $(NUMDIR*BLKSIZ),r6 /* no. bytes in total dir */ 105*11099Ssam bsbw taper /* read no. bytes indicated */ 106*11099Ssam 107*11099Ssam /* search entire directory for user-specified file name */ 108*11099Ssam clrl r5 /* dir buff loc = 0 */ 109*11099Ssam nxtdir: 110*11099Ssam cmpc3 r9,(r5),(r4) /* see if dir entry matches filename */ 111*11099Ssam beql fndfil /* found match */ 112*11099Ssam acbl $NUMDIR*BLKSIZ-1,$ENTSIZ,r5,nxtdir 113*11099Ssam /* see if done with tp dir */ 114*11099Ssam brw start /* entry not in directory; start over */ 115*11099Ssam 116*11099Ssam /* found desired tp dir entry */ 117*11099Ssam fndfil: 118*11099Ssam movzwl BNUM(r5),tapa(fp) /* start block no., 2 bytes */ 119*11099Ssam addl2 $DIRBLK-1,tapa(fp) /* skip boot block(s) */ 120*11099Ssam movzwl FILSIZ(r5),r6 /* low 2 bytes file size */ 121*11099Ssam insv FILSIZ-1(r5),$16,$8,r6 /* file size, high byte */ 122*11099Ssam cmpl r6,$RELOC-512 /* check if file fits below stack */ 123*11099Ssam blss filok /* file o.k. */ 124*11099Ssam brw start /* file too large */ 125*11099Ssam 126*11099Ssam /* time to read in desired file from tape */ 127*11099Ssam filok: 128*11099Ssam movl r6,r5 /* start of bss space */ 129*11099Ssam bsbb taper 130*11099Ssam bsbb rew 131*11099Ssam 132*11099Ssam /* clear core */ 133*11099Ssam subl3 r5,$RELOC-4,r0 /* no. bytes to clear */ 134*11099Ssam 1: 135*11099Ssam clrb (r5)+ 136*11099Ssam sobgtr r0,1b 137*11099Ssam 138*11099Ssam /* time to jump to start of file & execute */ 139*11099Ssam addl3 $20,fp,ap 140*11099Ssam clrl r5 141*11099Ssam calls $0,(r5) 142*11099Ssam bad: 143*11099Ssam brw start 144*11099Ssam 145*11099Ssam /* rewind tape */ 146*11099Ssam rew: 147*11099Ssam movb $5,readcom+2 /* position opcode */ 148*11099Ssam clrl tapa(fp) /* block 0 */ 149*11099Ssam clrl r6 /* 0 bytes */ 150*11099Ssam bsbb taper 151*11099Ssam movb $2,readcom+2 /* read opcode */ 152*11099Ssam rsb 153*11099Ssam 154*11099Ssam /* read (r6) bytes from tapa(fp) into loc 0 */ 155*11099Ssam taper: 156*11099Ssam clrl r8 /* initialize checksum */ 157*11099Ssam movab readcom,r0 /* read command packet addr */ 158*11099Ssam movzbl $TU_PACKETLEN/2,r1 /* size of readcom block */ 159*11099Ssam 1: 160*11099Ssam movzwl (r0)+,r2 /* get 2 chars from block */ 161*11099Ssam bsbb xmit /* xmit and update ckecksum */ 162*11099Ssam sobgtr r1,1b /* loop if more */ 163*11099Ssam 164*11099Ssam /* now do variable part of packet */ 165*11099Ssam movl r6,r2 /* byte count */ 166*11099Ssam bsbb xmit 167*11099Ssam movzwl tapa(fp),r2 /* starting block number */ 168*11099Ssam bsbb xmit 169*11099Ssam movzwl r8,r2 /* accumulated ckecksum */ 170*11099Ssam bsbb xmit 171*11099Ssam 172*11099Ssam /* collect read packet from device */ 173*11099Ssam clrl r0 /* starting addr */ 174*11099Ssam 1: 175*11099Ssam bsbb recv2 /* get 2 packet characters */ 176*11099Ssam decb r2 /* data packet? */ 177*11099Ssam bneq 1f /* branch on end of data */ 178*11099Ssam movzbl r1,r8 /* get byte count of packet */ 179*11099Ssam 180*11099Ssam /* read data into memory */ 181*11099Ssam 2: 182*11099Ssam bsbb recv1 /* get a char */ 183*11099Ssam movb r1,(r0)+ /* stuff into memory */ 184*11099Ssam sobgtr r8,2b /* loop if more */ 185*11099Ssam bsbb recv2 /* skip checksum */ 186*11099Ssam brb 1b /* read next packet */ 187*11099Ssam 188*11099Ssam /* end of data xfer; check for errors */ 189*11099Ssam 1: 190*11099Ssam subl2 r6,r0 /* all bytes xfered? */ 191*11099Ssam bneq 9f /* nope, error */ 192*11099Ssam bsbb recv2 /* get success code */ 193*11099Ssam tstl r1 /* error in read? */ 194*11099Ssam blss 9f /* branch if status error */ 195*11099Ssam movl $5,r0 196*11099Ssam 1: 197*11099Ssam bsbb recv2 /* discard 10 bytes */ 198*11099Ssam sobgtr r0,1b 199*11099Ssam rsb 200*11099Ssam 201*11099Ssam /* fatal error */ 202*11099Ssam 9: 203*11099Ssam movab ermsg,r1 204*11099Ssam 1: 205*11099Ssam movb (r1)+,r0 206*11099Ssam beql bad 207*11099Ssam bsbb putc 208*11099Ssam brb 1b 209*11099Ssam 210*11099Ssam /* update checksum in r8 and xmit 2 characters */ 211*11099Ssam xmit: 212*11099Ssam addw2 r2,r8 /* update checksum */ 213*11099Ssam bcc xmit2 /* branch if no overflow */ 214*11099Ssam incw r8 /* add in carry */ 215*11099Ssam 216*11099Ssam /* send the 2 characters contained in r2 */ 217*11099Ssam xmit2: 218*11099Ssam bsbb 1f /* xmit one of 'em */ 219*11099Ssam ashl $-8,r2,r2 /* get next char */ 220*11099Ssam /* fall into... */ 221*11099Ssam 1: 222*11099Ssam mfpr $CSTS,r7 /* get xmit status */ 223*11099Ssam bbc $TU_READY,r7,1b /* loop until ready */ 224*11099Ssam mtpr r2,$CSTD /* send char */ 225*11099Ssam rsb 226*11099Ssam 227*11099Ssam /* receive 2 characters, return in r2 and r1 */ 228*11099Ssam recv2: 229*11099Ssam bsbb recv1 /* recv one of 'em */ 230*11099Ssam /* fall into... */ 231*11099Ssam 232*11099Ssam /* receive 1 character */ 233*11099Ssam recv1: 234*11099Ssam movzbl r1,r2 /* save previous byte */ 235*11099Ssam 1: 236*11099Ssam mfpr $CSRS,r7 /* get recv status */ 237*11099Ssam bbc $TU_READY,r7,1b /* loop until ready */ 238*11099Ssam mfpr $CSRD,r1 /* get char */ 239*11099Ssam blss 9b /* branch on recv error */ 240*11099Ssam rsb 241*11099Ssam 242*11099Ssam getc: 243*11099Ssam mfpr $RXCS,r0 244*11099Ssam bbc $RXCS_pd,r0,getc /* receiver ready ? */ 245*11099Ssam mfpr $RXDB,r0 246*11099Ssam extzv $0,$7,r0,r0 247*11099Ssam cmpb r0,$015 248*11099Ssam bneq putc /* echo and return */ 249*11099Ssam bsbb putc /* carriage return */ 250*11099Ssam movb $0,r0 251*11099Ssam bsbb putc /* delay */ 252*11099Ssam movb $012,r0 /* send line feed and return */ 253*11099Ssam putc: 254*11099Ssam mfpr $TXCS,r2 255*11099Ssam bbc $TXCS_pr,r2,putc /* transmitter ready ? */ 256*11099Ssam extzv $0,$7,r0,r0 257*11099Ssam mtpr r0,$TXDB 258*11099Ssam rsb 259*11099Ssam 260*11099Ssam .align 2 261*11099Ssam readcom: 262*11099Ssam .byte 2 /* command packet flag */ 263*11099Ssam .byte 10 /* number of bytes in message */ 264*11099Ssam .byte 2 /* tu read opcode */ 265*11099Ssam .byte 0 /* modifier */ 266*11099Ssam .byte 0 /* unit number */ 267*11099Ssam .byte 0 /* switches */ 268*11099Ssam .word 0 /* sequence number */ 269*11099Ssam /* byte count and block number follow */ 270*11099Ssam 271*11099Ssam ermsg: 272*11099Ssam .asciz "tu58 err\r\n" 273*11099Ssam end: 274