xref: /qemu/pc-bios/s390-ccw/sclp.c (revision 9a22473c70f3d07068a673e91562947b19e02995)
10369b2ebSAlexander Graf /*
20369b2ebSAlexander Graf  * SCLP ASCII access driver
30369b2ebSAlexander Graf  *
40369b2ebSAlexander Graf  * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
50369b2ebSAlexander Graf  *
60369b2ebSAlexander Graf  * This work is licensed under the terms of the GNU GPL, version 2 or (at
70369b2ebSAlexander Graf  * your option) any later version. See the COPYING file in the top-level
80369b2ebSAlexander Graf  * directory.
90369b2ebSAlexander Graf  */
100369b2ebSAlexander Graf 
110369b2ebSAlexander Graf #include "s390-ccw.h"
120369b2ebSAlexander Graf #include "sclp.h"
130369b2ebSAlexander Graf 
140369b2ebSAlexander Graf static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
150369b2ebSAlexander Graf 
160369b2ebSAlexander Graf /* Perform service call. Return 0 on success, non-zero otherwise. */
170369b2ebSAlexander Graf static int sclp_service_call(unsigned int command, void *sccb)
180369b2ebSAlexander Graf {
190369b2ebSAlexander Graf         int cc;
200369b2ebSAlexander Graf 
210369b2ebSAlexander Graf         asm volatile(
220369b2ebSAlexander Graf                 "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
230369b2ebSAlexander Graf                 "       ipm     %0\n"
240369b2ebSAlexander Graf                 "       srl     %0,28"
250369b2ebSAlexander Graf                 : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
260369b2ebSAlexander Graf                 : "cc", "memory");
27bdc7fe36SChristian Borntraeger         consume_sclp_int();
280369b2ebSAlexander Graf         if (cc == 3)
290369b2ebSAlexander Graf                 return -EIO;
300369b2ebSAlexander Graf         if (cc == 2)
310369b2ebSAlexander Graf                 return -EBUSY;
320369b2ebSAlexander Graf         return 0;
330369b2ebSAlexander Graf }
340369b2ebSAlexander Graf 
350369b2ebSAlexander Graf static void sclp_set_write_mask(void)
360369b2ebSAlexander Graf {
370369b2ebSAlexander Graf     WriteEventMask *sccb = (void *)_sccb;
380369b2ebSAlexander Graf 
390369b2ebSAlexander Graf     sccb->h.length = sizeof(WriteEventMask);
400369b2ebSAlexander Graf     sccb->mask_length = sizeof(unsigned int);
410369b2ebSAlexander Graf     sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
420369b2ebSAlexander Graf     sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
430369b2ebSAlexander Graf     sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
440369b2ebSAlexander Graf     sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
450369b2ebSAlexander Graf 
460369b2ebSAlexander Graf     sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
470369b2ebSAlexander Graf }
480369b2ebSAlexander Graf 
490369b2ebSAlexander Graf void sclp_setup(void)
500369b2ebSAlexander Graf {
510369b2ebSAlexander Graf     sclp_set_write_mask();
520369b2ebSAlexander Graf }
530369b2ebSAlexander Graf 
540369b2ebSAlexander Graf static int _strlen(const char *str)
550369b2ebSAlexander Graf {
560369b2ebSAlexander Graf     int i;
570369b2ebSAlexander Graf     for (i = 0; *str; i++)
580369b2ebSAlexander Graf         str++;
590369b2ebSAlexander Graf     return i;
600369b2ebSAlexander Graf }
610369b2ebSAlexander Graf 
620369b2ebSAlexander Graf static void _memcpy(char *dest, const char *src, int len)
630369b2ebSAlexander Graf {
640369b2ebSAlexander Graf     int i;
650369b2ebSAlexander Graf     for (i = 0; i < len; i++)
660369b2ebSAlexander Graf         dest[i] = src[i];
670369b2ebSAlexander Graf }
680369b2ebSAlexander Graf 
690369b2ebSAlexander Graf void sclp_print(const char *str)
700369b2ebSAlexander Graf {
710369b2ebSAlexander Graf     int len = _strlen(str);
720369b2ebSAlexander Graf     WriteEventData *sccb = (void *)_sccb;
730369b2ebSAlexander Graf 
740369b2ebSAlexander Graf     sccb->h.length = sizeof(WriteEventData) + len;
750369b2ebSAlexander Graf     sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
760369b2ebSAlexander Graf     sccb->ebh.length = sizeof(EventBufferHeader) + len;
770369b2ebSAlexander Graf     sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
780369b2ebSAlexander Graf     sccb->ebh.flags = 0;
790369b2ebSAlexander Graf     _memcpy(sccb->data, str, len);
800369b2ebSAlexander Graf 
810369b2ebSAlexander Graf     sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
820369b2ebSAlexander Graf }
83*9a22473cSFarhan Ali 
84*9a22473cSFarhan Ali void sclp_get_loadparm_ascii(char *loadparm)
85*9a22473cSFarhan Ali {
86*9a22473cSFarhan Ali 
87*9a22473cSFarhan Ali     ReadInfo *sccb = (void *)_sccb;
88*9a22473cSFarhan Ali 
89*9a22473cSFarhan Ali     memset((char *)_sccb, 0, sizeof(ReadInfo));
90*9a22473cSFarhan Ali     sccb->h.length = sizeof(ReadInfo);
91*9a22473cSFarhan Ali     if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) {
92*9a22473cSFarhan Ali         ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8);
93*9a22473cSFarhan Ali     }
94*9a22473cSFarhan Ali }
95