1/*- 2 * Copyright (c) 2002-2003 3 * Hidetoshi Shimokawa. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * 16 * This product includes software developed by Hidetoshi Shimokawa. 17 * 18 * 4. Neither the name of the author nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34
| 1/*- 2 * Copyright (c) 2002-2003 3 * Hidetoshi Shimokawa. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * 16 * This product includes software developed by Hidetoshi Shimokawa. 17 * 18 * 4. Neither the name of the author nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34
|
| 35#ifdef __FreeBSD__
|
35#include <sys/cdefs.h>
| 36#include <sys/cdefs.h>
|
36__FBSDID("$FreeBSD: head/sys/dev/firewire/fwcrom.c 120660 2003-10-02 04:06:56Z simokawa $");
| 37__FBSDID("$FreeBSD: head/sys/dev/firewire/fwcrom.c 127468 2004-03-26 23:17:10Z simokawa $"); 38#endif
|
37 38#include <sys/param.h> 39#if defined(_KERNEL) || defined(TEST) 40#include <sys/queue.h> 41#endif 42#ifdef _KERNEL 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#else 46#include <netinet/in.h> 47#include <fcntl.h> 48#include <stdio.h> 49#include <err.h> 50#include <stdlib.h> 51#include <string.h> 52#endif
| 39 40#include <sys/param.h> 41#if defined(_KERNEL) || defined(TEST) 42#include <sys/queue.h> 43#endif 44#ifdef _KERNEL 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#else 48#include <netinet/in.h> 49#include <fcntl.h> 50#include <stdio.h> 51#include <err.h> 52#include <stdlib.h> 53#include <string.h> 54#endif
|
| 55 56#ifdef __DragonFly__ 57#include "firewire.h" 58#include "iec13213.h" 59#else
|
53#include <dev/firewire/firewire.h> 54#include <dev/firewire/iec13213.h>
| 60#include <dev/firewire/firewire.h> 61#include <dev/firewire/iec13213.h>
|
| 62#endif
|
55 56#define MAX_ROM (1024 - sizeof(u_int32_t) * 5) 57#define CROM_END(cc) ((vm_offset_t)(cc)->stack[0].dir + MAX_ROM - 1) 58 59void 60crom_init_context(struct crom_context *cc, u_int32_t *p) 61{ 62 struct csrhdr *hdr; 63 64 hdr = (struct csrhdr *)p;
| 63 64#define MAX_ROM (1024 - sizeof(u_int32_t) * 5) 65#define CROM_END(cc) ((vm_offset_t)(cc)->stack[0].dir + MAX_ROM - 1) 66 67void 68crom_init_context(struct crom_context *cc, u_int32_t *p) 69{ 70 struct csrhdr *hdr; 71 72 hdr = (struct csrhdr *)p;
|
65 if (hdr->info_len == 1) { 66 /* minimum ROM */
| 73 if (hdr->info_len <= 1) { 74 /* minimum or invalid ROM */
|
67 cc->depth = -1;
| 75 cc->depth = -1;
|
| 76 return;
|
68 } 69 p += 1 + hdr->info_len; 70 71 /* check size of root directory */ 72 if (((struct csrdirectory *)p)->crc_len == 0) { 73 cc->depth = -1; 74 return; 75 } 76 cc->depth = 0; 77 cc->stack[0].dir = (struct csrdirectory *)p; 78 cc->stack[0].index = 0; 79} 80 81struct csrreg * 82crom_get(struct crom_context *cc) 83{ 84 struct crom_ptr *ptr; 85 86 ptr = &cc->stack[cc->depth]; 87 return (&ptr->dir->entry[ptr->index]); 88} 89 90void 91crom_next(struct crom_context *cc) 92{ 93 struct crom_ptr *ptr; 94 struct csrreg *reg; 95 96 if (cc->depth < 0) 97 return; 98 reg = crom_get(cc); 99 if ((reg->key & CSRTYPE_MASK) == CSRTYPE_D) { 100 if (cc->depth >= CROM_MAX_DEPTH) { 101 printf("crom_next: too deep\n"); 102 goto again; 103 } 104 cc->depth ++; 105 106 ptr = &cc->stack[cc->depth]; 107 ptr->dir = (struct csrdirectory *) (reg + reg->val); 108 ptr->index = 0; 109 goto check; 110 } 111again: 112 ptr = &cc->stack[cc->depth]; 113 ptr->index ++; 114check: 115 if (ptr->index < ptr->dir->crc_len && 116 (vm_offset_t)crom_get(cc) <= CROM_END(cc)) 117 return; 118 119 if (ptr->index < ptr->dir->crc_len) 120 printf("crom_next: bound check failed\n"); 121 122 if (cc->depth > 0) { 123 cc->depth--; 124 goto again; 125 } 126 /* no more data */ 127 cc->depth = -1; 128} 129 130 131struct csrreg * 132crom_search_key(struct crom_context *cc, u_int8_t key) 133{ 134 struct csrreg *reg; 135 136 while(cc->depth >= 0) { 137 reg = crom_get(cc); 138 if (reg->key == key) 139 return reg; 140 crom_next(cc); 141 } 142 return NULL; 143} 144 145int 146crom_has_specver(u_int32_t *p, u_int32_t spec, u_int32_t ver) 147{ 148 struct csrreg *reg; 149 struct crom_context c, *cc; 150 int state = 0; 151 152 cc = &c; 153 crom_init_context(cc, p); 154 while(cc->depth >= 0) { 155 reg = crom_get(cc); 156 if (state == 0) { 157 if (reg->key == CSRKEY_SPEC && reg->val == spec) 158 state = 1; 159 else 160 state = 0; 161 } else { 162 if (reg->key == CSRKEY_VER && reg->val == ver) 163 return 1; 164 else 165 state = 0; 166 } 167 crom_next(cc); 168 } 169 return 0; 170} 171 172void 173crom_parse_text(struct crom_context *cc, char *buf, int len) 174{ 175 struct csrreg *reg; 176 struct csrtext *textleaf; 177 u_int32_t *bp; 178 int i, qlen; 179 static char *nullstr = "(null)"; 180 181 if (cc->depth < 0) 182 return; 183 184 reg = crom_get(cc); 185 if (reg->key != CROM_TEXTLEAF || 186 (vm_offset_t)(reg + reg->val) > CROM_END(cc)) { 187 strncpy(buf, nullstr, len); 188 return; 189 } 190 textleaf = (struct csrtext *)(reg + reg->val); 191 192 if ((vm_offset_t)textleaf + textleaf->crc_len > CROM_END(cc)) { 193 strncpy(buf, nullstr, len); 194 return; 195 } 196 197 /* XXX should check spec and type */ 198 199 bp = (u_int32_t *)&buf[0]; 200 qlen = textleaf->crc_len - 2; 201 if (len < qlen * 4) 202 qlen = len/4; 203 for (i = 0; i < qlen; i ++) 204 *bp++ = ntohl(textleaf->text[i]); 205 /* make sure to terminate the string */ 206 if (len <= qlen * 4) 207 buf[len - 1] = 0; 208 else 209 buf[qlen * 4] = 0; 210} 211 212u_int16_t 213crom_crc(u_int32_t *ptr, int len) 214{ 215 int i, shift; 216 u_int32_t data, sum, crc = 0; 217 218 for (i = 0; i < len; i++) { 219 data = ptr[i]; 220 for (shift = 28; shift >= 0; shift -= 4) { 221 sum = ((crc >> 12) ^ (data >> shift)) & 0xf; 222 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; 223 } 224 crc &= 0xffff; 225 } 226 return((u_int16_t) crc); 227} 228 229#ifndef _KERNEL 230static void 231crom_desc_specver(u_int32_t spec, u_int32_t ver, char *buf, int len) 232{ 233 char *s = NULL; 234 235 if (spec == CSRVAL_ANSIT10 || spec == 0) { 236 switch (ver) { 237 case CSRVAL_T10SBP2: 238 s = "SBP-2"; 239 break; 240 default: 241 if (spec != 0) 242 s = "unknown ANSIT10"; 243 } 244 } 245 if (spec == CSRVAL_1394TA || spec == 0) { 246 switch (ver) { 247 case CSR_PROTAVC: 248 s = "AV/C"; 249 break; 250 case CSR_PROTCAL: 251 s = "CAL"; 252 break; 253 case CSR_PROTEHS: 254 s = "EHS"; 255 break; 256 case CSR_PROTHAVI: 257 s = "HAVi"; 258 break; 259 case CSR_PROTCAM104: 260 s = "1394 Cam 1.04"; 261 break; 262 case CSR_PROTCAM120: 263 s = "1394 Cam 1.20"; 264 break; 265 case CSR_PROTCAM130: 266 s = "1394 Cam 1.30"; 267 break; 268 case CSR_PROTDPP: 269 s = "1394 Direct print"; 270 break; 271 case CSR_PROTIICP: 272 s = "Industrial & Instrument"; 273 break; 274 default: 275 if (spec != 0) 276 s = "unknown 1394TA"; 277 } 278 } 279 if (s != NULL) 280 snprintf(buf, len, "%s", s); 281} 282 283char * 284crom_desc(struct crom_context *cc, char *buf, int len) 285{ 286 struct csrreg *reg; 287 struct csrdirectory *dir; 288 char *desc, st; 289 u_int16_t crc; 290 291 reg = crom_get(cc); 292 switch (reg->key & CSRTYPE_MASK) { 293 case CSRTYPE_I: 294#if 0 295 len -= snprintf(buf, len, "%d", reg->val); 296 buf += strlen(buf); 297#else 298 *buf = '\0'; 299#endif 300 break; 301 case CSRTYPE_C: 302 len -= snprintf(buf, len, "offset=0x%04x(%d)", 303 reg->val, reg->val); 304 buf += strlen(buf); 305 break; 306 case CSRTYPE_L: 307 /* XXX fall through */ 308 case CSRTYPE_D: 309 dir = (struct csrdirectory *) (reg + reg->val); 310 crc = crom_crc((u_int32_t *)&dir->entry[0], dir->crc_len); 311 len -= snprintf(buf, len, "len=%d crc=0x%04x(%s) ", 312 dir->crc_len, dir->crc, 313 (crc == dir->crc) ? "OK" : "NG"); 314 buf += strlen(buf); 315 } 316 switch (reg->key) { 317 case 0x03: 318 desc = "module_vendor_ID"; 319 break; 320 case 0x04: 321 desc = "hardware_version"; 322 break; 323 case 0x0c: 324 desc = "node_capabilities"; 325 break; 326 case 0x12: 327 desc = "unit_spec_ID"; 328 break; 329 case 0x13: 330 desc = "unit_sw_version"; 331 crom_desc_specver(0, reg->val, buf, len); 332 break; 333 case 0x14: 334 desc = "logical_unit_number"; 335 break; 336 case 0x17: 337 desc = "model_ID"; 338 break; 339 case 0x38: 340 desc = "command_set_spec_ID"; 341 break; 342 case 0x39: 343 desc = "command_set"; 344 break; 345 case 0x3a: 346 desc = "unit_characteristics"; 347 break; 348 case 0x3b: 349 desc = "command_set_revision"; 350 break; 351 case 0x3c: 352 desc = "firmware_revision"; 353 break; 354 case 0x3d: 355 desc = "reconnect_timeout"; 356 break; 357 case 0x54: 358 desc = "management_agent"; 359 break; 360 case 0x81: 361 desc = "text_leaf"; 362 crom_parse_text(cc, buf + strlen(buf), len); 363 break; 364 case 0xd1: 365 desc = "unit_directory"; 366 break; 367 case 0xd4: 368 desc = "logical_unit_directory"; 369 break; 370 default: 371 desc = "unknown"; 372 } 373 return desc; 374} 375#endif 376 377#if defined(_KERNEL) || defined(TEST) 378 379int 380crom_add_quad(struct crom_chunk *chunk, u_int32_t entry) 381{ 382 int index; 383 384 index = chunk->data.crc_len; 385 if (index >= CROM_MAX_CHUNK_LEN - 1) { 386 printf("too large chunk %d\n", index); 387 return(-1); 388 } 389 chunk->data.buf[index] = entry; 390 chunk->data.crc_len++; 391 return(index); 392} 393 394int 395crom_add_entry(struct crom_chunk *chunk, int key, int val) 396{ 397 struct csrreg *reg; 398 u_int32_t i; 399 400 reg = (struct csrreg *)&i; 401 reg->key = key; 402 reg->val = val; 403 return(crom_add_quad(chunk, (u_int32_t) i)); 404} 405 406int 407crom_add_chunk(struct crom_src *src, struct crom_chunk *parent, 408 struct crom_chunk *child, int key) 409{ 410 int index; 411 412 if (parent == NULL) { 413 STAILQ_INSERT_TAIL(&src->chunk_list, child, link); 414 return(0); 415 } 416 417 index = crom_add_entry(parent, key, 0); 418 if (index < 0) { 419 return(-1); 420 } 421 child->ref_chunk = parent; 422 child->ref_index = index; 423 STAILQ_INSERT_TAIL(&src->chunk_list, child, link); 424 return(index); 425} 426 427#define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext)) 428int 429crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent, 430 struct crom_chunk *chunk, char *buf) 431{ 432 struct csrtext *tl; 433 u_int32_t *p; 434 int len, i; 435 char t[MAX_TEXT]; 436 437 len = strlen(buf); 438 if (len > MAX_TEXT) {
| 77 } 78 p += 1 + hdr->info_len; 79 80 /* check size of root directory */ 81 if (((struct csrdirectory *)p)->crc_len == 0) { 82 cc->depth = -1; 83 return; 84 } 85 cc->depth = 0; 86 cc->stack[0].dir = (struct csrdirectory *)p; 87 cc->stack[0].index = 0; 88} 89 90struct csrreg * 91crom_get(struct crom_context *cc) 92{ 93 struct crom_ptr *ptr; 94 95 ptr = &cc->stack[cc->depth]; 96 return (&ptr->dir->entry[ptr->index]); 97} 98 99void 100crom_next(struct crom_context *cc) 101{ 102 struct crom_ptr *ptr; 103 struct csrreg *reg; 104 105 if (cc->depth < 0) 106 return; 107 reg = crom_get(cc); 108 if ((reg->key & CSRTYPE_MASK) == CSRTYPE_D) { 109 if (cc->depth >= CROM_MAX_DEPTH) { 110 printf("crom_next: too deep\n"); 111 goto again; 112 } 113 cc->depth ++; 114 115 ptr = &cc->stack[cc->depth]; 116 ptr->dir = (struct csrdirectory *) (reg + reg->val); 117 ptr->index = 0; 118 goto check; 119 } 120again: 121 ptr = &cc->stack[cc->depth]; 122 ptr->index ++; 123check: 124 if (ptr->index < ptr->dir->crc_len && 125 (vm_offset_t)crom_get(cc) <= CROM_END(cc)) 126 return; 127 128 if (ptr->index < ptr->dir->crc_len) 129 printf("crom_next: bound check failed\n"); 130 131 if (cc->depth > 0) { 132 cc->depth--; 133 goto again; 134 } 135 /* no more data */ 136 cc->depth = -1; 137} 138 139 140struct csrreg * 141crom_search_key(struct crom_context *cc, u_int8_t key) 142{ 143 struct csrreg *reg; 144 145 while(cc->depth >= 0) { 146 reg = crom_get(cc); 147 if (reg->key == key) 148 return reg; 149 crom_next(cc); 150 } 151 return NULL; 152} 153 154int 155crom_has_specver(u_int32_t *p, u_int32_t spec, u_int32_t ver) 156{ 157 struct csrreg *reg; 158 struct crom_context c, *cc; 159 int state = 0; 160 161 cc = &c; 162 crom_init_context(cc, p); 163 while(cc->depth >= 0) { 164 reg = crom_get(cc); 165 if (state == 0) { 166 if (reg->key == CSRKEY_SPEC && reg->val == spec) 167 state = 1; 168 else 169 state = 0; 170 } else { 171 if (reg->key == CSRKEY_VER && reg->val == ver) 172 return 1; 173 else 174 state = 0; 175 } 176 crom_next(cc); 177 } 178 return 0; 179} 180 181void 182crom_parse_text(struct crom_context *cc, char *buf, int len) 183{ 184 struct csrreg *reg; 185 struct csrtext *textleaf; 186 u_int32_t *bp; 187 int i, qlen; 188 static char *nullstr = "(null)"; 189 190 if (cc->depth < 0) 191 return; 192 193 reg = crom_get(cc); 194 if (reg->key != CROM_TEXTLEAF || 195 (vm_offset_t)(reg + reg->val) > CROM_END(cc)) { 196 strncpy(buf, nullstr, len); 197 return; 198 } 199 textleaf = (struct csrtext *)(reg + reg->val); 200 201 if ((vm_offset_t)textleaf + textleaf->crc_len > CROM_END(cc)) { 202 strncpy(buf, nullstr, len); 203 return; 204 } 205 206 /* XXX should check spec and type */ 207 208 bp = (u_int32_t *)&buf[0]; 209 qlen = textleaf->crc_len - 2; 210 if (len < qlen * 4) 211 qlen = len/4; 212 for (i = 0; i < qlen; i ++) 213 *bp++ = ntohl(textleaf->text[i]); 214 /* make sure to terminate the string */ 215 if (len <= qlen * 4) 216 buf[len - 1] = 0; 217 else 218 buf[qlen * 4] = 0; 219} 220 221u_int16_t 222crom_crc(u_int32_t *ptr, int len) 223{ 224 int i, shift; 225 u_int32_t data, sum, crc = 0; 226 227 for (i = 0; i < len; i++) { 228 data = ptr[i]; 229 for (shift = 28; shift >= 0; shift -= 4) { 230 sum = ((crc >> 12) ^ (data >> shift)) & 0xf; 231 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; 232 } 233 crc &= 0xffff; 234 } 235 return((u_int16_t) crc); 236} 237 238#ifndef _KERNEL 239static void 240crom_desc_specver(u_int32_t spec, u_int32_t ver, char *buf, int len) 241{ 242 char *s = NULL; 243 244 if (spec == CSRVAL_ANSIT10 || spec == 0) { 245 switch (ver) { 246 case CSRVAL_T10SBP2: 247 s = "SBP-2"; 248 break; 249 default: 250 if (spec != 0) 251 s = "unknown ANSIT10"; 252 } 253 } 254 if (spec == CSRVAL_1394TA || spec == 0) { 255 switch (ver) { 256 case CSR_PROTAVC: 257 s = "AV/C"; 258 break; 259 case CSR_PROTCAL: 260 s = "CAL"; 261 break; 262 case CSR_PROTEHS: 263 s = "EHS"; 264 break; 265 case CSR_PROTHAVI: 266 s = "HAVi"; 267 break; 268 case CSR_PROTCAM104: 269 s = "1394 Cam 1.04"; 270 break; 271 case CSR_PROTCAM120: 272 s = "1394 Cam 1.20"; 273 break; 274 case CSR_PROTCAM130: 275 s = "1394 Cam 1.30"; 276 break; 277 case CSR_PROTDPP: 278 s = "1394 Direct print"; 279 break; 280 case CSR_PROTIICP: 281 s = "Industrial & Instrument"; 282 break; 283 default: 284 if (spec != 0) 285 s = "unknown 1394TA"; 286 } 287 } 288 if (s != NULL) 289 snprintf(buf, len, "%s", s); 290} 291 292char * 293crom_desc(struct crom_context *cc, char *buf, int len) 294{ 295 struct csrreg *reg; 296 struct csrdirectory *dir; 297 char *desc, st; 298 u_int16_t crc; 299 300 reg = crom_get(cc); 301 switch (reg->key & CSRTYPE_MASK) { 302 case CSRTYPE_I: 303#if 0 304 len -= snprintf(buf, len, "%d", reg->val); 305 buf += strlen(buf); 306#else 307 *buf = '\0'; 308#endif 309 break; 310 case CSRTYPE_C: 311 len -= snprintf(buf, len, "offset=0x%04x(%d)", 312 reg->val, reg->val); 313 buf += strlen(buf); 314 break; 315 case CSRTYPE_L: 316 /* XXX fall through */ 317 case CSRTYPE_D: 318 dir = (struct csrdirectory *) (reg + reg->val); 319 crc = crom_crc((u_int32_t *)&dir->entry[0], dir->crc_len); 320 len -= snprintf(buf, len, "len=%d crc=0x%04x(%s) ", 321 dir->crc_len, dir->crc, 322 (crc == dir->crc) ? "OK" : "NG"); 323 buf += strlen(buf); 324 } 325 switch (reg->key) { 326 case 0x03: 327 desc = "module_vendor_ID"; 328 break; 329 case 0x04: 330 desc = "hardware_version"; 331 break; 332 case 0x0c: 333 desc = "node_capabilities"; 334 break; 335 case 0x12: 336 desc = "unit_spec_ID"; 337 break; 338 case 0x13: 339 desc = "unit_sw_version"; 340 crom_desc_specver(0, reg->val, buf, len); 341 break; 342 case 0x14: 343 desc = "logical_unit_number"; 344 break; 345 case 0x17: 346 desc = "model_ID"; 347 break; 348 case 0x38: 349 desc = "command_set_spec_ID"; 350 break; 351 case 0x39: 352 desc = "command_set"; 353 break; 354 case 0x3a: 355 desc = "unit_characteristics"; 356 break; 357 case 0x3b: 358 desc = "command_set_revision"; 359 break; 360 case 0x3c: 361 desc = "firmware_revision"; 362 break; 363 case 0x3d: 364 desc = "reconnect_timeout"; 365 break; 366 case 0x54: 367 desc = "management_agent"; 368 break; 369 case 0x81: 370 desc = "text_leaf"; 371 crom_parse_text(cc, buf + strlen(buf), len); 372 break; 373 case 0xd1: 374 desc = "unit_directory"; 375 break; 376 case 0xd4: 377 desc = "logical_unit_directory"; 378 break; 379 default: 380 desc = "unknown"; 381 } 382 return desc; 383} 384#endif 385 386#if defined(_KERNEL) || defined(TEST) 387 388int 389crom_add_quad(struct crom_chunk *chunk, u_int32_t entry) 390{ 391 int index; 392 393 index = chunk->data.crc_len; 394 if (index >= CROM_MAX_CHUNK_LEN - 1) { 395 printf("too large chunk %d\n", index); 396 return(-1); 397 } 398 chunk->data.buf[index] = entry; 399 chunk->data.crc_len++; 400 return(index); 401} 402 403int 404crom_add_entry(struct crom_chunk *chunk, int key, int val) 405{ 406 struct csrreg *reg; 407 u_int32_t i; 408 409 reg = (struct csrreg *)&i; 410 reg->key = key; 411 reg->val = val; 412 return(crom_add_quad(chunk, (u_int32_t) i)); 413} 414 415int 416crom_add_chunk(struct crom_src *src, struct crom_chunk *parent, 417 struct crom_chunk *child, int key) 418{ 419 int index; 420 421 if (parent == NULL) { 422 STAILQ_INSERT_TAIL(&src->chunk_list, child, link); 423 return(0); 424 } 425 426 index = crom_add_entry(parent, key, 0); 427 if (index < 0) { 428 return(-1); 429 } 430 child->ref_chunk = parent; 431 child->ref_index = index; 432 STAILQ_INSERT_TAIL(&src->chunk_list, child, link); 433 return(index); 434} 435 436#define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext)) 437int 438crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent, 439 struct crom_chunk *chunk, char *buf) 440{ 441 struct csrtext *tl; 442 u_int32_t *p; 443 int len, i; 444 char t[MAX_TEXT]; 445 446 len = strlen(buf); 447 if (len > MAX_TEXT) {
|
439#if __FreeBSD_version < 500000
| 448#if defined(__DragonFly__) || __FreeBSD_version < 500000
|
440 printf("text(%d) trancated to %d.\n", len, MAX_TEXT); 441#else 442 printf("text(%d) trancated to %td.\n", len, MAX_TEXT); 443#endif 444 len = MAX_TEXT; 445 } 446 447 tl = (struct csrtext *) &chunk->data; 448 tl->crc_len = howmany(sizeof(struct csrtext) + len, sizeof(u_int32_t)); 449 tl->spec_id = 0; 450 tl->spec_type = 0; 451 tl->lang_id = 0; 452 bzero(&t[0], roundup2(len, sizeof(u_int32_t))); 453 bcopy(buf, &t[0], len); 454 p = (u_int32_t *)&t[0]; 455 for (i = 0; i < howmany(len, sizeof(u_int32_t)); i ++) 456 tl->text[i] = ntohl(*p++); 457 return (crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF)); 458} 459 460static int 461crom_copy(u_int32_t *src, u_int32_t *dst, int *offset, int len, int maxlen) 462{ 463 if (*offset + len > maxlen) { 464 printf("Config. ROM is too large for the buffer\n"); 465 return(-1); 466 } 467 bcopy(src, (char *)(dst + *offset), len * sizeof(u_int32_t)); 468 *offset += len; 469 return(0); 470} 471 472int 473crom_load(struct crom_src *src, u_int32_t *buf, int maxlen) 474{ 475 struct crom_chunk *chunk, *parent; 476 struct csrhdr *hdr; 477#ifdef _KERNEL 478 u_int32_t *ptr; 479 int i; 480#endif 481 int count, offset; 482 int len; 483 484 offset = 0; 485 /* Determine offset */ 486 STAILQ_FOREACH(chunk, &src->chunk_list, link) { 487 chunk->offset = offset; 488 /* Assume the offset of the parent is already known */ 489 parent = chunk->ref_chunk; 490 if (parent != NULL) { 491 struct csrreg *reg; 492 reg = (struct csrreg *) 493 &parent->data.buf[chunk->ref_index]; 494 reg->val = offset - 495 (parent->offset + 1 + chunk->ref_index); 496 } 497 offset += 1 + chunk->data.crc_len; 498 } 499 500 /* Calculate CRC and dump to the buffer */ 501 len = 1 + src->hdr.info_len; 502 count = 0; 503 if (crom_copy((u_int32_t *)&src->hdr, buf, &count, len, maxlen) < 0) 504 return(-1); 505 STAILQ_FOREACH(chunk, &src->chunk_list, link) { 506 chunk->data.crc = 507 crom_crc(&chunk->data.buf[0], chunk->data.crc_len); 508 509 len = 1 + chunk->data.crc_len; 510 if (crom_copy((u_int32_t *)&chunk->data, buf, 511 &count, len, maxlen) < 0) 512 return(-1); 513 } 514 hdr = (struct csrhdr *)buf; 515 hdr->crc_len = count - 1; 516 hdr->crc = crom_crc(&buf[1], hdr->crc_len); 517 518#ifdef _KERNEL 519 /* byte swap */ 520 ptr = buf; 521 for (i = 0; i < count; i ++) { 522 *ptr = htonl(*ptr); 523 ptr++; 524 } 525#endif 526 527 return(count); 528} 529#endif 530 531#ifdef TEST 532int 533main () { 534 struct crom_src src; 535 struct crom_chunk root,unit1,unit2,unit3; 536 struct crom_chunk text1,text2,text3,text4,text5,text6,text7; 537 u_int32_t buf[256], *p; 538 int i; 539 540 bzero(&src, sizeof(src)); 541 bzero(&root, sizeof(root)); 542 bzero(&unit1, sizeof(unit1)); 543 bzero(&unit2, sizeof(unit2)); 544 bzero(&unit3, sizeof(unit3)); 545 bzero(&text1, sizeof(text1)); 546 bzero(&text2, sizeof(text2)); 547 bzero(&text3, sizeof(text3)); 548 bzero(&text3, sizeof(text4)); 549 bzero(&text3, sizeof(text5)); 550 bzero(&text3, sizeof(text6)); 551 bzero(&text3, sizeof(text7)); 552 bzero(buf, sizeof(buf)); 553 554 /* BUS info sample */ 555 src.hdr.info_len = 4; 556 src.businfo.bus_name = CSR_BUS_NAME_IEEE1394; 557 src.businfo.eui64.hi = 0x11223344; 558 src.businfo.eui64.lo = 0x55667788; 559 src.businfo.link_spd = FWSPD_S400; 560 src.businfo.generation = 0; 561 src.businfo.max_rom = MAXROM_4; 562 src.businfo.max_rec = 10; 563 src.businfo.cyc_clk_acc = 100; 564 src.businfo.pmc = 0; 565 src.businfo.bmc = 1; 566 src.businfo.isc = 1; 567 src.businfo.cmc = 1; 568 src.businfo.irmc = 1; 569 STAILQ_INIT(&src.chunk_list); 570 571 /* Root directory */ 572 crom_add_chunk(&src, NULL, &root, 0); 573 crom_add_entry(&root, CSRKEY_NCAP, 0x123456); 574 /* private company_id */ 575 crom_add_entry(&root, CSRKEY_VENDOR, 0xacde48); 576
| 449 printf("text(%d) trancated to %d.\n", len, MAX_TEXT); 450#else 451 printf("text(%d) trancated to %td.\n", len, MAX_TEXT); 452#endif 453 len = MAX_TEXT; 454 } 455 456 tl = (struct csrtext *) &chunk->data; 457 tl->crc_len = howmany(sizeof(struct csrtext) + len, sizeof(u_int32_t)); 458 tl->spec_id = 0; 459 tl->spec_type = 0; 460 tl->lang_id = 0; 461 bzero(&t[0], roundup2(len, sizeof(u_int32_t))); 462 bcopy(buf, &t[0], len); 463 p = (u_int32_t *)&t[0]; 464 for (i = 0; i < howmany(len, sizeof(u_int32_t)); i ++) 465 tl->text[i] = ntohl(*p++); 466 return (crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF)); 467} 468 469static int 470crom_copy(u_int32_t *src, u_int32_t *dst, int *offset, int len, int maxlen) 471{ 472 if (*offset + len > maxlen) { 473 printf("Config. ROM is too large for the buffer\n"); 474 return(-1); 475 } 476 bcopy(src, (char *)(dst + *offset), len * sizeof(u_int32_t)); 477 *offset += len; 478 return(0); 479} 480 481int 482crom_load(struct crom_src *src, u_int32_t *buf, int maxlen) 483{ 484 struct crom_chunk *chunk, *parent; 485 struct csrhdr *hdr; 486#ifdef _KERNEL 487 u_int32_t *ptr; 488 int i; 489#endif 490 int count, offset; 491 int len; 492 493 offset = 0; 494 /* Determine offset */ 495 STAILQ_FOREACH(chunk, &src->chunk_list, link) { 496 chunk->offset = offset; 497 /* Assume the offset of the parent is already known */ 498 parent = chunk->ref_chunk; 499 if (parent != NULL) { 500 struct csrreg *reg; 501 reg = (struct csrreg *) 502 &parent->data.buf[chunk->ref_index]; 503 reg->val = offset - 504 (parent->offset + 1 + chunk->ref_index); 505 } 506 offset += 1 + chunk->data.crc_len; 507 } 508 509 /* Calculate CRC and dump to the buffer */ 510 len = 1 + src->hdr.info_len; 511 count = 0; 512 if (crom_copy((u_int32_t *)&src->hdr, buf, &count, len, maxlen) < 0) 513 return(-1); 514 STAILQ_FOREACH(chunk, &src->chunk_list, link) { 515 chunk->data.crc = 516 crom_crc(&chunk->data.buf[0], chunk->data.crc_len); 517 518 len = 1 + chunk->data.crc_len; 519 if (crom_copy((u_int32_t *)&chunk->data, buf, 520 &count, len, maxlen) < 0) 521 return(-1); 522 } 523 hdr = (struct csrhdr *)buf; 524 hdr->crc_len = count - 1; 525 hdr->crc = crom_crc(&buf[1], hdr->crc_len); 526 527#ifdef _KERNEL 528 /* byte swap */ 529 ptr = buf; 530 for (i = 0; i < count; i ++) { 531 *ptr = htonl(*ptr); 532 ptr++; 533 } 534#endif 535 536 return(count); 537} 538#endif 539 540#ifdef TEST 541int 542main () { 543 struct crom_src src; 544 struct crom_chunk root,unit1,unit2,unit3; 545 struct crom_chunk text1,text2,text3,text4,text5,text6,text7; 546 u_int32_t buf[256], *p; 547 int i; 548 549 bzero(&src, sizeof(src)); 550 bzero(&root, sizeof(root)); 551 bzero(&unit1, sizeof(unit1)); 552 bzero(&unit2, sizeof(unit2)); 553 bzero(&unit3, sizeof(unit3)); 554 bzero(&text1, sizeof(text1)); 555 bzero(&text2, sizeof(text2)); 556 bzero(&text3, sizeof(text3)); 557 bzero(&text3, sizeof(text4)); 558 bzero(&text3, sizeof(text5)); 559 bzero(&text3, sizeof(text6)); 560 bzero(&text3, sizeof(text7)); 561 bzero(buf, sizeof(buf)); 562 563 /* BUS info sample */ 564 src.hdr.info_len = 4; 565 src.businfo.bus_name = CSR_BUS_NAME_IEEE1394; 566 src.businfo.eui64.hi = 0x11223344; 567 src.businfo.eui64.lo = 0x55667788; 568 src.businfo.link_spd = FWSPD_S400; 569 src.businfo.generation = 0; 570 src.businfo.max_rom = MAXROM_4; 571 src.businfo.max_rec = 10; 572 src.businfo.cyc_clk_acc = 100; 573 src.businfo.pmc = 0; 574 src.businfo.bmc = 1; 575 src.businfo.isc = 1; 576 src.businfo.cmc = 1; 577 src.businfo.irmc = 1; 578 STAILQ_INIT(&src.chunk_list); 579 580 /* Root directory */ 581 crom_add_chunk(&src, NULL, &root, 0); 582 crom_add_entry(&root, CSRKEY_NCAP, 0x123456); 583 /* private company_id */ 584 crom_add_entry(&root, CSRKEY_VENDOR, 0xacde48); 585
|
| 586#ifdef __DragonFly__ 587 crom_add_simple_text(&src, &root, &text1, "DragonFly"); 588 crom_add_entry(&root, CSRKEY_HW, __DragonFly_cc_version); 589 crom_add_simple_text(&src, &root, &text2, "DragonFly-1"); 590#else
|
577 crom_add_simple_text(&src, &root, &text1, "FreeBSD"); 578 crom_add_entry(&root, CSRKEY_HW, __FreeBSD_version); 579 crom_add_simple_text(&src, &root, &text2, "FreeBSD-5");
| 591 crom_add_simple_text(&src, &root, &text1, "FreeBSD"); 592 crom_add_entry(&root, CSRKEY_HW, __FreeBSD_version); 593 crom_add_simple_text(&src, &root, &text2, "FreeBSD-5");
|
| 594#endif
|
580 581 /* SBP unit directory */ 582 crom_add_chunk(&src, &root, &unit1, CROM_UDIR); 583 crom_add_entry(&unit1, CSRKEY_SPEC, CSRVAL_ANSIT10); 584 crom_add_entry(&unit1, CSRKEY_VER, CSRVAL_T10SBP2); 585 crom_add_entry(&unit1, CSRKEY_COM_SPEC, CSRVAL_ANSIT10); 586 crom_add_entry(&unit1, CSRKEY_COM_SET, CSRVAL_SCSI); 587 /* management_agent */ 588 crom_add_entry(&unit1, CROM_MGM, 0x1000); 589 crom_add_entry(&unit1, CSRKEY_UNIT_CH, (10<<8) | 8); 590 /* Device type and LUN */ 591 crom_add_entry(&unit1, CROM_LUN, 0); 592 crom_add_entry(&unit1, CSRKEY_MODEL, 1); 593 crom_add_simple_text(&src, &unit1, &text3, "scsi_target"); 594 595 /* RFC2734 IPv4 over IEEE1394 */ 596 crom_add_chunk(&src, &root, &unit2, CROM_UDIR); 597 crom_add_entry(&unit2, CSRKEY_SPEC, CSRVAL_IETF); 598 crom_add_simple_text(&src, &unit2, &text4, "IANA"); 599 crom_add_entry(&unit2, CSRKEY_VER, 1); 600 crom_add_simple_text(&src, &unit2, &text5, "IPv4"); 601 602 /* RFC3146 IPv6 over IEEE1394 */ 603 crom_add_chunk(&src, &root, &unit3, CROM_UDIR); 604 crom_add_entry(&unit3, CSRKEY_SPEC, CSRVAL_IETF); 605 crom_add_simple_text(&src, &unit3, &text6, "IANA"); 606 crom_add_entry(&unit3, CSRKEY_VER, 2); 607 crom_add_simple_text(&src, &unit3, &text7, "IPv6"); 608 609 crom_load(&src, buf, 256); 610 p = buf; 611#define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" 612 for (i = 0; i < 256/8; i ++) { 613 printf(DUMP_FORMAT, 614 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); 615 p += 8; 616 } 617 return(0); 618} 619#endif
| 595 596 /* SBP unit directory */ 597 crom_add_chunk(&src, &root, &unit1, CROM_UDIR); 598 crom_add_entry(&unit1, CSRKEY_SPEC, CSRVAL_ANSIT10); 599 crom_add_entry(&unit1, CSRKEY_VER, CSRVAL_T10SBP2); 600 crom_add_entry(&unit1, CSRKEY_COM_SPEC, CSRVAL_ANSIT10); 601 crom_add_entry(&unit1, CSRKEY_COM_SET, CSRVAL_SCSI); 602 /* management_agent */ 603 crom_add_entry(&unit1, CROM_MGM, 0x1000); 604 crom_add_entry(&unit1, CSRKEY_UNIT_CH, (10<<8) | 8); 605 /* Device type and LUN */ 606 crom_add_entry(&unit1, CROM_LUN, 0); 607 crom_add_entry(&unit1, CSRKEY_MODEL, 1); 608 crom_add_simple_text(&src, &unit1, &text3, "scsi_target"); 609 610 /* RFC2734 IPv4 over IEEE1394 */ 611 crom_add_chunk(&src, &root, &unit2, CROM_UDIR); 612 crom_add_entry(&unit2, CSRKEY_SPEC, CSRVAL_IETF); 613 crom_add_simple_text(&src, &unit2, &text4, "IANA"); 614 crom_add_entry(&unit2, CSRKEY_VER, 1); 615 crom_add_simple_text(&src, &unit2, &text5, "IPv4"); 616 617 /* RFC3146 IPv6 over IEEE1394 */ 618 crom_add_chunk(&src, &root, &unit3, CROM_UDIR); 619 crom_add_entry(&unit3, CSRKEY_SPEC, CSRVAL_IETF); 620 crom_add_simple_text(&src, &unit3, &text6, "IANA"); 621 crom_add_entry(&unit3, CSRKEY_VER, 2); 622 crom_add_simple_text(&src, &unit3, &text7, "IPv6"); 623 624 crom_load(&src, buf, 256); 625 p = buf; 626#define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" 627 for (i = 0; i < 256/8; i ++) { 628 printf(DUMP_FORMAT, 629 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); 630 p += 8; 631 } 632 return(0); 633} 634#endif
|