📄 usbuhcdschedulequeue.c
字号:
/* usbUhcdScheduleQueue.c - USB UHCD HCD schdule queue routines *//* 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--------------------01j,03mar05,mta SPR 9660401i,02mar05,ami SPR #106383 (Max UHCI Host Controller Issue)01h,25feb05,mta SPR 10627601g,15oct04,ami Refgen Changes01f,05oct04,mta SPR100704- Removal of floating point math01e,11aug04,mta Fix for print-stop-print issue with ISP158201d,03aug04,mta coverity error fixes01c,03aug04,mta Coverity error fixes01b,26jun03,mat changing the code to WRS standards.01a,25apr03,ram written.*//*DESCRIPTIONThis file contains functions which are used for transferscheduling and management.INCLUDE FILES: usb2/usbOsal.h, usb2/usbHst.h, usb2/usbUhci.h,usb2/usbUhcdCommon.h, usb2/usbUhcdScheduleQueue.h,usb2/usbUhcdSupport.h, usb2/usbUhcdScheduleQSupport.h,usb2/usbUhcdRhEmulate.h, usb/usbPciLib.h*//*INTERNAL ******************************************************************************* * Filename : UHCD_ScheduleQueue.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 are used for * transfer scheduling and management. * * ******************************************************************************//* includes */#include "usb2/usbOsal.h"#include "usb2/usbHst.h"#include "usb2/usbUhci.h"#include "usb2/usbUhcdCommon.h"#include "usb2/usbUhcdScheduleQueue.h"#include "usb2/usbUhcdSupport.h"#include "usb2/usbUhcdScheduleQSupport.h"#include "usb2/usbUhcdRhEmulate.h"#include "usb/usbPciLib.h"/* Pointer to the global array of Host controller structures.*/extern PUHCD_DATA *g_pUHCDData;/* Forward declaration of the function to process the completed TDs */void uhc_ProcessCompletedTDs (PUHCD_DATA pHCDData);/* Global variables - End *//* forward declarations */void usbUhcdMakeTDLE(UINT32 uBusIndex, PUSB_UHCD_TD td);void usbUhcdMakeQDLE(UINT32 uBusIndex, PUSB_UHCD_QH qh);void usbUhcdMakeFrameelementLE(UINT32 uBusIndex, USB_UHCD_FRAME_LIST * pframeList,UINT32 index);/***************************************************************************** usbUhcdCreateFrameList - creates frame list.** The HCD maintains - a tree of 256 elements to maintain the* bandwidth usage in every frame for the interrupt transfers.* - an array of 1024 static isochronous Transfer Descriptor elements.* This function allocates memory for the data structures and initialises* them. Also this function allocates memory for the frame list maintained* by the UHCI Host controller and initialises the list.** RETURNS: False if the frame list creation is a failure** ERRNO:* None.** \NOMANUAL*/BOOLEAN usbUhcdCreateFrameList ( PUHCD_DATA pHCDData ) { /* Temporary pointer to hold the memory allocated for an isochronous TD */ USB_UHCD_TD *itd = NULL; /* Temporary pointer to hold the memory allocated for the Queue Head */ USB_UHCD_QH *qh = NULL; /* * To hold the last few bits of the allocated memory location. * Used to check whether the allocated memory is aligned. */ UINT16 offset = 0; /* To serve as an index element */ UINT16 i = 0; /* * To hold the index of the link element in the periodic tree * maintained by the HCD. */ INT32 linkIndex = 0; /* to hold the pesudo td pointer */ VOID *allocatedMem = NULL; /* To hold the pointer to the TD */ USB_UHCD_TD *td = NULL; UINT16 offset1 = 0; UINT32 dword0 = 0; OS_LOG_MESSAGE_MEDIUM(UHCD,"usbUhcdCreateFrameList()\n",0,0,0,0); /* * The HCD maintains the following information * - A periodic tree of 256 elements to hold the bandwidth usage of * the interrupt endpoints. The tip of the periodic tree will be * pointing to the list containing the control and bulk Queue Heads. * - A periodic table which is a static array of 1024 elements with each * element in the array containing information on the bandwidth usage * of the isochronous endpoints. * Each element of the periodic table will be pointing to a leaf of * the periodic tree. * * The UCHI Host Controller maintains a frame list with each element in the * list pointing to the corresponding element of the periodic table. This * enables the Host controller to traverse the list in every frame. */ /* Allocate memory for the periodic tree */ pHCDData->usbUhcdTree = (USB_UHCD_PERIODIC_TREE *) OS_MALLOC(sizeof(USB_UHCD_PERIODIC_TREE) * 255); /* Check if memory allocation is successful */ if (pHCDData->usbUhcdTree == NULL) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Unable to allocate memory!\n",0,0,0,0); return(FALSE); } /* Allocate memory for the periodic table */ pHCDData->usbUhcdTable = (USB_UHCD_PERIODIC_TABLE *) OS_MALLOC(sizeof(USB_UHCD_PERIODIC_TABLE)*1024); /* Check if memory allocation is successful */ if (pHCDData->usbUhcdTable == NULL) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Unable to allocate memory!\n",0,0,0,0); OS_FREE(pHCDData->usbUhcdTree); return(FALSE); } /* Allocate memory for the frame list maintained by the Host controller */ pHCDData->usbUhcdFrameList = pHCDData->forFreeing = (USB_UHCD_FRAME_LIST *) OS_MALLOC(sizeof(USB_UHCD_FRAME_LIST) + 4096); /* Check if memory allocation is successful */ if (pHCDData->usbUhcdFrameList == NULL) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Unable to allocate memory!\n",0,0,0,0); OS_FREE(pHCDData->usbUhcdTable); OS_FREE(pHCDData->usbUhcdTree); return(FALSE); } /* Get the least 12 bits of the allocated memory */ offset = ((unsigned) pHCDData->usbUhcdFrameList) & 0xFFF; /* * If the lower 12 bits are not 0, * then the memory allocated is 4KB aligned */ if (offset != 0) { OS_LOG_MESSAGE_MEDIUM(UHCD,"4KB aligned memory\n",0,0,0,0); /* Allign the frame list to a 4KB boundry */ pHCDData->usbUhcdFrameList = (USB_UHCD_FRAME_LIST *) (((UCHAR *)pHCDData->usbUhcdFrameList) + 4096 - offset); } /* Fill the frame list memory allocated with 0s */ OS_MEMSET((void *) pHCDData->usbUhcdFrameList, 0, sizeof (USB_UHCD_FRAME_LIST)); /* Fill the periodic table memory allocated with 0s */ OS_MEMSET((void *) pHCDData->usbUhcdTable, 0, sizeof (USB_UHCD_PERIODIC_TABLE)*1024); /* Fill the periodic tree memory allocated with 0s */ OS_MEMSET((void *) pHCDData->usbUhcdTree, 0, sizeof (USB_UHCD_PERIODIC_TREE)*255); /* Create a control QH */ pHCDData->usbUhcdCQh = usbUhcdFormEmptyQh(); /* Create a bulk QH */ pHCDData->usbUhcdBQh = usbUhcdFormEmptyQh(); /* Create a Bandwidth Reclamation QH */ pHCDData->usbUhcdBRQh = usbUhcdFormEmptyQh(); /* allocate a pseudo TD for Bandwidth Reclamation Qh */ allocatedMem = OS_MALLOC( sizeof(USB_UHCD_TD)+16); /* Check if the memory allocation is successful */ if (pHCDData->usbUhcdCQh == NULL || pHCDData->usbUhcdBQh == NULL || pHCDData->usbUhcdBRQh == NULL || allocatedMem == NULL ) { OS_LOG_MESSAGE_MEDIUM(UHCD,"Memory allocation unsuccessful\n",0,0,0,0); OS_FREE(pHCDData->usbUhcdTable); OS_FREE(pHCDData->usbUhcdTree); UHCI_FREE(pHCDData->forFreeing); if (pHCDData->usbUhcdCQh != NULL) { UHCI_FREE((UCHAR*)pHCDData->usbUhcdCQh - pHCDData->usbUhcdCQh->offsetForFreeing); } if (pHCDData->usbUhcdBQh != NULL) { UHCI_FREE((UCHAR*)pHCDData->usbUhcdBQh - pHCDData->usbUhcdBQh->offsetForFreeing ); } if (pHCDData->usbUhcdBRQh != NULL) { UHCI_FREE((UCHAR*)pHCDData->usbUhcdBRQh - pHCDData->usbUhcdBRQh->offsetForFreeing ); } if (allocatedMem != NULL) { UHCI_FREE(allocatedMem ); } return(FALSE); } /* Store the last 4 bits of the allocated memory address */ offset1 = ((UINT32)allocatedMem) & 0x0F; /* * If the offset value is 0, then the allocated memory is alligned * to 16 bytes. Else it is not alligned */ if (offset1 != 0) { /* Allign the address to 16 byte boundry */ td = (USB_UHCD_TD *) ((UCHAR *)allocatedMem + (0x10 - offset1)); } /* 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); /* Indicate that this is not the last element in the queue */ td->dWord0Td &= ~(USBUHCD_LINK_TERMINATE); /* Make the path of traversal for the HC as depth first. */ td->dWord0Td &=~(USBUHCD_LINK_VF); /* Update the TD's link pointer */ td->dWord0Td &=~(USBUHCD_LINK_PTR_MASK); td->dWord0Td |= USBUHCD_LINK_PTR_FMT( ((unsigned) td) >> 4); td->dWord0Td = USB_UHCD_CONVERT_TO_BUS_MEM(pHCDData->busIndex,(PVOID)td->dWord0Td); usbUhcdMakeTDLE(pHCDData->busIndex, td); DMA_FLUSH(td, sizeof(USB_UHCD_TD)); /* * Store the allocated address (non-alligned) into the TD. So that * it can be used while freeing */ td->offsetForFreeing = ((UCHAR*)td - (UCHAR *)allocatedMem); /* Update the Bandwidth Reclamation Queue head */ pHCDData->usbUhcdBRQh->td = td; dword0 = 0; dword0 &= ~(USBUHCD_LINK_PTR_MASK); dword0 |= ( USBUHCD_LINK_PTR_FMT(((unsigned) td) >> 4)); dword0 &= ~(USBUHCD_LINK_TERMINATE); dword0 = USB_UHCD_CONVERT_TO_BUS_MEM(pHCDData->busIndex, (PVOID)dword0); pHCDData->usbUhcdBRQh->dWord1Qh = dword0; /* * Update the link pointers of the control QH. * ie control QH points to bulk QH */ pHCDData->usbUhcdCQh->nextQh = pHCDData->usbUhcdBQh; pHCDData->usbUhcdCQh->dWord0Qh &= ~(USBUHCD_LINK_PTR_MASK); pHCDData->usbUhcdCQh->dWord0Qh |= USBUHCD_LINK_PTR_FMT(((unsigned) pHCDData->usbUhcdBQh) >> 4); /* Make the QH as not the last element in the schedule */ pHCDData->usbUhcdCQh->dWord0Qh &= ~(USBUHCD_LINK_TERMINATE); pHCDData->usbUhcdCQh->dWord0Qh = USB_UHCD_CONVERT_TO_BUS_MEM(pHCDData->busIndex, (PVOID)pHCDData->usbUhcdCQh->dWord0Qh); /* Indicate that the element next to the control QH is a bulk QH */ pHCDData->usbUhcdCQh->dWord0Qh |= USBUHCD_LINK_QH; /* * Update the link pointers of the Bulk QH. * ie Bulk QH points to Bandwidth reclamation queue head */ pHCDData->usbUhcdBQh->nextQh = pHCDData->usbUhcdBRQh; pHCDData->usbUhcdBQh->dWord0Qh &= ~(USBUHCD_LINK_PTR_MASK); pHCDData->usbUhcdBQh->dWord0Qh |= USBUHCD_LINK_PTR_FMT(((unsigned) pHCDData->usbUhcdBRQh) >> 4); /* Make the QH as not the last element in the schedule */ pHCDData->usbUhcdBQh->dWord0Qh &= ~(USBUHCD_LINK_TERMINATE); pHCDData->usbUhcdBQh->dWord0Qh = USB_MEM_TO_PCI((PVOID)pHCDData->usbUhcdBQh->dWord0Qh); /* Indicate that the element next to the control QH is a bulk QH */ pHCDData->usbUhcdBQh->dWord0Qh |= USBUHCD_LINK_QH; usbUhcdMakeQDLE(pHCDData->busIndex, pHCDData->usbUhcdCQh); usbUhcdMakeQDLE(pHCDData->busIndex, pHCDData->usbUhcdBQh); usbUhcdMakeQDLE(pHCDData->busIndex, pHCDData->usbUhcdBRQh); DMA_FLUSH(pHCDData->usbUhcdBRQh, sizeof(USB_UHCD_QH)); /* Create the static QH of the periodic tree */ for (i = 0; i < 255; ++i) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -