static void idepmac_sleep_interface(int i, unsigned base, int mediabay) { struct device_node* np = pmac_ide[i].node; /* We clear the timings */ pmac_ide[i].timings[0] = 0; pmac_ide[i].timings[1] = 0; /* The media bay will handle itself just fine */ if (mediabay) return; /* Disable and reset the bus */ feature_set(np, FEATURE_IDE0_reset); feature_clear(np, FEATURE_IDE0_enable); switch(pmac_ide[i].aapl_bus_id) { case 0: feature_set(np, FEATURE_IDE0_reset); feature_clear(np, FEATURE_IDE0_enable); break; case 1: feature_set(np, FEATURE_IDE1_reset); feature_clear(np, FEATURE_IDE1_enable); break; case 2: feature_set(np, FEATURE_IDE2_reset); break; } }
static void idepmac_wake_disk(int i, unsigned long base) { struct device_node* np = pmac_ide[i].node; int j; /* Revive IDE disk and controller */ switch(pmac_ide[i].aapl_bus_id) { case 0: feature_set(np, FEATURE_IDE0_reset); feature_set(np, FEATURE_IOBUS_enable); 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); feature_set(np, FEATURE_IOBUS_enable); 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; } mdelay(IDE_WAKEUP_DELAY_MS); /* Reset timings */ pmac_ide_selectproc(&ide_hwifs[i].drives[0]); mdelay(10); /* 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; } }
/* * This procedure runs as a kernel thread to poll the media bay * once each tick and register and unregister the IDE interface * with the IDE driver. It needs to be a thread because * ide_register can't be called from interrupt context. */ int media_bay_task(void *x) { volatile struct media_bay_info* bay; int i = 0; strcpy(current->comm, "media-bay"); for (;;) { bay = &media_bays[i]; poll_media_bay(i); if (bay->content_id != bay->previous_id) { bay->reset_timer = (bay->content_id != MB_NO) ? MB_RESET_COUNT: 0; bay->ready = 0; #ifdef CONFIG_BLK_DEV_IDE bay->cd_timer = 0; if (bay->content_id != MB_CD && bay->cd_index >= 0) { printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, bay->cd_index); ide_unregister(bay->cd_index); bay->cd_index = -1; } #endif } else if (bay->reset_timer) { if (--bay->reset_timer == 0) { feature_clear(bay->dev_node, FEATURE_Mediabay_reset); bay->ready = 1; #ifdef CONFIG_BLK_DEV_IDE bay->cd_timer = 0; if (bay->content_id == MB_CD && bay->cd_base != 0) bay->cd_timer = MB_IDE_WAIT; #endif } #ifdef CONFIG_BLK_DEV_IDE } else if (bay->cd_timer && (--bay->cd_timer == 0 || MB_IDE_READY(i)) && bay->cd_index < 0) { bay->cd_timer = 0; printk(KERN_DEBUG "Registering IDE, base:0x%08lx, irq:%d\n", bay->cd_base, bay->cd_irq); printk("\n"); bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq); if (bay->cd_index == -1) printk("\nCD-ROM badly inserted. Remove it and try again !\n"); else printk(KERN_DEBUG "media-bay %d is ide %d\n", i, bay->cd_index); #endif } bay->previous_id = bay->content_id; current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); if (signal_pending(current)) return 0; i = (i+1)%media_bay_count; } }
static void idepmac_sleep_disk(int i, unsigned long base) { struct device_node* np = pmac_ide[i].node; int j; /* 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; } } feature_set(np, FEATURE_IDE0_reset); feature_clear(np, FEATURE_IDE0_enable); switch(pmac_ide[i].aapl_bus_id) { case 0: feature_set(np, FEATURE_IDE0_reset); feature_clear(np, FEATURE_IDE0_enable); break; case 1: feature_set(np, FEATURE_IDE1_reset); feature_clear(np, FEATURE_IDE1_enable); break; case 2: feature_set(np, FEATURE_IDE2_reset); break; } pmac_ide[i].timings[0] = 0; pmac_ide[i].timings[1] = 0; }
static void idepmac_wake_interface(int i, unsigned long base, int mediabay) { struct device_node* np = pmac_ide[i].node; if (!mediabay) { /* Revive IDE disk and controller */ switch(pmac_ide[i].aapl_bus_id) { case 0: feature_set(np, FEATURE_IDE0_reset); feature_set(np, FEATURE_IOBUS_enable); 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); feature_set(np, FEATURE_IOBUS_enable); 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; } } /* Reset timings */ pmac_ide_selectproc(&ide_hwifs[i].drives[0]); mdelay(10); }
static void set_media_bay(int which, int id) { volatile struct media_bay_info* bay; bay = &media_bays[which]; bay->content_id = id; bay->last_value = id; switch (id) { case MB_CD: feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable); feature_set(bay->dev_node, FEATURE_Mediabay_enable); feature_set(bay->dev_node, FEATURE_CD_power); feature_set(bay->dev_node, FEATURE_Mediabay_IDE_enable); printk(KERN_INFO "media bay %d contains a CD-ROM drive\n", which); break; case MB_FD: feature_clear(bay->dev_node, FEATURE_CD_power); feature_set(bay->dev_node, FEATURE_Mediabay_enable); feature_set(bay->dev_node, FEATURE_Mediabay_floppy_enable); feature_set(bay->dev_node, FEATURE_SWIM3_enable); printk(KERN_INFO "media bay %d contains a floppy disk drive\n", which); break; case MB_NO: feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable); feature_clear(bay->dev_node, FEATURE_CD_power); printk(KERN_INFO "media bay %d is empty\n", which); break; default: feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable); feature_clear(bay->dev_node, FEATURE_CD_power); feature_set(bay->dev_node, FEATURE_Mediabay_enable); printk(KERN_INFO "media bay %d contains an unknown device (%d)\n", which, id); break; } udelay(500); }
__pmac /* I don't know of any chrp with a mediabay -- Cort */ void media_bay_init(void) { struct device_node *np; int n,i; for (i=0; i<MAX_BAYS; i++) { memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info)); media_bays[i].content_id = -1; #ifdef CONFIG_BLK_DEV_IDE media_bays[i].cd_index = -1; #endif } np = find_devices("media-bay"); n = 0; while(np && (n<MAX_BAYS)) { if (np->n_addrs == 0) continue; media_bays[n].addr = (volatile struct media_bay_hw *) ioremap(np->addrs[0].address, sizeof(struct media_bay_hw)); #ifdef MB_USE_INTERRUPTS if (np->n_intrs == 0) { printk(KERN_ERR "media bay %d has no irq\n",n); continue; } if (request_irq(np_intrs[0].line, media_bay_intr, 0, "Media bay", NULL)) { printk(KERN_ERR "Couldn't get IRQ %d for media bay %d\n", irq, n); continue; } #endif media_bay_count++; set_media_bay(n, MB_CONTENTS(n)); if (media_bays[n].content_id != MB_NO) { feature_clear(media_bays[n].dev_node, FEATURE_Mediabay_reset); udelay(500); } media_bays[n].ready = 1; media_bays[n].previous_id = media_bays[n].content_id; media_bays[n].reset_timer = 0; media_bays[n].dev_node = np; #ifdef CONFIG_BLK_DEV_IDE media_bays[n].cd_timer = 0; #endif n++; np=np->next; } if (media_bay_count) { printk(KERN_INFO "Registered %d media-bay(s)\n", media_bay_count); kernel_thread(media_bay_task, NULL, 0); } }
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 */ }