| /* 3b2_cpu.h: AT&T 3B2 Model 400 IO dispatch implemenation | |
| Copyright (c) 2017, Seth J. Morabito | |
| Permission is hereby granted, free of charge, to any person | |
| obtaining a copy of this software and associated documentation | |
| files (the "Software"), to deal in the Software without | |
| restriction, including without limitation the rights to use, copy, | |
| modify, merge, publish, distribute, sublicense, and/or sell copies | |
| of the Software, and to permit persons to whom the Software is | |
| furnished to do so, subject to the following conditions: | |
| The above copyright notice and this permission notice shall be | |
| included in all copies or substantial portions of the Software. | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
| BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
| ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| SOFTWARE. | |
| Except as contained in this notice, the name of the author shall | |
| not be used in advertising or otherwise to promote the sale, use or | |
| other dealings in this Software without prior written authorization | |
| from the author. | |
| */ | |
| #include "3b2_io.h" | |
| struct iolink iotable[] = { | |
| { MMUBASE, MMUBASE+MMUSIZE, &mmu_read, &mmu_write }, | |
| { IFBASE, IFBASE+IFSIZE, &if_read, &if_write }, | |
| { IDBASE, IDBASE+IDSIZE, &id_read, &id_write }, | |
| { TIMERBASE, TIMERBASE+TIMERSIZE, &timer_read, &timer_write }, | |
| { NVRAMBASE, NVRAMBASE+NVRAMSIZE, &nvram_read, &nvram_write }, | |
| { CSRBASE, CSRBASE+CSRSIZE, &csr_read, &csr_write }, | |
| { IUBASE, IUBASE+IUSIZE, &iu_read, &iu_write }, | |
| { DMAIDBASE, DMAIDBASE+DMAIDSIZE, &dmac_read, &dmac_write }, | |
| { DMAIUABASE, DMAIUABASE+DMAIUASIZE, &dmac_read, &dmac_write }, | |
| { DMAIUBBASE, DMAIUBBASE+DMAIUBSIZE, &dmac_read, &dmac_write }, | |
| { DMACBASE, DMACBASE+DMACSIZE, &dmac_read, &dmac_write }, | |
| { DMAIFBASE, DMAIFBASE+DMAIFSIZE, &dmac_read, &dmac_write }, | |
| { TODBASE, TODBASE+TODSIZE, &tod_read, &tod_write }, | |
| { 0, 0, NULL, NULL} | |
| }; | |
| uint32 io_read(uint32 pa, size_t size) | |
| { | |
| struct iolink *p; | |
| /* Special devices */ | |
| if (pa == 0x4c003) { | |
| /* MEMSIZE register */ | |
| /* It appears that the following values map to memory sizes: | |
| 0x00: 512KB ( 524,288 B) | |
| 0x01: 2MB (2,097,152 B) | |
| 0x02: 1MB (1,048,576 B) | |
| 0x03: 4MB (4,194,304 B) | |
| */ | |
| switch(MEM_SIZE) { | |
| case 0x80000: /* 512KB */ | |
| return 0; | |
| case 0x100000: /* 1MB */ | |
| return 2; | |
| case 0x200000: /* 2MB */ | |
| return 1; | |
| case 0x400000: /* 4MB */ | |
| return 3; | |
| default: | |
| return 0; | |
| } | |
| } | |
| /* IO Board Area - Unimplemented */ | |
| if (pa >= 0x200000 && pa < 0x2000000) { | |
| sim_debug(IO_D_MSG, &cpu_dev, "[%08x] [IO BOARD READ] ADDR=%08x\n", R[NUM_PC], pa); | |
| /* When we implement boards, register them here | |
| N.B.: High byte of board ID is read at 0xnnnnn0, | |
| low byte at 0xnnnnn1 */ | |
| /* Since we have no cards in our system, there's nothing | |
| to read. We indicate that our bus read timed out with | |
| CSRTIMO, then abort.*/ | |
| csr_data |= CSRTIMO; | |
| cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); | |
| return 0; | |
| } | |
| for (p = &iotable[0]; p->low != 0; p++) { | |
| if ((pa >= p->low) && (pa < p->high) && p->read) { | |
| return p->read(pa, size); | |
| } | |
| } | |
| /* Not found. */ | |
| sim_debug(IO_D_MSG, &cpu_dev, | |
| "[%08x] [io_read] ADDR=%08x: No device found.\n", | |
| R[NUM_PC], pa); | |
| csr_data |= CSRTIMO; | |
| cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); | |
| return 0; | |
| } | |
| void io_write(uint32 pa, uint32 val, size_t size) | |
| { | |
| struct iolink *p; | |
| /* IO Board Area - Unimplemented */ | |
| if (pa >= 0x200000 && pa < 0x2000000) { | |
| sim_debug(IO_D_MSG, &cpu_dev, | |
| "[%08x] ADDR=%08x, DATA=%08x\n", | |
| R[NUM_PC], pa, val); | |
| csr_data |= CSRTIMO; | |
| cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); | |
| return; | |
| } | |
| for (p = &iotable[0]; p->low != 0; p++) { | |
| if ((pa >= p->low) && (pa < p->high) && p->write) { | |
| p->write(pa, val, size); | |
| return; | |
| } | |
| } | |
| /* Not found. */ | |
| sim_debug(IO_D_MSG, &cpu_dev, | |
| "[%08x] [io_write] ADDR=%08x: No device found.\n", | |
| R[NUM_PC], pa); | |
| csr_data |= CSRTIMO; | |
| cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); | |
| } |