/[pcsx2_0.9.7]/trunk/pcsx2/Dmac.h
ViewVC logotype

Contents of /trunk/pcsx2/Dmac.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 10 months ago) by william
File MIME type: text/plain
File size: 15089 byte(s)
committing r3113 initial commit again...
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16
17 #ifndef __DMAC_H__
18 #define __DMAC_H__
19
20 extern u8 *psH; // hw mem
21
22 // Useful enums for some of the fields.
23 enum pce_values
24 {
25 PCE_NOTHING = 0,
26 PCE_RESERVED,
27 PCE_DISABLED,
28 PCE_ENABLED
29 };
30
31
32 enum tag_id
33 {
34 TAG_CNTS = 0,
35 TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end
36 TAG_CNT, // Transfer QWC following the tag.
37 TAG_NEXT, // Transfer QWC following tag. TADR = ADDR
38 TAG_REF, // Transfer QWC from ADDR field
39 TAG_REFS, // Transfer QWC from ADDR field (Stall Control)
40 TAG_CALL, // Transfer QWC following the tag, save succeeding tag
41 TAG_RET, // Transfer QWC following the tag, load next tag
42 TAG_END // Transfer QWC following the tag
43 };
44
45 enum mfd_type
46 {
47 NO_MFD = 0,
48 MFD_RESERVED,
49 MFD_VIF1,
50 MFD_GIF
51 };
52
53 enum sts_type
54 {
55 NO_STS = 0,
56 STS_SIF0,
57 STS_fromSPR,
58 STS_fromIPU
59 };
60
61 enum std_type
62 {
63 NO_STD = 0,
64 STD_VIF1,
65 STD_GIF,
66 STD_SIF1
67 };
68
69 enum TransferMode
70 {
71 NORMAL_MODE = 0,
72 CHAIN_MODE,
73 INTERLEAVE_MODE,
74 UNDEFINED_MODE
75 };
76
77 //
78 // --- DMA ---
79 //
80
81 // Doing double duty as both the top 32 bits *and* the lower 32 bits of a chain tag.
82 // Theoretically should probably both be in a u64 together, but with the way the
83 // code is layed out, this is easier for the moment.
84
85 union tDMA_TAG {
86 struct {
87 u32 QWC : 16;
88 u32 reserved2 : 10;
89 u32 PCE : 2;
90 u32 ID : 3;
91 u32 IRQ : 1;
92 };
93 struct {
94 u32 ADDR : 31;
95 u32 SPR : 1;
96 };
97 u32 _u32;
98
99 tDMA_TAG(u32 val) { _u32 = val; }
100 u16 upper() const { return (_u32 >> 16); }
101 u16 lower() const { return (u16)_u32; }
102 wxString tag_to_str() const
103 {
104 switch(ID)
105 {
106 case TAG_REFE: return wxsFormat(L"REFE %08X", _u32); break;
107 case TAG_CNT: return L"CNT"; break;
108 case TAG_NEXT: return wxsFormat(L"NEXT %08X", _u32); break;
109 case TAG_REF: return wxsFormat(L"REF %08X", _u32); break;
110 case TAG_REFS: return wxsFormat(L"REFS %08X", _u32); break;
111 case TAG_CALL: return L"CALL"; break;
112 case TAG_RET: return L"RET"; break;
113 case TAG_END: return L"END"; break;
114 default: return L"????"; break;
115 }
116 }
117 void reset() { _u32 = 0; }
118 };
119 #define DMA_TAG(value) ((tDMA_TAG)(value))
120
121 union tDMA_CHCR {
122 struct {
123 u32 DIR : 1; // Direction: 0 - to memory, 1 - from memory. VIF1 & SIF2 only.
124 u32 reserved1 : 1;
125 u32 MOD : 2;
126 u32 ASP : 2; // ASP1 & ASP2; Address stack pointer. 0, 1, or 2 addresses.
127 u32 TTE : 1; // Tag Transfer Enable. 0 - Disable / 1 - Enable.
128 u32 TIE : 1; // Tag Interrupt Enable. 0 - Disable / 1 - Enable.
129 u32 STR : 1; // Start. 0 while stopping DMA, 1 while it's running.
130 u32 reserved2 : 7;
131 u32 TAG : 16;
132 };
133 u32 _u32;
134
135 tDMA_CHCR( u32 val) { _u32 = val; }
136
137 bool test(u32 flags) const { return !!(_u32 & flags); }
138 void set(u32 value) { _u32 = value; }
139 void set_flags(u32 flags) { _u32 |= flags; }
140 void clear_flags(u32 flags) { _u32 &= ~flags; }
141 void reset() { _u32 = 0; }
142 u16 upper() const { return (_u32 >> 16); }
143 u16 lower() const { return (u16)_u32; }
144 wxString desc() const { return wxsFormat(L"Chcr: 0x%x", _u32); }
145 };
146
147 #define CHCR(value) ((tDMA_CHCR)(value))
148
149 union tDMA_SADR {
150 struct {
151 u32 ADDR : 14;
152 u32 reserved2 : 18;
153 };
154 u32 _u32;
155
156 tDMA_SADR(u32 val) { _u32 = val; }
157
158 void reset() { _u32 = 0; }
159 wxString desc() const { return wxsFormat(L"Sadr: 0x%x", _u32); }
160 };
161
162 union tDMA_MADR {
163 struct {
164 u32 ADDR : 31; // Transfer memory address
165 u32 SPR : 1; // Memory/SPR Address
166 };
167 u32 _u32;
168
169 tDMA_MADR(u32 val) { _u32 = val; }
170
171 void reset() { _u32 = 0; }
172 wxString desc() const { return wxsFormat(L"Madr: 0x%x", _u32); }
173 };
174
175 union tDMA_TADR {
176 struct {
177 u32 ADDR : 31; // Next Tag address
178 u32 SPR : 1; // Memory/SPR Address
179 };
180 u32 _u32;
181
182 tDMA_TADR(u32 val) { _u32 = val; }
183
184 void reset() { _u32 = 0; }
185 wxString desc() const { return wxsFormat(L"Tadr: 0x%x", _u32); }
186 };
187
188 union tDMA_ASR { // The Address Stack Register
189 struct {
190 u32 ADDR : 31; // Tag memory address
191 u32 SPR : 1; // Memory/SPR Address
192 };
193 u32 _u32;
194
195 tDMA_ASR(u32 val) { _u32 = val; }
196
197 void reset() { _u32 = 0; }
198 wxString desc() const { return wxsFormat(L"Asr: 0x%x", _u32); }
199 };
200
201 union tDMA_QWC {
202 struct {
203 u32 QWC : 16;
204 u32 reserved2 : 16;
205 };
206 u32 _u32;
207
208 tDMA_QWC(u32 val) { _u32 = val; }
209
210 void reset() { _u32 = 0; }
211 wxString desc() const { return wxsFormat(L"QWC: 0x%x", _u32); }
212 };
213 static __forceinline void setDmacStat(u32 num);
214 static __forceinline tDMA_TAG *dmaGetAddr(u32 addr, bool write);
215 static __forceinline void throwBusError(const char *s);
216
217 struct DMACh {
218 tDMA_CHCR chcr;
219 u32 null0[3];
220 u32 madr;
221 u32 null1[3];
222 u16 qwc; u16 pad;
223 u32 null2[3];
224 u32 tadr;
225 u32 null3[3];
226 u32 asr0;
227 u32 null4[3];
228 u32 asr1;
229 u32 null5[11];
230 u32 sadr;
231
232 void chcrTransfer(tDMA_TAG* ptag)
233 {
234 chcr.TAG = ptag[0].upper();
235 }
236
237 void qwcTransfer(tDMA_TAG* ptag)
238 {
239 qwc = ptag[0].QWC;
240 }
241
242 bool transfer(const char *s, tDMA_TAG* ptag)
243 {
244 if (ptag == NULL) // Is ptag empty?
245 {
246 throwBusError(s);
247 return false;
248 }
249 chcrTransfer(ptag);
250
251 qwcTransfer(ptag);
252 return true;
253 }
254
255 void unsafeTransfer(tDMA_TAG* ptag)
256 {
257 chcrTransfer(ptag);
258 qwcTransfer(ptag);
259 }
260
261 tDMA_TAG *getAddr(u32 addr, u32 num, bool write)
262 {
263 tDMA_TAG *ptr = dmaGetAddr(addr, write);
264 if (ptr == NULL)
265 {
266 throwBusError("dmaGetAddr");
267 setDmacStat(num);
268 chcr.STR = false;
269 }
270
271 return ptr;
272 }
273
274 tDMA_TAG *DMAtransfer(u32 addr, u32 num)
275 {
276 tDMA_TAG *tag = getAddr(addr, num, false);
277
278 if (tag == NULL) return NULL;
279
280 chcrTransfer(tag);
281 qwcTransfer(tag);
282 return tag;
283 }
284
285 tDMA_TAG dma_tag() const
286 {
287 return DMA_TAG(chcr._u32);
288 }
289
290 wxString cmq_to_str() const
291 {
292 return wxsFormat(L"chcr = %lx, madr = %lx, qwc = %lx", chcr._u32, madr, qwc);
293 }
294
295 wxString cmqt_to_str() const
296 {
297 return wxsFormat(L"chcr = %lx, madr = %lx, qwc = %lx, tadr = %1x", chcr._u32, madr, qwc, tadr);
298 }
299 };
300
301 enum INTCIrqs
302 {
303 INTC_GS = 0,
304 INTC_SBUS,
305 INTC_VBLANK_S,
306 INTC_VBLANK_E,
307 INTC_VIF0,
308 INTC_VIF1,
309 INTC_VU0,
310 INTC_VU1,
311 INTC_IPU,
312 INTC_TIM0,
313 INTC_TIM1,
314 INTC_TIM2,
315 INTC_TIM3,
316 INTC_SFIFO,
317 INTVU0_WD
318 };
319
320 enum dmac_conditions
321 {
322 DMAC_STAT_SIS = (1<<13), // stall condition
323 DMAC_STAT_MEIS = (1<<14), // mfifo empty
324 DMAC_STAT_BEIS = (1<<15), // bus error
325 DMAC_STAT_SIM = (1<<29), // stall mask
326 DMAC_STAT_MEIM = (1<<30) // mfifo mask
327 };
328
329 enum DMACIrqs
330 {
331 DMAC_VIF0 = 0,
332 DMAC_VIF1,
333 DMAC_GIF,
334 DMAC_FROM_IPU,
335 DMAC_TO_IPU,
336 DMAC_SIF0,
337 DMAC_SIF1,
338 DMAC_SIF2,
339 DMAC_FROM_SPR,
340 DMAC_TO_SPR,
341
342 // We're setting error conditions through hwDmacIrq, so these correspond to the conditions above.
343 DMAC_STALL_SIS = 13, // SIS
344 DMAC_MFIFO_EMPTY = 14, // MEIS
345 DMAC_BUS_ERROR = 15 // BEIS
346 };
347
348 //DMA interrupts & masks
349 enum DMAInter
350 {
351 BEISintr = 0x00008000,
352 VIF0intr = 0x00010001,
353 VIF1intr = 0x00020002,
354 GIFintr = 0x00040004,
355 IPU0intr = 0x00080008,
356 IPU1intr = 0x00100010,
357 SIF0intr = 0x00200020,
358 SIF1intr = 0x00400040,
359 SIF2intr = 0x00800080,
360 SPR0intr = 0x01000100,
361 SPR1intr = 0x02000200,
362 SISintr = 0x20002000,
363 MEISintr = 0x40004000
364 };
365
366 union tDMAC_QUEUE
367 {
368 struct
369 {
370 u16 VIF0 : 1;
371 u16 VIF1 : 1;
372 u16 GIF : 1;
373 u16 IPU0 : 1;
374 u16 IPU1 : 1;
375 u16 SIF0 : 1;
376 u16 SIF1 : 1;
377 u16 SIF2 : 1;
378 u16 SPR0 : 1;
379 u16 SPR1 : 1;
380 u16 SIS : 1;
381 u16 MEIS : 1;
382 u16 BEIS : 1;
383 };
384 u16 _u16;
385
386 tDMAC_QUEUE(u16 val) { _u16 = val; }
387 void reset() { _u16 = 0; }
388 bool empty() const { return (_u16 == 0); }
389 };
390
391 static __forceinline const wxChar* ChcrName(u32 addr)
392 {
393 switch (addr)
394 {
395 case D0_CHCR: return L"Vif 0";
396 case D1_CHCR: return L"Vif 1";
397 case D2_CHCR: return L"GIF";
398 case D3_CHCR: return L"Ipu 0";
399 case D4_CHCR: return L"Ipu 1";
400 case D5_CHCR: return L"Sif 0";
401 case D6_CHCR: return L"Sif 1";
402 case D7_CHCR: return L"Sif 2";
403 case D8_CHCR: return L"SPR 0";
404 case D9_CHCR: return L"SPR 1";
405 default: return L"???";
406 }
407 }
408
409 // Believe it or not, making this const can generate compiler warnings in gcc.
410 static __forceinline int ChannelNumber(u32 addr)
411 {
412 switch (addr)
413 {
414 case D0_CHCR: return 0;
415 case D1_CHCR: return 1;
416 case D2_CHCR: return 2;
417 case D3_CHCR: return 3;
418 case D4_CHCR: return 4;
419 case D5_CHCR: return 5;
420 case D6_CHCR: return 6;
421 case D7_CHCR: return 7;
422 case D8_CHCR: return 8;
423 case D9_CHCR: return 9;
424 default:
425 {
426 DevCon.Warning("Invalid DMA channel number");
427 return 51; // some value
428 }
429 }
430 }
431
432 union tDMAC_CTRL {
433 struct {
434 u32 DMAE : 1; // 0/1 - disables/enables all DMAs
435 u32 RELE : 1; // 0/1 - cycle stealing off/on
436 u32 MFD : 2; // Memory FIFO drain channel (mfd_type)
437 u32 STS : 2; // Stall Control source channel (sts type)
438 u32 STD : 2; // Stall Control drain channel (std_type)
439 u32 RCYC : 3; // Release cycle (8/16/32/64/128/256)
440 u32 reserved1 : 21;
441 };
442 u32 _u32;
443
444 tDMAC_CTRL(u32 val) { _u32 = val; }
445
446 bool test(u32 flags) const { return !!(_u32 & flags); }
447 void set_flags(u32 flags) { _u32 |= flags; }
448 void clear_flags(u32 flags) { _u32 &= ~flags; }
449 void reset() { _u32 = 0; }
450 wxString desc() const { return wxsFormat(L"Ctrl: 0x%x", _u32); }
451 };
452
453 union tDMAC_STAT {
454 struct {
455 u32 CIS : 10;
456 u32 reserved1 : 3;
457 u32 SIS : 1;
458 u32 MEIS : 1;
459 u32 BEIS : 1;
460 u32 CIM : 10;
461 u32 reserved2 : 3;
462 u32 SIM : 1;
463 u32 MEIM : 1;
464 u32 reserved3 : 1;
465 };
466 u32 _u32;
467
468 tDMAC_STAT(u32 val) { _u32 = val; }
469
470 bool test(u32 flags) const { return !!(_u32 & flags); }
471 void set_flags(u32 flags) { _u32 |= flags; }
472 void clear_flags(u32 flags) { _u32 &= ~flags; }
473 void reset() { _u32 = 0; }
474 wxString desc() const { return wxsFormat(L"Stat: 0x%x", _u32); }
475 };
476
477 union tDMAC_PCR {
478 struct {
479 u32 CPC : 10;
480 u32 reserved1 : 6;
481 u32 CDE : 10;
482 u32 reserved2 : 5;
483 u32 PCE : 1;
484 };
485 u32 _u32;
486
487 tDMAC_PCR(u32 val) { _u32 = val; }
488
489 bool test(u32 flags) const { return !!(_u32 & flags); }
490 void set_flags(u32 flags) { _u32 |= flags; }
491 void clear_flags(u32 flags) { _u32 &= ~flags; }
492 void reset() { _u32 = 0; }
493 wxString desc() const { return wxsFormat(L"Pcr: 0x%x", _u32); }
494 };
495
496 union tDMAC_SQWC {
497 struct {
498 u32 SQWC : 8;
499 u32 reserved1 : 8;
500 u32 TQWC : 8;
501 u32 reserved2 : 8;
502 };
503 u32 _u32;
504
505 tDMAC_SQWC(u32 val) { _u32 = val; }
506
507 bool test(u32 flags) const { return !!(_u32 & flags); }
508 void set_flags(u32 flags) { _u32 |= flags; }
509 void clear_flags(u32 flags) { _u32 &= ~flags; }
510 void reset() { _u32 = 0; }
511 wxString desc() const { return wxsFormat(L"Sqwc: 0x%x", _u32); }
512 };
513
514 union tDMAC_RBSR {
515 struct {
516 u32 RMSK : 31;
517 u32 reserved1 : 1;
518 };
519 u32 _u32;
520
521 tDMAC_RBSR(u32 val) { _u32 = val; }
522
523 void reset() { _u32 = 0; }
524 wxString desc() const { return wxsFormat(L"Rbsr: 0x%x", _u32); }
525 };
526
527 union tDMAC_RBOR {
528 struct {
529 u32 ADDR : 31;
530 u32 reserved1 : 1;
531 };
532 u32 _u32;
533
534 tDMAC_RBOR(u32 val) { _u32 = val; }
535
536 void reset() { _u32 = 0; }
537 wxString desc() const { return wxsFormat(L"Rbor: 0x%x", _u32); }
538 };
539
540 union tDMAC_STADR {
541 struct {
542 u32 ADDR : 31;
543 u32 reserved1 : 1;
544 };
545 u32 _u32;
546
547 tDMAC_STADR(u32 val) { _u32 = val; }
548
549 void reset() { _u32 = 0; }
550 wxString desc() const { return wxsFormat(L"Stadr: 0x%x", _u32); }
551 };
552
553
554 struct DMACregisters
555 {
556 tDMAC_CTRL ctrl;
557 u32 padding[3];
558 tDMAC_STAT stat;
559 u32 padding1[3];
560 tDMAC_PCR pcr;
561 u32 padding2[3];
562
563 tDMAC_SQWC sqwc;
564 u32 padding3[3];
565 tDMAC_RBSR rbsr;
566 u32 padding4[3];
567 tDMAC_RBOR rbor;
568 u32 padding5[3];
569 tDMAC_STADR stadr;
570 };
571
572 // Currently guesswork.
573 union tINTC_STAT {
574 struct {
575 u32 interrupts : 10;
576 u32 placeholder : 22;
577 };
578 u32 _u32;
579
580 tINTC_STAT(u32 val) { _u32 = val; }
581
582 bool test(u32 flags) const { return !!(_u32 & flags); }
583 void set_flags(u32 flags) { _u32 |= flags; }
584 void clear_flags(u32 flags) { _u32 &= ~flags; }
585 void reset() { _u32 = 0; }
586 wxString desc() const { return wxsFormat(L"Stat: 0x%x", _u32); }
587 };
588
589 union tINTC_MASK {
590 struct {
591 u32 int_mask : 10;
592 u32 placeholder:22;
593 };
594 u32 _u32;
595
596 tINTC_MASK(u32 val) { _u32 = val; }
597
598 bool test(u32 flags) const { return !!(_u32 & flags); }
599 void set_flags(u32 flags) { _u32 |= flags; }
600 void clear_flags(u32 flags) { _u32 &= ~flags; }
601 void reset() { _u32 = 0; }
602 wxString desc() const { return wxsFormat(L"Mask: 0x%x", _u32); }
603 };
604
605 struct INTCregisters
606 {
607 tINTC_STAT stat;
608 u32 padding[3];
609 tINTC_MASK mask;
610 };
611
612 #define dmacRegs ((DMACregisters*)(PS2MEM_HW+0xE000))
613 #define intcRegs ((INTCregisters*)(PS2MEM_HW+0xF000))
614
615 static __forceinline void throwBusError(const char *s)
616 {
617 Console.Error("%s BUSERR", s);
618 dmacRegs->stat.BEIS = true;
619 }
620
621 static __forceinline void setDmacStat(u32 num)
622 {
623 dmacRegs->stat.set_flags(1 << num);
624 }
625
626 // Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
627 static __forceinline tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write)
628 {
629 // if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
630
631 // FIXME: Why??? DMA uses physical addresses
632 addr &= 0x1ffffff0;
633
634 if (addr < Ps2MemSize::Base)
635 {
636 return (tDMA_TAG*)&psM[addr];
637 }
638
639 if (addr >= 0x11004000 && addr < 0x11010000)
640 {
641 //Access for VU Memory
642 return (tDMA_TAG*)vtlb_GetPhyPtr(addr & 0x1FFFFFF0);
643 }
644
645 if (addr >= Ps2MemSize::Base && addr < 0x10000000)
646 {
647 return (tDMA_TAG*)(write ? psMHW : psMHR);
648 }
649
650 Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
651 return NULL;
652 }
653
654 // Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
655 static __forceinline tDMA_TAG *dmaGetAddr(u32 addr, bool write)
656 {
657 // if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
658
659 if (DMA_TAG(addr).SPR) return (tDMA_TAG*)&psS[addr & 0x3ff0];
660
661 // FIXME: Why??? DMA uses physical addresses
662 addr &= 0x1ffffff0;
663
664 if (addr < Ps2MemSize::Base)
665 {
666 return (tDMA_TAG*)&psM[addr];
667 }
668
669 // Secret scratchpad address for DMA = end of maximum main memory?
670 if (addr >= 0x10000000 && addr < 0x10004000)
671 {
672 //Console.Warning("Writing to the scratchpad without the SPR flag set!");
673 return (tDMA_TAG*)&psS[addr & 0x3ff0];
674 }
675
676 if (addr >= Ps2MemSize::Base && addr < 0x10000000)
677 {
678 return (tDMA_TAG*)(write ? psMHW : psMHR);
679 }
680
681 Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
682 return NULL;
683 }
684
685 void hwIntcIrq(int n);
686 void hwDmacIrq(int n);
687
688 bool hwDmacSrcChainWithStack(DMACh *dma, int id);
689 bool hwDmacSrcChain(DMACh *dma, int id);
690
691 extern void intcInterrupt();
692 extern void dmacInterrupt();
693
694 #endif

  ViewVC Help
Powered by ViewVC 1.1.22