patch-2.3.21 linux/drivers/block/ide-pmac.c
Next file: linux/drivers/block/ide.c
Previous file: linux/drivers/block/ide-geometry.c
Back to the patch index
Back to the overall index
- Lines: 157
- Date:
Mon Oct 11 10:10:19 1999
- Orig file:
v2.3.20/linux/drivers/block/ide-pmac.c
- Orig date:
Tue Aug 31 17:29:13 1999
diff -u --recursive --new-file v2.3.20/linux/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c
@@ -30,8 +30,9 @@
#include <asm/mediabay.h>
#include <asm/feature.h>
#ifdef CONFIG_PMAC_PBOOK
-#include <asm/adb.h>
-#include <asm/pmu.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/irq.h>
#endif
#include "ide_modes.h"
@@ -50,9 +51,9 @@
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
#ifdef CONFIG_PMAC_PBOOK
-static int idepmac_notify(struct notifier_block *, unsigned long, void *);
-struct notifier_block idepmac_sleep_notifier = {
- idepmac_notify
+static int idepmac_notify(struct pmu_sleep_notifier *self, int when);
+struct pmu_sleep_notifier idepmac_sleep_notifier = {
+ idepmac_notify, SLEEP_LEVEL_BLOCK,
};
#endif /* CONFIG_PMAC_PBOOK */
@@ -224,7 +225,7 @@
pmac_ide_count = i;
#ifdef CONFIG_PMAC_PBOOK
- notifier_chain_register(&sleep_notifier_list, &idepmac_sleep_notifier);
+ pmu_register_sleep_notifier(&idepmac_sleep_notifier);
#endif /* CONFIG_PMAC_PBOOK */
}
@@ -384,29 +385,107 @@
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
#ifdef CONFIG_PMAC_PBOOK
-static int idepmac_notify(struct notifier_block *this,
- unsigned long code, void *p)
+static void idepmac_sleep_disk(int i, unsigned long base)
{
- int i, timeout;
+ int j;
- switch (code) {
- case PBOOK_SLEEP:
- /* do anything here?? */
+ /* Reset to PIO 0 */
+ out_le32((unsigned *)(base + 0x200 + _IO_BASE), 0x2f8526);
+
+ /* FIXME: We only handle the master IDE */
+ if (ide_hwifs[i].drives[0].media == ide_disk) {
+ /* Spin down the drive */
+ outb(0xa0, base+0x60);
+ outb(0x0, base+0x30);
+ outb(0x0, base+0x20);
+ outb(0x0, base+0x40);
+ outb(0x0, base+0x50);
+ outb(0xe0, base+0x70);
+ outb(0x2, base+0x160);
+ for (j = 0; j < 10; j++) {
+ int status;
+ mdelay(100);
+ status = inb(base+0x70);
+ if (!(status & BUSY_STAT) && (status & DRQ_STAT))
+ break;
+ }
+ }
+}
+
+static void idepmac_wake_disk(int i, unsigned long base)
+{
+ int j;
+
+ /* Revive IDE disk and controller */
+ feature_set(pmac_ide_node[i], FEATURE_IDE_enable);
+ mdelay(1);
+ feature_set(pmac_ide_node[i], FEATURE_IDE_DiskPower);
+ mdelay(100);
+ feature_set(pmac_ide_node[i], FEATURE_IDE_Reset);
+ mdelay(1);
+ /* Make sure we are still PIO0 */
+ out_le32((unsigned *)(base + 0x200 + _IO_BASE), 0x2f8526);
+ mdelay(100);
+
+ /* Wait up to 10 seconds (enough for recent drives) */
+ for (j = 0; j < 100; j++) {
+ int status;
+ mdelay(100);
+ status = inb(base + 0x70);
+ if (!(status & BUSY_STAT))
+ break;
+ }
+}
+
+/* Here we handle media bay devices */
+static void
+idepmac_wake_bay(int i, unsigned long base)
+{
+ int timeout;
+
+ timeout = 5000;
+ while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
+ mdelay(1);
+ --timeout;
+ }
+}
+
+static int idepmac_notify(struct pmu_sleep_notifier *self, int when)
+{
+ int i, ret;
+ unsigned long base;
+
+ switch (when) {
+ case PBOOK_SLEEP_REQUEST:
+ break;
+ case PBOOK_SLEEP_REJECT:
+ break;
+ case PBOOK_SLEEP_NOW:
+ for (i = 0; i < pmac_ide_count; ++i) {
+ if ((base = pmac_ide_regbase[i]) == 0)
+ continue;
+ /* Disable irq during sleep */
+ disable_irq(pmac_ide_irq[i]);
+ ret = check_media_bay_by_base(base, MB_CD);
+ if (ret == -ENODEV)
+ /* not media bay - put the disk to sleep */
+ idepmac_sleep_disk(i, base);
+ }
break;
case PBOOK_WAKE:
- /* wait for the controller(s) to become ready */
- timeout = 5000;
for (i = 0; i < pmac_ide_count; ++i) {
- unsigned long base = pmac_ide_regbase[i];
- if (check_media_bay_by_base(base, MB_CD) == -EINVAL)
+ if ((base = pmac_ide_regbase[i]) == 0)
continue;
- while ((inb(base + 0x70) & BUSY_STAT) && timeout) {
- mdelay(1);
- --timeout;
- }
+ /* We don't handle media bay devices this way */
+ ret = check_media_bay_by_base(base, MB_CD);
+ if (ret == -ENODEV)
+ idepmac_wake_disk(i, base);
+ else if (ret == 0)
+ idepmac_wake_bay(i, base);
+ enable_irq(pmac_ide_irq[i]);
}
break;
}
- return NOTIFY_DONE;
+ return PBOOK_SLEEP_OK;
}
#endif /* CONFIG_PMAC_PBOOK */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)