/[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 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 2 months ago) by william
File MIME type: text/plain
File size: 13274 byte(s)
re-commit (had local access denied errors when committing)
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 #pragma once
17
18 // Useful enums for some of the fields.
19 enum pce_values
20 {
21 PCE_NOTHING = 0,
22 PCE_RESERVED,
23 PCE_DISABLED,
24 PCE_ENABLED
25 };
26
27
28 enum tag_id
29 {
30 TAG_CNTS = 0,
31 TAG_REFE = 0, // Transfer Packet According to ADDR field, clear STR, and end
32 TAG_CNT, // Transfer QWC following the tag.
33 TAG_NEXT, // Transfer QWC following tag. TADR = ADDR
34 TAG_REF, // Transfer QWC from ADDR field
35 TAG_REFS, // Transfer QWC from ADDR field (Stall Control)
36 TAG_CALL, // Transfer QWC following the tag, save succeeding tag
37 TAG_RET, // Transfer QWC following the tag, load next tag
38 TAG_END // Transfer QWC following the tag
39 };
40
41 enum mfd_type
42 {
43 NO_MFD = 0,
44 MFD_RESERVED,
45 MFD_VIF1,
46 MFD_GIF
47 };
48
49 enum sts_type
50 {
51 NO_STS = 0,
52 STS_SIF0,
53 STS_fromSPR,
54 STS_fromIPU
55 };
56
57 enum std_type
58 {
59 NO_STD = 0,
60 STD_VIF1,
61 STD_GIF,
62 STD_SIF1
63 };
64
65 enum LogicalTransferMode
66 {
67 NORMAL_MODE = 0,
68 CHAIN_MODE,
69 INTERLEAVE_MODE,
70 UNDEFINED_MODE
71 };
72
73 //
74 // --- DMA ---
75 //
76
77 // Doing double duty as both the top 32 bits *and* the lower 32 bits of a chain tag.
78 // Theoretically should probably both be in a u64 together, but with the way the
79 // code is layed out, this is easier for the moment.
80
81 union tDMA_TAG {
82 struct {
83 u32 QWC : 16;
84 u32 _reserved2 : 10;
85 u32 PCE : 2;
86 u32 ID : 3;
87 u32 IRQ : 1;
88 };
89 struct {
90 u32 ADDR : 31;
91 u32 SPR : 1;
92 };
93 u32 _u32;
94
95 tDMA_TAG() {}
96
97 tDMA_TAG(u32 val) { _u32 = val; }
98 u16 upper() const { return (_u32 >> 16); }
99 u16 lower() const { return (u16)_u32; }
100 wxString tag_to_str() const
101 {
102 switch(ID)
103 {
104 case TAG_REFE: return wxsFormat(L"REFE %08X", _u32); break;
105 case TAG_CNT: return L"CNT"; break;
106 case TAG_NEXT: return wxsFormat(L"NEXT %08X", _u32); break;
107 case TAG_REF: return wxsFormat(L"REF %08X", _u32); break;
108 case TAG_REFS: return wxsFormat(L"REFS %08X", _u32); break;
109 case TAG_CALL: return L"CALL"; break;
110 case TAG_RET: return L"RET"; break;
111 case TAG_END: return L"END"; break;
112 default: return L"????"; break;
113 }
114 }
115 void reset() { _u32 = 0; }
116 };
117 #define DMA_TAG(value) ((tDMA_TAG)(value))
118
119 union tDMA_CHCR {
120 struct {
121 u32 DIR : 1; // Direction: 0 - to memory, 1 - from memory. VIF1 & SIF2 only.
122 u32 _reserved1 : 1;
123 u32 MOD : 2; // Logical transfer mode. Normal, Chain, or Interleave (see LogicalTransferMode enum)
124 u32 ASP : 2; // ASP1 & ASP2; Address stack pointer. 0, 1, or 2 addresses.
125 u32 TTE : 1; // Tag Transfer Enable. 0 - Disable / 1 - Enable.
126 u32 TIE : 1; // Tag Interrupt Enable. 0 - Disable / 1 - Enable.
127 u32 STR : 1; // Start. 0 while stopping DMA, 1 while it's running.
128 u32 _reserved2 : 7;
129 u32 TAG : 16; // Maintains upper 16 bits of the most recently read DMAtag.
130 };
131 u32 _u32;
132
133 tDMA_CHCR( u32 val) { _u32 = val; }
134
135 bool test(u32 flags) const { return !!(_u32 & flags); }
136 void set(u32 value) { _u32 = value; }
137 void set_flags(u32 flags) { _u32 |= flags; }
138 void clear_flags(u32 flags) { _u32 &= ~flags; }
139 void reset() { _u32 = 0; }
140 u16 upper() const { return (_u32 >> 16); }
141 u16 lower() const { return (u16)_u32; }
142 wxString desc() const { return wxsFormat(L"Chcr: 0x%x", _u32); }
143 tDMA_TAG tag() { return (tDMA_TAG)_u32; }
144 };
145
146 #define CHCR(value) ((tDMA_CHCR)(value))
147
148 union tDMA_SADR {
149 struct {
150 u32 ADDR : 14;
151 u32 reserved2 : 18;
152 };
153 u32 _u32;
154
155 tDMA_SADR(u32 val) { _u32 = val; }
156
157 void reset() { _u32 = 0; }
158 wxString desc() const { return wxsFormat(L"Sadr: 0x%x", _u32); }
159 tDMA_TAG tag() const { return (tDMA_TAG)_u32; }
160 };
161
162 union tDMA_QWC {
163 struct {
164 u16 QWC;
165 u16 _unused;
166 };
167 u32 _u32;
168
169 tDMA_QWC(u32 val) { _u32 = val; }
170
171 void reset() { _u32 = 0; }
172 wxString desc() const { return wxsFormat(L"QWC: 0x%04x", QWC); }
173 tDMA_TAG tag() const { return (tDMA_TAG)_u32; }
174 };
175
176 struct DMACh {
177 tDMA_CHCR chcr;
178 u32 _null0[3];
179 u32 madr;
180 u32 _null1[3];
181 u16 qwc; u16 pad;
182 u32 _null2[3];
183 u32 tadr;
184 u32 _null3[3];
185 u32 asr0;
186 u32 _null4[3];
187 u32 asr1;
188 u32 _null5[11];
189 u32 sadr;
190
191 void chcrTransfer(tDMA_TAG* ptag)
192 {
193 chcr.TAG = ptag[0].upper();
194 }
195
196 void qwcTransfer(tDMA_TAG* ptag)
197 {
198 qwc = ptag[0].QWC;
199 }
200
201 bool transfer(const char *s, tDMA_TAG* ptag);
202 void unsafeTransfer(tDMA_TAG* ptag);
203 tDMA_TAG *getAddr(u32 addr, u32 num, bool write);
204 tDMA_TAG *DMAtransfer(u32 addr, u32 num);
205 tDMA_TAG dma_tag();
206
207 wxString cmq_to_str() const;
208 wxString cmqt_to_str() const;
209 };
210
211 enum INTCIrqs
212 {
213 INTC_GS = 0,
214 INTC_SBUS,
215 INTC_VBLANK_S,
216 INTC_VBLANK_E,
217 INTC_VIF0,
218 INTC_VIF1,
219 INTC_VU0,
220 INTC_VU1,
221 INTC_IPU,
222 INTC_TIM0,
223 INTC_TIM1,
224 INTC_TIM2,
225 INTC_TIM3,
226 INTC_SFIFO,
227 INTVU0_WD
228 };
229
230 enum dmac_conditions
231 {
232 DMAC_STAT_SIS = (1<<13), // stall condition
233 DMAC_STAT_MEIS = (1<<14), // mfifo empty
234 DMAC_STAT_BEIS = (1<<15), // bus error
235 DMAC_STAT_SIM = (1<<29), // stall mask
236 DMAC_STAT_MEIM = (1<<30) // mfifo mask
237 };
238
239 //DMA interrupts & masks
240 enum DMAInter
241 {
242 BEISintr = 0x00008000,
243 VIF0intr = 0x00010001,
244 VIF1intr = 0x00020002,
245 GIFintr = 0x00040004,
246 IPU0intr = 0x00080008,
247 IPU1intr = 0x00100010,
248 SIF0intr = 0x00200020,
249 SIF1intr = 0x00400040,
250 SIF2intr = 0x00800080,
251 SPR0intr = 0x01000100,
252 SPR1intr = 0x02000200,
253 SISintr = 0x20002000,
254 MEISintr = 0x40004000
255 };
256
257 union tDMAC_QUEUE
258 {
259 struct
260 {
261 u16 VIF0 : 1;
262 u16 VIF1 : 1;
263 u16 GIF : 1;
264 u16 IPU0 : 1;
265 u16 IPU1 : 1;
266 u16 SIF0 : 1;
267 u16 SIF1 : 1;
268 u16 SIF2 : 1;
269 u16 SPR0 : 1;
270 u16 SPR1 : 1;
271 u16 SIS : 1;
272 u16 MEIS : 1;
273 u16 BEIS : 1;
274 };
275 u16 _u16;
276
277 tDMAC_QUEUE(u16 val) { _u16 = val; }
278 void reset() { _u16 = 0; }
279 bool empty() const { return (_u16 == 0); }
280 };
281
282 static __fi const wxChar* ChcrName(u32 addr)
283 {
284 switch (addr)
285 {
286 case D0_CHCR: return L"Vif 0";
287 case D1_CHCR: return L"Vif 1";
288 case D2_CHCR: return L"GIF";
289 case D3_CHCR: return L"Ipu 0";
290 case D4_CHCR: return L"Ipu 1";
291 case D5_CHCR: return L"Sif 0";
292 case D6_CHCR: return L"Sif 1";
293 case D7_CHCR: return L"Sif 2";
294 case D8_CHCR: return L"SPR 0";
295 case D9_CHCR: return L"SPR 1";
296 default: return L"???";
297 }
298 }
299
300 // Believe it or not, making this const can generate compiler warnings in gcc.
301 static __fi int ChannelNumber(u32 addr)
302 {
303 switch (addr)
304 {
305 case D0_CHCR: return 0;
306 case D1_CHCR: return 1;
307 case D2_CHCR: return 2;
308 case D3_CHCR: return 3;
309 case D4_CHCR: return 4;
310 case D5_CHCR: return 5;
311 case D6_CHCR: return 6;
312 case D7_CHCR: return 7;
313 case D8_CHCR: return 8;
314 case D9_CHCR: return 9;
315 default:
316 {
317 pxFailDev("Invalid DMA channel number");
318 return 51; // some value
319 }
320 }
321 }
322
323 union tDMAC_CTRL {
324 struct {
325 u32 DMAE : 1; // 0/1 - disables/enables all DMAs
326 u32 RELE : 1; // 0/1 - cycle stealing off/on
327 u32 MFD : 2; // Memory FIFO drain channel (mfd_type)
328 u32 STS : 2; // Stall Control source channel (sts type)
329 u32 STD : 2; // Stall Control drain channel (std_type)
330 u32 RCYC : 3; // Release cycle (8/16/32/64/128/256)
331 u32 _reserved1 : 21;
332 };
333 u32 _u32;
334
335 tDMAC_CTRL(u32 val) { _u32 = val; }
336
337 bool test(u32 flags) const { return !!(_u32 & flags); }
338 void set_flags(u32 flags) { _u32 |= flags; }
339 void clear_flags(u32 flags) { _u32 &= ~flags; }
340 void reset() { _u32 = 0; }
341 wxString desc() const { return wxsFormat(L"Ctrl: 0x%x", _u32); }
342 };
343
344 union tDMAC_STAT {
345 struct {
346 u32 CIS : 10;
347 u32 _reserved1 : 3;
348 u32 SIS : 1;
349 u32 MEIS : 1;
350 u32 BEIS : 1;
351 u32 CIM : 10;
352 u32 _reserved2 : 3;
353 u32 SIM : 1;
354 u32 MEIM : 1;
355 u32 _reserved3 : 1;
356 };
357 u32 _u32;
358 u16 _u16[2];
359
360 tDMAC_STAT(u32 val) { _u32 = val; }
361
362 bool test(u32 flags) const { return !!(_u32 & flags); }
363 void set_flags(u32 flags) { _u32 |= flags; }
364 void clear_flags(u32 flags) { _u32 &= ~flags; }
365 void reset() { _u32 = 0; }
366 wxString desc() const { return wxsFormat(L"Stat: 0x%x", _u32); }
367
368 bool TestForInterrupt() const
369 {
370 return ((_u16[0] & _u16[1]) != 0) || BEIS;
371 }
372 };
373
374 union tDMAC_PCR {
375 struct {
376 u32 CPC : 10;
377 u32 _reserved1 : 6;
378 u32 CDE : 10;
379 u32 _reserved2 : 5;
380 u32 PCE : 1;
381 };
382 u32 _u32;
383
384 tDMAC_PCR(u32 val) { _u32 = val; }
385
386 bool test(u32 flags) const { return !!(_u32 & flags); }
387 void set_flags(u32 flags) { _u32 |= flags; }
388 void clear_flags(u32 flags) { _u32 &= ~flags; }
389 void reset() { _u32 = 0; }
390 wxString desc() const { return wxsFormat(L"Pcr: 0x%x", _u32); }
391 };
392
393 union tDMAC_SQWC {
394 struct {
395 u32 SQWC : 8;
396 u32 _reserved1 : 8;
397 u32 TQWC : 8;
398 u32 _reserved2 : 8;
399 };
400 u32 _u32;
401
402 tDMAC_SQWC(u32 val) { _u32 = val; }
403
404 bool test(u32 flags) const { return !!(_u32 & flags); }
405 void set_flags(u32 flags) { _u32 |= flags; }
406 void clear_flags(u32 flags) { _u32 &= ~flags; }
407 void reset() { _u32 = 0; }
408 wxString desc() const { return wxsFormat(L"Sqwc: 0x%x", _u32); }
409 };
410
411 union tDMAC_RBSR {
412 struct {
413 u32 RMSK : 31;
414 u32 _reserved1 : 1;
415 };
416 u32 _u32;
417
418 tDMAC_RBSR(u32 val) { _u32 = val; }
419
420 void reset() { _u32 = 0; }
421 wxString desc() const { return wxsFormat(L"Rbsr: 0x%x", _u32); }
422 };
423
424 union tDMAC_RBOR {
425 struct {
426 u32 ADDR : 31;
427 u32 _reserved1 : 1;
428 };
429 u32 _u32;
430
431 tDMAC_RBOR(u32 val) { _u32 = val; }
432
433 void reset() { _u32 = 0; }
434 wxString desc() const { return wxsFormat(L"Rbor: 0x%x", _u32); }
435 };
436
437 // --------------------------------------------------------------------------------------
438 // tDMAC_ADDR
439 // --------------------------------------------------------------------------------------
440 // This struct is used for several DMA address types, including some that do not have
441 // effective SPR bit (the bit is ignored for all addresses that are not "allowed" to access
442 // the scratchpad, including STADR, toSPR.MADR, fromSPR.MADR, etc.).
443 //
444 union tDMAC_ADDR
445 {
446 struct {
447 u32 ADDR : 31; // Transfer memory address
448 u32 SPR : 1; // Memory/SPR Address (only effective for MADR and TADR of non-SPR DMAs)
449 };
450 u32 _u32;
451
452 tDMAC_ADDR() {}
453 tDMAC_ADDR(u32 val) { _u32 = val; }
454
455 void clear() { _u32 = 0; }
456
457 void AssignADDR(uint addr)
458 {
459 ADDR = addr;
460 if (SPR) ADDR &= (Ps2MemSize::Scratch-1);
461 }
462
463 void IncrementQWC(uint incval = 1)
464 {
465 ADDR += incval;
466 if (SPR) ADDR &= (Ps2MemSize::Scratch-1);
467 }
468
469 wxString ToString(bool sprIsValid=true) const
470 {
471 return pxsFmt((sprIsValid && SPR) ? L"0x%04X(SPR)" : L"0x%08X", ADDR);
472 }
473
474 wxCharBuffer ToUTF8(bool sprIsValid=true) const
475 {
476 return FastFormatAscii().Write((sprIsValid && SPR) ? "0x%04X(SPR)" : "0x%08X", ADDR).c_str();
477 }
478 };
479
480 struct DMACregisters
481 {
482 tDMAC_CTRL ctrl;
483 u32 _padding[3];
484 tDMAC_STAT stat;
485 u32 _padding1[3];
486 tDMAC_PCR pcr;
487 u32 _padding2[3];
488
489 tDMAC_SQWC sqwc;
490 u32 _padding3[3];
491 tDMAC_RBSR rbsr;
492 u32 _padding4[3];
493 tDMAC_RBOR rbor;
494 u32 _padding5[3];
495 tDMAC_ADDR stadr;
496 u32 _padding6[3];
497 };
498
499 // Currently guesswork.
500 union tINTC_STAT {
501 struct {
502 u32 interrupts : 10;
503 u32 _placeholder : 22;
504 };
505 u32 _u32;
506
507 tINTC_STAT(u32 val) { _u32 = val; }
508
509 bool test(u32 flags) const { return !!(_u32 & flags); }
510 void set_flags(u32 flags) { _u32 |= flags; }
511 void clear_flags(u32 flags) { _u32 &= ~flags; }
512 void reset() { _u32 = 0; }
513 wxString desc() const { return wxsFormat(L"Stat: 0x%x", _u32); }
514 };
515
516 union tINTC_MASK {
517 struct {
518 u32 int_mask : 10;
519 u32 _placeholder:22;
520 };
521 u32 _u32;
522
523 tINTC_MASK(u32 val) { _u32 = val; }
524
525 bool test(u32 flags) const { return !!(_u32 & flags); }
526 void set_flags(u32 flags) { _u32 |= flags; }
527 void clear_flags(u32 flags) { _u32 &= ~flags; }
528 void reset() { _u32 = 0; }
529 wxString desc() const { return wxsFormat(L"Mask: 0x%x", _u32); }
530 };
531
532 struct INTCregisters
533 {
534 tINTC_STAT stat;
535 u32 _padding1[3];
536 tINTC_MASK mask;
537 u32 _padding2[3];
538 };
539
540 #define intcRegs ((INTCregisters*)(eeHw+0xF000))
541
542 static DMACregisters& dmacRegs = (DMACregisters&)eeHw[0xE000];
543
544 // Various useful locations
545 static DMACh& vif0ch = (DMACh&)eeHw[0x8000];
546 static DMACh& vif1ch = (DMACh&)eeHw[0x9000];
547 static DMACh& gifch = (DMACh&)eeHw[0xA000];
548 static DMACh& spr0ch = (DMACh&)eeHw[0xD000];
549 static DMACh& spr1ch = (DMACh&)eeHw[0xD400];
550
551 extern void throwBusError(const char *s);
552 extern void setDmacStat(u32 num);
553 extern tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write);
554 extern tDMA_TAG *dmaGetAddr(u32 addr, bool write);
555
556 extern void hwIntcIrq(int n);
557 extern void hwDmacIrq(int n);
558
559 extern void FireMFIFOEmpty();
560 extern bool hwMFIFOWrite(u32 addr, const u128* data, uint size_qwc);
561 extern void hwDmacSrcTadrInc(DMACh& dma);
562 extern bool hwDmacSrcChainWithStack(DMACh& dma, int id);
563 extern bool hwDmacSrcChain(DMACh& dma, int id);
564
565 template< uint page > u32 dmacRead32( u32 mem );
566 template< uint page > extern bool dmacWrite32( u32 mem, mem32_t& value );

  ViewVC Help
Powered by ViewVC 1.1.22