version 1.3, 2006/06/17 17:04:44 |
version 1.3.2.6, 2008/01/21 09:44:14 |
|
|
* Intel PIIX and compatible Power Management controller driver. |
* Intel PIIX and compatible Power Management controller driver. |
*/ |
*/ |
|
|
|
#include <sys/cdefs.h> |
|
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
#include <sys/device.h> |
#include <sys/device.h> |
#include <sys/kernel.h> |
#include <sys/kernel.h> |
#include <sys/lock.h> |
#include <sys/rwlock.h> |
#include <sys/proc.h> |
#include <sys/proc.h> |
|
|
#include <machine/bus.h> |
#include <sys/bus.h> |
|
|
#include <dev/pci/pcidevs.h> |
#include <dev/pci/pcidevs.h> |
#include <dev/pci/pcireg.h> |
#include <dev/pci/pcireg.h> |
|
|
|
|
#include <dev/i2c/i2cvar.h> |
#include <dev/i2c/i2cvar.h> |
|
|
|
#include <dev/ic/acpipmtimer.h> |
|
|
#ifdef PIIXPM_DEBUG |
#ifdef PIIXPM_DEBUG |
#define DPRINTF(x) printf x |
#define DPRINTF(x) printf x |
#else |
#else |
|
|
struct piixpm_softc { |
struct piixpm_softc { |
struct device sc_dev; |
struct device sc_dev; |
|
|
bus_space_tag_t sc_iot; |
bus_space_tag_t sc_smb_iot; |
bus_space_handle_t sc_ioh; |
bus_space_handle_t sc_smb_ioh; |
void * sc_ih; |
void * sc_smb_ih; |
int sc_poll; |
int sc_poll; |
|
|
|
bus_space_tag_t sc_pm_iot; |
|
bus_space_handle_t sc_pm_ioh; |
|
|
pci_chipset_tag_t sc_pc; |
pci_chipset_tag_t sc_pc; |
pcitag_t sc_pcitag; |
pcitag_t sc_pcitag; |
|
|
struct i2c_controller sc_i2c_tag; |
struct i2c_controller sc_i2c_tag; |
struct lock sc_i2c_lock; |
krwlock_t sc_i2c_rwlock; |
struct { |
struct { |
i2c_op_t op; |
i2c_op_t op; |
void * buf; |
void * buf; |
size_t len; |
size_t len; |
int flags; |
int flags; |
volatile int error; |
volatile int error; |
} sc_i2c_xfer; |
} sc_i2c_xfer; |
|
|
void * sc_powerhook; |
|
struct pci_conf_state sc_pciconf; |
|
pcireg_t sc_devact[2]; |
pcireg_t sc_devact[2]; |
}; |
}; |
|
|
int piixpm_match(struct device *, struct cfdata *, void *); |
int piixpm_match(struct device *, struct cfdata *, void *); |
void piixpm_attach(struct device *, struct device *, void *); |
void piixpm_attach(struct device *, struct device *, void *); |
|
|
void piixpm_powerhook(int, void *); |
static bool piixpm_suspend(device_t); |
|
static bool piixpm_resume(device_t); |
|
|
int piixpm_i2c_acquire_bus(void *, int); |
int piixpm_i2c_acquire_bus(void *, int); |
void piixpm_i2c_release_bus(void *, int); |
void piixpm_i2c_release_bus(void *, int); |
Line 89 CFATTACH_DECL(piixpm, sizeof(struct piix |
|
Line 96 CFATTACH_DECL(piixpm, sizeof(struct piix |
|
piixpm_match, piixpm_attach, NULL, NULL); |
piixpm_match, piixpm_attach, NULL, NULL); |
|
|
int |
int |
piixpm_match(struct device *parent, struct cfdata *match, void *aux) |
piixpm_match(struct device *parent, struct cfdata *match, |
|
void *aux) |
{ |
{ |
struct pci_attach_args *pa; |
struct pci_attach_args *pa; |
|
|
Line 105 piixpm_match(struct device *parent, stru |
|
Line 113 piixpm_match(struct device *parent, stru |
|
case PCI_VENDOR_ATI: |
case PCI_VENDOR_ATI: |
switch (PCI_PRODUCT(pa->pa_id)) { |
switch (PCI_PRODUCT(pa->pa_id)) { |
case PCI_PRODUCT_ATI_SB200_SMB: |
case PCI_PRODUCT_ATI_SB200_SMB: |
|
case PCI_PRODUCT_ATI_SB300_SMB: |
|
case PCI_PRODUCT_ATI_SB400_SMB: |
return 1; |
return 1; |
} |
} |
break; |
break; |
|
case PCI_VENDOR_SERVERWORKS: |
|
switch (PCI_PRODUCT(pa->pa_id)) { |
|
case PCI_PRODUCT_SERVERWORKS_OSB4: |
|
case PCI_PRODUCT_SERVERWORKS_CSB5: |
|
case PCI_PRODUCT_SERVERWORKS_CSB6: |
|
case PCI_PRODUCT_SERVERWORKS_HT1000SB: |
|
return 1; |
|
} |
} |
} |
|
|
return 0; |
return 0; |
Line 120 piixpm_attach(struct device *parent, str |
|
Line 138 piixpm_attach(struct device *parent, str |
|
struct pci_attach_args *pa = aux; |
struct pci_attach_args *pa = aux; |
struct i2cbus_attach_args iba; |
struct i2cbus_attach_args iba; |
pcireg_t base, conf; |
pcireg_t base, conf; |
|
pcireg_t pmmisc; |
pci_intr_handle_t ih; |
pci_intr_handle_t ih; |
|
char devinfo[256]; |
const char *intrstr = NULL; |
const char *intrstr = NULL; |
|
|
sc->sc_pc = pa->pa_pc; |
sc->sc_pc = pa->pa_pc; |
sc->sc_pcitag = pa->pa_tag; |
sc->sc_pcitag = pa->pa_tag; |
|
|
aprint_naive("\n"); |
aprint_naive("\n"); |
aprint_normal(": Power Management Controller\n"); |
|
|
|
sc->sc_powerhook = powerhook_establish(piixpm_powerhook, sc); |
pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); |
if (sc->sc_powerhook == NULL) |
aprint_normal("\n%s: %s (rev. 0x%02x)\n", |
aprint_error("%s: can't establish powerhook\n", |
device_xname(self), devinfo, PCI_REVISION(pa->pa_class)); |
sc->sc_dev.dv_xname); |
|
|
if (!pmf_device_register(self, piixpm_suspend, piixpm_resume)) |
|
aprint_error_dev(self, "couldn't establish power handler\n"); |
|
|
/* Read configuration */ |
/* Read configuration */ |
conf = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_HOSTC); |
conf = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_HOSTC); |
DPRINTF((": conf 0x%x", conf)); |
DPRINTF((": conf 0x%x", conf)); |
|
|
|
if ((PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) || |
|
(PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_82371AB_PMC)) |
|
goto nopowermanagement; |
|
|
|
/* check whether I/O access to PM regs is enabled */ |
|
pmmisc = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_PMREGMISC); |
|
if (!(pmmisc & 1)) |
|
goto nopowermanagement; |
|
|
|
sc->sc_pm_iot = pa->pa_iot; |
|
/* Map I/O space */ |
|
base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_PM_BASE); |
|
if (bus_space_map(sc->sc_pm_iot, PCI_MAPREG_IO_ADDR(base), |
|
PIIX_PM_SIZE, 0, &sc->sc_pm_ioh)) { |
|
aprint_error("%s: can't map power management I/O space\n", |
|
sc->sc_dev.dv_xname); |
|
goto nopowermanagement; |
|
} |
|
|
|
/* |
|
* Revision 0 and 1 are PIIX4, 2 is PIIX4E, 3 is PIIX4M. |
|
* PIIX4 and PIIX4E have a bug in the timer latch, see Errata #20 |
|
* in the "Specification update" (document #297738). |
|
*/ |
|
acpipmtimer_attach(&sc->sc_dev, sc->sc_pm_iot, sc->sc_pm_ioh, |
|
PIIX_PM_PMTMR, |
|
(PCI_REVISION(pa->pa_class) < 3) ? ACPIPMT_BADLATCH : 0 ); |
|
|
|
nopowermanagement: |
if ((conf & PIIX_SMB_HOSTC_HSTEN) == 0) { |
if ((conf & PIIX_SMB_HOSTC_HSTEN) == 0) { |
aprint_normal("%s: SMBus disabled\n", sc->sc_dev.dv_xname); |
aprint_normal("%s: SMBus disabled\n", sc->sc_dev.dv_xname); |
return; |
return; |
} |
} |
|
|
/* Map I/O space */ |
/* Map I/O space */ |
sc->sc_iot = pa->pa_iot; |
sc->sc_smb_iot = pa->pa_iot; |
base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_BASE) & 0xffff; |
base = pci_conf_read(pa->pa_pc, pa->pa_tag, PIIX_SMB_BASE) & 0xffff; |
if (bus_space_map(sc->sc_iot, PCI_MAPREG_IO_ADDR(base), |
if (bus_space_map(sc->sc_smb_iot, PCI_MAPREG_IO_ADDR(base), |
PIIX_SMB_SIZE, 0, &sc->sc_ioh)) { |
PIIX_SMB_SIZE, 0, &sc->sc_smb_ioh)) { |
aprint_error("%s: can't map I/O space\n", |
aprint_error("%s: can't map smbus I/O space\n", |
sc->sc_dev.dv_xname); |
sc->sc_dev.dv_xname); |
return; |
return; |
} |
} |
Line 161 piixpm_attach(struct device *parent, str |
|
Line 211 piixpm_attach(struct device *parent, str |
|
/* Install interrupt handler */ |
/* Install interrupt handler */ |
if (pci_intr_map(pa, &ih) == 0) { |
if (pci_intr_map(pa, &ih) == 0) { |
intrstr = pci_intr_string(pa->pa_pc, ih); |
intrstr = pci_intr_string(pa->pa_pc, ih); |
sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, |
sc->sc_smb_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, |
piixpm_intr, sc); |
piixpm_intr, sc); |
if (sc->sc_ih != NULL) { |
if (sc->sc_smb_ih != NULL) { |
aprint_normal("%s: interrupting at %s", |
aprint_normal("%s: interrupting at %s", |
sc->sc_dev.dv_xname, intrstr); |
sc->sc_dev.dv_xname, intrstr); |
sc->sc_poll = 0; |
sc->sc_poll = 0; |
Line 176 piixpm_attach(struct device *parent, str |
|
Line 226 piixpm_attach(struct device *parent, str |
|
aprint_normal("\n"); |
aprint_normal("\n"); |
|
|
/* Attach I2C bus */ |
/* Attach I2C bus */ |
lockinit(&sc->sc_i2c_lock, PRIBIO | PCATCH, "iiclk", 0, 0); |
rw_init(&sc->sc_i2c_rwlock); |
sc->sc_i2c_tag.ic_cookie = sc; |
sc->sc_i2c_tag.ic_cookie = sc; |
sc->sc_i2c_tag.ic_acquire_bus = piixpm_i2c_acquire_bus; |
sc->sc_i2c_tag.ic_acquire_bus = piixpm_i2c_acquire_bus; |
sc->sc_i2c_tag.ic_release_bus = piixpm_i2c_release_bus; |
sc->sc_i2c_tag.ic_release_bus = piixpm_i2c_release_bus; |
sc->sc_i2c_tag.ic_exec = piixpm_i2c_exec; |
sc->sc_i2c_tag.ic_exec = piixpm_i2c_exec; |
|
|
bzero(&iba, sizeof(iba)); |
bzero(&iba, sizeof(iba)); |
iba.iba_name = "iic"; |
|
iba.iba_tag = &sc->sc_i2c_tag; |
iba.iba_tag = &sc->sc_i2c_tag; |
config_found(self, &iba, iicbus_print); |
config_found_ia(self, "i2cbus", &iba, iicbus_print); |
|
|
return; |
return; |
} |
} |
|
|
void |
static bool |
piixpm_powerhook(int why, void *cookie) |
piixpm_suspend(device_t dv) |
{ |
{ |
struct piixpm_softc *sc = cookie; |
struct piixpm_softc *sc = device_private(dv); |
pci_chipset_tag_t pc = sc->sc_pc; |
|
pcitag_t tag = sc->sc_pcitag; |
|
|
|
switch (why) { |
sc->sc_devact[0] = pci_conf_read(sc->sc_pc, sc->sc_pcitag, |
case PWR_SUSPEND: |
PIIX_DEVACTA); |
pci_conf_capture(pc, tag, &sc->sc_pciconf); |
sc->sc_devact[1] = pci_conf_read(sc->sc_pc, sc->sc_pcitag, |
sc->sc_devact[0] = pci_conf_read(pc, tag, PIIX_DEVACTA); |
PIIX_DEVACTB); |
sc->sc_devact[1] = pci_conf_read(pc, tag, PIIX_DEVACTB); |
|
break; |
|
case PWR_RESUME: |
|
pci_conf_restore(pc, tag, &sc->sc_pciconf); |
|
pci_conf_write(pc, tag, PIIX_DEVACTA, sc->sc_devact[0]); |
|
pci_conf_write(pc, tag, PIIX_DEVACTB, sc->sc_devact[1]); |
|
break; |
|
} |
|
|
|
return; |
return true; |
|
} |
|
|
|
static bool |
|
piixpm_resume(device_t dv) |
|
{ |
|
struct piixpm_softc *sc = device_private(dv); |
|
|
|
pci_conf_write(sc->sc_pc, sc->sc_pcitag, PIIX_DEVACTA, |
|
sc->sc_devact[0]); |
|
pci_conf_write(sc->sc_pc, sc->sc_pcitag, PIIX_DEVACTB, |
|
sc->sc_devact[1]); |
|
|
|
return true; |
} |
} |
|
|
int |
int |
Line 221 piixpm_i2c_acquire_bus(void *cookie, int |
|
Line 273 piixpm_i2c_acquire_bus(void *cookie, int |
|
if (cold || sc->sc_poll || (flags & I2C_F_POLL)) |
if (cold || sc->sc_poll || (flags & I2C_F_POLL)) |
return (0); |
return (0); |
|
|
return (lockmgr(&sc->sc_i2c_lock, LK_EXCLUSIVE, NULL)); |
rw_enter(&sc->sc_i2c_rwlock, RW_WRITER); |
|
return 0; |
} |
} |
|
|
void |
void |
Line 232 piixpm_i2c_release_bus(void *cookie, int |
|
Line 285 piixpm_i2c_release_bus(void *cookie, int |
|
if (cold || sc->sc_poll || (flags & I2C_F_POLL)) |
if (cold || sc->sc_poll || (flags & I2C_F_POLL)) |
return; |
return; |
|
|
lockmgr(&sc->sc_i2c_lock, LK_RELEASE, NULL); |
rw_exit(&sc->sc_i2c_rwlock); |
} |
} |
|
|
int |
int |
Line 249 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
Line 302 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
|
|
/* Wait for bus to be idle */ |
/* Wait for bus to be idle */ |
for (retries = 100; retries > 0; retries--) { |
for (retries = 100; retries > 0; retries--) { |
st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_HS); |
st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
|
PIIX_SMB_HS); |
if (!(st & PIIX_SMB_HS_BUSY)) |
if (!(st & PIIX_SMB_HS_BUSY)) |
break; |
break; |
DELAY(PIIXPM_DELAY); |
DELAY(PIIXPM_DELAY); |
} |
} |
DPRINTF(("%s: exec: st 0x%b\n", sc->sc_dev.dv_xname, st, |
DPRINTF(("%s: exec: st 0x%d\n", sc->sc_dev.dv_xname, st & 0xff)); |
PIIX_SMB_HS_BITS)); |
|
if (st & PIIX_SMB_HS_BUSY) |
if (st & PIIX_SMB_HS_BUSY) |
return (1); |
return (1); |
|
|
Line 273 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
Line 326 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
sc->sc_i2c_xfer.error = 0; |
sc->sc_i2c_xfer.error = 0; |
|
|
/* Set slave address and transfer direction */ |
/* Set slave address and transfer direction */ |
bus_space_write_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_TXSLVA, |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_TXSLVA, |
PIIX_SMB_TXSLVA_ADDR(addr) | |
PIIX_SMB_TXSLVA_ADDR(addr) | |
(I2C_OP_READ_P(op) ? PIIX_SMB_TXSLVA_READ : 0)); |
(I2C_OP_READ_P(op) ? PIIX_SMB_TXSLVA_READ : 0)); |
|
|
b = cmdbuf; |
b = cmdbuf; |
if (cmdlen > 0) |
if (cmdlen > 0) |
/* Set command byte */ |
/* Set command byte */ |
bus_space_write_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_HCMD, b[0]); |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
|
PIIX_SMB_HCMD, b[0]); |
|
|
if (I2C_OP_WRITE_P(op)) { |
if (I2C_OP_WRITE_P(op)) { |
/* Write data */ |
/* Write data */ |
b = buf; |
b = buf; |
if (len > 0) |
if (len > 0) |
bus_space_write_1(sc->sc_iot, sc->sc_ioh, |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
PIIX_SMB_HD0, b[0]); |
PIIX_SMB_HD0, b[0]); |
if (len > 1) |
if (len > 1) |
bus_space_write_1(sc->sc_iot, sc->sc_ioh, |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
PIIX_SMB_HD1, b[1]); |
PIIX_SMB_HD1, b[1]); |
} |
} |
|
|
Line 306 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
Line 360 piixpm_i2c_exec(void *cookie, i2c_op_t o |
|
|
|
/* Start transaction */ |
/* Start transaction */ |
ctl |= PIIX_SMB_HC_START; |
ctl |= PIIX_SMB_HC_START; |
bus_space_write_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_HC, ctl); |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HC, ctl); |
|
|
if (flags & I2C_F_POLL) { |
if (flags & I2C_F_POLL) { |
/* Poll for completion */ |
/* Poll for completion */ |
DELAY(PIIXPM_DELAY); |
DELAY(PIIXPM_DELAY); |
for (retries = 1000; retries > 0; retries--) { |
for (retries = 1000; retries > 0; retries--) { |
st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, |
st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
PIIX_SMB_HS); |
PIIX_SMB_HS); |
if ((st & PIIX_SMB_HS_BUSY) == 0) |
if ((st & PIIX_SMB_HS_BUSY) == 0) |
break; |
break; |
|
|
* Transfer timeout. Kill the transaction and clear status bits. |
* Transfer timeout. Kill the transaction and clear status bits. |
*/ |
*/ |
aprint_error("%s: timeout, status 0x%x\n", sc->sc_dev.dv_xname, st); |
aprint_error("%s: timeout, status 0x%x\n", sc->sc_dev.dv_xname, st); |
bus_space_write_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_HC, |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HC, |
PIIX_SMB_HC_KILL); |
PIIX_SMB_HC_KILL); |
DELAY(PIIXPM_DELAY); |
DELAY(PIIXPM_DELAY); |
st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_HS); |
st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS); |
if ((st & PIIX_SMB_HS_FAILED) == 0) |
if ((st & PIIX_SMB_HS_FAILED) == 0) |
aprint_error("%s: transaction abort failed, status 0x%x\n", |
aprint_error("%s: transaction abort failed, status 0x%x\n", |
sc->sc_dev.dv_xname, st); |
sc->sc_dev.dv_xname, st); |
bus_space_write_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_HS, st); |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, st); |
return (1); |
return (1); |
} |
} |
|
|
Line 357 piixpm_intr(void *arg) |
|
Line 411 piixpm_intr(void *arg) |
|
size_t len; |
size_t len; |
|
|
/* Read status */ |
/* Read status */ |
st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_HS); |
st = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS); |
if ((st & PIIX_SMB_HS_BUSY) != 0 || (st & (PIIX_SMB_HS_INTR | |
if ((st & PIIX_SMB_HS_BUSY) != 0 || (st & (PIIX_SMB_HS_INTR | |
PIIX_SMB_HS_DEVERR | PIIX_SMB_HS_BUSERR | |
PIIX_SMB_HS_DEVERR | PIIX_SMB_HS_BUSERR | |
PIIX_SMB_HS_FAILED)) == 0) |
PIIX_SMB_HS_FAILED)) == 0) |
/* Interrupt was not for us */ |
/* Interrupt was not for us */ |
return (0); |
return (0); |
|
|
DPRINTF(("%s: intr st 0x%b\n", sc->sc_dev.dv_xname, st, |
DPRINTF(("%s: intr st 0x%d\n", sc->sc_dev.dv_xname, st & 0xff)); |
PIIX_SMB_HS_BITS)); |
|
|
|
/* Clear status bits */ |
/* Clear status bits */ |
bus_space_write_1(sc->sc_iot, sc->sc_ioh, PIIX_SMB_HS, st); |
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh, PIIX_SMB_HS, st); |
|
|
/* Check for errors */ |
/* Check for errors */ |
if (st & (PIIX_SMB_HS_DEVERR | PIIX_SMB_HS_BUSERR | |
if (st & (PIIX_SMB_HS_DEVERR | PIIX_SMB_HS_BUSERR | |
Line 385 piixpm_intr(void *arg) |
|
Line 438 piixpm_intr(void *arg) |
|
b = sc->sc_i2c_xfer.buf; |
b = sc->sc_i2c_xfer.buf; |
len = sc->sc_i2c_xfer.len; |
len = sc->sc_i2c_xfer.len; |
if (len > 0) |
if (len > 0) |
b[0] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, |
b[0] = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
PIIX_SMB_HD0); |
PIIX_SMB_HD0); |
if (len > 1) |
if (len > 1) |
b[1] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, |
b[1] = bus_space_read_1(sc->sc_smb_iot, sc->sc_smb_ioh, |
PIIX_SMB_HD1); |
PIIX_SMB_HD1); |
} |
} |
|
|