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