diff options
author | simokawa <simokawa@FreeBSD.org> | 2003-04-26 16:45:40 +0000 |
---|---|---|
committer | simokawa <simokawa@FreeBSD.org> | 2003-04-26 16:45:40 +0000 |
commit | b380739760e705fd780f133e9899b3d27db7ad5f (patch) | |
tree | 415c88f229ca2c29c533d24164e2cb651fb3d627 /sys | |
parent | 4d37b34b62b2f79aebba964702976feae37ff78a (diff) | |
download | FreeBSD-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.c | 87 | ||||
-rw-r--r-- | sys/dev/firewire/firewirereg.h | 1 | ||||
-rw-r--r-- | sys/dev/firewire/fwcrom.c | 114 | ||||
-rw-r--r-- | sys/dev/firewire/iec13213.h | 2 | ||||
-rw-r--r-- | sys/dev/firewire/sbp.c | 84 |
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 ++){ |