File: /usr/src/linux/drivers/s390/char/hwc_cpi.c

1     
2     /*
3      * Author: Martin Peschke <mpeschke@de.ibm.com>
4      * Copyright (C) 2001 IBM Entwicklung GmbH, IBM Corporation
5      */
6     
7     #include <linux/string.h>
8     #include <linux/ctype.h>
9     #include <linux/module.h>
10     #include <linux/init.h>
11     #include <linux/errno.h>
12     #include <linux/malloc.h>
13     #include <linux/version.h>
14     #include <asm/semaphore.h>
15     #include <asm/ebcdic.h>
16     #include "hwc_rw.h"
17     #include "hwc.h"
18     
19     #define CPI_LENGTH_SYSTEM_TYPE	8
20     #define CPI_LENGTH_SYSTEM_NAME	8
21     #define CPI_LENGTH_SYSPLEX_NAME	8
22     
23     typedef struct {
24     	_EBUF_HEADER
25     	u8 id_format;
26     	u8 reserved0;
27     	u8 system_type[CPI_LENGTH_SYSTEM_TYPE];
28     	u64 reserved1;
29     	u8 system_name[CPI_LENGTH_SYSTEM_NAME];
30     	u64 reserved2;
31     	u64 system_level;
32     	u64 reserved3;
33     	u8 sysplex_name[CPI_LENGTH_SYSPLEX_NAME];
34     	u8 reserved4[16];
35     } __attribute__ ((packed)) 
36     
37     cpi_evbuf_t;
38     
39     typedef struct _cpi_hwcb_t {
40     	_HWCB_HEADER
41     	cpi_evbuf_t cpi_evbuf;
42     } __attribute__ ((packed)) 
43     
44     cpi_hwcb_t;
45     
46     cpi_hwcb_t *cpi_hwcb;
47     
48     static int __init cpi_module_init (void);
49     static void __exit cpi_module_exit (void);
50     
51     module_init (cpi_module_init);
52     module_exit (cpi_module_exit);
53     
54     MODULE_AUTHOR (
55     		      "Martin Peschke, IBM Deutschland Entwicklung GmbH "
56     		      "<mpeschke@de.ibm.com>");
57     
58     MODULE_DESCRIPTION (
59       "identify this operating system instance to the S/390 or zSeries hardware");
60     
61     static char *system_name = NULL;
62     MODULE_PARM (system_name, "s");
63     MODULE_PARM_DESC (system_name, "e.g. hostname - max. 8 characters");
64     
65     static char *sysplex_name = NULL;
66     #ifdef ALLOW_SYSPLEX_NAME
67     MODULE_PARM (sysplex_name, "s");
68     MODULE_PARM_DESC (sysplex_name, "if applicable - max. 8 characters");
69     #endif
70     
71     static char *system_type = "LINUX";
72     
73     hwc_request_t cpi_request =
74     {};
75     
76     hwc_callback_t cpi_callback;
77     
78     static DECLARE_MUTEX_LOCKED (sem);
79     
80     static int __init 
81     cpi_module_init (void)
82     {
83     	int retval;
84     	int system_type_length;
85     	int system_name_length;
86     	int sysplex_name_length = 0;
87     
88     	if (!MACHINE_HAS_HWC) {
89     		printk ("cpi: bug: hardware console not present\n");
90     		retval = -EINVAL;
91     		goto out;
92     	}
93     	if (!system_type) {
94     		printk ("cpi: bug: no system type specified\n");
95     		retval = -EINVAL;
96     		goto out;
97     	}
98     	system_type_length = strlen (system_type);
99     	if (system_type_length > CPI_LENGTH_SYSTEM_NAME) {
100     		printk ("cpi: bug: system type has length of %i characters - "
101     			"only %i characters supported\n",
102     			system_type_length,
103     			CPI_LENGTH_SYSTEM_TYPE);
104     		retval = -EINVAL;
105     		goto out;
106     	}
107     	if (!system_name) {
108     		printk ("cpi: no system name specified\n");
109     		retval = -EINVAL;
110     		goto out;
111     	}
112     	system_name_length = strlen (system_name);
113     	if (system_name_length > CPI_LENGTH_SYSTEM_NAME) {
114     		printk ("cpi: system name has length of %i characters - "
115     			"only %i characters supported\n",
116     			system_name_length,
117     			CPI_LENGTH_SYSTEM_NAME);
118     		retval = -EINVAL;
119     		goto out;
120     	}
121     	if (sysplex_name) {
122     		sysplex_name_length = strlen (sysplex_name);
123     		if (sysplex_name_length > CPI_LENGTH_SYSPLEX_NAME) {
124     			printk ("cpi: sysplex name has length of %i characters - "
125     				"only %i characters supported\n",
126     				sysplex_name_length,
127     				CPI_LENGTH_SYSPLEX_NAME);
128     			retval = -EINVAL;
129     			goto out;
130     		}
131     	}
132     	cpi_hwcb = kmalloc (sizeof (cpi_hwcb_t), GFP_KERNEL);
133     	if (!cpi_hwcb) {
134     		printk ("cpi: no storage to fulfill request\n");
135     		retval = -ENOMEM;
136     		goto out;
137     	}
138     	memset (cpi_hwcb, 0, sizeof (cpi_hwcb_t));
139     
140     	cpi_hwcb->length = sizeof (cpi_hwcb_t);
141     	cpi_hwcb->cpi_evbuf.length = sizeof (cpi_evbuf_t);
142     	cpi_hwcb->cpi_evbuf.type = 0x0B;
143     
144     	memset (cpi_hwcb->cpi_evbuf.system_type, ' ', CPI_LENGTH_SYSTEM_TYPE);
145     	memcpy (cpi_hwcb->cpi_evbuf.system_type, system_type, system_type_length);
146     	HWC_ASCEBC_STR (cpi_hwcb->cpi_evbuf.system_type, CPI_LENGTH_SYSTEM_TYPE);
147     	EBC_TOUPPER (cpi_hwcb->cpi_evbuf.system_type, CPI_LENGTH_SYSTEM_TYPE);
148     
149     	memset (cpi_hwcb->cpi_evbuf.system_name, ' ', CPI_LENGTH_SYSTEM_NAME);
150     	memcpy (cpi_hwcb->cpi_evbuf.system_name, system_name, system_name_length);
151     	HWC_ASCEBC_STR (cpi_hwcb->cpi_evbuf.system_name, CPI_LENGTH_SYSTEM_NAME);
152     	EBC_TOUPPER (cpi_hwcb->cpi_evbuf.system_name, CPI_LENGTH_SYSTEM_NAME);
153     
154     	cpi_hwcb->cpi_evbuf.system_level = LINUX_VERSION_CODE;
155     
156     	if (sysplex_name) {
157     		memset (cpi_hwcb->cpi_evbuf.sysplex_name, ' ', CPI_LENGTH_SYSPLEX_NAME);
158     		memcpy (cpi_hwcb->cpi_evbuf.sysplex_name, sysplex_name, sysplex_name_length);
159     		HWC_ASCEBC_STR (cpi_hwcb->cpi_evbuf.sysplex_name, CPI_LENGTH_SYSPLEX_NAME);
160     		EBC_TOUPPER (cpi_hwcb->cpi_evbuf.sysplex_name, CPI_LENGTH_SYSPLEX_NAME);
161     	}
162     	cpi_request.block = cpi_hwcb;
163     	cpi_request.word = HWC_CMDW_WRITEDATA;
164     	cpi_request.callback = cpi_callback;
165     
166     	retval = hwc_send (&cpi_request);
167     	if (retval) {
168     		printk ("cpi: failed (%i)\n", retval);
169     		goto free;
170     	}
171     	down (&sem);
172     
173     	switch (cpi_hwcb->response_code) {
174     	case 0x0020:
175     		printk ("cpi: succeeded\n");
176     		break;
177     	default:
178     		printk ("cpi: failed with response code 0x%x\n",
179     			cpi_hwcb->response_code);
180     	}
181     
182           free:
183     	kfree (cpi_hwcb);
184     
185           out:
186     	return retval;
187     }
188     
189     static void __exit 
190     cpi_module_exit (void)
191     {
192     	printk ("cpi: exit\n");
193     }
194     
195     void 
196     cpi_callback (hwc_request_t * req)
197     {
198     	up (&sem);
199     }
200