ide-floppy.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,099 行 · 第 1/5 页

C
2,099
字号
	printk(KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No");		switch (gcw.drq_type) {		case 0: sprintf(buffer, "Microprocessor DRQ");break;		case 1: sprintf(buffer, "Interrupt DRQ");break;		case 2: sprintf(buffer, "Accelerated DRQ");break;		case 3: sprintf(buffer, "Reserved");break;	}	printk(KERN_INFO "Command Packet DRQ Type: %s\n", buffer);	switch (gcw.packet_size) {		case 0: sprintf(buffer, "12 bytes");break;		case 1: sprintf(buffer, "16 bytes");break;		default: sprintf(buffer, "Reserved");break;	}	printk(KERN_INFO "Command Packet Size: %s\n", buffer);	printk(KERN_INFO "Model: %.40s\n",id->model);	printk(KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev);	printk(KERN_INFO "Serial Number: %.20s\n",id->serial_no);	printk(KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512);	printk(KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");	printk(KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");	printk(KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");	printk(KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");	printk(KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");	printk(KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO);	printk(KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA);	printk(KERN_INFO "Single Word DMA supported modes:\n");	for (i=0,mask=1;i<8;i++,mask=mask << 1) {		if (id->dma_1word & mask)			printk(KERN_INFO "   Mode %d%s\n", i,			(id->dma_1word & (mask << 8)) ? " (active)" : "");	}	printk(KERN_INFO "Multi Word DMA supported modes:\n");	for (i=0,mask=1;i<8;i++,mask=mask << 1) {		if (id->dma_mword & mask)			printk(KERN_INFO "   Mode %d%s\n", i,			(id->dma_mword & (mask << 8)) ? " (active)" : "");	}	if (id->field_valid & 0x0002) {		printk(KERN_INFO "Enhanced PIO Modes: %s\n",			id->eide_pio_modes & 1 ? "Mode 3":"None");		if (id->eide_dma_min == 0)			sprintf(buffer, "Not supported");		else			sprintf(buffer, "%d ns",id->eide_dma_min);		printk(KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer);		if (id->eide_dma_time == 0)			sprintf(buffer, "Not supported");		else			sprintf(buffer, "%d ns",id->eide_dma_time);		printk(KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer);		if (id->eide_pio == 0)			sprintf(buffer, "Not supported");		else			sprintf(buffer, "%d ns",id->eide_pio);		printk(KERN_INFO "Minimum PIO cycle without IORDY: %s\n",			buffer);		if (id->eide_pio_iordy == 0)			sprintf(buffer, "Not supported");		else			sprintf(buffer, "%d ns",id->eide_pio_iordy);		printk(KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer);	} else		printk(KERN_INFO "According to the device, fields 64-70 are not valid.\n");#endif /* IDEFLOPPY_DEBUG_INFO */	if (gcw.protocol != 2)		printk(KERN_ERR "ide-floppy: Protocol is not ATAPI\n");	else if (gcw.device_type != 0)		printk(KERN_ERR "ide-floppy: Device type is not set to floppy\n");	else if (!gcw.removable)		printk(KERN_ERR "ide-floppy: The removable flag is not set\n");	else if (gcw.drq_type == 3) {		printk(KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type);	} else if (gcw.packet_size != 0) {		printk(KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n");	} else		return 1;	return 0;}static void idefloppy_add_settings(ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;/* *			drive	setting name	read/write	ioctl	ioctl		data type	min	max	mul_factor	div_factor	data pointer		set function */	ide_add_setting(drive,	"bios_cyl",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	1023,				1,	1,	&drive->bios_cyl,		NULL);	ide_add_setting(drive,	"bios_head",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	255,				1,	1,	&drive->bios_head,		NULL);	ide_add_setting(drive,	"bios_sect",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	63,				1,	1,	&drive->bios_sect,		NULL);	ide_add_setting(drive,	"ticks",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	255,				1,	1,	&floppy->ticks,		NULL);}/* *	Driver initialization. */static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy){	struct idefloppy_id_gcw gcw;	*((u16 *) &gcw) = drive->id->config;	drive->driver_data = floppy;	drive->ready_stat = 0;	memset(floppy, 0, sizeof(idefloppy_floppy_t));	floppy->drive = drive;	floppy->pc = floppy->pc_stack;	if (gcw.drq_type == 1)		set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags);	/*	 *	We used to check revisions here. At this point however	 *	I'm giving up. Just assume they are all broken, its easier.	 *	 *	The actual reason for the workarounds was likely	 *	a driver bug after all rather than a firmware bug,	 *	and the workaround below used to hide it. It should	 *	be fixed as of version 1.9, but to be on the safe side	 *	we'll leave the limitation below for the 2.2.x tree.	 */	if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) {		set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags);		/* This value will be visible in the /proc/ide/hdx/settings */		floppy->ticks = IDEFLOPPY_TICKS_DELAY;		blk_queue_max_sectors(drive->queue, 64);	}	/*	*      Guess what?  The IOMEGA Clik! drive also needs the	*      above fix.  It makes nasty clicking noises without	*      it, so please don't remove this.	*/	if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {		blk_queue_max_sectors(drive->queue, 64);		set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);	}	(void) idefloppy_get_capacity(drive);	idefloppy_add_settings(drive);}static int idefloppy_cleanup (ide_drive_t *drive){	idefloppy_floppy_t *floppy = drive->driver_data;	struct gendisk *g = drive->disk;	if (ide_unregister_subdriver(drive))		return 1;	drive->driver_data = NULL;	kfree(floppy);	del_gendisk(g);	g->fops = ide_fops;	return 0;}#ifdef CONFIG_PROC_FSstatic ide_proc_entry_t idefloppy_proc[] = {	{ "geometry",	S_IFREG|S_IRUGO,	proc_ide_read_geometry,	NULL },	{ NULL, 0, NULL, NULL }};#else#define	idefloppy_proc	NULL#endif	/* CONFIG_PROC_FS */static int idefloppy_attach(ide_drive_t *drive);/* *	IDE subdriver functions, registered with ide.c */static ide_driver_t idefloppy_driver = {	.owner			= THIS_MODULE,	.name			= "ide-floppy",	.version		= IDEFLOPPY_VERSION,	.media			= ide_floppy,	.busy			= 0,	.supports_dsc_overlap	= 0,	.cleanup		= idefloppy_cleanup,	.do_request		= idefloppy_do_request,	.end_request		= idefloppy_do_end_request,	.capacity		= idefloppy_capacity,	.proc			= idefloppy_proc,	.attach			= idefloppy_attach,	.drives			= LIST_HEAD_INIT(idefloppy_driver.drives),};static int idefloppy_open(struct inode *inode, struct file *filp){	ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;	idefloppy_floppy_t *floppy = drive->driver_data;	idefloppy_pc_t pc;	drive->usage++;		debug_log(KERN_INFO "Reached idefloppy_open\n");	if (drive->usage == 1) {		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);		/* Just in case */		idefloppy_create_test_unit_ready_cmd(&pc);		if (idefloppy_queue_pc_tail(drive, &pc)) {			idefloppy_create_start_stop_cmd(&pc, 1);			(void) idefloppy_queue_pc_tail(drive, &pc);		}		if (idefloppy_get_capacity (drive)		   && (filp->f_flags & O_NDELAY) == 0		    /*		    ** Allow O_NDELAY to open a drive without a disk, or with		    ** an unreadable disk, so that we can get the format		    ** capacity of the drive or begin the format - Sam		    */		    ) {			drive->usage--;			return -EIO;		}		if (floppy->wp && (filp->f_mode & 2)) {			drive->usage--;			return -EROFS;		}				set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);		/* IOMEGA Clik! drives do not support lock/unlock commands */                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {			idefloppy_create_prevent_cmd(&pc, 1);			(void) idefloppy_queue_pc_tail(drive, &pc);		}		check_disk_change(inode->i_bdev);	} else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {		drive->usage--;		return -EBUSY;	}	return 0;}static int idefloppy_release(struct inode *inode, struct file *filp){	ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;	idefloppy_pc_t pc;		debug_log(KERN_INFO "Reached idefloppy_release\n");	if (drive->usage == 1) {		idefloppy_floppy_t *floppy = drive->driver_data;		/* IOMEGA Clik! drives do not support lock/unlock commands */                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {			idefloppy_create_prevent_cmd(&pc, 0);			(void) idefloppy_queue_pc_tail(drive, &pc);		}		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);	}	drive->usage--;	return 0;}static int idefloppy_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	struct block_device *bdev = inode->i_bdev;	ide_drive_t *drive = bdev->bd_disk->private_data;	idefloppy_floppy_t *floppy = drive->driver_data;	void __user *argp = (void __user *)arg;	int err = generic_ide_ioctl(file, bdev, cmd, arg);	int prevent = (arg) ? 1 : 0;	idefloppy_pc_t pc;	if (err != -EINVAL)		return err;	switch (cmd) {	case CDROMEJECT:		prevent = 0;		/* fall through */	case CDROM_LOCKDOOR:		if (drive->usage > 1)			return -EBUSY;		/* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {			idefloppy_create_prevent_cmd(&pc, prevent);			(void) idefloppy_queue_pc_tail(drive, &pc);		}		if (cmd == CDROMEJECT) {			idefloppy_create_start_stop_cmd(&pc, 2);			(void) idefloppy_queue_pc_tail(drive, &pc);		}		return 0;	case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:		return 0;	case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:		return idefloppy_get_format_capacities(drive, argp);	case IDEFLOPPY_IOCTL_FORMAT_START:		if (!(file->f_mode & 2))			return -EPERM;		if (drive->usage > 1) {			/* Don't format if someone is using the disk */			clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,				  &floppy->flags);			return -EBUSY;		}		set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);		err = idefloppy_begin_format(drive, argp);		if (err)			clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);		return err;		/*		** Note, the bit will be cleared when the device is		** closed.  This is the cleanest way to handle the		** situation where the drive does not support		** format progress reporting.		*/	case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:		return idefloppy_get_format_progress(drive, argp);	} 	return -EINVAL;}static int idefloppy_media_changed(struct gendisk *disk){	ide_drive_t *drive = disk->private_data;	idefloppy_floppy_t *floppy = drive->driver_data;	/* do not scan partitions twice if this is a removable device */	if (drive->attach) {		drive->attach = 0;		return 0;	}	return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);}static int idefloppy_revalidate_disk(struct gendisk *disk){	ide_drive_t *drive = disk->private_data;	set_capacity(disk, current_capacity(drive));	return 0;}static struct block_device_operations idefloppy_ops = {	.owner		= THIS_MODULE,	.open		= idefloppy_open,	.release	= idefloppy_release,	.ioctl		= idefloppy_ioctl,	.media_changed	= idefloppy_media_changed,	.revalidate_disk= idefloppy_revalidate_disk};static int idefloppy_attach (ide_drive_t *drive){	idefloppy_floppy_t *floppy;	struct gendisk *g = drive->disk;	if (!strstr("ide-floppy", drive->driver_req))		goto failed;	if (!drive->present)		goto failed;	if (drive->media != ide_floppy)		goto failed;	if (!idefloppy_identify_device (drive, drive->id)) {		printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name);		goto failed;	}	if (drive->scsi) {		printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);		goto failed;	}	if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {		printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);		goto failed;	}	if (ide_register_subdriver(drive, &idefloppy_driver)) {		printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);		kfree (floppy);		goto failed;	}	DRIVER(drive)->busy++;	idefloppy_setup (drive, floppy);	DRIVER(drive)->busy--;	g->minors = 1 << PARTN_BITS;	g->driverfs_dev = &drive->gendev;	strcpy(g->devfs_name, drive->devfs_name);	g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;	g->fops = &idefloppy_ops;	drive->attach = 1;	add_disk(g);	return 0;failed:	return 1;}MODULE_DESCRIPTION("ATAPI FLOPPY Driver");static void __exit idefloppy_exit (void){	ide_unregister_driver(&idefloppy_driver);}/* *	idefloppy_init will register the driver for each floppy. */static int idefloppy_init (void){	printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");	ide_register_driver(&idefloppy_driver);	return 0;}module_init(idefloppy_init);module_exit(idefloppy_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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