首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

IBM AIX 设备驱动程序开发 -3

IBM AIX 设备驱动程序开发 -3

设备配置例程清单 12. 1) devswadd 内核服务:
1
int devswadd (dev_t devno, struct devsw *dswptr)




这在设备交换表中为 devno 指定的设备增加了一个由 dswptr 指向的设备条目。它通常由设备驱动程序的 ddconfig() 例程调用。
清单 13. 2) devswdel() 内核服务:
1
int devswdel(dev_t devno)




这在设备交换表中删除一个设备条目。它由 ddconfig() 例程调用,以终止设备驱动程序。
uio 结构的组件和意义uio 结构包含一个内存缓冲,用于在实现驱动程序例程时在用户和内核空间之间的数据交换。uio 结构描述虚拟内存中不连续的缓冲。ureadc、uwritec、uiomove 和 uphysio 内核服务全都执行进入或离开 uio 结构所描述的数据缓冲的数据传输。uio 结构是在 /usr/include/sys/uio.h 文件中定义的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct uio {
/* ptr to array of iovec structs describing  user buffer for data transfer */
   struct  iovec *uio_iov;
/* ptr to array of xmem structs containing cross memory descriptors for iovec array.*/  
   struct  xmem  *uio_xmem;
/* #iovec elements remaining to be processed*/
   int32long64_t  uio_iovcnt;

/* #iovec elements already processed */
   int32long64_t  uio_iovdcnt;
#ifdef _LONG_LONG
/* byte offset in file/dev to read/write */
   offset_t uio_offset;   
#else /* _LONG_LONG */
#ifdef __64BIT__
/* off_t offset for ANSI-C mode */
   off_t   uio_offset;     
#else
/* ANSI-C does not support long long */
   int     uio_rsvd;
/* off_t offset for ANSI-C mode      */      
   off_t   uio_offset;     
#endif /* __64BIT__ */
#endif  /* _LONG_LONG */
/* Byte count for data transfer  */
   int32long64_t uio_resid;               
/* Type of buffer being described by uio structure. Data pointed by
  buffer can either be in user or kernel or cross-memory region. */
   short   uio_segflg;
/* copy of file modes from open file structure */   
   long    uio_fmode;      
};




设备驱动程序示例sample_driver.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <stdio.h>
#include <syslog.h>
#include <sys/types.h> /* for dev_t and other types */
#include <sys/errno.h> /* for errno declarations */
#include <sys/sysconfig.h> /* for sysconfig() */
#include <sys/device.h> /* for devsw */
#include <sys/uio.h> /* for uiomove */
#include <sys/sysmacros.h>

struct dr_data
{
  char buffer[1024];
}dr_data[5];

int dr_open(dev_t devno, ulong devflag, chan_t chan, int ext)
{
   bsdlog(LOG_KERN|LOG_DEBUG,"Inside dr_open\n");
   return 0;
}


int dr_close (dev_t devno, chan_t chan)
{
   bsdlog(LOG_KERN|LOG_DEBUG,"Inside dr_close \n");
   return 0;
}

