1.LLDD -> SAS传输层 -> SCSI层
1).LLDD实例化一个scsi host,然后在系统中声明存在,以后发给该LLDD的I/O就经过scsi host,
scsi host又调用LLDD在实例化scsi host时指定的传输层的函数实现I/O。
因此所有需要实例化scsi host的LLDD需要提供一个struct scsi_transport_template的结构体变量,将该变量赋值给scsi host的成员transportt。
2).而该struct scsi_transport_template结构体的变量一般不是由LLDD来定义的,都是通过调用LLDD上面一层的传输层(SAS传输层,FC传输层,iscsi传输层...)的函数返回的,
如调用SAS传输层的sas_attach_transport函数,就会返回该struct scsi_transport_template结构体的变量。
3).不过调用sas_attach_transport函数需要的参数是一个struct sas_function_template结构体的变量,因此LLDD直接调用sas_attach_transport函数的就需要定义一个
struct sas_function_template结构体的变量,这个变量就是LLDD同SAS传输层直接的接口,SAS传输层返回给LLDD的那个给scsi host的struct scsi_transport_template结构体的变量
中的函数的实现内容,也是依赖于LLDD提供给SAS传输层的这个接口的。
实质上,都是上层使用下层提供的可调用的接口,实现本层的一系列函数,然后再从一系列函数中取重要的一部分,实现一个对上层提供服务的接口。
软件分层的实现方法就是调用下层提供的接口,向上层提供服务接口。软件分层的意义就在于代码的复用。
2.增加的LIBSAS层:LLDD -> LIBSAS层 -> SAS传输层 -> SCSI层
1).LIBSAS层介于SAS传输层和LLDD之间,它需要LLDD提供的调用接口:static struct sas_domain_function_template。
2).LIBSAS层向SAS传输层提供的服务接口:struct sas_function_template。
3).因此当LLDD使用LIBSAS层的时候,要定义一个struct sas_function_template结构体的变量,把它注册到LIBSAS层,
LIBSAS层将它定义的struct sas_function_template sft注册到SAS传输层,然后SAS传输层返回提供给SCSI层的struct scsi_transport_template结构体的变量,
LIBSAS层将该提供给SCSI层的结构体变量返回给LLDD,LLDD用该结构体变量实例化scsi host,完成在SCSI层的注册。
4)LLDD也可以不使用LIBSAS层而直接同SAS传输层沟通,那就需要自己实现SAS协议相关的代码,然后实现SAS传输层需要的调用接口。
mptsas驱动就是没有使用libsas层,直接同sas transport层沟通工作的。
5).LIBSAS层存在的意义就是为一些可以利用它的LLDD提供代码复用。