SylixOS块设备驱动开发(四)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2021年1月10日17:13:27 1 1,023

创建块设备并自动挂载

1. 概述

从本小节开始,我们以一个虚拟磁盘块设备驱动为例来讲解如何编写一个基础的块设备驱动。说是虚拟的磁盘也就是分配一段内存来当做磁盘来使用,对磁盘的读写也就是访问内存的不同位置来实现。

2. 块设备注册

SylixOS中的块设备是通过LW_BLK_DEV 这个数据结构来描述的,这个结构就是一个实际磁盘控制器的抽象:

typedef struct {
    PCHAR       BLKD_pcName;                                            /* 可以为 NULL 或者 "\0"        */
                                                                        /* nfs romfs 文件系统使用       */
    FUNCPTR     BLKD_pfuncBlkRd;		                                /* function to read blocks      */
    FUNCPTR     BLKD_pfuncBlkWrt;		                                /* function to write blocks     */
    FUNCPTR     BLKD_pfuncBlkIoctl;		                                /* function to ioctl device     */
    FUNCPTR     BLKD_pfuncBlkReset;		                                /* function to reset device     */
    FUNCPTR     BLKD_pfuncBlkStatusChk;                                 /* function to check status     */
    
    ULONG       BLKD_ulNSector;                                         /* number of sectors            */
    ULONG       BLKD_ulBytesPerSector;                                  /* bytes per sector             */
    ULONG       BLKD_ulBytesPerBlock;                                   /* bytes per block              */
    
    BOOL        BLKD_bRemovable;                                        /* removable medium flag        */
    BOOL        BLKD_bDiskChange;                                       /* media change flag            */
    INT         BLKD_iRetry;                                            /* retry count for I/O errors   */
    INT         BLKD_iFlag;                                             /* O_RDONLY or O_RDWR           */
    
    /*
     *  以下参数操作系统使用, 必须初始化为 0.
     */
    INT         BLKD_iLogic;                                            /* if this is a logic disk      */
    UINT        BLKD_uiLinkCounter;                                     /* must be 0                    */
    PVOID       BLKD_pvLink;                                            /* must be NULL                 */
    
    UINT        BLKD_uiPowerCounter;                                    /* must be 0                    */
    UINT        BLKD_uiInitCounter;                                     /* must be 0                    */
} LW_BLK_DEV;

一个块设备通常都会有自己的磁盘缓冲,在SylixOS中,块设备缓冲是通过 LW_DISKCACHE_ATTR 数据结构来描述的:

typedef struct {
    PVOID           DCATTR_pvCacheMem;                                  /*  扇区缓存地址                */
    size_t          DCATTR_stMemSize;                                   /*  扇区缓存大小                */
    INT             DCATTR_iBurstOpt;                                   /*  缓存属性                    */
    INT             DCATTR_iMaxRBurstSector;                            /*  磁盘猝发读的最大扇区数      */
    INT             DCATTR_iMaxWBurstSector;                            /*  磁盘猝发写的最大扇区数      */
    INT             DCATTR_iMsgCount;                                   /*  管线消息队列缓存个数        */
    INT             DCATTR_iPipeline;                                   /*  处理管线线程数量            */
    BOOL            DCATTR_bParallel;                                   /*  是否支持并行读写            */
    ULONG           DCATTR_ulReserved[8];                               /*  保留                        */
} LW_DISKCACHE_ATTR;

在对上述两个数据结构初始化之后,就可以调用 API_OemDiskMount2 来创建块设备并自动尝试挂载相应的分区:

PLW_OEMDISK_CB    API_OemDiskMount2(CPCHAR             pcVolName,
                                           PLW_BLK_DEV        pblkdDisk,
                                           PLW_DISKCACHE_ATTR pdcattrl);

成功调用后,接口返回一个磁盘控制块句柄:

typedef struct {
    PLW_BLK_DEV          OEMDISK_pblkdDisk;                             /*  物理磁盘驱动                */
    PLW_BLK_DEV          OEMDISK_pblkdCache;                            /*  CACHE 驱动块                */
    PLW_BLK_DEV          OEMDISK_pblkdPart[LW_CFG_MAX_DISKPARTS];       /*  各分区驱动块                */
    INT                  OEMDISK_iVolSeq[LW_CFG_MAX_DISKPARTS];         /*  对应个分区的卷序号          */
    PLW_DEV_HDR          OEMDISK_pdevhdr[LW_CFG_MAX_DISKPARTS];         /*  安装后的设备头              */
    PVOID                OEMDISK_pvCache;                               /*  自动分配内存地址            */
    UINT                 OEMDISK_uiNPart;                               /*  分区数                      */
    INT                  OEMDISK_iBlkNo;                                /*  /dev/blk/? 设备号           */
    CHAR                 OEMDISK_cVolName[1];                           /*  磁盘根挂载节点名            */
} LW_OEMDISK_CB;

