Annotation of previous_trunk/src/dma.c, revision 1.1

1.1     ! root        1: /* NeXT DMA Emulation 
        !             2:  * Contains informations from QEMU-NeXT
        !             3:  * NeXT Integrated Channel Processor (ISP) consists of 12 channel processors
        !             4:  * with 128 bytes internal buffer for each channel.
        !             5:  * 12 channels:
        !             6:  * SCSI, Sound in, Sound out, Optical disk, Printer, SCC, DSP, 
        !             7:  * Ethernet transmit, Ethernet receive, Video, Memory to register, Register to memory
        !             8:  */
        !             9: 
        !            10: #include "ioMem.h"
        !            11: #include "ioMemTables.h"
        !            12: #include "m68000.h"
        !            13: #include "scsi.h"
        !            14: #include "esp.h"
        !            15: #include "mo.h"
        !            16: #include "scc.h"
        !            17: #include "sysReg.h"
        !            18: #include "dma.h"
        !            19: #include "configuration.h"
        !            20: #include "ethernet.h"
        !            21: #include "floppy.h"
        !            22: #include "printer.h"
        !            23: #include "snd.h"
        !            24: #include "dsp.h"
        !            25: #include "mmu_common.h"
        !            26: #include "kms.h"
        !            27: #include "audio.h"
        !            28: 
        !            29: #define LOG_DMA_LEVEL LOG_DEBUG
        !            30: 
        !            31: #define IO_SEG_MASK    0x1FFFF
        !            32: 
        !            33: 
        !            34: int get_channel(Uint32 address);
        !            35: int get_interrupt_type(int channel);
        !            36: void dma_interrupt(int channel);
        !            37: void dma_initialize_buffer(int channel, Uint8 offset);
        !            38: 
        !            39: 
        !            40: struct {
        !            41:     Uint8 csr;
        !            42:     Uint32 saved_next;
        !            43:     Uint32 saved_limit;
        !            44:     Uint32 saved_start;
        !            45:     Uint32 saved_stop;
        !            46:     Uint32 next;
        !            47:     Uint32 limit;
        !            48:     Uint32 start;
        !            49:     Uint32 stop;
        !            50:     
        !            51:     Uint8 direction;
        !            52: } dma[12];
        !            53: 
        !            54: 
        !            55: /* DMA internal buffers */
        !            56: #define DMA_BURST_SIZE  16
        !            57: 
        !            58: int espdma_buf_size = 0;
        !            59: int espdma_buf_limit = 0;
        !            60: Uint8 espdma_buf[DMA_BURST_SIZE];
        !            61: int modma_buf_size = 0;
        !            62: int modma_buf_limit = 0;
        !            63: Uint8 modma_buf[DMA_BURST_SIZE];
        !            64: 
        !            65: 
        !            66: /* Read and write CSR bits for 68030 based NeXT Computer. */
        !            67: 
        !            68: /* read CSR bits */
        !            69: #define DMA_ENABLE      0x01   /* enable dma transfer */
        !            70: #define DMA_SUPDATE     0x02   /* single update */
        !            71: #define DMA_COMPLETE    0x08   /* current dma has completed */
        !            72: #define DMA_BUSEXC      0x10   /* bus exception occurred */
        !            73: /* write CSR bits */
        !            74: #define DMA_SETENABLE   0x01   /* set enable */
        !            75: #define DMA_SETSUPDATE  0x02   /* set single update */
        !            76: #define DMA_M2DEV       0x00   /* dma from mem to dev */
        !            77: #define DMA_DEV2M       0x04   /* dma from dev to mem */
        !            78: #define DMA_CLRCOMPLETE 0x08   /* clear complete conditional */
        !            79: #define DMA_RESET       0x10   /* clr cmplt, sup, enable */
        !            80: #define DMA_INITBUF     0x20   /* initialize DMA buffers */
        !            81: 
        !            82: /* CSR masks */
        !            83: #define DMA_CMD_MASK    (DMA_SETENABLE|DMA_SETSUPDATE|DMA_CLRCOMPLETE|DMA_RESET|DMA_INITBUF)
        !            84: #define DMA_STAT_MASK   (DMA_ENABLE|DMA_SUPDATE|DMA_COMPLETE|DMA_BUSEXC)
        !            85: 
        !            86: 
        !            87: /* Read and write CSR bits for 68040 based Machines.
        !            88:  * We convert these to 68030 values before using in functions.
        !            89:  * read CSR bits *
        !            90:  #define DMA_ENABLE      0x01000000
        !            91:  #define DMA_SUPDATE     0x02000000
        !            92:  #define DMA_COMPLETE    0x08000000
        !            93:  #define DMA_BUSEXC      0x10000000
        !            94:  * write CSR bits *
        !            95:  #define DMA_SETENABLE   0x00010000
        !            96:  #define DMA_SETSUPDATE  0x00020000
        !            97:  #define DMA_M2DEV       0x00000000
        !            98:  #define DMA_DEV2M       0x00040000
        !            99:  #define DMA_CLRCOMPLETE 0x00080000
        !           100:  #define DMA_RESET       0x00100000
        !           101:  #define DMA_INITBUF     0x00200000
        !           102:  */
        !           103: 
        !           104: 
        !           105: 
        !           106: static inline Uint32 dma_getlong(Uint8 *buf, Uint32 pos) {
        !           107:        return (buf[pos] << 24) | (buf[pos+1] << 16) | (buf[pos+2] << 8) | buf[pos+3];
        !           108: }
        !           109: 
        !           110: static inline void dma_putlong(Uint32 val, Uint8 *buf, Uint32 pos) {
        !           111:        buf[pos] = val >> 24;
        !           112:        buf[pos+1] = val >> 16;
        !           113:        buf[pos+2] = val >> 8;
        !           114:        buf[pos+3] = val;
        !           115: }
        !           116: 
        !           117: 
        !           118: int get_channel(Uint32 address) {
        !           119:     int channel = address&IO_SEG_MASK;
        !           120: 
        !           121:     switch (channel) {
        !           122:         case 0x010: Log_Printf(LOG_DMA_LEVEL,"channel SCSI:"); return CHANNEL_SCSI; break;
        !           123:         case 0x040: Log_Printf(LOG_DMA_LEVEL,"channel Sound Out:"); return CHANNEL_SOUNDOUT; break;
        !           124:         case 0x050: Log_Printf(LOG_DMA_LEVEL,"channel MO Disk:"); return CHANNEL_DISK; break;
        !           125:         case 0x080: Log_Printf(LOG_DMA_LEVEL,"channel Sound in:"); return CHANNEL_SOUNDIN; break;
        !           126:         case 0x090: Log_Printf(LOG_DMA_LEVEL,"channel Printer:"); return CHANNEL_PRINTER; break;
        !           127:         case 0x0c0: Log_Printf(LOG_DMA_LEVEL,"channel SCC:"); return CHANNEL_SCC; break;
        !           128:         case 0x0d0: Log_Printf(LOG_DMA_LEVEL,"channel DSP:"); return CHANNEL_DSP; break;
        !           129:         case 0x110: Log_Printf(LOG_DMA_LEVEL,"channel Ethernet Tx:"); return CHANNEL_EN_TX; break;
        !           130:         case 0x150: Log_Printf(LOG_DMA_LEVEL,"channel Ethernet Rx:"); return CHANNEL_EN_RX; break;
        !           131:         case 0x180: Log_Printf(LOG_DMA_LEVEL,"channel Video:"); return CHANNEL_VIDEO; break;
        !           132:         case 0x1d0: Log_Printf(LOG_DMA_LEVEL,"channel M2R:"); return CHANNEL_M2R; break;
        !           133:         case 0x1c0: Log_Printf(LOG_DMA_LEVEL,"channel R2M:"); return CHANNEL_R2M; break;
        !           134:             
        !           135:         default:
        !           136:             Log_Printf(LOG_WARN, "Unknown DMA channel!\n");
        !           137:             return -1;
        !           138:             break;
        !           139:     }
        !           140: }
        !           141: 
        !           142: int get_interrupt_type(int channel) {
        !           143:     switch (channel) {
        !           144:         case CHANNEL_SCSI: return INT_SCSI_DMA; break;
        !           145:         case CHANNEL_SOUNDOUT: return INT_SND_OUT_DMA; break;
        !           146:         case CHANNEL_DISK: return INT_DISK_DMA; break;
        !           147:         case CHANNEL_SOUNDIN: return INT_SND_IN_DMA; break;
        !           148:         case CHANNEL_PRINTER: return INT_PRINTER_DMA; break;
        !           149:         case CHANNEL_SCC: return INT_SCC_DMA; break;
        !           150:         case CHANNEL_DSP: return INT_DSP_DMA; break;
        !           151:         case CHANNEL_EN_TX: return INT_EN_TX_DMA; break;
        !           152:         case CHANNEL_EN_RX: return INT_EN_RX_DMA; break;
        !           153:         case CHANNEL_VIDEO: return INT_VIDEO; break;
        !           154:         case CHANNEL_M2R: return INT_M2R_DMA; break;
        !           155:         case CHANNEL_R2M: return INT_R2M_DMA; break;
        !           156:                         
        !           157:         default:
        !           158:             Log_Printf(LOG_WARN, "Unknown DMA interrupt!\n");
        !           159:             return 0;
        !           160:             break;
        !           161:     }
        !           162: }
        !           163: 
        !           164: void DMA_CSR_Read(void) { // 0x02000010, length of register is byte on 68030 based NeXT Computer
        !           165:     int channel = get_channel(IoAccessCurrentAddress);
        !           166:     
        !           167:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dma[channel].csr;
        !           168:     IoMem[(IoAccessCurrentAddress+1) & IO_SEG_MASK] = IoMem[(IoAccessCurrentAddress+2) & IO_SEG_MASK] = IoMem[(IoAccessCurrentAddress+3) & IO_SEG_MASK] = 0x00; // just to be sure
        !           169:     Log_Printf(LOG_DMA_LEVEL,"DMA CSR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].csr, m68k_getpc());
        !           170: }
        !           171: 
        !           172: void DMA_CSR_Write(void) {
        !           173:     int channel = get_channel(IoAccessCurrentAddress);
        !           174:     int interrupt = get_interrupt_type(channel);
        !           175:     Uint8 writecsr = IoMem[IoAccessCurrentAddress & IO_SEG_MASK]|IoMem[(IoAccessCurrentAddress+1) & IO_SEG_MASK]|IoMem[(IoAccessCurrentAddress+2) & IO_SEG_MASK]|IoMem[(IoAccessCurrentAddress+3) & IO_SEG_MASK];
        !           176: 
        !           177:     Log_Printf(LOG_DMA_LEVEL,"DMA CSR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, writecsr, m68k_getpc());
        !           178:     
        !           179:     /* For debugging */
        !           180:     if(writecsr&DMA_DEV2M)
        !           181:         Log_Printf(LOG_DMA_LEVEL,"DMA from dev to mem");
        !           182:     else
        !           183:         Log_Printf(LOG_DMA_LEVEL,"DMA from mem to dev");
        !           184:     
        !           185:     switch (writecsr&DMA_CMD_MASK) {
        !           186:         case DMA_RESET:
        !           187:             Log_Printf(LOG_DMA_LEVEL,"DMA reset"); break;
        !           188:         case DMA_INITBUF:
        !           189:             Log_Printf(LOG_DMA_LEVEL,"DMA initialize buffers"); break;
        !           190:         case (DMA_RESET | DMA_INITBUF):
        !           191:         case (DMA_RESET | DMA_INITBUF | DMA_CLRCOMPLETE):
        !           192:             Log_Printf(LOG_DMA_LEVEL,"DMA reset and initialize buffers"); break;
        !           193:         case DMA_CLRCOMPLETE:
        !           194:             Log_Printf(LOG_DMA_LEVEL,"DMA end chaining"); break;
        !           195:         case (DMA_SETSUPDATE | DMA_CLRCOMPLETE):
        !           196:             Log_Printf(LOG_DMA_LEVEL,"DMA continue chaining"); break;
        !           197:         case DMA_SETENABLE:
        !           198:             Log_Printf(LOG_DMA_LEVEL,"DMA start single transfer"); break;
        !           199:         case (DMA_SETENABLE | DMA_SETSUPDATE):
        !           200:         case (DMA_SETENABLE | DMA_SETSUPDATE | DMA_CLRCOMPLETE):
        !           201:             Log_Printf(LOG_DMA_LEVEL,"DMA start chaining"); break;
        !           202:         case 0:
        !           203:             Log_Printf(LOG_DMA_LEVEL,"DMA no command"); break;
        !           204:         default:
        !           205:             Log_Printf(LOG_DMA_LEVEL,"DMA: unknown command!"); break;
        !           206:     }
        !           207: 
        !           208:     /* Handle CSR bits */
        !           209:     dma[channel].direction = writecsr&DMA_DEV2M;
        !           210: 
        !           211:     if (writecsr&DMA_RESET) {
        !           212:         dma[channel].csr &= ~(DMA_COMPLETE | DMA_SUPDATE | DMA_ENABLE);
        !           213:     }
        !           214:     if (writecsr&DMA_INITBUF) {
        !           215:         dma_initialize_buffer(channel, 0);
        !           216:     }
        !           217:     if (writecsr&DMA_SETSUPDATE) {
        !           218:         dma[channel].csr |= DMA_SUPDATE;
        !           219:     }
        !           220:     if (writecsr&DMA_SETENABLE) {
        !           221:         dma[channel].csr |= DMA_ENABLE;
        !           222:         
        !           223:         /* Enable Memory to Memory DMA, if read and write channels are enabled */
        !           224:         if (channel == CHANNEL_R2M || channel == CHANNEL_M2R) {
        !           225:             if (dma[channel].next==dma[channel].limit) {
        !           226:                 dma[channel].csr &= ~DMA_ENABLE;
        !           227:             }
        !           228:             dma_m2m();
        !           229:         }
        !           230:     }
        !           231:     if (writecsr&DMA_CLRCOMPLETE) {
        !           232:         dma[channel].csr &= ~DMA_COMPLETE;
        !           233:     }
        !           234: 
        !           235:     set_interrupt(interrupt, RELEASE_INT); // experimental
        !           236: }
        !           237: 
        !           238: void DMA_Saved_Next_Read(void) { // 0x02004000
        !           239:     int channel = get_channel(IoAccessCurrentAddress-0x3FF0);
        !           240:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].saved_next);
        !           241:        Log_Printf(LOG_DMA_LEVEL,"DMA SNext read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].saved_next, m68k_getpc());
        !           242: }
        !           243: 
        !           244: void DMA_Saved_Next_Write(void) {
        !           245:     int channel = get_channel(IoAccessCurrentAddress-0x3FF0);
        !           246:     dma[channel].saved_next = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           247:     Log_Printf(LOG_DMA_LEVEL,"DMA SNext write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].saved_next, m68k_getpc());
        !           248: }
        !           249: 
        !           250: void DMA_Saved_Limit_Read(void) { // 0x02004004
        !           251:     int channel = get_channel(IoAccessCurrentAddress-0x3FF4);
        !           252:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].saved_limit);
        !           253:        Log_Printf(LOG_DMA_LEVEL,"DMA SLimit read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].saved_limit, m68k_getpc());
        !           254: }
        !           255: 
        !           256: void DMA_Saved_Limit_Write(void) {
        !           257:     int channel = get_channel(IoAccessCurrentAddress-0x3FF4);
        !           258:     dma[channel].saved_limit = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           259:     Log_Printf(LOG_DMA_LEVEL,"DMA SLimit write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].saved_limit, m68k_getpc());
        !           260: }
        !           261: 
        !           262: void DMA_Saved_Start_Read(void) { // 0x02004008
        !           263:     int channel = get_channel(IoAccessCurrentAddress-0x3FF8);
        !           264:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].saved_start);
        !           265:        Log_Printf(LOG_DMA_LEVEL,"DMA SStart read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].saved_start, m68k_getpc());
        !           266: }
        !           267: 
        !           268: void DMA_Saved_Start_Write(void) {
        !           269:     int channel = get_channel(IoAccessCurrentAddress-0x3FF8);
        !           270:     dma[channel].saved_start = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           271:     Log_Printf(LOG_DMA_LEVEL,"DMA SStart write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].saved_start, m68k_getpc());
        !           272: }
        !           273: 
        !           274: void DMA_Saved_Stop_Read(void) { // 0x0200400c
        !           275:     int channel = get_channel(IoAccessCurrentAddress-0x3FFC);
        !           276:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].saved_stop);
        !           277:        Log_Printf(LOG_DMA_LEVEL,"DMA SStop read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].saved_stop, m68k_getpc());
        !           278: }
        !           279: 
        !           280: void DMA_Saved_Stop_Write(void) {
        !           281:     int channel = get_channel(IoAccessCurrentAddress-0x3FFC);
        !           282:     dma[channel].saved_stop = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           283:     Log_Printf(LOG_DMA_LEVEL,"DMA SStop write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].saved_stop, m68k_getpc());
        !           284: }
        !           285: 
        !           286: void DMA_Next_Read(void) { // 0x02004010
        !           287:     int channel = get_channel(IoAccessCurrentAddress-0x4000);
        !           288:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].next);
        !           289:        Log_Printf(LOG_DMA_LEVEL,"DMA Next read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].next, m68k_getpc());
        !           290: }
        !           291: 
        !           292: void DMA_Next_Write(void) {
        !           293:     int channel = get_channel(IoAccessCurrentAddress-0x4000);
        !           294:     dma[channel].next = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           295:     Log_Printf(LOG_DMA_LEVEL,"DMA Next write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].next, m68k_getpc());
        !           296: }
        !           297: 
        !           298: void DMA_Limit_Read(void) { // 0x02004014
        !           299:     int channel = get_channel(IoAccessCurrentAddress-0x4004);
        !           300:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].limit);
        !           301:        Log_Printf(LOG_DMA_LEVEL,"DMA Limit read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].limit, m68k_getpc());
        !           302: }
        !           303: 
        !           304: void DMA_Limit_Write(void) {
        !           305:     int channel = get_channel(IoAccessCurrentAddress-0x4004);
        !           306:     dma[channel].limit = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           307:     Log_Printf(LOG_DMA_LEVEL,"DMA Limit write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].limit, m68k_getpc());
        !           308: }
        !           309: 
        !           310: void DMA_Start_Read(void) { // 0x02004018
        !           311:     int channel = get_channel(IoAccessCurrentAddress-0x4008);
        !           312:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].start);
        !           313:        Log_Printf(LOG_DMA_LEVEL,"DMA Start read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].start, m68k_getpc());
        !           314: }
        !           315: 
        !           316: void DMA_Start_Write(void) {
        !           317:     int channel = get_channel(IoAccessCurrentAddress-0x4008);
        !           318:     dma[channel].start = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           319:     Log_Printf(LOG_DMA_LEVEL,"DMA Start write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].start, m68k_getpc());
        !           320: }
        !           321: 
        !           322: void DMA_Stop_Read(void) { // 0x0200401c
        !           323:     int channel = get_channel(IoAccessCurrentAddress-0x400C);
        !           324:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].stop);
        !           325:        Log_Printf(LOG_DMA_LEVEL,"DMA Stop read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].stop, m68k_getpc());
        !           326: }
        !           327: 
        !           328: void DMA_Stop_Write(void) {
        !           329:     int channel = get_channel(IoAccessCurrentAddress-0x400C);
        !           330:     dma[channel].stop = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           331:     Log_Printf(LOG_DMA_LEVEL,"DMA Stop write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].stop, m68k_getpc());
        !           332: }
        !           333: 
        !           334: void DMA_Init_Read(void) { // 0x02004210
        !           335:     int channel = get_channel(IoAccessCurrentAddress-0x4200);
        !           336:     IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].next);
        !           337:        Log_Printf(LOG_DMA_LEVEL,"DMA Init read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].next, m68k_getpc());
        !           338: }
        !           339: 
        !           340: void DMA_Init_Write(void) {
        !           341:     int channel = get_channel(IoAccessCurrentAddress-0x4200);
        !           342:     dma[channel].next = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !           343:     dma_initialize_buffer(channel, dma[channel].next&0xF);
        !           344:     Log_Printf(LOG_DMA_LEVEL,"DMA Init write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].next, m68k_getpc());
        !           345: }
        !           346: 
        !           347: /* Initialize DMA internal buffer */
        !           348: 
        !           349: void dma_initialize_buffer(int channel, Uint8 offset) {
        !           350:     if (offset>0) {
        !           351:         Log_Printf(LOG_WARN, "DMA Initializing buffer with offset %i", offset);
        !           352:     }
        !           353:     switch (channel) {
        !           354:         case CHANNEL_SCSI:
        !           355:             esp_dma.status = 0x00; /* just a guess */
        !           356:             espdma_buf_size = 0;
        !           357:             espdma_buf_limit = offset;
        !           358:             break;
        !           359:         case CHANNEL_DISK:
        !           360:             modma_buf_size = 0;
        !           361:             modma_buf_limit = offset;
        !           362:             break;
        !           363:         default:
        !           364:             break;
        !           365:     }
        !           366: }
        !           367: 
        !           368: /* DMA interrupt functions */
        !           369: 
        !           370: void dma_interrupt(int channel) {
        !           371:     int interrupt = get_interrupt_type(channel);
        !           372: 
        !           373:     /* If we have reached limit, generate an interrupt and set the flags */
        !           374:     if (dma[channel].next==dma[channel].limit) {
        !           375:         
        !           376:         dma[channel].csr |= DMA_COMPLETE;
        !           377:         
        !           378:         if (dma[channel].csr & DMA_SUPDATE) { /* if we are in chaining mode */
        !           379:             dma[channel].next = dma[channel].start;
        !           380:             dma[channel].limit = dma[channel].stop;
        !           381:             /* Set bits in CSR */
        !           382:             dma[channel].csr &= ~DMA_SUPDATE; /* 1st done */
        !           383:         } else {
        !           384:             dma[channel].csr &= ~DMA_ENABLE; /* all done */
        !           385:         }
        !           386:         set_interrupt(interrupt, SET_INT);
        !           387:     } else if (dma[channel].csr&DMA_BUSEXC) {
        !           388:         set_interrupt(interrupt, SET_INT);
        !           389:     }
        !           390: }
        !           391: 
        !           392: 
        !           393: /* DMA Read and Write Memory Functions */
        !           394: 
        !           395: /* Channel SCSI (shared with floppy drive) */
        !           396: void dma_esp_write_memory(void) {
        !           397:     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Write to memory at $%08x, %i bytes (ESP counter %i)",
        !           398:                dma[CHANNEL_SCSI].next,dma[CHANNEL_SCSI].limit-dma[CHANNEL_SCSI].next,esp_counter);
        !           399:     
        !           400:     if (!(dma[CHANNEL_SCSI].csr&DMA_ENABLE)) {
        !           401:         Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Error! DMA not enabled!");
        !           402:         return;
        !           403:     }
        !           404:     if ((dma[CHANNEL_SCSI].limit%DMA_BURST_SIZE) || (dma[CHANNEL_SCSI].next%4)) {
        !           405:         Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Error! Bad alignment! (Next: $%08X, Limit: $%08X)",
        !           406:                    dma[CHANNEL_SCSI].next, dma[CHANNEL_SCSI].limit);
        !           407:         abort();
        !           408:     }
        !           409: 
        !           410:     TRY(prb) {
        !           411:         if (espdma_buf_size>0) {
        !           412:             Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Starting with %i residual bytes in DMA buffer.", espdma_buf_size);
        !           413:         }
        !           414: 
        !           415:         while (dma[CHANNEL_SCSI].next<=dma[CHANNEL_SCSI].limit) {
        !           416:             /* Fill DMA channel FIFO (only if limit < FIFO size) */
        !           417:             if (espdma_buf_limit<DMA_BURST_SIZE) {
        !           418:                 if (floppy_select) {
        !           419:                     while (espdma_buf_limit<DMA_BURST_SIZE && flp_buffer.size>0) {
        !           420:                         espdma_buf[espdma_buf_limit]=flp_buffer.data[flp_buffer.limit-flp_buffer.size];
        !           421:                         flp_buffer.size--;
        !           422:                         espdma_buf_limit++;
        !           423:                         espdma_buf_size++;
        !           424:                     }
        !           425:                 } else {
        !           426:                     while (espdma_buf_limit<DMA_BURST_SIZE && esp_counter>0 && SCSIbus.phase==PHASE_DI) {
        !           427:                         espdma_buf[espdma_buf_limit]=SCSIdisk_Send_Data();
        !           428:                         esp_counter--;
        !           429:                         espdma_buf_limit++;
        !           430:                         espdma_buf_size++;
        !           431:                     }
        !           432:                 }
        !           433:             }
        !           434:             
        !           435:             if (espdma_buf_limit<DMA_BURST_SIZE) { /* Not complete, stop */
        !           436:                 Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: No more data. Stopping with %i residual bytes.",
        !           437:                            espdma_buf_size);
        !           438:                 break;
        !           439:             } else { /* Empty DMA channel FIFO (only if limit reached FIFO size) */
        !           440:                 ESP_DMA_set_status();
        !           441: 
        !           442:                 while (dma[CHANNEL_SCSI].next<dma[CHANNEL_SCSI].limit && espdma_buf_size>0) {
        !           443:                     NEXTMemory_WriteLong(dma[CHANNEL_SCSI].next, dma_getlong(espdma_buf, DMA_BURST_SIZE-espdma_buf_size));
        !           444:                     dma[CHANNEL_SCSI].next+=4;
        !           445:                     espdma_buf_size-=4;
        !           446:                 }
        !           447:                 if (espdma_buf_size>0) { /* Not complete, stop */
        !           448:                     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Channel limit reached. Stopping with %i residual bytes.",
        !           449:                                espdma_buf_size);
        !           450:                     break;
        !           451:                 }
        !           452:                 espdma_buf_limit = espdma_buf_size; /* Should be 0 */
        !           453:             }
        !           454:         }
        !           455:     } CATCH(prb) {
        !           456:         Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Bus error while writing to %08x",dma[CHANNEL_SCSI].next);
        !           457:         dma[CHANNEL_SCSI].csr &= ~DMA_ENABLE;
        !           458:         dma[CHANNEL_SCSI].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           459:     } ENDTRY
        !           460:     
        !           461:     dma_interrupt(CHANNEL_SCSI);
        !           462: }
        !           463: 
        !           464: void dma_esp_flush_buffer(void) {
        !           465:     if (!(dma[CHANNEL_SCSI].csr&DMA_ENABLE)) {
        !           466:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Not flushing buffer. DMA not enabled.");
        !           467:         return;
        !           468:     }
        !           469:     if (dma[CHANNEL_SCSI].direction!=DMA_DEV2M) {
        !           470:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Not flushing buffer. Bad direction!");
        !           471:         return;
        !           472:     }
        !           473: 
        !           474:     TRY(prb) {
        !           475:         if (dma[CHANNEL_SCSI].next<dma[CHANNEL_SCSI].limit) {
        !           476:             Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Flush buffer to memory at $%08x, 4 bytes",dma[CHANNEL_SCSI].next);
        !           477:             if (espdma_buf_size>0) {
        !           478:                 /* Write one long word to memory */
        !           479:                 NEXTMemory_WriteLong(dma[CHANNEL_SCSI].next, dma_getlong(espdma_buf, espdma_buf_limit-espdma_buf_size));
        !           480:                 espdma_buf_size-=4;
        !           481:             }
        !           482:             dma[CHANNEL_SCSI].next+=4;
        !           483:         } else {
        !           484:             Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Not flushing buffer. DMA done.");
        !           485:         }
        !           486:     } CATCH(prb) {
        !           487:         Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Bus error while flushing to %08x",dma[CHANNEL_SCSI].next);
        !           488:         dma[CHANNEL_SCSI].csr &= ~DMA_ENABLE;
        !           489:         dma[CHANNEL_SCSI].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           490:     } ENDTRY
        !           491:     
        !           492:     dma_interrupt(CHANNEL_SCSI);
        !           493: }
        !           494: 
        !           495: void dma_esp_read_memory(void) {
        !           496:     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Read from memory at $%08x, %i bytes (ESP counter %i)",
        !           497:                dma[CHANNEL_SCSI].next,dma[CHANNEL_SCSI].limit-dma[CHANNEL_SCSI].next,esp_counter);
        !           498:     
        !           499:     if (!(dma[CHANNEL_SCSI].csr&DMA_ENABLE)) {
        !           500:         Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Error! DMA not enabled!");
        !           501:         return;
        !           502:     }
        !           503:     if ((dma[CHANNEL_SCSI].limit%DMA_BURST_SIZE) || (dma[CHANNEL_SCSI].next%4)) {
        !           504:         Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Error! Bad alignment! (Next: $%08X, Limit: $%08X)",
        !           505:                    dma[CHANNEL_SCSI].next, dma[CHANNEL_SCSI].limit);
        !           506:         abort();
        !           507:     }
        !           508:     
        !           509:     TRY(prb) {
        !           510:         if (espdma_buf_size>0) {
        !           511:             Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Starting with %i residual bytes in DMA buffer.", espdma_buf_size);
        !           512:         }
        !           513:         
        !           514:         while (dma[CHANNEL_SCSI].next<dma[CHANNEL_SCSI].limit) {
        !           515:             /* Read data from memory to DMA channel FIFO (only if limit < FIFO size) */
        !           516:             if (espdma_buf_limit<DMA_BURST_SIZE) {
        !           517:                 while (dma[CHANNEL_SCSI].next<dma[CHANNEL_SCSI].limit && espdma_buf_limit<DMA_BURST_SIZE) {
        !           518:                     dma_putlong(NEXTMemory_ReadLong(dma[CHANNEL_SCSI].next), espdma_buf, espdma_buf_limit);
        !           519:                     dma[CHANNEL_SCSI].next+=4;
        !           520:                     espdma_buf_limit+=4;
        !           521:                     espdma_buf_size+=4;
        !           522:                 }
        !           523:             }
        !           524:             
        !           525:             if (espdma_buf_limit<DMA_BURST_SIZE) { /* Not complete, stop */
        !           526:                 Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Channel limit reached. Stopping with %i residual bytes.",
        !           527:                            espdma_buf_size);
        !           528:                 break;
        !           529:             } else { /* Empty DMA channel FIFO (only if limit reached FIFO size) */
        !           530:                 ESP_DMA_set_status();
        !           531: 
        !           532:                 if (floppy_select) {
        !           533:                     while (espdma_buf_size>0 && flp_buffer.size<flp_buffer.limit) {
        !           534:                         flp_buffer.data[flp_buffer.size]=espdma_buf[espdma_buf_limit-espdma_buf_size];
        !           535:                         flp_buffer.size++;
        !           536:                         espdma_buf_size--;
        !           537:                     }
        !           538:                 } else {
        !           539:                     while (espdma_buf_size>0 && esp_counter>0 && SCSIbus.phase==PHASE_DO) {
        !           540:                         SCSIdisk_Receive_Data(espdma_buf[espdma_buf_limit-espdma_buf_size]);
        !           541:                         esp_counter--;
        !           542:                         espdma_buf_size--;
        !           543:                     }
        !           544:                 }
        !           545:                 if (espdma_buf_size>0) { /* Not complete, stop */
        !           546:                     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: No more data request. Stopping with %i residual bytes.",
        !           547:                                espdma_buf_size);
        !           548:                     break;
        !           549:                 }
        !           550:                 espdma_buf_limit = espdma_buf_size; /* Should be 0 */
        !           551:             }
        !           552:         }
        !           553:     } CATCH(prb) {
        !           554:         Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Bus error while reading from %08x",dma[CHANNEL_SCSI].next);
        !           555:         dma[CHANNEL_SCSI].csr &= ~DMA_ENABLE;
        !           556:         dma[CHANNEL_SCSI].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           557:     } ENDTRY
        !           558:     
        !           559:     if ((floppy_select && flp_buffer.size<flp_buffer.limit) || SCSIbus.phase==PHASE_DO) {
        !           560:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Warning! Data not yet written to disk.");
        !           561:         if (espdma_buf_size!=0) {
        !           562:             Log_Printf(LOG_WARN, "[DMA] Channel SCSI: WARNING: Loss of data in DMA buffer possible!");
        !           563:         }
        !           564:     }
        !           565:     
        !           566:     dma_interrupt(CHANNEL_SCSI);
        !           567: }
        !           568: 
        !           569: 
        !           570: /* Channel MO */
        !           571: void dma_mo_write_memory(void) {
        !           572:     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel MO: Write to memory at $%08x, %i bytes",
        !           573:                dma[CHANNEL_DISK].next,dma[CHANNEL_DISK].limit-dma[CHANNEL_DISK].next);
        !           574:     
        !           575:     if (!(dma[CHANNEL_DISK].csr&DMA_ENABLE)) {
        !           576:         Log_Printf(LOG_WARN, "[DMA] Channel MO: Error! DMA not enabled!");
        !           577:         return;
        !           578:     }
        !           579:     if ((dma[CHANNEL_DISK].limit%DMA_BURST_SIZE) || (dma[CHANNEL_DISK].next%4)) {
        !           580:         Log_Printf(LOG_WARN, "[DMA] Channel MO: Error! Bad alignment! (Next: $%08X, Limit: $%08X)",
        !           581:                    dma[CHANNEL_DISK].next, dma[CHANNEL_DISK].limit);
        !           582:         abort();
        !           583:     }
        !           584:     
        !           585:     TRY(prb) {
        !           586:         if (modma_buf_size>0) {
        !           587:             Log_Printf(LOG_WARN, "[DMA] Channel MO: Starting with %i residual bytes in DMA buffer.", modma_buf_size);
        !           588:         }
        !           589:         
        !           590:         while (dma[CHANNEL_DISK].next<=dma[CHANNEL_DISK].limit) {
        !           591:             /* Fill DMA channel FIFO (only if limit < FIFO size) */
        !           592:             if (modma_buf_limit<DMA_BURST_SIZE) {
        !           593:                 while (modma_buf_limit<DMA_BURST_SIZE && ecc_buffer[eccout].size>0) {
        !           594:                     modma_buf[modma_buf_limit]=ecc_buffer[eccout].data[ecc_buffer[eccout].limit-ecc_buffer[eccout].size];
        !           595:                     ecc_buffer[eccout].size--;
        !           596:                     modma_buf_limit++;
        !           597:                     modma_buf_size++;
        !           598:                 }
        !           599:             }
        !           600:             
        !           601:             if (modma_buf_limit<DMA_BURST_SIZE) { /* Not complete, stop */
        !           602:                 Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel MO: No more data. Stopping with %i residual bytes.",
        !           603:                            modma_buf_size);
        !           604:                 break;
        !           605:             } else { /* Empty DMA channel FIFO (only if limit reached FIFO size) */
        !           606:                 while (dma[CHANNEL_DISK].next<dma[CHANNEL_DISK].limit && modma_buf_size>0) {
        !           607:                     NEXTMemory_WriteLong(dma[CHANNEL_DISK].next, dma_getlong(modma_buf, DMA_BURST_SIZE-modma_buf_size));
        !           608:                     dma[CHANNEL_DISK].next+=4;
        !           609:                     modma_buf_size-=4;
        !           610:                 }
        !           611:                 if (modma_buf_size>0) { /* Not complete, stop */
        !           612:                     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel MO: Channel limit reached. Stopping with %i residual bytes.",
        !           613:                                modma_buf_size);
        !           614:                     break;
        !           615:                 }
        !           616:                 modma_buf_limit = modma_buf_size; /* Should be 0 */
        !           617:             }
        !           618:         }
        !           619:     } CATCH(prb) {
        !           620:         Log_Printf(LOG_WARN, "[DMA] Channel MO: Bus error while writing to %08x",dma[CHANNEL_DISK].next);
        !           621:         dma[CHANNEL_DISK].csr &= ~DMA_ENABLE;
        !           622:         dma[CHANNEL_DISK].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           623:     } ENDTRY
        !           624:     
        !           625:     dma_interrupt(CHANNEL_DISK);
        !           626: }
        !           627: 
        !           628: void dma_mo_read_memory(void) {
        !           629:     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel MO: Read from memory at $%08x, %i bytes",
        !           630:                dma[CHANNEL_DISK].next,dma[CHANNEL_DISK].limit-dma[CHANNEL_DISK].next);
        !           631:     
        !           632:     if (!(dma[CHANNEL_DISK].csr&DMA_ENABLE)) {
        !           633:         Log_Printf(LOG_WARN, "[DMA] Channel MO: Error! DMA not enabled!");
        !           634:         return;
        !           635:     }
        !           636:     if ((dma[CHANNEL_DISK].limit%DMA_BURST_SIZE) || (dma[CHANNEL_DISK].next%4)) {
        !           637:         Log_Printf(LOG_WARN, "[DMA] Channel MO: Error! Bad alignment! (Next: $%08X, Limit: $%08X)",
        !           638:                    dma[CHANNEL_DISK].next, dma[CHANNEL_DISK].limit);
        !           639:         abort();
        !           640:     }
        !           641:     
        !           642:     TRY(prb) {
        !           643:         if (modma_buf_size>0) {
        !           644:             Log_Printf(LOG_WARN, "[DMA] Channel MO: Starting with %i residual bytes in DMA buffer.", modma_buf_size);
        !           645:         }
        !           646:         
        !           647:         while (dma[CHANNEL_DISK].next<dma[CHANNEL_DISK].limit) {
        !           648:             /* Read data from memory to DMA channel FIFO (only if limit < FIFO size) */
        !           649:             if (modma_buf_limit<DMA_BURST_SIZE) {
        !           650:                 while (dma[CHANNEL_DISK].next<dma[CHANNEL_DISK].limit && modma_buf_limit<DMA_BURST_SIZE) {
        !           651:                     dma_putlong(NEXTMemory_ReadLong(dma[CHANNEL_DISK].next), modma_buf, modma_buf_limit);
        !           652:                     dma[CHANNEL_DISK].next+=4;
        !           653:                     modma_buf_limit+=4;
        !           654:                     modma_buf_size+=4;
        !           655:                 }
        !           656:             }
        !           657:             
        !           658:             if (modma_buf_limit<DMA_BURST_SIZE) { /* Not complete, stop */
        !           659:                 Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel MO: Channel limit reached. Stopping with %i residual bytes.",
        !           660:                            modma_buf_size);
        !           661:                 break;
        !           662:             } else { /* Empty DMA channel FIFO (only if limit reached FIFO size) */
        !           663:                 while (modma_buf_size>0 && ecc_buffer[eccin].size<ecc_buffer[eccin].limit) {
        !           664:                     ecc_buffer[eccin].data[ecc_buffer[eccin].size]=modma_buf[modma_buf_limit-modma_buf_size];
        !           665:                     ecc_buffer[eccin].size++;
        !           666:                     modma_buf_size--;
        !           667:                 }
        !           668:                 if (modma_buf_size>0) { /* Not complete, stop */
        !           669:                     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel MO: No more data request. Stopping with %i residual bytes.",
        !           670:                                modma_buf_size);
        !           671:                     break;
        !           672:                 }
        !           673:                 modma_buf_limit = modma_buf_size; /* Should be 0 */
        !           674:             }
        !           675:         }
        !           676:     } CATCH(prb) {
        !           677:         Log_Printf(LOG_WARN, "[DMA] Channel MO: Bus error while reading from %08x",dma[CHANNEL_DISK].next);
        !           678:         dma[CHANNEL_DISK].csr &= ~DMA_ENABLE;
        !           679:         dma[CHANNEL_DISK].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           680:     } ENDTRY
        !           681:     
        !           682:     if (ecc_buffer[eccin].size<ecc_buffer[eccin].limit) {
        !           683:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel MO: Warning! Data not yet written to disk.");
        !           684:         if (modma_buf_size!=0) {
        !           685:             Log_Printf(LOG_WARN, "[DMA] Channel MO: WARNING: Loss of data in DMA buffer possible!");
        !           686:         }
        !           687:     }
        !           688:     
        !           689:     dma_interrupt(CHANNEL_DISK);
        !           690: }
        !           691: 
        !           692: 
        !           693: Uint8* dma_sndout_read_memory(int* len) {
        !           694:     int i;
        !           695:     Uint8* result = NULL;
        !           696:     *len          = 0;
        !           697:     
        !           698:     if (dma[CHANNEL_SOUNDOUT].csr&DMA_ENABLE) {
        !           699:         
        !           700:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel Sound Out: Read from memory at $%08x, %i bytes",
        !           701:                    dma[CHANNEL_SOUNDOUT].next,dma[CHANNEL_SOUNDOUT].limit-dma[CHANNEL_SOUNDOUT].next);
        !           702:         
        !           703:         if ((dma[CHANNEL_SOUNDOUT].limit&3) || (dma[CHANNEL_SOUNDOUT].next&3)) {
        !           704:             Log_Printf(LOG_WARN, "[DMA] Channel Sound Out: Error! Bad alignment! (Next: $%08X, Limit: $%08X)",
        !           705:                        dma[CHANNEL_SOUNDOUT].next, dma[CHANNEL_SOUNDOUT].limit);
        !           706:             dma[CHANNEL_SOUNDOUT].next &= ~3;
        !           707:             dma[CHANNEL_SOUNDOUT].limit &= ~3;
        !           708:         }
        !           709:         
        !           710:         TRY(prb) {
        !           711:             *len   = dma[CHANNEL_SOUNDOUT].limit - dma[CHANNEL_SOUNDOUT].next;
        !           712:             result = malloc(*len * 2);
        !           713:             for(i = 0; dma[CHANNEL_SOUNDOUT].next<dma[CHANNEL_SOUNDOUT].limit; dma[CHANNEL_SOUNDOUT].next++, i++)
        !           714:                 result[i] = NEXTMemory_ReadByte(dma[CHANNEL_SOUNDOUT].next);
        !           715:         } CATCH(prb) {
        !           716:             Log_Printf(LOG_WARN, "[DMA] Channel Sound Out: Bus error reading from %08x",dma[CHANNEL_SOUNDOUT].next);
        !           717:             dma[CHANNEL_SOUNDOUT].csr &= ~DMA_ENABLE;
        !           718:             dma[CHANNEL_SOUNDOUT].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           719:         } ENDTRY
        !           720:     }
        !           721:     
        !           722:     return result;
        !           723: }
        !           724: 
        !           725: void dma_sndout_intr() {
        !           726:     if (dma[CHANNEL_SOUNDOUT].csr&DMA_ENABLE) {
        !           727:         dma_interrupt(CHANNEL_SOUNDOUT);
        !           728:     }
        !           729: }
        !           730: 
        !           731: int dma_sndin_write_memory() {
        !           732:        int value = 0;
        !           733:        
        !           734:     if (dma[CHANNEL_SOUNDIN].csr&DMA_ENABLE) {
        !           735:                
        !           736:                Audio_Input_Lock();
        !           737: 
        !           738:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel Sound In: Write to memory at $%08x, %i bytes",
        !           739:                    dma[CHANNEL_SOUNDIN].next,dma[CHANNEL_SOUNDIN].limit-dma[CHANNEL_SOUNDIN].next);
        !           740: 
        !           741:                TRY(prb) {
        !           742:             while (dma[CHANNEL_SOUNDIN].next<dma[CHANNEL_SOUNDIN].limit) {
        !           743:                 value = Audio_Input_Read();
        !           744:                                if (value < 0) {
        !           745:                                        break;
        !           746:                                }
        !           747:                                NEXTMemory_WriteByte(dma[CHANNEL_SOUNDIN].next, value);
        !           748:                                dma[CHANNEL_SOUNDIN].next++;
        !           749:             }
        !           750:         } CATCH(prb) {
        !           751:             Log_Printf(LOG_WARN, "[DMA] Channel Sound In: Bus error reading from %08x",dma[CHANNEL_SOUNDIN].next);
        !           752:             dma[CHANNEL_SOUNDIN].csr &= ~DMA_ENABLE;
        !           753:             dma[CHANNEL_SOUNDIN].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           754:         } ENDTRY
        !           755:                
        !           756:                Audio_Input_Unlock();
        !           757: 
        !           758:         dma[CHANNEL_SOUNDIN].saved_limit = dma[CHANNEL_SOUNDIN].next;
        !           759:         dma_interrupt(CHANNEL_SOUNDIN);
        !           760:                
        !           761:                return (dma[CHANNEL_SOUNDIN].next==dma[CHANNEL_SOUNDIN].limit);
        !           762:     }
        !           763:        return 1;
        !           764: }
        !           765: 
        !           766: /* Channel Printer */
        !           767: void dma_printer_read_memory(void) {
        !           768:     if (dma[CHANNEL_PRINTER].csr&DMA_ENABLE) {
        !           769:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel Printer: Read from memory at $%08x, %i bytes",
        !           770:                    dma[CHANNEL_PRINTER].next,dma[CHANNEL_PRINTER].limit-dma[CHANNEL_PRINTER].next);
        !           771:         
        !           772:         if ((dma[CHANNEL_PRINTER].limit%4) || (dma[CHANNEL_PRINTER].next%4)) {
        !           773:             Log_Printf(LOG_WARN, "[DMA] Channel Printer: Error! Bad alignment! (Next: $%08X, Limit: $%08X)",
        !           774:                        dma[CHANNEL_PRINTER].next, dma[CHANNEL_PRINTER].limit);
        !           775:             abort();
        !           776:         }
        !           777:         
        !           778:         TRY(prb) {
        !           779:             while (dma[CHANNEL_PRINTER].next<dma[CHANNEL_PRINTER].limit && lp_buffer.size<lp_buffer.limit) {
        !           780:                 lp_buffer.data[lp_buffer.size]=NEXTMemory_ReadByte(dma[CHANNEL_PRINTER].next);
        !           781:                 lp_buffer.size++;
        !           782:                 dma[CHANNEL_PRINTER].next++;
        !           783:             }
        !           784:         } CATCH(prb) {
        !           785:             Log_Printf(LOG_WARN, "[DMA] Channel Printer: Bus error reading from %08x",dma[CHANNEL_PRINTER].next);
        !           786:             dma[CHANNEL_PRINTER].csr &= ~DMA_ENABLE;
        !           787:             dma[CHANNEL_PRINTER].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           788:         } ENDTRY
        !           789:         
        !           790:         dma_interrupt(CHANNEL_PRINTER);
        !           791:     }
        !           792: }
        !           793: 
        !           794: 
        !           795: /* Channel Ethernet (this channel does not use DMA buffering) */
        !           796: #define EN_EOP      0x80000000 /* end of packet */
        !           797: #define EN_BOP      0x40000000 /* beginning of packet */
        !           798: #define ENADDR(x)   ((x)&~(EN_EOP|EN_BOP))
        !           799: 
        !           800: Uint32 saved_next_turbo = 0;
        !           801: 
        !           802: static void dma_enet_interrupt(int channel) {
        !           803:     int interrupt = get_interrupt_type(channel);
        !           804:     
        !           805:     dma[channel].csr |= DMA_COMPLETE;
        !           806:     
        !           807:     if (dma[channel].csr & DMA_SUPDATE) { /* if we are in chaining mode */
        !           808:         /* Update pointers */
        !           809:                saved_next_turbo = dma[channel].next;
        !           810:         dma[channel].next = dma[channel].start;
        !           811:         dma[channel].limit = dma[channel].stop;
        !           812:         /* Set bits in CSR */
        !           813:         dma[channel].csr &= ~DMA_SUPDATE; /* 1st done */
        !           814:     } else {
        !           815:         dma[channel].csr &= ~DMA_ENABLE; /* all done */
        !           816:     }
        !           817:     set_interrupt(interrupt, SET_INT);
        !           818: }
        !           819: 
        !           820: void dma_enet_write_memory(bool eop) {
        !           821:     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel Ethernet Receive: Write to memory at $%08x, %i bytes",
        !           822:                dma[CHANNEL_EN_RX].next,dma[CHANNEL_EN_RX].limit-dma[CHANNEL_EN_RX].next);
        !           823:     
        !           824:     if (!(dma[CHANNEL_EN_RX].csr&DMA_ENABLE)) {
        !           825:         Log_Printf(LOG_WARN, "[DMA] Channel Ethernet Receive: Error! DMA not enabled!");
        !           826:         return;
        !           827:     }
        !           828:     if ((dma[CHANNEL_EN_RX].limit%DMA_BURST_SIZE) || (dma[CHANNEL_EN_RX].next%DMA_BURST_SIZE)) {
        !           829:         Log_Printf(LOG_WARN, "[DMA] Channel Ethernet Receive: Error! Bad alignment! (Next: $%08X, Limit: $%08X)",
        !           830:                    dma[CHANNEL_EN_RX].next, dma[CHANNEL_EN_RX].limit);
        !           831:         abort();
        !           832:     }
        !           833:     
        !           834:     TRY(prb) {
        !           835:         while (dma[CHANNEL_EN_RX].next<dma[CHANNEL_EN_RX].limit && enet_rx_buffer.size>0) {
        !           836:             NEXTMemory_WriteByte(dma[CHANNEL_EN_RX].next, enet_rx_buffer.data[enet_rx_buffer.limit-enet_rx_buffer.size]);
        !           837:             enet_rx_buffer.size--;
        !           838:             dma[CHANNEL_EN_RX].next++;
        !           839:         }
        !           840:     } CATCH(prb) {
        !           841:         Log_Printf(LOG_WARN, "[DMA] Channel Ethernet Receive: Bus error while writing to %08x",dma[CHANNEL_EN_RX].next);
        !           842:         dma[CHANNEL_EN_RX].csr &= ~DMA_ENABLE;
        !           843:         dma[CHANNEL_EN_RX].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           844:     } ENDTRY
        !           845:     
        !           846:     if (enet_rx_buffer.size==0) {
        !           847:         if (eop) { /* TODO: check if this is correct */
        !           848:             Log_Printf(LOG_WARN, "[DMA] Channel Ethernet Receive: Last buffer of chain done.");
        !           849:             dma[CHANNEL_EN_RX].next|=EN_BOP;
        !           850:         }
        !           851:         dma[CHANNEL_EN_RX].saved_limit = dma[CHANNEL_EN_RX].next;
        !           852:     }
        !           853: 
        !           854:     dma_enet_interrupt(CHANNEL_EN_RX);
        !           855: }
        !           856: 
        !           857: bool dma_enet_read_memory(void) {
        !           858:     if (dma[CHANNEL_EN_TX].csr&DMA_ENABLE) {
        !           859:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel Ethernet Transmit: Read from memory at $%08x, %i bytes",
        !           860:                    dma[CHANNEL_EN_TX].next,ENADDR(dma[CHANNEL_EN_TX].limit)-dma[CHANNEL_EN_TX].next);
        !           861:         
        !           862:         TRY(prb) {
        !           863:             while (dma[CHANNEL_EN_TX].next<ENADDR(dma[CHANNEL_EN_TX].limit) && enet_tx_buffer.size<enet_tx_buffer.limit) {
        !           864:                 enet_tx_buffer.data[enet_tx_buffer.size]=NEXTMemory_ReadByte(dma[CHANNEL_EN_TX].next);
        !           865:                 enet_tx_buffer.size++;
        !           866:                 dma[CHANNEL_EN_TX].next++;
        !           867:             }
        !           868:         } CATCH(prb) {
        !           869:             Log_Printf(LOG_WARN, "[DMA] Channel Ethernet Transmit: Bus error while writing to %08x",dma[CHANNEL_EN_TX].next);
        !           870:             dma[CHANNEL_EN_TX].csr &= ~DMA_ENABLE;
        !           871:             dma[CHANNEL_EN_TX].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           872:         } ENDTRY
        !           873:         
        !           874:         if (dma[CHANNEL_EN_TX].limit&EN_EOP) {
        !           875:             Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel Ethernet Transmit: Packet done.");
        !           876:             dma_enet_interrupt(CHANNEL_EN_TX);
        !           877:             return true;
        !           878:         }
        !           879:         dma_enet_interrupt(CHANNEL_EN_TX);
        !           880:     }
        !           881:     return false;
        !           882: }
        !           883: 
        !           884: 
        !           885: /* Memory to Memory */
        !           886: 
        !           887: Uint32 m2m_buffer[DMA_BURST_SIZE];
        !           888: int m2m_buffer_size;
        !           889: 
        !           890: void M2MDMA_IO_Handler(void) {
        !           891:     CycInt_AcknowledgeInterrupt();
        !           892:     
        !           893:     if (dma[CHANNEL_R2M].csr&DMA_ENABLE) {
        !           894:         dma_m2m_write_memory();
        !           895:         CycInt_AddRelativeInterruptCycles(4, INTERRUPT_M2M_IO);
        !           896:     }
        !           897: }
        !           898: 
        !           899: void dma_m2m(void) {
        !           900:     if ((dma[CHANNEL_M2R].csr&DMA_ENABLE) && (dma[CHANNEL_R2M].csr&DMA_ENABLE)) {
        !           901:         if (((dma[CHANNEL_R2M].limit-dma[CHANNEL_R2M].next)%DMA_BURST_SIZE) ||
        !           902:             ((dma[CHANNEL_M2R].limit-dma[CHANNEL_M2R].next)%DMA_BURST_SIZE)) {
        !           903:             Log_Printf(LOG_WARN, "[DMA] Channel M2M: Error! Memory not burst size aligned!");
        !           904:             return;
        !           905:         }
        !           906:         
        !           907:         Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel M2M: Copying %i bytes from $%08X to %i bytes at $%08X.",
        !           908:                    dma[CHANNEL_M2R].limit-dma[CHANNEL_M2R].next,dma[CHANNEL_M2R].next,
        !           909:                    dma[CHANNEL_R2M].limit-dma[CHANNEL_R2M].next,dma[CHANNEL_R2M].next);
        !           910:         
        !           911:         CycInt_AddRelativeInterruptCycles(4, INTERRUPT_M2M_IO);
        !           912:     }
        !           913: }
        !           914: 
        !           915: void dma_m2m_write_memory(void) {
        !           916:     
        !           917:     if (dma[CHANNEL_R2M].next<dma[CHANNEL_R2M].limit) {
        !           918: 
        !           919:         if (dma[CHANNEL_M2R].next<dma[CHANNEL_M2R].limit) {
        !           920:             /* (Re)fill the buffer, if there is still data to read */
        !           921:             m2m_buffer_size = 0;
        !           922: 
        !           923:             TRY(prb) {
        !           924:                 while (m2m_buffer_size < DMA_BURST_SIZE) {
        !           925:                     m2m_buffer[m2m_buffer_size]=NEXTMemory_ReadByte(dma[CHANNEL_M2R].next);
        !           926:                     m2m_buffer_size++;
        !           927:                     dma[CHANNEL_M2R].next++;
        !           928:                 }
        !           929:             } CATCH(prb) {
        !           930:                 Log_Printf(LOG_WARN, "[DMA] Channel M2M: Bus error while reading from %08x",dma[CHANNEL_M2R].next);
        !           931:                 dma[CHANNEL_M2R].csr &= ~DMA_ENABLE;
        !           932:                 dma[CHANNEL_M2R].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           933:             } ENDTRY
        !           934:             
        !           935:             dma_interrupt(CHANNEL_M2R);
        !           936:         } else {
        !           937:             /* Re-use data in buffer */
        !           938:             m2m_buffer_size = DMA_BURST_SIZE;
        !           939:         }
        !           940:         
        !           941:         TRY(prb) {
        !           942:             /* Write the contents of the buffer to memory */
        !           943:             while (m2m_buffer_size > 0) {
        !           944:                 NEXTMemory_WriteByte(dma[CHANNEL_R2M].next, m2m_buffer[DMA_BURST_SIZE-m2m_buffer_size]);
        !           945:                 m2m_buffer_size--;
        !           946:                 dma[CHANNEL_R2M].next++;
        !           947:             }
        !           948:         } CATCH(prb) {
        !           949:             Log_Printf(LOG_WARN, "[DMA] Channel M2M: Bus error while writing to %08x",dma[CHANNEL_R2M].next);
        !           950:             dma[CHANNEL_R2M].csr &= ~DMA_ENABLE;
        !           951:             dma[CHANNEL_R2M].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           952:         } ENDTRY
        !           953:     }
        !           954:     
        !           955:     dma_interrupt(CHANNEL_R2M);
        !           956: }
        !           957: 
        !           958: 
        !           959: /* Channel DSP */
        !           960: #define LOG_DMA_DSP_LEVEL      LOG_DEBUG
        !           961: 
        !           962: void dma_dsp_write_memory(Uint8 val) {
        !           963:        Log_Printf(LOG_DMA_DSP_LEVEL, "[DMA] Channel DSP: Write to memory at $%08x, %i bytes",
        !           964:                           dma[CHANNEL_DSP].next,dma[CHANNEL_DSP].limit-dma[CHANNEL_DSP].next);
        !           965:        
        !           966:        if (!(dma[CHANNEL_DSP].csr&DMA_ENABLE)) {
        !           967:                Log_Printf(LOG_WARN, "[DMA] Channel DSP: Error! DMA not enabled!");
        !           968:                return;
        !           969:        }
        !           970:        
        !           971:        TRY(prb) {
        !           972:                if (dma[CHANNEL_DSP].next<dma[CHANNEL_DSP].limit) {
        !           973:                        NEXTMemory_WriteByte(dma[CHANNEL_DSP].next, val);
        !           974:                        dma[CHANNEL_DSP].next++;
        !           975:                }
        !           976:        } CATCH(prb) {
        !           977:                Log_Printf(LOG_WARN, "[DMA] Channel DSP: Bus error while writing to %08x",dma[CHANNEL_DSP].next);
        !           978:                dma[CHANNEL_DSP].csr &= ~DMA_ENABLE;
        !           979:                dma[CHANNEL_DSP].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !           980:        } ENDTRY
        !           981:        
        !           982:        if (dma[CHANNEL_DSP].next==dma[CHANNEL_DSP].limit) {
        !           983:                DSP_SetIRQB();
        !           984:                dma_interrupt(CHANNEL_DSP);
        !           985:        }
        !           986: }
        !           987: 
        !           988: Uint8 dma_dsp_read_memory(void) {
        !           989:        Uint8 val = 0;
        !           990:        
        !           991:        Log_Printf(LOG_DMA_DSP_LEVEL, "[DMA] Channel DSP: Read from memory at $%08x, %i bytes",
        !           992:                           dma[CHANNEL_DSP].next,dma[CHANNEL_DSP].limit-dma[CHANNEL_DSP].next);
        !           993:        
        !           994:        if (!(dma[CHANNEL_DSP].csr&DMA_ENABLE)) {
        !           995:                Log_Printf(LOG_WARN, "[DMA] Channel DSP: Error! DMA not enabled!");
        !           996:                return val;
        !           997:        }
        !           998:        
        !           999:        TRY(prb) {
        !          1000:                if (dma[CHANNEL_DSP].next<dma[CHANNEL_DSP].limit) {
        !          1001:                        val = NEXTMemory_ReadByte(dma[CHANNEL_DSP].next);
        !          1002:                        dma[CHANNEL_DSP].next++;
        !          1003:                }
        !          1004:        } CATCH(prb) {
        !          1005:                Log_Printf(LOG_WARN, "[DMA] Channel DSP: Bus error while writing to %08x",dma[CHANNEL_DSP].next);
        !          1006:                dma[CHANNEL_DSP].csr &= ~DMA_ENABLE;
        !          1007:                dma[CHANNEL_DSP].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !          1008:        } ENDTRY
        !          1009:        
        !          1010:        if (dma[CHANNEL_DSP].next==dma[CHANNEL_DSP].limit) {
        !          1011:                DSP_SetIRQB();
        !          1012:                dma_interrupt(CHANNEL_DSP);
        !          1013:        }
        !          1014:        return val;
        !          1015: }
        !          1016: 
        !          1017: bool dma_dsp_ready(void) {
        !          1018:        if (!(dma[CHANNEL_DSP].csr&DMA_ENABLE) ||
        !          1019:                !(dma[CHANNEL_DSP].next<dma[CHANNEL_DSP].limit)) {
        !          1020:                Log_Printf(LOG_DEBUG, "[DMA] Channel DSP: Not ready!");
        !          1021:                return false;
        !          1022:        } else {
        !          1023:                return true;
        !          1024:        }
        !          1025: }
        !          1026: 
        !          1027: 
        !          1028: /* ---------------------- DMA Scratchpad ---------------------- */
        !          1029: 
        !          1030: /* This is used to interrupt at vertical screen retrace.
        !          1031:  * TODO: find out how the interrupt is generated in real
        !          1032:  * hardware using the Limit register of the DMA chip.
        !          1033:  * (0xEA * 1024 = visible videomem size)
        !          1034:  */
        !          1035: 
        !          1036: 
        !          1037: /* Interrupt Handler (called from Video_InterruptHandler in video.c) */
        !          1038: void dma_video_interrupt(void) {
        !          1039:     if (dma[CHANNEL_VIDEO].limit==0xEA) {
        !          1040:         set_interrupt(INT_VIDEO, SET_INT); /* interrupt is released by writing to CSR */
        !          1041:     } else if (dma[CHANNEL_VIDEO].limit && dma[CHANNEL_VIDEO].limit!=0xEA) {
        !          1042:         abort();
        !          1043:     }
        !          1044: }
        !          1045: 
        !          1046: 
        !          1047: /* FIXME: This is just for passing power-on test. Add real SCC channel later. */
        !          1048: 
        !          1049: void dma_scc_read_memory(void) {
        !          1050:     Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCC: Read from memory at $%08x, %i bytes",
        !          1051:                dma[CHANNEL_SCC].next,dma[CHANNEL_SCC].limit-dma[CHANNEL_SCC].next);
        !          1052:     while (dma[CHANNEL_SCC].next<dma[CHANNEL_SCC].limit) {
        !          1053:         scc_buf[0]=NEXTMemory_ReadByte(dma[CHANNEL_SCC].next);
        !          1054:         dma[CHANNEL_SCC].next++;
        !          1055:     }
        !          1056:     
        !          1057:     dma_interrupt(CHANNEL_SCC);
        !          1058: }
        !          1059: 
        !          1060: 
        !          1061: /* DMA CSR on Turbo systems */
        !          1062: 
        !          1063: /* CSR read bits */
        !          1064: #define TDMA_BYTECOUNT_MASK    0x00000007
        !          1065: #define TDMA_WRITEPTR_MASK     0x00000018
        !          1066: #define TDMA_READPTR_MASK      0x00000060
        !          1067: #define TDMA_DIRTY_MASK                0x00000180
        !          1068: #define TDMA_BUFSEL                    0x00000200
        !          1069: 
        !          1070: #define TDMA_ENABLE                    0x01000000
        !          1071: #define TDMA_SUPDATE           0x02000000
        !          1072: #define TDMA_COMPLETE          0x08000000
        !          1073: #define TDMA_BUSEXC                    0x10000000
        !          1074: 
        !          1075: /* CSR write bits */
        !          1076: #define TDMA_SETENABLE         0x00010000
        !          1077: #define TDMA_SETSUPDATE                0x00020000
        !          1078: #define TDMA_DEV2M                     0x00040000
        !          1079: #define TDMA_CLRCOMPLETE       0x00080000
        !          1080: #define TDMA_RESET                     0x00100000
        !          1081: #define TDMA_SETCOMPLETE       0x00200000
        !          1082: #define TDMA_FLUSH                     0x00400000
        !          1083: #define TDMA_BUFRESET          0x00800000
        !          1084: 
        !          1085: /* CSR masks */
        !          1086: #define TDMA_CMD_MASK    0x00FB0000
        !          1087: 
        !          1088: void TDMA_CSR_Read(void) { // 0x02000010, length of register is byte on 68030 based NeXT Computer
        !          1089:        int channel = get_channel(IoAccessCurrentAddress);
        !          1090:        
        !          1091:        IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, dma[channel].csr<<24);
        !          1092: 
        !          1093:        Log_Printf(LOG_DMA_LEVEL,"DMA CSR read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, dma[channel].csr<<24, m68k_getpc());
        !          1094: }
        !          1095: 
        !          1096: void TDMA_CSR_Write(void) {
        !          1097:        int channel = get_channel(IoAccessCurrentAddress);
        !          1098:        int interrupt = get_interrupt_type(channel);
        !          1099:        Uint32 writecsr = IoMem_ReadLong(IoAccessCurrentAddress & IO_SEG_MASK);
        !          1100: 
        !          1101:        Log_Printf(LOG_DMA_LEVEL,"DMA CSR write at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, writecsr, m68k_getpc());
        !          1102:        
        !          1103:        /* For debugging */
        !          1104:        if(writecsr&TDMA_DEV2M)
        !          1105:                Log_Printf(LOG_DMA_LEVEL,"DMA from dev to mem");
        !          1106:        else
        !          1107:                Log_Printf(LOG_DMA_LEVEL,"DMA from mem to dev");
        !          1108:        
        !          1109:        switch (writecsr&TDMA_CMD_MASK) {
        !          1110:                case TDMA_RESET:
        !          1111:                        Log_Printf(LOG_DMA_LEVEL,"DMA reset"); break;
        !          1112:                case TDMA_BUFRESET:
        !          1113:                        Log_Printf(LOG_DMA_LEVEL,"DMA initialize buffers"); break;
        !          1114:                case (TDMA_RESET | TDMA_BUFRESET):
        !          1115:                case (TDMA_RESET | TDMA_BUFRESET | TDMA_CLRCOMPLETE):
        !          1116:                        Log_Printf(LOG_DMA_LEVEL,"DMA reset and initialize buffers"); break;
        !          1117:                case TDMA_CLRCOMPLETE:
        !          1118:                        Log_Printf(LOG_DMA_LEVEL,"DMA end chaining"); break;
        !          1119:                case (TDMA_SETSUPDATE | TDMA_CLRCOMPLETE):
        !          1120:                        Log_Printf(LOG_DMA_LEVEL,"DMA continue chaining"); break;
        !          1121:                case TDMA_SETENABLE:
        !          1122:                        Log_Printf(LOG_DMA_LEVEL,"DMA start single transfer"); break;
        !          1123:                case (TDMA_SETENABLE | TDMA_SETSUPDATE):
        !          1124:                case (TDMA_SETENABLE | TDMA_SETSUPDATE | TDMA_CLRCOMPLETE):
        !          1125:                        Log_Printf(LOG_DMA_LEVEL,"DMA start chaining"); break;
        !          1126:                case 0:
        !          1127:                        Log_Printf(LOG_DMA_LEVEL,"DMA no command"); break;
        !          1128:                default:
        !          1129:                        Log_Printf(LOG_WARN,"DMA: unknown command!"); break;
        !          1130:        }
        !          1131:        
        !          1132:        /* Handle CSR bits */
        !          1133:        dma[channel].direction = (writecsr>>16)&DMA_DEV2M;
        !          1134:        
        !          1135:        if (writecsr&TDMA_RESET) {
        !          1136:                dma[channel].csr &= ~(DMA_COMPLETE | DMA_SUPDATE | DMA_ENABLE);
        !          1137:        }
        !          1138:        if (writecsr&TDMA_BUFRESET) {
        !          1139:                dma_initialize_buffer(channel, 0);
        !          1140:        }
        !          1141:        if (writecsr&TDMA_SETSUPDATE) {
        !          1142:                dma[channel].csr |= DMA_SUPDATE;
        !          1143:        }
        !          1144:        if (writecsr&TDMA_SETENABLE) {
        !          1145:                dma[channel].csr |= DMA_ENABLE;
        !          1146:        }
        !          1147:        if (writecsr&TDMA_CLRCOMPLETE) {
        !          1148:                dma[channel].csr &= ~DMA_COMPLETE;
        !          1149:        }
        !          1150:        
        !          1151:        set_interrupt(interrupt, RELEASE_INT);
        !          1152: }
        !          1153: 
        !          1154: void TDMA_Saved_Next_Read(void) { // 0x02004050
        !          1155:        IoMem_WriteLong(IoAccessCurrentAddress & IO_SEG_MASK, saved_next_turbo);
        !          1156:        Log_Printf(LOG_DMA_LEVEL,"TDMA SNext read at $%08x val=$%08x PC=$%08x\n", IoAccessCurrentAddress, saved_next_turbo, m68k_getpc());
        !          1157: }
        !          1158: 
        !          1159: /* Flush DMA buffer */
        !          1160: /* FIXME: Implement function for all buffered channels */
        !          1161: void tdma_flush_buffer(int channel) {
        !          1162:        int i;
        !          1163:        
        !          1164:        if (!(dma[CHANNEL_SCSI].csr&DMA_ENABLE)) {
        !          1165:                Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Not flushing buffer. DMA not enabled.");
        !          1166:                return;
        !          1167:        }
        !          1168:        if (dma[CHANNEL_SCSI].direction!=DMA_DEV2M) {
        !          1169:                Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Not flushing buffer. Bad direction!");
        !          1170:                return;
        !          1171:        }
        !          1172:        
        !          1173:        TRY(prb) {
        !          1174:                Log_Printf(LOG_DMA_LEVEL, "[DMA] Channel SCSI: Flush buffer to memory at $%08x, %i bytes",
        !          1175:                                   dma[CHANNEL_SCSI].next,espdma_buf_size);
        !          1176:                
        !          1177:                for (i = 0; i < DMA_BURST_SIZE; i+=4) {
        !          1178:                        if (dma[CHANNEL_SCSI].next<dma[CHANNEL_SCSI].limit) {
        !          1179:                                if (espdma_buf_size) {
        !          1180:                                        NEXTMemory_WriteLong(dma[CHANNEL_SCSI].next, dma_getlong(espdma_buf, espdma_buf_limit-espdma_buf_size));
        !          1181:                                        espdma_buf_size-=4;
        !          1182:                                }
        !          1183:                                dma[CHANNEL_SCSI].next+=4;
        !          1184:                        }
        !          1185:                }
        !          1186:        } CATCH(prb) {
        !          1187:                Log_Printf(LOG_WARN, "[DMA] Channel SCSI: Bus error while flushing to %08x",dma[CHANNEL_SCSI].next);
        !          1188:                dma[CHANNEL_SCSI].csr &= ~DMA_ENABLE;
        !          1189:                dma[CHANNEL_SCSI].csr |= (DMA_COMPLETE|DMA_BUSEXC);
        !          1190:        } ENDTRY
        !          1191:        
        !          1192:        dma_interrupt(CHANNEL_SCSI);
        !          1193: }

unix.superglobalmegacorp.com

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