u16 _zeros : 12;
u16 mask_length;
u64 sclp_active_facility_mask;
- sccb_mask_t sclp_receive_mask;
- sccb_mask_t sclp_send_mask;
- u32 read_data_function_mask;
+ u8 masks[2 * 1021 + 4]; /* variable length */
+ /*
+ * u8 sclp_receive_mask[mask_length];
+ * u8 sclp_send_mask[mask_length];
+ * u32 read_data_function_mask;
+ */
} __attribute__((packed));
unsigned long flags;
struct sclp_statechangebuf *scbuf;
+ BUILD_BUG_ON(sizeof(struct sclp_statechangebuf) > PAGE_SIZE);
+
scbuf = (struct sclp_statechangebuf *) evbuf;
- if (scbuf->mask_length != sizeof(sccb_mask_t))
- return;
spin_lock_irqsave(&sclp_lock, flags);
if (scbuf->validity_sclp_receive_mask)
- sclp_receive_mask = scbuf->sclp_receive_mask;
+ sclp_receive_mask = sccb_get_recv_mask(scbuf);
if (scbuf->validity_sclp_send_mask)
- sclp_send_mask = scbuf->sclp_send_mask;
+ sclp_send_mask = sccb_get_send_mask(scbuf);
spin_unlock_irqrestore(&sclp_lock, flags);
if (scbuf->validity_sclp_active_facility_mask)
sclp.facilities = scbuf->sclp_active_facility_mask;
sclp_init_req.sccb = sccb;
sccb->header.length = sizeof(*sccb);
sccb->mask_length = sizeof(sccb_mask_t);
- sccb->receive_mask = receive_mask;
- sccb->send_mask = send_mask;
- sccb->sclp_receive_mask = 0;
- sccb->sclp_send_mask = 0;
+ sccb_set_recv_mask(sccb, receive_mask);
+ sccb_set_send_mask(sccb, send_mask);
+ sccb_set_sclp_recv_mask(sccb, 0);
+ sccb_set_sclp_send_mask(sccb, 0);
}
/* Start init mask request. If calculate is non-zero, calculate the mask as
sccb->header.response_code == 0x20) {
/* Successful request */
if (calculate) {
- sclp_receive_mask = sccb->sclp_receive_mask;
- sclp_send_mask = sccb->sclp_send_mask;
+ sclp_receive_mask = sccb_get_sclp_recv_mask(sccb);
+ sclp_send_mask = sccb_get_sclp_send_mask(sccb);
} else {
sclp_receive_mask = 0;
sclp_send_mask = 0;
struct sccb_header header;
u16 _reserved;
u16 mask_length;
- sccb_mask_t receive_mask;
- sccb_mask_t send_mask;
- sccb_mask_t sclp_receive_mask;
- sccb_mask_t sclp_send_mask;
+ u8 masks[4 * 1021]; /* variable length */
+ /*
+ * u8 receive_mask[mask_length];
+ * u8 send_mask[mask_length];
+ * u8 sclp_receive_mask[mask_length];
+ * u8 sclp_send_mask[mask_length];
+ */
} __attribute__((packed));
+static inline sccb_mask_t sccb_get_mask(u8 *masks, size_t len, int i)
+{
+ sccb_mask_t res = 0;
+
+ memcpy(&res, masks + i * len, min(sizeof(res), len));
+ return res;
+}
+
+static inline void sccb_set_mask(u8 *masks, size_t len, int i, sccb_mask_t val)
+{
+ memset(masks + i * len, 0, len);
+ memcpy(masks + i * len, &val, min(sizeof(val), len));
+}
+
+#define sccb_get_generic_mask(sccb, i) \
+({ \
+ __typeof__(sccb) __sccb = sccb; \
+ \
+ sccb_get_mask(__sccb->masks, __sccb->mask_length, i); \
+})
+#define sccb_get_recv_mask(sccb) sccb_get_generic_mask(sccb, 0)
+#define sccb_get_send_mask(sccb) sccb_get_generic_mask(sccb, 1)
+#define sccb_get_sclp_recv_mask(sccb) sccb_get_generic_mask(sccb, 2)
+#define sccb_get_sclp_send_mask(sccb) sccb_get_generic_mask(sccb, 3)
+
+#define sccb_set_generic_mask(sccb, i, val) \
+({ \
+ __typeof__(sccb) __sccb = sccb; \
+ \
+ sccb_set_mask(__sccb->masks, __sccb->mask_length, i, val); \
+})
+#define sccb_set_recv_mask(sccb, val) sccb_set_generic_mask(sccb, 0, val)
+#define sccb_set_send_mask(sccb, val) sccb_set_generic_mask(sccb, 1, val)
+#define sccb_set_sclp_recv_mask(sccb, val) sccb_set_generic_mask(sccb, 2, val)
+#define sccb_set_sclp_send_mask(sccb, val) sccb_set_generic_mask(sccb, 3, val)
+
struct read_cpu_info_sccb {
struct sccb_header header;
u16 nr_configured;
void sclp_early_wait_irq(void);
int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb);
unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb);
+unsigned int sclp_early_con_check_vt220(struct init_sccb *sccb);
int sclp_early_set_event_mask(struct init_sccb *sccb,
sccb_mask_t receive_mask,
sccb_mask_t send_mask);
if (sccb->header.response_code != 0x20)
return;
- if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK)
+ if (sclp_early_con_check_vt220(sccb))
sclp.has_vt220 = 1;
if (sclp_early_con_check_linemode(sccb))
memset(sccb, 0, sizeof(*sccb));
sccb->header.length = sizeof(*sccb);
sccb->mask_length = sizeof(sccb_mask_t);
- sccb->receive_mask = receive_mask;
- sccb->send_mask = send_mask;
+ sccb_set_recv_mask(sccb, receive_mask);
+ sccb_set_send_mask(sccb, send_mask);
if (sclp_early_cmd(SCLP_CMDW_WRITE_EVENT_MASK, sccb))
return -EIO;
if (sccb->header.response_code != 0x20)
unsigned int sclp_early_con_check_linemode(struct init_sccb *sccb)
{
- if (!(sccb->sclp_send_mask & EVTYP_OPCMD_MASK))
+ if (!(sccb_get_sclp_send_mask(sccb) & EVTYP_OPCMD_MASK))
return 0;
- if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
+ if (!(sccb_get_sclp_recv_mask(sccb) & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
return 0;
return 1;
}
+unsigned int sclp_early_con_check_vt220(struct init_sccb *sccb)
+{
+ if (sccb_get_sclp_send_mask(sccb) & EVTYP_VT220MSG_MASK)
+ return 1;
+ return 0;
+}
+
static int sclp_early_setup(int disable, int *have_linemode, int *have_vt220)
{
unsigned long receive_mask, send_mask;
struct init_sccb *sccb;
int rc;
+ BUILD_BUG_ON(sizeof(struct init_sccb) > PAGE_SIZE);
+
*have_linemode = *have_vt220 = 0;
sccb = (struct init_sccb *) &sclp_early_sccb;
receive_mask = disable ? 0 : EVTYP_OPCMD_MASK;
if (rc)
return rc;
*have_linemode = sclp_early_con_check_linemode(sccb);
- *have_vt220 = sccb->send_mask & EVTYP_VT220MSG_MASK;
+ *have_vt220 = !!(sccb_get_send_mask(sccb) & EVTYP_VT220MSG_MASK);
return rc;
}