347 lines
7.2 KiB
C++
347 lines
7.2 KiB
C++
#include "precomp.h"
|
||
|
||
|
||
//
|
||
// OA.CPP
|
||
// Order Accumulation, both cpi32 and display driver sides
|
||
//
|
||
// Copyright(c) Microsoft 1997-
|
||
//
|
||
|
||
#define MLZ_FILE_ZONE ZONE_ORDER
|
||
|
||
|
||
|
||
//
|
||
//
|
||
// FUNCTION: OA_ResetOrderList
|
||
//
|
||
//
|
||
// DESCRIPTION:
|
||
//
|
||
// Frees all Orders and Additional Order Data in the Order List.
|
||
// Frees up the Order Heap memory.
|
||
//
|
||
//
|
||
// PARAMETERS:
|
||
//
|
||
// None.
|
||
//
|
||
//
|
||
// RETURNS:
|
||
//
|
||
// Nothing.
|
||
//
|
||
//
|
||
void ASHost::OA_ResetOrderList(void)
|
||
{
|
||
LPOA_SHARED_DATA lpoaShared;
|
||
|
||
DebugEntry(ASHost::OA_ResetOrderList);
|
||
|
||
TRACE_OUT(("Free order list"));
|
||
|
||
lpoaShared = OA_SHM_START_WRITING;
|
||
|
||
//
|
||
// First free all the orders on the list.
|
||
//
|
||
OAFreeAllOrders(lpoaShared);
|
||
|
||
//
|
||
// Ensure that the list pointers are NULL.
|
||
//
|
||
if ((lpoaShared->orderListHead.next != 0) || (lpoaShared->orderListHead.prev != 0))
|
||
{
|
||
ERROR_OUT(("Non-NULL list pointers (%lx)(%lx)",
|
||
lpoaShared->orderListHead.next,
|
||
lpoaShared->orderListHead.prev));
|
||
|
||
COM_BasedListInit(&lpoaShared->orderListHead);
|
||
}
|
||
|
||
OA_SHM_STOP_WRITING;
|
||
DebugExitVOID(ASHost::OA_ResetOrderList);
|
||
}
|
||
|
||
//
|
||
// OA_SyncOutgoing()
|
||
// Called when a share starts or somebody new joins the share.
|
||
// Resets currently accumulated orders, which were based on old obsolete
|
||
// caps and data.
|
||
//
|
||
void ASHost::OA_SyncOutgoing(void)
|
||
{
|
||
OAFreeAllOrders(g_poaData[1 - g_asSharedMemory->displayToCore.newBuffer]);
|
||
}
|
||
|
||
|
||
//
|
||
//
|
||
// OA_GetFirstListOrder()
|
||
//
|
||
// Returns:
|
||
// Pointer to the first order in the Order List.
|
||
//
|
||
//
|
||
LPINT_ORDER ASHost::OA_GetFirstListOrder(void)
|
||
{
|
||
LPOA_SHARED_DATA lpoaShared;
|
||
LPINT_ORDER retOrder = NULL;
|
||
|
||
DebugEntry(ASHost::OA_GetFirstListOrder);
|
||
|
||
lpoaShared = OA_SHM_START_READING;
|
||
|
||
//
|
||
// Get the first entry from the linked list.
|
||
//
|
||
retOrder = (LPINT_ORDER)COM_BasedListFirst(&lpoaShared->orderListHead,
|
||
FIELD_OFFSET(INT_ORDER, OrderHeader.list));
|
||
|
||
OA_SHM_STOP_READING;
|
||
|
||
TRACE_OUT(("First order = 0x%08x", retOrder));
|
||
|
||
DebugExitVOID(ASHost::OA_GetFirstListOrder);
|
||
return(retOrder);
|
||
}
|
||
|
||
|
||
//
|
||
//
|
||
// OA_RemoveListOrder(..)
|
||
//
|
||
// Removes the specified order from the Order List by marking it as spoilt.
|
||
//
|
||
// Returns:
|
||
// Pointer to the order following the removed order.
|
||
//
|
||
//
|
||
LPINT_ORDER ASHost::OA_RemoveListOrder(LPINT_ORDER pCondemnedOrder)
|
||
{
|
||
LPOA_SHARED_DATA lpoaShared;
|
||
LPINT_ORDER pSaveOrder;
|
||
|
||
// DebugEntry(ASHost::OA_RemoveListOrder);
|
||
|
||
TRACE_OUT(("Remove list order 0x%08x", pCondemnedOrder));
|
||
|
||
lpoaShared = OA_SHM_START_WRITING;
|
||
|
||
//
|
||
// Check for a valid order.
|
||
//
|
||
if (pCondemnedOrder->OrderHeader.Common.fOrderFlags & OF_SPOILT)
|
||
{
|
||
TRACE_OUT(("Invalid order"));
|
||
DC_QUIT;
|
||
}
|
||
|
||
//
|
||
// Mark the order as spoilt.
|
||
//
|
||
pCondemnedOrder->OrderHeader.Common.fOrderFlags |= OF_SPOILT;
|
||
|
||
//
|
||
// Update the count of bytes currently in the Order List.
|
||
//
|
||
lpoaShared->totalOrderBytes -= (UINT)MAX_ORDER_SIZE(pCondemnedOrder);
|
||
|
||
//
|
||
// SAve the order so we can remove it from the linked list after having
|
||
// got the next element in the chain.
|
||
//
|
||
pSaveOrder = pCondemnedOrder;
|
||
|
||
pCondemnedOrder = (LPINT_ORDER)COM_BasedListNext(&(lpoaShared->orderListHead),
|
||
pCondemnedOrder, FIELD_OFFSET(INT_ORDER, OrderHeader.list));
|
||
|
||
ASSERT(pCondemnedOrder != pSaveOrder);
|
||
|
||
//
|
||
// Delete the unwanted order from the linked list.
|
||
//
|
||
COM_BasedListRemove(&pSaveOrder->OrderHeader.list);
|
||
|
||
//
|
||
// Check that the list is still consistent with the total number of
|
||
// order bytes.
|
||
//
|
||
if ( (lpoaShared->orderListHead.next != 0) &&
|
||
(lpoaShared->orderListHead.prev != 0) &&
|
||
(lpoaShared->totalOrderBytes == 0) )
|
||
{
|
||
ERROR_OUT(("List head wrong: %ld %ld", lpoaShared->orderListHead.next,
|
||
lpoaShared->orderListHead.prev));
|
||
COM_BasedListInit(&lpoaShared->orderListHead);
|
||
pCondemnedOrder = NULL;
|
||
}
|
||
|
||
DC_EXIT_POINT:
|
||
OA_SHM_STOP_WRITING;
|
||
|
||
// DebugExitPVOID(ASHost::OA_RemoveListOrder, pCondemnedOrder);
|
||
return(pCondemnedOrder);
|
||
}
|
||
|
||
|
||
//
|
||
//
|
||
// OA_GetTotalOrderListBytes(..)
|
||
//
|
||
// Returns:
|
||
// The total number of bytes in the orders currently stored in the Order
|
||
// List.
|
||
//
|
||
//
|
||
UINT ASHost::OA_GetTotalOrderListBytes(void)
|
||
{
|
||
LPOA_SHARED_DATA lpoaShared;
|
||
UINT rc;
|
||
|
||
DebugEntry(ASHost::OA_GetTotalOrderListBytes);
|
||
|
||
lpoaShared = OA_SHM_START_READING;
|
||
|
||
rc = lpoaShared->totalOrderBytes;
|
||
|
||
OA_SHM_STOP_READING;
|
||
|
||
DebugExitDWORD(ASHost::OA_GetTotalOrderListBytes, rc);
|
||
return(rc);
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// OA_LocalHostReset()
|
||
//
|
||
void ASHost::OA_LocalHostReset(void)
|
||
{
|
||
OA_FLOW_CONTROL oaFlowEsc;
|
||
|
||
DebugEntry(ASHost::OA_LocalHostReset);
|
||
|
||
m_oaFlow = OAFLOW_FAST;
|
||
oaFlowEsc.oaFlow = m_oaFlow;
|
||
OSI_FunctionRequest(OA_ESC_FLOW_CONTROL, (LPOSI_ESCAPE_HEADER)&oaFlowEsc, sizeof(oaFlowEsc));
|
||
|
||
DebugExitVOID(ASHost::OA_LocalHostReset);
|
||
}
|
||
|
||
|
||
//
|
||
// OA_FlowControl()
|
||
// Sees if we've changed between fast and slow throughput, and adjusts some
|
||
// accumulation variables accordingly.
|
||
//
|
||
void ASHost::OA_FlowControl(UINT newSize)
|
||
{
|
||
OA_FLOW_CONTROL oaFlowEsc;
|
||
|
||
DebugEntry(ASHost::OA_FlowControl);
|
||
|
||
//
|
||
// Work out the new parameters.
|
||
//
|
||
if (newSize < OA_FAST_THRESHOLD)
|
||
{
|
||
//
|
||
// Throughput is slow
|
||
//
|
||
if (m_oaFlow == OAFLOW_FAST)
|
||
{
|
||
m_oaFlow = OAFLOW_SLOW;
|
||
TRACE_OUT(("OA_FlowControl: SLOW; spoil more orders and spoil by SDA"));
|
||
}
|
||
else
|
||
{
|
||
// No change
|
||
DC_QUIT;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Throughput is fast
|
||
//
|
||
if (m_oaFlow == OAFLOW_SLOW)
|
||
{
|
||
m_oaFlow = OAFLOW_FAST;
|
||
TRACE_OUT(("OA_FlowControl: FAST; spoil fewer orders and don't spoil by SDA"));
|
||
}
|
||
else
|
||
{
|
||
// No change
|
||
DC_QUIT;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Tell the display driver about the new state
|
||
//
|
||
oaFlowEsc.oaFlow = m_oaFlow;
|
||
OSI_FunctionRequest(OA_ESC_FLOW_CONTROL, (LPOSI_ESCAPE_HEADER)&oaFlowEsc, sizeof(oaFlowEsc));
|
||
|
||
DC_EXIT_POINT:
|
||
DebugExitVOID(ASHost::OA_FlowControl);
|
||
}
|
||
|
||
|
||
//
|
||
// OA_QueryOrderAccum - see oa.h
|
||
//
|
||
UINT ASHost::OA_QueryOrderAccum(void)
|
||
{
|
||
LPOA_FAST_DATA lpoaFast;
|
||
UINT rc = 0;
|
||
|
||
DebugEntry(ASHost::OA_QueryOrderAccum);
|
||
|
||
lpoaFast = OA_FST_START_WRITING;
|
||
|
||
//
|
||
// Get the current value.
|
||
//
|
||
rc = lpoaFast->ordersAccumulated;
|
||
|
||
//
|
||
// Clear the value for next time we swap the buffers.
|
||
//
|
||
lpoaFast->ordersAccumulated = 0;
|
||
|
||
OA_FST_STOP_WRITING;
|
||
DebugExitDWORD(ASHost::OA_QueryOrderAccum, rc);
|
||
return(rc);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
// OAFreeAllOrders
|
||
//
|
||
// Free the all the individual orders on the orders list, without
|
||
// discarding the list itself.
|
||
//
|
||
void ASHost::OAFreeAllOrders(LPOA_SHARED_DATA lpoaShared)
|
||
{
|
||
DebugEntry(ASHost::OAFreeAllOrders);
|
||
|
||
//
|
||
// Simply clear the list head.
|
||
//
|
||
COM_BasedListInit(&lpoaShared->orderListHead);
|
||
|
||
lpoaShared->totalHeapOrderBytes = 0;
|
||
lpoaShared->totalOrderBytes = 0;
|
||
lpoaShared->totalAdditionalOrderBytes = 0;
|
||
lpoaShared->nextOrder = 0;
|
||
|
||
DebugExitVOID(ASHost::OAFreeAllOrders);
|
||
}
|
||
|
||
|
||
|