Example #1
0
int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing,
			       ide_hwif_t **hwifp,
			       void(*fixup)(ide_hwif_t *hwif))
{
	int index, retry = 1;
	ide_hwif_t *hwif;
	do {
		for (index = 0; index < MAX_HWIFS; ++index) {
			hwif = &ide_hwifs[index];
			if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
				goto found;
		}
		for (index = 0; index < MAX_HWIFS; ++index) {
			hwif = &ide_hwifs[index];
			if (hwif->hold)
				continue;
			if ((!hwif->present && !hwif->mate && !initializing) ||
			    (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
				goto found;
		}
		for (index = 0; index < MAX_HWIFS; index++)
			ide_unregister(index);
	} while (retry--);
	return -1;
found:
	if (hwif->present){
		ide_unregister(index);
	}
	else if (!hwif->hold) {
		init_hwif_data(hwif, index);
		init_hwif_default(hwif, index);
	}
	if (hwif->present)
		return -1;
	memcpy(&hwif->hw, hw, sizeof(*hw));
	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
	hwif->irq = hw->irq;
	hwif->noprobe = 0;
	hwif->chipset = hw->chipset;
	hwif->gendev.parent = hw->dev;

	if (!initializing) {
		probe_hwif_init_with_fixup(hwif, fixup);
		ide_proc_register_port(hwif);
	}

	if (hwifp)
		*hwifp = hwif;
	return (initializing || hwif->present) ? index : -1;
}
Example #2
0
void ide_release(dev_link_t *link)
{
    ide_info_t *info = link->priv;
    
    DEBUG(0, "ide_release(0x%p)\n", link);

    if (info->ndev) {
	/* FIXME: if this fails we need to queue the cleanup somehow
	   -- need to investigate the required PCMCIA magic */
	ide_unregister(info->hd);
	/* deal with brain dead IDE resource management */
	request_region(link->io.BasePort1, link->io.NumPorts1,
		       info->node.dev_name);
	if (link->io.NumPorts2)
	    request_region(link->io.BasePort2, link->io.NumPorts2,
			   info->node.dev_name);
	MOD_DEC_USE_COUNT;
    }
    info->ndev = 0;
    link->dev = NULL;
    
    CardServices(ReleaseConfiguration, link->handle);
    CardServices(ReleaseIO, link->handle, &link->io);
    CardServices(ReleaseIRQ, link->handle, &link->irq);
    
    link->state &= ~DEV_CONFIG;

} /* ide_release */
Example #3
0
static void ide_release(void *arg)
{
    dev_link_t *link = arg;
    ide_info_t *info = link->priv;
    
    if (!(link->state & DEV_CONFIG))
	return;

    DEBUG(0, "ide_do_release(0x%p)\n", link);

    if (info->ndev) {
        /* FIXME: if this fails we need to queue the cleanup somehow
           -- need to investigate the required PCMCIA magic */
	ide_unregister(info->hd);
	MOD_DEC_USE_COUNT;
    }

    request_region(link->io.BasePort1, link->io.NumPorts1,"ide-cs");
    if (link->io.NumPorts2)
	request_region(link->io.BasePort2, link->io.NumPorts2,"ide-cs");
    
    info->ndev = 0;
    link->dev = NULL;
    
    CardServices(ReleaseConfiguration, link->handle);
    CardServices(ReleaseIO, link->handle, &link->io);
    CardServices(ReleaseIRQ, link->handle, &link->irq);
    
    link->state &= ~DEV_CONFIG;

} /* ide_release */
Example #4
0
static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
{
    ide_hwif_t *hwif;
    hw_regs_t hw;
    int i;
    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };

    memset(&hw, 0, sizeof(hw));
    ide_std_init_ports(&hw, io, ctl);
    hw.irq = irq;
    hw.chipset = ide_pci;
    hw.dev = &handle->dev;

    hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
    if (hwif == NULL)
	return -1;

    i = hwif->index;

    if (hwif->present)
	ide_unregister(i, 0, 0);
    else if (!hwif->hold)
	ide_init_port_data(hwif, i);

    ide_init_port_hw(hwif, &hw);
    hwif->quirkproc = &ide_undecoded_slave;

    idx[0] = i;

    ide_device_add(idx, NULL);

    return hwif->present ? i : -1;
}
Example #5
0
static int __devexit plat_ide_remove(struct platform_device *pdev)
{
    ide_hwif_t *hwif = pdev->dev.driver_data;

    ide_unregister(hwif);

    return 0;
}
Example #6
0
static void idepnp_remove(struct pnp_dev * dev)
{
	ide_hwif_t *hwif = pnp_get_drvdata(dev);
	if (hwif) {
		ide_unregister(hwif->index);
	} else
		printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
}
static void
delkin_cb_remove (struct pci_dev *dev)
{
	ide_hwif_t *hwif = pci_get_drvdata(dev);

	if (hwif)
		ide_unregister(hwif->index);
	pci_disable_device(dev);
}
Example #8
0
static void idepnp_remove(struct pnp_dev *dev)
{
    ide_hwif_t *hwif = pnp_get_drvdata(dev);

    ide_unregister(hwif);

    release_region(pnp_port_start(dev, 1), 1);
    release_region(pnp_port_start(dev, 0), 8);
}
Example #9
0
static void __devexit rapide_remove(struct expansion_card *ec)
{
	ide_hwif_t *hwif = ecard_get_drvdata(ec);

	ecard_set_drvdata(ec, NULL);

	/* there must be a better way */
	ide_unregister(hwif - ide_hwifs);
	ecard_release_resources(ec);
}
Example #10
0
static void
delkin_cb_remove (struct pci_dev *dev)
{
	ide_hwif_t *hwif = pci_get_drvdata(dev);

	ide_unregister(hwif);

	pci_release_regions(dev);
	pci_disable_device(dev);
}
Example #11
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;
	}
}
Example #12
0
void __exit cleanup_module (void)
{
	int index;

	for (index = 0; index < MAX_HWIFS; ++index)
		ide_unregister(index);

#ifdef CONFIG_BLK_DEV_IDEPNP
	pnpide_exit();
#endif

	proc_ide_destroy();

	bus_unregister(&ide_bus_type);
}
Example #13
0
void ide_release(struct pcmcia_device *link)
{
    ide_info_t *info = link->priv;
    
    DEBUG(0, "ide_release(0x%p)\n", link);

    if (info->ndev) {
	/* FIXME: if this fails we need to queue the cleanup somehow
	   -- need to investigate the required PCMCIA magic */
	ide_unregister(info->hd);
    }
    info->ndev = 0;

    pcmcia_disable_device(link);
} /* ide_release */
Example #14
0
void ide_release(u_long arg)
{
    dev_link_t *link = (dev_link_t *)arg;
    ide_info_t *info = link->priv;

    DEBUG(0, "ide_release(0x%p)\n", link);

    if (info->ndev) {
        ide_unregister(info->hd);
        MOD_DEC_USE_COUNT;
    }
    info->ndev = 0;
    link->dev = NULL;

    CardServices(ReleaseConfiguration, link->handle);
    CardServices(ReleaseIO, link->handle, &link->io);
    CardServices(ReleaseIRQ, link->handle, &link->irq);

    link->state &= ~DEV_CONFIG;

} /* ide_release */
Example #15
0
void ide_release(dev_link_t *link)
{
    ide_info_t *info = link->priv;
    
    DEBUG(0, "ide_release(0x%p)\n", link);

    if (info->ndev) {
	/* FIXME: if this fails we need to queue the cleanup somehow
	   -- need to investigate the required PCMCIA magic */
	ide_unregister(info->hd);
    }
    info->ndev = 0;
    link->dev = NULL;
    
    pcmcia_release_configuration(link->handle);
    pcmcia_release_io(link->handle, &link->io);
    pcmcia_release_irq(link->handle, &link->irq);
    
    link->state &= ~DEV_CONFIG;

} /* ide_release */
Example #16
0
static int __devinit palm_bk3710_probe(struct platform_device *pdev)
{
	struct clk *clk;
	struct resource *mem, *irq;
	ide_hwif_t *hwif;
	unsigned long base, rate;
	int i;
	hw_regs_t hw;
	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };

	clk = clk_get(&pdev->dev, "IDECLK");
	if (IS_ERR(clk))
		return -ENODEV;

	clk_enable(clk);
	rate = clk_get_rate(clk);
	ideclk_period = 1000000000UL / rate;

	/* Register the IDE interface with Linux ATA Interface */
	memset(&hw, 0, sizeof(hw));

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (mem == NULL) {
		printk(KERN_ERR "failed to get memory region resource\n");
		return -ENODEV;
	}

	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (irq == NULL) {
		printk(KERN_ERR "failed to get IRQ resource\n");
		return -ENODEV;
	}

	if (request_mem_region(mem->start, mem->end - mem->start + 1,
			       "palm_bk3710") == NULL) {
		printk(KERN_ERR "failed to request memory region\n");
		return -EBUSY;
	}

	base = IO_ADDRESS(mem->start);

	/* Configure the Palm Chip controller */
	palm_bk3710_chipinit((void __iomem *)base);

	for (i = 0; i < IDE_NR_PORTS - 2; i++)
		hw.io_ports[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i;
	hw.io_ports[IDE_CONTROL_OFFSET] = base + IDE_PALM_ATA_PRI_CTL_OFFSET;
	hw.irq = irq->start;
	hw.chipset = ide_palm3710;

	hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
	if (hwif == NULL)
		goto out;

	i = hwif->index;

	if (hwif->present)
		ide_unregister(i, 0, 1);
	else if (!hwif->hold)
		ide_init_port_data(hwif, i);

	ide_init_port_hw(hwif, &hw);
	hwif->fixup = NULL;

	hwif->tuneproc	= &palm_bk3710_tune_drive;
	hwif->speedproc = &palm_bk3710_tune_chipset;
	hwif->mmio = 2;
	default_hwif_mmiops(hwif);

	if (rate >= 100000000)
		hwif->ultra_mask = 0x3f;  /* UDMA Mode 5 */
	else
		hwif->ultra_mask = 0x1f;  /* UDMA Mode 4 */
	hwif->mwdma_mask = 0x7;
	hwif->drives[0].autotune = 1;
	hwif->drives[1].autotune = 1;

	hwif->ide_dma_check = &palm_bk3710_config_drive_xfer_rate;
	hwif->udma_four = 1;

	if (!noautodma)
		hwif->autodma = 1;
	hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;

	ide_setup_dma(hwif, base, 8);

	idx[0] = i;

	ide_device_add(idx);

	if (!hwif->present)
		goto out;

	return 0;
out:
	printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
	return -ENODEV;
}
Example #17
0
int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
			unsigned int cmd, unsigned long arg)
{
	unsigned long flags;
	ide_driver_t *drv;
	void __user *p = (void __user *)arg;
	int err = 0, (*setfunc)(ide_drive_t *, int);
	u8 *val;

	switch (cmd) {
	case HDIO_GET_32BIT:	    val = &drive->io_32bit;	 goto read_val;
	case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
	case HDIO_GET_UNMASKINTR:   val = &drive->unmask;	 goto read_val;
	case HDIO_GET_DMA:	    val = &drive->using_dma;	 goto read_val;
	case HDIO_SET_32BIT:	    setfunc = set_io_32bit;	 goto set_val;
	case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings;	 goto set_val;
	case HDIO_SET_PIO_MODE:	    setfunc = set_pio_mode;	 goto set_val;
	case HDIO_SET_UNMASKINTR:   setfunc = set_unmaskirq;	 goto set_val;
	case HDIO_SET_DMA:	    setfunc = set_using_dma;	 goto set_val;
	}

	switch (cmd) {
		case HDIO_OBSOLETE_IDENTITY:
		case HDIO_GET_IDENTITY:
			if (bdev != bdev->bd_contains)
				return -EINVAL;
			if (drive->id_read == 0)
				return -ENOMSG;
			if (copy_to_user(p, drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
				return -EFAULT;
			return 0;

		case HDIO_GET_NICE:
			return put_user(drive->dsc_overlap	<<	IDE_NICE_DSC_OVERLAP	|
					drive->atapi_overlap	<<	IDE_NICE_ATAPI_OVERLAP	|
					drive->nice0		<< 	IDE_NICE_0		|
					drive->nice1		<<	IDE_NICE_1		|
					drive->nice2		<<	IDE_NICE_2,
					(long __user *) arg);

#ifdef CONFIG_IDE_TASK_IOCTL
		case HDIO_DRIVE_TASKFILE:
		        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
				return -EACCES;
			switch(drive->media) {
				case ide_disk:
					return ide_taskfile_ioctl(drive, cmd, arg);
				default:
					return -ENOMSG;
			}
#endif /* CONFIG_IDE_TASK_IOCTL */

		case HDIO_DRIVE_CMD:
			if (!capable(CAP_SYS_RAWIO))
				return -EACCES;
			return ide_cmd_ioctl(drive, cmd, arg);

		case HDIO_DRIVE_TASK:
			if (!capable(CAP_SYS_RAWIO))
				return -EACCES;
			return ide_task_ioctl(drive, cmd, arg);

		case HDIO_SCAN_HWIF:
		{
			hw_regs_t hw;
			int args[3];
			if (!capable(CAP_SYS_RAWIO)) return -EACCES;
			if (copy_from_user(args, p, 3 * sizeof(int)))
				return -EFAULT;
			memset(&hw, 0, sizeof(hw));
			ide_init_hwif_ports(&hw, (unsigned long) args[0],
					    (unsigned long) args[1], NULL);
			hw.irq = args[2];
			if (ide_register_hw(&hw, 0, NULL) == -1)
				return -EIO;
			return 0;
		}
	        case HDIO_UNREGISTER_HWIF:
			if (!capable(CAP_SYS_RAWIO)) return -EACCES;
			/* (arg > MAX_HWIFS) checked in function */
			ide_unregister(arg);
			return 0;
		case HDIO_SET_NICE:
			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
			if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
				return -EPERM;
			drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
			drv = *(ide_driver_t **)bdev->bd_disk->private_data;
			if (drive->dsc_overlap && !drv->supports_dsc_overlap) {
				drive->dsc_overlap = 0;
				return -EPERM;
			}
			drive->nice1 = (arg >> IDE_NICE_1) & 1;
			return 0;
		case HDIO_DRIVE_RESET:
		{
			unsigned long flags;
			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
			
			/*
			 *	Abort the current command on the
			 *	group if there is one, taking
			 *	care not to allow anything else
			 *	to be queued and to die on the
			 *	spot if we miss one somehow
			 */

			spin_lock_irqsave(&ide_lock, flags);

			if (HWGROUP(drive)->resetting) {
				spin_unlock_irqrestore(&ide_lock, flags);
				return -EBUSY;
			}

			ide_abort(drive, "drive reset");

			BUG_ON(HWGROUP(drive)->handler);
				
			/* Ensure nothing gets queued after we
			   drop the lock. Reset will clear the busy */
		   
			HWGROUP(drive)->busy = 1;
			spin_unlock_irqrestore(&ide_lock, flags);
			(void) ide_do_reset(drive);

			return 0;
		}

		case CDROMEJECT:
		case CDROMCLOSETRAY:
			return scsi_cmd_ioctl(file, bdev->bd_disk, cmd, p);

		case HDIO_GET_BUSSTATE:
			if (!capable(CAP_SYS_ADMIN))
				return -EACCES;
			if (put_user(HWIF(drive)->bus_state, (long __user *)arg))
				return -EFAULT;
			return 0;

		case HDIO_SET_BUSSTATE:
			if (!capable(CAP_SYS_ADMIN))
				return -EACCES;
			if (HWIF(drive)->busproc)
				return HWIF(drive)->busproc(drive, (int)arg);
			return -EOPNOTSUPP;
		default:
			return -EINVAL;
	}

read_val:
	down(&ide_setting_sem);
	spin_lock_irqsave(&ide_lock, flags);
	err = *val;
	spin_unlock_irqrestore(&ide_lock, flags);
	up(&ide_setting_sem);
	return err >= 0 ? put_user(err, (long __user *)arg) : err;

set_val:
	if (bdev != bdev->bd_contains)
		err = -EINVAL;
	else {
		if (!capable(CAP_SYS_ADMIN))
			err = -EACCES;
		else {
			down(&ide_setting_sem);
			err = setfunc(drive, arg);
			up(&ide_setting_sem);
		}
	}
	return err;
}