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

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.1.4 ! root       26: #include "kms.h"
        !            27: #include "audio.h"
1.1       root       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: 
                     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);
1.1       root       38: 
                     39: 
1.1.1.3   root       40: struct {
                     41:     Uint8 csr;
1.1       root       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;
1.1.1.3   root       50:     
                     51:     Uint8 direction;
                     52: } dma[12];
                     53: 
                     54: 
                     55: /* DMA internal buffers */
                     56: #define DMA_BURST_SIZE  16
1.1       root       57: 
1.1.1.3   root       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];
1.1       root       64: 
                     65: 
1.1.1.3   root       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: 
1.1       root      117: 
                    118: int get_channel(Uint32 address) {
                    119:     int channel = address&IO_SEG_MASK;
1.1.1.3   root      120: 
1.1       root      121:     switch (channel) {
1.1.1.3   root      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;
1.1       root      134:             
                    135:         default:
1.1.1.3   root      136:             Log_Printf(LOG_WARN, "Unknown DMA channel!\n");
1.1       root      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;
1.1.1.3   root      153:         case CHANNEL_VIDEO: return INT_VIDEO; break;
1.1       root      154:         case CHANNEL_M2R: return INT_M2R_DMA; break;
                    155:         case CHANNEL_R2M: return INT_R2M_DMA; break;
                    156:                         
                    157:         default:
1.1.1.3   root      158:             Log_Printf(LOG_WARN, "Unknown DMA interrupt!\n");
1.1       root      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);
1.1.1.3   root      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());
1.1       root      170: }
                    171: 
                    172: void DMA_CSR_Write(void) {
                    173:     int channel = get_channel(IoAccessCurrentAddress);
                    174:     int interrupt = get_interrupt_type(channel);
1.1.1.3   root      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)
1.1       root      181:         Log_Printf(LOG_DMA_LEVEL,"DMA from dev to mem");
1.1.1.3   root      182:     else
1.1       root      183:         Log_Printf(LOG_DMA_LEVEL,"DMA from mem to dev");
1.1.1.3   root      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;
1.1       root      206:     }
1.1.1.3   root      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);
1.1.1.2   root      213:     }
1.1.1.3   root      214:     if (writecsr&DMA_INITBUF) {
                    215:         dma_initialize_buffer(channel, 0);
1.1       root      216:     }
1.1.1.3   root      217:     if (writecsr&DMA_SETSUPDATE) {
1.1       root      218:         dma[channel].csr |= DMA_SUPDATE;
                    219:     }
1.1.1.3   root      220:     if (writecsr&DMA_SETENABLE) {
                    221:         dma[channel].csr |= DMA_ENABLE;
1.1.1.4 ! root      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();
1.1.1.3   root      229:         }
1.1       root      230:     }
1.1.1.3   root      231:     if (writecsr&DMA_CLRCOMPLETE) {
                    232:         dma[channel].csr &= ~DMA_COMPLETE;
1.1       root      233:     }
1.1.1.3   root      234: 
                    235:     set_interrupt(interrupt, RELEASE_INT); // experimental
1.1       root      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);
1.1.1.3   root      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());
1.1       root      338: }
                    339: 
                    340: void DMA_Init_Write(void) {
                    341:     int channel = get_channel(IoAccessCurrentAddress-0x4200);
1.1.1.3   root      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());
1.1       root      345: }
                    346: 
1.1.1.3   root      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:     }
1.1       root      366: }
                    367: 
1.1.1.3   root      368: /* DMA interrupt functions */
                    369: 
                    370: void dma_interrupt(int channel) {
                    371:     int interrupt = get_interrupt_type(channel);
1.1.1.4 ! root      372: 
1.1.1.3   root      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:     }
1.1       root      390: }
                    391: 
                    392: 
1.1.1.3   root      393: /* DMA Read and Write Memory Functions */
1.1       root      394: 
1.1.1.3   root      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);
1.1       root      399:     
1.1.1.3   root      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
1.1       root      460:     
1.1.1.3   root      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
1.1       root      491:     
1.1.1.3   root      492:     dma_interrupt(CHANNEL_SCSI);
                    493: }
1.1       root      494: 
1.1.1.3   root      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);
1.1       root      498:     
1.1.1.3   root      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:     }
1.1       root      508:     
1.1.1.3   root      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
1.1       root      558:     
1.1.1.3   root      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:     }
1.1       root      565:     
1.1.1.3   root      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);
1.1       root      574:     
1.1.1.3   root      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();
1.1       root      583:     }
1.1.1.3   root      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: }
1.1       root      627: 
1.1.1.3   root      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);
1.1       root      631:     
1.1.1.3   root      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);
1.1       root      690: }
                    691: 
                    692: 
