From 24a85e15478bdc67ed53c13736e67f54f1540127 Mon Sep 17 00:00:00 2001 From: deraadt Date: Thu, 22 Jul 2010 18:11:16 +0000 Subject: [PATCH] When suspending, save & restore as many registers as we can from the 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 | 56 +++++++++++++++++++++++++++++++++++++++-- sys/dev/pci/pciidevar.h | 12 ++++++++- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c index cdd8551ac80..529fec17576 100644 --- a/sys/dev/pci/pciide.c +++ b/sys/dev/pci/pciide.c @@ -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); } diff --git a/sys/dev/pci/pciidevar.h b/sys/dev/pci/pciidevar.h index 9de332aaa6f..45684f7d5bd 100644 --- a/sys/dev/pci/pciidevar.h +++ b/sys/dev/pci/pciidevar.h @@ -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 */ -- 2.20.1