trunk/src/mess/drivers/pc9801.c
r23720 | r23721 | |
354 | 354 | : driver_device(mconfig, type, tag), |
355 | 355 | m_maincpu(*this, "maincpu"), |
356 | 356 | m_dmac(*this, "i8237"), |
| 357 | m_pic1(*this, "pic8259_master"), |
| 358 | m_pic2(*this, "pic8259_slave"), |
357 | 359 | m_fdc_2hd(*this, "upd765_2hd"), |
358 | 360 | m_fdc_2dd(*this, "upd765_2dd"), |
359 | 361 | m_rtc(*this, UPD1990A_TAG), |
r23720 | r23721 | |
369 | 371 | |
370 | 372 | required_device<cpu_device> m_maincpu; |
371 | 373 | required_device<am9517a_device> m_dmac; |
| 374 | required_device<pic8259_device> m_pic1; |
| 375 | required_device<pic8259_device> m_pic2; |
372 | 376 | required_device<upd765a_device> m_fdc_2hd; |
373 | 377 | optional_device<upd765a_device> m_fdc_2dd; |
374 | 378 | required_device<upd1990a_device> m_rtc; |
r23720 | r23721 | |
486 | 490 | inline UINT8 m_pc9801rs_grcg_r(UINT32 offset,int vbank); |
487 | 491 | inline void m_pc9801rs_grcg_w(UINT32 offset,int vbank,UINT8 data); |
488 | 492 | DECLARE_CUSTOM_INPUT_MEMBER(system_type_r); |
| 493 | static UINT32 pc9801_286_a20(bool state); |
489 | 494 | |
490 | 495 | DECLARE_WRITE8_MEMBER(sasi_data_w); |
491 | 496 | DECLARE_WRITE_LINE_MEMBER(sasi_io_w); |
r23720 | r23721 | |
535 | 540 | DECLARE_WRITE8_MEMBER(pc9821_memory_w); |
536 | 541 | // DECLARE_READ8_MEMBER(pc9801_ext_opna_r); |
537 | 542 | // DECLARE_WRITE8_MEMBER(pc9801_ext_opna_w); |
| 543 | DECLARE_READ8_MEMBER(pic_r); |
| 544 | DECLARE_WRITE8_MEMBER(pic_w); |
538 | 545 | |
539 | 546 | DECLARE_READ8_MEMBER(pc9801rs_ide_io_0_r); |
540 | 547 | DECLARE_READ8_MEMBER(pc9801rs_ide_io_1_r); |
r23720 | r23721 | |
608 | 615 | INTERRUPT_GEN_MEMBER(pc9801_vrtc_irq); |
609 | 616 | // DECLARE_INPUT_CHANGED_MEMBER(key_stroke); |
610 | 617 | // DECLARE_INPUT_CHANGED_MEMBER(shift_stroke); |
611 | | DECLARE_WRITE_LINE_MEMBER(pc9801_master_set_int_line); |
612 | 618 | DECLARE_READ8_MEMBER(get_slave_ack); |
613 | 619 | DECLARE_WRITE_LINE_MEMBER(pc9801_dma_hrq_changed); |
614 | 620 | DECLARE_WRITE_LINE_MEMBER(pc9801_tc_w); |
r23720 | r23721 | |
624 | 630 | DECLARE_WRITE8_MEMBER(fdc_2dd_w); |
625 | 631 | DECLARE_READ8_MEMBER(ppi_sys_porta_r); |
626 | 632 | DECLARE_READ8_MEMBER(ppi_sys_portb_r); |
| 633 | DECLARE_READ8_MEMBER(ppi_sys_portc_r); |
627 | 634 | DECLARE_READ8_MEMBER(ppi_prn_portb_r); |
628 | 635 | DECLARE_WRITE8_MEMBER(ppi_sys_portc_w); |
629 | 636 | DECLARE_READ8_MEMBER(ppi_fdd_porta_r); |
r23720 | r23721 | |
958 | 965 | if(offset & 0x14) |
959 | 966 | printf("Read to undefined port [%02x]\n",offset+0x00); |
960 | 967 | else |
961 | | return machine().device<pic8259_device>((offset & 8) ? "pic8259_slave" : "pic8259_master")->read(space, (offset & 2) >> 1); |
| 968 | return ((offset & 8) ? m_pic2 : m_pic1)->read(space, (offset & 2) >> 1); |
962 | 969 | } |
963 | 970 | else // odd |
964 | 971 | { |
r23720 | r23721 | |
975 | 982 | if(offset & 0x14) |
976 | 983 | printf("Write to undefined port [%02x] <- %02x\n",offset+0x00,data); |
977 | 984 | else |
978 | | machine().device<pic8259_device>((offset & 8) ? "pic8259_slave" : "pic8259_master")->write(space, (offset & 2) >> 1, data); |
| 985 | ((offset & 8) ? m_pic2 : m_pic1)->write(space, (offset & 2) >> 1, data); |
979 | 986 | } |
980 | 987 | else // odd |
981 | 988 | { |
r23720 | r23721 | |
1857 | 1864 | /* reset POR bit, TODO: is there any other way? */ |
1858 | 1865 | por = machine().device<i8255_device>("ppi8255_sys")->read(space, 2) & ~0x20; |
1859 | 1866 | machine().device<i8255_device>("ppi8255_sys")->write(space, 2,por); |
| 1867 | m_maincpu->set_input_line(INPUT_LINE_A20, 0); |
1860 | 1868 | m_maincpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE); |
| 1869 | m_gate_a20 = 0; |
1861 | 1870 | } |
1862 | 1871 | |
1863 | 1872 | if(offset == 0x02) |
r23720 | r23721 | |
1870 | 1879 | else if(data == 0x03) |
1871 | 1880 | m_gate_a20 = 0; |
1872 | 1881 | } |
| 1882 | m_maincpu->set_input_line(INPUT_LINE_A20, m_gate_a20); |
1873 | 1883 | } |
1874 | 1884 | |
1875 | 1885 | READ8_MEMBER(pc9801_state::pc9801rs_30_r) |
r23720 | r23721 | |
2262 | 2272 | { |
2263 | 2273 | //printf("%08x %d\n",offset,m_gate_a20); |
2264 | 2274 | |
2265 | | //if(m_gate_a20 == 0) |
2266 | | // offset &= 0xfffff; |
| 2275 | if(m_gate_a20 == 0) |
| 2276 | offset &= 0xfffff; |
2267 | 2277 | |
2268 | 2278 | if ( offset <= 0x0009ffff) { return pc9801rs_wram_r(space,offset); } |
2269 | 2279 | else if(offset >= 0x000a0000 && offset <= 0x000a3fff) { return pc9801_tvram_r(space,offset-0xa0000); } |
r23720 | r23721 | |
2279 | 2289 | |
2280 | 2290 | WRITE8_MEMBER(pc9801_state::pc9801ux_memory_w) |
2281 | 2291 | { |
2282 | | //if(m_gate_a20 == 0) |
2283 | | // offset &= 0xfffff; |
| 2292 | if(m_gate_a20 == 0) |
| 2293 | offset &= 0xfffff; |
2284 | 2294 | |
2285 | 2295 | if ( offset <= 0x0009ffff) { pc9801rs_wram_w(space,offset,data); } |
2286 | 2296 | else if(offset >= 0x000a0000 && offset <= 0x000a3fff) { pc9801_tvram_w(space,offset-0xa0000,data); } |
r23720 | r23721 | |
2291 | 2301 | // printf("%08x %08x\n",offset,data); |
2292 | 2302 | } |
2293 | 2303 | |
| 2304 | READ8_MEMBER(pc9801_state::pic_r) |
| 2305 | { |
| 2306 | return ((offset >= 4) ? m_pic2 : m_pic1)->read(space, offset & 3); |
| 2307 | } |
| 2308 | |
| 2309 | WRITE8_MEMBER(pc9801_state::pic_w) |
| 2310 | { |
| 2311 | ((offset >= 4) ? m_pic2 : m_pic1)->write(space, offset & 3, data); |
| 2312 | } |
| 2313 | |
2294 | 2314 | static ADDRESS_MAP_START( pc9801ux_map, AS_PROGRAM, 16, pc9801_state ) |
2295 | | /* TODO! */ |
2296 | | AM_RANGE(0x000000, 0xffffff) AM_READWRITE8(pc980ux_memory_r,pc9801ux_memory_w,0xffff) |
| 2315 | AM_RANGE(0x000000, 0x09ffff) AM_RAMBANK("wram") |
| 2316 | AM_RANGE(0x0a0000, 0x0a3fff) AM_READWRITE8(pc9801_tvram_r, pc9801_tvram_w, 0xffff) |
| 2317 | AM_RANGE(0x0a4000, 0x0a4fff) AM_READWRITE8(pc9801rs_knjram_r, pc9801rs_knjram_w, 0xffff) |
| 2318 | AM_RANGE(0x0a8000, 0x0b0fff) AM_READWRITE8(pc9801_gvram_r, pc9801_gvram_w, 0xffff) |
| 2319 | AM_RANGE(0x0e0000, 0x0fffff) AM_READ8(pc9801rs_ipl_r, 0xffff) |
| 2320 | |
| 2321 | // AM_RANGE(0x000000, 0xffffff) AM_READWRITE8(pc980ux_memory_r,pc9801ux_memory_w,0xffff) |
2297 | 2322 | ADDRESS_MAP_END |
2298 | 2323 | |
2299 | 2324 | static ADDRESS_MAP_START( pc9801ux_io, AS_IO, 16, pc9801_state ) |
2300 | 2325 | ADDRESS_MAP_UNMAP_HIGH |
2301 | | AM_RANGE(0x0000, 0x001f) AM_READWRITE8(pc9801_00_r, pc9801_00_w, 0xffff) // i8259 PIC (bit 3 ON slave / master) / i8237 DMA |
| 2326 | |
| 2327 | AM_RANGE(0x0000, 0x001f) AM_DEVREADWRITE8("i8237", am9517a_device, read, write, 0xff00) |
| 2328 | AM_RANGE(0x0000, 0x000f) AM_READWRITE8(pic_r, pic_w, 0x00ff) // i8259 PIC (bit 3 ON slave / master) / i8237 DMA |
2302 | 2329 | AM_RANGE(0x0020, 0x0027) AM_READWRITE8(pc9801_20_r, pc9801_20_w, 0xffff) // RTC / DMA registers (LS244) |
2303 | 2330 | AM_RANGE(0x0030, 0x0037) AM_READWRITE8(pc9801rs_30_r, pc9801_30_w, 0xffff) //i8251 RS232c / i8255 system port |
2304 | 2331 | AM_RANGE(0x0040, 0x0047) AM_READWRITE8(pc9801_40_r, pc9801_40_w, 0xffff) //i8255 printer port / i8251 keyboard |
r23720 | r23721 | |
2914 | 2941 | */ |
2915 | 2942 | |
2916 | 2943 | |
2917 | | WRITE_LINE_MEMBER(pc9801_state::pc9801_master_set_int_line) |
2918 | | { |
2919 | | //printf("%02x\n",interrupt); |
2920 | | m_maincpu->set_input_line(0, state ? HOLD_LINE : CLEAR_LINE); |
2921 | | } |
2922 | | |
2923 | 2944 | READ8_MEMBER(pc9801_state::get_slave_ack) |
2924 | 2945 | { |
2925 | 2946 | if (offset==7) { // IRQ = 7 |
r23720 | r23721 | |
3100 | 3121 | m_beeper->set_state(!(data & 0x08)); |
3101 | 3122 | } |
3102 | 3123 | |
| 3124 | READ8_MEMBER(pc9801_state::ppi_sys_portc_r) |
| 3125 | { |
| 3126 | return 0xa0; // 0x80 cpu triple fault reset flag? |
| 3127 | } |
| 3128 | |
3103 | 3129 | static I8255A_INTERFACE( ppi_system_intf ) |
3104 | 3130 | { |
3105 | 3131 | DEVCB_DRIVER_MEMBER(pc9801_state,ppi_sys_porta_r), /* Port A read */ |
3106 | 3132 | DEVCB_NULL, /* Port A write */ |
3107 | 3133 | DEVCB_DRIVER_MEMBER(pc9801_state,ppi_sys_portb_r), /* Port B read */ |
3108 | 3134 | DEVCB_NULL, /* Port B write */ |
3109 | | DEVCB_NULL, /* Port C read */ |
| 3135 | DEVCB_DRIVER_MEMBER(pc9801_state,ppi_sys_portc_r), /* Port C read */ |
3110 | 3136 | DEVCB_DRIVER_MEMBER(pc9801_state,ppi_sys_portc_w) /* Port C write */ |
3111 | 3137 | }; |
3112 | 3138 | |
r23720 | r23721 | |
3236 | 3262 | void pc9801_state::fdc_2hd_irq(bool state) |
3237 | 3263 | { |
3238 | 3264 | // printf("IRQ 2HD %d\n",state); |
3239 | | machine().device<pic8259_device>("pic8259_slave")->ir3_w(state); |
| 3265 | m_pic2->ir3_w(state); |
3240 | 3266 | } |
3241 | 3267 | |
3242 | 3268 | void pc9801_state::fdc_2hd_drq(bool state) |
r23720 | r23721 | |
3251 | 3277 | |
3252 | 3278 | if(m_fdc_2dd_ctrl & 8) |
3253 | 3279 | { |
3254 | | machine().device<pic8259_device>("pic8259_slave")->ir2_w(state); |
| 3280 | m_pic2->ir2_w(state); |
3255 | 3281 | } |
3256 | 3282 | } |
3257 | 3283 | |
r23720 | r23721 | |
3268 | 3294 | //printf("%02x %d\n",m_fdc_ctrl,state); |
3269 | 3295 | |
3270 | 3296 | if(m_fdc_ctrl & 1) |
3271 | | machine().device<pic8259_device>("pic8259_slave")->ir3_w(state); |
| 3297 | m_pic2->ir3_w(state); |
3272 | 3298 | else |
3273 | | machine().device<pic8259_device>("pic8259_slave")->ir2_w(state); |
| 3299 | m_pic2->ir2_w(state); |
3274 | 3300 | } |
3275 | 3301 | |
3276 | 3302 | void pc9801_state::pc9801rs_fdc_drq(bool state) |
r23720 | r23721 | |
3296 | 3322 | DEVCB_NULL |
3297 | 3323 | }; |
3298 | 3324 | |
| 3325 | UINT32 pc9801_state::pc9801_286_a20(bool state) |
| 3326 | { |
| 3327 | return (state ? 0xffffff : 0x0fffff); |
| 3328 | } |
| 3329 | |
| 3330 | static const i80286_interface pc9801_286 = |
| 3331 | { |
| 3332 | pc9801_state::pc9801_286_a20 |
| 3333 | }; |
| 3334 | |
3299 | 3335 | /**************************************** |
3300 | 3336 | * |
3301 | 3337 | * Init emulation status |
r23720 | r23721 | |
3315 | 3351 | |
3316 | 3352 | IRQ_CALLBACK_MEMBER(pc9801_state::irq_callback) |
3317 | 3353 | { |
3318 | | return machine().device<pic8259_device>( "pic8259_master" )->acknowledge(); |
| 3354 | return m_pic1->acknowledge(); |
3319 | 3355 | } |
3320 | 3356 | |
3321 | 3357 | MACHINE_START_MEMBER(pc9801_state,pc9801_common) |
r23720 | r23721 | |
3365 | 3401 | { |
3366 | 3402 | MACHINE_START_CALL_MEMBER(pc9801_common); |
3367 | 3403 | |
3368 | | m_work_ram = auto_alloc_array(machine(), UINT8, 0xa0000); |
3369 | | m_ext_work_ram = auto_alloc_array(machine(), UINT8, 0x700000); |
3370 | | save_pointer(NAME(m_work_ram), 0xa0000); |
3371 | | save_pointer(NAME(m_ext_work_ram), 0x700000); |
| 3404 | m_work_ram = m_ram->pointer(); |
| 3405 | m_ext_work_ram = m_ram->pointer() + 0xa0000; |
3372 | 3406 | |
3373 | 3407 | m_ram_size = m_ram->size() - 0xa0000; |
3374 | 3408 | |
| 3409 | // TODO: rs and 9821 also |
| 3410 | if(!strncmp(machine().system().name, "pc9801ux", 8)) |
| 3411 | { |
| 3412 | address_space& space = m_maincpu->space(AS_PROGRAM); |
| 3413 | membank("wram")->set_base(m_ram->pointer()); |
| 3414 | space.install_read_bank(0x100000, 0x100000 + m_ram_size - 1, "ext_wram"); |
| 3415 | space.install_write_bank(0x100000, 0x100000 + m_ram_size - 1, "ext_wram"); |
| 3416 | membank("ext_wram")->set_base(m_ram->pointer() + 0xa0000); |
| 3417 | } |
| 3418 | |
3375 | 3419 | upd765a_device *fdc; |
3376 | 3420 | fdc = machine().device<upd765a_device>(":upd765_2hd"); |
3377 | 3421 | fdc->setup_intrq_cb(upd765a_device::line_cb(FUNC(pc9801_state::pc9801rs_fdc_irq), this)); |
r23720 | r23721 | |
3462 | 3506 | m_keyb_press = 0xff; // temp kludge, for PC-9821 booting |
3463 | 3507 | // m_has_opna = ioport("SOUND_CONFIG")->read() & 1; |
3464 | 3508 | memset(m_work_ram, 0, sizeof(UINT8) * 0xa0000); |
| 3509 | m_maincpu->set_input_line(INPUT_LINE_A20, m_gate_a20); |
3465 | 3510 | } |
3466 | 3511 | |
3467 | 3512 | MACHINE_RESET_MEMBER(pc9801_state,pc9821) |
r23720 | r23721 | |
3475 | 3520 | { |
3476 | 3521 | if(m_vrtc_irq_mask) |
3477 | 3522 | { |
3478 | | machine().device<pic8259_device>("pic8259_master")->ir2_w(0); |
3479 | | machine().device<pic8259_device>("pic8259_master")->ir2_w(1); |
| 3523 | m_pic1->ir2_w(0); |
| 3524 | m_pic1->ir2_w(1); |
3480 | 3525 | m_vrtc_irq_mask = 0; // TODO: this irq auto-masks? |
3481 | 3526 | } |
3482 | 3527 | // else |
r23720 | r23721 | |
3499 | 3544 | { |
3500 | 3545 | // printf("irq %02x\n",m_mouse.freq_reg); |
3501 | 3546 | m_mouse.freq_index = 0; |
3502 | | machine().device<pic8259_device>("pic8259_slave")->ir5_w(0); |
3503 | | machine().device<pic8259_device>("pic8259_slave")->ir5_w(1); |
| 3547 | m_pic2->ir5_w(0); |
| 3548 | m_pic2->ir5_w(1); |
3504 | 3549 | } |
3505 | 3550 | } |
3506 | 3551 | } |
3507 | 3552 | |
3508 | 3553 | WRITE_LINE_MEMBER( pc9801_state::keyboard_irq ) |
3509 | 3554 | { |
3510 | | machine().device<pic8259_device>("pic8259_master")->ir1_w(state); |
| 3555 | m_pic1->ir1_w(state); |
3511 | 3556 | } |
3512 | 3557 | |
3513 | 3558 | static PC9801_KBD_INTERFACE( pc9801_keyboard_intf ) |
r23720 | r23721 | |
3549 | 3594 | |
3550 | 3595 | MCFG_PIT8253_ADD( "pit8253", pc9801_pit8253_config ) |
3551 | 3596 | MCFG_I8237_ADD("i8237", 5000000, dmac_intf) // unknown clock |
3552 | | MCFG_PIC8259_ADD( "pic8259_master", WRITELINE(pc9801_state, pc9801_master_set_int_line), VCC, READ8(pc9801_state,get_slave_ack) ) |
| 3597 | MCFG_PIC8259_ADD( "pic8259_master", INPUTLINE("maincpu", 0), VCC, READ8(pc9801_state,get_slave_ack) ) |
3553 | 3598 | MCFG_PIC8259_ADD( "pic8259_slave", DEVWRITELINE("pic8259_master", pic8259_device, ir7_w), GND, NULL ) // TODO: Check ir7_w |
3554 | 3599 | MCFG_I8255_ADD( "ppi8255_sys", ppi_system_intf ) |
3555 | 3600 | MCFG_I8255_ADD( "ppi8255_prn", ppi_printer_intf ) |
r23720 | r23721 | |
3618 | 3663 | |
3619 | 3664 | MCFG_PIT8253_ADD( "pit8253", pc9801_pit8253_config ) |
3620 | 3665 | MCFG_I8237_ADD("i8237", MAIN_CLOCK_X1*8, pc9801rs_dmac_intf) // unknown clock |
3621 | | MCFG_PIC8259_ADD( "pic8259_master", WRITELINE(pc9801_state, pc9801_master_set_int_line), VCC, READ8(pc9801_state,get_slave_ack) ) |
| 3666 | MCFG_PIC8259_ADD( "pic8259_master", INPUTLINE("maincpu", 0), VCC, READ8(pc9801_state,get_slave_ack) ) |
3622 | 3667 | MCFG_PIC8259_ADD( "pic8259_slave", DEVWRITELINE("pic8259_master", pic8259_device, ir7_w), GND, NULL ) // TODO: Check ir7_w |
3623 | 3668 | MCFG_I8255_ADD( "ppi8255_sys", ppi_system_intf ) |
3624 | 3669 | MCFG_I8255_ADD( "ppi8255_prn", ppi_printer_intf ) |
r23720 | r23721 | |
3663 | 3708 | MCFG_SOUND_ROUTE(ALL_OUTPUTS,"mono",0.15) |
3664 | 3709 | MACHINE_CONFIG_END |
3665 | 3710 | |
3666 | | static const unsigned i286_address_mask = 0x00ffffff; |
| 3711 | static const UINT32 a20_mask = 0xfffff; |
3667 | 3712 | |
3668 | 3713 | static MACHINE_CONFIG_DERIVED( pc9801ux, pc9801rs ) |
3669 | 3714 | MCFG_CPU_REPLACE("maincpu",I80286,10000000) |
3670 | | MCFG_CPU_CONFIG(i286_address_mask) |
| 3715 | MCFG_CPU_CONFIG(a20_mask) |
3671 | 3716 | MCFG_CPU_PROGRAM_MAP(pc9801ux_map) |
3672 | 3717 | MCFG_CPU_IO_MAP(pc9801ux_io) |
| 3718 | MCFG_CPU_CONFIG(pc9801_286) |
3673 | 3719 | MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq) |
3674 | 3720 | MACHINE_CONFIG_END |
3675 | 3721 | |
r23720 | r23721 | |
3684 | 3730 | |
3685 | 3731 | MCFG_PIT8253_ADD( "pit8253", pc9821_pit8253_config ) |
3686 | 3732 | MCFG_I8237_ADD("i8237", 16000000, pc9801rs_dmac_intf) // unknown clock |
3687 | | MCFG_PIC8259_ADD( "pic8259_master", WRITELINE(pc9801_state, pc9801_master_set_int_line), VCC, READ8(pc9801_state,get_slave_ack) ) |
| 3733 | MCFG_PIC8259_ADD( "pic8259_master", INPUTLINE("maincpu", 0), VCC, READ8(pc9801_state,get_slave_ack) ) |
3688 | 3734 | MCFG_PIC8259_ADD( "pic8259_slave", DEVWRITELINE("pic8259_master", pic8259_device, ir7_w), GND, NULL ) // TODO: Check ir7_w |
3689 | 3735 | MCFG_I8255_ADD( "ppi8255_sys", ppi_system_intf ) |
3690 | 3736 | MCFG_I8255_ADD( "ppi8255_prn", ppi_printer_intf ) |