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