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

  ViewVC Help
Powered by ViewVC 1.1.22