aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-07-10 05:24:09 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-07-10 05:24:42 -0400
commit05dd25307ca67cbfa0207bbba2e6c79fa97d125b (patch)
tree4601c5732e71883bffab31a4a786f838e8473f58 /drivers/s390/char
parentbccdbdc9bd7db3a32c14d8a47f1fb66e3de3c92f (diff)
[S390] sclp: introduce some new interfaces.
Introduce some new interfaces so that random subsystems don't have to mess around with sclp internal structures. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/sclp.h7
-rw-r--r--drivers/s390/char/sclp_info.c108
2 files changed, 86 insertions, 29 deletions
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index dbb99d1b6f57..cb5888f79007 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -72,6 +72,13 @@ typedef unsigned int sclp_cmdw_t;
72 72
73typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ 73typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
74 74
75struct sccb_header {
76 u16 length;
77 u8 function_code;
78 u8 control_mask[3];
79 u16 response_code;
80} __attribute__((packed));
81
75struct gds_subvector { 82struct gds_subvector {
76 u8 length; 83 u8 length;
77 u8 key; 84 u8 key;
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
index 7bcbe643b087..7d21dbb12fcd 100644
--- a/drivers/s390/char/sclp_info.c
+++ b/drivers/s390/char/sclp_info.c
@@ -11,47 +11,97 @@
11#include <asm/sclp.h> 11#include <asm/sclp.h>
12#include "sclp.h" 12#include "sclp.h"
13 13
14struct sclp_readinfo_sccb s390_readinfo_sccb; 14struct 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;
15 32
16void __init sclp_readinfo_early(void) 33void __init sclp_readinfo_early(void)
17{ 34{
18 sclp_cmdw_t command;
19 struct sccb_header *sccb;
20 int ret; 35 int ret;
36 int i;
37 struct sclp_readinfo_sccb *sccb;
38 sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
39 SCLP_CMDW_READ_SCP_INFO};
21 40
22 __ctl_set_bit(0, 9); /* enable service signal subclass mask */ 41 /* Enable service signal subclass mask. */
23 42 __ctl_set_bit(0, 9);
24 sccb = &s390_readinfo_sccb.header; 43 sccb = &early_readinfo_sccb;
25 command = SCLP_CMDW_READ_SCP_INFO_FORCED; 44 for (i = 0; i < ARRAY_SIZE(commands); i++) {
26 while (1) { 45 do {
27 u16 response; 46 memset(sccb, 0, sizeof(*sccb));
28 47 sccb->header.length = sizeof(*sccb);
29 memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb)); 48 sccb->header.control_mask[2] = 0x80;
30 sccb->length = sizeof(s390_readinfo_sccb); 49 ret = sclp_service_call(commands[i], sccb);
31 sccb->control_mask[2] = 0x80; 50 } while (ret == -EBUSY);
32
33 ret = sclp_service_call(command, &s390_readinfo_sccb);
34
35 if (ret == -EIO)
36 goto out;
37 if (ret == -EBUSY)
38 continue;
39 51
52 if (ret)
53 break;
40 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | 54 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
41 PSW_MASK_WAIT | PSW_DEFAULT_KEY); 55 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
42 local_irq_disable(); 56 local_irq_disable();
57 /*
58 * Contents of the sccb might have changed
59 * therefore a barrier is needed.
60 */
43 barrier(); 61 barrier();
62 if (sccb->header.response_code == 0x10) {
63 early_readinfo_sccb_valid = 1;
64 break;
65 }
66 if (sccb->header.response_code != 0x1f0)
67 break;
68 }
69 /* Disable service signal subclass mask again. */
70 __ctl_clear_bit(0, 9);
71}
44 72
45 response = sccb->response_code; 73unsigned long long __init sclp_memory_detect(void)
74{
75 unsigned long long memsize;
76 struct sclp_readinfo_sccb *sccb;
46 77
47 if (response == 0x10) 78 if (!early_readinfo_sccb_valid)
48 break; 79 return 0;
80 sccb = &early_readinfo_sccb;
81 if (sccb->rnsize)
82 memsize = sccb->rnsize << 20;
83 else
84 memsize = sccb->rnsize2 << 20;
85 if (sccb->rnmax)
86 memsize *= sccb->rnmax;
87 else
88 memsize *= sccb->rnmax2;
89 return memsize;
90}
49 91
50 if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) 92/*
51 break; 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.
95 */
96void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
97{
98 struct sclp_readinfo_sccb *sccb;
52 99
53 command = SCLP_CMDW_READ_SCP_INFO; 100 if (!early_readinfo_sccb_valid)
54 } 101 return;
55out: 102 sccb = &early_readinfo_sccb;
56 __ctl_clear_bit(0, 9); /* disable service signal subclass mask */ 103 info->is_valid = 1;
104 if (sccb->flags & 0x2)
105 info->has_dump = 1;
106 memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
57} 107}