编写设备驱动程序

probe() 入口点(SCSI 目标驱动程序)

SCSI 目标设备不是自标识设备,因此目标驱动程序必须具有 probe(9E) 例程。该例程必须确定所需类型的设备是否存在以及是否正在响应。

probe(9E) 例程的常规结构和返回代码与其他设备驱动程序的结构和返回代码相同。SCSI 目标驱动程序必须在其 probe(9E) 入口点中使用 scsi_probe(9F) 例程。scsi_probe(9F) 向设备发送 SCSI 查询命令并返回指示结果的代码。如果 SCSI 查询命令成功,则 scsi_probe(9F) 将分配 scsi_inquiry(9S) 结构并使用设备的查询数据填充该结构。从 scsi_probe(9F) 返回之后,scsi_device(9S) 结构的 sd_inq 字段将指向此 scsi_inquiry(9S) 结构。

由于 probe(9E) 必须是无状态的,因此目标驱动程序必须在 probe(9E) 返回之前调用 scsi_unprobe(9F),即使 scsi_probe(9F) 失败也是如此。

示例 17–1 显示了典型的 probe(9E) 例程。该示例中的例程从其 dev_info 结构的专用字段中检索 scsi_device(9S) 结构。该例程还检索设备的 SCSI 目标和逻辑单元号,以便列显在消息中。然后,probe(9E) 例程将调用 scsi_probe(9F) 以验证预期设备(在本例中为打印机)是否存在。

如果成功,scsi_probe(9F) 会将 scsi_inquiry(9S) 结构中设备的 SCSI 查询数据连接到 scsi_device(9S) 结构的 sd_inq 字段。然后,驱动程序便可以确定设备类型是否为打印机,相关情况将在 inq_dtype 字段中报告。如果设备是打印机,则使用 scsi_log(9F) 报告类型,并使用 scsi_dname(9F) 将设备类型转换为字符串。


示例 17–1 SCSI 目标驱动程序 probe(9E) 例程

static int
xxprobe(dev_info_t *dip)
{
    struct scsi_device *sdp;
    int rval, target, lun;
    /*
     * Get a pointer to the scsi_device(9S) structure
     */
    sdp = (struct scsi_device *)ddi_get_driver_private(dip);

    target = sdp->sd_address.a_target;
    lun = sdp->sd_address.a_lun;
    /*
     * Call scsi_probe(9F) to send the Inquiry command. It will
     * fill in the sd_inq field of the scsi_device structure.
     */
    switch (scsi_probe(sdp, NULL_FUNC)) {
    case SCSIPROBE_FAILURE:
    case SCSIPROBE_NORESP:
    case SCSIPROBE_NOMEM:
       /*
        * In these cases, device might be powered off,
        * in which case we might be able to successfully
        * probe it at some future time - referred to
        * as `deferred attach'.
        */
        rval = DDI_PROBE_PARTIAL;
        break;
    case SCSIPROBE_NONCCS:
    default:
        /*
         * Device isn't of the type we can deal with,
         * and/or it will never be usable.
         */
        rval = DDI_PROBE_FAILURE;
        break;
    case SCSIPROBE_EXISTS:
        /*
         * There is a device at the target/lun address. Check
         * inq_dtype to make sure that it is the right device
         * type. See scsi_inquiry(9S)for possible device types.
         */
        switch (sdp->sd_inq->inq_dtype) {
        case DTYPE_PRINTER:
        scsi_log(sdp, "xx", SCSI_DEBUG,
           "found %s device at target%d, lun%d\n",
            scsi_dname((int)sdp->sd_inq->inq_dtype),
            target, lun);
        rval = DDI_PROBE_SUCCESS;
        break;
        case DTYPE_NOTPRESENT:
        default:
        rval = DDI_PROBE_FAILURE;
        break;     
        }    
    }
    scsi_unprobe(sdp);
    return (rval);
}

更全面的 probe(9E) 例程可以检查 scsi_inquiry(9S) 以确保设备是特定驱动程序期望的类型。