예제 #1
0
s32 us_app_stub_init(void)
{
    US_DEBUG("tcp_sock len:%u \n",sizeof(struct tcp_sock));
    US_DEBUG("tcp_sock len:%u \n",sizeof(struct inet_request_sock));
    US_DEBUG("tcp_sock len:%u \n",sizeof(struct tcp_timewait_sock));


    us_objslab * us_sp = us_memobj_slab_create(2,
                         sizeof(struct msghdr) + sizeof(struct iovec)*US_MSGHDR_IOVLEN_MAX, 8);
    if(us_sp == NULL) {
        US_ERR("TH:%u,msghdr slab cache create failed!\n",US_GET_LCORE());
        return US_ENOMEM;
    }

    US_PER_LCORE(us_msghdr_slab) = us_sp;
    //us_slab_stub_test();
    //us_socket_test();
    //us_server_stub_init();
    us_proxy_stub_init();

    //if(us_client_init(10)<0){
    //	US_ERR("TH:%u,client init failed!\n",US_GET_LCORE());
    //	return US_RET_OK;
    //}

    return US_RET_OK;
}
예제 #2
0
파일: ip_output.c 프로젝트: lehoon/fast-tcp
s32 ip_init(void)
{
	s32	i = 0;
	s32 skc_id ;
	struct sk_buff 	*skb = NULL;
	struct sock		*sk = NULL;
	struct net		*pnet = US_PER_LCORE(init_net);
	
	sk = us_sock_alloc(pnet);
	skc_id = sk->sk_id;
	memset(sk, 0, sizeof(struct sock));
	sk->sk_id = skc_id;

	US_DEBUG("TH:%u,ip_init sk_id:%u\n",US_GET_LCORE(),sk->sk_id);
	if (!sk){
		US_ERR("TH:%d,fatal error! No ipv4->tcp_sock!",US_GET_LCORE());
		return US_ENOMEM;
	}

	sk->sk_wmem_alloc = 1;

	sk->sk_prot = US_PER_LCORE(tcp_prot);
	sk->sk_prot_creator = sk->sk_prot;
	sk->sk_family = AF_INET;
	sk->sk_net = pnet;
	
	sk->sk_reuse = 0;
	
	//sock_init_data(sk,sk);
	sk->sk_protocol		= IPPROTO_TCP;
	sk->sk_userlocks 	= (SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK);

	pnet->ipv4.tcp_sock = sk;

	US_PER_LCORE(mmbuf_flush) = 0;
	US_PER_LCORE(mmbuf_num) = 0;

	memset(pnet->ipv4.tcp_skb,0,sizeof(void *)*US_MAX_PKT_BURST_OUT*2);
	for(i = 0; i< US_MAX_PKT_BURST_OUT*2 ; i++){
		skb = alloc_skb(sk,MAX_TCP_HEADER,US_SKB_CLONE);
		if(skb == NULL){
			US_ERR("TH:%d,fatal error! No skb alloced for ipv4->tcp_sock!",US_GET_LCORE());
			return US_ENOMEM;
		}

		skb->len = 0;		//Do not put here;
		skb_build_ip_head(skb,pnet);
		pnet->ipv4.tcp_skb[i] = skb;
	}

	pnet->ipv4.tcp_skb_index = 0;
	//if(rte_pktmbuf_trim((struct rte_mbuf*)skb->head,MAX_TCP_HEADER) < 0){
	//	US_ERR("TH:%d,fatal error! No skb reserved for ipv4->tcp_sock!",US_GET_LCORE);	
	//	return US_ENOBUFS;
	//}
	
	return US_RET_OK;
}
예제 #3
0
파일: freecom.c 프로젝트: CSCLOG/beaglebone
/*
 * Transport for the Freecom USB/IDE adaptor.
 *
 */