一般的做法是定义一个全局的块设备数据结构变量,块缓冲数据结构可以定义为局部变量,初始化后进行块设备创建:

static LW_BLK_DEV vdisk_dev;
static PLW_OEMDISK_CB *vdisk_oemcb;

int module_init (void)
{
    PLW_BLK_DEV pdev = &vdisk_dev;
    LW_DISKCACHE_ATTR dcattrl;

    /*
    *  配置块设备参数
    */
    pdev->BLKD_pcName = "VirtualDisk";
    pdev->BLKD_ulNSector = VIRTUAL_DISK_SIZE / SECTOR_BYTES;
    pdev->BLKD_ulBytesPerSector = SECTOR_BYTES;
    pdev->BLKD_ulBytesPerBlock = SECTOR_BYTES;
    pdev->BLKD_bRemovable = LW_TRUE;
    pdev->BLKD_iRetry = 1;
    pdev->BLKD_iFlag = O_RDWR;
    pdev->BLKD_bDiskChange = LW_TRUE;
    pdev->BLKD_pfuncBlkRd = vdisk_read;
    pdev->BLKD_pfuncBlkWrt = vdisk_write;
    pdev->BLKD_pfuncBlkIoctl = vdisk_ioctl;
    pdev->BLKD_pfuncBlkReset = vdisk_reset;
    pdev->BLKD_pfuncBlkStatusChk = vdisk_status_chk;

    pdev->BLKD_iLogic = 0;
    pdev->BLKD_uiLinkCounter = 0;
    pdev->BLKD_pvLink = LW_NULL;

    pdev->BLKD_uiPowerCounter = 0;
    pdev->BLKD_uiInitCounter = 0;

    dcattrl.DCATTR_pvCacheMem = LW_NULL;
    dcattrl.DCATTR_stMemSize = (size_t)(DISK_CACHE_SIZE);
    dcattrl.DCATTR_iBurstOpt = LW_DCATTR_BOPT_CACHE_COHERENCE;
    dcattrl.DCATTR_iMaxRBurstSector = (INT)BUSTOR_SECTOR;
    dcattrl.DCATTR_iMaxWBurstSector = (INT)BUSTOR_SECTOR;
    dcattrl.DCATTR_iMsgCount = 4;
    dcattrl.DCATTR_bParallel = LW_TRUE;
    dcattrl.DCATTR_iPipeline = 1;

    vdisk_oemcb = API_OemDiskMount2("/media/vdisk", pdev, &dcattrl);
    if (!vdisk_oemcb) {
        printk("oem disk mount fail.\r\n");
        free(vdisk_start);
        return  (PX_ERROR);
    }

    return  (ERROR_NONE);
}

void module_exit (void)
{
    if (vdisk_oemcb) {
        API_OemDiskUnmount(vdisk_oemcb);
    }
}

具体的初始化参数会在下面章节讲解,API_OemDiskMount2 第一个参数表示块设备要挂载的位置,系统会自动截取最后一个'/'后面的字符串加上块设备序号或者分区号组成最终的设备名和挂载目录。

同时还要定义一个全局变量用来保存虚拟磁盘的内存起始地址:

#define VIRTUAL_DISK_SIZE 20 * LW_CFG_MB_SIZE

static void *vdisk_start;

int module_init (void)
{
    vdisk_start = malloc(VIRTUAL_DISK_SIZE);
    if (!vdisk_start) {
        printk("create virtual disk fail.\n");
        return  (PX_ERROR);
    }

    return  (ERROR_NONE);
}

在驱动中使用malloc接口申请内存当做虚拟磁盘空间,默认的大小为20MB。

gewenbin
  • 本文由 发表于 2021年1月10日17:13:27
  • 转载请务必保留本文链接:http://www.databusworld.cn/9948.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

评论:1   其中:访客  1   博主  0
    • liqingquan liqingquan 3

      打卡