--- /dev/null
+/*\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