1
/***************************************************************************
5
Functions to emulate general aspects of the machine
6
(RAM, ROM, interrupts, I/O ports)
8
The information herein is heavily based on
9
'Ralph Browns Interrupt List'
10
Release 52, Last Change 20oct96
13
clean up (maybe split) the different pieces of hardware
14
PIC, PIT, DMA... add support for LPT, COM (almost done)
15
emulation of a serial mouse on a COM port (almost done)
16
support for Game Controller port at 0x0201
17
support for XT harddisk (under the way, see machine/pc_hdc.c)
18
whatever 'hardware' comes to mind,
19
maybe SoundBlaster? EGA? VGA?
21
***************************************************************************/
24
#include "machine/pcshare.h"
25
#include "machine/pckeybrd.h"
26
#include "machine/8237dma.h"
27
#include "machine/pic8259.h"
28
#include "machine/pit8253.h"
29
#include "machine/8042kbdc.h"
30
#include "machine/mc146818.h"
32
#define VERBOSE_DBG 0 /* general debug messages */
33
#define DBG_LOG(N,M,A) \
34
if(VERBOSE_DBG>=N){ if( M )logerror("%11.6f: %-24s",pc_keyb.machine().time().as_double(),(char*)M ); logerror A; }
36
#define VERBOSE_JOY 0 /* JOY (joystick port) */
37
#define JOY_LOG(N,M,A) \
38
if(VERBOSE_JOY>=N){ if( M )logerror("%11.6f: %-24s",pc_keyb.machine().time().as_double(),(char*)M ); logerror A; }
41
static TIMER_CALLBACK( pc_keyb_timer );
44
keyboard seams to permanently sent data clocked by the mainboard
45
clock line low for longer means "resync", keyboard sends 0xaa as answer
46
will become automatically 0x00 after a while
50
running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
52
running_machine *m_machine;
53
void (*int_cb)(running_machine &, int);
62
void init_pc_common(running_machine &machine, UINT32 flags, void (*set_keyb_int_func)(running_machine &, int))
65
if (flags & PCCOMMON_KEYBOARD_AT)
66
at_keyboard_init(machine, AT_KEYBOARD_TYPE_AT);
68
at_keyboard_init(machine, AT_KEYBOARD_TYPE_PC);
69
at_keyboard_set_scan_code_set(1);
71
memset(&pc_keyb, 0, sizeof(pc_keyb));
72
pc_keyb.m_machine = &machine;
73
pc_keyb.int_cb = set_keyb_int_func;
74
pc_keyb.timer = machine.scheduler().timer_alloc(FUNC(pc_keyb_timer));
77
UINT8 pc_keyb_read(void)
84
static TIMER_CALLBACK( pc_keyb_timer )
89
/* Clock has been low for more than 5 msec, start diagnostic test */
90
at_keyboard_reset(machine);
91
pc_keyb.self_test = 1;
97
void pc_keyb_set_clock(int on)
101
if (pc_keyb.on != on)
104
pc_keyb.timer->adjust(attotime::from_msec(5));
106
if ( pc_keyb.self_test ) {
107
/* The self test of the keyboard takes some time. 2 msec seems to work. */
108
/* This still needs to verified against a real keyboard. */
109
pc_keyb.timer->adjust(attotime::from_msec( 2 ));
111
pc_keyb.timer->reset();
112
pc_keyb.self_test = 0;
120
void pc_keyb_clear(void)
123
if ( pc_keyb.int_cb ) {
124
pc_keyb.int_cb(pc_keyb.machine(), 0);
128
void pc_keyboard(void)
132
at_keyboard_polling();
136
if ( (data=at_keyboard_read())!=-1) {
138
DBG_LOG(1,"KB_scancode",("$%02x\n", pc_keyb.data));
139
if ( pc_keyb.int_cb ) {
140
pc_keyb.int_cb(pc_keyb.machine(), 1);
142
pc_keyb.self_test = 0;
151
static int dma_channel;
152
static UINT8 dma_offset[2][4];
153
static UINT8 at_pages[0x10];
155
static WRITE_LINE_DEVICE_HANDLER( pc_dma_hrq_changed )
157
cputag_set_input_line(device->machine(), "maincpu", INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
160
i8237_hlda_w( device, state );
164
static READ8_HANDLER( pc_dma_read_byte )
166
offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16)
169
return space->read_byte(page_offset + offset);
173
static WRITE8_HANDLER( pc_dma_write_byte )
175
offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16)
178
space->write_byte(page_offset + offset, data);
181
static READ8_HANDLER(dma_page_select_r)
183
UINT8 data = at_pages[offset % 0x10];
188
data = dma_offset[(offset / 8) & 1][2];
191
data = dma_offset[(offset / 8) & 1][3];
194
data = dma_offset[(offset / 8) & 1][1];
197
data = dma_offset[(offset / 8) & 1][0];
204
static WRITE8_HANDLER(dma_page_select_w)
206
at_pages[offset % 0x10] = data;
211
dma_offset[(offset / 8) & 1][2] = data;
214
dma_offset[(offset / 8) & 1][3] = data;
217
dma_offset[(offset / 8) & 1][1] = data;
220
dma_offset[(offset / 8) & 1][0] = data;
225
static void set_dma_channel(device_t *device, int channel, int state)
227
if (!state) dma_channel = channel;
230
static WRITE_LINE_DEVICE_HANDLER( pc_dack0_w ) { set_dma_channel(device, 0, state); }
231
static WRITE_LINE_DEVICE_HANDLER( pc_dack1_w ) { set_dma_channel(device, 1, state); }
232
static WRITE_LINE_DEVICE_HANDLER( pc_dack2_w ) { set_dma_channel(device, 2, state); }
233
static WRITE_LINE_DEVICE_HANDLER( pc_dack3_w ) { set_dma_channel(device, 3, state); }
235
static I8237_INTERFACE( dma8237_1_config )
237
DEVCB_LINE(pc_dma_hrq_changed),
239
DEVCB_MEMORY_HANDLER("maincpu", PROGRAM, pc_dma_read_byte),
240
DEVCB_MEMORY_HANDLER("maincpu", PROGRAM, pc_dma_write_byte),
241
{ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL },
242
{ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL },
243
{ DEVCB_LINE(pc_dack0_w), DEVCB_LINE(pc_dack1_w), DEVCB_LINE(pc_dack2_w), DEVCB_LINE(pc_dack3_w) }
246
static I8237_INTERFACE( dma8237_2_config )
252
{ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL },
253
{ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL },
254
{ DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL }
262
static WRITE_LINE_DEVICE_HANDLER( pic8259_1_set_int_line )
264
cputag_set_input_line(device->machine(), "maincpu", 0, state ? HOLD_LINE : CLEAR_LINE);
267
static READ8_DEVICE_HANDLER( get_slave_ack )
269
if (offset==2) { // IRQ = 2
270
return pic8259_acknowledge(device->machine().device("pic8259_2"));
275
static const struct pic8259_interface pic8259_1_config =
277
DEVCB_LINE(pic8259_1_set_int_line),
279
DEVCB_HANDLER(get_slave_ack)
282
static const struct pic8259_interface pic8259_2_config =
284
DEVCB_DEVICE_LINE("pic8259_1", pic8259_ir2_w),
289
IRQ_CALLBACK(pcat_irq_callback)
291
return pic8259_acknowledge(device->machine().device("pic8259_1"));
294
static WRITE_LINE_DEVICE_HANDLER( at_pit8254_out0_changed )
296
if ( device->machine().device("pic8259_1") )
298
pic8259_ir0_w(device->machine().device("pic8259_1"), state);
303
static WRITE_LINE_DEVICE_HANDLER( at_pit8254_out2_changed )
305
//at_speaker_set_input( state ? 1 : 0 );
309
static const struct pit8253_config at_pit8254_config =
313
4772720/4, /* heartbeat IRQ */
315
DEVCB_LINE(at_pit8254_out0_changed)
317
4772720/4, /* dram refresh */
321
4772720/4, /* pio port c pin 4, and speaker polling enough */
323
DEVCB_LINE(at_pit8254_out2_changed)
328
ADDRESS_MAP_START( pcat32_io_common, AS_IO, 32 )
329
AM_RANGE(0x0000, 0x001f) AM_DEVREADWRITE8("dma8237_1", i8237_r, i8237_w, 0xffffffff)
330
AM_RANGE(0x0020, 0x003f) AM_DEVREADWRITE8("pic8259_1", pic8259_r, pic8259_w, 0xffffffff)
331
AM_RANGE(0x0040, 0x005f) AM_DEVREADWRITE8("pit8254", pit8253_r, pit8253_w, 0xffffffff)
332
AM_RANGE(0x0060, 0x006f) AM_READWRITE8(kbdc8042_8_r, kbdc8042_8_w, 0xffffffff)
333
AM_RANGE(0x0070, 0x007f) AM_RAM //AM_DEVREADWRITE8_MODERN("rtc", mc146818_device, read, write, 0xffffffff)
334
AM_RANGE(0x0080, 0x009f) AM_READWRITE8(dma_page_select_r,dma_page_select_w, 0xffffffff)//TODO
335
AM_RANGE(0x00a0, 0x00bf) AM_DEVREADWRITE8("pic8259_2", pic8259_r, pic8259_w, 0xffffffff)
336
AM_RANGE(0x00c0, 0x00df) AM_DEVREADWRITE8("dma8237_2", i8237_r, i8237_w, 0xffff)
339
MACHINE_CONFIG_FRAGMENT(pcat_common)
340
MCFG_PIC8259_ADD( "pic8259_1", pic8259_1_config )
341
MCFG_PIC8259_ADD( "pic8259_2", pic8259_2_config )
342
MCFG_I8237_ADD( "dma8237_1", XTAL_14_31818MHz/3, dma8237_1_config )
343
MCFG_I8237_ADD( "dma8237_2", XTAL_14_31818MHz/3, dma8237_2_config )
344
MCFG_PIT8254_ADD( "pit8254", at_pit8254_config )
345
// MCFG_MC146818_ADD( "rtc", MC146818_STANDARD )