# # fake boot ROM for MicroVAX, UQSSP/MSCP disk # read boot block into memory, # and call it with parameters pointing to and used by # a device driver # # the MicroVAX ROM actually has horrible VMB in it. # this code is stuck in block 0, # with a header VMB will recognize. # the boot block is put in block 1. # VMB reads block 0; # the header tells it to read block 0 (sic); # code packaged in uvhdr.s relocates us to the # standard ROM address, moves VMB's parameters into # our standard places, and calls us. # # # KDA50 defs # .set IP,0x0 # ip register .set SA,0x2 # sa register .set STEP0,10 # STEP1 == bit 11 .set BPOWN,31 # bit 31 == port owns descriptor .set RTOC,4 # # mscp defs # packet offsets have 4 added to account for UQSSP header (mostly length) # .set m_crf,4 # command ref number .set m_unit,8 # disk unit number .set m_opcd,12 # opcode .set m_sts,14 # status (word) .set RPKSIZE,16 # as much as we want on rcv .set m_bcnt,16 # byte count .set SOSIZE,20 # as much as we send for ONLINE .set m_buff,20 # buffer address .set m_lbn,32 # block number .set SRSIZE,36 # as much as we send to read .set SOSIZE,36 # as much as we send for ONLINE .set OPONL,011 # unit online .set OPRD,041 # read block # # MicroVAX Q-bus defs # .set LMEAE,040 # bit to allow DMA from Q-bus .set ICR,0x20001f40 # where to set it # # boot ROM conventions # .set WMEM,0x200 # sp == some working memory + WMEM # usually working memory == 0 .set BSIZE,512 # size of a block .set BBLOCK,1 # boot LBN ourstack: # # here to start off, at 0xfa02 # registers: # r2 device register address # r3 unit number # r5 boot flags; ignored but preserved # sp working memory + WMEM # # registers to save: r0 r1 r3 r5 r10 r11 ap sp # rombegin: movl sp,savesp movab ourstack,sp # # init the KDA50 # bisw2 $LMEAE,*$ICR # enable dma clrw IP(r2) # reset: kick into startup 0: movw SA(r2),r7 blss oops bbc $STEP0+1,r7,0b # wait for step1 movw $0x8000,SA(r2) # no vector, ring size (2^0,2^0) 0: movw SA(r2),r7 blss oops bbc $STEP0+2,r7,0b # wait for step2 movab rsp,r6 # ring address movw r6,SA(r2) 0: movw SA(r2),r7 blss oops bbc $STEP0+3,r7,0b # wait for step3 ashl $-16,r6,r6 movw r6,SA(r2) 0: movw SA(r2),r7 blss oops bbc $STEP0+4,r7,0b # wait for step4 movw $1,SA(r2) # GO # # read boot block into bottom of memory # pushl r0 # rblk eats it movab rblk,r6 # set up device driver address subl3 $WMEM,savesp,-(sp) # physical addr # trick: we know driver doesn't use r5, so we needn't save boot flags movl $BBLOCK,r8 jsb (r6) blbc r0,oops tstl (sp)+ movl (sp)+,r0 # # start boot block # registers now: # r0 device type (unchanged) # r1 BI node number (unchanged) # r2 device register addr # r3 device unit number (unchanged) # r5 boot flags (unchanged) # r6 address of our device driver # sp `working memory + 0x200' (unchanged) # movl savesp,sp jmp 0xc-WMEM(sp) # # here when something is broken # oops: halt # # device driver; called above and by boot block and friends # # r2 device registers # r3 device unit number # r5 buffer address, relative to `working memory' (ignored) # 4(sp) physical buffer address; we use that # r8 block number # # do not destroy r1-r6 r10 r11 ap # on return, low bit of r0 set if we read it, clear if we failed # rblk: movq r10,-(sp) clrl r0 # assume failure movab cp,r10 movab rp,r11 movab rsp,r9 movzbl $OPRD,m_opcd(r10) # make READ packet movl 4+8(sp),m_buff(r10) # unmapped address movzwl $BSIZE,m_bcnt(r10) movl r8,m_lbn(r10) movzbl $SRSIZE,(r10) bsbb sendrcv beql rdone movl r3,m_unit(r10) # didn't work; make ONLINE packet movzbl $OPONL,m_opcd(r10) movzbl $SOSIZE,(r10) clrl m_bcnt(r10) # ugh clrl m_buff(r10) # ugh clrl m_lbn(r10) # ugh bsbb sendrcv bneq rfail movzbl $OPRD,m_opcd(r10) # and try read again movl 4+8(sp),m_buff(r10) movzwl $BSIZE,m_bcnt(r10) movl r8,m_lbn(r10) movzbl $SRSIZE,(r10) bsbb sendrcv bneq rfail rdone: incl r0 # success rfail: movq (sp)+,r10 rsb sendrcv: movzbl $RPKSIZE,(r11) movab m_crf(r10),RTOC(r9) movab m_crf(r11),(r9) bbss $BPOWN,(r9),0f # make response buffer available 0: bbss $BPOWN,RTOC(r9),0f # send the ONLINE packet 0: movw IP(r2),r7 # kick to make it go 0: bbs $BPOWN,(r9),0b # wait for answer tstb m_sts(r11) # tstb: ignore `already online' flag rsb # # KDB50 communication area # .align 2 savesp: .space 4 # working mem + WMEM .space 8 # crap at the top rsp: .space 4 # response descriptor .space 4 # command descriptor # # a pair of packets # +4 for length # cp: .space SRSIZE+4 # command packet rp: .space RPKSIZE+4 # response packet