|
|
1.1 ! root 1: /* Previous - scc.c ! 2: ! 3: This file is distributed under the GNU Public License, version 2 or at ! 4: your option any later version. Read the file gpl.txt for details. ! 5: ! 6: Serial Communication Controller (AMD AM8530H) Emulation. ! 7: ! 8: Incomplete. Hacked to pass power-on test --> see SCC_Reset() ! 9: ! 10: */ ! 11: ! 12: #include "ioMem.h" ! 13: #include "ioMemTables.h" ! 14: #include "m68000.h" ! 15: #include "configuration.h" ! 16: #include "scc.h" ! 17: #include "sysReg.h" ! 18: #include "dma.h" ! 19: ! 20: #define IO_SEG_MASK 0x1FFFF ! 21: ! 22: #define LOG_SCC_LEVEL LOG_NONE ! 23: #define LOG_SCC_REG_LEVEL LOG_NONE ! 24: ! 25: ! 26: /* Registers */ ! 27: ! 28: Uint8 scc_control_read(Uint8 channel); ! 29: void scc_control_write(Uint8 channel, Uint8 val); ! 30: Uint8 scc_data_read(Uint8 channel); ! 31: void scc_data_write(Uint8 channel, Uint8 val); ! 32: ! 33: ! 34: void SCC_ControlB_Read(void) { // 0x02018000 ! 35: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = scc_control_read(1); ! 36: Log_Printf(LOG_SCC_REG_LEVEL,"[SCC] Channel B control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 37: } ! 38: ! 39: void SCC_ControlB_Write(void) { ! 40: scc_control_write(1, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]); ! 41: Log_Printf(LOG_SCC_REG_LEVEL,"[SCC] Channel B control write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 42: } ! 43: ! 44: void SCC_ControlA_Read(void) { // 0x02018001 ! 45: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = scc_control_read(0); ! 46: Log_Printf(LOG_SCC_REG_LEVEL,"[SCC] Channel A control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 47: } ! 48: ! 49: void SCC_ControlA_Write(void) { ! 50: scc_control_write(0, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]); ! 51: Log_Printf(LOG_SCC_REG_LEVEL,"[SCC] Channel A control write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 52: } ! 53: ! 54: void SCC_DataB_Read(void) { // 0x02018002 ! 55: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = scc_data_read(1); ! 56: Log_Printf(LOG_SCC_REG_LEVEL,"[SCC] Channel B data read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 57: } ! 58: ! 59: void SCC_DataB_Write(void) { ! 60: scc_data_write(1, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]); ! 61: Log_Printf(LOG_SCC_REG_LEVEL,"[SCC] Channel B data write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 62: } ! 63: ! 64: void SCC_DataA_Read(void) { // 0x02018003 ! 65: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = scc_data_read(0); ! 66: Log_Printf(LOG_SCC_REG_LEVEL,"[SCC] Channel A data read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 67: } ! 68: ! 69: void SCC_DataA_Write(void) { ! 70: scc_data_write(0, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]); ! 71: Log_Printf(LOG_SCC_REG_LEVEL,"[SCC] Channel A data write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 72: } ! 73: ! 74: ! 75: /* SCC Registers */ ! 76: ! 77: struct { ! 78: Uint8 rreg[16]; ! 79: Uint8 wreg[16]; ! 80: } scc[2]; ! 81: ! 82: Uint8 scc_register_pointer = 0; ! 83: ! 84: /* Write function prototypes */ ! 85: void scc_write_init_command(Uint8 ch, Uint8 val); ! 86: void scc_write_mode(Uint8 ch, Uint8 val); ! 87: void scc_write_master_intr_reset(Uint8 val); ! 88: ! 89: ! 90: Uint8 scc_control_read(Uint8 ch) { ! 91: Uint8 val = 0; ! 92: ! 93: switch (scc_register_pointer) { ! 94: case 0: ! 95: case 1: ! 96: case 3: ! 97: case 10: ! 98: val = scc[ch].rreg[scc_register_pointer]; ! 99: break; ! 100: ! 101: case 12: ! 102: case 13: ! 103: case 15: ! 104: val = scc[ch].wreg[scc_register_pointer]; ! 105: break; ! 106: ! 107: case 2: ! 108: val = scc[0].wreg[2]; // FIXME: different for channel B ! 109: break; ! 110: ! 111: case 8: ! 112: val = 0; // FIXME: Data Read ! 113: break; ! 114: ! 115: default: ! 116: Log_Printf(LOG_WARN, "[SCC] Invalid register (%i) read\n",scc_register_pointer); ! 117: break; ! 118: } ! 119: ! 120: Log_Printf(LOG_SCC_LEVEL,"[SCC] Channel %c: Register %i read %02X\n", ! 121: ch?'B':'A',scc_register_pointer,val); ! 122: ! 123: scc_register_pointer = 0; ! 124: ! 125: return val; ! 126: } ! 127: ! 128: void scc_control_write(Uint8 ch, Uint8 val) { ! 129: ! 130: if (scc_register_pointer==0) { ! 131: scc_register_pointer = val&7; ! 132: if ((val&0x38)==8) { ! 133: scc_register_pointer |= 8; ! 134: } ! 135: if (val&0xF0) { ! 136: scc_write_init_command(ch, val); ! 137: } ! 138: } else { ! 139: Log_Printf(LOG_SCC_LEVEL,"[SCC] Channel %c: Register %i write %02X\n", ! 140: ch?'B':'A',scc_register_pointer,val); ! 141: ! 142: switch (scc_register_pointer) { ! 143: case 1: ! 144: scc_write_mode(ch, val); ! 145: break; ! 146: case 9: ! 147: scc_write_master_intr_reset(val); ! 148: break; ! 149: case 2: ! 150: case 3: ! 151: case 4: ! 152: case 5: ! 153: case 6: ! 154: case 7: ! 155: case 8: ! 156: case 10: ! 157: case 11: ! 158: case 12: ! 159: case 13: ! 160: case 14: ! 161: case 15: ! 162: break; ! 163: ! 164: default: ! 165: Log_Printf(LOG_WARN, "[SCC] Invalid register (%i) write\n",scc_register_pointer); ! 166: break; ! 167: } ! 168: ! 169: scc_register_pointer = 0; ! 170: } ! 171: } ! 172: ! 173: Uint8 scc_data_read(Uint8 ch) { ! 174: Uint8 val = 0; ! 175: ! 176: val = scc_buf[0]; ! 177: ! 178: Log_Printf(LOG_SCC_LEVEL,"[SCC] Channel %c: Data read %02X\n", ! 179: ch?'B':'A',val); ! 180: ! 181: return val; ! 182: } ! 183: ! 184: void scc_data_write(Uint8 ch, Uint8 val) { ! 185: ! 186: scc_buf[0] = val; ! 187: ! 188: scc[ch].rreg[R_STATUS] = RR0_TXEMPTY|RR0_RXAVAIL; ! 189: ! 190: Log_Printf(LOG_SCC_LEVEL,"[SCC] Channel %c: Data write %02X\n", ! 191: ch?'B':'A',val); ! 192: } ! 193: ! 194: ! 195: /* Reset functions */ ! 196: static void scc_channel_reset(Uint8 ch, bool hard) { ! 197: ! 198: Log_Printf(LOG_SCC_LEVEL, "[SCC] Reset channel %c\n", ch?'B':'A'); ! 199: ! 200: scc[ch].wreg[0] = 0x00; ! 201: scc[ch].wreg[1] &= ~0xDB; ! 202: scc[ch].wreg[3] &= ~0x01; ! 203: scc[ch].wreg[4] |= 0x04; ! 204: scc[ch].wreg[5] &= ~0x9E; ! 205: scc[0].wreg[9] &= ~0x20; ! 206: scc[1].wreg[9] &= ~0x20; ! 207: scc[ch].wreg[10] &= ~0x9F; ! 208: scc[ch].wreg[14] = (scc[ch].wreg[14]&~0x3C)|0x20; ! 209: scc[ch].wreg[15] = 0xF8; ! 210: ! 211: scc[ch].rreg[0] = (scc[ch].rreg[0]&~0xC7)|0x44; ! 212: scc[ch].rreg[1] = 0x06; ! 213: scc[ch].rreg[3] = 0x00; ! 214: scc[ch].rreg[10] = 0x00; ! 215: ! 216: if (hard) { ! 217: scc[0].wreg[9] = (scc[0].wreg[9]&~0xFC)|0xC0; ! 218: scc[1].wreg[9] = (scc[1].wreg[9]&~0xFC)|0xC0; ! 219: scc[ch].wreg[10] = 0x00; ! 220: scc[ch].wreg[11] = 0x08; ! 221: scc[ch].wreg[14] = (scc[ch].wreg[14]&~0x3F)|0x20; ! 222: } ! 223: } ! 224: ! 225: void SCC_Reset(Uint8 ch) { ! 226: if(ch==0 || ch==1) { // channel reset ! 227: scc_channel_reset(ch, false); ! 228: } else { // hard reset ! 229: scc_channel_reset(0, true); ! 230: scc_channel_reset(1, true); ! 231: } ! 232: } ! 233: ! 234: /* Register write functions */ ! 235: ! 236: void scc_write_init_command(Uint8 ch, Uint8 val) { ! 237: ! 238: } ! 239: ! 240: void scc_write_mode(Uint8 ch, Uint8 val) { ! 241: if ((val&0xC0)==0xC0) { ! 242: dma_scc_read_memory(); ! 243: scc[ch].rreg[R_STATUS] |= RR0_RXAVAIL; ! 244: } ! 245: } ! 246: ! 247: void scc_write_master_intr_reset(Uint8 val) { ! 248: switch ((val>>6)&3) { ! 249: case 1: ! 250: SCC_Reset(1); ! 251: break; ! 252: case 2: ! 253: SCC_Reset(0); ! 254: break; ! 255: case 3: ! 256: SCC_Reset(2); ! 257: break; ! 258: ! 259: default: ! 260: break; ! 261: } ! 262: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.