1 // license:GPL-2.0+
2 // copyright-holders:Dirk Best
3 /***************************************************************************
4 
5     Commodore A590 / A2091
6 
7     DMAC based HD controller for the Amiga 500 and Zorro-II
8 
9 ***************************************************************************/
10 
11 #include "emu.h"
12 #include "a590.h"
13 #include "machine/nscsi_bus.h"
14 #include "bus/nscsi/devices.h"
15 
16 
17 //**************************************************************************
18 //  DEVICE DEFINITIONS
19 //**************************************************************************
20 
21 DEFINE_DEVICE_TYPE_NS(ZORRO_A590,  bus::amiga::zorro, a590_device,  "zorro_a590",  "CBM A590 HD Controller")
22 DEFINE_DEVICE_TYPE_NS(ZORRO_A2091, bus::amiga::zorro, a2091_device, "zorro_a2091", "CBM A2091 HD Controller")
23 
24 
25 namespace bus { namespace amiga { namespace zorro {
26 
27 //-------------------------------------------------
28 //  input_ports - device-specific input ports
29 //-------------------------------------------------
30 
31 static INPUT_PORTS_START( a590_pcb )
32 	PORT_START("dips")
33 	PORT_DIPNAME(0x01, 0x01, "A590 Auto-Boot")
34 	PORT_DIPLOCATION("DIP:1")
35 	PORT_DIPSETTING(0x00, "Enabled")
36 	PORT_DIPSETTING(0x01, "Disabled")
37 	PORT_DIPNAME(0x02, 0x00, "A590 LUN")
38 	PORT_DIPLOCATION("DIP:2")
39 	PORT_DIPSETTING(0x00, "Disabled")
40 	PORT_DIPSETTING(0x02, "Enabled")
41 	PORT_DIPNAME(0x04, 0x04, "A590 Wait period")
42 	PORT_DIPLOCATION("DIP:3")
43 	PORT_DIPSETTING(0x00, "Short")
44 	PORT_DIPSETTING(0x04, "Long")
45 	PORT_DIPNAME(0x08, 0x00, "A590 Reserved")
46 	PORT_DIPLOCATION("DIP:4")
47 	PORT_DIPSETTING(0x00, "Enabled")
48 	PORT_DIPSETTING(0x08, "Disabled")
49 	PORT_START("jp1")
50 	PORT_DIPNAME(0x0f, 0x01, "A590 Memory size")
51 	PORT_DIPLOCATION("JP1:1,2,3,4")
52 	PORT_DIPSETTING(0x01, "Amnesia")
53 	PORT_DIPSETTING(0x02, "512K")
54 	PORT_DIPSETTING(0x04, "1MB")
55 	PORT_DIPSETTING(0x08, "2MB")
56 	PORT_START("jp2")
57 	PORT_DIPNAME(0x01, 0x00, "A590 Drive LED")
58 	PORT_DIPLOCATION("JP2:1")
59 	PORT_DIPSETTING(0x00, "XT Drive")
60 	PORT_DIPSETTING(0x01, "SCSI Drive")
61 	PORT_START("jp4")
62 	PORT_DIPNAME(0x01, 0x00, "A590 Interrupt")
63 	PORT_DIPLOCATION("JP4:1")
64 	PORT_DIPSETTING(0x00, "INT 2")
65 	PORT_DIPSETTING(0x01, "INT 6")
66 INPUT_PORTS_END
67 
device_input_ports() const68 ioport_constructor a590_device::device_input_ports() const
69 {
70 	return INPUT_PORTS_NAME( a590_pcb );
71 }
72 
73 static INPUT_PORTS_START( a2091_pcb )
74 	PORT_START("jp1")
75 	PORT_DIPNAME(0x0f, 0x01, "A2091 Memory size")
76 	PORT_DIPLOCATION("JP1:1,2,3,4")
77 	PORT_DIPSETTING(0x01, "0K")
78 	PORT_DIPSETTING(0x02, "512K")
79 	PORT_DIPSETTING(0x04, "1MB")
80 	PORT_DIPSETTING(0x08, "2MB")
81 	PORT_START("jp2")
82 	PORT_DIPNAME(0x01, 0x00, "A2091 Auto-Boot")
83 	PORT_DIPLOCATION("JP2:1")
84 	PORT_DIPSETTING(0x00, "Enabled")
85 	PORT_DIPSETTING(0x01, "Disabled")
86 	PORT_START("jp3")
87 	PORT_DIPNAME(0x01, 0x00, "A2091 Interrupt")
88 	PORT_DIPLOCATION("JP3:1")
89 	PORT_DIPSETTING(0x00, "INT 2")
90 	PORT_DIPSETTING(0x01, "INT 6")
91 	PORT_START("jp5")
92 	PORT_DIPNAME(0x01, 0x00, "A2091 LUN")
93 	PORT_DIPLOCATION("JP5:1")
94 	PORT_DIPSETTING(0x00, "Disabled")
95 	PORT_DIPSETTING(0x01, "Enabled")
96 	PORT_DIPNAME(0x02, 0x00, "A2091 Time-Out")
97 	PORT_DIPLOCATION("JP5:2")
98 	PORT_DIPSETTING(0x00, "Short")
99 	PORT_DIPSETTING(0x02, "Long")
100 	PORT_DIPNAME(0x04, 0x00, "A2091 Reserved")
101 	PORT_DIPLOCATION("JP5:3")
102 	PORT_DIPSETTING(0x00, "Disabled")
103 	PORT_DIPSETTING(0x02, "Enabled")
104 	PORT_START("jp201")
105 	PORT_DIPNAME(0x01, 0x00, "A2091 WD33C93 Clock")
106 	PORT_DIPLOCATION("JP201:1")
107 	PORT_DIPSETTING(0x00, "7 MHz")
108 	PORT_DIPSETTING(0x01, "14 MHz")
109 INPUT_PORTS_END
110 
device_input_ports() const111 ioport_constructor a2091_device::device_input_ports() const
112 {
113 	return INPUT_PORTS_NAME( a2091_pcb );
114 }
115 
116 //-------------------------------------------------
117 //  device_add_mconfig - add device configuration
118 //-------------------------------------------------
119 
wd33c93(device_t * device)120 void dmac_hdc_device_base::wd33c93(device_t *device)
121 {
122 	device->set_clock(10000000);
123 	downcast<wd33c93a_device *>(device)->irq_cb().set(*this, FUNC(dmac_hdc_device_base::scsi_irq_w));
124 	downcast<wd33c93a_device *>(device)->drq_cb().set(*this, FUNC(dmac_hdc_device_base::scsi_drq_w));
125 }
126 
device_add_mconfig(machine_config & config)127 void dmac_hdc_device_base::device_add_mconfig(machine_config &config)
128 {
129 	amiga_dmac_device &dmac(AMIGA_DMAC(config, "dmac", 0));
130 	dmac.scsi_read_handler().set(FUNC(dmac_hdc_device_base::dmac_scsi_r));
131 	dmac.scsi_write_handler().set(FUNC(dmac_hdc_device_base::dmac_scsi_w));
132 	dmac.int_handler().set(FUNC(dmac_hdc_device_base::dmac_int_w));
133 	dmac.cfgout_handler().set(FUNC(dmac_hdc_device_base::dmac_cfgout_w));
134 
135 	NSCSI_BUS(config, "scsi", 0);
136 	NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr, false);
137 	NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, "harddisk", false);
138 	NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
139 	NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
140 	NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
141 	NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr, false);
142 	NSCSI_CONNECTOR(config, "scsi:7").option_set("wd33c93", WD33C93A)
143 			.machine_config([this] (device_t *device) { wd33c93(device); });
144 }
145 
146 
147 //-------------------------------------------------
148 //  rom_region - device-specific ROM region
149 //-------------------------------------------------
150 
151 ROM_START( dmac_hdc )
152 	ROM_REGION16_BE(0x8000, "bootrom", 0)
153 	ROM_DEFAULT_BIOS("v70")
154 
155 	ROM_SYSTEM_BIOS(0, "v46", "Version 4.6") // a590 only?
156 	ROMX_LOAD("390389-02.u13", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(0)) // checksum-16: d703
157 	ROMX_LOAD("390388-02.u12", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(0)) // checksum-16: e7e4
158 	ROMX_LOAD("390389-02.u13", 0x4000, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(0))
159 	ROMX_LOAD("390388-02.u12", 0x4001, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(0))
160 
161 	ROM_SYSTEM_BIOS(1, "v592", "Version 5.92") // a2091 only?
162 	ROMX_LOAD("390508-02_a2091_low_byte_u13_v5.92.u13",  0x0000, 0x2000, CRC(4bedbcb1) SHA1(0b97991d7058a8d0c8d000409b4b82bb96ca1dc9), ROM_SKIP(1) | ROM_BIOS(1)) // checksum-16: 23d8 (?)
163 	ROMX_LOAD("390509-02_a2091_high_byte_u12_v5.92.u12", 0x0001, 0x2000, CRC(8f9dd6f8) SHA1(3a8a4639a498bf9a95cb11c45c13687efa714942), ROM_SKIP(1) | ROM_BIOS(1)) // checksum-16: 288c (ok)
164 	ROMX_LOAD("390508-02_a2091_low_byte_u13_v5.92.u13",  0x4000, 0x2000, CRC(4bedbcb1) SHA1(0b97991d7058a8d0c8d000409b4b82bb96ca1dc9), ROM_SKIP(1) | ROM_BIOS(1))
165 	ROMX_LOAD("390509-02_a2091_high_byte_u12_v5.92.u12", 0x4001, 0x2000, CRC(8f9dd6f8) SHA1(3a8a4639a498bf9a95cb11c45c13687efa714942), ROM_SKIP(1) | ROM_BIOS(1))
166 
167 	ROM_SYSTEM_BIOS(2, "v60", "Version 6.0") // a590 only?
168 	ROMX_LOAD("390389-03.u13", 0x0000, 0x2000, CRC(2e77bbff) SHA1(8a098845068f32cfa4d34a278cd290f61d35a52c), ROM_SKIP(1) | ROM_BIOS(2)) // checksum-16: cbe8 (ok)
CRC(b0b8cf24)169 	ROMX_LOAD("390388-03.u12", 0x0001, 0x2000, CRC(b0b8cf24) SHA1(fcf4017505f4d441814b45d559c19eab43816b30), ROM_SKIP(1) | ROM_BIOS(2)) // checksum-16: dfa0 (ok)
170 	ROMX_LOAD("390389-03.u13", 0x4000, 0x2000, CRC(2e77bbff) SHA1(8a098845068f32cfa4d34a278cd290f61d35a52c), ROM_SKIP(1) | ROM_BIOS(2))
171 	ROMX_LOAD("390388-03.u12", 0x4001, 0x2000, CRC(b0b8cf24) SHA1(fcf4017505f4d441814b45d559c19eab43816b30), ROM_SKIP(1) | ROM_BIOS(2))
172 
173 	// changelog v6.1: prevent accesses to location 0 by application programs
174 	ROM_SYSTEM_BIOS(3, "v61", "Version 6.1")
175 	ROMX_LOAD("390721-01.u13", 0x0000, 0x2000, CRC(00dbf615) SHA1(503940d04fb3b49eaa61100fd3a487018b35e25a), ROM_SKIP(1) | ROM_BIOS(3)) // checksum-16: f4b8 (ok)
176 	ROMX_LOAD("390722-01.u12", 0x0001, 0x2000, CRC(c460cfdb) SHA1(0de457daec3b84f75e8fb344defe24ce56cda3e0), ROM_SKIP(1) | ROM_BIOS(3)) // checksum-16: 088b (ok)
177 	ROMX_LOAD("390721-01.u13", 0x4000, 0x2000, CRC(00dbf615) SHA1(503940d04fb3b49eaa61100fd3a487018b35e25a), ROM_SKIP(1) | ROM_BIOS(3))
178 	ROMX_LOAD("390722-01.u12", 0x4001, 0x2000, CRC(c460cfdb) SHA1(0de457daec3b84f75e8fb344defe24ce56cda3e0), ROM_SKIP(1) | ROM_BIOS(3))
179 
180 	// changelog v6.6: fixes dual SCSI problems with the wd33c93a controller
181 	ROM_SYSTEM_BIOS(4, "v66", "Version 6.6")
182 	ROMX_LOAD("390721-02.u13", 0x0000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(4)) // checksum-16: d464 (ok)
183 	ROMX_LOAD("390722-02.u12", 0x0001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(4)) // checksum-16: f929 (ok)
184 	ROMX_LOAD("390721-02.u13", 0x4000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(4))
185 	ROMX_LOAD("390722-02.u12", 0x4001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(4))
186 
187 	// final Commodore released version
188 	ROM_SYSTEM_BIOS(5, "v70", "Version 7.0") // also seen with -07
189 	ROMX_LOAD("390721-04.u13", 0x0000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(5)) // checksum-16: 081c (ok)
190 	ROMX_LOAD("390722-04.u12", 0x0001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(5)) // checksum-16: 3ef2 (ok)
191 	ROMX_LOAD("390721-04.u13", 0x4000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(5))
192 	ROMX_LOAD("390722-04.u12", 0x4001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(5))
193 
194 	// third-party upgrade ROM, requires a small ROM adapter pcb
195 	ROM_SYSTEM_BIOS(6, "g614", "Guru-ROM 6.14")
196 	ROMX_LOAD("gururom_v614.bin", 0x0000, 0x8000, CRC(04e52f93) SHA1(6da21b6f5e8f8837d64507cd8a4d5cdcac4f426b), ROM_GROUPWORD | ROM_BIOS(6))
197 
198 	// pal16l8a
199 	ROM_REGION(0x104, "ram_controller", 0)
200 	ROM_LOAD("390333-03.u5", 0x000, 0x104, CRC(dc4a8d9b) SHA1(761a1318106e49057f95258699076ec1079967ad))
201 ROM_END
202 
203 const tiny_rom_entry *dmac_hdc_device_base::device_rom_region() const
204 {
205 	return ROM_NAME( dmac_hdc );
206 }
207 
208 
209 //**************************************************************************
210 //  LIVE DEVICE
211 //**************************************************************************
212 
213 //-------------------------------------------------
214 //  dmac_hdc_device_base - constructor
215 //-------------------------------------------------
216 
dmac_hdc_device_base(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)217 dmac_hdc_device_base::dmac_hdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
218 	device_t(mconfig, type, tag, owner, clock),
219 	m_int6(false),
220 	m_dmac(*this, "dmac"),
221 	m_wdc(*this, "scsi:7:wd33c93")
222 {
223 }
224 
a590_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)225 a590_device::a590_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
226 	dmac_hdc_device_base(mconfig, ZORRO_A590, tag, owner, clock),
227 	device_exp_card_interface(mconfig, *this),
228 	m_dips(*this, "dips"),
229 	m_jp1(*this, "jp1"),
230 	m_jp2(*this, "jp2"),
231 	m_jp4(*this, "jp4")
232 {
233 }
234 
a2091_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)235 a2091_device::a2091_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
236 	dmac_hdc_device_base(mconfig, ZORRO_A2091, tag, owner, clock),
237 	device_zorro2_card_interface(mconfig, *this),
238 	m_jp1(*this, "jp1"),
239 	m_jp2(*this, "jp2"),
240 	m_jp3(*this, "jp3"),
241 	m_jp5(*this, "jp5"),
242 	m_jp201(*this, "jp201")
243 {
244 }
245 
246 //-------------------------------------------------
247 //  device_start - device-specific startup
248 //-------------------------------------------------
249 
device_start()250 void dmac_hdc_device_base::device_start()
251 {
252 }
253 
device_start()254 void a590_device::device_start()
255 {
256 	dmac_hdc_device_base::device_start();
257 
258 	// setup DMAC
259 	m_dmac->set_address_space(&m_slot->space());
260 	m_dmac->set_rom(memregion("bootrom")->base());
261 }
262 
device_start()263 void a2091_device::device_start()
264 {
265 	dmac_hdc_device_base::device_start();
266 
267 	// setup DMAC
268 	m_dmac->set_address_space(&m_slot->space());
269 	m_dmac->set_rom(memregion("bootrom")->base());
270 }
271 
272 //-------------------------------------------------
273 //  device_reset - device-specific reset
274 //-------------------------------------------------
275 
device_reset()276 void dmac_hdc_device_base::device_reset()
277 {
278 }
279 
resize_ram(int config)280 void dmac_hdc_device_base::resize_ram(int config)
281 {
282 	// allocate space for RAM
283 	switch (config & 0x0f)
284 	{
285 	case 0x01:
286 		m_ram.resize(0);
287 		m_dmac->ramsz_w(0);
288 		break;
289 	case 0x02:
290 		m_ram.resize(0x080000);
291 		m_dmac->ramsz_w(1);
292 		break;
293 	case 0x04:
294 		m_ram.resize(0x100000);
295 		m_dmac->ramsz_w(2);
296 		break;
297 	case 0x08:
298 		m_ram.resize(0x200000);
299 		m_dmac->ramsz_w(3);
300 		break;
301 	}
302 
303 	m_dmac->set_ram(&m_ram[0]);
304 }
305 
device_reset()306 void a590_device::device_reset()
307 {
308 	dmac_hdc_device_base::device_reset();
309 }
310 
device_reset()311 void a2091_device::device_reset()
312 {
313 	dmac_hdc_device_base::device_reset();
314 }
315 
316 
317 //**************************************************************************
318 //  IMPLEMENTATION
319 //**************************************************************************
320 
WRITE_LINE_MEMBER(a590_device::cfgin_w)321 WRITE_LINE_MEMBER( a590_device::cfgin_w )
322 {
323 	// make sure we configure ourselves first
324 	m_int6 = m_jp4->read() & 0x01;
325 	resize_ram(m_dips->read() & 0x0f);
326 
327 	// then tell the DMAC to start configuring
328 	m_dmac->configin_w(state);
329 }
330 
WRITE_LINE_MEMBER(a2091_device::cfgin_w)331 WRITE_LINE_MEMBER( a2091_device::cfgin_w )
332 {
333 	// make sure we configure ourselves first
334 	m_int6 = m_jp3->read() & 0x01;
335 	resize_ram(m_jp1->read() & 0x0f);
336 
337 	// then tell the DMAC to start configuring
338 	m_dmac->configin_w(state);
339 }
340 
dmac_scsi_r(offs_t offset)341 uint8_t dmac_hdc_device_base::dmac_scsi_r(offs_t offset)
342 {
343 	switch (offset)
344 	{
345 	case 0x48: return m_wdc->indir_addr_r();
346 	case 0x49: return m_wdc->indir_reg_r();
347 	}
348 
349 	return 0xff;
350 }
351 
dmac_scsi_w(offs_t offset,uint8_t data)352 void dmac_hdc_device_base::dmac_scsi_w(offs_t offset, uint8_t data)
353 {
354 	switch (offset)
355 	{
356 	case 0x48: m_wdc->indir_addr_w(data); break;
357 	case 0x49: m_wdc->indir_reg_w(data); break;
358 	}
359 }
360 
WRITE_LINE_MEMBER(dmac_hdc_device_base::dmac_int_w)361 WRITE_LINE_MEMBER( dmac_hdc_device_base::dmac_int_w )
362 {
363 	if (m_int6)
364 		int6_w(state);
365 	else
366 		int2_w(state);
367 }
368 
WRITE_LINE_MEMBER(dmac_hdc_device_base::scsi_irq_w)369 WRITE_LINE_MEMBER( dmac_hdc_device_base::scsi_irq_w )
370 {
371 	// should be or'ed with xt-ide IRQ
372 	m_dmac->intx_w(state);
373 }
374 
WRITE_LINE_MEMBER(dmac_hdc_device_base::scsi_drq_w)375 WRITE_LINE_MEMBER( dmac_hdc_device_base::scsi_drq_w )
376 {
377 	m_dmac->xdreq_w(state);
378 }
379 
380 } } } // namespace bus::amiga::zorro
381