1b018dcd1SHidetoshi Shimokawa /* 2b018dcd1SHidetoshi Shimokawa * Copyright (C) 2002 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 * $FreeBSD$ 35b018dcd1SHidetoshi Shimokawa */ 36b018dcd1SHidetoshi Shimokawa 37b018dcd1SHidetoshi Shimokawa #include <sys/param.h> 38b018dcd1SHidetoshi Shimokawa #include <dev/firewire/firewire.h> 39b018dcd1SHidetoshi Shimokawa #include <dev/firewire/iec13213.h> 40b018dcd1SHidetoshi Shimokawa #ifdef _KERNEL 41b018dcd1SHidetoshi Shimokawa #include <sys/systm.h> 42b018dcd1SHidetoshi Shimokawa #include <sys/kernel.h> 43b018dcd1SHidetoshi Shimokawa #else 44b018dcd1SHidetoshi Shimokawa #include <netinet/in.h> 45b018dcd1SHidetoshi Shimokawa #include <fcntl.h> 46b018dcd1SHidetoshi Shimokawa #include <stdio.h> 47b018dcd1SHidetoshi Shimokawa #include <err.h> 48b018dcd1SHidetoshi Shimokawa #include <stdlib.h> 49b018dcd1SHidetoshi Shimokawa #include <string.h> 50b018dcd1SHidetoshi Shimokawa #endif 51b018dcd1SHidetoshi Shimokawa 52b018dcd1SHidetoshi Shimokawa void 53b018dcd1SHidetoshi Shimokawa crom_init_context(struct crom_context *cc, u_int32_t *p) 54b018dcd1SHidetoshi Shimokawa { 55b018dcd1SHidetoshi Shimokawa struct csrhdr *hdr; 56b018dcd1SHidetoshi Shimokawa 57b018dcd1SHidetoshi Shimokawa hdr = (struct csrhdr *)p; 58b018dcd1SHidetoshi Shimokawa if (hdr->info_len == 1) { 59b018dcd1SHidetoshi Shimokawa /* minimum ROM */ 60b018dcd1SHidetoshi Shimokawa cc->depth = -1; 61b018dcd1SHidetoshi Shimokawa } 62b018dcd1SHidetoshi Shimokawa p += 1 + hdr->info_len; 63b018dcd1SHidetoshi Shimokawa cc->depth = 0; 64b018dcd1SHidetoshi Shimokawa cc->stack[0].dir = (struct csrdirectory *)p; 65b018dcd1SHidetoshi Shimokawa cc->stack[0].index = 0; 66b018dcd1SHidetoshi Shimokawa } 67b018dcd1SHidetoshi Shimokawa 68b018dcd1SHidetoshi Shimokawa struct csrreg * 69b018dcd1SHidetoshi Shimokawa crom_get(struct crom_context *cc) 70b018dcd1SHidetoshi Shimokawa { 71b018dcd1SHidetoshi Shimokawa struct crom_ptr *ptr; 72b018dcd1SHidetoshi Shimokawa 73b018dcd1SHidetoshi Shimokawa ptr = &cc->stack[cc->depth]; 74b018dcd1SHidetoshi Shimokawa return (&ptr->dir->entry[ptr->index]); 75b018dcd1SHidetoshi Shimokawa } 76b018dcd1SHidetoshi Shimokawa 77b018dcd1SHidetoshi Shimokawa void 78b018dcd1SHidetoshi Shimokawa crom_next(struct crom_context *cc) 79b018dcd1SHidetoshi Shimokawa { 80b018dcd1SHidetoshi Shimokawa struct crom_ptr *ptr; 81b018dcd1SHidetoshi Shimokawa struct csrreg *reg; 82b018dcd1SHidetoshi Shimokawa 83b018dcd1SHidetoshi Shimokawa if (cc->depth < 0) 84b018dcd1SHidetoshi Shimokawa return; 85b018dcd1SHidetoshi Shimokawa reg = crom_get(cc); 86b018dcd1SHidetoshi Shimokawa if ((reg->key & CSRTYPE_MASK) == CSRTYPE_D) { 87b018dcd1SHidetoshi Shimokawa cc->depth ++; 88b018dcd1SHidetoshi Shimokawa if (cc->depth > CROM_MAX_DEPTH) { 89b018dcd1SHidetoshi Shimokawa printf("crom_next: too deep\n"); 90b018dcd1SHidetoshi Shimokawa cc->depth --; 91b018dcd1SHidetoshi Shimokawa goto again; 92b018dcd1SHidetoshi Shimokawa } 937ddbf617SHidetoshi Shimokawa ptr = &cc->stack[cc->depth]; 947ddbf617SHidetoshi Shimokawa ptr->dir = (struct csrdirectory *) (reg + reg->val); 957ddbf617SHidetoshi Shimokawa ptr->index = 0; 967ddbf617SHidetoshi Shimokawa goto check; 97b018dcd1SHidetoshi Shimokawa } 98b018dcd1SHidetoshi Shimokawa again: 99b018dcd1SHidetoshi Shimokawa ptr = &cc->stack[cc->depth]; 100b018dcd1SHidetoshi Shimokawa ptr->index ++; 1017ddbf617SHidetoshi Shimokawa check: 102b018dcd1SHidetoshi Shimokawa if (ptr->index < ptr->dir->crc_len) 103b018dcd1SHidetoshi Shimokawa return; 104b018dcd1SHidetoshi Shimokawa if (cc->depth > 0) { 105b018dcd1SHidetoshi Shimokawa cc->depth--; 106b018dcd1SHidetoshi Shimokawa goto again; 107b018dcd1SHidetoshi Shimokawa } 108b018dcd1SHidetoshi Shimokawa /* no more data */ 109b018dcd1SHidetoshi Shimokawa cc->depth = -1; 110b018dcd1SHidetoshi Shimokawa } 111b018dcd1SHidetoshi Shimokawa 112b018dcd1SHidetoshi Shimokawa 113b018dcd1SHidetoshi Shimokawa struct csrreg * 114b018dcd1SHidetoshi Shimokawa crom_search_key(struct crom_context *cc, u_int8_t key) 115b018dcd1SHidetoshi Shimokawa { 116b018dcd1SHidetoshi Shimokawa struct csrreg *reg; 117b018dcd1SHidetoshi Shimokawa 118b018dcd1SHidetoshi Shimokawa while(cc->depth >= 0) { 119b018dcd1SHidetoshi Shimokawa reg = crom_get(cc); 120b018dcd1SHidetoshi Shimokawa if (reg->key == key) 121b018dcd1SHidetoshi Shimokawa return reg; 122b018dcd1SHidetoshi Shimokawa crom_next(cc); 123b018dcd1SHidetoshi Shimokawa } 124b018dcd1SHidetoshi Shimokawa return NULL; 125b018dcd1SHidetoshi Shimokawa } 126b018dcd1SHidetoshi Shimokawa 127b018dcd1SHidetoshi Shimokawa void 128b018dcd1SHidetoshi Shimokawa crom_parse_text(struct crom_context *cc, char *buf, int len) 129b018dcd1SHidetoshi Shimokawa { 130b018dcd1SHidetoshi Shimokawa struct csrreg *reg; 131b018dcd1SHidetoshi Shimokawa struct csrtext *textleaf; 132b018dcd1SHidetoshi Shimokawa u_int32_t *bp; 133b018dcd1SHidetoshi Shimokawa int i, qlen; 134b018dcd1SHidetoshi Shimokawa static char *nullstr = "(null)"; 135b018dcd1SHidetoshi Shimokawa 136b018dcd1SHidetoshi Shimokawa reg = crom_get(cc); 137b018dcd1SHidetoshi Shimokawa if (reg->key != CROM_TEXTLEAF) { 138b018dcd1SHidetoshi Shimokawa strncpy(buf, nullstr, len); 139b018dcd1SHidetoshi Shimokawa return; 140b018dcd1SHidetoshi Shimokawa } 141b018dcd1SHidetoshi Shimokawa textleaf = (struct csrtext *)(reg + reg->val); 142b018dcd1SHidetoshi Shimokawa 143b018dcd1SHidetoshi Shimokawa /* XXX should check spec and type */ 144b018dcd1SHidetoshi Shimokawa 145b018dcd1SHidetoshi Shimokawa bp = (u_int32_t *)&buf[0]; 146b018dcd1SHidetoshi Shimokawa qlen = textleaf->crc_len - 2; 147b018dcd1SHidetoshi Shimokawa if (len < qlen * 4) 148b018dcd1SHidetoshi Shimokawa qlen = len/4; 149b018dcd1SHidetoshi Shimokawa for (i = 0; i < qlen; i ++) 150b018dcd1SHidetoshi Shimokawa *bp++ = ntohl(textleaf->text[i]); 151b018dcd1SHidetoshi Shimokawa /* make sure to terminate the string */ 152b018dcd1SHidetoshi Shimokawa if (len <= qlen * 4) 153b018dcd1SHidetoshi Shimokawa buf[len - 1] = 0; 154b018dcd1SHidetoshi Shimokawa else 155b018dcd1SHidetoshi Shimokawa buf[qlen * 4] = 0; 156b018dcd1SHidetoshi Shimokawa } 157b018dcd1SHidetoshi Shimokawa 158b018dcd1SHidetoshi Shimokawa u_int16_t 159b018dcd1SHidetoshi Shimokawa crom_crc(u_int32_t *ptr, int len) 160b018dcd1SHidetoshi Shimokawa { 161b018dcd1SHidetoshi Shimokawa int i, shift; 162b018dcd1SHidetoshi Shimokawa u_int32_t data, sum, crc = 0; 163b018dcd1SHidetoshi Shimokawa 164b018dcd1SHidetoshi Shimokawa for (i = 0; i < len; i++) { 165b018dcd1SHidetoshi Shimokawa data = ptr[i]; 166b018dcd1SHidetoshi Shimokawa for (shift = 28; shift >= 0; shift -= 4) { 167b018dcd1SHidetoshi Shimokawa sum = ((crc >> 12) ^ (data >> shift)) & 0xf; 168b018dcd1SHidetoshi Shimokawa crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; 169b018dcd1SHidetoshi Shimokawa } 170b018dcd1SHidetoshi Shimokawa crc &= 0xffff; 171b018dcd1SHidetoshi Shimokawa } 172b018dcd1SHidetoshi Shimokawa return((u_int16_t) crc); 173b018dcd1SHidetoshi Shimokawa } 174b018dcd1SHidetoshi Shimokawa 175b018dcd1SHidetoshi Shimokawa #ifndef _KERNEL 176b018dcd1SHidetoshi Shimokawa char * 177b018dcd1SHidetoshi Shimokawa crom_desc(struct crom_context *cc, char *buf, int len) 178b018dcd1SHidetoshi Shimokawa { 179b018dcd1SHidetoshi Shimokawa struct csrreg *reg; 180b018dcd1SHidetoshi Shimokawa struct csrdirectory *dir; 181b018dcd1SHidetoshi Shimokawa char *desc; 182b018dcd1SHidetoshi Shimokawa 183b018dcd1SHidetoshi Shimokawa reg = crom_get(cc); 184b018dcd1SHidetoshi Shimokawa switch (reg->key & CSRTYPE_MASK) { 185b018dcd1SHidetoshi Shimokawa case CSRTYPE_I: 186b018dcd1SHidetoshi Shimokawa snprintf(buf, len, "%d", reg->val); 187b018dcd1SHidetoshi Shimokawa break; 188b018dcd1SHidetoshi Shimokawa case CSRTYPE_L: 189b018dcd1SHidetoshi Shimokawa case CSRTYPE_C: 190b018dcd1SHidetoshi Shimokawa snprintf(buf, len, "offset=0x%04x(%d)", reg->val, reg->val); 191b018dcd1SHidetoshi Shimokawa break; 192b018dcd1SHidetoshi Shimokawa case CSRTYPE_D: 193b018dcd1SHidetoshi Shimokawa dir = (struct csrdirectory *) (reg + reg->val); 194b018dcd1SHidetoshi Shimokawa snprintf(buf, len, "len=0x%04x(%d) crc=0x%04x", 195b018dcd1SHidetoshi Shimokawa dir->crc_len, dir->crc_len, dir->crc); 196b018dcd1SHidetoshi Shimokawa } 197b018dcd1SHidetoshi Shimokawa switch (reg->key) { 198b018dcd1SHidetoshi Shimokawa case 0x03: 199b018dcd1SHidetoshi Shimokawa desc = "module_vendor_ID"; 200b018dcd1SHidetoshi Shimokawa break; 201b018dcd1SHidetoshi Shimokawa case 0x04: 202b018dcd1SHidetoshi Shimokawa desc = "hardware_version"; 203b018dcd1SHidetoshi Shimokawa break; 204b018dcd1SHidetoshi Shimokawa case 0x0c: 205b018dcd1SHidetoshi Shimokawa desc = "node_capabilities"; 206b018dcd1SHidetoshi Shimokawa break; 207b018dcd1SHidetoshi Shimokawa case 0x12: 208b018dcd1SHidetoshi Shimokawa desc = "unit_spec_ID"; 209b018dcd1SHidetoshi Shimokawa break; 210b018dcd1SHidetoshi Shimokawa case 0x13: 211b018dcd1SHidetoshi Shimokawa desc = "unit_sw_version"; 212b018dcd1SHidetoshi Shimokawa break; 213b018dcd1SHidetoshi Shimokawa case 0x14: 214b018dcd1SHidetoshi Shimokawa desc = "logical_unit_number"; 215b018dcd1SHidetoshi Shimokawa break; 216b018dcd1SHidetoshi Shimokawa case 0x17: 217b018dcd1SHidetoshi Shimokawa desc = "model_ID"; 218b018dcd1SHidetoshi Shimokawa break; 219b018dcd1SHidetoshi Shimokawa case 0x38: 220b018dcd1SHidetoshi Shimokawa desc = "command_set_spec_ID"; 221b018dcd1SHidetoshi Shimokawa break; 222b018dcd1SHidetoshi Shimokawa case 0x39: 223b018dcd1SHidetoshi Shimokawa desc = "command_set"; 224b018dcd1SHidetoshi Shimokawa break; 225b018dcd1SHidetoshi Shimokawa case 0x3a: 226b018dcd1SHidetoshi Shimokawa desc = "unit_characteristics"; 227b018dcd1SHidetoshi Shimokawa break; 228b018dcd1SHidetoshi Shimokawa case 0x3b: 229b018dcd1SHidetoshi Shimokawa desc = "command_set_revision"; 230b018dcd1SHidetoshi Shimokawa break; 231b018dcd1SHidetoshi Shimokawa case 0x3c: 232b018dcd1SHidetoshi Shimokawa desc = "firmware_revision"; 233b018dcd1SHidetoshi Shimokawa break; 234b018dcd1SHidetoshi Shimokawa case 0x3d: 235b018dcd1SHidetoshi Shimokawa desc = "reconnect_timeout"; 236b018dcd1SHidetoshi Shimokawa break; 237b018dcd1SHidetoshi Shimokawa case 0x54: 238b018dcd1SHidetoshi Shimokawa desc = "management_agent"; 239b018dcd1SHidetoshi Shimokawa break; 240b018dcd1SHidetoshi Shimokawa case 0x81: 241b018dcd1SHidetoshi Shimokawa desc = "text_leaf"; 242b018dcd1SHidetoshi Shimokawa crom_parse_text(cc, buf, len); 243b018dcd1SHidetoshi Shimokawa break; 244b018dcd1SHidetoshi Shimokawa case 0xd1: 245b018dcd1SHidetoshi Shimokawa desc = "unit_directory"; 246b018dcd1SHidetoshi Shimokawa break; 247b018dcd1SHidetoshi Shimokawa case 0xd4: 248b018dcd1SHidetoshi Shimokawa desc = "logical_unit_directory"; 249b018dcd1SHidetoshi Shimokawa break; 250b018dcd1SHidetoshi Shimokawa default: 251b018dcd1SHidetoshi Shimokawa desc = "unknown"; 252b018dcd1SHidetoshi Shimokawa } 253b018dcd1SHidetoshi Shimokawa return desc; 254b018dcd1SHidetoshi Shimokawa } 255b018dcd1SHidetoshi Shimokawa #endif 256