393 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * Copyright IBM Corp. 1999,20124 *5 * Author(s): Martin Peschke <mpeschke@de.ibm.com>6 * Martin Schwidefsky <schwidefsky@de.ibm.com>7 */8 9#ifndef __SCLP_H__10#define __SCLP_H__11 12#include <linux/types.h>13#include <linux/list.h>14#include <asm/asm-extable.h>15#include <asm/sclp.h>16#include <asm/ebcdic.h>17 18/* maximum number of pages concerning our own memory management */19#define MAX_KMEM_PAGES (sizeof(unsigned long) << 3)20#define SCLP_CONSOLE_PAGES 621 22#define SCLP_EVTYP_MASK(T) (1UL << (sizeof(sccb_mask_t) * BITS_PER_BYTE - (T)))23 24#define EVTYP_OPCMD 0x0125#define EVTYP_MSG 0x0226#define EVTYP_CONFMGMDATA 0x0427#define EVTYP_DIAG_TEST 0x0728#define EVTYP_STATECHANGE 0x0829#define EVTYP_PMSGCMD 0x0930#define EVTYP_ASYNC 0x0A31#define EVTYP_CTLPROGIDENT 0x0B32#define EVTYP_STORE_DATA 0x0C33#define EVTYP_ERRNOTIFY 0x1834#define EVTYP_VT220MSG 0x1A35#define EVTYP_SDIAS 0x1C36#define EVTYP_SIGQUIESCE 0x1D37#define EVTYP_OCF 0x1E38 39#define EVTYP_OPCMD_MASK SCLP_EVTYP_MASK(EVTYP_OPCMD)40#define EVTYP_MSG_MASK SCLP_EVTYP_MASK(EVTYP_MSG)41#define EVTYP_CONFMGMDATA_MASK SCLP_EVTYP_MASK(EVTYP_CONFMGMDATA)42#define EVTYP_DIAG_TEST_MASK SCLP_EVTYP_MASK(EVTYP_DIAG_TEST)43#define EVTYP_STATECHANGE_MASK SCLP_EVTYP_MASK(EVTYP_STATECHANGE)44#define EVTYP_PMSGCMD_MASK SCLP_EVTYP_MASK(EVTYP_PMSGCMD)45#define EVTYP_ASYNC_MASK SCLP_EVTYP_MASK(EVTYP_ASYNC)46#define EVTYP_CTLPROGIDENT_MASK SCLP_EVTYP_MASK(EVTYP_CTLPROGIDENT)47#define EVTYP_STORE_DATA_MASK SCLP_EVTYP_MASK(EVTYP_STORE_DATA)48#define EVTYP_ERRNOTIFY_MASK SCLP_EVTYP_MASK(EVTYP_ERRNOTIFY)49#define EVTYP_VT220MSG_MASK SCLP_EVTYP_MASK(EVTYP_VT220MSG)50#define EVTYP_SDIAS_MASK SCLP_EVTYP_MASK(EVTYP_SDIAS)51#define EVTYP_SIGQUIESCE_MASK SCLP_EVTYP_MASK(EVTYP_SIGQUIESCE)52#define EVTYP_OCF_MASK SCLP_EVTYP_MASK(EVTYP_OCF)53 54#define GNRLMSGFLGS_DOM 0x800055#define GNRLMSGFLGS_SNDALRM 0x400056#define GNRLMSGFLGS_HOLDMSG 0x200057 58#define LNTPFLGS_CNTLTEXT 0x800059#define LNTPFLGS_LABELTEXT 0x400060#define LNTPFLGS_DATATEXT 0x200061#define LNTPFLGS_ENDTEXT 0x100062#define LNTPFLGS_PROMPTTEXT 0x080063 64typedef unsigned int sclp_cmdw_t;65 66#define SCLP_CMDW_READ_CPU_INFO 0x0001000167#define SCLP_CMDW_READ_SCP_INFO 0x0002000168#define SCLP_CMDW_READ_STORAGE_INFO 0x0004000169#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x0012000170#define SCLP_CMDW_READ_EVENT_DATA 0x0077000571#define SCLP_CMDW_WRITE_EVENT_DATA 0x0076000572#define SCLP_CMDW_WRITE_EVENT_MASK 0x0078000573 74#define GDS_ID_MDSMU 0x131075#define GDS_ID_MDSROUTEINFO 0x131176#define GDS_ID_AGUNWRKCORR 0x154977#define GDS_ID_SNACONDREPORT 0x153278#define GDS_ID_CPMSU 0x121279#define GDS_ID_ROUTTARGINSTR 0x154D80#define GDS_ID_OPREQ 0x807081#define GDS_ID_TEXTCMD 0x132082 83#define GDS_KEY_SELFDEFTEXTMSG 0x3184 85typedef u64 sccb_mask_t;86 87struct sccb_header {88 u16 length;89 u8 function_code;90 u8 control_mask[3];91 u16 response_code;92} __attribute__((packed));93 94struct init_sccb {95 struct sccb_header header;96 u16 _reserved;97 u16 mask_length;98 u8 masks[4 * 1021]; /* variable length */99 /*100 * u8 receive_mask[mask_length];101 * u8 send_mask[mask_length];102 * u8 sclp_receive_mask[mask_length];103 * u8 sclp_send_mask[mask_length];104 */105} __attribute__((packed));106 107#define SCLP_MASK_SIZE_COMPAT 4108 109static inline sccb_mask_t sccb_get_mask(u8 *masks, size_t len, int i)110{111 sccb_mask_t res = 0;112 113 memcpy(&res, masks + i * len, min(sizeof(res), len));114 return res;115}116 117static inline void sccb_set_mask(u8 *masks, size_t len, int i, sccb_mask_t val)118{119 memset(masks + i * len, 0, len);120 memcpy(masks + i * len, &val, min(sizeof(val), len));121}122 123#define sccb_get_generic_mask(sccb, i) \124({ \125 __typeof__(sccb) __sccb = sccb; \126 \127 sccb_get_mask(__sccb->masks, __sccb->mask_length, i); \128})129#define sccb_get_recv_mask(sccb) sccb_get_generic_mask(sccb, 0)130#define sccb_get_send_mask(sccb) sccb_get_generic_mask(sccb, 1)131#define sccb_get_sclp_recv_mask(sccb) sccb_get_generic_mask(sccb, 2)132#define sccb_get_sclp_send_mask(sccb) sccb_get_generic_mask(sccb, 3)133 134#define sccb_set_generic_mask(sccb, i, val) \135({ \136 __typeof__(sccb) __sccb = sccb; \137 \138 sccb_set_mask(__sccb->masks, __sccb->mask_length, i, val); \139})140#define sccb_set_recv_mask(sccb, val) sccb_set_generic_mask(sccb, 0, val)141#define sccb_set_send_mask(sccb, val) sccb_set_generic_mask(sccb, 1, val)142#define sccb_set_sclp_recv_mask(sccb, val) sccb_set_generic_mask(sccb, 2, val)143#define sccb_set_sclp_send_mask(sccb, val) sccb_set_generic_mask(sccb, 3, val)144 145struct read_cpu_info_sccb {146 struct sccb_header header;147 u16 nr_configured;148 u16 offset_configured;149 u16 nr_standby;150 u16 offset_standby;151 /*152 * Without ext sccb, struct size is PAGE_SIZE.153 * With ext sccb, struct size is EXT_SCCB_READ_CPU.154 */155 u8 reserved[];156} __attribute__((packed, aligned(PAGE_SIZE)));157 158struct read_info_sccb {159 struct sccb_header header; /* 0-7 */160 u16 rnmax; /* 8-9 */161 u8 rnsize; /* 10 */162 u8 _pad_11[16 - 11]; /* 11-15 */163 u16 ncpurl; /* 16-17 */164 u16 cpuoff; /* 18-19 */165 u8 _pad_20[24 - 20]; /* 20-23 */166 u8 loadparm[8]; /* 24-31 */167 u8 _pad_32[42 - 32]; /* 32-41 */168 u8 fac42; /* 42 */169 u8 fac43; /* 43 */170 u8 _pad_44[48 - 44]; /* 44-47 */171 u64 facilities; /* 48-55 */172 u8 _pad_56[66 - 56]; /* 56-65 */173 u8 fac66; /* 66 */174 u8 _pad_67[76 - 67]; /* 67-83 */175 u32 ibc; /* 76-79 */176 u8 _pad80[84 - 80]; /* 80-83 */177 u8 fac84; /* 84 */178 u8 fac85; /* 85 */179 u8 _pad_86[91 - 86]; /* 86-90 */180 u8 fac91; /* 91 */181 u8 _pad_92[98 - 92]; /* 92-97 */182 u8 fac98; /* 98 */183 u8 hamaxpow; /* 99 */184 u32 rnsize2; /* 100-103 */185 u64 rnmax2; /* 104-111 */186 u32 hsa_size; /* 112-115 */187 u8 fac116; /* 116 */188 u8 fac117; /* 117 */189 u8 fac118; /* 118 */190 u8 fac119; /* 119 */191 u16 hcpua; /* 120-121 */192 u8 _pad_122[124 - 122]; /* 122-123 */193 u32 hmfai; /* 124-127 */194 u8 _pad_128[134 - 128]; /* 128-133 */195 u8 byte_134; /* 134 */196 u8 cpudirq; /* 135 */197 u16 cbl; /* 136-137 */198 u8 _pad_138[EXT_SCCB_READ_SCP - 138];199} __packed __aligned(PAGE_SIZE);200 201struct read_storage_sccb {202 struct sccb_header header;203 u16 max_id;204 u16 assigned;205 u16 standby;206 u16 :16;207 u32 entries[];208} __packed;209 210static inline void sclp_fill_core_info(struct sclp_core_info *info,211 struct read_cpu_info_sccb *sccb)212{213 char *page = (char *) sccb;214 215 memset(info, 0, sizeof(*info));216 info->configured = sccb->nr_configured;217 info->standby = sccb->nr_standby;218 info->combined = sccb->nr_configured + sccb->nr_standby;219 memcpy(&info->core, page + sccb->offset_configured,220 info->combined * sizeof(struct sclp_core_entry));221}222 223#define SCLP_HAS_CHP_INFO (sclp.facilities & 0x8000000000000000ULL)224#define SCLP_HAS_CHP_RECONFIG (sclp.facilities & 0x2000000000000000ULL)225#define SCLP_HAS_CPU_INFO (sclp.facilities & 0x0800000000000000ULL)226#define SCLP_HAS_CPU_RECONFIG (sclp.facilities & 0x0400000000000000ULL)227#define SCLP_HAS_PCI_RECONFIG (sclp.facilities & 0x0000000040000000ULL)228#define SCLP_HAS_AP_RECONFIG (sclp.facilities & 0x0000000100000000ULL)229 230struct gds_subvector {231 u8 length;232 u8 key;233} __attribute__((packed));234 235struct gds_vector {236 u16 length;237 u16 gds_id;238} __attribute__((packed));239 240struct evbuf_header {241 u16 length;242 u8 type;243 u8 flags;244 u16 _reserved;245} __attribute__((packed));246 247struct sclp_req {248 struct list_head list; /* list_head for request queueing. */249 sclp_cmdw_t command; /* sclp command to execute */250 void *sccb; /* pointer to the sccb to execute */251 char status; /* status of this request */252 int start_count; /* number of SVCs done for this req */253 /* Callback that is called after reaching final status. */254 void (*callback)(struct sclp_req *, void *data);255 void *callback_data;256 int queue_timeout; /* request queue timeout (sec), set by257 caller of sclp_add_request(), if258 needed */259 /* Internal fields */260 unsigned long queue_expires; /* request queue timeout (jiffies) */261};262 263#define SCLP_REQ_FILLED 0x00 /* request is ready to be processed */264#define SCLP_REQ_QUEUED 0x01 /* request is queued to be processed */265#define SCLP_REQ_RUNNING 0x02 /* request is currently running */266#define SCLP_REQ_DONE 0x03 /* request is completed successfully */267#define SCLP_REQ_FAILED 0x05 /* request is finally failed */268#define SCLP_REQ_QUEUED_TIMEOUT 0x06 /* request on queue timed out */269 270#define SCLP_QUEUE_INTERVAL 5 /* timeout interval for request queue */271 272/* function pointers that a high level driver has to use for registration */273/* of some routines it wants to be called from the low level driver */274struct sclp_register {275 struct list_head list;276 /* User wants to receive: */277 sccb_mask_t receive_mask;278 /* User wants to send: */279 sccb_mask_t send_mask;280 /* H/W can receive: */281 sccb_mask_t sclp_receive_mask;282 /* H/W can send: */283 sccb_mask_t sclp_send_mask;284 /* called if event type availability changes */285 void (*state_change_fn)(struct sclp_register *);286 /* called for events in cp_receive_mask/sclp_receive_mask */287 void (*receiver_fn)(struct evbuf_header *);288};289 290/* externals from sclp.c */291int sclp_add_request(struct sclp_req *req);292void sclp_sync_wait(void);293int sclp_register(struct sclp_register *reg);294void sclp_unregister(struct sclp_register *reg);295int sclp_remove_processed(struct sccb_header *sccb);296int sclp_deactivate(void);297int sclp_reactivate(void);298int sclp_sync_request(sclp_cmdw_t command, void *sccb);299int sclp_sync_request_timeout(sclp_cmdw_t command, void *sccb, int timeout);300int sclp_sdias_init(void);301 302enum {303 sclp_init_state_uninitialized,304 sclp_init_state_initializing,305 sclp_init_state_initialized306};307 308extern int sclp_init_state;309extern int sclp_console_pages;310extern bool sclp_console_drop;311extern unsigned long sclp_console_full;312extern bool sclp_mask_compat_mode;313 314void sclp_early_wait_irq(void);315int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb);316unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb);317unsigned int sclp_early_con_check_vt220(struct init_sccb *sccb);318int sclp_early_set_event_mask(struct init_sccb *sccb,319 sccb_mask_t receive_mask,320 sccb_mask_t send_mask);321struct read_info_sccb * __init sclp_early_get_info(void);322 323/* useful inlines */324 325/* Perform service call. Return 0 on success, non-zero otherwise. */326static inline int sclp_service_call(sclp_cmdw_t command, void *sccb)327{328 int cc = 4; /* Initialize for program check handling */329 330 asm volatile(331 "0: .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */332 "1: ipm %0\n"333 " srl %0,28\n"334 "2:\n"335 EX_TABLE(0b, 2b)336 EX_TABLE(1b, 2b)337 : "+&d" (cc) : "d" (command), "a" (__pa(sccb))338 : "cc", "memory");339 if (cc == 4)340 return -EINVAL;341 if (cc == 3)342 return -EIO;343 if (cc == 2)344 return -EBUSY;345 return 0;346}347 348/* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */349/* translate single character from ASCII to EBCDIC */350static inline unsigned char351sclp_ascebc(unsigned char ch)352{353 return (MACHINE_IS_VM) ? _ascebc[ch] : _ascebc_500[ch];354}355 356/* translate string from EBCDIC to ASCII */357static inline void358sclp_ebcasc_str(char *str, int nr)359{360 (MACHINE_IS_VM) ? EBCASC(str, nr) : EBCASC_500(str, nr);361}362 363/* translate string from ASCII to EBCDIC */364static inline void365sclp_ascebc_str(char *str, int nr)366{367 (MACHINE_IS_VM) ? ASCEBC(str, nr) : ASCEBC_500(str, nr);368}369 370static inline struct gds_vector *371sclp_find_gds_vector(void *start, void *end, u16 id)372{373 struct gds_vector *v;374 375 for (v = start; (void *) v < end; v = (void *) v + v->length)376 if (v->gds_id == id)377 return v;378 return NULL;379}380 381static inline struct gds_subvector *382sclp_find_gds_subvector(void *start, void *end, u8 key)383{384 struct gds_subvector *sv;385 386 for (sv = start; (void *) sv < end; sv = (void *) sv + sv->length)387 if (sv->key == key)388 return sv;389 return NULL;390}391 392#endif /* __SCLP_H__ */393