Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 Dec 2002 18:19:15 +0900
From:      Hidetoshi Shimokawa <simokawa@sat.t.u-tokyo.ac.jp>
To:        Jaye Mathisen <mrcpu@internetcds.com>, Chuck McCrobie <mccrobie2000@yahoo.com>
Cc:        freebsd-firewire@freebsd.org
Subject:   Re: Problem recognizing second disk in 2 disk firewire enclosure.
Message-ID:  <ybssmwh5gj0.wl@ett.sat.t.u-tokyo.ac.jp>
In-Reply-To: <ybswuly7gc1.wl@ett.sat.t.u-tokyo.ac.jp>
References:  <20021225053353.GA1284@backmaster.cdsnet.net> <20021224095328.GZ1284@backmaster.cdsnet.net> <ybsznqu7pko.wl@ett.sat.t.u-tokyo.ac.jp> <ybswuly7gc1.wl@ett.sat.t.u-tokyo.ac.jp>

next in thread | previous in thread | raw e-mail | index | archive | help
At Wed, 25 Dec 2002 15:39:10 +0900,
Hidetoshi Shimokawa wrote:
> It actually has 2 LUNs. Sbp.c has basic support for multiple LUNs but
> getcsrdata() in firewire.c is not powerfull enough to parse multiple
> LUNs. I'll improve config ROM support in kernel.

Please try the attached patch which should make sbp.c to find
more than one LUN.

/\ Hidetoshi Shimokawa
\/  simokawa@sat.t.u-tokyo.ac.jp
PGP public key: http://www.sat.t.u-tokyo.ac.jp/~simokawa/pgp.html

Index: conf/files
===================================================================
RCS file: /pub/FreeBSD-CVS/src/sys/conf/files,v
retrieving revision 1.340.2.127
diff -u -r1.340.2.127 files
--- conf/files	26 Dec 2002 06:29:44 -0000	1.340.2.127
+++ conf/files	29 Dec 2002 09:12:39 -0000
@@ -213,6 +213,7 @@
 dev/firewire/fwohci_pci.c	optional firewire pci
 dev/firewire/fwmem.c	optional firewire
 dev/firewire/fwdev.c	optional firewire
+dev/firewire/crom.c	optional firewire
 dev/firewire/if_fwe.c	optional fwe
 dev/firewire/sbp.c	optional sbp
 dev/fxp/if_fxp.c	optional fxp
Index: dev/firewire/iec13213.h
===================================================================
RCS file: /pub/FreeBSD-CVS/src/sys/dev/firewire/iec13213.h,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 iec13213.h
--- dev/firewire/iec13213.h	3 Nov 2002 10:58:18 -0000	1.1.2.1
+++ dev/firewire/iec13213.h	29 Dec 2002 08:58:40 -0000
@@ -33,14 +33,50 @@
  * $FreeBSD$
  *
  */
+
+#define CSRTYPE_SHIFT	6
+#define CSRTYPE_MASK	(3 << CSRTYPE_SHIFT)
+#define CSRTYPE_I	(0 << CSRTYPE_SHIFT) /* Immediate */
+#define CSRTYPE_C	(1 << CSRTYPE_SHIFT) /* CSR offset */
+#define CSRTYPE_L	(2 << CSRTYPE_SHIFT) /* Leaf */
+#define CSRTYPE_D	(3 << CSRTYPE_SHIFT) /* Directory */
+
+#define CSRKEY_MASK	0x3f
+#define CSRKEY_DESC	0x01 /* Descriptor */
+#define CSRKEY_BDINFO	0x02 /* Bus_Dependent_Info */
+#define CSRKEY_VENDOR	0x03 /* Vendor */
+#define CSRKEY_HW	0x04 /* Hardware_Version */
+#define CSRKEY_MODULE	0x07 /* Module */
+#define CSRKEY_NCAP	0x0c /* Node_Capabilities */
+#define CSRKEY_EUI64	0x0d /* EUI_64 */
+#define CSRKEY_UNIT	0x11 /* Unit */
+#define CSRKEY_SPEC	0x12 /* Specifier_ID */
+#define CSRKEY_VER	0x13 /* Version */
+#define CSRKEY_DINFO	0x14 /* Dependent_Info */
+#define CSRKEY_ULOC	0x15 /* Unit_Location */
+#define CSRKEY_MODEL	0x17 /* Model */
+#define CSRKEY_INST	0x18 /* Instance */
+#define CSRKEY_KEYW	0x19 /* Keyword */
+#define CSRKEY_FEAT	0x1a /* Feature */
+#define CSRKEY_EROM	0x1b /* Extended_ROM */
+#define CSRKEY_EKSID	0x1c /* Extended_Key_Specifier_ID */
+#define CSRKEY_EKEY	0x1d /* Extended_Key */
+#define CSRKEY_EDATA	0x1e /* Extended_Data */
+#define CSRKEY_MDESC	0x1f /* Modifiable_Descriptor */
+#define CSRKEY_DID	0x20 /* Directory_ID */
+#define CSRKEY_REV	0x21 /* Revision */
+
+#define CROM_TEXTLEAF	(CSRTYPE_L | CSRKEY_DESC)	/* 0x81 */
+#define CROM_LUN	(CSRTYPE_I | CSRKEY_DINFO)	/* 0x14 */
+
+/* ???
 #define CSRKEY_MVID	0x3
-#define CSRKEY_NCAP	0xc
 #define CSRKEY_NUNQ	0x8d
 #define CSRKEY_NPWR	0x30
-#define CSRKEY_SPEC	0x12
+*/
+
 #define	CSRVAL_1394TA	0x00a02d
 #define	CSRVAL_ANSIT10	0x00609e
