📄 itdptd.c
字号:
qha_free(qha_cache, first_itd);
urb->hcpriv = 0;
return;
}/* phcd_iso_itd_free_list */
/*
* phcd_submit_iso - ISO transfer URB submit routine
*
* phci_hcd *hcd
* - Main host controller driver structure
* struct urb *urb
* - USB Request Block, contains information regarding the type and how much data
* is requested to be transferred.
* unsigned long *status
* - Variable provided by the calling routine that will contain the status of the
* phcd_submit_iso actions
*
* API Description
* This is mainly responsible for:
* - Allocating memory for the endpoint information structure (pQHead_st)
* - Requesting for bus bandwidth from the USB core
* - Allocating and initializing Payload and PTD memory
*/
unsigned long phcd_submit_iso( phci_hcd *hcd,
struct usb_host_endpoint *ep,
struct urb *urb,
unsigned long *status
)
{
struct _periodic_list *periodic_list;
struct hcd_dev *dev;
struct ehci_qh *qhead;
struct ehci_itd *itd, *prev_itd;
struct list_head *itd_list;
unsigned long ep_in, max_pkt, mult;
unsigned long bus_time, high_speed, start_frame;
unsigned long flags, packets;
iso_dbg(ISO_DBG_ENTRY, "phcd_submit_iso Entry\n");
/* Local variable initialization */
high_speed = 0;
periodic_list = &hcd->periodic_list[0];
dev = (struct hcd_dev *) bus_to_hcd(urb->dev->bus);
urb->hcpriv = (void *) 0;
prev_itd = (struct ehci_itd *) 0;
itd = (struct ehci_itd *) 0;
start_frame = 0;
ep_in = usb_pipein(urb->pipe);
/*
* Take the endpoint, if there is still no memory allocated
* for it allocate some and indicate this is for ISO.
*/
qhead = ep->hcpriv;
if(!qhead)
{
/*
* TO DO: Check who free this up, I did not observed this
* freed up
*/
qhead = phci_hcd_qh_alloc(hcd);
if(qhead == 0)
{
iso_dbg(ISO_DBG_ERR,"[phcd_submit_iso Error]: Not enough memory\n");
return -ENOMEM;
}
qhead->type = TD_PTD_BUFF_TYPE_ISTL;
ep->hcpriv = qhead;
} /* if(!qhead) */
/*
* Get the number of additional packets that the endpoint can support during a
* single microframe.
*/
max_pkt = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
/*
* We need to add 1 since our Multi starts with 1 instead of the USB specs defined
* zero (0).
*/
mult = 1 + ((max_pkt >> 11) & 0x3);
/* This is the actual length per for the whole transaction */
max_pkt *= mult;
/* Check bandwidth */
bus_time= 0;
if(urb->dev->speed == USB_SPEED_FULL)
{
if(urb->bandwidth == 0)
{
bus_time = usb_check_bandwidth(urb->dev, urb);
if(bus_time < 0)
{
usb_dec_dev_use(urb->dev);
*status = bus_time;
return *status;
}
}
} /*if(urb->dev->speed == USB_SPEED_FULL) */
else /*HIGH SPEED*/
{
high_speed = 1;
/*
* Calculate bustime as dictated by the USB Specs Section 5.11.3
* for high speed ISO
*/
bus_time = 633232L;
bus_time += (2083L * ((3167L + BitTime(max_pkt) * 1000L)/1000L));
bus_time = bus_time/1000L;
bus_time += BW_HOST_DELAY;
bus_time = NS_TO_US(bus_time);
}
usb_claim_bandwidth(urb->dev, urb, bus_time, 1);
/* Initialize the start split (ssplit) and complete split (csplit) variables of qhead */
if( phcd_iso_scheduling_info(hcd, qhead, max_pkt, high_speed, ep_in) < 0 )
{
iso_dbg(ISO_DBG_ERR, "[phcd_submit_iso Error]: No space available\n");
return -ENOSPC;
}
if(urb->iso_frame_desc[0].offset != 0)
{
*status = -EINVAL;
iso_dbg(ISO_DBG_ERR, "[phcd_submit_iso Error]: Invalid value\n");
return *status;
}
if(qhead->next_uframe == -1 ||
hcd->periodic_sched == 0)
{
/* Calculate the current frame number */
if(urb->transfer_flags & URB_ISO_ASAP)
start_frame = isp1761_reg_read32( hcd->dev,
hcd->regs.frameindex,
start_frame
);
else
start_frame = urb->start_frame;
INIT_LIST_HEAD(&hcd->urb_list);
/* The only valid bits of the frame index is the lower 14 bits. */
start_frame = start_frame & 0xFF;
/*
* Remove the count for the micro frame (uSOF) and just leave the
* count for the frame (SOF). Since 1 SOF is equal to 8 uSOF then
* shift right by three is like dividing it by 8 (each shift is divide by two)
*/
start_frame >>= 3;
start_frame += 2;
qhead->next_uframe = start_frame + urb->number_of_packets;
} /* if(qhead->next_uframe == -1 || hcd->periodic_sched == 0) */
else
{
/*
* The periodic frame list size is only 32 elements deep, so we need
* the frame index to be less than or equal to 32 (actually 31 if we
* start from 0)
*/
start_frame = (qhead->next_uframe) % PTD_PERIODIC_SIZE;
qhead->next_uframe = start_frame + urb->number_of_packets;
qhead->next_uframe %= PTD_PERIODIC_SIZE;
}
spin_lock_irqsave(&hcd->lock, flags);
iso_dbg(ISO_DBG_DATA,"[phcd_submit_iso]: Number of packets: %d\n", urb->number_of_packets);
iso_dbg(ISO_DBG_DATA,"[phcd_submit_iso]: Packet Length: %d\n",
urb->iso_frame_desc[0].length);
iso_dbg(ISO_DBG_DATA,"[phcd_submit_iso]: Max packet: %d\n", (int) max_pkt);
/* Make as many tds as number of packets */
for(packets = 0; packets < urb->number_of_packets; packets++)
{
/*
* Allocate memory for the ITD data structure and initialize it.
*
* This data structure follows the format of the ITD
* structure defined by the EHCI standard on the top part
* but also contains Philips specific elements in the bottom
* part
*/
itd = (struct ehci_itd *) kmalloc(sizeof(struct ehci_itd), GFP_ATOMIC);
if(!itd)
{
*status = -ENOMEM;
/* Handle ITD list cleanup */
if(urb->hcpriv)
{
phcd_iso_itd_free_list(hcd, urb, *status);
}
iso_dbg(ISO_DBG_ERR,"[phcd_submit_iso Error]: No memory available\n");
return *status;
}
memset(itd, 0, sizeof(struct ehci_itd));
INIT_LIST_HEAD(&itd->itd_list);
itd->itd_dma = cpu_to_le32(itd);
itd->urb = urb;
/*
* Indicate that this ITD is the last in the list.
*
* Also set the itd_index to TD_PTD_INV_PTD_INDEX
* (0xFFFFFFFF). This would indicate when we allocate
* a PTD that this ITD did not have a PTD allocated
* before.
*/
itd->hw_next = EHCI_LIST_END;
itd->itd_index = TD_PTD_INV_PTD_INDEX;
/* This ITD will go into this frame*/
itd->framenumber = start_frame + packets;
/* Number of the packet*/
itd->index = packets;
itd->framenumber = itd->framenumber % PTD_PERIODIC_SIZE;
itd->ssplit = qhead->ssplit;
itd->csplit = qhead->csplit;
/* Initialize the following elements of the ITS structure
* > itd->length = length; -- the size of the request
* > itd->multi = multi; -- the number of transactions for
* this EP per micro frame
* > itd->hw_bufp[0] = buf_dma; -- The base address of the buffer where
* to put the data (this base address was
* the buffer provided plus the offset)
* And then, allocating memory from the PAYLOAD memory area, where the data
* coming from the requesting party will be placed or data requested by the
* requesting party will be retrieved when it is available.
*/
*status = phcd_iso_itd_fill(hcd, itd, urb, packets);
if(*status !=0)
{
/* Handle ITD list cleanup */
if(urb->hcpriv)
{
phcd_iso_itd_free_list(hcd, urb, *status);
}
iso_dbg(ISO_DBG_ERR,"[phcd_submit_iso Error]: Error in filling up ITD\n");
return *status;
}
/*
* If this ITD is not the head/root ITD, link this ITD to the ITD
* that came before it.
*/
if(prev_itd)
prev_itd->hw_next = cpu_to_le32(itd);
prev_itd = itd;
/*
* Allocate an ISO PTD from the ISO PTD map list and
* set the equivalent bit of the allocated PTD to active
* in the bitmap so that this PTD will be included into
* the periodic schedule
*/
phcd_iso_get_itd_ptd_index(hcd, itd);
/*if we dont have any space left*/
if(itd->itd_index == TD_PTD_INV_PTD_INDEX)
{
*status = -ENOSPC;
/* Handle ITD list cleanup */
if(urb->hcpriv)
{
phcd_iso_itd_free_list(hcd, urb, *status);
}
return *status;
}
/* Insert this td into the periodic list*/
periodic_list[itd->framenumber].framenumber = itd->framenumber;
itd_list = &periodic_list[itd->framenumber].itd_head;
list_add_tail(&itd->itd_list, itd_list);
/* Inidcate that a new ITD have been scheduled */
hcd->periodic_sched++;
/* Determine if there are any ITD scheduled before this one. */
if(urb->hcpriv == 0)
urb->hcpriv = itd;
}/* for(packets = 0; packets... */
spin_unlock_irqrestore(&hcd->lock, flags);
/* Last td of current transaction*/
itd->hw_next = EHCI_LIST_END;
urb->error_count = 0;
return *status;
} /* phcd_submit_iso */
#endif /* CONFIG_ISO_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -