import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / s390 / boot / ipleckd.S
1 #
2 #  arch/s390/boot/ipleckd.S
3 #    IPL record for 3380/3390 DASD
4 #
5 #  S390 version
6 #    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 #    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>
8 #
9 #
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
13
14 # change 09/20/00       removed obsolete store of ipldevice to textesegment
15
16 # Usage of registers
17 # r1:   ipl subchannel ( general use, dont overload without save/restore !)
18 # r10:
19 # r13:  base register   index to 0x0000
20 # r14:  callers address
21 # r15:  temporary save register (we have no stack!)
22
23 # storage layout:
24
25 #include <asm/lowcore.h>
26         
27         .org 0
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.
31
32         .org 0x58
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
38
39         .org 0xe0
40 .Llstad:.long   0x00000000,0x00000000   # sectorno + ct of bootlist
41
42         .org 0xf0                       # Lets start now...
43 _start: .globl _start
44         l       %r1,__LC_SUBCHANNEL_ID  # get IPL-subchannel from lowcore
45         st      %r1,__LC_IPLDEV         # keep it for reipl
46         stsch   .Lrdcdata
47         oi      .Lrdcdata+5,0x84        # enable ssch and multipath mode
48 .Lecs:  xi      .Lrdcdata+27,0x01       # enable concurrent sense
49         msch    .Lrdcdata       
50         xi      .Lprgn,6                # restore Wait and d/a bit in PCnew PSW
51         l       %r2,.Lparm
52         mvc     0x0(8,%r2),.Lnull       # set parmarea to null
53         lctl    %c6,%c6,.Lc6            # enable all interrupts
54 .Lrdc:                                  # read device characteristics
55         la      %r6,.Lrdcccw     
56         st      %r6,.Lorb+8             # store cp-address to orb
57         bras    %r15,.Lssch             # start I/O
58         oi      .Llodata+1,0x80
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*
62 .Lbootlist:     
63         l       %r2,.Llstad     
64         l       %r3,.Lblklst     
65         lhi     %r4,1
66         bras    %r14,.Lreadblks
67 .Lloader:       
68         l       %r10,.Lblklst           # r10 is index to bootlist
69         lhi     %r5,4                   # r5:   skip 4 blocks = firstpage....
70 .Lkloop:
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
77         icm     %r3,0xe,4(%r10)
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
82 .L006:  
83         sr      %r5,%r4                 # decrease number of blocks to skip
84         j       .Lkcont                 # advance to next entry
85 .L007:  
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?
90 .Ldoread:
91         ltr     %r2,%r2                 # test startblock
92         jz      .Lzeroes                # startblocks is zero (hole)
93 .Ldiskread:     
94         bras    %r14,.Lreadblks
95         j       .Lkcont
96 .Lzeroes:
97         lr      %r2,%r3
98 .L001:  slr     %r3,%r3
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
104 .Lkcont:        
105         ahi     %r10,8
106         j       .Lkloop
107 .Lchkparm:
108         lm      %r3,%r4,.Lstart         # load .Lstart and .Lparm
109         clc     0x0(4,%r4),.Lnull     
110         je      .Lrunkern
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)
115 .Lrunkern:
116 #       lhi     %r2,17
117 #       sll     %r2,12
118 #       st      %r1,0xc6c(%r2)          # store iplsubchannel to lowcore
119 #       st      %r1,0xc6c               # store iplsubchannel to lowcore
120         br      %r3
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 )
125 # r5:   destroyed
126 # r6:   blocks per track ( input by caller )
127 # r7:   number of heads 
128 # r8:   
129 # r9:   
130 # r10:  
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)
136 .Lreadblks:
137         la      %r12,.Ldeccw     
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
143         slr     %r7,%r7
144         icm     %r7,3,.Lrdcdata+14      # load heads to r7
145         lhi     %r6,9
146         clc     .Lrdcdata+3(2),.L9345
147         je      .L011
148         lhi     %r6,10
149         clc     .Lrdcdata+3(2),.L3380
150         je      .L011
151         lhi     %r6,12
152         clc     .Lrdcdata+3(2),.L3390     
153         je      .L011                   
154         bras    %r14,.Ldisab
155 .L011:  
156         # loop for nbl times
157 .Lrdloop:       
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
174         or      %r3,%r2
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
189 .L005:  
190         ah      %r3,.Lcountarea+6       # add blocksize to target address
191         ahi     %r12,8                  # add sizeof(ccw) to base address
192         j       .Lrdloop
193 # end of function
194 # This function does the start IO
195 # r1:   Subchannel number
196 # r8:   ORB address
197 # r9:   IRB address
198 .Lssch:
199         lhi     %r13,10                 # initialize retries
200 .L012:  
201         ssch    .Lorb                   # start I/O
202         jz      .Ltpi                   # ok?
203         bras    %r14,.Ldisab            # error
204 .Ltpi:  
205         lpsw    .Lwaitpsw               # load wait-PSW
206 .Lionewaddr:    
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
215 .L003:
216         tm      .Lirb+8,0xf3            # DS different from CE/DE
217         jz      .L004                   # ok ?
218         bct     %r13,.L012              # retries <= 5 ?
219         bras    %r14,.Ldisab            # error
220 .L004:
221         tm      .Lirb+8,0x04            # DE set?
222         jz      .Ltpi                   # DE not set, loop
223 .Lsschend:
224         br      %r15                    # return to caller
225 # end of function
226 # In case of error goto disabled wait with %r14 containing the caller
227 .Ldisab:
228         st      %r14,.Ldisabpsw+4     
229         lpsw    .Ldisabpsw     
230
231 # FIXME pre-initialized data should be listed first
232 # NULLed storage can be taken from anywhere ;) 
233 .Lblklst:       
234         .long   0x00002000     
235         .align 8
236 .Ldisabpsw: 
237         .long 0x000a0000,0x00000000
238 .Lwaitpsw:
239         .long 0x020a0000,0x00000000+.Ltpi
240 .Lorb:  
241         .long 0x0049504c,0x0080ff00     # intparm is " IPL"
242 .Lc6:   .long 0xff000000
243 .Lstart:
244         .long   0x00010000              # do not separate .Lstart and .Lparm
245 .Lparm: 
246         .long   0x00008000              # they are loaded with a LM
247 .L3390:
248         .word   0x3390
249 .L9345:
250         .word   0x9345
251 .L3380:
252         .word   0x3380
253 .Lnull: 
254         .long 0x00000000,0x00000000
255         .align 4
256 .Lrdcdata:
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
265 .Lirb:
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
274 .Lcountarea:    
275         .word 0x0000                    # cyl;
276         .word 0x0000                    # head;
277         .byte 0x00                      # record;
278         .byte 0x00                      # key length;
279         .word 0x0000                    # data length == blocksize;
280 .Ldedata:
281         .long 0x40c00000,0x00000000
282         .long 0x00000000,0x00000000
283 .Llodata:
284         .long 0x06000001,0x00000000
285         .long 0x00000000,0x01000000
286         .long 0x12345678
287         .org 0x7c8
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
293 .Ldeccw:
294         .long 0x63400010,0x00000000+.Ldedata
295 .Lloccw:
296         .long 0x47400010,0x00000000+.Llodata
297 .Lrdccw:        
298         .long 0x86400000,0x00000000
299         .org 0x800
300 # end of pre initialized data is here CCWarea follows
301 # from here we load 1k blocklist 
302 # end of function
303