-#define CSRKEY_VER	0x13
 #define	CSR_PROTAVC	0x010001
 #define	CSR_PROTCAL	0x010002
 #define	CSR_PROTEHS	0x010004
@@ -70,8 +106,8 @@
 struct csrtext {
 	u_int32_t crc:16,
 		  crc_len:16;
-	u_int32_t spec_id:16,
-		  spec_type:16;
+	u_int32_t spec_id:24,
+		  spec_type:8;
 	u_int32_t lang_id;
 	u_int32_t text[0];
 };
@@ -90,3 +126,22 @@
 		  v_id:24;
 	u_int32_t c_id_lo;
 };
+
+#define CROM_MAX_DEPTH	10
+struct crom_ptr {
+	struct csrdirectory *dir;
+	int index;
+};
+
+struct crom_context {
+	int depth;
+	struct crom_ptr stack[CROM_MAX_DEPTH];
+};
+
+void crom_init_context(struct crom_context *, u_int32_t *);
+struct csrreg *crom_get(struct crom_context *);
+void crom_next(struct crom_context *);
+void crom_parse_text(struct crom_context *, char *, int);
+u_int16_t crom_crc(u_int32_t *r, int);
+char *crom_desc(struct crom_context *, char *, int);
+struct csrreg *crom_search_key(struct crom_context *, u_int8_t);
Index: dev/firewire/sbp.c
===================================================================
RCS file: /pub/FreeBSD-CVS/src/sys/dev/firewire/sbp.c,v
retrieving revision 1.5.2.4
diff -u -r1.5.2.4 sbp.c
--- dev/firewire/sbp.c	26 Dec 2002 09:10:47 -0000	1.5.2.4
+++ dev/firewire/sbp.c	29 Dec 2002 08:58:40 -0000
@@ -253,8 +253,9 @@
 #define SBP_DEV_ATTACHED	5	/* in operation */
 #define SBP_DEV_DEAD		6	/* unavailable unit */
 #define SBP_DEV_RETRY		7	/* unavailable unit */
-	int status;
-	int lun_id;
+	u_int8_t status;
+	u_int8_t type;
+	u_int16_t lun_id;
 	struct cam_path *path;
 	struct sbp_target *target;
 	struct sbp_login_res login;
