对于非自我识别设备,probe(9E) 入口点应确定系统上是否存在硬件设备。
对于 probe(),要确定是否存在设备实例,probe()需要执行通常 attach(9E) 也执行的许多任务。尤其是,probe() 可能需要映射设备寄存器。
探测设备寄存器是特定于设备的。驱动程序通常必须执行一系列硬件测试来确保硬件确实存在。测试条件必须足够严格以避免错误地识别设备。例如,在设备实际上不可用的情况下可能显示存在该设备,因为异常设备在行为上看起来与预期的设备相似。
测试返回以下标志:
DDI_PROBE_SUCCESS(探测成功)
DDI_PROBE_FAILURE(探测失败)
DDI_PROBE_DONTCARE(探测不成功,但仍需调用 attach(9E))
DDI_PROBE_PARTIAL(现在不存在实例,但将来可能会出现)
对于给定设备实例,直到 probe(9E) 在该设备上至少成功一次时,才会调用 attach(9E)。
probe(9E) 必须释放 probe() 已分配的所有资源,因为可能会调用 probe() 多次。但是,即使 probe(9E) 已成功,也不一定要调用 attach(9E)。
可以在驱动程序的 probe(9E) 例程中使用 ddi_dev_is_sid(9F) 来确定设备是否可以自我识别。在为同一设备的自我识别版本和非自我识别版本编写驱动程序时,ddi_dev_is_sid() 非常有用。
以下示例是一个样例 probe() 例程。
static int xxprobe(dev_info_t *dip) { ddi_acc_handle_t dev_hdl; ddi_device_acc_attr_t dev_attr; Pio_csr *csrp; uint8_t csrval; /* * if the device is self identifying, no need to probe */ if (ddi_dev_is_sid(dip) == DDI_SUCCESS) return (DDI_PROBE_DONTCARE); /* * Initalize the device access attributes and map in * the devices CSR register (register 0) */ dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; if (ddi_regs_map_setup(dip, 0, (caddr_t *)&csrp, 0, sizeof (Pio_csr), &dev_attr, &dev_hdl) != DDI_SUCCESS) return (DDI_PROBE_FAILURE); /* * Reset the device * Once the reset completes the CSR should read back * (PIO_DEV_READY | PIO_IDLE_INTR) */ ddi_put8(dev_hdl, csrp, PIO_RESET); csrval = ddi_get8(dev_hdl, csrp); /* * tear down the mappings and return probe success/failure */ ddi_regs_map_free(&dev_hdl); if ((csrval & 0xff) == (PIO_DEV_READY | PIO_IDLE_INTR)) return (DDI_PROBE_SUCCESS); else return (DDI_PROBE_FAILURE); }
调用驱动程序的 probe(9E) 例程时,驱动程序并不知道正在探测的设备是否存在于总线上。因此,驱动程序可能会尝试访问不存在设备的设备寄存器。结果,在某些总线上可能会产生总线故障。
以下示例给出了使用 ddi_poke8(9F) 来检查设备是否存在的 probe(9E) 例程。ddi_poke8() 谨慎地尝试将值写入指定的虚拟地址,必要时使用父结点驱动程序协助进程。如果地址无效或无法在不出现错误的情况下写入值,则会返回错误代码。另请参见 ddi_peek(9F)。
在本示例中,使用 ddi_regs_map_setup(9F) 来映射设备寄存器。
static int xxprobe(dev_info_t *dip) { ddi_acc_handle_t dev_hdl; ddi_device_acc_attr_t dev_attr; Pio_csr *csrp; uint8_t csrval; /* * if the device is self-identifying, no need to probe */ if (ddi_dev_is_sid(dip) == DDI_SUCCESS) return (DDI_PROBE_DONTCARE); /* * Initialize the device access attrributes and map in * the device's CSR register (register 0) */ dev_attr.devacc_attr_version - DDI_DEVICE_ATTR_V0; dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; if (ddi_regs_map_setup(dip, 0, (caddr_t *)&csrp, 0, sizeof (Pio_csr), &dev_attr, &dev_hdl) != DDI_SUCCESS) return (DDI_PROBE_FAILURE); /* * The bus can generate a fault when probing for devices that * do not exist. Use ddi_poke8(9f) to handle any faults that * might occur. * * Reset the device. Once the reset completes the CSR should read * back (PIO_DEV_READY | PIO_IDLE_INTR) */ if (ddi_poke8(dip, csrp, PIO_RESET) != DDI_SUCCESS) { ddi_regs_map_free(&dev_hdl); return (DDI_FAILURE); csrval = ddi_get8(dev_hdl, csrp); /* * tear down the mappings and return probe success/failure */ ddi_regs_map_free(&dev_hdl); if ((csrval & 0xff) == (PIO_DEV_READY | PIO_IDLE_INTR)) return (DDI_PROBE_SUCCESS); else return (DDI_PROBE_FAILURE); }