Annotation of previous/src/scc.c, revision 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.