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