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个我晕的对白才能表达我们此刻的心情吧.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值