@@ -388,7 +389,6 @@
 static void
 sbp_show_sdev_info(struct sbp_dev *sdev, int new)
 {
-	int lun;
 	struct fw_device *fwdev;
 
 	printf("%s:%d:%d ",
@@ -400,11 +400,10 @@
 		return;
 	}
 	fwdev = sdev->target->fwdev;
-	lun = getcsrdata(fwdev, 0x14);
 	printf("ordered:%d type:%d EUI:%08x%08x node:%d "
 		"speed:%d maxrec:%d",
-		(lun & 0x00400000) >> 22,
-		(lun & 0x001f0000) >> 16,
+		(sdev->type & 0x40) >> 6,
+		(sdev->type & 0x1f),
 		fwdev->eui.hi,
 		fwdev->eui.lo,
 		fwdev->dst,
@@ -422,9 +421,11 @@
 static struct sbp_target *
 sbp_alloc_target(struct sbp_softc *sbp, struct fw_device *fwdev)
 {
-	int i, lun;
+	int i, maxlun, lun;
 	struct sbp_target *target;
 	struct sbp_dev *sdev;
+	struct crom_context cc;
+	struct csrreg *reg;
 
 SBP_DEBUG(1)
 	printf("sbp_alloc_target\n");
@@ -448,10 +449,24 @@
 	}
 	target->mgm_hi = 0xffff;
 	target->mgm_lo = 0xf0000000 | target->mgm_lo << 2;
-	/* XXX should probe all luns */
 	/* XXX num_lun may be changed. realloc luns? */
-	lun = getcsrdata(target->fwdev, 0x14) & 0xff;
-	target->num_lun = lun + 1;
+	crom_init_context(&cc, target->fwdev->csrrom);
+	/* XXX shoud parse appropriate unit directory only */
+	maxlun = -1;
+	while (cc.depth >= 0) {
+		reg = crom_search_key(&cc, CROM_LUN);
+		if (reg == NULL)
+			break;
+		lun = reg->val & 0xff;
+		printf("lun %d found\n", lun);
+		if (maxlun < lun)
+			maxlun = lun;
+		crom_next(&cc);
+	}
+	target->num_lun = maxlun + 1;
+	if (maxlun < 0) {
+		printf("no lun found!\n");
+	}
 	target->luns = (struct sbp_dev *) malloc(
 				sizeof(struct sbp_dev) * target->num_lun, 
 				M_SBP, M_NOWAIT | M_ZERO);
@@ -460,10 +475,17 @@
 		sdev->lun_id = i;
 		sdev->target = target;
 		STAILQ_INIT(&sdev->ocbs);
-		if (i == lun)
-			sdev->status = SBP_DEV_RESET;
-		else
-			sdev->status = SBP_DEV_DEAD;
+		sdev->status = SBP_DEV_DEAD;
+	}
+	crom_init_context(&cc, target->fwdev->csrrom);
+	while (cc.depth >= 0) {
+		reg = crom_search_key(&cc, CROM_LUN);
+		if (reg == NULL)
+			break;
+		lun = reg->val & 0xff;
+		target->luns[lun].status = SBP_DEV_RESET;
+		target->luns[lun].type = (reg->val & 0x0f00) >> 16;
+		crom_next(&cc);
 	}
 	return target;
 }
Index: modules/firewire/firewire/Makefile
===================================================================
RCS file: /pub/FreeBSD-CVS/src/sys/modules/firewire/firewire/Makefile,v
retrieving revision 1.2.2.2
diff -u -r1.2.2.2 Makefile
--- modules/firewire/firewire/Makefile	26 Dec 2002 04:27:33 -0000	1.2.2.2
+++ modules/firewire/firewire/Makefile	29 Dec 2002 09:01:27 -0000
@@ -9,7 +9,7 @@
 	  firewire.c firewire.h firewire_phy.h firewirebusreg.h firewirereg.h \
 	  fwohci.c fwohci_pci.c fwohcireg.h fwohcivar.h \
 	  iec13213.h iec68113.h \
-	  fwmem.c fwmem.h fwdev.c
+	  fwmem.c fwmem.h fwdev.c crom.c
 
 EXPORT_SYMS= YES
 
