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
304