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

Reply via email to