《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 其他 > Linux设备驱动程序架构分析之MMC/SD(九)

Linux设备驱动程序架构分析之MMC/SD(九)

2015-04-29
关键词: structmmc_host

1204行,由structmmc_host得到struct s3cmci_host。

1205行,从host->mrq取出mmc_request以便使用。

1206行,因为host->cmd_is_stop被设置为0,所以cmd被设置为mrq->cmd。

1214-1216行,清空SDICmdSta寄存器、SDIDatSta寄存器和SDIFSTA寄存器。

1216-1245行,如果cmd->data不为0,即当前command带有要处理的数据,则执行这个if语句块,进行数据处理的准备工作。

1219行,调用s3cmci_setup_data(host,cmd->data),该函数定义在drivers/mmc/host/s3cmci.c文件中:

捕获.PNG

捕获.PNG

捕获.PNG

1054-1057行,如果命令数据为空,则清零SDIDatCon寄存器。

1059-1067行,根据Datasheet的描述,如果在多模块下必须分配字大小,即BlkSize[1:0]=00,所以这里“与”3来判断是不是单模块。如果在单模块处理的情况下,模块数大于1,则出错退出。

1069-1082行,循环判断是否有数据正在发送或接收,如果有,则停止传输,并复位时钟。最多循环3次。

1086-1087行,如果使用DMA传输,则使能SDIDatCon寄存器的第15位DMA功能。

1089-1090行,如果数据总线宽度为4线,则使能SDIDatCon寄存器的第16位宽总线WideBus功能。

1092-1093行,配置SDIDatCon寄存器的第17位,数据传输模式为块传输模式。

1095-1098行,如果是写数据,配置SDIDatCon寄存器的第20位,收到回应后开始写数据。然后配置SDIDatCon寄存器的第12、13位,设置为写模式。

1100-1103行,如果是读数据,配置SDIDatCon寄存器的第19位,命令发送后开始读数据。

然后配置SDIDatCon寄存器的第12、13位,设置为读模式。

1105-1108行,如果是S3C2440,配置SDIDatCon寄存器的第22、23位为10,即传输单位为word。然后配置SDIDatCon寄存器的第14位,开始数据传输。

1110行,将dcon写入SDIDatCon寄存器。

1114行,将data->blksz写入SDIBSize寄存器。

1117-1118行,设置出现FIFO失败SDI中断使能;数据接收CRC错误SDI中断使能;数据接收超时SDI中断使能;数据计时为0SDI中断使能。

1120行,调用enable_imask使能设置的中断。

1124-1132行,设置SDIDTimer寄存器。

回到s3cmci_send_request函数:

1223-1230行,如果s3cmci_setup_data出错,则打印信息并退出。

1232-1233行,如果使用DMA,则调用s3cmci_prepare_dma函数,该函数定义在drivers/mmc/host/s3cmci.c文件中,关于DMA相关的函数,我们不再详细跟踪了。

1235行,如果没有使用DMA数据传输方式,则调用s3cmci_prepare_pio函数,即使用FIFO数据传输方式,具体来说,就是调用 do_pio_write向FIFO中填充数据,当64字节的FIFO少于33字节时就会产生中断;或者从SD读数据,则先使能中断,当FIFO多于31 字节时,则会调用中断服务程序,中断服务程序会调用do_pio_read读出FIFO的数据。

s3cmci_prepare_pio函数定义在drivers/mmc/host/s3cmci.c文件中:

捕获.PNG

1141行,根据data->flags确定是读还是写。

1151行,如果是写,则调用do_pio_write函数。do_pio_write函数定义在drivers/mmc/host/s3cmci.c文件中:

捕获.PNG

捕获.PNG

527行,取得SDIDAT寄存器的物理地址保存在to_ptr变量中。

529行,调用fifo_free(host)函数取得FIFO的剩余可用空间的字节数保存在fifo变量中,这里,fifo变量代表这次while循环最多可写的字节个数。如果剩余空间大于3个字节,即最小写一个字,则循环条件成立。

530-532行,如果host->pio_bytes为0,则调用get_data_buffer从分散聚集列表中取得保存要写的数据的缓 冲区,缓冲区的长度和起始地址分别保存在get_data_buffer的2个参数host->pio_bytes和第3个参数 host->pio_ptr中。

533-539行,如果get_data_buffer出错,打印信息退出。

551-552行,如果fifo大于等于host->pio_bytes,即FIFO的可用空间大于等于保存要写数据的缓冲区长度,则将fifo设置为host->pio_bytes。

554行,如果fifo小于host->pio_bytes,即FIFO的可用空间小于要写数据的缓冲区长度,则将fifo设置为fifo – (fifo & 3)。从注释可以看到,这是为了保证以字为单位进行写操作。

556行,host->pio_bytes-= fifo,保存这次写操作后,剩余的要写的字节数。

557行,host->pio_count+= fifo,保存已经写了多少个字节。

559行,将字节数转化为字数。

561-562行,写数据到SDIDAT寄存器。

563行,host->pio_ptr= ptr,保存当前还剩余要写数据的位置。 

564行,结束这次while循环,回到529行重新执行上述过程。     

566行,使能SDIIntMsk第4位,如果Tx FIFO填充满一半,就产生中断。

回到s3cmci_prepare_pio函数中:

1152行,使能SDIIntMsk第4位,如果Tx FIFO填充满一半,就产生中断。

1154行,使能SDIIntMsk第0位,如果Rx FIFO填充满一半,就生产中断。

1155行,使能SDIIntMsk第2位,如果Rx FIFO读取了最后的数据,就产生中断。

回到s3cmci_send_request函数:

1248行,调用s3cmci_send_command(host,cmd)发送命令。

该函数定义在drivers/mmc/host/s3cmci.c文件中:

捕获.PNG

本站内容除特别声明的原创文章之外,转载内容只为传递更多信息,并不代表本网站赞同其观点。转载的所有的文章、图片、音/视频文件等资料的版权归版权所有权人所有。本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如涉及作品内容、版权和其它问题,请及时通过电子邮件或电话通知我们,以便迅速采取适当措施,避免给双方造成不必要的经济损失。联系电话:010-82306118;邮箱:aet@chinaaet.com。