summaryrefslogtreecommitdiffstats
path: root/usr.sbin/fwcontrol
diff options
context:
space:
mode:
authorsimokawa <simokawa@FreeBSD.org>2003-04-17 03:38:03 +0000
committersimokawa <simokawa@FreeBSD.org>2003-04-17 03:38:03 +0000
commit29b43e58e396537013e1057229debf865e3901e1 (patch)
tree11114a8420b3e8fd28f1d77e46ddae593b132e23 /usr.sbin/fwcontrol
parentf946ac101075e1f9e524d40e1cccc51f674b7f5a (diff)
downloadFreeBSD-src-29b43e58e396537013e1057229debf865e3901e1.zip
FreeBSD-src-29b43e58e396537013e1057229debf865e3901e1.tar.gz
MFp4(simokawa_firewire):
Many internal structure changes for the FireWire driver. - Compute CRC in CROM parsing. - Add support for configuration ROM build. - Simplify dummy buffer handling. - busdma conversion - Use swi_taskqueue_giant for -current. Mark the interrupt routine as MPSAFE. - AR buffer handling. Don't reallocate AR buffer but just recycle it. Don't malloc and copy per packet in fwohci_arcv(). Pass packet to fw_rcv() using iovec. Application must prepare receiving buffer in advance. - Change fw_bind API so that application should pre-allocate xfer structure. - Add fw_xfer_unload() for recycling struct fw_xfer. - Add post_busreset hook - Remove unused 'sub' and 'act_type' in struct fw_xfer. - Remove npacket from struct fw_bulkxfer. - Don't call back handlers in fwochi_arcv() if the packet has not drained in AT queue - Make firewire works on big endian platform. - Use native endian for packet header and remove unnecessary ntohX/htonX. - Remove FWXFERQ_PACKET mode. We don't use it anymore. - Remove unnecessary restriction of FWSTMAXCHUNK. - Don't set root node for phy config packet if the root node is not cycle master capable but set myself for root node. We should be the root node after next bus reset. Spotted by: Yoshihiro Tabira <tabira@scd.mei.co.jp> - Improve self id handling Tested on: i386, sparc64 and i386 with forced bounce buffer
Diffstat (limited to 'usr.sbin/fwcontrol')
-rw-r--r--usr.sbin/fwcontrol/fwcontrol.c26
-rw-r--r--usr.sbin/fwcontrol/fwcrom.c259
-rw-r--r--usr.sbin/fwcontrol/fwdv.c6
3 files changed, 275 insertions, 16 deletions
diff --git a/usr.sbin/fwcontrol/fwcontrol.c b/usr.sbin/fwcontrol/fwcontrol.c
index 6044ece..3ac3814 100644
--- a/usr.sbin/fwcontrol/fwcontrol.c
+++ b/usr.sbin/fwcontrol/fwcontrol.c
@@ -127,8 +127,8 @@ read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int read, u_int3
else
asyreq->pkt.mode.rreqq.tcode = FWTCODE_WREQQ;
- asyreq->pkt.mode.rreqq.dest_hi = htons(0xffff);
- asyreq->pkt.mode.rreqq.dest_lo = htonl(addr_lo);
+ asyreq->pkt.mode.rreqq.dest_hi = 0xffff;
+ asyreq->pkt.mode.rreqq.dest_lo = addr_lo;
qld = (u_int32_t *)&asyreq->pkt;
if (!read)
@@ -157,9 +157,9 @@ send_phy_config(int fd, int root_node, int gap_count)
asyreq->pkt.mode.ld[1] = 0;
asyreq->pkt.mode.common.tcode = FWTCODE_PHY;
if (root_node >= 0)
- asyreq->pkt.mode.ld[1] |= htonl((root_node & 0x3f) << 24 | 1 << 23);
+ asyreq->pkt.mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23;
if (gap_count >= 0)
- asyreq->pkt.mode.ld[1] |= htonl(1 << 22 | (gap_count & 0x3f) << 16);
+ asyreq->pkt.mode.ld[1] |= 1 << 22 | (gap_count & 0x3f) << 16;
asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1];
printf("send phy_config root_node=%d gap_count=%d\n",
@@ -251,8 +251,9 @@ show_crom(u_int32_t *crom_buf)
struct csrreg *reg;
struct csrdirectory *dir;
struct csrhdr *hdr;
+ u_int16_t crc;
- printf("first quad: 0x%08x\n", *crom_buf);
+ printf("first quad: 0x%08x ", *crom_buf);
hdr = (struct csrhdr *)crom_buf;
if (hdr->info_len == 1) {
/* minimum ROM */
@@ -261,13 +262,24 @@ show_crom(u_int32_t *crom_buf)
printf("verndor ID: 0x%06x\n", reg->val);
return;
}
- printf("len: %d\n", hdr->crc_len);
+ printf("info_len=%d crc_len=%d crc=0x%04x",
+ hdr->info_len, hdr->crc_len, hdr->crc);
+ crc = crom_crc(crom_buf+1, hdr->crc_len);
+ if (crc == hdr->crc)
+ printf("(OK)\n");
+ else
+ printf("(NG)\n");
parse_bus_info_block(crom_buf+1, hdr->info_len);
crom_init_context(&cc, crom_buf);
dir = cc.stack[0].dir;
- printf("root_directory: len=0x%04x(%d) crc=0x%04x\n",
+ printf("root_directory: len=0x%04x(%d) crc=0x%04x",
dir->crc_len, dir->crc_len, dir->crc);
+ crc = crom_crc((u_int32_t *)&dir->entry[0], dir->crc_len);
+ if (crc == dir->crc)
+ printf("(OK)\n");
+ else
+ printf("(NG)\n");
if (dir->crc_len < 1)
return;
while (cc.depth >= 0) {
diff --git a/usr.sbin/fwcontrol/fwcrom.c b/usr.sbin/fwcontrol/fwcrom.c
index d58be50..af57c8e 100644
--- a/usr.sbin/fwcontrol/fwcrom.c
+++ b/usr.sbin/fwcontrol/fwcrom.c
@@ -35,8 +35,9 @@
*/
#include <sys/param.h>
-#include <dev/firewire/firewire.h>
-#include <dev/firewire/iec13213.h>
+#if defined(_KERNEL) || defined(TEST)
+#include <sys/queue.h>
+#endif
#ifdef _KERNEL
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -48,6 +49,8 @@
#include <stdlib.h>
#include <string.h>
#endif
+#include <dev/firewire/firewire.h>
+#include <dev/firewire/iec13213.h>
void
crom_init_context(struct crom_context *cc, u_int32_t *p)
@@ -179,20 +182,28 @@ crom_desc(struct crom_context *cc, char *buf, int len)
struct csrreg *reg;
struct csrdirectory *dir;
char *desc;
+ u_int16_t crc;
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_L:
+ /* XXX fall through */
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);
+ 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;
}
switch (reg->key) {
case 0x03:
@@ -239,7 +250,7 @@ crom_desc(struct crom_context *cc, char *buf, int len)
break;
case 0x81:
desc = "text_leaf";
- crom_parse_text(cc, buf, len);
+ crom_parse_text(cc, buf + strlen(buf), len);
break;
case 0xd1:
desc = "unit_directory";
@@ -253,3 +264,239 @@ crom_desc(struct crom_context *cc, char *buf, int len)
return desc;
}
#endif
+
+#if defined(_KERNEL) || defined(TEST)
+
+int
+crom_add_quad(struct crom_chunk *chunk, u_int32_t entry)
+{
+ int index;
+
+ index = chunk->data.crc_len;
+ if (index >= CROM_MAX_CHUNK_LEN - 1) {
+ printf("too large chunk %d\n", index);
+ return(-1);
+ }
+ chunk->data.buf[index] = entry;
+ chunk->data.crc_len++;
+ return(index);
+}
+
+int
+crom_add_entry(struct crom_chunk *chunk, int key, int val)
+{
+ struct csrreg *reg;
+ u_int32_t i;
+
+ reg = (struct csrreg *)&i;
+ reg->key = key;
+ reg->val = val;
+ return(crom_add_quad(chunk, (u_int32_t) i));
+}
+
+int
+crom_add_chunk(struct crom_src *src, struct crom_chunk *parent,
+ struct crom_chunk *child, int key)
+{
+ int index;
+
+ if (parent == NULL) {
+ STAILQ_INSERT_TAIL(&src->chunk_list, child, link);
+ return(0);
+ }
+
+ index = crom_add_entry(parent, key, 0);
+ if (index < 0) {
+ return(-1);
+ }
+ child->ref_chunk = parent;
+ child->ref_index = index;
+ STAILQ_INSERT_TAIL(&src->chunk_list, child, link);
+ return(index);
+}
+
+int
+crom_add_simple_text(struct crom_src *src, struct crom_chunk *parent,
+ struct crom_chunk *chunk, char *buf)
+{
+ struct csrtext *tl;
+ u_int32_t *p;
+ int len, i;
+
+ len = strlen(buf);
+#define MAX_TEXT ((CROM_MAX_CHUNK_LEN + 1) * 4 - sizeof(struct csrtext))
+ if (len > MAX_TEXT) {
+ printf("text(%d) trancated to %d.\n", len, MAX_TEXT);
+ len = MAX_TEXT;
+ }
+
+ tl = (struct csrtext *) &chunk->data;
+ tl->crc_len = roundup2(sizeof(struct csrtext) + len, 4) / 4;
+ tl->spec_id = 0;
+ tl->spec_type = 0;
+ tl->lang_id = 0;
+ p = (u_int32_t *) buf;
+ for (i = 0; i < roundup2(len, 4) / 4; i ++)
+ tl->text[i] = ntohl(*p++);
+ return (crom_add_chunk(src, parent, chunk, CROM_TEXTLEAF));
+}
+
+static int
+crom_copy(u_int32_t *src, u_int32_t *dst, int *offset, int len, int maxlen)
+{
+ if (*offset + len > maxlen) {
+ printf("Config. ROM is too large for the buffer\n");
+ return(-1);
+ }
+ bcopy(src, (char *)(dst + *offset), len * sizeof(u_int32_t));
+ *offset += len;
+ return(0);
+}
+
+int
+crom_load(struct crom_src *src, u_int32_t *buf, int maxlen)
+{
+ struct crom_chunk *chunk, *parent;
+ struct csrhdr *hdr;
+#if 0
+ u_int32_t *ptr;
+#endif
+ int count, offset;
+ int len;
+
+ offset = 0;
+ /* Determine offset */
+ STAILQ_FOREACH(chunk, &src->chunk_list, link) {
+ chunk->offset = offset;
+ /* Assume the offset of the parent is already known */
+ parent = chunk->ref_chunk;
+ if (parent != NULL) {
+ struct csrreg *reg;
+ reg = (struct csrreg *)
+ &parent->data.buf[chunk->ref_index];
+ reg->val = offset -
+ (parent->offset + 1 + chunk->ref_index);
+ }
+ offset += 1 + chunk->data.crc_len;
+ }
+
+ /* Calculate CRC and dump to the buffer */
+ len = 1 + src->hdr.info_len;
+ count = 0;
+ if (crom_copy((u_int32_t *)&src->hdr, buf, &count, len, maxlen) < 0)
+ return(-1);
+ STAILQ_FOREACH(chunk, &src->chunk_list, link) {
+ chunk->data.crc =
+ crom_crc(&chunk->data.buf[0], chunk->data.crc_len);
+
+ len = 1 + chunk->data.crc_len;
+ if (crom_copy((u_int32_t *)&chunk->data, buf,
+ &count, len, maxlen) < 0)
+ return(-1);
+ }
+ hdr = (struct csrhdr *)buf;
+ hdr->crc_len = count - 1;
+ hdr->crc = crom_crc(buf + 1, hdr->crc_len);
+
+#if 0
+ /* byte swap */
+ ptr = buf;
+ for (i = 0; i < count; i ++) {
+ *ptr = htonl(*ptr);
+ ptr++;
+ }
+#endif
+
+ return(count);
+}
+#endif
+
+#ifdef TEST
+int
+main () {
+ struct crom_src src;
+ struct crom_chunk root,unit1,unit2,unit3;
+ struct crom_chunk text1,text2,text3,text4,text5,text6,text7;
+ u_int32_t buf[256], *p;
+ int i;
+
+ bzero(&src, sizeof(src));
+ bzero(&root, sizeof(root));
+ bzero(&unit1, sizeof(unit1));
+ bzero(&unit2, sizeof(unit2));
+ bzero(&unit3, sizeof(unit3));
+ bzero(&text1, sizeof(text1));
+ bzero(&text2, sizeof(text2));
+ bzero(&text3, sizeof(text3));
+ bzero(&text3, sizeof(text4));
+ bzero(&text3, sizeof(text5));
+ bzero(&text3, sizeof(text6));
+ bzero(&text3, sizeof(text7));
+ bzero(buf, sizeof(buf));
+
+ /* BUS info sample */
+ src.hdr.info_len = 4;
+ src.businfo.bus_name = CSR_BUS_NAME_IEEE1394;
+ src.businfo.eui64.hi = 0x11223344;
+ src.businfo.eui64.lo = 0x55667788;
+ src.businfo.link_spd = FWSPD_S400;
+ src.businfo.generation = 0;
+ src.businfo.max_rom = MAXROM_4;
+ src.businfo.max_rec = 10;
+ src.businfo.cyc_clk_acc = 100;
+ src.businfo.pmc = 0;
+ src.businfo.bmc = 1;
+ src.businfo.isc = 1;
+ src.businfo.cmc = 1;
+ src.businfo.irmc = 1;
+ STAILQ_INIT(&src.chunk_list);
+
+ /* Root directory */
+ crom_add_chunk(&src, NULL, &root, 0);
+ crom_add_entry(&root, CSRKEY_NCAP, 0x123456);
+ /* private company_id */
+ crom_add_entry(&root, CSRKEY_VENDOR, 0xacde48);
+
+ crom_add_simple_text(&src, &root, &text1, "FreeBSD");
+ crom_add_entry(&root, CSRKEY_HW, __FreeBSD_version);
+ crom_add_simple_text(&src, &root, &text2, "FreeBSD-5");
+
+ /* SBP unit directory */
+ crom_add_chunk(&src, &root, &unit1, CROM_UDIR);
+ crom_add_entry(&unit1, CSRKEY_SPEC, CSRVAL_ANSIT10);
+ crom_add_entry(&unit1, CSRKEY_VER, CSRVAL_T10SBP2);
+ crom_add_entry(&unit1, CSRKEY_COM_SPEC, CSRVAL_ANSIT10);
+ crom_add_entry(&unit1, CSRKEY_COM_SET, CSRVAL_SCSI);
+ /* management_agent */
+ crom_add_entry(&unit1, CROM_MGM, 0x1000);
+ crom_add_entry(&unit1, CSRKEY_UNIT_CH, (10<<8) | 8);
+ /* Device type and LUN */
+ crom_add_entry(&unit1, CROM_LUN, 0);
+ crom_add_entry(&unit1, CSRKEY_MODEL, 1);
+ crom_add_simple_text(&src, &unit1, &text3, "scsi_target");
+
+ /* RFC2734 IPv4 over IEEE1394 */
+ crom_add_chunk(&src, &root, &unit2, CROM_UDIR);
+ crom_add_entry(&unit2, CSRKEY_SPEC, CSRVAL_IETF);
+ crom_add_simple_text(&src, &unit2, &text4, "IANA");
+ crom_add_entry(&unit2, CSRKEY_VER, 1);
+ crom_add_simple_text(&src, &unit2, &text5, "IPv4");
+
+ /* RFC3146 IPv6 over IEEE1394 */
+ crom_add_chunk(&src, &root, &unit3, CROM_UDIR);
+ crom_add_entry(&unit3, CSRKEY_SPEC, CSRVAL_IETF);
+ crom_add_simple_text(&src, &unit3, &text6, "IANA");
+ crom_add_entry(&unit3, CSRKEY_VER, 2);
+ crom_add_simple_text(&src, &unit3, &text7, "IPv6");
+
+ crom_load(&src, buf, 256);
+ p = buf;
+#define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n"
+ for (i = 0; i < 256/8; i ++) {
+ printf(DUMP_FORMAT,
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+ p += 8;
+ }
+ return(0);
+}
+#endif
diff --git a/usr.sbin/fwcontrol/fwdv.c b/usr.sbin/fwcontrol/fwdv.c
index 432625a..43f5a98 100644
--- a/usr.sbin/fwcontrol/fwdv.c
+++ b/usr.sbin/fwcontrol/fwdv.c
@@ -173,7 +173,7 @@ again:
fprintf(stderr, "0x%04x\n", ntohs(ciph->fdf.dv.cyc));
}
#endif
- if (ntohs(pkt->mode.stream.len) <= sizeof(struct ciphdr))
+ if (pkt->mode.stream.len <= sizeof(struct ciphdr))
/* no payload */
goto next;
for (dv = (struct dvdbc *)ptr;
@@ -281,13 +281,13 @@ dvsend(int d, char *filename, char ich, int count)
iso_data = 0;
pkt = (struct fw_pkt *) &iso_data;
- pkt->mode.stream.len = htons(DSIZE + sizeof(struct ciphdr));
+ pkt->mode.stream.len = DSIZE + sizeof(struct ciphdr);
pkt->mode.stream.sy = 0;
pkt->mode.stream.tcode = FWTCODE_STREAM;
pkt->mode.stream.chtag = ich;
iso_empty = iso_data;
pkt = (struct fw_pkt *) &iso_empty;
- pkt->mode.stream.len = htons(sizeof(struct ciphdr));
+ pkt->mode.stream.len = sizeof(struct ciphdr);
bzero(hdr[0], sizeof(hdr[0]));
hdr[0][0] = iso_data;
OpenPOWER on IntegriCloud