1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * CSS definitions 4 * 5 * Copyright IBM Corp. 2020 6 * Author: Pierre Morel <pmorel@linux.ibm.com> 7 */ 8 9 #ifndef _S390X_CSS_H_ 10 #define _S390X_CSS_H_ 11 12 /* subchannel ID bit 16 must always be one */ 13 #define SCHID_ONE 0x00010000 14 15 #define CCW_F_CD 0x80 16 #define CCW_F_CC 0x40 17 #define CCW_F_SLI 0x20 18 #define CCW_F_SKP 0x10 19 #define CCW_F_PCI 0x08 20 #define CCW_F_IDA 0x04 21 #define CCW_F_S 0x02 22 #define CCW_F_MIDA 0x01 23 24 #define CCW_C_NOP 0x03 25 #define CCW_C_TIC 0x08 26 27 struct ccw1 { 28 uint8_t code; 29 uint8_t flags; 30 uint16_t count; 31 uint32_t data_address; 32 } __attribute__ ((aligned(8))); 33 34 #define ORB_CTRL_KEY 0xf0000000 35 #define ORB_CTRL_SPND 0x08000000 36 #define ORB_CTRL_STR 0x04000000 37 #define ORB_CTRL_MOD 0x02000000 38 #define ORB_CTRL_SYNC 0x01000000 39 #define ORB_CTRL_FMT 0x00800000 40 #define ORB_CTRL_PFCH 0x00400000 41 #define ORB_CTRL_ISIC 0x00200000 42 #define ORB_CTRL_ALCC 0x00100000 43 #define ORB_CTRL_SSIC 0x00080000 44 #define ORB_CTRL_CPTC 0x00040000 45 #define ORB_CTRL_C64 0x00020000 46 #define ORB_CTRL_I2K 0x00010000 47 #define ORB_CTRL_LPM 0x0000ff00 48 #define ORB_CTRL_ILS 0x00000080 49 #define ORB_CTRL_MIDAW 0x00000040 50 #define ORB_CTRL_ORBX 0x00000001 51 52 #define ORB_LPM_DFLT 0x00008000 53 54 struct orb { 55 uint32_t intparm; 56 uint32_t ctrl; 57 uint32_t cpa; 58 uint32_t prio; 59 uint32_t reserved[4]; 60 } __attribute__ ((aligned(4))); 61 62 struct scsw { 63 #define SCSW_SC_PENDING 0x00000001 64 #define SCSW_SC_SECONDARY 0x00000002 65 #define SCSW_SC_PRIMARY 0x00000004 66 #define SCSW_SC_INTERMEDIATE 0x00000008 67 #define SCSW_SC_ALERT 0x00000010 68 uint32_t ctrl; 69 uint32_t ccw_addr; 70 #define SCSW_DEVS_DEV_END 0x04 71 #define SCSW_DEVS_SCH_END 0x08 72 uint8_t dev_stat; 73 #define SCSW_SCHS_PCI 0x80 74 #define SCSW_SCHS_IL 0x40 75 uint8_t sch_stat; 76 uint16_t count; 77 }; 78 79 struct pmcw { 80 uint32_t intparm; 81 #define PMCW_DNV 0x0001 82 #define PMCW_ENABLE 0x0080 83 #define PMCW_MBUE 0x0010 84 #define PMCW_DCTME 0x0008 85 #define PMCW_ISC_MASK 0x3800 86 #define PMCW_ISC_SHIFT 11 87 uint16_t flags; 88 uint16_t devnum; 89 uint8_t lpm; 90 uint8_t pnom; 91 uint8_t lpum; 92 uint8_t pim; 93 uint16_t mbi; 94 uint8_t pom; 95 uint8_t pam; 96 uint8_t chpid[8]; 97 #define PMCW_MBF1 0x0004 98 uint32_t flags2; 99 }; 100 #define PMCW_CHANNEL_TYPE(pmcw) (pmcw->flags2 >> 21) 101 102 struct schib { 103 struct pmcw pmcw; 104 struct scsw scsw; 105 uint64_t mbo; 106 uint8_t md[4]; 107 } __attribute__ ((aligned(4))); 108 extern struct schib schib; 109 110 struct irb { 111 struct scsw scsw; 112 uint32_t esw[5]; 113 uint32_t ecw[8]; 114 uint32_t emw[8]; 115 } __attribute__ ((aligned(4))); 116 117 #define CCW_CMD_SENSE_ID 0xe4 118 #define CSS_SENSEID_COMMON_LEN 8 119 struct senseid { 120 /* common part */ 121 uint8_t reserved; /* always 0x'FF' */ 122 uint16_t cu_type; /* control unit type */ 123 uint8_t cu_model; /* control unit model */ 124 uint16_t dev_type; /* device type */ 125 uint8_t dev_model; /* device model */ 126 uint8_t unused; /* padding byte */ 127 uint8_t padding[256 - 8]; /* Extended part */ 128 } __attribute__ ((aligned(4))) __attribute__ ((packed)); 129 130 /* CSS low level access functions */ 131 132 static inline int ssch(unsigned long schid, struct orb *addr) 133 { 134 register long long reg1 asm("1") = schid; 135 int cc; 136 137 asm volatile( 138 " ssch 0(%2)\n" 139 " ipm %0\n" 140 " srl %0,28\n" 141 : "=d" (cc) 142 : "d" (reg1), "a" (addr), "m" (*addr) 143 : "cc", "memory"); 144 return cc; 145 } 146 147 static inline int stsch(unsigned long schid, struct schib *addr) 148 { 149 register unsigned long reg1 asm ("1") = schid; 150 uint64_t bogus_cc = 1; 151 int cc; 152 153 asm volatile( 154 " tmll %[bogus_cc],3\n" 155 " stsch 0(%3)\n" 156 " ipm %0\n" 157 " srl %0,28" 158 : "=d" (cc), "=m" (*addr) 159 : "d" (reg1), "a" (addr), [bogus_cc] "d" (bogus_cc) 160 : "cc"); 161 return cc; 162 } 163 164 static inline int msch(unsigned long schid, struct schib *addr) 165 { 166 register unsigned long reg1 asm ("1") = schid; 167 int cc; 168 169 asm volatile( 170 " msch 0(%3)\n" 171 " ipm %0\n" 172 " srl %0,28" 173 : "=d" (cc) 174 : "d" (reg1), "m" (*addr), "a" (addr) 175 : "cc"); 176 return cc; 177 } 178 179 static inline int tsch(unsigned long schid, struct irb *addr) 180 { 181 register unsigned long reg1 asm ("1") = schid; 182 uint64_t bogus_cc = 2; 183 int cc; 184 185 asm volatile( 186 " tmll %[bogus_cc],3\n" 187 " tsch 0(%3)\n" 188 " ipm %0\n" 189 " srl %0,28" 190 : "=d" (cc), "=m" (*addr) 191 : "d" (reg1), "a" (addr), [bogus_cc] "d" (bogus_cc) 192 : "cc"); 193 return cc; 194 } 195 196 static inline int hsch(unsigned long schid) 197 { 198 register unsigned long reg1 asm("1") = schid; 199 int cc; 200 201 asm volatile( 202 " hsch\n" 203 " ipm %0\n" 204 " srl %0,28" 205 : "=d" (cc) 206 : "d" (reg1) 207 : "cc"); 208 return cc; 209 } 210 211 static inline int xsch(unsigned long schid) 212 { 213 register unsigned long reg1 asm("1") = schid; 214 int cc; 215 216 asm volatile( 217 " xsch\n" 218 " ipm %0\n" 219 " srl %0,28" 220 : "=d" (cc) 221 : "d" (reg1) 222 : "cc"); 223 return cc; 224 } 225 226 static inline int csch(unsigned long schid) 227 { 228 register unsigned long reg1 asm("1") = schid; 229 int cc; 230 231 asm volatile( 232 " csch\n" 233 " ipm %0\n" 234 " srl %0,28" 235 : "=d" (cc) 236 : "d" (reg1) 237 : "cc"); 238 return cc; 239 } 240 241 static inline int rsch(unsigned long schid) 242 { 243 register unsigned long reg1 asm("1") = schid; 244 int cc; 245 246 asm volatile( 247 " rsch\n" 248 " ipm %0\n" 249 " srl %0,28" 250 : "=d" (cc) 251 : "d" (reg1) 252 : "cc"); 253 return cc; 254 } 255 256 static inline int rchp(unsigned long chpid) 257 { 258 register unsigned long reg1 asm("1") = chpid; 259 uint64_t bogus_cc = 1; 260 int cc; 261 262 asm volatile( 263 " tmll %[bogus_cc],3\n" 264 " rchp\n" 265 " ipm %0\n" 266 " srl %0,28" 267 : "=d" (cc) 268 : "d" (reg1), [bogus_cc] "d" (bogus_cc) 269 : "cc"); 270 return cc; 271 } 272 273 static inline int stcrw(uint32_t *crw) 274 { 275 uint64_t bogus_cc = 1; 276 int cc; 277 278 asm volatile( 279 " tmll %[bogus_cc],3\n" 280 " stcrw %[crw]\n" 281 " ipm %[cc]\n" 282 " srl %[cc],28" 283 : [cc] "=d" (cc) 284 : [crw] "Q" (*crw), [bogus_cc] "d" (bogus_cc) 285 : "cc", "memory"); 286 return cc; 287 } 288 289 /* Debug functions */ 290 char *dump_pmcw_flags(uint16_t f); 291 char *dump_scsw_flags(uint32_t f); 292 293 void dump_scsw(struct scsw *scsw); 294 void dump_irb(struct irb *irbp); 295 void dump_schib(struct schib *sch); 296 struct ccw1 *dump_ccw(struct ccw1 *cp); 297 void dump_irb(struct irb *irbp); 298 void dump_pmcw(struct pmcw *p); 299 void dump_orb(struct orb *op); 300 301 int css_enumerate(void); 302 #define MAX_ENABLE_RETRIES 5 303 304 #define IO_SCH_ISC 3 305 int css_enable(int schid, int isc); 306 bool css_enabled(int schid); 307 308 /* Library functions */ 309 int start_ccw1_chain(unsigned int sid, struct ccw1 *ccw); 310 struct ccw1 *ccw_alloc(int code, void *data, int count, unsigned char flags); 311 void css_irq_io(void); 312 int css_residual_count(unsigned int schid); 313 314 void enable_io_isc(uint8_t isc); 315 int wait_and_check_io_completion(int schid); 316 317 int css_find_installed_chpid(int sid, uint8_t *chpid_out); 318 int css_generate_crw(int sid); 319 320 /* 321 * CHSC definitions 322 */ 323 struct chsc_header { 324 uint16_t len; 325 uint16_t code; 326 }; 327 328 /* Store Channel Subsystem Characteristics */ 329 struct chsc_scsc { 330 struct chsc_header req; 331 uint16_t req_fmt; 332 uint8_t cssid; 333 uint8_t reserved[9]; 334 struct chsc_header res; 335 uint32_t res_fmt; 336 #define CSSC_EXTENDED_MEASUREMENT_BLOCK 48 337 uint64_t general_char[255]; 338 uint64_t chsc_char[254]; 339 }; 340 341 extern struct chsc_scsc *chsc_scsc; 342 #define CHSC_SCSC 0x0010 343 #define CHSC_SCSC_LEN 0x0010 344 345 bool get_chsc_scsc(void); 346 347 #define CSS_GENERAL_FEAT_BITLEN (255 * 64) 348 #define CSS_CHSC_FEAT_BITLEN (254 * 64) 349 350 #define CHSC_SCSC 0x0010 351 #define CHSC_SCSC_LEN 0x0010 352 353 #define CHSC_ERROR 0x0000 354 #define CHSC_RSP_OK 0x0001 355 #define CHSC_RSP_INVAL 0x0002 356 #define CHSC_RSP_REQERR 0x0003 357 #define CHSC_RSP_ENOCMD 0x0004 358 #define CHSC_RSP_NODATA 0x0005 359 #define CHSC_RSP_SUP31B 0x0006 360 #define CHSC_RSP_EFRMT 0x0007 361 #define CHSC_RSP_ECSSID 0x0008 362 #define CHSC_RSP_ERFRMT 0x0009 363 #define CHSC_RSP_ESSID 0x000A 364 #define CHSC_RSP_EBUSY 0x000B 365 #define CHSC_RSP_MAX 0x000B 366 367 static inline int _chsc(void *p) 368 { 369 int cc; 370 371 asm volatile(" .insn rre,0xb25f0000,%2,0\n" 372 " ipm %0\n" 373 " srl %0,28\n" 374 : "=d" (cc), "=m" (p) 375 : "d" (p), "m" (p) 376 : "cc"); 377 378 return cc; 379 } 380 381 bool chsc(void *p, uint16_t code, uint16_t len); 382 383 #include <bitops.h> 384 #define css_test_general_feature(bit) test_bit_inv(bit, chsc_scsc->general_char) 385 #define css_test_chsc_feature(bit) test_bit_inv(bit, chsc_scsc->chsc_char) 386 387 #define SCHM_DCTM 1 /* activate Device Connection TiMe */ 388 #define SCHM_MBU 2 /* activate Measurement Block Update */ 389 390 static inline void schm(void *mbo, unsigned int flags) 391 { 392 register void *__gpr2 asm("2") = mbo; 393 register long __gpr1 asm("1") = flags; 394 395 asm("schm" : : "d" (__gpr2), "d" (__gpr1)); 396 } 397 398 bool css_enable_mb(int sid, uint64_t mb, uint16_t mbi, uint16_t flg, bool fmt1); 399 bool css_disable_mb(int schid); 400 401 struct measurement_block_format0 { 402 uint16_t ssch_rsch_count; 403 uint16_t sample_count; 404 uint32_t device_connect_time; 405 uint32_t function_pending_time; 406 uint32_t device_disconnect_time; 407 uint32_t cu_queuing_time; 408 uint32_t device_active_only_time; 409 uint32_t device_busy_time; 410 uint32_t initial_cmd_resp_time; 411 }; 412 413 struct measurement_block_format1 { 414 uint32_t ssch_rsch_count; 415 uint32_t sample_count; 416 uint32_t device_connect_time; 417 uint32_t function_pending_time; 418 uint32_t device_disconnect_time; 419 uint32_t cu_queuing_time; 420 uint32_t device_active_only_time; 421 uint32_t device_busy_time; 422 uint32_t initial_cmd_resp_time; 423 uint32_t irq_delay_time; 424 uint32_t irq_prio_delay_time; 425 }; 426 427 #endif 428