Here is another attempt at the drive bay eject code.. this one will detect if the bay is already installed and do a better job of of identifying bay devices.
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 1 Jun 2009 06:00:29 -0000 @@ -339,6 +339,130 @@ 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 *); + +#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; + int64_t sta; +}; + +int is_ejectable_bay(struct aml_node *node); +int is_ata(struct aml_node *node); +int is_ejectable(struct aml_node *node); + +int +is_ata(struct aml_node *node) +{ + return (aml_searchname(node, "_GTM") != NULL || + aml_searchname(node, "_GTF") != NULL || + aml_searchname(node, "_STM") != NULL || + aml_searchname(node, "_SDD") != NULL); +} + +int +is_ejectable(struct aml_node *node) +{ + return aml_searchname(node, "_EJ0") != NULL; +} + +int +is_ejectable_bay(struct aml_node *node) +{ + return ((is_ata(node) || is_ata(node->parent)) && is_ejectable(node)); +} + +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\n", + dev->dv_xname, b,d,f, ide->chnl); + + if (sta == 0 && ide->sta) + wdcdetach(&wsc->pciide_channels[ide->chnl].wdc_channel,0); + else if (sta && !ide->sta) + wdcattach(&wsc->pciide_channels[ide->chnl].wdc_channel); + ide->sta = sta; + } + 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; + + /* Check if this is an ejectable bay */ + if (!is_ejectable_bay(node)) + return 0; + + 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_evalinteger(sc, node, "_STA", 0, NULL, &ide->sta); + printf("Got Initial STA: %llx\n", ide->sta); + + aml_register_notify(node, "acpiide", acpiide_notify, ide, 0); + return 0; +} + int acpi_match(struct device *parent, void *match, void *aux) { @@ -584,6 +708,9 @@ 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_walknodes(&aml_root, AML_WALK_PRE, acpi_foundide, sc); /* attach docks */ aml_find_node(&aml_root, "_DCK", acpi_founddock, sc);