2 # arch/s390/boot/ipleckd.S
3 # IPL record for 3380/3390 DASD
6 # Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 # Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>
10 # FIXME: should use the countarea to determine the blocksize
11 # FIXME: should insert zeroes into memory when filling holes
12 # FIXME: calculate blkpertrack from rdc data and blksize
14 # change 09/20/00 removed obsolete store of ipldevice to textesegment
17 # r1: ipl subchannel ( general use, dont overload without save/restore !)
19 # r13: base register index to 0x0000
20 # r14: callers address
21 # r15: temporary save register (we have no stack!)
25 #include <asm/lowcore.h>
28 .psw: .long 0x00080000,0x80000000+_start
29 .ccw1: .long 0x06000000,0x00001000 # Re-Read enough of bootsector to start
30 .ccw2: .long 0x00000000,0x00000000 # read countarea of record 1 to s/w.
33 .Lextn: .long 0x000a0000,0x00000000+.Lextn
34 .Lsvcn: .long 0x000a0000,0x00000000+.Lsvcn
35 .Lprgn: .long 0x00080000,0x00000000+.Lecs
36 .Lmcn: .long 0x000a0000,0x00000000+.Lmcn
37 .Lion: .long 0x00080000,0x80000000+.Lionewaddr
40 .Llstad:.long 0x00000000,0x00000000 # sectorno + ct of bootlist
42 .org 0xf0 # Lets start now...
44 l %r1,__LC_SUBCHANNEL_ID # get IPL-subchannel from lowcore
45 st %r1,__LC_IPLDEV # keep it for reipl
47 oi .Lrdcdata+5,0x84 # enable ssch and multipath mode
48 .Lecs: xi .Lrdcdata+27,0x01 # enable concurrent sense
50 xi .Lprgn,6 # restore Wait and d/a bit in PCnew PSW
52 mvc 0x0(8,%r2),.Lnull # set parmarea to null
53 lctl %c6,%c6,.Lc6 # enable all interrupts
54 .Lrdc: # read device characteristics
56 st %r6,.Lorb+8 # store cp-address to orb
57 bras %r15,.Lssch # start I/O
59 lh %r5,.Lcountarea+6 # init r5 from countarea
60 stcm %r5,3,.Lrdccw+2 # and store into rd template *FIXME*
61 stcm %r5,3,.Llodata+14 # and store into lodata *FIXME*
68 l %r10,.Lblklst # r10 is index to bootlist
69 lhi %r5,4 # r5: skip 4 blocks = firstpage....
71 clc .Lnull(8),0(%r10) # test blocklist
72 jz .Lchkparm # end of list?
73 l %r2,0(%r10) # get startblock to r2
74 slr %r4,%r4 # erase r4
75 icm %r4,1,7(%r10) # get blockcount
76 slr %r3,%r3 # get address to r3
78 chi %r5,0 # still blocks to skip?
79 jz .Ldoread # no: start reading
80 cr %r5,%r4 # #skipblocks >= blockct?
81 jm .L007 # no: skip the blocks one by one
83 sr %r5,%r4 # decrease number of blocks to skip
84 j .Lkcont # advance to next entry
86 ahi %r2,1 # skip 1 block...
87 bctr %r4,0 # update blockct
88 ah %r3,.Lcountarea+6 # increment address
89 bct %r5,.L007 # 4 blocks skipped?
91 ltr %r2,%r2 # test startblock
92 jz .Lzeroes # startblocks is zero (hole)
99 icm %r3,3,.Lcountarea+6 # get blocksize
100 slr %r5,%r5 # no bytes to move
101 .L008: mvcle %r2,%r4,0 # fill zeroes to storage
102 jo .L008 # until block is filled
103 brct %r4,.L001 # skip to next block
108 lm %r3,%r4,.Lstart # load .Lstart and .Lparm
109 clc 0x0(4,%r4),.Lnull
111 mvc 0x480(128,%r3),0(%r4) # move 1k-0x80 to parmarea
112 mvc 0x500(256,%r3),0x80(%r4)
113 mvc 0x600(256,%r3),0x180(%r4)
114 mvc 0x700(256,%r3),0x280(%r4)
118 # st %r1,0xc6c(%r2) # store iplsubchannel to lowcore
119 # st %r1,0xc6c # store iplsubchannel to lowcore
121 # This function does the start IO
122 # r2: number of first block to read ( input by caller )
123 # r3: address to read data to ( input by caller )
124 # r4: number of blocks to read ( input by caller )
126 # r6: blocks per track ( input by caller )
127 # r7: number of heads
131 # r11: temporary register
132 # r12: local use for base address
133 # r13: base address for module
134 # r14: address of caller for subroutine
135 # r15: temporary save register (since we have no stack)
138 st %r12,8+.Lorb # store cpaddr to orb
139 ahi %r12,0x10 # increment r12 to point to rdccw
140 oi 1(%r12),0x40 # set CC in rd template
141 # first setup the read CCWs
142 lr %r15,%r4 # save number or blocks
144 icm %r7,3,.Lrdcdata+14 # load heads to r7
146 clc .Lrdcdata+3(2),.L9345
149 clc .Lrdcdata+3(2),.L3380
152 clc .Lrdcdata+3(2),.L3390
158 mvc 0(8,%r12),.Lrdccw # copy template to this ccw
159 st %r3,4(%r12) # store target address to this ccw
160 bct %r4,.L005 # decrement no of blks still to do
161 ni 1(%r12),0x3f # delete CC from last ccw
162 lr %r4,%r15 # restore number of blocks
163 # read CCWs are setup now
164 stcm %r4,3,.Llodata+2 # store blockno to lodata clears r4
165 ar %r4,%r2 # r4 (clear): ebl = blk + nbl
166 bctr %r4,0 # decrement r4 ( last blk touched
167 srda %r2,32 # trk = blk / bpt, bot = blk % bpt
168 dr %r2,%r6 # r3: trk, r2: bot
169 ahi %r2,1 # bot++ ( we start counting at 1 )
170 stcm %r2,1,.Llodata+12 # store bot to lodata
171 xr %r2,%r2 # cy = trk / heads, hd = trk % heads
172 dr %r2,%r7 # r3: cy, r2: hd
173 sll %r3,16 # combine to CCHH in r3
175 st %r3,.Ldedata+8 # store cchh to dedata
176 st %r3,.Llodata+4 # store cchh to lodata
177 st %r3,.Llodata+8 # store cchh to lodata
178 lr %r15,%r5 # save r5
179 srda %r4,32 # tr2 = ebl / bpt
180 dr %r4,%r6 # r5: tr2, r4: bot2
181 xr %r4,%r4 # cy2 = tr2 / heads, hd2 = hd2 % heads
182 dr %r4,%r7 # r5: cy2, r4: hd2
183 stcm %r5,3,.Ldedata+12 # store cy2,hd2 to dedata
184 stcm %r4,3,.Ldedata+14 # store cy2,hd2 to dedata
185 lr %r5,%r15 # restore r5
186 # CCWs are setup now, arent they?
187 bras %r15,.Lssch # start I/O
188 br %r14 # return to caller
190 ah %r3,.Lcountarea+6 # add blocksize to target address
191 ahi %r12,8 # add sizeof(ccw) to base address
194 # This function does the start IO
195 # r1: Subchannel number
199 lhi %r13,10 # initialize retries
201 ssch .Lorb # start I/O
203 bras %r14,.Ldisab # error
205 lpsw .Lwaitpsw # load wait-PSW
207 c %r1,0xb8 # compare to ipl subhchannel
208 jnz .Ltpi # not equal: loop
209 clc 0xbc(4),.Lorb # cross check the intparm
210 jnz .Ltpi # not equal: loop
211 tsch .Lirb # get status
212 tm .Lirb+9,0xff # channel status ?
213 jz .L003 # CS == 0x00
214 bras %r14,.Ldisab # error
216 tm .Lirb+8,0xf3 # DS different from CE/DE
218 bct %r13,.L012 # retries <= 5 ?
219 bras %r14,.Ldisab # error
221 tm .Lirb+8,0x04 # DE set?
222 jz .Ltpi # DE not set, loop
224 br %r15 # return to caller
226 # In case of error goto disabled wait with %r14 containing the caller
231 # FIXME pre-initialized data should be listed first
232 # NULLed storage can be taken from anywhere ;)
237 .long 0x000a0000,0x00000000
239 .long 0x020a0000,0x00000000+.Ltpi
241 .long 0x0049504c,0x0080ff00 # intparm is " IPL"
242 .Lc6: .long 0xff000000
244 .long 0x00010000 # do not separate .Lstart and .Lparm
246 .long 0x00008000 # they are loaded with a LM
254 .long 0x00000000,0x00000000
257 .long 0x00000000,0x00000000
258 .long 0x00000000,0x00000000
259 .long 0x00000000,0x00000000
260 .long 0x00000000,0x00000000
261 .long 0x00000000,0x00000000
262 .long 0x00000000,0x00000000
263 .long 0x00000000,0x00000000
264 .long 0x00000000,0x00000000
266 .long 0x00000000,0x00000000
267 .long 0x00000000,0x00000000
268 .long 0x00000000,0x00000000
269 .long 0x00000000,0x00000000
270 .long 0x00000000,0x00000000
271 .long 0x00000000,0x00000000
272 .long 0x00000000,0x00000000
273 .long 0x00000000,0x00000000
278 .byte 0x00 # key length;
279 .word 0x0000 # data length == blocksize;
281 .long 0x40c00000,0x00000000
282 .long 0x00000000,0x00000000
284 .long 0x06000001,0x00000000
285 .long 0x00000000,0x01000000
288 .Lrdcccw: # CCW read device characteristics
289 .long 0x64400040,0x00000000+.Lrdcdata
290 .long 0x63400010,0x00000000+.Ldedata
291 .long 0x47400010,0x00000000+.Llodata
292 .long 0x12000008,0x00000000+.Lcountarea
294 .long 0x63400010,0x00000000+.Ldedata
296 .long 0x47400010,0x00000000+.Llodata
298 .long 0x86400000,0x00000000
300 # end of pre initialized data is here CCWarea follows
301 # from here we load 1k blocklist