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 14LC_EXT_NEW_PSW = 0x58 # addr of ext int handler 15LC_EXT_NEW_PSW_64 = 0x1b0 # addr of ext int handler 64 bit 16LC_EXT_INT_PARAM = 0x80 # addr of ext int parameter 17LC_EXT_INT_CODE = 0x86 # addr of ext int code 18LC_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 272ENTRY(_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 basr %r13,0 281 lmh %r0,%r15,.Lzeroes-.(%r13) # clear upper register halves 282.Lesa2: 283#endif 284 lr %r10,%r2 # save string pointer 285 lhi %r2,0 286 bras %r14,_sclp_setup # enable console 287 ltr %r2,%r2 288 jnz .LendS5 289 lr %r2,%r10 290 bras %r14,_sclp_print # print string 291 ltr %r2,%r2 292 jnz .LendS5 293 lhi %r2,1 294 bras %r14,_sclp_setup # disable console 295.LendS5: 296#ifdef CONFIG_64BIT 297 tm LC_AR_MODE_ID,1 298 jno .Lesa3 299 lmh %r6,%r15,96(%r15) # store upper register halves 300 ahi %r15,80 301.Lesa3: 302#endif 303 lm %r6,%r15,120(%r15) # restore registers 304 br %r14 305.Lzeroes: 306 .fill 64,4,0 307 308.LwritedataS4: 309 .long 0x00760005 # SCLP command for write data 310.LwritesccbS4: 311 # sccb 312 .word .LmtoS4-.LwritesccbS4 313 .byte 0 314 .byte 0,0,0 315 .word 0 316 317 # evbuf 318.LevbufS4: 319 .word .LmtoS4-.LevbufS4 320 .byte 0x02 321 .byte 0 322 .word 0 323 324.LmdbS4: 325 # mdb 326 .word .LmtoS4-.LmdbS4 327 .word 1 328 .long 0xd4c4c240 329 .long 1 330 331 # go 332.LgoS4: 333 .word .LmtoS4-.LgoS4 334 .word 1 335 .long 0 336 .byte 0,0,0,0,0,0,0,0 337 .byte 0,0,0 338 .byte 0 339 .byte 0,0,0,0,0,0,0 340 .byte 0 341 .word 0 342 .byte 0,0,0,0,0,0,0,0,0,0 343 .byte 0,0,0,0,0,0,0,0 344 .byte 0,0,0,0,0,0,0,0 345 346.LmtoS4: 347 .word .LmtoendS4-.LmtoS4 348 .word 4 349 .word 0x1000 350 .byte 0 351 .byte 0,0,0 352.LmtoendS4: 353 354 # Global constants 355.LsccbS0: 356 .long _sclp_work_area 357.Lascebc: 358 .long _ascebc 359 360.section .data,"aw",@progbits 361 .balign 4096 362_sclp_work_area: 363 .fill 4096 364.previous 365