当前位置:文档之家› 如何编写一个显卡的驱动程序

如何编写一个显卡的驱动程序

如何编写一个显卡的驱动程序
如何编写一个显卡的驱动程序

如何编写一个显卡的驱动程序

在后续的几篇里面会详细介绍如何编写一个显卡的驱动程序。

framebuffer device在内核里面作为显卡驱动模型,许多函数和数据结构都是特定,正是这些特定的东西为我们的编程提供了方便。要开发frame buffer device驱动,你应该阅读

Source\Source\Documentation\fb下面的说明文件,三个重要文件00-INDEX, framebuffer.txt,internals.txt,其他文件都是针对具体显卡芯片的说明了。

文件00-INDEX译文

文档/documentation/fb的索引文件。如果你对frame buffer设备有什么想法,mail:Geert Uytterhoeven

00-index 这个文件

framebuffer.txt--- frame buffer 设备介绍

internals.txt----frame buffer设备内部快速浏览

modedb.txt----关于视频模式的资料

aty128fb.txt----关于ATI Rage128显卡的frame buffer设备

clgenfb.txt-----关于Cirrus Logic的显卡

matroxfb.txt----关于Matrox的显卡

pvr2fb.txt----关于PowerVR 2的显卡

tgafb.txt----关于TGA(DECChip 21030)显卡

vesafb.txt----关于VESA显卡

帧缓冲设备(framebuffer.txt译文)

维护: Geert Uytterhoeven

最后校正: May 10, 2001

翻译:good02xaut@https://www.doczj.com/doc/779772029.html,

0.介绍

帧缓冲设备提供了显卡的抽象描述。他同时代表了显卡上的显存,应用程序通过定义好的接口可以访问显卡,而不需要知道底层的任何操作。该设备使用特殊的设备节点,通常位于/dev目录,如/dev/fb*.

1.用户角度的/dev/fb*

从用户的角度看,帧缓冲设备和其他位于/dev下面的设备类似。他是一个字符设备,通常主设备号是29,次设备号定义帧缓冲的个数。

通常,使用如下方式(前面的数字代码次设备号)

0 = /dev/fb0 First frame buffer

1 = /dev/fb1 Second frame buffer

...

31 = /dev/fb31 32nd frame buffer

考虑到向下兼容,你可以创建符号链接:

/dev/fb0current -> fb0

/dev/fb1current -> fb1

and so on...

帧缓冲设备也是一种普通的内存设备,你可以读写其内容。例如,对屏幕抓屏:

cp /dev/fb0 myfile

你也可以同时有多个显示设备,例如你的主板上出了内置的显卡还有另一独立的显卡。对应的帧缓冲设备(/dev/fb0 and /dev/fb1 etc.)可以独立工作。

应用程序如 X server一般使用/dev/fb0作为默认的显示帧缓冲区。你可以自定把某个设备作为默认的帧缓冲设备,设置$FRAMEBUFFER环境变量即可。在sh/bash:

export FRAMEBUFFER=/dev/fb1

在csh中:

setenv FRAMEBUFFER /dev/fb1

设定后,X server将使用第二个帧缓冲区设备。

2.程序员角度看/dev/fb*

正如你所知,一个帧缓冲设备和内存设备类似/dev/mem,并且有许多共性。你可以read,write,seek以及mmap()。不同仅仅是帧缓冲的内存不是所有的内存区,而是显卡专用的那部分内存。

/dev/fb*也允许尽行ioctl操作,通过ioctl可以读取或设定设备参数。颜色映射表也是通过Ioctl设定。查看就知道有多少ioctl应用以及相关数据结构。

这里给出摘要:

- 你可以获取设备一些不变的信息,如设备名,屏幕的组织(平面,象素,...)对应内存区的长度和起始地址。

- 也可以获取能够发生变化的信息,例如位深,颜色格式,时序等。如果你改变这些值,驱动程序将对值进行优化,以满足设备特性(返回EINVAL,如果你的设定,设备不支持)

- 你也可以获取或设定部分颜色表。

所有这些特性让应用程序十分容易的使用设备。X server可以使用/dev/fb*而不需知道硬件的寄存器是如何组织的。 XF68_FBDev是一个用于位映射(单色)X server,唯一要做的就是在应用程序在相应的位置设定是否显示。

在新内核中,帧缓冲设备可以工作于模块中,允许动态加载。这类驱动必须调用register_framebuffer()在系统中注册。使用模块更方便!

3.帧缓冲分辨率设定

帧缓冲的分辨率可以用工具fbset设定。他可以改变视频设备的显示模式。主要就是改变当前视频模式,如在启动过程中,在/etc/rc.* 或 /etc/init.d/* 文件中调用,可以把视频模式从单色显示变成真彩. fbset使用存储在配置文件中的视频模式数据表,你可以在文件中增加自己需要的显示模式。

4.X Server

X server (XF68_FBDev)是对帧缓冲设备的最主要应用。从XFree86 3.2后,X server就是XFree86 的一部分了,有2个工作模式:

- 在/etc/XF86Config文件中,如果`Display'段关于 `fbdev'的配置:

Modes "default"

X server 将使用前面讨论的,从环境变量$FRAMEBUFFER获取当前帧缓冲设备.

你也可以设定颜色位深,使用Depth关键字,使用Virtual设定虚拟分辨率。这也是默认设置。

- 然而你也可以通过设定/etc/XF86Config,改变分辨率。这样有很多灵活性,唯一的不足就是你必须设定刷新频率。可以用fbset -x通过fbset或xvidtune切换显示模式。

5.视频模式频率

CRT显示器是用3个电子枪轰击磷粉完成颜色的显示的。电子枪从左到右的水平扫描,并从上至下的垂直扫描。通过改变枪的电压,所显示的颜色可以不同。当电子枪完成一行扫描重新回到下一行的开始,被称作“水平折回”。当一屏幕全部扫描完毕,电子枪将回到最左上脚,被成为“垂直折回”。在折回的途中电子枪是关闭的。电子枪打点的移动速度取决于点时钟。如果点时钟是28.37516 MHz,打一个点需要35242 ps。

1/(28.37516E6 Hz) = 35.242E-9 s

如果屏幕分辨率是640x480,那么一行的时间是:

640*35.242E-9 s = 22.555E-6 s

然而水平折回也是需要时间的,通常272个打点时间,因此一行总共需要:

(640+272)*35.242E-9 s = 32.141E-6 s

我们就认为水平扫描的频率是31KHz:

1/(32.141E-6 s) = 31.113E3 Hz

一屏幕含有480行,加上垂直折回时间49,一屏所需的时间:

(480+49)*32.141E-6 s = 17.002E-3 s

我们就认为垂直扫描的频率是59Hz:

1/(17.002E-3 s) = 58.815 Hz

这也意味着屏幕数据每秒钟刷新59次。为了得到稳定的图像显示效果,VESA垂直扫描频率不低于72Hz。但是也因人而异,有些人50Hz感觉不到任何问题,有些至少在80Hz以上才可以。

由于显示器不知道什么时候新行开始扫描,显卡为每一行扫描提供水平同步信号。类似的,他也为每一帧显示提供垂直同步信号。图像在屏幕上点的位置取决于这些同步信号的发生时刻。下图给出了所有时序的概要。水平折回的时间就是左边空白+右边空白+水平同步长度。垂直折回的时间就是上空白+下空白+垂直同步长。

+----------+---------------------------------------------+----------+-------+

| | ^ | | |

| | |upper_margin | | |

| | ? | | |

+----------###############################################----------+-------+

| # ^ # | |

| # | # | |

| # | # | |

| # | # | |

| left # | # right | hsync |

| margin # | xres # margin | len |

|<-------->#<---------------+--------------------------->#<-------->|<----->|

| # | # | |

| # | # | |

| # | # | |

| # |yres # | |

| # | # | |

| # | # | |

| # | # | |

| # | # | |

| # | # | |

| # | # | |

| # | # | |

| # | # | |

| # ? # | |

+----------###############################################----------+-------+

| | ^ | | |

| | |lower_margin | | |

| | ? | | |

+----------+---------------------------------------------+----------+-------+

| | ^ | | |

| | |vsync_len | | |

| | ? | | |

+----------+---------------------------------------------+----------+-------+

6.把XFree86时序变成frame buffer device时序

典型的显示模式:

"800x600" 50 800 856 976 1040 600 637 643 666

< name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL

而帧缓冲设备使用下面的参数:

- pixclock: 点时钟 in ps (pico seconds)

- left_margin: time from sync to picture

- right_margin: time from picture to sync

- upper_margin: time from sync to picture

- lower_margin: time from picture to sync

- hsync_len: length of horizontal sync

- vsync_len: length of vertical sync

1) Pixelclock:

xfree: in MHz

fb: in picoseconds (ps)

pixclock = 1000000 / DCF

2) horizontal timings:

left_margin = HFL - SH2

right_margin = SH1 - HR

hsync_len = SH2 - SH1

3) vertical timings:

upper_margin = VFL - SV2

lower_margin = SV1 - VR

vsync_len = SV2 - SV1

更好的VESA的例子可以在XFree86的源码中找到,"xc/programs/Xserver/hw/xfree86/doc/modeDB.txt".

7. 引用

获取更多关于帧缓冲设备以及应用的参考,请访问:https://www.doczj.com/doc/779772029.html,/或者查阅下面的文档:

- The manual pages for fbset: fbset(8), fb.modes(5)

- The manual pages for XFree86: XF68_FBDev(1), XF86Config(4/5)

- The mighty kernel sources:

o linux/drivers/video/

o linux/include/linux/fb.h

o linux/include/video/

帧缓冲设备的内部数据结构(internals.txt)

Geert Uytterhoeven , 21 July 1998

翻译:good02xaut@https://www.doczj.com/doc/779772029.html,

××××帧缓冲设备中用到的结构体××××

以下数据结构在帧缓冲设备使用,定义

1. Outside the kernel (user space)

?struct fb_fix_screeninfo

?帧缓冲设备中设备无关的常值数据信息。可以通过Ioctl的FBIOGET_FSCREENINFO获取。

?struct fb_var_screeninfo

?帧缓冲设备中设备无关的变量数据信息和特定的显示模式。可以通过iotcl的FBIOGET_VSCREENINFO获取,并通过ioctl的FBIOPUT_VSCREENINFO设定。还有FBIOPAN_DISPLAY 可以用。

?struct fb_cmap

?设备无关的颜色表信息。你可以通过ioctl的FBIOGETCMAP 和 FBIOPUTCMAP读取或设定。2. Inside the kernel

?struct fb_info

?常规信息,API以及帧缓冲设备的底层信息(主板地址...).

?struct `par'

?唯一指定该设备的显示模式的设备相关信息。

?struct display

?帧缓冲设备和控制台驱动之间的接口。

--------------------------------------------------------------------------------

*** 常用的帧缓冲 API ***

Monochrome (FB_VISUAL_MONO01 and FB_VISUAL_MONO10)

-------------------------------------------------

每个象素是黑或白。

Pseudo color (FB_VISUAL_PSEUDOCOLOR and FB_VISUAL_STATIC_PSEUDOCOLOR)

---------------------------------------------------------------------

索引颜色显示

True color (FB_VISUAL_TRUECOLOR)

--------------------------------

真彩显示,分成红绿兰三基色

Direct color (FB_VISUAL_DIRECTCOLOR)

------------------------------------

每个象素颜色也是有红绿蓝组成,不过每个颜色值是个索引,需要查表。

Grayscale displays

------------------

灰度显示,红绿蓝的值都一样

准备开始写我们自己的驱动之前,请详细阅读如下文件:

\Documentation\fb目录 vesafb.txt,matroxfb.txt,sa1100fb.txt

\drivers\video目录 fbmem.c,fbgen.c,fbmon.c,fbcmap.c

skeletonfb.c

vesafb.c,sa1100fb.c,sa1100fb.h

include\linux目录 fb.h

最值得关注的是skeletonfb.c,该文件给出了一个fb device 驱动的框架。准备好了,就开始写自己的fram buffer device driver:)

还是要补充点,下面是/linux/fb.h的部分注释,加粗的是常用的,红色是关键的,一般不可少。旁边没有汉字,要么很简单没必要加注,要么就用不到!注释:good02xaut@https://www.doczj.com/doc/779772029.html,

#ifndef _LINUX_FB_H

#define _LINUX_FB_H

#include

#include

/* Definitions of frame buffers */

