⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * This function issues a special IDE device request * onto the request queue. * * If action is ide_wait, then the rq is queued at the end of the * request queue, and the function sleeps until it has been processed. * This is for use when invoked from an ioctl handler. * * If action is ide_preempt, then the rq is queued at the head of * the request queue, displacing the currently-being-processed * request and this function returns immediately without waiting * for the new rq to be completed.  This is VERY DANGEROUS, and is * intended for careful use by the ATAPI tape/cdrom driver code. * * If action is ide_next, then the rq is queued immediately after * the currently-being-processed-request (if any), and the function * returns without waiting for the new rq to be completed.  As above, * This is VERY DANGEROUS, and is intended for careful use by the * ATAPI tape/cdrom driver code. * * If action is ide_end, then the rq is queued at the end of the * request queue, and the function returns immediately without waiting * for the new rq to be completed. This is again intended for careful * use by the ATAPI tape/cdrom driver code. */int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action){	unsigned long flags;	ide_hwgroup_t *hwgroup = HWGROUP(drive);	unsigned int major = HWIF(drive)->major;	struct list_head * queue_head;	DECLARE_MUTEX_LOCKED(sem);#ifdef CONFIG_BLK_DEV_PDC4030	if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)		return -ENOSYS;  /* special drive cmds not supported */#endif	rq->errors = 0;	rq->rq_status = RQ_ACTIVE;	rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);	if (action == ide_wait)		rq->sem = &sem;	spin_lock_irqsave(&io_request_lock, flags);	queue_head = &drive->queue.queue_head;	if (list_empty(queue_head) || action == ide_preempt) {		if (action == ide_preempt)			hwgroup->rq = NULL;	} else {		if (action == ide_wait || action == ide_end) {			queue_head = queue_head->prev;		} else			queue_head = queue_head->next;	}	list_add(&rq->queue, queue_head);	ide_do_request(hwgroup, 0);	spin_unlock_irqrestore(&io_request_lock, flags);	if (action == ide_wait) {		down(&sem);			/* wait for it to be serviced */		return rq->errors ? -EIO : 0;	/* return -EIO if errors */	}	return 0;}/* * This routine is called to flush all partitions and partition tables * for a changed disk, and then re-read the new partition table. * If we are revalidating a disk because of a media change, then we * enter with usage == 0.  If we are using an ioctl, we automatically have * usage == 1 (we need an open channel to use an ioctl :-), so this * is our limit. */int ide_revalidate_disk (kdev_t i_rdev){	ide_drive_t *drive;	ide_hwgroup_t *hwgroup;	unsigned int p, major, minor;	long flags;	if ((drive = get_info_ptr(i_rdev)) == NULL)		return -ENODEV;	major = MAJOR(i_rdev);	minor = drive->select.b.unit << PARTN_BITS;	hwgroup = HWGROUP(drive);	spin_lock_irqsave(&io_request_lock, flags);	if (drive->busy || (drive->usage > 1)) {		spin_unlock_irqrestore(&io_request_lock, flags);		return -EBUSY;	};	drive->busy = 1;	MOD_INC_USE_COUNT;	spin_unlock_irqrestore(&io_request_lock, flags);	for (p = 0; p < (1<<PARTN_BITS); ++p) {		if (drive->part[p].nr_sects > 0) {			kdev_t devp = MKDEV(major, minor+p);			struct super_block * sb = get_super(devp);			fsync_dev          (devp);			if (sb)				invalidate_inodes(sb);			invalidate_buffers (devp);			set_blocksize(devp, 1024);		}		drive->part[p].start_sect = 0;		drive->part[p].nr_sects   = 0;	};	if (DRIVER(drive)->revalidate)		DRIVER(drive)->revalidate(drive);	drive->busy = 0;	wake_up(&drive->wqueue);	MOD_DEC_USE_COUNT;	return 0;}static void revalidate_drives (void){	ide_hwif_t *hwif;	ide_drive_t *drive;	int index, unit;	for (index = 0; index < MAX_HWIFS; ++index) {		hwif = &ide_hwifs[index];		for (unit = 0; unit < MAX_DRIVES; ++unit) {			drive = &ide_hwifs[index].drives[unit];			if (drive->revalidate) {				drive->revalidate = 0;				if (!initializing)					(void) ide_revalidate_disk(MKDEV(hwif->major, unit<<PARTN_BITS));			}		}	}}static void ide_probe_module (void){	if (!ide_probe) {#if defined(CONFIG_KMOD) && defined(CONFIG_BLK_DEV_IDE_MODULE)		(void) request_module("ide-probe-mod");#endif /* (CONFIG_KMOD) && (CONFIG_BLK_DEV_IDE_MODULE) */	} else {		(void) ide_probe->init();	}	revalidate_drives();}static void ide_driver_module (void){	int index;	ide_module_t *module = ide_modules;	for (index = 0; index < MAX_HWIFS; ++index)		if (ide_hwifs[index].present)			goto search;	ide_probe_module();search:	while (module) {		(void) module->init();		module = module->next;	}	revalidate_drives();}static int ide_open (struct inode * inode, struct file * filp){	ide_drive_t *drive;	int rc;	if ((drive = get_info_ptr(inode->i_rdev)) == NULL)		return -ENXIO;	MOD_INC_USE_COUNT;	if (drive->driver == NULL)		ide_driver_module();#ifdef CONFIG_KMOD	if (drive->driver == NULL) {		if (drive->media == ide_disk)			(void) request_module("ide-disk");		if (drive->media == ide_cdrom)			(void) request_module("ide-cd");		if (drive->media == ide_tape)			(void) request_module("ide-tape");		if (drive->media == ide_floppy)			(void) request_module("ide-floppy");	}#endif /* CONFIG_KMOD */	while (drive->busy)		sleep_on(&drive->wqueue);	drive->usage++;	if (drive->driver != NULL) {		if ((rc = DRIVER(drive)->open(inode, filp, drive)))			MOD_DEC_USE_COUNT;		return rc;	}	printk ("%s: driver not present\n", drive->name);	drive->usage--;	MOD_DEC_USE_COUNT;	return -ENXIO;}/* * Releasing a block device means we sync() it, so that it can safely * be forgotten about... */static int ide_release (struct inode * inode, struct file * file){	ide_drive_t *drive;	if ((drive = get_info_ptr(inode->i_rdev)) != NULL) {		drive->usage--;		if (drive->driver != NULL)			DRIVER(drive)->release(inode, file, drive);		MOD_DEC_USE_COUNT;	}	return 0;}int ide_replace_subdriver (ide_drive_t *drive, const char *driver){	if (!drive->present || drive->busy || drive->usage)		goto abort;	if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))		goto abort;	strncpy(drive->driver_req, driver, 9);	ide_driver_module();	drive->driver_req[0] = 0;	ide_driver_module();	if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver))		return 0;abort:	return 1;}#ifdef CONFIG_PROC_FSide_proc_entry_t generic_subdriver_entries[] = {	{ "capacity",	S_IFREG|S_IRUGO,	proc_ide_read_capacity,	NULL },	{ NULL, 0, NULL, NULL }};#endif/* * Note that we only release the standard ports, * and do not even try to handle any extra ports * allocated for weird IDE interface chipsets. */void hwif_unregister (ide_hwif_t *hwif){	if (hwif->straight8) {		ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);		goto jump_eight;	}	if (hwif->io_ports[IDE_DATA_OFFSET])		ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1);	if (hwif->io_ports[IDE_ERROR_OFFSET])		ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);	if (hwif->io_ports[IDE_NSECTOR_OFFSET])		ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);	if (hwif->io_ports[IDE_SECTOR_OFFSET])		ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1);	if (hwif->io_ports[IDE_LCYL_OFFSET])		ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1);	if (hwif->io_ports[IDE_HCYL_OFFSET])		ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);	if (hwif->io_ports[IDE_SELECT_OFFSET])		ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);	if (hwif->io_ports[IDE_STATUS_OFFSET])		ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);jump_eight:	if (hwif->io_ports[IDE_CONTROL_OFFSET])		ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)	if (hwif->io_ports[IDE_IRQ_OFFSET])		ide_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */}void ide_unregister (unsigned int index){	struct gendisk *gd, **gdp;	ide_drive_t *drive, *d;	ide_hwif_t *hwif, *g;	ide_hwgroup_t *hwgroup;	int irq_count = 0, unit, i;	unsigned long flags;	unsigned int p, minor;	ide_hwif_t old_hwif;	if (index >= MAX_HWIFS)		return;	save_flags(flags);	/* all CPUs */	cli();			/* all CPUs */	hwif = &ide_hwifs[index];	if (!hwif->present)		goto abort;	for (unit = 0; unit < MAX_DRIVES; ++unit) {		drive = &hwif->drives[unit];		if (!drive->present)			continue;		if (drive->busy || drive->usage)			goto abort;		if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))			goto abort;	}	hwif->present = 0;		/*	 * All clear?  Then blow away the buffer cache	 */	sti();	for (unit = 0; unit < MAX_DRIVES; ++unit) {		drive = &hwif->drives[unit];		if (!drive->present)			continue;		minor = drive->select.b.unit << PARTN_BITS;		for (p = 0; p < (1<<PARTN_BITS); ++p) {			if (drive->part[p].nr_sects > 0) {				kdev_t devp = MKDEV(hwif->major, minor+p);				struct super_block * sb = get_super(devp);				if (sb) invalidate_inodes(sb);				invalidate_buffers (devp);			}		}#ifdef CONFIG_PROC_FS		destroy_proc_ide_drives(hwif);#endif	}	cli();	hwgroup = hwif->hwgroup;	/*	 * free the irq if we were the only hwif using it	 */	g = hwgroup->hwif;	do {		if (g->irq == hwif->irq)			++irq_count;		g = g->next;	} while (g != hwgroup->hwif);	if (irq_count == 1)		free_irq(hwif->irq, hwgroup);	/*	 * Note that we only release the standard ports,	 * and do not even try to handle any extra ports	 * allocated for weird IDE interface chipsets.	 */	hwif_unregister(hwif);	/*	 * Remove us from the hwgroup, and free	 * the hwgroup if we were the only member	 */	d = hwgroup->drive;	for (i = 0; i < MAX_DRIVES; ++i) {		drive = &hwif->drives[i];		if (drive->de) {			devfs_unregister (drive->de);			drive->de = NULL;		}		if (!drive->present)			continue;		while (hwgroup->drive->next != drive)			hwgroup->drive = hwgroup->drive->next;		hwgroup->drive->next = drive->next;		if (hwgroup->drive == drive)			hwgroup->drive = NULL;		if (drive->id != NULL) {			kfree(drive->id);			drive->id = NULL;		}		drive->present = 0;		blk_cleanup_queue(&drive->queue);	}	if (d->present)		hwgroup->drive = d;	while (hwgroup->hwif->next != hwif)		hwgroup->hwif = hwgroup->hwif->next;	hwgroup->hwif->next = hwif->next;	if (hwgroup->hwif == hwif)		kfree(hwgroup);	else		hwgroup->hwif = HWIF(hwgroup->drive);#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)	if (hwif->dma_base) {		(void) ide_release_dma(hwif);		hwif->dma_base = 0;	}#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */	/*	 * Remove us from the kernel's knowledge	 */	unregister_blkdev(hwif->major, hwif->name);	kfree(blksize_size[hwif->major]);	kfree(max_sectors[hwif->major]);	kfree(max_readahead[hwif->major]);	blk_dev[hwif->major].data = NULL;	blk_dev[hwif->major].queue = NULL;	blksize_size[hwif->major] = NULL;	for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))		if (*gdp == hwif->gd)			break;	if (*gdp == NULL)		printk("gd not in disk chain!\n");	else {		gd = *gdp; *gdp = gd->next;		kfree(gd->sizes);		kfree(gd->part);		if (gd->de_arr)			kfree (gd->de_arr);		if (gd->flags)			kfree (gd->flags);		kfree(gd);	}	old_hwif		= *hwif;	init_hwif_data (index);	/* r

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -