summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsimokawa <simokawa@FreeBSD.org>2003-04-26 16:45:40 +0000
committersimokawa <simokawa@FreeBSD.org>2003-04-26 16:45:40 +0000
commitb380739760e705fd780f133e9899b3d27db7ad5f (patch)
tree415c88f229ca2c29c533d24164e2cb651fb3d627 /sys
parent4d37b34b62b2f79aebba964702976feae37ff78a (diff)
downloadFreeBSD-src-b380739760e705fd780f133e9899b3d27db7ad5f.zip
FreeBSD-src-b380739760e705fd780f133e9899b3d27db7ad5f.tar.gz
- Improve configuration ROM parser for multiple unit directory.
- Remove getcsrdata(). - Don't print device type, this can be obtained by fwcontrol. Tested with: Maxtor 5000XT Tested by: Daniel O'Connor <doconnor@gsoft.com.au>
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/firewire/firewire.c87
-rw-r--r--sys/dev/firewire/firewirereg.h1
-rw-r--r--sys/dev/firewire/fwcrom.c114
-rw-r--r--sys/dev/firewire/iec13213.h2
-rw-r--r--sys/dev/firewire/sbp.c84
5 files changed, 139 insertions, 149 deletions
diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c
index eda6650..853c586 100644
--- a/sys/dev/firewire/firewire.c
+++ b/sys/dev/firewire/firewire.c
@@ -1498,25 +1498,6 @@ nextnode:
}
/*
- * To obtain CSR register values.
- */
-u_int32_t
-getcsrdata(struct fw_device *fwdev, u_int8_t key)
-{
- int i;
- struct csrhdr *chdr;
- struct csrreg *creg;
- chdr = (struct csrhdr *)&fwdev->csrrom[0];
- for( i = chdr->info_len + 4; i <= fwdev->rommax - CSRROMOFF; i+=4){
- creg = (struct csrreg *)&fwdev->csrrom[i/4];
- if(creg->key == key){
- return (u_int32_t)creg->val;
- }
- }
- return 0;
-}
-
-/*
* To attach sub-devices layer onto IEEE1394 bus.
*/
static void
@@ -1528,71 +1509,11 @@ fw_attach_dev(struct firewire_comm *fc)
device_t *devlistp;
int devcnt;
struct firewire_dev_comm *fdc;
- u_int32_t spec, ver;
-
- STAILQ_FOREACH(fwdev, &fc->devices, link) {
- if(fwdev->status == FWDEVINIT){
- spec = getcsrdata(fwdev, CSRKEY_SPEC);
- if(spec == 0)
- continue;
- ver = getcsrdata(fwdev, CSRKEY_VER);
- if(ver == 0)
- continue;
- fwdev->maxrec = (fwdev->csrrom[2] >> 12) & 0xf;
-
- device_printf(fc->bdev, "Device ");
- switch(spec){
- case CSRVAL_ANSIT10:
- switch(ver){
- case CSRVAL_T10SBP2:
- printf("SBP-II");
- break;
- default:
- break;
- }
- break;
- case CSRVAL_1394TA:
- switch(ver){
- case CSR_PROTAVC:
- printf("AV/C");
- break;
- case CSR_PROTCAL:
- printf("CAL");
- break;
- case CSR_PROTEHS:
- printf("EHS");
- break;
- case CSR_PROTHAVI:
- printf("HAVi");
- break;
- case CSR_PROTCAM104:
- printf("1394 Cam 1.04");
- break;
- case CSR_PROTCAM120:
- printf("1394 Cam 1.20");
- break;
- case CSR_PROTCAM130:
- printf("1394 Cam 1.30");
- break;
- case CSR_PROTDPP:
- printf("1394 Direct print");
- break;
- case CSR_PROTIICP:
- printf("Industrial & Instrument");
- break;
- default:
- printf("unknown 1394TA");
- break;
- }
- break;
- default:
- printf("unknown spec");
- break;
- }
+
+ STAILQ_FOREACH(fwdev, &fc->devices, link)
+ if (fwdev->status == FWDEVINIT)
fwdev->status = FWDEVATTACHED;
- printf("\n");
- }
- }
+
err = device_get_children(fc->bdev, &devlistp, &devcnt);
if( err != 0 )
return;
diff --git a/sys/dev/firewire/firewirereg.h b/sys/dev/firewire/firewirereg.h
index ebe74f1..3418aac 100644
--- a/sys/dev/firewire/firewirereg.h
+++ b/sys/dev/firewire/firewirereg.h
@@ -273,7 +273,6 @@ struct fw_xfer *fw_xfer_alloc_buf __P((struct malloc_type *, int, int));
void fw_init __P((struct firewire_comm *));
int fw_tbuf_update __P((struct firewire_comm *, int, int));
int fw_rbuf_update __P((struct firewire_comm *, int, int));
-u_int32_t getcsrdata __P((struct fw_device *, u_int8_t));
void fw_asybusy __P((struct fw_xfer *));
int fw_bindadd __P((struct firewire_comm *, struct fw_bind *));
int fw_bindremove __P((struct firewire_comm *, struct fw_bind *));
diff --git a/sys/dev/firewire/fwcrom.c b/sys/dev/firewire/fwcrom.c
index 282a7fd..19dd37f 100644
--- a/sys/dev/firewire/fwcrom.c
+++ b/sys/dev/firewire/fwcrom.c
@@ -63,6 +63,12 @@ crom_init_context(struct crom_context *cc, u_int32_t *p)
cc->depth = -1;
}
p += 1 + hdr->info_len;
+
+ /* check size of root directory */
+ if (((struct csrdirectory *)p)->crc_len == 0) {
+ cc->depth = -1;
+ return;
+ }
cc->depth = 0;
cc->stack[0].dir = (struct csrdirectory *)p;
cc->stack[0].index = 0;
@@ -127,6 +133,33 @@ crom_search_key(struct crom_context *cc, u_int8_t key)
return NULL;
}
+int
+crom_has_specver(u_int32_t *p, u_int32_t spec, u_int32_t ver)
+{
+ struct csrreg *reg;
+ struct crom_context c, *cc;
+ int state = 0;
+
+ cc = &c;
+ crom_init_context(cc, p);
+ while(cc->depth >= 0) {
+ reg = crom_get(cc);
+ if (state == 0) {
+ if (reg->key == CSRKEY_SPEC && reg->val == spec)
+ state = 1;
+ else
+ state = 0;
+ } else {
+ if (reg->key == CSRKEY_VER && reg->val == ver)
+ return 1;
+ else
+ state = 0;
+ }
+ crom_next(cc);
+ }
+ return 0;
+}
+
void
crom_parse_text(struct crom_context *cc, char *buf, int len)
{
@@ -136,6 +169,9 @@ crom_parse_text(struct crom_context *cc, char *buf, int len)
int i, qlen;
static char *nullstr = "(null)";
+ if (cc->depth < 0)
+ return;
+
reg = crom_get(cc);
if (reg->key != CROM_TEXTLEAF) {
strncpy(buf, nullstr, len);
@@ -176,34 +212,91 @@ crom_crc(u_int32_t *ptr, int len)
}
#ifndef _KERNEL
+static void
+crom_desc_specver(u_int32_t spec, u_int32_t ver, char *buf, int len)
+{
+ char *s = NULL;
+
+ if (spec == CSRVAL_ANSIT10 || spec == 0) {
+ switch (ver) {
+ case CSRVAL_T10SBP2:
+ s = "SBP-2";
+ break;
+ default:
+ if (spec != 0)
+ s = "unknown ANSIT10";
+ }
+ }
+ if (spec == CSRVAL_1394TA || spec == 0) {
+ switch (ver) {
+ case CSR_PROTAVC:
+ s = "AV/C";
+ break;
+ case CSR_PROTCAL:
+ s = "CAL";
+ break;
+ case CSR_PROTEHS:
+ s = "EHS";
+ break;
+ case CSR_PROTHAVI:
+ s = "HAVi";
+ break;
+ case CSR_PROTCAM104:
+ s = "1394 Cam 1.04";
+ break;
+ case CSR_PROTCAM120:
+ s = "1394 Cam 1.20";
+ break;
+ case CSR_PROTCAM130:
+ s = "1394 Cam 1.30";
+ break;
+ case CSR_PROTDPP:
+ s = "1394 Direct print";
+ break;
+ case CSR_PROTIICP:
+ s = "Industrial & Instrument";
+ break;
+ default:
+ if (spec != 0)
+ s = "unknown 1394TA";
+ }
+ }
+ if (s != NULL)
+ snprintf(buf, len, "%s", s);
+}
+
char *
crom_desc(struct crom_context *cc, char *buf, int len)
{
struct csrreg *reg;
struct csrdirectory *dir;
- char *desc;
+ char *desc, st;
u_int16_t crc;
reg = crom_get(cc);
switch (reg->key & CSRTYPE_MASK) {
case CSRTYPE_I:
- snprintf(buf, len, "%d", reg->val);
+#if 0
+ len -= snprintf(buf, len, "%d", reg->val);
+ buf += strlen(buf);
+#else
+ *buf = '\0';
+#endif
break;
case CSRTYPE_C:
- snprintf(buf, len, "offset=0x%04x(%d)", reg->val, reg->val);
+ len -= snprintf(buf, len, "offset=0x%04x(%d)",
+ reg->val, reg->val);
+ buf += strlen(buf);
break;
case CSRTYPE_L:
/* XXX fall through */
case CSRTYPE_D:
dir = (struct csrdirectory *) (reg + reg->val);
crc = crom_crc((u_int32_t *)&dir->entry[0], dir->crc_len);
- len -= snprintf(buf, len, "len=%d crc=0x%04x",
- dir->crc_len, dir->crc);
- if (crc == dir->crc)
- strncat(buf, "(OK) ", len);
- else
- strncat(buf, "(NG) ", len);
- len -= 5;
+ len -= snprintf(buf, len, "len=%d crc=0x%04x(%s) ",
+ dir->crc_len, dir->crc,
+ (crc == dir->crc) ? "OK" : "NG");
+ buf += strlen(buf);
}
switch (reg->key) {
case 0x03:
@@ -220,6 +313,7 @@ crom_desc(struct crom_context *cc, char *buf, int len)
break;
case 0x13:
desc = "unit_sw_version";
+ crom_desc_specver(0, reg->val, buf, len);
break;
case 0x14:
desc = "logical_unit_number";
diff --git a/sys/dev/firewire/iec13213.h b/sys/dev/firewire/iec13213.h
index efd51aa..25ce305 100644
--- a/sys/dev/firewire/iec13213.h
+++ b/sys/dev/firewire/iec13213.h
@@ -170,6 +170,8 @@ 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);
struct csrreg *crom_search_key(struct crom_context *, u_int8_t);
+int crom_has_specver(u_int32_t *, u_int32_t, u_int32_t);
+
#ifndef _KERNEL
char *crom_desc(struct crom_context *, char *, int);
#endif
diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c
index d27d467..bf9aa6d 100644
--- a/sys/dev/firewire/sbp.c
+++ b/sys/dev/firewire/sbp.c
@@ -526,14 +526,16 @@ END_DEBUG
target->fwdev = fwdev;
target->target_id = i;
/* XXX we may want to reload mgm port after each bus reset */
- if((target->mgm_lo = getcsrdata(fwdev, 0x54)) == 0 ){
- /* bad target */
+ /* XXX there might be multiple management agents */
+ crom_init_context(&cc, target->fwdev->csrrom);
+ reg = crom_search_key(&cc, CROM_MGM);
+ if (reg == NULL || reg->val == 0) {
printf("NULL management address\n");
target->fwdev = NULL;
return NULL;
}
target->mgm_hi = 0xffff;
- target->mgm_lo = 0xf0000000 | target->mgm_lo << 2;
+ target->mgm_lo = 0xf0000000 | (reg->val << 2);
target->mgm_ocb_cur = NULL;
SBP_DEBUG(1)
printf("target:%d mgm_port: %x\n", i, target->mgm_lo);
@@ -619,59 +621,36 @@ END_DEBUG
sbp_free_ocb(sdev, ocb);
}
crom_next(&cc);
- }
- return target;
- }
-
-static void
-sbp_get_text_leaf(struct fw_device *fwdev, int key, char *buf, int len)
-{
- static char *nullstr = "(null)";
- int i, clen, found=0;
- struct csrhdr *chdr;
- struct csrreg *creg;
- u_int32_t *src, *dst;
-
- chdr = (struct csrhdr *)&fwdev->csrrom[0];
- /* skip crom header, bus info and root directory */
- creg = (struct csrreg *)chdr + chdr->info_len + 2;
- /* search unitl the one before the last. */
- for (i = chdr->info_len + 2; i < fwdev->rommax / 4; i++) {
- if((creg++)->key == key){
- found = 1;
- break;
- }
- }
- if (!found || creg->key != CROM_TEXTLEAF) {
- strncpy(buf, nullstr, len);
- return;
}
- src = (u_int32_t *) creg + creg->val;
- clen = ((*src >> 16) - 2) * 4;
- src += 3;
- dst = (u_int32_t *) buf;
- if (len < clen)
- clen = len;
- for (i = 0; i < clen/4; i++)
- *dst++ = htonl(*src++);
- buf[clen] = 0;
+ return target;
}
static void
sbp_probe_lun(struct sbp_dev *sdev)
{
struct fw_device *fwdev;
- int rev;
+ struct crom_context c, *cc = &c;
+ struct csrreg *reg;
- fwdev = sdev->target->fwdev;
bzero(sdev->vendor, sizeof(sdev->vendor));
bzero(sdev->product, sizeof(sdev->product));
- sbp_get_text_leaf(fwdev, 0x03, sdev->vendor, sizeof(sdev->vendor));
- sbp_get_text_leaf(fwdev, 0x17, sdev->product, sizeof(sdev->product));
- rev = getcsrdata(sdev->target->fwdev, 0x3c);
- snprintf(sdev->revision, sizeof(sdev->revision), "%06x", rev);
-}
+ fwdev = sdev->target->fwdev;
+ crom_init_context(cc, fwdev->csrrom);
+ /* get vendor string */
+ crom_search_key(cc, CSRKEY_VENDOR);
+ crom_next(cc);
+ crom_parse_text(cc, sdev->vendor, sizeof(sdev->vendor));
+ /* get firmware revision */
+ reg = crom_search_key(cc, CSRKEY_FIRM_VER);
+ if (reg != NULL)
+ snprintf(sdev->revision, sizeof(sdev->revision),
+ "%06x", reg->val);
+ /* get product string */
+ crom_search_key(cc, CSRKEY_MODEL);
+ crom_next(cc);
+ crom_parse_text(cc, sdev->product, sizeof(sdev->product));
+}
static void
sbp_login_callout(void *arg)
@@ -680,10 +659,8 @@ sbp_login_callout(void *arg)
sbp_mgm_orb(sdev, ORB_FUN_LGI, NULL);
}
-#define SBP_FWDEV_ALIVE(fwdev) \
- ((fwdev->status == FWDEVATTACHED) \
- && (getcsrdata(fwdev, CSRKEY_SPEC) == CSRVAL_ANSIT10) \
- && (getcsrdata(fwdev, CSRKEY_VER) == CSRVAL_T10SBP2))
+#define SBP_FWDEV_ALIVE(fwdev) (((fwdev)->status == FWDEVATTACHED) \
+ && crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2))
static void
sbp_probe_target(void *arg)
@@ -812,13 +789,10 @@ END_DEBUG
SBP_DEBUG(0)
printf("sbp_post_explore: EUI:%08x%08x ",
fwdev->eui.hi, fwdev->eui.lo);
- if (fwdev->status == FWDEVATTACHED) {
- printf("spec=%d key=%d.\n",
- getcsrdata(fwdev, CSRKEY_SPEC) == CSRVAL_ANSIT10,
- getcsrdata(fwdev, CSRKEY_VER) == CSRVAL_T10SBP2);
- } else {
+ if (fwdev->status != FWDEVATTACHED)
printf("not attached, state=%d.\n", fwdev->status);
- }
+ else
+ printf("attached\n");
END_DEBUG
alive = SBP_FWDEV_ALIVE(fwdev);
for(i = 0 ; i < SBP_NUM_TARGETS ; i ++){
OpenPOWER on IntegriCloud