首先判断挂载的类型是否符和已经定义好的文件系统类型。里面的实现方式是比较对应字符串是否相同。
mount_findfs(g_bdfsmap, filesystemtype);
其中g_bdfsmap就是已经定义好的文件系统类型。
static const struct fsmap_t g_bdfsmap[] =
{
#ifdef CONFIG_FS_FAT
{ "vfat", &fat_operations },
#endif
#ifdef CONFIG_FS_ROMFS
{ "romfs", &romfs_operations },
#endif
#ifdef CONFIG_FS_SMARTFS
{ "smartfs", &smartfs_operations },
#endif
{ NULL, NULL },
};
根据文件路径找到相应的inode节点。//如何寻找的实现方式说明已经在之前的stat系统调用文章中说明。
接下来最核心的函数是
mops->bind(blkdrvr_inode, data, &fshandle);
该bind方法,该方法首先分配一个绑定的结构体空间
fs = (struct fat_mountpt_s *)kmm_zalloc(sizeof(struct fat_mountpt_s));
最终该结构体内容要被各种fat相关参数填充。
接下来就是fat文件系统挂载的核心函数
int fat_mount(struct fat_mountpt_s *fs, bool writeable)
一路跟踪下来,该函数中有关读写的都比较重要,我们先来看一下读函数(主要是读取一些扇区的信息)
int fat_hwread(struct fat_mountpt_s *fs, uint8_t *buffer, off_t sector,
unsigned int nsectors)
该函数主要是调用已经注册好的回调函数
inode->u.i_bops->read(inode, buffer,sector, nsectors);
而该回调函数又在注册块设备驱动的时候被赋值
int register_blockdriver(FAR const char *path,
FAR const struct block_operations *bops,
mode_t mode, FAR void *priv)
{
<span style="white-space:pre"> </span>node->u.i_bops = bops;
#ifdef CONFIG_FILE_MODE
node->i_mode = mode;
#endif
node->i_private = priv;}
sd卡注册的块设备驱动应该是在相关mmcsd相关源文件中,而usb注册的块设备在相关usbhost相关源文件中。
首先介绍的sd的注册过程。
int mmcsd_slotinitialize(int minor, FAR struct sdio_dev_s *dev)
{
FAR struct mmcsd_state_s *priv;
char devname[16];
int ret = -ENOMEM;
fvdbg("minor: %d\n", minor);
/* Sanity check */
#ifdef CONFIG_DEBUG
if (minor < 0 || minor > 255 || !dev)
{
return -EINVAL;
}
#endif
/* Allocate a MMC/SD state structure */
priv = (FAR struct mmcsd_state_s *)kmm_malloc(sizeof(struct mmcsd_state_s));
if (priv)
{
/* Initialize the MMC/SD state structure */
memset(priv, 0, sizeof(struct mmcsd_state_s));
sem_init(&priv->sem, 0, 1);
/* Bind the MMCSD driver to the MMCSD state structure */
priv->dev = dev;
priv->dev_id = minor;
/* Initialize the hardware associated with the slot */
ret = mmcsd_hwinitialize(priv);
/* Was the slot initialized successfully? */
if (ret != OK)
{
if (ret == SDIO_OK)
{
return OK;
}
/* No... But the error ENODEV is returned if hardware initialization
* succeeded but no card is inserted in the slot. In this case, the
* no error occurred, but the driver is still not ready.
*/
if (ret == -ENODEV)
{
/* No card in the slot (or if there is, we could not recognize
* it).. Setup to receive the media inserted event
*/
SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
fvdbg("MMC/SD slot is empty\n");
}
else
{
/* Some other non-recoverable bad thing happened */
fdbg("ERROR: Failed to initialize MMC/SD slot: %d\n", ret);
goto errout_with_alloc;
}
}
#if defined(CONFIG_DRVR_WRITEBUFFER) || defined(CONFIG_DRVR_READAHEAD)
/* Initialize buffering */
#warning "Missing setup of rwbuffer"
ret = rwb_initialize(&priv->rwbuffer);
if (ret < 0)
{
fdbg("ERROR: Buffer setup failed: %d\n", ret);
goto errout_with_hwinit;
}
#endif
/* Create a MMCSD device name */
snprintf(devname, 16, "/dev/mmcsd%d", minor);
/* Inode private data is a reference to the MMCSD state structure */
ret = register_blockdriver(devname, &g_bops, 0, priv);
相关回调函数方法是
static const struct block_operations g_bops =
{
mmcsd_open, /* open */
mmcsd_close, /* close */
mmcsd_read, /* read */
#ifdef CONFIG_FS_WRITABLE
mmcsd_write, /* write */
#else
NULL, /* write */
#endif
mmcsd_geometry, /* geometry */
mmcsd_ioctl /* ioctl */
};
而在上面用到的read方法:
static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,size_t startsector, unsigned int nsectors);
#define SDIO_LOCK(dev,state) ((dev)->lock(dev,state))
#define SDIO_RESET(dev) ((dev)->reset(dev))
#define SDIO_STATUS(dev) ((dev)->status(dev))
#define SDIO_WIDEBUS(dev,wide) ((dev)->widebus(dev,wide))
#define SDIO_CLOCK(dev,rate) ((dev)->clock(dev,rate))
#define SDIO_ATTACH(dev) ((dev)->attach(dev))
#define SDIO_SENDCMD(dev,cmd,arg) ((dev)->sendcmd(dev,cmd,arg))
#define SDIO_RECVSETUP(dev,buffer,nbytes) ((dev)->recvsetup(dev,buffer,nbytes))
#define SDIO_SENDSETUP(dev,buffer,nbytes) ((dev)->sendsetup(dev,buffer,nbytes))
#define SDIO_CANCEL(dev) ((dev)->cancel(dev))
#define SDIO_WAITRESPONSE(dev,cmd) ((dev)->waitresponse(dev,cmd))
#define SDIO_RECVR1(dev,cmd,R1) ((dev)->recvR1(dev,cmd,R1)) /* 48-bit */
#define SDIO_RECVR2(dev,cmd,R2) ((dev)->recvR2(dev,cmd,R2)) /* 136-bit */
#define SDIO_RECVR3(dev,cmd,R3) ((dev)->recvR3(dev,cmd,R3)) /* 48-bit */
#define SDIO_RECVR4(dev,cmd,R4) ((dev)->recvR4(dev,cmd,R4)) /* 48-bit */
#define SDIO_RECVR5(dev,cmd,R5) ((dev)->recvR5(dev,cmd,R5)) /* 48-bit */
#define SDIO_RECVR6(dev,cmd,R6) ((dev)->recvR6(dev,cmd,R6)) /* 48-bit */
#define SDIO_RECVR7(dev,cmd,R7) ((dev)->recvR7(dev,cmd,R7)) /* 48-bit */
#define SDIO_WAITENABLE(dev,eventset) ((dev)->waitenable(dev,eventset))
#define SDIO_EVENTWAIT(dev,timeout) ((dev)->eventwait(dev,timeout))
#define SDIO_CALLBACKENABLE(dev,eventset) ((dev)->callbackenable(dev,eventset))
{
375 #ifdef CONFIG_SDIO_MUXBUS
376 .lock = xxx_lock,
377 #endif
378 .reset = xxx_reset,
379 .status = xxx_status,
380 .widebus = xxx_widebus,
381 .clock = xxx_clock,
382 .attach = xxx_attach,
383 .sendcmd = xxx_sendcmd,
384 #ifdef CONFIG_SDIO_BLOCKSETUP
385 .blocksetup = xxx_blocksetup,
386 #endif
387 .recvsetup = xxx_recvsetup,
388 .sendsetup = xxx_sendsetup,
389 .cancel = xxx_cancel,
390 .waitresponse = xxx_waitresponse,
391 .recvR1 = xxx_recvshortcrc,
392 .recvR2 = xxx_recvlong,
393 .recvR3 = xxx_recvshortcrc,
394 .recvR4 = xxx_recvshortcrc,
395 .recvR5 = xxx_recvshortcrc,
396 .recvR6 = xxx_recvshortcrc,
397 .recvR7 = xxx_recvshortcrc,
398 .waitenable = xxx_waitenable,
399 .eventwait = xxx_eventwait,
400 .callbackenable = xxx_callbackenable,
401 .registercallback = xxx_registercallback,
402 #ifdef CONFIG_SDIO_DMA
403 .dmasupported = xxx_dmasupported,
404 #ifdef CONFIG_SDIO_PREFLIGHT
405 .dmapreflight = xxx_dmapreflight,
406 #endif
407 .dmarecvsetup = xxx_dmarecvsetup,
408 .dmasendsetup = xxx_dmasendsetup,
409 #endif
410 },
最终这些回调函数会被上面的框架所调用,而实际上这些函数都是对寄存器的读写操作。
注意mmc中有两种模式一种是sd,一种是sdio。前一种主要是为sd卡,后者主要是为wifi,所以sdio也有相关的一系列回调函数。
接下来是usb挂载文件系统:
usb最初的注册函数是usbhost_msc_initialize。这个接口是usb框架提供的接口。
于是usbhost_registerclass(&g_storage);
最后调用注册块设备注册的函数register_blockdriver是 int usbhost_initvolume(FAR struct usbhost_state_s *priv);当然在这之前会分配相应的结构体空间。而在执行这一函数的前提是在connect的时候执行的。问题是谁去出发这个connect的条件,在查看nuttx源码的时候没有找到???
与mmc不相同的是usb首先调用相关框架的函数,然后再调用注册的回调函数,但是整体上都是相同的,跟着框架的逻辑走,最后调用回调函数,具体这两者的驱动的通信方式是怎么样的,那还需要我好好研究再做总结。
mount这个一个系统调用涉及了很多的方面东西(文件系统,块设备驱动)。