From nobody Thu Apr 30 09:18:12 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4g5pVs2q2wz6bRdt for ; Thu, 30 Apr 2026 09:18:13 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4g5pVs0S0pz45h4 for ; Thu, 30 Apr 2026 09:18:13 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777540693; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ncXjZLwam4Hbrq1g76x51+sqbN82K/3DZ10jyWtflL8=; b=ApTsWD2nI6EUh7MeY6KDS0lUTbu4UR7GWfTNYSqzshEeCocOlk4SbXS9UEyx+dU+MjwCoY YH8BGD+lLpkWQV949FhsYsxaxD2RgHYePl45nUwcVU2END/TGkYZo2Nj4yaleXV5Du66T0 9m+w0voaks48WShZargQn7sisv3YC36yMIwDvC0XAS2oEYlh92xBAEM/6f6qME6xp6lYrP q3WJRayTgfYRxyX+7Z6W5ADZurySW5uLffJ+nCqz08HjBw6D+5VDrYIlVg3T+NhvXK2jEC jZuo2CI+d4q3Kb8ZQSXh6Zd9kH8hcav8eNMUicMVpuk6DAp0erMQAkQOzKZKrw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1777540693; a=rsa-sha256; cv=none; b=cA5TCOddcAPRcjyOpEYQDQ32XrCWuQ4QHo0d1y3sbiDqDQZg3E6vHSddsS0W0fWIY6pfqT EWAXs8ENbuGjK1GZfRG0ynV4jrEq0uT5y4ptfgjWkPf6ByE6uBcV5Y9vLGecZGrZRHrjFn 5LF04obrLYQWTUKL6ROprSDeM30949EPYpQ1XCmD2lWMBKYWj03DqP3wKYys2trnIcV5nZ P7Ui7X6TJxq88HhS8w8FWZrMTdaTGlP9aaaWbpw6KlvwSwngsySEf3NuB0avKefqj0WzL1 6GYY3NxEpynFHyTqxc92KExGR4FlTip9MjXyHdKTSnnSLt2kkBjifznyiF6Gxg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1777540693; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ncXjZLwam4Hbrq1g76x51+sqbN82K/3DZ10jyWtflL8=; b=pXwKsmuF9VW0WuuA+5KMEqShkcA+pp23CKcXKk6m5gAuAuPjYdmKeip6WtCIZOkwEdZibs 595KhYm9IjFaL3Mh696wPobcn1KF6PflmDI7RRp9oPfCVYhDxSPPes1XeAjrCXrXNmHc3+ KQTWiIrwHdFfnAf0KRIa0s4EwKh7P2QqA1VHTAdeoksja+kyofUJOWHCMfZx73rxmifieg fFG/GImCjlUayVit4TVjnD23mmatXgkWpfWYn02lzM1u2nWyJnv7NIcLEvxX+1eVdaOvGb u/6pmByr6H3xCwknHrbLU6HwZn0c7gPXe2Lh14aEjDcOUT9DPjwphi91HWwacA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4g5pVr6r6mz1KD3 for ; Thu, 30 Apr 2026 09:18:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 416a2 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 30 Apr 2026 09:18:12 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Corvi=?utf-8?Q?n K=C3=B6h?=ne Subject: git: 226b37dc3ad5 - main - dev/ichsmb: disable block buffer if supported List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: corvink X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 226b37dc3ad5641c18f8542c18baea3ea641c5af Auto-Submitted: auto-generated Date: Thu, 30 Apr 2026 09:18:12 +0000 Message-Id: <69f31e54.416a2.7d72e12f@gitrepo.freebsd.org> The branch main has been updated by corvink: URL: https://cgit.FreeBSD.org/src/commit/?id=226b37dc3ad5641c18f8542c18baea3ea641c5af commit 226b37dc3ad5641c18f8542c18baea3ea641c5af Author: Corvin Köhne AuthorDate: 2026-03-30 09:33:20 +0000 Commit: Corvin Köhne CommitDate: 2026-04-30 09:15:18 +0000 dev/ichsmb: disable block buffer if supported In order to improve the efficiency of block read/write calls, Intel has introduced a block buffer. Instead of generating an interrupt after receiving/sending a single byte, the data is buffered in the block buffer. It allows the SMBus controller to generate a single interrupt for the whole transfer. At the moment, we don't support that and don't expect the SMBus controller to behave in that way. Unfortunately, BIOS code can also access the SMBus controller and may enable the block buffer. Poorly written BIOS code may also keep the block buffer enabled breaking our driver. Therefore, we should check if the device supports a block buffer and disable it for every request because we don't know if some BIOS code has reconfigured the SMBus controller in between. Reviewed by: emaste MFC after: 1 week Sponsored by: Beckhoff Automation GmbH & Co. KG Pull Request: https://github.com/freebsd/freebsd-src/pull/2161 --- sys/dev/ichsmb/ichsmb.c | 18 +++++++++++++++ sys/dev/ichsmb/ichsmb_pci.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ sys/dev/ichsmb/ichsmb_reg.h | 3 +++ sys/dev/ichsmb/ichsmb_var.h | 3 +++ 4 files changed, 78 insertions(+) diff --git a/sys/dev/ichsmb/ichsmb.c b/sys/dev/ichsmb/ichsmb.c index e40a8a8a3886..0df757d9cc0e 100644 --- a/sys/dev/ichsmb/ichsmb.c +++ b/sys/dev/ichsmb/ichsmb.c @@ -395,6 +395,15 @@ ichsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) sc->block_write = true; mtx_lock(&sc->mutex); + /* + * We don't expect the block buffer to be enabled. However, BIOS code + * might enable it and doesn't restore it at any time, so we should + * ensure it's disabled before sending an SMBus command. + */ + if (sc->features & ICHSMB_FEATURE_BLOCK_BUFFER) { + bus_write_1(sc->io_res, ICH_AUX_CNT, + bus_read_1(sc->io_res, ICH_AUX_CNT) & ~ICH_AUX_CNT_E32B); + } sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK; bus_write_1(sc->io_res, ICH_XMIT_SLVA, slave | ICH_XMIT_SLVA_WRITE); @@ -424,6 +433,15 @@ ichsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) sc->block_write = false; mtx_lock(&sc->mutex); + /* + * We don't expect the block buffer to be enabled. However, BIOS code + * might enable it and doesn't restore it at any time, so we should + * ensure it's disabled before sending an SMBus command. + */ + if (sc->features & ICHSMB_FEATURE_BLOCK_BUFFER) { + bus_write_1(sc->io_res, ICH_AUX_CNT, + bus_read_1(sc->io_res, ICH_AUX_CNT) & ~ICH_AUX_CNT_E32B); + } sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK; bus_write_1(sc->io_res, ICH_XMIT_SLVA, slave | ICH_XMIT_SLVA_READ); diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c index 7d6d94dbb4a4..af3e0f004b88 100644 --- a/sys/dev/ichsmb/ichsmb_pci.c +++ b/sys/dev/ichsmb/ichsmb_pci.c @@ -129,106 +129,153 @@ static const struct pci_device_table ichsmb_devices[] = { { PCI_DEV(PCI_VENDOR_INTEL, ID_82801CA), PCI_DESCR("Intel 82801CA (ICH3) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801DC), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801DC (ICH4) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801EB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801EB (ICH5) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801FB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801FB (ICH6) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801GB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801GB (ICH7) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801H), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801H (ICH8) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801I), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801I (ICH9) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801GB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801GB (ICH7) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801H), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801H (ICH8) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801I), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801I (ICH9) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_EP80579), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel EP80579 SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801JI), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801JI (ICH10) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801JD), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801JD (ICH10) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PCH), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel PCH SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_6300ESB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 6300ESB (ICH) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_631xESB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 631xESB/6321ESB (ESB2) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_DH89XXCC), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel DH89xxCC SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PATSBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Patsburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Cougar Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Panther Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_AVOTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Avoton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lynx Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lynx Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WCPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wildcat Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WCPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wildcat Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BAYTRAIL), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Baytrail SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BRASWELL), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Braswell SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COLETOCRK), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Coleto Creek SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WELLSBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wellsburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_SRPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Sunrise Point-H SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_SRPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Sunrise Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_DENVERTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Denverton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BROXTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Broxton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LEWISBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lewisburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LEWISBURG2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lewisburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_KABYLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Kaby Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CANNONLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Cannon Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COMETLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Comet Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COMETLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Comet Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_TIGERLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Tiger Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_TIGERLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Tiger Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ELKHARTLAKE), PCI_DESCR("Intel Elkhart Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_GEMINILAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Gemini Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CEDARFORK), PCI_DESCR("Intel Cedar Fork SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ICELAKE), PCI_DESCR("Intel Ice Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE3), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_RAPTORLAKE), PCI_DESCR("Intel Raptor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE3), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, }; @@ -288,6 +335,7 @@ ichsmb_pci_probe(device_t dev) static int ichsmb_pci_attach(device_t dev) { + const struct pci_device_table *tbl; const sc_p sc = device_get_softc(dev); int error; @@ -296,6 +344,12 @@ ichsmb_pci_attach(device_t dev) sc->ich_cmd = -1; sc->dev = dev; + tbl = PCI_MATCH(dev, ichsmb_devices); + if (tbl == NULL) + return (ENXIO); + + sc->features = (uint32_t)tbl->driver_data; + /* Allocate an I/O range */ sc->io_rid = ICH_SMB_BASE; sc->io_res = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, diff --git a/sys/dev/ichsmb/ichsmb_reg.h b/sys/dev/ichsmb/ichsmb_reg.h index 78e398a556ef..be3b9e4a899d 100644 --- a/sys/dev/ichsmb/ichsmb_reg.h +++ b/sys/dev/ichsmb/ichsmb_reg.h @@ -84,6 +84,9 @@ #define ICH_D0 0x05 /* host data 0 */ #define ICH_D1 0x06 /* host data 1 */ #define ICH_BLOCK_DB 0x07 /* block data byte */ +#define ICH_AUX_CNT 0x0d /* auxiliary control */ +#define ICH_AUX_CNT_E32B 0x02 /* enable 32 byte buffer */ +#define ICH_AUX_CNT_AAC 0x01 /* automatically append crc */ #endif /* _DEV_ICHSMB_ICHSMB_REG_H_ */ diff --git a/sys/dev/ichsmb/ichsmb_var.h b/sys/dev/ichsmb/ichsmb_var.h index 8aeaf403781b..f16a40be9777 100644 --- a/sys/dev/ichsmb/ichsmb_var.h +++ b/sys/dev/ichsmb/ichsmb_var.h @@ -41,6 +41,8 @@ #include "smbus_if.h" +#define ICHSMB_FEATURE_BLOCK_BUFFER 0x01 /* supports 32 byte block buffer */ + /* Per-device private info */ struct ichsmb_softc { @@ -52,6 +54,7 @@ struct ichsmb_softc { struct resource *irq_res; /* interrupt resource */ int irq_rid; /* interrupt bus id */ void *irq_handle; /* handle for interrupt code */ + uint32_t features; /* supported device features */ /* Device state */ int ich_cmd; /* ich command, or -1 */