trunk/src/mess/machine/a2hsscsi.c
| r0 | r25514 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | a2hsscsi.c |
| 4 | |
| 5 | Implementation of the Apple II High Speed SCSI Card |
| 6 | |
| 7 | This uses an ASIC called "Sandwich II"; the card itself is |
| 8 | sometimes known as "Cocoon". |
| 9 | |
| 10 | Notes: |
| 11 | C0n0-C0n7 = NCR5380 registers in normal order |
| 12 | C0n8 = DMA address low |
| 13 | C0n9 = DMA address high |
| 14 | C0nA = DMA count low |
| 15 | C0nB = DMA count high |
| 16 | C0nC = DMA control |
| 17 | C0nD = Enable DMA / reset 5380 |
| 18 | C0nE = Priority (read bits 5-7) / Fire watchdog (write bit 7) / RAM bank (write bits 0-3) |
| 19 | C0nF = DMA speed (bit 7 = 0 for fast, 1 for slow) / ROM bank (write bits 0-4) |
| 20 | |
| 21 | DMA control register (C0nC): |
| 22 | 0x01 = pseudo-DMA enable |
| 23 | 0x02 = DMA enable |
| 24 | 0x04 = test mode |
| 25 | 0x08 = disable stop-DMA-on-IRQ |
| 26 | 0x10 = DMA direction (read only) |
| 27 | 0x20 = 5380 IRQ enable |
| 28 | 0x40 = system DMA status (read only) |
| 29 | 0x80 = DMA stopped due to IRQ |
| 30 | |
| 31 | Enable DMA / reset 5380 register (C0nD): |
| 32 | 0x01 = Resume DMA after rollover or IRQ |
| 33 | 0x02 = Reset the 5380 |
| 34 | 0x40 = Clear test mode |
| 35 | 0x80 = Set test mode |
| 36 | |
| 37 | *********************************************************************/ |
| 38 | |
| 39 | #include "a2hsscsi.h" |
| 40 | #include "includes/apple2.h" |
| 41 | #include "machine/scsibus.h" |
| 42 | #include "machine/nscsi_cd.h" |
| 43 | #include "machine/nscsi_hd.h" |
| 44 | |
| 45 | /*************************************************************************** |
| 46 | PARAMETERS |
| 47 | ***************************************************************************/ |
| 48 | |
| 49 | //************************************************************************** |
| 50 | // GLOBAL VARIABLES |
| 51 | //************************************************************************** |
| 52 | |
| 53 | const device_type A2BUS_HSSCSI = &device_creator<a2bus_hsscsi_device>; |
| 54 | |
| 55 | #define SCSI_ROM_REGION "scsi_rom" |
| 56 | #define SCSI_BUS_TAG "scsibus" |
| 57 | #define SCSI_5380_TAG "scsibus:7:ncr5380" |
| 58 | |
| 59 | static MACHINE_CONFIG_FRAGMENT( ncr5380 ) |
| 60 | MCFG_DEVICE_MODIFY(DEVICE_SELF) |
| 61 | MCFG_DEVICE_CLOCK(10000000) |
| 62 | MCFG_NCR5380N_DRQ_HANDLER(DEVWRITELINE("^^", a2bus_hsscsi_device, drq_w)) |
| 63 | MACHINE_CONFIG_END |
| 64 | |
| 65 | static SLOT_INTERFACE_START( hsscsi_devices ) |
| 66 | SLOT_INTERFACE("cdrom", NSCSI_CDROM) |
| 67 | SLOT_INTERFACE("harddisk", NSCSI_HARDDISK) |
| 68 | SLOT_INTERFACE_INTERNAL("ncr5380", NCR5380N) |
| 69 | SLOT_INTERFACE_END |
| 70 | |
| 71 | static MACHINE_CONFIG_FRAGMENT( hsscsi ) |
| 72 | MCFG_SCSIBUS_ADD("scsi") |
| 73 | MCFG_NSCSI_BUS_ADD(SCSI_BUS_TAG) |
| 74 | MCFG_NSCSI_ADD("scsibus:0", hsscsi_devices, 0, false) |
| 75 | MCFG_NSCSI_ADD("scsibus:1", hsscsi_devices, 0, false) |
| 76 | MCFG_NSCSI_ADD("scsibus:2", hsscsi_devices, 0, false) |
| 77 | MCFG_NSCSI_ADD("scsibus:3", hsscsi_devices, 0, false) |
| 78 | MCFG_NSCSI_ADD("scsibus:4", hsscsi_devices, 0, false) |
| 79 | MCFG_NSCSI_ADD("scsibus:5", hsscsi_devices, 0, false) |
| 80 | MCFG_NSCSI_ADD("scsibus:6", hsscsi_devices, "harddisk", false) |
| 81 | MCFG_NSCSI_ADD("scsibus:7", hsscsi_devices, "ncr5380", true) |
| 82 | MCFG_DEVICE_CARD_MACHINE_CONFIG("ncr5380", ncr5380) |
| 83 | MACHINE_CONFIG_END |
| 84 | |
| 85 | ROM_START( hsscsi ) |
| 86 | ROM_REGION(0x8000, SCSI_ROM_REGION, 0) |
| 87 | ROM_LOAD( "341-0803.bin", 0x0000, 0x8000, CRC(2c15618b) SHA1(7d32227299933bfc1b7f8bc2062906fdfe530674) ) |
| 88 | ROM_END |
| 89 | |
| 90 | /*************************************************************************** |
| 91 | FUNCTION PROTOTYPES |
| 92 | ***************************************************************************/ |
| 93 | |
| 94 | //------------------------------------------------- |
| 95 | // machine_config_additions - device-specific |
| 96 | // machine configurations |
| 97 | //------------------------------------------------- |
| 98 | |
| 99 | machine_config_constructor a2bus_hsscsi_device::device_mconfig_additions() const |
| 100 | { |
| 101 | return MACHINE_CONFIG_NAME( hsscsi ); |
| 102 | } |
| 103 | |
| 104 | //------------------------------------------------- |
| 105 | // rom_region - device-specific ROM region |
| 106 | //------------------------------------------------- |
| 107 | |
| 108 | const rom_entry *a2bus_hsscsi_device::device_rom_region() const |
| 109 | { |
| 110 | return ROM_NAME( hsscsi ); |
| 111 | } |
| 112 | |
| 113 | //************************************************************************** |
| 114 | // LIVE DEVICE |
| 115 | //************************************************************************** |
| 116 | |
| 117 | a2bus_hsscsi_device::a2bus_hsscsi_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : |
| 118 | device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
| 119 | device_a2bus_card_interface(mconfig, *this), |
| 120 | m_ncr5380(*this, SCSI_5380_TAG), |
| 121 | m_scsibus(*this, SCSI_BUS_TAG) |
| 122 | { |
| 123 | } |
| 124 | |
| 125 | a2bus_hsscsi_device::a2bus_hsscsi_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 126 | device_t(mconfig, A2BUS_HSSCSI, "Apple II High-Speed SCSI Card", tag, owner, clock, "a2hsscsi", __FILE__), |
| 127 | device_a2bus_card_interface(mconfig, *this), |
| 128 | m_ncr5380(*this, SCSI_5380_TAG), |
| 129 | m_scsibus(*this, SCSI_BUS_TAG) |
| 130 | { |
| 131 | } |
| 132 | |
| 133 | //------------------------------------------------- |
| 134 | // device_start - device-specific startup |
| 135 | //------------------------------------------------- |
| 136 | |
| 137 | void a2bus_hsscsi_device::device_start() |
| 138 | { |
| 139 | // set_a2bus_device makes m_slot valid |
| 140 | set_a2bus_device(); |
| 141 | |
| 142 | astring tempstring; |
| 143 | m_rom = device().machine().root_device().memregion(this->subtag(tempstring, SCSI_ROM_REGION))->base(); |
| 144 | |
| 145 | memset(m_ram, 0, 8192); |
| 146 | |
| 147 | save_item(NAME(m_ram)); |
| 148 | save_item(NAME(m_rambank)); |
| 149 | save_item(NAME(m_rombank)); |
| 150 | save_item(NAME(m_bank)); |
| 151 | save_item(NAME(m_drq)); |
| 152 | save_item(NAME(m_816block)); |
| 153 | } |
| 154 | |
| 155 | void a2bus_hsscsi_device::device_reset() |
| 156 | { |
| 157 | m_rambank = 0; |
| 158 | m_rombank = 0; |
| 159 | m_c0ne = m_c0nf = 0; |
| 160 | m_816block = false; |
| 161 | } |
| 162 | |
| 163 | |
| 164 | /*------------------------------------------------- |
| 165 | read_c0nx - called for reads from this card's c0nx space |
| 166 | -------------------------------------------------*/ |
| 167 | |
| 168 | UINT8 a2bus_hsscsi_device::read_c0nx(address_space &space, UINT8 offset) |
| 169 | { |
| 170 | switch (offset) |
| 171 | { |
| 172 | case 0: |
| 173 | case 1: |
| 174 | case 2: |
| 175 | case 3: |
| 176 | case 4: |
| 177 | case 5: |
| 178 | case 6: |
| 179 | case 7: |
| 180 | // printf("Read 5380 @ %x\n", offset); |
| 181 | return m_ncr5380->read(space, offset); |
| 182 | break; |
| 183 | |
| 184 | case 0xc: |
| 185 | return 0x00; // indicate watchdog? |
| 186 | |
| 187 | case 0xe: // code at cf32 wants to RMW this without killing the ROM bank |
| 188 | return m_c0ne; |
| 189 | |
| 190 | case 0xf: |
| 191 | return m_c0nf; |
| 192 | |
| 193 | default: |
| 194 | printf("Read c0n%x (PC=%x)\n", offset, space.device().safe_pc()); |
| 195 | break; |
| 196 | } |
| 197 | |
| 198 | return 0xff; |
| 199 | } |
| 200 | |
| 201 | |
| 202 | /*------------------------------------------------- |
| 203 | write_c0nx - called for writes to this card's c0nx space |
| 204 | -------------------------------------------------*/ |
| 205 | |
| 206 | void a2bus_hsscsi_device::write_c0nx(address_space &space, UINT8 offset, UINT8 data) |
| 207 | { |
| 208 | switch (offset) |
| 209 | { |
| 210 | case 0: |
| 211 | case 1: |
| 212 | case 2: |
| 213 | case 3: |
| 214 | case 4: |
| 215 | case 5: |
| 216 | case 6: |
| 217 | case 7: |
| 218 | // printf("%02x to 5380 reg %x\n", data, offset); |
| 219 | m_ncr5380->write(space, offset, data); |
| 220 | break; |
| 221 | #if 0 |
| 222 | case 8: // DMA address low |
| 223 | break; |
| 224 | |
| 225 | case 9: // DMA address high |
| 226 | break; |
| 227 | |
| 228 | case 0xa: // DMA count low |
| 229 | break; |
| 230 | |
| 231 | case 0xb: // DMA count high |
| 232 | break; |
| 233 | |
| 234 | case 0xc: // DMA control |
| 235 | break; |
| 236 | #endif |
| 237 | |
| 238 | case 0xd: // DMA enable / reset |
| 239 | printf("%02x to DMA enable/reset\n", data); |
| 240 | if (data & 0x2) |
| 241 | { |
| 242 | // printf("Resetting SCSI: %02x at %x\n", data, space.device().safe_pc()); |
| 243 | m_ncr5380->reset(); |
| 244 | } |
| 245 | break; |
| 246 | |
| 247 | case 0xe: |
| 248 | m_c0ne = data; |
| 249 | m_rombank = (data & 0x1f) * 0x400; |
| 250 | printf("c0ne to %x (ROM bank %x)\n", data & 0x1f, m_rombank); |
| 251 | break; |
| 252 | |
| 253 | case 0xf: |
| 254 | m_c0nf = data; |
| 255 | m_rambank = (data & 0x7) * 0x400; |
| 256 | printf("c0nf to %x (RAM bank %x)\n", data & 0x7, m_rambank); |
| 257 | break; |
| 258 | |
| 259 | default: |
| 260 | printf("Write %02x to c0n%x (PC=%x)\n", data, offset, space.device().safe_pc()); |
| 261 | break; |
| 262 | } |
| 263 | } |
| 264 | |
| 265 | /*------------------------------------------------- |
| 266 | read_cnxx - called for reads from this card's cnxx space |
| 267 | -------------------------------------------------*/ |
| 268 | |
| 269 | UINT8 a2bus_hsscsi_device::read_cnxx(address_space &space, UINT8 offset) |
| 270 | { |
| 271 | // one slot image at the start of the ROM, it appears |
| 272 | return m_rom[offset]; |
| 273 | } |
| 274 | |
| 275 | void a2bus_hsscsi_device::write_cnxx(address_space &space, UINT8 offset, UINT8 data) |
| 276 | { |
| 277 | // printf("Write %02x to cn%02x (PC=%x)\n", data, offset, space.device().safe_pc()); |
| 278 | } |
| 279 | |
| 280 | /*------------------------------------------------- |
| 281 | read_c800 - called for reads from this card's c800 space |
| 282 | -------------------------------------------------*/ |
| 283 | |
| 284 | UINT8 a2bus_hsscsi_device::read_c800(address_space &space, UINT16 offset) |
| 285 | { |
| 286 | // bankswitched RAM at c800-cbff |
| 287 | // bankswitched ROM at cc00-cfff |
| 288 | if (offset < 0x400) |
| 289 | { |
| 290 | // printf("Read RAM at %x = %02x\n", offset+m_rambank, m_ram[offset + m_rambank]); |
| 291 | if (m_816block) |
| 292 | { |
| 293 | return m_ncr5380->dma_r(); |
| 294 | } |
| 295 | |
| 296 | return m_ram[offset + m_rambank]; |
| 297 | } |
| 298 | else |
| 299 | { |
| 300 | return m_rom[(offset-0x400) + m_rombank]; |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | /*------------------------------------------------- |
| 305 | write_c800 - called for writes to this card's c800 space |
| 306 | -------------------------------------------------*/ |
| 307 | void a2bus_hsscsi_device::write_c800(address_space &space, UINT16 offset, UINT8 data) |
| 308 | { |
| 309 | if (offset < 0x400) |
| 310 | { |
| 311 | // printf("%02x to RAM at %x\n", data, offset+m_rambank); |
| 312 | if (m_816block) |
| 313 | { |
| 314 | m_ncr5380->dma_w(data); |
| 315 | } |
| 316 | else |
| 317 | { |
| 318 | m_ram[offset + m_rambank] = data; |
| 319 | } |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | WRITE_LINE_MEMBER( a2bus_hsscsi_device::drq_w ) |
| 324 | { |
| 325 | m_drq = (state ? 0x80 : 0x00); |
| 326 | } |
trunk/src/mess/machine/a2hsscsi.h
| r0 | r25514 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | a2hsscsi.h |
| 4 | |
| 5 | Implementation of the Apple II High Speed SCSI Card |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | |
| 9 | #ifndef __A2BUS_HSSCSI__ |
| 10 | #define __A2BUS_HSSCSI__ |
| 11 | |
| 12 | #include "emu.h" |
| 13 | #include "machine/a2bus.h" |
| 14 | #include "machine/ncr5380n.h" |
| 15 | |
| 16 | //************************************************************************** |
| 17 | // TYPE DEFINITIONS |
| 18 | //************************************************************************** |
| 19 | |
| 20 | class a2bus_hsscsi_device: |
| 21 | public device_t, |
| 22 | public device_a2bus_card_interface |
| 23 | { |
| 24 | public: |
| 25 | // construction/destruction |
| 26 | a2bus_hsscsi_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); |
| 27 | a2bus_hsscsi_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 28 | |
| 29 | // optional information overrides |
| 30 | virtual machine_config_constructor device_mconfig_additions() const; |
| 31 | virtual const rom_entry *device_rom_region() const; |
| 32 | |
| 33 | required_device<ncr5380n_device> m_ncr5380; |
| 34 | required_device<nscsi_bus_device> m_scsibus; |
| 35 | |
| 36 | DECLARE_WRITE_LINE_MEMBER( drq_w ); |
| 37 | |
| 38 | protected: |
| 39 | virtual void device_start(); |
| 40 | virtual void device_reset(); |
| 41 | |
| 42 | // overrides of standard a2bus slot functions |
| 43 | virtual UINT8 read_c0nx(address_space &space, UINT8 offset); |
| 44 | virtual void write_c0nx(address_space &space, UINT8 offset, UINT8 data); |
| 45 | virtual UINT8 read_cnxx(address_space &space, UINT8 offset); |
| 46 | virtual void write_cnxx(address_space &space, UINT8 offset, UINT8 data); |
| 47 | virtual UINT8 read_c800(address_space &space, UINT16 offset); |
| 48 | virtual void write_c800(address_space &space, UINT16 offset, UINT8 data); |
| 49 | |
| 50 | private: |
| 51 | UINT8 *m_rom; |
| 52 | UINT8 m_ram[8192]; // 8 banks of 1024 bytes |
| 53 | int m_rambank, m_rombank; |
| 54 | UINT8 m_drq; |
| 55 | UINT8 m_bank; |
| 56 | bool m_816block; |
| 57 | UINT8 m_c0ne, m_c0nf; |
| 58 | }; |
| 59 | |
| 60 | // device type definition |
| 61 | extern const device_type A2BUS_HSSCSI; |
| 62 | |
| 63 | #endif /* __A2BUS_HSSCSI__ */ |