diff --git a/headers/private/firewire/firewire.h b/headers/private/firewire/firewire.h index 5f84e66fad..d02ab1146a 100644 --- a/headers/private/firewire/firewire.h +++ b/headers/private/firewire/firewire.h @@ -103,9 +103,16 @@ struct fw_reg_req_t { #define FWRCODE_ER_TYPE 6 #define FWRCODE_ER_ADDR 7 +/* + * Defined 1394a-2000 + * Table 5B-1 + */ #define FWSPD_S100 0 #define FWSPD_S200 1 #define FWSPD_S400 2 +#define FWSPD_S800 3 +#define FWSPD_S1600 4 +#define FWSPD_S3200 5 #define FWP_TL_VALID (1 << 7) @@ -281,10 +288,18 @@ struct fw_devlstreq { struct fw_devinfo dev[FW_MAX_DEVLST]; }; +/* + * Defined in IEEE 1394a-2000 + * 4.3.4.1 + */ #define FW_SELF_ID_PORT_CONNECTED_TO_CHILD 3 #define FW_SELF_ID_PORT_CONNECTED_TO_PARENT 2 #define FW_SELF_ID_PORT_NOT_CONNECTED 1 #define FW_SELF_ID_PORT_NOT_EXISTS 0 + +#define FW_SELF_ID_PAGE0 0 +#define FW_SELF_ID_PAGE1 1 + #if BYTE_ORDER == BIG_ENDIAN union fw_self_id { struct { @@ -294,7 +309,7 @@ union fw_self_id { link_active:1, gap_count:6, phy_speed:2, - phy_delay:2, + reserved:2, contender:1, power_class:3, port0:2, @@ -309,18 +324,32 @@ union fw_self_id { phy_id:6, sequel:1, sequence_num:3, - :2, - porta:2, - portb:2, - portc:2, - portd:2, - porte:2, - portf:2, - portg:2, - porth:2, - :1, + reserved2:2, + port3:2, + port4:2, + port5:2, + port6:2, + port7:2, + port8:2, + port9:2, + port10:2, + reserved1:1, more_packets:1; } p1; + struct { + uint32_t + id:2, + phy_id:6, + sequel:1, + sequence_num:3, + :2, + port11:2, + port12:2, + port13:2, + port14:2, + port15:2, + :8; + } p2; }; #else union fw_self_id { @@ -332,7 +361,7 @@ union fw_self_id { port0:2, power_class:3, contender:1, - phy_delay:2, + reserved:2, phy_speed:2, gap_count:6, link_active:1, @@ -343,20 +372,34 @@ union fw_self_id { struct { uint32_t more_packets:1, reserved1:1, - porth:2, - portg:2, - portf:2, - porte:2, - portd:2, - portc:2, - portb:2, - porta:2, + port10:2, + port9:2, + port8:2, + port7:2, + port6:2, + port5:2, + port4:2, + port3:2, reserved2:2, sequence_num:3, sequel:1, phy_id:6, id:2; } p1; + struct { + uint32_t + reserved3:8, + port15:2, + port14:2, + port13:2, + port12:2, + port11:2, + reserved4:2, + sequence_num:3, + sequel:1, + phy_id:6, + id:2; + } p2; }; #endif @@ -422,7 +465,7 @@ struct fw_crom_buf { #endif #define MAKEMINOR(f, u, s) \ - unit2minor((f) | (((u) & 0xff) << 8) | (s & 0xff)) + ((f) | (((u) & 0xff) << 8) | (s & 0xff)) #define DEV2UNIT(x) ((dev2unit(x) & 0xff00) >> 8) #define DEV2SUB(x) (dev2unit(x) & 0xff) diff --git a/headers/private/firewire/fwphyreg.h b/headers/private/firewire/fwphyreg.h index 825a21f520..93a28dc1e4 100644 --- a/headers/private/firewire/fwphyreg.h +++ b/headers/private/firewire/fwphyreg.h @@ -34,6 +34,10 @@ * $FreeBSD: src/sys/dev/firewire/fwphyreg.h,v 1.3 2005/01/06 01:42:41 imp Exp $ */ +/* + * IEEE 1394a + * Figure 5B - 1 + */ struct phyreg_base { #if BYTE_ORDER == BIG_ENDIAN uint8_t phy_id:6, @@ -100,6 +104,10 @@ struct phyreg_base { #endif }; +/* + * IEEE 1394a + * Figure 5B - 2 + */ struct phyreg_page0 { #if BYTE_ORDER == BIG_ENDIAN uint8_t astat:2, @@ -160,6 +168,10 @@ struct phyreg_page0 { #endif }; +/* + * IEEE 1394a + * Figure 5B - 3 + */ struct phyreg_page1 { uint8_t compliance; uint8_t :8; diff --git a/src/add-ons/kernel/bus_managers/firewire/firewire.c b/src/add-ons/kernel/bus_managers/firewire/firewire.c index 31c80eadd4..0bfa0dbd0b 100644 --- a/src/add-ons/kernel/bus_managers/firewire/firewire.c +++ b/src/add-ons/kernel/bus_managers/firewire/firewire.c @@ -60,7 +60,7 @@ #define PROBE_THREAD_PRIORITY 80 -int firewire_debug=1, try_bmr=1, hold_count=3; +int firewire_debug=1, try_bmr=1, hold_count=0; #define FW_MAXASYRTY 4 @@ -435,6 +435,31 @@ firewire_attach(struct firewire_comm *fc, struct firewire_softc *sc) // fwdev_makedev(sc); + fc->crom_src_buf = (struct crom_src_buf *)malloc( + sizeof(struct crom_src_buf)); + if (fc->crom_src_buf == NULL) { + device_printf(fc->dev, "%s: Malloc Failure crom src buff\n", __func__); + return ENOMEM; + } + memset(fc->crom_src_buf, 0, sizeof(struct crom_src_buf)); + fc->topology_map = (struct fw_topology_map *)malloc( + sizeof(struct fw_topology_map)); + if (fc->topology_map == NULL) { + device_printf(fc->dev, "%s: Malloc Failure topology map\n", __func__); + free(fc->crom_src_buf); + return ENOMEM; + } + memset(fc->topology_map, 0, sizeof(struct fw_topology_map)); + fc->speed_map = (struct fw_speed_map *)malloc( + sizeof(struct fw_speed_map)); + if (fc->speed_map == NULL) { + device_printf(fc->dev, "%s: Malloc Failure speed map\n", __func__); + free(fc->crom_src_buf); + free(fc->topology_map); + return ENOMEM; + } + memset(fc->speed_map, 0, sizeof(struct fw_speed_map)); + mtx_init(&fc->wait_lock, "fwwait", NULL, MTX_DEF); mtx_init(&fc->tlabel_lock, "fwtlabel", NULL, MTX_DEF); // CALLOUT_INIT(&fc->timeout_callout); @@ -448,7 +473,7 @@ firewire_attach(struct firewire_comm *fc, struct firewire_softc *sc) hz/WATCHDOG_HZ, B_PERIODIC_TIMER); /* create thread */ -// kthread_create(fw_bus_probe_thread, (void *)fc, &fc->probe_thread, +// kproc_create(fw_bus_probe_thread, (void *)fc, &fc->probe_thread, // 0, 0, "fw%d_probe", unit); fc->probe_thread = spawn_kernel_thread(fw_bus_probe_thread, "fw_probe", PROBE_THREAD_PRIORITY, fc); @@ -468,7 +493,9 @@ firewire_attach(struct firewire_comm *fc, struct firewire_softc *sc) }*/ /* bus_reset */ + FW_GLOCK(fc); fw_busreset(fc, FWBUSNOTREADY); + FW_GUNLOCK(fc); fc->ibr(fc); return 0; @@ -495,6 +522,8 @@ firewire_detach(struct firewire_softc *sc) mtx_unlock(&fc->wait_lock); DELAY(hz*60); + if (fc->arq !=0 && fc->arq->maxq > 0) + fw_drain_txq(fc); /* if ((err = fwdev_destroydev(sc)) != 0) return err; @@ -518,7 +547,7 @@ firewire_detach(struct firewire_softc *sc) delete_timer(fc->busprobe_callout); - /* XXX xfree_free and untimeout on all xfers */ + /* XXX xfer_free and untimeout on all xfers */ for (fwdev = STAILQ_FIRST(&fc->devices); fwdev != NULL; fwdev = fwdev_next) { fwdev_next = STAILQ_NEXT(fwdev, link); @@ -638,12 +667,6 @@ fw_init_crom(struct firewire_comm *fc) { struct crom_src *src; - fc->crom_src_buf = (struct crom_src_buf *) - malloc(sizeof(struct crom_src_buf)); - if (fc->crom_src_buf == NULL) - return; - memset(fc->crom_src_buf, 0, sizeof(struct crom_src_buf));; - src = &fc->crom_src_buf->src; bzero(src, sizeof(struct crom_src)); @@ -660,7 +683,8 @@ fw_init_crom(struct firewire_comm *fc) src->businfo.cyc_clk_acc = 100; src->businfo.max_rec = fc->maxrec; src->businfo.max_rom = MAXROM_4; - src->businfo.generation = 1; +#define FW_GENERATION_CHANGEABLE 2 + src->businfo.generation = FW_GENERATION_CHANGEABLE; src->businfo.link_spd = fc->speed; src->businfo.eui64.hi = fc->eui.hi; @@ -679,9 +703,6 @@ fw_reset_crom(struct firewire_comm *fc) struct crom_src *src; struct crom_chunk *root; - if (fc->crom_src_buf == NULL) - fw_init_crom(fc); - buf = fc->crom_src_buf; src = fc->crom_src; root = fc->crom_root; @@ -716,20 +737,20 @@ fw_busreset(struct firewire_comm *fc, uint32_t new_status) struct firewire_dev_comm *fdc; struct crom_src *src; // device_t *devlistp; - void *newrom; + uint32_t *newrom; // int i, devcnt; struct firewire_child_info *element = fc->childList; - switch(fc->status){ - case FWBUSMGRELECT: + FW_GLOCK_ASSERT(fc); + if (fc->status == FWBUSMGRELECT) // callout_stop(&fc->bmr_callout); delete_timer(fc->bmr_callout); - break; - default: - break; - } fc->status = new_status; fw_reset_csr(fc); + + if (fc->status == FWBUSNOTREADY) + fw_init_crom(fc); + fw_reset_crom(fc); @@ -751,17 +772,29 @@ fw_busreset(struct firewire_comm *fc, uint32_t new_status) element = element->link; } + src = &fc->crom_src_buf->src; + /* + * If the old config rom needs to be overwritten, + * bump the businfo.generation indicator to + * indicate that we need to be reprobed + * See 1394a-2000 8.3.2.5.4 for more details. + * generation starts at 2 and rolls over at 0xF + * back to 2. + * + * A generation of 0 indicates a device + * that is not 1394a-2000 compliant. + * A generation of 1 indicates a device that + * does not change it's Bus Info Block or + * Configuration ROM. + */ +#define FW_MAX_GENERATION 0xF newrom = malloc(CROMSIZE); memset(newrom, 0, CROMSIZE); src = &fc->crom_src_buf->src; - crom_load(src, (uint32_t *)newrom, CROMSIZE); + crom_load(src, newrom, CROMSIZE); if (bcmp(newrom, fc->config_rom, CROMSIZE) != 0) { - /* bump generation and reload */ - src->businfo.generation ++; - /* generation must be between 0x2 and 0xF */ - if (src->businfo.generation < 2) - src->businfo.generation ++; - crom_load(src, (uint32_t *)newrom, CROMSIZE); + if ( src->businfo.generation++ > FW_MAX_GENERATION ) + src->businfo.generation = FW_GENERATION_CHANGEABLE; bcopy(newrom, (void *)fc->config_rom, CROMSIZE); } free(newrom); @@ -828,13 +861,6 @@ void fw_init(struct firewire_comm *fc) fc->ir[i]->maxq = FWMAXQUEUE; fc->it[i]->maxq = FWMAXQUEUE; } -/* Initialize csr registers */ - fc->topology_map = (struct fw_topology_map *)malloc( - sizeof(struct fw_topology_map)); - memset(fc->topology_map, 0, sizeof(struct fw_topology_map)); - fc->speed_map = (struct fw_speed_map *)malloc( - sizeof(struct fw_speed_map)); - memset(fc->speed_map, 0, sizeof(struct fw_speed_map)); CSRARC(fc, TOPO_MAP) = 0x3f1 << 16; CSRARC(fc, TOPO_MAP + 4) = 1; CSRARC(fc, SPED_MAP) = 0x3f1 << 16; @@ -1300,12 +1326,11 @@ fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count) fp->mode.common.tcode |= FWTCODE_PHY; if (firewire_debug) - printf("send phy_config root_node=%d gap_count=%d\n", - root_node, gap_count); + device_printf(fc->bdev, "%s: root_node=%d gap_count=%d\n", + __func__, root_node, gap_count); fw_asyreq(fc, -1, xfer); } -#if 0 /* * Dump self ID. */ @@ -1314,14 +1339,30 @@ fw_print_sid(uint32_t sid) { union fw_self_id *s; s = (union fw_self_id *) &sid; - printf("node:%d link:%d gap:%d spd:%d del:%d con:%d pwr:%d" - " p0:%d p1:%d p2:%d i:%d m:%d\n", - s->p0.phy_id, s->p0.link_active, s->p0.gap_count, - s->p0.phy_speed, s->p0.phy_delay, s->p0.contender, - s->p0.power_class, s->p0.port0, s->p0.port1, - s->p0.port2, s->p0.initiated_reset, s->p0.more_packets); + if ( s->p0.sequel ) { + if ( s->p1.sequence_num == FW_SELF_ID_PAGE0 ) { + printf("node:%d p3:%d p4:%d p5:%d p6:%d p7:%d" + "p8:%d p9:%d p10:%d\n", + s->p1.phy_id, s->p1.port3, s->p1.port4, + s->p1.port5, s->p1.port6, s->p1.port7, + s->p1.port8, s->p1.port9, s->p1.port10); + } else if (s->p2.sequence_num == FW_SELF_ID_PAGE1 ){ + printf("node:%d p11:%d p12:%d p13:%d p14:%d p15:%d\n", + s->p2.phy_id, s->p2.port11, s->p2.port12, + s->p2.port13, s->p2.port14, s->p2.port15); + } else { + printf("node:%d Unknown Self ID Page number %d\n", + s->p1.phy_id, s->p1.sequence_num); + } + } else { + printf("node:%d link:%d gap:%d spd:%d con:%d pwr:%d" + " p0:%d p1:%d p2:%d i:%d m:%d\n", + s->p0.phy_id, s->p0.link_active, s->p0.gap_count, + s->p0.phy_speed, s->p0.contender, + s->p0.power_class, s->p0.port0, s->p0.port1, + s->p0.port2, s->p0.initiated_reset, s->p0.more_packets); + } } -#endif /* * To receive self ID. @@ -1345,7 +1386,8 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) self_id = &fc->topology_map->self_id[0]; for(i = 0; i < fc->sid_cnt; i ++){ if (sid[1] != ~sid[0]) { - printf("fw_sidrcv: invalid self-id packet\n"); + device_printf(fc->bdev, "%s:" + "ERROR invalid self-id packet\n", __func__); sid += 2; continue; } @@ -1354,9 +1396,9 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) if(self_id->p0.sequel == 0){ fc->topology_map->node_count ++; c_port = 0; -#if 0 - fw_print_sid(sid[0]); -#endif + if (firewire_debug) + fw_print_sid(sid[0]); + node = self_id->p0.phy_id; if(fc->max_node < node){ fc->max_node = self_id->p0.phy_id; @@ -1391,7 +1433,6 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) self_id++; fc->topology_map->self_id_count ++; } - device_printf(fc->bdev, "%d nodes", fc->max_node + 1); /* CRC */ fc->topology_map->crc = fw_crc16( (uint32_t *)&fc->topology_map->generation, @@ -1410,16 +1451,11 @@ void fw_sidrcv(struct firewire_comm* fc, uint32_t *sid, u_int len) bcopy(p, &CSRARC(fc, SPED_MAP + 8), (fc->speed_map->crc_len - 1)*4); fc->max_hop = fc->max_node - i_branch; - printf(", maxhop <= %d", fc->max_hop); - - if(fc->irm == -1 ){ - printf(", Not found IRM capable node"); - }else{ - printf(", cable IRM = %d", fc->irm); - if (fc->irm == fc->nodeid) - printf(" (me)"); - } - printf("\n"); + device_printf(fc->bdev, "%d nodes, maxhop <= %d %s irm(%d) %s\n", + fc->max_node + 1, fc->max_hop, + (fc->irm == -1) ? "Not IRM capable" : "cable IRM", + fc->irm, + (fc->irm == fc->nodeid) ? " (me) " : ""); if (try_bmr && (fc->irm != -1) && (CSRARC(fc, BUS_MGR_ID) == 0x3f)) { if (fc->irm == fc->nodeid) { @@ -1456,10 +1492,24 @@ fw_bus_probe(void *arg) fc->status = FWBUSEXPLORE; /* Invalidate all devices, just after bus reset. */ + if (firewire_debug) + device_printf(fc->bdev, "%s:" + "iterate and invalidate all nodes\n", + __func__); STAILQ_FOREACH(fwdev, &fc->devices, link) if (fwdev->status != FWDEVINVAL) { fwdev->status = FWDEVINVAL; fwdev->rcnt = 0; + if (firewire_debug) + device_printf(fc->bdev, "%s:" + "Invalidate Dev ID: %08x%08x\n", + __func__, fwdev->eui.hi, fwdev->eui.lo); + } else { + if (firewire_debug) + device_printf(fc->bdev, "%s:" + "Dev ID: %08x%08x already invalid\n", + __func__, fwdev->eui.hi, fwdev->eui.lo); + } splx(s); @@ -1469,13 +1519,13 @@ fw_bus_probe(void *arg) static int fw_explore_read_quads(struct fw_device *fwdev, int offset, - uint32_t *quad, int n) + uint32_t *quad, int length) { struct fw_xfer *xfer; uint32_t tmp; int i, error; - for (i = 0; i < n; i ++, offset += sizeof(uint32_t)) { + for (i = 0; i < length; i ++, offset += sizeof(uint32_t)) { xfer = fwmem_read_quad(fwdev, NULL, -1, 0xffff, 0xf0000000 | offset, (void *)&tmp, fw_xferwake); @@ -1552,7 +1602,8 @@ fw_explore_node(struct fw_device *dfwdev) uint32_t *csr; struct csrhdr *hdr; struct bus_info *binfo; - int err, node, spd; + int err, node; + uint32_t speed_test = 0; fc = dfwdev->fc; csr = dfwdev->csrrom; @@ -1560,28 +1611,49 @@ fw_explore_node(struct fw_device *dfwdev) /* First quad */ err = fw_explore_read_quads(dfwdev, CSRROMOFF, &csr[0], 1); - if (err) + if (err) { + device_printf(fc->bdev, "%s: node%d: explore_read_quads failure\n", + __func__, node); + dfwdev->status = FWDEVINVAL; return (-1); + } hdr = (struct csrhdr *)&csr[0]; if (hdr->info_len != 4) { if (firewire_debug) - printf("node%d: wrong bus info len(%d)\n", - node, hdr->info_len); + device_printf(fc->bdev, "%s:" + " node%d: wrong bus info len(%d)\n", + __func__, node, hdr->info_len); + dfwdev->status = FWDEVINVAL; return (-1); } /* bus info */ err = fw_explore_read_quads(dfwdev, CSRROMOFF + 0x04, &csr[1], 4); - if (err) - return (-1); - binfo = (struct bus_info *)&csr[1]; - if (binfo->bus_name != CSR_BUS_NAME_IEEE1394) { - if (firewire_debug) - printf("node%d: invalid bus name 0x%08x\n", - node, binfo->bus_name); + if (err) { + device_printf(fc->bdev, "%s: node%d: error reading 0x04\n", + __func__, node); + dfwdev->status = FWDEVINVAL; return (-1); } - spd = fc->speed_map->speed[fc->nodeid][node]; + binfo = (struct bus_info *)&csr[1]; + if (binfo->bus_name != CSR_BUS_NAME_IEEE1394) { + device_printf(fc->bdev, "%s: node%d: invalid bus name 0x%08x\n", + __func__, node, binfo->bus_name); + dfwdev->status = FWDEVINVAL; + return (-1); + } + + if (firewire_debug) + device_printf(fc->bdev, "%s: node(%d) BUS INFO BLOCK:\n" + "irmc(%d) cmc(%d) isc(%d) bmc(%d) pmc(%d) " + "cyc_clk_acc(%d) max_rec(%d) max_rom(%d) " + "generation(%d) link_spd(%d)\n", + __func__, node, + binfo->irmc, binfo->cmc, binfo->isc, + binfo->bmc, binfo->pmc, binfo->cyc_clk_acc, + binfo->max_rec, binfo->max_rom, + binfo->generation, binfo->link_spd); + STAILQ_FOREACH(fwdev, &fc->devices, link) if (FW_EUI64_EQUAL(fwdev->eui, binfo->eui64)) break; @@ -1589,13 +1661,49 @@ fw_explore_node(struct fw_device *dfwdev) /* new device */ fwdev = malloc(sizeof(struct fw_device)); if (fwdev == NULL) { - if (firewire_debug) - printf("node%d: no memory\n", node); + device_printf(fc->bdev, "%s: node%d: no memory\n", + __func__, node); return (-1); } memset(fwdev, 0, sizeof(struct fw_device)); fwdev->fc = fc; fwdev->eui = binfo->eui64; + fwdev->dst = dfwdev->dst; + fwdev->maxrec = dfwdev->maxrec; + fwdev->status = dfwdev->status; + + /* + * Pre-1394a-2000 didn't have link_spd in + * the Bus Info block, so try and use the + * speed map value. + * 1394a-2000 compliant devices only use + * the Bus Info Block link spd value, so + * ignore the speed map alltogether. SWB + */ + if ( binfo->link_spd == FWSPD_S100 /* 0 */) { + device_printf(fc->bdev, "%s: " + "Pre 1394a-2000 detected\n", + __func__); + fwdev->speed = fc->speed_map->speed[fc->nodeid][node]; + } else + fwdev->speed = binfo->link_spd; + /* + * Test this speed with a read to the CSRROM. + * If it fails, slow down the speed and retry. + */ + while (fwdev->speed > FWSPD_S100 /* 0 */) { + err = fw_explore_read_quads(fwdev, CSRROMOFF, + &speed_test, 1); + if (err) { + device_printf(fc->bdev, "%s: fwdev->speed(%s)" + " decremented due to negotiation\n", + __func__, + linkspeed[fwdev->speed]); + fwdev->speed--; + } else + break; + + } /* inesrt into sorted fwdev list */ pfwdev = NULL; STAILQ_FOREACH(tfwdev, &fc->devices, link) { @@ -1611,18 +1719,17 @@ fw_explore_node(struct fw_device *dfwdev) STAILQ_INSERT_AFTER(&fc->devices, pfwdev, fwdev, link); device_printf(fc->bdev, "New %s device ID:%08x%08x\n", - linkspeed[spd], + linkspeed[fwdev->speed], fwdev->eui.hi, fwdev->eui.lo); - } - fwdev->dst = node; - fwdev->status = FWDEVINIT; - fwdev->speed = spd; - - /* unchanged ? */ - if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) { - if (firewire_debug) - printf("node%d: crom unchanged\n", node); - return (0); + } else { + fwdev->dst = node; + fwdev->status = FWDEVINIT; + /* unchanged ? */ + if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) { + if (firewire_debug) + device_printf(fc->dev, "node%d: crom unchanged\n", node); + return (0); + } } bzero(&fwdev->csrrom[0], CROMSIZE); @@ -1634,6 +1741,10 @@ fw_explore_node(struct fw_device *dfwdev) err = fw_explore_csrblock(fwdev, 0x14, 1); /* root directory */ if (err) { + if (firewire_debug) + device_printf(fc->dev, "%s:" + " explore csrblock failed err(%d)\n", + __func__, err); fwdev->status = FWDEVINVAL; fwdev->csrrom[0] = 0; } @@ -1677,12 +1788,25 @@ fw_explore(struct firewire_comm *fc) for (node = 0; node <= fc->max_node; node ++) { /* We don't probe myself and linkdown nodes */ - if (node == fc->nodeid) + if (node == fc->nodeid) { + if (firewire_debug) + device_printf(fc->bdev, "%s:" + " found myself node(%d) fc->nodeid(%d)" + " fc->max_node(%d)\n", + __func__, node, fc->nodeid, fc->max_node); + continue; + } else if (firewire_debug) { + device_printf(fc->bdev, "%s:" + "node(%d) fc->max_node(%d) found\n", + __func__, node, fc->max_node); + } + fwsid = fw_find_self_id(fc, node); if (!fwsid || !fwsid->p0.link_active) { if (firewire_debug) - printf("node%d: link down\n", node); + device_printf(fc->bdev, "%s: node%d: link down\n", + __func__, node); continue; } nodes[todo++] = node; @@ -1697,8 +1821,8 @@ fw_explore(struct firewire_comm *fc) if (err) nodes[todo2++] = nodes[i]; if (firewire_debug) - printf("%s: node %d, err = %d\n", - __FUNCTION__, node, err); + device_printf(fc->bdev, "%s: node %d, err = %d\n", + __func__, node, err); } todo = todo2; } @@ -1730,7 +1854,7 @@ fw_bus_probe_thread(void *arg) } mtx_unlock(&fc->wait_lock); -// kthread_exit(0); +// kproc_exit(0); return 0; } @@ -1753,11 +1877,18 @@ fw_attach_dev(struct firewire_comm *fc) fwdev->status = FWDEVATTACHED; } else if (fwdev->status == FWDEVINVAL) { fwdev->rcnt ++; + if (firewire_debug) + device_printf(fc->bdev, "%s:" + "fwdev->rcnt(%d), hold_count(%d)\n", + __func__, fwdev->rcnt, hold_count); if (fwdev->rcnt > hold_count) { /* * Remove devices which have not been seen * for a while. */ + device_printf(fc->bdev, "%s:" + "Removing missing device ID:%08x%08x\n", + __func__, fwdev->eui.hi, fwdev->eui.lo); STAILQ_REMOVE(&fc->devices, fwdev, fw_device, link); free(fwdev); @@ -1766,16 +1897,16 @@ fw_attach_dev(struct firewire_comm *fc) } /* err = device_get_children(fc->bdev, &devlistp, &devcnt); - if( err != 0 ) - return; - for( i = 0 ; i < devcnt ; i++){ - if (device_get_state(devlistp[i]) >= DS_ATTACHED) { - fdc = device_get_softc(devlistp[i]); - if (fdc->post_explore != NULL) - fdc->post_explore(fdc); + if( err == 0 ) { + for( i = 0 ; i < devcnt ; i++){ + if (device_get_state(devlistp[i]) >= DS_ATTACHED) { + fdc = device_get_softc(devlistp[i]); + if (fdc->post_explore != NULL) + fdc->post_explore(fdc); + } } - } - free(devlistp, M_TEMP);*/ + free(devlistp, M_TEMP); + }*/ while(element){ // fdc = &element->cookie.fd; @@ -1864,8 +1995,9 @@ fw_rcv_copy(struct fw_rcv_buf *rb) for (i = 0; i < rb->nvec; i++, rb->vec++) { len = MIN(rb->vec->iov_len, plen); if (res < len) { - printf("rcv buffer(%d) is %d bytes short.\n", - rb->xfer->recv.pay_len, len - res); + device_printf(rb->fc->bdev, "%s:" + " rcv buffer(%d) is %d bytes short.\n", + __func__, rb->xfer->recv.pay_len, len - res); len = res; } bcopy(rb->vec->iov_base, p, len); @@ -1912,13 +2044,15 @@ fw_rcv(struct fw_rcv_buf *rb) rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src, fp->mode.hdr.tlrt >> 2, fp->mode.hdr.tcode); if(rb->xfer == NULL) { - printf("fw_rcv: unknown response " - "%s(%x) src=0x%x tl=0x%x rt=%d data=0x%x\n", - tcode_str[tcode], tcode, - fp->mode.hdr.src, - fp->mode.hdr.tlrt >> 2, - fp->mode.hdr.tlrt & 3, - fp->mode.rresq.data); + device_printf(rb->fc->bdev, "%s: " + "unknown response " + "%s(%x) src=0x%x tl=0x%x rt=%d data=0x%x\n", + __func__, + tcode_str[tcode], tcode, + fp->mode.hdr.src, + fp->mode.hdr.tlrt >> 2, + fp->mode.hdr.tlrt & 3, + fp->mode.rresq.data); #if 0 printf("try ad-hoc work around!!\n"); rb->xfer = fw_tl2xfer(rb->fc, fp->mode.hdr.src, @@ -1950,7 +2084,9 @@ fw_rcv(struct fw_rcv_buf *rb) #endif break; default: - printf("unexpected flag 0x%02x\n", rb->xfer->flag); + device_printf(rb->fc->bdev, "%s: " + "unexpected flag 0x%02x\n", __func__, rb->xfer->flag); + } return; case FWTCODE_WREQQ: @@ -1961,13 +2097,20 @@ fw_rcv(struct fw_rcv_buf *rb) bind = fw_bindlookup(rb->fc, fp->mode.rreqq.dest_hi, fp->mode.rreqq.dest_lo); if(bind == NULL){ - printf("Unknown service addr 0x%04x:0x%08x %s(%x)" + device_printf(rb->fc->bdev, "%s: " + "Unknown service addr 0x%04x:0x%08x %s(%x)" " src=0x%x data=%lx\n", - fp->mode.wreqq.dest_hi, fp->mode.wreqq.dest_lo, - tcode_str[tcode], tcode, - fp->mode.hdr.src, ntohl(fp->mode.wreqq.data)); + __func__, + fp->mode.wreqq.dest_hi, + fp->mode.wreqq.dest_lo, + tcode_str[tcode], tcode, + fp->mode.hdr.src, + ntohl(fp->mode.wreqq.data)); + if (rb->fc->status == FWBUSINIT) { - printf("fw_rcv: cannot respond(bus reset)!\n"); + device_printf(rb->fc->bdev, "%s: " + "cannot respond(bus reset)!\n", + __func__); return; } rb->xfer = fw_xfer_alloc(); @@ -2013,9 +2156,9 @@ fw_rcv(struct fw_rcv_buf *rb) len += rb->vec[i].iov_len; rb->xfer = STAILQ_FIRST(&bind->xferlist); if (rb->xfer == NULL) { -#if 1 - printf("Discard a packet for this bind.\n"); -#endif + device_printf(rb->fc->bdev, "%s: " + "Discard a packet for this bind.\n", + __func__); return; } STAILQ_REMOVE_HEAD(&bind->xferlist, link); @@ -2066,7 +2209,8 @@ fw_rcv(struct fw_rcv_buf *rb) } #endif default: - printf("fw_rcv: unknow tcode %d\n", tcode); + device_printf(rb->fc->bdev,"%s: unknown tcode %d\n", + __func__, tcode); break; } } @@ -2239,6 +2383,12 @@ fw_crc16(uint32_t *ptr, uint32_t len){ return((uint16_t) crc); } +/* + * Find the root node, if it is not + * Cycle Master Capable, then we should + * override this and become the Cycle + * Master + */ static int fw_bmr(struct firewire_comm *fc) { @@ -2263,13 +2413,13 @@ fw_bmr(struct firewire_comm *fc) } else cmstr = -1; - device_printf(fc->bdev, "bus manager %d ", CSRARC(fc, BUS_MGR_ID)); + device_printf(fc->bdev, "bus manager %d %s\n", + CSRARC(fc, BUS_MGR_ID), + (CSRARC(fc, BUS_MGR_ID) != fc->nodeid) ? "(me)" : ""); if(CSRARC(fc, BUS_MGR_ID) != fc->nodeid) { /* We are not the bus manager */ - printf("\n"); return(0); } - printf("(me)\n"); /* Optimize gapcount */ if(fc->max_hop <= MAX_GAPHOP ) diff --git a/src/add-ons/kernel/bus_managers/firewire/fwohci.c b/src/add-ons/kernel/bus_managers/firewire/fwohci.c index 2de6f48068..3a8f133511 100644 --- a/src/add-ons/kernel/bus_managers/firewire/fwohci.c +++ b/src/add-ons/kernel/bus_managers/firewire/fwohci.c @@ -283,8 +283,8 @@ fwohci_set_bus_manager(struct firewire_comm *fc, u_int node) if((bm & 0x3f) == 0x3f) bm = node; if (firewire_debug) - device_printf(sc->fc.dev, - "fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i); + device_printf(sc->fc.dev, "%s: %d->%d (loop=%d)\n", + __func__, bm, node, i); return(bm); } @@ -309,7 +309,7 @@ again: } if(i >= MAX_RETRY) { if (firewire_debug) - device_printf(sc->fc.dev, "phy read failed(1).\n"); + device_printf(sc->fc.dev, "%s: failed(1).\n", __func__); if (++retry < MAX_RETRY) { DELAY(100); goto again; @@ -320,15 +320,15 @@ again: if ((stat & OHCI_INT_REG_FAIL) != 0 || ((fun >> PHYDEV_REGADDR) & 0xf) != addr) { if (firewire_debug) - device_printf(sc->fc.dev, "phy read failed(2).\n"); + device_printf(sc->fc.dev, "%s: failed(2).\n", __func__); if (++retry < MAX_RETRY) { DELAY(100); goto again; } } - if (firewire_debug || retry >= MAX_RETRY) - device_printf(sc->fc.dev, - "fwphy_rddata: 0x%x loop=%d, retry=%d\n", addr, i, retry); + if (firewire_debug > 1 || retry >= MAX_RETRY) + device_printf(sc->fc.dev, "%s: 0x%x loop=%d, retry=%d\n", + __func__, addr, i, retry); #undef MAX_RETRY return((fun >> PHYDEV_RDDATA )& 0xff); } @@ -1007,7 +1007,7 @@ txloop: if (maxdesc < db_tr->dbcnt) { maxdesc = db_tr->dbcnt; if (firewire_debug) - printf("maxdesc: %d\n", maxdesc); + printf("%s: maxdesc %d\n", __func__, maxdesc); } /* last db */ LAST_DB(db_tr, db); @@ -1478,10 +1478,12 @@ fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch) ir = &dbch->xferq; if(ir->buf == NULL && (ir->flag & FWXFERQ_EXTBUF) == 0) { - dbch->Area = alloc_mem(&buf_virt, &buf_phy, + if (dbch->Area <= 0) { + dbch->Area = alloc_mem(&buf_virt, &buf_phy, ir->psize * dbch->ndb, 0, "fw rx Area"); - if(dbch->Area < B_OK) - return(ENOMEM); + if(dbch->Area < B_OK) + return(ENOMEM); + } } for (idb = 0; idb < dbch->ndb; idb ++) { @@ -1796,6 +1798,8 @@ fwohci_stop(struct fwohci_softc *sc) { u_int i; + fwohci_set_intr(&sc->fc, 0); + /* Now stopping all DMA channel */ OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN); OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN); @@ -1807,9 +1811,6 @@ fwohci_stop(struct fwohci_softc *sc) OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN); } - if (sc->fc.arq !=0 && sc->fc.arq->maxq > 0) - fw_drain_txq(&sc->fc); - #if 0 /* Let dcons(4) be accessed */ /* Stop interrupt */ OWRITE(sc, FWOHCI_INTMASKCLR, @@ -1865,12 +1866,13 @@ fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) struct firewire_comm *fc = (struct firewire_comm *)sc; uint32_t node_id, plen; + FW_GLOCK_ASSERT(fc); if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) { fc->status = FWBUSRESET; /* Disable bus reset interrupt until sid recv. */ OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R); - device_printf(fc->dev, "BUS reset\n"); + device_printf(fc->dev, "%s: BUS reset\n", __func__); OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST); OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC); @@ -1908,10 +1910,11 @@ fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat, int count) plen = OREAD(sc, OHCI_SID_CNT); fc->nodeid = node_id & 0x3f; - device_printf(fc->dev, "node_id=0x%08x, gen=%d, ", - node_id, (plen >> 16) & 0xff); + device_printf(fc->dev, "%s: node_id=0x%08x, SelfID Count=%d, ", + __func__, fc->nodeid, (plen >> 16) & 0xff); if (!(node_id & OHCI_NODE_VALID)) { - printf("Bus reset failure\n"); + device_printf(fc->dev, "%s: Bus reset failure\n", + __func__); goto sidout; } @@ -2023,9 +2026,11 @@ fwohci_task_busreset(void *arg) { struct fwohci_softc *sc = (struct fwohci_softc *)arg; + FW_GLOCK(&sc->fc); fw_busreset(&sc->fc, FWBUSRESET); OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0])); OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2])); + FW_GUNLOCK(&sc->fc); } static void @@ -2037,6 +2042,9 @@ fwohci_task_sid(void *arg) int i, plen; + /* We really should have locking + * here. Not sure why it's not + */ plen = OREAD(sc, OHCI_SID_CNT); if (plen & OHCI_SID_ERR) { @@ -2056,14 +2064,13 @@ fwohci_task_sid(void *arg) } for (i = 0; i < plen / 4; i ++) buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i+1]); -#if 1 /* XXX needed?? */ + /* pending all pre-bus_reset packets */ fwohci_txd(sc, &sc->atrq); fwohci_txd(sc, &sc->atrs); fwohci_arcv(sc, &sc->arrs, -1); fwohci_arcv(sc, &sc->arrq, -1); fw_drain_txq(fc); -#endif fw_sidrcv(fc, buf, plen); free(buf); } @@ -2088,6 +2095,7 @@ fwohci_check_stat(struct fwohci_softc *sc) { uint32_t stat, irstat, itstat; + FW_GLOCK_ASSERT(&sc->fc); stat = OREAD(sc, FWOHCI_INTSTAT); if (stat == 0xffffffff) { device_printf(sc->fc.dev, @@ -2120,16 +2128,23 @@ fwohci_check_stat(struct fwohci_softc *sc) int32 fwohci_intr(void *arg) { + int32 ret; struct fwohci_softc *sc = (struct fwohci_softc *)arg; - return (fwohci_check_stat(sc)); + //FW_GLOCK(&sc->fc); + ret = fwohci_check_stat(sc); + //FW_GUNLOCK(&sc->fc); + return ret; } void fwohci_poll(struct firewire_comm *fc, int quick, int count) { struct fwohci_softc *sc = (struct fwohci_softc *)fc; + + FW_GLOCK(fc); fwohci_check_stat(sc); + FW_GUNLOCK(fc); } static void @@ -2479,6 +2494,7 @@ fwohci_ibr(struct firewire_comm *fc) device_printf(fc->dev, "Initiate bus reset\n"); sc = (struct fwohci_softc *)fc; + FW_GLOCK(fc); /* * Make sure our cached values from the config rom are * initialised. @@ -2499,6 +2515,7 @@ fwohci_ibr(struct firewire_comm *fc) fun |= FW_PHY_ISBR | FW_PHY_RHB; fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun); #endif + FW_GUNLOCK(fc); } void @@ -2956,7 +2973,7 @@ err: db_tr = STAILQ_NEXT(db_tr, link); resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK; - } while (resCount == 0) + } printf(" done\n"); dbch->top = db_tr; dbch->buf_offset = dbch->xferq.psize - resCount; diff --git a/src/add-ons/kernel/bus_managers/firewire/fwohci_pci.c b/src/add-ons/kernel/bus_managers/firewire/fwohci_pci.c index 259bbb4085..0814ba1764 100644 --- a/src/add-ons/kernel/bus_managers/firewire/fwohci_pci.c +++ b/src/add-ons/kernel/bus_managers/firewire/fwohci_pci.c @@ -208,7 +208,8 @@ fwohci_pci_attach(int index) TRACE("mapped registers to %p\n", sc->regAddr); // setup interrupt handler - if (install_io_interrupt_handler(sc->irq, fwohci_intr, sc, 0) < B_OK) { + if (install_io_interrupt_handler(sc->irq, fwohci_intr, + sc, 0) < B_OK) { ERROR("can't install interrupt handler\n"); goto err; } diff --git a/src/add-ons/kernel/bus_managers/firewire/fwohcireg.h b/src/add-ons/kernel/bus_managers/firewire/fwohcireg.h index e620b4d85b..2eb83e882e 100644 --- a/src/add-ons/kernel/bus_managers/firewire/fwohcireg.h +++ b/src/add-ons/kernel/bus_managers/firewire/fwohcireg.h @@ -415,32 +415,31 @@ struct fwohci_trailer{ #define OHCI_CNTL_PHYPKT (0x1 << 10) #define OHCI_CNTL_SID (0x1 << 9) +/* + * defined in OHCI 1.1 + * chapter 6.1 + */ #define OHCI_INT_DMA_ATRQ (0x1 << 0) #define OHCI_INT_DMA_ATRS (0x1 << 1) #define OHCI_INT_DMA_ARRQ (0x1 << 2) #define OHCI_INT_DMA_ARRS (0x1 << 3) #define OHCI_INT_DMA_PRRQ (0x1 << 4) #define OHCI_INT_DMA_PRRS (0x1 << 5) -#define OHCI_INT_DMA_IT (0x1 << 6) -#define OHCI_INT_DMA_IR (0x1 << 7) -#define OHCI_INT_PW_ERR (0x1 << 8) -#define OHCI_INT_LR_ERR (0x1 << 9) - +#define OHCI_INT_DMA_IT (0x1 << 6) +#define OHCI_INT_DMA_IR (0x1 << 7) +#define OHCI_INT_PW_ERR (0x1 << 8) +#define OHCI_INT_LR_ERR (0x1 << 9) #define OHCI_INT_PHY_SID (0x1 << 16) #define OHCI_INT_PHY_BUS_R (0x1 << 17) - #define OHCI_INT_REG_FAIL (0x1 << 18) - #define OHCI_INT_PHY_INT (0x1 << 19) #define OHCI_INT_CYC_START (0x1 << 20) #define OHCI_INT_CYC_64SECOND (0x1 << 21) #define OHCI_INT_CYC_LOST (0x1 << 22) #define OHCI_INT_CYC_ERR (0x1 << 23) - #define OHCI_INT_ERR (0x1 << 24) #define OHCI_INT_CYC_LONG (0x1 << 25) #define OHCI_INT_PHY_REG (0x1 << 26) - #define OHCI_INT_EN (0x1 << 31) #define IP_CHANNELS 0x0234 diff --git a/src/add-ons/kernel/bus_managers/firewire/fwohcivar.h b/src/add-ons/kernel/bus_managers/firewire/fwohcivar.h index b529e19d62..cf4dcce6c5 100644 --- a/src/add-ons/kernel/bus_managers/firewire/fwohcivar.h +++ b/src/add-ons/kernel/bus_managers/firewire/fwohcivar.h @@ -85,7 +85,6 @@ int fwohci_detach (struct fwohci_softc *); int fwohci_stop (struct fwohci_softc *); #else void fwohci_intr (void *arg); -int fwohci_filt (void *arg); int fwohci_init (struct fwohci_softc *, device_t); void fwohci_poll (struct firewire_comm *, int, int); void fwohci_reset (struct fwohci_softc *, device_t); diff --git a/src/bin/fwcontrol/fwcontrol.c b/src/bin/fwcontrol/fwcontrol.c index 7aefad9ef8..f0c72cba4a 100644 --- a/src/bin/fwcontrol/fwcontrol.c +++ b/src/bin/fwcontrol/fwcontrol.c @@ -46,14 +46,9 @@ __FBSDID("$FreeBSD: src/usr.sbin/fwcontrol/fwcontrol.c,v 1.23 2006/10/26 22:33:3 #include "iec13213.h" #include "fwphyreg.h" #include "iec68113.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include +#define EX_SOFTWARE 1 +#define EX_IOERR 1 #else #include #include @@ -67,16 +62,17 @@ __FBSDID("$FreeBSD: src/usr.sbin/fwcontrol/fwcontrol.c,v 1.23 2006/10/26 22:33:3 #include #include #include - -#include -#include +#include +#endif #include +#include +#include +#include #include #include #include -#include -#endif #include +#include #include "fwmethods.h" #ifndef __HAIKU__ @@ -87,32 +83,31 @@ static void usage(void) { fprintf(stderr, - "fwcontrol [-u bus_num] [-rt] [-g gap_count] [-o node] " - "[-b pri_req] [-c node] [-d node] [-l file] " -#ifdef __HAIKU__ - "[-M mode] [-R file] [-S file] \n" -#else - "[-R file] [-S file] [-m target]\n" + "fwcontrol [-u bus_num] [-prt] [-c node] [-d node] [-o node] [-s node]\n" + "\t [-l file] [-g gap_count] [-f force_root ] [-b pri_req]\n" + "\t [-M mode] [-R filename] [-S filename] " +#ifndef __HAIKU__ + "[-m EUI64 | hostname]\n" #endif - "\t-u: specify bus number\n" - "\t-g: broadcast gap_count by phy_config packet\n" - "\t-o: send link-on packet to the node\n" - "\t-s: write RESET_START register on the node\n" - "\t-b: set PRIORITY_BUDGET register on all supported nodes\n" - "\t-c: read configuration ROM\n" + "\t-p: Display current PHY register settings\n" "\t-r: bus reset\n" "\t-t: read topology map\n" + "\t-c: read configuration ROM\n" "\t-d: hex dump of configuration ROM\n" + "\t-o: send link-on packet to the node\n" + "\t-s: write RESET_START register on the node\n" "\t-l: load and parse hex dump file of configuration ROM\n" - "\t-R: Receive DV or MPEG TS stream\n" -#ifdef __HAIKU__ + "\t-g: broadcast gap_count by phy_config packet\n" + "\t-f: broadcast force_root by phy_config packet\n" + "\t-b: set PRIORITY_BUDGET register on all supported nodes\n" "\t-M: Specify either d for dv mode or m for mpeg mode\n" - "\t-S: Send DV stream\n"); -#else + "\t-R: Receive DV or MPEG TS stream\n" "\t-S: Send DV stream\n" - "\t-m: set fwmem target\n"); +#ifndef __HAIKU__ + "\t-m: set fwmem target\n" #endif + ); exit(EX_USAGE); } @@ -124,18 +119,14 @@ fweui2eui64(const struct fw_eui64 *fweui, struct eui64 *eui) *(u_int32_t*)&(eui->octet[4]) = htonl(fweui->lo); } -static struct fw_devlstreq * -get_dev(int fd) +static void +get_dev(int fd, struct fw_devlstreq *data) { - struct fw_devlstreq *data; - - data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); if (data == NULL) - err(1, "malloc"); + err(1, "%s: data malloc", __func__); if( ioctl(fd, FW_GDEVLST, data) < 0) { - err(1, "ioctl"); + err(1, "%s: ioctl", __func__); } - return data; } static int @@ -166,17 +157,25 @@ str2node(int fd, const char *nodestr) #endif return (-1); - data = get_dev(fd); + data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); + if (data == NULL) + err(1, "%s: data malloc", __func__); + get_dev(fd, data); for (i = 0; i < data->info_len; i++) { fweui2eui64(&data->dev[i].eui, &tmpeui); if (memcmp(&eui, &tmpeui, sizeof(struct eui64)) == 0) { node = data->dev[i].dst; + if (data != NULL) + free(data); goto gotnode; } } - if (i >= data->info_len) + if (i >= data->info_len) { + if (data != NULL) + free(data); return (-1); + } gotnode: if (node < 0 || node > 63) @@ -194,7 +193,10 @@ list_dev(int fd) char addr[EUI64_SIZ]; int i; - data = get_dev(fd); + data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); + if (data == NULL) + err(1, "%s: data malloc", __func__); + get_dev(fd, data); printf("%d devices (info_len=%d)\n", data->n, data->info_len); printf("node EUI64 status\n"); for (i = 0; i < data->info_len; i++) { @@ -217,6 +219,8 @@ read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int readmode, u_ u_int32_t *qld, res; asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16); + if (asyreq == NULL) + err(1, "%s:asyreq malloc", __func__); asyreq->req.len = 16; #if 0 asyreq->req.type = FWASREQNODE; @@ -236,7 +240,7 @@ read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int readmode, u_ qld = (u_int32_t *)&asyreq->pkt; if (!readmode) - asyreq->pkt.mode.wreqq.data = data; + asyreq->pkt.mode.wreqq.data = htonl(data); if (ioctl(fd, FW_ASYREQ, asyreq) < 0) { err(1, "ioctl"); @@ -249,37 +253,56 @@ read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int readmode, u_ return 0; } +/* + * Send a PHY Config Packet + * ieee 1394a-2005 4.3.4.3 + * + * Message ID Root ID R T Gap Count + * 00(2 bits) (6 bits) 1 1 (6 bits) + * + * if "R" is set, then Root ID will be the next + * root node upon the next bus reset. + * if "T" is set, then Gap Count will be the + * value that all nodes use for their Gap Count + * if "R" and "T" are not set, then this message + * is either ignored or interpreted as an extended + * PHY config Packet as per 1394a-2005 4.3.4.4 + */ static void send_phy_config(int fd, int root_node, int gap_count) { struct fw_asyreq *asyreq; asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12); + if (asyreq == NULL) + err(1, "%s:asyreq malloc", __func__); asyreq->req.len = 12; asyreq->req.type = FWASREQNODE; asyreq->pkt.mode.ld[0] = 0; asyreq->pkt.mode.ld[1] = 0; asyreq->pkt.mode.common.tcode = FWTCODE_PHY; if (root_node >= 0) - asyreq->pkt.mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23; + asyreq->pkt.mode.ld[1] |= ((root_node << 24) | (1 << 23)); if (gap_count >= 0) - asyreq->pkt.mode.ld[1] |= 1 << 22 | (gap_count & 0x3f) << 16; + asyreq->pkt.mode.ld[1] |= ((1 << 22) | (gap_count << 16)); asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1]; printf("send phy_config root_node=%d gap_count=%d\n", root_node, gap_count); if (ioctl(fd, FW_ASYREQ, asyreq) < 0) - err(1, "ioctl"); + err(1, "%s: ioctl", __func__); free(asyreq); } static void -send_link_on(int fd, int node) +link_on(int fd, int node) { struct fw_asyreq *asyreq; asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12); + if (asyreq == NULL) + err(1, "%s:asyreq malloc", __func__); asyreq->req.len = 12; asyreq->req.type = FWASREQNODE; asyreq->pkt.mode.common.tcode = FWTCODE_PHY; @@ -287,7 +310,7 @@ send_link_on(int fd, int node) asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1]; if (ioctl(fd, FW_ASYREQ, asyreq) < 0) - err(1, "ioctl"); + err(1, "%s: ioctl", __func__); free(asyreq); } @@ -297,6 +320,8 @@ reset_start(int fd, int node) struct fw_asyreq *asyreq; asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16); + if (asyreq == NULL) + err(1, "%s:asyreq malloc", __func__); asyreq->req.len = 16; asyreq->req.type = FWASREQNODE; asyreq->pkt.mode.wreqq.dst = FWLOCALBUS | (node & 0x3f); @@ -309,7 +334,7 @@ reset_start(int fd, int node) asyreq->pkt.mode.wreqq.data = htonl(0x1); if (ioctl(fd, FW_ASYREQ, asyreq) < 0) - err(1, "ioctl"); + err(1, "%s: ioctl", __func__); free(asyreq); } @@ -323,7 +348,10 @@ set_pri_req(int fd, u_int32_t pri_req) u_int32_t max, reg, old; int i; - data = get_dev(fd); + data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); + if (data == NULL) + err(1, "%s: data malloc", __func__); + get_dev(fd, data); #define BUGET_REG 0xf0000218 for (i = 0; i < data->info_len; i++) { devinfo = &data->dev[i]; @@ -377,7 +405,10 @@ get_crom(int fd, int node, void *crom_buf, int len) int i, error; struct fw_devlstreq *data; - data = get_dev(fd); + data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); + if (data == NULL) + err(1, "%s: data malloc", __func__); + get_dev(fd, data); for (i = 0; i < data->info_len; i++) { if (data->dev[i].dst == node && data->dev[i].eui.lo != 0) @@ -393,7 +424,7 @@ get_crom(int fd, int node, void *crom_buf, int len) buf.ptr = crom_buf; bzero(crom_buf, len); if ((error = ioctl(fd, FW_GCROM, &buf)) < 0) { - err(1, "ioctl"); + err(1, "%s: ioctl", __func__); } return error; @@ -502,9 +533,9 @@ show_topology_map(int fd) static const char *speed[] = {"S100", "S200", "S400", "S800"}; tmap = malloc(sizeof(struct fw_topology_map)); if (tmap == NULL) - return; + err(1, "%s:tmap malloc", __func__); if (ioctl(fd, FW_GTPMAP, tmap) < 0) { - err(1, "ioctl"); + err(1, "%s: ioctl", __func__); } printf("crc_len: %d generation:%d node_count:%d sid_count:%d\n", tmap->crc_len, tmap->generation, @@ -517,13 +548,12 @@ show_topology_map(int fd) printf("%02d sequel packet\n", sid.p0.phy_id); continue; } - printf("%02d %2d %2d %4s %d %d %3s" + printf("%02d %2d %2d %4s %d %3s" " %s %s %s %d %d\n", sid.p0.phy_id, sid.p0.link_active, sid.p0.gap_count, speed[sid.p0.phy_speed], - sid.p0.phy_delay, sid.p0.contender, pwr_class[sid.p0.power_class], port_status[sid.p0.port0], @@ -545,7 +575,7 @@ read_phy_registers(int fd, u_int8_t *buf, int offset, int len) for (i = 0; i < len; i++) { reg.addr = offset + i; if (ioctl(fd, FWOHCI_RDPHYREG, ®) < 0) - err(1, "ioctl"); + err(1, "%s: ioctl", __func__); buf[i] = (u_int8_t) reg.data; printf("0x%02x ", reg.data); } @@ -560,7 +590,7 @@ read_phy_page(int fd, u_int8_t *buf, int page, int port) reg.addr = 0x7; reg.data = ((page & 7) << 5) | (port & 0xf); if (ioctl(fd, FWOHCI_WRPHYREG, ®) < 0) - err(1, "ioctl"); + err(1, "%s: ioctl", __func__); read_phy_registers(fd, buf, 8, 8); } @@ -623,28 +653,15 @@ dump_phy_registers(int fd) ); } -static void -open_dev(int *fd, char *devbase) +static int +open_dev(int *fd, char *devname) { -#ifndef __HAIKU__ - char name[256]; - int i; -#endif - if (*fd < 0) { -#ifdef __HAIKU__ - *fd = open(devbase, O_RDWR); -#else - for (i = 0; i < 4; i++) { - snprintf(name, sizeof(name), "%s.%d", devbase, i); - if ((*fd = open(name, O_RDWR)) >= 0) - break; - } -#endif + *fd = open(devname, O_RDWR); if (*fd < 0) - err(1, "open"); - + return (-1); } + return (0); } #ifndef __HAIKU__ @@ -666,25 +683,40 @@ detect_recv_fn(int fd, char ich) u_int32_t *ptr; struct ciphdr *ciph; fwmethod *retfn; +#define RECV_NUM_PACKET 16 +#define RECV_PACKET_SZ 1024 bufreq.rx.nchunk = 8; - bufreq.rx.npacket = 16; - bufreq.rx.psize = 1024; + bufreq.rx.npacket = RECV_NUM_PACKET; + bufreq.rx.psize = RECV_PACKET_SZ; bufreq.tx.nchunk = 0; bufreq.tx.npacket = 0; bufreq.tx.psize = 0; -printf("detect dv format\n"); + if (ioctl(fd, FW_SSTBUF, &bufreq) < 0) - err(1, "ioctl FW_SSTBUF"); + err(1, "%s: ioctl FW_SSTBUF", __func__); isoreq.ch = ich & 0x3f; isoreq.tag = (ich >> 6) & 3; if (ioctl(fd, FW_SRSTREAM, &isoreq) < 0) - err(1, "ioctl FW_SRSTREAM"); + err(1, "%s: ioctl FW_SRSTREAM", __func__); - buf = (char *)malloc(1024*16); - len = read(fd, buf, 1024*16); + buf = (char *)malloc(RECV_NUM_PACKET * RECV_PACKET_SZ); + if (buf == NULL) + err(1, "%s:buf malloc", __func__); + /* + * fwdev.c seems to return EIO on error and + * the return value of the last uiomove + * on success. For now, checking that the + * return is not less than zero should be + * sufficient. fwdev.c::fw_read() should + * return the total length read, not the value + * of the last uiomove(). + */ + len = read(fd, buf, RECV_NUM_PACKET * RECV_PACKET_SZ); + if (len < 0) + err(1, "%s: error reading from device\n", __func__); ptr = (u_int32_t *) buf; ciph = (struct ciphdr *)(ptr + 1); @@ -707,111 +739,180 @@ printf("detect dv format\n"); int main(int argc, char **argv) { +#define MAX_BOARDS 10 u_int32_t crom_buf[1024/4]; + u_int32_t crom_buf_hex[1024/4]; + char devbase[64]; #ifdef __HAIKU__ - char devbase[1024] = "/dev/bus/fw/0"; + const char *device_string = "/dev/bus/fw/"; #else - char devbase[1024] = "/dev/fw0"; + const char *device_string = "/dev/fw"; #endif - int fd, ch, len=1024; + int fd = -1, ch, len=1024; + int32_t current_board = 0; + /* + * If !command_set, then -u will display the nodes for the board. + * This emulates the previous behavior when -u is passed by itself + */ + bool command_set = false; + bool open_needed = false; long tmp; struct fw_eui64 eui; struct eui64 target; fwmethod *recvfn = NULL; +/* + * Holders for which functions + * to iterate through + */ + bool display_board_only = false; + bool display_crom = false; + bool send_bus_reset = false; + bool display_crom_hex = false; + bool load_crom_from_file = false; +#ifndef __HAIKU__ + bool set_fwmem_target = false; +#endif + bool dump_topology = false; + bool dump_phy_reg = false; - fd = -1; + int32_t priority_budget = -1; + int32_t set_root_node = -1; + int32_t set_gap_count = -1; + int32_t send_link_on = -1; + int32_t send_reset_start = -1; + + char *crom_string = NULL; + char *crom_string_hex = NULL; + char *recv_data = NULL; + char *send_data = NULL; if (argc < 2) { - open_dev(&fd, devbase); - list_dev(fd); + for (current_board = 0; current_board < MAX_BOARDS; current_board++) { + snprintf(devbase, sizeof(devbase), "%s%d", device_string, current_board); + if (open_dev(&fd, devbase) < 0) { + if (current_board == 0) { + usage(); + } + return(EIO); + } + list_dev(fd); + close(fd); + fd = -1; + } } - + /* + * Parse all command line options, then execute requested operations. + */ #ifdef __HAIKU__ - while ((ch = getopt(argc, argv, "M:g:o:s:b:prtc:d:l:u:R:S:")) != -1) + while ((ch = getopt(argc, argv, "M:f:g:o:s:b:prtc:d:l:u:R:S:")) != -1) { #else - while ((ch = getopt(argc, argv, "M:g:m:o:s:b:prtc:d:l:u:R:S:")) != -1) + while ((ch = getopt(argc, argv, "M:f:g:m:o:s:b:prtc:d:l:u:R:S:")) != -1) { #endif switch(ch) { case 'b': - tmp = strtol(optarg, NULL, 0); - if (tmp < 0 || tmp > (long)0xffffffff) - errx(EX_USAGE, "invalid number: %s", optarg); - open_dev(&fd, devbase); - set_pri_req(fd, tmp); + priority_budget = strtol(optarg, NULL, 0); + if (priority_budget < 0 || priority_budget > INT32_MAX) + errx(EX_USAGE, "%s: invalid number: %s", __func__, optarg); + command_set = true; + open_needed = true; + display_board_only = false; break; case 'c': - open_dev(&fd, devbase); - tmp = str2node(fd, optarg); - get_crom(fd, tmp, crom_buf, len); - show_crom(crom_buf); + crom_string = malloc(strlen(optarg)+1); + if (crom_string == NULL) + err(EX_SOFTWARE, "%s:crom_string malloc", __func__); + if ( (strtol(crom_string, NULL, 0) < 0) || strtol(crom_string, NULL, 0) > MAX_BOARDS) + err(EX_USAGE, "%s:Invalid value for node", __func__); + strcpy(crom_string, optarg); + display_crom = 1; + open_needed = true; + command_set = true; + display_board_only = false; break; case 'd': - open_dev(&fd, devbase); - tmp = str2node(fd, optarg); - get_crom(fd, tmp, crom_buf, len); - dump_crom(crom_buf); + crom_string_hex = malloc(strlen(optarg)+1); + if (crom_string_hex == NULL) + err(EX_SOFTWARE, "%s:crom_string_hex malloc", __func__); + strcpy(crom_string_hex, optarg); + display_crom_hex = 1; + open_needed = true; + command_set = true; + display_board_only = false; + break; + case 'f': +#define MAX_PHY_CONFIG 0x3f + set_root_node = strtol(optarg, NULL, 0); + if ( (set_root_node < 0) || (set_root_node > MAX_PHY_CONFIG) ) + err(EX_USAGE, "%s:set_root_node out of range", __func__); + open_needed = true; + command_set = true; + display_board_only = false; break; case 'g': - tmp = strtol(optarg, NULL, 0); - open_dev(&fd, devbase); - send_phy_config(fd, -1, tmp); + set_gap_count = strtol(optarg, NULL, 0); + if ( (set_gap_count < 0) || (set_gap_count > MAX_PHY_CONFIG) ) + err(EX_USAGE, "%s:set_gap_count out of range", __func__); + open_needed = true; + command_set = true; + display_board_only = false; break; case 'l': + load_crom_from_file = 1; load_crom(optarg, crom_buf); - show_crom(crom_buf); + command_set = true; + display_board_only = false; break; #ifndef __HAIKU__ case 'm': - if (eui64_hostton(optarg, &target) != 0 && - eui64_aton(optarg, &target) != 0) - errx(EX_USAGE, "invalid target: %s", optarg); - eui.hi = ntohl(*(u_int32_t*)&(target.octet[0])); - eui.lo = ntohl(*(u_int32_t*)&(target.octet[4])); - sysctl_set_int("hw.firewire.fwmem.eui64_hi", eui.hi); - sysctl_set_int("hw.firewire.fwmem.eui64_lo", eui.lo); + set_fwmem_target = 1; + open_needed = 0; + command_set = true; + display_board_only = false; + if (eui64_hostton(optarg, &target) != 0 && + eui64_aton(optarg, &target) != 0) + err(EX_USAGE, "%s: invalid target: %s", __func__, optarg); break; #endif case 'o': - open_dev(&fd, devbase); - tmp = str2node(fd, optarg); - send_link_on(fd, tmp); + send_link_on = str2node(fd, optarg); + if ( (send_link_on < 0) || (send_link_on > INT32_MAX) ) + err(EX_USAGE, "%s: node out of range: %s\n",__func__, optarg); + open_needed = true; + command_set = true; + display_board_only = false; break; case 'p': - open_dev(&fd, devbase); - dump_phy_registers(fd); + dump_phy_reg = 1; + open_needed = true; + command_set = true; + display_board_only = false; break; case 'r': - open_dev(&fd, devbase); - if(ioctl(fd, FW_IBUSRST, &tmp) < 0) - err(1, "ioctl"); + send_bus_reset = 1; + open_needed = true; + command_set = true; + display_board_only = false; break; case 's': - open_dev(&fd, devbase); - tmp = str2node(fd, optarg); - reset_start(fd, tmp); + send_reset_start = str2node(fd, optarg); + if ( (send_reset_start < 0) || (send_reset_start > INT32_MAX) ) + err(EX_USAGE, "%s: node out of range: %s\n", __func__, optarg); + open_needed = true; + command_set = true; + display_board_only = false; break; case 't': - open_dev(&fd, devbase); - show_topology_map(fd); + dump_topology = 1; + open_needed = true; + command_set = true; + display_board_only = false; break; case 'u': - tmp = strtol(optarg, NULL, 0); -#ifdef __HAIKU__ - snprintf(devbase, sizeof(devbase), "/dev/bus/fw/%ld", tmp); -#else - snprintf(devbase, sizeof(devbase), "/dev/fw%ld", tmp); -#endif - if (fd > 0) { - close(fd); - fd = -1; - } - if (argc == optind) { - open_dev(&fd, devbase); - list_dev(fd); - } + if(!command_set) + display_board_only = true; + current_board = strtol(optarg, NULL, 0); + open_needed = true; break; -#define TAG (1<<6) -#define CHANNEL 63 case 'M': switch (optarg[0]) { case 'm': @@ -824,22 +925,166 @@ main(int argc, char **argv) errx(EX_USAGE, "unrecognized method: %s", optarg); } + command_set = true; + display_board_only = false; break; case 'R': - open_dev(&fd, devbase); - if (recvfn == NULL) /* guess... */ - recvfn = detect_recv_fn(fd, TAG | CHANNEL); - close(fd); - fd = -1; - open_dev(&fd, devbase); - (*recvfn)(fd, optarg, TAG | CHANNEL, -1); + recv_data = malloc(strlen(optarg)+1); + if (recv_data == NULL) + err(EX_SOFTWARE, "%s:recv_data malloc", __func__); + strcpy(recv_data, optarg); + open_needed = false; + command_set = true; + display_board_only = false; break; case 'S': - open_dev(&fd, devbase); - dvsend(fd, optarg, TAG | CHANNEL, -1); + send_data = malloc(strlen(optarg)+1); + if (send_data == NULL) + err(EX_SOFTWARE, "%s:send_data malloc", __func__); + strcpy(send_data, optarg); + open_needed = true; + command_set = true; + display_board_only = false; break; default: usage(); + return 0; } + } /* end while */ + + /* + * If -u is passed, execute + * command for that card only. + * + * If -u is not passed, execute + * command for card 0 only. + * + */ + if(open_needed){ + snprintf(devbase, sizeof(devbase), "%s%d", device_string, current_board); + if (open_dev(&fd, devbase) < 0) { + errx(EX_IOERR, "%s: Error opening board #%d\n", __func__, current_board); + } + } + /* + * display the nodes on this board "-u" + * only + */ + if (display_board_only) + list_dev(fd); + + /* + * dump_phy_reg "-p" + */ + if (dump_phy_reg) + dump_phy_registers(fd); + + /* + * send a BUS_RESET Event "-r" + */ + if (send_bus_reset) { + if(ioctl(fd, FW_IBUSRST, &tmp) < 0) + err(EX_IOERR, "%s: ioctl", __func__); + } + /* + * Print out the CROM for this node "-c" + */ + if (display_crom) { + tmp = str2node(fd, crom_string); + get_crom(fd, tmp, crom_buf, len); + show_crom(crom_buf); + free(crom_string); + } + /* + * Hex Dump the CROM for this node "-d" + */ + if (display_crom_hex) { + tmp = str2node(fd, crom_string_hex); + get_crom(fd, tmp, crom_buf_hex, len); + dump_crom(crom_buf_hex); + free(crom_string_hex); + } + /* + * Set Priority Budget to value for this node "-b" + */ + if (priority_budget >= 0) + set_pri_req(fd, priority_budget); + + /* + * Explicitly set the root node of this bus to value "-f" + */ + if (set_root_node >= 0) + send_phy_config(fd, set_root_node, -1); + + /* + * Set the gap count for this card/bus "-g" + */ + if (set_gap_count >= 0) + send_phy_config(fd, -1, set_gap_count); + + /* + * Load a CROM from a file "-l" + */ + if (load_crom_from_file) + show_crom(crom_buf); +#ifndef __HAIKU__ + /* + * Set the fwmem target for a node to argument "-m" + */ + if (set_fwmem_target) { + eui.hi = ntohl(*(u_int32_t*)&(target.octet[0])); + eui.lo = ntohl(*(u_int32_t*)&(target.octet[4])); + sysctl_set_int("hw.firewire.fwmem.eui64_hi", eui.hi); + sysctl_set_int("hw.firewire.fwmem.eui64_lo", eui.lo); + } +#endif + /* + * Send a link on to this board/bus "-o" + */ + if (send_link_on >= 0) + link_on(fd, send_link_on); + + /* + * Send a reset start to this board/bus "-s" + */ + if (send_reset_start >= 0) + reset_start(fd, send_reset_start); + + /* + * Dump the node topology for this board/bus "-t" + */ + if (dump_topology) + show_topology_map(fd); + + /* + * Recieve data file from node "-R" + */ +#define TAG (1<<6) +#define CHANNEL 63 + if (recv_data != NULL){ + if (recvfn == NULL) { /* guess... */ + recvfn = detect_recv_fn(fd, TAG | CHANNEL); + close(fd); + } + snprintf(devbase, sizeof(devbase), "%s%d", device_string, current_board); + if (open_dev(&fd, devbase) < 0) + errx(EX_IOERR, "%s: Error opening board #%d in recv_data\n", __func__, current_board); + (*recvfn)(fd, recv_data, TAG | CHANNEL, -1); + free(recv_data); + } + + /* + * Send data file to node "-S" + */ + if (send_data != NULL){ + dvsend(fd, send_data, TAG | CHANNEL, -1); + free(send_data); + } + + if (fd > 0) { + close(fd); + fd = -1; + } return 0; } + diff --git a/src/bin/fwcontrol/fwdv.c b/src/bin/fwcontrol/fwdv.c index 63e5897e42..ed8d63fda4 100644 --- a/src/bin/fwcontrol/fwdv.c +++ b/src/bin/fwcontrol/fwdv.c @@ -211,14 +211,19 @@ again: (dv->payload[0] & DV_DSF_12) == 0) dv->payload[0] |= DV_DSF_12; nb = nblocks[system]; - fprintf(stderr, "%d", k%10); + fprintf(stderr, "%d:%02d:%02d %d\r", + k / (3600 * frame_rate[system]), + (k / (60 * frame_rate[system])) % 60, + (k / frame_rate[system]) % 60, + k % frame_rate[system]); + #if FIX_FRAME if (m > 0 && m != nb) { /* padding bad frame */ npad = ((nb - m) % nb); if (npad < 0) npad += nb; - fprintf(stderr, "(%d blocks padded)", + fprintf(stderr, "\n%d blocks padded\n", npad); npad *= DSIZE; wbuf[vec].iov_base = pad; @@ -230,10 +235,6 @@ again: } #endif k++; - if (k % frame_rate[system] == 0) { - /* every second */ - fprintf(stderr, "\n"); - } fflush(stderr); m = 0; } @@ -254,9 +255,8 @@ next: if (vec > 0) writev(fd, wbuf, vec); } - if(fd != STDOUT_FILENO) { + if(fd != STDOUT_FILENO) close(fd); - } fprintf(stderr, "\n"); } diff --git a/src/bin/fwcontrol/fwmpegts.c b/src/bin/fwcontrol/fwmpegts.c index c7cdf32a84..ba1bedd564 100644 --- a/src/bin/fwcontrol/fwmpegts.c +++ b/src/bin/fwcontrol/fwmpegts.c @@ -196,10 +196,9 @@ mpegtsrecv(int d, const char *filename, char ich, int count) if (len < 0) { if (errno == EAGAIN) { fprintf(stderr, "(EAGAIN) - push 'Play'?\n"); - if (len <= 0) - continue; - } else - err(1, "read failed"); + continue; + } + err(1, "read failed"); } ptr = (uint32_t *) buf;