/* * CSS definitions * * Copyright IBM, Corp. 2020 * Author: Pierre Morel * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2. */ #ifndef CSS_H #define CSS_H #define lowcore_ptr ((struct lowcore *)0x0) /* subchannel ID bit 16 must always be one */ #define SCHID_ONE 0x00010000 #define CCW_F_CD 0x80 #define CCW_F_CC 0x40 #define CCW_F_SLI 0x20 #define CCW_F_SKP 0x10 #define CCW_F_PCI 0x08 #define CCW_F_IDA 0x04 #define CCW_F_S 0x02 #define CCW_F_MIDA 0x01 #define CCW_C_NOP 0x03 #define CCW_C_TIC 0x08 struct ccw1 { uint8_t code; uint8_t flags; uint16_t count; uint32_t data_address; } __attribute__ ((aligned(8))); #define ORB_CTRL_KEY 0xf0000000 #define ORB_CTRL_SPND 0x08000000 #define ORB_CTRL_STR 0x04000000 #define ORB_CTRL_MOD 0x02000000 #define ORB_CTRL_SYNC 0x01000000 #define ORB_CTRL_FMT 0x00800000 #define ORB_CTRL_PFCH 0x00400000 #define ORB_CTRL_ISIC 0x00200000 #define ORB_CTRL_ALCC 0x00100000 #define ORB_CTRL_SSIC 0x00080000 #define ORB_CTRL_CPTC 0x00040000 #define ORB_CTRL_C64 0x00020000 #define ORB_CTRL_I2K 0x00010000 #define ORB_CTRL_LPM 0x0000ff00 #define ORB_CTRL_ILS 0x00000080 #define ORB_CTRL_MIDAW 0x00000040 #define ORB_CTRL_ORBX 0x00000001 #define ORB_LPM_DFLT 0x00008000 struct orb { uint32_t intparm; uint32_t ctrl; uint32_t cpa; uint32_t prio; uint32_t reserved[4]; } __attribute__ ((aligned(4))); struct scsw { #define SCSW_SC_PENDING 0x00000001 #define SCSW_SC_SECONDARY 0x00000002 #define SCSW_SC_PRIMARY 0x00000004 #define SCSW_SC_INTERMEDIATE 0x00000008 #define SCSW_SC_ALERT 0x00000010 uint32_t ctrl; uint32_t ccw_addr; #define SCSW_DEVS_DEV_END 0x04 #define SCSW_DEVS_SCH_END 0x08 uint8_t dev_stat; #define SCSW_SCHS_PCI 0x80 #define SCSW_SCHS_IL 0x40 uint8_t sch_stat; uint16_t count; }; struct pmcw { uint32_t intparm; #define PMCW_DNV 0x0001 #define PMCW_ENABLE 0x0080 #define PMCW_ISC_MASK 0x3800 #define PMCW_ISC_SHIFT 11 uint16_t flags; uint16_t devnum; uint8_t lpm; uint8_t pnom; uint8_t lpum; uint8_t pim; uint16_t mbi; uint8_t pom; uint8_t pam; uint8_t chpid[8]; uint32_t flags2; }; #define PMCW_CHANNEL_TYPE(pmcw) (pmcw->flags2 >> 21) struct schib { struct pmcw pmcw; struct scsw scsw; uint8_t md[12]; } __attribute__ ((aligned(4))); struct irb { struct scsw scsw; uint32_t esw[5]; uint32_t ecw[8]; uint32_t emw[8]; } __attribute__ ((aligned(4))); #define CCW_CMD_SENSE_ID 0xe4 #define CSS_SENSEID_COMMON_LEN 8 struct senseid { /* common part */ uint8_t reserved; /* always 0x'FF' */ uint16_t cu_type; /* control unit type */ uint8_t cu_model; /* control unit model */ uint16_t dev_type; /* device type */ uint8_t dev_model; /* device model */ uint8_t unused; /* padding byte */ uint8_t padding[256 - 8]; /* Extended part */ } __attribute__ ((aligned(4))) __attribute__ ((packed)); /* CSS low level access functions */ static inline int ssch(unsigned long schid, struct orb *addr) { register long long reg1 asm("1") = schid; int cc; asm volatile( " ssch 0(%2)\n" " ipm %0\n" " srl %0,28\n" : "=d" (cc) : "d" (reg1), "a" (addr), "m" (*addr) : "cc", "memory"); return cc; } static inline int stsch(unsigned long schid, struct schib *addr) { register unsigned long reg1 asm ("1") = schid; int cc; asm volatile( " stsch 0(%3)\n" " ipm %0\n" " srl %0,28" : "=d" (cc), "=m" (*addr) : "d" (reg1), "a" (addr) : "cc"); return cc; } static inline int msch(unsigned long schid, struct schib *addr) { register unsigned long reg1 asm ("1") = schid; int cc; asm volatile( " msch 0(%3)\n" " ipm %0\n" " srl %0,28" : "=d" (cc) : "d" (reg1), "m" (*addr), "a" (addr) : "cc"); return cc; } static inline int tsch(unsigned long schid, struct irb *addr) { register unsigned long reg1 asm ("1") = schid; int cc; asm volatile( " tsch 0(%3)\n" " ipm %0\n" " srl %0,28" : "=d" (cc), "=m" (*addr) : "d" (reg1), "a" (addr) : "cc"); return cc; } static inline int hsch(unsigned long schid) { register unsigned long reg1 asm("1") = schid; int cc; asm volatile( " hsch\n" " ipm %0\n" " srl %0,28" : "=d" (cc) : "d" (reg1) : "cc"); return cc; } static inline int xsch(unsigned long schid) { register unsigned long reg1 asm("1") = schid; int cc; asm volatile( " xsch\n" " ipm %0\n" " srl %0,28" : "=d" (cc) : "d" (reg1) : "cc"); return cc; } static inline int csch(unsigned long schid) { register unsigned long reg1 asm("1") = schid; int cc; asm volatile( " csch\n" " ipm %0\n" " srl %0,28" : "=d" (cc) : "d" (reg1) : "cc"); return cc; } static inline int rsch(unsigned long schid) { register unsigned long reg1 asm("1") = schid; int cc; asm volatile( " rsch\n" " ipm %0\n" " srl %0,28" : "=d" (cc) : "d" (reg1) : "cc"); return cc; } static inline int rchp(unsigned long chpid) { register unsigned long reg1 asm("1") = chpid; int cc; asm volatile( " rchp\n" " ipm %0\n" " srl %0,28" : "=d" (cc) : "d" (reg1) : "cc"); return cc; } /* Debug functions */ char *dump_pmcw_flags(uint16_t f); char *dump_scsw_flags(uint32_t f); void dump_scsw(struct scsw *scsw); void dump_irb(struct irb *irbp); void dump_schib(struct schib *sch); struct ccw1 *dump_ccw(struct ccw1 *cp); void dump_irb(struct irb *irbp); void dump_pmcw(struct pmcw *p); void dump_orb(struct orb *op); int css_enumerate(void); #define MAX_ENABLE_RETRIES 5 #define IO_SCH_ISC 3 int css_enable(int schid, int isc); /* Library functions */ int start_ccw1_chain(unsigned int sid, struct ccw1 *ccw); int start_single_ccw(unsigned int sid, int code, void *data, int count, unsigned char flags); void css_irq_io(void); int css_residual_count(unsigned int schid); void enable_io_isc(uint8_t isc); int wait_and_check_io_completion(int schid); #endif