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

📄 ide.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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);			}		}	}	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.	 */	ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);	ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);	/*	 * 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->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;	}	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);#ifdef CONFIG_BLK_DEV_IDEDMA	if (hwif->dma_base)		(void) ide_release_dma(hwif);#endif /* CONFIG_BLK_DEV_IDEDMA */	/*	 * 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].request_fn = NULL;	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);		kfree(gd);	}	init_hwif_data (index);	/* restore hwif data to pristine status */abort:	restore_flags(flags);	/* all CPUs */#endif}int ide_register (int arg1, int arg2, int irq){	int index, retry = 1;	ide_hwif_t *hwif;	ide_ioreg_t data_port = (ide_ioreg_t) arg1, ctl_port = (ide_ioreg_t) arg2;	do {		for (index = 0; index < MAX_HWIFS; ++index) {			hwif = &ide_hwifs[index];			if (hwif->io_ports[IDE_DATA_OFFSET] == data_port)				goto found;		}		for (index = 0; index < MAX_HWIFS; ++index) {			hwif = &ide_hwifs[index];			if (!hwif->present)				goto found;		}		for (index = 0; index < MAX_HWIFS; index++)			ide_unregister(index);	} while (retry--);	return -1;found:	if (hwif->present)		ide_unregister(index);	if (hwif->present)		return -1;	ide_init_hwif_ports(hwif->io_ports, data_port, &hwif->irq);	if (ctl_port)		hwif->io_ports[IDE_CONTROL_OFFSET] = ctl_port;	hwif->irq = irq;	hwif->noprobe = 0;	ide_init_module(IDE_PROBE_MODULE);	ide_init_module(IDE_DRIVER_MODULE);	return hwif->present ? index : -1;}void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set){	ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;	while ((*p) && strcmp((*p)->name, name) < 0)		p = &((*p)->next);	if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL)		goto abort;	memset(setting, 0, sizeof(*setting));	if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)		goto abort;	strcpy(setting->name, name);		setting->rw = rw;	setting->read_ioctl = read_ioctl;	setting->write_ioctl = write_ioctl;	setting->data_type = data_type;		setting->min = min;	setting->max = max;			setting->mul_factor = mul_factor;	setting->div_factor = div_factor;	setting->data = data;	setting->set = set;			setting->next = *p;	if (drive->driver)		setting->auto_remove = 1;	*p = setting;	return;abort:	if (setting)		kfree(setting);}void ide_remove_setting(ide_drive_t *drive, char *name){	ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting;	while ((*p) && strcmp((*p)->name, name))		p = &((*p)->next);	if ((setting = (*p)) == NULL)		return;	(*p) = setting->next;	kfree(setting->name);	kfree(setting);}static ide_settings_t *ide_find_setting_by_ioctl(ide_drive_t *drive, int cmd){	ide_settings_t *setting = drive->settings;	while (setting) {		if (setting->read_ioctl == cmd || setting->write_ioctl == cmd)			break;		setting = setting->next;	}	return setting;}ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name){	ide_settings_t *setting = drive->settings;	while (setting) {		if (strcmp(setting->name, name) == 0)			break;		setting = setting->next;	}	return setting;}static void auto_remove_settings(ide_drive_t *drive){	ide_settings_t *setting;repeat:	setting = drive->settings;	while (setting) {		if (setting->auto_remove) {			ide_remove_setting(drive, setting->name);			goto repeat;		}		setting = setting->next;	}}int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting){	int		val = -EINVAL;	unsigned long	flags;	if ((setting->rw & SETTING_READ)) {		spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);		switch(setting->data_type) {			case TYPE_BYTE:				val = *((u8 *) setting->data);				break;			case TYPE_SHORT:				val = *((u16 *) setting->data);				break;			case TYPE_INT:			case TYPE_INTA:				val = *((u32 *) setting->data);				break;		}		spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);	}	return val;}int ide_spin_wait_hwgroup (ide_drive_t *drive, unsigned long *flags){	ide_hwgroup_t *hwgroup = HWGROUP(drive);	unsigned long timeout = jiffies + (3 * HZ);	spin_lock_irqsave(&hwgroup->spinlock, *flags);	while (hwgroup->busy) {		spin_unlock_irqrestore(&hwgroup->spinlock, *flags);		__sti();	/* local CPU only; needed for jiffies */		if (0 < (signed long)(jiffies - timeout)) {			printk("%s: channel busy\n", drive->name);			return -EBUSY;		}		spin_lock_irqsave(&hwgroup->spinlock, *flags);	}	return 0;}int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val){	unsigned long flags;	int i;	u32 *p;	if (!capable(CAP_SYS_ADMIN))		return -EACCES;	if (!(setting->rw & SETTING_WRITE))		return -EPERM;	if (val < setting->min || val > setting->max)		return -EINVAL;	if (setting->set)		return setting->set(drive, val);	if (ide_spin_wait_hwgroup(drive, &flags))		return -EBUSY;	switch (setting->data_type) {		case TYPE_BYTE:			*((u8 *) setting->data) = val;			break;		case TYPE_SHORT:			*((u16 *) setting->data) = val;			break;		case TYPE_INT:			*((u32 *) setting->data) = val;			break;		case TYPE_INTA:			p = (u32 *) setting->data;			for (i = 0; i < 1 << PARTN_BITS; i++, p++)				*p = val;			break;	}	spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);	return 0;}static int set_io_32bit(ide_drive_t *drive, int arg){	drive->io_32bit = arg;#ifdef CONFIG_BLK_DEV_DTC2278	if (HWIF(drive)->chipset == ide_dtc2278)		HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;#endif /* CONFIG_BLK_DEV_DTC2278 */	return 0;}static int set_using_dma(ide_drive_t *drive, int arg){	if (!drive->driver || !DRIVER(drive)->supports_dma)		return -EPERM;	if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)		return -EPERM;	if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive))		return -EIO;	return 0;}static int set_pio_mode(ide_drive_t *drive, int arg){	struct request rq;	if (!HWIF(drive)->tuneproc)		return -ENOSYS;	if (drive->special.b.set_tune)		return -EBUSY;	ide_init_drive_cmd(&rq);	drive->tune_req = (byte) arg;	drive->special.b.set_tune = 1;	(void) ide_do_drive_cmd (drive, &rq, ide_wait);	return 0;}void ide_add_generic_settings(ide_drive_t *drive){/* *			drive	setting name		read/write access				read ioctl		write ioctl		data type	min	max				mul_factor	div_factor	data pointer			set function */	ide_add_setting(drive,	"io_32bit",		drive->no_io_32bit ? SETTING_READ : SETTING_RW,	HDIO_GET_32BIT,		HDIO_SET_32BIT,		TYPE_BYTE,	0,	1 + (SUPPORT_VLB_SYNC << 1),	1,		1,		&drive->io_32bit,		set_io_32bit);	ide_add_setting(drive,	"keepsettings",		SETTING_RW,					HDIO_GET_KEEPSETTINGS,	HDIO_SET_KEEPSETTINGS,	TYPE_BYTE,	0,	1,				1,		1,		&drive->keep_settings,		NULL);	ide_add_setting(drive,	"nice1",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->nice1,			NULL);	ide_add_setting(drive,	"pio_mode",		SETTING_WRITE,					-1,			HDIO_SET_PIO_MODE,	TYPE_BYTE,	0,	255,				1,		1,		NULL,				set_pio_mode);	ide_add_setting(drive,	"slow",			SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->slow,			NULL);	ide_add_setting(drive,	"unmaskirq",		drive->no_unmask ? SETTING_READ : SETTING_RW,	HDIO_GET_UNMASKINTR,	HDIO_SET_UNMASKINTR,	TYPE_BYTE,	0,	1,				1,		1,		&drive->unmask,			NULL);	ide_add_setting(drive,	"using_dma",		SETTING_RW,					HDIO_GET_DMA,		HDIO_SET_DMA,		TYPE_BYTE,	0,	1,				1,		1,		&drive->using_dma,		set_using_dma);}int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf){	struct request rq;	byte buffer[4];	if (!buf)		buf = buffer;	memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);	ide_init_drive_cmd(&rq);	rq.buffer = buf;	*buf++ = cmd;	*buf++ = nsect;	*buf++ = feature;	*buf++ = sectors;	return ide_do_drive_cmd(drive, &rq, ide_wait);}static int ide_ioctl (struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	int err, major, minor;	ide_drive_t *drive;	struct request rq;	kdev_t dev;	ide_settings_t *setting;	if (!inode || !(dev = inode->i_rdev))		return -EINVAL;	major = MAJOR(dev); minor = MINOR(dev);	if ((drive = get_info_ptr(inode->i_rdev)) == NULL)		return -ENODEV;	if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {		if (cmd == setting->read_ioctl) {			err = ide_read_setting(drive, setting);			return err >= 0 ? put_user(err, (long *) arg) : err;		} else {			if ((MINOR(inode->i_rdev) & PARTN_MASK))				return -EINVAL;			return ide_write_setting(drive, setting, arg);		}	}	ide_init_drive_cmd (&rq);	switch (cmd) {		case HDIO_GETGEO:		{			struct hd_geometry *loc = (struct hd_geometry *) arg;			if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;			if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT;			if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT;			if (put_user(drive->bios_cyl, (unsigned short *) &loc->cylinders)) return -EFAULT;			if (put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect,				(unsigned long *) &loc->start)) return -EFAULT;			return 0;		}		case BLKSSZGET:			/* Block size of media */			return put_user(blksize_size[HWIF(drive)->major]						    [minor&PARTN_MASK],						    (int *)arg);				case BLKFLSBUF:			if (!capable(CAP_SYS_ADMIN)) return -EACCES;			fsync_dev(inode->i_rdev);			invalidate_buffers(inode->i_rdev);			return 0;	 	case BLKGETSIZE:   /* Return device size */			return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (long *) arg);		case BLKRRPART: /* Re-read partition tables */			if (!capable(CAP_SYS_A

⌨️ 快捷键说明

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