Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }