The Pedigree Project  0.1
Dma.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "Dma.h"
21 
22 #include "pedigree/kernel/Log.h"
23 #include "pedigree/kernel/processor/PhysicalMemoryManager.h"
24 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
25 
26 Dma::Dma(
27  IoBase *pRegs, IoBase *pFb, NvCard card, NvType type, uintptr_t ramSize)
28  : m_pRegs(pRegs), m_pFramebuffer(pFb), m_Card(card), m_Type(type),
29  m_nRamSize(ramSize), m_nDmaBuffer(0), m_pDmaBuffer(0),
30  m_DmaBuffer("nVidia DMA Buffer"), m_nPut(0), m_nCurrent(0), m_nMax(0),
31  m_nFree(0)
32 {
33  if (!PhysicalMemoryManager::instance().allocateRegion(
34  m_DmaBuffer, 10,
35 #ifdef X86_COMMON
37 #endif
41  {
42  ERROR("NVIDIA: Dma buffer allocation failed!");
43  return;
44  }
45  m_pDmaBuffer = reinterpret_cast<uint32_t *>(m_DmaBuffer.virtualAddress());
46  m_nPut = 0;
47  m_nCurrent = 0;
48 }
49 
50 void Dma::init()
51 {
52  IoBase *pRegs = m_pRegs;
53 
54  // Powerup all nvidia hardware function blocks.
55  pRegs->write32(0x13111111, NV32_PWRUPCTRL);
56  // Enable "enhanced mode" (?)
57  pRegs->write8(0x04, NVCRTCX_REPAINT1);
58 
59  // Set timer numerator to 8 (in b0-15)
60  pRegs->write32(0x00000008, NVACC_PT_NUMERATOR);
61  // Set timer denominator to 3 (in b0-15)
62  pRegs->write32(0x00000003, NVACC_PT_DENOMINATR);
63 
64  // Disable timer-alarm INT requests
65  pRegs->write32(0x00000000, NVACC_PT_INTEN);
66  // Reset timer-alarm INT status bit (b0)
67  pRegs->write32(0xffffffff, NVACC_PT_INTSTAT);
68 
69  // Enable PRAMIN write access on pre NV10 before programming it!
70  if (m_Card == NV04A)
71  {
72  // Set framebuffer config: type = notiling, PRAMIN write access enabled
73  // */
74  pRegs->write32(0x0001114, NV32_PFB_CONFIG_0);
75  }
76  else if (m_Type <= NV40 || m_Type == NV45)
77  {
78  // Setup acc engine 'source' tile addressranges.
79  pRegs->write32(0, NVACC_NV10_FBTIL0AD);
80  pRegs->write32(0, NVACC_NV10_FBTIL1AD);
81  pRegs->write32(0, NVACC_NV10_FBTIL2AD);
82  pRegs->write32(0, NVACC_NV10_FBTIL3AD);
83  pRegs->write32(0, NVACC_NV10_FBTIL4AD);
84  pRegs->write32(0, NVACC_NV10_FBTIL5AD);
85  pRegs->write32(0, NVACC_NV10_FBTIL6AD);
86  pRegs->write32(0, NVACC_NV10_FBTIL7AD);
87  pRegs->write32(m_nRamSize - 1, NVACC_NV10_FBTIL0ED);
88  pRegs->write32(m_nRamSize - 1, NVACC_NV10_FBTIL1ED);
89  pRegs->write32(m_nRamSize - 1, NVACC_NV10_FBTIL2ED);
90  pRegs->write32(m_nRamSize - 1, NVACC_NV10_FBTIL3ED);
91  pRegs->write32(m_nRamSize - 1, NVACC_NV10_FBTIL4ED);
92  pRegs->write32(m_nRamSize - 1, NVACC_NV10_FBTIL5ED);
93  pRegs->write32(m_nRamSize - 1, NVACC_NV10_FBTIL6ED);
94  pRegs->write32(m_nRamSize - 1, NVACC_NV10_FBTIL7ED);
95  }
96  else
97  {
98  ERROR("NVIDIA: Not implemented");
99  }
100 
101  // First clear the entire RAM hashtable (RAMHT).
102  for (int i = 0; i < 0x0400; i++)
103  pRegs->write32(0x00000000, NVACC_HT_HANDL_00 + (i << 2));
104 
105  // Setting up the FIFO handles. I'm keeping the used handles IDENTICAL to
106  // the haiku driver to aid debugging.
107  if (m_Card >= NV40A)
108  {
109  // (first set)
110  pRegs->write32(
111  0x80000000 | NV10_CONTEXT_SURFACES_2D,
112  NVACC_HT_HANDL_00); // 32bit handle (not used)
113  pRegs->write32(
114  0x0010114c, NVACC_HT_VALUE_00); // Instance 0x114c, Channel = 0x00
115 
116  pRegs->write32(
117  0x80000000 | NV_IMAGE_BLIT,
118  NVACC_HT_HANDL_01); // 32bit handle (not used)
119  pRegs->write32(
120  0x00101148, NVACC_HT_VALUE_01); // Instance 0x1148, Channel = 0x00
121 
122  pRegs->write32(
123  0x80000000 | NV4_GDI_RECTANGLE_TEXT,
124  NVACC_HT_HANDL_02); // 32bit handle (not used)
125  pRegs->write32(
126  0x0010114a, NVACC_HT_VALUE_02); // Instance 0x114a, Channel = 0x00
127 
128  // (second set)
129  pRegs->write32(
130  0x80000000 | NV_ROP5_SOLID,
131  NVACC_HT_HANDL_10); // 32bit handle (not used)
132  pRegs->write32(
133  0x00101142, NVACC_HT_VALUE_10); // Instance 0x1142, Channel = 0x00
134 
135  pRegs->write32(
136  0x80000000 | NV_IMAGE_BLACK_RECTANGLE,
137  NVACC_HT_HANDL_11); // 32bit handle (not used)
138  pRegs->write32(
139  0x00101144, NVACC_HT_VALUE_11); // Instance 0x1144, Channel = 0x00
140 
141  pRegs->write32(
142  0x80000000 | NV_IMAGE_PATTERN,
143  NVACC_HT_HANDL_12); // 32bit handle (not used)
144  pRegs->write32(
145  0x00101146, NVACC_HT_VALUE_12); // Instance 0x1146, Channel = 0x00
146 
147  pRegs->write32(
148  0x80000000 | NV_SCALED_IMAGE_FROM_MEMORY,
149  NVACC_HT_HANDL_13); // 32bit handle (not used)
150  pRegs->write32(
151  0x0010114e, NVACC_HT_VALUE_13); // Instance 0x114e, Channel = 0x00
152 
153  // Set up FIFO contexts in instance RAM.
154  pRegs->write32(
155  0x00003000,
156  NVACC_PR_CTX0_R); // DMA page table present and of linear type.
157  pRegs->write32(
158  m_nRamSize - 1,
159  NVACC_PR_CTX1_R); // DMA limit: size is all cardRAM.
160  pRegs->write32(
161  (0x00000000 & 0xfffff000) | 0x00000002,
162  NVACC_PR_CTX2_R); // DMA access type is READ_AND_WRITE;
163  // Memory starts at start of cardRAM (b12-31).
164  pRegs->write32(0x00000002, NVACC_PR_CTX3_R); // Unknown.
165 
166  // Setting up for set '0', command NV_ROP5_SOLID.
167  pRegs->write32(0x02080043, NVACC_PR_CTX0_0); // NVclass 0x43, patchcfg
168  // ROP_AND, nv10+: little
169  // endian.
170  pRegs->write32(0x00000000, NVACC_PR_CTX1_0); // colorspace not set,
171  // notify instance invalid
172  // (b16-31)
173  pRegs->write32(
174  0x00000000, NVACC_PR_CTX2_0); // DMA0 and DMA1 instance invalid
175  pRegs->write32(0x00000000, NVACC_PR_CTX3_0); // Method traps disabled.
176  pRegs->write32(0x00000000, NVACC_PR_CTX0_1); // extra
177  pRegs->write32(0x00000000, NVACC_PR_CTX1_1); // extra
178 
179  // Setting up for set '1', command NV_IMAGE_BLACK_RECTANGLE
180  pRegs->write32(0x02080019, NVACC_PR_CTX0_2); // NVclass 0x019, patchvfg
181  // ROP_AND, nv10+: little
182  // endian.
183  pRegs->write32(0x00000000, NVACC_PR_CTX1_2); // colorspace not set,
184  // notify instance invalid
185  // (b16-31)
186  pRegs->write32(
187  0x00000000, NVACC_PR_CTX2_2); // DMA0 and DMA1 instance invalid
188  pRegs->write32(0x00000000, NVACC_PR_CTX3_2); // Method traps disabled.
189  pRegs->write32(0x00000000, NVACC_PR_CTX0_3); // extra
190  pRegs->write32(0x00000000, NVACC_PR_CTX1_3); // extra
191 
192  // Setting up for set '2', command NV_IMAGE_PATTERN
193  pRegs->write32(0x02080018, NVACC_PR_CTX0_4); // NVclass 0x018, patchcfg
194  // ROP_AND, nv10+: little
195  // endian.
196  pRegs->write32(0x00000000, NVACC_PR_CTX1_4); // colorspace not set,
197  // notify instance invalid
198  // (b16-31)
199  pRegs->write32(
200  0x00000000, NVACC_PR_CTX2_4); // DMA0 and DMA1 instance invalid
201  pRegs->write32(0x00000000, NVACC_PR_CTX3_4); // Method traps disabled.
202  pRegs->write32(0x00000000, NVACC_PR_CTX0_5); // extra
203  pRegs->write32(0x00000000, NVACC_PR_CTX1_5); // extra
204 
205  // Setting up for set '4', command NV12_IMAGE_BLIT
206  pRegs->write32(0x0208009f, NVACC_PR_CTX0_6); // NVclass 0x09f, patchcfg
207  // ROP_AND, nv10+: little
208  // endian
209  pRegs->write32(0x00000000, NVACC_PR_CTX1_6); // colorspace not set,
210  // notify instance invalid
211  // (b16-31)
212  pRegs->write32(
213  0x00001140,
214  NVACC_PR_CTX2_6); // DMA0 instance 0x1140 and DMA1 instance invalid
215  pRegs->write32(
216  0x00001140, NVACC_PR_CTX3_6); // trap 0 is 0x1140, trap 1 disabled.
217  pRegs->write32(0x00000000, NVACC_PR_CTX0_7); // extra
218  pRegs->write32(0x00000000, NVACC_PR_CTX1_7); // extra
219 
220  // Setting up for set '5', command NV4_GDI_RECTANGLE_TEXT
221  pRegs->write32(0x0208004a, NVACC_PR_CTX0_8); // NVclass 0x04a, patchcfg
222  // ROP_AND, nv10+: little
223  // endian
224  pRegs->write32(
225  0x02000000,
226  NVACC_PR_CTX1_8); // colorspace not set, notify instance is 0x0200
227  pRegs->write32(
228  0x00000000, NVACC_PR_CTX2_8); // DMA0 and DMA1 instance invalid
229  pRegs->write32(0x00000000, NVACC_PR_CTX3_8); // Method traps disabled.
230  pRegs->write32(0x00000000, NVACC_PR_CTX0_9); // extra
231  pRegs->write32(0x00000000, NVACC_PR_CTX1_9); // extra
232 
233  // Setting up for set '6', command NV10_CONTEXT_SURFACES_2D
234  pRegs->write32(
235  0x02080062,
236  NVACC_PR_CTX0_A); // NVclass 0x062, nv10+: little endian
237  pRegs->write32(0x00000000, NVACC_PR_CTX1_A); // colorspace not set,
238  // notify instance invalid
239  // (b16-31)
240  pRegs->write32(
241  0x00001140,
242  NVACC_PR_CTX2_A); // DMA0 instance 0x1140 and DMA1 instance invalid
243  pRegs->write32(
244  0x00001140, NVACC_PR_CTX3_A); // trap 0 is 0x1140, trap 1 disabled.
245  pRegs->write32(0x00000000, NVACC_PR_CTX0_B); // extra
246  pRegs->write32(0x00000000, NVACC_PR_CTX1_B); // extra
247 
248  // Setting up for set '7', command NV_SCALED_IMAGE_FROM_MEMORY
249  pRegs->write32(
250  0x02080077, NVACC_PR_CTX0_C); // NVclass 0x77, nv10+: little endian
251  pRegs->write32(0x00000000, NVACC_PR_CTX1_C); // colorspace not set,
252  // notify instance invalid
253  // (b16-31)
254  pRegs->write32(
255  0x00001140,
256  NVACC_PR_CTX2_C); // DMA0 instance 0x1140 and DMA1 instance invalid
257  pRegs->write32(
258  0x00001140, NVACC_PR_CTX3_C); // trap 0 is 0x1140, trap 1 disabled.
259  pRegs->write32(0x00000000, NVACC_PR_CTX0_D); // extra
260  pRegs->write32(0x00000000, NVACC_PR_CTX1_D); // extra
261 
262  // Setup DMA set pointed at by PF_CACH1_DMAI
263  pRegs->write32(
264  0x00003002,
265  NVACC_PR_CTX0_E); // DMA page table present and of linear type.
266  pRegs->write32(
267  0x00007fff, NVACC_PR_CTX1_E); // DMA limit: tablesize is 32k bytes.
268  pRegs->write32(
269  ((m_nRamSize - 1) & 0xffff8000) | 0x00000002,
270  NVACC_PR_CTX2_E); // DMA access in READ_AND_WRITE
271  // table is located at end of cardRAM.
272 
273  m_nDmaBuffer = (m_nRamSize - 1) & 0xffff8000; // This is the index into
274  // the FRAMEBUFFER, not
275  // CTRL area!!
276  }
277  else
278  {
279  // (first set)
280  pRegs->write32(
281  0x80000000 | NV4_SURFACE,
282  NVACC_HT_HANDL_00); // 32bit handle (not used)
283  pRegs->write32(
284  0x80011145, NVACC_HT_VALUE_00); // Instance 0x114c, Channel = 0x00
285 
286  pRegs->write32(
287  0x80000000 | NV_IMAGE_BLIT,
288  NVACC_HT_HANDL_01); // 32bit handle (not used)
289  pRegs->write32(
290  0x80011146, NVACC_HT_VALUE_01); // Instance 0x1148, Channel = 0x00
291 
292  pRegs->write32(
293  0x80000000 | NV4_GDI_RECTANGLE_TEXT,
294  NVACC_HT_HANDL_02); // 32bit handle (not used)
295  pRegs->write32(
296  0x80011147, NVACC_HT_VALUE_02); // Instance 0x114a, Channel = 0x00
297 
298  pRegs->write32(
299  0x80000000 | NV4_CONTEXT_SURFACES_ARGB_ZS,
300  NVACC_HT_HANDL_03); // 32bit handle (not used)
301  pRegs->write32(
302  0x80011148, NVACC_HT_VALUE_03); // Instance 0x114a, Channel = 0x00
303 
304  pRegs->write32(
305  0x80000000 | NV4_DX5_TEXTURE_TRIANGLE,
306  NVACC_HT_HANDL_04); // 32bit handle (not used)
307  pRegs->write32(
308  0x80011149, NVACC_HT_VALUE_04); // Instance 0x114a, Channel = 0x00
309 
310  pRegs->write32(
311  0x80000000 | NV4_DX6_MULTI_TEXTURE_TRIANGLE,
312  NVACC_HT_HANDL_05); // 32bit handle (not used)
313  pRegs->write32(
314  0x8001114a, NVACC_HT_VALUE_05); // Instance 0x114a, Channel = 0x00
315 
316  pRegs->write32(
317  0x80000000 | NV1_RENDER_SOLID_LIN,
318  NVACC_HT_HANDL_06); // 32bit handle (not used)
319  pRegs->write32(
320  0x8001114c, NVACC_HT_VALUE_06); // Instance 0x114a, Channel = 0x00
321 
322  // (second set)
323  pRegs->write32(
324  0x80000000 | NV_ROP5_SOLID,
325  NVACC_HT_HANDL_10); // 32bit handle (not used)
326  pRegs->write32(
327  0x80011142, NVACC_HT_VALUE_10); // Instance 0x1142, Channel = 0x00
328 
329  pRegs->write32(
330  0x80000000 | NV_IMAGE_BLACK_RECTANGLE,
331  NVACC_HT_HANDL_11); // 32bit handle (not used)
332  pRegs->write32(
333  0x80011143, NVACC_HT_VALUE_11); // Instance 0x1143, Channel = 0x00
334 
335  pRegs->write32(
336  0x80000000 | NV_IMAGE_PATTERN,
337  NVACC_HT_HANDL_12); // 32bit handle (not used)
338  pRegs->write32(
339  0x80011144, NVACC_HT_VALUE_12); // Instance 0x1144, Channel = 0x00
340 
341  pRegs->write32(
342  0x80000000 | NV_SCALED_IMAGE_FROM_MEMORY,
343  NVACC_HT_HANDL_13); // 32bit handle (not used)
344  pRegs->write32(
345  0x8001114b, NVACC_HT_VALUE_13); // Instance 0x114B, Channel = 0x00
346 
347  // Set up FIFO contexts in instance RAM.
348  pRegs->write32(
349  0x00003000,
350  NVACC_PR_CTX0_R); // DMA page table present and of linear type.
351  pRegs->write32(
352  m_nRamSize - 1,
353  NVACC_PR_CTX1_R); // DMA limit: size is all cardRAM.
354  pRegs->write32(
355  (0x00000000 & 0xfffff000) | 0x00000002,
356  NVACC_PR_CTX2_R); // DMA access type is READ_AND_WRITE;
357  // Memory starts at start of cardRAM (b12-31).
358  pRegs->write32(0x00000002, NVACC_PR_CTX3_R); // Unknown.
359 
360  // Setting up for set '0', command NV_ROP5_SOLID.
361  pRegs->write32(0x01080043, NVACC_PR_CTX0_0); // NVclass 0x43, patchcfg
362  // ROP_AND, nv10+: little
363  // endian.
364  pRegs->write32(0x00000000, NVACC_PR_CTX1_0); // colorspace not set,
365  // notify instance invalid
366  // (b16-31)
367  pRegs->write32(
368  0x00000000, NVACC_PR_CTX2_0); // DMA0 and DMA1 instance invalid
369  pRegs->write32(0x00000000, NVACC_PR_CTX3_0); // Method traps disabled.
370 
371  // Setting up for set '1', command NV_IMAGE_BLACK_RECTANGLE
372  pRegs->write32(0x01080019, NVACC_PR_CTX0_1); // NVclass 0x019, patchvfg
373  // ROP_AND, nv10+: little
374  // endian.
375  pRegs->write32(0x00000000, NVACC_PR_CTX1_1); // colorspace not set,
376  // notify instance invalid
377  // (b16-31)
378  pRegs->write32(
379  0x00000000, NVACC_PR_CTX2_1); // DMA0 and DMA1 instance invalid
380  pRegs->write32(0x00000000, NVACC_PR_CTX3_1); // Method traps disabled.
381 
382  // Setting up for set '2', command NV_IMAGE_PATTERN
383  pRegs->write32(0x01080018, NVACC_PR_CTX0_2); // NVclass 0x018, patchcfg
384  // ROP_AND, nv10+: little
385  // endian.
386  pRegs->write32(0x00000002, NVACC_PR_CTX1_2); // colorspace not set,
387  // notify instance is
388  // $0200 (b16-31)
389  pRegs->write32(
390  0x00000000, NVACC_PR_CTX2_2); // DMA0 and DMA1 instance invalid
391  pRegs->write32(0x00000000, NVACC_PR_CTX3_2); // Method traps disabled.
392 
393  // Setting up for set '3', command...
394  if (m_Card > NV10A)
395  // NV10_CONTEXT_SURFACES_2D
396  pRegs->write32(0x01008062, NVACC_PR_CTX0_3);
397  else
398  // NV4_SURFACE
399  pRegs->write32(0x01008042, NVACC_PR_CTX0_3);
400  pRegs->write32(0x00000000, NVACC_PR_CTX1_3); // colorspace not set,
401  // notify instance invalid
402  // (b16-31)
403  pRegs->write32(
404  0x11401140, NVACC_PR_CTX2_3); // DMA0 and DMA1 instance invalid
405  pRegs->write32(0x00000000, NVACC_PR_CTX3_3); // Method traps disabled.
406 
407  // Setting up for set '4', command NV12_IMAGE_BLIT
408  if (m_Type >= NV11)
409  pRegs->write32(0x0100809f, NVACC_PR_CTX0_4); // NVclass 0x09f,
410  // patchcfg ROP_AND,
411  // nv10+: little
412  // endian
413  else
414  // ... or NV_IMAGE_BLIT
415  pRegs->write32(0x0100805f, NVACC_PR_CTX0_4);
416  pRegs->write32(0x00000000, NVACC_PR_CTX1_4); // colorspace not set,
417  // notify instance invalid
418  // (b16-31)
419  pRegs->write32(
420  0x11401140,
421  NVACC_PR_CTX2_4); // DMA0 instance 0x1140 and DMA1 instance invalid
422  pRegs->write32(
423  0x00000000, NVACC_PR_CTX3_4); // trap 0 is 0x1140, trap 1 disabled.
424 
425  // Setting up for set '5', command NV4_GDI_RECTANGLE_TEXT
426  pRegs->write32(0x0100804a, NVACC_PR_CTX0_5); // NVclass 0x04a, patchcfg
427  // ROP_AND, nv10+: little
428  // endian
429  pRegs->write32(
430  0x00000002,
431  NVACC_PR_CTX1_5); // colorspace not set, notify instance is 0x0200
432  pRegs->write32(
433  0x00000000, NVACC_PR_CTX2_5); // DMA0 and DMA1 instance invalid
434  pRegs->write32(0x00000000, NVACC_PR_CTX3_5); // Method traps disabled.
435 
436  // Setting up for set '6', command ...
437  if (m_Card >= NV10A)
438  // NV10_CONTEXT_SURFACES_ARGB_ZS
439  pRegs->write32(
440  0x00000093,
441  NVACC_PR_CTX0_6); // NVclass 0x062, nv10+: little endian
442  else
443  // NV4_CONTEXT_SURFACES_ARGB_ZS
444  pRegs->write32(0x00000053, NVACC_PR_CTX0_6);
445  pRegs->write32(0x00000000, NVACC_PR_CTX1_6); // colorspace not set,
446  // notify instance invalid
447  // (b16-31)
448  pRegs->write32(
449  0x11401140,
450  NVACC_PR_CTX2_6); // DMA0 instance 0x1140 and DMA1 instance invalid
451  pRegs->write32(
452  0x00000000, NVACC_PR_CTX3_6); // trap 0 is 0x1140, trap 1 disabled.
453 
454  // Setting up for set '7', command ...
455  if (m_Card >= NV10A)
456  // NV10_DX5_TEXTURE_TRIANGLE
457  pRegs->write32(
458  0x0300a094,
459  NVACC_PR_CTX0_7); // NVclass 0x77, nv10+: little endian
460  else
461  // NV4_DX5_TEXTURE_TRIANGLE
462  pRegs->write32(0x0300a054, NVACC_PR_CTX0_7);
463  pRegs->write32(0x00000000, NVACC_PR_CTX1_7); // colorspace not set,
464  // notify instance invalid
465  // (b16-31)
466  pRegs->write32(
467  0x11401140,
468  NVACC_PR_CTX2_7); // DMA0 instance 0x1140 and DMA1 instance invalid
469  pRegs->write32(
470  0x00000000, NVACC_PR_CTX3_7); // trap 0 is 0x1140, trap 1 disabled.
471 
472  // Setting up for set '8', command ...
473  if (m_Card >= NV10A)
474  // NV10_DX6_MULTI_TEXTURE_TRIANGLE
475  pRegs->write32(
476  0x0300a095,
477  NVACC_PR_CTX0_8); // NVclass 0x77, nv10+: little endian
478  else
479  // NV4_DX6_MULTI_TEXTURE_TRIANGLE
480  pRegs->write32(0x0300a055, NVACC_PR_CTX0_8);
481  pRegs->write32(0x00000000, NVACC_PR_CTX1_8); // colorspace not set,
482  // notify instance invalid
483  // (b16-31)
484  pRegs->write32(
485  0x11401140,
486  NVACC_PR_CTX2_8); // DMA0 instance 0x1140 and DMA1 instance invalid
487  pRegs->write32(
488  0x00000000, NVACC_PR_CTX3_8); // trap 0 is 0x1140, trap 1 disabled.
489 
490  // Setting up for set '9', command 'NV_SCALED_IMAGE_FROM_MEMORY'
491  pRegs->write32(
492  0x01018077, NVACC_PR_CTX0_9); // NVclass 0x77, nv10+: little endian
493  pRegs->write32(0x00000000, NVACC_PR_CTX1_9); // colorspace not set,
494  // notify instance invalid
495  // (b16-31)
496  pRegs->write32(
497  0x11401140,
498  NVACC_PR_CTX2_9); // DMA0 instance 0x1140 and DMA1 instance invalid
499  pRegs->write32(
500  0x00000000, NVACC_PR_CTX3_9); // trap 0 is 0x1140, trap 1 disabled.
501 
502  // Setting up for set 'A', command 'NV1_RENDER_SOLID_LIN'
503  pRegs->write32(
504  0x0300a01c, NVACC_PR_CTX0_A); // NVclass 0x77, nv10+: little endian
505  pRegs->write32(0x00000000, NVACC_PR_CTX1_A); // colorspace not set,
506  // notify instance invalid
507  // (b16-31)
508  pRegs->write32(
509  0x11401140,
510  NVACC_PR_CTX2_A); // DMA0 instance 0x1140 and DMA1 instance invalid
511  pRegs->write32(
512  0x00000000, NVACC_PR_CTX3_A); // trap 0 is 0x1140, trap 1 disabled.
513 
514  // Setup DMA set pointed at by PF_CACH1_DMAI
515  if (/* isAGP */ false)
516  pRegs->write32(
517  0x00033002,
518  NVACC_PR_CTX0_C); // DMA page table present and of linear type.
519  else
520  // PCI, not AGP.
521  pRegs->write32(
522  0x00023002,
523  NVACC_PR_CTX0_C); // DMA page table present and of linear type.
524  pRegs->write32(
525  0x00007fff, NVACC_PR_CTX1_C); // DMA limit: tablesize is 32k bytes.
526  pRegs->write32(
527  m_DmaBuffer.physicalAddress() | 0x00000002,
528  NVACC_PR_CTX2_C); // DMA access in READ_AND_WRITE
529  // table is located in main system RAM.
530  // Stuff for 3D only?
531  pRegs->write32(0x00000500, NVACC_BPIXEL); // 16-bit little endian RGB.
532  }
533 
534  // Do an explicit engine reset.
535  pRegs->write32(0xffffffff, NVACC_DEBUG0);
536  pRegs->write32(0x00000000, NVACC_DEBUG0);
537 
538  // Disable all acceleration engine INT requests.
539  pRegs->write32(0x00000000, NVACC_ACC_INTE);
540  // Reset all acceleration engine INT status bits.
541  pRegs->write32(0xffffffff, NVACC_ACC_INTS);
542 
543  // Context control enabled.
544  pRegs->write32(0x10010100, NVACC_NV10_CTX_CTRL);
545  // All acceleration buffers, pitches and colors are valid.
546  pRegs->write32(0xffffffff, NVACC_NV10_ACC_STAT);
547  // Enable acceleration engine command FIFO
548  pRegs->write32(0x00000001, NVACC_FIFO_EN);
549  // Setup surface type:
550  pRegs->write32(
551  pRegs->read32(NVACC_NV10_SURF_TYP) & 0x0007ff00, NVACC_NV10_SURF_TYP);
552  pRegs->write32(
553  pRegs->read32(NVACC_NV10_SURF_TYP) | 0x00020101, NVACC_NV10_SURF_TYP);
554 
555  // Does exactly what it says on the tin.
556  setUpReverseEngineeredMagicRegs();
557 
558  // Setup clipping.
559  pRegs->write32(0x00000000, NVACC_ABS_UCLP_XMIN);
560  pRegs->write32(0x00000000, NVACC_ABS_UCLP_YMIN);
561  pRegs->write32(0x00007fff, NVACC_ABS_UCLP_XMAX);
562  pRegs->write32(0x00007fff, NVACC_ABS_UCLP_YMAX);
563 
564  // **PFIFO**
565 
566  // (setup caches)
567  // disable caches reassign
568  pRegs->write32(0x00000000, NVACC_PF_CACHES);
569  // PFIFO mode: channel 0 is in DMA mode, channels 1-32 are in PIO mode.
570  pRegs->write32(0x00000001, NVACC_PF_MODE);
571  // Cache1 push0 access disabled
572  pRegs->write32(0x00000000, NVACC_PF_CACH1_PSH0);
573  // Cache1 pull0 access disabled
574  pRegs->write32(0x00000000, NVACC_PF_CACH1_PUL0);
575  // Cache1 push1 mode = DMA
576  if (m_Card >= NV40A)
577  pRegs->write32(0x00010000, NVACC_PF_CACH1_PSH1);
578  else
579  pRegs->write32(0x00000100, NVACC_PF_CACH1_PSH1);
580  // Cache1 DMA Put offset = 0
581  pRegs->write32(0x00000000, NVACC_PF_CACH1_DMAP);
582  // Cache1 DMA Get offset = 0;
583  pRegs->write32(0x00000000, NVACC_PF_CACH1_DMAG);
584  // Cache1 DMA instance address = 0x0114e (but haiku has 0x1150 for
585  // >=NV40A...
586  if (m_Card >= NV40A)
587  pRegs->write32(0x00001150, NVACC_PF_CACH1_DMAI);
588  else
589  pRegs->write32(0x0000114e, NVACC_PF_CACH1_DMAI);
590  // Cache0 push0 access disabled
591  pRegs->write32(0x00000000, NVACC_PF_CACH0_PSH0);
592  // Cache0 pull0 access disabled.
593  pRegs->write32(0x00000000, NVACC_PF_CACH0_PUL0);
594 
595  // RAMHT (hashtable) base address = 0x10000, size=4k
596  // search = 128 (is byte offset between hash 'sets')
597  // NOTE
598  // so HT base is 0x00710000, last is 0x00710fff.
599  // In this space you defined the engine command handles (HT_HANDL_XX) which
600  // in turn points to the defines in CTX register space (which is sort of
601  // RAM)
602  pRegs->write32(0x03000100, NVACC_PF_RAMHT);
603  // RAM FC baseaddress = 0x11000 (fize is fixed to 0x5k(?))
604  pRegs->write32(0x00000110, NVACC_PF_RAMFC);
605  // RAM RO baseaddress = 0x11200
606  pRegs->write32(0x00000112, NVACC_PF_RAMRO);
607  // PFIFO size: ch0-15 = 512 bytes, ch16-31 = 124 bytes
608  pRegs->write32(0x0000ffff, NVACC_PF_SIZE);
609  // Cache1 hash instance = 0xffff
610  pRegs->write32(0x0000ffff, NVACC_PF_CACH1_HASH);
611  // Disable all PFIFO INTs
612  pRegs->write32(0x00000000, NVACC_PF_INTEN);
613  // Reset all PFOFP INT status bits
614  pRegs->write32(0xffffffff, NVACC_PF_INTSTAT);
615  // cach0 pull0 engine = acceleration engine (graphics)
616  pRegs->write32(0x00000001, NVACC_PF_CACH0_PUL1);
617  // Cache1 DMA control: disable some stuff
618  pRegs->write32(0x00000000, NVACC_PF_CACH1_DMAC);
619  // cache1 engine 0 upto/including 7 is software (could also be graphics or
620  // DVD)
621  pRegs->write32(0x00000000, NVACC_PF_CACH1_ENG);
622  // cache1 DMA fetch: trigger at 128 bytes, size is 32 bytes, max requests is
623  // 15, use little endian.
624  pRegs->write32(0x000f0078, NVACC_PF_CACH1_DMAF);
625  // cache1 DMA push, b0 = 1: access is enabled
626  pRegs->write32(0x00000001, NVACC_PF_CACH1_DMAS);
627  // cache1 push0 access enabled.
628  pRegs->write32(0x00000001, NVACC_PF_CACH1_PSH0);
629  // cache1 pull0 access enabled.
630  pRegs->write32(0x00000001, NVACC_PF_CACH1_PUL0);
631  // cache1 pull1 engine = acceleration engine (graphics)
632  pRegs->write32(0x00000001, NVACC_PF_CACH1_PUL1);
633  // Enable PFIFO caches reassign
634  pRegs->write32(0x00000001, NVACC_PF_CACHES);
635 
636  // Init DMA command buffer info.
637 
638  m_nPut = 0;
639  m_nCurrent = 0;
640 
641  // The DMA buffer can hold 8k 32-bit words (it's 32kb in size),
642  // or 256k 32-bit words (1Mb in size) dependant on architecture.
643  // One word is reserved at the end of the buffer to be able to instruct the
644  // engine to do a buffer wrap-around!
645  m_nMax = 8192 - 1;
646  m_nFree = m_nMax;
647 
648  // Set up each FIFO.
649  m_pFifoPtrs[NV_ROP5_SOLID] = 0 * 0x00002000;
650  m_pFifoPtrs[NV_IMAGE_BLACK_RECTANGLE] = 1 * 0x00002000;
651  m_pFifoPtrs[NV_IMAGE_PATTERN] = 2 * 0x00002000;
652  m_pFifoPtrs[NV4_SURFACE] = 3 * 0x00002000;
653  m_pFifoPtrs[NV_IMAGE_BLIT] = 4 * 0x00002000;
654  m_pFifoPtrs[NV4_GDI_RECTANGLE_TEXT] = 5 * 0x00002000;
655  m_pFifoPtrs[NV4_CONTEXT_SURFACES_ARGB_ZS] = 6 * 0x00002000;
656  m_pFifoPtrs[NV4_DX5_TEXTURE_TRIANGLE] = 7 * 0x00002000;
657 
658  m_pFifos[0] = NV_ROP5_SOLID;
659  m_pFifos[1] = NV_IMAGE_BLACK_RECTANGLE;
660  m_pFifos[2] = NV_IMAGE_PATTERN;
661  m_pFifos[3] = NV4_SURFACE;
662  m_pFifos[4] = NV_IMAGE_BLIT;
663  m_pFifos[5] = NV4_GDI_RECTANGLE_TEXT;
664  m_pFifos[6] = NV_SCALED_IMAGE_FROM_MEMORY;
665 
666  initFifo(NV_GENERAL_FIFO_CH0, m_pFifos[0]);
667  initFifo(NV_GENERAL_FIFO_CH1, m_pFifos[1]);
668  initFifo(NV_GENERAL_FIFO_CH2, m_pFifos[2]);
669  initFifo(NV_GENERAL_FIFO_CH3, m_pFifos[3]);
670  initFifo(NV_GENERAL_FIFO_CH4, m_pFifos[4]);
671  initFifo(NV_GENERAL_FIFO_CH5, m_pFifos[5]);
672  initFifo(NV_GENERAL_FIFO_CH6, m_pFifos[6]);
673 
674  // Set pixel width.
675  ensureFree(5);
676  dmaCmd(NV4_SURFACE, NV4_SURFACE_FORMAT, 4);
677  writeBuffer(4); // Surface depth (for 16-bit little endian)
678  writeBuffer(2048 | (2048 << 16)); // bytes per row (copied?)
679  writeBuffer(0); // OffsetSource
680  writeBuffer(0); // OffsetDest - screen location.
681 
682  // Setup pattern colourdepth
683  ensureFree(2);
684  dmaCmd(NV_IMAGE_PATTERN, NV_IMAGE_PATTERN_SETCOLORFORMAT, 1);
685  writeBuffer(1); // cmd depth - 1 for 16 bit little endian.
686 
687  ensureFree(2);
688  dmaCmd(NV4_GDI_RECTANGLE_TEXT, NV4_GDI_RECTANGLE_TEXT_SETCOLORFORMAT, 1);
689  writeBuffer(1); // cmd depth - 1 for 16 bit little endian.
690 
691  // Load our pattern into the engine.
692  ensureFree(7);
693  dmaCmd(NV_IMAGE_PATTERN, NV_IMAGE_PATTERN_SETSHAPE, 1);
694  writeBuffer(0x00000000); // SetShape: 0 = 8x8, 1 = 64x1, 2 = 1x64
695  dmaCmd(NV_IMAGE_PATTERN, NV_IMAGE_PATTERN_SETCOLOR0, 4);
696  writeBuffer(0xffffffff); // Setcolor0
697  writeBuffer(0xffffffff); // Setcolor1
698  writeBuffer(0xffffffff); // Setpattern0
699  writeBuffer(0xffffffff); // Setpattern1
700 
701  // Start DMA transfer!
702  start();
703 }
704 
705 Dma::~Dma()
706 {
707 }
708 
709 void Dma::dmaCmd(uint32_t cmd, uint32_t offset, uint16_t size)
710 {
711  if (m_Card >= NV40A)
712  m_pFramebuffer->write32(
713  (size << 18) | ((m_pFifoPtrs[cmd] + offset) & 0x0000fffc),
714  m_nDmaBuffer + ((m_nCurrent++) << 2));
715  else
716  m_pDmaBuffer[m_nCurrent++] =
717  ((size << 18) | ((m_pFifoPtrs[cmd] + offset) & 0x0000fffc));
718  m_nFree -= (size + 1);
719 }
720 
721 void Dma::writeBuffer(uint32_t arg)
722 {
723  if (m_Card >= NV40A)
724  m_pFramebuffer->write32(arg, m_nDmaBuffer + ((m_nCurrent++) << 2));
725  else
726  m_pDmaBuffer[m_nCurrent++] = arg;
727 }
728 
729 void Dma::start()
730 {
731  if (m_nCurrent != m_nPut)
732  {
733  m_nPut = m_nCurrent;
734  m_pRegs->write32(m_nPut << 2, NVACC_FIFO + NV_GENERAL_DMAPUT);
735  }
736 }
737 
738 void Dma::ensureFree(uint16_t cmd_size)
739 {
740  while ((m_nFree < cmd_size))
741  {
742  uint32_t dmaget = m_pRegs->read32(NVACC_FIFO + NV_GENERAL_DMAGET) >> 2;
743  NOTICE("Get: " << Hex << dmaget);
744  if (m_nPut >= dmaget)
745  {
746  // Engine is fetching 'behind us', the last piece of the buffer is
747  // free.
748 
749  m_nFree = m_nMax - m_nCurrent;
750  if (m_nFree < cmd_size)
751  {
752  // Not enough room left, so instruct DMA engine to reset the
753  // buffer when it reaches the end of it.
754  writeBuffer(0x20000000);
755  m_nCurrent = 0;
756  start();
757 
758  // NOW the engine is fetching 'in front of us', so the first
759  // piece of the buffer is free.
760  m_nFree = dmaget - m_nCurrent;
761 
762  // Leave a gap between where we put new commands and where the
763  // engine is executing. Else we can crash the engine.
764  if (m_nFree < 256)
765  m_nFree = 0;
766  else
767  m_nFree -= 256;
768  }
769  }
770  else
771  {
772  // Engine is fetching 'in front of us', so the first piece of the
773  // buffer is free.
774  m_nFree = dmaget - m_nCurrent;
775 
776  // Leave a gap between where we put new commands and where the
777  // engine is executing. Else we can crash the engine.
778  if (m_nFree < 256)
779  m_nFree = 0;
780  else
781  m_nFree -= 256;
782  }
783  }
784 }
785 
786 void Dma::initFifo(uint32_t ch, uint32_t handle)
787 {
788  // Issue FIFO channel assign cmd.
789  NOTICE("initFifo: put: " << Hex << m_nPut << ", cur: " << m_nCurrent);
790  writeBuffer((1 << 18) | ch);
791  writeBuffer(0x80000000 | handle);
792 
793  m_nFree -= 2;
794 }
795 
796 void Dma::screenToScreenBlit(
797  uint16_t src_x, uint16_t src_y, uint16_t dest_x, uint16_t dest_y,
798  uint16_t h, uint16_t w)
799 {
800  ensureFree(2);
801 
802  // Now setup ROP (Raster OP) for GXCopy */
803  dmaCmd(NV_ROP5_SOLID, NV_ROP5_SOLID_SETROP5, 1);
804  writeBuffer(0xcc); // SetRop5
805 
806  ensureFree(4);
807 
808  dmaCmd(NV_IMAGE_BLIT, NV_IMAGE_BLIT_SOURCEORG, 3);
809  writeBuffer((src_y << 16) | src_x);
810  writeBuffer((dest_y << 16) | dest_x);
811  writeBuffer(((h + 1) << 16) | (w + 1));
812 
813  start();
814  NOTICE("screenToScreenBlit -- end");
815 }
816 
817 void Dma::fillRectangle(uint16_t x, uint16_t y, uint16_t h, uint16_t w)
818 {
819  uint32_t c = 0xFFFFFFFF;
820 
821  ensureFree(2);
822 
823  // Now setup ROP (Raster OP) for GXCopy
824  dmaCmd(NV_ROP5_SOLID, NV_ROP5_SOLID_SETROP5, 1);
825  writeBuffer(0xcc); // SetRop5
826 
827  // Setup fill colour
828  dmaCmd(NV4_GDI_RECTANGLE_TEXT, NV4_GDI_RECTANGLE_TEXT_COLOR1A, 1);
829  writeBuffer(c);
830 
831  ensureFree(3);
832 
833  dmaCmd(NV4_GDI_RECTANGLE_TEXT, NV4_GDI_RECTANGLE_TEXT_UCR0_LEFTTOP, 2);
834  writeBuffer((x << 16) | (y & 0xffff));
835  writeBuffer(((w + 1) << 16) | (h + 1));
836 
837  start();
838 }
839 
840 void Dma::setUpReverseEngineeredMagicRegs()
841 {
842  switch (m_Card)
843  {
844  case NV40A:
845  {
846  // Init some function blocks.
847  m_pRegs->write32(0x401287c0, NVACC_DEBUG1);
848  m_pRegs->write32(0x60de8051, NVACC_DEBUG3);
849  // Disable specific functions, but enable SETUP_SPARE2.
850  m_pRegs->write32(0x00008000, NVACC_NV10_DEBUG4);
851  m_pRegs->write32(0x00be3c5f, NVACC_NV25_WHAT0);
852 
853  // Setup some unknown serially accessed registers
854  uint32_t tmp = m_pRegs->read32(NV32_NV4X_WHAT0) & 0xff;
855  for (int cnt = 0; (tmp && !(tmp & 0x1)); tmp >>= 1, cnt++)
856  m_pRegs->write32(cnt, NVACC_NV4X_WHAT2);
857 
858  int m_CardType = NV40;
859  switch (m_CardType)
860  {
861  case NV40:
862  case NV45:
863  m_pRegs->write32(0x83280fff, NVACC_NV40_WHAT0);
864  m_pRegs->write32(0x000000a0, NVACC_NV40_WHAT1);
865  m_pRegs->write32(0x0078e366, NVACC_NV40_WHAT2);
866  m_pRegs->write32(0x0000014c, NVACC_NV40_WHAT3);
867  break;
868  }
869 
870  m_pRegs->write32(0x2ffff800, NVACC_NV10_TIL3PT);
871  m_pRegs->write32(0x00006000, NVACC_NV10_TIL3ST);
872  m_pRegs->write32(0x01000000, NVACC_NV4X_WHAT1);
873  // Engine data source DMA instance = $1140
874  m_pRegs->write32(0x00001140, NVACC_NV4X_DMA_SRC);
875  break;
876  }
877 
878  case NV30A:
879  // Init some function blocks, but most is unknown.
880  m_pRegs->write32(0x40108700, NVACC_DEBUG1);
881  m_pRegs->write32(0x00140000, NVACC_NV25_WHAT1);
882  m_pRegs->write32(0xf00e0431, NVACC_DEBUG3);
883  m_pRegs->write32(0x00008000, NVACC_NV10_DEBUG4);
884  m_pRegs->write32(0xf04b1f36, NVACC_NV25_WHAT0);
885  m_pRegs->write32(0x1002d888, NVACC_NV20_WHAT3);
886  m_pRegs->write32(0x62ff007f, NVACC_NV25_WHAT2);
887 
888  // Copy tile setup stuff.
889  for (int i = 0; i < 32; i++)
890  {
891  // Copy NV10_FBTIL0AD upto/including NV10_FBTIL7ST
892  m_pRegs->write32(
893  m_pRegs->read32(NVACC_NV10_FBTIL0AD + (i << 2)),
894  NVACC_NV20_WHAT0 + (i << 2));
895  m_pRegs->write32(
896  m_pRegs->read32(NVACC_NV10_FBTIL0AD + (i << 2)),
897  NVACC_NV20_2_WHAT0 + (i << 2));
898  }
899 
900  // Copy some RAM configuration info(?)
901  m_pRegs->write32(
902  m_pRegs->read32(NV32_PFB_CONFIG_0), NVACC_NV20_WHAT_T0);
903  m_pRegs->write32(
904  m_pRegs->read32(NV32_PFB_CONFIG_1), NVACC_NV20_WHAT_T1);
905 
906  m_pRegs->write32(0x00ea0000, NVACC_RDI_INDEX);
907  m_pRegs->write32(
908  m_pRegs->read32(NV32_PFB_CONFIG_0), NVACC_RDI_DATA);
909 
910  m_pRegs->write32(0x00ea0004, NVACC_RDI_INDEX);
911  m_pRegs->write32(
912  m_pRegs->read32(NV32_PFB_CONFIG_1), NVACC_RDI_DATA);
913 
914  // Setup location of active screen in framebuffer.
915  // NOTE: OFFSET0 is 2D destination buffer offset.
916  // OFFSET1 is 2D source buffer offset.
917  m_pRegs->write32(0, NVACC_NV20_OFFSET0);
918  m_pRegs->write32(0, NVACC_NV20_OFFSET1);
919 
920  // Setup buffer pitch.
921  // m_pRegs->write32(bytes-per-row&0xffff, NVACC_NV20_PITCH0);
922  // m_pRegs->write32(bytes-per-row&0xffff, NVACC_NV20_PITCH1);
923 
924  // Setup accessible card memory range.
925  m_pRegs->write32(m_nRamSize - 1, NVACC_NV20_BLIMIT6);
926  m_pRegs->write32(m_nRamSize - 1, NVACC_NV20_BLIMIT7);
927 
928  m_pRegs->write32(0x00000000, NVACC_NV10_TIL2AD);
929  m_pRegs->write32(0xffffffff, NVACC_NV10_TIL0ED);
930  break;
931  default:
932  break;
933  }
934 }
static PhysicalMemoryManager & instance()
Definition: cmd.h:30
virtual void write8(uint8_t value, size_t offset=0)=0
Abstrace base class for hardware I/O capabilities.
Definition: IoBase.h:31
virtual uint32_t read32(size_t offset=0)=0
#define NOTICE(text)
Definition: Log.h:74
Definition: Log.h:136
#define ERROR(text)
Definition: Log.h:82
virtual void write32(uint32_t value, size_t offset=0)=0