]>
git.ipfire.org Git - people/trikolon/ipfire-2.x.git/blob - src/hwinfo/src/hd/s390.c
10 #if defined(__s390__) || defined(__s390x__)
12 #include <sysfs/libsysfs.h>
13 #include <sysfs/dlist.h>
16 #define BUSNAME_GROUP "ccwgroup"
17 #define BUSNAME_IUCV "iucv"
19 static void hd_scan_s390_ex(hd_data_t
*hd_data
, int disks_only
)
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;
32 unsigned int devtype
=0,devmod
=0,cutype
=0,cumod
=0;
34 /* list of each channel's cutype, used for finding multichannel devices */
35 int cutypes
[1<<16]={0};
38 hd_data
->module
=mod_s390
;
40 remove_hd_entries(hd_data
);
42 bus
=sysfs_open_bus(BUSNAME
);
43 bus_group
=sysfs_open_bus(BUSNAME_GROUP
);
47 ADD2LOG("unable to open" BUSNAME
"bus");
51 devlist
=sysfs_get_bus_devices(bus
);
52 if(bus_group
) devlist_group
=sysfs_get_bus_devices(bus_group
);
56 ADD2LOG("unable to get devices on bus " BUSNAME
);
60 /* build cutypes list */
61 dlist_for_each_data(devlist
, curdev
, struct sysfs_device
)
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
)
67 if(strcmp("cutype",curattr
->name
)==0)
68 cutype
=strtol(curattr
->value
,NULL
,16);
70 cutypes
[channel
]=cutype
;
72 /* check for each channel if it must be skipped and identify virtual reader/punch */
73 for(i
=0;i
<(1<<16);i
++)
75 if(cutypes
[i
]==0x3088) /* It seems that QDIO devices only appear once */
76 cutypes
[i
+1]*=-1; /* negative cutype -> skip */
78 if(cutypes
[i
]==0x2540)
80 virtual_machine
=1; /* we are running in VM */
81 cutypes
[i
]=-2; /* reader */
82 cutypes
[i
+1]=-3; /* punch */
86 /* identify grouped channels */
87 if(devlist_group
) dlist_for_each_data(devlist_group
, curdev
, struct sysfs_device
)
89 struct sysfs_directory
* d
;
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 */
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)
102 if(cl
->name
[4]=='0') /* first channel in group gets an entry */
104 if(cutypes
[channel
]<0) cutypes
[channel
]*=-1; /* make sure its positive */
106 else /* other channels in group are skipped */
107 if(cutypes
[channel
]>0) cutypes
[channel
]*=-1; /* make sure its negative */
113 dlist_for_each_data(devlist
, curdev
, struct sysfs_device
)
116 res
=new_mem(sizeof *res
);
118 attributes
= sysfs_get_device_attributes(curdev
);
119 dlist_for_each_data(attributes
,curattr
, struct sysfs_attribute
)
121 if (strcmp("online",curattr
->name
)==0)
122 res
->io
.enabled
=atoi(curattr
->value
);
123 else if (strcmp("cutype",curattr
->name
)==0)
125 cutype
=strtol(curattr
->value
,NULL
,16);
126 cumod
=strtol(index(curattr
->value
,'/')+1,NULL
,16);
127 } else if (strcmp("devtype",curattr
->name
)==0)
129 devtype
=strtol(curattr
->value
,NULL
,16);
130 devmod
=strtol(index(curattr
->value
,'/')+1,NULL
,16);
131 } else if (strcmp("readonly",curattr
->name
)==0)
133 readonly
=atoi(curattr
->value
);
138 res
->io
.access
=readonly
?acc_ro
:acc_rw
;
139 res
->io
.base
=strtol(rindex(curdev
->bus_id
,'.')+1,NULL
,16);
141 /* Skip additional channels for multi-channel devices */
142 if(cutypes
[res
->io
.base
] < -3)
145 if(disks_only
&& cutype
!=0x3990 && cutype
!=0x2105 && cutype
!=0x3880 && cutype
!=0x9343 && cutype
!=0x6310 &&
146 (cutype
!= 0x1731 || devtype
!= 0x1732 || cumod
!= 3))
153 case 0x1731: /* QDIO (QETH, HSI, zFCP) */
156 case 0x3088: /* CU3088 (CTC, LCS) */
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
);
166 hd
->sysfs_device_link
= new_str(hd_sysfs_id(curdev
->path
));
167 hd
->sysfs_bus_id
= new_str(strrchr(curdev
->path
,'/')+1);
169 if(cutypes
[res
->io
.base
]==-2) /* virtual reader */
171 hd
->base_class
.id
=bc_scanner
;
173 if(cutypes
[res
->io
.base
]==-3) /* virtual punch */
175 hd
->base_class
.id
=bc_printer
;
177 /* all other device data (names, classes etc.) comes from the s390 ID file */
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
);
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 */
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
);
201 /* add activated IUCV devices */
202 bus
=sysfs_open_bus(BUSNAME_IUCV
);
205 devlist
=sysfs_get_bus_devices(bus
);
208 dlist_for_each_data(devlist
, curdev
, struct sysfs_device
)
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 */
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
)
220 if(strcmp("user",curattr
->name
)==0)
221 hd
->rom_id
=new_str(curattr
->value
);
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
);
233 void hd_scan_s390(hd_data_t
*hd_data
)
235 if (!hd_probe_feature(hd_data
, pr_s390
)) return;
236 hd_scan_s390_ex(hd_data
, 0);
239 void hd_scan_s390disks(hd_data_t
*hd_data
)
241 if (!hd_probe_feature(hd_data
, pr_s390disks
)) return;
242 hd_scan_s390_ex(hd_data
, 1);