DF-4783 / mmcbang.c
/* * mmcbang.c -- DF-4783 PoC trigger (TEST ONLY, never for sys/). * * Invokes the sdhci_pci driver's OWN attach/detach driver-methods on unit 0 * so the device_t remains in the devclass and the cycle is repeatable: * * sysctl hw.mmcbang.action=1 -> sdhci_pci_detach() (card removal / * hot-unplug teardown) * sysctl hw.mmcbang.action=2 -> sdhci_pci_attach() (re-insert / rescan) * * detach cascades: sdhci_cleanup_slot -> device_delete_child(mmcX) -> * mmc_detach -> mmc_delete_cards -> device_delete_child(mmcsdX) -> * mmcsd_detach + newbus frees the mmcsd softc — while raw-pread spammers * are inside mmcsd_strategy() on /dev/mmcsd0 (no exclusion: DF-4646 family). */ #include <sys/param.h> #include <sys/module.h> #include <sys/kernel.h> #include <sys/conf.h> #include <sys/systm.h> #include <sys/bus.h> #include <sys/sysctl.h> #include <sys/kobj.h> static int mmcbang_action(SYSCTL_HANDLER_ARGS); static int mmcbang_act = 0; SYSCTL_NODE(_hw, OID_AUTO, mmcbang, CTLFLAG_RW, 0, "mmcsd bang test"); SYSCTL_PROC(_hw_mmcbang, OID_AUTO, action, CTLTYPE_INT | CTLFLAG_RW, &mmcbang_act, 0, mmcbang_action, "I", "1=detach 2=attach"); static int mmcbang_action(SYSCTL_HANDLER_ARGS) { devclass_t dc; driver_t *drv; kobj_method_t *m; device_t dev; int error; int (*attach_fn)(device_t) = NULL; int (*detach_fn)(device_t) = NULL; error = sysctl_handle_int(oidp, &mmcbang_act, 0, req); if (error || req->newptr == NULL) return (error); if (mmcbang_act == 0) return (0); dc = devclass_find("sdhci_pci"); if (dc == NULL) { kprintf("mmcbang: devclass 'sdhci_pci' not found\n"); return (ENOENT); } dev = devclass_get_device(dc, 0); if (dev == NULL) { kprintf("mmcbang: sdhci_pci0 not present\n"); return (ENOENT); } drv = device_get_driver(dev); if (drv == NULL || drv->methods == NULL) { kprintf("mmcbang: no driver\n"); return (ENOENT); } for (m = drv->methods; m && m->func; ++m) { if (m->desc == NULL) continue; if (m->desc == &device_attach_desc) attach_fn = (int (*)(device_t))m->func; else if (m->desc == &device_detach_desc) detach_fn = (int (*)(device_t))m->func; } if (mmcbang_act == 1 && detach_fn) { kprintf("mmcbang: DETACH on %s...\n", device_get_nameunit(dev)); error = detach_fn(dev); kprintf("mmcbang: detach returned %d\n", error); } else if (mmcbang_act == 2 && attach_fn) { kprintf("mmcbang: ATTACH on %s...\n", device_get_nameunit(dev)); error = attach_fn(dev); kprintf("mmcbang: attach returned %d\n", error); } else { kprintf("mmcbang: no method\n"); error = ENODEV; } return (error); } DEV_MODULE(mmcbang, NULL, NULL); |