/*************************************************************************** Intel 8237 Programmable DMA Controller emulation Copyright Nicola Salmoria and the MAME Team. Visit http://mamedev.org for licensing and usage restrictions. **************************************************************************** _____ _____ _I/OR 1 |* \_/ | 40 A7 _I/OW 2 | | 39 A6 _MEMR 3 | | 38 A5 _MEMW 4 | | 37 A4 5 | | 36 _EOP READY 6 | | 35 A3 HLDA 7 | | 34 A2 ADSTB 8 | | 33 A1 AEN 9 | | 32 A0 HRQ 10 | 8237 | 31 Vcc _CS 11 | | 30 DB0 CLK 12 | | 29 DB1 RESET 13 | | 28 DB2 DACK2 14 | | 27 DB3 DACK3 15 | | 26 DB4 DREQ3 16 | | 25 DACK0 DREQ2 17 | | 24 DACK1 DREQ1 18 | | 23 DB5 DREQ0 19 | | 22 DB6 GND 20 |_____________| 21 DB7 ***************************************************************************/ #pragma once #ifndef __I8237__ #define __I8237__ #include "emu.h" /*************************************************************************** DEVICE CONFIGURATION MACROS ***************************************************************************/ #define MCFG_I8237_ADD(_tag, _clock, _config) \ MCFG_DEVICE_ADD(_tag, I8237, _clock) \ MCFG_DEVICE_CONFIG(_config) #define I8237_INTERFACE(_name) \ const i8237_interface (_name) = /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ // ======================> i8237_interface struct i8237_interface { devcb_write_line m_out_hrq_cb; devcb_write_line m_out_eop_cb; /* accessors to main memory */ devcb_read8 m_in_memr_cb; devcb_write8 m_out_memw_cb; /* channel accessors */ devcb_read8 m_in_ior_cb[4]; devcb_write8 m_out_iow_cb[4]; devcb_write_line m_out_dack_cb[4]; }; // ======================> i8237_device class i8237_device : public device_t, public i8237_interface { public: // construction/destruction i8237_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); /* register access */ UINT8 i8237_r(UINT32 offset); void i8237_w(UINT32 offset, UINT8 data); /* hold acknowledge */ void i8237_hlda_w(UINT8 state) { m_hlda = state; } /* data request */ void i8237_drq_write(int channel, int state); void i8237_timerproc(); protected: // device-level overrides virtual void device_config_complete(); virtual void device_start(); virtual void device_reset(); virtual void device_post_load() { } virtual void device_clock_changed() { } static TIMER_CALLBACK( i8237_timerproc_callback ); static TIMER_CALLBACK( receive_event_callback ); private: void i8237_do_read(); void i8237_do_write(); void i8237_advance(); void i8327_set_dack(int channel); /* States that the i8237 device can be in */ enum dma8237_state { DMA8237_SI, /* Idle state */ DMA8237_S0, /* HRQ has been triggered, waiting to receive HLDA */ // DMA8237_SW, /* Wait state */ DMA8237_SC, /* Cascade mode, waiting for peripheral */ /* Normal transfer states */ DMA8237_S1, /* Output A8-A15; only used when A8-A15 really needs to be output */ DMA8237_S2, /* Output A0-A7 */ DMA8237_S3, /* Initiate read; skipped in compressed timing. On the S2->S3 transition DACK is set. */ DMA8237_S4, /* Perform read/write */ /* Memory to memory transfer states */ DMA8237_S11, /* Output A8-A15 */ // DMA8237_S12, /* Output A0-A7 */ // DMA8237_S13, /* Initiate read */ // DMA8237_S14, /* Perform read/write */ // DMA8237_S21, /* Output A8-A15 */ // DMA8237_S22, /* Output A0-A7 */ // DMA8237_S23, /* Initiate read */ // DMA8237_S24, /* Perform read/write */ }; devcb_resolved_write_line m_out_hrq_func; devcb_resolved_write_line m_out_eop_func; devcb_resolved_read8 m_in_memr_func; devcb_resolved_write8 m_out_memw_func; emu_timer *m_timer; struct { devcb_resolved_read8 m_in_ior_func; devcb_resolved_write8 m_out_iow_func; devcb_resolved_write_line m_out_dack_func; UINT16 m_base_address; UINT16 m_base_count; UINT16 m_address; UINT16 m_count; UINT8 m_mode; int m_high_address_changed; } m_chan[4]; UINT32 m_msb : 1; UINT32 m_eop : 1; UINT8 m_temp; UINT8 m_temporary_data; UINT8 m_command; UINT8 m_drq; UINT8 m_mask; UINT8 m_hrq; UINT8 m_hlda; /* bits 0- 3 : Terminal count for channels 0-3 * bits 4- 7 : Transfer in progress for channels 0-3 */ UINT8 m_status; dma8237_state m_state; /* State the device is currently in */ int m_service_channel; /* Channel we will be servicing */ int m_last_service_channel; /* Previous channel we serviced; used to determine channel priority. */ }; // device type definition extern const device_type I8237; /*************************************************************************** PROTOTYPES ***************************************************************************/ /* register access */ READ8_DEVICE_HANDLER( i8237_r ); WRITE8_DEVICE_HANDLER( i8237_w ); /* hold acknowledge */ WRITE_LINE_DEVICE_HANDLER( i8237_hlda_w ); /* ready */ WRITE_LINE_DEVICE_HANDLER( i8237_ready_w ); /* data request */ WRITE_LINE_DEVICE_HANDLER( i8237_dreq0_w ); WRITE_LINE_DEVICE_HANDLER( i8237_dreq1_w ); WRITE_LINE_DEVICE_HANDLER( i8237_dreq2_w ); WRITE_LINE_DEVICE_HANDLER( i8237_dreq3_w ); /* end of process */ WRITE_LINE_DEVICE_HANDLER( i8237_eop_w ); #endif