Most of the time, when you want to help or contribute to a "libre" project, you are lost. This page will try to help new developers getting up to speed on nouveau development by overviewing some base concepts and giving some code and web pointers. ### The Memory [[x86 architecture|http://en.wikipedia.org/wiki/X86_architecture]] has 3 memory address spaces: * The [[physical memory address space|http://en.wikipedia.org/wiki/Physical_address]] is used for communication with the [[memory controller|http://en.wikipedia.org/wiki/Memory_controller]]. That's the one mainly used for driver development. You can access it with the `/dev/mem` device node. * The [[virtual memory address space|http://en.wikipedia.org/wiki/Virtual_address]] is what a process sees. It's managed by [[memory management unit|http://en.wikipedia.org/wiki/Memory_management_unit]] inside the [[microprocessor|http://en.wikipedia.org/wiki/Microprocessor]]. * The [[I/O (Input/Output) ports space|http://en.wikipedia.org/wiki/Memory-mapped_I/O]]. It is an address space on its own, namely it does not have any connection with the 2 previous address spaces. It's used for VGA hardware programming. On [[x86 architecture|http://en.wikipedia.org/wiki/X86_architecture]], the [[physical<->virtual(logical) memory mapping|http://www.bertolinux.com/kernel/english/KernelAnalysis-HOWTO-7.html#ss7.3]] is done using the [[pagination|http://en.wikipedia.org/wiki/Page_table]] mechanism. ### PCI (Peripheral Component Interconnect) Your are going to plug your graphic cards into [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] slots on your [[motherboard|http://en.wikipedia.org/wiki/Motherboard]]. [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] specifications are not freely available to the public :( . But in our case, we will only want to have an overall understanding of the programming model. The programming entry point for this computer [[bus|http://en.wikipedia.org/wiki/Bus_(computing)]] is the [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] [[configuration space|http://en.wikipedia.org/wiki/PCI_Configuration_Space]]. It is accessed with the `0xCF8` and `0xCFC` I/O ports in the [[x86 architecture|http://en.wikipedia.org/wiki/X86_architecture]] I/O ports address space. To be a bit more specific `0xCF8` is the address port, and the `0xCFC` the data port. Each [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] entity (minimal addressable unit on the [[bus|http://en.wikipedia.org/wiki/Bus_(computing)]] like the byte in memory) has its own [[configuration space|http://en.wikipedia.org/wiki/PCI_Configuration_Space]]. You can have a look at some code in the [[Linux|http://www.kernel.org]] kernel source code to have a deeper understanding. Check out _linux_kernel_source_`/arch/i386/pci/direct.c` source file. In the case of the [[XORG|http://www.x.org/]] server, you have a [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] programming module which write accesses `/dev/mem` (that's one of the reasons why the [[XORG|http://www.x.org/]] server must run with root privileges). Have a look at _xorg-server_source_`/hw/xfree86/os-support/bus/Pci.c` source file and _xorg-server_source_`/hw/xfree86/doc/devel/RAC.notes`. You can play with the [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect"]] system using the [[pciutils|http://mj.ucw.cz/pciutils.shtml]] or directly with the [[Linux|http://www.kernel.org/]] kernel sysfs (system file system) file in `/sys/bus/pci/devices`. Both methods will interpret the content of the [[configuration space|http://en.wikipedia.org/wiki/PCI_Configuration_Space]]. An entity will have in its [[configuration space|http://en.wikipedia.org/wiki/PCI_Configuration_Space]] 3 types of resources: * I/O memory. This is a chunk of physical memory which is decoded by the entity. Checkout the content of the `/proc/iomem`. * I/O ports. Those from the [[I/O ports space|http://en.wikipedia.org/wiki/Memory-mapped_I/O]] that will be decoded by the entity. Checkout the content of the `/proc/ioports` file. * IRQs (Interrupt ReQuests). Checkout the content of the `/proc/irq` directory. The configuration of such resources is done using 2 systems: * [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] [[PNP|http://tldp.org/HOWTO/Plug-and-Play-HOWTO.html]] (Plug-aNd-Play) which is obsolete. * ACPI (Advanced Configuration and Power Interface) which is the current way to do it, see [[below|GraphicStackOverview#ACPI]]. [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect"]] programming using the [[XORG|http://www.x.org/]] server is ugly. It is a task which is meant to be done by the OS (Operating System) kernel. ### AGP (Accelerated Graphic Port), PCI Express cards A graphic card plugged into an [[AGP|http://en.wikipedia.org/wiki/Accelerated_Graphics_Port]] slot or a [[PCI Express|http://en.wikipedia.org/wiki/PCI_Express]] slot will be seen by the system like a [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] device. ### ACPI (Advanced Configuration and Power Interface) Today, computers are [[ACPI|http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface]] capable. [[ACPI|http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface]] replaces [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] [[PNP|http://tldp.org/HOWTO/Plug-and-Play-HOWTO.html]] for of entity configuration and adds power management, multiprocessors sweet, and other things to the lot. Unlike [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]], [[ACPI|http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface]] [[specification|http://www.acpi.info/]] is freely available. [[ACPI|http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface]] is memory table based: at computer boot time, the OS must find the RSDP (Root System Description Pointer) in physical memory. On [[x86 architecture|http://en.wikipedia.org/wiki/X86_architecture]], it is a matter of finding the "RSD PTR" string in specific physical memory regions. Checkout the Intel Architecture - Personal Computer (IA-PC) section in the [[specification|http://www.acpi.info/]] and the `acpi_scan_rsdp` function in _linux_kernel_source_`/arch/i386/kernel/acpi/boot.c`. ### XORG, DDX (Device Dependent X) and DIX (Device Independent X) * [[XORG|http://www.x.org/]] is the lot, the entire project, the reference implementation of the client libs and servers of the [[X Window System|http://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture]]. You need to understand the [[X Window core protocol|http://en.wikipedia.org/wiki/X_Window_core_protocol]]. Keep in mind that [[XORG|http://www.x.org/]] has more than one server like the DMX (Distributed Multihead X) server, the kdrive server or the famous XGL server. * DIX is the part of [[XORG|http://www.x.org/]] which deals with the clients, network transparency and software rendering. In the [[XORG|http://www.x.org/]] source package layout, it's almost everything except the _xorg-server_source_`/hw` directory. You will find the **`main`** function, in _xorg-server_source_`/dix/main.c` source file. * DDX is the part of [[XORG|http://www.x.org/]] dealing with the hardware (and with the OSes to a certain extend). There are several DDX in the _xorg-server_source_`/hw` directory of the [[XORG|http://www.x.org/]] source package: XGL, kdrive, xfree86 etc... The one we are interested in is of course the xfree86 one since nouveau is a set of hardware drivers for this DDX. Indeed, each DDX comes with its hardware drivers. Have a look in _xorg-server_source_`/hw/kdrive`, there you will find drivers for several cards for the kdrive X server. The assembly of the xfree86 DDX with the DIX part shape the famous [[XORG|http://www.x.org/]] server. ### XORG server design One of the first things the [[XORG|http://www.x.org/]] server will do is to load the nouveau video driver module. The xfree86 DDX implements a dynamic module loading system which is just a wrapper around the [[libc|http://www.gnu.org/software/libc/libc.html]] dynamic loader. The dynamic loader is based on symbols, namely function entry points or data pointers which are resolved or not at runtime. To understand the document below, you must know what is a _server generation_. When you start the [[XORG|http://www.x.org/]] server, the first _server generation_ is generated. When the last client goes away, then a new _server generation_ will start. You will see in the DIX and DDX code that there is a significant difference between the first _server generation_ and subsequent _server generation_s because some operations are useless to be performed several times, for instance sockets creation. To understand the [[XORG|http://www.x.org/]] server design, read ******very****** carefully ******[[the xfree86 DDX DESIGN document|http://webcvs.freedesktop.org/xorg/xc/programs/Xserver/hw/xfree86/doc/DESIGN?view=markup]]******. [[X Window System|http://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture]] model revolves around the _screen_ object, and the previous document states that one _screen_ is managed by one video driver only in the xfree86 DDX. Moreover don't forget that a _screen_ has a xfree86 DDX structure (`ScrnInfoRec` living for the entire server life) and DIX structure (`ScreenRec` living for only one server generation), both embedding some per _screen_ video driver private data. Of course, there is also [[in depth documentation|http://gitweb.freedesktop.org/?p=xorg/doc/xorg-docs.git;a=tree]]. ### Video mode setting and RandR (the X Resize, Rotate and Reflect Extension in short) 1.2 extension One of latest big improvements in [[XORG|http://www.x.org/]] is the [[RandR 1.2 extension|http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git;a=blob;h=345ef4eca0f58b7c98b45d51d114dbb4b6d09e02;hb=aada204b1fc9ba6461efad3fe6bd032ee98536e1;f=randrproto.txt]]. It's a system that allows fine grained control of video mode setting. The RandR model deals with outputs and CRTCs (Cathode Ray Tube Controllers). CRTC is a legacy name from the past when all display devices were Cathode Ray Tubes. Today, a CRTC can drive flat displays. Typical nvidia chips embed 2 CRTCs, and the cards which host those chips have typically a [[S-Video|http://en.wikipedia.org/wiki/S-video]] (Separate Video) connector which outputs [[PAL|http://en.wikipedia.org/wiki/PAL]] (Phase Alternating Line) or [[NTSC|http://en.wikipedia.org/wiki/NTSC]] (National Television System(s) Committee) video signal, have a [[VGA|http://en.wikipedia.org/wiki/VGA_connector]] (Video Graphics Array) connector which outputs a VGA signal, a [[DVI|http://en.wikipedia.org/wiki/Digital_Visual_Interface]] (Digital Visual Interface) connector which outputs a VGA signal and/or a single/dual [[TMDS|http://en.wikipedia.org/wiki/TMDS]] (Transition Minimized Differential Signaling) digital signal. On mobile editions of nvidia chips, you will have pins outputting [[LVDS|http://en.wikipedia.org/wiki/Low_voltage_differential_signaling]] (Low Voltage Differential Signaling) in order to drive a LDFP (Local Digital Flat Panel). There is a [[GIT|http://git.or.cz]] [[RandR-1.2 branch|http://gitweb.freedesktop.org/?p=nouveau/xf86-video-nouveau.git;a=shortlog;h=randr-1.2]] for the nouveau video driver. ### The nouveau xfree86 DDX video driver module If you read **properly** the ******[[the xfree86 DDX DESIGN document|http://webcvs.freedesktop.org/xorg/xc/programs/Xserver/hw/xfree86/doc/DESIGN?view=markup]]******, and in particular its latest section, you will look for the `nouveauModuleData` structure in _xf86-video-nouveau_`/src/nv_driver.c` source file from the nouveau xfree86 DDX video driver source package directory layout. This structure will tell you there is only a setup function for this driver called right after the module is loaded in the [[XORG|http://www.x.org/]] server address space, called `nouveauSetup` in _xf86-video-nouveau_source_`/src/nv_driver.c` source file. `nouveauSetup` will register the nouveau `DriverRec` structure that will points to the `NVIdentify`, `NVProbe` and `NVAvailableOptions` functions, still in _xf86-video-nouveau_source_`/src/nv_driver.c`. During the probe phase of the [[XORG|http://www.x.org/]] server done using the `NVProbe` function of the video driver module, driver hooks in the xfree86 DDX `ScrnInfoRec` will be filled in. Here come, `NVPreInit`, `NVScreenInit`, `NVSwitchMode`, `NVAdjustFrame`, `NVEnterVT`, `NVLeaveVT`, `NVFreeScreen`, `NVValidMode` driver functions. * `NVIdentify` from the `DriverRec` structure named `NV` prints information about the chipsets handled by the driver. In _xf86-video-nouveau_source_`/src/nv_driver.c` this function logs the chipsets families supported and in _xf86-video-nv_source_/src/nv_driver.c` this function logs all of the chipsets supported with their [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] ids (identifiers). * `NVAvailableOptions` from the `DriverRec` structure named `NV` provides the initialized `OptionInfoRec` structure which will describe the various configuration options for this driver. Yes, those options which can be set in the device section of the famous _xorg.conf_ file. In _xf86-video-nouveau_source_`/src/nv_driver.c`, those options are statically defined in the `OptionInfoRec` structure named `NVOptions` in _xf86-video-nouveau_source_`/src/nv_const.h`. `NVAvailableOptions` from _xf86-video-nv_source_`/src/nv_driver.c` is the same, except that there is a special `OptionInfoRec` structure for the riva 128 chip the riva driver files (for chipset archaeologists) and the common `OptionInfoRec` structure lies into _xf86-video-nouveau_source_`/src/nv_driver.c`. * `NVProbe` looks for the supported chipsets on the [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] bus and match them with the enabled device sections from the X server configuration. If the PROBE_DETECT flag is passed to this probe function, only detection is performed, no [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] resources are claimed by the driver. There is a special detection for some _bridged_ [[AGP|http://en.wikipedia.org/wiki/Accelerated_Graphics_Port]]/[[PCI Express|http://en.wikipedia.org/wiki/PCI_Express]] chipsets. Those [[AGP|http://en.wikipedia.org/wiki/Accelerated_Graphics_Port]] chipsets _bridged_ to [[PCI Express|http://en.wikipedia.org/wiki/PCI_Express]] have special [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] ids. The real [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] ids of the chipset for programming purpose is stored in the chipset [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] [[mmio|http://en.wikipedia.org/wiki/Memory-mapped_I/O]] (Memory Mapped Input Output). Indeed, this is an ugly hack. * `NVPreInit` is `NVProbe` on steroids. It will determine the amount of video ram, will validate video modes, etc... One thing the driver will do is to determine the chipset architecture from the ids calling `NVDetermineChipsetArch` (inline for the NV driver). It checks for 32 bpp (bits per pixel) support and that the color depth is 8,15,16 or 24 bits. It shows that there are at most 2 CRTCs. The NV driver supports Dual``Head which seems to be configured only through the xfree86 DDX vbe module and implies no hardware cursor and the following new event handling functions: `NVSwitchModeVBE`, `NVEnterVTVBE` and `NVLeaveVTVBE`. Locating the VRAM mapping base physical address implies to mask the [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] entity second memory base address with the 0xFF800000 value. Same thing for the MMIO registers base physical address (first [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] entity memory base address) with the 0xFFFFC000 value. #### EXA EXA is not an acronym. It is an [[API|http://en.wikipedia.org/wiki/Application_programming_interface]] for [[XORG|http://www.x.org/]] acceleration. The xfree86 DDX is the only DDX to implement it. EXA acceleration is initialized (if enabled) each time a _screen_ is initialized (for instance at the start of a new _server generation_), hence checkout the `NVScreenInit` function in _xf86-video-nouveau_source_`/src/nv_driver.c`. In the case EXA is enabled in the configuration file, you will be routed to `NVExaInit` in _xf86-video-nouveau_source_`/src/nv_exa.c` source file. In this function, all the EXA hooks will be sent to the [[XORG|http://www.x.org/]] EXA module and initialized with the `exaDriverInit` EXA module function, namely: `NVDownloadFromScreen`, `NVUploadToScreen`, `NVExaPrepareCopy`, `NVExaCopy`, `NVExaDoneCopy`, `NVExaPrepareSolid`, `NVExaSolid`, `NVExaDoneSolid`, `NVCheckComposite`, `NVPrepareComposite`, `NVComposite`, `NVDoneComposite`, all those functions are in _xf86-video-nouveau_source_`/src/nv_exa.c`. More on EXA on [[freedesktop wiki|http://wiki.x.org/wiki/ExaStatus]] and in _xorg-server_source_`/hw/xfree86/doc/devel/exa-driver.txt` #### DRI (Direct Rendering Infrastructure) and its kernel counterpart, the DRM (Direct Rendering Manager) The [[DRI|http://en.wikipedia.org/wiki/Direct_Rendering_Infrastructure]] and the [[DRM|http://en.wikipedia.org/wiki/Direct_Rendering_Manager]] are the plumbing for programming the graphic card hardware. It is mainly used by [[mesa|http://www.mesa3d.org/]], the "libre" opengl implementation, but since the access to the hardware must be synchronized among all graphic card hardware clients, the xfree86 DDX video driver module has to cope with it since itself is such client. Then when EXA will want to perform accelerated operations, it will have to _DRI dialog_ with the hardware. You have a [[DRI|http://en.wikipedia.org/wiki/Direct_Rendering_Infrastructure]] xfree86 DDX module in _xorg-server_source_`/hw/xf86/dri` for xfree86 DDX code which wants hardware access the [[DRI|http://en.wikipedia.org/wiki/Direct_Rendering_Infrastructure]] way. This module and the related xfree86 DDX code will use the DRM user level interface library, [[libdrm|http://dri.freedesktop.org/libdrm/]]. In theory, future DRM evolution will allow us to get rid of the [[PCI|http://en.wikipedia.org/wiki/Peripheral_Component_Interconnect]] programming code from [[XORG|http://www.x.org/]] server.