2 * Channel IO definitions
4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
6 * Inspired by various s390 headers in Linux 3.9.
8 * This work is licensed under the terms of the GNU GPL, version 2 or (at
9 * your option) any later version. See the COPYING file in the top-level
17 * path management control word
20 u32 intparm
; /* interruption parameter */
21 u32 qf
:1; /* qdio facility */
23 u32 isc
:3; /* interruption subclass */
24 u32 res5
:3; /* reserved zeros */
25 u32 ena
:1; /* enabled */
26 u32 lm
:2; /* limit mode */
27 u32 mme
:2; /* measurement-mode enable */
28 u32 mp
:1; /* multipath mode */
29 u32 tf
:1; /* timing facility */
30 u32 dnv
:1; /* device number valid */
31 u32 dev
:16; /* device number */
32 u8 lpm
; /* logical path mask */
33 u8 pnom
; /* path not operational mask */
34 u8 lpum
; /* last path used mask */
35 u8 pim
; /* path installed mask */
36 u16 mbi
; /* measurement-block index */
37 u8 pom
; /* path operational mask */
38 u8 pam
; /* path available mask */
39 u8 chpid
[8]; /* CHPID 0-7 (if available) */
40 u32 unused1
:8; /* reserved zeros */
41 u32 st
:3; /* subchannel type */
42 u32 unused2
:18; /* reserved zeros */
43 u32 mbfc
:1; /* measurement block format control */
44 u32 xmwme
:1; /* extended measurement word mode enable */
45 u32 csense
:1; /* concurrent sense; can be enabled ...*/
46 /* ... per MSCH, however, if facility */
47 /* ... is not installed, this results */
48 /* ... in an operand exception. */
49 } __attribute__ ((packed
));
51 /* Target SCHIB configuration. */
62 } __attribute__ ((packed
));
71 } __attribute__ ((packed
));
73 /* Function Control */
74 #define SCSW_FCTL_START_FUNC 0x4000
75 #define SCSW_FCTL_HALT_FUNC 0x2000
76 #define SCSW_FCTL_CLEAR_FUNC 0x1000
78 /* Activity Control */
79 #define SCSW_ACTL_RESUME_PEND 0x0800
80 #define SCSW_ACTL_START_PEND 0x0400
81 #define SCSW_ACTL_HALT_PEND 0x0200
82 #define SCSW_ACTL_CLEAR_PEND 0x0100
83 #define SCSW_ACTL_CH_ACTIVE 0x0080
84 #define SCSW_ACTL_DEV_ACTIVE 0x0040
85 #define SCSW_ACTL_SUSPENDED 0x0020
88 #define SCSW_SCTL_ALERT 0x0010
89 #define SCSW_SCTL_INTERMED 0x0008
90 #define SCSW_SCTL_PRIMARY 0x0004
91 #define SCSW_SCTL_SECONDARY 0x0002
92 #define SCSW_SCTL_STATUS_PEND 0x0001
94 /* SCSW Device Status Flags */
95 #define SCSW_DSTAT_ATTN 0x80
96 #define SCSW_DSTAT_STATMOD 0x40
97 #define SCSW_DSTAT_CUEND 0x20
98 #define SCSW_DSTAT_BUSY 0x10
99 #define SCSW_DSTAT_CHEND 0x08
100 #define SCSW_DSTAT_DEVEND 0x04
101 #define SCSW_DSTAT_UCHK 0x02
102 #define SCSW_DSTAT_UEXCP 0x01
104 /* SCSW Subchannel Status Flags */
105 #define SCSW_CSTAT_PCINT 0x80
106 #define SCSW_CSTAT_BADLEN 0x40
107 #define SCSW_CSTAT_PROGCHK 0x20
108 #define SCSW_CSTAT_PROTCHK 0x10
109 #define SCSW_CSTAT_CHDCHK 0x08
110 #define SCSW_CSTAT_CHCCHK 0x04
111 #define SCSW_CSTAT_ICCHK 0x02
112 #define SCSW_CSTAT_CHAINCHK 0x01
115 * subchannel information block
117 typedef struct schib
{
118 struct pmcw pmcw
; /* path management control word */
119 struct scsw scsw
; /* subchannel status word */
120 u64 mba
; /* measurement block address */
121 u8 mda
[4]; /* model dependent area */
122 } __attribute__ ((packed
, aligned(4))) Schib
;
124 typedef struct subchannel_id
{
136 } __attribute__ ((packed
, aligned(4))) SubChannelId
;
141 } __attribute__((packed
));
143 typedef struct chsc_area_sda
{
144 struct chsc_header request
;
151 u32 operation_data_area
[252];
152 struct chsc_header response
;
156 } __attribute__((packed
)) ChscAreaSda
;
162 struct subchannel_id schid
;
163 u32 intparm
; /* interruption parameter */
170 } __attribute__ ((packed
, aligned(4)));
172 /* channel command word (format 0) */
173 typedef struct ccw0
{
186 } __attribute__ ((packed
, aligned(8))) Ccw0
;
188 /* channel command word (format 1) */
189 typedef struct ccw1
{
194 } __attribute__ ((packed
, aligned(8))) Ccw1
;
196 /* do_cio() CCW formats */
197 #define CCW_FMT0 0x00
198 #define CCW_FMT1 0x01
200 #define CCW_FLAG_DC 0x80
201 #define CCW_FLAG_CC 0x40
202 #define CCW_FLAG_SLI 0x20
203 #define CCW_FLAG_SKIP 0x10
204 #define CCW_FLAG_PCI 0x08
205 #define CCW_FLAG_IDA 0x04
206 #define CCW_FLAG_SUSPEND 0x02
208 /* Common CCW commands */
209 #define CCW_CMD_READ_IPL 0x02
210 #define CCW_CMD_NOOP 0x03
211 #define CCW_CMD_BASIC_SENSE 0x04
212 #define CCW_CMD_TIC 0x08
213 #define CCW_CMD_SENSE_ID 0xe4
215 /* Virtio CCW commands */
216 #define CCW_CMD_SET_VQ 0x13
217 #define CCW_CMD_VDEV_RESET 0x33
218 #define CCW_CMD_READ_FEAT 0x12
219 #define CCW_CMD_WRITE_FEAT 0x11
220 #define CCW_CMD_READ_CONF 0x22
221 #define CCW_CMD_WRITE_CONF 0x21
222 #define CCW_CMD_WRITE_STATUS 0x31
223 #define CCW_CMD_SET_IND 0x43
224 #define CCW_CMD_SET_CONF_IND 0x53
225 #define CCW_CMD_READ_VQ_CONF 0x32
227 /* DASD CCW commands */
228 #define CCW_CMD_DASD_READ 0x06
229 #define CCW_CMD_DASD_SEEK 0x07
230 #define CCW_CMD_DASD_SEARCH_ID_EQ 0x31
231 #define CCW_CMD_DASD_READ_MT 0x86
234 * Command-mode operation request block
236 typedef struct cmd_orb
{
237 u32 intparm
; /* interruption parameter */
238 u32 key
:4; /* flags, like key, suspend control, etc. */
239 u32 spnd
:1; /* suspend control */
240 u32 res1
:1; /* reserved */
241 u32 mod
:1; /* modification control */
242 u32 sync
:1; /* synchronize control */
243 u32 fmt
:1; /* format control */
244 u32 pfch
:1; /* prefetch control */
245 u32 isic
:1; /* initial-status-interruption control */
246 u32 alcc
:1; /* address-limit-checking control */
247 u32 ssic
:1; /* suppress-suspended-interr. control */
248 u32 res2
:1; /* reserved */
249 u32 c64
:1; /* IDAW/QDIO 64 bit control */
250 u32 i2k
:1; /* IDAW 2/4kB block size control */
251 u32 lpm
:8; /* logical path mask */
252 u32 ils
:1; /* incorrect length */
253 u32 zero
:6; /* reserved zeros */
254 u32 orbx
:1; /* ORB extension control */
255 u32 cpa
; /* channel program address */
256 } __attribute__ ((packed
, aligned(4))) CmdOrb
;
264 #define CU_TYPE_UNKNOWN 0x0000
265 #define CU_TYPE_DASD_2107 0x2107
266 #define CU_TYPE_VIRTIO 0x3832
267 #define CU_TYPE_DASD_3990 0x3990
270 * sense-id response buffer layout
272 typedef struct senseid
{
274 u8 reserved
; /* always 0x'FF' */
275 u16 cu_type
; /* control unit type */
276 u8 cu_model
; /* control unit model */
277 u16 dev_type
; /* device type */
278 u8 dev_model
; /* device model */
279 u8 unused
; /* padding byte */
282 } __attribute__ ((packed
, aligned(4))) SenseId
;
285 * architected values for first sense byte - common_status. Bits 0-5 of this
286 * field are common to all device types.
288 #define SNS_STAT0_CMD_REJECT 0x80
289 #define SNS_STAT0_INTERVENTION_REQ 0x40
290 #define SNS_STAT0_BUS_OUT_CHECK 0x20
291 #define SNS_STAT0_EQUIPMENT_CHECK 0x10
292 #define SNS_STAT0_DATA_CHECK 0x08
293 #define SNS_STAT0_OVERRUN 0x04
294 #define SNS_STAT0_INCOMPL_DOMAIN 0x01
296 /* ECKD DASD status[0] byte */
297 #define SNS_STAT1_PERM_ERR 0x80
298 #define SNS_STAT1_INV_TRACK_FORMAT 0x40
299 #define SNS_STAT1_EOC 0x20
300 #define SNS_STAT1_MESSAGE_TO_OPER 0x10
301 #define SNS_STAT1_NO_REC_FOUND 0x08
302 #define SNS_STAT1_FILE_PROTECTED 0x04
303 #define SNS_STAT1_WRITE_INHIBITED 0x02
304 #define SNS_STAT1_IMPRECISE_END 0x01
306 /* ECKD DASD status[1] byte */
307 #define SNS_STAT2_REQ_INH_WRITE 0x80
308 #define SNS_STAT2_CORRECTABLE 0x40
309 #define SNS_STAT2_FIRST_LOG_ERR 0x20
310 #define SNS_STAT2_ENV_DATA_PRESENT 0x10
311 #define SNS_STAT2_IMPRECISE_END 0x04
313 /* ECKD DASD 24-byte Sense fmt_msg codes */
314 #define SENSE24_FMT_PROG_SYS 0x0
315 #define SENSE24_FMT_EQUIPMENT 0x2
316 #define SENSE24_FMT_CONTROLLER 0x3
317 #define SENSE24_FMT_MISC 0xF
319 /* basic sense response buffer layout */
320 typedef struct SenseDataEckdDasd
{
321 uint8_t common_status
;
324 uint8_t phys_drive_id
;
325 uint8_t low_cyl_addr
;
326 uint8_t head_high_cyl_addr
;
328 uint64_t fmt_dependent_info
[2];
330 uint8_t program_action_code
;
331 uint16_t config_info
;
333 uint8_t cyl_head_addr
[3];
334 } __attribute__ ((packed
, aligned(4))) SenseDataEckdDasd
;
336 #define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4)
337 #define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F)
339 #define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK)
340 #define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK)
342 /* interruption response block */
348 } __attribute__ ((packed
, aligned(4))) Irb
;
350 /* Used for SEEK ccw commands */
351 typedef struct CcwSeekData
{
355 } __attribute__((packed
)) CcwSeekData
;
357 /* Used for SEARCH ID ccw commands */
358 typedef struct CcwSearchIdData
{
362 } __attribute__((packed
)) CcwSearchIdData
;
364 int enable_mss_facility(void);
365 void enable_subchannel(SubChannelId schid
);
366 uint16_t cu_type(SubChannelId schid
);
367 int basic_sense(SubChannelId schid
, uint16_t cutype
, void *sense_data
,
369 int do_cio(SubChannelId schid
, uint16_t cutype
, uint32_t ccw_addr
, int fmt
);
372 * Some S390 specific IO instructions as inline
375 static inline int stsch_err(struct subchannel_id schid
, struct schib
*addr
)
377 register struct subchannel_id reg1
asm ("1") = schid
;
385 : "+d" (ccode
), "=m" (*addr
)
386 : "d" (reg1
), "a" (addr
)
391 static inline int msch(struct subchannel_id schid
, struct schib
*addr
)
393 register struct subchannel_id reg1
asm ("1") = schid
;
401 : "d" (reg1
), "a" (addr
), "m" (*addr
)
406 static inline int msch_err(struct subchannel_id schid
, struct schib
*addr
)
408 register struct subchannel_id reg1
asm ("1") = schid
;
417 : "d" (reg1
), "a" (addr
), "m" (*addr
)
422 static inline int tsch(struct subchannel_id schid
, struct irb
*addr
)
424 register struct subchannel_id reg1
asm ("1") = schid
;
431 : "=d" (ccode
), "=m" (*addr
)
432 : "d" (reg1
), "a" (addr
)
437 static inline int ssch(struct subchannel_id schid
, struct cmd_orb
*addr
)
439 register struct subchannel_id reg1
asm("1") = schid
;
448 : "d" (reg1
), "a" (addr
), "m" (*addr
)
453 static inline int csch(struct subchannel_id schid
)
455 register struct subchannel_id reg1
asm("1") = schid
;
468 static inline int tpi(struct tpi_info
*addr
)
476 : "=d" (ccode
), "=m" (*addr
)
482 static inline int chsc(void *chsc_area
)
484 typedef struct { char _
[4096]; } addr_type
;
488 " .insn rre,0xb25f0000,%2,0\n"
491 : "=d" (cc
), "=m" (*(addr_type
*) chsc_area
)
492 : "d" (chsc_area
), "m" (*(addr_type
*) chsc_area
)