| /* sage_stddev.c: Standard devices for sage-II system | |
| Copyright (c) 2009-2010 Holger Veit | |
| 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 | |
| Holger Veit 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 Holger Veit et al shall not be | |
| used in advertising or otherwise to promote the sale, use or other dealings | |
| in this Software without prior written authorization from Holger Veit et al. | |
| 22-Jan-10 HV Initial version | |
| */ | |
| #include "sim_defs.h" | |
| #include "m68k_cpu.h" | |
| #include "chip_defs.h" | |
| static int i8251_bitmask[] = { 0x1f, 0x3f, 0x7f, 0xff }; | |
| /* Debug Flags */ | |
| DEBTAB i8251_dt[] = { | |
| { "READ", DBG_UART_RD }, | |
| { "WRITE", DBG_UART_WR }, | |
| { "IRQ", DBG_UART_IRQ }, | |
| { NULL, 0 } | |
| }; | |
| t_stat i8251_io(IOHANDLER* ioh,uint32* value,uint32 rw,uint32 mask) | |
| { | |
| int port = ioh->offset; | |
| I8251* chip = (I8251*)ioh->ctxt; | |
| if (rw==MEM_WRITE) { | |
| return chip->write ? chip->write(chip,port,*value) : i8251_write(chip,port,*value); | |
| } else { | |
| return chip->read ? chip->read(chip,port,value) : i8251_read(chip,port,value); | |
| } | |
| } | |
| t_stat i8251_write(I8251* chip,int port,uint32 value) | |
| { | |
| int bits; | |
| if (port==0) { /* data port */ | |
| chip->obuf = value & chip->bitmask; | |
| TRACE_PRINT1(DBG_UART_WR,"WR DATA = 0x%02x",chip->obuf); | |
| if (chip->init==3) { /* is fully initialized */ | |
| if ((chip->mode & I8251_MODE_BAUD)==I8251_MODE_SYNC) { | |
| sim_printf("i8251: sync mode not implemented\n"); | |
| return STOP_IMPL; | |
| } | |
| if (chip->cmd & I8251_CMD_TXEN) { | |
| /* transmit data */ | |
| chip->status &= ~(I8251_ST_TXEMPTY|I8251_ST_TXRDY); | |
| sim_activate(chip->out,chip->out->wait); | |
| } | |
| } | |
| return SCPE_OK; | |
| } else { /* control port */ | |
| switch (chip->init) { | |
| case 0: /* expect mode word */ | |
| chip->mode = value; | |
| TRACE_PRINT1(DBG_UART_WR,"WR MODE = 0x%02x",value); | |
| chip->init = (value & I8251_MODE_BAUD)==I8251_MODE_SYNC ? 1 : 3; | |
| bits = (chip->mode & I8251_AMODE_BITS) >> 2; | |
| chip->bitmask = i8251_bitmask[bits]; | |
| break; | |
| case 1: /* expect sync1 */ | |
| chip->sync1 = value; | |
| TRACE_PRINT1(DBG_UART_WR,"WR SYNC1 = 0x%02x",value); | |
| chip->init = 2; | |
| break; | |
| case 2: /* expect sync2 */ | |
| chip->sync2 = value; | |
| TRACE_PRINT1(DBG_UART_WR,"WR SYNC2 = 0x%02x",value); | |
| chip->init = 3; | |
| break; | |
| case 3: /* expect cmd word */ | |
| chip->cmd = value; | |
| TRACE_PRINT1(DBG_UART_WR,"WR CMD = 0x%02x",value); | |
| if (value & I8251_CMD_EH) { | |
| sim_printf("i8251: hunt mode not implemented\n"); | |
| return STOP_IMPL; | |
| } | |
| if (value & I8251_CMD_IR) | |
| chip->init = 0; | |
| if (value & I8251_CMD_ER) | |
| chip->status &= ~(I8251_ST_FE|I8251_ST_OE|I8251_ST_PE); | |
| if (value & I8251_CMD_SBRK) | |
| sim_printf("i8251: BREAK sent\n"); | |
| if (value & I8251_CMD_RXE) { | |
| sim_activate(chip->in,chip->in->wait); | |
| } else { | |
| if (!chip->oob) sim_cancel(chip->in); | |
| } | |
| if (value & I8251_CMD_TXEN) { | |
| if (!(chip->status & I8251_ST_TXEMPTY)) | |
| sim_activate(chip->out,chip->out->wait); | |
| else { | |
| chip->status |= I8251_ST_TXRDY; | |
| if (chip->txint) chip->txint(chip); | |
| } | |
| } else { | |
| chip->status &= ~I8251_ST_TXRDY; | |
| sim_cancel(chip->out); | |
| } | |
| } | |
| return SCPE_OK; | |
| } | |
| } | |
| t_stat i8251_read(I8251* chip,int port,uint32* value) | |
| { | |
| if (port==0) { /* data read */ | |
| *value = chip->ibuf; | |
| chip->status &= ~I8251_ST_RXRDY; /* mark read buffer as empty */ | |
| TRACE_PRINT1(DBG_UART_RD,"RD DATA = 0x%02x",*value); | |
| } else { /* status read */ | |
| *value = chip->status & 0xff; | |
| TRACE_PRINT1(DBG_UART_RD,"RD STATUS = 0x%02x",*value); | |
| } | |
| return SCPE_OK; | |
| } | |
| t_stat i8251_reset(I8251* chip) | |
| { | |
| chip->init = 0; | |
| chip->oob = FALSE; | |
| chip->crlf = 0; | |
| return SCPE_OK; | |
| } |