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