|
|
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.