#define FB_MAJOR 29 /*主设备号*/

#define FB_MAX 32 /* sufficient for now */

/* ioctls

0x46 is 'F' */

#define FBIOGET_VSCREENINFO 0x4600

#define FBIOPUT_VSCREENINFO 0x4601

#define FBIOGET_FSCREENINFO 0x4602

#define FBIOGETCMAP 0x4604

#define FBIOPUTCMAP 0x4605

#define FBIOPAN_DISPLAY 0x4606

/* 0x4607-0x460B are defined below */

/* #define FBIOGET_MONITORSPEC 0x460C */

/* #define FBIOPUT_MONITORSPEC 0x460D */

/* #define FBIOSWITCH_MONIBIT 0x460E */

#define FBIOGET_CON2FBMAP 0x460F

#define FBIOPUT_CON2FBMAP 0x4610

#define FBIOBLANK 0x4611 /* arg: 0 or vesa level + 1 */

#define FBIOGET_VBLANK _IOR('F', 0x12, struct fb_vblank)

#define FBIO_ALLOC 0x4613

#define FBIO_FREE 0x4614

#define FBIOGET_GLYPH 0x4615

#define FBIOGET_HWCINFO 0x4616

#define FBIOPUT_MODEINFO 0x4617

#define FBIOGET_DISPINFO 0x4618

#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */

#define FB_TYPE_PLANES 1 /* Non interleaved planes */

#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */

#define FB_TYPE_TEXT 3 /* Text/attributes */

#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */

#define FB_AUX_TEXT_MDA 0 /* Monochrome text */

#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */

#define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */

#define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 reserved bytes */ #define FB_AUX_TEXT_MGA_STEP8 4 /* other MGAs: text, attr, 6 reserved bytes */

#define FB_AUX_VGA_PLANES_VGA4 0 /* 16 color planes (EGA/VGA) */

#define FB_AUX_VGA_PLANES_CFB4 1 /* CFB4 in planes (VGA) */

#define FB_AUX_VGA_PLANES_CFB8 2 /* CFB8 in planes (VGA) */

#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */

#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */

#define FB_VISUAL_TRUECOLOR 2 /* True color */

#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */

#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */

#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */

#define FB_ACCEL_NONE 0 /* no hardware accelerator */

#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */

#define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */

#define FB_ACCEL_S3_TRIO64 3 /* Cybervision64 (S3 Trio64) */

#define FB_ACCEL_NCR_77C32BLT 4 /* RetinaZ3 (NCR 77C32BLT) */

#define FB_ACCEL_S3_VIRGE 5 /* Cybervision64/3D (S3 ViRGE) */

#define FB_ACCEL_ATI_MACH64GX 6 /* ATI Mach 64GX family */

#define FB_ACCEL_DEC_TGA 7 /* DEC 21030 TGA */

#define FB_ACCEL_ATI_MACH64CT 8 /* ATI Mach 64CT family */

#define FB_ACCEL_ATI_MACH64VT 9 /* ATI Mach 64CT family VT class */

#define FB_ACCEL_ATI_MACH64GT 10 /* ATI Mach 64CT family GT class */

#define FB_ACCEL_SUN_CREATOR 11 /* Sun Creator/Creator3D */

#define FB_ACCEL_SUN_CGSIX 12 /* Sun cg6 */

#define FB_ACCEL_SUN_LEO 13 /* Sun leo/zx */

#define FB_ACCEL_IMS_TWINTURBO 14 /* IMS Twin Turbo */

#define FB_ACCEL_3DLABS_PERMEDIA2 15 /* 3Dlabs Permedia 2 */

#define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W (Millenium) */

#define FB_ACCEL_MATROX_MGA1064SG 17 /* Matrox MGA1064SG (Mystique) */ #define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */

#define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (Millenium II) */ #define FB_ACCEL_MATROX_MGAG100 20 /* Matrox G100 (Productiva G100) */

#define FB_ACCEL_MATROX_MGAG200 21 /* Matrox G200 (Myst, Mill, ...) */

#define FB_ACCEL_SUN_CG14 22 /* Sun cgfourteen */

#define FB_ACCEL_SUN_BWTWO 23 /* Sun bwtwo */

#define FB_ACCEL_SUN_CGTHREE 24 /* Sun cgthree */

#define FB_ACCEL_SUN_TCX 25 /* Sun tcx */

#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */

#define FB_ACCEL_NV3 27 /* nVidia RIVA 128 */

#define FB_ACCEL_NV4 28 /* nVidia RIVA TNT */

#define FB_ACCEL_NV5 29 /* nVidia RIVA TNT2 */

#define FB_ACCEL_CT_6555x 30 /* C&T 6555x */

#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */

#define FB_ACCEL_ATI_RAGE128 32 /* ATI Rage128 family */

#define FB_ACCEL_IGS_CYBER2000 33 /* CyberPro 2000 */

#define FB_ACCEL_IGS_CYBER2010 34 /* CyberPro 2010 */

#define FB_ACCEL_IGS_CYBER5000 35 /* CyberPro 5000 */

#define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */

#define FB_ACCEL_3DLABS_PERMEDIA3 37 /* 3Dlabs Permedia 3 */

/*上面的宏定义不用关心*/

/*不可修改的屏幕信息,用户空间可见*/

