/* Note: We support only master drives for now. This will have to be * improved if we want to handle sleep on the iMacDV where the CD-ROM * is a slave */ static int idepmac_notify_sleep(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[i].regbase) == 0) continue; /* Disable irq during sleep */ disable_irq(pmac_ide[i].irq); ret = check_media_bay_by_base(base, MB_CD); if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present) /* not media bay - put the disk to sleep */ idepmac_sleep_disk(i, base); } break; case PBOOK_WAKE: for (i = 0; i < pmac_ide_count; ++i) { ide_hwif_t *hwif; if ((base = pmac_ide[i].regbase) == 0) continue; hwif = &ide_hwifs[i]; /* We don't handle media bay devices this way */ ret = check_media_bay_by_base(base, MB_CD); if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present) idepmac_wake_disk(i, base); else if (ret == 0) idepmac_wake_bay(i, base); enable_irq(pmac_ide[i].irq); #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC if (hwif->drives[0].present && hwif->drives[0].using_dma) pmac_ide_dma_onoff(&hwif->drives[0], 1); #endif } break; } return PBOOK_SLEEP_OK; }
void __init pmac_ide_probe(void) { struct device_node *np; int i; struct device_node *atas; struct device_node *p, **pp, *removables, **rp; unsigned long base; int irq, big_delay; ide_hwif_t *hwif; if (_machine != _MACH_Pmac) return; pp = &atas; rp = &removables; p = find_devices("ATA"); if (p == NULL) p = find_devices("IDE"); if (p == NULL) p = find_type_devices("ide"); if (p == NULL) p = find_type_devices("ata"); /* Move removable devices such as the media-bay CDROM on the PB3400 to the end of the list. */ for (; p != NULL; p = p->next) { if (p->parent && p->parent->type && strcasecmp(p->parent->type, "media-bay") == 0) { *rp = p; rp = &p->next; } else { *pp = p; pp = &p->next; } } *rp = NULL; *pp = removables; big_delay = 0; for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) { struct device_node *tp; int *bidp; int in_bay = 0; /* * If this node is not under a mac-io or dbdma node, * leave it to the generic PCI driver. */ for (tp = np->parent; tp != 0; tp = tp->parent) if (tp->type && (strcmp(tp->type, "mac-io") == 0 || strcmp(tp->type, "dbdma") == 0)) break; if (tp == 0) continue; if (np->n_addrs == 0) { printk(KERN_WARNING "ide: no address for device %s\n", np->full_name); continue; } /* * If this slot is taken (e.g. by ide-pci.c) try the next one. */ while (i < MAX_HWIFS && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0) ++i; if (i >= MAX_HWIFS) break; base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE; /* XXX This is bogus. Should be fixed in the registry by checking the kind of host interrupt controller, a bit like gatwick fixes in irq.c */ if (np->n_intrs == 0) { printk(KERN_WARNING "ide: no intrs for device %s, using 13\n", np->full_name); irq = 13; } else { irq = np->intrs[0].line; } pmac_ide[i].regbase = base; pmac_ide[i].irq = irq; pmac_ide[i].node = np; if (device_is_compatible(np, "keylargo-ata")) { if (strcmp(np->name, "ata-4") == 0) pmac_ide[i].kind = controller_kl_ata4; else pmac_ide[i].kind = controller_kl_ata3; } else if (device_is_compatible(np, "heathrow-ata")) pmac_ide[i].kind = controller_heathrow; else pmac_ide[i].kind = controller_ohare; bidp = (int *)get_property(np, "AAPL,bus-id", NULL); pmac_ide[i].aapl_bus_id = bidp ? *bidp : 0; if (np->parent && np->parent->name && strcasecmp(np->parent->name, "media-bay") == 0) { #ifdef CONFIG_PMAC_PBOOK media_bay_set_ide_infos(np->parent,base,irq,i); #endif /* CONFIG_PMAC_PBOOK */ in_bay = 1; } else if (pmac_ide[i].kind == controller_ohare) { /* The code below is having trouble on some ohare machines * (timing related ?). Until I can put my hand on one of these * units, I keep the old way */ feature_set(np, FEATURE_IDE0_enable); } else { /* This is necessary to enable IDE when net-booting */ printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n", pmac_ide[i].aapl_bus_id); switch(pmac_ide[i].aapl_bus_id) { case 0: feature_set(np, FEATURE_IDE0_reset); mdelay(10); feature_set(np, FEATURE_IDE0_enable); mdelay(10); feature_clear(np, FEATURE_IDE0_reset); break; case 1: feature_set(np, FEATURE_IDE1_reset); mdelay(10); feature_set(np, FEATURE_IDE1_enable); mdelay(10); feature_clear(np, FEATURE_IDE1_reset); break; case 2: /* This one exists only for KL, I don't know about any enable bit */ feature_set(np, FEATURE_IDE2_reset); mdelay(10); feature_clear(np, FEATURE_IDE2_reset); break; } big_delay = 1; } hwif = &ide_hwifs[i]; pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); hwif->chipset = ide_pmac; hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay; #ifdef CONFIG_PMAC_PBOOK if (in_bay && check_media_bay_by_base(base, MB_CD) == 0) hwif->noprobe = 0; #endif /* CONFIG_PMAC_PBOOK */ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC if (np->n_addrs >= 2) { /* has a DBDMA controller channel */ pmac_ide_setup_dma(np, i); } #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ ++i; } pmac_ide_count = i; if (big_delay) mdelay(IDE_WAKEUP_DELAY_MS); #ifdef CONFIG_PMAC_PBOOK pmu_register_sleep_notifier(&idepmac_sleep_notifier); #endif /* CONFIG_PMAC_PBOOK */ }
/* Note: We support only master drives for now. This will have to be * improved if we want to handle sleep on the iMacDV where the CD-ROM * is a slave */ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when) { int i, ret; unsigned long base; unsigned long flags; int big_delay; switch (when) { case PBOOK_SLEEP_REQUEST: break; case PBOOK_SLEEP_REJECT: break; case PBOOK_SLEEP_NOW: for (i = 0; i < pmac_ide_count; ++i) { ide_hwif_t *hwif; ide_drive_t *drive; int unlock = 0; if ((base = pmac_ide[i].regbase) == 0) continue; hwif = &ide_hwifs[i]; drive = &hwif->drives[0]; if (drive->present) { /* Wait for HW group to complete operations */ if (ide_spin_wait_hwgroup(drive)) { // What can we do here ? Wake drive we had already // put to sleep and return an error ? } else { unlock = 1; /* Lock HW group */ HWGROUP(drive)->busy = 1; /* Stop the device */ idepmac_sleep_device(drive, i, base); } } /* Disable irq during sleep */ disable_irq(pmac_ide[i].irq); if (unlock) spin_unlock_irq(&io_request_lock); /* Check if this is a media bay with an IDE device or not * a media bay. */ ret = check_media_bay_by_base(base, MB_CD); if ((ret == 0) || (ret == -ENODEV)) idepmac_sleep_interface(i, base, (ret == 0)); } break; case PBOOK_WAKE: big_delay = 0; for (i = 0; i < pmac_ide_count; ++i) { if ((base = pmac_ide[i].regbase) == 0) continue; /* Check if this is a media bay with an IDE device or not * a media bay */ ret = check_media_bay_by_base(base, MB_CD); if ((ret == 0) || (ret == -ENODEV)) { idepmac_wake_interface(i, base, (ret == 0)); big_delay = 1; } } /* Let hardware get up to speed */ if (big_delay) mdelay(IDE_WAKEUP_DELAY_MS); for (i = 0; i < pmac_ide_count; ++i) { ide_hwif_t *hwif; ide_drive_t *drive; int j, used_dma; if ((base = pmac_ide[i].regbase) == 0) continue; hwif = &ide_hwifs[i]; drive = &hwif->drives[0]; /* Wait for the drive to come up and set it's DMA */ if (drive->present) { /* Wait up to 20 seconds */ for (j = 0; j < 200; j++) { int status; mdelay(100); status = inb(base + 0x70); if (!(status & BUSY_STAT)) break; } } /* We don't have re-configured DMA yet */ used_dma = drive->using_dma; drive->using_dma = 0; /* We resume processing on the HW group */ spin_lock_irqsave(&io_request_lock, flags); enable_irq(pmac_ide[i].irq); if (drive->present) HWGROUP(drive)->busy = 0; spin_unlock_irqrestore(&io_request_lock, flags); /* Wake the device * We could handle the slave here */ if (drive->present) idepmac_wake_device(drive, used_dma); } break; } return PBOOK_SLEEP_OK; }