diff options
author | Miodrag Milanovic <mmicko@gmail.com> | 2011-05-07 12:03:33 +0000 |
---|---|---|
committer | Miodrag Milanovic <mmicko@gmail.com> | 2011-05-07 12:03:33 +0000 |
commit | df7401d0e2aa2358e0ed1d7c6554d8e971d003f3 (patch) | |
tree | e8ea9ce1a666f61dc9c71ed535229e6aa5d42466 | |
parent | f7d01e8bf53d9f6b2e60dbb95514f6c5a3a561f7 (diff) |
Moved some devices back to MESS since they belong there and are not used by arcades. (no whatsnew)
Note that msm8251 would be nice to have on emu section but it depends of serial.c which needs to be rewritten in order to be useful. Also upd765 is used only by MESS and it's pain to keep it in emu since it is not yet bug free.
-rw-r--r-- | .gitattributes | 6 | ||||
-rw-r--r-- | src/emu/emu.mak | 3 | ||||
-rw-r--r-- | src/emu/machine/msm8251.c | 825 | ||||
-rw-r--r-- | src/emu/machine/msm8251.h | 88 | ||||
-rw-r--r-- | src/emu/machine/serial.c | 733 | ||||
-rw-r--r-- | src/emu/machine/serial.h | 247 | ||||
-rw-r--r-- | src/emu/machine/upd765.c | 2457 | ||||
-rw-r--r-- | src/emu/machine/upd765.h | 161 | ||||
-rw-r--r-- | src/mame/drivers/sg1000.c | 264 | ||||
-rw-r--r-- | src/mame/includes/sg1000.h | 34 |
10 files changed, 13 insertions, 4805 deletions
diff --git a/.gitattributes b/.gitattributes index 723537cb085..8028ed45853 100644 --- a/.gitattributes +++ b/.gitattributes @@ -859,8 +859,6 @@ src/emu/machine/msm58321.c svneol=native#text/plain src/emu/machine/msm58321.h svneol=native#text/plain src/emu/machine/msm6242.c svneol=native#text/plain src/emu/machine/msm6242.h svneol=native#text/plain -src/emu/machine/msm8251.c svneol=native#text/plain -src/emu/machine/msm8251.h svneol=native#text/plain src/emu/machine/nmc9306.c svneol=native#text/plain src/emu/machine/nmc9306.h svneol=native#text/plain src/emu/machine/nvram.c svneol=native#text/plain @@ -907,8 +905,6 @@ src/emu/machine/scsihd.c svneol=native#text/plain src/emu/machine/scsihd.h svneol=native#text/plain src/emu/machine/secflash.c svneol=native#text/plain src/emu/machine/secflash.h svneol=native#text/plain -src/emu/machine/serial.c svneol=native#text/plain -src/emu/machine/serial.h svneol=native#text/plain src/emu/machine/smc91c9x.c svneol=native#text/plain src/emu/machine/smc91c9x.h svneol=native#text/plain src/emu/machine/timekpr.c svneol=native#text/plain @@ -923,8 +919,6 @@ src/emu/machine/upd4701.c svneol=native#text/plain src/emu/machine/upd4701.h svneol=native#text/plain src/emu/machine/upd7201.c svneol=native#text/plain src/emu/machine/upd7201.h svneol=native#text/plain -src/emu/machine/upd765.c svneol=native#text/plain -src/emu/machine/upd765.h svneol=native#text/plain src/emu/machine/wd17xx.c svneol=native#text/plain src/emu/machine/wd17xx.h svneol=native#text/plain src/emu/machine/wd33c93.c svneol=native#text/plain diff --git a/src/emu/emu.mak b/src/emu/emu.mak index 2e794605003..34e4a03bf65 100644 --- a/src/emu/emu.mak +++ b/src/emu/emu.mak @@ -207,7 +207,6 @@ EMUMACHINEOBJS = \ $(EMUMACHINE)/msm5832.o \ $(EMUMACHINE)/msm58321.o \ $(EMUMACHINE)/msm6242.o \ - $(EMUMACHINE)/msm8251.o \ $(EMUMACHINE)/nmc9306.o \ $(EMUMACHINE)/nvram.o \ $(EMUMACHINE)/pc16552d.o \ @@ -229,7 +228,6 @@ EMUMACHINEOBJS = \ $(EMUMACHINE)/scsidev.o \ $(EMUMACHINE)/scsihd.o \ $(EMUMACHINE)/secflash.o \ - $(EMUMACHINE)/serial.o \ $(EMUMACHINE)/smc91c9x.o \ $(EMUMACHINE)/timekpr.o \ $(EMUMACHINE)/tmp68301.o \ @@ -237,7 +235,6 @@ EMUMACHINEOBJS = \ $(EMUMACHINE)/upd1990a.o \ $(EMUMACHINE)/upd4701.o \ $(EMUMACHINE)/upd7201.o \ - $(EMUMACHINE)/upd765.o \ $(EMUMACHINE)/wd17xx.o \ $(EMUMACHINE)/wd33c93.o \ $(EMUMACHINE)/x2212.o \ diff --git a/src/emu/machine/msm8251.c b/src/emu/machine/msm8251.c deleted file mode 100644 index 1615f4b5c5f..00000000000 --- a/src/emu/machine/msm8251.c +++ /dev/null @@ -1,825 +0,0 @@ -/********************************************************************* - - msm8251.c - - MSM/Intel 8251 Universal Synchronous/Asynchronous Receiver Transmitter code - -*********************************************************************/ - -#include "emu.h" -#include "msm8251.h" - - -/*************************************************************************** - MACROS -***************************************************************************/ - -#define VERBOSE 0 - -#define LOG(x) do { if (VERBOSE) logerror x; } while (0) - - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -typedef struct _msm8251_t msm8251_t; -struct _msm8251_t -{ - devcb_resolved_read_line in_rxd_func; - devcb_resolved_write_line out_txd_func; - devcb_resolved_read_line in_dsr_func; - devcb_resolved_write_line out_dtr_func; - devcb_resolved_write_line out_rts_func; - devcb_resolved_write_line out_rxrdy_func; - devcb_resolved_write_line out_txrdy_func; - devcb_resolved_write_line out_txempty_func; - devcb_resolved_write_line out_syndet_func; - - /* flags controlling how msm8251_control_w operates */ - UINT8 flags; - /* offset into sync_bytes used during sync byte transfer */ - UINT8 sync_byte_offset; - /* number of sync bytes written so far */ - UINT8 sync_byte_count; - /* the sync bytes written */ - UINT8 sync_bytes[2]; - /* status of msm8251 */ - UINT8 status; - UINT8 command; - /* mode byte - bit definitions depend on mode - e.g. synchronous, asynchronous */ - UINT8 mode_byte; - - /* data being received */ - UINT8 data; - - /* receive reg */ - serial_receive_register receive_reg; - /* transmit reg */ - serial_transmit_register transmit_reg; - - data_form form; - - /* the serial connection that data is transfered over */ - /* this is usually connected to the serial device */ - serial_connection connection; -}; - - - -/*************************************************************************** - PROTOTYPES -***************************************************************************/ - -static void msm8251_in_callback(running_machine &machine, int id, unsigned long state); -static void msm8251_update_tx_empty(device_t *device); -static void msm8251_update_tx_ready(device_t *device); - - - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -INLINE msm8251_t *get_token(device_t *device) -{ - assert(device != NULL); - assert(device->type() == MSM8251); - - return (msm8251_t *) downcast<legacy_device_base *>(device)->token(); -} - - -INLINE const msm8251_interface *get_interface(device_t *device) -{ - assert(device != NULL); - assert(device->type() == MSM8251); - - return (const msm8251_interface *) device->static_config(); -} - - -/*************************************************************************** - GLOBAL VARIABLES -***************************************************************************/ - -const msm8251_interface default_msm8251_interface = { DEVCB_NULL, }; - - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ - -/*------------------------------------------------- - msm8251_in_callback --------------------------------------------------*/ - -static void msm8251_in_callback(running_machine &machine, int id, unsigned long state) -{ - device_t *device; - msm8251_t *uart; - int changed; - - /* NPW 29-Nov-2008 - These two lines are a hack and indicate why our "serial" infrastructure needs to be updated */ - device = machine.device("uart"); - uart = get_token(device); - - changed = uart->connection.input_state^state; - - uart->connection.input_state = state; - - /* did cts change state? */ - if (changed & SERIAL_STATE_CTS) - { - /* yes */ - /* update tx ready */ - /* msm8251_update_tx_ready(device); */ - } -} - - - -/*------------------------------------------------- - DEVICE_START( msm8251 ) --------------------------------------------------*/ - -static DEVICE_START( msm8251 ) -{ - msm8251_t *uart = get_token(device); - const msm8251_interface *intf = get_interface(device); - - serial_helper_setup(); - - // resolve callbacks - uart->out_rxrdy_func.resolve(intf->out_rxrdy_func, *device); - uart->out_txrdy_func.resolve(intf->out_txrdy_func, *device); - uart->out_txempty_func.resolve(intf->out_txempty_func, *device); - - /* setup this side of the serial connection */ - serial_connection_init(device->machine(),&uart->connection); - serial_connection_set_in_callback(device->machine(),&uart->connection, msm8251_in_callback); - uart->connection.input_state = 0; -} - - - -/*------------------------------------------------- - msm8251_update_rx_ready --------------------------------------------------*/ - -static void msm8251_update_rx_ready(device_t *device) -{ - msm8251_t *uart = get_token(device); - int state; - - state = uart->status & MSM8251_STATUS_RX_READY; - - /* masked? */ - if ((uart->command & (1<<2))==0) - { - state = 0; - } - - uart->out_rxrdy_func(state != 0); -} - - - -/*------------------------------------------------- - msm8251_receive_clock --------------------------------------------------*/ - -void msm8251_receive_clock(device_t *device) -{ - msm8251_t *uart = get_token(device); - - /* receive enable? */ - if (uart->command & (1<<2)) - { - //logerror("MSM8251\n"); - /* get bit received from other side and update receive register */ - receive_register_update_bit(&uart->receive_reg, get_in_data_bit(uart->connection.input_state)); - - if (uart->receive_reg.flags & RECEIVE_REGISTER_FULL) - { - receive_register_extract(&uart->receive_reg, &uart->form); - msm8251_receive_character(device, uart->receive_reg.byte_received); - } - } -} - - - -/*------------------------------------------------- - msm8251_transmit_clock --------------------------------------------------*/ - -void msm8251_transmit_clock(device_t *device) -{ - msm8251_t *uart = get_token(device); - - /* transmit enable? */ - if (uart->command & (1<<0)) - { - - /* transmit register full? */ - if ((uart->status & MSM8251_STATUS_TX_READY)==0) - { - /* if transmit reg is empty */ - if ((uart->transmit_reg.flags & TRANSMIT_REGISTER_EMPTY)!=0) - { - /* set it up */ - transmit_register_setup(&uart->transmit_reg, &uart->form, uart->data); - /* msm8251 transmit reg now empty */ - uart->status |=MSM8251_STATUS_TX_EMPTY; - /* ready for next transmit */ - uart->status |=MSM8251_STATUS_TX_READY; - - msm8251_update_tx_empty(device); - msm8251_update_tx_ready(device); - } - } - - /* if transmit is not empty... transmit data */ - if ((uart->transmit_reg.flags & TRANSMIT_REGISTER_EMPTY)==0) - { - // logerror("MSM8251\n"); - transmit_register_send_bit(device->machine(),&uart->transmit_reg, &uart->connection); - } - } - -#if 0 - /* hunt mode? */ - /* after each bit has been shifted in, it is compared against the current sync byte */ - if (uart->command & (1<<7)) - { - /* data matches sync byte? */ - if (uart->data == uart->sync_bytes[uart->sync_byte_offset]) - { - /* sync byte matches */ - /* update for next sync byte? */ - uart->sync_byte_offset++; - - /* do all sync bytes match? */ - if (uart->sync_byte_offset == uart->sync_byte_count) - { - /* ent hunt mode */ - uart->command &=~(1<<7); - } - } - else - { - /* if there is no match, reset */ - uart->sync_byte_offset = 0; - } - } -#endif -} - - - -/*------------------------------------------------- - msm8251_update_tx_ready --------------------------------------------------*/ - -static void msm8251_update_tx_ready(device_t *device) -{ - msm8251_t *uart = get_token(device); - - /* clear tx ready state */ - int tx_ready; - - /* tx ready output is set if: - DB Buffer Empty & - CTS is set & - Transmit enable is 1 - */ - - tx_ready = 0; - - /* transmit enable? */ - if ((uart->command & (1<<0))!=0) - { - /* other side has rts set (comes in as CTS at this side) */ - if (uart->connection.input_state & SERIAL_STATE_CTS) - { - if (uart->status & MSM8251_STATUS_TX_EMPTY) - { - /* enable transfer */ - tx_ready = 1; - } - } - } - - uart->out_txrdy_func(tx_ready); -} - - - -/*------------------------------------------------- - msm8251_update_tx_empty --------------------------------------------------*/ - -static void msm8251_update_tx_empty(device_t *device) -{ - msm8251_t *uart = get_token(device); - - if (uart->status & MSM8251_STATUS_TX_EMPTY) - { - /* tx is in marking state (high) when tx empty! */ - set_out_data_bit(uart->connection.State, 1); - serial_connection_out(device->machine(),&uart->connection); - } - - uart->out_txempty_func((uart->status & MSM8251_STATUS_TX_EMPTY) != 0); -} - - - -/*------------------------------------------------- - DEVICE_RESET( msm8251 ) --------------------------------------------------*/ - -static DEVICE_RESET( msm8251 ) -{ - msm8251_t *uart = get_token(device); - - LOG(("MSM8251: Reset\n")); - - /* what is the default setup when the 8251 has been reset??? */ - - /* msm8251 datasheet explains the state of tx pin at reset */ - /* tx is set to 1 */ - set_out_data_bit(uart->connection.State,1); - - /* assumption, rts is set to 1 */ - uart->connection.State &= ~SERIAL_STATE_RTS; - serial_connection_out(device->machine(), &uart->connection); - - transmit_register_reset(&uart->transmit_reg); - receive_register_reset(&uart->receive_reg); - /* expecting mode byte */ - uart->flags |= MSM8251_EXPECTING_MODE; - /* not expecting a sync byte */ - uart->flags &= ~MSM8251_EXPECTING_SYNC_BYTE; - - /* no character to read by cpu */ - /* transmitter is ready and is empty */ - uart->status = MSM8251_STATUS_TX_EMPTY | MSM8251_STATUS_TX_READY; - uart->mode_byte = 0; - uart->command = 0; - - /* update tx empty pin output */ - msm8251_update_tx_empty(device); - /* update rx ready pin output */ - msm8251_update_rx_ready(device); - /* update tx ready pin output */ - msm8251_update_tx_ready(device); -} - - - -/*------------------------------------------------- - WRITE8_DEVICE_HANDLER(msm8251_control_w) --------------------------------------------------*/ - -WRITE8_DEVICE_HANDLER(msm8251_control_w) -{ - msm8251_t *uart = get_token(device); - - if (uart->flags & MSM8251_EXPECTING_MODE) - { - if (uart->flags & MSM8251_EXPECTING_SYNC_BYTE) - { - LOG(("MSM8251: Sync byte\n")); - - LOG(("Sync byte: %02x\n", data)); - /* store sync byte written */ - uart->sync_bytes[uart->sync_byte_offset] = data; - uart->sync_byte_offset++; - - if (uart->sync_byte_offset == uart->sync_byte_count) - { - /* finished transfering sync bytes, now expecting command */ - uart->flags &= ~(MSM8251_EXPECTING_MODE | MSM8251_EXPECTING_SYNC_BYTE); - uart->sync_byte_offset = 0; - // uart->status = MSM8251_STATUS_TX_EMPTY | MSM8251_STATUS_TX_READY; - } - } - else - { - LOG(("MSM8251: Mode byte\n")); - - uart->mode_byte = data; - - /* Synchronous or Asynchronous? */ - if ((data & 0x03)!=0) - { - /* Asynchronous - - bit 7,6: stop bit length - 0 = inhibit - 1 = 1 bit - 2 = 1.5 bits - 3 = 2 bits - bit 5: parity type - 0 = parity odd - 1 = parity even - bit 4: parity test enable - 0 = disable - 1 = enable - bit 3,2: character length - 0 = 5 bits - 1 = 6 bits - 2 = 7 bits - 3 = 8 bits - bit 1,0: baud rate factor - 0 = defines command byte for synchronous or asynchronous - 1 = x1 - 2 = x16 - 3 = x64 - */ - - LOG(("MSM8251: Asynchronous operation\n")); - - LOG(("Character length: %d\n", (((data>>2) & 0x03)+5))); - - if (data & (1<<4)) - { - LOG(("enable parity checking\n")); - } - else - { - LOG(("parity check disabled\n")); - } - - if (data & (1<<5)) - { - LOG(("even parity\n")); - } - else - { - LOG(("odd parity\n")); - } - - { - UINT8 stop_bit_length; - - stop_bit_length = (data>>6) & 0x03; - - switch (stop_bit_length) - { - case 0: - { - /* inhibit */ - LOG(("stop bit: inhibit\n")); - } - break; - - case 1: - { - /* 1 */ - LOG(("stop bit: 1 bit\n")); - } - break; - - case 2: - { - /* 1.5 */ - LOG(("stop bit: 1.5 bits\n")); - } - break; - - case 3: - { - /* 2 */ - LOG(("stop bit: 2 bits\n")); - } - break; - } - } - - uart->form.word_length = ((data>>2) & 0x03)+5; - uart->form.parity = SERIAL_PARITY_NONE; - switch ((data>>6) & 0x03) - { - case 0: - case 1: - uart->form.stop_bit_count = 1; - break; - case 2: - case 3: - uart->form.stop_bit_count = 2; - break; - } - receive_register_setup(&uart->receive_reg, &uart->form); - - -#if 0 - /* data bits */ - uart->receive_char_length = (((data>>2) & 0x03)+5); - - if (data & (1<<4)) - { - /* parity */ - uart->receive_char_length++; - } - - /* stop bits */ - uart->receive_char_length++; - - uart->receive_flags &=~MSM8251_TRANSFER_RECEIVE_SYNCHRONISED; - uart->receive_flags |= MSM8251_TRANSFER_RECEIVE_WAITING_FOR_START_BIT; -#endif - /* not expecting mode byte now */ - uart->flags &= ~MSM8251_EXPECTING_MODE; -// uart->status = MSM8251_STATUS_TX_EMPTY | MSM8251_STATUS_TX_READY; - } - else - { - /* bit 7: Number of sync characters - 0 = 1 character - 1 = 2 character - bit 6: Synchronous mode - 0 = Internal synchronisation - 1 = External synchronisation - bit 5: parity type - 0 = parity odd - 1 = parity even - bit 4: parity test enable - 0 = disable - 1 = enable - bit 3,2: character length - 0 = 5 bits - 1 = 6 bits - 2 = 7 bits - 3 = 8 bits - bit 1,0 = 0 - */ - LOG(("MSM8251: Synchronous operation\n")); - - /* setup for sync byte(s) */ - uart->flags |= MSM8251_EXPECTING_SYNC_BYTE; - uart->sync_byte_offset = 0; - if (data & 0x07) - { - uart->sync_byte_count = 1; - } - else - { - uart->sync_byte_count = 2; - } - - } - } - } - else - { - /* command */ - LOG(("MSM8251: Command byte\n")); - - uart->command = data; - - LOG(("Command byte: %02x\n", data)); - - if (data & (1<<7)) - { - LOG(("hunt mode\n")); - } - - if (data & (1<<5)) - { - LOG(("/rts set to 0\n")); - } - else - { - LOG(("/rts set to 1\n")); - } - - if (data & (1<<2)) - { - LOG(("receive enable\n")); - } - else - { - LOG(("receive disable\n")); - } - - if (data & (1<<1)) - { - LOG(("/dtr set to 0\n")); - } - else - { - LOG(("/dtr set to 1\n")); - } - - if (data & (1<<0)) - { - LOG(("transmit enable\n")); - } - else - { - LOG(("transmit disable\n")); - } - - - /* bit 7: - 0 = normal operation - 1 = hunt mode - bit 6: - 0 = normal operation - 1 = internal reset - bit 5: - 0 = /RTS set to 1 - 1 = /RTS set to 0 - bit 4: - 0 = normal operation - 1 = reset error flag - bit 3: - 0 = normal operation - 1 = send break character - bit 2: - 0 = receive disable - 1 = receive enable - bit 1: - 0 = /DTR set to 1 - 1 = /DTR set to 0 - bit 0: - 0 = transmit disable - 1 = transmit enable - */ - - uart->connection.State &=~SERIAL_STATE_RTS; - if (data & (1<<5)) - { - /* rts set to 0 */ - uart->connection.State |= SERIAL_STATE_RTS; - } - - uart->connection.State &=~SERIAL_STATE_DTR; - if (data & (1<<1)) - { - uart->connection.State |= SERIAL_STATE_DTR; - } - - if ((data & (1<<0))==0) - { - /* held in high state when transmit disable */ - set_out_data_bit(uart->connection.State,1); - } - - - /* refresh outputs */ - serial_connection_out(device->machine(), &uart->connection); - - if (data & (1<<4)) - { - uart->status &= ~(MSM8251_STATUS_PARITY_ERROR | MSM8251_STATUS_OVERRUN_ERROR | MSM8251_STATUS_FRAMING_ERROR); - } - - if (data & (1<<6)) - { - device->reset(); - } - - msm8251_update_rx_ready(device); - msm8251_update_tx_ready(device); - - } -} - - - -/*------------------------------------------------- - READ8_DEVICE_HANDLER(msm8251_status_r) --------------------------------------------------*/ - -READ8_DEVICE_HANDLER(msm8251_status_r) -{ - msm8251_t *uart = get_token(device); - - LOG(("status: %02x\n", uart->status)); - return uart->status; -} - - - -/*------------------------------------------------- - WRITE8_DEVICE_HANDLER(msm8251_data_w) --------------------------------------------------*/ - -WRITE8_DEVICE_HANDLER(msm8251_data_w) -{ - msm8251_t *uart = get_token(device); - - uart->data = data; - - logerror("write data: %02x\n",data); - - /* writing clears */ - uart->status &=~MSM8251_STATUS_TX_READY; - - /* if transmitter is active, then tx empty will be signalled */ - - msm8251_update_tx_ready(device); -} - - - -/*------------------------------------------------- - msm8251_receive_character - called when last - bit of data has been received --------------------------------------------------*/ - -void msm8251_receive_character(device_t *device, UINT8 ch) -{ - msm8251_t *uart = get_token(device); - - logerror("msm8251 receive char: %02x\n",ch); - - uart->data = ch; - - /* char has not been read and another has arrived! */ - if (uart->status & MSM8251_STATUS_RX_READY) - { - uart->status |= MSM8251_STATUS_OVERRUN_ERROR; - } - uart->status |= MSM8251_STATUS_RX_READY; - - msm8251_update_rx_ready(device); -} - - - -/*------------------------------------------------- - READ8_DEVICE_HANDLER(msm8251_data_r) - read data --------------------------------------------------*/ - -READ8_DEVICE_HANDLER(msm8251_data_r) -{ - msm8251_t *uart = get_token(device); - - logerror("read data: %02x, STATUS=%02x\n",uart->data,uart->status); - /* reading clears */ - uart->status &= ~MSM8251_STATUS_RX_READY; - - msm8251_update_rx_ready(device); - return uart->data; -} - - - -/*------------------------------------------------- - msm8251_connect_to_serial_device - initialise - transfer using serial device - set the callback - which will be called when serial device has - updated it's state --------------------------------------------------*/ - -void msm8251_connect_to_serial_device(device_t *device, device_t *image) -{ - msm8251_t *uart = get_token(device); - serial_device_connect(image, &uart->connection); -} - - - -/*------------------------------------------------- - msm8251_connect --------------------------------------------------*/ - -void msm8251_connect(device_t *device, serial_connection *other_connection) -{ - msm8251_t *uart = get_token(device); - serial_connection_link(device->machine(), &uart->connection, other_connection); -} - - -/*------------------------------------------------- - DEVICE_GET_INFO( msm8251 ) --------------------------------------------------*/ - -DEVICE_GET_INFO( msm8251 ) -{ - switch (state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(msm8251_t); break; - case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(msm8251); break; - case DEVINFO_FCT_STOP: /* Nothing */ break; - case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(msm8251); break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "Intel 8251 UART"); break; - case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 8251 UART"); break; - case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; - case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; - case DEVINFO_STR_CREDITS: /* Nothing */ break; - } -} - -DEFINE_LEGACY_DEVICE(MSM8251, msm8251); diff --git a/src/emu/machine/msm8251.h b/src/emu/machine/msm8251.h deleted file mode 100644 index e01bcfc4503..00000000000 --- a/src/emu/machine/msm8251.h +++ /dev/null @@ -1,88 +0,0 @@ -/********************************************************************* - - msm8251.h - - MSM/Intel 8251 Universal Synchronous/Asynchronous Receiver Transmitter code - -*********************************************************************/ - -#ifndef __MSM8251_H__ -#define __MSM8251_H__ - -#include "machine/serial.h" - - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -DECLARE_LEGACY_DEVICE(MSM8251, msm8251); - -#define MSM8251_EXPECTING_MODE 0x01 -#define MSM8251_EXPECTING_SYNC_BYTE 0x02 - -#define MSM8251_STATUS_FRAMING_ERROR 0x020 -#define MSM8251_STATUS_OVERRUN_ERROR 0x010 -#define MSM8251_STATUS_PARITY_ERROR 0x08 -#define MSM8251_STATUS_TX_EMPTY 0x04 -#define MSM8251_STATUS_RX_READY 0x02 -#define MSM8251_STATUS_TX_READY 0x01 - -#define MCFG_MSM8251_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, MSM8251, 0) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_MSM8251_REMOVE(_tag) \ - MCFG_DEVICE_REMOVE(_tag) - - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -typedef struct _msm8251_interface msm8251_interface; -struct _msm8251_interface -{ - devcb_read_line in_rxd_func; - devcb_write_line out_txd_func; - devcb_read_line in_dsr_func; - devcb_write_line out_dtr_func; - devcb_write_line out_rts_func; - devcb_write_line out_rxrdy_func; - devcb_write_line out_txrdy_func; - devcb_write_line out_txempty_func; - devcb_write_line out_syndet_func; -}; - - -/*************************************************************************** - PROTOTYPES -***************************************************************************/ - -extern const msm8251_interface default_msm8251_interface; - -/* read data register */ -READ8_DEVICE_HANDLER(msm8251_data_r); - -/* read status register */ -READ8_DEVICE_HANDLER(msm8251_status_r); - -/* write data register */ -WRITE8_DEVICE_HANDLER(msm8251_data_w); - -/* write control word */ -WRITE8_DEVICE_HANDLER(msm8251_control_w); - -/* The 8251 has seperate transmit and receive clocks */ -/* use these two functions to update the msm8251 for each clock */ -/* on NC100 system, the clocks are the same */ -void msm8251_transmit_clock(device_t *device); -void msm8251_receive_clock(device_t *device); - -/* connecting to serial output */ -void msm8251_connect_to_serial_device(device_t *device, device_t *image); -void msm8251_connect(device_t *device, serial_connection *other_connection); - -void msm8251_receive_character(device_t *device, UINT8 ch); - -#endif /* __MSM8251_H__ */ diff --git a/src/emu/machine/serial.c b/src/emu/machine/serial.c deleted file mode 100644 index 7dc5234c8e6..00000000000 --- a/src/emu/machine/serial.c +++ /dev/null @@ -1,733 +0,0 @@ -/* internal serial transmission */ - -/* select a file on host filesystem to transfer using serial method, -setup serial interface software in driver and let the transfer begin */ - -/* this is used in the Amstrad NC Notepad emulation */ - - - -/* - - the output starts at 1 level. It changes to 0 when the start bit has been transmitted. - This therefore signals that data is following. - When all data bits have been received, stop bits are transmitted with a value of 1. - - msm8251 expects this in asynchronous mode: - packet format: - - bit count function value - 1 start bit 0 - note 1 data bits x - note 2 parity bit x - note 3 stop bits 1 - - Note: - 1. Data size can be defined (usual value is 8) - 2. Parity bit (if parity is set to odd or even). Value of bit - is defined by data parity. - 3. There should be at least 1 stop bit. -*/ - -#include "emu.h" -#include "serial.h" - - -#define VERBOSE 0 -#define LOG(x) do { if (VERBOSE) logerror x; } while (0) - -/* a read/write bit stream. used to transmit data and to receive data */ -typedef struct _data_stream data_stream; -struct _data_stream -{ - /* pointer to buffer */ - unsigned char *pData; - /* length of buffer */ - unsigned long DataLength; - - /* bit offset within current byte */ - unsigned long BitCount; - /* byte offset within data */ - unsigned long ByteCount; -}; - -typedef struct _serial_t serial_t; -struct _serial_t -{ - /* transmit data bit-stream */ - data_stream transmit; - /* receive data bit-stream */ - data_stream receive; - - /* register to receive data */ - serial_receive_register receive_reg; - /* register to transmit data */ - serial_transmit_register transmit_reg; - - /* connection to transmit/receive data over */ - serial_connection connection; - - /* data form to transmit/receive */ - data_form form; - - int transmit_state; - - /* baud rate */ - unsigned long BaudRate; - - /* baud rate timer */ - emu_timer *timer; -}; - -INLINE serial_t *get_safe_token(device_t *device) -{ - assert(device != NULL); - //assert(device->type() == SERIAL); - - return (serial_t *)downcast<legacy_device_base *>(device)->token(); -} - - -/* the serial streams */ -static TIMER_CALLBACK(serial_device_baud_rate_callback); - - -/*********************************************************/ - -static unsigned char serial_parity_table[256]; - -void serial_helper_setup(void) -{ - int i; - - /* if sum of all bits in the byte is even, then the data - has even parity, otherwise it has odd parity */ - for (i=0; i<256; i++) - { - int data; - int sum; - int b; - - sum = 0; - data = i; - - for (b=0; b<8; b++) - { - sum+=data & 0x01; - - data = data>>1; - } - - serial_parity_table[i] = sum & 0x01; - } -} - -static unsigned char serial_helper_get_parity(unsigned char data) -{ - return serial_parity_table[data & 0x0ff]; -} - -static void serial_device_in_callback(running_machine &machine, int id, unsigned long status) -{ -/* serial_t *ser = get_safe_token(device); - - ser->connection.input_state = status;*/ -} - -/***** SERIAL DEVICE ******/ -void serial_device_setup(device_t *device, int baud_rate, int num_data_bits, int stop_bit_count, int parity_code) -{ - serial_t *ser = get_safe_token(device); - - ser->BaudRate = baud_rate; - ser->form.word_length = num_data_bits; - ser->form.stop_bit_count = stop_bit_count; - ser->form.parity = parity_code; - ser->timer = device->machine().scheduler().timer_alloc(FUNC(serial_device_baud_rate_callback), (void *)device); - - serial_connection_init(device->machine(),&ser->connection); - serial_connection_set_in_callback(device->machine(),&ser->connection, serial_device_in_callback); - - /* signal to other end it is clear to send! */ - /* data is initially high state */ - /* set /rts */ - ser->connection.State |= SERIAL_STATE_RTS; - /* signal to other end data is ready to be accepted */ - /* set /dtr */ - ser->connection.State |= SERIAL_STATE_DTR; - set_out_data_bit(ser->connection.State, 1); - serial_connection_out(device->machine(),&ser->connection); - transmit_register_reset(&ser->transmit_reg); - receive_register_reset(&ser->receive_reg); - receive_register_setup(&ser->receive_reg, &ser->form); -} - - -unsigned long serial_device_get_state(device_t *device) -{ - serial_t *ser = get_safe_token(device); - - return ser->connection.State; -} - -void serial_device_set_transmit_state(device_t *device, int state) -{ - int previous_state; - serial_t *ser = get_safe_token(device); - - previous_state = ser->transmit_state; - - ser->transmit_state = state; - - if ((state^previous_state)!=0) - { - if (state) - { - /* start timer */ - ser->timer->adjust(attotime::zero, 0, attotime::from_hz(ser->BaudRate)); - } - else - { - /* remove timer */ - ser->timer->reset(); - } - } - -} - -/* get a bit from input stream */ -static int data_stream_get_data_bit_from_data_byte(data_stream *stream) -{ - int data_bit; - int data_byte; - - if (stream->ByteCount<stream->DataLength) - { - /* get data from buffer */ - data_byte= stream->pData[stream->ByteCount]; - } - else - { - /* over end of buffer, so return 0 */ - data_byte= 0; - } - - /* get bit from data */ - data_bit = (data_byte>>(7-stream->BitCount)) & 0x01; - - /* update bit count */ - stream->BitCount++; - /* ripple overflow onto byte count */ - stream->ByteCount+=stream->BitCount>>3; - /* lock bit count into range */ - stream->BitCount &=0x07; - - /* do not let it read over end of data */ - if (stream->ByteCount>=stream->DataLength) - { - stream->ByteCount = stream->DataLength-1; - } - - return data_bit; -} - - -void receive_register_setup(serial_receive_register *receive, data_form *data_form) -{ - receive->bit_count = data_form->word_length + data_form->stop_bit_count; - - if (data_form->parity != SERIAL_PARITY_NONE) - { - receive->bit_count++; - } -} - - -/* this is generic code to be used in serial chip implementations */ -/* the majority of serial chips work in the same way and this code will work */ -/* for them */ - -/* receive a bit */ -void receive_register_update_bit(serial_receive_register *receive, int bit) -{ - int previous_bit; - - LOG(("receive register receive bit: %1x\n",bit)); - previous_bit = receive->register_data & 1; - - /* shift previous bit 7 out */ - receive->register_data = receive->register_data<<1; - /* shift new bit in */ - receive->register_data = (receive->register_data & 0xfffe) | bit; - /* update bit count received */ - receive->bit_count_received++; - - /* asyncrhonouse mode */ - if (receive->flags & RECEIVE_REGISTER_WAITING_FOR_START_BIT) - { - /* the previous bit is stored in uart.receive char bit 0 */ - /* has the bit state changed? */ - if (((previous_bit ^ bit) & 0x01)!=0) - { - /* yes */ - if (bit==0) - { - //logerror("receive register saw start bit\n"); - - /* seen start bit! */ - /* not waiting for start bit now! */ - receive->flags &=~RECEIVE_REGISTER_WAITING_FOR_START_BIT; - receive->flags |=RECEIVE_REGISTER_SYNCHRONISED; - /* reset bit count received */ - receive->bit_count_received = 0; - } - } - } - else - if (receive->flags & RECEIVE_REGISTER_SYNCHRONISED) - { - /* received all bits? */ - if (receive->bit_count_received==receive->bit_count) - { - receive->bit_count_received = 0; - receive->flags &=~RECEIVE_REGISTER_SYNCHRONISED; - receive->flags |= RECEIVE_REGISTER_WAITING_FOR_START_BIT; - //logerror("receive register full\n"); - receive->flags |= RECEIVE_REGISTER_FULL; - } - } -} - -void receive_register_reset(serial_receive_register *receive_reg) -{ - receive_reg->bit_count_received = 0; - receive_reg->flags &=~RECEIVE_REGISTER_FULL; - receive_reg->flags &=~RECEIVE_REGISTER_SYNCHRONISED; - receive_reg->flags |= RECEIVE_REGISTER_WAITING_FOR_START_BIT; -} - -void receive_register_extract(serial_receive_register *receive_reg, data_form *data_form) -{ - unsigned long data_shift; - UINT8 data; - - receive_register_reset(receive_reg); - - data_shift = 0; - - /* if parity is even or odd, there should be a parity bit in the stream! */ - if (data_form->parity!=SERIAL_PARITY_NONE) - { - data_shift++; - } - - data_shift+=data_form->stop_bit_count; - - /* strip off stop bits and parity */ - data = receive_reg->register_data>>data_shift; - - /* mask off other bits so data byte has 0's in unused bits */ - data = data & (0x0ff - >> - (8-(data_form->word_length))); - - receive_reg->byte_received = data; - - /* parity enable? */ - switch (data_form->parity) - { - case SERIAL_PARITY_NONE: - break; - - /* check parity */ - case SERIAL_PARITY_ODD: - case SERIAL_PARITY_EVEN: - { - //unsigned char computed_parity; - //unsigned char parity_received; - - /* get state of parity bit received */ - //parity_received = (receive_reg->register_data>>data_form->stop_bit_count) & 0x01; - - /* compute parity for received bits */ - //computed_parity = serial_helper_get_parity(data); - - if (data_form->parity == SERIAL_PARITY_ODD) - { - /* odd parity */ - - - } - else - { - /* even parity */ - - - } - - } - break; - } -} - -/***** TRANSMIT REGISTER *****/ - -void transmit_register_reset(serial_transmit_register *transmit_reg) -{ - transmit_reg->flags |=TRANSMIT_REGISTER_EMPTY; -} - -/* used to construct data in stream format */ -static void transmit_register_add_bit(serial_transmit_register *transmit_reg, int bit) -{ - /* combine bit */ - transmit_reg->register_data = transmit_reg->register_data<<1; - transmit_reg->register_data &=~1; - transmit_reg->register_data|=(bit & 0x01); - transmit_reg->bit_count++; -} - - -/* generate data in stream format ready for transfer */ -void transmit_register_setup(serial_transmit_register *transmit_reg, data_form *data_form,unsigned char data_byte) -{ - int i; - unsigned char transmit_data; - - - transmit_reg->bit_count_transmitted = 0; - transmit_reg->bit_count = 0; - transmit_reg->flags &=~TRANSMIT_REGISTER_EMPTY; - - /* start bit */ - transmit_register_add_bit(transmit_reg,0); - - /* data bits */ - transmit_data = data_byte; - for (i=0; i<data_form->word_length; i++) - { - int databit; - - /* get bit from data */ - databit = (transmit_data>>(data_form->word_length-1)) & 0x01; - /* add bit to formatted byte */ - transmit_register_add_bit(transmit_reg, databit); - transmit_data = transmit_data<<1; - } - - /* parity */ - if (data_form->parity!=SERIAL_PARITY_NONE) - { - /* odd or even parity */ - unsigned char parity; - - /* get parity */ - /* if parity = 0, data has even parity - i.e. there is an even number of one bits in the data */ - /* if parity = 1, data has odd parity - i.e. there is an odd number of one bits in the data */ - parity = serial_helper_get_parity(data_byte); - - transmit_register_add_bit(transmit_reg, parity); - } - - /* stop bit(s) */ - for (i=0; i<data_form->stop_bit_count; i++) - { - transmit_register_add_bit(transmit_reg,1); - } -} - - -/* get a bit from the transmit register */ -static int transmit_register_get_data_bit(serial_transmit_register *transmit_reg) -{ - int bit; - - bit = (transmit_reg->register_data>> - (transmit_reg->bit_count - 1 - - transmit_reg->bit_count_transmitted)) & 0x01; - - transmit_reg->bit_count_transmitted++; - - /* have all bits of this stream formatted byte been sent? */ - if (transmit_reg->bit_count_transmitted==transmit_reg->bit_count) - { - /* yes - generate a new byte to send */ - transmit_reg->flags |= TRANSMIT_REGISTER_EMPTY; - } - - return bit; -} - - -void transmit_register_send_bit(running_machine &machine, serial_transmit_register *transmit_reg, serial_connection *connection) -{ - int data; - - data = transmit_register_get_data_bit(transmit_reg); - - /* set tx data bit */ - set_out_data_bit(connection->State, data); - - /* state out through connection */ - serial_connection_out(machine, connection); -} - -static void serial_protocol_none_sent_char(device_t *device) -{ - int i; - int bit; - unsigned char data_byte; - serial_t *ser = get_safe_token(device); - - /* generate byte to transmit */ - data_byte = 0; - for (i=0; i<ser->form.word_length; i++) - { - data_byte = data_byte<<1; - bit = data_stream_get_data_bit_from_data_byte(&ser->transmit); - data_byte = data_byte|bit; - } - /* setup register */ - transmit_register_setup(&ser->transmit_reg,&ser->form, data_byte); - - logerror("serial device transmitted char: %02x\n",data_byte); -} - -static TIMER_CALLBACK(serial_device_baud_rate_callback) -{ - serial_t *ser = get_safe_token((device_t*)ptr); - - /* receive data into receive register */ - receive_register_update_bit(&ser->receive_reg, get_in_data_bit(ser->connection.input_state)); - - if (ser->receive_reg.flags & RECEIVE_REGISTER_FULL) - { - //logerror("SERIAL DEVICE\n"); - receive_register_extract(&ser->receive_reg, &ser->form); - - logerror("serial device receive char: %02x\n",ser->receive_reg.byte_received); - } - - /* is transmit empty? */ - if (ser->transmit_reg.flags & TRANSMIT_REGISTER_EMPTY) - { - /* char has been sent, execute callback */ - serial_protocol_none_sent_char((device_t*)ptr); - } - - /* other side says it is clear to send? */ - if (ser->connection.input_state & SERIAL_STATE_CTS) - { - /* send bit */ - transmit_register_send_bit(machine, &ser->transmit_reg, &ser->connection); - } -} - -/* connect the specified connection to this serial device */ -void serial_device_connect(device_t *device, serial_connection *connection) -{ - serial_t *ser = get_safe_token(device); - serial_connection_link(device->machine(), connection, &ser->connection); -} - - -/* load image */ -static int serial_device_load_internal(device_image_interface &image, unsigned char **ptr, int *pDataSize) -{ - int datasize; - unsigned char *data; - - /* get file size */ - datasize = image.length(); - - if (datasize!=0) - { - /* malloc memory for this data */ - data = (unsigned char *)malloc(datasize); - - if (data!=NULL) - { - /* read whole file */ - image.fread(data, datasize); - - *ptr = data; - *pDataSize = datasize; - - logerror("File loaded!\r\n"); - - /* ok! */ - return 1; - } - } - return 0; -} - -/* reset position in stream */ -static void data_stream_reset(data_stream *stream) -{ - /* reset byte offset */ - stream->ByteCount= 0; - /* reset bit count */ - stream->BitCount = 0; -} - -/* free stream */ -static void data_stream_free(data_stream *stream) -{ - if (stream->pData!=NULL) - { - free(stream->pData); - stream->pData = NULL; - } - stream->DataLength = 0; -} - -/* initialise stream */ -static void data_stream_init(data_stream *stream, unsigned char *pData, unsigned long DataLength) -{ - stream->pData = pData; - stream->DataLength = DataLength; - data_stream_reset(stream); -} - -DEVICE_START(serial) -{ - //serial_t *ser = get_safe_token(device); -} - -DEVICE_RESET(serial) -{ -// serial_t *ser = get_safe_token(device); -} - -DEVICE_IMAGE_LOAD(serial) -{ - int data_length; - unsigned char *data; - device_t *device = &image.device(); - - serial_t *ser = get_safe_token(device); - - /* load file and setup transmit data */ - if (serial_device_load_internal(image, &data, &data_length)) - { - data_stream_init(&ser->transmit, data, data_length); - return IMAGE_INIT_PASS; - } - - return IMAGE_INIT_FAIL; -} - - -DEVICE_IMAGE_UNLOAD(serial) -{ - device_t *device = &image.device(); - serial_t *ser = get_safe_token(device); - - /* stop transmit */ - serial_device_set_transmit_state(device, 0); - /* free streams */ - data_stream_free(&ser->transmit); - data_stream_free(&ser->receive); -} - - -DEVICE_GET_INFO( serial ) -{ - switch ( state ) - { - case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(serial_t); break; - case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; - case DEVINFO_INT_IMAGE_TYPE: info->i = IO_SERIAL; break; - case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break; - case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 1; break; - case DEVINFO_INT_IMAGE_CREATABLE: info->i = 1; break; - - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( serial ); break; - case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( serial ); break; - case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME( serial ); break; - case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(serial ); break; - case DEVINFO_STR_NAME: strcpy( info->s, "Serial port"); break; - case DEVINFO_STR_FAMILY: strcpy(info->s, "Serial port"); break; - case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, ""); break; - case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; - case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; - case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MESS Team"); break; - } -} - -/*******************************************************************************/ -/*******************************************************************************/ -/********* SERIAL CONNECTION ***********/ - - -/* this converts state at this end to a state the other end can accept */ -/* e.g. CTS at this end becomes RTS at other end. - RTS at this end becomes CTS at other end. - TX at this end becomes RX at other end. - RX at this end becomes TX at other end. - etc - - The same thing is done inside the serial null-terminal lead */ - -static unsigned long serial_connection_spin_bits(unsigned long input_status) -{ - - return - /* cts -> rts */ - (((input_status & 0x01)<<1) | - /* rts -> cts */ - ((input_status>>1) & 0x01) | - /* dsr -> dtr */ - (((input_status>>2) & 0x01)<<3) | - /* dtr -> dsr */ - (((input_status>>3) & 0x01)<<2) | - /* rx -> tx */ - (((input_status>>4) & 0x01)<<5) | - /* tx -> rx */ - (((input_status>>5) & 0x01)<<4)); -} - - -/* setup callbacks for connection */ -void serial_connection_init(running_machine &machine, serial_connection *connection) -{ - connection->out_callback = NULL; - connection->in_callback = NULL; -} - -/* set callback which will be executed when in status has changed */ -void serial_connection_set_in_callback(running_machine &machine, serial_connection *connection, void (*in_cb)(running_machine &machine, int id, unsigned long status)) -{ - connection->in_callback = in_cb; -} - -/* output new state through connection */ -void serial_connection_out(running_machine &machine, serial_connection *connection) -{ - if (connection->out_callback!=NULL) - { - unsigned long state_at_other_end; - - state_at_other_end = serial_connection_spin_bits(connection->State); - - connection->out_callback(machine, connection->id, state_at_other_end); - } -} - -/* join two serial connections together */ -void serial_connection_link(running_machine &machine, serial_connection *connection_a, serial_connection *connection_b) -{ - /* both connections should have their in connection setup! */ - /* the in connection is the callback they use to update their state based - on the output from the other side */ - connection_a->out_callback = connection_b->in_callback; - connection_b->out_callback = connection_a->in_callback; - - /* let b know the state of a */ - serial_connection_out(machine,connection_a); - /* let a know the state of b */ - serial_connection_out(machine,connection_b); -} - -DEFINE_LEGACY_IMAGE_DEVICE(SERIAL, serial); diff --git a/src/emu/machine/serial.h b/src/emu/machine/serial.h deleted file mode 100644 index d958f6a9a08..00000000000 --- a/src/emu/machine/serial.h +++ /dev/null @@ -1,247 +0,0 @@ -/***************************************************************************** - * - * machine/serial.h - * - * internal serial transmission - * - * This code is used to transmit a file stored on the host filesystem - * (e.g. PC harddrive) to an emulated system. - * - * The file is converted into a serial bit-stream which can be received - * by the emulated serial chip in the emulated system. - * - * The file can be transmitted using different protocols. - * - * A and B are two computers linked with a serial connection - * A and B can transmit and receive data, through the same connection - * - * These flags apply to A and B, and give the state of the input & output - * signals at each side. - * - ****************************************************************************/ - -#ifndef SERIAL_H_ -#define SERIAL_H_ - - -/* - CTS = Clear to Send. (INPUT) - Other end of connection is ready to accept data - - - NOTE: - - This output is active low on serial chips (e.g. 0 is CTS is set), - but here it is active high! -*/ -#define SERIAL_STATE_CTS 0x0001 - -/* - RTS = Request to Send. (OUTPUT) - This end is ready to send data, and requests if the other - end is ready to accept it - - NOTE: - - This output is active low on serial chips (e.g. 0 is RTS is set), - but here it is active high! -*/ -#define SERIAL_STATE_RTS 0x0002 - -/* - DSR = Data Set ready. (INPUT) - Other end of connection has data - - - NOTE: - - This output is active low on serial chips (e.g. 0 is DSR is set), - but here it is active high! -*/ -#define SERIAL_STATE_DSR 0x0004 - -/* - DTR = Data terminal Ready. (OUTPUT) - TX contains new data. - - NOTE: - - This output is active low on serial chips (e.g. 0 is DTR is set), - but here it is active high! -*/ -#define SERIAL_STATE_DTR 0x0008 -/* RX = Recieve data. (INPUT) */ -#define SERIAL_STATE_RX_DATA 0x00010 -/* TX = Transmit data. (OUTPUT) */ -#define SERIAL_STATE_TX_DATA 0x00020 - -/* parity selections */ -/* if all the bits are added in a byte, if the result is: - even -> parity is even - odd -> parity is odd -*/ -enum -{ - SERIAL_PARITY_NONE, /* no parity. a parity bit will not be in the transmitted/received data */ - SERIAL_PARITY_ODD, /* odd parity */ - SERIAL_PARITY_EVEN /* even parity */ -}; - -/* this macro is used to extract the received data from the status */ -#define get_in_data_bit(x) ((x & SERIAL_STATE_RX_DATA)>>4) - -/* this macro is used to set the transmitted data in the status */ -#define set_out_data_bit(x, data) \ - x&=~SERIAL_STATE_TX_DATA; \ - x|=(data<<5) - - -/*******************************************************************************/ -/**** SERIAL CONNECTION ***/ - - -/* this structure represents a serial connection */ -typedef struct _serial_connection serial_connection; -struct _serial_connection -{ - int id; - /* state of this side */ - unsigned long State; - - /* state of other side - store here */ - unsigned long input_state; - - /* this callback is executed when this side has refreshed it's state, - to let the other end know */ - void (*out_callback)(running_machine &machine, int id, unsigned long state); - /* this callback is executed when the other side has refreshed it's state, - to let the other end know */ - void (*in_callback)(running_machine &machine, int id, unsigned long state); -}; - -/*----------- defined in machine/serial.c -----------*/ - -/* setup out and in callbacks */ -void serial_connection_init(running_machine &machine, serial_connection *connection); - -/* set callback which will be executed when in status has changed */ -void serial_connection_set_in_callback(running_machine &machine, serial_connection *connection, void (*in_cb)(running_machine &machine, int id, unsigned long status)); - -/* output status, if callback is setup it will be executed with the new status */ -void serial_connection_out(running_machine &machine, serial_connection *connection); - -/* join two serial connections */ -void serial_connection_link(running_machine &machine, serial_connection *connection_a, serial_connection *connection_b); - - -/*******************************************************************************/ - -/* form of data being transmitted and received */ -typedef struct _data_form data_form; -struct _data_form -{ - /* length of word in bits */ - unsigned long word_length; - /* parity state */ - unsigned long parity; - /* number of stop bits */ - unsigned long stop_bit_count; -}; - -/*******************************************************************************/ - -/*******************************************************************************/ -/**** RECEIVE AND TRANSMIT GENERIC CODE ****/ - -/* this can be used by most of the serial chip implementations, -because they all work in roughly the same way. -There is generic code to send and receive data in the specified form */ - -/* receive is waiting for start bit. The transition from high-low indicates -start of start bit. This is used to synchronise with the data being transfered */ -#define RECEIVE_REGISTER_WAITING_FOR_START_BIT 0x01 -/* receive is synchronised with data, data bits will be clocked in */ -#define RECEIVE_REGISTER_SYNCHRONISED 0x02 -/* set if receive register has been filled */ -#define RECEIVE_REGISTER_FULL 0x04 - - -/* the receive register holds data in receive form! */ -/* this must be extracted to get the data byte received */ -typedef struct _serial_receive_register serial_receive_register; -struct _serial_receive_register -{ - /* data */ - unsigned long register_data; - /* flags */ - unsigned long flags; - /* bit count received */ - unsigned long bit_count_received; - /* length of data to receive - includes data bits, parity bit and stop bit */ - unsigned long bit_count; - - /* the byte of data received */ - unsigned char byte_received; -}; - -void receive_register_setup(serial_receive_register *receive, data_form *data_form); -void receive_register_update_bit(serial_receive_register *receive, int bit_state); -void receive_register_extract(serial_receive_register *receive_reg, data_form *data_form); -void receive_register_reset(serial_receive_register *receive_reg); - -/* the transmit register is the final stage -in the serial transmit procedure */ -/* normally, data is written to the transmit reg, -then it is assembled into transmit form and transmitted */ -/* the transmit register holds data in transmit form */ - -/* register is empty and ready to be filled with data */ -#define TRANSMIT_REGISTER_EMPTY 0x0001 - -typedef struct _serial_transmit_register serial_transmit_register; -struct _serial_transmit_register -{ - /* data */ - unsigned long register_data; - /* flags */ - unsigned long flags; - /* number of bits transmitted */ - unsigned long bit_count_transmitted; - /* length of data to send */ - unsigned long bit_count; -}; - -/* setup transmit reg ready for transmit */ -void transmit_register_setup(serial_transmit_register *transmit_reg, data_form *data_form,unsigned char data_byte); -void transmit_register_send_bit(running_machine &machine, serial_transmit_register *transmit_reg, serial_connection *connection); -void transmit_register_reset(serial_transmit_register *transmit_reg); - -/*******************************************************************************/ -/**** SERIAL HELPER ****/ - -void serial_helper_setup(void); - -/*******************************************************************************/ -/**** SERIAL DEVICE ****/ - -unsigned long serial_device_get_state(device_t *device); - -/* connect this device to the emulated serial chip */ -/* id is the serial device to connect to */ -/* connection is the serial connection to connect to the serial device */ -void serial_device_connect(device_t *image, serial_connection *connection); - -DECLARE_LEGACY_IMAGE_DEVICE(SERIAL, serial); - -#define MCFG_SERIAL_ADD(_tag) \ - MCFG_DEVICE_ADD(_tag, SERIAL, 0) - -DEVICE_START(serial); -DEVICE_IMAGE_LOAD(serial); - -void serial_device_setup(device_t *image, int baud_rate, int num_data_bits, int stop_bit_count, int parity_code); - -/* set the transmit state of the serial device */ -void serial_device_set_transmit_state(device_t *image, int state); - -#endif /* SERIAL_H_ */ diff --git a/src/emu/machine/upd765.c b/src/emu/machine/upd765.c deleted file mode 100644 index b6bbaceb5a7..00000000000 --- a/src/emu/machine/upd765.c +++ /dev/null @@ -1,2457 +0,0 @@ -/*************************************************************************** - - machine/upd765.c - - Functions to emulate a UPD765/Intel 8272 compatible floppy disk controller - - Code by Kevin Thacker. - - TODO: - - - overrun condition - - Scan Commands - - crc error in id field and crc error in data field errors - - disc not present, and no sectors on track for data, deleted data, write, write deleted, - read a track etc - - end of cylinder condition - almost working, needs fixing with - PCW and PC drivers - - resolve "ready" state stuff (ready state when reset for PC, ready state change while processing command AND - while idle) - - Changes: - 091006 (Mariusz Wojcieszek, changes needed by QX-10): - - allowed "Sense Interrupt Status" command when Seek is active - - DIO bit in status register (0x40) is cleared when "Read Data" command is executed, - it is later set during result phase. - -***************************************************************************/ - -#include "emu.h" -#include "machine/upd765.h" - - -typedef enum -{ - UPD765_COMMAND_PHASE_FIRST_BYTE, - UPD765_COMMAND_PHASE_BYTES, - UPD765_RESULT_PHASE, - UPD765_EXECUTION_PHASE_READ, - UPD765_EXECUTION_PHASE_WRITE -} UPD765_PHASE; - -/* supported versions */ -typedef enum -{ - TYPE_UPD765A = 0, - TYPE_UPD765B = 1, - TYPE_SMC37C78 = 2, - TYPE_UPD72065 = 3 -} UPD765_VERSION; - - -/* uncomment the following line for verbose information */ -#define LOG_VERBOSE 0 -#define LOG_COMMAND 0 -#define LOG_EXTRA 0 -#define LOG_INTERRUPT 0 - -/* uncomment this to not allow end of cylinder "error" */ -#define NO_END_OF_CYLINDER - - - -/* state of upd765 Interrupt (INT) output */ -#define UPD765_INT 0x02 -/* data rate for floppy discs (MFM data) */ -#define UPD765_DATA_RATE 32 -/* state of upd765 terminal count input*/ -#define UPD765_TC 0x04 - -#define UPD765_DMA_MODE 0x08 - -#define UPD765_SEEK_OPERATION_IS_RECALIBRATE 0x01 - -#define UPD765_SEEK_ACTIVE 0x010 -/* state of upd765 DMA DRQ output */ -#define UPD765_DMA_DRQ 0x020 -/* state of upd765 FDD READY input */ -#define UPD765_FDD_READY 0x040 - -#define UPD765_MF 0x40 - -#define UPD765_RESET 0x080 - -typedef struct _upd765_t upd765_t; -struct _upd765_t -{ - devcb_resolved_write_line out_int_func; - devcb_resolved_write_line out_drq_func; - - unsigned long sector_counter; - /* version of fdc to emulate */ - UPD765_VERSION version; - - /* main status register */ - unsigned char FDC_main; - /* data register */ - unsigned char upd765_data_reg; - - unsigned char c,h,r,n; - - int sector_id; - - int data_type; - - char format_data[4]; - - UPD765_PHASE upd765_phase; - unsigned int upd765_command_bytes[16]; - unsigned int upd765_result_bytes[16]; - unsigned int upd765_transfer_bytes_remaining; - unsigned int upd765_transfer_bytes_count; - unsigned int upd765_status[4]; - /* present cylinder number per drive */ - unsigned int pcn[4]; - - /* drive being accessed. drive outputs from fdc */ - unsigned int drive; - /* side being accessed: side output from fdc */ - unsigned int side; - - - /* step rate time in us */ - unsigned long srt_in_ms; - - unsigned int ncn; - -// unsigned int upd765_id_index; - char *execution_phase_data; - unsigned int upd765_flags; - -// unsigned char specify[2]; -// unsigned char perpendicular_mode[1]; - - int command; - - emu_timer *seek_timer; - emu_timer *timer; - int timer_type; - - emu_timer *command_timer; - - char *data_buffer; - const upd765_interface *intf; -}; - -//static void upd765_setup_data_request(unsigned char Data); -static void upd765_setup_command(device_t *device); -static TIMER_CALLBACK(upd765_continue_command); -static int upd765_sector_count_complete(device_t *device); -static void upd765_increment_sector(device_t *device); -static void upd765_update_state(device_t *device); -static void upd765_set_dma_drq(device_t *device,int state); -static void upd765_set_int(device_t *device,int state); - -static const INT8 upd765_cmd_size[32] = -{ - 1,1,9,3,2,9,9,2,1,9,2,1,9,6,1,3, - 1,9,1,1,1,1,9,1,1,9,1,1,1,9,1,1 -}; - -INLINE upd765_t *get_safe_token(device_t *device) -{ - assert(device != NULL); - assert(device->type() == UPD765A || device->type() == UPD765B || - device->type() == SMC37C78 || device->type() == UPD72065); - - return (upd765_t *)downcast<legacy_device_base *>(device)->token(); -} - -static device_t *current_image(device_t *device) -{ - device_t *image = NULL; - upd765_t *fdc = get_safe_token(device); - - if (!fdc->intf->get_image) - { - if (fdc->intf->floppy_drive_tags[fdc->drive] != NULL) - { - if (device->owner() != NULL) - image = device->owner()->subdevice(fdc->intf->floppy_drive_tags[fdc->drive]); - else - image = device->machine().device(fdc->intf->floppy_drive_tags[fdc->drive]); - } - } - else - { - image = fdc->intf->get_image(device, fdc->drive); - } - return image; -} - -static void upd765_setup_drive_and_side(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - /* drive index upd765 sees */ - fdc->drive = fdc->upd765_command_bytes[1] & 0x03; - /* side index upd765 sees */ - fdc->side = (fdc->upd765_command_bytes[1]>>2) & 0x01; -} - - -/* setup status register 0 based on data in status register 1 and 2 */ -static void upd765_setup_st0(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - /* clear completition status bits, drive bits and side bits */ - fdc->upd765_status[0] &= ~((1<<7) | (1<<6) | (1<<2) | (1<<1) | (1<<0)); - /* fill in drive */ - fdc->upd765_status[0] |= fdc->drive | (fdc->side<<2); - - /* fill in completion status bits based on bits in st0, st1, st2 */ - /* no error bits set */ - if ((fdc->upd765_status[1] | fdc->upd765_status[2])==0) - { - return; - } - - fdc->upd765_status[0] |= 0x040; -} - - -static int upd765_n_to_bytes(int n) -{ - /* 0-> 128 bytes, 1->256 bytes, 2->512 bytes etc */ - /* data_size = ((1<<(N+7)) */ - return 1<<(n+7); -} - -static void upd765_set_data_request(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - fdc->FDC_main |= 0x080; -} - -static void upd765_clear_data_request(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - fdc->FDC_main &= ~0x080; -} - -static int upd765_get_rdy(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - - if (fdc->intf->rdy_pin == UPD765_RDY_PIN_CONNECTED) - { - device_t *img = current_image(device); - return floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY); - } - else - return 1; -} - -static void upd765_seek_complete(device_t *device) -{ - /* tested on Amstrad CPC */ - - /* if a seek is done without drive connected: */ - /* abnormal termination of command, - seek complete, - not ready - */ - - /* if a seek is done with drive connected, but disc missing: */ - /* abnormal termination of command, - seek complete, - not ready */ - - /* if a seek is done with drive connected and disc in drive */ - /* seek complete */ - - - /* On the PC however, it appears that recalibrates and seeks can be performed without - a disc in the drive. */ - - /* Therefore, the above output is dependant on the state of the drive */ - - /* In the Amstrad CPC, the drive select is provided by the UPD765. A single port is also - assigned for setting the drive motor state. The motor state controls the motor of the selected - drive */ - - /* On the PC the drive can be selected with the DIGITAL OUTPUT REGISTER, and the motor of each - of the 4 possible drives is also settable using the same register */ - - /* Assumption for PC: (NOT TESTED - NEEDS VERIFICATION) */ - - /* If a seek is done without drive connected: */ - /* abnormal termination of command, - seek complete, - fault - */ - - /* if a seek is done with drive connected, but disc missing: */ - /* seek complete */ - - /* if a seek is done with drive connected and disc in drive: */ - /* seek complete */ - - /* On Amstrad CPC: - If drive not connected, or drive connected but disc not in drive, not ready! - If drive connected and drive motor on, ready! - On PC: - Drive is always ready! - - In 37c78 docs, the ready bits of the upd765 are marked as unused. - This indicates it is always ready!!!!! - */ - - device_t *img = current_image(device); - upd765_t *fdc = get_safe_token(device); - - fdc->pcn[fdc->drive] = fdc->ncn; - - fdc->upd765_status[0] = 0x20; - - /* drive ready? */ - if (img != NULL && upd765_get_rdy(device)) - { - /* recalibrate? */ - if (fdc->upd765_flags & UPD765_SEEK_OPERATION_IS_RECALIBRATE) - { - /* not at track 0? */ - if (fdc->pcn[fdc->drive] != 0) - /* no, track 0 failed after 77 steps */ - fdc->upd765_status[0] |= 0x40 | 0x10; - } - } - else - { - /* abnormal termination, not ready */ - fdc->upd765_status[0] |= 0x40 | 0x08; - } - - /* set drive and side. note: commented out side to avoid problems with the tf20 */ - fdc->upd765_status[0] |= fdc->drive; //| (fdc->side<<2); - - upd765_set_int(device,0); - upd765_set_int(device,1); - - fdc->upd765_flags &= ~UPD765_SEEK_ACTIVE; - - upd765_idle(device); -} - -static TIMER_CALLBACK(upd765_seek_timer_callback) -{ - device_t *device = (device_t *)ptr; - upd765_t *fdc = get_safe_token(device); - /* seek complete */ - upd765_seek_complete(device); - - fdc->seek_timer->reset(); -} - -static void upd765_timer_func(device_t *device, int timer_type) -{ - upd765_t *fdc = get_safe_token(device); - /* type 0 = data transfer mode in execution phase */ - if (fdc->timer_type == 0) - { - /* set data request */ - upd765_set_data_request(device); - - fdc->timer_type = 4; - - if (!(fdc->upd765_flags & UPD765_DMA_MODE)) - { - if (fdc->upd765_command_bytes[0] & UPD765_MF) - { - /* MFM */ - fdc->timer->reset(attotime::from_usec(13)); - } - else - { - /* FM */ - fdc->timer->reset(attotime::from_usec(27)); - } - } - else - { - upd765_timer_func(device, fdc->timer_type); - } - } - else if (fdc->timer_type==2) - { - /* result phase begin */ - - /* generate a int for specific commands */ - switch (fdc->command) { - case 2: /* read a track */ - case 5: /* write data */ - case 6: /* read data */ - case 9: /* write deleted data */ - case 10: /* read id */ - case 12: /* read deleted data */ - case 13: /* format at track */ - case 17: /* scan equal */ - case 19: /* scan low or equal */ - case 29: /* scan high or equal */ - upd765_set_int(device,1); - break; - - default: - break; - } - - upd765_set_data_request(device); - - fdc->timer->reset(); - } - else if (fdc->timer_type == 4) - { - /* if in dma mode, a int is not generated per byte. If not in DMA mode - a int is generated per byte */ - if (fdc->upd765_flags & UPD765_DMA_MODE) - { - upd765_set_dma_drq(device,1); - } - else - { - if (fdc->FDC_main & (1<<7)) - { - /* set int to indicate data is ready */ - upd765_set_int(device,1); - } - } - - fdc->timer->reset(); - } -} - -static TIMER_CALLBACK(upd765_timer_callback) -{ - device_t *device = (device_t *)ptr; - upd765_timer_func(device,param); -} - -/* after (32-27) the DRQ is set, then 27 us later, the int is set. -I don't know if this is correct, but it is required for the PCW driver. -In this driver, the first NMI calls the handler function, furthur NMI's are -effectively disabled by reading the data before the NMI int can be set. -*/ - -static void upd765_setup_timed_generic(device_t *device, int timer_type, attotime duration) -{ - upd765_t *fdc = get_safe_token(device); - - fdc->timer_type = timer_type; - - if (!(fdc->upd765_flags & UPD765_DMA_MODE)) - { - fdc->timer->adjust(duration); - } - else - { - upd765_timer_func(device,fdc->timer_type); - fdc->timer->reset(); - } -} - -/* setup data request */ -static void upd765_setup_timed_data_request(device_t *device, int bytes) -{ - /* setup timer to trigger in UPD765_DATA_RATE us */ - upd765_setup_timed_generic(device, 0, attotime::from_usec(32-27) /*UPD765_DATA_RATE)*bytes*/); -} - -/* setup result data request */ -static void upd765_setup_timed_result_data_request(device_t *device) -{ - upd765_setup_timed_generic(device, 2, attotime::from_usec(UPD765_DATA_RATE*2)); -} - - -/* sets up a timer to issue a seek complete in signed_tracks time */ -static void upd765_setup_timed_int(device_t *device,int signed_tracks) -{ - upd765_t *fdc = get_safe_token(device); - /* setup timer to signal after seek time is complete */ - fdc->seek_timer->adjust(attotime::from_double(fdc->srt_in_ms*abs(signed_tracks)*0.001)); -} - -static void upd765_seek_setup(device_t *device, int is_recalibrate) -{ - device_t *img; - int signed_tracks; - upd765_t *fdc = get_safe_token(device); - - fdc->upd765_flags |= UPD765_SEEK_ACTIVE; - - if (is_recalibrate) - { - /* head cannot be specified with recalibrate */ - fdc->upd765_command_bytes[1] &=~0x04; - } - - upd765_setup_drive_and_side(device); - - img = current_image(device); - - fdc->FDC_main |= (1<<fdc->drive); - fdc->FDC_main |= 0x20; // execution phase - fdc->FDC_main &= ~0x10; // not busy, can send another seek/recalibrate - // for a different drive, or sense int status - - /* recalibrate command? */ - if (is_recalibrate) - { - fdc->upd765_flags |= UPD765_SEEK_OPERATION_IS_RECALIBRATE; - - fdc->ncn = 0; - - /* if drive is already at track 0, or drive is not ready */ - if (img == NULL || floppy_tk00_r(img) == CLEAR_LINE || (!upd765_get_rdy(device))) - { - /* seek completed */ -// upd765_seek_complete(device); - // delay for the time of 1 step, the PCW does not like immediate recalibrates - upd765_setup_timed_int(device,1); - } - else - { - /* is drive present? */ - if (1) //image_slotexists(img)) //fix me - { - /* yes - calculate real number of tracks to seek */ - - int current_track; - - /* get current track */ - current_track = floppy_drive_get_current_track(img); - - /* get number of tracks to seek */ - signed_tracks = -current_track; - } - else - { - /* no, seek 77 tracks and then stop */ - /* true for UPD765A, but not for other variants */ - signed_tracks = -77; - } - - if (signed_tracks!=0) - { - /* perform seek - if drive isn't present it will not do anything */ - floppy_drive_seek(img, signed_tracks); - - upd765_setup_timed_int(device,signed_tracks); - } - else - { - upd765_seek_complete(device); - } - } - } - else - { - - fdc->upd765_flags &= ~UPD765_SEEK_OPERATION_IS_RECALIBRATE; - - fdc->ncn = fdc->upd765_command_bytes[2]; - - /* get signed tracks */ - signed_tracks = fdc->ncn - fdc->pcn[fdc->drive]; - - /* if no tracks to seek, or drive is not ready, seek is complete */ - if (img == NULL || (signed_tracks==0) || (!upd765_get_rdy(device))) - { - upd765_seek_complete(device); - } - else - { - /* perform seek - if drive isn't present it will not do anything */ - floppy_drive_seek(img, signed_tracks); - - /* seek complete - issue an interrupt */ - upd765_setup_timed_int(device,signed_tracks); - } - } -// upd765_idle(device); -} - - - -static void upd765_setup_execution_phase_read(device_t *device, char *ptr, int size) -{ - upd765_t *fdc = get_safe_token(device); - - fdc->FDC_main &= ~0x040; /* FDC->CPU */ - - fdc->upd765_transfer_bytes_count = 0; - fdc->upd765_transfer_bytes_remaining = size; - fdc->execution_phase_data = ptr; - fdc->upd765_phase = UPD765_EXECUTION_PHASE_READ; - - upd765_setup_timed_data_request(device, 1); -} - -static void upd765_setup_execution_phase_write(device_t *device, char *ptr, int size) -{ - upd765_t *fdc = get_safe_token(device); - - fdc->FDC_main &= ~0x040; /* FDC->CPU */ - - fdc->upd765_transfer_bytes_count = 0; - fdc->upd765_transfer_bytes_remaining = size; - fdc->execution_phase_data = ptr; - fdc->upd765_phase = UPD765_EXECUTION_PHASE_WRITE; - - /* setup a data request with first byte */ - upd765_setup_timed_data_request(device,1); -} - - -static void upd765_setup_result_phase(device_t *device, int byte_count) -{ - upd765_t *fdc = get_safe_token(device); - - fdc->FDC_main |= 0x040; /* FDC->CPU */ - fdc->FDC_main &= ~0x020; /* not execution phase */ - - fdc->upd765_transfer_bytes_count = 0; - fdc->upd765_transfer_bytes_remaining = byte_count; - fdc->upd765_phase = UPD765_RESULT_PHASE; - - upd765_setup_timed_result_data_request(device); -} - -void upd765_idle(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - - fdc->FDC_main &= ~0x040; /* CPU->FDC */ - fdc->FDC_main &= ~0x020; /* not execution phase */ - fdc->FDC_main &= ~0x010; /* not busy */ - fdc->upd765_phase = UPD765_COMMAND_PHASE_FIRST_BYTE; - - upd765_set_data_request(device); -} - - - -/* change flags */ -static void upd765_change_flags(device_t *device,unsigned int flags, unsigned int mask) -{ - unsigned int new_flags; - unsigned int changed_flags; - upd765_t *fdc = get_safe_token(device); - - assert((flags & ~mask) == 0); - - /* compute the new flags and which ones have changed */ - new_flags = fdc->upd765_flags & ~mask; - new_flags |= flags; - changed_flags = fdc->upd765_flags ^ new_flags; - fdc->upd765_flags = new_flags; - - /* if interrupt changed, call the handler */ - if (changed_flags & UPD765_INT) - fdc->out_int_func((fdc->upd765_flags & UPD765_INT) ? 1 : 0); - - /* if DRQ changed, call the handler */ - if (changed_flags & UPD765_DMA_DRQ) - fdc->out_drq_func((fdc->upd765_flags & UPD765_DMA_DRQ) ? 1 : 0); -} - - - -/* set int output */ -static void upd765_set_int(device_t *device, int state) -{ - if (LOG_INTERRUPT) - logerror("upd765_set_int(): state=%d\n", state); - upd765_change_flags(device, state ? UPD765_INT : 0, UPD765_INT); -} - - - -/* set dma request output */ -static void upd765_set_dma_drq(device_t *device, int state) -{ - upd765_change_flags(device, state ? UPD765_DMA_DRQ : 0, UPD765_DMA_DRQ); -} - - - -/* Drive ready */ - -/* - -A drive will report ready if: -- drive is selected -- disc is in the drive -- disk is rotating at a constant speed (normally 300rpm) - -On more modern PCs, a ready signal is not provided by the drive. -This signal is not used in the PC design and was eliminated to save costs -If you look at the datasheets for the modern UPD765 variants, you will see the Ready -signal is not mentioned. - -On the original UPD765A, ready signal is required, and some commands will fail if the drive -is not ready. - - - - -*/ - - - - -/* done when ready state of drive changes */ -/* this ignores if command is active, in which case command should terminate immediatly -with error */ -static void upd765_set_ready_change_callback(device_t *controller, device_t *img, int state) -{ - upd765_t *fdc = get_safe_token(controller); - int drive = floppy_get_drive(img); - - if (LOG_EXTRA) - logerror("upd765: ready state change\n"); - - /* drive that changed state */ - fdc->upd765_status[0] = 0x0c0 | drive; - - /* not ready */ - if (state==0 && fdc->intf->rdy_pin == UPD765_RDY_PIN_CONNECTED ) - fdc->upd765_status[0] |= 8; - - /* trigger an int */ - upd765_set_int(controller, 1); -} - - -/* terminal count input */ -WRITE_LINE_DEVICE_HANDLER( upd765_tc_w ) -{ - int old_state; - upd765_t *fdc = get_safe_token(device); - - old_state = fdc->upd765_flags; - - /* clear drq */ - upd765_set_dma_drq(device, 0); - - fdc->upd765_flags &= ~UPD765_TC; - if (state) - { - fdc->upd765_flags |= UPD765_TC; - } - - /* changed state? */ - if (((fdc->upd765_flags^old_state) & UPD765_TC)!=0) - { - /* now set? */ - if ((fdc->upd765_flags & UPD765_TC)!=0) - { - /* yes */ - if (fdc->timer) - { - if (fdc->timer_type==0) - { - fdc->timer->reset(); - - - } - } - -#ifdef NO_END_OF_CYLINDER - fdc->command_timer->adjust(attotime::zero); -#else - upd765_update_state(device); -#endif - } - } -} - -READ8_DEVICE_HANDLER( upd765_status_r ) -{ - upd765_t *fdc = get_safe_token(device); - if (LOG_EXTRA) - logerror("%s: upd765_status_r: %02x\n", device->machine().describe_context(), fdc->FDC_main); - return fdc->FDC_main; -} - - -/* control mark handling code */ - -/* if SK==1, and we are executing a read data command, and a deleted data mark is found, -skip it. -if SK==1, and we are executing a read deleted data command, and a data mark is found, -skip it. */ - -static int upd765_read_skip_sector(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - /* skip set? */ - if ((fdc->upd765_command_bytes[0] & (1<<5))!=0) - { - /* read data? */ - if (fdc->command == 0x06) - { - /* did we just find a sector with deleted data mark? */ - if (fdc->data_type == UPD765_DAM_DELETED_DATA) - { - /* skip it */ - return TRUE; - } - } - /* deleted data? */ - else - if (fdc->command == 0x0c) - { - /* did we just find a sector with data mark ? */ - if (fdc->data_type == UPD765_DAM_DATA) - { - /* skip it */ - return TRUE; - } - } - } - - /* do not skip */ - return FALSE; -} - -/* this is much closer to how the upd765 actually gets sectors */ -/* used by read data, read deleted data, write data, write deleted data */ -/* What the upd765 does: - - - get next sector id from disc - - if sector id matches id specified in command, it will - search for next data block and read data from it. - - - if the index is seen twice while it is searching for a sector, then the sector cannot be found -*/ - -static void upd765_get_next_id(device_t *device, chrn_id *id) -{ - upd765_t *fdc = get_safe_token(device); - device_t *img = current_image(device); - - /* get next id from disc */ - floppy_drive_get_next_id(img, fdc->side,id); - - fdc->sector_id = id->data_id; - - /* set correct data type */ - fdc->data_type = UPD765_DAM_DATA; - if (id->flags & ID_FLAG_DELETED_DATA) - { - fdc->data_type = UPD765_DAM_DELETED_DATA; - } -} - -static int upd765_get_matching_sector(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - device_t *img = current_image(device); - chrn_id id; - - /* number of times we have seen index hole */ - int index_count = 0; - - /* get sector id's */ - do - { - upd765_get_next_id(device, &id); - - /* tested on Amstrad CPC - All bytes must match, otherwise - a NO DATA error is reported */ - if (id.R == fdc->upd765_command_bytes[4]) - { - if (id.C == fdc->upd765_command_bytes[2]) - { - if (id.H == fdc->upd765_command_bytes[3]) - { - if (id.N == fdc->upd765_command_bytes[5]) - { - /* end of cylinder is set if: - 1. sector data is read completely (i.e. no other errors occur like - no data. - 2. sector being read is same specified by EOT - 3. terminal count is not received */ - if (fdc->upd765_command_bytes[4]==fdc->upd765_command_bytes[6]) - { - /* set end of cylinder */ - fdc->upd765_status[1] |= UPD765_ST1_END_OF_CYLINDER; - } - - return TRUE; - } - } - } - else - { - /* the specified sector ID was found, however, the C value specified - in the read/write command did not match the C value read from the disc */ - - /* no data - checked on Amstrad CPC */ - fdc->upd765_status[1] |= UPD765_ST1_NO_DATA; - /* bad C value */ - fdc->upd765_status[2] |= UPD765_ST2_WRONG_CYLINDER; - - if (id.C == 0x0ff) - { - /* the C value is 0x0ff which indicates a bad track in the IBM soft-sectored - format */ - fdc->upd765_status[2] |= UPD765_ST2_BAD_CYLINDER; - } - - return FALSE; - } - } - - /* index set? */ - if (floppy_drive_get_flag_state(img, FLOPPY_DRIVE_INDEX)) - { - index_count++; - } - - } - while (index_count!=2); - - if (fdc->upd765_command_bytes[4] != fdc->upd765_command_bytes[6]) - { - /* no data - specified sector ID was not found */ - fdc->upd765_status[1] |= UPD765_ST1_NO_DATA; - } - - return 0; -} - -static void upd765_read_complete(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); -/* causes problems!!! - need to fix */ -#ifdef NO_END_OF_CYLINDER - /* set end of cylinder */ - fdc->upd765_status[1] &= ~UPD765_ST1_END_OF_CYLINDER; -#else - /* completed read command */ - - /* end of cylinder is set when: - - a whole sector has been read - - terminal count input is not set - - AND the the sector specified by EOT was read - */ - - /* if end of cylinder is set, and we did receive a terminal count, then clear it */ - if ((fdc->upd765_flags & UPD765_TC)!=0) - { - /* set end of cylinder */ - fdc->upd765_status[1] &= ~UPD765_ST1_END_OF_CYLINDER; - } -#endif - - upd765_setup_st0(device); - - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */ - fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */ - fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */ - fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */ - - upd765_setup_result_phase(device,7); -} - -static void upd765_read_data(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - device_t *img = current_image(device); - - if (!upd765_get_rdy(device)) - { - fdc->upd765_status[0] = 0x0c0 | (1<<4) | fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0x00; - fdc->upd765_status[2] = 0x00; - - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */ - fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */ - fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */ - fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */ - upd765_setup_result_phase(device,7); - return; - } - - if (LOG_VERBOSE) - logerror("sector c: %02x h: %02x r: %02x n: %02x\n",fdc->upd765_command_bytes[2], fdc->upd765_command_bytes[3],fdc->upd765_command_bytes[4], fdc->upd765_command_bytes[5]); - - /* find a sector to read data from */ - { - int found_sector_to_read; - - found_sector_to_read = 0; - /* check for finished reading sectors */ - do - { - /* get matching sector */ - if (upd765_get_matching_sector(device)) - { - - /* skip it? */ - if (upd765_read_skip_sector(device)) - { - /* yes */ - - /* check that we haven't finished reading all sectors */ - if (upd765_sector_count_complete(device)) - { - /* read complete */ - upd765_read_complete(device); - return; - } - - /* read not finished */ - - /* increment sector count */ - upd765_increment_sector(device); - } - else - { - /* found a sector to read */ - found_sector_to_read = 1; - } - } - else - { - /* error in finding sector */ - upd765_read_complete(device); - return; - } - } - while (found_sector_to_read==0); - } - - { - int data_size; - - data_size = upd765_n_to_bytes(fdc->upd765_command_bytes[5]); - - floppy_drive_read_sector_data(img, fdc->side, fdc->sector_id,fdc->data_buffer,data_size); - - upd765_setup_execution_phase_read(device,fdc->data_buffer, data_size); - } -} - - -static void upd765_format_track(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - device_t *img = current_image(device); - - /* write protected? */ - if (floppy_wpt_r(img) == CLEAR_LINE) - { - fdc->upd765_status[1] |= UPD765_ST1_NOT_WRITEABLE; - - upd765_setup_st0(device); - /* TODO: Check result is correct */ - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = fdc->format_data[0]; - fdc->upd765_result_bytes[4] = fdc->format_data[1]; - fdc->upd765_result_bytes[5] = fdc->format_data[2]; - fdc->upd765_result_bytes[6] = fdc->format_data[3]; - upd765_setup_result_phase(device,7); - - return; - } - - upd765_setup_execution_phase_write(device, &fdc->format_data[0], 4); -} - -static void upd765_read_a_track(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - int data_size; - - /* SKIP not allowed with this command! */ - - /* get next id */ - chrn_id id; - - upd765_get_next_id(device, &id); - - /* TO BE CONFIRMED! */ - /* check id from disc */ - if (id.C==fdc->upd765_command_bytes[2]) - { - if (id.H==fdc->upd765_command_bytes[3]) - { - if (id.R==fdc->upd765_command_bytes[4]) - { - if (id.N==fdc->upd765_command_bytes[5]) - { - /* if ID found, then no data is not set */ - /* otherwise no data will remain set */ - fdc->upd765_status[1] &=~UPD765_ST1_NO_DATA; - } - } - } - } - - - data_size = upd765_n_to_bytes(id.N); - - floppy_drive_read_sector_data(current_image(device), fdc->side, fdc->sector_id,fdc->data_buffer,data_size); - - upd765_setup_execution_phase_read(device,fdc->data_buffer, data_size); -} - -static int upd765_just_read_last_sector_on_track(device_t *device) -{ - if (floppy_drive_get_flag_state(current_image(device), FLOPPY_DRIVE_INDEX)) - return 1; - return 0; -} - -static void upd765_write_complete(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - -/* causes problems!!! - need to fix */ -#ifdef NO_END_OF_CYLINDER - /* set end of cylinder */ - fdc->upd765_status[1] &= ~UPD765_ST1_END_OF_CYLINDER; -#else - /* completed read command */ - - /* end of cylinder is set when: - - a whole sector has been read - - terminal count input is not set - - AND the the sector specified by EOT was read - */ - - /* if end of cylinder is set, and we did receive a terminal count, then clear it */ - if ((fdc->upd765_flags & UPD765_TC)!=0) - { - /* set end of cylinder */ - fdc->upd765_status[1] &= ~UPD765_ST1_END_OF_CYLINDER; - } -#endif - - upd765_setup_st0(device); - - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */ - fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */ - fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */ - fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */ - - upd765_setup_result_phase(device,7); -} - - -static void upd765_write_data(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - if (!upd765_get_rdy(device)) - { - fdc->upd765_status[0] = 0x0c0 | (1<<4) | fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0x00; - fdc->upd765_status[2] = 0x00; - - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */ - fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */ - fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */ - fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */ - upd765_setup_result_phase(device,7); - return; - } - - /* write protected? */ - if (floppy_wpt_r(current_image(device)) == CLEAR_LINE) - { - fdc->upd765_status[1] |= UPD765_ST1_NOT_WRITEABLE; - - upd765_write_complete(device); - return; - } - - if (upd765_get_matching_sector(device)) - { - int data_size; - - data_size = upd765_n_to_bytes(fdc->upd765_command_bytes[5]); - - upd765_setup_execution_phase_write(device,fdc->data_buffer, data_size); - } - else - { - upd765_setup_result_phase(device,7); - } -} - - -/* return true if we have read all sectors, false if not */ -static int upd765_sector_count_complete(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); -/* this is not correct?? */ -#if 1 - /* if terminal count has been set - yes */ - if (fdc->upd765_flags & UPD765_TC) - { - /* completed */ - return 1; - } - - - - /* multi-track? */ - if (fdc->upd765_command_bytes[0] & 0x080) - { - /* it appears that in multi-track mode, - the EOT parameter of the command is ignored!? - - or is it ignored the first time and not the next, so that - if it is started on side 0, it will end at EOT on side 1, - but if started on side 1 it will end at end of track???? - - PC driver requires this to end at last sector on side 1, and - ignore EOT parameter. - - To be checked!!!! - */ - - /* if just read last sector and on side 1 - finish */ - if (upd765_just_read_last_sector_on_track(device)) - { - if (floppy_get_heads_per_disk(flopimg_get_image(current_image(device)))==1) { - return 1; - } else { - if (fdc->side==1) - return 1; - } - } - - /* if not on second side then we haven't finished yet */ - if (fdc->side!=1) - { - /* haven't finished yet */ - return 0; - } - } - else - { - /* sector id == EOT? */ - if ((fdc->upd765_command_bytes[4]==fdc->upd765_command_bytes[6])) - { - - /* completed */ - return 1; - } - } -#else - - /* if terminal count has been set - yes */ - if (fdc->upd765_flags & UPD765_TC) - { - /* completed */ - return 1; - } - - /* Multi-Track operation: - - Verified on Amstrad CPC. - - disc format used: - 9 sectors per track - 2 sides - Sector IDs: &01, &02, &03, &04, &05, &06, &07, &08, &09 - - Command specified: - SIDE = 0, - C = 0,H = 0,R = 1, N = 2, EOT = 1 - Sectors read: - Sector 1 side 0 - Sector 1 side 1 - - Command specified: - SIDE = 0, - C = 0,H = 0,R = 1, N = 2, EOT = 3 - Sectors read: - Sector 1 side 0 - Sector 2 side 0 - Sector 3 side 0 - Sector 1 side 1 - Sector 2 side 1 - Sector 3 side 1 - - - Command specified: - SIDE = 0, - C = 0, H = 0, R = 7, N = 2, EOT = 3 - Sectors read: - Sector 7 side 0 - Sector 8 side 0 - Sector 9 side 0 - Sector 10 not found. Error "No Data" - - Command specified: - SIDE = 1, - C = 0, H = 1, R = 1, N = 2, EOT = 1 - Sectors read: - Sector 1 side 1 - - Command specified: - SIDE = 1, - C = 0, H = 1, R = 1, N = 2, EOT = 2 - Sectors read: - Sector 1 side 1 - Sector 1 side 2 - - */ - - /* sector id == EOT? */ - if ((fdc->upd765_command_bytes[4]==fdc->upd765_command_bytes[6])) - { - /* multi-track? */ - if (fdc->upd765_command_bytes[0] & 0x080) - { - /* if we have reached EOT (fdc->upd765_command_bytes[6]) - on side 1, then read is complete */ - if (fdc->side==1) - return 1; - - return 0; - - } - - /* completed */ - return 1; - } -#endif - /* not complete */ - return 0; -} - -static void upd765_increment_sector(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - /* multi-track? */ - if (fdc->upd765_command_bytes[0] & 0x080) - { - /* reached EOT? */ - /* if (fdc->upd765_command_bytes[4]==fdc->upd765_command_bytes[6])*/ - if (upd765_just_read_last_sector_on_track(device)) - { - /* yes */ - - /* reached EOT */ - /* change side to 1 */ - fdc->side = 1; - /* reset sector id to 1 */ - fdc->upd765_command_bytes[4] = 1; - /* set head to 1 for get next sector test */ - fdc->upd765_command_bytes[3] = 1; - } - else - { - /* increment */ - fdc->upd765_command_bytes[4]++; - } - - } - else - { - fdc->upd765_command_bytes[4]++; - } -} - -/* control mark handling code */ - -/* if SK==0, and we are executing a read data command, and a deleted data sector is found, -the data is not skipped. The data is read, but the control mark is set and the read is stopped */ -/* if SK==0, and we are executing a read deleted data command, and a data sector is found, -the data is not skipped. The data is read, but the control mark is set and the read is stopped */ -static int upd765_read_data_stop(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - /* skip not set? */ - if ((fdc->upd765_command_bytes[0] & (1<<5))==0) - { - /* read data? */ - if (fdc->command == 0x06) - { - /* did we just read a sector with deleted data? */ - if (fdc->data_type == UPD765_DAM_DELETED_DATA) - { - /* set control mark */ - fdc->upd765_status[2] |= UPD765_ST2_CONTROL_MARK; - - /* quit */ - return TRUE; - } - } - /* deleted data? */ - else - if (fdc->command == 0x0c) - { - /* did we just read a sector with data? */ - if (fdc->data_type == UPD765_DAM_DATA) - { - /* set control mark */ - fdc->upd765_status[2] |= UPD765_ST2_CONTROL_MARK; - - /* quit */ - return TRUE; - } - } - } - - /* continue */ - return FALSE; -} - -static TIMER_CALLBACK(upd765_continue_command) -{ - device_t *device = (device_t *)ptr; - upd765_t *fdc = get_safe_token(device); - if ((fdc->upd765_phase == UPD765_EXECUTION_PHASE_READ) || - (fdc->upd765_phase == UPD765_EXECUTION_PHASE_WRITE)) - { - switch (fdc->command) - { - /* read a track */ - case 0x02: - { - fdc->sector_counter++; - - /* sector counter == EOT */ - if (fdc->sector_counter==fdc->upd765_command_bytes[6]) - { - /* TODO: Add correct info here */ - - fdc->upd765_status[1] |= UPD765_ST1_END_OF_CYLINDER; - - upd765_setup_st0(device); - - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */ - fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */ - fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */ - fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */ - - upd765_setup_result_phase(device,7); - } - else - { - upd765_read_a_track(device); - } - } - break; - - /* format track */ - case 0x0d: - { - floppy_drive_format_sector(current_image(device), fdc->side, fdc->sector_counter, - fdc->format_data[0], fdc->format_data[1], - fdc->format_data[2], fdc->format_data[3], - fdc->upd765_command_bytes[5]); - - fdc->sector_counter++; - - /* sector_counter = SC */ - if (fdc->sector_counter == fdc->upd765_command_bytes[3]) - { - /* TODO: Check result is correct */ - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = fdc->format_data[0]; - fdc->upd765_result_bytes[4] = fdc->format_data[1]; - fdc->upd765_result_bytes[5] = fdc->format_data[2]; - fdc->upd765_result_bytes[6] = fdc->format_data[3]; - upd765_setup_result_phase(device,7); - } - else - { - upd765_format_track(device); - } - } - break; - - /* write data, write deleted data */ - case 0x09: - case 0x05: - { - /* sector id == EOT */ - UINT8 ddam; - - ddam = 0; - if (fdc->command == 0x09) - { - ddam = 1; - } - - /* write data to disc */ - floppy_drive_write_sector_data(current_image(device), fdc->side, fdc->sector_id,fdc->data_buffer,upd765_n_to_bytes(fdc->upd765_command_bytes[5]),ddam); - - if (upd765_sector_count_complete(device)) - { - upd765_increment_sector(device); - upd765_write_complete(device); - } - else - { - upd765_increment_sector(device); - upd765_write_data(device); - } - } - break; - - /* read data, read deleted data */ - case 0x0c: - case 0x06: - { - - /* read all sectors? */ - - /* sector id == EOT */ - if (upd765_sector_count_complete(device) || upd765_read_data_stop(device)) - { - upd765_read_complete(device); - } - else - { - upd765_increment_sector(device); - upd765_read_data(device); - } - } - break; - - default: - break; - } - } -} - - -static int upd765_get_command_byte_count(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - fdc->command = fdc->upd765_command_bytes[0] & 0x01f; - - if (fdc->version==TYPE_UPD765A) - { - return upd765_cmd_size[fdc->command]; - } - else - { - if (fdc->version==TYPE_UPD72065) - { - switch(fdc->upd765_command_bytes[0]) - { - case 0x34: // Reset Standby - case 0x35: // Set Standby - case 0x36: // Software Reset - return 1; - default: - return upd765_cmd_size[fdc->command]; - } - } - if (fdc->version==TYPE_SMC37C78) - { - switch (fdc->command) - { - /* version */ - case 0x010: - return 1; - - /* verify */ - case 0x016: - return 9; - - /* configure */ - case 0x013: - return 4; - - /* dumpreg */ - case 0x0e: - return 1; - - /* perpendicular mode */ - case 0x012: - return 1; - - /* lock */ - case 0x014: - return 1; - - /* seek/relative seek are together! */ - - default: - return upd765_cmd_size[fdc->command]; - } - } - } - - return upd765_cmd_size[fdc->command]; -} - - - - - -void upd765_update_state(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - switch (fdc->upd765_phase) { - case UPD765_RESULT_PHASE: - /* set data reg */ - fdc->upd765_data_reg = fdc->upd765_result_bytes[fdc->upd765_transfer_bytes_count]; - - if (fdc->upd765_transfer_bytes_count == 0) - { - /* clear int for specific commands */ - switch (fdc->command) { - case 2: /* read a track */ - case 5: /* write data */ - case 6: /* read data */ - case 9: /* write deleted data */ - case 10: /* read id */ - case 12: /* read deleted data */ - case 13: /* format at track */ - case 17: /* scan equal */ - case 19: /* scan low or equal */ - case 29: /* scan high or equal */ - upd765_set_int(device, 0); - break; - - default: - break; - } - } - - if (LOG_VERBOSE) - logerror("UPD765: RESULT: %02x\n", fdc->upd765_data_reg); - - fdc->upd765_transfer_bytes_count++; - fdc->upd765_transfer_bytes_remaining--; - - if (fdc->upd765_transfer_bytes_remaining==0) - { - upd765_idle(device); - } - else - { - upd765_set_data_request(device); - } - break; - - case UPD765_EXECUTION_PHASE_READ: - /* setup data register */ - fdc->upd765_data_reg = fdc->execution_phase_data[fdc->upd765_transfer_bytes_count]; - fdc->upd765_transfer_bytes_count++; - fdc->upd765_transfer_bytes_remaining--; - - if (LOG_EXTRA) - logerror("EXECUTION PHASE READ: %02x\n", fdc->upd765_data_reg); - - if ((fdc->upd765_transfer_bytes_remaining==0) || (fdc->upd765_flags & UPD765_TC)) - { - fdc->command_timer->adjust(attotime::zero); - } - else - { - /* trigger int */ - upd765_setup_timed_data_request(device,1); - } - break; - - case UPD765_COMMAND_PHASE_FIRST_BYTE: - fdc->FDC_main |= 0x10; /* set BUSY */ - - if (LOG_VERBOSE) - logerror("%s: upd765(): command=0x%02x\n", device->machine().describe_context(), fdc->upd765_data_reg); - - /* seek in progress? */ - if (fdc->upd765_flags & UPD765_SEEK_ACTIVE) - { - /* any command results in a invalid - I think that seek, recalibrate and - sense interrupt status may work*/ - if (fdc->upd765_data_reg != 8) /* Sense Interrupt Status */ - fdc->upd765_data_reg = 0; - } - - fdc->upd765_command_bytes[0] = fdc->upd765_data_reg; - - fdc->upd765_transfer_bytes_remaining = upd765_get_command_byte_count(device); - - fdc->upd765_transfer_bytes_count = 1; - fdc->upd765_transfer_bytes_remaining--; - - if (fdc->upd765_transfer_bytes_remaining==0) - { - upd765_setup_command(device); - } - else - { - /* request more data */ - upd765_set_data_request(device); - fdc->upd765_phase = UPD765_COMMAND_PHASE_BYTES; - } - break; - - case UPD765_COMMAND_PHASE_BYTES: - if (LOG_VERBOSE) - logerror("%s: upd765(): command=0x%02x\n", device->machine().describe_context(), fdc->upd765_data_reg); - - fdc->upd765_command_bytes[fdc->upd765_transfer_bytes_count] = fdc->upd765_data_reg; - fdc->upd765_transfer_bytes_count++; - fdc->upd765_transfer_bytes_remaining--; - - if (fdc->upd765_transfer_bytes_remaining==0) - { - upd765_setup_command(device); - } - else - { - /* request more data */ - upd765_set_data_request(device); - } - break; - - case UPD765_EXECUTION_PHASE_WRITE: - fdc->execution_phase_data[fdc->upd765_transfer_bytes_count]=fdc->upd765_data_reg; - fdc->upd765_transfer_bytes_count++; - fdc->upd765_transfer_bytes_remaining--; - - if ((fdc->upd765_transfer_bytes_remaining == 0) || (fdc->upd765_flags & UPD765_TC)) - { - fdc->command_timer->adjust(attotime::zero); - } - else - { - upd765_setup_timed_data_request(device,1); - } - break; - } -} - - -READ8_DEVICE_HANDLER(upd765_data_r) -{ - upd765_t *fdc = get_safe_token(device); - -// if ((fdc->FDC_main & 0x0c0) == 0x0c0) - if ((fdc->FDC_main & 0x080) == 0x080) - { - if ( - (fdc->upd765_phase == UPD765_EXECUTION_PHASE_READ) || - (fdc->upd765_phase == UPD765_EXECUTION_PHASE_WRITE)) - { - - /* reading the data byte clears the interrupt */ - upd765_set_int(device,CLEAR_LINE); - } - - /* reset data request */ - upd765_clear_data_request(device); - - /* update state */ - upd765_update_state(device); - } - - if (LOG_EXTRA) - logerror("DATA R: %02x\n", fdc->upd765_data_reg); - - return fdc->upd765_data_reg; -} - -WRITE8_DEVICE_HANDLER(upd765_data_w) -{ - upd765_t *fdc = get_safe_token(device); - - if (LOG_EXTRA) - logerror("DATA W: %02x\n", data); - - /* write data to data reg */ - fdc->upd765_data_reg = data; - - if ((fdc->FDC_main & 0x0c0)==0x080) - { - if ( - (fdc->upd765_phase == UPD765_EXECUTION_PHASE_READ) || - (fdc->upd765_phase == UPD765_EXECUTION_PHASE_WRITE)) - { - - /* reading the data byte clears the interrupt */ - upd765_set_int(device, CLEAR_LINE); - } - - /* reset data request */ - upd765_clear_data_request(device); - - /* update state */ - upd765_update_state(device); - } -} - -static void upd765_setup_invalid(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - - fdc->command = 0; - fdc->upd765_result_bytes[0] = 0x080; - upd765_setup_result_phase(device,1); -} - -static void upd765_setup_command(device_t *device) -{ - upd765_t *fdc = get_safe_token(device); - - static const char *const commands[] = - { - NULL, /* [00] */ - NULL, /* [01] */ - "Read Track", /* [02] */ - "Specify", /* [03] */ - "Sense Drive Status", /* [04] */ - "Write Data", /* [05] */ - "Read Data", /* [06] */ - "Recalibrate", /* [07] */ - "Sense Interrupt Status", /* [08] */ - "Write Deleted Data", /* [09] */ - "Read ID", /* [0A] */ - NULL, /* [0B] */ - "Read Deleted Data", /* [0C] */ - "Format Track", /* [0D] */ - "Dump Registers", /* [0E] */ - "Seek", /* [0F] */ - "Version", /* [10] */ - NULL, /* [11] */ - "Perpendicular Mode", /* [12] */ - "Configure", /* [13] */ - "Lock" /* [14] */ - }; - - device_t *img; - const char *cmd = NULL; - chrn_id id; - - /* if not in dma mode set execution phase bit */ - if (!(fdc->upd765_flags & UPD765_DMA_MODE)) - { - fdc->FDC_main |= 0x020; /* execution phase */ - } - - if (LOG_COMMAND) - { - if ((fdc->upd765_command_bytes[0] & 0x1f) < ARRAY_LENGTH(commands)) - cmd = commands[fdc->upd765_command_bytes[0] & 0x1f]; - logerror("upd765_setup_command(): Setting up command 0x%02X (%s)\n", - fdc->upd765_command_bytes[0] & 0x1f, cmd ? cmd : "???"); - } - - switch (fdc->upd765_command_bytes[0] & 0x1f) - { - case 0x03: /* specify */ - /* setup step rate */ - fdc->srt_in_ms = 16-((fdc->upd765_command_bytes[1]>>4) & 0x0f); - - fdc->upd765_flags &= ~UPD765_DMA_MODE; - - if ((fdc->upd765_command_bytes[2] & 0x01)==0) - { - fdc->upd765_flags |= UPD765_DMA_MODE; - } - - upd765_idle(device); - break; - - case 0x04: /* sense drive status */ - upd765_setup_drive_and_side(device); - img = current_image(device); - - fdc->upd765_status[3] = fdc->drive | (fdc->side<<2); - - if (img) - { - fdc->upd765_status[3] |= !floppy_tk00_r(img) << 4; - fdc->upd765_status[3] |= !floppy_wpt_r(img) << 6; - - if (upd765_get_rdy(device)) - { - fdc->upd765_status[3] |= 0x20; - } - } - - fdc->upd765_status[3] |= 0x08; - - /* two side and fault not set but should be? */ - fdc->upd765_result_bytes[0] = fdc->upd765_status[3]; - upd765_setup_result_phase(device,1); - break; - - case 0x07: /* recalibrate */ - upd765_seek_setup(device, 1); - break; - - case 0x0f: /* seek */ - upd765_seek_setup(device, 0); - break; - - case 0x0a: /* read id */ - upd765_setup_drive_and_side(device); - img = current_image(device); - - fdc->upd765_status[0] = fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0; - fdc->upd765_status[2] = 0; - - /* drive ready? */ - if (upd765_get_rdy(device)) - { - /* is disk inserted? */ - device_image_interface *image = dynamic_cast<device_image_interface *>( img); - if (image->exists()) - { - int index_count = 0; - - /* floppy drive is ready and disc is inserted */ - - /* this is the id that appears when a disc is not formatted */ - /* to be checked on Amstrad */ - id.C = 0; - id.H = 0; - id.R = 0x01; - id.N = 0x02; - - /* repeat for two index counts before quitting */ - do - { - /* get next id from disc */ - if (floppy_drive_get_next_id(img, fdc->side, &id)) - { - /* got an id - quit */ - break; - } - - if (floppy_drive_get_flag_state(img, FLOPPY_DRIVE_INDEX)) - { - /* update index count */ - index_count++; - } - } - while (index_count!=2); - - /* at this point, we have seen a id or two index pulses have occured! */ - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = id.C; /* C */ - fdc->upd765_result_bytes[4] = id.H; /* H */ - fdc->upd765_result_bytes[5] = id.R; /* R */ - fdc->upd765_result_bytes[6] = id.N; /* N */ - - upd765_setup_result_phase(device,7); - } - else - { - /* floppy drive is ready, but no disc is inserted */ - /* this occurs on the PC */ - /* in this case, the command never quits! */ - /* there are no index pulses to stop the command! */ - } - } - else - { - /* what are id values when drive not ready? */ - - /* not ready, abnormal termination */ - fdc->upd765_status[0] |= (1<<3) | (1<<6); - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - fdc->upd765_result_bytes[1] = fdc->upd765_status[1]; - fdc->upd765_result_bytes[2] = fdc->upd765_status[2]; - fdc->upd765_result_bytes[3] = 0; /* C */ - fdc->upd765_result_bytes[4] = 0; /* H */ - fdc->upd765_result_bytes[5] = 0; /* R */ - fdc->upd765_result_bytes[6] = 0; /* N */ - } - break; - - - case 0x08: /* sense interrupt status */ - /* interrupt pending? */ - if (fdc->upd765_flags & UPD765_INT) - { - /* yes. Clear int */ - upd765_set_int(device, CLEAR_LINE); - - /* clear drive seek bits */ - fdc->FDC_main &= ~(1 | 2 | 4 | 8); - - /* return status */ - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - /* return pcn */ - fdc->upd765_result_bytes[1] = fdc->pcn[fdc->drive]; - - /* return result */ - upd765_setup_result_phase(device,2); - } - else - { - if(fdc->version == TYPE_UPD72065 && (fdc->FDC_main & 0x0f) == 0x00) - { // based on XM6 - upd765_setup_invalid(device); - } - else - { - /* no int */ - fdc->upd765_result_bytes[0] = 0x80; - /* return pcn */ - fdc->upd765_result_bytes[1] = fdc->pcn[fdc->drive]; - - /* return result */ - upd765_setup_result_phase(device,2); - } - } - break; - - case 0x06: /* read data */ - upd765_setup_drive_and_side(device); - - fdc->upd765_status[0] = fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0; - fdc->upd765_status[2] = 0; - - upd765_read_data(device); - break; - - case 0x0c: - /* read deleted data */ - upd765_setup_drive_and_side(device); - - fdc->upd765_status[0] = fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0; - fdc->upd765_status[2] = 0; - - /* .. for now */ - upd765_read_data(device); - break; - - case 0x09: - /* write deleted data */ - upd765_setup_drive_and_side(device); - - fdc->upd765_status[0] = fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0; - fdc->upd765_status[2] = 0; - - /* ... for now */ - upd765_write_data(device); - break; - - case 0x02: - /* read a track */ - upd765_setup_drive_and_side(device); - img = current_image(device); - fdc->upd765_status[0] = fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0; - fdc->upd765_status[2] = 0; - - fdc->upd765_status[0] |= UPD765_ST1_NO_DATA; - - /* wait for index */ - do - { - /* get next id from disc */ - floppy_drive_get_next_id(img, fdc->side,&id); - } - while ((floppy_drive_get_flag_state(img, FLOPPY_DRIVE_INDEX))==0); - - fdc->sector_counter = 0; - - upd765_read_a_track(device); - break; - - case 0x05: /* write data */ - upd765_setup_drive_and_side(device); - - fdc->upd765_status[0] = fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0; - fdc->upd765_status[2] = 0; - - upd765_write_data(device); - break; - - case 0x0d: /* format a track */ - upd765_setup_drive_and_side(device); - - fdc->upd765_status[0] = fdc->drive | (fdc->side<<2); - fdc->upd765_status[1] = 0; - fdc->upd765_status[2] = 0; - - fdc->sector_counter = 0; - - upd765_format_track(device); - break; - - default: /* invalid */ - switch (fdc->version) - { - case TYPE_UPD765A: - upd765_setup_invalid(device); - break; - - case TYPE_UPD765B: - /* from upd765b data sheet */ - if ((fdc->upd765_command_bytes[0] & 0x01f)==0x010) - { - /* version */ - fdc->upd765_status[0] = 0x090; - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - upd765_setup_result_phase(device,1); - } - break; - - case TYPE_UPD72065: - switch(fdc->upd765_command_bytes[0] & 0x3f) - { - case 0x36: // Software Reset - upd765_reset(device,0); - upd765_idle(device); - if(LOG_COMMAND) - logerror("upd72065: command - Software Reset\n"); - break; - default: - upd765_setup_invalid(device); - break; - } - break; - - case TYPE_SMC37C78: - /* TO BE COMPLETED!!! !*/ - switch (fdc->upd765_command_bytes[0] & 0x1f) - { - case 0x10: /* version */ - fdc->upd765_status[0] = 0x90; - fdc->upd765_result_bytes[0] = fdc->upd765_status[0]; - upd765_setup_result_phase(device,1); - break; - - case 0x13: /* configure */ - upd765_idle(device); - break; - - case 0x0e: /* dump reg */ - fdc->upd765_result_bytes[0] = fdc->pcn[0]; - fdc->upd765_result_bytes[1] = fdc->pcn[1]; - fdc->upd765_result_bytes[2] = fdc->pcn[2]; - fdc->upd765_result_bytes[3] = fdc->pcn[3]; - - upd765_setup_result_phase(device,10); - break; - - case 0x12: /* perpendicular mode */ - upd765_idle(device); - break; - - case 0x14: /* lock */ - upd765_setup_result_phase(device,1); - break; - } - break; - } - } -} - - -/* dma acknowledge write */ -WRITE8_DEVICE_HANDLER(upd765_dack_w) -{ - /* clear request */ - upd765_set_dma_drq(device, CLEAR_LINE); - - /* write data */ - upd765_data_w(device, offset, data); -} - -READ8_DEVICE_HANDLER(upd765_dack_r) -{ - /* clear data request */ - upd765_set_dma_drq(device,CLEAR_LINE); - - /* read data */ - return upd765_data_r(device, offset); -} - -static TIMER_CALLBACK( interrupt_callback ) -{ - device_t* device = (device_t*)ptr; - upd765_set_int(device, 1); -} - -void upd765_reset(device_t *device, int offset) -{ - upd765_t *fdc = get_safe_token(device); - - /* upd765 in idle state - ready to accept commands */ - upd765_idle(device); - - /* set int low */ - upd765_set_int(device, 0); - /* set dma drq output */ - upd765_set_dma_drq(device,0); - - /* tandy 100hx assumes that after NEC is reset, it is in DMA mode */ - fdc->upd765_flags |= UPD765_DMA_MODE; - - /* if ready input is set during reset generate an int */ - if (fdc->upd765_flags & UPD765_FDD_READY) - { - int i; - int a_drive_is_ready; - - fdc->upd765_status[0] = 0x080 | 0x040; - - /* for the purpose of pc-xt. If any of the drives have a disk inserted, - do not set not-ready - need to check with pc_fdc->c whether all drives - are checked or only the drive selected with the drive select bits?? */ - - a_drive_is_ready = 0; - for (i = 0; i < 4; i++) - { - if (fdc->intf->floppy_drive_tags[i]!=NULL) - { - device_t *img; - - if (device->owner() != NULL) - img = device->owner()->subdevice(fdc->intf->floppy_drive_tags[i]); - else - img = device->machine().device(fdc->intf->floppy_drive_tags[i]); - - device_image_interface *image = dynamic_cast<device_image_interface *>( img); - if (image->exists()) - { - a_drive_is_ready = 1; - break; - } - } - - } - - if (!a_drive_is_ready && fdc->intf->rdy_pin == UPD765_RDY_PIN_CONNECTED ) - { - fdc->upd765_status[0] |= 0x08; - } - - device->machine().scheduler().timer_set(attotime::from_usec(5), FUNC(interrupt_callback),0,device); - } -} - -WRITE_LINE_DEVICE_HANDLER( upd765_reset_w ) -{ - upd765_t *fdc = get_safe_token(device); - - int flags; - - /* get previous reset state */ - flags = fdc->upd765_flags; - - /* set new reset state */ - /* clear reset */ - fdc->upd765_flags &= ~UPD765_RESET; - - /* reset */ - if (state) - { - fdc->upd765_flags |= UPD765_RESET; - - upd765_set_int(device, 0); - } - - /* reset changed state? */ - if (((flags^fdc->upd765_flags) & UPD765_RESET)!=0) - { - /* yes */ - - /* no longer reset */ - if ((fdc->upd765_flags & UPD765_RESET)==0) - { - /* reset nec */ - upd765_reset(device, 0); - } - } -} - - -WRITE_LINE_DEVICE_HANDLER( upd765_ready_w ) -{ - upd765_t *fdc = get_safe_token(device); - - /* clear ready state */ - fdc->upd765_flags &= ~UPD765_FDD_READY; - - if (state) - { - fdc->upd765_flags |= UPD765_FDD_READY; - } -} - - -/* Device Interface */ - -static void common_start(device_t *device, int device_type) -{ - upd765_t *fdc = get_safe_token(device); - // validate arguments - - assert(device != NULL); - assert(device->tag() != NULL); - assert(device->static_config() != NULL); - - fdc->intf = (const upd765_interface*)device->static_config(); - - fdc->version = (UPD765_VERSION)device_type; - fdc->timer = device->machine().scheduler().timer_alloc(FUNC(upd765_timer_callback), (void*)device); - fdc->seek_timer = device->machine().scheduler().timer_alloc(FUNC(upd765_seek_timer_callback), (void*)device); - fdc->command_timer = device->machine().scheduler().timer_alloc(FUNC(upd765_continue_command), (void*)device); - - fdc->upd765_flags &= UPD765_FDD_READY; - fdc->data_buffer = auto_alloc_array(device->machine(), char, 32*1024); - - fdc->out_int_func.resolve(fdc->intf->out_int_func, *device); - fdc->out_drq_func.resolve(fdc->intf->out_drq_func, *device); - - // register for state saving - //state_save_register_item(device->machine(), "upd765", device->tag(), 0, upd765->number); -} - -static DEVICE_START( upd765a ) -{ - common_start(device, TYPE_UPD765A); -} - -static DEVICE_START( upd765b ) -{ - common_start(device, TYPE_UPD765B); -} - -static DEVICE_START( smc37c78 ) -{ - common_start(device, TYPE_SMC37C78); -} - -static DEVICE_START( upd72065 ) -{ - common_start(device, TYPE_UPD72065); -} - -static DEVICE_RESET( upd765 ) -{ - int i; - upd765_t *fdc = get_safe_token(device); - for (i = 0; i < 4; i++) { - if (fdc->intf->floppy_drive_tags[i]!=NULL) - { - device_t *img; - - if (device->owner() != NULL) - img = device->owner()->subdevice(fdc->intf->floppy_drive_tags[i]); - else - img = device->machine().device(fdc->intf->floppy_drive_tags[i]); - - floppy_drive_set_controller(img, device); - floppy_drive_set_ready_state_change_callback(img, upd765_set_ready_change_callback); - } - } - - upd765_reset(device,0); -} - -DEVICE_GET_INFO( upd765a ) -{ - switch (state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(upd765_t); break; - case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(upd765a); break; - case DEVINFO_FCT_STOP: /* Nothing */ break; - case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(upd765); break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "UPD765A"); break; - case DEVINFO_STR_FAMILY: strcpy(info->s, "UPD765A"); break; - case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; - case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; - case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break; - } -} - - -DEVICE_GET_INFO( upd765b ) -{ - switch (state) - { - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "UPD765B"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(upd765b); break; - - default: DEVICE_GET_INFO_CALL(upd765a); break; - } -} - -DEVICE_GET_INFO( smc37c78 ) -{ - switch (state) - { - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "SMC37C78"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(smc37c78); break; - - default: DEVICE_GET_INFO_CALL(upd765a); break; - } -} - -DEVICE_GET_INFO( upd72065 ) -{ - switch (state) - { - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "UPD72065"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(upd72065); break; - - default: DEVICE_GET_INFO_CALL(upd765a); break; - } -} - -DEFINE_LEGACY_DEVICE(UPD765A, upd765a); -DEFINE_LEGACY_DEVICE(UPD765B, upd765b); -DEFINE_LEGACY_DEVICE(SMC37C78, smc37c78); -DEFINE_LEGACY_DEVICE(UPD72065, upd72065); diff --git a/src/emu/machine/upd765.h b/src/emu/machine/upd765.h deleted file mode 100644 index 17e86526dd4..00000000000 --- a/src/emu/machine/upd765.h +++ /dev/null @@ -1,161 +0,0 @@ -/*************************************************************************** - - machine/upd765.h - - Functions to emulate a NEC upd765/Intel 8272 compatible - floppy disk controller - -***************************************************************************/ - -#ifndef __UPD765_H__ -#define __UPD765_H__ - -#include "devcb.h" -#include "imagedev/flopdrv.h" - - -/*************************************************************************** - MACROS -***************************************************************************/ - -DECLARE_LEGACY_DEVICE(UPD765A, upd765a); -DECLARE_LEGACY_DEVICE(UPD765B, upd765b); -DECLARE_LEGACY_DEVICE(SMC37C78, smc37c78); -DECLARE_LEGACY_DEVICE(UPD72065, upd72065); - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -/* RDY pin connected state */ -typedef enum -{ - UPD765_RDY_PIN_NOT_CONNECTED = 0, - UPD765_RDY_PIN_CONNECTED = 1 -} UPD765_RDY_PIN; - -#define UPD765_DAM_DELETED_DATA 0x0f8 -#define UPD765_DAM_DATA 0x0fb - -typedef device_t *(*upd765_get_image_func)(device_t *device, int floppy_index); -#define UPD765_GET_IMAGE(name) device_t *name(device_t *device, int floppy_index ) - - -typedef struct upd765_interface -{ - /* interrupt issued */ - devcb_write_line out_int_func; - - /* dma data request */ - devcb_write_line out_drq_func; - - /* image lookup */ - upd765_get_image_func get_image; - - UPD765_RDY_PIN rdy_pin; - - const char *floppy_drive_tags[4]; -} upd765_interface; - - -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - -/* read of data register */ -READ8_DEVICE_HANDLER(upd765_data_r); -/* write to data register */ -WRITE8_DEVICE_HANDLER(upd765_data_w); -/* read of main status register */ -READ8_DEVICE_HANDLER(upd765_status_r); - -/* dma acknowledge with write */ -WRITE8_DEVICE_HANDLER(upd765_dack_w); -/* dma acknowledge with read */ -READ8_DEVICE_HANDLER(upd765_dack_r); - -/* reset upd765 */ -void upd765_reset(device_t *device, int); - -/* reset pin of upd765 */ -WRITE_LINE_DEVICE_HANDLER(upd765_reset_w); - -/* set upd765 terminal count input state */ -WRITE_LINE_DEVICE_HANDLER(upd765_tc_w); - -/* set upd765 ready input*/ -WRITE_LINE_DEVICE_HANDLER(upd765_ready_w); - -void upd765_idle(device_t *device); - -/*********************/ -/* STATUS REGISTER 1 */ - -/* this is set if a TC signal was not received after the sector data was read */ -#define UPD765_ST1_END_OF_CYLINDER (1<<7) -/* this is set if the sector ID being searched for is not found */ -#define UPD765_ST1_NO_DATA (1<<2) -/* set if disc is write protected and a write/format operation was performed */ -#define UPD765_ST1_NOT_WRITEABLE (1<<1) - -/*********************/ -/* STATUS REGISTER 2 */ - -/* C parameter specified did not match C value read from disc */ -#define UPD765_ST2_WRONG_CYLINDER (1<<4) -/* C parameter specified did not match C value read from disc, and C read from disc was 0x0ff */ -#define UPD765_ST2_BAD_CYLINDER (1<<1) -/* this is set if the FDC encounters a Deleted Data Mark when executing a read data -command, or FDC encounters a Data Mark when executing a read deleted data command */ -#define UPD765_ST2_CONTROL_MARK (1<<6) - -/*************************************************************************** - DEVICE CONFIGURATION MACROS -***************************************************************************/ - -#define MCFG_UPD765A_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, UPD765A, 0) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_UPD765A_MODIFY(_tag, _intrf) \ - MCFG_DEVICE_MODIFY(_tag) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_UPD765A_REMOVE(_tag) \ - MCFG_DEVICE_REMOVE(_tag) - -#define MCFG_UPD765B_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, UPD765B, 0) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_UPD765B_MODIFY(_tag, _intrf) \ - MCFG_DEVICE_MODIFY(_tag) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_UPD765B_REMOVE(_tag) \ - MCFG_DEVICE_REMOVE(_tag) - -#define MCFG_SMC37C78_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, SMC37C78, 0) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_SMC37C78_MODIFY(_tag, _intrf) \ - MCFG_DEVICE_MODIFY(_tag) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_SMC37C78_REMOVE(_tag) \ - MCFG_DEVICE_REMOVE(_tag) - -#define MCFG_UPD72065_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, UPD72065, 0) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_UPD72065_MODIFY(_tag, _intrf) \ - MCFG_DEVICE_MODIFY(_tag) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define MCFG_UPD72065_REMOVE(_tag) \ - MCFG_DEVICE_REMOVE(_tag) - - -#endif /* __UPD765_H__ */ diff --git a/src/mame/drivers/sg1000.c b/src/mame/drivers/sg1000.c index dec385ef3a4..f5cb55802a0 100644 --- a/src/mame/drivers/sg1000.c +++ b/src/mame/drivers/sg1000.c @@ -66,18 +66,13 @@ Notes: #include "emu.h" #include "cpu/z80/z80.h" -#include "imagedev/flopdrv.h" #include "imagedev/cartslot.h" #include "imagedev/cassette.h" #include "machine/ram.h" #include "imagedev/printer.h" -#include "formats/basicdsk.h" #include "machine/ctronics.h" #include "machine/i8255.h" -#include "machine/msm8251.h" -#include "machine/upd765.h" #include "sound/sn76496.h" -#include "video/tms9928a.h" #include "crsshair.h" #include "includes/sg1000.h" @@ -237,32 +232,6 @@ static ADDRESS_MAP_START( sc3000_io_map, AS_IO, 8, sg1000_state ) ADDRESS_MAP_END */ -/*------------------------------------------------- - ADDRESS_MAP( sf7000_map ) --------------------------------------------------*/ - -static ADDRESS_MAP_START( sf7000_map, AS_PROGRAM, 8, sf7000_state ) - AM_RANGE(0x0000, 0x3fff) AM_READ_BANK("bank1") AM_WRITE_BANK("bank2") - AM_RANGE(0x4000, 0xffff) AM_RAM -ADDRESS_MAP_END - -/*------------------------------------------------- - ADDRESS_MAP( sf7000_io_map ) --------------------------------------------------*/ - -static ADDRESS_MAP_START( sf7000_io_map, AS_IO, 8, sf7000_state ) - ADDRESS_MAP_GLOBAL_MASK(0xff) - AM_RANGE(0x7f, 0x7f) AM_DEVWRITE_LEGACY(SN76489A_TAG, sn76496_w) - AM_RANGE(0xbe, 0xbe) AM_READWRITE_LEGACY(TMS9928A_vram_r, TMS9928A_vram_w) - AM_RANGE(0xbf, 0xbf) AM_READWRITE_LEGACY(TMS9928A_register_r, TMS9928A_register_w) - AM_RANGE(0xdc, 0xdf) AM_DEVREADWRITE(UPD9255_0_TAG, i8255_device, read, write) - AM_RANGE(0xe0, 0xe0) AM_DEVREAD_LEGACY(UPD765_TAG, upd765_status_r) - AM_RANGE(0xe1, 0xe1) AM_DEVREADWRITE_LEGACY(UPD765_TAG, upd765_data_r, upd765_data_w) - AM_RANGE(0xe4, 0xe7) AM_DEVREADWRITE(UPD9255_1_TAG, i8255_device, read, write) - AM_RANGE(0xe8, 0xe8) AM_DEVREADWRITE_LEGACY(UPD8251_TAG, msm8251_data_r, msm8251_data_w) - AM_RANGE(0xe9, 0xe9) AM_DEVREADWRITE_LEGACY(UPD8251_TAG, msm8251_status_r, msm8251_control_w) -ADDRESS_MAP_END - /*************************************************************************** INPUT PORTS ***************************************************************************/ @@ -378,7 +347,7 @@ INPUT_PORTS_END INPUT_PORTS( sk1100 ) -------------------------------------------------*/ -static INPUT_PORTS_START( sk1100 ) +INPUT_PORTS_START( sk1100 ) PORT_START("PA0") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHAR('q') @@ -509,23 +478,6 @@ static INPUT_PORTS_START( sc3000 ) PORT_INCLUDE( tvdraw ) INPUT_PORTS_END -/*------------------------------------------------- - INPUT_PORTS( sf7000 ) --------------------------------------------------*/ - -static INPUT_PORTS_START( sf7000 ) - PORT_INCLUDE( sk1100 ) - - PORT_START("BAUD") - PORT_CONFNAME( 0x05, 0x05, "Baud rate") - PORT_CONFSETTING( 0x00, "9600 baud" ) - PORT_CONFSETTING( 0x01, "4800 baud" ) - PORT_CONFSETTING( 0x02, "2400 baud" ) - PORT_CONFSETTING( 0x03, "1200 baud" ) - PORT_CONFSETTING( 0x04, "600 baud" ) - PORT_CONFSETTING( 0x05, "300 baud" ) -INPUT_PORTS_END - /*************************************************************************** DEVICE CONFIGURATION ***************************************************************************/ @@ -534,7 +486,7 @@ INPUT_PORTS_END TMS9928a_interface tms9928a_interface -------------------------------------------------*/ -static INTERRUPT_GEN( sg1000_int ) +INTERRUPT_GEN( sg1000_int ) { TMS9928A_interrupt(device->machine()); } @@ -544,7 +496,7 @@ static void sg1000_vdp_interrupt(running_machine &machine, int state) cputag_set_input_line(machine, Z80_TAG, INPUT_LINE_IRQ0, state); } -static const TMS9928a_interface tms9928a_interface = +const TMS9928a_interface tms9928a_interface = { TMS99x8A, 0x4000, @@ -632,7 +584,7 @@ WRITE8_MEMBER( sc3000_state::ppi_pc_w ) /* TODO printer */ } -static I8255_INTERFACE( sc3000_ppi_intf ) +I8255_INTERFACE( sc3000_ppi_intf ) { DEVCB_DRIVER_MEMBER(sc3000_state, ppi_pa_r), // Port A read DEVCB_NULL, // Port A write @@ -646,7 +598,7 @@ static I8255_INTERFACE( sc3000_ppi_intf ) cassette_config sc3000_cassette_config -------------------------------------------------*/ -static const cassette_config sc3000_cassette_config = +const cassette_config sc3000_cassette_config = { cassette_default_formats, NULL, @@ -654,126 +606,6 @@ static const cassette_config sc3000_cassette_config = NULL }; -/*------------------------------------------------- - I8255_INTERFACE( sf7000_ppi_intf ) --------------------------------------------------*/ - -READ8_MEMBER( sf7000_state::ppi_pa_r ) -{ - /* - Signal Description - - PA0 INT from FDC - PA1 BUSY from Centronics printer - PA2 INDEX from FDD - PA3 - PA4 - PA5 - PA6 - PA7 - */ - - UINT8 data = 0; - - data |= m_fdc_irq; - data |= centronics_busy_r(m_centronics) << 1; - data |= m_fdc_index << 2; - - return data; -} - -WRITE8_MEMBER( sf7000_state::ppi_pc_w ) -{ - /* - Signal Description - - PC0 /INUSE signal to FDD - PC1 /MOTOR ON signal to FDD - PC2 TC signal to FDC - PC3 RESET signal to FDC - PC4 not connected - PC5 not connected - PC6 /ROM SEL (switch between IPL ROM and RAM) - PC7 /STROBE to Centronics printer - */ - - /* floppy motor */ - floppy_mon_w(m_floppy0, BIT(data, 1)); - floppy_drive_set_ready_state(m_floppy0, 1, 1); - - /* FDC terminal count */ - upd765_tc_w(m_fdc, BIT(data, 2)); - - /* FDC reset */ - if (BIT(data, 3)) - { - upd765_reset(m_fdc, 0); - } - - /* ROM selection */ - memory_set_bank(machine(), "bank1", BIT(data, 6)); - - /* printer strobe */ - centronics_strobe_w(m_centronics, BIT(data, 7)); -} - -static I8255_INTERFACE( sf7000_ppi_intf ) -{ - DEVCB_DRIVER_MEMBER(sf7000_state, ppi_pa_r), // Port A read - DEVCB_NULL, // Port A write - DEVCB_NULL, // Port B read - DEVCB_DEVICE_HANDLER(CENTRONICS_TAG, centronics_data_w), // Port B write - DEVCB_NULL, // Port C read - DEVCB_DRIVER_MEMBER(sf7000_state, ppi_pc_w) // Port C write -}; - -/*------------------------------------------------- - upd765_interface sf7000_upd765_interface --------------------------------------------------*/ - -WRITE_LINE_MEMBER( sf7000_state::fdc_intrq_w ) -{ - m_fdc_irq = state; -} - -static const struct upd765_interface sf7000_upd765_interface = -{ - DEVCB_DRIVER_LINE_MEMBER(sf7000_state, fdc_intrq_w), - DEVCB_NULL, - NULL, - UPD765_RDY_PIN_CONNECTED, - { FLOPPY_0, NULL, NULL, NULL } -}; - -/*------------------------------------------------- - FLOPPY_OPTIONS( sf7000 ) --------------------------------------------------*/ - -static FLOPPY_OPTIONS_START( sf7000 ) - FLOPPY_OPTION(sf7000, "sf7", "SF7 disk image", basicdsk_identify_default, basicdsk_construct_default, NULL, - HEADS([1]) - TRACKS([40]) - SECTORS([16]) - SECTOR_LENGTH([256]) - FIRST_SECTOR_ID([1])) -FLOPPY_OPTIONS_END - -/*------------------------------------------------- - floppy_config sf7000_floppy_config --------------------------------------------------*/ - -static const floppy_config sf7000_floppy_config = -{ - DEVCB_NULL, - DEVCB_NULL, - DEVCB_NULL, - DEVCB_NULL, - DEVCB_NULL, - FLOPPY_STANDARD_5_25_DSHD, - FLOPPY_OPTIONS_NAME(sf7000), - NULL -}; - /*************************************************************************** CARTRIDGE LOADING ***************************************************************************/ @@ -994,50 +826,6 @@ void sc3000_state::machine_start() state_save_register_global(machine(), m_keylatch); } -/*------------------------------------------------- - sf7000_fdc_index_callback - --------------------------------------------------*/ - -static void sf7000_fdc_index_callback(device_t *controller, device_t *img, int state) -{ - sf7000_state *driver_state = img->machine().driver_data<sf7000_state>(); - - driver_state->m_fdc_index = state; -} - -/*------------------------------------------------- - MACHINE_START( sf7000 ) --------------------------------------------------*/ - -void sf7000_state::machine_start() -{ - /* configure VDP */ - TMS9928A_configure(&tms9928a_interface); - - /* configure FDC */ - floppy_drive_set_index_pulse_callback(m_floppy0, sf7000_fdc_index_callback); - - /* configure memory banking */ - memory_configure_bank(machine(), "bank1", 0, 1, machine().region(Z80_TAG)->base(), 0); - memory_configure_bank(machine(), "bank1", 1, 1, ram_get_ptr(m_ram), 0); - memory_configure_bank(machine(), "bank2", 0, 1, ram_get_ptr(m_ram), 0); - - /* register for state saving */ - state_save_register_global(machine(), m_keylatch); - state_save_register_global(machine(), m_fdc_irq); - state_save_register_global(machine(), m_fdc_index); -} - -/*------------------------------------------------- - MACHINE_RESET( sf7000 ) --------------------------------------------------*/ - -void sf7000_state::machine_reset() -{ - memory_set_bank(machine(), "bank1", 0); - memory_set_bank(machine(), "bank2", 0); -} - /*************************************************************************** MACHINE DRIVERS ***************************************************************************/ @@ -1138,42 +926,6 @@ static MACHINE_CONFIG_START( sc3000, sc3000_state ) MCFG_RAM_DEFAULT_SIZE("2K") MACHINE_CONFIG_END -/*------------------------------------------------- - MACHINE_CONFIG_START( sf7000, sf7000_state ) --------------------------------------------------*/ - -static MACHINE_CONFIG_START( sf7000, sf7000_state ) - /* basic machine hardware */ - MCFG_CPU_ADD(Z80_TAG, Z80, XTAL_10_738635MHz/3) - MCFG_CPU_PROGRAM_MAP(sf7000_map) - MCFG_CPU_IO_MAP(sf7000_io_map) - MCFG_CPU_VBLANK_INT(SCREEN_TAG, sg1000_int) - - /* video hardware */ - MCFG_FRAGMENT_ADD(tms9928a) - MCFG_SCREEN_MODIFY(SCREEN_TAG) - MCFG_SCREEN_REFRESH_RATE((float)XTAL_10_738635MHz/2/342/262) - MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ - - /* sound hardware */ - MCFG_SPEAKER_STANDARD_MONO("mono") - MCFG_SOUND_ADD(SN76489A_TAG, SN76489A, XTAL_10_738635MHz/3) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) - - /* devices */ - MCFG_I8255_ADD(UPD9255_0_TAG, sc3000_ppi_intf) - MCFG_I8255_ADD(UPD9255_1_TAG, sf7000_ppi_intf) - MCFG_MSM8251_ADD(UPD8251_TAG, default_msm8251_interface) - MCFG_UPD765A_ADD(UPD765_TAG, sf7000_upd765_interface) - MCFG_FLOPPY_DRIVE_ADD(FLOPPY_0, sf7000_floppy_config) -// MCFG_PRINTER_ADD("sp400") /* serial printer */ - MCFG_CENTRONICS_ADD(CENTRONICS_TAG, standard_centronics) - MCFG_CASSETTE_ADD(CASSETTE_TAG, sc3000_cassette_config) - - /* internal ram */ - MCFG_RAM_ADD(RAM_TAG) - MCFG_RAM_DEFAULT_SIZE("64K") -MACHINE_CONFIG_END /*************************************************************************** ROMS @@ -1202,11 +954,6 @@ ROM_START( omv2000 ) ROM_LOAD( "omvbios.bin", 0x0000, 0x4000, CRC(c5a67b95) SHA1(6d7c64dd60dee4a33061d3d3a7c2ed190d895cdb) ) ROM_END -ROM_START( sf7000 ) - ROM_REGION( 0x10000, Z80_TAG, 0 ) - ROM_LOAD( "ipl.rom", 0x0000, 0x2000, CRC(d76810b8) SHA1(77339a6db2593aadc638bed77b8e9bed5d9d87e3) ) -ROM_END - /*************************************************************************** SYSTEM DRIVERS ***************************************************************************/ @@ -1216,6 +963,5 @@ CONS( 1983, sg1000, 0, 0, sg1000, sg1000, 0, CONS( 1984, sg1000m2, sg1000, 0, sc3000, sc3000, 0, "Sega", "SG-1000 II", GAME_SUPPORTS_SAVE ) COMP( 1983, sc3000, 0, sg1000, sc3000, sc3000, 0, "Sega", "SC-3000", GAME_SUPPORTS_SAVE ) COMP( 1983, sc3000h, sc3000, 0, sc3000, sc3000, 0, "Sega", "SC-3000H", GAME_SUPPORTS_SAVE ) -COMP( 1983, sf7000, sc3000, 0, sf7000, sf7000, 0, "Sega", "SC-3000/Super Control Station SF-7000", GAME_SUPPORTS_SAVE ) CONS( 1984, omv1000, sg1000, 0, omv, omv, 0, "Tsukuda Original", "Othello Multivision FG-1000", GAME_SUPPORTS_SAVE ) CONS( 1984, omv2000, sg1000, 0, omv, omv, 0, "Tsukuda Original", "Othello Multivision FG-2000", GAME_SUPPORTS_SAVE ) diff --git a/src/mame/includes/sg1000.h b/src/mame/includes/sg1000.h index 20b1b792af5..72cd136503b 100644 --- a/src/mame/includes/sg1000.h +++ b/src/mame/includes/sg1000.h @@ -2,6 +2,8 @@ #define __SG1000__ #include "machine/ram.h" +#include "video/tms9928a.h" +#include "imagedev/cassette.h" #define SCREEN_TAG "screen" #define Z80_TAG "z80" @@ -26,6 +28,12 @@ #define IS_CARTRIDGE_MUSIC_EDITOR(ptr) \ (!strncmp("PIANO", (const char *)&ptr[0x0841], 5)) +extern const TMS9928a_interface tms9928a_interface; +INPUT_PORTS_EXTERN( sk1100 ); +extern INTERRUPT_GEN( sg1000_int ); +extern const i8255_interface ( sc3000_ppi_intf ); +extern const cassette_config sc3000_cassette_config; + class sg1000_state : public driver_device { public: @@ -73,30 +81,4 @@ public: DECLARE_WRITE8_MEMBER( ppi_pc_w ); }; -class sf7000_state : public sc3000_state -{ -public: - sf7000_state(const machine_config &mconfig, device_type type, const char *tag) - : sc3000_state(mconfig, type, tag), - m_fdc(*this, UPD765_TAG), - m_centronics(*this, CENTRONICS_TAG), - m_floppy0(*this, FLOPPY_0) - { } - - required_device<device_t> m_fdc; - required_device<device_t> m_centronics; - required_device<device_t> m_floppy0; - - virtual void machine_start(); - virtual void machine_reset(); - - DECLARE_READ8_MEMBER( ppi_pa_r ); - DECLARE_WRITE8_MEMBER( ppi_pc_w ); - DECLARE_WRITE_LINE_MEMBER( fdc_intrq_w ); - - /* floppy state */ - int m_fdc_irq; - int m_fdc_index; -}; - #endif |