struct fb_fix_screeninfo {

char id[16]; /* identification string eg "TT Builtin" */

unsigned long smem_start; /* Start of frame buffer mem 显存的起始地址*/ /* (physical address) */

__u32 smem_len; /* Length of frame buffer mem 显存的大小 */

__u32 type; /* see FB_TYPE_* */

__u32 type_aux; /* Interleave for interleaved Planes */

__u32 visual; /* see FB_VISUAL_* */

__u16 xpanstep; /* zero if no hardware panning */

__u16 ypanstep; /* zero if no hardware panning */

__u16 ywrapstep; /* zero if no hardware ywrap */

__u32 line_length; /* length of a line in bytes 每行的字节数 */

unsigned long mmio_start; /* Start of Memory Mapped I/O */

/* (physical address) */

__u32 mmio_len; /* Length of Memory Mapped I/O */

__u32 accel; /* Type of acceleration available */

__u16 reserved[3]; /* Reserved for future compatibility */

};

/* Interpretation of offset for color fields: All offsets are from the right,

* inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you

* can use the offset as right argument to <<). A pixel afterwards is a bit

* stream and is written to video memory as that unmodified. This implies

* big-endian byte order if bits_per_pixel is greater than 8.*/

/*像素所占字节内,各个颜色的位分配比如RGB=888,565,555等等,*/

struct fb_bitfield {

__u32 offset; /* beginning of bitfield */

__u32 length; /* length of bitfield */

__u32 msb_right; /* != 0 : Most significant bit is */

/* right */

};

/*下面的宏也不常用*/

#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */

#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/

#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */

#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */

#define FB_ACTIVATE_MASK 15

/* values */

#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */

#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */

#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */

#define FB_ACCELF_TEXT 1 /* text mode acceleration */

#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */

#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */

#define FB_SYNC_EXT 4 /* external sync */

#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */

#define FB_SYNC_BROADCAST 16 /* broadcast video timings

Framebuffer驱动程序模型

下图会向你展示目前的framebuffer设备驱动的结构,最常用的是非标准驱动。很明显他所处的层次最高,程序编写是最容易的。理解了这个图的,你已经很轻松的去完成一个fb驱动,比如给

sa1100,s2410,s2440系列的ARM的LCD控制器写驱动。

Color Map 剖析

在framebuffer驱动程序设计中,cmap这个东东太晕了。现在我要把他赤裸裸的剖析给大家:)1. struct fb_cmap

/*颜色映射表*/

struct fb_cmap {

__u32 start; /* First entry */

__u32 len; /* Number of entries */

__u16 *red; /* 红色 */

__u16 *green; /*绿色*/

__u16 *blue; /*蓝色*/

__u16 *transp; /* 透明度,允许 NULL */

};

该结构在fb.h文件中定义,在struct fb_ops结构中有两个成员函数与其相关:

/*获取颜色表*/

int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);

/*设定颜色表*/

int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);

在struct fb_info结构中有变量:

struct fb_cmap cmap; /* Current cmap */

在fpgen基础操作下提供:

extern int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);

extern int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);

在文件/* drivers/video/fbcmap.c */中提供更多的cmap应用

extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);

extern void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);

extern int fb_get_cmap(struct fb_cmap *cmap, int kspc,

int (*getcolreg)(u_int, u_int *, u_int *, u_int *,u_int *, struct fb_info *),

struct fb_info *fb_info);

extern int fb_set_cmap(struct fb_cmap *cmap, int kspc,

int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,struct fb_info *),

struct fb_info *fb_info);

extern struct fb_cmap *fb_default_cmap(int len);

extern void fb_invert_cmaps(void);

2.通过文件解析

在anakinfb.c文件中,cmap如图

在stifb.c

本文介绍的设备是位于/video目录下面的anakinfb.c驱动程序。虽然我不清楚那个设备的特性,但是从对程序的分析中我们仍然知道如何编写一个frame buffer设备驱动。

本文是个标准的fb驱动。共221行,包含函数如下:

1.static int anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int

*transp, struct fb_info *info) 31行

2.static int anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,u_int

transp, struct fb_info *info) 45行

3.static int anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)

57行

4.static int anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)

75行

5.static int anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)

111行

6.static int anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info

*info) 117行

7.static int anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info

*info) 130行

8.static int anakinfb_switch_con(int con, struct fb_info *info) 147行

9.static int anakinfb_updatevar(int con, struct fb_info *info) 155行

10.static void anakinfb_blank(int blank, struct fb_info *info) 161行

11. int __init anakinfb_init(void) 178行

函数1,2是寄存器操作用。函数3,4,5,6,7是fb_ops函数。函数8用于切换控制台。函数9用于更新变量。函数10用于闪烁屏幕。函数11用于初始化设备。

很奇怪,对fb设备的读写函数怎么没有!值得说明的是open,release,read,write,ioctl,mmap等函数的实现是由fbmem.c文件实现了。也就是说所有的fb设备在给定了fb_info后,所有的操作都是一样的。在明确的fb_info前提下,fbmem.c中的函数可以工作的很好。这样大家应该感到非常轻松了吧,只要完成上述的几个设备相关的函数,frame buffer设备的驱动就写完了:)

系统的结构如图:

Stifb驱动模型

linux/drivers/video/stifb.c - Generic frame buffer driver for HP * workstations with STI (standard text interface) video firmware.

这个驱动程序和前面的anakin设备完全不同,因为他不是采用标准的格式,而是根据based on skeletonfb, which wasCreated 28 Dec 1997 by Geert Uytterhoeven也就是skeletonfb.c提供的框架完成的。

共230行,包含函数如下:

1.static int sti_encode_fix(struct fb_fix_screeninfo *fix, const void *par, struct

fb_info_gen *info) 60行

2.static int sti_decode_var(const struct fb_var_screeninfo *var,void *par, struct

fb_info_gen *info) 71行

3.static int sti_encode_var(struct fb_var_screeninfo *var, const void *par, struct

fb_info_gen *info) 78行

4.static void sti_get_par(void *par, struct fb_info_gen *info) 94行

5.static void sti_set_par(const void *par, struct fb_info_gen *info) 99行

6.static int sti_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,

unsigned *transp, struct fb_info *info) 104行

7.static int sti_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,

unsigned transp, struct fb_info *info) 111行

8.static void sti_set_disp(const void *par, struct display *disp, struct fb_info_gen *info)

118行

9.static void sti_detect(void) 127行

10.static int sti_blank(int blank_mode, const struct fb_info *info) 132行

11.int __init stifb_init(void) 161行

12.void stifb_cleanup(struct fb_info *info) 201行

13.int __init stifb_setup(char *options) 208行

其中1到10是必须的,参考下面的图。11是初始化代码。12.13没有完成具体功能。

再给出fb_fix_screeninfo系统调用结构图:

Frame buffer与console

Framebuffer作为显卡在内核中的注册设备,为了满足应用需要,通常还要为console操作提供专用操作函数。Console是系统提供的一种特殊的文本输出终端,如图所示。常用的console已经不再是从前的单色显示,而是16色或者更多颜色显示。根据文本的代表的不同属性,显示不同的颜色。

把对console的支持内嵌到fb的驱动中,或许有其自己的道理,我没有看出来。不过既然要提供这种支持,我们的驱动程序就要添枝加叶了。

在准fb设备设备驱动中是没有对console支持的。只有在非标准的fb驱动,也就是基于skeletonfb.c

架构的程序,需要提供这部分代码。下面从各个方面介绍framebuffer对console的支持。

1. 各个文件中的支持

fb.h文件中

struct fb_info结构中:

struct display *disp; /* initial display variable */

struct vc_data *display_fg; /* Console visible on this display */

int (*changevar)(int); /* tell console var has changed */

int (*switch_con)(int, struct fb_info*); /* tell fb to switch consoles */

fbgen.c文件中:

void fbgen_set_disp(int con, struct fb_info_gen *info)

int fbgen_update_var(int con, struct fb_info *info)

int fbgen_switch(int con, struct fb_info *info)

新增加文件fbcon.c

struct display fb_display[MAX_NR_CONSOLES];

char con2fb_map[MAX_NR_CONSOLES];

…..

新增加文件fbcon.h:

struct display_switch

struct display

新增文件console_struct.h:

struct vc_data

……

2. console中的颜色设定

该部分内容准备略掉,可以自行参考fbcon-cfb*.c文件。

3. console和fb的高层理解

当我们在fb中引入console后,就相当于把一张白纸变成了一个日记本。本来对于fb来说只有颜色和位置的关系,引入console后,首先就是console的描述。

每个console相当于日记本的一页,不同的console可以切换。Console因为是要显示文本,又和字体联系到一起。Console的管理是十分复杂的,远远超过了framebuffer本身。在RH9中,我们可以自己体验一下console和fb的协调问题。

使用Init3多用户模式登陆,这里是没有X server支持的。所有的输入输出都是基于console的。Framebuffer就相当于你的显示器。通过ALT+CTRL+F*,我们可以切换到不同的console,而每个console 的设置都可以很独立的完成。每隔console会在自己的数据区记录历史命令,在不同的console可以登陆不同的用户到系统。但是,因为只有一个屏幕,所以当前可视的console只有一个。Frame buffer驱动程序要能够根据ALT+CTRL+F*切换命令去完成console的切换显示。

这样大家应该明白frame buffer和console的关系了吧。后续我们会具体讲述fb对console的支持。但是对console本身不会设计太多,具体参考tty或console的设计。当完成了fb对console的支持,frame buffer device driver设计就完了:)

Fb console中的字体

/driver/video目录下:

font_6x11.c,font_8x8.c,font_8x16.c

font_acorn_8x8.c,font_pearl_8x8.c,

font_sun8x16.c,font_sun12x22.c

fonts.c

这些文件都是用来处理在fbcon中的字体显示问题。其中除最后一个文件fonts.c外,其他都是字模文件由cpi2fnt产生。

/include/video/目录下:

font.h

1.首先介绍font.h文件

font.h文件中,定义了字体的描述结构

struct fbcon_font_desc {

int idx; //字体的索引号

char *name;//字体的描述

int width, height;//字模的宽和高

void *data;//字模的起始指针

int pref; //额外信息,平台用

};

width的值不一定是8的整数倍,考虑到计算机存储的问题,即使width小于8的整数倍,存储时仍以字节为单位,不足的右补齐0。

Linux内核自带了7种字体,name依次为:

font_vga_8x8,

font_vga_8x16,

font_pearl_8x8,

font_vga_6x11,

font_sun_8x16,

font_sun_12x22,

font_acorn_8x8;

根据定义name长度不大于32字节。

2. Font.c文件

/* 根据字体名返回该字体的描述结构 */

struct fbcon_font_desc *fbcon_find_font(char *name);

/*根据屏幕大小,获取默认字体描述 */

struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres);

由此看来,linux中基于fbcon的字体比较单一,描述和使用也相对简单。主要是由于采用字模描述,只描述256个ascii字符,故存储空间不大,从2048到11264不等。

Fbcon中的颜色查找表

Fbcon-cfbx表示该console使用的是xbpp颜色描述。颜色数为2^x。

在此,我们仅以x=8,x=24举例,使用颜色分别是256色和真彩16M。

/driver/video/fbcon-cfb8.c

/driver/video/fbcon-cfb24.c

/include/video/fbcon-cfb8.h

/include/video/fbcon-cfb24.h

这4个文件实现的具体的操作,而fbcon的底层操作,参考前面的fbcon的介绍,不重复了:)

实现fbcon的颜色映射只需完成下面的功能,以fb8为例:

struct display_switch fbcon_cfb8;

void fbcon_cfb8_setup(struct display *p);

void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx, int height, int width); void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, int sx, int height, int width);

void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx);

void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, int count, int yy, int xx);

void fbcon_cfb8_revc(struct display *p, int xx, int yy);

void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p,int bottom_only);

fbcon_cfb8是系统的实现关键,具体解释参考fbcon介绍。

fbcon_cfb8_setup函数完成设定display结构中next_line和next_palne的值。

fbcon_cfb8_bmove函数完成当前坐标的移动。

fbcon_cfb8_clear函数通过调用rectfill函数清屏幕缓冲区。

fbcon_cfb8_putc函数向屏幕输出单字符,字体宽度必须小于等于16。

fbcon_cfb8_putcs函数向屏幕输出字符串。

fbcon_cfb8_revc函数从屏幕输入单个字符,并回显到fb上。

fbcon_cfb8_clear_margins函数和fbcon_cfb8_clear类似,调用rectfill清除区域。

其中,fb_writel函数和fb_readl函数实现输入输出的底层操作。这两个函数实际上实在fbcon_h中定义的宏操作,IOMEM操作而已。

关注一下“(nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx,”

这是所谓8bpp的具体实现,不同的位深就在写fb缓冲时体现了。让我们从后向前分析,

1.()^bgx,颜色和背景色异或,只有这样才能保证背景色改变时,文字一直显示。

2.~&eorx,eorx是前景色和背景色异或后的值,只有在前景色和背景色一致的时候,eorx才是0。

3. nibbletab_cfb8[~],根据字体的~值,调用查找表,取颜色值

4.~从字体文件中去读字模的值。

还有点疑问,就是这两句的作用,attr_fgcol在fbcon_h中定义:

fgx=attr_fgcol(p,c);

bgx=attr_bgcol(p,c);

从前面的看,c应该是个字符的ascii码,ascii与颜色有什么关系呢?研究中….

驱动程序原理

知识体系结构 应用程序:是一段可以执行的代码,由操作系统管理。 编译原理,链接器,装载器:是对操作系统依赖的一个工具,将用户的代码变成可执行的机器码,编译器仅仅检查和翻译用户的语言逻辑,但并不装配成符合操作系统要求的可执行文件格式,如windows要求的EXE文件为PE格式(EXE文件并不仅仅是一个可执行的代码段,而且包含了很多其他的内容,如数据段)。 操作系统接口API:是一个可以被用户程序调用的系统功能接口,可以说,我们编写程序,除了计算和流程控制这些只需要用到CPU指令和CPU寄存器的代码外,其余要访问其他(硬件)资源(包括内存,外设)的代码,均是通过调用OS的API来操作除CPU外的资源的,如向屏幕写一个字母,对于程序来说简单得很,print(“A”); 但是其编译后执行的过程是复杂的,编译后的程序会调用操作系统的API,将当前应用程序的状态(上下文,如光标的位置)以及字母传递给显示器的驱动程序去显示。 操作系统管理与调度:操作系统要实现一般通用的资源管理,也要实现资源使用的协调,包含CPU,内存,磁盘,外设。 首先要确定为什么需要操作系统,操作系统设计的目标是什么? 1.我们总是不能等做完一件事情才去做另外一件,因为有些事情做的过程需要等待,有时候也需要暂停一下当前的任务,先去处理更急的事情,等我回来 时又需要以前的任务保持当时的状态,所以需要计算机也要具备这样的能 力,那怎么实现呢? 2.CPU和内存是计算机的最需要的资源,就如我们的人脑一样,一般很难在同一时间做两件事情。需要处理好一件事情再处理另一件,如果处理得越快就 越好,但是不能前一件事情要等待,你就休息了,后面一件也做不了,计算 机的办法就是你不用CPU了,那好你等待下,我先处理下一个事情。 3.我们写程序,不可能对每个应用,我们重新去写那些驱动程序,也不可能按照自己的想法去处理这些通常的资源管理。否则很多人各自写的应用软件就 没法在一个电脑上运行。 操作系统目标: 1.实现代码重用,对于硬件的访问,对于CPU和内存的充分利用,使不同的应用不需要重新去写这些代码。 2.实现各个任务(不同应用程序)的协调使用,使用户可以实现暂停、重新启用某个任务。 3.实现数据的安全管理,实现良好的人机界面的管理。 4.实现一个开放的体系结构,提供系统调用使用户可以快速编写自己的应用,并提供编译器、链接器、装载器来让用户编写的程序变成可以与操作系统接口的 可执行软件。 操作系统的功能分层: CPU管理是操作系统的核心:操作系统与用户程序其实可以看成是一个程序,与以前的单任务系统和单片机程序没有本质的区别。 我们来看整个PC机运行过程: 1.系统上电。 2.主板上CPU的CS值设置为0Fx000,IP值设置为0xFFF0,这样CS:IP就指向0xFFFF0位置,这个是程序的开始地址,而硬件上在总线上挂接在0xFFFF0地址 的是主板的BIOS芯片,BIOS开始运行,BIOS是Basic Input Output System简写, 意思即基本的输入输出系统,如果学过单片机就很好理解,其实就是一个程序,由主

什么是驱动程序资料

什么是驱动程序? 驱动程序扮演沟通的角色,把硬件的功能告诉电脑系统,并且也将系统的指令传达给硬件,让它开始工作。 年轻人最大的动力,或者最大的优势就在于,你一旦想做什么你就马上去做。说这是天真也好,甚至对一些事情的无知也好,有这种勇气和决心就应该去做。” 什么是BSP? BSP是板级支持包,是介于主板硬件和操作系统之间的一层,应该说是属于操作系统的一部分,主要目的是为了支持操作系统,使之能够更好的运行于硬件主板。BSP是相对于操作系统而言的,不同的操作系统对应于不同定义形式的BSP,例如VxWorks的BSP和Linu x的BSP相对于某一CPU来说尽管实现的功能一样,可是写法和接口定义是完全不同的,所以写BSP一定要按照该系统BSP的定义形式来写(BSP的编程过程大多数是在某一个成型的BSP模板上进行修改),这样才能与上层OS保持正确的接口,良好的支持上层OS。 例如:在VxWorks中的网卡驱动,首先在config.h中包含该网卡,然后将网卡含网卡信息的参数放入数组END_TBL_ENTRY endDevTbl [ ] 中,系统通过函数muxDevLoad ( )调用这个数组来安装网卡驱动。而在Linux中的网卡驱动,是在space.c中声明该网络设备,再把网卡驱动的一些函数加到dev结构中,由函数ether_setup()来完成网卡驱动的安装。 纯粹的BSP所包含的内容一般说来是和系统有关的驱动和程序,如网络驱动和系统中网络协议有关,串口驱动和系统下载调试有关等等。离开这些驱动系统就不能正常工作。 用户也可以添加自己的程序到BSP中,但严格来说不应该算BSP.一般来说这种做法不建议。因为一旦操作系统能良好运行于最终的主板硬件后,BSP也就固定了,不需要做任何改动。而用户自己在BSP中的程序还会不断的升级更新,这样势必对BSP有不好的影响,对系统造成影响,同时由于BSP调试编译环境较差,也不利于程序的编译调试。 如何编写Linux设备驱动程序 Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它和dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kerne l中的函数,有些常用的操作要自己来编写,而且调试也不方便。 一、Linux device driver 的概念

usb驱动程序教程

编写Windows https://www.doczj.com/doc/779772029.html,的usb驱动程序教程 Windows https://www.doczj.com/doc/779772029.html, 是微软推出的功能强大的嵌入式操作系统,国内采用此操作系统的厂商已经很多了,本文就以windows https://www.doczj.com/doc/779772029.html,为例,简单介绍一下如何开发windows https://www.doczj.com/doc/779772029.html, 下的USB驱动程序。 Windows https://www.doczj.com/doc/779772029.html, 的USB系统软件分为两层: USB Client设备驱动程序和底层的Windows CE实现的函数层。USB设备驱动程序主要负责利用系统提供的底层接口配置设备,和设备进行通讯。底层的函数提本身又由两部分组成,通用串行总线驱动程序(USBD)模块和较低的主控制器驱动程序(HCD)模块。HCD负责最最底层的处理,USBD模块实现较高的USBD函数接口。USB设备驱动主要利用 USBD接口函数和他们的外围设备打交道。 USB设备驱动程序主要和USBD打交道,所以我们必须详细的了解USBD提供的函数。 主要的传输函数有: abourttransfer issuecontroltransfer closetransfer issuein te rruptransfer getisochresult issueisochtransfer gettransferstatus istransfercomplete issuebulktransfer issuevendortransfer 主要的用于打开和关闭usbd和usb设备之间的通信通道的函数有: abortpipetransfers closepipe isdefaultpipehalted ispipehalted openpipe resetdefaultpipe resetpipe 相应的打包函数接口有: getframelength getframenumber releaseframelengthcontrol setframelength takeframelengthcontrol 取得设置设备配置函数: clearfeature setdescriptor getdescriptor setfeature

程序、驱动程序及硬件简述

程序 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 请概括的说一说什么是程序…… =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 程序都分为几大类…… ============================================== 编写程序时都要注意哪些事项? 答:1.①程序是计算机的一组指令,经过编译和执行才能最终完成程序设计的动作。程序设计的最终结果是软件。 ②为了让电脑执行某项具体任务而提供给它的详细指令集合就是程序(program)。 2.字处理程序(就是我们常说的计算机语言,如C语言,BASIC等)、电脑工资表系统、电脑游戏和电子数据表都是电脑程序 3.一般来讲,程序设计风格是指编写程序时所表现出的特点,习惯和逻辑思路.因此程序设计的风格总体而言应该强调程序简单和清晰,并且是可以理解的. "清晰第一,效率第二"已成为当今主导的程序设计风格. 程序设计风格主要体现在以下几个方面: ⒈源程序文挡化 源程序文挡化应考虑如下几点: ⑴符号名的命名 符号名的命名应具有一定的实际含义,以便于对程序功能的理解. ⑵程序注释 正确的注释能够帮助读者理解程序.注释一般分为序言性注释和功能性注释.序言性注释通常位于每个程序的开头部分,它给出了程序的整体说明,主要描述内容包括:程序标题,程序功能说明,主要算法,接口说明,程序位置,开发简历,程序设计者,复审者,复审日期,修改日期等.功能性注释的位置一般嵌在源程序体中,主要描述其后的语句或程序做什么. ⑶视觉组织 为使程序的结构一目了然,可以在程序中利用空格,空行,缩进等技巧使程序的结构层次清晰 驱动程序 1.驱动程序属于什么程序?它的作用是什么? 驱动程序属于系统辅助程序一种 它的作用就是让操作系统能够全面的,详细的了解并控制的硬件 主要的驱动程序有显卡,网卡,声卡,各种外接设备比如打印机,扫描仪等等 CPU、内存这些都不需要驱动程序

字符设备驱动程序课程设计报告

中南大学 字符设备驱动程序 课程设计报告 姓名:王学彬 专业班级:信安1002班 学号:0909103108 课程:操作系统安全课程设计 指导老师:张士庚 一、课程设计目的 1.了解Linux字符设备驱动程序的结构; 2.掌握Linux字符设备驱动程序常用结构体和操作函数的使用方法; 3.初步掌握Linux字符设备驱动程序的编写方法及过程; 4.掌握Linux字符设备驱动程序的加载方法及测试方法。 二、课程设计内容 5.设计Windows XP或者Linux操作系统下的设备驱动程序; 6.掌握虚拟字符设备的设计方法和测试方法;

7.编写测试应用程序,测试对该设备的读写等操作。 三、需求分析 3.1驱动程序介绍 驱动程序负责将应用程序如读、写等操作正确无误的传递给相关的硬件,并使硬件能够做出正确反应的代码。驱动程序像一个黑盒子,它隐藏了硬件的工作细节,应用程序只需要通过一组标准化的接口实现对硬件的操作。 3.2 Linux设备驱动程序分类 Linux设备驱动程序在Linux的内核源代码中占有很大的比例,源代码的长度日益增加,主要是驱动程序的增加。虽然Linux内核的不断升级,但驱动程序的结构还是相对稳定。 Linux系统的设备分为字符设备(char device),块设备(block device)和网络设备(network device)三种。字符设备是指在存取时没有缓存的设备,而块设备的读写都有缓存来支持,并且块设备必须能够随机存取(random access)。典型的字符设备包括鼠标,键盘,串行口等。块设备主要包括硬盘软盘设备,CD-ROM等。 网络设备在Linux里做专门的处理。Linux的网络系统主要是基于BSD unix的socket 机制。在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据传递。系统有支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持。 3.3驱动程序的结构 驱动程序的结构如图3.1所示,应用程序经过系统调用,进入核心层,内核要控制硬件需要通过驱动程序实现,驱动程序相当于内核与硬件之间的“系统调用”。

USB驱动程序编写

USB驱动程序编写 linux下usb驱动编写(内核2.4)——2.6与此接口有区别2006-09-15 14:57我们知道了在Linux 下如何去使用一些最常见的USB设备。但对于做系统设计的程序员来说,这是远远不够的,我们还需要具有驱动程序的阅读、修改和开发能力。在此下篇中,就是要通过简单的USB驱动的例子,随您一起进入USB驱动开发的世界。 USB骨架程序(usb-skeleton),是USB驱动程序的基础,通过对它源码的学习和理解,可以使我们迅速地了解USB驱动架构,迅速地开发我们自己的USB硬件的驱动。 USB驱动开发 在掌握了USB设备的配置后,对于程序员,我们就可以尝试进行一些简单的USB驱动的修改和开发了。这一段落,我们会讲解一个最基础USB框架的基础上,做两个小的USB驱动的例子。 USB骨架 在Linux kernel源码目录中driver/usb/usb-skeleton.c为我们提供了一个最基础的USB驱动程序。我们称为USB骨架。通过它我们仅需要修改极少的部分,就可以完成一个USB设备的驱动。我们的USB驱动开发也是从她开始的。 那些linux下不支持的USB设备几乎都是生产厂商特定的产品。如果生产厂商在他们的产品中使用自己定义的协议,他们就需要为此设备创建特定的驱动程序。当然我们知道,有些生产厂商公开他们的USB协议,并帮助Linux驱动程序的开发,然而有些生产厂商却根本不公开他们的USB协议。因为每一个不同的协议都会产生一个新的驱动程序,所以就有了这个通用的USB驱动骨架程序,它是以pci 骨架为模板的。 如果你准备写一个linux驱动程序,首先要熟悉USB协议规范。USB主页上有它的帮助。一些比较典型的驱动可以在上面发现,同时还介绍了USB urbs的概念,而这个是usb驱动程序中最基本的。 Linux USB 驱动程序需要做的第一件事情就是在Linux USB 子系统里注册,并提供一些相关信息,例如这个驱动程序支持那种设备,当被支持的设备从系统插入或拔出时,会有哪些动作。所有这些信息都传送到USB 子系统中,在usb骨架驱动程序中是这样来表示的: static struct usb_driver skel_driver = { name: skeleton, probe: skel_probe, disconnect: skel_disconnect, fops: &skel_fops, minor: USB_SKEL_MINOR_BASE, id_table: skel_table,

linux驱动程序的编写

linux驱动程序的编写 一、实验目的 1.掌握linux驱动程序的编写方法 2.掌握驱动程序动态模块的调试方法 3.掌握驱动程序填加到内核的方法 二、实验内容 1. 学习linux驱动程序的编写流程 2. 学习驱动程序动态模块的调试方法 3. 学习驱动程序填加到内核的流程 三、实验设备 PentiumII以上的PC机,LINUX操作系统,EL-ARM860实验箱 四、linux的驱动程序的编写 嵌入式应用对成本和实时性比较敏感,而对linux的应用主要体现在对硬件的驱动程序的编写和上层应用程序的开发上。 嵌入式linux驱动程序的基本结构和标准Linux的结构基本一致,也支持模块化模式,所以,大部分驱动程序编成模块化形式,而且,要求可以在不同的体系结构上安装。linux是可以支持模块化模式的,但由于嵌入式应用是针对具体的应用,所以,一般不采用该模式,而是把驱动程序直接编译进内核之中。但是这种模式是调试驱动模块的极佳方法。 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。同时,设备驱动程序是内核的一部分,它完成以下的功能:对设备初始化和释放;把数据从内核传送到硬件和从硬件读取数据;读取应用程序传送给设备文件的数据和回送应用程序请求的数据;检测和处理设备出现的错误。在linux操作系统下有字符设备和块设备,网络设备三类主要的设备文件类型。 字符设备和块设备的主要区别是:在对字符设备发出读写请求时,实际的硬件I/O一般就紧接着发生了;块设备利用一块系统内存作为缓冲区,当用户进程对设备请求满足用户要求时,就返回请求的数据。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。 1 字符设备驱动结构 Linux字符设备驱动的关键数据结构是cdev和file_operations结构体。

USB设备驱动程序设计

USB设备驱动程序设计 引言 USB 总线是1995 年微软、IBM 等公司推出的一种新型通信标准总线, 特点是速度快、价格低、独立供电、支持热插拔等,其版本从早期的1.0、1.1 已经发展到目前的2.0 版本,2.0 版本的最高数据传输速度达到480Mbit/s,能 满足包括视频在内的多种高速外部设备的数据传输要求,由于其众多的优点,USB 总线越来越多的被应用到计算机与外设的接口中,芯片厂家也提供了多种USB 接口芯片供设计者使用,为了开发出功能强大的USB 设备,设计者往往 需要自己开发USB 设备驱动程序,驱动程序开发一直是Windows 开发中较难 的一个方面,但是通过使用专门的驱动程序开发包能减小开发的难度,提高工 作效率,本文使用Compuware Numega 公司的DriverStudio3.2 开发包,开发了基于NXP 公司USB2.0 控制芯片ISP1581 的USB 设备驱动程序。 USB 设备驱动程序的模型 USB 设备驱动程序是一种典型的WDM(Windows Driver Model)驱动程序,其程序模型如图1 所示。用户应用程序工作在Windows 操作系统的用户模式层,它不能直接访问USB 设备,当需要访问时,通过调用操作系统的 API(Application programming interface)函数生成I/O 请求信息包(IRP),IRP 被传输到工作于内核模式层的设备驱动程序,并通过驱动程序完成与UBS 外设通 信。设备驱动程序包括两层:函数驱动程序层和总线驱动程序层,函数驱动程 序一方面通过IRP 及API 函数与应用程序通信,另一方面调用相应的总线驱动 程序,总线驱动程序完成和外设硬件通信。USB 总线驱动程序已经由操作系统 提供,驱动程序开发的重点是函数驱动程序。 USB 设备驱动程序的设计

电脑显卡真4K硬解码软解码的测试

电脑显卡真4K硬解码软解码的测试 笔记本4K分辨率下播放4K视频,这次才真的妥了! 看着这个标题,现行很多人会纳闷——4K视频解码/播放不是没问题了吗?电脑早就能流畅播放4K视频了啊,很多手机也都可以啊! 真的吗?请问你的屏幕分辨率是多少啊?请你拿台笔记本,然后外接4K屏再播放4K视频看看,流畅吗? 另外,你看着流畅的4K视频,画质真的没有猫腻吗? 向下看吧,我们以无数的测试和亲身经历,为你独家解读笔记本“真4K解码”的各种机关、秘籍。特别提示:本文描述的各种情况和问题,仅针对笔记本平台,且仅针对4K分辨率输出情况下。台式机用户、4K智能电视用户、4K电视盒用户,以及低分辨率屏幕使用者毋对号入座。脑补:关于4K视频播放的若干真相 ●4K分辨率下4K视频播放,台式机/4K智能电视/4K盒子较轻松,笔记本绝大部分都有问题 从震撼的效果和精细程度来看,4K视频自然是在4K分辨率的显示器/电视上看最爽。我们先明确一点:在4K分辨率的屏幕上,4K视频解码,在台式机尤其是这两年推出的中高端台式机上并不是太大问题。另外,4K智能电视自带的解码功能和4K盒子也能在4K分辨率下流畅应对大部分4K视频。 但无论是智能电视还是盒子,都是一笔额外的开支,而且也有各种软硬件上的问题。 笔记本电脑如今可说是人手一台,且如今的笔记本性能强大,应该可以轻松搞定4K分辨率下的4K视频吧!但,就在20天前,这都还是“奢望”——绝大部分笔记本输出4K分辨率后,播放4K视频并不流畅,抑或是有其他问题。●1366×768/1920×1080/2560×1440分辨率下,笔记本放4K视频不费劲,但4K分辨率下基本搞不定 笔者做这个选题时很多笔记本用户表示不理解,说自己的笔记本可以流畅播放4K视频。还是那句话,请你外接一台4K分辨率的电视/显示器再看看,还能流畅吗?答案是:99.9%的情况下不会流畅,而且会非常卡顿! 拿着自己手机叫嚣4K解码早不是问题的朋友,我也只问你这个问题:你的

最新开发usb驱动程序的方法连载一

最新开发usb驱动程序的方法连载一 开发usb驱动程序的方法(连载二) NT还有更多其他的对象,例如中断对象、Controller对象、定时器对象等等,但在我们开发的驱动程序中并没有用到,因此在这里不做介绍。 I/O缓冲策略 很明显的,驱动程序和客户应用程序经常需要进行数据交换,但我们知道驱动程序和客户应用程序可能不在同一个地址空间,因此操作系统必须解决两者之间的数据交换。这就就设计到设备的I/O缓冲策略。 读写请求的I/O缓冲策略 前面说到通过设置Device对象的Flag可以选择控制处理读写请求的I/O缓冲策略。下面对这些缓冲策略分别做一介绍。 1、缓冲I/O(DO_BUFFERED_IO) 在读写请求的一开始,I/O管理器检查用户缓冲区的可访问性,然后分配与调用者的缓冲区一样大的非分页池,并把它的地址放在IRP的AssociatedIrp.SystemBuffer域中。驱动程序就利用这个域来进行实际数据的传输。 对于IRP_MJ_READ读请求,I/O管理器还把IRP的UserBuffer域设置成调用者缓冲区的用户空间地址。当请求完成时,I/O管理器利用这个地址将数据从驱动程序的系统空间拷贝回调用者的缓冲区。对于IRP_MJ_WRITE写请求,UserBuffer被设置为NULL,并把用户缓冲区的数据拷贝到系统缓冲区中。 2、直接I/O(DO_DIRECT_IO) I/O管理器首先检查用户缓冲区的可访问性,并在物理内存中锁定它。然后它为该缓冲区创建一个内存描述表(MDL),并把MDL的地址存放在IRP的MdlAddress域中。AssociatedIrp.SystemBuffer和 UserBuffer 都被设置为NULL。驱动程序可以调用函数 MmGetSystemAddressForMdl得到用户缓冲区的系统空间地址,从而进行数据操作。这个函数将调用者的缓冲区映射到非份页的地址空间。驱动程序完成I/O请求后,系统自动从系统空间解除缓冲区的映射。 3、这两种方法都不是 这种情况比较少用,因为这需要驱动程序自己来处理缓冲问题。 I/O管理器仅把调用者缓冲区的用户空间地址放到IRP的UserBuffer 域中。我们并不推荐这种方式。 IOCTL缓冲区的缓冲策略 IOCTL请求涉及来自调用者的输入缓冲区和返回到调用者的输出缓冲区。为了理解IOCTL请求,我们先来看看WIN32 API DeviceIoControl函数的原型。 BOOL DeviceIoControl ( HANDLE hDevice, // 设备句柄 DWORD dwIoControlCode, // IOCTL请求操作代码 LPVOID lpInBuffer, // 输入缓冲区地址 DWORD nInBufferSize, // 输入缓冲区大小 LPVOID lpOutBuffer, // 输出缓冲区地址 DWORD nOutBufferSize, // 输出缓冲区大小 LPDWORD lpBytesReturned, // 存放返回字节数的指针

NVIDIA显卡驱动怎么安装-

三一文库(https://www.doczj.com/doc/779772029.html,) 〔NVIDIA显卡驱动怎么安装?〕 *篇一:如何手动安装XP系统下nVidia显卡驱动程序转自DELL官方论坛--如何手动安装XP系统下nVidia 显卡驱动程序 尊敬的用户: 您好,首先感谢您选购DELL电脑,您所配的电脑,选配了目前最新的nVidiaG84/86芯片的显卡,它在XP系统下的驱动下载链接是: :https://www.doczj.com/doc/779772029.html,.dell/video/R158222.EXE =====================分割线 ====================== 注意:如果您下载下来不能自动安装或者打不开页面,则请参考下面的手动安装说明. 如何手动安装进行如下说明: 1.下载驱动程序. 您可以从以下地址下载显卡驱动程序: :us.download.nvidia/Wi...it_english_whql.exe 下载程序后,双击运行,选择“Iacceptthetermsinthelicenseagreement”,我同意后,

点Next。 系统会自动选择解压缩地址,不需要更改,继续点Next 即可。 4.解压缩过程中,等待即可。 5.继续等待安装。 在安装过程中,会提示程序安装错误,不用担心,先点确定,退出即可。 7.退回到桌面后,我们开始手动安装,右击我的电脑—属性—硬件—设备管理器,找到显示卡一项(也可能是在未知设备中的“视频控制器”),点右键,选择“更新驱动程序”。 8.安装向导会自动提示,选择“从列表或指定位置安装(高级)一项”。 9.然后选择“不要搜索,我要自己选择要安装的驱动程序”。 10.系统会自动列出部分显卡驱动,先不要选择,点击“从磁盘安装”。 11.打开后,选择“浏览”。 12.这时,找到我们刚才解压后的地址:本地磁盘C—NVIDIA—Win2KXP—158.22 13.找到驱动文件(后缀名为.inf)后,点“打开”。 14.继续点“确定”。

USB驱动程序的编写采用WDM驱动程序

U S B驱动程序的编写采用W D M驱动程序 Document serial number【UU89WT-UU98YT-UU8CB-UUUT-UUT108】

USB驱动程序的编写采用WDM 驱动程序。WDM 驱动程序是一些例程的集合,它们被动地存在,等待主机系 统软件(PnP 管理器、I/O 管理器、电源管理器等)来调用或激活它们。具体驱动程序不同,其所包含 的例程也不同。一个WDM 驱动程序的基本组成包括以下5个例程:(1)驱动程序入口例程:处理驱动程序的初始化。 (2)即插即用例程:处理PnP 设备的添加、删除和停止。 (3)分发例程:处理用户应用程序发出的各种 I/O 请求。 (4)电源管理例程:处理电源管理请求。 (5)卸载例程:处理驱动程序的卸载。 包含文件: , , , , , makefile,sources) 在文件中,包含了上述五个例程: 中定义了各种数据结构还有各种IOCTL控制码,用于不同数据的读写。

中实现了各种驱动例程。包含了上述五个所说例程外还包含了其他例程,课程从下面的驱动 程序入口例程得出一些信息。 驱动程序入口例程: NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject = NULL; DriverObject->MajorFunction[IRP_MJ_CREATE] = Ezusb_Create; DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ezusb_Close; ources. If you want to add a new source # file to this

编译hello设备驱动程序详细过程

编译hello world设备驱动程序详细过程 1、安装与你的开发板相同的内核版本的虚拟机,我的板子内核是2.6.8.1,虚拟机是2.6.9, 一般是虚拟机的内核只能比板子内核新,不能旧 #uanme –a [1](在任何目录下,输入此命令,查看虚拟机的内核版本,我的内核版本是2.6.9) 2、在虚拟机上设置共享目录,我的共享目录在linux下的/mnt/hgfs/share [2]share是自己命名的,我的物理机上,即Windows下的目录是G:/share, 3、在Windows下,把开发板的的交叉开发工具链[3],内核源码包[4],复制到物理机的共享目录下[5] 即Windows下的目录是G:/share, 4、#cp /mnt/hgfs/share/cross-3.3.2.tar.bz2 /usr/local/arm [6] 在Linux下,把交叉工具链,复制到/usr/local/arm目录下 5、#cd /usr/local/arm 6、#tar jxvf cross-3.3.2.tar.bz2 [7] 并在当前目录/usr/local/arm下解压它cross-2.95.3.tar.bz2和gec2410-linux-2.6.8.tar.bz2也是用同样的命令去解压 7、#export PATH=/usr/local/arm/3.3.2/bin:$PATH [8] 安装交叉工具链,在需要使用交叉编译时,只要在终端输入如下命令 #export PATH=/usr/local/arm/版本/bin:$PATH 即可,在需要更改不同版本的工具链时,重新启动一个终端,然后再一次输入上面的命令即可,使用哪个版本的交叉工具链,视你要编译的内核版本决定,编译2.4版本的内核,则用2.95.3版本的交叉工具链,而2.6版本内核的,则要用3.3.2版本的交叉工具链。 8、#cp gec2410-linux-2.6.8.tar.bz2 /root [9]把内核拷贝到/root目录下, 9、#cd /root 10、#tar gec2410-linux-2.6.8.tar.bz2 [10] 在/root解压开发板的内核源码压缩包gec2410-linux-2.6.8.tar.bz2,得到gec2410-linux-2.6.8.1文件夹 11、#cd /root/ gec2410-linux-2.6.8.1 12、#cp gec2410.cfg .config [11] gec2410.cfg文件是广嵌开发板提供的默认内核配置文件,在这里首先把内核配置成默认配置,然后在此基础上用make menuconfig进一步配置,但在这里,不进行进一步的配置,对于内核配置,还需要看更多的知识,在这里先存疑。 13、#make [12]在内核源代码的根目录gec2410-linux-2.6.8.1下用make命令编译内核,注意,先安装交叉工具链,再编译内核,因为这里编译的hello.ko驱动模块最终是下载到开发板上运行的,而不是在虚拟机的Linux系统运行的,如果是为了在虚拟机的Linux系统运行的,则不用安装交叉编译工具链arm-linux-gcc,而直接用gcc,用命令#arm-linux-gcc –v 可以查看当前已经安装的交叉编译工具链的版本。这里编译内核不是为了得到内核的映象文件zImage(虽然会得到内核的映象文件zImage),而是为了得到编译hello.o模块需要相关联,相依赖(depends on)的模块。 14、#cd /root 12、#mkdir hello [13]在/root目录下建立hello文件夹, 13、#cd hel 14 、#vi hello.c [12]编辑hello.c文件,内容是《Linux设备驱动程序》第三版22页的hello world程序。 15、#vi Makefile [13]在hello文件夹下编辑Makefile文件, 16、obj-m := module.o [14] 这是Makefile的内容,为obj-m := module.omodule.o视你编辑的.c文件而定,这里则要写成hello.o,写完后,保存退出。 17、cd /root/hello

开发usb驱动程序的方法(连载一)

开发usb驱动程序的方法(连载一) 开始驱动程序设计 下面的文字是从Microsoft的DDK帮助中节选出来的,它让我们明白在开始设计驱动程序应该注意些什么问题,这些都是具有普遍意义的开发准则。应该支持哪些I/O请求在开始写任何代码之前,应该首先确定我们的驱动程序应该处理哪些IRP例程。 如果你在设计一个设备驱动程序,你应该支持和其他相同类型设备的NT驱动程序相同的IRP_MJ_XXX 和IOCTL请求代码。 如果你是在设计一个中间层NT驱动程序,应该首先确认你下层驱动程序所管理的设备,因为一个高层的驱动程序必须具有低层驱动程序绝大多数IRP_MJ_XXX例程入口。高层驱动程序在接到I/O 请求时,在确定自身IRP当前堆栈单元参数有效的前提下,设置好IRP中下一个低层驱动程序的堆栈单元,然后再调用IoCallDriver 将请求传递给下层驱动程序处理。 一旦决定好了你的驱动程序应该处理哪些IRP_MJ_XXX,就可以开始确定驱动程序应该有多少个Dispatch例程。当然也可以考虑把某些 RP_MJ_XXX处理的例程合并为同一例程处理。例如在ChangerDisk 和 VDisk里,对IRP_MJ_CREATE和IRP_MJ_CLOSE处理的例程就是同一函数。对IRP_MJ_READ和IRP_MJ_WRITE处理的例程也是同一个函数。 应该有多少个Device对象? 一个驱动程序必须为它所管理的每个可能成为I/O请求的目标的物理和逻辑设备创建一个命名Device对象。一些低层的驱动程序还可能要创建一些不确定数目的Device对象。例如一个硬盘驱动程序必须为每一个物理硬盘创建一个Device对象,同时还必须为每个物理磁盘上的每个逻辑分区创建一个Device对象。一个高层驱动驱动程序必须为它所代表的虚拟设备创建一个Device 对象,这样更高层的驱动程序才能连接它们的Device对象到这个驱动程序的Device对象。另外,一个高层驱动程序通常为它低层驱动程序所创建的Device对象创建一系列的虚拟或逻辑Device对象。 尽管你可以分阶段来设计你的驱动程序,因此一个处在开发阶段的驱动程序不必一开始就创建出所有它将要处理的所有Device对象。但从一开始就确定好你最终要创建的所有Device对象将有助于设计者所要解决的任何同步问题。另外,确定所要创建的Device对象还有助于你定义Device对象的Device Extension 的内容和数据结构。 开始驱动程序开发 驱动程序的开发是一个从粗到细逐步求精的过程。NT DDK的src\ 目录下有一个庞大的样板代码,几乎覆盖了所有类型的设备驱动程序、高层驱动程序和过滤器驱动程序。在开始开发你的驱动程序之前,你应该在这个样板库下面寻找是否有和你所要开发的类似类型的例程。例如我们所开发的驱动程序,虽然DDK 对USB描述得不是很详细,我们还是可以在src\storage\class目录发现很多和USB设备有关的驱动程序。下面我们来看开发驱动程序的基本步骤。 最简的驱动程序框架 1、写一个DriverEntry例程,在里面调用IoCreateDevice创建一个Device对象。 2、写一个处理IRP_MJ_CREA TE请求的Dispatch例程的基本框架 (参见DDK Kernel-Mode Drivers 4.4.3描述的一个DispatchCreate 例程所要完成的最基本工作。当然写了DispatchCreate例程后,要在DriverEntry 例程为IRP_MJ_CREA TE初始化例程入口)。如果驱动程序创建了多于一个Device对象,则必须为IRP_MJ_CLOSE 请求写一个例程,该例程通常情况下可以和DispatchCreate共用一个例程,参见参见DDK Kernel-Mode Drivers 4.4.3。 3、编译连接你的驱动程序。

显卡测试软件GPU-Z使用详解(新)

GPU-Z是一款极度简易的显卡识别工具(继承了CPU-Z的优良传统),只要双击直接运行,显卡的的主要参数就可尽收眼底。这点比起Everest和RivaTuner 来说,确实方便了不知多少倍。 下面我们就已目前笔记本市场主流的nVIDIA GF8400m GS为例,来具体介绍一下GPU-Z的参数含义。 Dell 1520搭载的GeForce8600M GT 独立显卡 ①.显卡名称部分: 名称/Name:此处显示的是显卡的名称,也就是这款笔记本所采用的显卡型号。 (经过笔者的测试,发现目前最新的0.1.0版本的GPU-Z对显卡名称的识别,并非基于显示核心的硬件ID码,而是源于显卡驱动信息中的硬件名称。这样的检测方法虽然实现起来比较简单,但是获得的信息并不十分可靠,后文将会具体说明。) ②.显示芯片型号部分: 核心代号/GPU:此处显示GPU芯片的代号,如:G84M、G86M、RV630、RV610等。 修订版本/Revision:此处显示GPU芯片的步进制程编号。 制造工艺/Technology:此处显示GPU芯片的制程工艺,如80nm、65nm、55nm

等。 核心面积/Die Size:此处显示GPU芯片的核心尺寸。(目前版本的GPU-Z 还没有添加该数据库) ③.显卡的硬件信息部分: BIOS版本/BIOS Version:此处显示显卡BIOS的版本号。 设备ID/Device ID:此处显示设备的ID码。 制造厂商/Subvendor:此处显示该显卡的制造厂商名称。 ④.显示芯片参数部分: 光栅引擎/ROPs:此处显示GPU拥有的ROP光栅操作处理器的数量,越多性能越强。 总线接口/Bus Interface:此处显示显卡和主板北桥芯片之间的总线接口类型以及接口速度。 着色单元/Shaders:此处显示GPU拥有的着色器的数量,越多性能越强。 (目前主流的nVIDIA GeForce8和ATI HD2000系列显卡均采用统一渲染架构,着色单元统称流处理器(Stream Processor)。而之前的显卡的着色单元则分为像素着色器(Pixel Shaders)和顶点着色器(Vertex Shaders)两部分。)DirectX版本/DirectX Support:此处显示GPU所支持的DirectX版本。 像素填充率/Pixel Fillrate:此处显示GPU的像素填充率,越多性能越强。 纹理填充率/Texture Fillrate:此处显示GPU的纹理填充率,越多性能越强。 ⑤.显存信息部分: 显存类型/Memory Type:此处显示显卡所采用的显存类型,如:GDDR3、DDR2、DDR等。 显存位宽/Bus Width:此处显示GPU与显存之间连接的带宽,越多性能越强。 (显卡的这项参数是我们应该重点关注的地方,市面上众多“阉割”卡就是被黑心的厂商在这里做了手脚。这样的例子很多,比如:某知名品牌的一款高端笔记本(为了避免不必要的麻烦,笔者就不爆料了),原本128bit位宽的GeForce86000M GS,厂家为了降低成本,将显卡位宽活生生的砍掉一半,只剩下64bit,致使3D性能大打折扣。消费者乐呵呵的把机器买到手,一玩游戏,才发现实际的表现十分糟糕,这时后悔也晚了。所以,选购独显笔记本的时候一定要特别留意这个参数。注:Geforce8400和HD2400原生的显存位宽就只有64位,不必担心被动手脚。) 显存容量/Memory Size:此处显示显卡板载的物理显存容量。 显存带宽/Bandwidth:此处显示GPU-Z与显存之间的数据传输速度,越多性能越强。 ⑥.驱动部分: 驱动程序版本/Driver Version:此处为系统内当前使用的显卡驱动的版本号。 ⑦.显卡频率部分: 核心频率/GPU Clock:显示GPU当前的运行频率。

GPU服务器上显卡压力测试工具及测试方法介绍

Stree_GPU压力测试 一、测试介绍 常搞服务器测试的,会有很多测试工具,比如测试硬盘的iometer,网络测试的有IxChariot,IPfer,测试内存的有stree,整机压力测试HPC_Breakin等,但整机测试GPU或是显卡的工具就比较少,专业的测试是必须要有的。 很多个人或是公司买了GPU服务器,显卡回来,安装上去后,不知道如何整机测试,怎么压力测试,怎么检测是否有问题,做开发设计的怎么测试主板是否有bug,整机散热调优方案,功耗测试等,通过使使用stree_GPU工具,可以使GPU/显卡发挥90%以上的性能,从而发现存在的隐患。 直接介绍一套简单的测试工具Stree_GPU,适合在windows 7,win8,win10,2008 R2等windows系统下测试的。 1页

1、准备工作环境 你的机器安装上显卡/GPU卡后,然后再安装上述的操作系统,机器需要连外网才能使用Stree_GPU测试。但它不占用外网资源。 2、安装驱动 这个不用我说了,你电脑上驱动都要安装,GPU/显卡一般是基于NVIDIA芯片开发的,驱动一般直接到它官网上下载,或是安装个驱动人生,然后让它帮你全部安装完驱动,省事^_^ 二、测试工具使用介绍 1、Stree_GPU工具使用介绍,此stree_GPU软件适用windows系统下 GPU/显卡专业测试工具stree_GPU测试工具下载: https://https://www.doczj.com/doc/779772029.html,/s/1PnxbcIQvM9Y4YtVude7WNg 2、首先你的机器在windows下环境配置好,即显卡驱动要安装上,可以在NVIDIA官网下载cuda程序安装,能识别到你的显卡并能调休; 3、确保你测试的机器连通外网,因为测试时要模拟卡的压力(算力); 4、把Stree_GPU程序解压后拷贝到如c盘根目录下,路径不要有中文; 5、解压后在Stree_GPU目录里,右键以管理员权限运行stree_GPU.bat 注意观察,如果执行之后屏幕上没有提示错误提示,没有红色的提示,则表示开始跑起来了,过一会才会有结果,比如会提示有GPU0:xxxMh/s,这里只要有数字出现就表示成功了,如果有多张卡,这里会列出来有GPU0,GPU1…..。如下 2页

一个简单字符设备驱动实例

如何编写Linux设备驱动程序 Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便。本文是在编写一块多媒体卡编制的驱动程序后的总结,获得了一些经验,愿与Linux fans共享,有不当之处,请予指正。 以下的一些文字主要来源于khg,johnsonm的Write linux device driver,Brennan's Guide to Inline Assembly,The Linux A-Z,还有清华BBS上的有关device driver的一些资料. 这些资料有的已经过时,有的还有一些错误,我依据自己的试验结果进行了修正. 一、Linux device driver 的概念 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1)对设备初始化和释放; 2)把数据从内核传送到硬件和从硬件读取数据; 3)读取应用程序传送给设备文件的数据和回送应用程序请求的数据; 4)检测和处理设备出现的错误。 在Linux操作系统下有两类主要的设备文件类型,一种是字符设备,另一种是块设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待. 已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备。另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序. 最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。 二、实例剖析 我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理.把下面的C代码输入机器,你就会获得一个真正的设备

相关主题
文本预览
相关文档 最新文档