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

📄 sg.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
                       &sg_idp->d_queue_depth);	    __put_user(0, &sg_idp->unused[0]);	    __put_user(0, &sg_idp->unused[1]);            return 0;        }    case SG_SET_FORCE_PACK_ID:        result = get_user(val, (int *)arg);        if (result) return result;        sfp->force_packid = val ? 1 : 0;        return 0;    case SG_GET_PACK_ID:        result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));        if (result) return result;	read_lock_irqsave(&sfp->rq_list_lock, iflags);	for (srp = sfp->headrp; srp; srp = srp->nextrp) {	    if ((1 == srp->done) && (! srp->sg_io_owned)) {		read_unlock_irqrestore(&sfp->rq_list_lock, iflags);                __put_user(srp->header.pack_id, (int *)arg);                return 0;            }        }	read_unlock_irqrestore(&sfp->rq_list_lock, iflags);        __put_user(-1, (int *)arg);        return 0;    case SG_GET_NUM_WAITING:	read_lock_irqsave(&sfp->rq_list_lock, iflags);        for (val = 0, srp = sfp->headrp; srp; srp = srp->nextrp) {	    if ((1 == srp->done) && (! srp->sg_io_owned))                ++val;        }	read_unlock_irqrestore(&sfp->rq_list_lock, iflags);        return put_user(val, (int *)arg);    case SG_GET_SG_TABLESIZE:        return put_user(sdp->sg_tablesize, (int *)arg);    case SG_SET_RESERVED_SIZE:        result = get_user(val, (int *)arg);        if (result) return result;        if (val != sfp->reserve.bufflen) {            if (sg_res_in_use(sfp))                return -EBUSY;            sg_remove_scat(&sfp->reserve);            sg_build_reserve(sfp, val);        }        return 0;    case SG_GET_RESERVED_SIZE:        val = (int)sfp->reserve.bufflen;        return put_user(val, (int *)arg);    case SG_SET_COMMAND_Q:        result = get_user(val, (int *)arg);        if (result) return result;        sfp->cmd_q = val ? 1 : 0;        return 0;    case SG_GET_COMMAND_Q:        return put_user((int)sfp->cmd_q, (int *)arg);    case SG_SET_KEEP_ORPHAN:        result = get_user(val, (int *)arg);        if (result) return result;	sfp->keep_orphan = val;        return 0;    case SG_GET_KEEP_ORPHAN:	return put_user((int)sfp->keep_orphan, (int *)arg);    case SG_NEXT_CMD_LEN:        result = get_user(val, (int *)arg);        if (result) return result;        sfp->next_cmd_len = (val > 0) ? val : 0;        return 0;    case SG_GET_VERSION_NUM:        return put_user(sg_version_num, (int *)arg);    case SG_GET_REQUEST_TABLE:	result = verify_area(VERIFY_WRITE, (void *) arg,			     size_sg_req_info * SG_MAX_QUEUE);	if (result) return result;	else {	    sg_req_info_t rinfo[SG_MAX_QUEUE];	    Sg_request * srp;	    read_lock_irqsave(&sfp->rq_list_lock, iflags);	    for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE;		 ++val, srp = srp ? srp->nextrp : srp) {		memset(&rinfo[val], 0, size_sg_req_info);		if (srp) {		    rinfo[val].req_state = srp->done + 1;		    rinfo[val].problem = srp->header.masked_status &			srp->header.host_status & srp->header.driver_status;		    rinfo[val].duration = srp->done ?			    srp->header.duration :			    sg_jif_to_ms(jiffies - srp->header.duration);		    rinfo[val].orphan = srp->orphan;		    rinfo[val].sg_io_owned = srp->sg_io_owned;		    rinfo[val].pack_id = srp->header.pack_id;		    rinfo[val].usr_ptr = srp->header.usr_ptr;		}	    }	    read_unlock_irqrestore(&sfp->rq_list_lock, iflags);	    __copy_to_user((void *)arg, rinfo, size_sg_req_info * SG_MAX_QUEUE);	    return 0;	}    case SG_EMULATED_HOST:        return put_user(sdp->device->host->hostt->emulated, (int *)arg);    case SG_SCSI_RESET:        if (filp->f_flags & O_NONBLOCK) {	    if (sdp->device->host->in_recovery)		return -EBUSY;	}	else if (! scsi_block_when_processing_errors(sdp->device))            return -EBUSY;        result = get_user(val, (int *)arg);        if (result) return result;	if (SG_SCSI_RESET_NOTHING == val)	    return 0;#ifdef SCSI_TRY_RESET_DEVICE	switch (val)	{	case SG_SCSI_RESET_DEVICE:	    val = SCSI_TRY_RESET_DEVICE;	    break;	case SG_SCSI_RESET_BUS:	    val = SCSI_TRY_RESET_BUS;	    break;	case SG_SCSI_RESET_HOST:	    val = SCSI_TRY_RESET_HOST;	    break;	default:	    return -EINVAL;	}	if(! capable(CAP_SYS_ADMIN))  return -EACCES;	return (scsi_reset_provider(sdp->device, val) == SUCCESS) ? 0 : -EIO;#else	SCSI_LOG_TIMEOUT(1, printk("sg_ioctl: SG_RESET_SCSI not supported\n"));	result = -EINVAL;#endif    case SCSI_IOCTL_SEND_COMMAND:	if (read_only) {	    unsigned char opcode = WRITE_6;	    Scsi_Ioctl_Command * siocp = (void *)arg;	    copy_from_user(&opcode, siocp->data, 1);	    if (! sg_allow_access(opcode, sdp->device->type))		return -EACCES;	}        return scsi_ioctl_send_command(sdp->device, (void *)arg);    case SG_SET_DEBUG:        result = get_user(val, (int *)arg);        if (result) return result;        sdp->sgdebug = (char)val;        return 0;    case SCSI_IOCTL_GET_IDLUN:    case SCSI_IOCTL_GET_BUS_NUMBER:    case SCSI_IOCTL_PROBE_HOST:    case SG_GET_TRANSFORM:        return scsi_ioctl(sdp->device, cmd_in, (void *)arg);    default:	if (read_only)            return -EACCES; /* don't know so take safe approach */        return scsi_ioctl(sdp->device, cmd_in, (void *)arg);    }}static unsigned int sg_poll(struct file * filp, poll_table * wait){    unsigned int res = 0;    Sg_device * sdp;    Sg_fd * sfp;    Sg_request * srp;    int count = 0;    unsigned long iflags;    if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))        return POLLERR;    poll_wait(filp, &sfp->read_wait, wait);    read_lock_irqsave(&sfp->rq_list_lock, iflags);    for (srp = sfp->headrp; srp; srp = srp->nextrp) {       	/* if any read waiting, flag it */	if ((0 == res) && (1 == srp->done) && (! srp->sg_io_owned))            res = POLLIN | POLLRDNORM;        ++count;    }    read_unlock_irqrestore(&sfp->rq_list_lock, iflags);    if (! sfp->cmd_q) {        if (0 == count)            res |= POLLOUT | POLLWRNORM;    }    else if (count < SG_MAX_QUEUE)        res |= POLLOUT | POLLWRNORM;    SCSI_LOG_TIMEOUT(3, printk("sg_poll: dev=%d, res=0x%x\n",                        MINOR(sdp->i_rdev), (int)res));    return res;}static int sg_fasync(int fd, struct file * filp, int mode){    int retval;    Sg_device * sdp;    Sg_fd * sfp;    if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))        return -ENXIO;    SCSI_LOG_TIMEOUT(3, printk("sg_fasync: dev=%d, mode=%d\n",                               MINOR(sdp->i_rdev), mode));    retval = fasync_helper(fd, filp, mode, &sfp->async_qp);    return (retval < 0) ? retval : 0;}/* This function is a "bottom half" handler that is called by the * mid level when a command is completed (or has failed). */static void sg_cmd_done_bh(Scsi_Cmnd * SCpnt){    Scsi_Request * SRpnt = SCpnt->sc_request;    int dev = MINOR(SRpnt->sr_request.rq_dev);    Sg_device * sdp = NULL;    Sg_fd * sfp;    Sg_request * srp = NULL;    read_lock(&sg_dev_arr_lock);    if (sg_dev_arr && (dev >= 0)) {	if (dev < sg_template.dev_max)	    sdp = sg_dev_arr[dev];    }    if (NULL == sdp) {	read_unlock(&sg_dev_arr_lock);	SCSI_LOG_TIMEOUT(1, printk("sg...bh: bad args dev=%d\n", dev));        scsi_release_request(SRpnt);        SRpnt = NULL;        return;    }    sfp = sdp->headfp;    while (sfp) {	read_lock(&sfp->rq_list_lock);	for (srp = sfp->headrp; srp; srp = srp->nextrp) {            if (SRpnt == srp->my_cmdp)                break;        }	read_unlock(&sfp->rq_list_lock);        if (srp)            break;        sfp = sfp->nextfp;    }    read_unlock(&sg_dev_arr_lock);    if (! srp) {	SCSI_LOG_TIMEOUT(1, printk("sg...bh: req missing, dev=%d\n", dev));        scsi_release_request(SRpnt);        SRpnt = NULL;        return;    }    /* First transfer ownership of data buffers to sg_device object. */    srp->data.k_use_sg = SRpnt->sr_use_sg;    srp->data.sglist_len = SRpnt->sr_sglist_len;    srp->data.bufflen = SRpnt->sr_bufflen;    srp->data.buffer = SRpnt->sr_buffer;    sg_clr_srpnt(SRpnt);    srp->my_cmdp = NULL;    srp->done = 1;    SCSI_LOG_TIMEOUT(4, printk("sg...bh: dev=%d, pack_id=%d, res=0x%x\n",		     dev, srp->header.pack_id, (int)SRpnt->sr_result));    srp->header.resid = SCpnt->resid;    /* sg_unmap_and(&srp->data, 0); */     /* unmap locked pages a.s.a.p. */    /* N.B. unit of duration changes here from jiffies to millisecs */    srp->header.duration = sg_jif_to_ms(jiffies - (int)srp->header.duration);    if (0 != SRpnt->sr_result) {	memcpy(srp->sense_b, SRpnt->sr_sense_buffer, sizeof(srp->sense_b));	srp->header.status = 0xff & SRpnt->sr_result;	srp->header.masked_status  = status_byte(SRpnt->sr_result);	srp->header.msg_status  = msg_byte(SRpnt->sr_result);	srp->header.host_status = host_byte(SRpnt->sr_result);	srp->header.driver_status = driver_byte(SRpnt->sr_result);	if ((sdp->sgdebug > 0) &&	    ((CHECK_CONDITION == srp->header.masked_status) ||	     (COMMAND_TERMINATED == srp->header.masked_status)))	    print_req_sense("sg_cmd_done_bh", SRpnt);	/* Following if statement is a patch supplied by Eric Youngdale */	if (driver_byte(SRpnt->sr_result) != 0	    && (SRpnt->sr_sense_buffer[0] & 0x7f) == 0x70	    && (SRpnt->sr_sense_buffer[2] & 0xf) == UNIT_ATTENTION	    && sdp->device->removable) {	    /* Detected disc change. Set the bit - this may be used if */	    /* there are filesystems using this device. */	    sdp->device->changed = 1;	}    }    /* Rely on write phase to clean out srp status values, so no "else" */    scsi_release_request(SRpnt);    SRpnt = NULL;    if (sfp->closed) { /* whoops this fd already released, cleanup */        SCSI_LOG_TIMEOUT(1,	       printk("sg...bh: already closed, freeing ...\n"));	/* should check if module is unloaded <<<<<<< */	sg_finish_rem_req(srp);	srp = NULL;	if (NULL == sfp->headrp) {            SCSI_LOG_TIMEOUT(1,		printk("sg...bh: already closed, final cleanup\n"));            sg_remove_sfp(sdp, sfp);	    sfp = NULL;        }    }    else if (srp && srp->orphan) {	if (sfp->keep_orphan)	    srp->sg_io_owned = 0;	else {	    sg_finish_rem_req(srp);	    srp = NULL;        }    }    if (sfp && srp) {	/* Now wake up any sg_read() that is waiting for this packet. */	wake_up_interruptible(&sfp->read_wait);	kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN);    }}static struct file_operations sg_fops = {	owner:		THIS_MODULE,	read:		sg_read,	write:		sg_write,	poll:		sg_poll,	ioctl:		sg_ioctl,	open:		sg_open,	release:	sg_release,	fasync:		sg_fasync,};static int sg_detect(Scsi_Device * scsidp){    switch (scsidp->type) {        case TYPE_DISK:        case TYPE_MOD:        case TYPE_ROM:        case TYPE_WORM:        case TYPE_TAPE: break;        default:        printk("Detected scsi generic sg%d at scsi%d,"                " channel %d, id %d, lun %d, type %d\n",               sg_template.dev_noticed,	       scsidp->host->host_no, scsidp->channel,               scsidp->id, scsidp->lun, scsidp->type);    }    sg_template.dev_noticed++;    return 1;}/* Driver initialization */static int sg_init(){    static int sg_registered = 0;    unsigned long iflags;    if ((sg_template.dev_noticed == 0) || sg_dev_arr)    	return 0;    write_lock_irqsave(&sg_dev_arr_lock, iflags);    if(!sg_registered) {	if (devfs_register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))        {            printk("Unable to get major %d for generic SCSI device\n",                   SCSI_GENERIC_MAJOR);	    write_unlock_irqrestore(&sg_dev_arr_lock, iflags);            return 1;        }        sg_registered++;    }    SCSI_LOG_TIMEOUT(3, printk("sg_init\n"));    sg_template.dev_max = sg_template.dev_noticed + SG_DEV_ARR_LUMP;    sg_dev_arr = (Sg_device **)kmalloc(sg_template.dev_max *     					sizeof(Sg_device *), GFP_ATOMIC);    if (NULL == sg_dev_arr) {        printk("sg_init: no space for sg_dev_arr\n");	write_unlock_irqrestore(&sg_dev_arr_lock, iflags);        return 1;    }    memset(sg_dev_arr, 0, sg_template.dev_max * sizeof(Sg_device *));    write_unlock_irqrestore(&sg_dev_arr_lock, iflags);#ifdef CONFIG_PROC_FS    sg_proc_init();#endif  /* CONFIG_PROC_FS */    return 0;}#ifndef MODULEstatic int __init sg_def_reserved_size_setup(char *str){    int tmp;    if (get_option(&str, &tmp) == 1) {	def_reserved_size = tmp;	if (tmp >= 0)	    sg_big_buff = tmp;	return 1;

⌨️ 快捷键说明

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