1 // license:BSD-3-Clause 2 // copyright-holders:Curt Coder 3 /*************************************************************************** 4 5 AMD AM9517A/8237A Multimode DMA Controller emulation 6 7 **************************************************************************** 8 _____ _____ 9 _IOR 1 |* \_/ | 40 A7 10 _IOW 2 | | 39 A6 11 _MEMR 3 | | 38 A5 12 _MEMW 4 | | 37 A4 13 * 5 | | 36 _EOP 14 READY 6 | | 35 A3 15 HACK 7 | | 34 A2 16 ADSTB 8 | | 33 A1 17 AEN 9 | | 32 A0 18 HREQ 10 | AM9517A | 31 Vcc 19 _CS 11 | 8237A | 30 DB0 20 CLK 12 | | 29 DB1 21 RESET 13 | | 28 DB2 22 DACK2 14 | | 27 DB3 23 DACK3 15 | | 26 DB4 24 DREQ3 16 | | 25 DACK0 25 DREQ2 17 | | 24 DACK1 26 DREQ1 18 | | 23 DB5 27 DREQ0 19 | | 22 DB6 28 Vss 20 |_____________| 21 DB7 29 30 ***************************************************************************/ 31 32 #ifndef MAME_MACHINE_AM9517_H 33 #define MAME_MACHINE_AM9517_H 34 35 #pragma once 36 37 38 39 /*************************************************************************** 40 TYPE DEFINITIONS 41 ***************************************************************************/ 42 43 // ======================> am9517a_device 44 45 class am9517a_device : public device_t, 46 public device_execute_interface 47 { 48 friend class pcxport_dmac_device; 49 50 public: 51 // construction/destruction 52 am9517a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 53 out_hreq_callback()54 auto out_hreq_callback() { return m_out_hreq_cb.bind(); } out_eop_callback()55 auto out_eop_callback() { return m_out_eop_cb.bind(); } 56 in_memr_callback()57 auto in_memr_callback() { return m_in_memr_cb.bind(); } out_memw_callback()58 auto out_memw_callback() { return m_out_memw_cb.bind(); } 59 in_ior_callback()60 template <unsigned C> auto in_ior_callback() { return m_in_ior_cb[C].bind(); } out_iow_callback()61 template <unsigned C> auto out_iow_callback() { return m_out_iow_cb[C].bind(); } out_dack_callback()62 template <unsigned C> auto out_dack_callback() { return m_out_dack_cb[C].bind(); } 63 64 virtual uint8_t read(offs_t offset); 65 virtual void write(offs_t offset, uint8_t data); 66 67 DECLARE_WRITE_LINE_MEMBER( hack_w ); 68 DECLARE_WRITE_LINE_MEMBER( ready_w ); 69 DECLARE_WRITE_LINE_MEMBER( eop_w ); 70 DECLARE_WRITE_LINE_MEMBER(dreq_w)71 template <unsigned C> DECLARE_WRITE_LINE_MEMBER( dreq_w ) { dma_request(C, state); } 72 DECLARE_WRITE_LINE_MEMBER( dreq0_w ); 73 DECLARE_WRITE_LINE_MEMBER( dreq1_w ); 74 DECLARE_WRITE_LINE_MEMBER( dreq2_w ); 75 DECLARE_WRITE_LINE_MEMBER( dreq3_w ); 76 77 protected: 78 am9517a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); 79 80 // device-level overrides 81 virtual void device_start() override; 82 virtual void device_reset() override; 83 virtual void execute_run() override; 84 85 virtual void end_of_process(); 86 87 virtual void dma_read(); 88 virtual void dma_write(); 89 transfer_size(int const channel)90 virtual int transfer_size(int const channel) const { return 1; } 91 92 int m_icount; 93 uint32_t m_address_mask; 94 95 struct 96 { 97 uint32_t m_address; 98 uint32_t m_count; 99 uint32_t m_base_address; 100 uint32_t m_base_count; 101 uint8_t m_mode; 102 } m_channel[4]; 103 104 int m_msb; 105 int m_hreq; 106 int m_hack; 107 int m_ready; 108 int m_eop; 109 int m_state; 110 int m_current_channel; 111 int m_last_channel; 112 uint8_t m_command; 113 uint8_t m_mask; 114 uint8_t m_status; 115 uint16_t m_temp; 116 uint8_t m_request; 117 118 private: 119 void dma_request(int channel, int state); 120 inline bool is_request_active(int channel); 121 inline bool is_software_request_active(int channel); 122 inline void set_hreq(int state); 123 inline void set_dack(); 124 inline void set_eop(int state); 125 inline int get_state1(bool msb_changed); 126 inline void dma_advance(); 127 128 devcb_write_line m_out_hreq_cb; 129 devcb_write_line m_out_eop_cb; 130 131 devcb_read8 m_in_memr_cb; 132 devcb_write8 m_out_memw_cb; 133 134 devcb_read8::array<4> m_in_ior_cb; 135 devcb_write8::array<4> m_out_iow_cb; 136 devcb_write_line::array<4> m_out_dack_cb; 137 }; 138 139 140 class v5x_dmau_device : public am9517a_device 141 { 142 public: 143 // construction/destruction 144 v5x_dmau_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 145 in_mem16r_callback()146 auto in_mem16r_callback() { return m_in_mem16r_cb.bind(); } out_mem16w_callback()147 auto out_mem16w_callback() { return m_out_mem16w_cb.bind(); } 148 in_io16r_callback()149 template <unsigned C> auto in_io16r_callback() { return m_in_io16r_cb[C].bind(); } out_io16w_callback()150 template <unsigned C> auto out_io16w_callback() { return m_out_io16w_cb[C].bind(); } 151 152 virtual uint8_t read(offs_t offset) override; 153 virtual void write(offs_t offset, uint8_t data) override; 154 155 protected: 156 // device-level overrides 157 virtual void device_start() override; 158 virtual void device_reset() override; 159 160 virtual void dma_read() override; 161 virtual void dma_write() override; 162 transfer_size(int const channel)163 virtual int transfer_size(int const channel) const override { return (m_channel[channel].m_mode & 0x1) ? 2 : 1; } 164 165 // 16 bit transfer callbacks 166 devcb_read16 m_in_mem16r_cb; 167 devcb_write16 m_out_mem16w_cb; 168 devcb_read16::array<4> m_in_io16r_cb; 169 devcb_write16::array<4> m_out_io16w_cb; 170 171 int m_selected_channel; 172 int m_base; 173 uint8_t m_command_high; 174 }; 175 176 177 class pcxport_dmac_device : public am9517a_device 178 { 179 public: 180 // construction/destruction 181 pcxport_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 182 183 protected: 184 virtual void device_reset() override; 185 186 virtual void end_of_process() override; 187 }; 188 189 class eisa_dma_device : public am9517a_device 190 { 191 public: 192 eisa_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 193 get_address_page()194 template <unsigned Channel> u8 get_address_page() { return m_channel[Channel].m_address >> 16; } set_address_page(u8 data)195 template <unsigned Channel> void set_address_page(u8 data) 196 { 197 m_channel[Channel].m_base_address = (m_channel[Channel].m_base_address & 0x0000ffffU) | (u32(data) << 16); 198 m_channel[Channel].m_address = (m_channel[Channel].m_address & 0x0000ffffU) | (u32(data) << 16); 199 } 200 get_address_page_high()201 template <unsigned Channel> u8 get_address_page_high() { return m_channel[Channel].m_address >> 24; } set_address_page_high(u8 data)202 template <unsigned Channel> void set_address_page_high(u8 data) 203 { 204 m_channel[Channel].m_base_address = (m_channel[Channel].m_base_address & 0x00ffffffU) | (u32(data) << 24); 205 m_channel[Channel].m_address = (m_channel[Channel].m_address & 0x00ffffffU) | (u32(data) << 24); 206 } 207 get_count_high()208 template <unsigned Channel> u8 get_count_high() { return m_channel[Channel].m_count >> 16; } set_count_high(u8 data)209 template <unsigned Channel> void set_count_high(u8 data) 210 { 211 m_channel[Channel].m_base_count = (m_channel[Channel].m_base_count & 0x0000ffffU) | (u32(data) << 16); 212 m_channel[Channel].m_count = (m_channel[Channel].m_count & 0x0000ffffU) | (u32(data) << 16); 213 } 214 set_ext_mode(u8 data)215 void set_ext_mode(u8 data) 216 { 217 m_ext_mode[data & 3] = data; 218 } 219 get_stop()220 template <unsigned Channel> u32 get_stop() { return m_stop[Channel]; } set_stop(offs_t offset,u32 data,u32 mem_mask)221 template <unsigned Channel> void set_stop(offs_t offset, u32 data, u32 mem_mask) 222 { 223 mem_mask &= 0x00fffffcU; 224 COMBINE_DATA(&m_stop[Channel]); 225 } 226 227 protected: 228 virtual void device_start() override; 229 230 private: 231 u32 m_stop[4]; 232 u8 m_ext_mode[4]; 233 }; 234 235 // device type definition 236 DECLARE_DEVICE_TYPE(AM9517A, am9517a_device) 237 DECLARE_DEVICE_TYPE(V5X_DMAU, v5x_dmau_device) 238 DECLARE_DEVICE_TYPE(PCXPORT_DMAC, pcxport_dmac_device) 239 DECLARE_DEVICE_TYPE(EISA_DMA, eisa_dma_device) 240 241 #endif // MAME_MACHINE_AM9517_H 242