Nouveau源码分析(三)
向DRM注册了Nouveau驱动之后,内核中的PCI模块就会扫描所有没有对应驱动的设备,然后和nouveau_drm_pci_table对照.
对于匹配的设备,PCI模块就调用对应的probe函数,也就是nouveau_drm_probe.
// /drivers/gpu/drm/nouveau/nouveau_drm.c
281 static int nouveau_drm_probe(struct pci_dev *pdev,
282 const struct pci_device_id *pent)
283 {
284 struct nouveau_device *device;
285 struct apertures_struct *aper;
286 bool boot = false;
287 int ret;
288
289 /* remove conflicting drivers (vesafb, efifb etc) */
290 aper = alloc_apertures(3);
291 if (!aper)
292 return -ENOMEM;
293
294 aper->ranges[0].base = pci_resource_start(pdev, 1);
295 aper->ranges[0].size = pci_resource_len(pdev, 1);
296 aper->count = 1;
297
298 if (pci_resource_len(pdev, 2)) {
299 aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
300 aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
301 aper->count++;
302 }
303
304 if (pci_resource_len(pdev, 3)) {
305 aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
306 aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
307 aper->count++;
308 }
309
310 #ifdef CONFIG_X86
311 boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
312 #endif
313 if (nouveau_modeset != 2)
314 remove_conflicting_framebuffers(aper, "nouveaufb", boot);
315 kfree(aper);
316
317 ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI,
318 nouveau_pci_name(pdev), pci_name(pdev),
319 nouveau_config, nouveau_debug, &device);
320 if (ret)
321 return ret;
322
323 pci_set_master(pdev);
324
325 ret = drm_get_pci_dev(pdev, pent, &driver);
326 if (ret) {
327 nouveau_object_ref(NULL, (struct nouveau_object **)&device);
328 return ret;
329 }
330
331 return 0;
332 }
第290~315行,分配了一个aper,把资源位置写进去,调用了remove_conflicting_framebuffer,接着释放这个aper.
一行注释和函数名已经说的很明白,就是移除冲突的framebuffer.
第317行,创建一个NV设备的结构体,这个函数我们要仔细看
// /drivers/gpu/drm/nouveau/core/include/engine/device.h
13 #define nouveau_device_create(p,t,n,s,c,d,u) \
14 nouveau_device_create_((void *)(p), (t), (n), (s), (c), (d), \
15 sizeof(**u), (void **)u)
16
17 int nouveau_device_create_(void *, enum nv_bus_type type, u64 name,
18 const char *sname, const char *cfg, const char *dbg,
19 int, void **);
想起了什么? 对,就是上一节讲的内容,我们还是先来看结构体.
// /drivers/gpu/drm/nouveau/core/include/core/device.h
65 struct nouveau_device {
66 struct nouveau_engine base;
67 struct list_head head;
68
69 struct pci_dev *pdev;
70 struct platform_device *platformdev;
71 u64 handle;
72
73 struct nvkm_event event;
74
75 const char *cfgopt;
76 const char *dbgopt;
77 const char *name;
78 const char *cname;
79 u64 disable_mask;
80
81 enum {
82 NV_04 = 0x04,
83 NV_10 = 0x10,
84 NV_11 = 0x11,