编写设备驱动程序

自动请求检测模式

如果使用排队(无论是标记排队还是无标记排队),则最好使用自动请求检测模式。任何后续命令都会清除应急处理状态 (contingent allegiance condition),并因此导致检测数据丢失。大多数 HBA 驱动程序会在执行目标驱动程序回调之前开始下一条命令。其他 HBA 驱动程序可以使用单独的、较低优先级的线程执行回调。采用该方法时,如果存在检查状况,那么向目标驱动程序通知包已完成所需的时间可能会增加。在这种情况下,目标驱动程序可能无法及时提交请求检测命令以检索检测数据。

为了避免检测数据丢失,HBA 驱动程序或控制器应在检测到检查条件时发出请求检测命令。该模式称为自动请求检测模式。请注意,并非所有 HBA 驱动程序都可以使用自动请求检测模式,而某些驱动程序只能在启用了自动请求检测模式时运行。

目标驱动程序使用 scsi_ifsetcap(9F) 来启用自动请求检测模式。以下示例说明了如何启用自动请求检测。


示例 17–6 启用自动请求检测模式

static int
xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
    struct xxstate *xsp;
    struct scsi_device *sdp = (struct scsi_device *)
    ddi_get_driver_private(dip);
   /*
    * Enable auto-request-sense; an auto-request-sense cmd might
    * fail due to a BUSY condition or transport error. Therefore,
    * it is recommended to allocate a separate request sense
    * packet as well.
    * Note that scsi_ifsetcap(9F) can return -1, 0, or 1
    */
    xsp->sdp_arq_enabled =
    ((scsi_ifsetcap(ROUTE, “auto-rqsense”, 1, 1) == 1) ? 1 :
0);
   /*
    * If the HBA driver supports auto request sense then the
    * status blocks should be sizeof (struct scsi_arq_status);
    */
else
   /*
    * One byte is sufficient
    */
    xsp->sdp_cmd_stat_size =  (xsp->sdp_arq_enabled ?
    sizeof (struct scsi_arq_status) : 1);
   /* ... */
}

如果使用 scsi_init_pkt(9F) 分配了一个包并且该包需要自动请求检测,则需要增加空间。目标驱动程序必须为状态块请求此空间,以便存储自动请求检测结构。请求检测命令中使用的检测长度即 struct scsi_extended_sense 中的 sizeof。通过为状态块分配 struct scsi_status 中的 sizeof,可以针对各个包禁用自动请求检测。

可像往常一样使用 scsi_transport(9F) 提交包。当该包中出现检查条件时,主机适配器驱动程序将执行以下步骤:

目标驱动程序的回调例程应通过检查 pkt_state 中的 STATE_ARQ_DONE 位,来验证检测数据是否可用。STATE_ARQ_DONE 表明出现了检查条件,并且已执行请求检测。如果包中暂时禁用了自动请求检测,则无法保证对检测数据的后续检索。

然后,目标驱动程序应验证自动请求检测命令是否已成功完成,并对检测数据进行解码。