1aad970f1SDavid E. O'Brien /*- 277ee030bSHidetoshi Shimokawa * Copyright (c) 2002-2003 3b018dcd1SHidetoshi Shimokawa * Hidetoshi Shimokawa. All rights reserved. 4b018dcd1SHidetoshi Shimokawa * 5b018dcd1SHidetoshi Shimokawa * Redistribution and use in source and binary forms, with or without 6b018dcd1SHidetoshi Shimokawa * modification, are permitted provided that the following conditions 7b018dcd1SHidetoshi Shimokawa * are met: 8b018dcd1SHidetoshi Shimokawa * 1. Redistributions of source code must retain the above copyright 9b018dcd1SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer. 10b018dcd1SHidetoshi Shimokawa * 2. Redistributions in binary form must reproduce the above copyright 11b018dcd1SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer in the 12b018dcd1SHidetoshi Shimokawa * documentation and/or other materials provided with the distribution. 13b018dcd1SHidetoshi Shimokawa * 3. All advertising materials mentioning features or use of this software 14b018dcd1SHidetoshi Shimokawa * must display the following acknowledgement: 15b018dcd1SHidetoshi Shimokawa * 16b018dcd1SHidetoshi Shimokawa * This product includes software developed by Hidetoshi Shimokawa. 17b018dcd1SHidetoshi Shimokawa * 18b018dcd1SHidetoshi Shimokawa * 4. Neither the name of the author nor the names of its contributors 19b018dcd1SHidetoshi Shimokawa * may be used to endorse or promote products derived from this software 20b018dcd1SHidetoshi Shimokawa * without specific prior written permission. 21b018dcd1SHidetoshi Shimokawa * 22b018dcd1SHidetoshi Shimokawa * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23b018dcd1SHidetoshi Shimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24b018dcd1SHidetoshi Shimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25b018dcd1SHidetoshi Shimokawa * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26b018dcd1SHidetoshi Shimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27b018dcd1SHidetoshi Shimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28b018dcd1SHidetoshi Shimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29b018dcd1SHidetoshi Shimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30b018dcd1SHidetoshi Shimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31b018dcd1SHidetoshi Shimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32b018dcd1SHidetoshi Shimokawa * SUCH DAMAGE. 33b018dcd1SHidetoshi Shimokawa */ 34b018dcd1SHidetoshi Shimokawa 3510d3ed64SHidetoshi Shimokawa #ifdef __FreeBSD__ 36aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 37aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3810d3ed64SHidetoshi Shimokawa #endif 39aad970f1SDavid E. O'Brien 40b018dcd1SHidetoshi Shimokawa #include <sys/param.h> 41fcbe55a5SHidetoshi Shimokawa 42fcbe55a5SHidetoshi Shimokawa #ifdef _BOOT 43fcbe55a5SHidetoshi Shimokawa #include <stand.h> 44fcbe55a5SHidetoshi Shimokawa #include <bootstrap.h> 45fcbe55a5SHidetoshi Shimokawa #else 4677ee030bSHidetoshi Shimokawa #if defined(_KERNEL) || defined(TEST) 4777ee030bSHidetoshi Shimokawa #include <sys/queue.h> 4877ee030bSHidetoshi Shimokawa #endif 49b018dcd1SHidetoshi Shimokawa #ifdef _KERNEL 50b018dcd1SHidetoshi Shimokawa #include <sys/systm.h> 51b018dcd1SHidetoshi Shimokawa #include <sys/kernel.h> 52b018dcd1SHidetoshi Shimokawa #else 53b018dcd1SHidetoshi Shimokawa #include <netinet/in.h> 54b018dcd1SHidetoshi Shimokawa #include <fcntl.h> 55b018dcd1SHidetoshi Shimokawa #include <stdio.h> 56b018dcd1SHidetoshi Shimokawa #include <err.h> 57b018dcd1SHidetoshi Shimokawa #include <stdlib.h> 58b018dcd1SHidetoshi Shimokawa #include <string.h> 59b018dcd1SHidetoshi Shimokawa #endif 60fcbe55a5SHidetoshi Shimokawa #endif 6110d3ed64SHidetoshi Shimokawa 6210d3ed64SHidetoshi Shimokawa #ifdef __DragonFly__ 6310d3ed64SHidetoshi Shimokawa #include "firewire.h" 6410d3ed64SHidetoshi Shimokawa #include "iec13213.h" 6510d3ed64SHidetoshi Shimokawa #else 6677ee030bSHidetoshi Shimokawa #include <dev/firewire/firewire.h> 6777ee030bSHidetoshi Shimokawa #include <dev/firewire/iec13213.h> 6810d3ed64SHidetoshi Shimokawa #endif 69b018dcd1SHidetoshi Shimokawa 7003161bbcSDoug Rabson #define MAX_ROM (1024 - sizeof(uint32_t) * 5) 7188e7cb59SHidetoshi Shimokawa #define CROM_END(cc) ((vm_offset_t)(cc)->stack[0].dir + MAX_ROM - 1) 7288e7cb59SHidetoshi Shimokawa 73b018dcd1SHidetoshi Shimokawa void 7403161bbcSDoug Rabson crom_init_context(struct crom_context *cc, uint32_t *p) 75b018dcd1SHidetoshi Shimokawa { 76b018dcd1SHidetoshi Shimokawa struct csrhdr *hdr; 77b018dcd1SHidetoshi Shimokawa 78b018dcd1SHidetoshi Shimokawa hdr = (struct csrhdr *)p; 7910d3ed64SHidetoshi Shimokawa if (hdr->info_len <= 1) { 8010d3ed64SHidetoshi Shimokawa /* minimum or invalid ROM */ 81b018dcd1SHidetoshi Shimokawa cc->depth = -1; 8210d3ed64SHidetoshi Shimokawa return; 83b018dcd1SHidetoshi Shimokawa } 84b018dcd1SHidetoshi Shimokawa p += 1 + hdr->info_len; 855e286c32SHidetoshi Shimokawa 865e286c32SHidetoshi Shimokawa /* check size of root directory */ 875e286c32SHidetoshi Shimokawa if (((struct csrdirectory *)p)->crc_len == 0) { 885e286c32SHidetoshi Shimokawa cc->depth = -1; 895e286c32SHidetoshi Shimokawa return; 905e286c32SHidetoshi Shimokawa } 91b018dcd1SHidetoshi Shimokawa cc->depth = 0; 92b018dcd1SHidetoshi Shimokawa cc->stack[0].dir = (struct csrdirectory *)p; 93b018dcd1SHidetoshi Shimokawa cc->stack[0].index = 0; 94b018dcd1SHidetoshi Shimokawa } 95b018dcd1SHidetoshi Shimokawa 96b018dcd1SHidetoshi Shimokawa struct csrreg * 97b018dcd1SHidetoshi Shimokawa crom_get(struct crom_context *cc) 98b018dcd1SHidetoshi Shimokawa { 99b018dcd1SHidetoshi Shimokawa struct crom_ptr *ptr; 100b018dcd1SHidetoshi Shimokawa 101b018dcd1SHidetoshi Shimokawa ptr = &cc->stack[cc->depth]; 102b018dcd1SHidetoshi Shimokawa return (&ptr->dir->entry[ptr->index]); 103b018dcd1SHidetoshi Shimokawa } 104b018dcd1SHidetoshi Shimokawa 105b018dcd1SHidetoshi Shimokawa void 106b018dcd1SHidetoshi Shimokawa crom_next(struct crom_context *cc) 107b018dcd1SHidetoshi Shimokawa { 108b018dcd1SHidetoshi Shimokawa struct crom_ptr *ptr; 109b018dcd1SHidetoshi Shimokawa struct csrreg *reg; 110b018dcd1SHidetoshi Shimokawa 111b018dcd1SHidetoshi Shimokawa if (cc->depth < 0) 112b018dcd1SHidetoshi Shimokawa return; 113b018dcd1SHidetoshi Shimokawa reg = crom_get(cc); 114b018dcd1SHidetoshi Shimokawa if ((reg->key & CSRTYPE_MASK) == CSRTYPE_D) { 11588e7cb59SHidetoshi Shimokawa if (cc->depth >= CROM_MAX_DEPTH) { 116b018dcd1SHidetoshi Shimokawa printf("crom_next: too deep\n"); 117b018dcd1SHidetoshi Shimokawa goto again; 118b018dcd1SHidetoshi Shimokawa } 11988e7cb59SHidetoshi Shimokawa cc->depth ++; 12088e7cb59SHidetoshi Shimokawa 1217ddbf617SHidetoshi Shimokawa ptr = &cc->stack[cc->depth]; 1227ddbf617SHidetoshi Shimokawa ptr->dir = (struct csrdirectory *) (reg + reg->val); 1237ddbf617SHidetoshi Shimokawa ptr->index = 0; 1247ddbf617SHidetoshi Shimokawa goto check; 125b018dcd1SHidetoshi Shimokawa } 126b018dcd1SHidetoshi Shimokawa again: 127b018dcd1SHidetoshi Shimokawa ptr = &cc->stack[cc->depth]; 128b018dcd1SHidetoshi Shimokawa ptr->index ++; 1297ddbf617SHidetoshi Shimokawa check: 13088e7cb59SHidetoshi Shimokawa if (ptr->index < ptr->dir->crc_len && 13188e7cb59SHidetoshi Shimokawa (vm_offset_t)crom_get(cc) <= CROM_END(cc)) 132b018dcd1SHidetoshi Shimokawa return; 13388e7cb59SHidetoshi Shimokawa 13488e7cb59SHidetoshi Shimokawa if (ptr->index < ptr->dir->crc_len) 13588e7cb59SHidetoshi Shimokawa printf("crom_next: bound check failed\n"); 13688e7cb59SHidetoshi Shimokawa 137b018dcd1SHidetoshi Shimokawa if (cc->depth > 0) { 138b018dcd1SHidetoshi Shimokawa cc->depth--; 139b018dcd1SHidetoshi Shimokawa goto again; 140b018dcd1SHidetoshi Shimokawa } 141b018dcd1SHidetoshi Shimokawa /* no more data */ 142b018dcd1SHidetoshi Shimokawa cc->depth = -1; 143b018dcd1SHidetoshi Shimokawa } 144b018dcd1SHidetoshi Shimokawa 145b018dcd1SHidetoshi Shimokawa 146b018dcd1SHidetoshi Shimokawa struct csrreg * 14703161bbcSDoug Rabson crom_search_key(struct crom_context *cc, uint8_t key) 148b018dcd1SHidetoshi Shimokawa { 149b018dcd1SHidetoshi Shimokawa struct csrreg *reg; 150b018dcd1SHidetoshi Shimokawa 151b018dcd1SHidetoshi Shimokawa while(cc->depth >= 0) { 152b018dcd1SHidetoshi Shimokawa reg = crom_get(cc); 153b018dcd1SHidetoshi Shimokawa if (reg->key == key) 154b018dcd1SHidetoshi Shimokawa return reg; 155b018dcd1SHidetoshi Shimokawa crom_next(cc); 156b018dcd1SHidetoshi Shimokawa } 157b018dcd1SHidetoshi Shimokawa return NULL; 158b018dcd1SHidetoshi Shimokawa } 159b018dcd1SHidetoshi Shimokawa 1605e286c32SHidetoshi Shimokawa int 16103161bbcSDoug Rabson crom_has_specver(uint32_t *p, uint32_t spec, uint32_t ver) 1625e286c32SHidetoshi Shimokawa { 1635e286c32SHidetoshi Shimokawa struct csrreg *reg; 1645e286c32SHidetoshi Shimokawa struct crom_context c, *cc; 1655e286c32SHidetoshi Shimokawa int state = 0; 1665e286c32SHidetoshi Shimokawa 1675e286c32SHidetoshi Shimokawa cc = &c; 1685e286c32SHidetoshi Shimokawa crom_init_context(cc, p); 1695e286c32SHidetoshi Shimokawa while(cc->depth >= 0) { 1705e286c32SHidetoshi Shimokawa reg = crom_get(cc); 1715e286c32SHidetoshi Shimokawa if (state == 0) { 1725e286c32SHidetoshi Shimokawa if (reg->key == CSRKEY_SPEC && reg->val == spec) 1735e286c32SHidetoshi Shimokawa state = 1; 1745e286c32SHidetoshi Shimokawa else 1755e286c32SHidetoshi Shimokawa state = 0; 1765e286c32SHidetoshi Shimokawa } else { 1775e286c32SHidetoshi Shimokawa if (reg->key == CSRKEY_VER && reg->val == ver) 1785e286c32SHidetoshi Shimokawa return 1; 1795e286c32SHidetoshi Shimokawa else 1805e286c32SHidetoshi Shimokawa state = 0; 1815e286c32SHidetoshi Shimokawa } 1825e286c32SHidetoshi Shimokawa crom_next(cc); 1835e286c32SHidetoshi Shimokawa } 1845e286c32SHidetoshi Shimokawa return 0; 1855e286c32SHidetoshi Shimokawa } 1865e286c32SHidetoshi Shimokawa 187b018dcd1SHidetoshi Shimokawa void 188b018dcd1SHidetoshi Shimokawa crom_parse_text(struct crom_context *cc, char *buf, int len) 189b018dcd1SHidetoshi Shimokawa { 190b018dcd1SHidetoshi Shimokawa struct csrreg *reg; 191b018dcd1SHidetoshi Shimokawa struct csrtext *textleaf; 19203161bbcSDoug Rabson uint32_t *bp; 193b018dcd1SHidetoshi Shimokawa int i, qlen; 194b018dcd1SHidetoshi Shimokawa static char *nullstr = "(null)"; 195b018dcd1SHidetoshi Shimokawa 1965e286c32SHidetoshi Shimokawa if (cc->depth < 0) 1975e286c32SHidetoshi Shimokawa return; 1985e286c32SHidetoshi Shimokawa 199b018dcd1SHidetoshi Shimokawa reg = crom_get(cc); 20088e7cb59SHidetoshi Shimokawa if (reg->key != CROM_TEXTLEAF || 20188e7cb59SHidetoshi Shimokawa (vm_offset_t)(reg + reg->val) > CROM_END(cc)) { 202b018dcd1SHidetoshi Shimokawa strncpy(buf, nullstr, len); 203b018dcd1SHidetoshi Shimokawa return; 204b018dcd1SHidetoshi Shimokawa } 205b018dcd1SHidetoshi Shimokawa textleaf = (struct csrtext *)(reg + reg->val); 206b018dcd1SHidetoshi Shimokawa 20788e7cb59SHidetoshi Shimokawa if ((vm_offset_t)textleaf + textleaf->crc_len > CROM_END(cc)) { 20888e7cb59SHidetoshi Shimokawa strncpy(buf, nullstr, len); 20988e7cb59SHidetoshi Shimokawa return; 21088e7cb59SHidetoshi Shimokawa } 21188e7cb59SHidetoshi Shimokawa 212b018dcd1SHidetoshi Shimokawa /* XXX should check spec and type */ 213b018dcd1SHidetoshi Shimokawa 21403161bbcSDoug Rabson bp = (uint32_t *)&buf[0]; 215b018dcd1SHidetoshi Shimokawa qlen = textleaf->crc_len - 2; 216b018dcd1SHidetoshi Shimokawa if (len < qlen * 4) 217b018dcd1SHidetoshi Shimokawa qlen = len/4; 218b018dcd1SHidetoshi Shimokawa for (i = 0; i < qlen; i ++) 219b018dcd1SHidetoshi Shimokawa *bp++ = ntohl(textleaf->text[i]); 220b018dcd1SHidetoshi Shimokawa /* make sure to terminate the string */ 221b018dcd1SHidetoshi Shimokawa if (len <= qlen * 4) 222b018dcd1SHidetoshi Shimokawa buf[len - 1] = 0; 223b018dcd1SHidetoshi Shimokawa else 224b018dcd1SHidetoshi Shimokawa buf[qlen * 4] = 0; 225b018dcd1SHidetoshi Shimokawa } 226b018dcd1SHidetoshi Shimokawa 22703161bbcSDoug Rabson uint16_t 22803161bbcSDoug Rabson crom_crc(uint32_t *ptr, int len) 229b018dcd1SHidetoshi Shimokawa { 230b018dcd1SHidetoshi Shimokawa int i, shift; 23103161bbcSDoug Rabson uint32_t data, sum, crc = 0; 232b018dcd1SHidetoshi Shimokawa 233b018dcd1SHidetoshi Shimokawa for (i = 0; i < len; i++) { 234b018dcd1SHidetoshi Shimokawa data = ptr[i]; 235b018dcd1SHidetoshi Shimokawa for (shift = 28; shift >= 0; shift -= 4) { 236b018dcd1SHidetoshi Shimokawa sum = ((crc >> 12) ^ (data >> shift)) & 0xf; 237b018dcd1SHidetoshi Shimokawa crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; 238b018dcd1SHidetoshi Shimokawa } 239b018dcd1SHidetoshi Shimokawa crc &= 0xffff; 240b018dcd1SHidetoshi Shimokawa } 24103161bbcSDoug Rabson return((uint16_t) crc); 242b018dcd1SHidetoshi Shimokawa } 243b018dcd1SHidetoshi Shimokawa 244fcbe55a5SHidetoshi Shimokawa #if !defined(_KERNEL) && !defined(_BOOT) 2455e286c32SHidetoshi Shimokawa static void 24603161bbcSDoug Rabson crom_desc_specver(uint32_t spec, uint32_t ver, char *buf, int len) 2475e286c32SHidetoshi Shimokawa { 2485e286c32SHidetoshi Shimokawa char *s = NULL; 2495e286c32SHidetoshi Shimokawa 2505e286c32SHidetoshi Shimokawa if (spec == CSRVAL_ANSIT10 || spec == 0) { 2515e286c32SHidetoshi Shimokawa switch (ver) { 2525e286c32SHidetoshi Shimokawa case CSRVAL_T10SBP2: 2535e286c32SHidetoshi Shimokawa s = "SBP-2"; 2545e286c32SHidetoshi Shimokawa break; 2555e286c32SHidetoshi Shimokawa default: 2565e286c32SHidetoshi Shimokawa if (spec != 0) 2575e286c32SHidetoshi Shimokawa s = "unknown ANSIT10"; 2585e286c32SHidetoshi Shimokawa } 2595e286c32SHidetoshi Shimokawa } 2605e286c32SHidetoshi Shimokawa if (spec == CSRVAL_1394TA || spec == 0) { 2615e286c32SHidetoshi Shimokawa switch (ver) { 2625e286c32SHidetoshi Shimokawa case CSR_PROTAVC: 2635e286c32SHidetoshi Shimokawa s = "AV/C"; 2645e286c32SHidetoshi Shimokawa break; 2655e286c32SHidetoshi Shimokawa case CSR_PROTCAL: 2665e286c32SHidetoshi Shimokawa s = "CAL"; 2675e286c32SHidetoshi Shimokawa break; 2685e286c32SHidetoshi Shimokawa case CSR_PROTEHS: 2695e286c32SHidetoshi Shimokawa s = "EHS"; 2705e286c32SHidetoshi Shimokawa break; 2715e286c32SHidetoshi Shimokawa case CSR_PROTHAVI: 2725e286c32SHidetoshi Shimokawa s = "HAVi"; 2735e286c32SHidetoshi Shimokawa break; 2745e286c32SHidetoshi Shimokawa case CSR_PROTCAM104: 2755e286c32SHidetoshi Shimokawa s = "1394 Cam 1.04"; 2765e286c32SHidetoshi Shimokawa break; 2775e286c32SHidetoshi Shimokawa case CSR_PROTCAM120: 2785e286c32SHidetoshi Shimokawa s = "1394 Cam 1.20"; 2795e286c32SHidetoshi Shimokawa break; 2805e286c32SHidetoshi Shimokawa case CSR_PROTCAM130: 2815e286c32SHidetoshi Shimokawa s = "1394 Cam 1.30"; 2825e286c32SHidetoshi Shimokawa break; 2835e286c32SHidetoshi Shimokawa case CSR_PROTDPP: 2845e286c32SHidetoshi Shimokawa s = "1394 Direct print"; 2855e286c32SHidetoshi Shimokawa break; 2865e286c32SHidetoshi Shimokawa case CSR_PROTIICP: 2875e286c32SHidetoshi Shimokawa s = "Industrial & Instrument"; 2885e286c32SHidetoshi Shimokawa break; 2895e286c32SHidetoshi Shimokawa default: 2905e286c32SHidetoshi Shimokawa if (spec != 0) 2915e286c32SHidetoshi Shimokawa s = "unknown 1394TA"; 2925e286c32SHidetoshi Shimokawa } 2935e286c32SHidetoshi Shimokawa } 2945e286c32SHidetoshi Shimokawa if (s != NULL) 2955e286c32SHidetoshi Shimokawa snprintf(buf, len, "%s", s); 2965e286c32SHidetoshi Shimokawa } 2975e286c32SHidetoshi Shimokawa 298b018dcd1SHidetoshi Shimokawa char * 299b018dcd1SHidetoshi Shimokawa crom_desc(struct crom_context *cc, char *buf, int len) 300b018dcd1SHidetoshi Shimokawa { 301b018dcd1SHidetoshi Shimokawa struct csrreg *reg; 302b018dcd1SHidetoshi Shimokawa struct csrdirectory *dir; 303ce7bda46SHidetoshi Shimokawa char *desc; 30403161bbcSDoug Rabson uint16_t crc; 305b018dcd1SHidetoshi Shimokawa 306b018dcd1SHidetoshi Shimokawa reg = crom_get(cc); 307b018dcd1SHidetoshi Shimokawa switch (reg->key & CSRTYPE_MASK) { 308b018dcd1SHidetoshi Shimokawa case CSRTYPE_I: 3095e286c32SHidetoshi Shimokawa #if 0 3105e286c32SHidetoshi Shimokawa len -= snprintf(buf, len, "%d", reg->val); 3115e286c32SHidetoshi Shimokawa buf += strlen(buf); 3125e286c32SHidetoshi Shimokawa #else 3135e286c32SHidetoshi Shimokawa *buf = '\0'; 3145e286c32SHidetoshi Shimokawa #endif 315b018dcd1SHidetoshi Shimokawa break; 316b018dcd1SHidetoshi Shimokawa case CSRTYPE_C: 3175e286c32SHidetoshi Shimokawa len -= snprintf(buf, len, "offset=0x%04x(%d)", 3185e286c32SHidetoshi Shimokawa reg->val, reg->val); 3195e286c32SHidetoshi Shimokawa buf += strlen(buf); 320b018dcd1SHidetoshi Shimokawa break; 32177ee030bSHidetoshi Shimokawa case CSRTYPE_L: 32277ee030bSHidetoshi Shimokawa /* XXX fall through */ 323b018dcd1SHidetoshi Shimokawa case CSRTYPE_D: 324b018dcd1SHidetoshi Shimokawa dir = (struct csrdirectory *) (reg + reg->val); 32503161bbcSDoug Rabson crc = crom_crc((uint32_t *)&dir->entry[0], dir->crc_len); 3265e286c32SHidetoshi Shimokawa len -= snprintf(buf, len, "len=%d crc=0x%04x(%s) ", 3275e286c32SHidetoshi Shimokawa dir->crc_len, dir->crc, 3285e286c32SHidetoshi Shimokawa (crc == dir->crc) ? "OK" : "NG"); 3295e286c32SHidetoshi Shimokawa buf += strlen(buf); 330b018dcd1SHidetoshi Shimokawa } 331b018dcd1SHidetoshi Shimokawa switch (reg->key) { 332b018dcd1SHidetoshi Shimokawa case 0x03: 333b018dcd1SHidetoshi Shimokawa desc = "module_vendor_ID"; 334b018dcd1SHidetoshi Shimokawa break; 335b018dcd1SHidetoshi Shimokawa case 0x04: 336b018dcd1SHidetoshi Shimokawa desc = "hardware_version"; 337b018dcd1SHidetoshi Shimokawa break; 338b018dcd1SHidetoshi Shimokawa case 0x0c: 339b018dcd1SHidetoshi Shimokawa desc = "node_capabilities"; 340b018dcd1SHidetoshi Shimokawa break; 341b018dcd1SHidetoshi Shimokawa case 0x12: 342b018dcd1SHidetoshi Shimokawa desc = "unit_spec_ID"; 343b018dcd1SHidetoshi Shimokawa break; 344b018dcd1SHidetoshi Shimokawa case 0x13: 345b018dcd1SHidetoshi Shimokawa desc = "unit_sw_version"; 3465e286c32SHidetoshi Shimokawa crom_desc_specver(0, reg->val, buf, len); 347b018dcd1SHidetoshi Shimokawa break; 348b018dcd1SHidetoshi Shimokawa case 0x14: 349b018dcd1SHidetoshi Shimokawa desc = "logical_unit_number"; 350b018dcd1SHidetoshi Shimokawa break; 351b018dcd1SHidetoshi Shimokawa case 0x17: 352b018dcd1SHidetoshi Shimokawa desc = "model_ID"; 353b018dcd1SHidetoshi Shimokawa break; 354b018dcd1SHidetoshi Shimokawa case 0x38: 355b018dcd1SHidetoshi Shimokawa desc = "command_set_spec_ID"; 356b018dcd1SHidetoshi Shimokawa break; 357b018dcd1SHidetoshi Shimokawa case 0x39: 358b018dcd1SHidetoshi Shimokawa desc = "command_set"; 359b018dcd1SHidetoshi Shimokawa break; 360b018dcd1SHidetoshi Shimokawa case 0x3a: 361b018dcd1SHidetoshi Shimokawa desc = "unit_characteristics"; 362b018dcd1SHidetoshi Shimokawa break; 363b018dcd1SHidetoshi Shimokawa case 0x3b: 364b018dcd1SHidetoshi Shimokawa desc = "command_set_revision"; 365b018dcd1SHidetoshi Shimokawa break; 366b018dcd1SHidetoshi Shimokawa case 0x3c: 367b018dcd1SHidetoshi Shimokawa desc = "firmware_revision"; 368b018dcd1SHidetoshi Shimokawa break; 369b018dcd1SHidetoshi Shimokawa case 0x3d: 370b018dcd1SHidetoshi Shimokawa desc = "reconnect_timeout"; 371b018dcd1SHidetoshi Shimokawa break; 372b018dcd1SHidetoshi Shimokawa case 0x54: 373b018dcd1SHidetoshi Shimokawa desc = "management_agent"; 374b018dcd1SHidetoshi Shimokawa break; 375b018dcd1SHidetoshi Shimokawa case 0x81: 376b018dcd1SHidetoshi Shimokawa desc = "text_leaf"; 37777ee030bSHidetoshi Shimokawa crom_parse_text(cc, buf + strlen(buf), len); 378b018dcd1SHidetoshi Shimokawa break; 379b018dcd1SHidetoshi Shimokawa case 0xd1: 380b018dcd1SHidetoshi Shimokawa desc = "unit_directory"; 381b018dcd1SHidetoshi Shimokawa break; 382b018dcd1SHidetoshi Shimokawa case 0xd4: 383b018dcd1SHidetoshi Shimokawa desc = "logical_unit_directory"; 384b018dcd1SHidetoshi Shimokawa break; 385b018dcd1SHidetoshi Shimokawa default: 386b018dcd1SHidetoshi Shimokawa desc = "unknown"; 387b018dcd1SHidetoshi Shimokawa } 388b018dcd1SHidetoshi Shimokawa return desc; 389b018dcd1SHidetoshi Shimokawa } 390b018dcd1SHidetoshi Shimokawa #endif 39177ee030bSHidetoshi Shimokawa 392fcbe55a5SHidetoshi Shimokawa #if defined(_KERNEL) || defined(_BOOT) || defined(TEST) 39377ee030bSHidetoshi Shimokawa 39477ee030bSHidetoshi Shimokawa int 39503161bbcSDoug Rabson crom_add_quad(struct crom_chunk *chunk, uint32_t entry) 39677ee030bSHidetoshi Shimokawa { 39777ee030bSHidetoshi Shimokawa int index; 39877ee030bSHidetoshi Shimokawa 39977ee030bSHidetoshi Shimokawa index = chunk->data.crc_len; 40077ee030bSHidetoshi Shimokawa if (index >= CROM_MAX_CHUNK_LEN - 1) { 40177ee030bSHidetoshi Shimokawa printf("too large chunk %d\n", index); 40277ee030bSHidetoshi Shimokawa return(-1); 40377ee030bSHidetoshi Shimokawa } 40477ee030bSHidetoshi Shimokawa chunk->data.buf[index] = entry; 40577ee030bSHidetoshi Shimokawa chunk->data.crc_len++; 40677ee030bSHidetoshi Shimokawa return(index); 40777ee030bSHidetoshi Shimokawa } 40877ee030bSHidetoshi Shimokawa 40977ee030bSHidetoshi Shimokawa int 41077ee030bSHidetoshi Shimokawa crom_add_entry(struct crom_chunk *chunk, int key, int val) 41177ee030bSHidetoshi Shimokawa { 41277ee030bSHidetoshi Shimokawa struct csrreg *reg; 41303161bbcSDoug Rabson uint32_t i; 41477ee030bSHidetoshi Shimokawa 41577ee030bSHidetoshi Shimokawa reg = (struct csrreg *)&i; 41677ee030bSHidetoshi Shimokawa reg->key = key; 41777ee030bSHidetoshi Shimokawa reg->val = val; 41803161bbcSDoug Rabson return(crom_add_quad(chunk, (uint32_t) i)); 41977ee030bSHidetoshi Shimokawa } 42077ee030bSHidetoshi Shimokawa 42177ee030bSHidetoshi Shimokawa int 42277ee030bSHidetoshi Shimokawa crom_add_chunk(struct crom_src *src, struct crom_chunk *parent, 42377ee030bSHidetoshi Shimokawa struct crom_chunk *child, int key) 42477ee030bSHidetoshi Shimokawa { 42577ee030bSHidetoshi Shimokawa int index; 42677ee030bSHidetoshi Shimokawa 42777ee030bSHidetoshi Shimokawa if (parent == NULL) { 42877ee030bSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&src->chunk_list, child, link); 42977ee030bSHidetoshi Shimokawa return(0); 43077ee030bSHidetoshi Shimokawa } 43177ee030bSHidetoshi Shimokawa 43277ee030bSHidetoshi Shimokawa index = crom_add_entry(parent, key, 0); 43377ee030bSHidetoshi Shimokawa if (index < 0) { 43477ee030bSHidetoshi Shimokawa return(-1); 43577ee030bSHidetoshi Shimokawa } 43677ee030bSHidetoshi Shimokawa child->ref_chunk = parent; 43777ee030bSHidetoshi Shimokawa child->ref_index = index; 43877ee030bSHidetoshi Shimokawa STAILQ_INSERT_TAIL(&src->chunk_list, child, link); 43977ee030bSHidetoshi Shimokawa return(index); 44077ee030bSHidetoshi Shimokawa } 44177ee030bSHidetoshi Shimokawa 442c4778b5dSHidetoshi Shimokawa #define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext)) 44377ee030bSHidetoshi Shimokawa int 44477ee030bSHidetoshi Shimokawa crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent, 44577ee030bSHidetoshi Shimokawa struct crom_chunk *chunk, char *buf) 44677ee030bSHidetoshi Shimokawa { 44777ee030bSHidetoshi Shimokawa struct csrtext *tl; 44803161bbcSDoug Rabson uint32_t *p; 44977ee030bSHidetoshi Shimokawa int len, i; 450c4778b5dSHidetoshi Shimokawa char t[MAX_TEXT]; 45177ee030bSHidetoshi Shimokawa 45277ee030bSHidetoshi Shimokawa len = strlen(buf); 45377ee030bSHidetoshi Shimokawa if (len > MAX_TEXT) { 45410d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 45577ee030bSHidetoshi Shimokawa printf("text(%d) trancated to %d.\n", len, MAX_TEXT); 45677ee030bSHidetoshi Shimokawa #else 45777ee030bSHidetoshi Shimokawa printf("text(%d) trancated to %td.\n", len, MAX_TEXT); 45877ee030bSHidetoshi Shimokawa #endif 45977ee030bSHidetoshi Shimokawa len = MAX_TEXT; 46077ee030bSHidetoshi Shimokawa } 46177ee030bSHidetoshi Shimokawa 46277ee030bSHidetoshi Shimokawa tl = (struct csrtext *) &chunk->data; 46303161bbcSDoug Rabson tl->crc_len = howmany(sizeof(struct csrtext) + len, sizeof(uint32_t)); 46477ee030bSHidetoshi Shimokawa tl->spec_id = 0; 46577ee030bSHidetoshi Shimokawa tl->spec_type = 0; 46677ee030bSHidetoshi Shimokawa tl->lang_id = 0; 46703161bbcSDoug Rabson bzero(&t[0], roundup2(len, sizeof(uint32_t))); 468c4778b5dSHidetoshi Shimokawa bcopy(buf, &t[0], len); 46903161bbcSDoug Rabson p = (uint32_t *)&t[0]; 47003161bbcSDoug Rabson for (i = 0; i < howmany(len, sizeof(uint32_t)); i ++) 47177ee030bSHidetoshi Shimokawa tl->text[i] = ntohl(*p++); 47277ee030bSHidetoshi Shimokawa return (crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF)); 47377ee030bSHidetoshi Shimokawa } 47477ee030bSHidetoshi Shimokawa 47577ee030bSHidetoshi Shimokawa static int 47603161bbcSDoug Rabson crom_copy(uint32_t *src, uint32_t *dst, int *offset, int len, int maxlen) 47777ee030bSHidetoshi Shimokawa { 47877ee030bSHidetoshi Shimokawa if (*offset + len > maxlen) { 47977ee030bSHidetoshi Shimokawa printf("Config. ROM is too large for the buffer\n"); 48077ee030bSHidetoshi Shimokawa return(-1); 48177ee030bSHidetoshi Shimokawa } 48203161bbcSDoug Rabson bcopy(src, (char *)(dst + *offset), len * sizeof(uint32_t)); 48377ee030bSHidetoshi Shimokawa *offset += len; 48477ee030bSHidetoshi Shimokawa return(0); 48577ee030bSHidetoshi Shimokawa } 48677ee030bSHidetoshi Shimokawa 48777ee030bSHidetoshi Shimokawa int 48803161bbcSDoug Rabson crom_load(struct crom_src *src, uint32_t *buf, int maxlen) 48977ee030bSHidetoshi Shimokawa { 49077ee030bSHidetoshi Shimokawa struct crom_chunk *chunk, *parent; 49177ee030bSHidetoshi Shimokawa struct csrhdr *hdr; 492fcbe55a5SHidetoshi Shimokawa #if defined(_KERNEL) || defined(_BOOT) 49303161bbcSDoug Rabson uint32_t *ptr; 494b83977f0SHidetoshi Shimokawa int i; 49577ee030bSHidetoshi Shimokawa #endif 49677ee030bSHidetoshi Shimokawa int count, offset; 49777ee030bSHidetoshi Shimokawa int len; 49877ee030bSHidetoshi Shimokawa 49977ee030bSHidetoshi Shimokawa offset = 0; 50077ee030bSHidetoshi Shimokawa /* Determine offset */ 50177ee030bSHidetoshi Shimokawa STAILQ_FOREACH(chunk, &src->chunk_list, link) { 50277ee030bSHidetoshi Shimokawa chunk->offset = offset; 50377ee030bSHidetoshi Shimokawa /* Assume the offset of the parent is already known */ 50477ee030bSHidetoshi Shimokawa parent = chunk->ref_chunk; 50577ee030bSHidetoshi Shimokawa if (parent != NULL) { 50677ee030bSHidetoshi Shimokawa struct csrreg *reg; 50777ee030bSHidetoshi Shimokawa reg = (struct csrreg *) 50877ee030bSHidetoshi Shimokawa &parent->data.buf[chunk->ref_index]; 50977ee030bSHidetoshi Shimokawa reg->val = offset - 51077ee030bSHidetoshi Shimokawa (parent->offset + 1 + chunk->ref_index); 51177ee030bSHidetoshi Shimokawa } 51277ee030bSHidetoshi Shimokawa offset += 1 + chunk->data.crc_len; 51377ee030bSHidetoshi Shimokawa } 51477ee030bSHidetoshi Shimokawa 51577ee030bSHidetoshi Shimokawa /* Calculate CRC and dump to the buffer */ 51677ee030bSHidetoshi Shimokawa len = 1 + src->hdr.info_len; 51777ee030bSHidetoshi Shimokawa count = 0; 51803161bbcSDoug Rabson if (crom_copy((uint32_t *)&src->hdr, buf, &count, len, maxlen) < 0) 51977ee030bSHidetoshi Shimokawa return(-1); 52077ee030bSHidetoshi Shimokawa STAILQ_FOREACH(chunk, &src->chunk_list, link) { 52177ee030bSHidetoshi Shimokawa chunk->data.crc = 52277ee030bSHidetoshi Shimokawa crom_crc(&chunk->data.buf[0], chunk->data.crc_len); 52377ee030bSHidetoshi Shimokawa 52477ee030bSHidetoshi Shimokawa len = 1 + chunk->data.crc_len; 52503161bbcSDoug Rabson if (crom_copy((uint32_t *)&chunk->data, buf, 52677ee030bSHidetoshi Shimokawa &count, len, maxlen) < 0) 52777ee030bSHidetoshi Shimokawa return(-1); 52877ee030bSHidetoshi Shimokawa } 52977ee030bSHidetoshi Shimokawa hdr = (struct csrhdr *)buf; 53077ee030bSHidetoshi Shimokawa hdr->crc_len = count - 1; 531b83977f0SHidetoshi Shimokawa hdr->crc = crom_crc(&buf[1], hdr->crc_len); 53277ee030bSHidetoshi Shimokawa 533fcbe55a5SHidetoshi Shimokawa #if defined(_KERNEL) || defined(_BOOT) 53477ee030bSHidetoshi Shimokawa /* byte swap */ 53577ee030bSHidetoshi Shimokawa ptr = buf; 53677ee030bSHidetoshi Shimokawa for (i = 0; i < count; i ++) { 53777ee030bSHidetoshi Shimokawa *ptr = htonl(*ptr); 53877ee030bSHidetoshi Shimokawa ptr++; 53977ee030bSHidetoshi Shimokawa } 54077ee030bSHidetoshi Shimokawa #endif 54177ee030bSHidetoshi Shimokawa 54277ee030bSHidetoshi Shimokawa return(count); 54377ee030bSHidetoshi Shimokawa } 54477ee030bSHidetoshi Shimokawa #endif 54577ee030bSHidetoshi Shimokawa 54677ee030bSHidetoshi Shimokawa #ifdef TEST 54777ee030bSHidetoshi Shimokawa int 54877ee030bSHidetoshi Shimokawa main () { 54977ee030bSHidetoshi Shimokawa struct crom_src src; 55077ee030bSHidetoshi Shimokawa struct crom_chunk root,unit1,unit2,unit3; 55177ee030bSHidetoshi Shimokawa struct crom_chunk text1,text2,text3,text4,text5,text6,text7; 55203161bbcSDoug Rabson uint32_t buf[256], *p; 55377ee030bSHidetoshi Shimokawa int i; 55477ee030bSHidetoshi Shimokawa 55577ee030bSHidetoshi Shimokawa bzero(&src, sizeof(src)); 55677ee030bSHidetoshi Shimokawa bzero(&root, sizeof(root)); 55777ee030bSHidetoshi Shimokawa bzero(&unit1, sizeof(unit1)); 55877ee030bSHidetoshi Shimokawa bzero(&unit2, sizeof(unit2)); 55977ee030bSHidetoshi Shimokawa bzero(&unit3, sizeof(unit3)); 56077ee030bSHidetoshi Shimokawa bzero(&text1, sizeof(text1)); 56177ee030bSHidetoshi Shimokawa bzero(&text2, sizeof(text2)); 56277ee030bSHidetoshi Shimokawa bzero(&text3, sizeof(text3)); 56377ee030bSHidetoshi Shimokawa bzero(&text3, sizeof(text4)); 56477ee030bSHidetoshi Shimokawa bzero(&text3, sizeof(text5)); 56577ee030bSHidetoshi Shimokawa bzero(&text3, sizeof(text6)); 56677ee030bSHidetoshi Shimokawa bzero(&text3, sizeof(text7)); 56777ee030bSHidetoshi Shimokawa bzero(buf, sizeof(buf)); 56877ee030bSHidetoshi Shimokawa 56977ee030bSHidetoshi Shimokawa /* BUS info sample */ 57077ee030bSHidetoshi Shimokawa src.hdr.info_len = 4; 57177ee030bSHidetoshi Shimokawa src.businfo.bus_name = CSR_BUS_NAME_IEEE1394; 57277ee030bSHidetoshi Shimokawa src.businfo.eui64.hi = 0x11223344; 57377ee030bSHidetoshi Shimokawa src.businfo.eui64.lo = 0x55667788; 57477ee030bSHidetoshi Shimokawa src.businfo.link_spd = FWSPD_S400; 57577ee030bSHidetoshi Shimokawa src.businfo.generation = 0; 57677ee030bSHidetoshi Shimokawa src.businfo.max_rom = MAXROM_4; 57777ee030bSHidetoshi Shimokawa src.businfo.max_rec = 10; 57877ee030bSHidetoshi Shimokawa src.businfo.cyc_clk_acc = 100; 57977ee030bSHidetoshi Shimokawa src.businfo.pmc = 0; 58077ee030bSHidetoshi Shimokawa src.businfo.bmc = 1; 58177ee030bSHidetoshi Shimokawa src.businfo.isc = 1; 58277ee030bSHidetoshi Shimokawa src.businfo.cmc = 1; 58377ee030bSHidetoshi Shimokawa src.businfo.irmc = 1; 58477ee030bSHidetoshi Shimokawa STAILQ_INIT(&src.chunk_list); 58577ee030bSHidetoshi Shimokawa 58677ee030bSHidetoshi Shimokawa /* Root directory */ 58777ee030bSHidetoshi Shimokawa crom_add_chunk(&src, NULL, &root, 0); 58877ee030bSHidetoshi Shimokawa crom_add_entry(&root, CSRKEY_NCAP, 0x123456); 58977ee030bSHidetoshi Shimokawa /* private company_id */ 59077ee030bSHidetoshi Shimokawa crom_add_entry(&root, CSRKEY_VENDOR, 0xacde48); 59177ee030bSHidetoshi Shimokawa 59210d3ed64SHidetoshi Shimokawa #ifdef __DragonFly__ 59310d3ed64SHidetoshi Shimokawa crom_add_simple_text(&src, &root, &text1, "DragonFly"); 59410d3ed64SHidetoshi Shimokawa crom_add_entry(&root, CSRKEY_HW, __DragonFly_cc_version); 59510d3ed64SHidetoshi Shimokawa crom_add_simple_text(&src, &root, &text2, "DragonFly-1"); 59610d3ed64SHidetoshi Shimokawa #else 59777ee030bSHidetoshi Shimokawa crom_add_simple_text(&src, &root, &text1, "FreeBSD"); 59877ee030bSHidetoshi Shimokawa crom_add_entry(&root, CSRKEY_HW, __FreeBSD_version); 59977ee030bSHidetoshi Shimokawa crom_add_simple_text(&src, &root, &text2, "FreeBSD-5"); 60010d3ed64SHidetoshi Shimokawa #endif 60177ee030bSHidetoshi Shimokawa 60277ee030bSHidetoshi Shimokawa /* SBP unit directory */ 60377ee030bSHidetoshi Shimokawa crom_add_chunk(&src, &root, &unit1, CROM_UDIR); 60477ee030bSHidetoshi Shimokawa crom_add_entry(&unit1, CSRKEY_SPEC, CSRVAL_ANSIT10); 60577ee030bSHidetoshi Shimokawa crom_add_entry(&unit1, CSRKEY_VER, CSRVAL_T10SBP2); 60677ee030bSHidetoshi Shimokawa crom_add_entry(&unit1, CSRKEY_COM_SPEC, CSRVAL_ANSIT10); 60777ee030bSHidetoshi Shimokawa crom_add_entry(&unit1, CSRKEY_COM_SET, CSRVAL_SCSI); 60877ee030bSHidetoshi Shimokawa /* management_agent */ 60977ee030bSHidetoshi Shimokawa crom_add_entry(&unit1, CROM_MGM, 0x1000); 61077ee030bSHidetoshi Shimokawa crom_add_entry(&unit1, CSRKEY_UNIT_CH, (10<<8) | 8); 61177ee030bSHidetoshi Shimokawa /* Device type and LUN */ 61277ee030bSHidetoshi Shimokawa crom_add_entry(&unit1, CROM_LUN, 0); 61377ee030bSHidetoshi Shimokawa crom_add_entry(&unit1, CSRKEY_MODEL, 1); 61477ee030bSHidetoshi Shimokawa crom_add_simple_text(&src, &unit1, &text3, "scsi_target"); 61577ee030bSHidetoshi Shimokawa 61677ee030bSHidetoshi Shimokawa /* RFC2734 IPv4 over IEEE1394 */ 61777ee030bSHidetoshi Shimokawa crom_add_chunk(&src, &root, &unit2, CROM_UDIR); 61877ee030bSHidetoshi Shimokawa crom_add_entry(&unit2, CSRKEY_SPEC, CSRVAL_IETF); 61977ee030bSHidetoshi Shimokawa crom_add_simple_text(&src, &unit2, &text4, "IANA"); 62077ee030bSHidetoshi Shimokawa crom_add_entry(&unit2, CSRKEY_VER, 1); 62177ee030bSHidetoshi Shimokawa crom_add_simple_text(&src, &unit2, &text5, "IPv4"); 62277ee030bSHidetoshi Shimokawa 62377ee030bSHidetoshi Shimokawa /* RFC3146 IPv6 over IEEE1394 */ 62477ee030bSHidetoshi Shimokawa crom_add_chunk(&src, &root, &unit3, CROM_UDIR); 62577ee030bSHidetoshi Shimokawa crom_add_entry(&unit3, CSRKEY_SPEC, CSRVAL_IETF); 62677ee030bSHidetoshi Shimokawa crom_add_simple_text(&src, &unit3, &text6, "IANA"); 62777ee030bSHidetoshi Shimokawa crom_add_entry(&unit3, CSRKEY_VER, 2); 62877ee030bSHidetoshi Shimokawa crom_add_simple_text(&src, &unit3, &text7, "IPv6"); 62977ee030bSHidetoshi Shimokawa 63077ee030bSHidetoshi Shimokawa crom_load(&src, buf, 256); 63177ee030bSHidetoshi Shimokawa p = buf; 63277ee030bSHidetoshi Shimokawa #define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" 63377ee030bSHidetoshi Shimokawa for (i = 0; i < 256/8; i ++) { 63477ee030bSHidetoshi Shimokawa printf(DUMP_FORMAT, 63577ee030bSHidetoshi Shimokawa p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); 63677ee030bSHidetoshi Shimokawa p += 8; 63777ee030bSHidetoshi Shimokawa } 63877ee030bSHidetoshi Shimokawa return(0); 63977ee030bSHidetoshi Shimokawa } 64077ee030bSHidetoshi Shimokawa #endif 641