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

    z80daisy.c

    Z80/180 daisy chaining support functions.

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

#include "cpuintrf.h"
#include "z80daisy.h"


void z80daisy_reset(const struct z80_irq_daisy_chain *daisy)
{
	/* loop over all devices and call their reset function */
	for ( ; daisy->param != -1; daisy++)
		if (daisy->reset)
			(*daisy->reset)(daisy->param);
}

int z80daisy_inquire_irq_state(const struct z80_irq_daisy_chain *daisy)
{
        /* loop over all devices; dev[0] is highest priority */
        for ( ; daisy->param != -1; daisy++)
        {
                int state = (Z80_DAISY_INT|Z80_DAISY_IEO) & (*daisy->irq_state)(daisy->param);
                if(state)
                   return state;
        }

        return 0;
}

void z80daisy_debug_irq_state(const struct z80_irq_daisy_chain *daisy)
{
        /* loop over all devices; dev[0] is highest priority */
        fprintf(stderr,"DAISY_CHAIN: ");
        for ( ; daisy->param != -1; daisy++)
        {
                int state = (*daisy->irq_state)(daisy->param);
                fprintf(stderr,"%s ",(state & Z80_DAISY_INT)? "INT":((state & Z80_DAISY_IEO)? "IEO":"non"));
        }
        fprintf(stderr,"\n");
}

int z80daisy_update_irq_state(const struct z80_irq_daisy_chain *daisy)
{
	/* loop over all devices; dev[0] is highest priority */
	for ( ; daisy->param != -1; daisy++)
	{
		int state = (*daisy->irq_state)(daisy->param);

		/* if this device is asserting the INT line, that's the one we want */
		if (state & Z80_DAISY_INT)
			return ASSERT_LINE;

		/* if this device is asserting the IEO line, it blocks everyone else */
		if (state & Z80_DAISY_IEO)
			return CLEAR_LINE;
	}

	return CLEAR_LINE;
}


int z80daisy_call_ack_device(const struct z80_irq_daisy_chain *daisy)
{
	/* loop over all devices; dev[0] is the highest priority */
	for ( ; daisy->param != -1; daisy++)
	{
		int state = (*daisy->irq_state)(daisy->param);

		/* if this device is asserting the INT line, that's the one we want */
		if (state & Z80_DAISY_INT)
			return (*daisy->irq_ack)(daisy->param);
	}

	logerror("z80daisy_call_ack_device: failed to find an device to ack!\n");
	return 0;
}


void z80daisy_call_reti_device(const struct z80_irq_daisy_chain *daisy)
{
	/* loop over all devices; dev[0] is the highest priority */
	for ( ; daisy->param != -1; daisy++)
	{
		int state = (*daisy->irq_state)(daisy->param);

		/* if this device is asserting the IEO line, that's the one we want */
		if (state & Z80_DAISY_IEO)
		{
			(*daisy->irq_reti)(daisy->param);
			return;
		}
	}

	logerror("z80daisy_call_reti_device: failed to find an device to reti!\n");
}
