blob: 221b67c7208936a780af166496c4485df4622e8b [file] [log] [blame]
/*
* CSS definitions
*
* Copyright IBM, Corp. 2020
* Author: Pierre Morel <pmorel@linux.ibm.com>
*
* 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