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

1.1       root        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

unix.superglobalmegacorp.com

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