]> git.ipfire.org Git - ipfire-2.x.git/blob - src/hwinfo/src/hd/s390.c
HWInfo wieder eingefuegt, da mit kudzu zu viele Segmentation Faults liefert.
[ipfire-2.x.git] / src / hwinfo / src / hd / s390.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "hd.h"
6 #include "hd_int.h"
7 #include "hddb.h"
8 #include "s390.h"
9
10 #if defined(__s390__) || defined(__s390x__)
11
12 #include <sysfs/libsysfs.h>
13 #include <sysfs/dlist.h>
14
15 #define BUSNAME "ccw"
16 #define BUSNAME_GROUP "ccwgroup"
17 #define BUSNAME_IUCV "iucv"
18
19 static void hd_scan_s390_ex(hd_data_t *hd_data, int disks_only)
20 {
21 hd_t* hd;
22 hd_res_t* res;
23 struct sysfs_bus *bus;
24 struct sysfs_bus *bus_group;
25 struct sysfs_device *curdev = NULL;
26 struct dlist *attributes = NULL;
27 struct sysfs_attribute *curattr = NULL;
28 struct dlist *devlist = NULL;
29 struct dlist *devlist_group = NULL;
30 int virtual_machine=0;
31
32 unsigned int devtype=0,devmod=0,cutype=0,cumod=0;
33
34 /* list of each channel's cutype, used for finding multichannel devices */
35 int cutypes[1<<16]={0};
36 int i;
37
38 hd_data->module=mod_s390;
39
40 remove_hd_entries(hd_data);
41
42 bus=sysfs_open_bus(BUSNAME);
43 bus_group=sysfs_open_bus(BUSNAME_GROUP);
44
45 if (!bus)
46 {
47 ADD2LOG("unable to open" BUSNAME "bus");
48 return;
49 }
50
51 devlist=sysfs_get_bus_devices(bus);
52 if(bus_group) devlist_group=sysfs_get_bus_devices(bus_group);
53
54 if(!devlist)
55 {
56 ADD2LOG("unable to get devices on bus " BUSNAME);
57 return;
58 }
59
60 /* build cutypes list */
61 dlist_for_each_data(devlist, curdev, struct sysfs_device)
62 {
63 int channel=strtol(rindex(curdev->bus_id,'.')+1,NULL,16);
64 attributes = sysfs_get_device_attributes(curdev);
65 dlist_for_each_data(attributes,curattr,struct sysfs_attribute)
66 {
67 if(strcmp("cutype",curattr->name)==0)
68 cutype=strtol(curattr->value,NULL,16);
69 }
70 cutypes[channel]=cutype;
71 }
72 /* check for each channel if it must be skipped and identify virtual reader/punch */
73 for(i=0;i<(1<<16);i++)
74 {
75 if(cutypes[i]==0x3088) /* It seems that QDIO devices only appear once */
76 cutypes[i+1]*=-1; /* negative cutype -> skip */
77
78 if(cutypes[i]==0x2540)
79 {
80 virtual_machine=1; /* we are running in VM */
81 cutypes[i]=-2; /* reader */
82 cutypes[i+1]=-3; /* punch */
83 }
84 }
85
86 /* identify grouped channels */
87 if(devlist_group) dlist_for_each_data(devlist_group, curdev, struct sysfs_device)
88 {
89 struct sysfs_directory* d;
90 struct dlist* dl;
91 struct sysfs_link* cl;
92 //printf("ccwg %s\n",curdev->path);
93 d=sysfs_open_directory(curdev->path);
94 dl=sysfs_get_dir_links(d);
95 dlist_for_each_data(dl,cl,struct sysfs_link) /* iterate over this channel group */
96 {
97 if(!rindex(cl->target,'.')) continue;
98 int channel=strtol(rindex(cl->target,'.')+1,NULL,16);
99 //printf("channel %x name %s target %s\n",channel,cl->name,cl->target);
100 if(strncmp("cdev",cl->name,4)==0)
101 {
102 if(cl->name[4]=='0') /* first channel in group gets an entry */
103 {
104 if(cutypes[channel]<0) cutypes[channel]*=-1; /* make sure its positive */
105 }
106 else /* other channels in group are skipped */
107 if(cutypes[channel]>0) cutypes[channel]*=-1; /* make sure its negative */
108 }
109
110 }
111 }
112
113 dlist_for_each_data(devlist, curdev, struct sysfs_device)
114 {
115 int readonly=0;
116 res=new_mem(sizeof *res);
117
118 attributes = sysfs_get_device_attributes(curdev);
119 dlist_for_each_data(attributes,curattr, struct sysfs_attribute)
120 {
121 if (strcmp("online",curattr->name)==0)
122 res->io.enabled=atoi(curattr->value);
123 else if (strcmp("cutype",curattr->name)==0)
124 {
125 cutype=strtol(curattr->value,NULL,16);
126 cumod=strtol(index(curattr->value,'/')+1,NULL,16);
127 } else if (strcmp("devtype",curattr->name)==0)
128 {
129 devtype=strtol(curattr->value,NULL,16);
130 devmod=strtol(index(curattr->value,'/')+1,NULL,16);
131 } else if (strcmp("readonly",curattr->name)==0)
132 {
133 readonly=atoi(curattr->value);
134 }
135 }
136
137 res->io.type=res_io;
138 res->io.access=readonly?acc_ro:acc_rw;
139 res->io.base=strtol(rindex(curdev->bus_id,'.')+1,NULL,16);
140
141 /* Skip additional channels for multi-channel devices */
142 if(cutypes[res->io.base] < -3)
143 continue;
144
145 if(disks_only && cutype!=0x3990 && cutype!=0x2105 && cutype!=0x3880 && cutype!=0x9343 && cutype!=0x6310 &&
146 (cutype != 0x1731 || devtype != 0x1732 || cumod != 3))
147 continue;
148
149 res->io.range=1;
150 switch (cutype)
151 {
152 /* three channels */
153 case 0x1731: /* QDIO (QETH, HSI, zFCP) */
154 res->io.range++;
155 /* two channels */
156 case 0x3088: /* CU3088 (CTC, LCS) */
157 res->io.range++;
158 }
159
160 hd=add_hd_entry(hd_data,__LINE__,0);
161 add_res_entry(&hd->res,res);
162 hd->vendor.id=MAKE_ID(TAG_SPECIAL,0x6001); /* IBM */
163 hd->device.id=MAKE_ID(TAG_SPECIAL,cutype);
164 hd->sub_device.id=MAKE_ID(TAG_SPECIAL,devtype);
165 hd->bus.id=bus_ccw;
166 hd->sysfs_device_link = new_str(hd_sysfs_id(curdev->path));
167 hd->sysfs_bus_id = new_str(strrchr(curdev->path,'/')+1);
168
169 if(cutypes[res->io.base]==-2) /* virtual reader */
170 {
171 hd->base_class.id=bc_scanner;
172 }
173 if(cutypes[res->io.base]==-3) /* virtual punch */
174 {
175 hd->base_class.id=bc_printer;
176 }
177 /* all other device data (names, classes etc.) comes from the s390 ID file */
178
179 hd->detail=free_hd_detail(hd->detail);
180 hd->detail=new_mem(sizeof *hd->detail);
181 hd->detail->ccw.type=hd_detail_ccw;
182 hd->detail->ccw.data=new_mem(sizeof(ccw_t));
183 hd->detail->ccw.data->cu_model=cumod;
184 hd->detail->ccw.data->dev_model=devmod;
185 hd->detail->ccw.data->lcss=(strtol(curdev->bus_id,0,16) << 8) + strtol(curdev->bus_id+2,0,16);
186 hddb_add_info(hd_data,hd);
187 }
188
189 if(virtual_machine)
190 {
191 /* add an unactivated IUCV device */
192 hd=add_hd_entry(hd_data,__LINE__,0);
193 hd->vendor.id=MAKE_ID(TAG_SPECIAL,0x6001); /* IBM */
194 hd->device.id=MAKE_ID(TAG_SPECIAL,0x0005); /* IUCV */
195 hd->bus.id=bus_iucv;
196 hd->base_class.id=bc_network;
197 hd->status.active=status_no;
198 hd->status.available=status_yes;
199 hddb_add_info(hd_data,hd);
200
201 /* add activated IUCV devices */
202 bus=sysfs_open_bus(BUSNAME_IUCV);
203 if(bus)
204 {
205 devlist=sysfs_get_bus_devices(bus);
206 if(devlist)
207 {
208 dlist_for_each_data(devlist, curdev, struct sysfs_device)
209 {
210 hd=add_hd_entry(hd_data,__LINE__,0);
211 hd->vendor.id=MAKE_ID(TAG_SPECIAL,0x6001); /* IBM */
212 hd->device.id=MAKE_ID(TAG_SPECIAL,0x0005); /* IUCV */
213 hd->bus.id=bus_iucv;
214 hd->base_class.id=bc_network;
215 hd->status.active=status_yes;
216 hd->status.available=status_yes;
217 attributes = sysfs_get_device_attributes(curdev);
218 dlist_for_each_data(attributes,curattr,struct sysfs_attribute)
219 {
220 if(strcmp("user",curattr->name)==0)
221 hd->rom_id=new_str(curattr->value);
222 }
223 hd->sysfs_device_link = new_str(hd_sysfs_id(curdev->path));
224 hd->sysfs_bus_id = new_str(strrchr(curdev->path,'/')+1);
225 hddb_add_info(hd_data,hd);
226 }
227 }
228 }
229
230 }
231 }
232
233 void hd_scan_s390(hd_data_t *hd_data)
234 {
235 if (!hd_probe_feature(hd_data, pr_s390)) return;
236 hd_scan_s390_ex(hd_data, 0);
237 }
238
239 void hd_scan_s390disks(hd_data_t *hd_data)
240 {
241 if (!hd_probe_feature(hd_data, pr_s390disks)) return;
242 hd_scan_s390_ex(hd_data, 1);
243 }
244
245 #endif
246