| #ifndef S390_CIO_IOASM_H | |
| #define S390_CIO_IOASM_H | |
| #include <asm/chpid.h> | |
| #include <asm/schid.h> | |
| #include "orb.h" | |
| #include "cio.h" | |
| /* | |
| * TPI info structure | |
| */ | |
| struct tpi_info { | |
| struct subchannel_id schid; | |
| __u32 intparm; /* interruption parameter */ | |
| __u32 adapter_IO : 1; | |
| __u32 reserved2 : 1; | |
| __u32 isc : 3; | |
| __u32 reserved3 : 12; | |
| __u32 int_type : 3; | |
| __u32 reserved4 : 12; | |
| } __attribute__ ((packed)); | |
| /* | |
| * Some S390 specific IO instructions as inline | |
| */ | |
| static inline int stsch_err(struct subchannel_id schid, struct schib *addr) | |
| { | |
| register struct subchannel_id reg1 asm ("1") = schid; | |
| int ccode = -EIO; | |
| asm volatile( | |
| " stsch 0(%3)\n" | |
| "0: ipm %0\n" | |
| " srl %0,28\n" | |
| "1:\n" | |
| EX_TABLE(0b,1b) | |
| : "+d" (ccode), "=m" (*addr) | |
| : "d" (reg1), "a" (addr) | |
| : "cc"); | |
| return ccode; | |
| } | |
| static inline int msch(struct subchannel_id schid, struct schib *addr) | |
| { | |
| register struct subchannel_id reg1 asm ("1") = schid; | |
| int ccode; | |
| asm volatile( | |
| " msch 0(%2)\n" | |
| " ipm %0\n" | |
| " srl %0,28" | |
| : "=d" (ccode) | |
| : "d" (reg1), "a" (addr), "m" (*addr) | |
| : "cc"); | |
| return ccode; | |
| } | |
| static inline int msch_err(struct subchannel_id schid, struct schib *addr) | |
| { | |
| register struct subchannel_id reg1 asm ("1") = schid; | |
| int ccode = -EIO; | |
| asm volatile( | |
| " msch 0(%2)\n" | |
| "0: ipm %0\n" | |
| " srl %0,28\n" | |
| "1:\n" | |
| EX_TABLE(0b,1b) | |
| : "+d" (ccode) | |
| : "d" (reg1), "a" (addr), "m" (*addr) | |
| : "cc"); | |
| return ccode; | |
| } | |
| static inline int tsch(struct subchannel_id schid, struct irb *addr) | |
| { | |
| register struct subchannel_id reg1 asm ("1") = schid; | |
| int ccode; | |
| asm volatile( | |
| " tsch 0(%3)\n" | |
| " ipm %0\n" | |
| " srl %0,28" | |
| : "=d" (ccode), "=m" (*addr) | |
| : "d" (reg1), "a" (addr) | |
| : "cc"); | |
| return ccode; | |
| } | |
| static inline int ssch(struct subchannel_id schid, union orb *addr) | |
| { | |
| register struct subchannel_id reg1 asm("1") = schid; | |
| int ccode = -EIO; | |
| asm volatile( | |
| " ssch 0(%2)\n" | |
| "0: ipm %0\n" | |
| " srl %0,28\n" | |
| "1:\n" | |
| EX_TABLE(0b, 1b) | |
| : "+d" (ccode) | |
| : "d" (reg1), "a" (addr), "m" (*addr) | |
| : "cc", "memory"); | |
| return ccode; | |
| } | |
| static inline int csch(struct subchannel_id schid) | |
| { | |
| register struct subchannel_id reg1 asm("1") = schid; | |
| int ccode; | |
| asm volatile( | |
| " csch\n" | |
| " ipm %0\n" | |
| " srl %0,28" | |
| : "=d" (ccode) | |
| : "d" (reg1) | |
| : "cc"); | |
| return ccode; | |
| } | |
| static inline int tpi(struct tpi_info *addr) | |
| { | |
| int ccode; | |
| asm volatile( | |
| " tpi 0(%2)\n" | |
| " ipm %0\n" | |
| " srl %0,28" | |
| : "=d" (ccode), "=m" (*addr) | |
| : "a" (addr) | |
| : "cc"); | |
| return ccode; | |
| } | |
| static inline int chsc(void *chsc_area) | |
| { | |
| typedef struct { char _[4096]; } addr_type; | |
| int cc; | |
| asm volatile( | |
| " .insn rre,0xb25f0000,%2,0\n" | |
| " ipm %0\n" | |
| " srl %0,28\n" | |
| : "=d" (cc), "=m" (*(addr_type *) chsc_area) | |
| : "d" (chsc_area), "m" (*(addr_type *) chsc_area) | |
| : "cc"); | |
| return cc; | |
| } | |
| static inline int rchp(struct chp_id chpid) | |
| { | |
| register struct chp_id reg1 asm ("1") = chpid; | |
| int ccode; | |
| asm volatile( | |
| " lr 1,%1\n" | |
| " rchp\n" | |
| " ipm %0\n" | |
| " srl %0,28" | |
| : "=d" (ccode) : "d" (reg1) : "cc"); | |
| return ccode; | |
| } | |
| #endif |