编辑博客时,回车的意思是切换段落,shift+回车才是换行。
SCSI Interface Controller: AMD am5380
1 U盘量产工具 - 主控芯片私有的SCSI命令
ChipEasy / ChipGenius
FlashGenius
MyDiskTest
HS握手时,Chirp KJ的频率大概是10KHz。
2 SCSI CDB
2.1 已经定义了CBI,为何又再定义一个BBB
USB MSC传输层协议分CBI(Control/Bulk/Interrupt)和BOT(Bulk-only Transport),而BOT又称为BBB。
对于USB MSC设备来说,USB设备和USB主机之间的通信,既然已经定义了一个CBI规范,那么为何还要再新定义一个BBB呢?
因为最开始USB协议定义的时候,那时候市场上的Floppy Disk还是用的很多的。所以针对Floppy设备特点,分别定义了多个端点来传输不同的信息,即Control端点传命令块,Bulk传数据,Interrupt传状态信息。而后来计算机行业发展了,Floppy类的设备很少用了,存储数据多数开始用Flash Memory了,再加上通过合理规划,可以用同一种端点(Bulk),传输上述三种信息,即命令块,数据,状态。因此,只需要物理上实现2个Bulk端点,节省掉了其他两个端点(Control端点和Interrupt端点),而达到同样的信息传输的目的。
常见的大容量存储设备的bInterfaceClass、bInterfaceSubClass和bInterfaceProtocol分别如下所示。
UFI CBI:0x08/0x04/0x00
UFI BOT:0x08/0x04/0x50
SCSI CBI:0x08/0x06/0x00
SCSI BOT:0x08/0x06/0x50
SFF-8070i/ATAPI BOT(移动硬盘用):0x08/0x05/0x50
Linux系统处理UFI和SCSI命令集参考如下的代码。
drivers/usb/storage/usb.c
get_transport(us);
get_protocol(us);
2.2 CBW and CSW
31个字节长度的USB CBW报文的前15个字节是固定的头,从偏移15开始到偏移30结束是16个字节长度的SCSI CDB。
13个字节长度的USB CSW的最后一个字节表示SCSI CDB执行状态,0表示成功,1或者2表示失败。
2.3 Format Unit
SCSI指令Format Unit和Mode Select,可以一定程度改变HDD的工作模式,其中包括扇区尺寸。由于能够改变扇区的定义,所以这2个指令可以看着是对HDD的低级格式化操作。
低级格式化历史:HDD一个完整扇区包括头部总计15字节的间隙(Gap)部分、同步(Sync)部分和地址标记(Address Mark)部分,总计512字节的数据(Data)部分,以及最后50字节的ECC部分,这些都是在低级格式化时所确定的。
2.4 Inquiry
Figure 2-1 标准Inquiry返回数据
Peripheral Device Type(PDT):标识当前连接逻辑单元的类型,0x00为直接存储设备,0x05为光盘
Removable Media Bit(RMB):置1表示U盘,置0表示HDD
Response Data Format:UFI设备置1,SCSI-2设备置2
Additional Length:参数长度,此值为31
Vendor Information:8个字节长度的ASCII字符串,不包括''
Product Identification:16个字节长度的ASCII字符串,不包括''
Product Revision Level:4 hexadecimal digits,不包括''
2.5 Mode Sense 6
unsigned char
usb_stor_mode_sense6_wp[4] = {
[0] = 3,
[1] = 0x00,
[2] = 0x80, /* bit 7 = WP */
};
When the number of bad sectors is greater than the threshold, which will cause USB flash drive enters write protect.
2.6 Read Capacity
返回的是最大扇区数目减1,即是num_sectors - 1。
2.7 Read10
CDB (SCSI Command Descriptor Block) 包中的offset 2 - 5是LBA,offset 7 - 8是扇区数目。
char umass_event[] = "UMASS_ERR=1";
char umass_port[32];
char *umass_env[] = {umass_event, umass_port, NULL};
kobject_uevent_env(&us->pusb_intf->dev.kobj, KOBJ_CHANGE, umass_env);
2.8 Request Sense
Figure 2-2 Request Sense
Valid:表示Information域是否有效
Information:4个字节的sense_data_info,表示出错的逻辑块地址
Additional Sense Length:值是10
SK、ASC、ASCQ:组成一个24bit的sense_data(大端格式),表示错误代码
USB host MSC(transport.c)每发送一个命令后,都会检测设备返回的CSW的状态值是否为0(Good Status),如果不为0,则USB host MSC马上发送REQUEST_SENSE命令,获取18字节的出错信息,并保存在srb->sense_buffer中供SCSI层分析。
drivers/usb/storage/transport.c
usb_stor_invoke_transport()
srb->sense_buffer
// SS_MEDIUM_NOT_PRESENT = 0x023a00
sense_key = 2;
asc = 0x3a;
ascq = 0x00;
3 Linux内核SCSI子系统
3.1 Linux Mass Storage Gadget
do_scsi_command() - 假如读写时由N个buffer,那么这个函数传输的buffer范围是从[1, N - 1],最后一个buffer由finish_reply()完成传输
finish_reply() - 传输最后一个buffer
send_status() - 完成CSW状态
3.2 SCSI Host注册使用到的函数
scsi_host_alloc()
scsi_add_host()
scsi_scan_host() - 执行INQUIRY命令,每扫描到一个lun(函数scsi_probe_and_add_lun())就创建一个struct scsi_device(譬如U盘一般只有一个lun,而读卡器和UFS可能有多个lun;每个struct scsi_device创建一个disk,可能有多个分区),与sd_probe()匹配。
3.3 sync执行流程
3.3.1 sys_sync
sys_sync()
wakeup_bdflush(0)
sync_inodes(0)
sync_supers()
sync_filesystems(0)
sync_filesystems(1)
sync_inodes(1)
3.3.2 命令行执行sync流程
SYSCALL_DEFINE0(sync)
->
wakeup_flusher_threads()
3.4 TUR执行流程
3.4.1 methodology
drivers/usb/storage/scsiglue.c
queuecommand_lck()
add dump_stack() to find who calls TUR.
3.4.2 enable TUR polling
echo 2000 >
/sys/module/block/parameters/events_dfl_poll_msecs
dfl means default.
3.4.3 Construct TUR Fail CDB
If the device is not ready, the bCSWStatus field in CSW is set to 0x01 (command failed). When device reports 00h in the bCSWStatus field in CSW, which indicates that media is ready.
// srb->sense_buffer
unsigned char
usb_stor_sense_media_notpresent[18] = {
[0] = 0x70,
[2] = 2, /* Sense Key */
[7] = 0x0a,
[12] = 0x3a, /* ASC */
[13] = 0, /* ASCQ */
};
3.5 usb层和scsi层传自定义参数
通过struct Scsi_Host {}
3.6 scatterlist转换为内存虚拟地址
struct scatterlist *scatterlist;
void *kaddr;
获取scatterlist
struct page *page = sg_page(&scatterlist[i]);
kaddr = kmap(page);
4 Android StorageManagerService
4.1 vdc - mConnector
抓取log
dumpsys mount
logcat | grep StorageManagerService
4.2 获得系统所有的存储卷
userdata分区是Android必须的一个分区,作为内置存储,一般也是加密后的分区(vold FBE EXT4_IOC_SET_ENCRYPTION_POLICY),但是userdata需要在vold启动之前挂载,所以它并不归vold管理,而是由init进程挂载。在init进程挂载完内置分区后,就会启动vold进程来处理外置分区。vold需要在内置分区/data下面模拟外置主分区(data/media)。
Framework StorageManagerService通过2个socket连接vold进程,一个是vold处理挂载类工作(包括App2SD的Asec和APK数据包OBB文件),另外一个是cryptd处理加密工作。
StorageManager mStorageMgr =
(StorageManager)this.getSystemService(Context.STORAGE_SERVICE);
StorageVolume[] vlists = mStorageMgr.getVolumeList();
String str = "";
for (StorageVolume sv: vlists) {
str += "path: " + sv.getPath() + " ";
}
// /storage/emulated/0
str += Environment.getExternalStorageDirectory().getPath();
tv.setText(str);
4.3 storage_list.xml
StorageManagerService.java
onVolumeCreatedLocked()
{
...
if (... || vol.disk.isSd()) // /storage/UUID
...
}
5 Abbreviations
ARC:Argonant RISC Core
AT91SAM9260:SAM means Smart ARM-based Microcontroller
ATMEL SAMBA:ATMEL Smart ARM-based Microcontroller Boot Assistant
bdi:backing device info - 脏页写回核心结构;文件系统page cache,使用struct address_space_operations(每个文件系统都有这个结构体,譬如 fat_aops)
DBR:DOS Boot Record
DWC2:Design Ware Controller 2,Apple的嵌入式设备,包括iPad和iPhone都是使用的DWC2
EBR:Extended Boot Record
IDA & IDR:Identification,IDR机制在Linux内核中指的是整数ID管理机制。实质上来讲,这就是一种将一个整数ID号和一个指针关联在一起的机制。IDA是用IDR来实现的ID分配机制,与IDR的区别是IDA仅仅分配与管理ID,并不将ID与指针相关联。
ISP1161:Philips' Integrated host Solution Pairs 1161,“Firms introduce USB host controllers”,https://www.eetimes.com/document.asp?doc_id=1290054
Linux dd命令参数:if表示input file,of表示output file,bs表示block size
MBR:Main Boot Record
MMC-2:SCSI Multimedia Commands-2
MGX:三星SSD主控
NTFS:n ei f ts
ps2251-63:Phison(Phison = “Five-Person”, 由五位Flash 研发经验超过14年专业人士创立),群联
RCU:Read-Copy Update,RCU支持一个更新者和多个读者同时访问。通过维护对象的多个版本,RCU保证读者看到的对象是前后一致的,并且保证在所有之前已存在的读者离开临界区时,这些版本才会被释放
SFF-8020i:Small Form Factor Committee,小型化委员会
SL811HS:Cypress/ScanLogic 811 Host/Slave,性能上与ISP1161(Integrated host Solution Pairs 1161)相当
SSS:Solid State System,鑫创,简称3S
TDI:TransDimension Inc.,该公司首先发明了将TT集成到EHCI RootHub中的方法,这样对于嵌入式系统来说,就省去了OHCI/UHCI的硬件,同时降低了成本,作为对该公司的纪念,Linux内核定义了宏ehci_is_TDI(ehci);产品UHC124表示USB Host Controller;收购了ARC USB技术;现已被chipidea收购,chipidea又被mips收购
TT:Transaction Translator(事务转换器,将USB2.0的包转换成USB1.1的包)
TUR:Test Unit Ready(类似心跳信号),sd_spinup_disk()执行该命令,底层排队函数
USB BH reset:Bigger Hammer or Brad Hosler,表示warm reset;you may be confused why the USB 3.0 spec calls the same type of reset "warm reset" in some places and "BH reset" in other places. "BH" reset is supposed to stand for "Big Hammer" reset, but it also stands for "Brad Hosler". Brad died shortly after the USB 3.0 bus specification was started, and they decided to name the reset after him. The suggestion was made shortly before the spec was finalized, so the wording is a bit inconsistent.
usb_stor_host_template.queuecommand()和ufshcd_queuecommand()。Linux工具sg_turs(SCSI Generic,隶属于sg3_utils)用来手工发送TUR命令。
UASP:USB Attached SCSI Protocol
vold OBB: Opaque Binary Blob
W-LUNs:UFS Well Known Logical Units