?? isp1161hc.cpp
字號:
/*++
Copyright (c) 2000 Philips Electronic Company, APIC
Module Name:
Isp1161Hc.cpp
Abstract:
This file implements the USB host controller driver for the
Philips ISP1161 HCI interface.
Author:
Zou Ying
Notes: Intial code released by zou ying for the x86 platform.
--*/
// C4100 unrefrenced formal parameter
// C4101 unrefrenced local variable
// C4705 statement has no effect
// C4706 assignment in conditional
#pragma warning (3 : 4100 4101 4705 4706)
#include <windows.h>
extern "C" { // nkintr.h now contains this, but autopc doesn't have the latest,
// so include here as well for now.
#include <nkintr.h>
}
#include <ceddk.h>
#include <phcdddsi.h>
#include "hcdi.h"
#include "globals.hpp"
#include "mem.hpp"
#include "hub.hpp"
#include "phcdinc.hpp"
#include "phcd.hpp"
#define ISP1161DBG 0
#define ISPDATADBG 0
#define ISPEP 0
DWORD CPhcd::ServiceList(PULONG pInterrupts)
{
pInterrupts = pInterrupts;
ServiceITLList();
ServiceATLList();
return 0;
}
DWORD CPhcd::ServiceITLList()
{
ULONG ulHcControlValue = READ_REGISTER_ULONG(HcControl(m_regBase));
if( ulHcControlValue & gcHcControlPLEmask)
{
ULONG ulIsoListEnabled = ulHcControlValue & gcHcControlIEmask;
if (ulIsoListEnabled)
{
ServiceEndpoint(gcEndptTypeIsochronous);
}
}
//if m_TdsPutToITLFirstIndex is NOT 0
if ( m_TdsPutToITLFirstIndex != 0 || m_TdsPutToITLSecondIndex != 0 )
{
ServiceITLTransferDescriptor(m_TdsPutToITLFirstIndex, m_TdsPutToITLFirst);
ServiceITLTransferDescriptor(m_TdsPutToITLSecondIndex, m_TdsPutToITLSecond);
}
return 0;
}
DWORD CPhcd::ServiceATLList()
{
/*=========================================================
We first check whether m_bReDump is TRUE or not. It it is,
that means, we can't server list, cause right now, some
PTD needs to be dumped again. We will call ReDump to dump
the PTDs. If m_bReDump is FALSE, we will begin to process
each list.
==========================================================*/
if (m_bReDump == TRUE)
{
ReDumpPtd();
m_bReDump = FALSE;
return 0;
}
/*========================================================
This ServiceList will be called every 1ms. It is possible
we can't dump PTD to ATL buffer, cause if you dump PTD
in the previous ms, hardware will be busy to process
ATL buffer in this ms. So, in this frame, you should
lave the buffer as it is. We use a variable m_ATLBeingReadOut
to record whether ATL buffer is busy or free. If it is
FALSE, we can ServiceList. If not, we will leave this
routine. This variable will be set to TRUE in IsTDComplete
==========================================================*/
if ( m_ATLBeingReadOut == TRUE)
return 0;
//Begin check lists.
ULONG ulHcControlValue = 0;
ulHcControlValue = READ_REGISTER_ULONG(HcControl(m_regBase));
// Porcess Perodic List
if( ulHcControlValue & gcHcControlPLEmask)
{
uFrameNumber = *HccaFrameNumber(m_pHcca);
ULONG paCur = *(HccaInterrupt(m_pHcca, (uFrameNumber & 0x1F)));
if ( paCur)
{
SEndpointDescriptor* pCur = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
//OK, here is the first endpoint, it can't be ISO, so
//Service Interrupt endpoint directly.
ServiceEndpoint(gcEndptTypeInterrupt);
}
}
//Process Control List
if( ulHcControlValue & gcHcControlCLEmask )
{
m_ControlBulkRatio = (ulHcControlValue & gcHcControlCBSRmask) + 1;
while (m_ControlBulkRatio)
{
ULONG paCtrlCurEd = READ_REGISTER_ULONG(HcControlCurrentEd(m_regBase));
if (paCtrlCurEd)
{
DEBUGMSG(ISP1161DBG,
(TEXT("PHCD:: Processing Control List,when ControlCurrentEdpoint is set\r\n")));
ServiceEndpoint(gcEndptTypeControl);
//should check frame time left
}
else
{
ULONG dwValue = READ_REGISTER_ULONG(HcCommandStatus(m_regBase));
if (dwValue & gcHcCommandStatusCLFmask)
{
ULONG paCtrlHeadEd;
paCtrlHeadEd = READ_REGISTER_ULONG(HcControlHeadEd(m_regBase));
WRITE_REGISTER_ULONG(HcControlCurrentEd(m_regBase), paCtrlHeadEd);
//OHCI spec Page 96
ClearControlListFilledBit(m_regBase);
ULONG paCtrlCurEd = READ_REGISTER_ULONG(HcControlCurrentEd(m_regBase));
if (paCtrlCurEd)
{
DEBUGMSG(ISP1161DBG,
(TEXT("PHCD:: Processing Control List,when ControlHeadEdpoint is set\r\n")));
ServiceEndpoint(gcEndptTypeControl);
//should check frame time left
}
}
}
m_ControlBulkRatio--;
}
}
//Process Bulk List
if( ulHcControlValue & gcHcControlBLEmask)
{
ULONG paBulkCurEd = READ_REGISTER_ULONG(HcBulkCurrentEd(m_regBase));
if (paBulkCurEd )
{
DEBUGMSG(ISP1161DBG,
(TEXT("PHCD:: Processing Bulk List,when BulkCurrentEdpoint is set\r\n")));
ServiceEndpoint(gcEndptTypeBulk);
}
else
{
ULONG dwValue = READ_REGISTER_ULONG(HcCommandStatus(m_regBase));
if (dwValue & gcHcCommandStatusBLFmask)
{
ULONG paBulkHeadEd;
paBulkHeadEd = READ_REGISTER_ULONG(HcBulkHeadEd(m_regBase));
WRITE_REGISTER_ULONG(HcBulkCurrentEd(m_regBase), paBulkHeadEd);
//OHCI spec Page 96
ClearBulkListFilledBit(m_regBase);
ULONG paBulkCurEd = READ_REGISTER_ULONG(HcBulkCurrentEd(m_regBase));
if (paBulkCurEd)
{
DEBUGMSG(ISP1161DBG,
(TEXT("PHCD:: Processing Bulk List,when BulkHeadEdpoint is set\r\n")));
ServiceEndpoint(gcEndptTypeBulk);
//should check frame time left
}
}
}
}
/*======================================================
We have prepared all the TDs that should be dumped to
ATL buffer, next fire ServiceTransferDescriptor
=======================================================*/
if ( m_TdsPutToATLIndex != 0)
ServiceATLTransferDescriptor();
return (0);
}
void CPhcd::ServiceEndpoint(UINT dwEndpointType)
{
SEndpointDescriptor* pCurEPDescriptor;
ULONG paCur;
ULONG paTd;
int i=0;
/*=======================================================
First, calculate how many PTDs we should prepare
/=======================================================*/
switch(dwEndpointType)
{
case gcEndptTypeControl:
paCur = READ_REGISTER_ULONG(HcControlCurrentEd(m_regBase));
while ( paCur != 0)
{
pCurEPDescriptor = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
if (pCurEPDescriptor->bfSkip) //Don't forget halt bit.
{
paCur = pCurEPDescriptor->paNextEd;
continue;
}
paTd = (pCurEPDescriptor->paTdQueueHead & gcEdTdQueueHeadMask);
if( (paTd != gcStaticEdIdentifier) && (paTd != pCurEPDescriptor->paTdQueueTail))
{
/*=======================================================
This variable records how many times Endpoint is
services, which means, how many TDs are supposed to
be put into the list.
/=======================================================*/
m_EdpointServicedOne1ms++;
/*===============================================================/
Put the TD which will be processed to m_TdsPutToATL[] buffer
/===============================================================*/
m_TdsPutToATL[m_TdsPutToATLIndex] = pCurEPDescriptor->paTdQueueHead;
m_TdsPutToATLIndex++;
//OHCI spec Page 98
SetControlListFilledBit(m_regBase);
/*================================================================
We have recorded the PTD that will be processed and are going to
jump out of this loop. At this time, we should also update CuurentEd
to the next ed.
==================================================================*/
paCur = pCurEPDescriptor->paNextEd;
WRITE_REGISTER_ULONG(HcControlCurrentEd(m_regBase), paCur);
break;
}
paCur = pCurEPDescriptor->paNextEd;
WRITE_REGISTER_ULONG(HcControlCurrentEd(m_regBase), paCur);
}
break;
case gcEndptTypeBulk:
paCur = READ_REGISTER_ULONG(HcBulkCurrentEd(m_regBase));
while ( paCur != 0)
{
pCurEPDescriptor = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
if (pCurEPDescriptor->bfSkip) //Don't forget halt bit.
{
paCur = pCurEPDescriptor->paNextEd;
continue;
}
paTd = (pCurEPDescriptor->paTdQueueHead & gcEdTdQueueHeadMask);
if ( paTd != gcStaticEdIdentifier && paTd != pCurEPDescriptor->paTdQueueTail )
{
m_EdpointServicedOne1ms++;
/*=====================================================================/
Put the TD which will be processed to m_TdsPutToATL[] buffer
/=====================================================================*/
m_TdsPutToATL[m_TdsPutToATLIndex] = pCurEPDescriptor->paTdQueueHead;
m_TdsPutToATLIndex++;
//OHCI spec Page 98
SetBulkListFilledBit(m_regBase);
paCur = pCurEPDescriptor->paNextEd; //Goes to the next
WRITE_REGISTER_ULONG(HcBulkCurrentEd(m_regBase), paCur);
break;
}
paCur = pCurEPDescriptor->paNextEd; //Goes to the next
WRITE_REGISTER_ULONG(HcBulkCurrentEd(m_regBase), paCur);
}
break;
case gcEndptTypeInterrupt:
uFrameNumber = *HccaFrameNumber(m_pHcca);
paCur = *HccaInterrupt(m_pHcca, (uFrameNumber & 0x1F));
while ( paCur != 0)
{
pCurEPDescriptor = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
if (pCurEPDescriptor->bfSkip || pCurEPDescriptor->bfIsIsochronous) //Don't forget halt bit.
{
paCur = pCurEPDescriptor->paNextEd;
continue;
}
paTd = (pCurEPDescriptor->paTdQueueHead & gcEdTdQueueHeadMask);
if ( paTd != gcStaticEdIdentifier && paTd != pCurEPDescriptor->paTdQueueTail )
{
/*=====================================================================/
Put the TD which will be processed to m_TdsPutToATL[] buffer
/=====================================================================*/
m_TdsPutToATL[m_TdsPutToATLIndex] = pCurEPDescriptor->paTdQueueHead;
m_TdsPutToATLIndex++;
}
paCur = pCurEPDescriptor->paNextEd; //Goes to the next
}
break;
case gcEndptTypeIsochronous:
uFrameNumber = *HccaFrameNumber(m_pHcca);
paCur = *HccaInterrupt(m_pHcca, (uFrameNumber & 0x1F));
while ( paCur != 0)
{
pCurEPDescriptor = (SEndpointDescriptor*)m_pobMem->PaToVa(paCur);
//We have reached to the bottom. It's possible this Endpoint
// is "skip" and not an ISO.
if (pCurEPDescriptor->bfSkip || (pCurEPDescriptor->bfIsIsochronous == 0))
{
paCur = pCurEPDescriptor->paNextEd;
continue;
}
paTd = (pCurEPDescriptor->paTdQueueHead & gcEdTdQueueHeadMask);
if ( paTd != gcStaticEdIdentifier && paTd != pCurEPDescriptor->paTdQueueTail )
{
/*=====================================================================/
Put the TD which will be processed to m_TdsPutToATLA or B[] buffer
If buffer A is empty, we put to A, If buffer B is empty,
we put to B. One more thing, by the time we put one TD to A, it is
possible this TD has already been put to B, and vice verca. So, every
time we put something to A, we check whether this TD is inside B, if
it is, we will not this TD to A anymore.
Policy updates:
The purpose of this function is to find out how many offset this ITD
may have and allocate each of them to ITLA and ITLB alternatively.
Not matter what, ITLA and ITLB contains the same ISO TD.
Well, we still need to guanrantee whether this TD is already dumped.
/=====================================================================*/
SIsochTransferDescriptor* pITd;
SIsochTransferDescriptor* pNextITd;
ULONG paNextITd;
pITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paTd);
BOOL bFirstFilledIn = FALSE;
if (m_TdsPutToITLFirstIndex == 0)
{
m_TdsPutToITLFirst[m_TdsPutToITLFirstIndex] = paTd;
m_TdsPutToITLFirstIndex++;
bFirstFilledIn = TRUE;
RETAILMSG(0,
(TEXT("PHCD::ServiceEndpoint: %d ISO TD: 0x%08X is added to ITLFirst, FrameNumber 0x%08X\r\n"),
m_TdsPutToITLFirstIndex, pCurEPDescriptor->paTdQueueHead, uFrameNumber));
}
//If First is filled in, we will choose the next.
if (bFirstFilledIn == TRUE)
{
paNextITd = pITd->paNextTd;
}
else
{
paNextITd = paTd;
}
if ( paNextITd != gcStaticEdIdentifier && paNextITd != pCurEPDescriptor->paTdQueueTail )
{
pNextITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paNextITd);
if (m_TdsPutToITLSecondIndex == 0)
{
m_TdsPutToITLSecond[m_TdsPutToITLSecondIndex] = paNextITd;
m_TdsPutToITLSecondIndex++;
RETAILMSG(0,
(TEXT("PHCD::ServiceEndpoint: %d ISO TD: 0x%08X is added to ITLSecond, FrameNumber 0x%08X\r\n"),
m_TdsPutToITLSecondIndex, paNextITd, uFrameNumber));
}
}
}
paCur = pCurEPDescriptor->paNextEd; //Goes to the next
}
break;
default:
break;
}
}
void CPhcd::ServiceITLTransferDescriptor(ULONG m_TdsPutToITLIndex, ULONG m_TdsPutToITL[])
{
SIsochTransferDescriptor* pCurITd;
ULONG paCurITd;
ULONG m_ITLTransferLen;
uFrameNumber = *HccaFrameNumber(m_pHcca);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -