听说开源驱动现在已经不错了,就试着把系统里面的闭源驱动(fglrx)切换成开源驱动。
首先,先卸载闭源驱动:emerge -C x11-drivers/ati-drivers,因为现在用的xorg.conf是通过ati的命令生成的,先干掉。
然后,在make.conf中的VIDEO_CARDS环境变量中,将原来的fglrx改成radeon,重新emerge xorg-server和libdrm。
为了开启kms,需要重新改下内核,具体的做法可以参照官方的文档。需要注意的是,要将原来的framebuffer驱动都去掉(Device Drivers->Graphics support->Support for frame buffer devices中的所有驱动),然后将Device Drivers->Graphics support->Direct Rendering Manager和它下面的ATI Radeon和Enable modesetting on radeon by default这两个子项编译入内核(启动Enable modesetting on radeon by default是ATI Radeon的子项)。对于radeon,还有特别重要的一点,就是要将固件编译入内核。首先要确保已经安装了x11-drivers/radeon-ucode这个包,然后在内核中,Device Drivers->Generic Driver Options中选中Include in-kernel firmware blobs in kernel binary,在下面的External firmware blobs to build into the kernel binary中,填入radeon/R600_rlc.bin radeon/R700_rlc.bin(我的显卡是HD 3400 Series),在Firmware blobs root directory中填入/lib/firmware,然后就可以重新编译内核了。
重新编译、安装完内核之后,就是要编辑grub.cfg文件了,去掉原来为splash使用的initrd,直接使用新内核。
重新启动,可以看见字符界面中,已经自动使用了1280×800的分辨率。不过进入kde之后,图形界面非常卡,kde还因为速度慢自动关闭了混成特效。后来发现是mesa没有重新emerge,重新安装了mesa然后重新登陆,原先kwin的效果仍然可以使用,大功告成。
安装debian系统的过程:1.首先,格式化成主分区,ext2分区;
拷贝两个文件系统的压缩包进新硬盘,使用root权限解压压缩包;
删除/boot/vmlinux,拷贝我们编译好的内核进/boot/目录;同时修改/etc/X11/xorg.conf文件中device栏中的pci设备号,功能号和总线号;
linux内核中显卡驱动的修改:如上面的介绍;
DMA通道支持Scatter/ Gather(聚/散)DMA和Block(块)DMA两种式。前者可以只用一次DMA操作传输非连续存储的多个数据块,但是主机或者本地处理器需要首先建立描述块,然后设置DMA的方式,并用描述块的地址初始化DMA描述指针寄存器(Descriptor Pointer Register),最后设置DMACSR来启动DMA操作。DMA启动之后首先从描述块中读出第一个描述块,然后开始DMA传输。
get_user_pages是用来将用户空间的页(pages)映射(锁)入内存,并得到它们的页结构(struct page)指针。
page_cache_release(pdx->DmaInfo[channel].PageList[i] );
用到get_user_pages函数还需page_cache_release来解锁。
BusAddr=pci_map_page( pdx, pdx->DmaInfo[channel].PageList[i], offset,BlockSize, pdx->DmaInfo[channel].direction );
由get_user_pages得到页表后,通过pci_map_page函数得到此页的总线地址(此地址写入DMA Channel 0/1 PCI Address寄存器)。
BusAddr=pci_map_page( pdx, pdx->DmaInfo[channel].PageList[i], offset,BlockSize, pdx->DmaInfo[channel].direction );
由get_user_pages得到页表后,通过pci_map_page函数得到此页的总线地址(此地址写入DMA Channel 0/1 PCI Address寄存器)。
上面是dma的经典写法,当驱动供用户空间使用时,get_user_pages能很好的工作。但是,当驱动时供内核调用,get_user_pages就会出错,此函数对用户缓冲区有效。这时有一个很好的函数virt_to_page,它可以由内核虚拟地址得到页结构,代替了get_user_pages的使用。
在x86下,外设的i/o地址是独立的,即有专门的指令访问外设i/o,i/o地址就是所谓的“总线地址”。而“物理地址”就是ram地址。
在arm中,i/o和ram统一编址,但linux为了统一各个平台,仍然保留这个概念,其实就是物理地址。
linux 无论kernel还是user space,都是直接访问虚拟地址(uclinux除外),要访问i/o,必须把i/o地址转换成虚拟地址才能访问。
MMU启动前程序中的地址为物理地址,和硬件手册中规定的地址一致。MMU启动后程序中的地址为虚拟地址,参照MMU地址映射表
4670显卡驱动初始化过程:
int rv770_init(struct radeon_device *rdev)
{
//申请dma空间并转换成总线地址
r = radeon_dummy_page_init(rdev);
/* This don't do much 就是初始化了gem链表*/