Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / arch / s390 / kernel / sclp.S
1 /*
2  * Mini SCLP driver.
3  *
4  * Copyright IBM Corp. 2004,2009
5  *
6  *   Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>,
7  *              Heiko Carstens <heiko.carstens@de.ibm.com>,
8  *
9  */
10
11 LC_EXT_NEW_PSW          = 0x58                  # addr of ext int handler
12 LC_EXT_NEW_PSW_64       = 0x1b0                 # addr of ext int handler 64 bit
13 LC_EXT_INT_PARAM        = 0x80                  # addr of ext int parameter
14 LC_EXT_INT_CODE         = 0x86                  # addr of ext int code
15 LC_AR_MODE_ID           = 0xa3
16
17 #
18 # Subroutine which waits synchronously until either an external interruption
19 # or a timeout occurs.
20 #
21 # Parameters:
22 #   R2  = 0 for no timeout, non-zero for timeout in (approximated) seconds
23 #
24 # Returns:
25 #   R2  = 0 on interrupt, 2 on timeout
26 #   R3  = external interruption parameter if R2=0
27 #
28
29 _sclp_wait_int:
30         stm     %r6,%r15,24(%r15)               # save registers
31         basr    %r13,0                          # get base register
32 .LbaseS1:
33         ahi     %r15,-96                        # create stack frame
34         la      %r8,LC_EXT_NEW_PSW              # register int handler
35         la      %r9,.LextpswS1-.LbaseS1(%r13)
36 #ifdef CONFIG_64BIT
37         tm      LC_AR_MODE_ID,1
38         jno     .Lesa1
39         la      %r8,LC_EXT_NEW_PSW_64           # register int handler 64 bit
40         la      %r9,.LextpswS1_64-.LbaseS1(%r13)
41 .Lesa1:
42 #endif
43         mvc     .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
44         mvc     0(16,%r8),0(%r9)
45         lhi     %r6,0x0200                      # cr mask for ext int (cr0.54)
46         ltr     %r2,%r2
47         jz      .LsetctS1
48         ahi     %r6,0x0800                      # cr mask for clock int (cr0.52)
49         stck    .LtimeS1-.LbaseS1(%r13)         # initiate timeout
50         al      %r2,.LtimeS1-.LbaseS1(%r13)
51         st      %r2,.LtimeS1-.LbaseS1(%r13)
52         sckc    .LtimeS1-.LbaseS1(%r13)
53
54 .LsetctS1:
55         stctl   %c0,%c0,.LctlS1-.LbaseS1(%r13)  # enable required interrupts
56         l       %r0,.LctlS1-.LbaseS1(%r13)
57         lhi     %r1,~(0x200 | 0x800)            # clear old values
58         nr      %r1,%r0
59         or      %r1,%r6                         # set new value
60         st      %r1,.LctlS1-.LbaseS1(%r13)
61         lctl    %c0,%c0,.LctlS1-.LbaseS1(%r13)
62         st      %r0,.LctlS1-.LbaseS1(%r13)
63         lhi     %r2,2                           # return code for timeout
64 .LloopS1:
65         lpsw    .LwaitpswS1-.LbaseS1(%r13)      # wait until interrupt
66 .LwaitS1:
67         lh      %r7,LC_EXT_INT_CODE
68         chi     %r7,0x1004                      # timeout?
69         je      .LtimeoutS1
70         chi     %r7,0x2401                      # service int?
71         jne     .LloopS1
72         sr      %r2,%r2
73         l       %r3,LC_EXT_INT_PARAM
74 .LtimeoutS1:
75         lctl    %c0,%c0,.LctlS1-.LbaseS1(%r13)  # restore interrupt setting
76         # restore old handler
77         mvc     0(16,%r8),.LoldpswS1-.LbaseS1(%r13)
78         lm      %r6,%r15,120(%r15)              # restore registers
79         br      %r14                            # return to caller
80
81         .align  8
82 .LoldpswS1:
83         .long   0, 0, 0, 0                      # old ext int PSW
84 .LextpswS1:
85         .long   0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
86 #ifdef CONFIG_64BIT
87 .LextpswS1_64:
88         .quad   0x0000000180000000, .LwaitS1    # PSW to handle ext int, 64 bit
89 #endif
90 .LwaitpswS1:
91         .long   0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
92 .LtimeS1:
93         .quad   0                               # current time
94 .LctlS1:
95         .long   0                               # CT0 contents
96
97 #
98 # Subroutine to synchronously issue a service call.
99 #
100 # Parameters:
101 #   R2  = command word
102 #   R3  = sccb address
103 #
104 # Returns:
105 #   R2  = 0 on success, 1 on failure
106 #   R3  = sccb response code if R2 = 0
107 #
108
109 _sclp_servc:
110         stm     %r6,%r15,24(%r15)               # save registers
111         ahi     %r15,-96                        # create stack frame
112         lr      %r6,%r2                         # save command word
113         lr      %r7,%r3                         # save sccb address
114 .LretryS2:
115         lhi     %r2,1                           # error return code
116         .insn   rre,0xb2200000,%r6,%r7          # servc
117         brc     1,.LendS2                       # exit if not operational
118         brc     8,.LnotbusyS2                   # go on if not busy
119         sr      %r2,%r2                         # wait until no longer busy
120         bras    %r14,_sclp_wait_int
121         j       .LretryS2                       # retry
122 .LnotbusyS2:
123         sr      %r2,%r2                         # wait until result
124         bras    %r14,_sclp_wait_int
125         sr      %r2,%r2
126         lh      %r3,6(%r7)
127 .LendS2:
128         lm      %r6,%r15,120(%r15)              # restore registers
129         br      %r14
130
131 #
132 # Subroutine to set up the SCLP interface.
133 #
134 # Parameters:
135 #   R2  = 0 to activate, non-zero to deactivate
136 #
137 # Returns:
138 #   R2  = 0 on success, non-zero on failure
139 #
140
141 _sclp_setup:
142         stm     %r6,%r15,24(%r15)               # save registers
143         ahi     %r15,-96                        # create stack frame
144         basr    %r13,0                          # get base register
145 .LbaseS3:
146         l       %r6,.LsccbS0-.LbaseS3(%r13)     # prepare init mask sccb
147         mvc     0(.LinitendS3-.LinitsccbS3,%r6),.LinitsccbS3-.LbaseS3(%r13)
148         ltr     %r2,%r2                         # initialization?
149         jz      .LdoinitS3                      # go ahead
150         # clear masks
151         xc      .LinitmaskS3-.LinitsccbS3(8,%r6),.LinitmaskS3-.LinitsccbS3(%r6)
152 .LdoinitS3:
153         l       %r2,.LwritemaskS3-.LbaseS3(%r13)# get command word
154         lr      %r3,%r6                         # get sccb address
155         bras    %r14,_sclp_servc                # issue service call
156         ltr     %r2,%r2                         # servc successful?
157         jnz     .LerrorS3
158         chi     %r3,0x20                        # write mask successful?
159         jne     .LerrorS3
160         # check masks
161         la      %r2,.LinitmaskS3-.LinitsccbS3(%r6)
162         l       %r1,0(%r2)                      # receive mask ok?
163         n       %r1,12(%r2)
164         cl      %r1,0(%r2)
165         jne     .LerrorS3
166         l       %r1,4(%r2)                      # send mask ok?
167         n       %r1,8(%r2)
168         cl      %r1,4(%r2)
169         sr      %r2,%r2
170         je      .LendS3
171 .LerrorS3:
172         lhi     %r2,1                           # error return code
173 .LendS3:
174         lm      %r6,%r15,120(%r15)              # restore registers
175         br      %r14
176 .LwritemaskS3:
177         .long   0x00780005                      # SCLP command for write mask
178 .LinitsccbS3:
179         .word   .LinitendS3-.LinitsccbS3
180         .byte   0,0,0,0
181         .word   0
182         .word   0
183         .word   4
184 .LinitmaskS3:
185         .long   0x80000000
186         .long   0x40000000
187         .long   0
188         .long   0
189 .LinitendS3:
190
191 #
192 # Subroutine which prints a given text to the SCLP console.
193 #
194 # Parameters:
195 #   R2  = address of nil-terminated ASCII text
196 #
197 # Returns:
198 #   R2  = 0 on success, 1 on failure
199 #
200
201 _sclp_print:
202         stm     %r6,%r15,24(%r15)               # save registers
203         ahi     %r15,-96                        # create stack frame
204         basr    %r13,0                          # get base register
205 .LbaseS4:
206         l       %r8,.LsccbS0-.LbaseS4(%r13)     # prepare write data sccb
207         mvc     0(.LmtoS4-.LwritesccbS4,%r8),.LwritesccbS4-.LbaseS4(%r13)
208         la      %r7,.LmtoS4-.LwritesccbS4(%r8)  # current mto addr
209         sr      %r0,%r0
210         l       %r10,.Lascebc-.LbaseS4(%r13)    # address of translation table
211 .LinitmtoS4:
212         # initialize mto
213         mvc     0(.LmtoendS4-.LmtoS4,%r7),.LmtoS4-.LbaseS4(%r13)
214         lhi     %r6,.LmtoendS4-.LmtoS4          # current mto length
215 .LloopS4:
216         ic      %r0,0(%r2)                      # get character
217         ahi     %r2,1
218         ltr     %r0,%r0                         # end of string?
219         jz      .LfinalizemtoS4
220         chi     %r0,0x15                        # end of line (NL)?
221         jz      .LfinalizemtoS4
222         stc     %r0,0(%r6,%r7)                  # copy to mto
223         la      %r11,0(%r6,%r7)
224         tr      0(1,%r11),0(%r10)               # translate to EBCDIC
225         ahi     %r6,1
226         j       .LloopS4
227 .LfinalizemtoS4:
228         sth     %r6,0(%r7)                      # update mto length
229         lh      %r9,.LmdbS4-.LwritesccbS4(%r8)  # update mdb length
230         ar      %r9,%r6
231         sth     %r9,.LmdbS4-.LwritesccbS4(%r8)
232         lh      %r9,.LevbufS4-.LwritesccbS4(%r8)# update evbuf length
233         ar      %r9,%r6
234         sth     %r9,.LevbufS4-.LwritesccbS4(%r8)
235         lh      %r9,0(%r8)                      # update sccb length
236         ar      %r9,%r6
237         sth     %r9,0(%r8)
238         ar      %r7,%r6                         # update current mto address
239         ltr     %r0,%r0                         # more characters?
240         jnz     .LinitmtoS4
241         l       %r2,.LwritedataS4-.LbaseS4(%r13)# write data
242         lr      %r3,%r8
243         bras    %r14,_sclp_servc
244         ltr     %r2,%r2                         # servc successful?
245         jnz     .LendS4
246         chi     %r3,0x20                        # write data successful?
247         je      .LendS4
248         lhi     %r2,1                           # error return code
249 .LendS4:
250         lm      %r6,%r15,120(%r15)              # restore registers
251         br      %r14
252
253 #
254 # Function which prints a given text to the SCLP console.
255 #
256 # Parameters:
257 #   R2  = address of nil-terminated ASCII text
258 #
259 # Returns:
260 #   R2  = 0 on success, 1 on failure
261 #
262
263         .globl _sclp_print_early
264 _sclp_print_early:
265         stm     %r6,%r15,24(%r15)               # save registers
266         ahi     %r15,-96                        # create stack frame
267 #ifdef CONFIG_64BIT
268         tm      LC_AR_MODE_ID,1
269         jno     .Lesa2
270         ahi     %r15,-80
271         stmh    %r6,%r15,96(%r15)               # store upper register halves
272 .Lesa2:
273 #endif
274         lr      %r10,%r2                        # save string pointer
275         lhi     %r2,0
276         bras    %r14,_sclp_setup                # enable console
277         ltr     %r2,%r2
278         jnz     .LendS5
279         lr      %r2,%r10
280         bras    %r14,_sclp_print                # print string
281         ltr     %r2,%r2
282         jnz     .LendS5
283         lhi     %r2,1
284         bras    %r14,_sclp_setup                # disable console
285 .LendS5:
286 #ifdef CONFIG_64BIT
287         tm      LC_AR_MODE_ID,1
288         jno     .Lesa3
289         lmh     %r6,%r15,96(%r15)               # store upper register halves
290         ahi     %r15,80
291 .Lesa3:
292 #endif
293         lm      %r6,%r15,120(%r15)              # restore registers
294         br      %r14
295
296 .LwritedataS4:
297         .long   0x00760005                      # SCLP command for write data
298 .LwritesccbS4:
299         # sccb
300         .word   .LmtoS4-.LwritesccbS4
301         .byte   0
302         .byte   0,0,0
303         .word   0
304
305         # evbuf
306 .LevbufS4:
307         .word   .LmtoS4-.LevbufS4
308         .byte   0x02
309         .byte   0
310         .word   0
311
312 .LmdbS4:
313         # mdb
314         .word   .LmtoS4-.LmdbS4
315         .word   1
316         .long   0xd4c4c240
317         .long   1
318
319         # go
320 .LgoS4:
321         .word   .LmtoS4-.LgoS4
322         .word   1
323         .long   0
324         .byte   0,0,0,0,0,0,0,0
325         .byte   0,0,0
326         .byte   0
327         .byte   0,0,0,0,0,0,0
328         .byte   0
329         .word   0
330         .byte   0,0,0,0,0,0,0,0,0,0
331         .byte   0,0,0,0,0,0,0,0
332         .byte   0,0,0,0,0,0,0,0
333
334 .LmtoS4:
335         .word   .LmtoendS4-.LmtoS4
336         .word   4
337         .word   0x1000
338         .byte   0
339         .byte   0,0,0
340 .LmtoendS4:
341
342         # Global constants
343 .LsccbS0:
344         .long   _sclp_work_area
345 .Lascebc:
346         .long   _ascebc
347
348 .section .data,"aw",@progbits
349         .balign 4096
350 _sclp_work_area:
351         .fill   4096
352 .previous