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