xref: /openbmc/qemu/pc-bios/s390-ccw/sclp.c (revision 795c40b8)
1 /*
2  * SCLP ASCII access driver
3  *
4  * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2 or (at
7  * your option) any later version. See the COPYING file in the top-level
8  * directory.
9  */
10 
11 #include "s390-ccw.h"
12 #include "sclp.h"
13 
14 static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
15 
16 /* Perform service call. Return 0 on success, non-zero otherwise. */
17 static int sclp_service_call(unsigned int command, void *sccb)
18 {
19         int cc;
20 
21         asm volatile(
22                 "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
23                 "       ipm     %0\n"
24                 "       srl     %0,28"
25                 : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
26                 : "cc", "memory");
27         consume_sclp_int();
28         if (cc == 3)
29                 return -EIO;
30         if (cc == 2)
31                 return -EBUSY;
32         return 0;
33 }
34 
35 static void sclp_set_write_mask(void)
36 {
37     WriteEventMask *sccb = (void *)_sccb;
38 
39     sccb->h.length = sizeof(WriteEventMask);
40     sccb->mask_length = sizeof(unsigned int);
41     sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
42     sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
43     sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
44     sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
45 
46     sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
47 }
48 
49 void sclp_setup(void)
50 {
51     sclp_set_write_mask();
52 }
53 
54 static int _strlen(const char *str)
55 {
56     int i;
57     for (i = 0; *str; i++)
58         str++;
59     return i;
60 }
61 
62 static void _memcpy(char *dest, const char *src, int len)
63 {
64     int i;
65     for (i = 0; i < len; i++)
66         dest[i] = src[i];
67 }
68 
69 void sclp_print(const char *str)
70 {
71     int len = _strlen(str);
72     WriteEventData *sccb = (void *)_sccb;
73 
74     sccb->h.length = sizeof(WriteEventData) + len;
75     sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
76     sccb->ebh.length = sizeof(EventBufferHeader) + len;
77     sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
78     sccb->ebh.flags = 0;
79     _memcpy(sccb->data, str, len);
80 
81     sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
82 }
83 
84 void sclp_get_loadparm_ascii(char *loadparm)
85 {
86 
87     ReadInfo *sccb = (void *)_sccb;
88 
89     memset((char *)_sccb, 0, sizeof(ReadInfo));
90     sccb->h.length = sizeof(ReadInfo);
91     if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) {
92         ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8);
93     }
94 }
95