1.1.1.4 ! root      693: Uint8* dma_sndout_read_memory(int* len) {
        !           694:     int i;
        !           695:     Uint8* result = NULL;
        !           696:     *len          = 0;
        !           697:     
1.1.1.3   root      698:     if (dma[CHANNEL_SOUNDOUT].csr&DMA_ENABLE) {
1.1.1.4 ! root      699:         
1.1.1.3   root      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);
1.1       root      702:         
1.1.1.4 ! root      703:         if ((dma[CHANNEL_SOUNDOUT].limit&3) || (dma[CHANNEL_SOUNDOUT].next&3)) {
1.1.1.3   root      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);
1.1.1.4 ! root      706:             dma[CHANNEL_SOUNDOUT].next &= ~3;
        !           707:             dma[CHANNEL_SOUNDOUT].limit &= ~3;
1.1.1.3   root      708:         }
                    709:         
                    710:         TRY(prb) {
1.1.1.4 ! root      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);
1.1.1.3   root      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
1.1.1.4 ! root      720:     }
        !           721:     
        !           722:     return result;
        !           723: }
        !           724: 
        !           725: void dma_sndout_intr() {
        !           726:     if (dma[CHANNEL_SOUNDOUT].csr&DMA_ENABLE) {
1.1.1.3   root      727:         dma_interrupt(CHANNEL_SOUNDOUT);
                    728:     }
                    729: }
1.1       root      730: 
1.1.1.4 ! root      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: }
1.1.1.3   root      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);
1.1       root      771:         
1.1.1.3   root      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();
1.1       root      776:         }
1.1.1.3   root      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);
1.1       root      791:     }
1.1.1.3   root      792: }
                    793: 
1.1       root      794: 
1.1.1.3   root      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: 
1.1.1.4 ! root      802: static void dma_enet_interrupt(int channel) {
1.1.1.3   root      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();
1.1       root      832:     }
                    833:     
1.1.1.3   root      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
1.1       root      845:     
1.1.1.3   root      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;
1.1       root      850:         }
1.1.1.3   root      851:         dma[CHANNEL_EN_RX].saved_limit = dma[CHANNEL_EN_RX].next;
1.1       root      852:     }
                    853: 
1.1.1.3   root      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: 
1.1.1.4 ! root      887: Uint32 m2m_buffer[DMA_BURST_SIZE];
        !           888: int m2m_buffer_size;
        !           889: 
        !           890: void M2MDMA_IO_Handler(void) {
        !           891:     CycInt_AcknowledgeInterrupt();
1.1       root      892:     
1.1.1.4 ! root      893:     if (dma[CHANNEL_R2M].csr&DMA_ENABLE) {
        !           894:         dma_m2m_write_memory();
        !           895:         CycInt_AddRelativeInterruptCycles(4, INTERRUPT_M2M_IO);
1.1.1.3   root      896:     }
1.1.1.4 ! root      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) {
1.1       root      916:     
1.1.1.4 ! root      917:     if (dma[CHANNEL_R2M].next<dma[CHANNEL_R2M].limit) {
1.1.1.3   root      918: 
                    919:         if (dma[CHANNEL_M2R].next<dma[CHANNEL_M2R].limit) {
1.1.1.4 ! root      920:             /* (Re)fill the buffer, if there is still data to read */
        !           921:             m2m_buffer_size = 0;
        !           922: 
1.1.1.3   root      923:             TRY(prb) {
1.1.1.4 ! root      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++;
1.1.1.3   root      928:                 }
                    929:             } CATCH(prb) {
1.1.1.4 ! root      930:                 Log_Printf(LOG_WARN, "[DMA] Channel M2M: Bus error while reading from %08x",dma[CHANNEL_M2R].next);
1.1.1.3   root      931:                 dma[CHANNEL_M2R].csr &= ~DMA_ENABLE;
                    932:                 dma[CHANNEL_M2R].csr |= (DMA_COMPLETE|DMA_BUSEXC);
                    933:             } ENDTRY
                    934:             
1.1.1.4 ! root      935:             dma_interrupt(CHANNEL_M2R);
        !           936:         } else {
        !           937:             /* Re-use data in buffer */
        !           938:             m2m_buffer_size = DMA_BURST_SIZE;
1.1.1.3   root      939:         }
                    940:         
                    941:         TRY(prb) {
                    942:             /* Write the contents of the buffer to memory */
1.1.1.4 ! root      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++;
1.1.1.3   root      947:             }
                    948:         } CATCH(prb) {
1.1.1.4 ! root      949:             Log_Printf(LOG_WARN, "[DMA] Channel M2M: Bus error while writing to %08x",dma[CHANNEL_R2M].next);
1.1.1.3   root      950:             dma[CHANNEL_R2M].csr &= ~DMA_ENABLE;
                    951:             dma[CHANNEL_R2M].csr |= (DMA_COMPLETE|DMA_BUSEXC);
                    952:         } ENDTRY
1.1       root      953:     }
1.1.1.4 ! root      954:     
        !           955:     dma_interrupt(CHANNEL_R2M);
1.1.1.3   root      956: }
1.1       root      957: 
1.1.1.3   root      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:     }
1.1       root     1056:     
1.1.1.3   root     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;
1.1.1.4 ! root     1112:                case TDMA_BUFRESET:
        !          1113:                        Log_Printf(LOG_DMA_LEVEL,"DMA initialize buffers"); break;
1.1.1.3   root     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);
1.1       root     1193: }

unix.superglobalmegacorp.com

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