SylixOS块设备驱动开发(七)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2021年1月10日18:11:28 1 1,351

虚拟块设备驱动源码

#define  __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <module.h>
#include <stdlib.h>
#include <string.h>

/*
*  BSP内存需求:
*  1. 虚拟磁盘由于是在内核用malloc申请的一块内存,所以需要保证BSP中内核data区域要大于这个磁盘内存的大小
*  2. 如果需要DCATTR_stMemSize磁盘缓存cache,这个cache是内核在内核堆上申请的,所以BSP中的data区也要大于这大小
*  3. 读猝发缓冲区大小为:猝发扇区数 * 扇区大小
*  4. 写猝发缓冲区大小为:猝发扇区数 * 扇区大小 * DCATTR_iMsgCount
*  5. 3和4如果使用cache一致性,那么内核申请的区域是DMA区域,否则是内核堆区
*
*/

#define SECTOR_BYTES       512
#define VIRTUAL_DISK_SIZE  20 * LW_CFG_MB_SIZE

#define BUSTOR_SECTOR      64
#define DISK_CACHE_SIZE    64 * LW_CFG_KB_SIZE

static LW_BLK_DEV vdisk_dev;
static PLW_OEMDISK_CB *vdisk_oemcb;
static void *vdisk_start;

static int vdisk_read (PLW_BLK_DEV dev, void *buf, int blk_start, int blk_num)
{
    //计算要读取的虚拟磁盘起始位置
    void *addr = vdisk_start + blk_start * dev->BLKD_ulBytesPerSector;

    //读取虚拟磁盘数据
    memcpy(buf, addr, blk_num * dev->BLKD_ulBytesPerSector);

    return  (ERROR_NONE);
}

static int vdisk_write (PLW_BLK_DEV dev, void *buf, int blk_start, int blk_num)
{
    //计算要读取的虚拟磁盘起始位置
    void *addr = vdisk_start + blk_start * dev->BLKD_ulBytesPerSector;

    //写入虚拟磁盘数据
    memcpy(addr, buf, blk_num * dev->BLKD_ulBytesPerSector);

    return  (ERROR_NONE);
}

static int vdisk_ioctl (PLW_BLK_DEV dev, int cmd, long arg)
{
    switch (cmd) {

    /*
     *  必须要支持的命令
     */
    case FIOSYNC:
    case FIODATASYNC:
    case FIOSYNCMETA:
    case FIOFLUSH:                                                      /*  将缓存写入磁盘              */

    case FIOUNMOUNT:                                                    /*  卸载卷                      */
    case FIODISKINIT:                                                   /*  初始化磁盘                  */
    case FIODISKCHANGE:                                                 /*  磁盘媒质发生变化            */
        break;

    case FIOTRIM:                                                       /* AHCI_TRIM_EN                 */
        break;
    /*
     *  低级格式化
     */
    case FIODISKFORMAT:                                                 /*  格式化卷                    */
        return  (PX_ERROR);                                             /*  不支持低级格式化            */

    /*
     *  FatFs 扩展命令
     */
    case LW_BLKD_CTRL_POWER:
    case LW_BLKD_CTRL_LOCK:
    case LW_BLKD_CTRL_EJECT:
        break;

    case LW_BLKD_GET_SECSIZE:
    case LW_BLKD_GET_BLKSIZE:
        *((LONG *)arg) = (LONG)dev->BLKD_ulBytesPerSector;
        break;

    case LW_BLKD_GET_SECNUM:
        *((ULONG *)arg) = (ULONG)dev->BLKD_ulNSector;
        break;

    case FIOWTIMEOUT:
    case FIORTIMEOUT:
        break;

    default:
        _ErrorHandle(ENOSYS);
        return  (PX_ERROR);
    }

    return  (ERROR_NONE);
}

static int vdisk_reset (PLW_BLK_DEV dev)
{
    return  (ERROR_NONE);
}

static int vdisk_status_chk (PLW_BLK_DEV dev)
{
    return  (ERROR_NONE);
}

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

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

    /*
    *  配置块设备参数
    */
    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);
    }

    if (vdisk_start) {
        free(vdisk_start);
    }
}

 

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

发表评论

匿名网友 填写信息

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

评论:1   其中:访客  1   博主  0
    • 没意思去扬州你不去 没意思去扬州你不去 4

      没意思去扬州你不去