/*static char *SCCSID = "@(#)lwerrors.c	6.2 92/01/31";*/
#include <os2def.h>			/* Needed by all. */
#include "const.h"			/* Needed by all. */
#include "chain.h"			/* Needed by "dir.h", "tables.h". */
#include "misc.h"			/* Needed by "buf.h", "dir.h". */
#include "buf.h"			/* Needed by "dir.h", "fsdata.h". */
#include "dir.h"			/* Needed by "fsdata.h", "tables.h". */
#include "volume.h"			/* Needed by "frame.h", "fsdata.h". */
#include "storage.h"			/* Needed by "tables.h". */
#include "tables.h"			/* Needed by "pr_cache.h". */
#include "assert.h"			/* ASSERT_BUF. */
#include "lw.h"				/* Needed by "fsdata.h". */
#include "frame.h"			/* Needed by "fsdata.h". */
#include "fsdata.h"			/* Needed by "asyncio.h". */
#include "pbmacros.h"			/* Needed by "asyncio.h". */
#include "strat2.h"			/* Needed by "asyncio.h". */
#include "asyncio.h"			/* PIOH, PLISTENT, FirstIOReq, etc. */
#include "pr_CACHE.h"			/* HashFind. */
#include "pr_LAZY.h"			/* HandleLWErrors */
#include "pr_DSKIO.h"			/* WriteHF. */
#ifdef DEBUG
    #include "pr_DEBUG.h"		/* dprintf. */
#endif


/***	HandleLWErrors - handle each error in an asyncio command chain
 *
 *	HandleLWErrors is passed the handle of a command chain for which one or
 *	more errors have occurred.  The device driver will have set the error
 *	and/or status flags in the command chain before HandleLWErrors is
 *	called.  HandleLWErrors will scan the command chain, and for each
 *	request in error, it will hotfix the sectors, unhold the buffers, and
 *	wakeup anyone waiting for those buffers.
 *
 *	HandleLWErrors may block.  Therefore, it cannot be called from a
 *	notify/interrupt routine.
 *
 *	Note that the current version of HandleLWErrors assumes that each
 *	request is at least SPB sectors long.  If LWAsync is changed to only
 *	write the dirty sectors of a block, HandleLWErrors must be changed to
 *	reflect this.
 *
 *	Entry	pioh	I/O handle which had an error.  All I/O for this handle
 *			must be completed before HandleLWErrors is called.
 *			Also, there must be at least one request in the list,
 *			HandleLWErrors will GP fault.
 *
 *	Exit	none
 *		Yields
 *
 *	HISTORY
 *	    29-Nov-1989 by JR (John Rogers, JohnRo@Microsoft)
 *		- Fixed bug (looped once too often).
 *	    21-Nov-1989 by JR (John Rogers, JohnRo@Microsoft)
 *		- Rework from code review.
 *	    08-Nov-1989 by JR (John Rogers, JohnRo@Microsoft)
 *		- Created HandleLWErrors() from scratch.
 */

VOID far
HandleLWErrors(PIOH pioh, PFRAME pfrm)		     /* may block */
{
    PLISTENT preq;			/* pointer to a given request */
    ULONG ulVolBits = pioh->pvol->ulVolBits;

    preq = FirstIOReq(GetIOListHead(pioh));
    while (TRUE) {		/* Check each request in the list. */

	/* Was there an error in this request? */
	if (preq->RWReq.RqHdr.Status & RH_UNREC_ERROR) {

	    ULONG ulBlocksLeft;
	    LSN vlsn;

	    /* Compute first VLSN for this request. */
	    vlsn = ulVolBits | preq->RWReq.Start_Block;
#ifdef DEBUG
	    dprintf(__FILE__": processing write error for lsn %lx\n", vlsn);
#endif

	    /*
	     * We write out all sectors in each buffer.  It won't amount
	     * to many extra, and we don't care about a little extra time
	     * during error handling.
	     */
	    ulBlocksLeft = preq->RWReq.Block_Count / SPB;
	    while (ulBlocksLeft > 0) {

		PBUFNODE pbuf = HashFind(vlsn);
		ASSERT_BUF(pbuf);
		WriteHF( vlsn,
			 (USHORT) SPB,		/* csector */
			 pbuf->pblkData,pfrm );	     /* virt addr of data. */
		vlsn += SPB;
		--ulBlocksLeft;

	    } /* while */

	    /* Cleanup (unlock buffers, etc) */
//#85759
//	    RequestCleanup( preq );
	} /* if error... */

	if (IsLastReq(preq))
	    break;
	preq = NextIOReq(preq);
    } /* while TRUE */

}
