Index: ata-chipset.c =================================================================== RCS file: /usr/cvs/src/sys/dev/ata/ata-chipset.c,v retrieving revision 1.192 diff -u -r1.192 ata-chipset.c --- ata-chipset.c 12 Mar 2007 15:34:08 -0000 1.192 +++ ata-chipset.c 31 May 2007 20:58:05 -0000 @@ -93,6 +93,8 @@ static int ata_highpoint_check_80pin(device_t dev, int mode); static int ata_intel_chipinit(device_t dev); static int ata_intel_allocate(device_t dev); +static void ata_intel_suspend(device_t dev); +static void ata_intel_resume(device_t dev); static void ata_intel_reset(device_t dev); static void ata_intel_old_setmode(device_t dev, int mode); static void ata_intel_new_setmode(device_t dev, int mode); @@ -1751,6 +1753,8 @@ else if (ctlr->chip->max_dma < ATA_SA150) { ctlr->allocate = ata_intel_allocate; ctlr->setmode = ata_intel_new_setmode; + ctlr->suspend = ata_intel_suspend; + ctlr->resume = ata_intel_resume; } /* SATA parts can be either compat or AHCI */ @@ -1918,6 +1922,30 @@ atadev->mode = mode; } +static void +ata_intel_suspend(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + ctlr->suspend_data.intel_ich.ide_timing = pci_read_config(dev, 0x40, 4); + ctlr->suspend_data.intel_ich.slave_timing = pci_read_config(dev, 0x44, 1); + ctlr->suspend_data.intel_ich.sdma_count = pci_read_config(dev, 0x48, 1); + ctlr->suspend_data.intel_ich.sdma_timing = pci_read_config(dev, 0x4A, 2); + ctlr->suspend_data.intel_ich.ide_config = pci_read_config(dev, 0x54, 4); +} + +static void +ata_intel_resume(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + pci_write_config(dev, 0x40, ctlr->suspend_data.intel_ich.ide_timing, 4); + pci_write_config(dev, 0x44, ctlr->suspend_data.intel_ich.slave_timing, 1); + pci_write_config(dev, 0x48, ctlr->suspend_data.intel_ich.sdma_count, 1); + pci_write_config(dev, 0x4A, ctlr->suspend_data.intel_ich.sdma_timing, 2); + pci_write_config(dev, 0x54, ctlr->suspend_data.intel_ich.ide_config, 4); +} + static int ata_intel_31244_allocate(device_t dev) { Index: ata-pci.c =================================================================== RCS file: /usr/cvs/src/sys/dev/ata/ata-pci.c,v retrieving revision 1.121 diff -u -r1.121 ata-pci.c --- ata-pci.c 23 Feb 2007 12:18:33 -0000 1.121 +++ ata-pci.c 31 May 2007 20:41:31 -0000 @@ -251,6 +251,46 @@ return 0; } +int +ata_pci_suspend(device_t dev) +{ + struct ata_pci_controller *controller = device_get_softc(dev); + int i; + + if (bootverbose) { + device_printf(dev, "Suspending, dumping config space:"); + for (i = 0; i < 0x100; i+= 4) { + if (i % 16 == 0) + printf("\n %02x:", i); + printf(" %08x", pci_read_config(dev, i, 4)); + } + printf("\n"); + } + if (controller->suspend) + controller->suspend(dev); + return (bus_generic_suspend(dev)); +} + +int +ata_pci_resume(device_t dev) +{ + struct ata_pci_controller *controller = device_get_softc(dev); + int i; + + if (controller->resume) + controller->resume(dev); + if (bootverbose) { + device_printf(dev, "Resuming, dumping config space:"); + for (i = 0; i < 0x100; i+= 4) { + if (i % 16 == 0) + printf("\n %02x:", i); + printf(" %08x", pci_read_config(dev, i, 4)); + } + printf("\n"); + } + return (bus_generic_resume(dev)); +} + struct resource * ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) @@ -509,8 +549,8 @@ DEVMETHOD(device_attach, ata_pci_attach), DEVMETHOD(device_detach, ata_pci_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_suspend, ata_pci_suspend), + DEVMETHOD(device_resume, ata_pci_resume), /* bus methods */ DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), Index: ata-pci.h =================================================================== RCS file: /usr/cvs/src/sys/dev/ata/ata-pci.h,v retrieving revision 1.76 diff -u -r1.76 ata-pci.h --- ata-pci.h 9 Mar 2007 22:23:39 -0000 1.76 +++ ata-pci.h 31 May 2007 20:49:51 -0000 @@ -36,6 +36,17 @@ char *text; }; +/* controller-specific data for suspend/resume */ +union ata_pci_suspend { + struct { + uint32_t ide_timing; /* 0x40 */ + uint8_t slave_timing; /* 0x44 */ + uint8_t sdma_count; /* 0x48 */ + uint16_t sdma_timing; /* 0x4A */ + uint32_t ide_config; /* 0x54 */ + } intel_ich; +}; + /* structure describing a PCI ATA controller */ struct ata_pci_controller { device_t dev; @@ -55,10 +66,13 @@ void (*reset)(device_t); void (*dmainit)(device_t); void (*setmode)(device_t, int); + void (*suspend)(device_t); + void (*resume)(device_t); struct { void (*function)(void *); void *argument; } interrupt[8]; /* XXX SOS max ch# for now */ + union ata_pci_suspend suspend_data; }; /* structure for SATA connection update hotplug/hotswap support */ @@ -431,6 +445,8 @@ int ata_pci_probe(device_t dev); int ata_pci_attach(device_t dev); int ata_pci_detach(device_t dev); +int ata_pci_suspend(device_t dev); +int ata_pci_resume(device_t dev); struct resource * ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags); int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r); int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filter, driver_intr_t *function, void *argument, void **cookiep);