Annotation of 42BSD/sys/mdec/tuboot.s, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.