xref: /openbmc/linux/drivers/s390/cio/io_sch.h (revision 22246614)
1 #ifndef S390_IO_SCH_H
2 #define S390_IO_SCH_H
3 
4 #include "schid.h"
5 
6 /*
7  * operation request block
8  */
9 struct orb {
10 	u32 intparm;	/* interruption parameter */
11 	u32 key  : 4;	/* flags, like key, suspend control, etc. */
12 	u32 spnd : 1;	/* suspend control */
13 	u32 res1 : 1;	/* reserved */
14 	u32 mod  : 1;	/* modification control */
15 	u32 sync : 1;	/* synchronize control */
16 	u32 fmt  : 1;	/* format control */
17 	u32 pfch : 1;	/* prefetch control */
18 	u32 isic : 1;	/* initial-status-interruption control */
19 	u32 alcc : 1;	/* address-limit-checking control */
20 	u32 ssic : 1;	/* suppress-suspended-interr. control */
21 	u32 res2 : 1;	/* reserved */
22 	u32 c64  : 1;	/* IDAW/QDIO 64 bit control  */
23 	u32 i2k  : 1;	/* IDAW 2/4kB block size control */
24 	u32 lpm  : 8;	/* logical path mask */
25 	u32 ils  : 1;	/* incorrect length */
26 	u32 zero : 6;	/* reserved zeros */
27 	u32 orbx : 1;	/* ORB extension control */
28 	u32 cpa;	/* channel program address */
29 }  __attribute__ ((packed, aligned(4)));
30 
31 struct io_subchannel_private {
32 	struct orb orb;		/* operation request block */
33 	struct ccw1 sense_ccw;	/* static ccw for sense command */
34 } __attribute__ ((aligned(8)));
35 
36 #define to_io_private(n) ((struct io_subchannel_private *)n->private)
37 #define sch_get_cdev(n) (dev_get_drvdata(&n->dev))
38 #define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c))
39 
40 #define MAX_CIWS 8
41 
42 /*
43  * sense-id response buffer layout
44  */
45 struct senseid {
46 	/* common part */
47 	u8  reserved;	/* always 0x'FF' */
48 	u16 cu_type;	/* control unit type */
49 	u8  cu_model;	/* control unit model */
50 	u16 dev_type;	/* device type */
51 	u8  dev_model;	/* device model */
52 	u8  unused;	/* padding byte */
53 	/* extended part */
54 	struct ciw ciw[MAX_CIWS];	/* variable # of CIWs */
55 }  __attribute__ ((packed, aligned(4)));
56 
57 struct ccw_device_private {
58 	struct ccw_device *cdev;
59 	struct subchannel *sch;
60 	int state;		/* device state */
61 	atomic_t onoff;
62 	unsigned long registered;
63 	struct ccw_dev_id dev_id;	/* device id */
64 	struct subchannel_id schid;	/* subchannel number */
65 	u8 imask;		/* lpm mask for SNID/SID/SPGID */
66 	int iretry;		/* retry counter SNID/SID/SPGID */
67 	struct {
68 		unsigned int fast:1;	/* post with "channel end" */
69 		unsigned int repall:1;	/* report every interrupt status */
70 		unsigned int pgroup:1;	/* do path grouping */
71 		unsigned int force:1;	/* allow forced online */
72 	} __attribute__ ((packed)) options;
73 	struct {
74 		unsigned int pgid_single:1; /* use single path for Set PGID */
75 		unsigned int esid:1;	    /* Ext. SenseID supported by HW */
76 		unsigned int dosense:1;	    /* delayed SENSE required */
77 		unsigned int doverify:1;    /* delayed path verification */
78 		unsigned int donotify:1;    /* call notify function */
79 		unsigned int recog_done:1;  /* dev. recog. complete */
80 		unsigned int fake_irb:1;    /* deliver faked irb */
81 		unsigned int intretry:1;    /* retry internal operation */
82 	} __attribute__((packed)) flags;
83 	unsigned long intparm;	/* user interruption parameter */
84 	struct qdio_irq *qdio_data;
85 	struct irb irb;		/* device status */
86 	struct senseid senseid;	/* SenseID info */
87 	struct pgid pgid[8];	/* path group IDs per chpid*/
88 	struct ccw1 iccws[2];	/* ccws for SNID/SID/SPGID commands */
89 	struct work_struct kick_work;
90 	wait_queue_head_t wait_q;
91 	struct timer_list timer;
92 	void *cmb;			/* measurement information */
93 	struct list_head cmb_list;	/* list of measured devices */
94 	u64 cmb_start_time;		/* clock value of cmb reset */
95 	void *cmb_wait;			/* deferred cmb enable/disable */
96 };
97 
98 static inline int ssch(struct subchannel_id schid, volatile struct orb *addr)
99 {
100 	register struct subchannel_id reg1 asm("1") = schid;
101 	int ccode;
102 
103 	asm volatile(
104 		"	ssch	0(%2)\n"
105 		"	ipm	%0\n"
106 		"	srl	%0,28"
107 		: "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
108 	return ccode;
109 }
110 
111 static inline int rsch(struct subchannel_id schid)
112 {
113 	register struct subchannel_id reg1 asm("1") = schid;
114 	int ccode;
115 
116 	asm volatile(
117 		"	rsch\n"
118 		"	ipm	%0\n"
119 		"	srl	%0,28"
120 		: "=d" (ccode) : "d" (reg1) : "cc");
121 	return ccode;
122 }
123 
124 static inline int csch(struct subchannel_id schid)
125 {
126 	register struct subchannel_id reg1 asm("1") = schid;
127 	int ccode;
128 
129 	asm volatile(
130 		"	csch\n"
131 		"	ipm	%0\n"
132 		"	srl	%0,28"
133 		: "=d" (ccode) : "d" (reg1) : "cc");
134 	return ccode;
135 }
136 
137 static inline int hsch(struct subchannel_id schid)
138 {
139 	register struct subchannel_id reg1 asm("1") = schid;
140 	int ccode;
141 
142 	asm volatile(
143 		"	hsch\n"
144 		"	ipm	%0\n"
145 		"	srl	%0,28"
146 		: "=d" (ccode) : "d" (reg1) : "cc");
147 	return ccode;
148 }
149 
150 static inline int xsch(struct subchannel_id schid)
151 {
152 	register struct subchannel_id reg1 asm("1") = schid;
153 	int ccode;
154 
155 	asm volatile(
156 		"	.insn	rre,0xb2760000,%1,0\n"
157 		"	ipm	%0\n"
158 		"	srl	%0,28"
159 		: "=d" (ccode) : "d" (reg1) : "cc");
160 	return ccode;
161 }
162 
163 #endif
164