`
dato0123
  • 浏览: 916838 次
文章分类
社区版块
存档分类
最新评论

Linux那些事儿之我是U盘(31)谁是最变态的结构体?

 
阅读更多

scsi子系统里的设备使用scsi命令来通信,scsi spec定义了一大堆的命令,spec里称这个为命令集,即所谓的command set.其中一些命令是每一个scsi设备都必须支持的,另一些命令则是可选的.而作为U,它所支持的是scsi transparent command set,所以它基本上就是支持所有的scsi命令了,不过我们其实并不关心任何一个具体的命令,只需要了解一些最基本的命令就是了.比如我们需要知道,所有的scsi设备都至少需要支持以下这四个scsi命令:INQUIRY,REQUEST SENSE,SEND DIAGNOSTIC,TEST UNIT READY.一会我们在代码中会遇见其中的几个,暂且不表.另外对于磁盘设备,它还需要支持另外一些命令,比如读方面的READ命令,写方面的WRITE命令,又比如我们经常做的格式化操作,它就对应FORMAT UNIT命令.对于磁盘这样的设备,SCSI协议里边称它为direct-access devices.这就是为什么你刚才在cat /proc/scsi/scsi的输出中能看到一个”Type:Direct-Access”这么一项.

知道了scsi总线上使用scsi命令来通信,那么我们下一步需要知道scsi host的作用,它主要就是负责发送命令给设备,然后设备就去执行命令.所以scsi host也被称为initiator(发起者),scsi设备被称为target(目的地).

那么我们就知道,如果我们没有scsi host,但是我们有遵守scsi协议接受scsi命令的device,那怎么办?谁来发起命令?没有硬件我们用软件,命令是谁传递过来的?应用层?或者scsi core?不管是谁,只要我们能够把上层的命令传递给设备,那就Ok了对不对?scsi核心层把一切都做好了,我们只要为一个scsi host申请相应的数据结构,让命令来了能够发送给设备,能够让设备接收到命令,那就万事大吉了对不对?或者说整个usb-storage的真正的功能也就实现了对不对?到这里我们就可以开始继续来看我们的代码了.别忘了我们还在usb_stor_acquire_resources()函数中,只不过刚刚讲完usb_stor_Bulk_max_lun()函数而已.

781,us->unusual_dev->initFunction是什么?不要说你一点印象也没有.在分析unusual_devs.h文件的时候曾经专门举过例子的,说有些设备需要一些初始化函数,它就定义在unusual_devs.h文件中,而我们通过UNUSUAL_DEV的定义已经把这些初始化函数给赋给了us->unusual_devinitFunction指针了.所以这时候,在传输开始之前,我们判断,是不是有这样一个函数,即这个函数指针是否为空,如果不为空,很好办,执行这个函数就是了.比如当时我们举例子的时候说的那两个惠普的CD刻录机就有个初始化函数init_8200e,那么就让它执行好了.当然,一般的设备肯定不需要这么一个函数.至于传递给这个函数的参数,struct us_unusual_dev结构体定义的时候,就把这个函数需要什么样的参数定义好了,需要的就是一个struct us_data *,那么很自然,传递的就是us.

然后790,scsi_host_alloc就是scsi子系统提供的函数,它的作用就是申请一个scsi host相应的数据结构.不过我们要注意的是它的参数,尤其是第一个参数, &usb_stor_host_template,其实这是一个struct scsi_host_template的结构体指针,从这一刻开始,我们需要开始了解drivers/usb/storage/scsiglue.c这个文件了,glue就是胶水的意思,scsi相关联的代码我们就都准备在这个文件里了.

usb_stor_host_template的定义就在drivers/usb/storage/scsiglue.c,

416 /*
417 * this defines our host template, with which we'll allocate hosts
418 */
419
420 struct scsi_host_template usb_stor_host_template = {
421 /* basic userland interface stuff */
422 .name = "usb-storage",
423 .proc_name = "usb-storage",
424 .proc_info = proc_info,
425 .info = host_info,
426
427 /* command interface -- queued only */
428 .queuecommand = queuecommand,
429
430 /* error and abort handlers */
431 .eh_abort_handler = command_abort,
432 .eh_device_reset_handler = device_reset,
433 .eh_bus_reset_handler = bus_reset,
434
435 /* queue commands only, only one command per LUN */
436 .can_queue = 1,
437 .cmd_per_lun = 1,
438
439 /* unknown initiator id */
440 .this_id = -1,
441
442 .slave_alloc = slave_alloc,
443 .slave_configure = slave_configure,
444
445 /* lots of sg segments can be handled */
446 .sg_tablesize = SG_ALL,
447
448 /* limit the total size of a transfer to 120 KB */
449 .max_sectors = 240,
450
451 /* merge commands... this seems to help performance, but
452 * periodically someone should test to see which setting is more
453 * optimal.
454 */
455 .use_clustering = 1,
456
456
457 /* emulated HBA */
458 .emulated = 1,
459
460 /* we do our own delay after a device or bus reset */
461 .skip_settle_delay = 1,
462
463 /* sysfs device attributes */
464 .sdev_attrs = sysfs_device_attr_list,
465
466 /* module management */
467 .module = THIS_MODULE
468 };

如果您觉得眼前这个结构体变量的定义或者说初始化很复杂,那么您错了.因为下面您将看到一个更变态的数据结构的定义,她就是传说中的struct scsi_host_template,她是scsi子系统定义的结构体,来自include/scsi/scsi_host.h文件:

40 struct scsi_host_template {
41 struct module *module;
42 const char *name;
43
44 /*
45 * Used to initialize old-style drivers. For new-style drivers
46 * just perform all work in your module initialization function.
47 *
48 * Status: OBSOLETE
49 */
50 int (* detect)(struct scsi_host_template *);
51
52 /*
53 * Used as unload callback for hosts with old-style drivers.
54 *
55 * Status: OBSOLETE
56 */
57 int (* release)(struct Scsi_Host *);
58
59 /*
60 * The info function will return whatever useful information the
61 * developer sees fit. If not provided, then the name field will
62 * be used instead.
63 *
64 * Status: OPTIONAL
65 */
66 const char *(* info)(struct Scsi_Host *);
67
68 /*
69 * Ioctl interface
70 *
71 * Status: OPTIONAL
72 */
73 int (* ioctl)(struct scsi_device *dev, int cmd, void __user *arg);
74
75 /*
76 * The queuecommand function is used to queue up a scsi
77 * command block to the LLDD. When the driver finished
78 * processing the command the done callback is invoked.
79 *
80 * If queuecommand returns 0, then the HBA has accepted the
81 * command. The done() function must be called on the command
82 * when the driver has finished with it. (you may call done on the
83 * command before queuecommand returns, but in this case you
84 * *must* return 0 from queuecommand).
85 *
86 * Queuecommand may also reject the command, in which case it may
87 * not touch the command and must not call done() for it.
88 *
89 * There are two possible rejection returns:
90 *
91 * SCSI_MLQUEUE_DEVICE_BUSY: Block this device temporarily, but
92 * allow commands to other devices serviced by this host.
93 *
94 * SCSI_MLQUEUE_HOST_BUSY: Block all devices served by this
95 * host temporarily.
96 *
97 * For compatibility, any other non-zero return is treated the
98 * same as SCSI_MLQUEUE_HOST_BUSY.
99 *
100 * NOTE: "temporarily" means either until the next command for#
101 * this device/host completes, or a period of time determined by
102 * I/O pressure in the system if there are no other outstanding
103 * commands.
104 *
105 * STATUS: REQUIRED
106 */
107 int (* queuecommand)(struct scsi_cmnd *,
108 void (*done)(struct scsi_cmnd *));
109
110 /*
111 * This is an error handling strategy routine. You don't need to
112 * define one of these if you don't want to - there is a default
113 * routine that is present that should work in most cases. For those
114 * driver authors that have the inclination and ability to write their
115 * own strategy routine, this is where it is specified. Note - the
116 * strategy routine is *ALWAYS* run in the context of the kernel eh
117 * thread. Thus you are guaranteed to *NOT* be in an interrupt
118 * handler when you execute this, and you are also guaranteed to
119 * *NOT* have any other commands being queued while you are in the
120 * strategy routine. When you return from this function, operations
121 * return to normal.
122 *
123 * See scsi_error.c scsi_unjam_host for additional comments about
124 * what this function should and should not be attempting to do.
125 *
126 * Status: REQUIRED (at least one of them)
127 */
128 int (* eh_strategy_handler)(struct Scsi_Host *);
129 int (* eh_abort_handler)(struct scsi_cmnd *);
130 int (* eh_device_reset_handler)(struct scsi_cmnd *);
131 int (* eh_bus_reset_handler)(struct scsi_cmnd *);
132 int (* eh_host_reset_handler)(struct scsi_cmnd *);
133
134 /*
135 * This is an optional routine to notify the host that the scsi
136 * timer just fired. The returns tell the timer routine what to
137 * do about this:
138 *
139 * EH_HANDLED: I fixed the error, please complete the command
140 * EH_RESET_TIMER: I need more time, reset the timer and
141 * begin counting again
142 * EH_NOT_HANDLED Begin normal error recovery
143 *
144 * Status: OPTIONAL
145 */
146 enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
147
148 /*
149 * Before the mid layer attempts to scan for a new device where none
150 * currently exists, it will call this entry in your driver. Should
151 * your driver need to allocate any structs or perform any other init
152 * items in order to send commands to a currently unused target/lun
153 * combo, then this is where you can perform those allocations. This
154 * is specifically so that drivers won't have to perform any kind of
155 * "is this a new device" checks in their queuecommand routine,
156 * thereby making the hot path a bit quicker.
157 *
158 * Return values: 0 on success, non-0 on failure
159 *
160 * Deallocation: If we didn't find any devices at this ID, you will
161 * get an immediate call to slave_destroy(). If we find something
162 * here then you will get a call to slave_configure(), then the
163 * device will be used for however long it is kept around, then when
164 * the device is removed from the system (or * possibly at reboot
165 * time), you will then get a call to slave_destroy(). This is
166 * assuming you implement slave_configure and slave_destroy.
167 * However, if you allocate memory and hang it off the device struct,
168 * then you must implement the slave_destroy() routine at a minimum
169 * in order to avoid leaking memory
170 * each time a device is tore down.
171 *
172 * Status: OPTIONAL
173 */
174 int (* slave_alloc)(struct scsi_device *);
175
176 /*
177 * Once the device has responded to an INQUIRY and we know the
178 * device is online, we call into the low level driver with the
179 * struct scsi_device *. If the low level device driver implements
180 * this function, it *must* perform the task of setting the queue
181 * depth on the device. All other tasks are optional and depend
182 * on what the driver supports and various implementation details.
183 *
184 * Things currently recommended to be handled at this time include:
185 *
186 * 1. Setting the device queue depth. Proper setting of this is
187 * described in the comments for scsi_adjust_queue_depth.
188 * 2. Determining if the device supports the various synchronous
189 * negotiation protocols. The device struct will already have
190 * responded to INQUIRY and the results of the standard items
191 * will have been shoved into the various device flag bits, eg.
192 * device->sdtr will be true if the device supports SDTR messages.
193 * 3. Allocating command structs that the device will need.
194 * 4. Setting the default timeout on this device (if needed).
195 * 5. Anything else the low level driver might want to do on a device
196 * specific setup basis...
197 * 6. Return 0 on success, non-0 on error. The device will be marked
198 * as offline on error so that no access will occur. If you return
199 * non-0, your slave_destroy routine will never get called for this
200 * device, so don't leave any loose memory hanging around, clean
201 * up after yourself before returning non-0
202 *
203 * Status: OPTIONAL
204 */
205 int (* slave_configure)(struct scsi_device *);
206
207 /*
208 * Immediately prior to deallocating the device and after all activity
209 * has ceased the mid layer calls this point so that the low level
210 * driver may completely detach itself from the scsi device and vice
211 * versa. The low level driver is responsible for freeing any memory
212 * it allocated in the slave_alloc or slave_configure calls.
213 *
214 * Status: OPTIONAL
215 */
216 void (* slave_destroy)(struct scsi_device *);
217
218 /*
219 * This function determines the bios parameters for a given
220 * harddisk. These tend to be numbers that are made up by
221 * the host adapter. Parameters:
222 * size, device, list (heads, sectors, cylinders)
223 *
224 * Status: OPTIONAL
225 */
226 int (* bios_param)(struct scsi_device *, struct block_device *,
227 sector_t, int []);
228
229 /*
230 * Can be used to export driver statistics and other infos to the
231 * world outside the kernel ie. userspace and it also provides an
232 * interface to feed the driver with information.
233 *
234 * Status: OBSOLETE
235 */
236 int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
237
238 /*
239 * Name of proc directory
240 */
241 char *proc_name;
242
243 /*
244 * Used to store the procfs directory if a driver implements the
245 * proc_info method.
246 */
247 struct proc_dir_entry *proc_dir;
248
249 /*
250 * This determines if we will use a non-interrupt driven
251 * or an interrupt driven scheme, It is set to the maximum number
252 * of simultaneous commands a given host adapter will accept.
253 */
254 int can_queue;
255
256 /*
257 * In many instances, especially where disconnect / reconnect are
258 * supported, our host also has an ID on the SCSI bus. If this is
259 * the case, then it must be reserved. Please set this_id to -1 if
260 * your setup is in single initiator mode, and the host lacks an
261 * ID.
262 */
263 int this_id;
264
265 /*
266 * This determines the degree to which the host adapter is capable
267 * of scatter-gather.
268 */
269 unsigned short sg_tablesize;
270
271 /*
272 * If the host adapter has limitations beside segment count
273 */
274 unsigned short max_sectors;
275
276 /*
277 * dma scatter gather segment boundary limit. a segment crossing this
278 * boundary will be split in two.
279 */
280 unsigned long dma_boundary;
281
282 /*
283 * This specifies "machine infinity" for host templates which don't
284 * limit the transfer size. Note this limit represents an absolute
285 * maximum, and may be over the transfer limits allowed for
286 * individual devices (e.g. 256 for SCSI-1)
287 */
288 #define SCSI_DEFAULT_MAX_SECTORS 1024
289
290 /*
291 * True if this host adapter can make good use of linked commands.
292 * This will allow more than one command to be queued to a given
293 * unit on a given host. Set this to the maximum number of command
294 * blocks to be provided for each device. Set this to 1 for one
295 * command block per lun, 2 for two, etc. Do not set this to 0.
296 * You should make sure that the host adapter will do the right thing
297 * before you try setting this above 1.
298 */
299 short cmd_per_lun;
300
301 /*
302 * present contains counter indicating how many boards of this
303 * type were found when we did the scan.
304 */
305 unsigned char present;
306
307 /*
308 * true if this host adapter uses unchecked DMA onto an ISA bus.
309 */
310 unsigned unchecked_isa_dma:1;
311
312 /*
313 * true if this host adapter can make good use of clustering.
314 * I originally thought that if the tablesize was large that it
315 * was a waste of CPU cycles to prepare a cluster list, but
316 * it works out that the Buslogic is faster if you use a smaller
317 * number of segments (i.e. use clustering). I guess it is
318 * inefficient.
319 */
320 unsigned use_clustering:1;
321
322 /*
323 * True for emulated SCSI host adapters (e.g. ATAPI)
324 */
325 unsigned emulated:1;
326
327 /*
328 * True if the low-level driver performs its own reset-settle delays.
329 */
330 unsigned skip_settle_delay:1;
331
332 /*
333 * Countdown for host blocking with no commands outstanding
334 */
335 unsigned int max_host_blocked;
336
337 /*
338 * Default value for the blocking. If the queue is empty,
339 * host_blocked counts down in the request_fn until it restarts
340 * host operations as zero is reached.
341 *
342 * FIXME: This should probably be a value in the template
343 */
344 #define SCSI_DEFAULT_HOST_BLOCKED 7
345
346 /*
347 * Pointer to the sysfs class properties for this host, NULL terminated.
348 */
349 struct class_device_attribute **shost_attrs;
350
351 /*
352 * Pointer to the SCSI device properties for this host, NULL terminated.
353 */
354 struct device_attribute **sdev_attrs;
355
356 /*
357 * List of hosts per template.
358 *
359 * This is only for use by scsi_module.c for legacy templates.
360 * For these access to it is synchronized implicitly by
361 * module_init/module_exit.
362 */
363 struct list_head legacy_hosts;
364 };
简直难以置信,一个结构体的定义加上注释从第40行到第364,写代码的同志辛苦了,定义出这么一个变态的数据结构来,咱们有理由相信写代码的那位或者那些人有很多是单身,因为那句"不在寂寞中恋爱,就在寂寞中变态"在他们身上体现的淋漓尽致.但是没办法,咱们还得继续讲,时光的背影如此悠悠,往日的岁月又上心头,此时不讲更待何时呢?您若是还没明白什么是温柔,还想好好感受雪花绽放的气候,那您就先歇会吧,咱们先往下走了.其他也不想说什么了,从这个结构体的名称,scsi_host_template来看,也基本知道,她是一种模版,很多情况都会被用到.她有很多元素,不过咱们mass storage里边定义的变量usb_stor_host_template并没有初始化所有的元素,只是初始化了其中一部分.实际上,scsi_host_template正如其名字一样,代表的是scsi host,通俗一点说,一个scsi,或者专业一点说scsi适配器,或者更专业的scsi主机适配器,或者scsi主机控制器,scsi卡可以有多个,而在Linux,每一个scsi卡对应一个数据结构,Scsi_Host(Linux中将通过使用一个scsi_host_template结构指针为参数的函数来为Scsi_Host初始化),但是有些Scsi_Host对应的并非是真实的scsi,硬件上并不存在,但仍然需要一个Scsi_Host,比如咱们的u,因为她得被模拟成scsi设备,所以得为她准备一个scsi,虚拟的scsi.回忆刚才cat /proc/scsi/scsi的输出,U盘的情况,显示的scsi信息多了最后这么一段,而其次呢,Host号也多了一个,原来Host只有scsi0,scsi1,而现在多出来一个scsi3.而这个scsi3其实就是一个虚拟的scsi.所以,为了创建这么一个虚拟的scsi卡的数据结构,咱们在drivers/usb/storage/scsiglue.c中定义了结构体变量struct scsi_host_template usb_stor_host_template.

实际上Scsi_Host也是一个变态的数据结构,咱们将在下节结合刚才提到的函数scsi_host_alloc来讲解这些变态的数据结构.晕了吧,没办法,在这么多复杂的数据结构面前,也许只有琼瑶阿姨最近给<<又见一帘幽梦>>中的设计的那段经典的连续13个我晕的对白才能表达我们此刻的心情吧.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics