1: /*
   2:  * Copyright (c) 1980, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: /* "@(#)tuboot.s	7.1 (Berkeley) 6/5/86" */
   8: 
   9: /*
  10:  * VAX tu58 console cassette boot block
  11:  *
  12:  * Helge Skrivervik CSRG/UCB 18jun83
  13:  *
  14:  * Reads a program from a rt-11 directory on tape
  15:  * and executes it.  Programs must be stripped of
  16:  * the header and is loaded ``bits as is''.
  17:  * You can return to this loader via ``ret'' as
  18:  * you are called ``calls $0,ent''.
  19:  * Error checking and recovery is almost nonexistant
  20:  * due to the severe space constraints.
  21:  *
  22:  * NOTE: Any changes to this program are likely to
  23:  *	 bring the size over 512 bytes ....
  24:  *
  25:  * Based on tp format bootstrap originally written by Thomas Ferrin.
  26:  *
  27:  */
  28:         .set    CTABLE,0x400    /* where to load the rad50 cnv table */
  29:         .set    RELOC,0x70000
  30: /* rt-11 directory definitions */
  31:         .set    DIRBLK,6        /* rt-11 directory starts at block 6 */
  32:         .set    FILSIZ,8        /* rt-11 direc entry offset for file size */
  33:         .set    ENTSIZ,14       /* size of 1 rt-11 dir entry, bytes */
  34:         .set    BLKSIZ,512      /* tape block size, bytes */
  35:         .set    NUMDIR,2        /* no. of dir blocks on tape */
  36:         .set    FNSIZ,8         /* size of rad50 filename + 2 */
  37:         .set    NAME,2          /* direc entry offset for filename */
  38:         .set    STATUS,1        /* direc entry offset for entry status */
  39: /* rt-11 directory entry status */
  40:         .set    RT_ESEG,8       /* end of directory segment */
  41:         .set    RT_NULL,2       /* empty entry */
  42:         .set    RT_FILE,4       /* valid file entry */
  43: /* processor registers and bits */
  44:         .set    RXCS,32
  45:         .set    RXDB,33
  46:         .set    TXCS,34
  47:         .set    TXDB,35
  48:         .set    RXCS_DONE,0x80
  49:         .set    TXCS_RDY,0x80
  50:         .set    TXCS_pr,7       /* bit position of TXCS ready bit */
  51:         .set    RXCS_pd,7       /* bit position of RXCS done bit */
  52: /* console storage registers and bits */
  53:         .set    CSRS,0x1c
  54:         .set    CSRD,0x1d
  55:         .set    CSTS,0x1e
  56:         .set    CSTD,0x1f
  57: /* TU commands and bits */
  58:         .set    TU_BREAK,1
  59:         .set    TU_INIT,4
  60:         .set    TU_CONTINUE,16
  61:         .set    TU_READY,7      /* bit position of CSRS ready bit */
  62:         .set    TU_PACKETLEN,8  /* length of readcom block */
  63: /* local stack variables */
  64:         .set    ext,-4                  /* file ext. */
  65:         .set    name,-20                /* 12 bytes for full name */
  66:         .set    rt_name,-20-FNSIZ       /* rad50 file name */
  67: /* reboot flags for boot */
  68:         .set    RB_ASK,3                /* ask name and come up single user */
  69: 
  70: /*
  71:  * Initialization.
  72:  */
  73: init:
  74:         .word   0               /* entry mask for dec monitor */
  75:         nop;nop;nop;nop;nop     /* some no-ops for 750 boot rom to skip */
  76:         nop;nop;nop;nop;nop
  77:         movl    $RELOC,fp       /* core loc to which to move this program */
  78:         addl3   $rt_name,fp,sp  /* set stack pointer; leave room for locals */
  79:         clrl    r0
  80: 1:
  81:         movc3   $end,(r0),(fp)  /* move boot up to relocated position */
  82:         jmp     start+RELOC
  83: 
  84: start:
  85:         mtpr    $TU_BREAK,$CSTS         /* set break condition */
  86:         clrl    r2                      /* nulls */
  87:         bsbw    xmit2                   /* wait 2 character times */
  88:         mfpr    $CSRD,r2                /* clear receive buffer */
  89:         movzwl  $TU_INIT|(TU_INIT<<8),r2        /* load 2 INIT opcodes */
  90:         bsbw    xmit2                   /* xmit 'em */
  91: 1:
  92:         mfpr    $CSRD,r7                /* get recv data */
  93:         cmpb    r7,$TU_CONTINUE         /* is it a continue flag? */
  94:         bneq    1b                      /* nope, look more */
  95: 
  96:         movab   name(fp),r4             /* start of filename storage */
  97:         clrq    (r4)                    /* init name field */
  98:         clrq    name+8(fp)
  99:         clrq    rt_name(fp)             /* init rad50 filename */
 100:         movzbl  $'=,r0                  /* prompt character */
 101:         bsbw    putc                    /* output char to main console */
 102: 
 103: /*
 104:  * Read in a file name from console.
 105:  */
 106:         movl    r4,r1                   /* loc at which to store file name */
 107: nxtc:
 108:         bsbw    getc                    /* get input char's in file name */
 109:         cmpb    r0,$012                 /* terminator ? */
 110:         beql    nullc
 111:         movb    r0,(r1)+
 112:         brb     nxtc
 113: nullc:
 114:         cmpl    r4,r1
 115:         beql    start                   /* restart if empty string */
 116:         clrb    (r1)                    /* add null byte at end */
 117: 
 118: /*
 119:  * User-specified filename has been stored at name(fp),
 120:  * read the entire directory contents into low core.
 121:  */
 122: dirred:
 123:         movl    $DIRBLK,r10             /* directory starts at block DIRBLK */
 124:         movl    $(NUMDIR*BLKSIZ),r6     /* no. bytes in total dir */
 125:         clrl    r11                     /* start address */
 126:         bsbw    taper                   /* read no. bytes indicated */
 127: /*
 128:  * Read in the character conversion table which reside in block 1
 129:  * (the second block) on the cassette. Place it after the directory
 130:  * on low core (from 0x400).
 131:  */
 132:         movl    $1,r10                  /* block number */
 133:         movl    $BLKSIZ,r6              /* read one block */
 134:         bsbw    taper
 135: 
 136: /*
 137:  * Convert the ascii filename to rad50.
 138:  * R4 still points to name(fp)
 139:  */
 140:         movl    $6,r3                   /* max length of filename */
 141: 1:
 142:         cmpb    $'.,(r4)+               /* look for '.' */
 143:         beql    1f
 144:         sobgtr  r3,1b
 145:         incl    r4                      /* point past '.' if ext is present */
 146: 1:
 147:         clrb    -1(r4)                  /* end name with null */
 148:         movl    $3,r3                   /* max length of extension */
 149:         movab   ext(fp),r5              /* place extension here */
 150: 1:
 151:         movb    (r4)+,(r5)+
 152:         beql    1f                      /* the string is null terminated */
 153:         sobgtr  r3,1b
 154: 1:
 155:         movab   name(fp),r4
 156:         movab   rt_name(fp),r5          /* ptr to rad50 name */
 157:         bsbw    rad50                   /* convert filename */
 158:         movab   ext(fp),r4
 159:         movab   rt_name+4(fp),r5
 160:         bsbw    rad50                   /* convert extension */
 161: 
 162: /*
 163:  * Search entire directory for user-specified file name.
 164:  */
 165: 
 166:         movab   rt_name(fp),r4          /* search for this file */
 167:         movl    $10,r5                  /* point to first file entry */
 168:         movzwl  -2(r5),r10              /* r10 = block # where files begin */
 169: 2:
 170:         cmpc3   $6,NAME(r5),(r4)        /* see if dir entry matches filename */
 171:         beql    fndfil                  /* found match */
 172: 1:
 173:         addw2   FILSIZ(r5),r10          /* add file length to block pointer */
 174:         addl2   $ENTSIZ,r5              /* move to next entry */
 175: #	cpmb  STATUS(r5),$RT_NULL     /* check if deleted file */
 176: #	beql  1b /* not really necessary since deleted entries will fail */
 177:                    /* to compare anyway */
 178:         cmpb    STATUS(r5),$RT_ESEG     /* check if end of segment */
 179:         bneq    2b
 180:         brw     start                   /* entry not in directory; start over */
 181: 
 182: /*
 183:  * Found desired directory entry
 184:  */
 185: fndfil:
 186:                                         /* start block no., 2 bytes in r10 */
 187:         movzwl  FILSIZ(r5),r6           /* file size (blocks) */
 188:         mull2   $BLKSIZ,r6              /* file size (bytes) */
 189:         cmpl    r6,$RELOC-512           /* check if file fits below stack */
 190:         blss    filok
 191:         brw     start                   /* file too large */
 192: 
 193: /*
 194:  * Read in desired file from tape.
 195:  */
 196: filok:
 197:         movl    r6,r5                   /* start of bss space */
 198:         clrl    r11                     /* start address */
 199:         bsbb    taper
 200: 
 201: /*
 202:  * Clear core.
 203:  */
 204:         subl3   r5,$RELOC-4,r0          /* no. bytes to clear */
 205: 1:
 206:         clrb    (r5)+
 207:         sobgtr  r0,1b
 208: 
 209: /*
 210:  * Jump to start of file & execute.
 211:  */
 212:         addl3   $20,fp,ap               /* ?? */
 213:         clrl    r5
 214:         movl    $RB_ASK,r11
 215:         calls   $0,(r5)
 216: bad:
 217:         brw     start
 218: 
 219: /*
 220:  * Read (r6) bytes from block (r10)
 221:  * into loc (r11).
 222:  */
 223: taper:
 224:         clrl    r8                      /* initialize checksum */
 225:         movab   readcom,r0              /* read command packet addr */
 226:         movzbl  $TU_PACKETLEN/2,r1	/* size of readcom block */
 227: 1:
 228:         movzwl  (r0)+,r2                /* get 2 chars from block */
 229:         bsbb    xmit                    /* xmit and update ckecksum */
 230:         sobgtr  r1,1b                   /* loop if more */
 231: 
 232: /*
 233:  * Now do variable part of packet.
 234:  */
 235:         movl    r6,r2                   /* byte count */
 236:         bsbb    xmit
 237:         movl    r10,r2                  /* starting block number */
 238:         bsbb    xmit
 239:         movzwl  r8,r2                   /* accumulated ckecksum */
 240:         bsbb    xmit
 241: 
 242: /*
 243:  * Collect read packet from device.
 244:  */
 245: 1:
 246:         bsbb    recv2                   /* get 2 packet characters */
 247:         decb    r2                      /* data packet? */
 248:         bneq    1f                      /* branch on end of data */
 249:         movzbl  r1,r8                   /* get byte count of packet */
 250: 
 251: /*
 252:  * Read data into memory.
 253:  */
 254: 2:
 255:         bsbb    recv1                   /* get a char */
 256:         movb    r1,(r11)+               /* stuff into memory */
 257:         sobgtr  r8,2b                   /* loop if more */
 258:         bsbb    recv2                   /* skip checksum */
 259:         brb     1b                      /* read next packet */
 260: 
 261: /*
 262:  * End of data xfer; check for errors.
 263:  */
 264: 1:
 265:         bsbb    recv2                   /* get success code */
 266:         tstl    r1                      /* error in read? */
 267:         blss    9f                      /* branch if status error */
 268:         movl    $5,r0
 269: 1:
 270:         bsbb    recv2                   /* discard 10 bytes */
 271:         sobgtr  r0,1b
 272:         rsb
 273: 
 274: /* Fatal error */
 275: 9:
 276:         movab   ermsg,r1
 277: 1:
 278:         movb    (r1)+,r0
 279:         beql    bad
 280:         bsbb    putc
 281:         brb     1b
 282: 
 283: /*
 284:  * Update checksum in r8 and xmit 2 characters.
 285:  */
 286: xmit:
 287:         addw2   r2,r8                   /* update checksum */
 288:         adwc    $0,r8                   /* add  in carry */
 289: 
 290: /* send the 2 characters contained in r2 */
 291: xmit2:
 292:         bsbb    1f                      /* xmit one of 'em */
 293:         ashl    $-8,r2,r2               /* get next char */
 294:                                         /* fall into... */
 295: 1:
 296:         mfpr    $CSTS,r7                /* get xmit status */
 297:         bbc     $TU_READY,r7,1b         /* loop until ready */
 298:         mtpr    r2,$CSTD                /* send char */
 299:         rsb
 300: 
 301: /*
 302:  * Receive 2 characters, return in r2 and r1.
 303:  */
 304: recv2:
 305:         bsbb    recv1                   /* recv one of 'em */
 306:                                         /* fall into... */
 307: 
 308: /*
 309:  * Receive 1 character.
 310:  */
 311: recv1:
 312:         movzbl  r1,r2                   /* save previous byte */
 313: 1:
 314:         mfpr    $CSRS,r7                /* get recv status */
 315:         bbc     $TU_READY,r7,1b         /* loop until ready */
 316:         mfpr    $CSRD,r1                /* get char */
 317:         blss    9b                      /* branch on recv error */
 318:         rsb
 319: 
 320: getc:
 321:         mfpr    $RXCS,r0
 322:         bbc     $RXCS_pd,r0,getc        /* receiver ready ? */
 323:         mfpr    $RXDB,r0
 324:         extzv   $0,$7,r0,r0
 325:         cmpb    r0,$015
 326:         bneq    putc                    /* echo and return */
 327:         bsbb    putc                    /* carriage return */
 328: #	movb  $0,r0
 329: #	bsbb  putc                    /* delay */
 330:         movb    $012,r0                 /* send line feed and return */
 331: putc:
 332:         mfpr    $TXCS,r2
 333:         bbc     $TXCS_pr,r2,putc        /* transmitter ready ? */
 334:         mtpr    r0,$TXDB
 335:         rsb
 336: 
 337: /*
 338:  * Convert the filename given from the console
 339:  * to radix 50 (rt-11) format.
 340:  */
 341: rad50:
 342:         clrw    r1
 343:         bsbb    getb50                  /* get next ascii byte, exit if null */
 344:         mull3   $03100,r0,r1
 345:         bsbb    getb50
 346:         mull3   $050,r0,r2
 347:         addl2   r2,r1
 348:         bsbb    getb50
 349:         addl2   r0,r1                   /* last byte, just add it in */
 350:         movw    r1,(r5)+                /* save result */
 351:         brb     rad50
 352: 
 353: getb50:
 354:         movzbl  (r4)+,r0                /* get next ascii byte */
 355:         beql    1f                      /* if zero: end of string */
 356:         movzbl  CTABLE(r0),r0           /* and get the r50 byte from the table*/
 357:         rsb
 358: 1:
 359:         tstl    (sp)+                   /* we're through, get back to where */
 360:                                         /* rad50 was called */
 361:         movw    r1,(r5)                 /* but first save the result */
 362:         rsb
 363: 
 364:         .align  2
 365: readcom:
 366:         .byte   2                       /* command packet flag */
 367:         .byte   10                      /* number of bytes in message */
 368:         .byte   2                       /* tu read opcode */
 369:         .byte   0                       /* modifier */
 370:         .byte   0                       /* unit number */
 371:         .byte   0                       /* switches */
 372:         .word   0                       /* sequence number */
 373:                                         /* byte count and block number follow */
 374: 
 375: ermsg:
 376:         .asciz  "tuerr\r\n"
 377: end:
 378: 
 379: /*
 380:  * Ascii to rad 50 conversion table,
 381:  * stored on the second block on the cassette
 382:  *
 383:  * NOTE: Always make sure this table ends up
 384:  * starting at byte 512!!!!
 385:  */
 386:         .align  2
 387:         .data   2
 388:         .long   0x1d1d1d1d
 389:         .long   0x1d1d1d1d
 390:         .long   0x1d1d1d1d
 391:         .long   0x1d1d1d1d
 392:         .long   0x1d1d1d1d
 393:         .long   0x1d1d1d1d
 394:         .long   0x1d1d1d1d
 395:         .long   0x1d1d1d1d
 396:         .long   0x1d1d1d00
 397:         .long   0x1d1d1d1b
 398:         .long   0x1d1d1d1d
 399:         .long   0x1d1c1d1d
 400:         .long   0x21201f1e
 401:         .long   0x25242322
 402:         .long   0x1d1d2726
 403:         .long   0x1d1d1d1d
 404:         .long   0x302011d
 405:         .long   0x7060504
 406:         .long   0xb0a0908
 407:         .long   0xf0e0d0c
 408:         .long   0x13121110
 409:         .long   0x17161514
 410:         .long   0x1d1a1918
 411:         .long   0x1d1d1d1d
 412:         .long   0x302011d
 413:         .long   0x7060504
 414:         .long   0xb0a0908
 415:         .long   0xf0e0d0c
 416:         .long   0x13121110
 417:         .long   0x17161514
 418:         .long   0x1d1a1918
 419:         .long   0x1d1d1d1d
 420:         .long   0x1d1d1d1d
 421:         .long   0x1d1d1d1d
 422:         .long   0x1d1d1d1d
 423:         .long   0x1d1d1d1d
 424:         .long   0x1d1d1d1d
 425:         .long   0x1d1d1d1d
 426:         .long   0x1d1d1d1d
 427:         .long   0x1d1d1d1d
 428:         .long   0x1d1d1d00
 429:         .long   0x1d1d1d1b
 430:         .long   0x1d1d1d1d
 431:         .long   0x1d1c1d1d
 432:         .long   0x21201f1e
 433:         .long   0x25242322
 434:         .long   0x1d1d2726
 435:         .long   0x1d1d1d1d
 436:         .long   0x302011d
 437:         .long   0x7060504
 438:         .long   0xb0a0908
 439:         .long   0xf0e0d0c
 440:         .long   0x13121110
 441:         .long   0x17161514
 442:         .long   0x1d1a1918
 443:         .long   0x1d1d1d1d
 444:         .long   0x302011d
 445:         .long   0x7060504
 446:         .long   0xb0a0908
 447:         .long   0xf0e0d0c
 448:         .long   0x13121110
 449:         .long   0x17161514
 450:         .long   0x1d1a1918
 451:         .long   0x1d1d1d
 452:         .data

Defined functions

bad defined in line 216; used 1 times
dirred defined in line 122; never used
end defined in line 377; used 1 times
  • in line 81
ermsg defined in line 375; used 1 times
filok defined in line 196; used 1 times
fndfil defined in line 185; used 1 times
getb50 defined in line 353; used 3 times
getc defined in line 320; used 2 times
init defined in line 73; never used
nullc defined in line 113; used 1 times
nxtc defined in line 107; used 1 times
putc defined in line 331; used 5 times
rad50 defined in line 341; used 3 times
readcom defined in line 365; used 1 times
recv1 defined in line 311; used 2 times
recv2 defined in line 304; used 4 times
start defined in line 84; used 5 times
taper defined in line 223; used 3 times
xmit defined in line 286; used 4 times
xmit2 defined in line 291; used 2 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 774
Valid CSS Valid XHTML 1.0 Strict