diff options
Diffstat (limited to 'sys/dev/isa')
-rw-r--r-- | sys/dev/isa/it.c | 121 | ||||
-rw-r--r-- | sys/dev/isa/itvar.h | 14 |
2 files changed, 75 insertions, 60 deletions
diff --git a/sys/dev/isa/it.c b/sys/dev/isa/it.c index 11707b69918..9484894d9e2 100644 --- a/sys/dev/isa/it.c +++ b/sys/dev/isa/it.c @@ -1,7 +1,7 @@ -/* $OpenBSD: it.c,v 1.27 2007/12/24 14:07:47 form Exp $ */ +/* $OpenBSD: it.c,v 1.28 2008/04/03 20:28:05 form Exp $ */ /* - * Copyright (c) 2007 Oleg Safiullin <form@pdp-11.org.ru> + * Copyright (c) 2007-2008 Oleg Safiullin <form@pdp-11.org.ru> * Copyright (c) 2006-2007 Juan Romero Pardines <juan@xtrarom.org> * Copyright (c) 2003 Julien Bordet <zejames@greyhats.org> * All rights reserved. @@ -50,7 +50,7 @@ int it_match(struct device *, void *, void *); void it_attach(struct device *, struct device *, void *); u_int8_t it_readreg(bus_space_tag_t, bus_space_handle_t, int); void it_writereg(bus_space_tag_t, bus_space_handle_t, int, u_int8_t); -void it_enter(bus_space_tag_t, bus_space_handle_t); +void it_enter(bus_space_tag_t, bus_space_handle_t, int); void it_exit(bus_space_tag_t, bus_space_handle_t); u_int8_t it_ec_readreg(struct it_softc *, int); @@ -98,78 +98,75 @@ int it_vrfact[IT_VOLT_COUNT] = { RFACT(68, 100), RFACT_NONE }; -int it_found; +LIST_HEAD(, it_softc) it_softc_list = LIST_HEAD_INITIALIZER(&it_softc_list); int it_match(struct device *parent, void *match, void *aux) { struct isa_attach_args *ia = aux; + struct it_softc *sc; bus_space_handle_t ioh; - bus_addr_t iobase; + int ec_iobase, found = 0; u_int16_t cr; - if (it_found || ia->ipa_io[0].base == IOBASEUNK) - return (0); - - /* map EC i/o space */ - if (bus_space_map(ia->ia_iot, ia->ipa_io[0].base, 8, 0, &ioh) != 0) { - DPRINTF(("it_probe: can't map EC i/o space")); - return (0); - } - - /* get vendor id */ - bus_space_write_1(ia->ia_iot, ioh, IT_EC_ADDR, IT_EC_VENDID); - cr = bus_space_read_1(ia->ia_iot, ioh, IT_EC_DATA); - - /* unmap EC i/o space */ - bus_space_unmap(ia->ia_iot, ioh, 8); - - /* check for ITE vendor ID */ - if (cr != IT_VEND_ITE) + if (ia->ipa_io[0].base != IO_IT1 && ia->ipa_io[0].base != IO_IT2) return (0); /* map i/o space */ - if (bus_space_map(ia->ia_iot, IO_IT, 2, 0, &ioh) != 0) { - DPRINTF(("it_probe: can't map i/o space")); + if (bus_space_map(ia->ia_iot, ia->ipa_io[0].base, 2, 0, &ioh) != 0) { + DPRINTF(("it_match: can't map i/o space")); return (0); } /* enter MB PnP mode */ - it_enter(ia->ia_iot, ioh); + it_enter(ia->ia_iot, ioh, ia->ipa_io[0].base); + + /* + * SMSC or similar SuperIO chips use 0x55 magic to enter PnP mode + * and 0xaa to exit. These chips also enter PnP mode via ITE + * `enter MB PnP mode' sequence, so force chip to exit PnP mode + * if this is the case. + */ + bus_space_write_1(ia->ia_iot, ioh, IT_IO_ADDR, 0xaa); /* get chip id */ cr = it_readreg(ia->ia_iot, ioh, IT_CHIPID1) << 8; cr |= it_readreg(ia->ia_iot, ioh, IT_CHIPID2); - /* get environment controller base address */ - it_writereg(ia->ia_iot, ioh, IT_LDN, IT_EC_LDN); - iobase = it_readreg(ia->ia_iot, ioh, IT_EC_MSB) << 8; - iobase |= it_readreg(ia->ia_iot, ioh, IT_EC_LSB); - - /* exit MB PnP mode and unmap */ - it_exit(ia->ia_iot, ioh); - bus_space_unmap(ia->ia_iot, ioh, 2); - - /* check if EC i/o base address match */ - if (ia->ipa_io[0].base != iobase) - return (0); - switch (cr) { case IT_ID_8705: case IT_ID_8712: case IT_ID_8716: case IT_ID_8718: case IT_ID_8726: - ia->ipa_nio = 1; - ia->ipa_io[0].length = 8; - ia->ipa_nmem = ia->ipa_nirq = ia->ipa_ndrq = 0; + /* get environment controller base address */ + it_writereg(ia->ia_iot, ioh, IT_LDN, IT_EC_LDN); + ec_iobase = it_readreg(ia->ia_iot, ioh, IT_EC_MSB) << 8; + ec_iobase |= it_readreg(ia->ia_iot, ioh, IT_EC_LSB); + + /* check if device already attached */ + LIST_FOREACH(sc, &it_softc_list, sc_list) + if (sc->sc_ec_iobase == ec_iobase) + break; + + if (sc == NULL) { + ia->ipa_nio = 1; + ia->ipa_io[0].length = 2; + ia->ipa_nmem = ia->ipa_nirq = ia->ipa_ndrq = 0; + found++; + } + break; - default: - return (0); } - return (1); + /* exit MB PnP mode */ + it_exit(ia->ia_iot, ioh); + + /* unmap i/o space */ + bus_space_unmap(ia->ia_iot, ioh, 2); + + return (found); } void @@ -181,21 +178,25 @@ it_attach(struct device *parent, struct device *self, void *aux) u_int8_t cr; sc->sc_iot = ia->ia_iot; - if (bus_space_map(sc->sc_iot, IO_IT, 2, 0, &sc->sc_ioh) != 0) { + sc->sc_iobase = ia->ipa_io[0].base; + if (bus_space_map(sc->sc_iot, sc->sc_iobase, 2, 0, &sc->sc_ioh) != 0) { printf(": can't map i/o space\n"); return; } - it_found++; - /* enter MB PnP mode */ - it_enter(sc->sc_iot, sc->sc_ioh); + it_enter(sc->sc_iot, sc->sc_ioh, sc->sc_iobase); /* get chip id and rev */ sc->sc_chipid = it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPID1) << 8; sc->sc_chipid |= it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPID2); sc->sc_chiprev = it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPREV); + /* get environment controller base address */ + it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_EC_LDN); + sc->sc_ec_iobase = it_readreg(sc->sc_iot, sc->sc_ioh, IT_EC_MSB) << 8; + sc->sc_ec_iobase |= it_readreg(sc->sc_iot, sc->sc_ioh, IT_EC_LSB); + /* initialize watchdog */ if (sc->sc_chipid != IT_ID_8705) { it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_WDT_LDN); @@ -207,11 +208,20 @@ it_attach(struct device *parent, struct device *self, void *aux) /* exit MB PnP mode and unmap */ it_exit(sc->sc_iot, sc->sc_ioh); - printf(": IT%xF rev 0x%02x\n", sc->sc_chipid, sc->sc_chiprev); + LIST_INSERT_HEAD(&it_softc_list, sc, sc_list); + + printf(": IT%xF rev 0x%02x", sc->sc_chipid, sc->sc_chiprev); + + if (sc->sc_ec_iobase == 0) { + printf(", EC disabled\n"); + return; + } + + printf(", EC port 0x%x\n", sc->sc_ec_iobase); /* map environment controller i/o space */ sc->sc_ec_iot = ia->ia_iot; - if (bus_space_map(sc->sc_ec_iot, ia->ipa_io[0].base, 8, 0, + if (bus_space_map(sc->sc_ec_iot, sc->sc_ec_iobase, 8, 0, &sc->sc_ec_ioh) != 0) { printf("%s: can't map EC i/o space\n", sc->sc_dev.dv_xname); return; @@ -262,12 +272,15 @@ it_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int r, u_int8_t v) } void -it_enter(bus_space_tag_t iot, bus_space_handle_t ioh) +it_enter(bus_space_tag_t iot, bus_space_handle_t ioh, int iobase) { bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x87); bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x01); bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55); - bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55); + if (iobase == IO_IT1) + bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55); + else + bus_space_write_1(iot, ioh, IT_IO_ADDR, 0xaa); } void @@ -384,7 +397,7 @@ it_wdog_cb(void *arg, int period) struct it_softc *sc = arg; /* enter MB PnP mode and select WDT device */ - it_enter(sc->sc_iot, sc->sc_ioh); + it_enter(sc->sc_iot, sc->sc_ioh, sc->sc_iobase); it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_WDT_LDN); /* disable watchdog timeout */ diff --git a/sys/dev/isa/itvar.h b/sys/dev/isa/itvar.h index 98522c49252..b70cc3a409f 100644 --- a/sys/dev/isa/itvar.h +++ b/sys/dev/isa/itvar.h @@ -1,7 +1,7 @@ -/* $OpenBSD: itvar.h,v 1.7 2007/12/23 17:44:07 form Exp $ */ +/* $OpenBSD: itvar.h,v 1.8 2008/04/03 20:28:05 form Exp $ */ /* - * Copyright (c) 2007 Oleg Safiullin <form@pdp-11.org.ru> + * Copyright (c) 2007-2008 Oleg Safiullin <form@pdp-11.org.ru> * Copyright (c) 2006-2007 Juan Romero Pardines <juan@xtrarom.org> * Copyright (c) 2003 Julien Bordet <zejames@greyhats.org> * All rights reserved. @@ -34,13 +34,12 @@ #define IT_EC_NUMSENSORS 15 #define IT_EC_VREF 4096 -#define IO_IT 0x2e +#define IO_IT1 0x2e +#define IO_IT2 0x4e #define IT_IO_ADDR 0x00 #define IT_IO_DATA 0x01 -#define IT_VEND_ITE 0x90 - #define IT_ID_8705 0x8705 #define IT_ID_8712 0x8712 #define IT_ID_8716 0x8716 @@ -67,7 +66,6 @@ #define IT_EC_FANEXTBASE 0x18 #define IT_EC_VOLTBASE 0x20 #define IT_EC_TEMPBASE 0x29 -#define IT_EC_VENDID 0x58 #define IT_WDT_LDN 0x07 @@ -82,6 +80,8 @@ struct it_softc { bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; + int sc_iobase; + int sc_ec_iobase; u_int16_t sc_chipid; u_int8_t sc_chiprev; @@ -90,6 +90,8 @@ struct it_softc { struct ksensor sc_sensors[IT_EC_NUMSENSORS]; struct ksensordev sc_sensordev; + + LIST_ENTRY(it_softc) sc_list; }; #endif /* _DEV_ISA_ITVAR_H_ */ |