/*static char *SCCSID = "@(#)ionotify.c 6.6 92/02/12";*/
#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.h>
#include <fsh.h>
#include <strat2.h>
#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "volume.h"
#include "frame.h"
#include "asyncio.h"
#include "lprintf.h"
#include "storage.h"
#include "tables.h"
#include "assert.h"
#include "lw.h"
#include "fsdata.h"
#include "pbmacros.h"
#include "pr_misc.h"
#include "pr_read.h"

#ifdef DEBUG
#include "pr_debug.h"
#endif

/*
 ***    IO_Notify - Asynchronous I/O notification routine (for SDR & SDW)
 *
 *      IO_Notify clears the bit for this request in the notification record,
 *      saves any error state, & wakes up any waiters (if all pending I/O is
 *      done).
 *
 *      Entry   es:bx = pointer to the I/O request list header
 *              'C' means an error has occurred
 *
 *          The BEGIN_NOTIFY handles the register calling convention.
 *
 *      Exit    none
 *
 *      HISTORY
 *          07-Feb-90 by JR (John Rogers, JohnRo@Microsoft)
 *              - Improved debug output and added assertion checks, per Mark
 *                Hitch.  Also added his lprintf() calls.
 */

#ifdef DEBUG
    extern USHORT usQReadsActive;       /* Defined and set in qread.c. */
    extern USHORT usQWritesActive;      /* Defined and set in qwrite.c. */
#endif

BEGIN_NOTIFY (IO_Notify, pxlh, erc )

    PIOH pioh;
    PNOTEREC pNoteRec;

    /* Get the address of the IOHandle at the front of pxlh */
    pioh = IOHFromListHead( pxlh );
    ASSERT_IOH(pioh);
    pNoteRec = (PNOTEREC) pioh->pNoteRec;
    ASSERT_NOTEREC(pNoteRec);

// @76193 don't print when logging
#if defined (DEBUG) || defined (LOG_PRINT)
    lprintf (LMOD_NTFY, "pioh%p", pioh);
#endif

#ifdef DEBUG_ASYNC
    dprintf ("\n%s: Received notify call...\n", __FILE__);
    dprintf ("  pxlh = %p, pioh = %p, pNoteRec = %p, lsn = %lx\n",
             pxlh, pioh, pNoteRec, pxlh->IOReq.RWReq.Start_Block);
#endif /* DEBUG_ASYNC */

#ifdef DEBUG
    {
        BYTE bCommandCode =
            FirstIOReq(GetIOListHead(pioh))->RWReq.RqHdr.Command_Code;
        if  ( (bCommandCode==PB_WRITE_X) || (bCommandCode==PB_WRITEV_X) ) {
            if (usQWritesActive <= 0) {
                dprintf (__FILE__": notify but no QWrites active!\n");
                Int3();
            } else {
                --usQWritesActive;
            }
        } else {
            if (usQReadsActive <= 0) {
                dprintf (__FILE__": notify but no QReads active!\n");
                Int3();
            } else {
                --usQReadsActive;
            }
        }
    }
#endif

    /* reset the bit for this request */
#ifdef DEBUG
    if ((pNoteRec->mask & (BYTE) pioh->bBitForThisOp) == 0) {
        dprintf (__FILE__": Mask bit already reset!...\n");
        dprintf ("  pxlh = %p, pioh = %p, pNoteRec = %p, lsn = %lx\n",
                 pxlh, pioh, pNoteRec, pxlh->IOReq.RWReq.Start_Block);
    }
#endif

// @76193 - don't print when logging
#if defined (DEBUG) || defined (LOG_PRINT)
    lprintf (LMOD_NTFY, "pNR %p; mask %x; bit %x",
             pNoteRec, pNoteRec->mask, (BYTE) pioh->bBitForThisOp);
#endif

    pNoteRec->mask &= ~(BYTE) pioh->bBitForThisOp;

#if defined (DEBUG) || defined (LOG_PRINT)
    lprintf (LMOD_NTFY, "mask %x; bit %x",
             pNoteRec->mask,(BYTE) pioh->bBitForThisOp);
#endif

    /* check to see if this one errored */
    if (erc != NO_ERROR) {
#ifdef DEBUG
        dprintf (__FILE__": Error, erc=%d...\n", erc);
        dprintf ("  pxlh = %p, pioh = %p, pNoteRec = %p, lsn = %lx\n",
                 pxlh, pioh, pNoteRec, pxlh->IOReq.RWReq.Start_Block);
#endif
        pNoteRec->errmsk |= (BYTE) pioh->bBitForThisOp;
    }

    /* add this pioh to the chain */

#if defined (DEBUG) || defined (LOG_PRINT)
    lprintf (LMOD_NTFY, "pre; pNR->pioh %p, pioh->piohNext %p",
             pNoteRec->pioh, pioh->piohNext);
#endif

    pioh->piohNext = pNoteRec->pioh;

#if defined (DEBUG) || defined (LOG_PRINT)
    lprintf (LMOD_NTFY, "post; pNR->pioh %p, pioh->piohNext %p",
             pNoteRec->pioh, pioh->piohNext);
#endif

    pNoteRec->pioh = pioh;

    /* if all done, then wake up any waiters */
    if (pNoteRec->mask == 0) {

        /* FSH_IOSEMCLEAR the semaphore in *pNoteRec.
         *
         * NOTE: MayBlock won't work because we run at interupt time.
         */

/* Clear the semaphore in *pNoteRec and issue a procrun2  */
        FSH_IOSEMCLEAR (&(pNoteRec->block));

    }
END_NOTIFY
