xref: /openbmc/qemu/pc-bios/s390-ccw/sclp.c (revision 3639f93f91fcba2c4d686653dcffb8224555b0a8)
19a22473cSFarhan Ali /*
29a22473cSFarhan Ali  * SCLP ASCII access driver
39a22473cSFarhan Ali  *
49a22473cSFarhan Ali  * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
59a22473cSFarhan Ali  *
69a22473cSFarhan Ali  * This work is licensed under the terms of the GNU GPL, version 2 or (at
79a22473cSFarhan Ali  * your option) any later version. See the COPYING file in the top-level
89a22473cSFarhan Ali  * directory.
99a22473cSFarhan Ali  */
109a22473cSFarhan Ali 
1190806fecSThomas Huth #include "libc.h"
129a22473cSFarhan Ali #include "s390-ccw.h"
139a22473cSFarhan Ali #include "sclp.h"
149a22473cSFarhan Ali 
15*3639f93fSThomas Huth long write(int fd, const void *str, size_t len);
16*3639f93fSThomas Huth 
179a22473cSFarhan Ali static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
189a22473cSFarhan Ali 
19af3bb73aSThomas Huth const unsigned char ebc2asc[256] =
20af3bb73aSThomas Huth       /* 0123456789abcdef0123456789abcdef */
21af3bb73aSThomas Huth         "................................" /* 1F */
22af3bb73aSThomas Huth         "................................" /* 3F */
23af3bb73aSThomas Huth         " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
24af3bb73aSThomas Huth         "-/.........,%_>?.........`:#@'=\""/* 7F */
25af3bb73aSThomas Huth         ".abcdefghi.......jklmnopqr......" /* 9F */
26af3bb73aSThomas Huth         "..stuvwxyz......................" /* BF */
27af3bb73aSThomas Huth         ".ABCDEFGHI.......JKLMNOPQR......" /* DF */
28af3bb73aSThomas Huth         "..STUVWXYZ......0123456789......";/* FF */
29af3bb73aSThomas Huth 
309a22473cSFarhan Ali /* Perform service call. Return 0 on success, non-zero otherwise. */
319a22473cSFarhan Ali static int sclp_service_call(unsigned int command, void *sccb)
329a22473cSFarhan Ali {
339a22473cSFarhan Ali         int cc;
349a22473cSFarhan Ali 
359a22473cSFarhan Ali         asm volatile(
369a22473cSFarhan Ali                 "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
379a22473cSFarhan Ali                 "       ipm     %0\n"
389a22473cSFarhan Ali                 "       srl     %0,28"
399a22473cSFarhan Ali                 : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
409a22473cSFarhan Ali                 : "cc", "memory");
419a22473cSFarhan Ali         consume_sclp_int();
429a22473cSFarhan Ali         if (cc == 3)
439a22473cSFarhan Ali                 return -EIO;
449a22473cSFarhan Ali         if (cc == 2)
459a22473cSFarhan Ali                 return -EBUSY;
469a22473cSFarhan Ali         return 0;
479a22473cSFarhan Ali }
489a22473cSFarhan Ali 
499a22473cSFarhan Ali static void sclp_set_write_mask(void)
509a22473cSFarhan Ali {
519a22473cSFarhan Ali     WriteEventMask *sccb = (void *)_sccb;
529a22473cSFarhan Ali 
539a22473cSFarhan Ali     sccb->h.length = sizeof(WriteEventMask);
549a22473cSFarhan Ali     sccb->mask_length = sizeof(unsigned int);
559a22473cSFarhan Ali     sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
569a22473cSFarhan Ali     sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
579a22473cSFarhan Ali     sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
589a22473cSFarhan Ali     sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
599a22473cSFarhan Ali 
609a22473cSFarhan Ali     sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
619a22473cSFarhan Ali }
629a22473cSFarhan Ali 
639a22473cSFarhan Ali void sclp_setup(void)
649a22473cSFarhan Ali {
659a22473cSFarhan Ali     sclp_set_write_mask();
669a22473cSFarhan Ali }
679a22473cSFarhan Ali 
689a22473cSFarhan Ali static int _strlen(const char *str)
699a22473cSFarhan Ali {
709a22473cSFarhan Ali     int i;
719a22473cSFarhan Ali     for (i = 0; *str; i++)
729a22473cSFarhan Ali         str++;
739a22473cSFarhan Ali     return i;
749a22473cSFarhan Ali }
759a22473cSFarhan Ali 
76*3639f93fSThomas Huth long write(int fd, const void *str, size_t len)
779a22473cSFarhan Ali {
789a22473cSFarhan Ali     WriteEventData *sccb = (void *)_sccb;
799a22473cSFarhan Ali 
80*3639f93fSThomas Huth     if (fd != 1 && fd != 2) {
81*3639f93fSThomas Huth         return -EIO;
82*3639f93fSThomas Huth     }
83*3639f93fSThomas Huth 
849a22473cSFarhan Ali     sccb->h.length = sizeof(WriteEventData) + len;
859a22473cSFarhan Ali     sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
869a22473cSFarhan Ali     sccb->ebh.length = sizeof(EventBufferHeader) + len;
879a22473cSFarhan Ali     sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
889a22473cSFarhan Ali     sccb->ebh.flags = 0;
8990806fecSThomas Huth     memcpy(sccb->data, str, len);
909a22473cSFarhan Ali 
919a22473cSFarhan Ali     sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
92*3639f93fSThomas Huth 
93*3639f93fSThomas Huth     return len;
94*3639f93fSThomas Huth }
95*3639f93fSThomas Huth 
96*3639f93fSThomas Huth void sclp_print(const char *str)
97*3639f93fSThomas Huth {
98*3639f93fSThomas Huth     write(1, str, _strlen(str));
999a22473cSFarhan Ali }
1009a22473cSFarhan Ali 
1019a22473cSFarhan Ali void sclp_get_loadparm_ascii(char *loadparm)
1029a22473cSFarhan Ali {
1039a22473cSFarhan Ali 
1049a22473cSFarhan Ali     ReadInfo *sccb = (void *)_sccb;
1059a22473cSFarhan Ali 
1069a22473cSFarhan Ali     memset((char *)_sccb, 0, sizeof(ReadInfo));
1079a22473cSFarhan Ali     sccb->h.length = sizeof(ReadInfo);
1089a22473cSFarhan Ali     if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) {
1099a22473cSFarhan Ali         ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8);
1109a22473cSFarhan Ali     }
1119a22473cSFarhan Ali }
112