Scsi - Index of
Scsi - Index of Scsi - Index of
154 for (i = 0; i < srb->cmd_len && i < 16; i++) 155 US_DEBUGPX(" %02x", srb->cmnd[i]); 156 US_DEBUGPX("\n"); 157 } 相信即使是天下无贼里边的傻根也能看懂这个函数,很简单,就是把要执行的scsi 命令打印出来.列出这 个函数没别的意思,让不熟悉scsi 的同志们知道基本上会遇到些啥命令.显然,刚才说的那个INQUIRY 也 包 含在其中的. 不过别看这个函数很easy,你要是不熟悉scsi 协议的话,你还真的解释不了这个函数.比如你说 srb->cmnd[]这个数组到底是什么内容?有什么格式?为啥函数一开始只判断cmnd[0]?实不相瞒,这里边 还真有学问.首先,在scsi 的规范里边定义了一些命令,每个命令都有一定的格式,命令的字节数也有好几 种, 有的命令是六个字节的,有的命令是10 个字节的,有的命令是12 个字节的.你看,你看,下面就是摘自scsi 规范里边的几张图,scsi 命令就该是这个样子. 这是6 字节的, 143 这是10 个字节的, 这是12 个字节的. 之所以有这好几种命令描述块,没什么特别的,也许只是想体现生物的多样性而已,又或许,印证了张爱 玲的那句话,也许每一个男子全都有过这样的两个女人,至少两个.娶了红玫瑰,久而久之,红的变成了墙上的 一抹蚊子血,白的还是”窗前明月光”;娶了白玫瑰,白的便是衣服上的一粒饭粘子,红的却是心口上的一颗朱 砂痣. 江湖中人们把这样几个字节的命令称之为CDB, command descriptor block, 命令描述符块.而我 们为CDB 准备了一个字符数组,结构体struct scsi_cmnd 中的unsigned char cmnd[16],你说最大就 12 个字节,干嘛不申请一个12 个字节的数组?给你一个建议:我记得复旦并没有一门课程叫做可持续性发 144 展,但是我记得我上海交大的同学有修过这样一门课程,有机会的话,去交大听一下吧. Ok,既然这个CDB 有16 个字节,那么为什么我们每次都判断cmnd[0]就够了?仔细看这三幅图,注意 到那个Operation code 了吗?没错,三幅图中的第一个字节都被称为Operation code,换言之,不管你是 什么样子的命令, 你都必须在第一个字节里签上自己的名字, 向世人说明你是谁. 于是在 include/scsi/scsi.h 中,定义了好多好多宏,比如#define INQUIRY 0x12,又比如#define READ_6 0x08,再比如#define FORMAT_UNIT 0x04,够了,实际上操作码就相当于scsi 命令的序列号,scsi 命令 总共也就那么多,8 位的操作码已经足够表示了,因此,我们只要用一个字节就可以判断出这是哪个命令了. 因为你的第一个字节就相当于你的眼睛,不管你埋藏的多深,你会发现最终总是你的眼睛背叛了你的心,这一 点郑中基大概感受颇深吧. 好了,命令说完了,开始进入真正处理命令的部分了. 迷雾重重的 bulk 传输(一) 2006 年的最后一个星期,来到了北京,开始了北漂的生活.和上海不同的是,在这里待了三个月之后,发现 竟然没有下过一次雨,难怪日本小孩说:”你们北京小孩真幸福,城外就是大沙漠,出了城就可以骑骆驼看日落 了.”不过,今天下雨了,下了大雨,好大好大,一阵阵的闪电,回家的时候下半身都湿了…(天哪,怎么写着写着 又往那个方向走去了…算了,我承认我只是一个用下半身思考的男青年.) 很累,但是听着北京不眠夜,又不想入睡,听着刘杨的声音,心里感到特别温暖,这些年里,从长沙,到上海,再
到北京,每每只有在夜深人静的时候,听着广播,才能忘却一些绝望.于是继续写吧,既然人生的幕布已经拉 开, 就一定要积极的演出;既然脚步已经跨出,风雨坎坷也不能退步;既然我已把希望播在这里,就一定要坚持到 胜利的谢幕. 375 行,us->proto_handler()其实是一个函数指针,知道它指向什么吗?不要说你不知道,早年我们在 storage_probe()中,确切的说,在get_protocol()就赋了值,当时只知道是get protocol,却不知道究竟干 什么用,现在该用上了,别以为写代码的都是傻子,一个指针要是没什么用人家才不会为它赋值呢.当初我们 就讲了,对于U 盘,proto_handler 被赋值为usb_stor_transparent_scsi_command,所以我们来看后 者吧. 后者定义于drivers/usb/storage/protocol.c: 172 void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, 173 struct us_data *us) 174 { 175 /* send the command to the transport layer */ 176 usb_stor_invoke_transport(srb, us); 177 178 if (srb->result == SAM_STAT_GOOD) { 179 /* Fix the READ CAPACITY result if necessary */ 180 if (us->flags & US_FL_FIX_CAPACITY) 181 fix_read_capacity(srb); 182 } 183 } 145 首先注意到的是usb_stor_invoke_transport()函数这个函数可不简单.咱们先做好思想准备, 接下 来就去见识一下她的庐山真面目. 她来自drivers/usb/storage/transport.c: 519 /*********************************************************************** 520 * Transport routines 521 **************************************************************** *******/ 522 523 /* Invoke the transport and basic error-handling/recovery methods 524 * 525 * This is used by the protocol layers to actually send the message to 526 * the device and receive the response. 527 */ 528 void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) 529 { 530 int need_auto_sense; 531 int result; 532 533 /* send the command to the transport layer */ 534 srb->resid = 0; 535 result = us->transport(srb, us); 536
- Page 93 and 94: Type: Direct-Access ANSI SCSI revis
- Page 95 and 96: 416 /* 417 * this defines our host
- Page 97 and 98: 69 * Ioctl interface 70 * 71 * Stat
- Page 99 and 100: 155 * "is this a new device" checks
- Page 101 and 102: 241 char *proc_name; 242 243 /* 244
- Page 103 and 104: 328 * True if the low-level driver
- Page 105 and 106: 可以看到这个函数的参数
- Page 107 and 108: 451 short unsigned int max_sectors;
- Page 109 and 110: 地 说明了为啥咱们要显式
- Page 111 and 112: usb_stor_acquire_resources()函数
- Page 113 and 114: 341 } 342 343 /* reject if target !
- Page 115 and 116: 内核的核心位置,kernel/exit.c
- Page 117 and 118: 1023 dissociate_dev(us); 1024 retur
- Page 119 and 120: 917 行,再次判断设备有没有
- Page 121 and 122: 181 182 /* fail the command if we a
- Page 123 and 124: 83 struct timer_list eh_timeout; /*
- Page 125 and 126: 123 两个scsi_done,一个是struct
- Page 127 and 128: 56 jiffie count on our counter, the
- Page 129 and 130: 中 看到如下的定义: UNUSUAL_
- Page 131 and 132: 269 memcpy(data+16, us->unusual_dev
- Page 133 and 134: 一切准备好了之后,我们就
- Page 135 and 136: 238 (sg->offset + *offset) & (PAGE_
- Page 137 and 138: 所以对于那些不能相应INQUI
- Page 139 and 140: 239 行对unsigned int sglen 赋值
- Page 141 and 142: 请求,所以这里就判断abort
- Page 143: 112 case GPCMD_READ_HEADER: what =
- Page 147 and 148: 580 /* 581 * If we have a failure,
- Page 149 and 150: 666 memcpy(srb->cmnd, old_cmnd, MAX
- Page 151 and 152: 950 struct bulk_cb_wrap *bcb = (str
- Page 153 and 154: 1034 /* get the status again */ 103
- Page 155 and 156: 426 /* store the actual length of t
- Page 157 and 158: 后她会给host 返回一个CSW.CB
- Page 159 and 160: 296 } 297 298 US_DEBUGP("-- transfe
- Page 161 and 162: 491 * scatter-gather or not, and ac
- Page 163 and 164: 迷雾重重的 Bulk 传输(五) us
- Page 165 and 166: 然后把她赋给了result.而us->
- Page 167 and 168: 而bcs->Status,标志命令执行
- Page 169 and 170: 就必须设置US_FL_IGNORE_RESIDUE
- Page 171 and 172: 485 }; 486 这是一个字符数组
- Page 173 and 174: srb->sense_buffer 里边的东西.S
- Page 175 and 176: 一个类似的函数,名叫usb_sto
- Page 177 and 178: 这种命令应该由mid level 来
- Page 179 and 180: Disk /dev/sda: 146.1 GB, 1461631057
- Page 181 and 182: through to the most significant bit
- Page 183 and 184: 1192 USB_TYPE_CLASS | USB_RECIP_INT
- Page 185 and 186: 315 行,scsi_report_device_reset(),
- Page 187 and 188: 285 US_DEBUGP("No reset during disc
- Page 189 and 190: 229 /* Wait for the aborted command
- Page 191 and 192: 两个函数中需要判断它,一
- Page 193 and 194: associate_dev()相对应.我们来
154 for (i = 0; i < srb->cmd_len && i < 16; i++)<br />
155 US_DEBUGPX(" %02x", srb->cmnd[i]);<br />
156 US_DEBUGPX("\n");<br />
157 }<br />
相信即使是天下无贼里边的傻根也能看懂这个函数,很简单,就是把要执行的scsi 命令打印出来.列出这<br />
个函数没别的意思,让不熟悉scsi 的同志们知道基本上会遇到些啥命令.显然,刚才说的那个INQUIRY 也<br />
包<br />
含在其中的.<br />
不过别看这个函数很easy,你要是不熟悉scsi 协议的话,你还真的解释不了这个函数.比如你说<br />
srb->cmnd[]这个数组到底是什么内容?有什么格式?为啥函数一开始只判断cmnd[0]?实不相瞒,这里边<br />
还真有学问.首先,在scsi 的规范里边定义了一些命令,每个命令都有一定的格式,命令的字节数也有好几<br />
种,<br />
有的命令是六个字节的,有的命令是10 个字节的,有的命令是12 个字节的.你看,你看,下面就是摘自scsi<br />
规范里边的几张图,scsi 命令就该是这个样子.<br />
这是6 字节的,<br />
143<br />
这是10 个字节的,<br />
这是12 个字节的.<br />
之所以有这好几种命令描述块,没什么特别的,也许只是想体现生物的多样性而已,又或许,印证了张爱<br />
玲的那句话,也许每一个男子全都有过这样的两个女人,至少两个.娶了红玫瑰,久而久之,红的变成了墙上的<br />
一抹蚊子血,白的还是”窗前明月光”;娶了白玫瑰,白的便是衣服上的一粒饭粘子,红的却是心口上的一颗朱<br />
砂痣.<br />
江湖中人们把这样几个字节的命令称之为CDB, command descriptor block, 命令描述符块.而我<br />
们为CDB 准备了一个字符数组,结构体struct scsi_cmnd 中的unsigned char cmnd[16],你说最大就<br />
12 个字节,干嘛不申请一个12 个字节的数组?给你一个建议:我记得复旦并没有一门课程叫做可持续性发<br />
144<br />
展,但是我记得我上海交大的同学有修过这样一门课程,有机会的话,去交大听一下吧.<br />
Ok,既然这个CDB 有16 个字节,那么为什么我们每次都判断cmnd[0]就够了?仔细看这三幅图,注意<br />
到那个Operation code 了吗?没错,三幅图中的第一个字节都被称为Operation code,换言之,不管你是<br />
什么样子的命令, 你都必须在第一个字节里签上自己的名字, 向世人说明你是谁. 于是在<br />
include/scsi/scsi.h 中,定义了好多好多宏,比如#define INQUIRY 0x12,又比如#define READ_6<br />
0x08,再比如#define FORMAT_UNIT 0x04,够了,实际上操作码就相当于scsi 命令的序列号,scsi 命令<br />
总共也就那么多,8 位的操作码已经足够表示了,因此,我们只要用一个字节就可以判断出这是哪个命令了.<br />
因为你的第一个字节就相当于你的眼睛,不管你埋藏的多深,你会发现最终总是你的眼睛背叛了你的心,这一<br />
点郑中基大概感受颇深吧.<br />
好了,命令说完了,开始进入真正处理命令的部分了.<br />
迷雾重重的 bulk 传输(一)<br />
2006 年的最后一个星期,来到了北京,开始了北漂的生活.和上海不同的是,在这里待了三个月之后,发现<br />
竟然没有下过一次雨,难怪日本小孩说:”你们北京小孩真幸福,城外就是大沙漠,出了城就可以骑骆驼看日落<br />
了.”不过,今天下雨了,下了大雨,好大好大,一阵阵的闪电,回家的时候下半身都湿了…(天哪,怎么写着写着<br />
又往那个方向走去了…算了,我承认我只是一个用下半身思考的男青年.)<br />
很累,但是听着北京不眠夜,又不想入睡,听着刘杨的声音,心里感到特别温暖,这些年里,从长沙,到上海,再