Esempio n. 1
0
inline void am9517a_device::set_eop(int state)
{
	if (m_eop != state)
	{
		m_out_eop_func(state);

		m_eop = state;
	}
}
Esempio n. 2
0
void i8237_device::i8237_timerproc()
{
	/* Check if operation is disabled */
	if ( m_command & 0x04 )
	{
		return;
	}

	switch ( m_state )
	{

	case DMA8237_SI:
	{
		/* Make sure EOP is high */
		if ( !m_eop )
		{
			m_eop = 1;
			m_out_eop_func(m_eop ? ASSERT_LINE : CLEAR_LINE);
		}

		/* Check if a new DMA request has been received. */
		/* Bit 6 of the command register determines whether the DREQ signals are active
          high or active low. */
		UINT16 pending_request = ( ( m_command & 0x40 ) ? ~m_drq : m_drq ) & ~m_mask;

		if ( pending_request & 0x0f )
		{
			int prio_channel = 0;

			/* Determine the channel that should be serviced */
			int channel = ( m_command & 0x10 ) ? m_last_service_channel : 3;
			for ( int i = 0; i < 4; i++ )
			{
				if ( pending_request & ( 1 << channel ) )
				{
					prio_channel = channel;
				}
				channel = ( channel - 1 ) & 0x03;
			}

			/* Store the channel we will be servicing and go to the next state */
			m_service_channel = prio_channel;
			m_last_service_channel = prio_channel;

			m_hrq = 1;
			m_out_hrq_func(m_hrq);
			m_state = DMA8237_S0;

			m_timer->enable( true );
		}
		else if (m_command == 3 && (m_drq & 1))
		{
			/* Memory-to-memory transfers */
			m_hlda = 1;
			m_state = DMA8237_S0;
		}
		else
		{
			m_timer->enable( false );
		}
		break;
	}

	case DMA8237_S0:
		/* S0 is the first of the DMA service. We have requested a hold but are waiting
          for confirmation. */
		if ( m_hlda )
		{
			if ( DMA_MODE_TRANSFERMODE( m_chan[m_service_channel].m_mode ) == DMA8237_CASCADE_MODE )
			{
				/* Cascade Mode, set DACK */
				i8327_set_dack(m_service_channel);

				/* Wait until peripheral is done */
				m_state = DMA8237_SC;
			}
			else
			{
				if ( m_command & 0x01 )
				{
					/* Memory-to-memory transfers */
					m_state = DMA8237_S11;
				}
				else
				{
					/* Regular transfers */
					m_state = DMA8237_S1;
				}
			}
		}
		break;

	case DMA8237_SC:	/* Cascade mode, waiting until peripheral is done */
		if ( ! ( m_drq & ( 0x01 << m_service_channel ) ) )
		{
			m_hrq = 0;
			m_hlda = 0;
			m_out_hrq_func(m_hrq);
			m_state = DMA8237_SI;

			/* Clear DACK */
			i8327_set_dack(-1);
		}

		/* Not sure if this is correct, documentation is not clear */
		/* Check if EOP output needs to be asserted  */
		if ( m_status & ( 0x01 << m_service_channel ) )
		{
			m_eop = 0;
			m_out_eop_func(m_eop ? ASSERT_LINE : CLEAR_LINE);
		}
		break;

	case DMA8237_S1:	/* Output A8-A15 */
		m_state = DMA8237_S2;
		break;

	case DMA8237_S2:	/* Output A7-A0 */
		/* set DACK */
		i8327_set_dack(m_service_channel);

		/* Check for compressed timing */
		if ( m_command & 0x08 )
		{
			m_state = DMA8237_S4;
		}
		else
		{
			m_state = DMA8237_S3;
		}
		break;

	case DMA8237_S3:	/* Initiate read */
		i8237_do_read();
		m_state = DMA8237_S4;
		break;

	case DMA8237_S4:	/* Perform read/write */
		/* Perform read when in compressed timing mode */
		if ( m_command & 0x08 )
		{
			i8237_do_read();
		}

		/* Perform write */
		i8237_do_write();


		/* Advance */
		i8237_advance();

		{
			int channel = m_service_channel;

			switch( DMA_MODE_TRANSFERMODE( m_chan[channel].m_mode ) )
			{
			case DMA8237_DEMAND_MODE:
				/* Check for terminal count or EOP signal or DREQ begin de-asserted */
				if ( ( m_status & ( 0x01 << channel ) ) || !m_eop || !( m_drq & ( 0x01 << channel ) ) )
				{
					m_hrq = 0;
					m_hlda = 0;
					m_out_hrq_func(m_hrq);
					m_state = DMA8237_SI;
				}
				else
				{
					m_state = m_chan[channel].m_high_address_changed ? DMA8237_S1 : DMA8237_S2;
				}
				break;

			case DMA8237_SINGLE_MODE:
				m_hrq = 0;
				m_hlda = 0;
				m_out_hrq_func(m_hrq);
				m_state = DMA8237_SI;
				break;

			case DMA8237_BLOCK_MODE:
				/* Check for terminal count or EOP signal */
				if ( ( m_status & ( 0x01 << channel ) ) || !m_eop )
				{
					m_hrq = 0;
					m_hlda = 0;
					m_out_hrq_func(m_hrq);
					m_state = DMA8237_SI;
				}
				else
				{
					m_state = m_chan[channel].m_high_address_changed ? DMA8237_S1 : DMA8237_S2;
				}
				break;
			}

			/* Check if EOP output needs to be asserted */
			if ( m_status & ( 0x01 << channel ) )
			{
				m_eop = 0;
				m_out_eop_func(m_eop ? ASSERT_LINE : CLEAR_LINE);
			}
		}

		/* clear DACK */
		if ( m_state == DMA8237_SI )
		{
			i8327_set_dack(-1);
		}
		break;

	case DMA8237_S11: /* Output A8-A15 */

//      logerror("###### dma8237_timerproc %s: from %04x count=%x to %04x count=%x\n", tag(),
//              m_chan[0].m_address, m_chan[0].m_count,
//              m_chan[1].m_address, m_chan[1].m_count);

		// FIXME: this will copy bytes correct, but not 16 bit words
		m_temporary_data = m_in_memr_func(m_chan[0].m_address);
		m_out_memw_func(m_chan[1].m_address, m_temporary_data);

		m_service_channel = 0;

		/* Advance */
		i8237_advance();

		// advance destination channel as well
		m_chan[1].m_count--;
		m_chan[1].m_address++;

		if (m_chan[0].m_count == 0xFFFF || m_chan[1].m_count == 0xFFFF) {
			m_hrq = 0;
			m_hlda = 0;
			m_out_hrq_func(m_hrq);
			m_state = DMA8237_SI;
			m_status |= 3; // set TC for channel 0 and 1
			m_drq &= ~3; // clear drq for channel 0 and 1

		//  logerror("!!! dma8237_timerproc DMA8237_S11 %s: m_drq=%x m_command=%x\n", tag(), m_drq, m_command);
		}
		break;
	}
}