针对 I/O 控制器的常见错误定义了一组标准的设备 ereport。只要检测到本节中所述的错误症状之一,便应生成这些 ereport。
本节中所述的 ereport 将分发给 eft 诊断引擎以进行诊断,eft 诊断引擎使用一组常用的标准规则来诊断这些 ereport。设备驱动程序检测的其他任何错误都必须在 Sun 事件注册表中定义为 ereport 事件,并必须伴有特定于设备的诊断软件或 eft 规则。
驱动程序已检测到设备处于无效状态。
当驱动程序检测到所传送或接收的数据看起来无效时,该驱动程序应发布错误。例如,在 bge 代码中,当 bge_chip_reset() 和 bge_receive_ring() 例程检测到无效数据时,这些例程将生成 ereport.io.device.inval_state 错误。
/*
* The SEND INDEX registers should be reset to zero by the
* global chip reset; if they're not, there'll be trouble
* later on.
*/
sx0 = bge_reg_get32(bgep, NIC_DIAG_SEND_INDEX_REG(0));
if (sx0 != 0) {
BGE_REPORT((bgep, "SEND INDEX - device didn't RESET"));
bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
return (DDI_FAILURE);
}
/* ... */
/*
* Sync (all) the receive ring descriptors
* before accepting the packets they describe
*/
DMA_SYNC(rrp->desc, DDI_DMA_SYNC_FORKERNEL);
if (*rrp->prod_index_p >= rrp->desc.nslots) {
bgep->bge_chip_state = BGE_CHIP_ERROR;
bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
return (NULL);
}
设备已报告自我纠正的内部错误。例如,设备的内部缓冲区中的硬件已检测到可纠正的 ECC 错误。
bge 驱动程序中未使用此错误标志。有关使用此错误的示例,请参见 OpenSolaris 中的 nxge_fm.c 文件。执行以下步骤来研究 nxge 驱动程序代码:
转到 OpenSolaris。
单击页面右上角的 "Source Browser"(源代码浏览器)。
在 "File Path"(文件路径)字段中输入 nxge。
单击 "Search"(搜索)按钮。
设备已报告无法纠正的内部错误。例如,设备的内部缓冲区中的硬件已检测到不可纠正的 ECC 错误。
bge 驱动程序中未使用此错误标志。有关使用此错误的示例,请参见 OpenSolaris 中的 nxge_fm.c 文件。
驱动程序检测到数据传输已意外停顿。
bge_factotum_stall_check() 例程提供了停顿检测的示例。
dogval = bge_atomic_shl32(&bgep->watchdog, 1);
if (dogval < bge_watchdog_count)
return (B_FALSE);
BGE_REPORT((bgep, "Tx stall detected,
watchdog code 0x%x", dogval));
bge_fm_ereport(bgep, DDI_FM_DEVICE_STALL);
return (B_TRUE);
设备未对驱动程序命令进行响应。
bge_chip_poll_engine(bge_t *bgep, bge_regno_t regno,
uint32_t mask, uint32_t val)
{
uint32_t regval;
uint32_t n;
for (n = 200; n; --n) {
regval = bge_reg_get32(bgep, regno);
if ((regval & mask) == val)
return (B_TRUE);
drv_usecwait(100);
}
bge_fm_ereport(bgep, DDI_FM_DEVICE_NO_RESPONSE);
return (B_FALSE);
}
设备引发了过多的连续性无效中断。
bge() 驱动程序内的 bge_intr 例程提供了有问题的中断检测的示例。bge_fm_ereport() 函数是 ddi_fm_ereport_post(9F) 函数的包装。请参见对错误事件排队中的 bge_fm_ereport() 示例。
if (bgep->missed_dmas >= bge_dma_miss_limit) {
/*
* If this happens multiple times in a row,
* it means DMA is just not working. Maybe
* the chip has failed, or maybe there's a
* problem on the PCI bus or in the host-PCI
* bridge (Tomatillo).
*
* At all events, we want to stop further
* interrupts and let the recovery code take
* over to see whether anything can be done
* about it ...
*/
bge_fm_ereport(bgep,
DDI_FM_DEVICE_BADINT_LIMIT);
goto chip_stop;
}