Annotation of previous/src/dma.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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