2 * drivers/s390/char/sclp_info.c
4 * Copyright IBM Corp. 2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
8 #include <linux/init.h>
9 #include <linux/errno.h>
10 #include <linux/string.h>
14 struct sclp_readinfo_sccb {
15 struct sccb_header header; /* 0-7 */
18 u8 _reserved0[24 - 11]; /* 11-23 */
19 u8 loadparm[8]; /* 24-31 */
20 u8 _reserved1[48 - 32]; /* 32-47 */
21 u64 facilities; /* 48-55 */
22 u8 _reserved2[91 - 56]; /* 56-90 */
24 u8 _reserved3[100 - 92]; /* 92-99 */
25 u32 rnsize2; /* 100-103 */
26 u64 rnmax2; /* 104-111 */
27 u8 _reserved4[4096 - 112]; /* 112-4095 */
28 } __attribute__((packed, aligned(4096)));
30 static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
31 static int __initdata early_readinfo_sccb_valid;
33 void __init sclp_readinfo_early(void)
37 struct sclp_readinfo_sccb *sccb;
38 sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
39 SCLP_CMDW_READ_SCP_INFO};
41 /* Enable service signal subclass mask. */
43 sccb = &early_readinfo_sccb;
44 for (i = 0; i < ARRAY_SIZE(commands); i++) {
46 memset(sccb, 0, sizeof(*sccb));
47 sccb->header.length = sizeof(*sccb);
48 sccb->header.control_mask[2] = 0x80;
49 ret = sclp_service_call(commands[i], sccb);
50 } while (ret == -EBUSY);
54 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
55 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
58 * Contents of the sccb might have changed
59 * therefore a barrier is needed.
62 if (sccb->header.response_code == 0x10) {
63 early_readinfo_sccb_valid = 1;
66 if (sccb->header.response_code != 0x1f0)
69 /* Disable service signal subclass mask again. */
70 __ctl_clear_bit(0, 9);
73 unsigned long long __init sclp_memory_detect(void)
75 unsigned long long memsize;
76 struct sclp_readinfo_sccb *sccb;
78 if (!early_readinfo_sccb_valid)
80 sccb = &early_readinfo_sccb;
82 memsize = sccb->rnsize << 20;
84 memsize = sccb->rnsize2 << 20;
86 memsize *= sccb->rnmax;
88 memsize *= sccb->rnmax2;
93 * This function will be called after sclp_memory_detect(), which gets called
94 * early from early.c code. Therefore the sccb should have valid contents.
96 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
98 struct sclp_readinfo_sccb *sccb;
100 if (!early_readinfo_sccb_valid)
102 sccb = &early_readinfo_sccb;
104 if (sccb->flags & 0x2)
106 memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);