-/*\r
- FUJITSU FMR-30 Emulator 'eFMR-30'\r
-\r
- Author : Takeda.Toshiya\r
- Date : 2008.12.31 -\r
-\r
- [ serial ]\r
-*/\r
-\r
-#include "serial.h"\r
-#include "../i8251.h"\r
-#include "../i8259.h"\r
-\r
-void SERIAL::initialize()\r
-{\r
- for(int i = 0; i < 4; i++) {\r
- sioctrl[i].baud = 0;\r
- sioctrl[i].ctrl = 0;\r
- sioctrl[i].rxrdy = false;\r
- sioctrl[i].txrdy = false;\r
- sioctrl[i].intstat = 0;\r
- sioctrl[i].intmask = 0;\r
- }\r
-}\r
-\r
-void SERIAL::write_io8(uint32 addr, uint32 data)\r
-{\r
- switch(addr & 0xffff) {\r
- case 0x0a:\r
- sioctrl[0].baud = data;\r
- break;\r
- case 0x0b:\r
- sioctrl[0].ctrl = data;\r
- d_kb->write_signal(SIG_I8251_LOOPBACK, data, 8);\r
- update_intr(0);\r
- break;\r
- case 0x12:\r
- sioctrl[1].baud = data;\r
- break;\r
- case 0x13:\r
- sioctrl[1].ctrl = data;\r
- d_sub->write_signal(SIG_I8251_LOOPBACK, data, 8);\r
- update_intr(1);\r
- break;\r
- case 0x62:\r
- sioctrl[2].baud = data;\r
- break;\r
- case 0x63:\r
- sioctrl[2].ctrl = data;\r
- d_ch1->write_signal(SIG_I8251_LOOPBACK, data, 8);\r
- update_intr(2);\r
- break;\r
- case 0x64:\r
- sioctrl[2].intmask = data;\r
- break;\r
- case 0x65:\r
- sioctrl[2].intstat &= ~data;\r
- break;\r
- case 0x72:\r
- sioctrl[3].baud = data;\r
- break;\r
- case 0x73:\r
- sioctrl[3].ctrl = data;\r
- d_ch2->write_signal(SIG_I8251_LOOPBACK, data, 8);\r
- update_intr(3);\r
- break;\r
- case 0x74:\r
- sioctrl[3].intmask = data;\r
- break;\r
- case 0x75:\r
- sioctrl[3].intstat &= ~data;\r
- break;\r
- }\r
-}\r
-\r
-uint32 SERIAL::read_io8(uint32 addr)\r
-{\r
- switch(addr & 0xffff) {\r
- case 0x0a:\r
- return sioctrl[0].baud;\r
- case 0x0b:\r
- return sioctrl[0].ctrl;\r
- case 0x12:\r
- return sioctrl[1].baud;\r
- case 0x13:\r
- return sioctrl[1].ctrl;\r
- case 0x62:\r
- return sioctrl[2].baud;\r
- case 0x63:\r
- return sioctrl[2].ctrl;\r
- case 0x64:\r
- return sioctrl[2].intmask;\r
- case 0x65:\r
- return sioctrl[2].intstat;\r
- case 0x66:\r
- return 0xf0; // append register\r
- case 0x72:\r
- return sioctrl[3].baud;\r
- case 0x73:\r
- return sioctrl[3].ctrl;\r
- case 0x74:\r
- return sioctrl[3].intmask;\r
- case 0x75:\r
- return sioctrl[3].intstat;\r
- case 0x76:\r
- return 0xf0; // append register\r
- }\r
- return 0xff;\r
-}\r
-\r
-void SERIAL::write_signal(int id, uint32 data, uint32 mask)\r
-{\r
- switch(id) {\r
- case SIG_SERIAL_RXRDY_KB:\r
- case SIG_SERIAL_RXRDY_SUB:\r
- case SIG_SERIAL_RXRDY_CH1:\r
- case SIG_SERIAL_RXRDY_CH2:\r
- sioctrl[id & 3].rxrdy = ((data & mask) != 0);\r
- update_intr(id & 3);\r
- break;\r
- case SIG_SERIAL_TXRDY_KB:\r
- case SIG_SERIAL_TXRDY_SUB:\r
- case SIG_SERIAL_TXRDY_CH1:\r
- case SIG_SERIAL_TXRDY_CH2:\r
- sioctrl[id & 3].txrdy = ((data & mask) != 0);\r
- update_intr(id & 3);\r
- break;\r
- }\r
-}\r
-\r
-void SERIAL::update_intr(int ch)\r
-{\r
- static const int pic_ids[4] = {\r
- SIG_I8259_CHIP0 | SIG_I8259_IR2, // keyboard\r
- SIG_I8259_CHIP0 | SIG_I8259_IR3, // sub\r
- SIG_I8259_CHIP0 | SIG_I8259_IR4, // rs-232c ch.1\r
- SIG_I8259_CHIP1 | SIG_I8259_IR4 // rs-232c ch.2\r
- };\r
- \r
- if((sioctrl[ch].rxrdy && (sioctrl[ch].ctrl & 0x40)) || (sioctrl[ch].txrdy && (sioctrl[ch].ctrl & 0x20))) {\r
- d_pic->write_signal(pic_ids[ch], 1, 1);\r
- sioctrl[ch].intstat |= 4;\r
- } else {\r
- d_pic->write_signal(pic_ids[ch], 0, 1);\r
- sioctrl[ch].intstat &= ~4;\r
- }\r
-}\r
+/*
+ FUJITSU FMR-30 Emulator 'eFMR-30'
+
+ Author : Takeda.Toshiya
+ Date : 2008.12.31 -
+
+ [ serial ]
+*/
+
+#include "serial.h"
+#include "../i8251.h"
+#include "../i8259.h"
+
+void SERIAL::initialize()
+{
+ memset(sioctrl, sizeof(sioctrl), 1);
+}
+
+void SERIAL::write_io8(uint32_t addr, uint32_t data)
+{
+ switch(addr & 0xffff) {
+ case 0x0a:
+ sioctrl[0].baud = data;
+ break;
+ case 0x0b:
+ sioctrl[0].ctrl = data;
+ d_kb->write_signal(SIG_I8251_LOOPBACK, data, 8);
+ update_intr(0);
+ break;
+ case 0x12:
+ sioctrl[1].baud = data;
+ break;
+ case 0x13:
+ sioctrl[1].ctrl = data;
+ d_sub->write_signal(SIG_I8251_LOOPBACK, data, 8);
+ update_intr(1);
+ break;
+ case 0x62:
+ sioctrl[2].baud = data;
+ break;
+ case 0x63:
+ sioctrl[2].ctrl = data;
+ d_ch1->write_signal(SIG_I8251_LOOPBACK, data, 8);
+ update_intr(2);
+ break;
+ case 0x64:
+ sioctrl[2].intmask = data;
+ break;
+ case 0x65:
+ sioctrl[2].intstat &= ~data;
+ break;
+ case 0x72:
+ sioctrl[3].baud = data;
+ break;
+ case 0x73:
+ sioctrl[3].ctrl = data;
+ d_ch2->write_signal(SIG_I8251_LOOPBACK, data, 8);
+ update_intr(3);
+ break;
+ case 0x74:
+ sioctrl[3].intmask = data;
+ break;
+ case 0x75:
+ sioctrl[3].intstat &= ~data;
+ break;
+ }
+}
+
+uint32_t SERIAL::read_io8(uint32_t addr)
+{
+ switch(addr & 0xffff) {
+ case 0x0a:
+ return sioctrl[0].baud;
+ case 0x0b:
+ return sioctrl[0].ctrl;
+ case 0x12:
+ return sioctrl[1].baud;
+ case 0x13:
+ return sioctrl[1].ctrl;
+ case 0x62:
+ return sioctrl[2].baud;
+ case 0x63:
+ return sioctrl[2].ctrl;
+ case 0x64:
+ return sioctrl[2].intmask;
+ case 0x65:
+ return sioctrl[2].intstat;
+ case 0x66:
+ return 0xf0; // append register
+ case 0x72:
+ return sioctrl[3].baud;
+ case 0x73:
+ return sioctrl[3].ctrl;
+ case 0x74:
+ return sioctrl[3].intmask;
+ case 0x75:
+ return sioctrl[3].intstat;
+ case 0x76:
+ return 0xf0; // append register
+ }
+ return 0xff;
+}
+
+void SERIAL::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ switch(id) {
+ case SIG_SERIAL_RXRDY_KB:
+ case SIG_SERIAL_RXRDY_SUB:
+ case SIG_SERIAL_RXRDY_CH1:
+ case SIG_SERIAL_RXRDY_CH2:
+ sioctrl[id & 3].rxrdy = ((data & mask) != 0);
+ update_intr(id & 3);
+ break;
+ case SIG_SERIAL_TXRDY_KB:
+ case SIG_SERIAL_TXRDY_SUB:
+ case SIG_SERIAL_TXRDY_CH1:
+ case SIG_SERIAL_TXRDY_CH2:
+ sioctrl[id & 3].txrdy = ((data & mask) != 0);
+ update_intr(id & 3);
+ break;
+ }
+}
+
+void SERIAL::update_intr(int ch)
+{
+ static const int pic_ids[4] = {
+ SIG_I8259_CHIP0 | SIG_I8259_IR2, // keyboard
+ SIG_I8259_CHIP0 | SIG_I8259_IR3, // sub
+ SIG_I8259_CHIP0 | SIG_I8259_IR4, // rs-232c ch.1
+ SIG_I8259_CHIP1 | SIG_I8259_IR4 // rs-232c ch.2
+ };
+
+ if((sioctrl[ch].rxrdy && (sioctrl[ch].ctrl & 0x40)) || (sioctrl[ch].txrdy && (sioctrl[ch].ctrl & 0x20))) {
+ d_pic->write_signal(pic_ids[ch], 1, 1);
+ sioctrl[ch].intstat |= 4;
+ } else {
+ d_pic->write_signal(pic_ids[ch], 0, 1);
+ sioctrl[ch].intstat &= ~4;
+ }
+}
+
+#define STATE_VERSION 1
+
+bool SERIAL::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ //state_fio->StateBuffer(sioctrl, sizeof(sioctrl), 1);
+ for(int i = 0; i < 4; i++) {
+ state_fio->StateUint8(sioctrl[i].baud);
+ state_fio->StateUint8(sioctrl[i].ctrl);
+ state_fio->StateBool(sioctrl[i].rxrdy);
+ state_fio->StateBool(sioctrl[i].txrdy);
+ state_fio->StateUint8(sioctrl[i].intmask);
+ state_fio->StateUint8(sioctrl[i].intstat);
+ }
+ return true;
+}