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 11LC_EXT_NEW_PSW = 0x58 # addr of ext int handler 12LC_EXT_NEW_PSW_64 = 0x1b0 # addr of ext int handler 64 bit 13LC_EXT_INT_PARAM = 0x80 # addr of ext int parameter 14LC_EXT_INT_CODE = 0x86 # addr of ext int code 15LC_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 353