/*
 * handler.h
 *
 * Author: Tomi Ollila <too@cs.hut.fi>
 *
 * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
 *                    All rights reserved.
 *
 * Created: Sun Sep  5 22:46:50 1993 too
 * Last modified: Mon Nov 15 23:26:52 1993 too
 *
 * $Id: handler.h,v 1.2 1993/11/17 12:06:50 too Exp $
 *
 * HISTORY
 * $Log: handler.h,v $
 * Revision 1.2  1993/11/17  12:06:50  too
 * *** empty log message ***
 *
 * Revision 1.1  1993/10/24  12:50:39  too
 * Initial revision
 *
 */

#ifndef _HANDLER_H_
#define _HANDLER_H_

#ifndef EXEC_MEMORY_H
#include <exec/memory.h>
#endif

#ifndef DEVICES_TIMER_H
#include <devices/timer.h>
#endif

#if !defined (_MULDIV_H_) && defined (__GNUC__)
#include "muldiv.h"
#endif

/*
 * Timer stuff
 */

static inline void Send_Timeout(struct timerequest * tr, LONG microtime)
{
#ifdef __GNUC__
  divmodu(tr->tr_time.tv_secs, tr->tr_time.tv_micro, microtime, 1000000);
#else
  tr->tr_time.tv_secs = microtime / 1000000;
  tr->tr_time.tv_micro = microtime % 1000000;
#endif  
  SendIO((struct IORequest *)tr);
}

static inline void Abort_Timeout(struct timerequest * tr)
{
  AbortIO((struct IORequest *)tr);
  WaitIO((struct IORequest *)tr);
}

/***************************************************************************/

/*
 * Macros for using packet information.
 */
#define msgToPkt(msg) ((struct DosPacket *)msg->mn_Node.ln_Name)
#define pktReplyTask(pkt) (pkt->dp_Port->mp_SigTask)

/*
 * Misc macros.
 */
#define EmptyList(list) (((struct List *)list)->lh_Head->ln_Succ == NULL)

static inline void * getBuffer(struct List * list, int size)
{
  if (EmptyList(list))
    return AllocMem(size, MEMF_PUBLIC);
  else
    return RemHead(list);
}

static inline void * getBufferInitNew(struct List * list, int size,
				      void * nd, int nds)
{
  if (EmptyList(list)) {
    void * p;
    if ((p = AllocMem(size, MEMF_PUBLIC | MEMF_CLEAR)) != NULL)
      CopyMem(nd, p, nds);
    return p;
  }
  else
    return RemHead(list);
}

/***************************************************************************/

/*
 * scan through list and execute 'code' for each list item.
 */
#define For_Each_List_Item(list, type, node, code) do { \
   type node; \
   for (node = (type)((struct List *)(list))->lh_Head; \
	((struct Node *)node)->ln_Succ; \
	node = (type)((struct Node *)node)->ln_Succ) \
     code } while (0)

/*
 * same as before, but cache next node since current item is FreeMem()med
 */
#define For_Each_List_Item_CacheNext(list, type, node, code) do { \
   type node; \
   struct Node * next; \
   for (node = (type)((struct List *)(list))->lh_Head; \
	(next = ((struct Node *)node)->ln_Succ); \
	node = (type)next) \
     code } while (0)

#if 0
#define For_Each_List_Item_CacheNext2(list, type, node, code) do { \
   type node; \
   struct Node * next = ((struct List *)(list))->lh_Head; \
   for (node = (type)((struct List *)(list))->lh_Head; \
	next; \
	node = (type)next) \
     { next = ((struct Node *)node)->ln_Succ; code } } while (0)

#define For_Each_List_Item_CacheNext2(list, type, node, code) do { \
   type node; \
   struct Node * next = ((struct List *)(list))->lh_Head; \
     \
   while (1) { \
     node = (type)next; \
     next = next->ln_Succ; \
     if (next) \
       code \
     else \
       break; \
     } \
   } while (0)

#endif

#endif /* _HANDLER_H_ */