static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
{
	struct freecom_cb_wrap *fcb;
	struct freecom_status  *fst;
	unsigned int ipipe, opipe;		/* We need both pipes. */
	int result;
	unsigned int partial;
	int length;

	fcb = (struct freecom_cb_wrap *) us->iobuf;
	fst = (struct freecom_status *) us->iobuf;

	US_DEBUGP("Freecom TRANSPORT STARTED\n");

	/* Get handles for both transports. */
	opipe = us->send_bulk_pipe;
	ipipe = us->recv_bulk_pipe;

	/* The ATAPI Command always goes out first. */
	fcb->Type = FCM_PACKET_ATAPI | 0x00;
	fcb->Timeout = 0;
	memcpy (fcb->Atapi, srb->cmnd, 12);
	memset (fcb->Filler, 0, sizeof (fcb->Filler));

	US_DEBUG(pdump (srb->cmnd, 12));

	/* Send it out. */
	result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
			FCM_PACKET_LENGTH, NULL);

	/* The Freecom device will only fail if there is something wrong in
	 * USB land.  It returns the status in its own registers, which
	 * come back in the bulk pipe. */
	if (result != USB_STOR_XFER_GOOD) {
		US_DEBUGP ("freecom transport error\n");
		return USB_STOR_TRANSPORT_ERROR;
	}

	/* There are times we can optimize out this status read, but it
	 * doesn't hurt us to always do it now. */
	result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
			FCM_STATUS_PACKET_LENGTH, &partial);
	US_DEBUGP("foo Status result %d %u\n", result, partial);
	if (result != USB_STOR_XFER_GOOD)
		return USB_STOR_TRANSPORT_ERROR;

	US_DEBUG(pdump ((void *) fst, partial));

	/* The firmware will time-out commands after 20 seconds. Some commands
	 * can legitimately take longer than this, so we use a different
	 * command that only waits for the interrupt and then sends status,
	 * without having to send a new ATAPI command to the device.
	 *
	 * NOTE: There is some indication that a data transfer after a timeout
	 * may not work, but that is a condition that should never happen.
	 */
	while (fst->Status & FCM_STATUS_BUSY) {
		US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n");
		US_DEBUGP("fst->Status is %x\n", fst->Status);

		/* Get the status again */
		fcb->Type = FCM_PACKET_STATUS;
		fcb->Timeout = 0;
		memset (fcb->Atapi, 0, sizeof(fcb->Atapi));
		memset (fcb->Filler, 0, sizeof (fcb->Filler));

		/* Send it out. */
		result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
				FCM_PACKET_LENGTH, NULL);

		/* The Freecom device will only fail if there is something
		 * wrong in USB land.  It returns the status in its own
		 * registers, which come back in the bulk pipe.
		 */
		if (result != USB_STOR_XFER_GOOD) {
			US_DEBUGP ("freecom transport error\n");
			return USB_STOR_TRANSPORT_ERROR;
		}

		/* get the data */
		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
				FCM_STATUS_PACKET_LENGTH, &partial);

		US_DEBUGP("bar Status result %d %u\n", result, partial);
		if (result != USB_STOR_XFER_GOOD)
			return USB_STOR_TRANSPORT_ERROR;

		US_DEBUG(pdump ((void *) fst, partial));
	}

	if (partial != 4)
		return USB_STOR_TRANSPORT_ERROR;
	if ((fst->Status & 1) != 0) {
		US_DEBUGP("operation failed\n");
		return USB_STOR_TRANSPORT_FAILED;
	}

	/* The device might not have as much data available as we
	 * requested.  If you ask for more than the device has, this reads
	 * and such will hang. */
	US_DEBUGP("Device indicates that it has %d bytes available\n",
			le16_to_cpu (fst->Count));
	US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb));

	/* Find the length we desire to read. */
	switch (srb->cmnd[0]) {
	case INQUIRY:
	case REQUEST_SENSE:	/* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
	case MODE_SENSE:
	case MODE_SENSE_10:
		length = le16_to_cpu(fst->Count);
		break;
	default:
		length = scsi_bufflen(srb);
	}

	/* verify that this amount is legal */
	if (length > scsi_bufflen(srb)) {
		length = scsi_bufflen(srb);
		US_DEBUGP("Truncating request to match buffer length: %d\n", length);
	}

	/* What we do now depends on what direction the data is supposed to
	 * move in. */

	switch (us->srb->sc_data_direction) {
	case DMA_FROM_DEVICE:
		/* catch bogus "read 0 length" case */
		if (!length)
			break;
		/* Make sure that the status indicates that the device
		 * wants data as well. */
		if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
			US_DEBUGP("SCSI wants data, drive doesn't have any\n");
			return USB_STOR_TRANSPORT_FAILED;
		}
		result = freecom_readdata (srb, us, ipipe, opipe, length);
		if (result != USB_STOR_TRANSPORT_GOOD)
			return result;

		US_DEBUGP("FCM: Waiting for status\n");
		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
				FCM_PACKET_LENGTH, &partial);
		US_DEBUG(pdump ((void *) fst, partial));

		if (partial != 4 || result > USB_STOR_XFER_SHORT)
			return USB_STOR_TRANSPORT_ERROR;
		if ((fst->Status & ERR_STAT) != 0) {
			US_DEBUGP("operation failed\n");
			return USB_STOR_TRANSPORT_FAILED;
		}
		if ((fst->Reason & 3) != 3) {
			US_DEBUGP("Drive seems still hungry\n");
			return USB_STOR_TRANSPORT_FAILED;
		}
		US_DEBUGP("Transfer happy\n");
		break;

	case DMA_TO_DEVICE:
		/* catch bogus "write 0 length" case */
		if (!length)
			break;
		/* Make sure the status indicates that the device wants to
		 * send us data. */
		/* !!IMPLEMENT!! */
		result = freecom_writedata (srb, us, ipipe, opipe, length);
		if (result != USB_STOR_TRANSPORT_GOOD)
			return result;

		US_DEBUGP("FCM: Waiting for status\n");
		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
				FCM_PACKET_LENGTH, &partial);

		if (partial != 4 || result > USB_STOR_XFER_SHORT)
			return USB_STOR_TRANSPORT_ERROR;
		if ((fst->Status & ERR_STAT) != 0) {
			US_DEBUGP("operation failed\n");
			return USB_STOR_TRANSPORT_FAILED;
		}
		if ((fst->Reason & 3) != 3) {
			US_DEBUGP("Drive seems still hungry\n");
			return USB_STOR_TRANSPORT_FAILED;
		}

		US_DEBUGP("Transfer happy\n");
		break;


	case DMA_NONE:
		/* Easy, do nothing. */
		break;

	default:
		/* should never hit here -- filtered in usb.c */
		US_DEBUGP ("freecom unimplemented direction: %d\n",
				us->srb->sc_data_direction);
		/* Return fail, SCSI seems to handle this better. */
		return USB_STOR_TRANSPORT_FAILED;
		break;
	}

	return USB_STOR_TRANSPORT_GOOD;
}
//仔细研读
static int usb_stor_control_thread(void * __us)
{

	struct us_data *us = (struct us_data *)__us;
	struct Scsi_Host *host = us_to_host(us);
//---------------------------
pr_info("7 usb stor control thread\n");

	for(;;) {
		US_DEBUGP("*** thread sleeping.\n");
		if (wait_for_completion_interruptible(&us->cmnd_ready))
			break;

		US_DEBUGP("*** thread awakened.\n");

		/* lock the device pointers */
		mutex_lock(&(us->dev_mutex));

		/* lock access to the state */
		scsi_lock(host);

		/* When we are called with no command pending, we're done */
		if (us->srb == NULL) {
			scsi_unlock(host);
			mutex_unlock(&us->dev_mutex);
			US_DEBUGP("-- exiting\n");
			break;
		}

		/* has the command timed out *already* ? */
		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
			us->srb->result = DID_ABORT << 16;
			goto SkipForAbort;
		}

		scsi_unlock(host);

		/* reject the command if the direction indicator 
		 * is UNKNOWN
		 */
		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
			US_DEBUGP("UNKNOWN data direction\n");
			us->srb->result = DID_ERROR << 16;
		}

		/* reject if target != 0 or if LUN is higher than
		 * the maximum known LUN
		 */
		else if (us->srb->device->id && 
				!(us->fflags & US_FL_SCM_MULT_TARG)) {
			US_DEBUGP("Bad target number (%d:%d)\n",
				  us->srb->device->id, us->srb->device->lun);
			us->srb->result = DID_BAD_TARGET << 16;
		}

		else if (us->srb->device->lun > us->max_lun) {
			US_DEBUGP("Bad LUN (%d:%d)\n",
				  us->srb->device->id, us->srb->device->lun);
			us->srb->result = DID_BAD_TARGET << 16;
		}

		/* Handle those devices which need us to fake 
		 * their inquiry data */
		else if ((us->srb->cmnd[0] == INQUIRY) &&
			    (us->fflags & US_FL_FIX_INQUIRY)) {
			unsigned char data_ptr[36] = {
			    0x00, 0x80, 0x02, 0x02,
			    0x1F, 0x00, 0x00, 0x00};

			US_DEBUGP("Faking INQUIRY command\n");
			fill_inquiry_response(us, data_ptr, 36);
			us->srb->result = SAM_STAT_GOOD;
		}

		/* we've got a command, let's do it! */
		else {
			US_DEBUG(usb_stor_show_command(us->srb));
			us->proto_handler(us->srb, us);
			usb_mark_last_busy(us->pusb_dev);
		}

		/* lock access to the state */
		scsi_lock(host);

		/* indicate that the command is done */
		if (us->srb->result != DID_ABORT << 16) {
			US_DEBUGP("scsi cmd done, result=0x%x\n", 
				   us->srb->result);
			us->srb->scsi_done(us->srb);
		} else {
SkipForAbort:
			US_DEBUGP("scsi command aborted\n");
		}

		/* If an abort request was received we need to signal that
		 * the abort has finished.  The proper test for this is
		 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
		 * the timeout might have occurred after the command had
		 * already completed with a different result code. */
		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
			complete(&(us->notify));

			/* Allow USB transfers to resume */
			clear_bit(US_FLIDX_ABORTING, &us->dflags);
			clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
		}

		/* finished working on this command */
		us->srb = NULL;
		scsi_unlock(host);

		/* unlock the device pointers */
		mutex_unlock(&us->dev_mutex);
	} /* for (;;) */

	/* Wait until we are told to stop */
	for (;;) {
		set_current_state(TASK_INTERRUPTIBLE);
		if (kthread_should_stop())
			break;
		schedule();
	}
	__set_current_state(TASK_RUNNING);
	return 0;
}	
예제 #5
0
파일: freecom.c 프로젝트: dmgerman/original
/*
 * Transport for the Freecom USB/IDE adaptor.
 *
 */
