windows-nt/Source/XPSP1/NT/drivers/wdm/dvd/mini/tecra/cxfer.cpp
2020-09-26 16:20:57 +08:00

503 lines
14 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
転送管理クラス
NP2) Sachiko Yasukawa
*/
#include "stdafx.h"
#include "includes.h"
#include "classlib.h"
#ifdef TEST
IMBoardListItem *pbuffers1[20];
IMBoardListItem *pbuffers2[20];
#endif
#define ISSETDMABUFFER (m_LinerAdd == NULL) ? FALSE : ((m_PhysAdd == NULL) ? FALSE : ((m_DMABufferSize == 0) ? FALSE : TRUE))
#define ISENDTRANSFERINIT (m_pStreamObject == NULL) ? FALSE : TRUE
BOOL CTransfer::Init( void )
{
m_pStreamObject = NULL;
m_DMABufferSize = 0;
m_pTopEventList = NULL;
m_pLastEventList = NULL;
m_pTopQueuedMPEGBuffer = NULL;
m_pLastQueuedMPEGBuffer = NULL;
m_pNextTransferMPEGBuffer = NULL;
m_TopPagePoint = 1;
m_LastPagePoint = 1;
//デバッグ用
BufCount = 0;
StreamCount = 0;
return TRUE;
};
//デストラクタ もし作ったバッファが残っていたら解放する
CTransfer::~CTransfer()
{
CTransferStreamList *pDeleteStreamList;
for( ;m_pStreamObject; ){
pDeleteStreamList = m_pStreamObject;
m_pStreamObject = (CTransferStreamList *)m_pStreamObject->GetNext();
delete pDeleteStreamList;
//デバッグ用
StreamCount--;
}
ASSERT(StreamCount == 0);
// DBG_PRINTF(("CLASSLIB:StreamCount = %d\n", StreamCount));
}
//イベントオブジェクトをセットする。
BOOL CTransfer::SetSink(IMPEGBoardEvent *pEvent)
{
ASSERT(pEvent);
// 受け取ったイベントオブジェクトのNextを初期化
pEvent->SetNext( NULL );
//きっと一個しかないよ。
//イベントリストに追加する
if(m_pTopEventList == NULL)
m_pTopEventList = m_pLastEventList = (IMBoardListItem *)pEvent;//ここはキャストし直し
else{
m_pLastEventList->SetNext((IMBoardListItem *)pEvent);//ここはキャストし直し
m_pLastEventList = (IMBoardListItem *)pEvent;//ここはキャストし直し
}
return TRUE;
}
//イベントオブジェクトを削除する。Add by Nakamura
BOOL CTransfer::UnSetSink(IMPEGBoardEvent *pEvent)
{
ASSERT(pEvent);
//イベントリストから削除する。
// イベントリストが存在しない場合は、エラー
if(m_pTopEventList == NULL || m_pLastEventList == NULL )
return FALSE;
// 1つしか登録されていない場合
if( m_pTopEventList == pEvent && m_pLastEventList == pEvent )
{
m_pTopEventList = m_pLastEventList = NULL;
return TRUE;
};
// 2つ以上登録されていて、先頭のオブジェクトを削除使用とする場合
if( m_pTopEventList == pEvent && m_pLastEventList != pEvent )
{
m_pTopEventList = m_pTopEventList->GetNext();
return TRUE;
};
// 2つ以上登録されていて、2つ目以降を削除しようとしている場合
IMBoardListItem *pTmpEvent;
for( pTmpEvent = m_pTopEventList; pTmpEvent != NULL; pTmpEvent = pTmpEvent->GetNext() )
{
// リスト上の削除対象イベントオブジェクトと同じか?
if( pTmpEvent->GetNext() == pEvent )
{
// 削除しようとしているオブジェクトが、最後である場合
if( pTmpEvent->GetNext() == m_pLastEventList )
m_pLastEventList = pTmpEvent;
// リストの張りなおし
pTmpEvent->SetNext( pTmpEvent->GetNext()->GetNext() );
return TRUE;
};
};
DBG_PRINTF(("CLASSLIB: CALLED CTransfer::UnSetSinkError!!!\n"));
DBG_BREAK();
return FALSE;
}
//DMABufferを設定する。
BOOL CTransfer::SetDMABuffer(DWORD size, BYTE* LinerAdd, BYTE *PhysAdd)
{
ASSERT(LinerAdd);
ASSERT(PhysAdd);
/*
if(!ISENDTRANSFERINIT)
return MBC_NOTINITIALIZE;
m_LinerAdd = LinerAdd;
m_PhysAdd = PhysAdd;
m_DMABufferSize = size;
*/
return TRUE;
}
//Queueに入ってないものをいれる。
BOOL CTransfer::EnQueue( IMPEGBuffer *pBuffer )
{
ASSERT( pBuffer != NULL );
pBuffer->SetNext( NULL );
//転送すべきバッファに追加
if(m_pTopQueuedMPEGBuffer == NULL){
m_pTopQueuedMPEGBuffer = m_pLastQueuedMPEGBuffer = m_pNextTransferMPEGBuffer = pBuffer;
m_TopPagePoint = 1;
m_LastPagePoint = 1;
// DBG_PRINTF(("CLASSLIB: m_pTopQueuedTOPMPEGBuffer = 0x%X\n", (DWORD)m_pTopQueuedMPEGBuffer));
// DBG_PRINTF(("CLASSLIB: m_pLastQueuedTOPMPEGBuffer = 0x%X\n", (DWORD)m_pLastQueuedMPEGBuffer));
// DBG_PRINTF(("CLASSLIB: PageSize = %d\n", pBuffer->GetPageNum()));
}
else{
m_pLastQueuedMPEGBuffer->SetNext(pBuffer);
m_pLastQueuedMPEGBuffer = pBuffer;
if( m_pNextTransferMPEGBuffer == NULL )
{
m_pNextTransferMPEGBuffer = m_pLastQueuedMPEGBuffer;
m_LastPagePoint = 1;
};
// DBG_PRINTF(("CLASSLIB: m_pTopQueuedTOPMPEGBuffer = 0x%X\n", (DWORD)m_pTopQueuedMPEGBuffer));
// DBG_PRINTF(("CLASSLIB: m_pLastQueuedTOPMPEGBuffer = 0x%X\n", (DWORD)m_pLastQueuedMPEGBuffer));
// DBG_PRINTF(("CLASSLIB: PageSize = %d\n", pBuffer->GetPageNum()));
}
// DBG_PRINTF(("CLASSLIB: CALLED CTransfer::EnQueue\n"));
if(!ISENDTRANSFERINIT){
DBG_PRINTF(("CLASSLIB:CTRANSFER::ENQUEUE:NOT INTIALIZE CTRANSFER\n"));
DBG_BREAK();
return FALSE;
}
return TRUE;
}
//Queueからとりだして転送する
BOOL CTransfer::DeQueue()
{
DWORD PageNum;
CBaseStream *pStream;
CTransferStreamList *pStreamList;
IHALStreamControl *pHALStream;
DWORD pLinear, pPhys, Flag;
int BufSize;
// DBG_PRINTF(("CLASSLIB: CALLED CTransfer::DeQueue\n"));
if(!ISENDTRANSFERINIT){
DBG_PRINTF(("CLASSLIB:CTRANSFER::DEQUEUE:NOT INTIALIZE CTRANSFER\n"));
DBG_BREAK();
return FALSE;
}
//pStream = m_pStreamObject->GetBaseStrem();
//DMAバッファをつかう場合の処理
if(ISSETDMABUFFER){
}
//DMAバッファを使わない場合の処理
else{
for(pStreamList = m_pStreamObject; pStreamList; pStreamList = (CTransferStreamList *)pStreamList->GetNext()){
pStream = pStreamList->GetBaseStream();
ASSERT(pStream);
pHALStream = pStream->GetHALStreamControl();
ASSERT(pHALStream);
DWORD QueueNum;
HALRESULT st;
DWORD Count;
//変換されてリストに入ってるバッファを実際にデータ転送
if((st = pHALStream->GetAvailableQueue( &QueueNum )) != HAL_SUCCESS){
_RPT0(_CRT_WARN, "CAN'T GETAVAILABLEQUEUE\n");
DBG_PRINTF(("CLASSLIB:CTransfer::DeQueue:CAN'T GETAVAILABLEQUEUE\n"));
DBG_BREAK();
return FALSE;
}
for(Count = 0; Count < QueueNum ; Count++){
IMPEGBuffer *pBuffer = NULL;
if( GetNextTransferPoint( &pBuffer, &PageNum ) == FALSE )
return TRUE;
if(!pBuffer->GetPagePointer(PageNum, &pLinear, &pPhys)){
return FALSE;
}
//CClassLibBufferを作るためにサイズを取得
BufSize = pBuffer->GetPageSize(PageNum);
//CClassLibBufferを作るためにflagを取得
if(PageNum == 1)
Flag = pBuffer->GetBufferFlag();
else
Flag = 0; //ここはコーディングし直す
//新しいバッファ管理クラスを作る
CClassLibBuffer *pBuf = m_Mem.Alloc(pBuffer, pStream, PageNum, BufSize, pPhys, pLinear, Flag);//データを設定
if(!pBuf){
_RPTF0(_CRT_WARN, "CAN'T New");
DBG_PRINTF(("CLASSLIB:CTRANSFER::ENQUEUE:CAN'T NEW\n"));
DBG_BREAK();
return FALSE;
}
//デバッグ用
BufCount++;
// DBG_PRINTF(("CLASSLIB: Dequeue: Senddata(%d) pBuffer = 0x%X IMPEGBuff=0x%x\n", BufCount, (DWORD)pBuf,pBuffer ));
if((st = pHALStream->SendData(pBuf)) != HAL_SUCCESS){
_RPT0(_CRT_WARN, "CAN'T SENDDATA TO HAL\n");
DBG_PRINTF(("CLASSLIB:CTransfer::DeQueue:CAN'T SENDDATA TO HAL\n"));
DBG_BREAK();
return FALSE;
}
}
}
}
return TRUE;
}
//Transferオブジェクトにストリームを追加する。
BOOL CTransfer::AddStreamObject(IBaseStream *INewStreamObject)
{
//CBaseStream *pBSt1, *pBSt2;
CTransferStreamList *pNewTransferStreamList, *pStreamList;
ASSERT(INewStreamObject);
//378742 PNPBOOT: tosdvd03 leaks 1 page of memory on unload.
// pNewTransferStreamList = new CTransferStreamList((CBaseStream *)INewStreamObject);
m_pNewTransferStreamList.Init( (CBaseStream *)INewStreamObject );
pNewTransferStreamList = &m_pNewTransferStreamList;
//
if(!pNewTransferStreamList){
DBG_PRINTF(("CLASSLIB:CTRANSFER::AddStreamObject:CAN'T NEW\n"));
DBG_BREAK();
return FALSE;
}
//デバッグ用
StreamCount++;
//まだ一つもストリームが追加されていない。
if(m_pStreamObject == NULL){
m_pStreamObject = pNewTransferStreamList;
//pBSt1 = m_pStreamObject->GetBaseStream();
//pHALStream = m_pBSt1->GetHALStreamControl();
m_pIHAL = m_pStreamObject->GetBaseStream()->GetClassLibHAL();
m_EndOfTransferEvent.SetEventType(ClassLibEvent_SendData);
m_EndOfTransferEvent.SetTransfer(this);
m_pIHAL->SetSinkClassLib((IMPEGBoardEvent *)/*(CClassLibEvent *)*/&m_EndOfTransferEvent);
}
//新しいストリームを追加
else{
//pBSt1 = pNewTransferStreamList;
for(pStreamList = m_pStreamObject; pStreamList->GetNext() != NULL; pStreamList = (CTransferStreamList *)pStreamList->GetNext());
pStreamList->SetNext((IMBoardListItem *)pNewTransferStreamList);
}
return TRUE;
}
//Transferオブジェクトからストリームを解放する。
BOOL CTransfer::ReleaseStreamObject(IBaseStream *IStreamObject)
{
CTransferStreamList *pStreamList, *pNextStreamList;
CBaseStream *pBaseStream;
ASSERT(IStreamObject);
//解放すべきストリームがないのでエラー
if(m_pStreamObject == NULL){
_RPTF0(_CRT_WARN, "CTransfer:THERE IS NO STREAM WHICH SHOULD BE RELEASED\n");
DBG_PRINTF(("CLASSLIB:CTRANSFER::ReleaseStreamObject:THERE IS NO STREAM WHICH SHOULD BE RELEASED\n"));
DBG_BREAK();
return FALSE;
}
else{
for(pStreamList = m_pStreamObject; ; pStreamList = (CTransferStreamList *)pStreamList->GetNext()){
if((pNextStreamList = (CTransferStreamList *)pStreamList->GetNext()) == NULL){
_RPTF0(_CRT_WARN, "CTransfer:THERE IS SUCH A STREAM WHICH SHOULD BE RELEASED\n");
DBG_PRINTF(("CLASSLIB:CTRANSFER::ReleaseStreamObject:THERE IS SUCH A STREAM WHICH SHOULD BE RELEASED\n"));
DBG_BREAK();
return FALSE;
}
if((pBaseStream = (CBaseStream *)pNextStreamList->GetBaseStream()) == (CBaseStream *)IStreamObject){
break;
}
ASSERT(pBaseStream);
}
pStreamList->SetNext(pNextStreamList->GetNext());
//378742 PNPBOOT: tosdvd03 leaks 1 page of memory on unload.
// delete pNextStreamList;
//
//デバッグ用
StreamCount--;
}
return TRUE;
}
//Queueをフラッシュする。
void CTransfer::Flush()
{
CTransferStreamList *pStreamList;
CBaseStream *pBaseStream;
IMPEGBoardEvent *pEvent;
DBG_PRINTF(("CLASSLIB:Before flash BufCount = %d\n", BufCount));
m_Mem.Flush();
BufCount=0;
for(pStreamList = m_pStreamObject; pStreamList; pStreamList = (CTransferStreamList *)pStreamList->GetNext()){
pBaseStream = pStreamList->GetBaseStream();
DWORD PageNum;
ASSERT(pBaseStream);
IMPEGBuffer *pBuffer = NULL;
BOOL NeedAdvice = FALSE;
// StreamがQueueに持っているバッファをすべて、転送中にマークする。
while( TRUE )
{
if( GetNextTransferPoint( &pBuffer, &PageNum ) == FALSE )
break;
}
while( HasQueuedBuffer() == TRUE )
{
NeedAdvice = FreeTopTransferPoint(&pBuffer);
if( NeedAdvice == TRUE )
{
for(pEvent = (IMPEGBoardEvent *)m_pTopEventList; pEvent != NULL;pEvent = (IMPEGBoardEvent *)((IMBoardListItem *)pEvent)->GetNext())
{
if((/*(CClassLibEvent *)*/pEvent)->GetEventType() == ClassLibEvent_SendData){
//MPEGBufferの先頭をひとつうしろにずらす
//Wrapperにもう使い終わったことを知らせる
pEvent->Advice(pBuffer);
}
}
};
}
}
DBG_PRINTF(("CLASSLIB:After flush BufCount = %d\n", BufCount));
ASSERT( BufCount == 0 );
}
//データ転送終了の処理
BOOL CTransfer::EndOfTransfer(CClassLibBuffer *pBuffer)
{
IMPEGBoardEvent *pEvent;
CBaseStream *pStream;
CTransferStreamList *pStreamList;
// DBG_PRINTF(("CLASSLIB: EndOfTransfer(%d) pBuffer = 0x%X\n", BufCount, (DWORD)pBuffer));
// DBG_PRINTF(("CLASSLIB: pBuffer->GetIMPEGBuffer() = 0x%X\n", (DWORD)pBuffer->GetIMPEGBuffer()));
ASSERT(pBuffer);
pStream = pBuffer->GetStream();
ASSERT(pStream);
IMPEGBuffer *pFree = NULL;
if( FreeTopTransferPoint(&pFree) == TRUE )
{
// DBG_PRINTF(("CLASSLIB: Free IMPEGBuffer() = 0x%X\n", (DWORD)pFree ));
ASSERT( pFree == pBuffer->GetIMPEGBuffer() );
//Wrapperから渡されたバッファの最後のページならバッファー開放
for(pEvent = (IMPEGBoardEvent *)m_pTopEventList; pEvent != NULL;pEvent = (IMPEGBoardEvent *)((IMBoardListItem *)pEvent)->GetNext()){
if(pEvent->GetEventType() == ClassLibEvent_SendData){
//Wrapperにもう使い終わったことを知らせる
// DBG_PRINTF(("CLASSLIB: EndOfTransfer Advice Buffer = 0x%X\n", pBuffer->GetIMPEGBuffer() ));
pEvent->Advice(pBuffer->GetIMPEGBuffer());
}
}
}
//リストからはずしたCClassLibBufferを解放
m_Mem.Free(pBuffer);
//デバッグ用
BufCount--;
ASSERT(BufCount>=0);
//STOP状態のときにHALに対してSendDataしない
for(pStreamList = m_pStreamObject; pStreamList; pStreamList = (CTransferStreamList *)pStreamList->GetNext()){
pStream = pStreamList->GetBaseStream();
ASSERT(pStream);
if(pStream->GetState() == Stop)
return TRUE;
}
if(DeQueue() == FALSE){
DBG_PRINTF(("CLASSLIB:CTRANSFER::EndOfTransfer:CAN'T DEQUEUE\n"));
DBG_BREAK();
return FALSE;
}
return TRUE;
}
BOOL CTransfer::HasQueuedBuffer( void )
{
if( m_pTopQueuedMPEGBuffer == NULL )
return FALSE;
return TRUE;
};
BOOL CTransfer::GetNextTransferPoint( IMPEGBuffer **Point, DWORD *Page )
{
if( m_pNextTransferMPEGBuffer == NULL )
{
*Point = NULL;
*Page = 0;
return FALSE;
};
*Point = m_pNextTransferMPEGBuffer;
*Page = m_LastPagePoint;
if( m_pNextTransferMPEGBuffer->GetPageNum() == m_LastPagePoint )
{
m_pNextTransferMPEGBuffer = (IMPEGBuffer *)m_pNextTransferMPEGBuffer->GetNext();
m_LastPagePoint = 1;
return TRUE;
};
m_LastPagePoint ++;
return TRUE;
};
BOOL CTransfer::FreeTopTransferPoint( IMPEGBuffer **Free )
{
ASSERT( m_pTopQueuedMPEGBuffer != NULL );
if( m_pTopQueuedMPEGBuffer == NULL
|| ( m_pTopQueuedMPEGBuffer == m_pNextTransferMPEGBuffer && m_LastPagePoint == m_TopPagePoint ) )
{
*Free = NULL;
return FALSE;
};
if( m_TopPagePoint == m_pTopQueuedMPEGBuffer->GetPageNum() )
{
*Free = m_pTopQueuedMPEGBuffer;
m_pTopQueuedMPEGBuffer = (IMPEGBuffer *)m_pTopQueuedMPEGBuffer->GetNext();
m_TopPagePoint = 1;
return TRUE; // Need Advice
};
*Free = NULL;
m_TopPagePoint ++;
return FALSE; // Not Need Advice
};
//HALによんでもらいたい
void CClassLibEvent::Advice(PVOID pBuffer)
{
ASSERT(m_pTransfer);
m_pTransfer->EndOfTransfer((CClassLibBuffer *)pBuffer);
}