1 // license:BSD-3-Clause
2 // copyright-holders:Nigel Barnes
3 /**********************************************************************
4
5 Acorn SCSI Host Adaptor
6
7 Known SCSI controller boards used:
8 Adaptec ACB-4000A
9
10 Known SCSI devices using adaptor:
11 SCSI ID 0 - Acorn Winchester 110: Seagate ST412 + Adaptec ACB-4000A
12 Acorn Winchester 120: NEC D5126 + Adaptec ACB-4000A
13 Acorn Winchester 130: Rodime R0203E + Adaptec ACB-4000A
14 SCSI ID 1 - Digistore Tape Streamer: Archive 2060S
15
16 Compatible 3rd party Winchesters using Akhter Host Adaptor:
17 Technomatic 20MB: Seagate ST225 + Adaptec ACB-4070
18 Technomatic 30MB:
19 Technomatic 40MB:
20
21 Additional notes:
22 The Digistore used a modified Acorn Host Adaptor, it re-mapped
23 the device to &FC44-47, from &FC40-43. This allows both the
24 Digistore and Winchester to co-exist.
25
26 Useful CHD parameters:
27 10MB -chs 306,4,33 -ss=256
28 20MB -chs 612,4,33 -ss=256
29 30MB -chs 640,6,33 -ss=256
30 512MB -chs 3971,16,33 -ss 256
31
32 TODO:
33 - test formatting, may require specific ACB-4000A commands.
34
35 **********************************************************************/
36
37 #include "emu.h"
38 #include "scsi.h"
39 #include "machine/nscsi_bus.h"
40 #include "bus/nscsi/devices.h"
41
42
43 //**************************************************************************
44 // DEVICE DEFINITIONS
45 //**************************************************************************
46
47 DEFINE_DEVICE_TYPE(BBC_SCSI, bbc_scsi_device, "bbc_scsi", "Acorn SCSI Host Adaptor");
48 DEFINE_DEVICE_TYPE(BBC_AWHD, bbc_awhd_device, "bbc_awhd", "Acorn Winchester Disc");
49
50
51 //-------------------------------------------------
52 // device_add_mconfig - add device configuration
53 //-------------------------------------------------
54
device_add_mconfig(machine_config & config)55 void bbc_scsi_device::device_add_mconfig(machine_config& config)
56 {
57 NSCSI_BUS(config, "scsi");
58 NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr);
59 NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr);
60 NSCSI_CONNECTOR(config, "scsi:7", default_scsi_devices, "scsicb", true)
61 .option_add_internal("scsicb", NSCSI_CB)
62 .machine_config([this](device_t* device) {
63 downcast<nscsi_callback_device&>(*device).bsy_callback().set(*this, FUNC(bbc_scsi_device::bsy_w));
64 downcast<nscsi_callback_device&>(*device).req_callback().set(*this, FUNC(bbc_scsi_device::req_w));
65 });
66 }
67
device_add_mconfig(machine_config & config)68 void bbc_awhd_device::device_add_mconfig(machine_config &config)
69 {
70 bbc_scsi_device::device_add_mconfig(config);
71
72 /* Adaptec ACB-4000A */
73 subdevice<nscsi_connector>("scsi:0")->set_default_option("harddisk");
74 subdevice<nscsi_connector>("scsi:0")->set_fixed(true);
75
76 BBC_1MHZBUS_SLOT(config, m_1mhzbus, DERIVED_CLOCK(1, 1), bbc_1mhzbus_devices, nullptr);
77 m_1mhzbus->irq_handler().set(m_1mhzbus, FUNC(bbc_1mhzbus_slot_device::irq_w));
78 m_1mhzbus->nmi_handler().set(m_1mhzbus, FUNC(bbc_1mhzbus_slot_device::nmi_w));
79 }
80
81
82 //**************************************************************************
83 // LIVE DEVICE
84 //**************************************************************************
85
86 //-------------------------------------------------
87 // bbc_scsi_device - constructor
88 //-------------------------------------------------
89
bbc_scsi_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)90 bbc_scsi_device::bbc_scsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
91 : device_t(mconfig, type, tag, owner, clock)
92 , device_bbc_1mhzbus_interface(mconfig, *this)
93 , m_scsi(*this, "scsi:7:scsicb")
94 {
95 }
96
bbc_scsi_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)97 bbc_scsi_device::bbc_scsi_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
98 : bbc_scsi_device(mconfig, BBC_SCSI, tag, owner, clock)
99 {
100 }
101
bbc_awhd_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)102 bbc_awhd_device::bbc_awhd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
103 : bbc_scsi_device(mconfig, BBC_AWHD, tag, owner, clock)
104 , m_1mhzbus(*this, "1mhzbus")
105 {
106 }
107
108 //-------------------------------------------------
109 // device_start - device-specific startup
110 //-------------------------------------------------
111
device_start()112 void bbc_scsi_device::device_start()
113 {
114 /* register for save states */
115 save_item(NAME(m_irq_enable));
116 save_item(NAME(m_irq_state));
117 }
118
119 //**************************************************************************
120 // IMPLEMENTATION
121 //**************************************************************************
122
fred_r(offs_t offset)123 uint8_t bbc_scsi_device::fred_r(offs_t offset)
124 {
125 uint8_t data = 0xff;
126
127 switch (offset)
128 {
129 case 0x40:
130 data = m_scsi->read();
131 m_scsi->ack_w(1);
132 break;
133 case 0x41:
134 data = (m_scsi->msg_r() << 0)
135 | (m_scsi->bsy_r() << 1)
136 | (m_irq_state << 4)
137 | (m_scsi->req_r() << 5)
138 | (m_scsi->io_r() << 6)
139 | (m_scsi->cd_r() << 7);
140 break;
141 }
142
143 return data;
144 }
145
fred_w(offs_t offset,uint8_t data)146 void bbc_scsi_device::fred_w(offs_t offset, uint8_t data)
147 {
148 switch (offset)
149 {
150 case 0x40:
151 m_scsi->write(data);
152 m_scsi->ack_w(1);
153 break;
154 case 0x42:
155 m_scsi->sel_w(1);
156 break;
157 case 0x43:
158 m_irq_enable = BIT(data, 0);
159 break;
160 }
161 }
162
WRITE_LINE_MEMBER(bbc_scsi_device::bsy_w)163 WRITE_LINE_MEMBER(bbc_scsi_device::bsy_w)
164 {
165 m_scsi->sel_w(0);
166 }
167
WRITE_LINE_MEMBER(bbc_scsi_device::req_w)168 WRITE_LINE_MEMBER(bbc_scsi_device::req_w)
169 {
170 m_scsi->ack_w(0);
171
172 m_irq_state = (m_irq_enable && !state) ? 0 : 1;
173 m_slot->irq_w(m_irq_state ? CLEAR_LINE : ASSERT_LINE);
174 }
175
176
fred_r(offs_t offset)177 uint8_t bbc_awhd_device::fred_r(offs_t offset)
178 {
179 uint8_t data = 0xff;
180
181 data &= bbc_scsi_device::fred_r(offset);
182 data &= m_1mhzbus->fred_r(offset);
183
184 return data;
185 }
186
fred_w(offs_t offset,uint8_t data)187 void bbc_awhd_device::fred_w(offs_t offset, uint8_t data)
188 {
189 bbc_scsi_device::fred_w(offset, data);
190 m_1mhzbus->fred_w(offset, data);
191 }
192
jim_r(offs_t offset)193 uint8_t bbc_awhd_device::jim_r(offs_t offset)
194 {
195 return m_1mhzbus->jim_r(offset);
196 }
197
jim_w(offs_t offset,uint8_t data)198 void bbc_awhd_device::jim_w(offs_t offset, uint8_t data)
199 {
200 m_1mhzbus->jim_w(offset, data);
201 }
202