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