|
|
1.1 root 1: #
2: # fake boot ROM for MicroVAX, UQSSP/MSCP disk
3: # read boot block into memory,
4: # and call it with parameters pointing to and used by
5: # a device driver
6: #
7: # the MicroVAX ROM actually has horrible VMB in it.
8: # this code is stuck in block 0,
9: # with a header VMB will recognize.
10: # the boot block is put in block 1.
11: # VMB reads block 0;
12: # the header tells it to read block 0 (sic);
13: # code packaged in uvhdr.s relocates us to the
14: # standard ROM address, moves VMB's parameters into
15: # our standard places, and calls us.
16: #
17:
18: #
19: # KDA50 defs
20: #
21: .set IP,0x0 # ip register
22: .set SA,0x2 # sa register
23:
24: .set STEP0,10 # STEP1 == bit 11
25:
26: .set BPOWN,31 # bit 31 == port owns descriptor
27: .set RTOC,4
28:
29: #
30: # mscp defs
31: # packet offsets have 4 added to account for UQSSP header (mostly length)
32: #
33:
34: .set m_crf,4 # command ref number
35: .set m_unit,8 # disk unit number
36: .set m_opcd,12 # opcode
37: .set m_sts,14 # status (word)
38: .set RPKSIZE,16 # as much as we want on rcv
39: .set m_bcnt,16 # byte count
40: .set SOSIZE,20 # as much as we send for ONLINE
41: .set m_buff,20 # buffer address
42: .set m_lbn,32 # block number
43: .set SRSIZE,36 # as much as we send to read
44: .set SOSIZE,36 # as much as we send for ONLINE
45:
46: .set OPONL,011 # unit online
47: .set OPRD,041 # read block
48:
49: #
50: # MicroVAX Q-bus defs
51: #
52: .set LMEAE,040 # bit to allow DMA from Q-bus
53: .set ICR,0x20001f40 # where to set it
54:
55: #
56: # boot ROM conventions
57: #
58: .set WMEM,0x200 # sp == some working memory + WMEM
59: # usually working memory == 0
60: .set BSIZE,512 # size of a block
61: .set BBLOCK,1 # boot LBN
62:
63: ourstack:
64: #
65: # here to start off, at 0xfa02
66: # registers:
67: # r2 device register address
68: # r3 unit number
69: # r5 boot flags; ignored but preserved
70: # sp working memory + WMEM
71: #
72: # registers to save: r0 r1 r3 r5 r10 r11 ap sp
73: #
74: rombegin:
75: movl sp,savesp
76: movab ourstack,sp
77:
78: #
79: # init the KDA50
80: #
81:
82: bisw2 $LMEAE,*$ICR # enable dma
83: clrw IP(r2) # reset: kick into startup
84: 0: movw SA(r2),r7
85: blss oops
86: bbc $STEP0+1,r7,0b # wait for step1
87: movw $0x8000,SA(r2) # no vector, ring size (2^0,2^0)
88: 0: movw SA(r2),r7
89: blss oops
90: bbc $STEP0+2,r7,0b # wait for step2
91: movab rsp,r6 # ring address
92: movw r6,SA(r2)
93: 0: movw SA(r2),r7
94: blss oops
95: bbc $STEP0+3,r7,0b # wait for step3
96: ashl $-16,r6,r6
97: movw r6,SA(r2)
98: 0: movw SA(r2),r7
99: blss oops
100: bbc $STEP0+4,r7,0b # wait for step4
101: movw $1,SA(r2) # GO
102:
103: #
104: # read boot block into bottom of memory
105: #
106:
107: pushl r0 # rblk eats it
108: movab rblk,r6 # set up device driver address
109: subl3 $WMEM,savesp,-(sp) # physical addr
110: # trick: we know driver doesn't use r5, so we needn't save boot flags
111: movl $BBLOCK,r8
112: jsb (r6)
113: blbc r0,oops
114: tstl (sp)+
115: movl (sp)+,r0
116: #
117: # start boot block
118: # registers now:
119: # r0 device type (unchanged)
120: # r1 BI node number (unchanged)
121: # r2 device register addr
122: # r3 device unit number (unchanged)
123: # r5 boot flags (unchanged)
124: # r6 address of our device driver
125: # sp `working memory + 0x200' (unchanged)
126: #
127: movl savesp,sp
128: jmp 0xc-WMEM(sp)
129:
130: #
131: # here when something is broken
132: #
133: oops: halt
134:
135: #
136: # device driver; called above and by boot block and friends
137: #
138: # r2 device registers
139: # r3 device unit number
140: # r5 buffer address, relative to `working memory' (ignored)
141: # 4(sp) physical buffer address; we use that
142: # r8 block number
143: #
144: # do not destroy r1-r6 r10 r11 ap
145: # on return, low bit of r0 set if we read it, clear if we failed
146: #
147:
148: rblk:
149: movq r10,-(sp)
150: clrl r0 # assume failure
151: movab cp,r10
152: movab rp,r11
153: movab rsp,r9
154: movzbl $OPRD,m_opcd(r10) # make READ packet
155: movl 4+8(sp),m_buff(r10) # unmapped address
156: movzwl $BSIZE,m_bcnt(r10)
157: movl r8,m_lbn(r10)
158: movzbl $SRSIZE,(r10)
159: bsbb sendrcv
160: beql rdone
161: movl r3,m_unit(r10) # didn't work; make ONLINE packet
162: movzbl $OPONL,m_opcd(r10)
163: movzbl $SOSIZE,(r10)
164: clrl m_bcnt(r10) # ugh
165: clrl m_buff(r10) # ugh
166: clrl m_lbn(r10) # ugh
167: bsbb sendrcv
168: bneq rfail
169: movzbl $OPRD,m_opcd(r10) # and try read again
170: movl 4+8(sp),m_buff(r10)
171: movzwl $BSIZE,m_bcnt(r10)
172: movl r8,m_lbn(r10)
173: movzbl $SRSIZE,(r10)
174: bsbb sendrcv
175: bneq rfail
176: rdone: incl r0 # success
177: rfail: movq (sp)+,r10
178: rsb
179:
180: sendrcv:
181: movzbl $RPKSIZE,(r11)
182: movab m_crf(r10),RTOC(r9)
183: movab m_crf(r11),(r9)
184: bbss $BPOWN,(r9),0f # make response buffer available
185: 0: bbss $BPOWN,RTOC(r9),0f # send the ONLINE packet
186: 0: movw IP(r2),r7 # kick to make it go
187: 0: bbs $BPOWN,(r9),0b # wait for answer
188: tstb m_sts(r11) # tstb: ignore `already online' flag
189: rsb
190:
191: #
192: # KDB50 communication area
193: #
194: .align 2
195: savesp: .space 4 # working mem + WMEM
196: .space 8 # crap at the top
197: rsp: .space 4 # response descriptor
198: .space 4 # command descriptor
199:
200: #
201: # a pair of packets
202: # +4 for length
203: #
204:
205: cp: .space SRSIZE+4 # command packet
206: rp: .space RPKSIZE+4 # response packet
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.