int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
{
        struct freecom_cb_wrap *fcb;
        struct freecom_status  *fst;
        int ipipe, opipe;             /* We need both pipes. */
        int result;
        int partial;
        int length;
        freecom_udata_t extra;

        extra = (freecom_udata_t) us->extra;

        fcb = (struct freecom_cb_wrap *) extra->buffer;
        fst = (struct freecom_status *) extra->buffer;

        US_DEBUGP("Freecom TRANSPORT STARTED\n");

        /* Get handles for both transports. */
        opipe = usb_sndbulkpipe (us->pusb_dev, us->ep_out);
        ipipe = usb_rcvbulkpipe (us->pusb_dev, us->ep_in);

#if 0
        /* Yuck, let's see if this helps us.  Artificially increase the
         * length on this. */
        if (srb->cmnd[0] == 0x03 && srb->cmnd[4] == 0x12)
                srb->cmnd[4] = 0x0E;
#endif

        /* The ATAPI Command always goes out first. */
        fcb->Type = FCM_PACKET_ATAPI | 0x00;
        fcb->Timeout = 0;
        memcpy (fcb->Atapi, srb->cmnd, 12);
        memset (fcb->Filler, 0, sizeof (fcb->Filler));

        US_DEBUG(pdump (srb->cmnd, 12));

        /* Send it out. */
        result = usb_stor_bulk_msg (us, fcb, opipe,
                        FCM_PACKET_LENGTH, &partial);

        /* The Freecom device will only fail if there is something wrong in
         * USB land.  It returns the status in its own registers, which
         * come back in the bulk pipe. */
        if (result != 0) {
                US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
                                result, partial);

		/* -ENOENT -- we canceled this transfer */
		if (result == -ENOENT) {
			US_DEBUGP("freecom_transport(): transfer aborted\n");
			return US_BULK_TRANSFER_ABORTED;
		}

                return USB_STOR_TRANSPORT_ERROR;
        }

        /* There are times we can optimize out this status read, but it
         * doesn't hurt us to always do it now. */
        result = usb_stor_bulk_msg (us, fst, ipipe,
                        FCM_PACKET_LENGTH, &partial);
        US_DEBUGP("foo Status result %d %d\n", result, partial);
	/* -ENOENT -- we canceled this transfer */
	if (result == -ENOENT) {
		US_DEBUGP("freecom_transport(): transfer aborted\n");
		return US_BULK_TRANSFER_ABORTED;
	}

        US_DEBUG(pdump ((void *) fst, partial));

	/* while we haven't recieved the IRQ */
	while (!(fst->Status & 0x2)) {
		/* send a command to re-fetch the status */
		US_DEBUGP("Re-attempting to get status...\n");

		fcb->Type = FCM_PACKET_STATUS;
		fcb->Timeout = 0;
		memset (fcb->Atapi, 0, 12);
		memset (fcb->Filler, 0, sizeof (fcb->Filler));

		/* Send it out. */
		result = usb_stor_bulk_msg (us, fcb, opipe,
				FCM_PACKET_LENGTH, &partial);

		/* The Freecom device will only fail if there is something
		 * wrong in USB land.  It returns the status in its own
		 * registers, which come back in the bulk pipe.
		 */
		if (result != 0) {
			US_DEBUGP ("freecom xport failure: r=%d, p=%d\n",
					result, partial);

			/* -ENOENT -- we canceled this transfer */
			if (result == -ENOENT) {
				US_DEBUGP("freecom_transport(): transfer aborted\n");
				return US_BULK_TRANSFER_ABORTED;
			}

			return USB_STOR_TRANSPORT_ERROR;
		}

		/* actually get the status info */
		result = usb_stor_bulk_msg (us, fst, ipipe,
				FCM_PACKET_LENGTH, &partial);
		US_DEBUGP("bar Status result %d %d\n", result, partial);
		/* -ENOENT -- we canceled this transfer */
		if (result == -ENOENT) {
			US_DEBUGP("freecom_transport(): transfer aborted\n");
			return US_BULK_TRANSFER_ABORTED;
		}

		US_DEBUG(pdump ((void *) fst, partial));
	}

        if (partial != 4 || result != 0) {
                return USB_STOR_TRANSPORT_ERROR;
        }
        if ((fst->Status & 1) != 0) {
                US_DEBUGP("operation failed\n");
                return USB_STOR_TRANSPORT_FAILED;
        }

        /* The device might not have as much data available as we
         * requested.  If you ask for more than the device has, this reads
         * and such will hang. */
        US_DEBUGP("Device indicates that it has %d bytes available\n",
                        le16_to_cpu (fst->Count));

        /* Find the length we desire to read.  It is the lesser of the SCSI
         * layer's requested length, and the length the device claims to
         * have available. */
        length = usb_stor_transfer_length (srb);
        US_DEBUGP("SCSI requested %d\n", length);
        if (length > le16_to_cpu (fst->Count))
                length = le16_to_cpu (fst->Count);

        /* What we do now depends on what direction the data is supposed to
         * move in. */

        switch (us->srb->sc_data_direction) {
        case SCSI_DATA_READ:
                /* Make sure that the status indicates that the device
                 * wants data as well. */
                if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
                        US_DEBUGP("SCSI wants data, drive doesn't have any\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
                result = freecom_readdata (srb, us, ipipe, opipe, length);
                if (result != USB_STOR_TRANSPORT_GOOD)
                        return result;

                US_DEBUGP("FCM: Waiting for status\n");
                result = usb_stor_bulk_msg (us, fst, ipipe,
                                FCM_PACKET_LENGTH, &partial);
		US_DEBUG(pdump ((void *) fst, partial));
                if (result == -ENOENT) {
                        US_DEBUGP ("freecom_transport: transfer aborted\n");
                        return US_BULK_TRANSFER_ABORTED;
                }
                if (partial != 4 || result != 0)
                        return USB_STOR_TRANSPORT_ERROR;
                if ((fst->Status & ERR_STAT) != 0) {
                        US_DEBUGP("operation failed\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
                if ((fst->Reason & 3) != 3) {
                        US_DEBUGP("Drive seems still hungry\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
                US_DEBUGP("Transfer happy\n");
                break;

        case SCSI_DATA_WRITE:
                /* Make sure the status indicates that the device wants to
                 * send us data. */
                /* !!IMPLEMENT!! */
                result = freecom_writedata (srb, us, ipipe, opipe, length);
                if (result != USB_STOR_TRANSPORT_GOOD)
                        return result;

#if 1
                US_DEBUGP("FCM: Waiting for status\n");
                result = usb_stor_bulk_msg (us, fst, ipipe,
                                FCM_PACKET_LENGTH, &partial);
                if (result == -ENOENT) {
                        US_DEBUGP ("freecom_transport: transfer aborted\n");
                        return US_BULK_TRANSFER_ABORTED;
                }
                if (partial != 4 || result != 0)
                        return USB_STOR_TRANSPORT_ERROR;
                if ((fst->Status & ERR_STAT) != 0) {
                        US_DEBUGP("operation failed\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
                if ((fst->Reason & 3) != 3) {
                        US_DEBUGP("Drive seems still hungry\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
#endif
                US_DEBUGP("Transfer happy\n");
                break;


        case SCSI_DATA_NONE:
                /* Easy, do nothing. */
                break;

        default:
                US_DEBUGP ("freecom unimplemented direction: %d\n",
                                us->srb->sc_data_direction);
                // Return fail, SCSI seems to handle this better.
                return USB_STOR_TRANSPORT_FAILED;
                break;
        }

        return USB_STOR_TRANSPORT_GOOD;

        US_DEBUGP("Freecom: transfer_length = %d\n",
			usb_stor_transfer_length (srb));

        US_DEBUGP("Freecom: direction = %d\n", srb->sc_data_direction);

        return USB_STOR_TRANSPORT_ERROR;
}
static int usb_stor_control_thread(void * __us)
{

	struct us_data *us = (struct us_data *)__us;
	struct Scsi_Host *host = us_to_host(us);
//---------------------------
pr_info("7 usb stor control thread\n");

	for(;;) {
		//若有u盘拔插或者有命令才会awake,否则一直就在这睡觉觉
		if (wait_for_completion_interruptible(&us->cmnd_ready))
			break;
//从此处wake

		/*  */
		mutex_lock(&(us->dev_mutex));

		/*每当需要写us->srb时候就需要锁之 */
		scsi_lock(host);

	
		if (us->srb == NULL) {
			scsi_unlock(host);
			mutex_unlock(&us->dev_mutex);
			US_DEBUGP("-- exiting\n");
			break;
		}

	
		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
			us->srb->result = DID_ABORT << 16;
			goto SkipForAbort;
		}

		scsi_unlock(host);

		
		 
		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
			US_DEBUGP("UNKNOWN data direction\n");
			us->srb->result = DID_ERROR << 16;
		}

		
		else if (us->srb->device->id && 
				!(us->fflags & US_FL_SCM_MULT_TARG)) {
			US_DEBUGP("Bad target number (%d:%d)\n",
				  us->srb->device->id, us->srb->device->lun);
			us->srb->result = DID_BAD_TARGET << 16;
		}

		else if (us->srb->device->lun > us->max_lun) {
			US_DEBUGP("Bad LUN (%d:%d)\n",
				  us->srb->device->id, us->srb->device->lun);
			us->srb->result = DID_BAD_TARGET << 16;
		}

		else if ((us->srb->cmnd[0] == INQUIRY) &&
			    (us->fflags & US_FL_FIX_INQUIRY)) {
			unsigned char data_ptr[36] = {
			    0x00, 0x80, 0x02, 0x02,
			    0x1F, 0x00, 0x00, 0x00};

			US_DEBUGP("Faking INQUIRY command\n");
			fill_inquiry_response(us, data_ptr, 36);
			us->srb->result = SAM_STAT_GOOD;
		}

		
		else {
			US_DEBUG(usb_stor_show_command(us->srb));
			us->proto_handler(us->srb, us);
			usb_mark_last_busy(us->pusb_dev);
		}

		
		scsi_lock(host);

		
		if (us->srb->result != DID_ABORT << 16) {
			US_DEBUGP("scsi cmd done, result=0x%x\n", 
				   us->srb->result);
			us->srb->scsi_done(us->srb);
		} else {
			SkipForAbort:
			US_DEBUGP("scsi command aborted\n");
		}

		/* */
		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
			complete(&(us->notify));

			
			clear_bit(US_FLIDX_ABORTING, &us->dflags);
			clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
		}

		
		us->srb = NULL;
		scsi_unlock(host);

		/
		mutex_unlock(&us->dev_mutex);
	} 
예제 #7
0
/*
 * Transport for the Freecom USB/IDE adaptor.
 *
 */
static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
{
	struct freecom_cb_wrap *fcb;
	struct freecom_status  *fst;
	unsigned int ipipe, opipe;		/* We need both pipes. */
	int result;
	unsigned int partial;
	int length;

	fcb = (struct freecom_cb_wrap *) us->iobuf;
	fst = (struct freecom_status *) us->iobuf;

	US_DEBUGP("Freecom TRANSPORT STARTED\n");

	/* Get handles for both transports. */
	opipe = us->send_bulk_pipe;
	ipipe = us->recv_bulk_pipe;

	/* The ATAPI Command always goes out first. */
	fcb->Type = FCM_PACKET_ATAPI | 0x00;
	fcb->Timeout = 0;
	memcpy (fcb->Atapi, srb->cmnd, 12);
	memset (fcb->Filler, 0, sizeof (fcb->Filler));

	US_DEBUG(pdump (srb->cmnd, 12));

	/* Send it out. */
	result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
			FCM_PACKET_LENGTH, NULL);

	/* The Freecom device will only fail if there is something wrong in
	 * USB land.  It returns the status in its own registers, which
	 * come back in the bulk pipe. */
	if (result != USB_STOR_XFER_GOOD) {
		US_DEBUGP ("freecom transport error\n");
		return USB_STOR_TRANSPORT_ERROR;
	}

	/* There are times we can optimize out this status read, but it
	 * doesn't hurt us to always do it now. */
	result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
			FCM_STATUS_PACKET_LENGTH, &partial);
	US_DEBUGP("foo Status result %d %u\n", result, partial);
	if (result != USB_STOR_XFER_GOOD)
		return USB_STOR_TRANSPORT_ERROR;

	US_DEBUG(pdump ((void *) fst, partial));

	/* The firmware will time-out commands after 20 seconds. Some commands
	 * can legitimately take longer than this, so we use a different
	 * command that only waits for the interrupt and then sends status,
<<<<<<< HEAD
	 * without having to send a new ATAPI command to the device.
=======
	 * without having to send a new ATAPI command to the device. 
>>>>>>> 296c66da8a02d52243f45b80521febece5ed498a
	 *
	 * NOTE: There is some indication that a data transfer after a timeout
	 * may not work, but that is a condition that should never happen.
	 */
	while (fst->Status & FCM_STATUS_BUSY) {
		US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n");
		US_DEBUGP("fst->Status is %x\n", fst->Status);

		/* Get the status again */
		fcb->Type = FCM_PACKET_STATUS;
		fcb->Timeout = 0;
		memset (fcb->Atapi, 0, sizeof(fcb->Atapi));
		memset (fcb->Filler, 0, sizeof (fcb->Filler));

		/* Send it out. */
		result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
				FCM_PACKET_LENGTH, NULL);

		/* The Freecom device will only fail if there is something
		 * wrong in USB land.  It returns the status in its own
		 * registers, which come back in the bulk pipe.
		 */
		if (result != USB_STOR_XFER_GOOD) {
			US_DEBUGP ("freecom transport error\n");
			return USB_STOR_TRANSPORT_ERROR;
		}

		/* get the data */
		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
				FCM_STATUS_PACKET_LENGTH, &partial);

		US_DEBUGP("bar Status result %d %u\n", result, partial);
		if (result != USB_STOR_XFER_GOOD)
			return USB_STOR_TRANSPORT_ERROR;

		US_DEBUG(pdump ((void *) fst, partial));
	}

	if (partial != 4)
		return USB_STOR_TRANSPORT_ERROR;
	if ((fst->Status & 1) != 0) {
		US_DEBUGP("operation failed\n");
		return USB_STOR_TRANSPORT_FAILED;
	}

	/* The device might not have as much data available as we
	 * requested.  If you ask for more than the device has, this reads
	 * and such will hang. */
	US_DEBUGP("Device indicates that it has %d bytes available\n",
			le16_to_cpu (fst->Count));
	US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb));

	/* Find the length we desire to read. */
	switch (srb->cmnd[0]) {
<<<<<<< HEAD
	case INQUIRY:
	case REQUEST_SENSE:	/* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
	case MODE_SENSE:
	case MODE_SENSE_10:
		length = le16_to_cpu(fst->Count);
		break;
	default:
		length = scsi_bufflen(srb);
=======
		case INQUIRY:
예제 #8
0
static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
{
	struct freecom_cb_wrap *fcb;
	struct freecom_status  *fst;
	unsigned int ipipe, opipe;		
	int result;
	unsigned int partial;
	int length;

	fcb = (struct freecom_cb_wrap *) us->iobuf;
	fst = (struct freecom_status *) us->iobuf;

	US_DEBUGP("Freecom TRANSPORT STARTED\n");

	
	opipe = us->send_bulk_pipe;
	ipipe = us->recv_bulk_pipe;

	
	fcb->Type = FCM_PACKET_ATAPI | 0x00;
	fcb->Timeout = 0;
	memcpy (fcb->Atapi, srb->cmnd, 12);
	memset (fcb->Filler, 0, sizeof (fcb->Filler));

	US_DEBUG(pdump (srb->cmnd, 12));

	
	result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
			FCM_PACKET_LENGTH, NULL);

	if (result != USB_STOR_XFER_GOOD) {
		US_DEBUGP ("freecom transport error\n");
		return USB_STOR_TRANSPORT_ERROR;
	}

	result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
			FCM_STATUS_PACKET_LENGTH, &partial);
	US_DEBUGP("foo Status result %d %u\n", result, partial);
	if (result != USB_STOR_XFER_GOOD)
		return USB_STOR_TRANSPORT_ERROR;

	US_DEBUG(pdump ((void *) fst, partial));

	while (fst->Status & FCM_STATUS_BUSY) {
		US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n");
		US_DEBUGP("fst->Status is %x\n", fst->Status);

		
		fcb->Type = FCM_PACKET_STATUS;
		fcb->Timeout = 0;
		memset (fcb->Atapi, 0, sizeof(fcb->Atapi));
		memset (fcb->Filler, 0, sizeof (fcb->Filler));

		
		result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
				FCM_PACKET_LENGTH, NULL);

		if (result != USB_STOR_XFER_GOOD) {
			US_DEBUGP ("freecom transport error\n");
			return USB_STOR_TRANSPORT_ERROR;
		}

		
		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
				FCM_STATUS_PACKET_LENGTH, &partial);

		US_DEBUGP("bar Status result %d %u\n", result, partial);
		if (result != USB_STOR_XFER_GOOD)
			return USB_STOR_TRANSPORT_ERROR;

		US_DEBUG(pdump ((void *) fst, partial));
	}

	if (partial != 4)
		return USB_STOR_TRANSPORT_ERROR;
	if ((fst->Status & 1) != 0) {
		US_DEBUGP("operation failed\n");
		return USB_STOR_TRANSPORT_FAILED;
	}

	US_DEBUGP("Device indicates that it has %d bytes available\n",
			le16_to_cpu (fst->Count));
	US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb));

	
	switch (srb->cmnd[0]) {
	case INQUIRY:
	case REQUEST_SENSE:	
	case MODE_SENSE:
	case MODE_SENSE_10:
		length = le16_to_cpu(fst->Count);
		break;
	default:
		length = scsi_bufflen(srb);
	}

	
	if (length > scsi_bufflen(srb)) {
		length = scsi_bufflen(srb);
		US_DEBUGP("Truncating request to match buffer length: %d\n", length);
	}


	switch (us->srb->sc_data_direction) {
	case DMA_FROM_DEVICE:
		
		if (!length)
			break;
		if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
			US_DEBUGP("SCSI wants data, drive doesn't have any\n");
			return USB_STOR_TRANSPORT_FAILED;
		}
		result = freecom_readdata (srb, us, ipipe, opipe, length);
		if (result != USB_STOR_TRANSPORT_GOOD)
			return result;

		US_DEBUGP("FCM: Waiting for status\n");
		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
				FCM_PACKET_LENGTH, &partial);
		US_DEBUG(pdump ((void *) fst, partial));

		if (partial != 4 || result > USB_STOR_XFER_SHORT)
			return USB_STOR_TRANSPORT_ERROR;
		if ((fst->Status & ERR_STAT) != 0) {
			US_DEBUGP("operation failed\n");
			return USB_STOR_TRANSPORT_FAILED;
		}
		if ((fst->Reason & 3) != 3) {
			US_DEBUGP("Drive seems still hungry\n");
			return USB_STOR_TRANSPORT_FAILED;
		}
		US_DEBUGP("Transfer happy\n");
		break;

	case DMA_TO_DEVICE:
		
		if (!length)
			break;
		
		result = freecom_writedata (srb, us, ipipe, opipe, length);
		if (result != USB_STOR_TRANSPORT_GOOD)
			return result;

		US_DEBUGP("FCM: Waiting for status\n");
		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
				FCM_PACKET_LENGTH, &partial);

		if (partial != 4 || result > USB_STOR_XFER_SHORT)
			return USB_STOR_TRANSPORT_ERROR;
		if ((fst->Status & ERR_STAT) != 0) {
			US_DEBUGP("operation failed\n");
			return USB_STOR_TRANSPORT_FAILED;
		}
		if ((fst->Reason & 3) != 3) {
			US_DEBUGP("Drive seems still hungry\n");
			return USB_STOR_TRANSPORT_FAILED;
		}

		US_DEBUGP("Transfer happy\n");
		break;


	case DMA_NONE:
		
		break;

	default:
		
		US_DEBUGP ("freecom unimplemented direction: %d\n",
				us->srb->sc_data_direction);
		
		return USB_STOR_TRANSPORT_FAILED;
		break;
	}

	return USB_STOR_TRANSPORT_GOOD;
}