When suspending, save & restore as many registers as we can from the
authorderaadt <deraadt@openbsd.org>
Thu, 22 Jul 2010 18:11:16 +0000 (18:11 +0000)
committerderaadt <deraadt@openbsd.org>
Thu, 22 Jul 2010 18:11:16 +0000 (18:11 +0000)
pciide front-ends chips.  More registers will have to added here, chip
by chip (warning messages about unknown chipsets, on resume, mean that
you should talk to me).  Also call the wdc back-end (our child) to have
it reset the controller properly on resume.  This makes all pciide that
we've tested unsuspend.
ok kettenis mlarkin

sys/dev/pci/pciide.c
sys/dev/pci/pciidevar.h

index cdd8551..529fec1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pciide.c,v 1.308 2010/04/20 06:59:47 jsg Exp $        */
+/*     $OpenBSD: pciide.c,v 1.309 2010/07/22 18:11:16 deraadt Exp $    */
 /*     $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $     */
 
 /*
@@ -1409,14 +1409,66 @@ int
 pciide_activate(struct device *self, int act)
 {
        int rv = 0;
+       struct pciide_softc *sc = (struct pciide_softc *)self;
+       int i;
 
        switch (act) {
        case DVACT_SUSPEND:
+               rv = config_activate_children(self, act);
+
+               for (i = 0; i < nitems(sc->sc_save); i++)
+                       sc->sc_save[i] = pci_conf_read(sc->sc_pc,
+                           sc->sc_tag, PCI_MAPREG_END + 0x18 + (i * 4));
+
+               if (sc->sc_pp->chip_map == sch_chip_map) {
+                       sc->sc_save2[0] = pci_conf_read(sc->sc_pc,
+                           sc->sc_tag, SCH_D0TIM);
+                       sc->sc_save2[1] = pci_conf_read(sc->sc_pc,
+                           sc->sc_tag, SCH_D1TIM);
+               } else if (sc->sc_pp->chip_map == piixsata_chip_map) {
+                       sc->sc_save2[0] = pciide_pci_read(sc->sc_pc,
+                           sc->sc_tag, ICH5_SATA_MAP);
+                       sc->sc_save2[1] = pciide_pci_read(sc->sc_pc,
+                           sc->sc_tag, ICH5_SATA_PI);
+                       sc->sc_save2[2] = pciide_pci_read(sc->sc_pc,
+                           sc->sc_tag, ICH_SATA_PCS);
+               } else if (sc->sc_pp->chip_map == piix_chip_map) {
+                       /* nothing to save */
+               } else if (sc->sc_pp->chip_map == phison_chip_map) {
+                       /* nothing to save */
+               }
+               break;
        case DVACT_RESUME:
+               for (i = 0; i < nitems(sc->sc_save); i++)
+                       pci_conf_write(sc->sc_pc, sc->sc_tag,
+                           PCI_MAPREG_END + 0x18 + (i * 4),
+                           sc->sc_save[i]);
+
+               if (sc->sc_pp->chip_map == sch_chip_map) {
+                       pci_conf_write(sc->sc_pc, sc->sc_tag,
+                           SCH_D0TIM, sc->sc_save2[0]);
+                       pci_conf_write(sc->sc_pc, sc->sc_tag,
+                           SCH_D1TIM, sc->sc_save2[1]);
+               } else if (sc->sc_pp->chip_map == piixsata_chip_map) {
+                       pciide_pci_write(sc->sc_pc, sc->sc_tag,
+                           ICH5_SATA_MAP, sc->sc_save2[0]);
+                       pciide_pci_write(sc->sc_pc, sc->sc_tag,
+                           ICH5_SATA_PI, sc->sc_save2[1]);
+                       pciide_pci_write(sc->sc_pc, sc->sc_tag,
+                           ICH_SATA_PCS, sc->sc_save2[2]);
+               } else if (sc->sc_pp->chip_map == piix_chip_map) {
+                       /* nothing more to restore */
+               } else if (sc->sc_pp->chip_map == phison_chip_map) {
+                       /* nothing more to restore */
+               } else {
+                       printf("%s: restore for unknown chip map %x\n",
+                           sc->sc_wdcdev.sc_dev.dv_xname,
+                           sc->sc_pp->ide_product);
+               }
+
                rv = config_activate_children(self, act);
                break;
        }
-
        return (rv);
 }
 
index 9de332a..45684f7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pciidevar.h,v 1.19 2009/10/05 20:01:40 jsg Exp $      */
+/*     $OpenBSD: pciidevar.h,v 1.20 2010/07/22 18:11:16 deraadt Exp $  */
 /*     $NetBSD: pciidevar.h,v 1.6 2001/01/12 16:04:00 bouyer Exp $     */
 
 /*
@@ -70,6 +70,16 @@ struct pciide_softc {
        bus_size_t              sc_dma_maxsegsz;
        bus_size_t              sc_dma_boundary;
 
+       /*
+        * Used as a register save space by pciide_activate()
+        * 
+        * sc_save[] is for the 6 pci regs starting at PCI_MAPREG_END + 0x18 --
+        * most IDE chipsets need a subset of those saved.  sc_save2 is for
+        * up to 6 other registers, which specific chips might need saved.
+        */
+       pcireg_t                sc_save[6];
+       pcireg_t                sc_save2[6];
+
        /* Chip description */
        const struct pciide_product_desc *sc_pp;
        /* unmap/detach */