// license:BSD-3-Clause // copyright-holders:Sergey Svishchev /*************************************************************************** IBM 6580 Displaywriter. A green-screen dedicated word-processing workstation. It uses 8" floppy disks. It could have up to 224k of ram. Consists of: Electronics Module 6580 Display 3300 Keyboard 5330 [a "beamspring"-type] Dual Diskette Unit 6360 Optional: Printers: 5215, 5218, 5228 Printer Sharing feature Mag Card Unit Asynchronous and Bisynchronous communications features 66-line display and adapter (800x1056 px, 8x16 character cell) All chips have IBM part numbers on them. F.e. on system board: 8493077 - 8086 4178619 - 8251A 4178617 - 8257-5 4178623 - 8259A 4178628 - 8255A-5 4178625 - 8253-5 IRQ levels per PSM p. 6-5 0 incoming data for printer sharing/3277 DE 1 transfer data to commo data link 2 printer and mag card data xfer 3 keyboard incoming data 4 diskette 5 (not in use) 6 software timer [50 ms period] 7 error on commo data link nmi "or when a dump switch operation is initiated" ["memory record" button] To do: - verify all frequency sources, document ROM revisions - memory size options - bus errors, interrupts - 92-key keyboard variant, keyboard click/beep, keyboard layouts - 25-line video board (instant scroll, sub/superscripts, graphics mode) - 66-line video board - either emulate floppy board, or complete its HLE (drive select, etc.) - add support for 8" drives with no track 0 sensor (recalibrate command is expected to return 0x70 in ST0) - double density floppies - "memory record" (system dump) generation to floppies - pass BAT with no errors (Basic Assurance Test) - pass RNA with no errors (Resident Non-Automatic Test) - pass PDD with no errors (Problem Determination Disk) - pass CED with no errors (Customer Engineering Diagnostics) - boot Textpack successfully (currently crashes with *90x* message) Useful documents: bitsavers://pdf/ibm/6580_Displaywriter/S241-6248-3_Displaywriter_Product_Support_Manual_Feb83.pdf bitsavers://pdf/ibm/6580_Displaywriter/S241-6248-2_Displaywriter_6360_6580_Product_Support_Manual_May82.pdf bitsavers://pdf/ibm/6580_Displaywriter/S241-6250-5_Displaywriter_6250_6580_Maintenance_Analysis_Procedures_May82.pdf http://www.nostalgia8.nl/cpm/ibm/cpm6dwrm.pdf http://www.kbdbabel.org/schematic/kbdbabel_doc_ibm_displaywriter.pdf https://docs.google.com/spreadsheets/d/1SYY_HrBqKjSOX9W4fe5xUsjbfiCt0Umjpo4ZIwgG3Nk/edit?usp=sharing Wanted: Displaywriter System Manual S544-2023-0 (?) -- mentioned in US patents 4648071 and 5675827 "IBM Displaywriter System Printer Guide," Order No. S544-0861-2, Copyright 1980. "Displaywriter System Product Support Manual," Order No. S241-6248-1, Copyright 1980 ****************************************************************************/ #include "emu.h" #include "bus/rs232/rs232.h" #include "cpu/i86/i86.h" #include "imagedev/floppy.h" #include "machine/i8251.h" #include "machine/i8255.h" #include "machine/i8257.h" #include "machine/pic8259.h" #include "machine/pit8253.h" #include "machine/ibm6580_kbd.h" //nclude "machine/ibm6580_fdc.h" #include "machine/ram.h" #include "machine/upd765.h" #include "emupal.h" #include "screen.h" #include "ibm6580.lh" #define I8086_TAG "i8086" #define I8259A_TAG "i8259" #define I8255A_TAG "i8255a" #define I8253_TAG "i8253" #define UPD765_TAG "upd765" #define VERBOSE_DBG 2 /* general debug messages */ #define DBG_LOG(N,M,A) \ do { \ if(VERBOSE_DBG>=N) \ { \ if( M ) \ logerror("%11.6f at %s: %-10s",machine().time().as_double(),machine().describe_context(),(char*)M ); \ logerror A; \ } \ } while (0) uint8_t gfx_expand[16] = { 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f, 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff }; class ibm6580_state : public driver_device { public: ibm6580_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_p_videoram(*this, "videoram") , m_ram(*this, RAM_TAG) , m_maincpu(*this, "maincpu") , m_pic8259(*this, "pic8259") , m_pit8253(*this, "pit8253") , m_ppi8255(*this, "ppi8255") , m_dma8257(*this, "dma8257") , m_screen(*this, "screen") , m_kbd(*this, "kbd") , m_fdc(*this, UPD765_TAG) , m_flop0(*this, UPD765_TAG ":0") , m_flop1(*this, UPD765_TAG ":1") , m_p_chargen(*this, "chargen") { } void ibm6580(machine_config &config); private: void ibm6580_palette(palette_device &palette) const; DECLARE_WRITE16_MEMBER(pic_latch_w); DECLARE_WRITE16_MEMBER(unk_latch_w); DECLARE_WRITE8_MEMBER(p40_w); DECLARE_READ8_MEMBER(p40_r); DECLARE_WRITE8_MEMBER(video_w); DECLARE_READ8_MEMBER(video_r); DECLARE_WRITE_LINE_MEMBER(vblank_w); DECLARE_READ8_MEMBER(ppi_a_r); DECLARE_WRITE8_MEMBER(led_w); DECLARE_WRITE8_MEMBER(ppi_c_w); DECLARE_READ8_MEMBER(ppi_c_r); DECLARE_WRITE_LINE_MEMBER(kb_data_w); DECLARE_WRITE_LINE_MEMBER(kb_clock_w); DECLARE_WRITE_LINE_MEMBER(kb_strobe_w); DECLARE_WRITE8_MEMBER(floppy_w); DECLARE_READ8_MEMBER(floppy_r); DECLARE_FLOPPY_FORMATS(floppy_formats); DECLARE_WRITE_LINE_MEMBER(floppy_intrq); DECLARE_WRITE_LINE_MEMBER(floppy_hdl); DECLARE_WRITE8_MEMBER(dmapg_w); DECLARE_WRITE_LINE_MEMBER(hrq_w); DECLARE_READ8_MEMBER(memory_read_byte); DECLARE_WRITE8_MEMBER(memory_write_byte); uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void ibm6580_io(address_map &map); void ibm6580_mem(address_map &map); virtual void machine_start() override; virtual void machine_reset() override; virtual void video_start() override; uint8_t m_p40, m_p50, m_e000, m_kb_data, m_ppi_c; bool m_kb_data_bit, m_kb_strobe; util::fifo m_kb_fifo; util::fifo m_floppy_mcu_sr, m_floppy_mcu_cr; int m_floppy_mcu_cr_fifo; uint8_t m_floppy_sr; floppy_image_device *m_floppies[2]; floppy_image_device *m_floppy; bool m_floppy_intrq, m_floppy_hdl, m_floppy_idle; uint8_t m_dma0pg; uint8_t floppy_mcu_command(); bool floppy_mcu_cr_full(); required_shared_ptr m_p_videoram; required_device m_ram; required_device m_maincpu; required_device m_pic8259; required_device m_pit8253; required_device m_ppi8255; required_device m_dma8257; required_device m_screen; required_device m_kbd; required_device m_fdc; required_device m_flop0; required_device m_flop1; required_region_ptr m_p_chargen; }; WRITE8_MEMBER(ibm6580_state::p40_w) { DBG_LOG(2,"___", ("%02x <- %02x\n", 0x40 + (offset << 1), data)); switch (offset) { case 0: m_p40 = data | 0x80; break; case 2: if (data) m_p40 |= 4; break; case 5: // write_gate0 doesn't work -- counter is read back as 0 if (BIT(data, 2)) // hack. video test checks timer counter value and this lets it pass. m_pit8253->set_clockin(0, (double)26880000); else m_pit8253->set_clockin(0, 0.0); m_p50 = 0; m_ppi_c = data; break; case 6: m_dma0pg = data; break; case 8: m_p50 = data; break; case 12: if (data) m_p40 &= ~0x14; break; } } READ8_MEMBER(ibm6580_state::p40_r) { uint8_t data = 0; switch (offset) { case 0: data = m_p40; m_p40 &= ~4; break; case 8: data = m_p50; m_p50 = 1; break; } DBG_LOG(3,"___", ("%02x == %02x\n", 0x40 + (offset << 1), data)); return data; } WRITE8_MEMBER(ibm6580_state::video_w) { DBG_LOG(2,"Video", ("%02x <- %02x\n", 0xe000 + (offset << 1), data)); switch (offset) { case 2: // some kind of gate m_e000 = data; break; } } READ8_MEMBER(ibm6580_state::video_r) { uint8_t data = 0; switch (offset) { case 8: data = 1; // 25-line video board ID. 66-line is 0x40. data |= (m_screen->hblank() ? 8 : 0); data |= (m_screen->vblank() ? 4 : 0); // pure guesswork. 0x2, 0x10 and 0x20 are unknown video signals. // 0x20 cannot be zero when 0x10 is zero. data |= ((m_screen->vpos() < 2) ? 2 : 0); if (m_e000) { data |= (m_screen->vblank() ? 0x20 : 0); data |= (m_screen->vblank() ? 0 : 0x10); } break; } if (offset != 8) DBG_LOG(2,"Video", ("%02x == %02x\n", 0xe000 + (offset << 1), data)); return data; } WRITE_LINE_MEMBER(ibm6580_state::vblank_w) { // if (state) // m_pic8259->ir6_w(state); if (ioport("DUMP")->read()) m_p40 |= 4; } WRITE16_MEMBER(ibm6580_state::pic_latch_w) { DBG_LOG(2,"PIC", ("latch <- %02x\n", data)); if (data) m_p40 |= 8; m_pic8259->ir0_w(data == 2 ? ASSERT_LINE : CLEAR_LINE); m_pic8259->ir1_w(data == 2 ? ASSERT_LINE : CLEAR_LINE); m_pic8259->ir2_w(data == 2 ? ASSERT_LINE : CLEAR_LINE); m_pic8259->ir3_w(data == 2 ? ASSERT_LINE : CLEAR_LINE); m_pic8259->ir4_w(data == 2 ? ASSERT_LINE : CLEAR_LINE); m_pic8259->ir5_w(data == 2 ? ASSERT_LINE : CLEAR_LINE); m_pic8259->ir6_w(data == 2 ? ASSERT_LINE : CLEAR_LINE); m_pic8259->ir7_w(data == 2 ? ASSERT_LINE : CLEAR_LINE); } WRITE16_MEMBER(ibm6580_state::unk_latch_w) { DBG_LOG(2,"UNK", ("latch <- %02x\n", data)); m_p40 |= 0x10; } WRITE8_MEMBER(ibm6580_state::led_w) { output().set_value("led5", BIT(data, 7)); output().set_value("led6", BIT(data, 6)); output().set_value("led7", BIT(data, 5)); output().set_value("led8", BIT(data, 4)); if (data & 0xf) return; switch (data >> 4) { case 0x1: printf ("LED 0 0001: Parity Generator/Checker\n"); break; case 0xe: printf ("LED 0 1110: Base RAM\n"); break; case 0x3: printf ("LED 0 0011: Processor Extension Test\n"); break; case 0x4: printf ("LED 0 0100: Display RAM\n"); break; case 0x5: printf ("LED 0 0101: Display Adapter Timing Test, Video Test\n"); break; case 0x6: printf ("LED 0 0110: Keyboard Cable Test, Physical Keyboard Test\n"); break; case 0x7: printf ("LED 0 0111: DMA Controller Test\n"); break; case 0x8: printf ("LED 0 1000: Diskette Module Wrap Test, Adapter Test\n"); break; case 0x9: printf ("LED 0 1001: Extra RAM Test\n"); break; case 0xa: printf ("LED 0 1010: Bus Time-Out Test\n"); break; case 0xc: printf ("LED 0 1100: RAM Addressability Test\n"); break; default: // printf ("LED 0x%08x: unknown\n", data); break; } } WRITE8_MEMBER(ibm6580_state::ppi_c_w) { DBG_LOG(2,"PPI", ("Port C <- %02x\n", data)); // bit 5 -- acknowledge // bit 6 -- reset // bit 7 -- ?? gate if (!BIT(data, 6)) { m_kb_fifo.clear(); } m_kbd->reset_w(!BIT(data, 6)); m_kbd->ack_w(BIT(data, 5)); } READ8_MEMBER(ibm6580_state::ppi_c_r) { uint8_t data = 0; data |= (m_kb_strobe << 3); DBG_LOG(3,"PPI", ("Port C == %02x\n", data)); return data; } READ8_MEMBER(ibm6580_state::ppi_a_r) { uint8_t data = m_kb_fifo.dequeue(); DBG_LOG(2,"PPI", ("Port A == %02x (fifo full: %d)\n", data, m_kb_fifo.full())); return data; } WRITE_LINE_MEMBER(ibm6580_state::kb_data_w) { m_kb_data_bit = !state; } WRITE_LINE_MEMBER(ibm6580_state::kb_clock_w) { if (!state) m_kb_data = (m_kb_data >> 1) | (m_kb_data_bit << 7); } WRITE_LINE_MEMBER(ibm6580_state::kb_strobe_w) { m_kb_strobe = !state; if (!state && BIT(m_ppi_c, 0)) { m_kb_fifo.enqueue(m_kb_data); DBG_LOG(1,"Kbd", ("enqueue %02x (fifo full: %d, m_ppi_c %02x)\n", m_kb_data, m_kb_fifo.full(), m_ppi_c)); } } WRITE_LINE_MEMBER(ibm6580_state::floppy_intrq) { m_floppy_intrq = state; if (state) m_floppy_idle = true; } WRITE_LINE_MEMBER(ibm6580_state::hrq_w) { m_maincpu->set_input_line(INPUT_LINE_HALT, state); m_dma8257->hlda_w(state); } READ8_MEMBER(ibm6580_state::memory_read_byte) { address_space& prog_space = m_maincpu->space(AS_PROGRAM); return prog_space.read_byte(offset | (m_dma0pg << 16)); } WRITE8_MEMBER(ibm6580_state::memory_write_byte) { address_space& prog_space = m_maincpu->space(AS_PROGRAM); prog_space.write_byte(offset | (m_dma0pg << 16), data); } bool ibm6580_state::floppy_mcu_cr_full() { uint8_t command = m_floppy_mcu_cr.peek(); if ((command & 1) && m_floppy_mcu_cr_fifo == 1) return true; if (command == 0x0c && m_floppy_mcu_cr_fifo == 4) return true; if (m_floppy_mcu_cr_fifo == 3) return true; else return false; } uint8_t ibm6580_state::floppy_mcu_command() { uint8_t data = 0, command = m_floppy_mcu_cr.dequeue(), i; DBG_LOG(2,"Floppy", ("mcu_command %02x\n", command)); m_floppy_mcu_sr.clear(); m_floppy_idle = true; switch (command) { case 0: m_fdc->soft_reset(); break; // 3 bytes case 4: break; // 1 byte -- get status? case 5: m_floppy_mcu_sr.enqueue(0x00); if (m_flop0->get_device()->exists()) m_floppy_mcu_sr.enqueue( m_flop0->get_device()->idx_r() ? 0x08 : 0); else m_floppy_mcu_sr.enqueue(0x08); break; // 3 bytes, no return -- engage head case 6: m_floppy_mcu_cr.dequeue(); i = m_floppy_mcu_cr.dequeue(); m_floppy_hdl = i; break; // 1 byte -- read head engage signal case 7: m_floppy_mcu_sr.enqueue(0x00); m_floppy_mcu_sr.enqueue(m_floppy_hdl); break; // 3 bytes case 8: break; // 4 bytes -- used by cp/m. drive select? case 0xc: break; // 1 byte -- get drive ready status? case 0xd: m_floppy_mcu_sr.enqueue(0x00); i = 0; if (m_flop0->get_device()->exists()) i |= m_flop0->get_device()->ready_r() ? 0 : 0x40; if (m_flop1->get_device()->exists()) i |= m_flop1->get_device()->ready_r() ? 0 : 0x80; m_floppy_mcu_sr.enqueue(i); break; // 3 bytes, no return -- recalibrate? case 0xe: m_floppy_mcu_cr.dequeue(); i = m_floppy_mcu_cr.dequeue(); #if 1 if (i & 1) m_fdc->set_floppy(m_flop0->get_device()); else if (i & 2) m_fdc->set_floppy(m_flop1->get_device()); #endif break; // 1 byte case 0x13: break; // 1 byte case 0x15: break; } m_floppy_mcu_cr.clear(); m_floppy_mcu_cr_fifo = 0; return data; } WRITE8_MEMBER(ibm6580_state::floppy_w) { DBG_LOG(2,"Floppy", ("%02x <- %02x\n", 0x8150 + (offset << 1), data)); switch (offset) { case 0: // 8150 -- mcu reset? m_floppy_mcu_sr.enqueue(0x00); m_floppy_mcu_sr.enqueue(0x00); break; case 1: // 8152 m_fdc->soft_reset(); break; case 5: // 815A m_fdc->fifo_w(space, offset, data); if (m_floppy_idle) m_floppy_idle = false; break; case 6: // 815C m_floppy_mcu_cr.enqueue(data); m_floppy_mcu_cr_fifo++; if (floppy_mcu_cr_full()) floppy_mcu_command(); break; } } READ8_MEMBER(ibm6580_state::floppy_r) { uint8_t data = 0; switch (offset) { case 0: // 8150 // bit 4 -- ?? ready // bit 5 -- mcu busy // bit 6 -- ?? idle if (m_floppy_mcu_sr.empty() && (m_floppy_idle || m_floppy_intrq)) data |= 0x40; break; case 4: // 8158 data = m_fdc->msr_r(space, offset); break; case 5: // 815a data = m_fdc->fifo_r(space, offset); break; case 6: // 815c if (!m_floppy_mcu_sr.empty()) data = m_floppy_mcu_sr.dequeue(); break; } if (offset) DBG_LOG(2,"Floppy", ("%02x == %02x\n", 0x8150 + (offset << 1), data)); else { floppy_image_device *f = m_flop0->get_device(); if (f) DBG_LOG(2,"Floppy", ("%02x == %02x (empty %d hdl %d + idle %d irq %d drq %d + dskchg %d idx %d cyl %d)\n", 0x8150 + (offset << 1), data, m_floppy_mcu_sr.empty(), m_floppy_hdl, m_floppy_idle, m_fdc->get_irq(), m_fdc->get_drq(), f->dskchg_r(), f->idx_r(), f->get_cyl() )); else DBG_LOG(2,"Floppy", ("%02x == %02x (idle %d irq %d drq %d)\n", 0x8150 + (offset << 1), data, m_floppy_idle, m_fdc->get_irq(), m_fdc->get_drq() )); } return data; } void ibm6580_state::ibm6580_mem(address_map &map) { map.unmap_value_high(); map(0x90000, 0x90001).w(FUNC(ibm6580_state::unk_latch_w)); map(0xef000, 0xeffff).ram().share("videoram"); // 66-line vram starts at 0xec000 map(0xfc000, 0xfffff).rom().region("user1", 0); } void ibm6580_state::ibm6580_io(address_map &map) { map.unmap_value_high(); map(0x0000, 0x0007).rw(m_pic8259, FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff); map(0x0008, 0x000f).w(FUNC(ibm6580_state::pic_latch_w)); map(0x0010, 0x0017).rw(m_ppi8255, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff); map(0x0020, 0x003f).rw(m_dma8257, FUNC(i8257_device::read), FUNC(i8257_device::write)).umask16(0x00ff); map(0x0040, 0x005f).rw(FUNC(ibm6580_state::p40_r), FUNC(ibm6580_state::p40_w)).umask16(0x00ff); map(0x0070, 0x007f).unmaprw(); map(0x0120, 0x0127).rw(m_pit8253, FUNC(pit8253_device::read), FUNC(pit8253_device::write)).umask16(0x00ff); map(0x0140, 0x0143).rw("upd8251a", FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff); map(0x0160, 0x0163).rw("upd8251b", FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff); map(0x4000, 0x400f).unmaprw(); map(0x5000, 0x500f).unmaprw(); map(0x6000, 0x601f).unmaprw(); map(0x8060, 0x807f).unmaprw(); map(0x8150, 0x815f).rw(FUNC(ibm6580_state::floppy_r), FUNC(ibm6580_state::floppy_w)).umask16(0x00ff); // HLE of floppy board map(0x81a0, 0x81af).unmaprw(); map(0xc000, 0xc00f).unmaprw(); map(0xe000, 0xe02f).rw(FUNC(ibm6580_state::video_r), FUNC(ibm6580_state::video_w)).umask16(0x00ff); } /* Input ports */ static INPUT_PORTS_START( ibm6580 ) PORT_START("DUMP") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Memory Record") PORT_CODE(KEYCODE_PRTSCR) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) INPUT_PORTS_END uint32_t ibm6580_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { uint8_t y,ra,gfx,fg,bg,chr,attr; uint16_t sy=0,ma=25,x,ca; fg = 1; bg = 0; for (y = 0; y < 25; y++) { for (ra = 0; ra < 16; ra++) { uint16_t *p = &bitmap.pix16(sy++); // graphics mode if (m_p_videoram[ma] & 0x100) { for (x = ma; x < ma + 80; x++) { chr = m_p_videoram[x]; attr = m_p_videoram[x] >> 8; switch (ra >> 1) { case 0: gfx = gfx_expand[chr & 15]; break; case 2: gfx = gfx_expand[chr >> 4]; break; case 4: gfx = gfx_expand[attr & 15]; break; case 6: gfx = gfx_expand[attr >> 4]; break; default: gfx = 0; break; } /* Display a scanline of a character */ *p++ = BIT(gfx, 7) ? fg : bg; *p++ = BIT(gfx, 6) ? fg : bg; *p++ = BIT(gfx, 5) ? fg : bg; *p++ = BIT(gfx, 4) ? fg : bg; *p++ = BIT(gfx, 3) ? fg : bg; *p++ = BIT(gfx, 2) ? fg : bg; *p++ = BIT(gfx, 1) ? fg : bg; *p++ = BIT(gfx, 0) ? fg : bg; } } else { // text mode for (x = ma; x < ma + 80; x++) { chr = m_p_videoram[x]; attr = m_p_videoram[x] >> 8; ca = (chr<<4); // font 2 if (attr & 0x02) ca += 0x1000; #if 0 // superscript if (attr & 0x20) ca |= (ra < 13) ? ra + 3 : 0; // subscript if (attr & 0x20) ca |= (ra > 2) ? ra - 3 : 0; #endif // underline if (attr & 0x08 && ra == 13) gfx = 0xff; else gfx = m_p_chargen[ca | ra]; // cursor if (attr & 0x04 && ra == 14) gfx = 0xff; else gfx = m_p_chargen[ca | ra]; // reverse video if (attr & 0x10) gfx ^= 255; // intense if (attr & 0x04) fg = 2; else fg = 1; /* Display a scanline of a character */ *p++ = BIT(gfx, 7) ? fg : bg; *p++ = BIT(gfx, 6) ? fg : bg; *p++ = BIT(gfx, 5) ? fg : bg; *p++ = BIT(gfx, 4) ? fg : bg; *p++ = BIT(gfx, 3) ? fg : bg; *p++ = BIT(gfx, 2) ? fg : bg; *p++ = BIT(gfx, 1) ? fg : bg; *p++ = BIT(gfx, 0) ? fg : bg; } } } ma+=80; } return 0; } void ibm6580_state::ibm6580_palette(palette_device &palette) const { palette.set_pen_color(0, 0, 0, 0 ); // Black palette.set_pen_color(1, 0, 192, 0 ); // Normal palette.set_pen_color(2, 0, 255, 0 ); // Bright } void ibm6580_state::machine_start() { address_space &program = m_maincpu->space(AS_PROGRAM); program.install_readwrite_bank(0, m_ram->size() - 1, "bank10"); membank("bank10")->set_base(m_ram->pointer()); m_fdc->set_rate(500000); // XXX workaround } void ibm6580_state::machine_reset() { m_p40 = m_p50 = m_e000 = m_ppi_c = m_floppy_sr = 0; m_kb_data_bit = false; m_floppy_idle = true; m_kb_fifo.clear(); m_pit8253->set_clockin(0, 0.0); if (ioport("DUMP")->read()) m_p40 |= 4; m_flop0->get_device()->mon_w(!m_flop0->get_device()->exists()); m_flop1->get_device()->mon_w(!m_flop1->get_device()->exists()); m_fdc->set_floppy(m_flop0->get_device()); m_floppy_mcu_sr.clear(); m_floppy_mcu_cr.clear(); m_floppy_mcu_cr_fifo = 0; } void ibm6580_state::video_start() { memset(m_p_videoram, 0x0, 0x1000); } static void dw_floppies(device_slot_interface &device) { device.option_add("8sssd", IBM_6360); } MACHINE_CONFIG_START(ibm6580_state::ibm6580) MCFG_DEVICE_ADD("maincpu", I8086, 14.7456_MHz_XTAL / 3) MCFG_DEVICE_PROGRAM_MAP(ibm6580_mem) MCFG_DEVICE_IO_MAP(ibm6580_io) MCFG_DEVICE_IRQ_ACKNOWLEDGE_DEVICE("pic8259", pic8259_device, inta_cb) RAM(config, RAM_TAG).set_default_size("128K").set_extra_options("160K,192K,224K,256K,320K,384K"); MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_RAW_PARAMS(25_MHz_XTAL / 2, 833, 0, 640, 428, 0, 400) MCFG_SCREEN_UPDATE_DRIVER(ibm6580_state, screen_update) MCFG_SCREEN_PALETTE("palette") MCFG_SCREEN_VBLANK_CALLBACK(WRITELINE(*this, ibm6580_state, vblank_w)) config.set_default_layout(layout_ibm6580); PALETTE(config, "palette", FUNC(ibm6580_state::ibm6580_palette), 3); PIC8259(config, m_pic8259, 0); m_pic8259->out_int_callback().set_inputline(m_maincpu, 0); i8255_device &ppi(I8255(config, "ppi8255")); ppi.in_pa_callback().set(FUNC(ibm6580_state::ppi_a_r)); ppi.out_pb_callback().set(FUNC(ibm6580_state::led_w)); ppi.out_pc_callback().set(FUNC(ibm6580_state::ppi_c_w)); ppi.in_pc_callback().set(FUNC(ibm6580_state::ppi_c_r)); MCFG_DEVICE_ADD("pit8253", PIT8253, 0) DW_KEYBOARD(config, m_kbd, 0); m_kbd->out_data_handler().set(FUNC(ibm6580_state::kb_data_w)); m_kbd->out_clock_handler().set(FUNC(ibm6580_state::kb_clock_w)); m_kbd->out_strobe_handler().set(FUNC(ibm6580_state::kb_strobe_w)); m_kbd->out_strobe_handler().append(m_ppi8255, FUNC(i8255_device::pc4_w)); I8257(config, m_dma8257, 14.7456_MHz_XTAL / 3); m_dma8257->out_hrq_cb().set(FUNC(ibm6580_state::hrq_w)); m_dma8257->out_tc_cb().set(m_fdc, FUNC(upd765a_device::tc_line_w)); m_dma8257->in_memr_cb().set(FUNC(ibm6580_state::memory_read_byte)); m_dma8257->out_memw_cb().set(FUNC(ibm6580_state::memory_write_byte)); m_dma8257->in_ior_cb<0>().set(m_fdc, FUNC(upd765a_device::mdma_r)); m_dma8257->out_iow_cb<0>().set(m_fdc, FUNC(upd765a_device::mdma_w)); UPD765A(config, m_fdc, 24_MHz_XTAL / 3, false, false); m_fdc->intrq_wr_callback().set(FUNC(ibm6580_state::floppy_intrq)); // m_fdc->intrq_wr_callback().append(m_pic8259, FUNC(pic8259_device::ir4_w)); m_fdc->drq_wr_callback().set(m_dma8257, FUNC(i8257_device::dreq0_w)); MCFG_FLOPPY_DRIVE_ADD(UPD765_TAG ":0", dw_floppies, "8sssd", floppy_image_device::default_floppy_formats) MCFG_FLOPPY_DRIVE_ADD(UPD765_TAG ":1", dw_floppies, "8sssd", floppy_image_device::default_floppy_formats) i8251_device &upd8251a(I8251(config, "upd8251a", 0)); upd8251a.txd_handler().set("rs232a", FUNC(rs232_port_device::write_txd)); upd8251a.dtr_handler().set("rs232a", FUNC(rs232_port_device::write_dtr)); upd8251a.rts_handler().set("rs232a", FUNC(rs232_port_device::write_rts)); upd8251a.rxrdy_handler().set(m_pic8259, FUNC(pic8259_device::ir2_w)); upd8251a.txrdy_handler().set(m_pic8259, FUNC(pic8259_device::ir2_w)); rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, nullptr)); rs232a.rxd_handler().set("upd8251a", FUNC(i8251_device::write_rxd)); rs232a.dsr_handler().set("upd8251a", FUNC(i8251_device::write_dsr)); rs232a.cts_handler().set("upd8251a", FUNC(i8251_device::write_cts)); i8251_device &upd8251b(I8251(config, "upd8251b", 0)); upd8251b.txd_handler().set("rs232b", FUNC(rs232_port_device::write_txd)); upd8251b.dtr_handler().set("rs232b", FUNC(rs232_port_device::write_dtr)); upd8251b.rts_handler().set("rs232b", FUNC(rs232_port_device::write_rts)); upd8251b.rxrdy_handler().set(m_pic8259, FUNC(pic8259_device::ir2_w)); upd8251b.txrdy_handler().set(m_pic8259, FUNC(pic8259_device::ir2_w)); rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr)); rs232b.rxd_handler().set("upd8251b", FUNC(i8251_device::write_rxd)); rs232b.dsr_handler().set("upd8251b", FUNC(i8251_device::write_dsr)); rs232b.cts_handler().set("upd8251b", FUNC(i8251_device::write_cts)); MCFG_SOFTWARE_LIST_ADD("flop_list", "ibm6580") MACHINE_CONFIG_END /* ROM definition */ ROM_START( ibm6580 ) ROM_REGION16_LE( 0x4000, "user1", 0 ) ROM_DEFAULT_BIOS("old") ROM_SYSTEM_BIOS(0, "old", "old bios - 1981") ROMX_LOAD("8493823_8k.bin", 0x0001, 0x2000, CRC(aa5524c0) SHA1(9938f2a82828b17966cb0be7fdbf73803c1f10d3), ROM_SKIP(1) | ROM_BIOS(0)) ROMX_LOAD("8493822_8k.bin", 0x0000, 0x2000, CRC(90e7e73a) SHA1(d3ee7a4d2cb8f4920b5d95e8c7f4fef06599d24e), ROM_SKIP(1) | ROM_BIOS(0)) ROM_SYSTEM_BIOS(1, "new", "new bios - 1983?") // was downloaded via DDT86 ROMX_LOAD( "dwrom16kb.bin", 0x0000, 0x4000, BAD_DUMP CRC(ced87929) SHA1(907a46f288809bc93a1f59f3fbef18bd44be42d9), ROM_BIOS(1)) ROM_REGION( 0x2000, "chargen", 0 ) ROM_LOAD( "8493383_chr.bin", 0x0000, 0x2000, CRC(779044df) SHA1(95ec46f9edf4d44c5dd3c955c73e00754d58e180)) ROM_END /* Driver */ /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ COMP( 1980, ibm6580, 0, 0, ibm6580, ibm6580, ibm6580_state, empty_init, "IBM", "IBM 6580 Displaywriter", MACHINE_IS_SKELETON)