^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * driver: reading from and writing to system console on S/390 via SCLP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright IBM Corp. 1999, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author(s): Martin Peschke <mpeschke@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Martin Schwidefsky <schwidefsky@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kmod.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "sclp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "sclp_rw.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * The room for the SCCB (only for writing) is not equal to a pages size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * (as it is specified as the maximum size in the SCLP documentation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * because of the additional data structure described above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define MAX_SCCB_ROOM (PAGE_SIZE - sizeof(struct sclp_buffer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static void sclp_rw_pm_event(struct sclp_register *reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) enum sclp_pm_event sclp_pm_event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) sclp_console_pm_event(sclp_pm_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Event type structure for write message and write priority message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static struct sclp_register sclp_rw_event = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .send_mask = EVTYP_MSG_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .pm_event_fn = sclp_rw_pm_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Setup a sclp write buffer. Gets a page as input (4K) and returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * a pointer to a struct sclp_buffer structure that is located at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * end of the input page. This reduces the buffer space by a few
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * bytes but simplifies things.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct sclp_buffer *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) sclp_make_buffer(void *page, unsigned short columns, unsigned short htab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct sclp_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct sccb_header *sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) sccb = (struct sccb_header *) page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * We keep the struct sclp_buffer structure at the end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * of the sccb page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) buffer = ((struct sclp_buffer *) ((addr_t) sccb + PAGE_SIZE)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) buffer->sccb = sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) buffer->retry_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) buffer->messages = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) buffer->char_sum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) buffer->current_line = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) buffer->current_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) buffer->columns = columns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) buffer->htab = htab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* initialize sccb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) memset(sccb, 0, sizeof(struct sccb_header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) sccb->length = sizeof(struct sccb_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * Return a pointer to the original page that has been used to create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) sclp_unmake_buffer(struct sclp_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return buffer->sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Initialize a new message the end of the provided buffer with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * enough room for max_len characters. Return 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) sclp_initialize_mto(struct sclp_buffer *buffer, int max_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct sccb_header *sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct msg_buf *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct mdb *mdb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct go *go;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct mto *mto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int msg_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* max size of new message including message text */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) msg_size = sizeof(struct msg_buf) + max_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* check if current buffer sccb can contain the mto */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) sccb = buffer->sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if ((MAX_SCCB_ROOM - sccb->length) < msg_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) msg = (struct msg_buf *)((addr_t) sccb + sccb->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) memset(msg, 0, sizeof(struct msg_buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) msg->header.length = sizeof(struct msg_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) msg->header.type = EVTYP_MSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) mdb = &msg->mdb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) mdb->header.length = sizeof(struct mdb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mdb->header.type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) mdb->header.tag = 0xD4C4C240; /* ebcdic "MDB " */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) mdb->header.revision_code = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) go = &mdb->go;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) go->length = sizeof(struct go);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) go->type = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) mto = &mdb->mto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mto->length = sizeof(struct mto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) mto->type = 4; /* message text object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) mto->line_type_flags = LNTPFLGS_ENDTEXT; /* end text */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* set pointer to first byte after struct mto. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) buffer->current_msg = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) buffer->current_line = (char *) (mto + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) buffer->current_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * Finalize message initialized by sclp_initialize_mto(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * updating the sizes of MTO, enclosing MDB, event buffer and SCCB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) sclp_finalize_mto(struct sclp_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct sccb_header *sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct msg_buf *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * update values of sizes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * (SCCB, Event(Message) Buffer, Message Data Block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) sccb = buffer->sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) msg = buffer->current_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) msg->header.length += buffer->current_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) msg->mdb.header.length += buffer->current_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) msg->mdb.mto.length += buffer->current_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) sccb->length += msg->header.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * count number of buffered messages (= number of Message Text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * Objects) and number of buffered characters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * for the SCCB currently used for buffering and at all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) buffer->messages++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) buffer->char_sum += buffer->current_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) buffer->current_line = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) buffer->current_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) buffer->current_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * processing of a message including escape characters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * returns number of characters written to the output sccb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * ("processed" means that is not guaranteed that the character have already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * been sent to the SCLP but that it will be done at least next time the SCLP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * is not busy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int spaces, i_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * parse msg for escape sequences (\t,\v ...) and put formated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * msg into an mto (created by sclp_initialize_mto).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * We have to do this work ourselfs because there is no support for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * these characters on the native machine and only partial support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * under VM (Why does VM interpret \n but the native machine doesn't ?)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Depending on i/o-control setting the message is always written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * immediately or we wait for a final new line maybe coming with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * next message. Besides we avoid a buffer overrun by writing its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * content.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * RESTRICTIONS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * \r and \b work within one line because we are not able to modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * previous output that have already been accepted by the SCLP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * \t combined with following \r is not correctly represented because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * \t is expanded to some spaces but \r does not know about a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * previous \t and decreases the current position by one column.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * This is in order to a slim and quick implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) for (i_msg = 0; i_msg < count; i_msg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) switch (msg[i_msg]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) case '\n': /* new line, line feed (ASCII) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* check if new mto needs to be created */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (buffer->current_line == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) rc = sclp_initialize_mto(buffer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return i_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) sclp_finalize_mto(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) case '\a': /* bell, one for several times */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* set SCLP sound alarm bit in General Object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (buffer->current_line == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) rc = sclp_initialize_mto(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) buffer->columns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return i_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) buffer->current_msg->mdb.go.general_msg_flags |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) GNRLMSGFLGS_SNDALRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case '\t': /* horizontal tabulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* check if new mto needs to be created */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (buffer->current_line == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) rc = sclp_initialize_mto(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) buffer->columns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return i_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* "go to (next htab-boundary + 1, same line)" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (buffer->current_length >= buffer->columns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* ok, add a blank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) *buffer->current_line++ = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) buffer->current_length++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) } while (buffer->current_length % buffer->htab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case '\f': /* form feed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case '\v': /* vertical tabulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* "go to (actual column, actual line + 1)" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* = new line, leading spaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (buffer->current_line != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) spaces = buffer->current_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) sclp_finalize_mto(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) rc = sclp_initialize_mto(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) buffer->columns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return i_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) memset(buffer->current_line, 0x40, spaces);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) buffer->current_line += spaces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) buffer->current_length = spaces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* one an empty line this is the same as \n */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) rc = sclp_initialize_mto(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) buffer->columns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return i_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) sclp_finalize_mto(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case '\b': /* backspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* "go to (actual column - 1, actual line)" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* decrement counter indicating position, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* do not remove last character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (buffer->current_line != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) buffer->current_length > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) buffer->current_length--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) buffer->current_line--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case 0x00: /* end of string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* transfer current line to SCCB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (buffer->current_line != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) sclp_finalize_mto(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* skip the rest of the message including the 0 byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) i_msg = count - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) default: /* no escape character */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* do not output unprintable characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!isprint(msg[i_msg]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* check if new mto needs to be created */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (buffer->current_line == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) rc = sclp_initialize_mto(buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) buffer->columns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return i_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) *buffer->current_line++ = sclp_ascebc(msg[i_msg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) buffer->current_length++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /* check if current mto is full */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (buffer->current_line != NULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) buffer->current_length >= buffer->columns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) sclp_finalize_mto(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* return number of processed characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return i_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * Return the number of free bytes in the sccb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) sclp_buffer_space(struct sclp_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct sccb_header *sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) sccb = buffer->sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) count = MAX_SCCB_ROOM - sccb->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (buffer->current_line != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) count -= sizeof(struct msg_buf) + buffer->current_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * Return number of characters in buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) sclp_chars_in_buffer(struct sclp_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) count = buffer->char_sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (buffer->current_line != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) count += buffer->current_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * called by sclp_console_init and/or sclp_tty_init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) sclp_rw_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static int init_done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (init_done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) rc = sclp_register(&sclp_rw_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) init_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) #define SCLP_BUFFER_MAX_RETRY 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * second half of Write Event Data-function that has to be done after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * interruption indicating completion of Service Call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) sclp_writedata_callback(struct sclp_req *request, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct sclp_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct sccb_header *sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) buffer = (struct sclp_buffer *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) sccb = buffer->sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (request->status == SCLP_REQ_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (buffer->callback != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) buffer->callback(buffer, -EIO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* check SCLP response code and choose suitable action */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) switch (sccb->response_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case 0x0020 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /* Normal completion, buffer processed, message(s) sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) case 0x0340: /* Contained SCLP equipment check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* remove processed buffers and requeue rest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (sclp_remove_processed((struct sccb_header *) sccb) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* not all buffers were processed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) sccb->response_code = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) buffer->request.status = SCLP_REQ_FILLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) rc = sclp_add_request(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) case 0x0040: /* SCLP equipment check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) case 0x05f0: /* Target resource in improper state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (++buffer->retry_count > SCLP_BUFFER_MAX_RETRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* retry request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) sccb->response_code = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) buffer->request.status = SCLP_REQ_FILLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) rc = sclp_add_request(request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (sccb->response_code == 0x71f0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (buffer->callback != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) buffer->callback(buffer, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * Setup the request structure in the struct sclp_buffer to do SCLP Write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * Event Data and pass the request to the core SCLP loop. Return zero on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * success, non-zero otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) sclp_emit_buffer(struct sclp_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) void (*callback)(struct sclp_buffer *, int))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* add current line if there is one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (buffer->current_line != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) sclp_finalize_mto(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* Are there messages in the output buffer ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (buffer->messages == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) buffer->request.status = SCLP_REQ_FILLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) buffer->request.callback = sclp_writedata_callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) buffer->request.callback_data = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) buffer->request.sccb = buffer->sccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) buffer->callback = callback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return sclp_add_request(&buffer->request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }