]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/hwinfo/src/hd/pcmcia.c
Kleiner netter neuer Versuch.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / hd / pcmcia.c
CommitLineData
a6316ce4
MT
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <fcntl.h>
6#include <dirent.h>
7#include <sys/ioctl.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <sys/mount.h>
11#include <linux/hdreg.h>
12
13#include "hd.h"
14#include "hd_int.h"
15#include "pcmcia.h"
16
17static void read_cardinfo(hd_data_t *hd_data);
18static void assign_bridges(hd_data_t *hd_data);
19static void add_sysfs_stuff(hd_data_t *hd_data, hd_t *hd);
20
21/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22 * PCMCIA info via cardctl
23 *
24 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
25 */
26
27
28void hd_scan_pcmcia(hd_data_t *hd_data)
29{
30 if(!hd_probe_feature(hd_data, pr_pcmcia)) return;
31
32 hd_data->module = mod_pcmcia;
33
34 /* some clean-up */
35 remove_hd_entries(hd_data);
36
37 read_cardinfo(hd_data);
38
39 assign_bridges(hd_data);
40
41}
42
43
44void read_cardinfo(hd_data_t *hd_data)
45{
46 str_list_t *sl, *sl0, *sl1;
47 int i0, i1, pcmcia_sock, manf_id0, manf_id1, func, prod_info;
48 char buf0[256], buf1[256], buf2[256], buf3[256];
49 hd_t *hd;
50 unsigned cardbus = 0; /* bitmask: cardbus vs. pc-card */
51
52 sl0 = read_file("| /sbin/cardctl status 2>/dev/null", 0, 0);
53
54 ADD2LOG("----- cardctl status -----\n");
55 for(sl = sl0; sl; sl = sl->next) {
56 ADD2LOG(" %s", sl->str);
57 }
58 ADD2LOG("----- cardctl status end -----\n");
59
60 for(pcmcia_sock = -1, sl = sl0; sl; sl = sl->next) {
61 if(sscanf(sl->str, " Socket %d:", &i0) == 1) {
62 pcmcia_sock = i0;
63 continue;
64 }
65
66 if(strstr(sl->str, " CardBus card")) {
67 if(pcmcia_sock >= 0 && pcmcia_sock < 8 * (int) sizeof cardbus) {
68 cardbus |= 1 << pcmcia_sock;
69 }
70 pcmcia_sock = -1;
71 continue;
72 }
73 }
74
75 free_str_list(sl0);
76
77 sl0 = read_file("| /sbin/cardctl ident 2>/dev/null", 0, 0);
78
79 ADD2LOG("----- cardctl ident -----\n");
80 for(sl = sl0; sl; sl = sl->next) {
81 ADD2LOG(" %s", sl->str);
82 }
83 ADD2LOG("----- cardctl ident end -----\n");
84
85 for(
86 pcmcia_sock = manf_id0 = manf_id1 = func = prod_info = -1, sl = sl0;
87 sl;
88 sl = sl->next
89 ) {
90 if(sscanf(sl->str, " manfid: %i, %i", &i0, &i1) == 2) {
91 manf_id0 = i0;
92 manf_id1 = i1;
93 }
94
95 if(sscanf(sl->str, " function: %d", &i0) == 1) {
96 /*
97 * "multifunction", "memory", "serial", "parallel",
98 * "fixed disk", "video", "network", "AIMS",
99 * "SCSI"
100 */
101 func = i0;
102 }
103
104 if(
105 (i0 = sscanf(
106 sl->str,
107 " product info: \"%255[^\"]\", \"%255[^\"]\", \"%255[^\"]\", \"%255[^\"]\"",
108 buf0, buf1, buf2, buf3
109 )) >= 1
110 ) {
111 prod_info = i0;
112 }
113
114 if(sscanf(sl->str, " Socket %d:", &i0) == 1) {
115 i1 = 1;
116 }
117 else {
118 i1 = 0;
119 }
120
121 if(i1 || !sl->next) {
122 if(pcmcia_sock >= 0 && (prod_info >= 1 || manf_id0 != -1)) {
123 hd = add_hd_entry(hd_data, __LINE__, 0);
124 hd->bus.id = bus_pcmcia;
125 hd->slot = pcmcia_sock;
126 hd->hotplug_slot = pcmcia_sock + 1;
127 if(manf_id0 != -1 && manf_id1 != -1) {
128 hd->vendor.id = MAKE_ID(TAG_PCMCIA, manf_id0);
129 hd->device.id = MAKE_ID(TAG_PCMCIA, manf_id1);
130 }
131 if(pcmcia_sock < 8 * (int) sizeof cardbus && (cardbus & (1 << pcmcia_sock))) {
132 hd->hotplug = hp_cardbus;
133 }
134 else {
135 hd->hotplug = hp_pcmcia;
136 }
137
138 if(func == 6) {
139 hd->base_class.id = bc_network;
140 hd->sub_class.id = 0x80; /* other */
141 }
142 if(prod_info >= 1) add_str_list(&hd->extra_info, buf0);
143 if(prod_info >= 2) add_str_list(&hd->extra_info, buf1);
144 if(prod_info >= 3) add_str_list(&hd->extra_info, buf2);
145 if(prod_info >= 4) add_str_list(&hd->extra_info, buf3);
146 if(prod_info >= 2) {
147 hd->vendor.name = new_str(buf0);
148 hd->device.name = new_str(buf1);
149 }
150 for(sl1 = hd->extra_info; sl1 ; sl1 = sl1->next) {
151 if(strstr(sl1->str, "Ethernet")) hd->sub_class.id = 0; /* ethernet */
152 if(
153 !hd->revision.name &&
154 !sl1->next &&
155 (
156 !strncasecmp(sl1->str, "rev.", sizeof "rev." - 1) ||
157 (
158 (sl1->str[0] == 'V' || sl1->str[0] == 'v') &&
159 (sl1->str[1] >= '0' && sl1->str[1] <= '9')
160 )
161 )
162 ) {
163 hd->revision.name = new_str(sl1->str);
164 }
165 }
166 }
167
168 manf_id0 = manf_id1 = func = prod_info = -1;
169 }
170
171 if(i1) pcmcia_sock = i0;
172
173 }
174
175 free_str_list(sl0);
176}
177
178
179/*
180 * Identify hotpluggable devices.
181 */
182void assign_bridges(hd_data_t *hd_data)
183{
184 hd_t *hd, *hd1, *bridge_hd;
185 unsigned p_sock[8], p_socks, u = 0;
186
187 for(hd = hd_data->hd; hd; hd = hd->next) {
188 if((bridge_hd = hd_get_device_by_idx(hd_data, hd->attached_to))) {
189 if(
190 bridge_hd->base_class.id == bc_bridge &&
191 bridge_hd->sub_class.id == sc_bridge_cardbus
192 ) {
193 hd->hotplug = hp_cardbus;
194 }
195 else if(
196 bridge_hd->base_class.id == bc_bridge &&
197 bridge_hd->sub_class.id == sc_bridge_pcmcia
198 ) {
199 hd->hotplug = hp_pcmcia;
200 }
201 }
202 }
203
204 for(p_socks = 0, hd = hd_data->hd; hd; hd = hd->next) {
205 if(
206 u < sizeof p_sock / sizeof *p_sock &&
207 is_pcmcia_ctrl(hd_data, hd)
208 ) {
209 p_sock[p_socks++] = hd->idx;
210 }
211 }
212
213 if(p_socks) {
214 for(hd = hd_data->hd; hd; hd = hd->next) {
215 if(
216 !hd->tag.remove &&
217 hd->bus.id == bus_pcmcia &&
218 hd->slot < p_socks &&
219 p_sock[hd->slot]
220 ) {
221 for(u = p_sock[hd->slot], hd1 = hd_data->hd; hd1; hd1 = hd1->next) {
222 if(hd1->tag.remove) continue;
223 if(hd1->status.available == status_no) continue;
224 if(hd1->attached_to == u) break;
225 }
226 if(hd1) {
227 hd1->hotplug = hd->hotplug;
228 hd1->hotplug_slot = hd->hotplug_slot;
229 if(!hd1->extra_info) {
230 hd1->extra_info = hd->extra_info;
231 hd->extra_info = NULL;
232 }
233 hd->tag.remove = 1;
234 }
235 else {
236 hd->attached_to = p_sock[hd->slot];
237 add_sysfs_stuff(hd_data, hd);
238 }
239 p_sock[hd->slot] = 0;
240 }
241 }
242
243 remove_tagged_hd_entries(hd_data);
244 }
245}
246
247
248void add_sysfs_stuff(hd_data_t *hd_data, hd_t *hd)
249{
250 hd_t *hd_par;
251 char *s = NULL, *s1;
252 struct sysfs_device *sf_dev;
253
254 hd_par = hd_get_device_by_idx(hd_data, hd->attached_to);
255
256 if(!hd_par || !hd_par->sysfs_id || hd->sysfs_id) return;
257
258 str_printf(&s, 0, "/sys%s/%d.0", hd_par->sysfs_id, hd->slot);
259
260 sf_dev = sysfs_open_device_path(s);
261
262 if(sf_dev) {
263 hd->sysfs_id = new_str(hd_sysfs_id(s));
264 s1 = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1);
265 if(s1) add_str_list(&hd->drivers, s1);
266 }
267
268 sysfs_close_device(sf_dev);
269
270 s = free_mem(s);
271}
272