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