xref: /kvm-unit-tests/lib/s390x/sclp-console.c (revision 7ed7df2332d3ad8feb96ea1a1f4b9b38cf29f8bd)
1*7ed7df23SJanosch Frank /*
2*7ed7df23SJanosch Frank  * SCLP ASCII access driver
3*7ed7df23SJanosch Frank  *
4*7ed7df23SJanosch Frank  * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
5*7ed7df23SJanosch Frank  *
6*7ed7df23SJanosch Frank  * This work is licensed under the terms of the GNU GPL, version 2 or (at
7*7ed7df23SJanosch Frank  * your option) any later version. See the COPYING file in the top-level
8*7ed7df23SJanosch Frank  * directory.
9*7ed7df23SJanosch Frank  */
10*7ed7df23SJanosch Frank 
11*7ed7df23SJanosch Frank #include <libcflat.h>
12*7ed7df23SJanosch Frank #include <string.h>
13*7ed7df23SJanosch Frank #include <asm/page.h>
14*7ed7df23SJanosch Frank #include "sclp.h"
15*7ed7df23SJanosch Frank 
16*7ed7df23SJanosch Frank char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
17*7ed7df23SJanosch Frank 
18*7ed7df23SJanosch Frank /* Perform service call. Return 0 on success, non-zero otherwise. */
19*7ed7df23SJanosch Frank int sclp_service_call(unsigned int command, void *sccb)
20*7ed7df23SJanosch Frank {
21*7ed7df23SJanosch Frank         int cc;
22*7ed7df23SJanosch Frank 
23*7ed7df23SJanosch Frank         asm volatile(
24*7ed7df23SJanosch Frank                 "       .insn   rre,0xb2200000,%1,%2\n"  /* servc %1,%2 */
25*7ed7df23SJanosch Frank                 "       ipm     %0\n"
26*7ed7df23SJanosch Frank                 "       srl     %0,28"
27*7ed7df23SJanosch Frank                 : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
28*7ed7df23SJanosch Frank                 : "cc", "memory");
29*7ed7df23SJanosch Frank         if (cc == 3)
30*7ed7df23SJanosch Frank                 return -1;
31*7ed7df23SJanosch Frank         if (cc == 2)
32*7ed7df23SJanosch Frank                 return -1;
33*7ed7df23SJanosch Frank         return 0;
34*7ed7df23SJanosch Frank }
35*7ed7df23SJanosch Frank 
36*7ed7df23SJanosch Frank static void sclp_set_write_mask(void)
37*7ed7df23SJanosch Frank {
38*7ed7df23SJanosch Frank 	WriteEventMask *sccb = (void *)_sccb;
39*7ed7df23SJanosch Frank 
40*7ed7df23SJanosch Frank 	sccb->h.length = sizeof(WriteEventMask);
41*7ed7df23SJanosch Frank 	sccb->mask_length = sizeof(unsigned int);
42*7ed7df23SJanosch Frank 	sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
43*7ed7df23SJanosch Frank 	sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII;
44*7ed7df23SJanosch Frank 	sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII;
45*7ed7df23SJanosch Frank 	sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII;
46*7ed7df23SJanosch Frank 
47*7ed7df23SJanosch Frank 	sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
48*7ed7df23SJanosch Frank }
49*7ed7df23SJanosch Frank 
50*7ed7df23SJanosch Frank void sclp_console_setup(void)
51*7ed7df23SJanosch Frank {
52*7ed7df23SJanosch Frank 	sclp_set_write_mask();
53*7ed7df23SJanosch Frank }
54*7ed7df23SJanosch Frank 
55*7ed7df23SJanosch Frank void sclp_print(const char *str)
56*7ed7df23SJanosch Frank {
57*7ed7df23SJanosch Frank 	int len = strlen(str);
58*7ed7df23SJanosch Frank 	WriteEventData *sccb = (void *)_sccb;
59*7ed7df23SJanosch Frank 
60*7ed7df23SJanosch Frank 	sccb->h.length = sizeof(WriteEventData) + len;
61*7ed7df23SJanosch Frank 	sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
62*7ed7df23SJanosch Frank 	sccb->ebh.length = sizeof(EventBufferHeader) + len;
63*7ed7df23SJanosch Frank 	sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
64*7ed7df23SJanosch Frank 	sccb->ebh.flags = 0;
65*7ed7df23SJanosch Frank 	memcpy(sccb->data, str, len);
66*7ed7df23SJanosch Frank 
67*7ed7df23SJanosch Frank 	sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
68*7ed7df23SJanosch Frank }
69