16c9f99dfSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */ 2a3b101f0SPierre Morel /* 3a3b101f0SPierre Morel * CSS definitions 4a3b101f0SPierre Morel * 5a3b101f0SPierre Morel * Copyright IBM, Corp. 2020 6a3b101f0SPierre Morel * Author: Pierre Morel <pmorel@linux.ibm.com> 7a3b101f0SPierre Morel */ 8a3b101f0SPierre Morel 9a3b101f0SPierre Morel #ifndef CSS_H 10a3b101f0SPierre Morel #define CSS_H 11a3b101f0SPierre Morel 128cb729e4SPierre Morel #define lowcore_ptr ((struct lowcore *)0x0) 138cb729e4SPierre Morel 14a3b101f0SPierre Morel /* subchannel ID bit 16 must always be one */ 15a3b101f0SPierre Morel #define SCHID_ONE 0x00010000 16a3b101f0SPierre Morel 17a3b101f0SPierre Morel #define CCW_F_CD 0x80 18a3b101f0SPierre Morel #define CCW_F_CC 0x40 19a3b101f0SPierre Morel #define CCW_F_SLI 0x20 20a3b101f0SPierre Morel #define CCW_F_SKP 0x10 21a3b101f0SPierre Morel #define CCW_F_PCI 0x08 22a3b101f0SPierre Morel #define CCW_F_IDA 0x04 23a3b101f0SPierre Morel #define CCW_F_S 0x02 24a3b101f0SPierre Morel #define CCW_F_MIDA 0x01 25a3b101f0SPierre Morel 26a3b101f0SPierre Morel #define CCW_C_NOP 0x03 27a3b101f0SPierre Morel #define CCW_C_TIC 0x08 28a3b101f0SPierre Morel 29a3b101f0SPierre Morel struct ccw1 { 30a3b101f0SPierre Morel uint8_t code; 31a3b101f0SPierre Morel uint8_t flags; 32a3b101f0SPierre Morel uint16_t count; 33a3b101f0SPierre Morel uint32_t data_address; 34a3b101f0SPierre Morel } __attribute__ ((aligned(8))); 35a3b101f0SPierre Morel 36a3b101f0SPierre Morel #define ORB_CTRL_KEY 0xf0000000 37a3b101f0SPierre Morel #define ORB_CTRL_SPND 0x08000000 38a3b101f0SPierre Morel #define ORB_CTRL_STR 0x04000000 39a3b101f0SPierre Morel #define ORB_CTRL_MOD 0x02000000 40a3b101f0SPierre Morel #define ORB_CTRL_SYNC 0x01000000 41a3b101f0SPierre Morel #define ORB_CTRL_FMT 0x00800000 42a3b101f0SPierre Morel #define ORB_CTRL_PFCH 0x00400000 43a3b101f0SPierre Morel #define ORB_CTRL_ISIC 0x00200000 44a3b101f0SPierre Morel #define ORB_CTRL_ALCC 0x00100000 45a3b101f0SPierre Morel #define ORB_CTRL_SSIC 0x00080000 46a3b101f0SPierre Morel #define ORB_CTRL_CPTC 0x00040000 47a3b101f0SPierre Morel #define ORB_CTRL_C64 0x00020000 48a3b101f0SPierre Morel #define ORB_CTRL_I2K 0x00010000 49a3b101f0SPierre Morel #define ORB_CTRL_LPM 0x0000ff00 50a3b101f0SPierre Morel #define ORB_CTRL_ILS 0x00000080 51a3b101f0SPierre Morel #define ORB_CTRL_MIDAW 0x00000040 52a3b101f0SPierre Morel #define ORB_CTRL_ORBX 0x00000001 53a3b101f0SPierre Morel 54a3b101f0SPierre Morel #define ORB_LPM_DFLT 0x00008000 55a3b101f0SPierre Morel 56a3b101f0SPierre Morel struct orb { 57a3b101f0SPierre Morel uint32_t intparm; 58a3b101f0SPierre Morel uint32_t ctrl; 59a3b101f0SPierre Morel uint32_t cpa; 60a3b101f0SPierre Morel uint32_t prio; 61a3b101f0SPierre Morel uint32_t reserved[4]; 62a3b101f0SPierre Morel } __attribute__ ((aligned(4))); 63a3b101f0SPierre Morel 64a3b101f0SPierre Morel struct scsw { 658cb729e4SPierre Morel #define SCSW_SC_PENDING 0x00000001 668cb729e4SPierre Morel #define SCSW_SC_SECONDARY 0x00000002 678cb729e4SPierre Morel #define SCSW_SC_PRIMARY 0x00000004 688cb729e4SPierre Morel #define SCSW_SC_INTERMEDIATE 0x00000008 698cb729e4SPierre Morel #define SCSW_SC_ALERT 0x00000010 70a3b101f0SPierre Morel uint32_t ctrl; 71a3b101f0SPierre Morel uint32_t ccw_addr; 728cb729e4SPierre Morel #define SCSW_DEVS_DEV_END 0x04 738cb729e4SPierre Morel #define SCSW_DEVS_SCH_END 0x08 74a3b101f0SPierre Morel uint8_t dev_stat; 758cb729e4SPierre Morel #define SCSW_SCHS_PCI 0x80 768cb729e4SPierre Morel #define SCSW_SCHS_IL 0x40 77a3b101f0SPierre Morel uint8_t sch_stat; 78a3b101f0SPierre Morel uint16_t count; 79a3b101f0SPierre Morel }; 80a3b101f0SPierre Morel 81a3b101f0SPierre Morel struct pmcw { 82a3b101f0SPierre Morel uint32_t intparm; 83a3b101f0SPierre Morel #define PMCW_DNV 0x0001 84a3b101f0SPierre Morel #define PMCW_ENABLE 0x0080 85551e6622SPierre Morel #define PMCW_ISC_MASK 0x3800 86551e6622SPierre Morel #define PMCW_ISC_SHIFT 11 87a3b101f0SPierre Morel uint16_t flags; 88a3b101f0SPierre Morel uint16_t devnum; 89a3b101f0SPierre Morel uint8_t lpm; 90a3b101f0SPierre Morel uint8_t pnom; 91a3b101f0SPierre Morel uint8_t lpum; 92a3b101f0SPierre Morel uint8_t pim; 93a3b101f0SPierre Morel uint16_t mbi; 94a3b101f0SPierre Morel uint8_t pom; 95a3b101f0SPierre Morel uint8_t pam; 96a3b101f0SPierre Morel uint8_t chpid[8]; 97a3b101f0SPierre Morel uint32_t flags2; 98a3b101f0SPierre Morel }; 99a3b101f0SPierre Morel #define PMCW_CHANNEL_TYPE(pmcw) (pmcw->flags2 >> 21) 100a3b101f0SPierre Morel 101a3b101f0SPierre Morel struct schib { 102a3b101f0SPierre Morel struct pmcw pmcw; 103a3b101f0SPierre Morel struct scsw scsw; 104a3b101f0SPierre Morel uint8_t md[12]; 105a3b101f0SPierre Morel } __attribute__ ((aligned(4))); 106a3b101f0SPierre Morel 107a3b101f0SPierre Morel struct irb { 108a3b101f0SPierre Morel struct scsw scsw; 109a3b101f0SPierre Morel uint32_t esw[5]; 110a3b101f0SPierre Morel uint32_t ecw[8]; 111a3b101f0SPierre Morel uint32_t emw[8]; 112a3b101f0SPierre Morel } __attribute__ ((aligned(4))); 113a3b101f0SPierre Morel 1148cb729e4SPierre Morel #define CCW_CMD_SENSE_ID 0xe4 1158cb729e4SPierre Morel #define CSS_SENSEID_COMMON_LEN 8 1168cb729e4SPierre Morel struct senseid { 1178cb729e4SPierre Morel /* common part */ 1188cb729e4SPierre Morel uint8_t reserved; /* always 0x'FF' */ 1198cb729e4SPierre Morel uint16_t cu_type; /* control unit type */ 1208cb729e4SPierre Morel uint8_t cu_model; /* control unit model */ 1218cb729e4SPierre Morel uint16_t dev_type; /* device type */ 1228cb729e4SPierre Morel uint8_t dev_model; /* device model */ 1238cb729e4SPierre Morel uint8_t unused; /* padding byte */ 1248cb729e4SPierre Morel uint8_t padding[256 - 8]; /* Extended part */ 1258cb729e4SPierre Morel } __attribute__ ((aligned(4))) __attribute__ ((packed)); 1268cb729e4SPierre Morel 127a3b101f0SPierre Morel /* CSS low level access functions */ 128a3b101f0SPierre Morel 129a3b101f0SPierre Morel static inline int ssch(unsigned long schid, struct orb *addr) 130a3b101f0SPierre Morel { 131a3b101f0SPierre Morel register long long reg1 asm("1") = schid; 132a3b101f0SPierre Morel int cc; 133a3b101f0SPierre Morel 134a3b101f0SPierre Morel asm volatile( 135a3b101f0SPierre Morel " ssch 0(%2)\n" 136a3b101f0SPierre Morel " ipm %0\n" 137a3b101f0SPierre Morel " srl %0,28\n" 138a3b101f0SPierre Morel : "=d" (cc) 139a3b101f0SPierre Morel : "d" (reg1), "a" (addr), "m" (*addr) 140a3b101f0SPierre Morel : "cc", "memory"); 141a3b101f0SPierre Morel return cc; 142a3b101f0SPierre Morel } 143a3b101f0SPierre Morel 144a3b101f0SPierre Morel static inline int stsch(unsigned long schid, struct schib *addr) 145a3b101f0SPierre Morel { 146a3b101f0SPierre Morel register unsigned long reg1 asm ("1") = schid; 147a3b101f0SPierre Morel int cc; 148a3b101f0SPierre Morel 149a3b101f0SPierre Morel asm volatile( 150a3b101f0SPierre Morel " stsch 0(%3)\n" 151a3b101f0SPierre Morel " ipm %0\n" 152a3b101f0SPierre Morel " srl %0,28" 153a3b101f0SPierre Morel : "=d" (cc), "=m" (*addr) 154a3b101f0SPierre Morel : "d" (reg1), "a" (addr) 155a3b101f0SPierre Morel : "cc"); 156a3b101f0SPierre Morel return cc; 157a3b101f0SPierre Morel } 158a3b101f0SPierre Morel 159a3b101f0SPierre Morel static inline int msch(unsigned long schid, struct schib *addr) 160a3b101f0SPierre Morel { 161a3b101f0SPierre Morel register unsigned long reg1 asm ("1") = schid; 162a3b101f0SPierre Morel int cc; 163a3b101f0SPierre Morel 164a3b101f0SPierre Morel asm volatile( 165a3b101f0SPierre Morel " msch 0(%3)\n" 166a3b101f0SPierre Morel " ipm %0\n" 167a3b101f0SPierre Morel " srl %0,28" 168a3b101f0SPierre Morel : "=d" (cc) 169a3b101f0SPierre Morel : "d" (reg1), "m" (*addr), "a" (addr) 170a3b101f0SPierre Morel : "cc"); 171a3b101f0SPierre Morel return cc; 172a3b101f0SPierre Morel } 173a3b101f0SPierre Morel 174a3b101f0SPierre Morel static inline int tsch(unsigned long schid, struct irb *addr) 175a3b101f0SPierre Morel { 176a3b101f0SPierre Morel register unsigned long reg1 asm ("1") = schid; 177a3b101f0SPierre Morel int cc; 178a3b101f0SPierre Morel 179a3b101f0SPierre Morel asm volatile( 180a3b101f0SPierre Morel " tsch 0(%3)\n" 181a3b101f0SPierre Morel " ipm %0\n" 182a3b101f0SPierre Morel " srl %0,28" 183a3b101f0SPierre Morel : "=d" (cc), "=m" (*addr) 184a3b101f0SPierre Morel : "d" (reg1), "a" (addr) 185a3b101f0SPierre Morel : "cc"); 186a3b101f0SPierre Morel return cc; 187a3b101f0SPierre Morel } 188a3b101f0SPierre Morel 189a3b101f0SPierre Morel static inline int hsch(unsigned long schid) 190a3b101f0SPierre Morel { 191a3b101f0SPierre Morel register unsigned long reg1 asm("1") = schid; 192a3b101f0SPierre Morel int cc; 193a3b101f0SPierre Morel 194a3b101f0SPierre Morel asm volatile( 195a3b101f0SPierre Morel " hsch\n" 196a3b101f0SPierre Morel " ipm %0\n" 197a3b101f0SPierre Morel " srl %0,28" 198a3b101f0SPierre Morel : "=d" (cc) 199a3b101f0SPierre Morel : "d" (reg1) 200a3b101f0SPierre Morel : "cc"); 201a3b101f0SPierre Morel return cc; 202a3b101f0SPierre Morel } 203a3b101f0SPierre Morel 204a3b101f0SPierre Morel static inline int xsch(unsigned long schid) 205a3b101f0SPierre Morel { 206a3b101f0SPierre Morel register unsigned long reg1 asm("1") = schid; 207a3b101f0SPierre Morel int cc; 208a3b101f0SPierre Morel 209a3b101f0SPierre Morel asm volatile( 210a3b101f0SPierre Morel " xsch\n" 211a3b101f0SPierre Morel " ipm %0\n" 212a3b101f0SPierre Morel " srl %0,28" 213a3b101f0SPierre Morel : "=d" (cc) 214a3b101f0SPierre Morel : "d" (reg1) 215a3b101f0SPierre Morel : "cc"); 216a3b101f0SPierre Morel return cc; 217a3b101f0SPierre Morel } 218a3b101f0SPierre Morel 219a3b101f0SPierre Morel static inline int csch(unsigned long schid) 220a3b101f0SPierre Morel { 221a3b101f0SPierre Morel register unsigned long reg1 asm("1") = schid; 222a3b101f0SPierre Morel int cc; 223a3b101f0SPierre Morel 224a3b101f0SPierre Morel asm volatile( 225a3b101f0SPierre Morel " csch\n" 226a3b101f0SPierre Morel " ipm %0\n" 227a3b101f0SPierre Morel " srl %0,28" 228a3b101f0SPierre Morel : "=d" (cc) 229a3b101f0SPierre Morel : "d" (reg1) 230a3b101f0SPierre Morel : "cc"); 231a3b101f0SPierre Morel return cc; 232a3b101f0SPierre Morel } 233a3b101f0SPierre Morel 234a3b101f0SPierre Morel static inline int rsch(unsigned long schid) 235a3b101f0SPierre Morel { 236a3b101f0SPierre Morel register unsigned long reg1 asm("1") = schid; 237a3b101f0SPierre Morel int cc; 238a3b101f0SPierre Morel 239a3b101f0SPierre Morel asm volatile( 240a3b101f0SPierre Morel " rsch\n" 241a3b101f0SPierre Morel " ipm %0\n" 242a3b101f0SPierre Morel " srl %0,28" 243a3b101f0SPierre Morel : "=d" (cc) 244a3b101f0SPierre Morel : "d" (reg1) 245a3b101f0SPierre Morel : "cc"); 246a3b101f0SPierre Morel return cc; 247a3b101f0SPierre Morel } 248a3b101f0SPierre Morel 249a3b101f0SPierre Morel static inline int rchp(unsigned long chpid) 250a3b101f0SPierre Morel { 251a3b101f0SPierre Morel register unsigned long reg1 asm("1") = chpid; 252a3b101f0SPierre Morel int cc; 253a3b101f0SPierre Morel 254a3b101f0SPierre Morel asm volatile( 255a3b101f0SPierre Morel " rchp\n" 256a3b101f0SPierre Morel " ipm %0\n" 257a3b101f0SPierre Morel " srl %0,28" 258a3b101f0SPierre Morel : "=d" (cc) 259a3b101f0SPierre Morel : "d" (reg1) 260a3b101f0SPierre Morel : "cc"); 261a3b101f0SPierre Morel return cc; 262a3b101f0SPierre Morel } 263a3b101f0SPierre Morel 264a3b101f0SPierre Morel /* Debug functions */ 265a3b101f0SPierre Morel char *dump_pmcw_flags(uint16_t f); 266a3b101f0SPierre Morel char *dump_scsw_flags(uint32_t f); 267a3b101f0SPierre Morel 268a3b101f0SPierre Morel void dump_scsw(struct scsw *scsw); 269a3b101f0SPierre Morel void dump_irb(struct irb *irbp); 270a3b101f0SPierre Morel void dump_schib(struct schib *sch); 271a3b101f0SPierre Morel struct ccw1 *dump_ccw(struct ccw1 *cp); 272a3b101f0SPierre Morel void dump_irb(struct irb *irbp); 273a3b101f0SPierre Morel void dump_pmcw(struct pmcw *p); 274a3b101f0SPierre Morel void dump_orb(struct orb *op); 275a3b101f0SPierre Morel 276a3b101f0SPierre Morel int css_enumerate(void); 277a3b101f0SPierre Morel #define MAX_ENABLE_RETRIES 5 278a3b101f0SPierre Morel 279551e6622SPierre Morel #define IO_SCH_ISC 3 280551e6622SPierre Morel int css_enable(int schid, int isc); 2818cb729e4SPierre Morel 2828cb729e4SPierre Morel /* Library functions */ 2838cb729e4SPierre Morel int start_ccw1_chain(unsigned int sid, struct ccw1 *ccw); 284a6e5e596SPierre Morel struct ccw1 *ccw_alloc(int code, void *data, int count, unsigned char flags); 2858cb729e4SPierre Morel void css_irq_io(void); 2868cb729e4SPierre Morel int css_residual_count(unsigned int schid); 2878cb729e4SPierre Morel 2888cb729e4SPierre Morel void enable_io_isc(uint8_t isc); 2898cb729e4SPierre Morel int wait_and_check_io_completion(int schid); 2908cb729e4SPierre Morel 291*7fbcef02SPierre Morel /* 292*7fbcef02SPierre Morel * CHSC definitions 293*7fbcef02SPierre Morel */ 294*7fbcef02SPierre Morel struct chsc_header { 295*7fbcef02SPierre Morel uint16_t len; 296*7fbcef02SPierre Morel uint16_t code; 297*7fbcef02SPierre Morel }; 298*7fbcef02SPierre Morel 299*7fbcef02SPierre Morel /* Store Channel Subsystem Characteristics */ 300*7fbcef02SPierre Morel struct chsc_scsc { 301*7fbcef02SPierre Morel struct chsc_header req; 302*7fbcef02SPierre Morel uint16_t req_fmt; 303*7fbcef02SPierre Morel uint8_t cssid; 304*7fbcef02SPierre Morel uint8_t reserved[9]; 305*7fbcef02SPierre Morel struct chsc_header res; 306*7fbcef02SPierre Morel uint32_t res_fmt; 307*7fbcef02SPierre Morel uint64_t general_char[255]; 308*7fbcef02SPierre Morel uint64_t chsc_char[254]; 309*7fbcef02SPierre Morel }; 310*7fbcef02SPierre Morel 311*7fbcef02SPierre Morel extern struct chsc_scsc *chsc_scsc; 312*7fbcef02SPierre Morel #define CHSC_SCSC 0x0010 313*7fbcef02SPierre Morel #define CHSC_SCSC_LEN 0x0010 314*7fbcef02SPierre Morel 315*7fbcef02SPierre Morel bool get_chsc_scsc(void); 316*7fbcef02SPierre Morel 317*7fbcef02SPierre Morel #define CSS_GENERAL_FEAT_BITLEN (255 * 64) 318*7fbcef02SPierre Morel #define CSS_CHSC_FEAT_BITLEN (254 * 64) 319*7fbcef02SPierre Morel 320*7fbcef02SPierre Morel #define CHSC_SCSC 0x0010 321*7fbcef02SPierre Morel #define CHSC_SCSC_LEN 0x0010 322*7fbcef02SPierre Morel 323*7fbcef02SPierre Morel #define CHSC_ERROR 0x0000 324*7fbcef02SPierre Morel #define CHSC_RSP_OK 0x0001 325*7fbcef02SPierre Morel #define CHSC_RSP_INVAL 0x0002 326*7fbcef02SPierre Morel #define CHSC_RSP_REQERR 0x0003 327*7fbcef02SPierre Morel #define CHSC_RSP_ENOCMD 0x0004 328*7fbcef02SPierre Morel #define CHSC_RSP_NODATA 0x0005 329*7fbcef02SPierre Morel #define CHSC_RSP_SUP31B 0x0006 330*7fbcef02SPierre Morel #define CHSC_RSP_EFRMT 0x0007 331*7fbcef02SPierre Morel #define CHSC_RSP_ECSSID 0x0008 332*7fbcef02SPierre Morel #define CHSC_RSP_ERFRMT 0x0009 333*7fbcef02SPierre Morel #define CHSC_RSP_ESSID 0x000A 334*7fbcef02SPierre Morel #define CHSC_RSP_EBUSY 0x000B 335*7fbcef02SPierre Morel #define CHSC_RSP_MAX 0x000B 336*7fbcef02SPierre Morel 337*7fbcef02SPierre Morel static inline int _chsc(void *p) 338*7fbcef02SPierre Morel { 339*7fbcef02SPierre Morel int cc; 340*7fbcef02SPierre Morel 341*7fbcef02SPierre Morel asm volatile(" .insn rre,0xb25f0000,%2,0\n" 342*7fbcef02SPierre Morel " ipm %0\n" 343*7fbcef02SPierre Morel " srl %0,28\n" 344*7fbcef02SPierre Morel : "=d" (cc), "=m" (p) 345*7fbcef02SPierre Morel : "d" (p), "m" (p) 346*7fbcef02SPierre Morel : "cc"); 347*7fbcef02SPierre Morel 348*7fbcef02SPierre Morel return cc; 349*7fbcef02SPierre Morel } 350*7fbcef02SPierre Morel 351*7fbcef02SPierre Morel bool chsc(void *p, uint16_t code, uint16_t len); 352*7fbcef02SPierre Morel 353*7fbcef02SPierre Morel #include <bitops.h> 354*7fbcef02SPierre Morel #define css_test_general_feature(bit) test_bit_inv(bit, chsc_scsc->general_char) 355*7fbcef02SPierre Morel #define css_test_chsc_feature(bit) test_bit_inv(bit, chsc_scsc->chsc_char) 356*7fbcef02SPierre Morel 357a3b101f0SPierre Morel #endif 358