Jordan wrote this diff to play with modular hotplug bay devices such as cd players. We need some tests on this to see if the acpi device to pci device mapping works right. Try removing and reinserting the cd bay device.
Be warned that this may panic your box. Please send me and jordan the results. Index: acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpi.c,v retrieving revision 1.137 diff -u -p -u -p -b -r1.137 acpi.c --- acpi.c 30 Apr 2009 20:42:14 -0000 1.137 +++ acpi.c 31 May 2009 18:18:53 -0000 @@ -339,6 +339,103 @@ acpi_foundprt(struct aml_node *node, voi return 0; } +int acpi_foundide(struct aml_node *node, void *arg); +int acpiide_notify(struct aml_node *, int, void *); + +int ide_installed=1; + +#include <dev/pci/pciidereg.h> +#include <dev/pci/pciidevar.h> +void wdcattach(struct channel_softc *); +int wdcdetach(struct channel_softc *, int); + +struct idechnl +{ + struct acpi_softc *sc; + int64_t addr; + int64_t chnl; +}; + +int +acpiide_notify(struct aml_node *node, int ntype, void *arg) +{ + struct idechnl *ide = arg; + struct acpi_softc *sc = ide->sc; + struct pciide_softc *wsc; + struct device *dev; + int b,d,f; + int64_t sta; + + if (aml_evalinteger(sc, node, "_STA", 0, NULL, &sta) != 0) + return 0; + + printf("IDE notify! %s %d status:%llx\n", aml_nodename(node), ntype, sta); + + /* Walk device list looking for IDE device match */ + TAILQ_FOREACH(dev, &alldevs, dv_list) { + if (strncmp(dev->dv_xname, "pciide", 6)) + continue; + + wsc = (struct pciide_softc *)dev; + pci_decompose_tag(NULL, wsc->sc_tag, &b, &d, &f); + if (b != ACPI_PCI_BUS(ide->addr) || + d != ACPI_PCI_DEV(ide->addr) || + f != ACPI_PCI_FN(ide->addr)) + continue; + printf("Found pciide: %s %x.%x.%x channel:%llx \"%s\"\n", + dev->dv_xname, b,d,f, ide->chnl, + wsc->pciide_channels[ide->chnl].name); +#if 1 + if (sta == 0 && ide_installed) { + ide_installed = 0; + wdcdetach(&wsc->pciide_channels[ide->chnl].wdc_channel,0); + } + else if (sta && !ide_installed) { + ide_installed = 1; + wdcattach(&wsc->pciide_channels[ide->chnl].wdc_channel); + } +#endif + } + return 0; +} + +int +acpi_foundide(struct aml_node *node, void *arg) +{ + struct acpi_softc *sc = arg; + struct aml_node *pp; + struct idechnl *ide; + int lvl; + + ide = malloc(sizeof(struct idechnl), M_DEVBUF, M_NOWAIT | M_ZERO); + ide->sc = sc; + + /* GTM/GTF can be at 2/3 levels: pciX.ideX.channelX[.driveX] */ + lvl = 0; + for (pp=node->parent; pp; pp=pp->parent) { + lvl++; + if (aml_searchname(pp, "_HID")) + break; + } + + /* Get PCI address and channel */ + if (lvl == 3) { + aml_evalinteger(sc, node->parent, "_ADR", 0, NULL, + &ide->chnl); + aml_xgetpci(node->parent, &ide->addr); + } + else if (lvl == 4) { + aml_evalinteger(sc, node->parent->parent, "_ADR", 0, NULL, + &ide->chnl); + aml_xgetpci(node->parent->parent, &ide->addr); + } + printf("%s %llx channel:%llx\n", + aml_nodename(node), ide->addr, ide->chnl); + + aml_register_notify(node->parent, "acpiide", acpiide_notify, ide, 0); + return 0; +} + int acpi_match(struct device *parent, void *match, void *aux) { @@ -584,6 +681,10 @@ acpi_attach(struct device *parent, struc /* attach battery, power supply and button devices */ aml_find_node(&aml_root, "_HID", acpi_foundhid, sc); + + /* Attach IDE bay */ + aml_find_node(&aml_root, "_GTF", acpi_foundide, sc); + aml_find_node(&aml_root, "_GTM", acpi_foundide, sc); /* attach docks */ aml_find_node(&aml_root, "_DCK", acpi_founddock, sc);