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);