int dr_read (dev_t devno, struct uio *uiop, chan_t chan, int ext)
{
   uint min;
   int rc;

   min = minor_num(devno);
   rc = uiomove(dr_data[min].buffer, 1024, UIO_READ, uiop);
   bsdlog(LOG_KERN | LOG_DEBUG, "Inside dr_read min:
   %d, buffer: %s \n", min, dr_data[min].buffer);
   return rc;
}

int dr_write (dev_t devno, struct uio *uiop, chan_t chan, int ext)
{
   uint min;
   int rc;

   min = minor_num(devno);
   rc = uiomove(dr_data[min].buffer, 1024, UIO_WRITE, uiop);
   bsdlog(LOG_KERN | LOG_DEBUG,"Inside dr_write min:
   %d, buffer: %s \n", min, dr_data[min].buffer);
   return rc;
}

int driverdd_config (dev_t devno, int cmd, struct uio *uiop)
{
   struct devsw dswp;
   int rc = 0;

   switch (cmd)
   {
       case CFG_INIT:
            dswp.d_open     = dr_open;
            dswp.d_close    = dr_close;
            dswp.d_read     = dr_read;
            dswp.d_write    = dr_write;
            dswp.d_ioctl    = nodev;
            dswp.d_strategy = nodev;
            dswp.d_ttys     = NULL;
            dswp.d_select   = nodev;
            dswp.d_config   = driverdd_config;
            dswp.d_print    = nodev;
            dswp.d_dump     = nodev;
            dswp.d_mpx      = nodev;
            dswp.d_revoke   = nodev;
            dswp.d_dsdptr   = NULL;
            dswp.d_selptr   = NULL;
            dswp.d_opts     = DEV_MPSAFE|DEV_64BIT;



            if((rc = devswadd(devno, &dswp)) != 0)
            {
                rc = major_num(devno);
                printf("Error in devswadd: %d\n", rc);
                return rc;
            }
            break;

        case CFG_TERM:
            if((rc = devswdel(devno)) != 0)
            {
                printf("Error in devswdel: %d\n", rc);
                return rc;
            }
            break;
        default:
             printf("Invalid command \n");
            return EINVAL;
    }
    return 0;
}




给定设备驱动程序的配置应用程序示例Config_mgr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/sysmacros.h>
#include <sys/sysconfig.h>
#include <sys/device.h>
#include <sys/mode.h>
#include <odmi.h>
#include <cf.h>
#include <sys/cfgodm.h>
#include <sys/cfgdb.h>

int main()
{
   struct cfg_load ext_load; /* to load kernel extension */
   struct cfg_dd ddcfg; /* to invoke driver config() */
   char c, str[80];
   int rc;
   int major, minor = 0;
   dev_t devno;

   rc = odm_initialize();

   printf("\n Enter choice, (l)oad, (u)nload \n");
   while((c = getchar()) < 'a' && c > 'z');

   switch(c) {
      case 'l':
          ext_load.path = "sample_driver";
          ext_load.libpath = NULL;
          ext_load.kmid = 0;

          if(sysconfig(SYS_KLOAD,
          &ext_load, sizeof(struct cfg_load))) {
             printf("Error in loading extension\n");
             exit (1);
          }
          else
             printf("Extension Successfully loaded, kmid is %d\n", ext_load.kmid);

          major = genmajor("sample_driver");
          printf("Major number: %d\n", major);
          devno = makedev64(major, minor);
          ddcfg.kmid = ext_load.kmid;
          ddcfg.devno = devno;
          ddcfg.cmd = CFG_INIT;
          ddcfg.ddsptr = NULL;
          ddcfg.ddslen = 0;

          if (rc = sysconfig(SYS_CFGDD,
             &ddcfg, sizeof(ddcfg))) {
             printf("Error in configuring device %d %d\n", rc, errno);
             exit (1);
          }

          for(minor = 0; minor <=2; minor++) {
             devno = makedev64(major, minor);
             sprintf(str, "/dev/drvdd%d", minor);
             if (mknod(str, 0666 | _S_IFCHR, devno) == -1){
               printf("Error while creating device %s\n", str);
               exit (1);
             }
          }
          break;

    case 'u':
         ext_load.path = " sample_driver";
         ext_load.libpath = NULL;
         ext_load.kmid = 0;

         if(sysconfig(SYS_QUERYLOAD, &ext_load,
         sizeof(struct cfg_load)))
            printf("Error while querying\n");

         if(sysconfig(SYS_KULOAD, &ext_load,
         sizeof(struct cfg_load)))
            printf("Error in unloading extension\n");
         else
            printf("Extension Successfully unloaded\n");
         break;


    default:
         printf("Incorrect option\n");
         break;
}
        return 0;
}




利用已实现设备驱动程序的应用程序的示例application.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
  int fd0, fd1;
  char rbuf[1024];

  fd0 = open("/dev/drvdd0", O_RDWR);
  if(fd0 < 0){
    printf("Error in opening /dev/drvdd0\n");
    return -1;
  }
  fd1 = open("/dev/drvdd1", O_RDWR);
  if(fd1 < 0){
    printf("Error in opening /dev/drvdd1\n");
    return -1;
  }
  write(fd0, "Hello", 5);
  write(fd1, "World", 5);

  read(fd0, rbuf, 5);
  printf("Read from /dev/drvdd0 : %s\n",rbuf);

  read(fd1, rbuf, 5);
  printf("Read from /dev/drvdd1 : %s\n",rbuf);
  return 0;
}




Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
all: sample_driver config_mgr application

config_mgr: config_mgr.c
          cc -q64 -o config_mgr -g config_mgr.c -lodm -lcfg

application: application.c
      cc -o application application.c

K_LIBS= -bI:/usr/lib/kernex.exp -lsys -lcsys

sample_driver: sample_driver.c
      cc -q64 -o sample_driver64.o -c sample_driver.c -D_KERNEL -D_64BIT_KERNEL
      ld -b64 -o sample_driver sample_driver64.o -e driverdd_config $(K_LIBS)
         
clean:
      rm -f *.o sample_driver sample_driver32
        sample_driver64 config_mgr application  2> /dev/null




样例驱动程序的编译和测试以 root 权限登录到 AIX 6.1 或更高版本的系统。将上述文件复制到开发目录,并在 shell 命令提示符下运行 make 命令。
此操作构建必要的驱动程序、配置实用程序和一个应用程序,该应用程序又会调用驱动程序 API。然后在命令提示符下运行 ./config_mgr 实用程序,并检查驱动程序是否已被成功加载。如果没有抛出错误,您可以继续执行 ./application,它将测试驱动程序 API。
返回列表