Ejemplo n.º 1
0
/*
 *  ======== GIO_reclaim ========
 */
Int GIO_reclaim(GIO_Object *obj, Ptr *pBuf, SizeT *pSize, UArg *pArg)
{
    IOM_Packet          *packet;
    Queue_Handle        doneList;
    Queue_Handle        freeList;
    UInt                key;
    Int                 status;
    Error_Block         eb;
    
    doneList = GIO_Instance_State_doneList(obj);
    freeList = GIO_Instance_State_freeList(obj);

    Error_init(&eb);

    while (obj->doneCount == 0) {
        if (Sync_wait(obj->sync, obj->timeout, &eb) == 
                Sync_WaitStatus_TIMEOUT) {

            return (IOM_ETIMEOUT);
        }
    }

    key = Hwi_disable();
    obj->doneCount--;
    packet = Queue_dequeue(doneList);
    Hwi_restore(key);

    if (pArg != NULL) {
        *pArg = packet->arg;
    }

    /* pBuf is set to NULL by GIO_read() and GIO_write() */
    if (pBuf != NULL) {
        *pBuf = packet->addr;
    }

    if (pSize != NULL) {
        *pSize = packet->size;
    }

    status = packet->status;

    /* 
     * re-signal if more buffers are ready
     * This is required in the case of ISyncEvent and ISyncSwi to allow 
     * clients to reclaim a single buffer and not force them to bleed the 
     * stream.
     */
    if (obj->doneCount > 0) {
        Sync_signal(obj->sync);
    }

    /* recycle packet back onto free list */
    key = Hwi_disable();
    obj->freeCount++;
    Queue_enqueue(freeList, (Queue_Elem *)packet);
    Hwi_restore(key);

    return (status);
}
Ejemplo n.º 2
0
/*
 *  ======== GIO_submit ========
 */
Int GIO_submit(GIO_Object *obj, Uns cmd, Ptr buf, 
        SizeT *pSize, GIO_AppCallback *appCallback)
{
    IOM_Packet      syncPacket;
    IOM_Packet      *packet;
    SizeT           nullSize; 
    Int             status;
    UInt            key;
    Queue_Handle    list;
    Error_Block     eb;
    IOM_Fxns        *iomFxns;

    iomFxns = (IOM_Fxns *)obj->fxns;

    if (appCallback == NULL) {
        packet = &syncPacket;
    }
    else {
        list = GIO_Instance_State_freeList(obj);

        if (obj->freeCount == 0) { 
            return (IOM_ENOPACKETS);
        }

        key = Hwi_disable();
        obj->freeCount--;
        packet = Queue_dequeue(list);
        Hwi_restore(key);
    }

    if (pSize == NULL) {
        nullSize = 0;
        pSize = &nullSize;
    }

    packet->cmd = cmd;
    packet->addr = buf;
    packet->size = *pSize;
    packet->status = IOM_COMPLETED;

    /*
     * 'appCallback' will be NULL for synchronous calls.
     * 'packet->misc' is used in the callback to call asynch callback
     * or post semaphore (sync).
     */
    packet->misc = (UArg)appCallback;

    status = iomFxns->mdSubmitChan(obj->mdChan, packet);

    if ((status == IOM_COMPLETED) || (status < 0)) {
        if (status == IOM_COMPLETED) {
            *pSize = packet->size;
            status = packet->status;
        }

        /* if asynch, put packet back on freeList */
        if (appCallback != NULL) {
            key = Hwi_disable();
            obj->freeCount++;
            Queue_enqueue(list, (Queue_Elem *)packet);
            Hwi_restore(key);
        }

        return (status);
    }

    /* 
     * call Sync_wait only if synchronous I/O and mdSubmitChan did not
     * return an error (status < 0)
     */
    if (appCallback == NULL) {
        Error_init(&eb);

        if (Sync_wait(obj->sync, obj->timeout, &eb) == 
                Sync_WaitStatus_SUCCESS) {
            *pSize = packet->size;
            status = packet->status;
        }
        else {
            *pSize = 0; 

            /*
             * NOTE: A channel timeout needs special handling. Timeouts are
             * usually due to some serious underlying device or system state
             * and may require the channel, or possibly the device,to be reset.
             * Because the mini-driver may still own the IOM_Packet here
             * driver's will need to perform timeout processing. We will call
             * the mini-driver's control fxn with the IOM_CHAN_TIMEDOUT command
             * code.
             */
            status = iomFxns->mdControlChan(obj->mdChan, 
                IOM_CHAN_TIMEDOUT, NULL);

            if (status != IOM_COMPLETED) {
                return (IOM_ETIMEOUTUNREC);  /* fatal, may have lost packet */
            }

            return (IOM_ETIMEOUT);
        }
    }

    return (status);
}
Ejemplo n.º 3
0
/*
 *  ======== Stream_reclaim ========
 */
SizeT Stream_reclaim(Stream_Object *obj, Ptr *bufp, UInt timeout, UArg *arg, 
    Error_Block *eb)
{
    DriverTypes_Packet  *packet = NULL;
    List_Handle         freeList;
    UInt                key;
    
    if (obj->issued == 0) {
        Error_raise(eb, Stream_E_noBuffersIssued, 0, 0);
        return (0);
    }

    while (obj->ready == 0) {
        if (!Sync_wait(obj->complete, timeout, eb)) {
            if (timeout != 0) {
                Error_raise(eb, Stream_E_timeout, timeout, 0);
            }
            return (0);
        }
    };
    IConverter_reclaim(obj->convHandle, &packet, eb);

    if (arg != NULL) {
        *arg = packet->arg;
    }

    /* bufp is NULL in Stream_read and Stream_write. */
    if (bufp != NULL) {
        *bufp = packet->addr;
    }

    key = Hwi_disable();
    obj->ready--;
    Hwi_restore(key);

    obj->issued--;

    /* 
     * re-signal if more buffers are ready
     * This is required in the case of ISyncEvent and ISyncSwi to allow 
     * clients to reclaim a single buffer and not force them to bleed the 
     * Stream. In the case of ISyncSem , this re-signal is an overhead
     */

    if (obj->ready > 0) {
        Sync_signal(obj->complete);
    }

    freeList = Stream_Instance_State_freeList(obj);

    /* recycle packet back onto free list */
    List_put(freeList, (List_Elem *)packet);

    if ((packet->error != NULL) &&
        (packet->error != DriverTypes_EABORTED)) {
        Error_raise(eb, packet->error, packet->status, 0);
        return (0);
    }
    else {
        return (packet->size);
    }
}