blob: a1136e052750565803b90ac478d69d3e46a70218 [file] [log] [blame]
Heiko Carstensab14de62007-02-05 21:18:37 +01001/*
2 * drivers/s390/char/sclp_info.c
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 */
7
8#include <linux/init.h>
9#include <linux/errno.h>
10#include <linux/string.h>
11#include <asm/sclp.h>
12#include "sclp.h"
13
Heiko Carstens05dd2532007-07-10 11:24:09 +020014struct sclp_readinfo_sccb {
15 struct sccb_header header; /* 0-7 */
16 u16 rnmax; /* 8-9 */
17 u8 rnsize; /* 10 */
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 */
23 u8 flags; /* 91 */
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)));
29
30static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
31static int __initdata early_readinfo_sccb_valid;
Heiko Carstensab14de62007-02-05 21:18:37 +010032
Heiko Carstens83119ad2007-07-10 11:24:10 +020033u64 sclp_facilities;
34
Heiko Carstensab14de62007-02-05 21:18:37 +010035void __init sclp_readinfo_early(void)
36{
Heiko Carstensab14de62007-02-05 21:18:37 +010037 int ret;
Heiko Carstens05dd2532007-07-10 11:24:09 +020038 int i;
39 struct sclp_readinfo_sccb *sccb;
40 sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
41 SCLP_CMDW_READ_SCP_INFO};
Heiko Carstensab14de62007-02-05 21:18:37 +010042
Heiko Carstens05dd2532007-07-10 11:24:09 +020043 /* Enable service signal subclass mask. */
44 __ctl_set_bit(0, 9);
45 sccb = &early_readinfo_sccb;
46 for (i = 0; i < ARRAY_SIZE(commands); i++) {
47 do {
48 memset(sccb, 0, sizeof(*sccb));
49 sccb->header.length = sizeof(*sccb);
50 sccb->header.control_mask[2] = 0x80;
51 ret = sclp_service_call(commands[i], sccb);
52 } while (ret == -EBUSY);
Heiko Carstensab14de62007-02-05 21:18:37 +010053
Heiko Carstens05dd2532007-07-10 11:24:09 +020054 if (ret)
55 break;
Heiko Carstensab14de62007-02-05 21:18:37 +010056 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
57 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
58 local_irq_disable();
Heiko Carstens05dd2532007-07-10 11:24:09 +020059 /*
60 * Contents of the sccb might have changed
61 * therefore a barrier is needed.
62 */
Heiko Carstensab14de62007-02-05 21:18:37 +010063 barrier();
Heiko Carstens05dd2532007-07-10 11:24:09 +020064 if (sccb->header.response_code == 0x10) {
65 early_readinfo_sccb_valid = 1;
Heiko Carstensab14de62007-02-05 21:18:37 +010066 break;
Heiko Carstens05dd2532007-07-10 11:24:09 +020067 }
68 if (sccb->header.response_code != 0x1f0)
Heiko Carstensab14de62007-02-05 21:18:37 +010069 break;
Heiko Carstensab14de62007-02-05 21:18:37 +010070 }
Heiko Carstens05dd2532007-07-10 11:24:09 +020071 /* Disable service signal subclass mask again. */
72 __ctl_clear_bit(0, 9);
73}
74
Heiko Carstens83119ad2007-07-10 11:24:10 +020075void __init sclp_facilities_detect(void)
76{
77 if (!early_readinfo_sccb_valid)
78 return;
79 sclp_facilities = early_readinfo_sccb.facilities;
80}
81
Heiko Carstens05dd2532007-07-10 11:24:09 +020082unsigned long long __init sclp_memory_detect(void)
83{
84 unsigned long long memsize;
85 struct sclp_readinfo_sccb *sccb;
86
87 if (!early_readinfo_sccb_valid)
88 return 0;
89 sccb = &early_readinfo_sccb;
90 if (sccb->rnsize)
91 memsize = sccb->rnsize << 20;
92 else
93 memsize = sccb->rnsize2 << 20;
94 if (sccb->rnmax)
95 memsize *= sccb->rnmax;
96 else
97 memsize *= sccb->rnmax2;
98 return memsize;
99}
100
101/*
102 * This function will be called after sclp_memory_detect(), which gets called
103 * early from early.c code. Therefore the sccb should have valid contents.
104 */
105void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
106{
107 struct sclp_readinfo_sccb *sccb;
108
109 if (!early_readinfo_sccb_valid)
110 return;
111 sccb = &early_readinfo_sccb;
112 info->is_valid = 1;
113 if (sccb->flags & 0x2)
114 info->has_dump = 1;
115 memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
Heiko Carstensab14de62007-02-05 21:18:37 +0100116}