drm: userspace rip out TTM API
[platform/upstream/libdrm.git] / shared-core / nouveau_state.c
1 /*
2  * Copyright 2005 Stephane Marchesin
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include "drmP.h"
26 #include "drm.h"
27 #include "drm_sarea.h"
28 #include "nouveau_drv.h"
29 #include "nouveau_drm.h"
30 #include "nv50_kms_wrapper.h"
31 #include "nv50_fbcon.h"
32
33 static int nouveau_init_card_mappings(struct drm_device *dev)
34 {
35         struct drm_nouveau_private *dev_priv = dev->dev_private;
36         int ret;
37
38         /* resource 0 is mmio regs */
39         /* resource 1 is linear FB */
40         /* resource 2 is RAMIN (mmio regs + 0x1000000) */
41         /* resource 6 is bios */
42
43         /* map the mmio regs */
44         ret = drm_addmap(dev, drm_get_resource_start(dev, 0),
45                               drm_get_resource_len(dev, 0),
46                               _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);
47         if (ret) {
48                 DRM_ERROR("Unable to initialize the mmio mapping (%d). "
49                           "Please report your setup to " DRIVER_EMAIL "\n",
50                           ret);
51                 return -EINVAL;
52         }
53         DRM_DEBUG("regs mapped ok at 0x%lx\n", dev_priv->mmio->offset);
54
55         /* map larger RAMIN aperture on NV40 cards */
56         dev_priv->ramin = NULL;
57         if (dev_priv->card_type >= NV_40) {
58                 int ramin_resource = 2;
59                 if (drm_get_resource_len(dev, ramin_resource) == 0)
60                         ramin_resource = 3;
61
62                 ret = drm_addmap(dev,
63                                  drm_get_resource_start(dev, ramin_resource),
64                                  drm_get_resource_len(dev, ramin_resource),
65                                  _DRM_REGISTERS, _DRM_READ_ONLY,
66                                  &dev_priv->ramin);
67                 if (ret) {
68                         DRM_ERROR("Failed to init RAMIN mapping, "
69                                   "limited instance memory available\n");
70                         dev_priv->ramin = NULL;
71                 }
72         }
73
74         /* On older cards (or if the above failed), create a map covering
75          * the BAR0 PRAMIN aperture */
76         if (!dev_priv->ramin) {
77                 ret = drm_addmap(dev,
78                                  drm_get_resource_start(dev, 0) + NV_RAMIN,
79                                  (1*1024*1024),
80                                  _DRM_REGISTERS, _DRM_READ_ONLY,
81                                  &dev_priv->ramin);
82                 if (ret) {
83                         DRM_ERROR("Failed to map BAR0 PRAMIN: %d\n", ret);
84                         return ret;
85                 }
86         }
87
88         return 0;
89 }
90
91 static int nouveau_stub_init(struct drm_device *dev) { return 0; }
92 static void nouveau_stub_takedown(struct drm_device *dev) {}
93
94 static int nouveau_init_engine_ptrs(struct drm_device *dev)
95 {
96         struct drm_nouveau_private *dev_priv = dev->dev_private;
97         struct nouveau_engine *engine = &dev_priv->Engine;
98
99         switch (dev_priv->chipset & 0xf0) {
100         case 0x00:
101                 engine->instmem.init    = nv04_instmem_init;
102                 engine->instmem.takedown= nv04_instmem_takedown;
103                 engine->instmem.populate        = nv04_instmem_populate;
104                 engine->instmem.clear           = nv04_instmem_clear;
105                 engine->instmem.bind            = nv04_instmem_bind;
106                 engine->instmem.unbind          = nv04_instmem_unbind;
107                 engine->mc.init         = nv04_mc_init;
108                 engine->mc.takedown     = nv04_mc_takedown;
109                 engine->timer.init      = nv04_timer_init;
110                 engine->timer.read      = nv04_timer_read;
111                 engine->timer.takedown  = nv04_timer_takedown;
112                 engine->fb.init         = nv04_fb_init;
113                 engine->fb.takedown     = nv04_fb_takedown;
114                 engine->graph.init      = nv04_graph_init;
115                 engine->graph.takedown  = nv04_graph_takedown;
116                 engine->graph.create_context    = nv04_graph_create_context;
117                 engine->graph.destroy_context   = nv04_graph_destroy_context;
118                 engine->graph.load_context      = nv04_graph_load_context;
119                 engine->graph.save_context      = nv04_graph_save_context;
120                 engine->fifo.channels   = 16;
121                 engine->fifo.init       = nouveau_fifo_init;
122                 engine->fifo.takedown   = nouveau_stub_takedown;
123                 engine->fifo.channel_id         = nv04_fifo_channel_id;
124                 engine->fifo.create_context     = nv04_fifo_create_context;
125                 engine->fifo.destroy_context    = nv04_fifo_destroy_context;
126                 engine->fifo.load_context       = nv04_fifo_load_context;
127                 engine->fifo.save_context       = nv04_fifo_save_context;
128                 break;
129         case 0x10:
130                 engine->instmem.init    = nv04_instmem_init;
131                 engine->instmem.takedown= nv04_instmem_takedown;
132                 engine->instmem.populate        = nv04_instmem_populate;
133                 engine->instmem.clear           = nv04_instmem_clear;
134                 engine->instmem.bind            = nv04_instmem_bind;
135                 engine->instmem.unbind          = nv04_instmem_unbind;
136                 engine->mc.init         = nv04_mc_init;
137                 engine->mc.takedown     = nv04_mc_takedown;
138                 engine->timer.init      = nv04_timer_init;
139                 engine->timer.read      = nv04_timer_read;
140                 engine->timer.takedown  = nv04_timer_takedown;
141                 engine->fb.init         = nv10_fb_init;
142                 engine->fb.takedown     = nv10_fb_takedown;
143                 engine->graph.init      = nv10_graph_init;
144                 engine->graph.takedown  = nv10_graph_takedown;
145                 engine->graph.create_context    = nv10_graph_create_context;
146                 engine->graph.destroy_context   = nv10_graph_destroy_context;
147                 engine->graph.load_context      = nv10_graph_load_context;
148                 engine->graph.save_context      = nv10_graph_save_context;
149                 engine->fifo.channels   = 32;
150                 engine->fifo.init       = nouveau_fifo_init;
151                 engine->fifo.takedown   = nouveau_stub_takedown;
152                 engine->fifo.channel_id         = nv10_fifo_channel_id;
153                 engine->fifo.create_context     = nv10_fifo_create_context;
154                 engine->fifo.destroy_context    = nv10_fifo_destroy_context;
155                 engine->fifo.load_context       = nv10_fifo_load_context;
156                 engine->fifo.save_context       = nv10_fifo_save_context;
157                 break;
158         case 0x20:
159                 engine->instmem.init    = nv04_instmem_init;
160                 engine->instmem.takedown= nv04_instmem_takedown;
161                 engine->instmem.populate        = nv04_instmem_populate;
162                 engine->instmem.clear           = nv04_instmem_clear;
163                 engine->instmem.bind            = nv04_instmem_bind;
164                 engine->instmem.unbind          = nv04_instmem_unbind;
165                 engine->mc.init         = nv04_mc_init;
166                 engine->mc.takedown     = nv04_mc_takedown;
167                 engine->timer.init      = nv04_timer_init;
168                 engine->timer.read      = nv04_timer_read;
169                 engine->timer.takedown  = nv04_timer_takedown;
170                 engine->fb.init         = nv10_fb_init;
171                 engine->fb.takedown     = nv10_fb_takedown;
172                 engine->graph.init      = nv20_graph_init;
173                 engine->graph.takedown  = nv20_graph_takedown;
174                 engine->graph.create_context    = nv20_graph_create_context;
175                 engine->graph.destroy_context   = nv20_graph_destroy_context;
176                 engine->graph.load_context      = nv20_graph_load_context;
177                 engine->graph.save_context      = nv20_graph_save_context;
178                 engine->fifo.channels   = 32;
179                 engine->fifo.init       = nouveau_fifo_init;
180                 engine->fifo.takedown   = nouveau_stub_takedown;
181                 engine->fifo.channel_id         = nv10_fifo_channel_id;
182                 engine->fifo.create_context     = nv10_fifo_create_context;
183                 engine->fifo.destroy_context    = nv10_fifo_destroy_context;
184                 engine->fifo.load_context       = nv10_fifo_load_context;
185                 engine->fifo.save_context       = nv10_fifo_save_context;
186                 break;
187         case 0x30:
188                 engine->instmem.init    = nv04_instmem_init;
189                 engine->instmem.takedown= nv04_instmem_takedown;
190                 engine->instmem.populate        = nv04_instmem_populate;
191                 engine->instmem.clear           = nv04_instmem_clear;
192                 engine->instmem.bind            = nv04_instmem_bind;
193                 engine->instmem.unbind          = nv04_instmem_unbind;
194                 engine->mc.init         = nv04_mc_init;
195                 engine->mc.takedown     = nv04_mc_takedown;
196                 engine->timer.init      = nv04_timer_init;
197                 engine->timer.read      = nv04_timer_read;
198                 engine->timer.takedown  = nv04_timer_takedown;
199                 engine->fb.init         = nv10_fb_init;
200                 engine->fb.takedown     = nv10_fb_takedown;
201                 engine->graph.init      = nv30_graph_init;
202                 engine->graph.takedown  = nv20_graph_takedown;
203                 engine->graph.create_context    = nv20_graph_create_context;
204                 engine->graph.destroy_context   = nv20_graph_destroy_context;
205                 engine->graph.load_context      = nv20_graph_load_context;
206                 engine->graph.save_context      = nv20_graph_save_context;
207                 engine->fifo.channels   = 32;
208                 engine->fifo.init       = nouveau_fifo_init;
209                 engine->fifo.takedown   = nouveau_stub_takedown;
210                 engine->fifo.channel_id         = nv10_fifo_channel_id;
211                 engine->fifo.create_context     = nv10_fifo_create_context;
212                 engine->fifo.destroy_context    = nv10_fifo_destroy_context;
213                 engine->fifo.load_context       = nv10_fifo_load_context;
214                 engine->fifo.save_context       = nv10_fifo_save_context;
215                 break;
216         case 0x40:
217         case 0x60:
218                 engine->instmem.init    = nv04_instmem_init;
219                 engine->instmem.takedown= nv04_instmem_takedown;
220                 engine->instmem.populate        = nv04_instmem_populate;
221                 engine->instmem.clear           = nv04_instmem_clear;
222                 engine->instmem.bind            = nv04_instmem_bind;
223                 engine->instmem.unbind          = nv04_instmem_unbind;
224                 engine->mc.init         = nv40_mc_init;
225                 engine->mc.takedown     = nv40_mc_takedown;
226                 engine->timer.init      = nv04_timer_init;
227                 engine->timer.read      = nv04_timer_read;
228                 engine->timer.takedown  = nv04_timer_takedown;
229                 engine->fb.init         = nv40_fb_init;
230                 engine->fb.takedown     = nv40_fb_takedown;
231                 engine->graph.init      = nv40_graph_init;
232                 engine->graph.takedown  = nv40_graph_takedown;
233                 engine->graph.create_context    = nv40_graph_create_context;
234                 engine->graph.destroy_context   = nv40_graph_destroy_context;
235                 engine->graph.load_context      = nv40_graph_load_context;
236                 engine->graph.save_context      = nv40_graph_save_context;
237                 engine->fifo.channels   = 32;
238                 engine->fifo.init       = nv40_fifo_init;
239                 engine->fifo.takedown   = nouveau_stub_takedown;
240                 engine->fifo.channel_id         = nv10_fifo_channel_id;
241                 engine->fifo.create_context     = nv40_fifo_create_context;
242                 engine->fifo.destroy_context    = nv40_fifo_destroy_context;
243                 engine->fifo.load_context       = nv40_fifo_load_context;
244                 engine->fifo.save_context       = nv40_fifo_save_context;
245                 break;
246         case 0x50:
247         case 0x80: /* gotta love NVIDIA's consistency.. */
248         case 0x90:
249                 engine->instmem.init    = nv50_instmem_init;
250                 engine->instmem.takedown= nv50_instmem_takedown;
251                 engine->instmem.populate        = nv50_instmem_populate;
252                 engine->instmem.clear           = nv50_instmem_clear;
253                 engine->instmem.bind            = nv50_instmem_bind;
254                 engine->instmem.unbind          = nv50_instmem_unbind;
255                 engine->mc.init         = nv50_mc_init;
256                 engine->mc.takedown     = nv50_mc_takedown;
257                 engine->timer.init      = nv04_timer_init;
258                 engine->timer.read      = nv04_timer_read;
259                 engine->timer.takedown  = nv04_timer_takedown;
260                 engine->fb.init         = nouveau_stub_init;
261                 engine->fb.takedown     = nouveau_stub_takedown;
262                 engine->graph.init      = nv50_graph_init;
263                 engine->graph.takedown  = nv50_graph_takedown;
264                 engine->graph.create_context    = nv50_graph_create_context;
265                 engine->graph.destroy_context   = nv50_graph_destroy_context;
266                 engine->graph.load_context      = nv50_graph_load_context;
267                 engine->graph.save_context      = nv50_graph_save_context;
268                 engine->fifo.channels   = 128;
269                 engine->fifo.init       = nv50_fifo_init;
270                 engine->fifo.takedown   = nv50_fifo_takedown;
271                 engine->fifo.channel_id         = nv50_fifo_channel_id;
272                 engine->fifo.create_context     = nv50_fifo_create_context;
273                 engine->fifo.destroy_context    = nv50_fifo_destroy_context;
274                 engine->fifo.load_context       = nv50_fifo_load_context;
275                 engine->fifo.save_context       = nv50_fifo_save_context;
276                 break;
277         default:
278                 DRM_ERROR("NV%02x unsupported\n", dev_priv->chipset);
279                 return 1;
280         }
281
282         return 0;
283 }
284
285 int
286 nouveau_card_init(struct drm_device *dev)
287 {
288         struct drm_nouveau_private *dev_priv = dev->dev_private;
289         struct nouveau_engine *engine;
290         int ret;
291
292         DRM_DEBUG("prev state = %d\n", dev_priv->init_state);
293
294         if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
295                 return 0;
296         dev_priv->ttm = 0;
297
298         /* Determine exact chipset we're running on */
299         if (dev_priv->card_type < NV_10)
300                 dev_priv->chipset = dev_priv->card_type;
301         else
302                 dev_priv->chipset =
303                         (NV_READ(NV03_PMC_BOOT_0) & 0x0ff00000) >> 20;
304
305         /* Initialise internal driver API hooks */
306         ret = nouveau_init_engine_ptrs(dev);
307         if (ret) return ret;
308         engine = &dev_priv->Engine;
309         dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
310
311         ret = nouveau_gpuobj_early_init(dev);
312         if (ret) return ret;
313
314         /* Initialise instance memory, must happen before mem_init so we
315          * know exactly how much VRAM we're able to use for "normal"
316          * purposes.
317          */
318         ret = engine->instmem.init(dev);
319         if (ret) return ret;
320
321         /* Setup the memory manager */
322         if (dev_priv->ttm) {
323                 ret = nouveau_mem_init_ttm(dev);
324                 if (ret) return ret;
325         } else {
326                 ret = nouveau_mem_init(dev);
327                 if (ret) return ret;
328         }
329
330         ret = nouveau_gpuobj_init(dev);
331         if (ret) return ret;
332
333         /* Parse BIOS tables / Run init tables? */
334
335         /* PMC */
336         ret = engine->mc.init(dev);
337         if (ret) return ret;
338
339         /* PTIMER */
340         ret = engine->timer.init(dev);
341         if (ret) return ret;
342
343         /* PFB */
344         ret = engine->fb.init(dev);
345         if (ret) return ret;
346
347         /* PGRAPH */
348         ret = engine->graph.init(dev);
349         if (ret) return ret;
350
351         /* PFIFO */
352         ret = engine->fifo.init(dev);
353         if (ret) return ret;
354
355         /* this call irq_preinstall, register irq handler and
356          * call irq_postinstall
357          */
358         ret = drm_irq_install(dev);
359         if (ret) return ret;
360
361         /* what about PVIDEO/PCRTC/PRAMDAC etc? */
362
363         ret = nouveau_dma_channel_init(dev);
364         if (ret) return ret;
365
366         dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
367
368         if (drm_core_check_feature(dev, DRIVER_MODESET))
369                 if (dev_priv->card_type >= NV_50) {
370                         nv50_kms_init(dev);
371                         //nv50_kms_connector_detect_all(dev);
372                         nv50_fbcon_init(dev);
373                 }
374
375         return 0;
376 }
377
378 static void nouveau_card_takedown(struct drm_device *dev)
379 {
380         struct drm_nouveau_private *dev_priv = dev->dev_private;
381         struct nouveau_engine *engine = &dev_priv->Engine;
382
383         DRM_DEBUG("prev state = %d\n", dev_priv->init_state);
384
385         if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) {
386                 nouveau_dma_channel_takedown(dev);
387
388                 engine->fifo.takedown(dev);
389                 engine->graph.takedown(dev);
390                 engine->fb.takedown(dev);
391                 engine->timer.takedown(dev);
392                 engine->mc.takedown(dev);
393
394                 nouveau_sgdma_nottm_hack_takedown(dev);
395                 nouveau_sgdma_takedown(dev);
396
397                 nouveau_gpuobj_takedown(dev);
398                 nouveau_gpuobj_del(dev, &dev_priv->vm_vram_pt);
399
400                 nouveau_mem_close(dev);
401                 engine->instmem.takedown(dev);
402
403                 drm_irq_uninstall(dev);
404
405                 nouveau_gpuobj_late_takedown(dev);
406
407                 dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
408         }
409 }
410
411 /* here a client dies, release the stuff that was allocated for its
412  * file_priv */
413 void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
414 {
415         struct drm_nouveau_private *dev_priv = dev->dev_private;
416
417         nouveau_fifo_cleanup(dev, file_priv);
418         nouveau_mem_release(file_priv,dev_priv->fb_heap);
419         nouveau_mem_release(file_priv,dev_priv->agp_heap);
420         nouveau_mem_release(file_priv,dev_priv->pci_heap);
421 }
422
423 int nouveau_setup_mappings(struct drm_device *dev)
424 {
425 #if defined(__powerpc__)
426         struct drm_nouveau_private *dev_priv = dev->dev_private;
427         struct device_node *dn;
428 #endif
429         int ret;
430         /* Map any PCI resources we need on the card */
431         ret = nouveau_init_card_mappings(dev);
432         if (ret) return ret;
433
434 #if defined(__powerpc__)
435         /* Put the card in BE mode if it's not */
436         if (NV_READ(NV03_PMC_BOOT_1))
437                 NV_WRITE(NV03_PMC_BOOT_1,0x00000001);
438
439         DRM_MEMORYBARRIER();
440 #endif
441
442 #if defined(__linux__) && defined(__powerpc__)
443         /* if we have an OF card, copy vbios to RAMIN */
444         dn = pci_device_to_OF_node(dev->pdev);
445         if (dn)
446         {
447                 int size;
448 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
449                 const uint32_t *bios = of_get_property(dn, "NVDA,BMP", &size);
450 #else
451                 const uint32_t *bios = get_property(dn, "NVDA,BMP", &size);
452 #endif
453                 if (bios)
454                 {
455                         int i;
456                         for(i=0;i<size;i+=4)
457                                 NV_WI32(i, bios[i/4]);
458                         DRM_INFO("OF bios successfully copied (%d bytes)\n",size);
459                 }
460                 else
461                         DRM_INFO("Unable to get the OF bios\n");
462         }
463         else
464                 DRM_INFO("Unable to get the OF node\n");
465 #endif
466         return 0;
467 }
468
469 /* first module load, setup the mmio/fb mapping */
470 /* KMS: we need mmio at load time, not when the first drm client opens. */
471 int nouveau_firstopen(struct drm_device *dev)
472 {
473         if (drm_core_check_feature(dev, DRIVER_MODESET))
474                 return 0;
475
476         return nouveau_setup_mappings(dev);
477 }
478
479 #define NV40_CHIPSET_MASK 0x00000baf
480 #define NV44_CHIPSET_MASK 0x00005450
481
482 int nouveau_load(struct drm_device *dev, unsigned long flags)
483 {
484         struct drm_nouveau_private *dev_priv;
485         void __iomem *regs;
486         uint32_t reg0,reg1;
487         uint8_t architecture = 0;
488
489         dev_priv = drm_calloc(1, sizeof(*dev_priv), DRM_MEM_DRIVER);
490         if (!dev_priv)
491                 return -ENOMEM;
492
493         dev_priv->flags = flags & NOUVEAU_FLAGS;
494         dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
495
496         DRM_DEBUG("vendor: 0x%X device: 0x%X class: 0x%X\n", dev->pci_vendor, dev->pci_device, dev->pdev->class);
497
498         /* Time to determine the card architecture */
499         regs = ioremap_nocache(pci_resource_start(dev->pdev, 0), 0x8);
500         if (!regs) {
501                 DRM_ERROR("Could not ioremap to determine register\n");
502                 return -ENOMEM;
503         }
504
505         reg0 = readl(regs+NV03_PMC_BOOT_0);
506         reg1 = readl(regs+NV03_PMC_BOOT_1);
507 #if defined(__powerpc__)
508         if (reg1)
509                 reg0=___swab32(reg0);
510 #endif
511
512         /* We're dealing with >=NV10 */
513         if ((reg0 & 0x0f000000) > 0 ) {
514                 /* Bit 27-20 contain the architecture in hex */
515                 architecture = (reg0 & 0xff00000) >> 20;
516         /* NV04 or NV05 */
517         } else if ((reg0 & 0xff00fff0) == 0x20004000) {
518                 architecture = 0x04;
519         }
520
521         iounmap(regs);
522
523         if (architecture >= 0x80) {
524                 dev_priv->card_type = NV_50;
525         } else if (architecture >= 0x60) {
526                 /* FIXME we need to figure out who's who for NV6x */
527                 dev_priv->card_type = NV_44;
528         } else if (architecture >= 0x50) {
529                 dev_priv->card_type = NV_50;
530         } else if (architecture >= 0x40) {
531                 uint8_t subarch = architecture & 0xf;
532                 /* Selection criteria borrowed from NV40EXA */
533                 if (NV40_CHIPSET_MASK & (1 << subarch)) {
534                         dev_priv->card_type = NV_40;
535                 } else if (NV44_CHIPSET_MASK & (1 << subarch)) {
536                         dev_priv->card_type = NV_44;
537                 } else {
538                         dev_priv->card_type = NV_UNKNOWN;
539                 }
540         } else if (architecture >= 0x30) {
541                 dev_priv->card_type = NV_30;
542         } else if (architecture >= 0x20) {
543                 dev_priv->card_type = NV_20;
544         } else if (architecture >= 0x17) {
545                 dev_priv->card_type = NV_17;
546         } else if (architecture >= 0x11) {
547                 dev_priv->card_type = NV_11;
548         } else if (architecture >= 0x10) {
549                 dev_priv->card_type = NV_10;
550         } else if (architecture >= 0x04) {
551                 dev_priv->card_type = NV_04;
552         } else {
553                 dev_priv->card_type = NV_UNKNOWN;
554         }
555
556         DRM_INFO("Detected an NV%d generation card (0x%08x)\n", dev_priv->card_type,reg0);
557
558         if (dev_priv->card_type == NV_UNKNOWN) {
559                 return -EINVAL;
560         }
561
562         /* For those who think they want to be funny. */
563         if (dev_priv->card_type < NV_50)
564                 dev->driver->driver_features &= ~DRIVER_MODESET;
565
566         /* Special flags */
567         if (dev->pci_device == 0x01a0) {
568                 dev_priv->flags |= NV_NFORCE;
569         } else if (dev->pci_device == 0x01f0) {
570                 dev_priv->flags |= NV_NFORCE2;
571         }
572
573         dev->dev_private = (void *)dev_priv;
574
575         /* init card now, otherwise bad things happen */
576         if (drm_core_check_feature(dev, DRIVER_MODESET)) {
577                 int rval = 0;
578
579                 rval = nouveau_setup_mappings(dev);
580                 if (rval != 0)
581                         return rval;
582
583                 rval = nouveau_card_init(dev);
584                 if (rval != 0)
585                         return rval;
586         }
587
588         return 0;
589 }
590
591 void nouveau_close(struct drm_device *dev)
592 {
593         struct drm_nouveau_private *dev_priv = dev->dev_private;
594
595         /* In the case of an error dev_priv may not be be allocated yet */
596         if (dev_priv && dev_priv->card_type) {
597                 nouveau_card_takedown(dev);
598
599                 if(dev_priv->fb_mtrr>0)
600                 {
601                         drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),nouveau_mem_fb_amount(dev), DRM_MTRR_WC);
602                         dev_priv->fb_mtrr=0;
603                 }
604         }
605 }
606
607 /* KMS: we need mmio at load time, not when the first drm client opens. */
608 void nouveau_lastclose(struct drm_device *dev)
609 {
610         if (drm_core_check_feature(dev, DRIVER_MODESET))
611                 return;
612
613         nouveau_close(dev);
614 }
615
616 int nouveau_unload(struct drm_device *dev)
617 {
618         if (drm_core_check_feature(dev, DRIVER_MODESET)) {
619                 nv50_kms_destroy(dev);
620                 nv50_fbcon_destroy(dev);
621                 nouveau_close(dev);
622         }
623
624         drm_free(dev->dev_private, sizeof(*dev->dev_private), DRM_MEM_DRIVER);
625         dev->dev_private = NULL;
626         return 0;
627 }
628
629 int
630 nouveau_ioctl_card_init(struct drm_device *dev, void *data,
631                         struct drm_file *file_priv)
632 {
633         return nouveau_card_init(dev);
634 }
635
636 int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
637 {
638         struct drm_nouveau_private *dev_priv = dev->dev_private;
639         struct drm_nouveau_getparam *getparam = data;
640
641         NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
642
643         switch (getparam->param) {
644         case NOUVEAU_GETPARAM_CHIPSET_ID:
645                 getparam->value = dev_priv->chipset;
646                 break;
647         case NOUVEAU_GETPARAM_PCI_VENDOR:
648                 getparam->value=dev->pci_vendor;
649                 break;
650         case NOUVEAU_GETPARAM_PCI_DEVICE:
651                 getparam->value=dev->pci_device;
652                 break;
653         case NOUVEAU_GETPARAM_BUS_TYPE:
654                 if (drm_device_is_agp(dev))
655                         getparam->value=NV_AGP;
656                 else if (drm_device_is_pcie(dev))
657                         getparam->value=NV_PCIE;
658                 else
659                         getparam->value=NV_PCI;
660                 break;
661         case NOUVEAU_GETPARAM_FB_PHYSICAL:
662                 getparam->value=dev_priv->fb_phys;
663                 break;
664         case NOUVEAU_GETPARAM_AGP_PHYSICAL:
665                 getparam->value=dev_priv->gart_info.aper_base;
666                 break;
667         case NOUVEAU_GETPARAM_PCI_PHYSICAL:
668                 if ( dev -> sg )
669                         getparam->value=(unsigned long)dev->sg->virtual;
670                 else
671                      {
672                      DRM_ERROR("Requested PCIGART address, while no PCIGART was created\n");
673                      return -EINVAL;
674                      }
675                 break;
676         case NOUVEAU_GETPARAM_FB_SIZE:
677                 getparam->value=dev_priv->fb_available_size;
678                 break;
679         case NOUVEAU_GETPARAM_AGP_SIZE:
680                 getparam->value=dev_priv->gart_info.aper_size;
681                 break;
682         default:
683                 DRM_ERROR("unknown parameter %lld\n", getparam->param);
684                 return -EINVAL;
685         }
686
687         return 0;
688 }
689
690 int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
691 {
692         struct drm_nouveau_private *dev_priv = dev->dev_private;
693         struct drm_nouveau_setparam *setparam = data;
694
695         NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
696
697         switch (setparam->param) {
698         case NOUVEAU_SETPARAM_CMDBUF_LOCATION:
699                 switch (setparam->value) {
700                 case NOUVEAU_MEM_AGP:
701                 case NOUVEAU_MEM_FB:
702                 case NOUVEAU_MEM_PCI:
703                 case NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE:
704                         break;
705                 default:
706                         DRM_ERROR("invalid CMDBUF_LOCATION value=%lld\n",
707                                         setparam->value);
708                         return -EINVAL;
709                 }
710                 dev_priv->config.cmdbuf.location = setparam->value;
711                 break;
712         case NOUVEAU_SETPARAM_CMDBUF_SIZE:
713                 dev_priv->config.cmdbuf.size = setparam->value;
714                 break;
715         default:
716                 DRM_ERROR("unknown parameter %lld\n", setparam->param);
717                 return -EINVAL;
718         }
719
720         return 0;
721 }
722
723 /* waits for idle */
724 void nouveau_wait_for_idle(struct drm_device *dev)
725 {
726         struct drm_nouveau_private *dev_priv=dev->dev_private;
727         switch(dev_priv->card_type) {
728         case NV_50:
729                 break;
730         default: {
731                 /* This stuff is more or less a copy of what is seen
732                  * in nv28 kmmio dump.
733                  */
734                 uint64_t started = dev_priv->Engine.timer.read(dev);
735                 uint64_t stopped = started;
736                 uint32_t status;
737                 do {
738                         uint32_t pmc_e = NV_READ(NV03_PMC_ENABLE);
739                         (void)pmc_e;
740                         status = NV_READ(NV04_PGRAPH_STATUS);
741                         if (!status)
742                                 break;
743                         stopped = dev_priv->Engine.timer.read(dev);
744                 /* It'll never wrap anyway... */
745                 } while (stopped - started < 1000000000ULL);
746                 if (status)
747                         DRM_ERROR("timed out with status 0x%08x\n",
748                                   status);
749         }
750         }
751 }