aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files5
-rw-r--r--sys/dev/firewire/fwcrom.c254
-rw-r--r--sys/dev/firewire/sbp.c52
-rw-r--r--sys/modules/firewire/firewire/Makefile2
4 files changed, 295 insertions, 18 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 5a560286b21d..484f5f714bff 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -384,10 +384,11 @@ dev/fe/if_fe.c optional fe
dev/fe/if_fe_pccard.c optional fe card
dev/fe/if_fe_pccard.c optional fe pccard
dev/firewire/firewire.c optional firewire
+dev/firewire/fwcrom.c optional firewire
+dev/firewire/fwdev.c optional firewire
+dev/firewire/fwmem.c optional firewire
dev/firewire/fwohci.c optional firewire
dev/firewire/fwohci_pci.c optional firewire pci
-dev/firewire/fwmem.c optional firewire
-dev/firewire/fwdev.c optional firewire
dev/firewire/if_fwe.c optional fwe
dev/firewire/sbp.c optional sbp
dev/fxp/if_fxp.c optional fxp
diff --git a/sys/dev/firewire/fwcrom.c b/sys/dev/firewire/fwcrom.c
new file mode 100644
index 000000000000..34e16746dc76
--- /dev/null
+++ b/sys/dev/firewire/fwcrom.c
@@ -0,0 +1,254 @@
+/*
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <dev/firewire/firewire.h>
+#include <dev/firewire/iec13213.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#else
+#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);
+}
+
+#ifndef _KERNEL
+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;
+}
+#endif
diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c
index 6ddb863c95a5..2317e99ce81d 100644
--- a/sys/dev/firewire/sbp.c
+++ b/sys/dev/firewire/sbp.c
@@ -253,8 +253,9 @@ struct sbp_dev{
#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 @@ END_DEBUG
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 @@ sbp_show_sdev_info(struct sbp_dev *sdev, int new)
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 @@ sbp_show_sdev_info(struct sbp_dev *sdev, int new)
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 @@ END_DEBUG
}
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 directories 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 @@ END_DEBUG
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;
}
@@ -1097,7 +1119,7 @@ END_DEBUG
fp->mode.wreqb.dest_lo = htonl(sdev->target->mgm_lo);
fp->mode.wreqb.len = htons(8);
fp->mode.wreqb.extcode = 0;
- fp->mode.wreqb.payload[0] = htonl(((sdev->target->sbp->fd.fc->nodeid | FWLOCALBUS )<< 16));
+ fp->mode.wreqb.payload[0] = htonl(nid << 16);
fp->mode.wreqb.payload[1] = htonl(vtophys(&ocb->orb[0]));
sbp_enqueue_ocb(sdev, ocb);
diff --git a/sys/modules/firewire/firewire/Makefile b/sys/modules/firewire/firewire/Makefile
index aaa75983afa3..01771f76e9ab 100644
--- a/sys/modules/firewire/firewire/Makefile
+++ b/sys/modules/firewire/firewire/Makefile
@@ -9,7 +9,7 @@ SRCS = bus_if.h device_if.h pci_if.h \
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
+ fwcrom.c fwdev.c fwmem.c fwmem.h
EXPORT_SYMS= YES