Beispiel #1
0
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;
	}
}
Beispiel #2
0
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;
	}
}
Beispiel #3
0
/*
 * 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;
	}
}
Beispiel #4
0
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;
}
Beispiel #5
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);
}
Beispiel #6
0
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);
}
Beispiel #7
0
__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);
	}
}
Beispiel #8
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 */
}