コード例 #1
0
ファイル: fhci-sched.c プロジェクト: Lance0312/osdi-exercise
/* confirm submitted packet */
void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt)
{
	struct td *td;
	struct packet *td_pkt;
	struct ed *ed;
	u32 trans_len;
	bool td_done = false;

	td = fhci_remove_td_from_frame(usb->actual_frame);
	td_pkt = td->pkt;
	trans_len = pkt->len;
	td->status = pkt->status;
	if (td->type == FHCI_TA_IN && td_pkt->info & PKT_DUMMY_PACKET) {
		if ((td->data + td->actual_len) && trans_len)
			memcpy(td->data + td->actual_len, pkt->data,
			       trans_len);
		cq_put(usb->ep0->dummy_packets_Q, pkt->data);
	}

	recycle_frame(usb, pkt);

	ed = td->ed;
	if (ed->mode == FHCI_TF_ISO) {
		if (ed->td_list.next->next != &ed->td_list) {
			struct td *td_next =
			    list_entry(ed->td_list.next->next, struct td,
				       node);

			td_next->start_frame = usb->actual_frame->frame_num;
		}
		td->actual_len = trans_len;
		td_done = true;
	} else if ((td->status & USB_TD_ERROR) &&
コード例 #2
0
ファイル: fhci-sched.c プロジェクト: Lance0312/osdi-exercise
static void recycle_frame(struct fhci_usb *usb, struct packet *pkt)
{
	pkt->data = NULL;
	pkt->len = 0;
	pkt->status = USB_TD_OK;
	pkt->info = 0;
	pkt->priv_data = NULL;

	cq_put(usb->ep0->empty_frame_Q, pkt);
}
コード例 #3
0
ファイル: fhci-tds.c プロジェクト: ANFS/ANFS-kernel
/*
 * Submitting a data frame to a specified endpoint of a USB device
 * The frame is put in the driver's transmit queue for this endpoint
 *
 * Arguments:
 * usb          A pointer to the USB structure
 * pkt          A pointer to the user frame structure
 * trans_type   Transaction tyep - IN,OUT or SETUP
 * dest_addr    Device address - 0~127
 * dest_ep      Endpoint number of the device - 0~16
 * trans_mode   Pipe type - ISO,Interrupt,bulk or control
 * dest_speed   USB speed - Low speed or FULL speed
 * data_toggle  Data sequence toggle - 0 or 1
 */
u32 fhci_host_transaction(struct fhci_usb *usb,
			  struct packet *pkt,
			  enum fhci_ta_type trans_type,
			  u8 dest_addr,
			  u8 dest_ep,
			  enum fhci_tf_mode trans_mode,
			  enum fhci_speed dest_speed, u8 data_toggle)
{
	struct endpoint *ep = usb->ep0;
	struct usb_td __iomem *td;
	u16 extra_data;
	u16 td_status;

	fhci_usb_disable_interrupt(usb);
	/* start from the next BD that should be filled */
	td = ep->empty_td;
	td_status = in_be16(&td->status);

	if (td_status & TD_R && in_be16(&td->length)) {
		/* if the TD is not free */
		fhci_usb_enable_interrupt(usb);
		return -1;
	}

	/* get the next TD in the ring */
	ep->empty_td = next_bd(ep->td_base, ep->empty_td, td_status);
	fhci_usb_enable_interrupt(usb);
	pkt->priv_data = td;
	out_be32(&td->buf_ptr, virt_to_phys(pkt->data));
	/* sets up transaction parameters - addr,endp,dir,and type */
	extra_data = (dest_ep << TD_ENDP_SHIFT) | dest_addr;
	switch (trans_type) {
	case FHCI_TA_IN:
		extra_data |= TD_TOK_IN;
		break;
	case FHCI_TA_OUT:
		extra_data |= TD_TOK_OUT;
		break;
	case FHCI_TA_SETUP:
		extra_data |= TD_TOK_SETUP;
		break;
	}
	if (trans_mode == FHCI_TF_ISO)
		extra_data |= TD_ISO;
	out_be16(&td->extra, extra_data);

	/* sets up the buffer descriptor */
	td_status = ((td_status & TD_W) | TD_R | TD_L | TD_I | TD_CNF);
	if (!(pkt->info & PKT_NO_CRC))
		td_status |= TD_TC;

	switch (trans_type) {
	case FHCI_TA_IN:
		if (data_toggle)
			pkt->info |= PKT_PID_DATA1;
		else
			pkt->info |= PKT_PID_DATA0;
		break;
	default:
		if (data_toggle) {
			td_status |= TD_PID_DATA1;
			pkt->info |= PKT_PID_DATA1;
		} else {
			td_status |= TD_PID_DATA0;
			pkt->info |= PKT_PID_DATA0;
		}
		break;
	}

	if ((dest_speed == FHCI_LOW_SPEED) &&
	    (usb->port_status == FHCI_PORT_FULL))
		td_status |= TD_LSP;

	out_be16(&td->status, td_status);

	/* set up buffer length */
	if (trans_type == FHCI_TA_IN)
		out_be16(&td->length, pkt->len + CRC_SIZE);
	else
		out_be16(&td->length, pkt->len);

	/* put the frame to the confirmation queue */
	cq_put(&ep->conf_frame_Q, pkt);

	if (cq_howmany(&ep->conf_frame_Q) == 1)
		out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO);

	return 0;
}
コード例 #4
0
ファイル: fhci-tds.c プロジェクト: ANFS/ANFS-kernel
/*
 * create the endpoint structure
 *
 * arguments:
 * usb		A pointer to the data structure of the USB
 * data_mem	The data memory partition(BUS)
 * ring_len	TD ring length
 */
u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem,
			   u32 ring_len)
{
	struct endpoint *ep;
	struct usb_td __iomem *td;
	unsigned long ep_offset;
	char *err_for = "enpoint PRAM";
	int ep_mem_size;
	u32 i;

	/* we need at least 3 TDs in the ring */
	if (!(ring_len > 2)) {
		fhci_err(usb->fhci, "illegal TD ring length parameters\n");
		return -EINVAL;
	}

	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
	if (!ep)
		return -ENOMEM;

	ep_mem_size = ring_len * sizeof(*td) + sizeof(struct fhci_ep_pram);
	ep_offset = cpm_muram_alloc(ep_mem_size, 32);
	if (IS_ERR_VALUE(ep_offset))
		goto err;
	ep->td_base = cpm_muram_addr(ep_offset);

	/* zero all queue pointers */
	if (cq_new(&ep->conf_frame_Q, ring_len + 2) ||
	    cq_new(&ep->empty_frame_Q, ring_len + 2) ||
	    cq_new(&ep->dummy_packets_Q, ring_len + 2)) {
		err_for = "frame_queues";
		goto err;
	}

	for (i = 0; i < (ring_len + 1); i++) {
		struct packet *pkt;
		u8 *buff;

		pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
		if (!pkt) {
			err_for = "frame";
			goto err;
		}

		buff = kmalloc(1028 * sizeof(*buff), GFP_KERNEL);
		if (!buff) {
			kfree(pkt);
			err_for = "buffer";
			goto err;
		}
		cq_put(&ep->empty_frame_Q, pkt);
		cq_put(&ep->dummy_packets_Q, buff);
	}

	/* we put the endpoint parameter RAM right behind the TD ring */
	ep->ep_pram_ptr = (void __iomem *)ep->td_base + sizeof(*td) * ring_len;

	ep->conf_td = ep->td_base;
	ep->empty_td = ep->td_base;

	ep->already_pushed_dummy_bd = false;

	/* initialize tds */
	td = ep->td_base;
	for (i = 0; i < ring_len; i++) {
		out_be32(&td->buf_ptr, 0);
		out_be16(&td->status, 0);
		out_be16(&td->length, 0);
		out_be16(&td->extra, 0);
		td++;
	}
	td--;
	out_be16(&td->status, TD_W); /* for last TD set Wrap bit */
	out_be16(&td->length, 0);

	/* endpoint structure has been created */
	usb->ep0 = ep;

	return 0;
err:
	fhci_ep0_free(usb);
	kfree(ep);
	fhci_err(usb->fhci, "no memory for the %s\n", err_for);
	return -ENOMEM;
}