Annotation of previous/src/scc.c, revision 1.1.1.1

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 (Zilog 8530) Emulation.
                      7:  
                      8:  Based on MESS source code.
                      9:  
                     10:  Port to Previous incomplete. Hacked to pass power-on test --> see SCC_Reset()
                     11:  
                     12:  */
                     13: 
                     14: #include "ioMem.h"
                     15: #include "ioMemTables.h"
                     16: #include "m68000.h"
                     17: #include "configuration.h"
                     18: #include "scc.h"
                     19: #include "sysReg.h"
                     20: #include "dma.h"
                     21: 
                     22: #define LOG_SCC_LEVEL LOG_WARN
                     23: #define IO_SEG_MASK    0x1FFFF
                     24: 
                     25: #define SCC_BUFSIZE 10  // what is actual buffer size of our controller?
                     26: 
                     27: 
                     28: /* Variables */
                     29: bool MasterIRQEnable;
                     30: int lastIRQStat;
                     31: typedef enum {
                     32:     IRQ_NONE,
                     33:     IRQ_B_TX,
                     34:     IRQ_A_TX,
                     35:     IRQ_B_EXT,
                     36:     IRQ_A_EXT
                     37: } IRQ_TYPES;
                     38: 
                     39: IRQ_TYPES IRQType;
                     40: 
                     41: typedef struct {
                     42:     Uint8 rreg[16];
                     43:     Uint8 wreg[16];
                     44:     bool txIRQEnable;
                     45:     bool txIRQPending;
                     46:     bool extIRQEnable;
                     47:     bool extIRQPending;
                     48:     bool rxIRQEnable;
                     49:     bool rxIRQPending;
                     50:     bool rxEnable;
                     51:     bool txEnable;
                     52:     bool syncHunt;
                     53:     bool txUnderrun;
                     54:     
                     55:     Uint8 rx_buf[SCC_BUFSIZE];
                     56:     Uint8 tx_buf[SCC_BUFSIZE];
                     57:     Uint32 rx_buf_size;
                     58:     Uint32 tx_buf_size;
                     59: } SCC_CHANNEL;
                     60: 
                     61: SCC_CHANNEL channel[2];
                     62: 
                     63: int IRQV;
                     64: 
                     65: bool write_reg_pointer; // true --> byte written is number of register, false --> byte gets written to register
                     66: Uint8 regnumber;
                     67: 
                     68: 
                     69: void SCC_Read(void) {
                     70:     bool data;
                     71:     Uint8 ch;
                     72:     Uint8 reg;
                     73:         
                     74:     if (IoAccessCurrentAddress&0x1)
                     75:         ch = 1; // Channel A
                     76:     else
                     77:         ch = 0; // Channel B
                     78:     
                     79:     if (IoAccessCurrentAddress&0x2)
                     80:         data = true;
                     81:     else
                     82:         data = false;
                     83:     
                     84:     if (data) {
                     85:         IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = channel[ch].rx_buf[0];
                     86:         Log_Printf(LOG_SCC_LEVEL, "SCC %c, Data read: %02x\n", ch == 1?'A':'B', channel[ch].rx_buf[0]);
                     87:     } else {
                     88:         reg = regnumber;
                     89:         IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = channel[ch].rreg[reg];
                     90:         Log_Printf(LOG_SCC_LEVEL, "SCC %c, Reg%i read: %02x\n", ch == 1?'A':'B', reg, channel[ch].rreg[reg]);
                     91:     }
                     92:     write_reg_pointer = true;
                     93: }
                     94: 
                     95: 
                     96: void SCC_Write(void) {
                     97:     bool data;
                     98:     Uint8 ch;
                     99:     Uint8 reg;
                    100:     Uint8 val;
                    101:     
                    102:     if (IoAccessCurrentAddress&0x1)
                    103:         ch = 1;
                    104:     else
                    105:         ch = 0;
                    106:     
                    107:     if (IoAccessCurrentAddress&0x2)
                    108:         data = true;
                    109:     else
                    110:         data = false;
                    111:     
                    112:     if (data) {
                    113:         channel[ch].rx_buf[0] = IoMem[IoAccessCurrentAddress&IO_SEG_MASK];
                    114:         Log_Printf(LOG_SCC_LEVEL, "SCC %c, Data write: %02x\n", ch == 1?'A':'B', channel[ch].rx_buf[0]);
                    115:         channel[ch].rreg[R_STATUS] = RR0_TXEMPTY|RR0_RXAVAIL; // Tx buffer empty | Rx Character Available
                    116:         return;
                    117:     }
                    118:     
                    119:     if (write_reg_pointer == true) {
                    120:         regnumber = IoMem[IoAccessCurrentAddress&IO_SEG_MASK];
                    121:         write_reg_pointer = false;
                    122:         return;
                    123:     } else if (write_reg_pointer == false) {
                    124:         reg = regnumber;
                    125:         val = channel[ch].wreg[reg] = IoMem[IoAccessCurrentAddress&IO_SEG_MASK];
                    126:         Log_Printf(LOG_SCC_LEVEL, "SCC %c, Reg%i write: %02x\n", ch == 1?'A':'B', reg, channel[ch].wreg[reg]);
                    127:     
                    128:         switch (reg) {
                    129:             case W_INIT:
                    130:                 switch ((val>>3) & 7) {
                    131:                     case 2: SCC_Interrupt(); break; // Reset Ext/Status Interrupts
                    132:                     case 5: channel[0].txIRQPending = false; break; // Reset pending Tx Interrupt
                    133:                     case 0: // Nothing
                    134:                     case 3: // Send SDLC abort
                    135:                     case 4: // Enable interrupt on next char Rx
                    136:                     case 6: // Error reset
                    137:                     case 7: // Reset Interrupt Under Service
                    138:                         break; // Not handled
                    139:                     default: break;
                    140:                 }
                    141:                 break;
                    142:                 
                    143:             case W_MODE: // Tx/Rx IRQ and data transfer mode definition
                    144:                 channel[ch].extIRQEnable = (val&1)?true:false; // External Interrupt Enable
                    145:                 channel[ch].txIRQEnable = (val&2)?true:false; // Transmit Interrupt Enable
                    146:                 channel[ch].rxIRQEnable = ((val&0x18)==0x18)?true:false; // Interrupt on Special only
                    147:                 SCC_Interrupt();
                    148:                 
                    149:                 if (val&0x40 && val&0x80) {
                    150:                     dma_memory_read(channel[ch].rx_buf, &channel[ch].rx_buf_size, CHANNEL_SCC);
                    151:                     channel[ch].rreg[R_STATUS] = RR0_RXAVAIL; // Rx Character Available
                    152:                 }
                    153:                 break;
                    154:                 
                    155:             case W_INTVEC: // Interrupt vector
                    156:                 IRQV = channel[ch].rreg[R_INTVEC] = val;
                    157:                 break;
                    158:                 
                    159:             case W_RECCONT: // Rx parameters and controls
                    160:                 channel[ch].rxEnable = channel[ch].wreg[reg]&1; // Rx Enable
                    161:                 channel[ch].syncHunt = (channel[ch].wreg[reg]&0x10)?true:false; // Enter Hunt Mode
                    162:                 break;
                    163:                 
                    164:             case W_TRANSCONT: // Tx parameters and controls
                    165:                 channel[ch].rxEnable = channel[ch].wreg[reg]&8;
                    166:                 if (channel[ch].txEnable)
                    167:                     channel[ch].rreg[R_STATUS] |= RR0_TXEMPTY; // Tx Empty
                    168:                 
                    169:             case W_MISCMODE:  // Tx/Rx miscellaneous parameters and modes
                    170:             case W_SYNCCHARA: // sync chars/SDLC address field
                    171:             case W_SYNCCHARF: // sync char/SDLC flag
                    172:                 break;
                    173:                 
                    174:             case W_TRANSBUF:
                    175:                 channel[ch].tx_buf[0] = val;
                    176:                 break;
                    177:                 
                    178:             case W_MASTERINT: // Master Interrupt Control
                    179:                 MasterIRQEnable = (val&8)?true:false;
                    180:                 SCC_Interrupt();
                    181:                 
                    182:                 /* Reset channels */
                    183:                 switch ((val>>6)&3) {
                    184:                     case 1: SCC_ResetChannel(0); break; // Reset Channel B
                    185:                     case 2: SCC_ResetChannel(1); break; // Reset Channel A
                    186:                     case 3: // Hardware Reset
                    187:                         SCC_Reset();
                    188:                         SCC_Interrupt();
                    189:                         break;
                    190:                     default: break;
                    191:                 }
                    192:                 break;
                    193:                 
                    194:             case W_MISCCONT: // Miscellaneous transmitter/receiver control bits
                    195:             case W_CLOCK:    // Clock mode control
                    196:             case W_BRG_LOW:  // Lower byte of baud rate generator
                    197:             case W_BRG_HIGH: // Upper byte of baud rate generator
                    198:                 break;
                    199:                 
                    200:             case W_MISC: // Miscellaneous control bits
                    201:                 if (val&0x01) // Baud rate generator enable?
                    202:                 {} // later
                    203:                 break;
                    204:                 
                    205:             case W_EXTSTAT: // later ...
                    206:                 break;
                    207:         }        
                    208:     }
                    209:     write_reg_pointer = true;
                    210: }
                    211: 
                    212: 
                    213: 
                    214: /* Functions */
                    215: 
                    216: void SCC_Interrupt(void)
                    217: {
                    218:        int irqstat;
                    219:     
                    220:        irqstat = 0;
                    221:        if (MasterIRQEnable)
                    222:        {
                    223:                if ((channel[0].txIRQEnable) && (channel[0].txIRQPending))
                    224:                {
                    225:                        IRQType = IRQ_B_TX;
                    226:                        irqstat = 1;
                    227:                }
                    228:                else if ((channel[1].txIRQEnable) && (channel[1].txIRQPending))
                    229:                {
                    230:                        IRQType = IRQ_A_TX;
                    231:                        irqstat = 1;
                    232:                }
                    233:                else if ((channel[0].extIRQEnable) && (channel[0].extIRQPending))
                    234:                {
                    235:                        IRQType = IRQ_B_EXT;
                    236:                        irqstat = 1;
                    237:                }
                    238:                else if ((channel[1].extIRQEnable) && (channel[1].extIRQPending))
                    239:                {
                    240:                        IRQType = IRQ_A_EXT;
                    241:                        irqstat = 1;
                    242:                }
                    243:        }
                    244:        else
                    245:        {
                    246:                IRQType = IRQ_NONE;
                    247:        }
                    248:     
                    249:     //  printf("SCC: irqstat %d, last %d\n", irqstat, lastIRQStat);
                    250:     //  printf("ch0: en %d pd %d  ch1: en %d pd %d\n", channel[0].txIRQEnable, channel[0].txIRQPending, channel[1].txIRQEnable, channel[1].txIRQPending);
                    251:     
                    252:        // don't spam the driver with unnecessary transitions
                    253:        if (irqstat != lastIRQStat)
                    254:        {
                    255:                lastIRQStat = irqstat;
                    256:         
                    257:                // tell the driver the new IRQ line status if possible
                    258:                Log_Printf(LOG_SCC_LEVEL, "SCC8530 IRQ status => %d\n", irqstat);
                    259: 
                    260:         if (irqstat) {
                    261:             set_interrupt(INT_SCC, SET_INT);
                    262:             Log_Printf(LOG_SCC_LEVEL, "SCC: Raise IRQ");
                    263:         }else{
                    264:             set_interrupt(INT_SCC, RELEASE_INT);
                    265:             Log_Printf(LOG_SCC_LEVEL, "SCC: Lower IRQ");
                    266:         }
                    267:         
                    268: //             if(!intrq_cb.isnull())
                    269: //                     intrq_cb(irqstat);
                    270:        }
                    271: }
                    272: 
                    273: 
                    274: void SCC_ResetChannel(int ch)
                    275: {
                    276: //     emu_timer *timersave = channel[ch].baudtimer;
                    277:     
                    278:        memset(&channel[ch], 0, sizeof(SCC_CHANNEL));
                    279:     
                    280:        channel[ch].txUnderrun = 1;
                    281: //     channel[ch].baudtimer = timersave;
                    282:     
                    283: //     channel[ch].baudtimer->adjust(attotime::never, ch);
                    284: }
                    285: 
                    286: void SCC_InitChannel(int ch)
                    287: {
                    288:        channel[ch].syncHunt = 1;
                    289: }
                    290: 
                    291: void SCC_Reset(void) {
                    292:     Log_Printf(LOG_WARN, "SCC: Device Reset (Hacked!)");
                    293:     IRQType = IRQ_NONE;
                    294:     MasterIRQEnable = false;
                    295:     IRQV = 0;
                    296:     
                    297:     SCC_InitChannel(0);
                    298:     SCC_InitChannel(1);
                    299:     SCC_ResetChannel(0);
                    300:     SCC_ResetChannel(1);
                    301:     
                    302:     write_reg_pointer = true;
                    303:     regnumber = 0;
                    304:     
                    305:     /*--- Hack to pass power-on test ---*/
                    306:     channel[0].rreg[R_STATUS] = 0xFF;
                    307:     channel[1].rreg[R_STATUS] = 0xFF;
                    308: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.