// license:BSD-3-Clause // copyright-holders:R. Belmont, O. Galibert #include "emu.h" #include "bus/nubus/nubus.h" #include "bus/nscsi/devices.h" #include "cpu/powerpc/ppc.h" #include "machine/6522via.h" #include "machine/8530scc.h" #include "machine/cuda.h" #include "machine/macadb.h" #include "machine/mv_sonora.h" #include "machine/ncr5390.h" #include "machine/ram.h" #include "machine/swim3.h" #include "machine/timer.h" #include "softlist_dev.h" #include "sound/awacs.h" #include "speaker.h" constexpr auto IO_CLOCK = 31.3344_MHz_XTAL; constexpr auto ENET_CLOCK = 20_MHz_XTAL; constexpr auto SOUND_CLOCK = 45.1584_MHz_XTAL; class macpdm_state : public driver_device { public: macpdm_state(const machine_config &mconfig, device_type type, const char *tag); void macpdm(machine_config &config); virtual void driver_init() override; virtual void driver_reset() override; private: required_device m_maincpu; required_device m_via1; required_device m_awacs; required_device m_cuda; required_device m_macadb; required_device m_ram; required_device m_scc; required_device m_scsibus; required_device m_ncr53c94; required_device m_fdc; required_device_array m_floppy; required_device m_video; floppy_image_device *m_cur_floppy = nullptr; uint32_t m_model_id = 0; uint64_t m_hmc_reg = 0, m_hmc_buffer = 0; uint8_t m_hmc_bit = 0; uint8_t m_irq_control = 0; uint8_t m_via2_ier = 0, m_via2_ifr = 0, m_via2_sier = 0, m_via2_sifr = 0; uint64_t m_dma_scsi_buffer = 0; uint32_t m_dma_badr = 0, m_dma_floppy_adr = 0; uint16_t m_dma_floppy_byte_count = 0, m_dma_floppy_offset = 0; uint16_t m_dma_berr_en = 0, m_dma_berr_flag = 0; uint32_t m_dma_scsi_a_base_adr = 0, m_dma_scsi_b_base_adr = 0; uint32_t m_dma_scsi_a_cur_offset = 0, m_dma_scsi_b_cur_offset = 0; uint8_t m_dma_scsi_a_ctrl = 0, m_dma_scsi_b_ctrl = 0, m_dma_floppy_ctrl = 0; uint8_t m_dma_scsi_buffer_byte_count = 0; uint8_t m_dma_scc_txa_ctrl = 0, m_dma_scc_rxa_ctrl = 0, m_dma_scc_txb_ctrl = 0, m_dma_scc_rxb_ctrl = 0; uint8_t m_dma_enet_rx_ctrl = 0, m_dma_enet_tx_ctrl = 0; bool m_dma_scsi_a_in_step = false, m_dma_floppy_in_step = false, m_floppy_drq = false; void pdm_map(address_map &map); DECLARE_WRITE_LINE_MEMBER(nmi_irq); DECLARE_WRITE_LINE_MEMBER(dma_irq); DECLARE_WRITE_LINE_MEMBER(enet_irq); DECLARE_WRITE_LINE_MEMBER(scc_irq); DECLARE_WRITE_LINE_MEMBER(via1_irq); DECLARE_WRITE_LINE_MEMBER(bus_err_irq); DECLARE_WRITE_LINE_MEMBER(fdc_dma_irq); DECLARE_WRITE_LINE_MEMBER(etx_dma_irq); DECLARE_WRITE_LINE_MEMBER(erx_dma_irq); DECLARE_WRITE_LINE_MEMBER(txa_dma_irq); DECLARE_WRITE_LINE_MEMBER(rxa_dma_irq); DECLARE_WRITE_LINE_MEMBER(txb_dma_irq); DECLARE_WRITE_LINE_MEMBER(rxb_dma_irq); DECLARE_WRITE_LINE_MEMBER(sndo_dma_irq); DECLARE_WRITE_LINE_MEMBER(sndi_dma_irq); DECLARE_WRITE_LINE_MEMBER(fdc_err_irq); DECLARE_WRITE_LINE_MEMBER(etx_err_irq); DECLARE_WRITE_LINE_MEMBER(erx_err_irq); DECLARE_WRITE_LINE_MEMBER(txa_err_irq); DECLARE_WRITE_LINE_MEMBER(rxa_err_irq); DECLARE_WRITE_LINE_MEMBER(txb_err_irq); DECLARE_WRITE_LINE_MEMBER(rxb_err_irq); DECLARE_WRITE_LINE_MEMBER(scsi_err_irq); DECLARE_WRITE_LINE_MEMBER(sndo_err_irq); DECLARE_WRITE_LINE_MEMBER(sndi_err_irq); DECLARE_WRITE_LINE_MEMBER(vblank_irq); DECLARE_WRITE_LINE_MEMBER(slot2_irq); DECLARE_WRITE_LINE_MEMBER(slot1_irq); DECLARE_WRITE_LINE_MEMBER(slot0_irq); DECLARE_WRITE_LINE_MEMBER(fdc_irq); DECLARE_WRITE_LINE_MEMBER(fdc_drq); DECLARE_WRITE_LINE_MEMBER(sound_irq); DECLARE_WRITE_LINE_MEMBER(scsi_irq); DECLARE_WRITE_LINE_MEMBER(scsi_drq); void phases_w(uint8_t phases); void sel35_w(int sel35); void devsel_w(uint8_t devsel); void hdsel_w(int hdsel); uint8_t via1_in_a(); uint8_t via1_in_b(); void via1_out_a(uint8_t data); void via1_out_b(uint8_t data); TIMER_DEVICE_CALLBACK_MEMBER(via1_60_15_timer); DECLARE_WRITE_LINE_MEMBER(via1_out_cb2); DECLARE_WRITE_LINE_MEMBER(cuda_reset_w); uint8_t via1_r(offs_t offset); void via1_w(offs_t offset, uint8_t data); uint8_t via2_ier_r(); void via2_ier_w(uint8_t data); uint8_t via2_ifr_r(); uint8_t via2_sier_r(); void via2_sier_w(uint8_t data); uint8_t via2_sifr_r(); void via2_sifr_w(uint8_t data); uint8_t fdc_r(offs_t offset); void fdc_w(offs_t offset, uint8_t data); uint8_t scc_r(offs_t offset); void scc_w(offs_t offset, uint8_t data); uint8_t scsi_r(offs_t offset); void scsi_w(offs_t offset, uint8_t data); uint8_t hmc_r(offs_t offset); void hmc_w(offs_t offset, uint8_t data); uint32_t id_r(); uint8_t diag_r(offs_t offset); uint8_t irq_control_r(); void irq_control_w(uint8_t data); void irq_main_set(uint8_t mask, int state); void via2_irq_main_set(uint8_t mask, int state); void via2_irq_slot_set(uint8_t mask, int state); uint32_t dma_badr_r(); void dma_badr_w(offs_t, uint32_t data, uint32_t mem_mask); uint16_t dma_berr_en_r(); void dma_berr_en_w(offs_t, uint16_t data, uint16_t mem_mask); uint16_t dma_berr_flag_r(); void dma_berr_flag_w(offs_t, uint16_t data, uint16_t mem_mask); void dma_scsi_a_step(); uint32_t dma_scsi_a_base_adr_r(); void dma_scsi_a_base_adr_w(offs_t, uint32_t data, uint32_t mem_mask); uint32_t dma_scsi_b_base_adr_r(); void dma_scsi_b_base_adr_w(offs_t, uint32_t data, uint32_t mem_mask); uint8_t dma_scsi_a_ctrl_r(); void dma_scsi_a_ctrl_w(uint8_t data); uint8_t dma_scsi_b_ctrl_r(); void dma_scsi_b_ctrl_w(uint8_t data); uint32_t dma_scsi_a_cur_adr_r(); uint32_t dma_scsi_b_cur_adr_r(); void dma_floppy_step(); uint8_t dma_floppy_ctrl_r(); void dma_floppy_ctrl_w(uint8_t data); uint32_t dma_floppy_adr_r(); void dma_floppy_adr_w(offs_t, uint32_t data, uint32_t mem_mask); uint16_t dma_floppy_byte_count_r(); void dma_floppy_byte_count_w(offs_t, uint16_t data, uint16_t mem_mask); uint8_t dma_scc_txa_ctrl_r(); void dma_scc_txa_ctrl_w(uint8_t data); uint8_t dma_scc_rxa_ctrl_r(); void dma_scc_rxa_ctrl_w(uint8_t data); uint8_t dma_scc_txb_ctrl_r(); void dma_scc_txb_ctrl_w(uint8_t data); uint8_t dma_scc_rxb_ctrl_r(); void dma_scc_rxb_ctrl_w(uint8_t data); uint8_t dma_enet_rx_ctrl_r(); void dma_enet_rx_ctrl_w(uint8_t data); uint8_t dma_enet_tx_ctrl_r(); void dma_enet_tx_ctrl_w(uint8_t data); uint32_t sound_dma_output(offs_t offset); void sound_dma_input(offs_t offset, uint32_t value); uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); }; macpdm_state::macpdm_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_via1(*this, "via6522_1"), m_awacs(*this, "awacs"), m_cuda(*this, "cuda"), m_macadb(*this, "macadb"), m_ram(*this, RAM_TAG), m_scc(*this, "scc"), m_scsibus(*this, "scsibus"), m_ncr53c94(*this, "scsibus:7:ncr53c94"), m_fdc(*this, "fdc"), m_floppy(*this, "fdc:%d", 0U), m_video(*this, "video") { m_cur_floppy = nullptr; } void macpdm_state::driver_init() { m_maincpu->space().install_ram(0, m_ram->mask(), 0x3000000,m_ram->pointer()); m_maincpu->space().nop_readwrite(m_ram->size(), 0xffffff, 0x3000000); m_model_id = 0xa55a3011; // 7100 = a55a3012 // 8100 = a55a3013 save_item(NAME(m_hmc_reg)); save_item(NAME(m_hmc_buffer)); save_item(NAME(m_hmc_bit)); save_item(NAME(m_via2_ier)); save_item(NAME(m_via2_ifr)); save_item(NAME(m_via2_sier)); save_item(NAME(m_via2_sifr)); save_item(NAME(m_irq_control)); save_item(NAME(m_dma_badr)); save_item(NAME(m_dma_berr_en)); save_item(NAME(m_dma_berr_flag)); save_item(NAME(m_dma_scsi_buffer)); save_item(NAME(m_dma_scsi_buffer_byte_count)); save_item(NAME(m_dma_scsi_a_in_step)); save_item(NAME(m_dma_scsi_a_base_adr)); save_item(NAME(m_dma_scsi_b_base_adr)); save_item(NAME(m_dma_scsi_a_ctrl)); save_item(NAME(m_dma_scsi_b_ctrl)); save_item(NAME(m_dma_scsi_a_cur_offset)); save_item(NAME(m_dma_scsi_b_cur_offset)); save_item(NAME(m_dma_floppy_ctrl)); save_item(NAME(m_dma_floppy_in_step)); save_item(NAME(m_dma_scc_txa_ctrl)); save_item(NAME(m_dma_scc_rxa_ctrl)); save_item(NAME(m_dma_scc_txb_ctrl)); save_item(NAME(m_dma_scc_rxb_ctrl)); save_item(NAME(m_dma_enet_rx_ctrl)); save_item(NAME(m_dma_enet_tx_ctrl)); save_item(NAME(m_dma_floppy_adr)); save_item(NAME(m_dma_floppy_offset)); save_item(NAME(m_dma_floppy_byte_count)); save_item(NAME(m_floppy_drq)); m_maincpu->space().install_read_tap(0x4000c2e0, 0x4000c2e7, 0, "cuda", [this](offs_t offset, u64 &data, u64 mem_mask) { if(mem_mask == 0xffff000000000000) { offs_t badr = m_maincpu->state_int(PPC_R16); m_maincpu->translate(AS_PROGRAM, TRANSLATE_READ_DEBUG, badr); logerror("cuda packet %08x : type %02x cmd %02x - %02x %02x %02x %02x bytecnt %04x\n", badr, m_maincpu->space().read_byte(badr), m_maincpu->space().read_byte(badr+1), m_maincpu->space().read_byte(badr+2), m_maincpu->space().read_byte(badr+3), m_maincpu->space().read_byte(badr+4), m_maincpu->space().read_byte(badr+5), m_maincpu->space().read_word(badr+6)); } }); } void macpdm_state::driver_reset() { m_hmc_reg = 0; m_hmc_buffer = 0; m_hmc_bit = 0; m_via2_ier = 0x00; m_via2_ifr = 0x00; m_via2_sier = 0x00; m_via2_sifr = 0x7f; m_irq_control = 0; m_dma_badr = 0; m_dma_berr_en = 0; m_dma_berr_flag = 0; m_dma_scsi_buffer = 0; m_dma_scsi_buffer_byte_count = 0; m_dma_scsi_a_in_step = false; m_dma_scsi_a_base_adr = 0; m_dma_scsi_b_base_adr = 0; m_dma_scsi_a_ctrl = 0; m_dma_scsi_b_ctrl = 0; m_dma_scsi_a_cur_offset = 0; m_dma_scsi_b_cur_offset = 0; m_dma_floppy_ctrl = 0; m_dma_scc_txa_ctrl = 0; m_dma_scc_rxa_ctrl = 0; m_dma_scc_txb_ctrl = 0; m_dma_scc_rxb_ctrl = 0; m_dma_enet_rx_ctrl = 0; m_dma_enet_tx_ctrl = 0; m_dma_floppy_adr = 0x15000; m_dma_floppy_offset = 0; m_dma_floppy_byte_count = 0; m_floppy_drq = false; m_video->set_vram_base((const u64 *)m_ram->pointer()); m_video->set_vram_offset(0); } uint8_t macpdm_state::irq_control_r() { return m_irq_control; } void macpdm_state::irq_control_w(uint8_t data) { if((m_irq_control ^ data) & 0x40) { m_irq_control = (m_irq_control & ~0xc0) | (data & 0x40); m_maincpu->set_input_line(PPC_IRQ, CLEAR_LINE); } if((data & 0xc0) == 0xc0 && (m_irq_control & 0x80)) { m_irq_control &= 0x7f; m_maincpu->set_input_line(PPC_IRQ, CLEAR_LINE); } } void macpdm_state::irq_main_set(uint8_t mask, int state) { if(((m_irq_control & mask) != 0) == state) return; m_irq_control ^= mask; if(m_irq_control & 0x40) { m_irq_control |= 0x80; m_maincpu->set_input_line(PPC_IRQ, ASSERT_LINE); } else { if(m_irq_control & 0x3f) { m_irq_control |= 0x80; m_maincpu->set_input_line(PPC_IRQ, ASSERT_LINE); } else { m_irq_control &= 0x7f; m_maincpu->set_input_line(PPC_IRQ, CLEAR_LINE); } } // logerror("irq control %02x\n", m_irq_control); } void macpdm_state::via2_irq_main_set(uint8_t mask, int state) { if(((m_via2_ifr & mask) != 0) == state) return; m_via2_ifr ^= mask; // logerror("via2 main %02x / %02x -> %02x\n", m_via2_ifr, m_via2_ier, m_via2_ifr & m_via2_ier); irq_main_set(0x02, (m_via2_ifr & m_via2_ier) != 0); } void macpdm_state::via2_irq_slot_set(uint8_t mask, int state) { if(((m_via2_sifr & mask) == 0) == state) return; m_via2_sifr ^= mask; via2_irq_main_set(0x02, ((~m_via2_sifr) & m_via2_sier) != 0); } // bit 7 = out - scc wait/request // bit 5 = out - head select, unconnected // bit 3 = ? - sync modem (?) uint8_t macpdm_state::via1_in_a() { return 0x00; } void macpdm_state::via1_out_a(uint8_t data) { } // bit 7 = ? - snd res (?) // bit 5 = out - sys sess/tip // bit 4 = out - via full/byte ack // bit 3 = in - xcvr sess/treq uint8_t macpdm_state::via1_in_b() { uint8_t val = 0; val |= m_cuda->get_treq() << 3; return val; } void macpdm_state::via1_out_b(uint8_t data) { m_cuda->set_byteack(BIT(data, 4)); m_cuda->set_tip(BIT(data, 5)); } TIMER_DEVICE_CALLBACK_MEMBER(macpdm_state::via1_60_15_timer) { m_via1->write_ca1(1); m_via1->write_ca1(0); } WRITE_LINE_MEMBER(macpdm_state::via1_out_cb2) { m_cuda->set_via_data(state & 1); } WRITE_LINE_MEMBER(macpdm_state::cuda_reset_w) { m_maincpu->set_input_line(INPUT_LINE_HALT, state); m_maincpu->set_input_line(INPUT_LINE_RESET, state); } uint8_t macpdm_state::via1_r(offs_t offset) { return m_via1->read(offset >> 9); } void macpdm_state::via1_w(offs_t offset, uint8_t data) { m_via1->write(offset >> 9, data); } uint8_t macpdm_state::via2_ier_r() { return m_via2_ier; } void macpdm_state::via2_ier_w(uint8_t data) { if(data & 0x80) m_via2_ier |= data & 0x3b; else m_via2_ier &= ~data; logerror("via2 ier %s %s %s %s\n", m_via2_ier & 0x20 ? "fdc" : "-", m_via2_ier & 0x10 ? "sound" : "-", m_via2_ier & 0x08 ? "scsi" : "-", m_via2_ier & 0x02 ? "slot" : "-", m_via2_ier & 0x01 ? "scsidrq" : "-"); irq_main_set(0x02, (m_via2_ifr & m_via2_ier) != 0); } uint8_t macpdm_state::via2_ifr_r() { return m_via2_ifr; } uint8_t macpdm_state::via2_sier_r() { return m_via2_ier; } void macpdm_state::via2_sier_w(uint8_t data) { if(data & 0x80) m_via2_sier |= data & 0x78; else m_via2_sier &= ~data; logerror("via2 sier %s %s %s %s\n", m_via2_sier & 0x40 ? "vbl" : "-", m_via2_sier & 0x20 ? "slot2" : "-", m_via2_sier & 0x10 ? "slot1" : "-", m_via2_sier & 0x08 ? "slot0" : "-"); via2_irq_main_set(0x02, ((~m_via2_sifr) & m_via2_sier) != 0); } uint8_t macpdm_state::via2_sifr_r() { return m_via2_sifr; } void macpdm_state::via2_sifr_w(uint8_t data) { if(data & (~m_via2_sifr) & 0x40) { m_via2_sifr |= 0x40; via2_irq_main_set(0x02, ((~m_via2_sifr) & m_via2_sier) != 0); } } uint8_t macpdm_state::scc_r(offs_t offset) { return m_scc->reg_r(offset >> 1); } void macpdm_state::scc_w(offs_t offset, uint8_t data) { m_scc->reg_w(offset, data); } uint8_t macpdm_state::fdc_r(offs_t offset) { return m_fdc->read(offset >> 9); } void macpdm_state::fdc_w(offs_t offset, uint8_t data) { m_fdc->write(offset >> 9, data); } uint8_t macpdm_state::scsi_r(offs_t offset) { return m_ncr53c94->read(offset >> 4); } void macpdm_state::scsi_w(offs_t offset, uint8_t data) { m_ncr53c94->write(offset >> 4, data); } uint8_t macpdm_state::hmc_r(offs_t offset) { return (m_hmc_reg >> m_hmc_bit) & 1 ? 0x80 : 0x00; } void macpdm_state::hmc_w(offs_t offset, uint8_t data) { if(offset & 8) m_hmc_bit = 0; else { if(data & 0x80) m_hmc_buffer |= u64(1) << m_hmc_bit; else m_hmc_buffer &= ~(u64(1) << m_hmc_bit); m_hmc_bit ++; if(m_hmc_bit == 35) { m_hmc_reg = m_hmc_buffer & ~3; // csiz is readonly, we pretend there isn't a l2 cache m_video->set_vram_offset(m_hmc_reg & 0x200000000 ? 0x100000 : 0); logerror("HMC l2=%c%c%c%c%c vbase=%c%s mbram=%cM size=%x%s romd=%d refresh=%02x w=%c%c%c%c ras=%d%d%d%d\n", m_hmc_reg & 0x008000000 ? '+' : '-', // l2_en m_hmc_reg & 0x400000000 ? '3' : '2', // l2_init m_hmc_reg & 0x004000000 ? '1' : '2', // l2_brst m_hmc_reg & 0x010000000 ? 'I' : 'U', // l2_inst m_hmc_reg & 0x002000000 ? 'w' : '.', // l2romw m_hmc_reg & 0x200000000 ? '1' : '0', // vbase m_hmc_reg & 0x100000000 ? " vtst" : "", // vtst m_hmc_reg & 0x080000000 ? '8' : '4', // mb_ram (m_hmc_reg >> 29) & 3, // size m_hmc_reg & 0x001000000 ? " nblrom" : "", // nblrom 12 - 2*((m_hmc_reg >> 22) & 3), // romd (m_hmc_reg >> 16) & 0x3f, // rfsh m_hmc_reg & 0x000000008 ? '3' : '2', // winit m_hmc_reg & 0x000000004 ? '3' : '2', // wbrst m_hmc_reg & 0x000008000 ? '1' : '2', // wcasp m_hmc_reg & 0x000004000 ? '1' : '2', // wcasd 3 - ((m_hmc_reg >> 12) & 3), // rdac 6 - ((m_hmc_reg >> 8) & 3), // rasd 5 - ((m_hmc_reg >> 6) & 3), // rasp 4 - ((m_hmc_reg >> 4) & 3)); // rcasd } } } uint8_t macpdm_state::diag_r(offs_t offset) { // returning 0 at address 0 gives the 'car crash' sound after the boot bong logerror("diag_r %x\n", offset); return offset ? 0 : 1; } void macpdm_state::phases_w(uint8_t phases) { if(m_cur_floppy) m_cur_floppy->seek_phase_w(phases); } void macpdm_state::sel35_w(int sel35) { logerror("fdc mac sel35 %d\n", sel35); } void macpdm_state::devsel_w(uint8_t devsel) { if(devsel == 1) m_cur_floppy = m_floppy[0]->get_device(); else if(devsel == 2) m_cur_floppy = m_floppy[1]->get_device(); else m_cur_floppy = nullptr; m_fdc->set_floppy(m_cur_floppy); } void macpdm_state::hdsel_w(int hdsel) { if(m_cur_floppy) m_cur_floppy->ss_w(hdsel); } uint32_t macpdm_state::id_r() { return m_model_id; } WRITE_LINE_MEMBER(macpdm_state::scc_irq) { logerror("scc irq %d\n", state); } WRITE_LINE_MEMBER(macpdm_state::via1_irq) { irq_main_set(0x01, state); } WRITE_LINE_MEMBER(macpdm_state::sound_irq) { via2_irq_main_set(0x20, state); } WRITE_LINE_MEMBER(macpdm_state::vblank_irq) { via2_irq_slot_set(0x40, state); } WRITE_LINE_MEMBER(macpdm_state::slot2_irq) { via2_irq_slot_set(0x20, state); } WRITE_LINE_MEMBER(macpdm_state::slot1_irq) { via2_irq_slot_set(0x10, state); } WRITE_LINE_MEMBER(macpdm_state::sndo_dma_irq) { // TODO } WRITE_LINE_MEMBER(macpdm_state::sndi_dma_irq) { // TODO } uint32_t macpdm_state::dma_badr_r() { return m_dma_badr; } void macpdm_state::dma_badr_w(offs_t, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_dma_badr); m_dma_badr &= 0xfffc0000; logerror("dma base address %08x\n", m_dma_badr); m_dma_floppy_adr = (m_dma_badr | 0x10000) + (m_dma_floppy_adr & 0xffff); } uint16_t macpdm_state::dma_berr_en_r() { return m_dma_berr_en; } void macpdm_state::dma_berr_en_w(offs_t, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_berr_en); logerror("dma bus error enable %08x\n", m_dma_berr_en); } uint16_t macpdm_state::dma_berr_flag_r() { return m_dma_berr_flag; } void macpdm_state::dma_berr_flag_w(offs_t, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_berr_flag); logerror("dma bus error flag %08x\n", m_dma_berr_flag); } // SCSI management void macpdm_state::dma_scsi_a_step() { m_dma_scsi_a_in_step = true; if(m_dma_scsi_a_ctrl & 0x40) { while(m_via2_ifr & 0x01) { if(m_dma_scsi_buffer_byte_count == 0) { m_dma_scsi_buffer_byte_count = 8; m_dma_scsi_buffer = m_maincpu->space().read_qword(m_dma_scsi_a_base_adr + m_dma_scsi_a_cur_offset); m_dma_scsi_a_cur_offset += 8; } m_dma_scsi_buffer_byte_count --; m_ncr53c94->dma_w(m_dma_scsi_buffer >> (8*m_dma_scsi_buffer_byte_count)); } } else { while(m_via2_ifr & 0x01) { uint8_t b = m_ncr53c94->dma_r(); m_dma_scsi_buffer = (m_dma_scsi_buffer & ~(u64(0xff) << (56 - 8*m_dma_scsi_buffer_byte_count))) | (u64(b) << (56 - 8*m_dma_scsi_buffer_byte_count)); m_dma_scsi_buffer_byte_count ++; if(m_dma_scsi_buffer_byte_count == 8) { m_dma_scsi_buffer_byte_count = 0; m_maincpu->space().write_qword(m_dma_scsi_a_base_adr + m_dma_scsi_a_cur_offset, m_dma_scsi_buffer); m_dma_scsi_a_cur_offset += 8; } } } m_dma_scsi_a_in_step = false; } WRITE_LINE_MEMBER(macpdm_state::scsi_irq) { via2_irq_main_set(0x08, state); } WRITE_LINE_MEMBER(macpdm_state::scsi_drq) { via2_irq_main_set(0x01, state); if((m_dma_scsi_a_ctrl & 0x02) && (m_via2_ifr & 0x01) && !m_dma_scsi_a_in_step) dma_scsi_a_step(); } uint32_t macpdm_state::dma_scsi_a_base_adr_r() { return m_dma_scsi_a_base_adr; } void macpdm_state::dma_scsi_a_base_adr_w(offs_t, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_dma_scsi_a_base_adr); m_dma_scsi_a_base_adr &= ~7; m_dma_scsi_a_cur_offset = 0; m_dma_scsi_buffer_byte_count = 0; logerror("dma_scsi_a_base_adr_w %08x\n", m_dma_scsi_a_base_adr); } uint32_t macpdm_state::dma_scsi_b_base_adr_r() { return m_dma_scsi_b_base_adr; } void macpdm_state::dma_scsi_b_base_adr_w(offs_t, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_dma_scsi_b_base_adr); m_dma_scsi_b_base_adr &= ~7; m_dma_scsi_a_cur_offset = 0; logerror("dma_scsi_b_base_adr_w %08x\n", m_dma_scsi_b_base_adr); } uint8_t macpdm_state::dma_scsi_a_ctrl_r() { return m_dma_scsi_a_ctrl; } void macpdm_state::dma_scsi_a_ctrl_w(uint8_t data) { m_dma_scsi_a_ctrl = data & 0x42; if(data & 1) { m_dma_scsi_a_ctrl &= 0x40; m_dma_scsi_a_cur_offset = 0; m_dma_scsi_buffer_byte_count = 0; } if(data & 0x10) { while(m_via2_ifr & 0x01) { uint8_t b = m_ncr53c94->dma_r(); m_dma_scsi_buffer = (m_dma_scsi_buffer & ~(u64(0xff) << (56 - 8*m_dma_scsi_buffer_byte_count))) | (u64(b) << (56 - 8*m_dma_scsi_buffer_byte_count)); m_dma_scsi_buffer_byte_count ++; if(m_dma_scsi_buffer_byte_count == 8) { m_dma_scsi_buffer_byte_count = 0; m_maincpu->space().write_qword(m_dma_scsi_a_base_adr + m_dma_scsi_a_cur_offset, m_dma_scsi_buffer); m_dma_scsi_a_cur_offset += 8; } } if(m_dma_scsi_buffer_byte_count) { m_maincpu->space().write_qword(m_dma_scsi_a_base_adr + m_dma_scsi_a_cur_offset, m_dma_scsi_buffer); m_dma_scsi_buffer_byte_count = 0; } } if((m_dma_scsi_a_ctrl & 0x02) && (m_via2_ifr & 0x01) && !m_dma_scsi_a_in_step) dma_scsi_a_step(); logerror("dma_scsi_a_ctrl_w %02x\n", m_dma_scsi_a_ctrl); } uint8_t macpdm_state::dma_scsi_b_ctrl_r() { return m_dma_scsi_b_ctrl; } void macpdm_state::dma_scsi_b_ctrl_w(uint8_t data) { // Channel B is not actually connected to anything m_dma_scsi_b_ctrl = data & 0x42; if(data & 1) { m_dma_scsi_b_ctrl &= 0x40; m_dma_scsi_b_cur_offset = 0; } logerror("dma_scsi_b_ctrl_w %02x\n", m_dma_scsi_b_ctrl); } uint32_t macpdm_state::dma_scsi_a_cur_adr_r() { return m_dma_scsi_a_base_adr + m_dma_scsi_a_cur_offset; } uint32_t macpdm_state::dma_scsi_b_cur_adr_r() { return m_dma_scsi_b_base_adr + m_dma_scsi_b_cur_offset; } // Floppy management uint8_t macpdm_state::dma_floppy_ctrl_r() { return m_dma_floppy_ctrl; } void macpdm_state::dma_floppy_ctrl_w(uint8_t data) { m_dma_floppy_ctrl = (m_dma_floppy_ctrl & 0x80) | (data & 0x4a); if(data & 0x01) { m_dma_floppy_ctrl &= 0x7f; m_dma_floppy_offset = 0; } if(data & 0x80) m_dma_floppy_ctrl &= 0x7f; logerror("dma floppy ctrl %02x\n", m_dma_floppy_ctrl); } uint16_t macpdm_state::dma_floppy_byte_count_r() { return m_dma_floppy_byte_count; } void macpdm_state::dma_floppy_byte_count_w(offs_t, uint16_t data, uint16_t mem_mask) { COMBINE_DATA(&m_dma_floppy_byte_count); logerror("dma floppy count %04x\n", m_dma_floppy_byte_count); } uint32_t macpdm_state::dma_floppy_adr_r() { return m_dma_floppy_adr; } void macpdm_state::dma_floppy_adr_w(offs_t, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_dma_floppy_adr); m_dma_floppy_adr = (m_dma_badr | 0x10000) + (m_dma_floppy_adr & 0xffff); m_dma_floppy_offset = 0; logerror("dma floppy adr %08x\n", m_dma_floppy_adr); } WRITE_LINE_MEMBER(macpdm_state::fdc_irq) { via2_irq_main_set(0x20, state); } void macpdm_state::dma_floppy_step() { m_dma_floppy_in_step = true; if(m_dma_floppy_ctrl & 0x40) { fatalerror("floppy dma write\n"); } else { while(m_floppy_drq) { u8 r = m_fdc->dma_r(); m_maincpu->space().write_byte(m_dma_floppy_adr + m_dma_floppy_offset, r); m_dma_floppy_offset ++; m_dma_floppy_byte_count --; // logerror("dma_w %03x, %02x\n", m_dma_floppy_offset, r); if(m_dma_floppy_byte_count == 0) { m_dma_floppy_ctrl &= ~0x02; m_dma_floppy_ctrl |= 0x80; logerror("dma floppy done\n"); // todo irq dma break; } } } m_dma_floppy_in_step = false; } WRITE_LINE_MEMBER(macpdm_state::fdc_drq) { m_floppy_drq = state; if((m_dma_floppy_ctrl & 0x02) && m_floppy_drq && !m_dma_floppy_in_step) dma_floppy_step(); } // SCC management uint8_t macpdm_state::dma_scc_txa_ctrl_r() { return m_dma_scc_txa_ctrl; } void macpdm_state::dma_scc_txa_ctrl_w(uint8_t data) { m_dma_scc_txa_ctrl = data; logerror("dma_scc_txa_ctrl_w %02x\n", m_dma_scc_txa_ctrl); } uint8_t macpdm_state::dma_scc_rxa_ctrl_r() { return m_dma_scc_rxa_ctrl; } void macpdm_state::dma_scc_rxa_ctrl_w(uint8_t data) { m_dma_scc_rxa_ctrl = data; logerror("dma_scc_rxa_ctrl_w %02x\n", m_dma_scc_rxa_ctrl); } uint8_t macpdm_state::dma_scc_txb_ctrl_r() { return m_dma_scc_txb_ctrl; } void macpdm_state::dma_scc_txb_ctrl_w(uint8_t data) { m_dma_scc_txb_ctrl = data; logerror("dma_scc_txb_ctrl_w %02x\n", m_dma_scc_txb_ctrl); } uint8_t macpdm_state::dma_scc_rxb_ctrl_r() { return m_dma_scc_rxb_ctrl; } void macpdm_state::dma_scc_rxb_ctrl_w(uint8_t data) { m_dma_scc_rxb_ctrl = data; logerror("dma_scc_rxb_ctrl_w %02x\n", m_dma_scc_rxb_ctrl); } uint8_t macpdm_state::dma_enet_rx_ctrl_r() { return m_dma_enet_rx_ctrl; } void macpdm_state::dma_enet_rx_ctrl_w(uint8_t data) { m_dma_enet_rx_ctrl = data; logerror("dma_enet_rx_ctrl_w %02x\n", m_dma_enet_rx_ctrl); } uint8_t macpdm_state::dma_enet_tx_ctrl_r() { return m_dma_enet_tx_ctrl; } void macpdm_state::dma_enet_tx_ctrl_w(uint8_t data) { m_dma_enet_tx_ctrl = data; logerror("dma_enet_tx_ctrl_w %02x\n", m_dma_enet_tx_ctrl); } uint32_t macpdm_state::sound_dma_output(offs_t offset) { offs_t adr = m_dma_badr + (offset & 0x10000 ? 0x12000 : 0x10000) + 4*(offset & 0x7ff); return m_maincpu->space().read_dword(adr); } void macpdm_state::sound_dma_input(offs_t offset, uint32_t value) { offs_t adr = m_dma_badr + (offset & 0x10000 ? 0x0e000 : 0x0c000) + 4*(offset & 0x7ff); m_maincpu->space().write_dword(adr, value); } void macpdm_state::pdm_map(address_map &map) { map(0x40000000, 0x403fffff).rom().region("bootrom", 0).mirror(0x0fc00000); map(0x50f00000, 0x50f00000).rw(FUNC(macpdm_state::via1_r), FUNC(macpdm_state::via1_w)).select(0x1e00); map(0x50f04000, 0x50f04000).rw(FUNC(macpdm_state::scc_r), FUNC(macpdm_state::scc_w)).select(0x000e); // 50f08000 = ethernet ID PROM // 50f0a000 = MACE ethernet controller map(0x50f10000, 0x50f10000).rw(FUNC(macpdm_state::scsi_r), FUNC(macpdm_state::scsi_w)).select(0xf0); map(0x50f10100, 0x50f10101).rw(m_ncr53c94, FUNC(ncr53c94_device::dma16_r), FUNC(ncr53c94_device::dma16_w)); map(0x50f14000, 0x50f1401f).rw(m_awacs, FUNC(awacs_device::read), FUNC(awacs_device::write)); map(0x50f16000, 0x50f16000).rw(FUNC(macpdm_state::fdc_r), FUNC(macpdm_state::fdc_w)).select(0x1e00); map(0x50f24000, 0x50f24003).rw(m_video, FUNC(mac_video_sonora_device::dac_r), FUNC(mac_video_sonora_device::dac_w)); map(0x50f26002, 0x50f26002).rw(FUNC(macpdm_state::via2_sifr_r), FUNC(macpdm_state::via2_sifr_w)).mirror(0x1fe0); map(0x50f26003, 0x50f26003).r(FUNC(macpdm_state::via2_ifr_r)).mirror(0x1fe0); map(0x50f26012, 0x50f26012).rw(FUNC(macpdm_state::via2_sier_r), FUNC(macpdm_state::via2_sier_w)).mirror(0x1fe0); map(0x50f26013, 0x50f26013).rw(FUNC(macpdm_state::via2_ier_r), FUNC(macpdm_state::via2_ier_w)).mirror(0x1fe0); map(0x50f28000, 0x50f28007).rw(m_video, FUNC(mac_video_sonora_device::vctrl_r), FUNC(mac_video_sonora_device::vctrl_w)); map(0x50f2a000, 0x50f2a000).rw(FUNC(macpdm_state::irq_control_r), FUNC(macpdm_state::irq_control_w)); map(0x50f2c000, 0x50f2dfff).r(FUNC(macpdm_state::diag_r)); map(0x50f31000, 0x50f31003).rw(FUNC(macpdm_state::dma_badr_r), FUNC(macpdm_state::dma_badr_w)); map(0x50f31c20, 0x50f31c20).rw(FUNC(macpdm_state::dma_enet_tx_ctrl_r), FUNC(macpdm_state::dma_enet_tx_ctrl_w)); map(0x50f32000, 0x50f32003).rw(FUNC(macpdm_state::dma_scsi_a_base_adr_r), FUNC(macpdm_state::dma_scsi_a_base_adr_w)); map(0x50f32004, 0x50f32007).rw(FUNC(macpdm_state::dma_scsi_b_base_adr_r), FUNC(macpdm_state::dma_scsi_b_base_adr_w)); map(0x50f32008, 0x50f32008).rw(FUNC(macpdm_state::dma_scsi_a_ctrl_r), FUNC(macpdm_state::dma_scsi_a_ctrl_w)); map(0x50f32009, 0x50f32009).rw(FUNC(macpdm_state::dma_scsi_b_ctrl_r), FUNC(macpdm_state::dma_scsi_b_ctrl_w)); map(0x50f32010, 0x50f32013).r(FUNC(macpdm_state::dma_scsi_a_cur_adr_r)); map(0x50f32014, 0x50f32017).r(FUNC(macpdm_state::dma_scsi_b_cur_adr_r)); map(0x50f32028, 0x50f32028).rw(FUNC(macpdm_state::dma_enet_rx_ctrl_r), FUNC(macpdm_state::dma_enet_rx_ctrl_w)); map(0x50f32060, 0x50f32063).rw(FUNC(macpdm_state::dma_floppy_adr_r), FUNC(macpdm_state::dma_floppy_adr_w)); map(0x50f32064, 0x50f32065).rw(FUNC(macpdm_state::dma_floppy_byte_count_r), FUNC(macpdm_state::dma_floppy_byte_count_w)); map(0x50f32068, 0x50f32068).rw(FUNC(macpdm_state::dma_floppy_ctrl_r), FUNC(macpdm_state::dma_floppy_ctrl_w)); map(0x50f32088, 0x50f32088).rw(FUNC(macpdm_state::dma_scc_txa_ctrl_r), FUNC(macpdm_state::dma_scc_txa_ctrl_w)); map(0x50f32098, 0x50f32098).rw(FUNC(macpdm_state::dma_scc_rxa_ctrl_r), FUNC(macpdm_state::dma_scc_rxa_ctrl_w)); map(0x50f320a8, 0x50f320a8).rw(FUNC(macpdm_state::dma_scc_txb_ctrl_r), FUNC(macpdm_state::dma_scc_txb_ctrl_w)); map(0x50f320b8, 0x50f320b8).rw(FUNC(macpdm_state::dma_scc_rxb_ctrl_r), FUNC(macpdm_state::dma_scc_rxb_ctrl_w)); map(0x50f32100, 0x50f32101).rw(FUNC(macpdm_state::dma_berr_en_r), FUNC(macpdm_state::dma_berr_en_w)); map(0x50f32102, 0x50f32103).rw(FUNC(macpdm_state::dma_berr_flag_r), FUNC(macpdm_state::dma_berr_flag_w)); map(0x50f40000, 0x50f4000f).rw(FUNC(macpdm_state::hmc_r), FUNC(macpdm_state::hmc_w)); map(0x5ffffff8, 0x5fffffff).r(FUNC(macpdm_state::id_r)); map(0xffc00000, 0xffffffff).rom().region("bootrom", 0); } void macpdm_state::macpdm(machine_config &config) { PPC601(config, m_maincpu, 60000000); m_maincpu->set_addrmap(AS_PROGRAM, &macpdm_state::pdm_map); MAC_VIDEO_SONORA(config, m_video); m_video->screen_vblank().set(FUNC(macpdm_state::vblank_irq)); SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); AWACS(config, m_awacs, SOUND_CLOCK/2); m_awacs->irq_out_cb().set(FUNC(macpdm_state::sndo_dma_irq)); m_awacs->irq_in_cb().set(FUNC(macpdm_state::sndi_dma_irq)); m_awacs->dma_output().set(FUNC(macpdm_state::sound_dma_output)); m_awacs->dma_input().set(FUNC(macpdm_state::sound_dma_input)); m_awacs->add_route(0, "lspeaker", 1.0); m_awacs->add_route(1, "rspeaker", 1.0); NSCSI_BUS(config, m_scsibus); NSCSI_CONNECTOR(config, "scsibus:0", default_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsibus:1", default_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsibus:2", default_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsibus:3", default_scsi_devices, "cdrom"); NSCSI_CONNECTOR(config, "scsibus:4", default_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsibus:5", default_scsi_devices, "harddisk"); NSCSI_CONNECTOR(config, "scsibus:6", default_scsi_devices, "harddisk"); NSCSI_CONNECTOR(config, "scsibus:7").option_set("ncr53c94", NCR53C94).machine_config([this] (device_t *device) { auto &ctrl = downcast(*device); ctrl.set_clock(ENET_CLOCK/2); ctrl.drq_handler_cb().set(*this, FUNC(macpdm_state::scsi_drq)); ctrl.irq_handler_cb().set(*this, FUNC(macpdm_state::scsi_irq)); }); SOFTWARE_LIST(config, "flop35_list").set_original("mac_flop"); SOFTWARE_LIST(config, "flop35hd_list").set_original("mac_hdflop"); SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd"); SWIM3(config, m_fdc, IO_CLOCK); m_fdc->irq_cb().set(FUNC(macpdm_state::fdc_irq)); m_fdc->drq_cb().set(FUNC(macpdm_state::fdc_drq)); m_fdc->hdsel_cb().set(FUNC(macpdm_state::hdsel_w)); m_fdc->devsel_cb().set(FUNC(macpdm_state::devsel_w)); m_fdc->phases_cb().set(FUNC(macpdm_state::phases_w)); m_fdc->sel35_cb().set(FUNC(macpdm_state::sel35_w)); applefdintf_device::add_35_hd(config, m_floppy[0]); applefdintf_device::add_35_nc(config, m_floppy[1]); // pclk is maincpu:60MHz/4, RTxCA is IO_CLOCK*2/17 or GPI input, RTxCB is IO_CLOCK*2/17 SCC8530(config, m_scc, 60000000/4); m_scc->intrq_callback().set(FUNC(macpdm_state::scc_irq)); R65NC22(config, m_via1, IO_CLOCK/40); m_via1->readpa_handler().set(FUNC(macpdm_state::via1_in_a)); m_via1->readpb_handler().set(FUNC(macpdm_state::via1_in_b)); m_via1->writepa_handler().set(FUNC(macpdm_state::via1_out_a)); m_via1->writepb_handler().set(FUNC(macpdm_state::via1_out_b)); m_via1->cb2_handler().set(FUNC(macpdm_state::via1_out_cb2)); m_via1->irq_handler().set(FUNC(macpdm_state::via1_irq)); RAM(config, m_ram); m_ram->set_default_size("8M"); m_ram->set_extra_options("16M,32M,64M,128M"); MACADB(config, m_macadb, IO_CLOCK/2); CUDA(config, m_cuda, CUDA_341S0060); m_cuda->reset_callback().set(FUNC(macpdm_state::cuda_reset_w)); m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_cuda->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); m_cuda->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); m_macadb->set_mcu_mode(true); m_macadb->adb_data_callback().set(m_cuda, FUNC(cuda_device::set_adb_line)); config.set_perfect_quantum(m_maincpu); TIMER(config, "beat_60_15").configure_periodic(FUNC(macpdm_state::via1_60_15_timer), attotime::from_double(1/60.15)); } static INPUT_PORTS_START( macpdm ) INPUT_PORTS_END ROM_START( pmac6100 ) ROM_REGION64_BE(0x400000, "bootrom", 0) ROM_LOAD( "9feb69b3.rom", 0x000000, 0x400000, CRC(a43fadbc) SHA1(6fac1c4e920a077c077b03902fef9199d5e8f2c3) ) ROM_END COMP( 1994, pmac6100, 0, 0, macpdm, macpdm, macpdm_state, driver_init, "Apple Computer", "Power Macintosh 6100/60", MACHINE_NOT_WORKING )