Xinu7/src/cmd/download/vax/src/sdl.boot.s
/* dl.s -- phase0, phase1 */
#define PH1LEN r0
#define PH1ADR r1
#define DELAY r2
#define ENTRY r3
#define IOBYTE r4
#define STATUS r5
#define SIDREG r6
#include <procreg.h>
#include <vdownload.h>
/*----------------------------------------------------------------------------
* Phase 0 of downloader. Loaded at location P1BSTRT using console deposit
* commands, loading stops with the 0xffffffff value. Reads phase1 of
* the downloader from the high speed line into a high location in memory
* (address in r0) and then executes phase1. Assumes processor in kernel
* mode with interrupts disabled, memory mapping disabled, on interrupt
* stack.
*
* Arguments:
* r0 - length in bytes of phase1
* r1 - address of highest byte at which phase1 is to be loaded + 1
* r2 - time delay before performing autostart
* r3 - entry point for performing autostart (if r2 >= 0)
*----------------------------------------------------------------------------
*/
.text
phase0: /* no entry mask -- not called */
movab tmpstk, sp /* give stack some memory */
mfpr $SID, SIDREG /* get system ID, if 8600, */
bicl2 $SYSTYPE, SIDREG /* setup RXCS and TXCS */
cmpl SIDREG, $VAX8600SID
jneq loadphase1 /* if not 8600, go get input */
mtpr $RXCS8600, $RXCS /* enable 8600 console I/O */
mtpr $TXCS8600, $TXCS
loadphase1:
bsbb getbyte /* read phase1 in reverse order */
cvtlb IOBYTE, IOBYTE /* (8600) chop off high bytes */
cmpb IOBYTE, $ESC /* if escaped, get real byte */
jneq storebyte /* otherwise go on */
bsbb getbyte
bicl2 $0xffffff40, IOBYTE /* remove stuffed bit */
storebyte:
movb IOBYTE, -(PH1ADR) /* store the byte */
sobgtr PH1LEN, loadphase1 /* go back to input more */
movl PH1ADR, sp /* give stack some memory */
jmp (PH1ADR) /* run the loaded phase1 */
getbyte:
mfpr $RXCS, STATUS /* get input status */
jbc $SLURDYBIT,STATUS,getbyte/* go back if input not ready */
mfpr $RXDB, IOBYTE /* get byte and store it */
rsb
.align 2 /* align loc ctr to longword */
.long P0MARKER /* marks end of phase0 */
tmpstk: /* stack for phase 0 */
/* definitions for phase1 */
#undef PH1LEN
#define SUM r0 /* the checksum */
/* r1 is PH1ADR
r2 is DELAY
r3 is ENTRY
r4 is IOBYTE
r5 is STATUS
r6 is SIDREG */
#define LENGTH r7 /* length of packet in words */
#define BASEADR r8 /* destination addr of packet */
#define COUNT r9 /* loop control variable */
#define PACKADR r10 /* current address in packet */
#define INWORD r11 /* the current input word */
#define SAVCLKV r12 /* saved copy of clock vector */
/*-----------------------------------------------------------------------
* Phase1 -- load program into low memory over console line. Phase1 is
* loaded into high memory by phase0
*-----------------------------------------------------------------------
*/
phase1: /* no entry mask -- not called */
clrl INWORD /* initialize high word to 0 */
getsoh:
bsbw rawgetc /* scan for SOH */
cmpb IOBYTE, $SOH
jneq getsoh
clrl SUM /* start check summing */
bsbw getwsum /* get low word of base address */
movw INWORD, BASEADR
bsbw getwsum /* get high word of base address*/
insv INWORD,$16,$16,BASEADR
bsbw getwsum /* get packet length */
movl INWORD, LENGTH
cmpw LENGTH, $PACKSIZE /* test packet length */
jgtr sendnak /* invalid length--retry */
movl LENGTH, COUNT /* set up to get packet */
jeql getsum
movaw packbuf, PACKADR
getwbuf:
bsbw getwsum /* get word for packet */
movw INWORD, (PACKADR)+ /* store in buffer */
sobgtr COUNT, getwbuf /* get rest of packet */
getsum:
bsbw getwsum /* test checksum */
tstw SUM /* sum should now be zero */
jeql copypack /* yes==> copy packet to memory */
sendnak: /* invalid packet - send NAK & */
movb $NAK, IOBYTE /* retry */
bsbw rawputc
jbr getsoh
copypack: /* valid packet--place it in */
movl LENGTH, COUNT /* memory and send ACK */
jeql sendack /* zero length packet */
movaw packbuf, PACKADR
storeword:
movw (PACKADR)+, (BASEADR)+
sobgtr COUNT, storeword
sendack:
movb $ACK, IOBYTE
bsbw rawputc
tstw LENGTH /* if zero length, that's all */
jneq getsoh /* else get another packet */
tstl DELAY /* see if autostart desired */
jeql startit /* no delay, just start it */
/* if delay<0, no autostart--> */
/* wait for user to break to */
/* console mode */
jlss haltit
/* implement autostart-- UVAXI and UVAXII don't have ICCS INT bit to */
/* busy-wait on, so drop interrupt priority to count down */
movl *$CVECTOR, SAVCLKV /* save old clock vector */
movab tickhandler+1, *$CVECTOR/* point to autostart handler */
movl $100, COUNT /* counts ticks (1/100th sec) */
mtpr $-CLKINTVL, $NICR /* set up clock with timer val */
mtpr $STRTCLK, $ICCS /* (UVAXEN are hardwired) */
mtpr $CLKIPL, $IPL /* lower interrupt priority */
/* loop until DELAY == 0 if autostarting, or until user breaks into */
/* console mode, if no autostart and not UVAXII */
occupycpu:
jbr occupycpu
/* tickhandler catches clock */
.align 2 /* interrupts on interrupt stk */
tickhandler:
mtpr $CLEARINT, $ICCS /* clear clock interrupt */
decl COUNT /* count 1/100th sec ticks */
jneq 1f /* not a full second yet, go on */
decl DELAY /* decrement count of seconds */
jeql arestore /* count completed, start code */
movl $100, COUNT /* count another second */
1: rei
arestore: /* restore from autostart */
mtpr $DISABLE, $IPL /* disable interrupts */
movl SAVCLKV, *$CVECTOR /* restore old clock vector */
mtpr $0, $NICR /* restore clock */
mtpr $0, $ICCS
startit: /* go to entry point of code */
jmp (ENTRY) /* should never return */
haltit:
/* if it's a UVAXII can halt, */
/* otherwise must do tight loop */
/* (halting may cause "reboot") */
mfpr $SID, SIDREG /* get system id register value */
bicl2 $SYSTYPE, SIDREG /* mask off system id */
cmpl SIDREG, $UVAXIISID /* if UVAXII, issue halt */
jneq occupycpu /* otherwise do tight loop */
movw $QMHALT,*$QMCPMBX /* raise console prog mailbox */
halt
getwsum: /* getwsum--get word, chksuming */
bsbw getc /* get low order byte */
movb IOBYTE, INWORD
bsbw getc /* get high order byte */
insv IOBYTE,$8,$8,INWORD /* high byte into word */
addw2 INWORD, SUM /* maintain checksum */
rsb
getc: /* get byte, honoring ESC */
bsbw rawgetc
cmpb $ESC, IOBYTE /* is it the ESC? */
jneq 1f /* no ==> return the byte */
bsbw rawgetc /* yes==> get the real byte */
bicl2 $0xffffff40, IOBYTE /* remove stuffed bit */
1:
rsb
rawgetc:
mfpr $RXCS, STATUS /* get status */
jbc $SLURDYBIT,STATUS,rawgetc/* go back if input not ready */
mfpr $RXDB, IOBYTE /* get byte */
cvtlb IOBYTE, IOBYTE /* (for 8600) */
rsb
rawputc: /* rawputc -- put character */
mfpr $TXCS, STATUS /* get status */
jbc $SLURDYBIT,STATUS,rawputc/* if busy, go back */
mtpr IOBYTE, $TXDB /* send byte */
rsb
packbuf: /* phase0 leaves PACKSIZE*2 */
/* bytes here for packet buffer */