📄 usbuhcdscheduleqsupport.c
字号:
/* usbUhcdScheduleQSupport.c - USB UHCD HCD schedule queue support *//* Copyright 2004-2005 Wind River Systems, Inc. This software includes software licensed to Wind River Systems, Inc. by Wipro, Ltd. Wind River licensees may use this software according to the terms of their Wind River license agreement(s) applicable to this software.*//*Modification history--------------------01i,18may05,mta Fix for bug while updating DWORD0 of QueueHead01h,28mar05,pdg non-PCI changes01g,02mar05,ami SPR #106383 (Max UHCI Host Controller Issue)01f,25feb05,mta SPR 10627601e,15oct04,ami Refgen Changes01d,05oct04,mta SPR100704- Removal of floating point math01c,28jul03,mat Endian related changes01b,26jun03,mat changing the code to WRS standards.01a,25apr03,ram written.*//*DESCRIPTIONThis file contains functions which provide support to theSchedule and Queue management module.INCLUDE FILES: usb2/usbOsal.h, usb2/usbHst.h, usb2/BusAbstractionLayer.h,usb2/usbUhci.h, usbPciLib.h, usb2/usbUhcdScheduleQueue.h,usb2/usbUhcdScheduleQSupport.h, usb2/usbUhcdCommon.h,usb2/usbUhcdSupport.h*//*INTERNAL ******************************************************************************* * Filename : usbUhcdScheduleQSupport.c * * Copyright : * * THE COPYRIGHT IN THE CONTENTS OF THIS SOFTWARE VEST WITH WIPRO * LIMITED A COMPANY INCORPORATED UNDER THE LAWS OF INDIA AND HAVING * ITS REGISTERED OFFICE AT DODDAKANNELLI SARJAPUR ROAD BANGALORE * 560 035. DISTRIBUTION OR COPYING OF THIS SOFTWARE BY * ANY INDIVIDUAL OR ENTITY OTHER THAN THE ADDRESSEE IS STRICTLY * PROHIBITED AND MAY INCUR LEGAL LIABILITY. IF YOU ARE NOT THE * ADDRESSEE PLEASE NOTIFY US IMMEDIATELY BY PHONE OR BY RETURN EMAIL. * THE ADDRESSEE IS ADVISED TO MAINTAIN THE PROPRIETARY INTERESTS OF * THIS COPYRIGHT AS PER APPLICABLE LAWS. * * * Description : This file contains functions which provide support * to the Schedule and Queue management module. * * ******************************************************************************//* includes */#include "usb2/usbOsal.h"#include "usb2/usbHst.h"#include "usb2/BusAbstractionLayer.h"#include "usb2/usbUhci.h"#include "usbPciLib.h"#include "usb2/usbUhcdScheduleQueue.h"#include "usb2/usbUhcdScheduleQSupport.h"#include "usb2/usbUhcdCommon.h"#include "usb2/usbUhcdSupport.h"/* forward declarations *//* External global variables - Start *//* Pointer to the global array of HOst controller structures.*/extern PUHCD_DATA *g_pUHCDData;/* External global variables - End *//***************************************************************************** usbUhcdFormEmptyTd - forms an empty Transfer Descriptor** This routine forms an empty Transfer Descriptor.** RETURNS: NULL if creation fails* * ERRNO:* None.** \NOMANUAL*/USB_UHCD_TD *usbUhcdFormEmptyTd ( UINT32 uPipeHandle ) { /* To hold the actual address returned by malloc (non-alligned) */ VOID *allocatedMem = NULL; /* To hold the pointer to the TD */ USB_UHCD_TD *td = NULL; /* * To hold the last 4 bits of the allocated address. This is used to check * whether the address is 16 byte alligned */ UINT8 offset = 0; UINT32 ctlSts = 0; UINT32 token = 0; USB_UHCD_HCD_PIPE *targetPipe = (USB_UHCD_HCD_PIPE *) uPipeHandle; /* * Allocate memory for the TD. * An additional 16 bytes are also allocated * keeping in view of the 16 byte allignment */ allocatedMem = OS_MALLOC( sizeof(USB_UHCD_TD)+16); /* Check if memory allocation is successful */ if (allocatedMem == NULL) { USB_UHCD_LOG_ERROR_MESSAGE("Memory allocation failed : TD\n"); return(NULL); } /* Store the last 4 bits of the allocated memory address */ offset = ((UINT32)allocatedMem) & 0x0F; /* * If the offset value is 0, then the allocated memory is alligned * to 16 bytes. Else it is not alligned */ if (offset != 0) { /* Allign the address to 16 byte boundry */ td = (USB_UHCD_TD *) ((UCHAR *)allocatedMem + (0x10 - offset)); } /* If alligned use the same address */ else { td = ( USB_UHCD_TD *) allocatedMem; } /* Fill the TD elements with 0 */ OS_MEMSET ((VOID *) td, 0, sizeof (USB_UHCD_TD) ); /* TD at this point is 16 byte alligned */ /* The Link pointer field in TD references a TD and not a Queue Head*/ td->dWord0Td &= ~(USBUHCD_LINK_QH); /* * Invalidate Link pointer pointer * This means that there are no more valid elements in the queue */ td->dWord0Td |=USBUHCD_LINK_TERMINATE; /* Make the TD active */ ctlSts |= USBUHCD_TDCS_STS_ACTIVE; /* If a valid pipe is passed, other fields of the TD can be populated */ if (uPipeHandle) { /* Populate the speed field */ if(targetPipe->uDeviceSpeed == LOW_SPEED) ctlSts |=USBUHCD_TDCS_LOWSPEED; else ctlSts &= ~(USBUHCD_TDCS_LOWSPEED); /* If Isochronous pipe, set iso to 1 */ if (targetPipe->endPointType == PIPE_ISOCHRONOUS) { ctlSts |= USBUHCD_TDCS_ISOCH; } /* if non isochronous populate CERR field - number of retries to be 3 */ else { /* Make the path of traversal for the HC as depth first. */ td->dWord0Td |= USBUHCD_LINK_VF; ctlSts |=USBUHCD_TDCS_ERRCTR_3ERR; } /* * Populate MAXLEN field with the * maximum packet size supported by the pipe */ if (targetPipe->uMaximumPacketSize) { token |= USBUHCD_TDTOK_MAXLEN_FMT (targetPipe->uMaximumPacketSize -1); } else { /* * write 0x7FF to Maxlen for a 0 maximum packet size * A value of 0 written would indicate a max packet size of 1. * This is done to avoid that */ token |= USBUHCD_TDTOK_MAXLEN_FMT (0x7FF); } /* Populate the endpoint number */ token |= USBUHCD_TDTOK_ENDPT_FMT (targetPipe->endPointNum); /* Populate the function address */ token |= USBUHCD_TDTOK_DEVADRS_FMT (targetPipe->deviceNum); } /* store the control status */ td->dWord1Td = ctlSts; /* store the token */ td->dWord2Td = token; /* * Store the allocated address (non-alligned) into the TD. So that * it can be used while freeing */ td->offsetForFreeing = ((UCHAR*)td - (UCHAR *)allocatedMem); /* Return the pointer to the alligned TD address */ return td; }/* End of usbUhcdFormEmptyTd() *//***************************************************************************** usbUhcdFormEmptyQh - forms an empty Queue Head** This routine forms an empty Queue Head.** RETURNS: NULL if creation fails** ERRNO:* None.** \NOMANUAL*/USB_UHCD_QH *usbUhcdFormEmptyQh (VOID) { /* Holds the actual address returned by malloc (non-alligned) */ VOID *allocatedMem = NULL; /* To hold the pointer to the Queue head */ USB_UHCD_QH *qh = NULL; /* * To hold the last 4 bits of the allocated address * This is required to check whether the address is aligned to 16 bytes */ UINT8 offset = 0; /* * Allocate memory for the QH. * An additional 16 bytes are also allocated * keeping in view of the 16 byte allignment */ allocatedMem = OS_MALLOC( sizeof(USB_UHCD_QH) + 16); /* Check if memory allocation is successful */ if (allocatedMem == NULL) { USB_UHCD_LOG_ERROR_MESSAGE("Memory allocation fails : QH\n"); return(NULL); } /* Store the last 4 bits of the allocated memory address */ offset = ((UINT32)allocatedMem) & 0x0F; /* * If the offset value is 0, then the allocated memory is alligned * to 16 bytes. Else it is not alligned */ if (offset != 0) { /* Allign the address to 16 byte boundry */ qh = (USB_UHCD_QH *) ((UCHAR *)allocatedMem + (0x10 - offset)); } /* If alligned, use the same address */ else { qh = ( USB_UHCD_QH *) allocatedMem; } /* Fill the Queue head memory with 0 */ OS_MEMSET((VOID *) qh, 0, sizeof (USB_UHCD_QH) ); /* qh at this point is 16 byte alligned */ /* Populate the fields of the QH */ /* * Make the link pointer invalid * This is done to indicate that this is the last QH in the schedule */ qh->dWord0Qh |= USBUHCD_LINK_TERMINATE; qh->dWord1Qh |= USBUHCD_LINK_TERMINATE; /* * The item referenced by the Queue Head link pointer * (mentioned in DWORD0) is a QH */ qh->dWord0Qh |= USBUHCD_LINK_QH; /* * The item referenced by the Queue element link pointer * (mentioned in DWORD1) is a TD */ qh->dWord1Qh &= ~(USBUHCD_LINK_QH); /* * Store the allocated address( non-alligned ) into the QH. So that * it can be used while freeing */ qh->offsetForFreeing = ((UCHAR*)qh - (UCHAR*)allocatedMem); /* Return the pointer to the QH */ return qh; }/* End of usbUhcdFormEmptyQh () *//***************************************************************************** usbUhcdFindLinkForQh - find the index of the next node in the list** This routine finds the index of the next node in the list.** RETURNS: 0 if node not found** ERRNO:* None.* * \NOMANUAL*/INT32 usbUhcdFindLinkForQh ( INT32 n ) { /* To hold the number of elements in the tree till this point */ INT32 numElement = 0; /* * To hold the level(polling interval supported by the HCD) * of the node indicated by 'n' */ INT32 level = 0; /* To hold the index of the first QH in this level */ INT32 first = 0; /* To hold the index of the first QH in the next lower level */ INT32 firstPrev = 0; /* To hold the index of the middle QH in the present level */ INT32 mid = 0; /* If paramenter is -Ve or 0, it is an error */ if (n <= 0) { USB_UHCD_LOG_ERROR_MESSAGE("Entered Index is Invalid\n"); return(-1); } /* As this is an index, add 1 to get the number of nodes till this point */ numElement = n + 1; /* Determine the level which contains the present QH */ level = usbUhciLog2(numElement) ; /* Determine the index of the 1st QH at this level */ first = (INT32) 1 << level; /* Determine the index of the 1st QH at the next lower level */ firstPrev = first / 2; /* Determine the index of the middle QH in the present level */ mid = first + firstPrev; /* If numElement is in the upper half, return * firstPrev - 1 + (numElement - first) */ if (numElement < mid) { return(firstPrev - 1 + (numElement - first)); } /* If N is in the bottom half, return firstPrev - 1 + (N - mid) */ else { return(firstPrev - 1 + (numElement - mid) ); } }/* End of usbUhcdFindLinkForQh () *//***************************************************************************** usbUhcdFindQlinkToTree - determines the index in periodic tree** This function is used to determine the Index into the periodic tree * which, the Nth entry of the frame list must point to. We have a 1024 * entries in the frame list and a 128 leafed tree. Thus every 128th* entry of the frame list points to the same point of the periodic tree** RETURNS: 0 if index not found** ERRNO:* None.** \NOMANUAL*/INT32 usbUhcdFindQlinkToTree (
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -