]> git.proxmox.com Git - mirror_qemu.git/blame - pc-bios/s390-ccw/sclp.c
vl.c: allocate TYPE_MACHINE list once during bootup
[mirror_qemu.git] / pc-bios / s390-ccw / sclp.c
CommitLineData
0369b2eb
AG
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
90806fec 11#include "libc.h"
0369b2eb
AG
12#include "s390-ccw.h"
13#include "sclp.h"
14
3639f93f
TH
15long write(int fd, const void *str, size_t len);
16
0369b2eb
AG
17static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096)));
18
af3bb73a
TH
19const unsigned char ebc2asc[256] =
20 /* 0123456789abcdef0123456789abcdef */
21 "................................" /* 1F */
22 "................................" /* 3F */
23 " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
24 "-/.........,%_>?.........`:#@'=\""/* 7F */
25 ".abcdefghi.......jklmnopqr......" /* 9F */
26 "..stuvwxyz......................" /* BF */
27 ".ABCDEFGHI.......JKLMNOPQR......" /* DF */
28 "..STUVWXYZ......0123456789......";/* FF */
29
0369b2eb
AG
30/* Perform service call. Return 0 on success, non-zero otherwise. */
31static int sclp_service_call(unsigned int command, void *sccb)
32{
33 int cc;
34
35 asm volatile(
36 " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */
37 " ipm %0\n"
38 " srl %0,28"
39 : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
40 : "cc", "memory");
bdc7fe36 41 consume_sclp_int();
0369b2eb
AG
42 if (cc == 3)
43 return -EIO;
44 if (cc == 2)
45 return -EBUSY;
46 return 0;
47}
48
dbf2091a 49void sclp_set_write_mask(uint32_t receive_mask, uint32_t send_mask)
0369b2eb 50{
abd696e4 51 WriteEventMask *sccb = (void *)_sccb;
0369b2eb
AG
52
53 sccb->h.length = sizeof(WriteEventMask);
54 sccb->mask_length = sizeof(unsigned int);
dbf2091a
CW
55 sccb->cp_receive_mask = receive_mask;
56 sccb->cp_send_mask = send_mask;
0369b2eb
AG
57
58 sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb);
59}
60
61void sclp_setup(void)
62{
dbf2091a 63 sclp_set_write_mask(0, SCLP_EVENT_MASK_MSG_ASCII);
0369b2eb
AG
64}
65
3639f93f 66long write(int fd, const void *str, size_t len)
0369b2eb 67{
abd696e4 68 WriteEventData *sccb = (void *)_sccb;
7618c0ae
CW
69 const char *p = str;
70 size_t data_len = 0;
71 size_t i;
0369b2eb 72
3639f93f
TH
73 if (fd != 1 && fd != 2) {
74 return -EIO;
75 }
76
7618c0ae
CW
77 for (i = 0; i < len; i++) {
78 if ((data_len + 1) >= SCCB_DATA_LEN) {
79 /* We would overflow the sccb buffer, abort early */
80 len = i;
81 break;
82 }
83
84 if (*p == '\n') {
85 /* Terminal emulators might need \r\n, so generate it */
86 sccb->data[data_len++] = '\r';
87 }
88
89 sccb->data[data_len++] = *p;
90 p++;
91 }
92
93 sccb->h.length = sizeof(WriteEventData) + data_len;
0369b2eb 94 sccb->h.function_code = SCLP_FC_NORMAL_WRITE;
7618c0ae 95 sccb->ebh.length = sizeof(EventBufferHeader) + data_len;
0369b2eb
AG
96 sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA;
97 sccb->ebh.flags = 0;
0369b2eb
AG
98
99 sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
3639f93f
TH
100
101 return len;
102}
103
104void sclp_print(const char *str)
105{
fc0e2087 106 write(1, str, strlen(str));
0369b2eb 107}
9a22473c
FA
108
109void sclp_get_loadparm_ascii(char *loadparm)
110{
111
112 ReadInfo *sccb = (void *)_sccb;
113
114 memset((char *)_sccb, 0, sizeof(ReadInfo));
115 sccb->h.length = sizeof(ReadInfo);
116 if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) {
a0e11b61 117 ebcdic_to_ascii((char *) sccb->loadparm, loadparm, LOADPARM_LEN);
9a22473c
FA
118 }
119}
ff5dbf1b
CW
120
121int sclp_read(char *str, size_t count)
122{
123 ReadEventData *sccb = (void *)_sccb;
124 char *buf = (char *)(&sccb->ebh) + 7;
125
126 /* If count exceeds max buffer size, then restrict it to the max size */
127 if (count > SCCB_SIZE - 8) {
128 count = SCCB_SIZE - 8;
129 }
130
131 sccb->h.length = SCCB_SIZE;
132 sccb->h.function_code = SCLP_UNCONDITIONAL_READ;
133
134 sclp_service_call(SCLP_CMD_READ_EVENT_DATA, sccb);
135 memcpy(str, buf, count);
136
137 return sccb->ebh.length - 7;
138}