The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=c402d2e4b70023c633e6b3af5436de7033166d04
commit c402d2e4b70023c633e6b3af5436de7033166d04 Author: Abdelkader Boudih <[email protected]> AuthorDate: 2026-07-17 04:03:53 +0000 Commit: Adrian Chadd <[email protected]> CommitDate: 2026-07-17 04:07:52 +0000 fwisound: match unit directories instead of IDENTIFY Migrated fwisound to use per-unit-directory child device Differential Revision: https://reviews.freebsd.org/D58203 Reviewed by: adrian --- share/man/man4/fwisound.4 | 5 +- sys/dev/firewire/fwisound.c | 168 ++++++++++++++------------------------------ 2 files changed, 54 insertions(+), 119 deletions(-) diff --git a/share/man/man4/fwisound.4 b/share/man/man4/fwisound.4 index 0da89fbe2bdc..a458c957276e 100644 --- a/share/man/man4/fwisound.4 +++ b/share/man/man4/fwisound.4 @@ -3,7 +3,7 @@ .\" .\" SPDX-License-Identifier: BSD-2-Clause .\" -.Dd June 19, 2026 +.Dd July 12, 2026 .Dt FWISOUND 4 .Os .Sh NAME @@ -20,7 +20,8 @@ driver provides audio capture from Apple FireWire devices that use a proprietary isochronous audio protocol .Pq not IEC 61883/AMDTP . .Pp -The driver matches FireWire units with Apple OUI +The driver attaches to unit directories in the device CSR configuration ROM +with Apple OUI .Pq 0x000a27 and decodes the .Qq sght diff --git a/sys/dev/firewire/fwisound.c b/sys/dev/firewire/fwisound.c index 9766f88060f7..63ebd5f01917 100644 --- a/sys/dev/firewire/fwisound.c +++ b/sys/dev/firewire/fwisound.c @@ -46,12 +46,9 @@ SYSCTL_INT(_hw_firewire_fwisound, OID_AUTO, iso_channel, CTLFLAG_RWTUN, printf("fwisound: " fmt, ## __VA_ARGS__); \ } while (0) -static void fwisound_identify(driver_t *, device_t); static int fwisound_probe(device_t); static int fwisound_attach(device_t); static int fwisound_detach(device_t); -static void fwisound_post_busreset(void *); -static void fwisound_post_explore(void *); static void fwisound_probe_task(void *, int); static void fwisound_start_task(void *, int); static void fwisound_stop_task(void *, int); @@ -105,49 +102,35 @@ fwisound_write_quadlet(struct fwisound_softc *sc, uint32_t offset, uint32_t val) return (err); } +/* + * Extract the audio command base register (key 0x40) from the unit directory. + */ static uint32_t -fwisound_find_audio_unit(struct fw_device *fwdev) +fwisound_find_audio_base(struct fw_unit *unit) { - struct csrhdr *hdr; - struct csrdirectory *root, *udir; - struct csrreg *reg, *u; - int i, j, spec_ok, ver_ok; - uint32_t audio_base; - - hdr = (struct csrhdr *)fwdev->csrrom; - if (hdr->info_len <= 1) + struct fw_device *fwdev = unit->fwdev; + struct csrdirectory *udir; + struct csrreg *reg; + uint32_t udir_qoff, udir_len, rom_quads; + int i; + + rom_quads = CSRROMSIZE / 4; + udir_qoff = unit->dir_offset / 4; + if (udir_qoff >= rom_quads) return (0); - root = (struct csrdirectory *)(fwdev->csrrom + 1 + hdr->info_len); - - for (i = 0; i < root->crc_len; i++) { - reg = &root->entry[i]; - - if (reg->key != CROM_UDIR) - continue; - - udir = (struct csrdirectory *)(reg + reg->val); - - spec_ok = 0; - ver_ok = 0; - audio_base = 0; - - for (j = 0; j < udir->crc_len; j++) { - u = &udir->entry[j]; - - if (u->key == CSRKEY_SPEC && u->val == FWISOUND_SPEC_ID) - spec_ok = 1; - else if (u->key == CSRKEY_VER && - u->val == FWISOUND_VERSION) - ver_ok = 1; - else if (u->key == IIDC_CROM_CMD_BASE) - audio_base = u->val; - } + udir = (struct csrdirectory *)&fwdev->csrrom[udir_qoff]; + udir_len = udir->crc_len; + if (udir_qoff + 1 + udir_len > rom_quads) + return (0); - if (spec_ok && ver_ok && audio_base != 0) - return (audio_base); + for (i = 0; i < (int)udir_len; i++) { + if (udir_qoff + 1 + i >= rom_quads) + break; + reg = &udir->entry[i]; + if (reg->key == IIDC_CROM_CMD_BASE && reg->val != 0) + return (reg->val); } - return (0); } @@ -445,96 +428,50 @@ fwisound_iso_input(struct fw_xferq *xferq) &sc->dma_ch, dma_ch); } -static void -fwisound_post_explore(void *arg) -{ - struct fwisound_softc *sc = (struct fwisound_softc *)arg; - struct fw_device *fwdev; - uint32_t audio_base; - int err; - - FWISOUND_LOCK(sc); - if (sc->state == FWISOUND_STATE_DETACHING) { - FWISOUND_UNLOCK(sc); - return; - } - - if (sc->fwdev != NULL) { - STAILQ_FOREACH(fwdev, &sc->fd.fc->devices, link) { - if (fwdev == sc->fwdev && - fwdev->status == FWDEVATTACHED) - break; - } - if (fwdev == NULL) { - device_printf(sc->dev, "device disconnected\n"); - sc->fwdev = NULL; - sc->state = FWISOUND_STATE_IDLE; - FWISOUND_UNLOCK(sc); - fwisound_iso_stop(sc); - FWISOUND_LOCK(sc); - } - } - - if (sc->fwdev == NULL) { - STAILQ_FOREACH(fwdev, &sc->fd.fc->devices, link) { - if (fwdev->status != FWDEVATTACHED) - continue; - - audio_base = fwisound_find_audio_unit(fwdev); - if (audio_base == 0) - continue; - - sc->fwdev = fwdev; - sc->cmd_hi = 0xffff; - sc->cmd_lo = 0xf0000000 | (audio_base << 2); - - FWISOUND_UNLOCK(sc); - err = taskqueue_enqueue(taskqueue_thread, - &sc->probe_task); - if (err != 0) - device_printf(sc->dev, - "taskqueue_enqueue failed: %d\n", err); - return; - } - } - - FWISOUND_UNLOCK(sc); -} - -static void -fwisound_post_busreset(void *arg __unused) -{ - -} - -static void -fwisound_identify(driver_t *driver, device_t parent) -{ - - if (device_find_child(parent, "fwisound", DEVICE_UNIT_ANY) == NULL) - BUS_ADD_CHILD(parent, 0, "fwisound", DEVICE_UNIT_ANY); -} static int fwisound_probe(device_t dev) { + struct fw_unit *unit; + + unit = fw_get_unit(dev); + if (unit == NULL) + return (ENXIO); + + if (unit->spec_id != FWISOUND_SPEC_ID || + unit->sw_version != FWISOUND_VERSION) + return (ENXIO); device_set_desc(dev, "Apple FireWire Audio"); - return (0); + return (BUS_PROBE_DEFAULT); } static int fwisound_attach(device_t dev) { struct fwisound_softc *sc; + struct fw_unit *unit; + uint32_t audio_base; + + unit = fw_get_unit(dev); + if (unit == NULL || unit->fwdev == NULL) + return (ENXIO); + + audio_base = fwisound_find_audio_base(unit); + if (audio_base == 0) { + device_printf(dev, "no audio base in unit directory\n"); + return (ENXIO); + } sc = device_get_softc(dev); sc->fd.dev = dev; - sc->fd.fc = device_get_ivars(dev); + sc->fd.fc = fw_get_comm(dev); sc->dev = dev; mtx_init(&sc->mtx, "fwisound", NULL, MTX_DEF); - sc->fwdev = NULL; + sc->fwdev = unit->fwdev; + sc->cmd_hi = 0xffff; + sc->cmd_lo = 0xf0000000 | (audio_base << 2); sc->state = FWISOUND_STATE_IDLE; sc->dma_ch = -1; sc->iso_active = 0; @@ -544,9 +481,6 @@ fwisound_attach(device_t dev) TASK_INIT(&sc->start_task, 0, fwisound_start_task, sc); TASK_INIT(&sc->stop_task, 0, fwisound_stop_task, sc); - sc->fd.post_busreset = fwisound_post_busreset; - sc->fd.post_explore = fwisound_post_explore; - sc->pcm_dev = device_add_child(dev, "pcm", DEVICE_UNIT_ANY); if (sc->pcm_dev == NULL) { device_printf(dev, "failed to add pcm child\n"); @@ -556,7 +490,8 @@ fwisound_attach(device_t dev) bus_attach_children(dev); - fwisound_post_explore(sc); + if (taskqueue_enqueue(taskqueue_thread, &sc->probe_task) != 0) + device_printf(dev, "failed to enqueue probe task\n"); return (0); } @@ -589,7 +524,6 @@ fwisound_detach(device_t dev) } static device_method_t fwisound_methods[] = { - DEVMETHOD(device_identify, fwisound_identify), DEVMETHOD(device_probe, fwisound_probe), DEVMETHOD(device_attach, fwisound_attach), DEVMETHOD(device_detach, fwisound_detach),
