This commit was manufactured by cvs2svn to create tag
[opensuse:hwinfo.git] / 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
17 static void hd_scan_s390_ex(hd_data_t *hd_data, int disks_only)
18 {
19   hd_t* hd;
20   hd_res_t* res;
21   struct sysfs_bus *bus;
22   struct sysfs_device *curdev = NULL;
23   struct dlist *attributes = NULL;
24   struct sysfs_attribute *curattr = NULL;
25   struct dlist *devlist = NULL;
26
27   unsigned int devtype=0,devmod=0,cutype=0,cumod=0;
28
29   /* list of each channel's cutype, used for finding multichannel devices */
30   int cutypes[1<<16]={0};
31   int i;
32
33   hd_data->module=mod_s390;
34
35   remove_hd_entries(hd_data);
36
37   //sl0=sl=read_file(PROCSUBCHANNELS, 2, 0);
38   bus=sysfs_open_bus(BUSNAME);
39
40   if (!bus)
41   {
42     ADD2LOG("unable to open" BUSNAME "bus");
43     return;
44   }
45
46   devlist=sysfs_get_bus_devices(bus);
47   
48   if(!devlist)
49   {
50         ADD2LOG("unable to get devices on bus " BUSNAME);
51         return;
52   }
53   
54   /* build cutypes list */
55   dlist_for_each_data(devlist, curdev, struct sysfs_device)
56   {
57     int channel=strtol(rindex(curdev->bus_id,'.')+1,NULL,16);
58     attributes = sysfs_get_device_attributes(curdev);
59     dlist_for_each_data(attributes,curattr,struct sysfs_attribute)
60     {
61       if(strcmp("cutype",curattr->name)==0)
62         cutype=strtol(curattr->value,NULL,16);
63     }
64     cutypes[channel]=cutype;
65   }
66   /* check for each channel if it must be skipped and identify virtual reader/punch */
67   for(i=0;i<(1<<16);i++)
68   {
69     if(/* cutypes[i]==0x1731 || */ cutypes[i]==0x3088)  /* It seems that QDIO devices only appear once */
70     {
71       cutypes[i+1]=-1;  /* skip */
72       if(cutypes[i]==0x1731)
73         cutypes[i+2]=-1;
74     }
75     if(cutypes[i]==0x2540)
76     {
77       cutypes[i]=-2;    /* reader */
78       cutypes[i+1]=-3;  /* punch */
79     }
80   }
81   
82   dlist_for_each_data(devlist, curdev, struct sysfs_device)
83   {
84     int readonly=0;
85     res=new_mem(sizeof *res);
86
87     attributes = sysfs_get_device_attributes(curdev);
88     dlist_for_each_data(attributes,curattr, struct sysfs_attribute)
89     {
90       if (strcmp("online",curattr->name)==0)
91         res->io.enabled=atoi(curattr->value);
92       else if (strcmp("cutype",curattr->name)==0)
93       {
94         cutype=strtol(curattr->value,NULL,16);
95         cumod=strtol(index(curattr->value,'/')+1,NULL,16);
96       } else if (strcmp("devtype",curattr->name)==0)
97       {
98         devtype=strtol(curattr->value,NULL,16);
99         devmod=strtol(index(curattr->value,'/')+1,NULL,16);
100       } else if (strcmp("readonly",curattr->name)==0)
101       {
102         readonly=atoi(curattr->value);
103       }
104     }
105     
106     res->io.type=res_io;
107     res->io.access=readonly?acc_ro:acc_rw;
108     res->io.base=strtol(rindex(curdev->bus_id,'.')+1,NULL,16);
109
110     /* Skip additional channels for multi-channel devices */
111     if(cutypes[res->io.base] == -1)
112       continue;
113
114     if(disks_only && cutype!=0x3990 &&
115        (cutype != 0x1731 || devtype != 0x1732 || cumod != 3))
116       continue;
117
118     res->io.range=1;
119     switch (cutype)
120     {
121       /* three channels */
122       case 0x1731:    /* QDIO (QETH, HSI, zFCP) */
123         res->io.range++;
124       /* two channels */
125       case 0x3088:    /* CU3088 (CTC, LCS) */
126         res->io.range++;
127     }
128
129     hd=add_hd_entry(hd_data,__LINE__,0);
130     add_res_entry(&hd->res,res);
131     hd->vendor.id=MAKE_ID(TAG_SPECIAL,0x6001); /* IBM */
132     hd->device.id=MAKE_ID(TAG_SPECIAL,cutype);
133     hd->sub_device.id=MAKE_ID(TAG_SPECIAL,devtype);
134     hd->bus.id=bus_ccw;
135     hd->sysfs_device_link = new_str(hd_sysfs_id(curdev->path));
136     hd->sysfs_bus_id = new_str(strrchr(curdev->path,'/')+1);
137     
138     if(cutypes[res->io.base]==-2)       /* virtual reader */
139     {
140       hd->base_class.id=bc_scanner;
141     }
142     if(cutypes[res->io.base]==-3)       /* virtual punch */
143     {
144       hd->base_class.id=bc_printer;
145     }
146     /* all other device data (names, classes etc.) comes from the s390 ID file */
147
148     hd->detail=free_hd_detail(hd->detail);
149     hd->detail=new_mem(sizeof *hd->detail);
150     hd->detail->ccw.type=hd_detail_ccw;
151     hd->detail->ccw.data=new_mem(sizeof(ccw_t));
152     hd->detail->ccw.data->cu_model=cumod;
153     hd->detail->ccw.data->dev_model=devmod;
154     hd->detail->ccw.data->lcss=(strtol(curdev->bus_id,0,16) << 8) + strtol(curdev->bus_id+2,0,16);
155     hddb_add_info(hd_data,hd);
156   }
157
158 }
159
160 void hd_scan_s390(hd_data_t *hd_data)
161 {
162   if (!hd_probe_feature(hd_data, pr_s390)) return;
163   hd_scan_s390_ex(hd_data, 0);
164 }
165
166 void hd_scan_s390disks(hd_data_t *hd_data)
167 {
168   if (!hd_probe_feature(hd_data, pr_s390disks)) return;
169   hd_scan_s390_ex(hd_data, 1);
170 }
171
172 #endif
173