/****************************************************************************
*
*            COPYRIGHT 1990,91,92 BY GRACILIS INC.
*
*              623 Palace St.
*            Aurora, Il. 60506
*
* GRACILIS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS
* SOFTWARE FOR ANY PURPOSE.
*
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
*
* Permission is granted for non-commercial distribution only.
*
******************************************************************************/
  
#include <dos.h>
#include "global.h"
#ifdef PACKETWIN
#include "mbuf.h"
#include "iface.h"
#include "gracilis.h"
  
  
/*
 * Dequeue of Available Buffers - Used with a head pointer and
 * a Counter to dequeue a pre-allocated receive buffer of type "struct mbuf".
 *
 * Use only for LIFO queues!  (i.e. don't need a tail pointer)
 */
struct mbuf *
f_dequeavail(headp, availcount)
struct mbuf **headp;
int16 *availcount;
{
    int i_state;
    struct mbuf *rx_mbufp;
  
    rx_mbufp = NULLBUF;
  
    i_state = dirps();
  
    rx_mbufp = *headp;
  
    if ( *headp != NULLBUF )
    {
        *headp = rx_mbufp->anext;
        (*availcount)--;
        rx_mbufp->anext = NULLBUF;
    }
  
    restore(i_state);
  
        /* return the mbuf used to receive data */
    return(rx_mbufp);
}
  
  
  
  
/*
 * Fill a preallocated mbuf queue with a specified number of buffers.
 * Used with a head pointer and a Counter.
 * THIS IS USED by PackeTen and PackeTwin
 * drivers to maintain their receive frame queues.
 *
 */
void
f_getavail(headp, getcount, bufsize, rxavailcount, ifacep, dma_flg)
struct mbuf **headp;            /* address of headq */
int16 getcount;                 /* number of mbufs to get */
int16 bufsize;                  /* size of data buffer */
int16 *rxavailcount;            /* headq's avail counter */
struct iface *ifacep;           /* device's iface control structure's */
                    /* address */
bool    dma_flg;
{
    int i_state;
    struct mbuf *rx_mbufp;
    int16   gotcount = 0;
    struct mbuf *badlist,*srchptr;  /* discard list */
    ulong realaddr;
    unsigned page,alloc_size;
  
#ifdef OLD_KA9Q
    struct phdr *hdr;
#endif
  
  
    badlist = NULLBUF;  /* init list to null */
  
    while ( (getcount > 0) )
    {
#ifdef OLD_KA9Q
        alloc_size = bufsize + sizeof(struct phdr);
#else
        alloc_size = bufsize;
#endif
        rx_mbufp = alloc_mbuf(alloc_size);
  
        /* If we are being asked for dma-able buffers, then check */
        if( dma_flg == TRUE )
        {
            /* A rendition of an absolute address for the ptr */
            realaddr = ((ulong)FP_SEG(rx_mbufp) << 4) +
            (ulong)FP_OFF(rx_mbufp);
  
            /* DMA page reg for 8237 */
            page = (unsigned)(realaddr >> 16);
            if(((realaddr + alloc_size) >> 16) != page)
            {
                rx_mbufp->next = NULL;
  
                /* put this buffer on a list to be free'd */
  
                if(badlist == NULLBUF)badlist = rx_mbufp;
                else
                {
                    /* find the end of the list */
                    srchptr = badlist;
                    while(srchptr->next != NULLBUF)
                        srchptr = srchptr->next;
                    /* put this one on the end */
                    srchptr->next = rx_mbufp;
                }
  
                /* cause the loop to try again */
                rx_mbufp = NULLBUF;
  
                pwait(NULL);    /* be nice to others... */
            }
  
        }
  
        if(rx_mbufp != NULLBUF )
        {
            /* setup the packet header for the DRIVER */
            /* calling this routine */
  
#ifdef OLD_KA9Q
            /* init to packet header's byte count */
            rx_mbufp->cnt = sizeof(struct phdr);
            hdr = (struct phdr *)rx_mbufp->data;
            hdr->type = ifacep->type;
            hdr->iface = ifacep;
  
  
            /* Rx data goes in after packet header  */
            /* works because data is a char pointer */
            rx_mbufp->data += sizeof(struct phdr);
#endif
  
            i_state = dirps();
  
            if ( *headp != NULLBUF )
            {
                rx_mbufp->anext = *headp;
                *headp = rx_mbufp;
            }
            else
            {
                *headp = rx_mbufp;
  
                /* done in alloc_mbuf() */
                /* rx_mbufp->anext = NULLBUF; */
            }
            (*rxavailcount)++;
            restore(i_state);
  
            getcount--;
  
            gotcount++;
        }
  
    }
    /* All done... now free any accumulated non-dma_able buffers */
    if(badlist != NULLBUF)free_p(badlist);
  
    return;
}
  
#endif /* PACKETWIN */
  