--- /dev/null	Sun Dec 29 18:10:00 2002
+++ dev/firewire/crom.c	Sun Dec 29 18:00:32 2002
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2002
+ * 	Hidetoshi Shimokawa. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *
+ *	This product includes software developed by Hidetoshi Shimokawa.
+ *
+ * 4. Neither the name of the author nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $Id: crom.c,v 1.2 2002/12/29 08:55:15 simokawa Exp $
+ */
+
+#include <sys/param.h>
+#include <dev/firewire/firewire.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <dev/firewire/iec13213.h>
+#include <sys/kernel.h>
+#else
+#include "iec13213.h"
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+void
+crom_init_context(struct crom_context *cc, u_int32_t *p)
+{
+	struct csrhdr *hdr;
+
+	hdr = (struct csrhdr *)p;
+	if (hdr->info_len == 1) {
+		/* minimum ROM */
+		cc->depth = -1;
+	}
+	p += 1 + hdr->info_len;
+	cc->depth = 0;
+	cc->stack[0].dir = (struct csrdirectory *)p;
+	cc->stack[0].index = 0;
+}
+
+struct csrreg *
+crom_get(struct crom_context *cc)
+{
+	struct crom_ptr *ptr;
+
+	ptr = &cc->stack[cc->depth];
+	return (&ptr->dir->entry[ptr->index]);
+}
+
+void
+crom_next(struct crom_context *cc)
+{
+	struct crom_ptr *ptr;
+	struct csrreg *reg;
+
+	if (cc->depth < 0)
+		return;
+	reg = crom_get(cc);
+	if ((reg->key & CSRTYPE_MASK) == CSRTYPE_D) {
+		cc->depth ++;
+		if (cc->depth > CROM_MAX_DEPTH) {
+			printf("crom_next: too deep\n");
+			cc->depth --;
+			goto again;
+		}
+		cc->stack[cc->depth].dir = (struct csrdirectory *)
+							(reg + reg->val);
+		cc->stack[cc->depth].index = 0;
+		return;
+	}
+again:
+	ptr = &cc->stack[cc->depth];
+	ptr->index ++;
+	if (ptr->index < ptr->dir->crc_len)
+		return;
+	if (cc->depth > 0) {
+		cc->depth--;
+		goto again;
+	}
+	/* no more data */
+	cc->depth = -1;
+}
+
+
+struct csrreg *
+crom_search_key(struct crom_context *cc, u_int8_t key)
+{
+	struct csrreg *reg;
+
+	while(cc->depth >= 0) {
+		reg = crom_get(cc);
+		if (reg->key == key)
+			return reg;
+		crom_next(cc);
+	}
+	return NULL;
+}
+
+void
+crom_parse_text(struct crom_context *cc, char *buf, int len)
+{
+	struct csrreg *reg;
+	struct csrtext *textleaf;
+	u_int32_t *bp;
+	int i, qlen;
+	static char *nullstr = "(null)";
+
+	reg = crom_get(cc);
+	if (reg->key != CROM_TEXTLEAF) {
+		strncpy(buf, nullstr, len);
+		return;
+	}
+	textleaf = (struct csrtext *)(reg + reg->val);
+
+	/* XXX should check spec and type */
+
+	bp = (u_int32_t *)&buf[0];
+	qlen = textleaf->crc_len - 2;
+	if (len < qlen * 4)
+		qlen = len/4;
+	for (i = 0; i < qlen; i ++)
+		*bp++ = ntohl(textleaf->text[i]);
+	/* make sure to terminate the string */
+	if (len <= qlen * 4)
+		buf[len - 1] = 0;
+	else
+		buf[qlen * 4] = 0;
+}
+
+u_int16_t
+crom_crc(u_int32_t *ptr, int len)
+{
+	int i, shift;
+	u_int32_t data, sum, crc = 0;
+
+	for (i = 0; i < len; i++) {
+		data = ptr[i];
+		for (shift = 28; shift >= 0; shift -= 4) {
+			sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
+			crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
+		}
+		crc &= 0xffff;
+	}
+	return((u_int16_t) crc);
+}
+
+char *
+crom_desc(struct crom_context *cc, char *buf, int len)
+{
+	struct csrreg *reg;
+	struct csrdirectory *dir;
+	char *desc;
+
+	reg = crom_get(cc);
+	switch (reg->key & CSRTYPE_MASK) {
+	case CSRTYPE_I:
+		snprintf(buf, len, "%d", reg->val);
+		break;
+	case CSRTYPE_L:
+	case CSRTYPE_C:
+		snprintf(buf, len, "offset=0x%04x(%d)", reg->val, reg->val);
+		break;
+	case CSRTYPE_D:
+		dir = (struct csrdirectory *) (reg + reg->val);
+		snprintf(buf, len, "len=0x%04x(%d) crc=0x%04x",
+			dir->crc_len, dir->crc_len, dir->crc);
+	}
+	switch (reg->key) {
+	case 0x03:
+		desc = "module_vendor_ID";
+		break;
+	case 0x04:
+		desc = "hardware_version";
+		break;
+	case 0x0c:
+		desc = "node_capabilities";
+		break;
+	case 0x12:
+		desc = "unit_spec_ID";
+		break;
+	case 0x13:
+		desc = "unit_sw_version";
+		break;
+	case 0x14:
+		desc = "logical_unit_number";
+		break;
+	case 0x17:
+		desc = "model_ID";
+		break;
+	case 0x38:
+		desc = "command_set_spec_ID";
+		break;
+	case 0x39:
+		desc = "command_set";
+		break;
+	case 0x3a:
+		desc = "unit_characteristics";
+		break;
+	case 0x3b:
+		desc = "command_set_revision";
+		break;
+	case 0x3c:
+		desc = "firmware_revision";
+		break;
+	case 0x3d:
+		desc = "reconnect_timeout";
+		break;
+	case 0x54:
+		desc = "management_agent";
+		break;
+	case 0x81:
+		desc = "text_leaf";
+		crom_parse_text(cc, buf, len);
+		break;
+	case 0xd1:
+		desc = "unit_directory";
+		break;
+	case 0xd4:
+		desc = "logical_unit_directory";
+		break;
+	default:
+		desc = "unknown";
+	}
+	return desc;
+}


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-firewire" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?ybssmwh5gj0.wl>