--- via82cxxx.orig.c 2006-05-01 09:18:15.000000000 +0200 +++ via82cxxx.c 2006-05-14 08:23:48.000000000 +0200 @@ -34,6 +34,7 @@ #include #include #include +#include #include #ifdef CONFIG_PPC_MULTIPLATFORM @@ -469,6 +470,99 @@ hwif->drives[1].autodma = hwif->autodma; } +/* Copy of sc1200.c */ + +static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) +{ + int h; + + for (h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; + if (prev) { + if (hwif == prev) + prev = NULL; // found previous, now look for next match + } else { + if (hwif && hwif->pci_dev == dev) + return hwif; // found next match + } + } + return NULL; // not found +} + +static int via_suspend(struct pci_dev *dev, pm_message_t state) +{ + ide_hwif_t *hwif = NULL; + ide_drive_t *drive = NULL; + struct request rq; + struct request_pm_state rqpm; + ide_task_t args; + unsigned int d; + + printk("VIA IDE: suspend(%u)\n", state.event); + + while ( ( hwif = lookup_pci_dev(hwif, dev) ) != NULL ) { + for (d = 0; d < MAX_DRIVES; ++d) { + drive = &(hwif->drives[d]); + if (drive->present) { + ide_init_drive_cmd(&rq); + memset(&rqpm, 0, sizeof(rqpm)); + memset(&args, 0, sizeof(args)); + rq.flags = REQ_PM_SUSPEND; + rq.pm = &rqpm; + rq.special = &args; + rqpm.pm_step = ide_pm_state_start_suspend; + rqpm.pm_state = state.event; + ide_do_drive_cmd(drive, &rq, ide_head_wait); + } + } + } + pci_save_state(dev); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + dev->current_state = state.event; + return 0; +} + +static int via_resume(struct pci_dev *dev) +{ + ide_hwif_t *hwif = NULL; + ide_drive_t *drive = NULL; + struct request rq; + struct request_pm_state rqpm; + ide_task_t args; + unsigned int d; + + printk("VIA IDE: resume\n"); + + pci_restore_state(dev); + pci_set_power_state(dev, PCI_D0); // bring chip back from sleep state + dev->current_state = PM_EVENT_ON; + /* if the device was busmaster before the suspend, make it busmaster again */ + if (dev->is_busmaster) + pci_set_master(dev); + /* if the device was enabled before suspend, reenable */ + if (dev->is_enabled) + pci_enable_device(dev); + + while ( ( hwif = lookup_pci_dev(hwif, dev) ) != NULL ) { + for (d = 0; d < MAX_DRIVES; ++d) { + drive = &(hwif->drives[d]); + if (drive->present) { + ide_init_drive_cmd(&rq); + memset(&args, 0, sizeof(args)); + memset(&rqpm, 0, sizeof(rqpm)); + rq.flags = REQ_PM_RESUME; + rq.pm = &rqpm; + rq.special = &args; + rqpm.pm_step = ide_pm_state_start_resume; + rqpm.pm_state = PM_EVENT_ON; + ide_do_drive_cmd(drive, &rq, ide_head_wait); + } + } + } + return 0; +} + static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = { { /* 0 */ .name = "VP_IDE", @@ -506,6 +600,8 @@ .name = "VIA_IDE", .id_table = via_pci_tbl, .probe = via_init_one, + .suspend = via_suspend, + .resume = via_resume, }; static int via_ide_init(void)