xref: /haiku/src/bin/pcmcia-cs/dump_cisreg.c (revision c90684742e7361651849be4116d0e5de3a817194)
1 /*======================================================================
2 
3     PCMCIA card configuration register dump
4 
5     dump_cisreg.c 1.31 2001/11/30 23:10:17
6 
7     The contents of this file are subject to the Mozilla Public
8     License Version 1.1 (the "License"); you may not use this file
9     except in compliance with the License. You may obtain a copy of
10     the License at http://www.mozilla.org/MPL/
11 
12     Software distributed under the License is distributed on an "AS
13     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14     implied. See the License for the specific language governing
15     rights and limitations under the License.
16 
17     The initial developer of the original code is David A. Hinds
18     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
19     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
20 
21     Alternatively, the contents of this file may be used under the
22     terms of the GNU General Public License version 2 (the "GPL"), in
23     which case the provisions of the GPL are applicable instead of the
24     above.  If you wish to allow the use of your version of this file
25     only under the terms of the GPL and not to allow others to use
26     your version of this file under the MPL, indicate your decision
27     by deleting the provisions above and replace them with the notice
28     and other provisions required by the GPL.  If you do not delete
29     the provisions above, a recipient may use your version of this
30     file under either the MPL or the GPL.
31 
32 ======================================================================*/
33 #if (defined(__BEOS__) || defined(__HAIKU__))
34 #include <OS.h>
35 #endif
36 #include <sys/types.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <sys/time.h>
44 #include <sys/ioctl.h>
45 #include <sys/stat.h>
46 
47 #include <pcmcia/cs_types.h>
48 #include <pcmcia/cs.h>
49 #include <pcmcia/cistpl.h>
50 #include <pcmcia/cisreg.h>
51 #include <pcmcia/ds.h>
52 
53 /*====================================================================*/
54 #if (!defined(__BEOS__) && !defined(__HAIKU__))
55 static int major = 0;
56 
57 static int lookup_dev(char *name)
58 {
59     FILE *f;
60     int n;
61     char s[32], t[32];
62 
63     f = fopen("/proc/devices", "r");
64     if (f == NULL)
65 	return -1;
66     while (fgets(s, 32, f) != NULL) {
67 	if (sscanf(s, "%d %s", &n, t) == 2)
68 	    if (strcmp(name, t) == 0)
69 		break;
70     }
71     fclose(f);
72     if (strcmp(name, t) == 0)
73 	return n;
74     else
75 	return -1;
76 }
77 #endif
78 
79 /*====================================================================*/
80 
81 static int open_sock(int sock)
82 {
83 #if (defined(__BEOS__) || defined(__HAIKU__))
84     char fn[B_OS_NAME_LENGTH];
85     sprintf(fn, "/dev/bus/pcmcia/sock/%d", sock);
86     return open(fn, O_RDONLY);
87 #else
88     static char *paths[] = {
89 	"/var/lib/pcmcia", "/var/run", "/dev", "/tmp", NULL
90     };
91     int fd;
92     char **p, fn[64];
93     dev_t dev = (major<<8) + sock;
94 
95     for (p = paths; *p; p++) {
96 	sprintf(fn, "%s/dc%d", *p, getpid());
97 	if (mknod(fn, (S_IFCHR|S_IREAD|S_IWRITE), dev) == 0) {
98 	    fd = open(fn, O_RDONLY);
99 	    unlink(fn);
100 	    if (fd >= 0)
101 		return fd;
102 	    if (errno == ENODEV) break;
103 	}
104     }
105     return -1;
106 #endif
107 } /* open_sock */
108 
109 /*====================================================================*/
110 
111 static int get_reg(int fd, int fn, off_t off)
112 {
113     ds_ioctl_arg_t arg;
114     int ret;
115 
116     arg.conf_reg.Function = fn;
117     arg.conf_reg.Action = CS_READ;
118     arg.conf_reg.Offset = off;
119     ret = ioctl(fd, DS_ACCESS_CONFIGURATION_REGISTER, &arg);
120     if (ret != 0) {
121 	printf("  read config register: %s\n\n", strerror(errno));
122 	return -1;
123     }
124     return arg.conf_reg.Value;
125 }
126 
127 static int dump_option(int fd, int fn, int mfc)
128 {
129     int v = get_reg(fd, fn, CISREG_COR);
130 
131     if (v == -1) return -1;
132     printf("  Configuration option register = %#2.2x\n", v);
133     printf("   ");
134     if (v & COR_LEVEL_REQ) printf(" [level_req]");
135     if (v & COR_SOFT_RESET) printf(" [soft_reset]");
136     if (mfc) {
137 	if (v & COR_FUNC_ENA) printf(" [func_ena]");
138 	if (v & COR_ADDR_DECODE) printf(" [addr_decode]");
139 	if (v & COR_IREQ_ENA) printf(" [ireq_ena]");
140 	printf(" [index = %#2.2x]\n", v & COR_MFC_CONFIG_MASK);
141     } else
142 	printf(" [index = %#2.2x]\n", v & COR_CONFIG_MASK);
143     return 0;
144 }
145 
146 static void dump_status(int fd, int fn)
147 {
148     int v = get_reg(fd, fn, CISREG_CCSR);
149 
150     printf("  Card configuration and status register = %#2.2x\n", v);
151     printf("   ");
152     if (v & CCSR_INTR_ACK) printf(" [intr_ack]");
153     if (v & CCSR_INTR_PENDING) printf(" [intr_pending]");
154     if (v & CCSR_POWER_DOWN) printf(" [power_down]");
155     if (v & CCSR_AUDIO_ENA) printf(" [audio]");
156     if (v & CCSR_IOIS8) printf(" [IOis8]");
157     if (v & CCSR_SIGCHG_ENA) printf(" [sigchg]");
158     if (v & CCSR_CHANGED) printf(" [changed]");
159     printf("\n");
160 }
161 
162 static void dump_pin(int fd, int fn)
163 {
164     int v = get_reg(fd, fn, CISREG_PRR);
165 
166     printf("  Pin replacement register = %#2.2x\n", v);
167     printf("   ");
168     if (v & PRR_WP_STATUS) printf(" [wp]");
169     if (v & PRR_READY_STATUS) printf(" [ready]");
170     if (v & PRR_BVD2_STATUS) printf(" [bvd2]");
171     if (v & PRR_BVD1_STATUS) printf(" [bvd1]");
172     if (v & PRR_WP_EVENT) printf(" [wp_event]");
173     if (v & PRR_READY_EVENT) printf(" [ready_event]");
174     if (v & PRR_BVD2_EVENT) printf(" [bvd2_event]");
175     if (v & PRR_BVD1_EVENT) printf(" [bvd1_event]");
176     printf("\n");
177 }
178 
179 static void dump_copy(int fd, int fn)
180 {
181     int v = get_reg(fd, fn, CISREG_SCR);
182 
183     printf("  Socket and copy register = %#2.2x\n", v);
184     printf("    [socket = %d] [copy = %d]\n",
185 	   v & SCR_SOCKET_NUM,
186 	   (v & SCR_COPY_NUM) >> 4);
187 }
188 
189 static void dump_ext_status(int fd, int fn)
190 {
191     int v = get_reg(fd, fn, CISREG_ESR);
192     printf("  Extended status register = %#2.2x\n", v);
193     printf("   ");
194     if (v & ESR_REQ_ATTN_ENA) printf(" [req_attn_ena]");
195     if (v & ESR_REQ_ATTN) printf(" [req_attn]");
196     printf("\n");
197 }
198 
199 /*====================================================================*/
200 
201 static void dump_all(int fd, int fn, int mfc, u_int mask)
202 {
203     int addr;
204     if (mask & PRESENT_OPTION) {
205 	if (dump_option(fd, fn, mfc) != 0)
206 	    return;
207     }
208     if (mask & PRESENT_STATUS)
209 	dump_status(fd, fn);
210     if (mask & PRESENT_PIN_REPLACE)
211 	dump_pin(fd, fn);
212     if (mask & PRESENT_COPY)
213 	dump_copy(fd, fn);
214     if (mask & PRESENT_EXT_STATUS)
215 	dump_ext_status(fd, fn);
216     if (mask & PRESENT_IOBASE_0) {
217 	addr = get_reg(fd, fn, CISREG_IOBASE_0);
218 	addr += get_reg(fd, fn, CISREG_IOBASE_1) << 8;
219 	printf("  IO base = 0x%04x\n", addr);
220     }
221     if (mask & PRESENT_IOSIZE)
222 	printf("  IO size = %d\n", get_reg(fd, fn, CISREG_IOSIZE));
223     if (mask == 0)
224 	printf("  no config registers\n\n");
225     else
226 	printf("\n");
227 }
228 
229 /*====================================================================*/
230 
231 #define MAX_SOCKS 8
232 
233 int main(int argc, char *argv[])
234 {
235     int i, j, nfn, fd, ret;
236     u_int mask;
237     ds_ioctl_arg_t arg;
238 
239 #if (!defined(__BEOS__) && !defined(__HAIKU__))
240     major = lookup_dev("pcmcia");
241     if (major < 0) {
242 	fprintf(stderr, "no pcmcia driver in /proc/devices\n");
243 	exit(EXIT_FAILURE);
244     }
245 #endif
246 
247     for (i = 0; i < MAX_SOCKS; i++) {
248 	fd = open_sock(i);
249 	if (fd < 0) break;
250 
251 	arg.tuple.TupleDataMax = sizeof(arg.tuple_parse.data);
252 	arg.tuple.Attributes = TUPLE_RETURN_COMMON;
253 	arg.tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
254 	arg.tuple.TupleOffset = 0;
255 	if (ioctl(fd, DS_GET_FIRST_TUPLE, &arg) == 0) {
256 	    ioctl(fd, DS_GET_TUPLE_DATA, &arg);
257 	    ioctl(fd, DS_PARSE_TUPLE, &arg);
258 	    nfn = arg.tuple_parse.parse.longlink_mfc.nfn;
259 	} else {
260 	    nfn = 1;
261 	    arg.tuple.DesiredTuple = CISTPL_DEVICE;
262 	    ret = ioctl(fd, DS_GET_FIRST_TUPLE, &arg);
263 	    if (ret != 0) {
264 		if (errno != ENODEV) perror("ioctl()");
265 		continue;
266 	    }
267 	}
268 
269 	arg.tuple.DesiredTuple = CISTPL_CONFIG;
270 
271 	for (j = 0; j < nfn; j++) {
272 	    printf("Socket %d function %d:\n", i, j);
273 	    if (ioctl(fd, DS_GET_NEXT_TUPLE, &arg) != 0) {
274 		printf("  no config tuple: %s\n\n", strerror(errno));
275 		continue;
276 	    }
277 	    ioctl(fd, DS_GET_TUPLE_DATA, &arg);
278 	    ioctl(fd, DS_PARSE_TUPLE, &arg);
279 	    printf("  Config register base = %#4.4x, mask = %#4.4x\n",
280 		   arg.tuple_parse.parse.config.base,
281 		   arg.tuple_parse.parse.config.rmask[0]);
282 	    mask = arg.tuple_parse.parse.config.rmask[0];
283 	    dump_all(fd, j, (nfn > 1), mask);
284 	}
285 
286     }
287     return 0;
288 }
289