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

📄 sg.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (sdp->detached)	    return -ENODEV;        if (filp->f_flags & O_NONBLOCK)            return -EAGAIN;	while (1) {	    res = 0;  /* following is a macro that beats race condition */	    __wait_event_interruptible(sfp->read_wait, (sdp->detached || 		    (srp = sg_get_rq_mark(sfp, req_pack_id))), res);	    if (sdp->detached)		return -ENODEV;	    if (0 == res)		break;	    return res; /* -ERESTARTSYS because signal hit process */	}    }    if (srp->header.interface_id != '\0')	return sg_new_read(sfp, buf, count, srp);    hp = &srp->header;    memset(&old_hdr, 0, SZ_SG_HEADER);    old_hdr.reply_len = (int)hp->timeout;    old_hdr.pack_len = old_hdr.reply_len;   /* very old, strange behaviour */    old_hdr.pack_id = hp->pack_id;    old_hdr.twelve_byte =	    ((srp->data.cmd_opcode >= 0xc0) && (12 == hp->cmd_len)) ? 1 : 0;    old_hdr.target_status = hp->masked_status;    old_hdr.host_status = hp->host_status;    old_hdr.driver_status = hp->driver_status;    if ((CHECK_CONDITION & hp->masked_status) ||	(DRIVER_SENSE & hp->driver_status))	memcpy(old_hdr.sense_buffer, srp->sense_b,	       sizeof(old_hdr.sense_buffer));    switch (hp->host_status)    { /* This setup of 'result' is for backward compatibility and is best	 ignored by the user who should use target, host + driver status */	case DID_OK:	case DID_PASSTHROUGH:	case DID_SOFT_ERROR:	    old_hdr.result = 0;	    break;	case DID_NO_CONNECT:	case DID_BUS_BUSY:	case DID_TIME_OUT:	    old_hdr.result = EBUSY;	    break;	case DID_BAD_TARGET:	case DID_ABORT:	case DID_PARITY:	case DID_RESET:	case DID_BAD_INTR:	    old_hdr.result = EIO;	    break;	case DID_ERROR:	    old_hdr.result =	      (srp->sense_b[0] == 0 && hp->masked_status == GOOD) ? 0 : EIO;	    break;	default:	    old_hdr.result = EIO;	    break;    }    /* Now copy the result back to the user buffer.  */    if (count >= SZ_SG_HEADER) {	__copy_to_user(buf, &old_hdr, SZ_SG_HEADER);        buf += SZ_SG_HEADER;	if (count > old_hdr.reply_len)	    count = old_hdr.reply_len;	if (count > SZ_SG_HEADER)	    sg_read_oxfer(srp, buf, count - SZ_SG_HEADER);    }    else	count = (old_hdr.result == 0) ? 0 : -EIO;    sg_finish_rem_req(srp);    return count;}static ssize_t sg_new_read(Sg_fd * sfp, char * buf, size_t count,			   Sg_request * srp){    sg_io_hdr_t * hp = &srp->header;    int err = 0;    int len;    if (count < SZ_SG_IO_HDR) {	err = -EINVAL;    	goto err_out;    }    hp->sb_len_wr = 0;    if ((hp->mx_sb_len > 0) && hp->sbp) {	if ((CHECK_CONDITION & hp->masked_status) ||	    (DRIVER_SENSE & hp->driver_status)) {	    int sb_len = sizeof(dummy_cmdp->sr_sense_buffer);	    sb_len = (hp->mx_sb_len > sb_len) ? sb_len : hp->mx_sb_len;	    len = 8 + (int)srp->sense_b[7]; /* Additional sense length field */	    len = (len > sb_len) ? sb_len : len;	    if ((err = verify_area(VERIFY_WRITE, hp->sbp, len)))		goto err_out;	    __copy_to_user(hp->sbp, srp->sense_b, len);	    hp->sb_len_wr = len;	}    }    if (hp->masked_status || hp->host_status || hp->driver_status)	hp->info |= SG_INFO_CHECK;    copy_to_user(buf, hp, SZ_SG_IO_HDR);    err = sg_read_xfer(srp);err_out:    sg_finish_rem_req(srp);    return (0 == err) ? count : err;}static ssize_t sg_write(struct file * filp, const char * buf,                        size_t count, loff_t *ppos){    int                   mxsize, cmd_size, k;    int                   input_size, blocking;    unsigned char         opcode;    Sg_device           * sdp;    Sg_fd               * sfp;    Sg_request          * srp;    struct sg_header      old_hdr;    sg_io_hdr_t         * hp;    unsigned char         cmnd[sizeof(dummy_cmdp->sr_cmnd)];    if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))        return -ENXIO;    SCSI_LOG_TIMEOUT(3, printk("sg_write: dev=%d, count=%d\n",                               MINOR(sdp->i_rdev), (int)count));    if (sdp->detached)    	return -ENODEV;    if (! ((filp->f_flags & O_NONBLOCK) ||           scsi_block_when_processing_errors(sdp->device)))        return -ENXIO;    if (ppos != &filp->f_pos)        ; /* FIXME: Hmm.  Seek to the right place, or fail?  */    if ((k = verify_area(VERIFY_READ, buf, count)))        return k;  /* protects following copy_from_user()s + get_user()s */    if (count < SZ_SG_HEADER)	return -EIO;    __copy_from_user(&old_hdr, buf, SZ_SG_HEADER);    blocking = !(filp->f_flags & O_NONBLOCK);    if (old_hdr.reply_len < 0)	return sg_new_write(sfp, buf, count, blocking, 0, NULL);    if (count < (SZ_SG_HEADER + 6))	return -EIO;   /* The minimum scsi command length is 6 bytes. */    if (! (srp = sg_add_request(sfp))) {	SCSI_LOG_TIMEOUT(1, printk("sg_write: queue full\n"));	return -EDOM;    }    buf += SZ_SG_HEADER;    __get_user(opcode, buf);    if (sfp->next_cmd_len > 0) {        if (sfp->next_cmd_len > MAX_COMMAND_SIZE) {            SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n"));            sfp->next_cmd_len = 0;	    sg_remove_request(sfp, srp);            return -EIO;        }        cmd_size = sfp->next_cmd_len;        sfp->next_cmd_len = 0; /* reset so only this write() effected */    }    else {        cmd_size = COMMAND_SIZE(opcode); /* based on SCSI command group */	if ((opcode >= 0xc0) && old_hdr.twelve_byte)            cmd_size = 12;    }    SCSI_LOG_TIMEOUT(4, printk("sg_write:   scsi opcode=0x%02x, cmd_size=%d\n",                               (int)opcode, cmd_size));/* Determine buffer size.  */    input_size = count - cmd_size;    mxsize = (input_size > old_hdr.reply_len) ? input_size :						old_hdr.reply_len;    mxsize -= SZ_SG_HEADER;    input_size -= SZ_SG_HEADER;    if (input_size < 0) {        sg_remove_request(sfp, srp);        return -EIO; /* User did not pass enough bytes for this command. */    }    hp = &srp->header;    hp->interface_id = '\0'; /* indicator of old interface tunnelled */    hp->cmd_len = (unsigned char)cmd_size;    hp->iovec_count = 0;    hp->mx_sb_len = 0;    if (input_size > 0)	hp->dxfer_direction = ((old_hdr.reply_len - SZ_SG_HEADER) > 0) ?			      SG_DXFER_TO_FROM_DEV : SG_DXFER_TO_DEV;    else	hp->dxfer_direction = (mxsize > 0) ? SG_DXFER_FROM_DEV :					     SG_DXFER_NONE;    hp->dxfer_len = mxsize;    hp->dxferp = (unsigned char *)buf + cmd_size;    hp->sbp = NULL;    hp->timeout = old_hdr.reply_len;    /* structure abuse ... */    hp->flags = input_size;             /* structure abuse ... */    hp->pack_id = old_hdr.pack_id;    hp->usr_ptr = NULL;    __copy_from_user(cmnd, buf, cmd_size);    k = sg_common_write(sfp, srp, cmnd, sfp->timeout, blocking);    return (k < 0) ? k : count;}static ssize_t sg_new_write(Sg_fd * sfp, const char * buf, size_t count,			    int blocking, int read_only, Sg_request ** o_srp){    int                   k;    Sg_request          * srp;    sg_io_hdr_t         * hp;    unsigned char         cmnd[sizeof(dummy_cmdp->sr_cmnd)];    int                   timeout;    if (count < SZ_SG_IO_HDR)	return -EINVAL;    if ((k = verify_area(VERIFY_READ, buf, count)))	return k;  /* protects following copy_from_user()s + get_user()s */    sfp->cmd_q = 1;  /* when sg_io_hdr seen, set command queuing on */    if (! (srp = sg_add_request(sfp))) {	SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n"));	return -EDOM;    }    hp = &srp->header;    __copy_from_user(hp, buf, SZ_SG_IO_HDR);    if (hp->interface_id != 'S') {	sg_remove_request(sfp, srp);	return -ENOSYS;    }    if (hp->flags & SG_FLAG_MMAP_IO) {    	if (hp->dxfer_len > sfp->reserve.bufflen) {	    sg_remove_request(sfp, srp);	    return -ENOMEM;	/* MMAP_IO size must fit in reserve buffer */	}	if (hp->flags & SG_FLAG_DIRECT_IO) {	    sg_remove_request(sfp, srp);	    return -EINVAL;	/* either MMAP_IO or DIRECT_IO (not both) */	}	if (sg_res_in_use(sfp)) {	    sg_remove_request(sfp, srp);	    return -EBUSY;	/* reserve buffer already being used */	}    }    timeout = sg_ms_to_jif(srp->header.timeout);    if ((! hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof(cmnd))) {	sg_remove_request(sfp, srp);	return -EMSGSIZE;    }    if ((k = verify_area(VERIFY_READ, hp->cmdp, hp->cmd_len))) {	sg_remove_request(sfp, srp);	return k;  /* protects following copy_from_user()s + get_user()s */    }    __copy_from_user(cmnd, hp->cmdp, hp->cmd_len);    if (read_only &&	(! sg_allow_access(cmnd[0], sfp->parentdp->device->type))) {	sg_remove_request(sfp, srp);	return -EACCES;    }    k = sg_common_write(sfp, srp, cmnd, timeout, blocking);    if (k < 0) return k;    if (o_srp) *o_srp = srp;    return count;}static int sg_common_write(Sg_fd * sfp, Sg_request * srp,			   unsigned char * cmnd, int timeout, int blocking){    int                   k;    Scsi_Request        * SRpnt;    Sg_device           * sdp = sfp->parentdp;    sg_io_hdr_t         * hp = &srp->header;    request_queue_t	* q;    srp->data.cmd_opcode = cmnd[0];  /* hold opcode of command */    hp->status = 0;    hp->masked_status = 0;    hp->msg_status = 0;    hp->info = 0;    hp->host_status = 0;    hp->driver_status = 0;    hp->resid = 0;    SCSI_LOG_TIMEOUT(4,	printk("sg_common_write:  scsi opcode=0x%02x, cmd_size=%d\n",	       (int)cmnd[0], (int)hp->cmd_len));    if ((k = sg_start_req(srp))) {	SCSI_LOG_TIMEOUT(1, printk("sg_write: start_req err=%d\n", k));	sg_finish_rem_req(srp);        return k;    /* probably out of space --> ENOMEM */    }    if ((k = sg_write_xfer(srp))) {	SCSI_LOG_TIMEOUT(1, printk("sg_write: write_xfer, bad address\n"));	sg_finish_rem_req(srp);	return k;    }    if (sdp->detached) {    	sg_finish_rem_req(srp);    	return -ENODEV;    }    SRpnt = scsi_allocate_request(sdp->device);    if(SRpnt == NULL) {    	SCSI_LOG_TIMEOUT(1, printk("sg_write: no mem\n"));    	sg_finish_rem_req(srp);    	return -ENOMEM;    }    srp->my_cmdp = SRpnt;    q = &SRpnt->sr_device->request_queue;    SRpnt->sr_request.rq_dev = sdp->i_rdev;    SRpnt->sr_request.rq_status = RQ_ACTIVE;    SRpnt->sr_sense_buffer[0] = 0;    SRpnt->sr_cmd_len = hp->cmd_len;    if (! (hp->flags & SG_FLAG_LUN_INHIBIT)) {	if (sdp->device->scsi_level <= SCSI_2)	    cmnd[1] = (cmnd[1] & 0x1f) | (sdp->device->lun << 5);    }    SRpnt->sr_use_sg = srp->data.k_use_sg;    SRpnt->sr_sglist_len = srp->data.sglist_len;    SRpnt->sr_bufflen = srp->data.bufflen;    SRpnt->sr_underflow = 0;    SRpnt->sr_buffer = srp->data.buffer;    switch (hp->dxfer_direction) {    case SG_DXFER_TO_FROM_DEV:    case SG_DXFER_FROM_DEV:	SRpnt->sr_data_direction = SCSI_DATA_READ; break;    case SG_DXFER_TO_DEV:	SRpnt->sr_data_direction = SCSI_DATA_WRITE; break;    case SG_DXFER_UNKNOWN:	SRpnt->sr_data_direction = SCSI_DATA_UNKNOWN; break;    default:	SRpnt->sr_data_direction = SCSI_DATA_NONE; break;    }    srp->data.k_use_sg = 0;    srp->data.sglist_len = 0;    srp->data.bufflen = 0;    srp->data.buffer = NULL;    hp->duration = jiffies;	/* unit jiffies now, millisecs after done *//* Now send everything of to mid-level. The next time we hear about this   packet is when sg_cmd_done_bh() is called (i.e. a callback). */    scsi_do_req(SRpnt, (void *)cmnd,		(void *)SRpnt->sr_buffer, hp->dxfer_len,		sg_cmd_done_bh, timeout, SG_DEFAULT_RETRIES);    /* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1)    generic_unplug_device(q);#endif    return 0;}static int sg_ioctl(struct inode * inode, struct file * filp,                    unsigned int cmd_in, unsigned long arg){    int result, val, read_only;    Sg_device * sdp;    Sg_fd * sfp;    Sg_request * srp;    unsigned long iflags;    if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp)))        return -ENXIO;    SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: dev=%d, cmd=0x%x\n",                               MINOR(sdp->i_rdev), (int)cmd_in));    read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));    switch(cmd_in)    {    case SG_IO:	{	    int blocking = 1;   /* ignore O_NONBLOCK flag */	    if (sdp->detached)		return -ENODEV;	    if(! scsi_block_when_processing_errors(sdp->device) )		return -ENXIO;	    result = verify_area(VERIFY_WRITE, (void *)arg, SZ_SG_IO_HDR);	    if (result) return result;	    result = sg_new_write(sfp, (const char *)arg, SZ_SG_IO_HDR,				  blocking, read_only, &srp);	    if (result < 0) return result;	    srp->sg_io_owned = 1;	    while (1) {		result = 0;  /* following macro to beat race condition */		__wait_event_interruptible(sfp->read_wait,		       (sdp->detached || sfp->closed || srp->done), result);		if (sdp->detached)		    return -ENODEV;		if (sfp->closed)		    return 0;       /* request packet dropped already */		if (0 == result)		    break;		srp->orphan = 1;		return result; /* -ERESTARTSYS because signal hit process */	    }	    srp->done = 2;	    result = sg_new_read(sfp, (char *)arg, SZ_SG_IO_HDR, srp);	    return (result < 0) ? result : 0;	}

⌨️ 快捷键说明

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