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

📄 ide-scsi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return 0;}static int idescsi_ide_release(struct inode *inode, struct file *filp){	struct gendisk *disk = inode->i_bdev->bd_disk;	struct ide_scsi_obj *scsi = ide_scsi_g(disk);	ide_scsi_put(scsi);	return 0;}static int idescsi_ide_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	struct block_device *bdev = inode->i_bdev;	struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk);	return generic_ide_ioctl(scsi->drive, file, bdev, cmd, arg);}static struct block_device_operations idescsi_ops = {	.owner		= THIS_MODULE,	.open		= idescsi_ide_open,	.release	= idescsi_ide_release,	.ioctl		= idescsi_ide_ioctl,};static int idescsi_slave_configure(struct scsi_device * sdp){	/* Configure detected device */	sdp->use_10_for_rw = 1;	sdp->use_10_for_ms = 1;	scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun);	return 0;}static const char *idescsi_info (struct Scsi_Host *host){	return "SCSI host adapter emulation for IDE ATAPI devices";}static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg){	idescsi_scsi_t *scsi = scsihost_to_idescsi(dev->host);	if (cmd == SG_SET_TRANSFORM) {		if (arg)			set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);		else			clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);		return 0;	} else if (cmd == SG_GET_TRANSFORM)		return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int __user *) arg);	return -EINVAL;}static int idescsi_queue (struct scsi_cmnd *cmd,		void (*done)(struct scsi_cmnd *)){	struct Scsi_Host *host = cmd->device->host;	idescsi_scsi_t *scsi = scsihost_to_idescsi(host);	ide_drive_t *drive = scsi->drive;	struct request *rq = NULL;	idescsi_pc_t *pc = NULL;	if (!drive) {		scmd_printk (KERN_ERR, cmd, "drive not present\n");		goto abort;	}	scsi = drive_to_idescsi(drive);	pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC);	rq = kmalloc (sizeof (struct request), GFP_ATOMIC);	if (rq == NULL || pc == NULL) {		printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);		goto abort;	}	memset (pc->c, 0, 12);	pc->flags = 0;	pc->rq = rq;	memcpy (pc->c, cmd->cmnd, cmd->cmd_len);	pc->buffer = NULL;	pc->sg = scsi_sglist(cmd);	pc->sg_cnt = scsi_sg_count(cmd);	pc->b_count = 0;	pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd);	pc->scsi_cmd = cmd;	pc->done = done;	pc->timeout = jiffies + cmd->timeout_per_command;	if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {		printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);		ide_scsi_hex_dump(cmd->cmnd, cmd->cmd_len);		if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {			printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);			ide_scsi_hex_dump(pc->c, 12);		}	}	ide_init_drive_cmd (rq);	rq->special = (char *) pc;	rq->cmd_type = REQ_TYPE_SPECIAL;	spin_unlock_irq(host->host_lock);	rq->rq_disk = scsi->disk;	(void) ide_do_drive_cmd (drive, rq, ide_end);	spin_lock_irq(host->host_lock);	return 0;abort:	kfree (pc);	kfree (rq);	cmd->result = DID_ERROR << 16;	done(cmd);	return 0;}static int idescsi_eh_abort (struct scsi_cmnd *cmd){	idescsi_scsi_t *scsi  = scsihost_to_idescsi(cmd->device->host);	ide_drive_t    *drive = scsi->drive;	int		busy;	int             ret   = FAILED;	/* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))		printk (KERN_WARNING "ide-scsi: abort called for %lu\n", cmd->serial_number);	if (!drive) {		printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_abort\n");		WARN_ON(1);		goto no_drive;	}	/* First give it some more time, how much is "right" is hard to say :-( */	busy = ide_wait_not_busy(HWIF(drive), 100);	/* FIXME - uses mdelay which causes latency? */	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))		printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");	spin_lock_irq(&ide_lock);	/* If there is no pc running we're done (our interrupt took care of it) */	if (!scsi->pc) {		ret = SUCCESS;		goto ide_unlock;	}	/* It's somewhere in flight. Does ide subsystem agree? */	if (scsi->pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&	    elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != scsi->pc->rq) {		/*		 * FIXME - not sure this condition can ever occur		 */		printk (KERN_ERR "ide-scsi: cmd aborted!\n");		if (blk_sense_request(scsi->pc->rq))			kfree(scsi->pc->buffer);		kfree(scsi->pc->rq);		kfree(scsi->pc);		scsi->pc = NULL;		ret = SUCCESS;	}ide_unlock:	spin_unlock_irq(&ide_lock);no_drive:	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))		printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");	return ret;}static int idescsi_eh_reset (struct scsi_cmnd *cmd){	struct request *req;	idescsi_scsi_t *scsi  = scsihost_to_idescsi(cmd->device->host);	ide_drive_t    *drive = scsi->drive;	int             ready = 0;	int             ret   = SUCCESS;	/* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))		printk (KERN_WARNING "ide-scsi: reset called for %lu\n", cmd->serial_number);	if (!drive) {		printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_reset\n");		WARN_ON(1);		return FAILED;	}	spin_lock_irq(cmd->device->host->host_lock);	spin_lock(&ide_lock);	if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {		printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");		spin_unlock(&ide_lock);		spin_unlock_irq(cmd->device->host->host_lock);		return FAILED;	}	/* kill current request */	blkdev_dequeue_request(req);	end_that_request_last(req, 0);	if (blk_sense_request(req))		kfree(scsi->pc->buffer);	kfree(scsi->pc);	scsi->pc = NULL;	kfree(req);	/* now nuke the drive queue */	while ((req = elv_next_request(drive->queue))) {		blkdev_dequeue_request(req);		end_that_request_last(req, 0);	}	HWGROUP(drive)->rq = NULL;	HWGROUP(drive)->handler = NULL;	HWGROUP(drive)->busy = 1;		/* will set this to zero when ide reset finished */	spin_unlock(&ide_lock);	ide_do_reset(drive);	/* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */	do {		spin_unlock_irq(cmd->device->host->host_lock);		msleep(50);		spin_lock_irq(cmd->device->host->host_lock);	} while ( HWGROUP(drive)->handler );	ready = drive_is_ready(drive);	HWGROUP(drive)->busy--;	if (!ready) {		printk (KERN_ERR "ide-scsi: reset failed!\n");		ret = FAILED;	}	spin_unlock_irq(cmd->device->host->host_lock);	return ret;}static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev,		sector_t capacity, int *parm){	idescsi_scsi_t *idescsi = scsihost_to_idescsi(sdev->host);	ide_drive_t *drive = idescsi->drive;	if (drive->bios_cyl && drive->bios_head && drive->bios_sect) {		parm[0] = drive->bios_head;		parm[1] = drive->bios_sect;		parm[2] = drive->bios_cyl;	}	return 0;}static struct scsi_host_template idescsi_template = {	.module			= THIS_MODULE,	.name			= "idescsi",	.info			= idescsi_info,	.slave_configure        = idescsi_slave_configure,	.ioctl			= idescsi_ioctl,	.queuecommand		= idescsi_queue,	.eh_abort_handler	= idescsi_eh_abort,	.eh_host_reset_handler  = idescsi_eh_reset,	.bios_param		= idescsi_bios,	.can_queue		= 40,	.this_id		= -1,	.sg_tablesize		= 256,	.cmd_per_lun		= 5,	.max_sectors		= 128,	.use_clustering		= DISABLE_CLUSTERING,	.emulated		= 1,	.proc_name		= "ide-scsi",};static int ide_scsi_probe(ide_drive_t *drive){	idescsi_scsi_t *idescsi;	struct Scsi_Host *host;	struct gendisk *g;	static int warned;	int err = -ENOMEM;	if (!warned && drive->media == ide_cdrom) {		printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n");		warned = 1;	}	if (idescsi_nocd && drive->media == ide_cdrom)		return -ENODEV;	if (!strstr("ide-scsi", drive->driver_req) ||	    !drive->present ||	    drive->media == ide_disk ||	    !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))		return -ENODEV;	g = alloc_disk(1 << PARTN_BITS);	if (!g)		goto out_host_put;	ide_init_disk(g, drive);	host->max_id = 1;#if IDESCSI_DEBUG_LOG	if (drive->id->last_lun)		printk(KERN_NOTICE "%s: id->last_lun=%u\n", drive->name, drive->id->last_lun);#endif	if ((drive->id->last_lun & 0x7) != 7)		host->max_lun = (drive->id->last_lun & 0x7) + 1;	else		host->max_lun = 1;	drive->driver_data = host;	idescsi = scsihost_to_idescsi(host);	idescsi->drive = drive;	idescsi->driver = &idescsi_driver;	idescsi->host = host;	idescsi->disk = g;	g->private_data = &idescsi->driver;	ide_proc_register_driver(drive, &idescsi_driver);	err = 0;	idescsi_setup(drive, idescsi);	g->fops = &idescsi_ops;	ide_register_region(g);	err = scsi_add_host(host, &drive->gendev);	if (!err) {		scsi_scan_host(host);		return 0;	}	/* fall through on error */	ide_unregister_region(g);	ide_proc_unregister_driver(drive, &idescsi_driver);	put_disk(g);out_host_put:	scsi_host_put(host);	return err;}static int __init init_idescsi_module(void){	return driver_register(&idescsi_driver.gen_driver);}static void __exit exit_idescsi_module(void){	driver_unregister(&idescsi_driver.gen_driver);}module_param(idescsi_nocd, int, 0600);MODULE_PARM_DESC(idescsi_nocd, "Disable handling of CD-ROMs so they may be driven by ide-cd");module_init(init_idescsi_module);module_exit(exit_idescsi_module);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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