intpm.c (162289) | intpm.c (165951) |
---|---|
1/*- 2 * Copyright (c) 1998, 1999 Takanori Watanabe 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1998, 1999 Takanori Watanabe 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/pci/intpm.c 162289 2006-09-13 18:56:39Z jhb $"); | 28__FBSDID("$FreeBSD: head/sys/pci/intpm.c 165951 2007-01-11 19:56:24Z jhb $"); |
29 30#include <sys/param.h> 31#include <sys/systm.h> | 29 30#include <sys/param.h> 31#include <sys/systm.h> |
32#include <sys/bus.h> |
|
32#include <sys/kernel.h> | 33#include <sys/kernel.h> |
33#include <machine/bus.h> 34 35#include <sys/uio.h> | 34#include <sys/lock.h> |
36#include <sys/module.h> | 35#include <sys/module.h> |
37#include <sys/bus.h> | 36#include <sys/mutex.h> |
38#include <sys/rman.h> | 37#include <sys/rman.h> |
39#include <machine/resource.h> | 38#include <machine/bus.h> |
40#include <dev/smbus/smbconf.h> 41 42#include "smbus_if.h" 43 | 39#include <dev/smbus/smbconf.h> 40 41#include "smbus_if.h" 42 |
44/*This should be removed if force_pci_map_int supported*/ 45#include <sys/interrupt.h> 46 | |
47#include <dev/pci/pcireg.h> 48#include <dev/pci/pcivar.h> 49#include <pci/intpmreg.h> 50 51#include "opt_intpm.h" 52 | 43#include <dev/pci/pcireg.h> 44#include <dev/pci/pcivar.h> 45#include <pci/intpmreg.h> 46 47#include "opt_intpm.h" 48 |
53static struct _pcsid 54{ 55 u_int32_t type; 56 char *desc; 57} pci_ids[] = { 58 { 0x71138086, "Intel 82371AB Power management controller" }, 59 { 0x719b8086, "Intel 82443MX Power management controller" }, 60#if 0 61 /* Not a good idea yet, this stops isab0 functioning */ 62 { 0x02001166, "ServerWorks OSB4 PCI to ISA Bridge" }, 63#endif 64 65 { 0x00000000, NULL } | 49struct intsmb_softc { 50 device_t dev; 51 struct resource *io_res; 52 struct resource *irq_res; 53 void *irq_hand; 54 device_t smbus; 55 int isbusy; 56 struct mtx lock; |
66}; 67 | 57}; 58 |
59#define INTSMB_LOCK(sc) mtx_lock(&(sc)->lock) 60#define INTSMB_UNLOCK(sc) mtx_unlock(&(sc)->lock) 61#define INTSMB_LOCK_ASSERT(sc) mtx_assert(&(sc)->lock, MA_OWNED) 62 |
|
68static int intsmb_probe(device_t); 69static int intsmb_attach(device_t); | 63static int intsmb_probe(device_t); 64static int intsmb_attach(device_t); |
70static int intsmb_intr(device_t dev); 71static int intsmb_slvintr(device_t dev); 72static void intsmb_alrintr(device_t dev); | 65static int intsmb_detach(device_t); 66static int intsmb_intr(struct intsmb_softc *sc); 67static int intsmb_slvintr(struct intsmb_softc *sc); 68static void intsmb_alrintr(struct intsmb_softc *sc); |
73static int intsmb_callback(device_t dev, int index, void *data); 74static int intsmb_quick(device_t dev, u_char slave, int how); 75static int intsmb_sendb(device_t dev, u_char slave, char byte); 76static int intsmb_recvb(device_t dev, u_char slave, char *byte); 77static int intsmb_writeb(device_t dev, u_char slave, char cmd, char byte); 78static int intsmb_writew(device_t dev, u_char slave, char cmd, short word); 79static int intsmb_readb(device_t dev, u_char slave, char cmd, char *byte); 80static int intsmb_readw(device_t dev, u_char slave, char cmd, short *word); 81static int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata); 82static int intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); 83static int intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf); | 69static int intsmb_callback(device_t dev, int index, void *data); 70static int intsmb_quick(device_t dev, u_char slave, int how); 71static int intsmb_sendb(device_t dev, u_char slave, char byte); 72static int intsmb_recvb(device_t dev, u_char slave, char *byte); 73static int intsmb_writeb(device_t dev, u_char slave, char cmd, char byte); 74static int intsmb_writew(device_t dev, u_char slave, char cmd, short word); 75static int intsmb_readb(device_t dev, u_char slave, char cmd, char *byte); 76static int intsmb_readw(device_t dev, u_char slave, char cmd, short *word); 77static int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata); 78static int intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); 79static int intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf); |
84static void intsmb_start(device_t dev, u_char cmd, int nointr); 85static int intsmb_stop(device_t dev); 86static int intsmb_stop_poll(device_t dev); 87static int intsmb_free(device_t dev); 88static int intpm_probe (device_t dev); 89static int intpm_attach (device_t dev); 90static void intpm_intr(void *arg); | 80static void intsmb_start(struct intsmb_softc *sc, u_char cmd, int nointr); 81static int intsmb_stop(struct intsmb_softc *sc); 82static int intsmb_stop_poll(struct intsmb_softc *sc); 83static int intsmb_free(struct intsmb_softc *sc); 84static void intsmb_rawintr(void *arg); |
91 | 85 |
92static devclass_t intsmb_devclass; | 86static int 87intsmb_probe(device_t dev) 88{ |
93 | 89 |
94static device_method_t intpm_methods[] = { 95 /* Device interface */ 96 DEVMETHOD(device_probe, intsmb_probe), 97 DEVMETHOD(device_attach, intsmb_attach), | 90 switch (pci_get_devid(dev)) { 91 case 0x71138086: /* Intel 82371AB */ 92 case 0x719b8086: /* Intel 82443MX */ 93#if 0 94 /* Not a good idea yet, this stops isab0 functioning */ 95 case 0x02001166: /* ServerWorks OSB4 */ 96#endif 97 device_set_desc(dev, "Intel PIIX4 SMBUS Interface"); 98 break; 99 default: 100 return (ENXIO); 101 } |
98 | 102 |
99 /* Bus interface */ 100 DEVMETHOD(bus_print_child, bus_generic_print_child), | 103 return (BUS_PROBE_DEFAULT); 104} |
101 | 105 |
102 /* SMBus interface */ 103 DEVMETHOD(smbus_callback, intsmb_callback), 104 DEVMETHOD(smbus_quick, intsmb_quick), 105 DEVMETHOD(smbus_sendb, intsmb_sendb), 106 DEVMETHOD(smbus_recvb, intsmb_recvb), 107 DEVMETHOD(smbus_writeb, intsmb_writeb), 108 DEVMETHOD(smbus_writew, intsmb_writew), 109 DEVMETHOD(smbus_readb, intsmb_readb), 110 DEVMETHOD(smbus_readw, intsmb_readw), 111 DEVMETHOD(smbus_pcall, intsmb_pcall), 112 DEVMETHOD(smbus_bwrite, intsmb_bwrite), 113 DEVMETHOD(smbus_bread, intsmb_bread), | 106static int 107intsmb_attach(device_t dev) 108{ 109 struct intsmb_softc *sc = device_get_softc(dev); 110 int error, rid, value; 111 char *str; |
114 | 112 |
115 { 0, 0 } 116}; | 113 sc = device_get_softc(dev); 114 mtx_init(&sc->lock, device_get_nameunit(dev), "intsmb", MTX_DEF); |
117 | 115 |
118struct intpm_pci_softc { 119 bus_space_tag_t smbst; 120 bus_space_handle_t smbsh; 121 bus_space_tag_t pmst; 122 bus_space_handle_t pmsh; 123 device_t smbus; 124}; | 116 rid = PCI_BASE_ADDR_SMB; 117 sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 118 RF_ACTIVE); 119 if (sc->io_res == NULL) { 120 device_printf(dev, "Could not allocate I/O space\n"); 121 error = ENXIO; 122 goto fail; 123 } |
125 | 124 |
125#ifndef NO_CHANGE_PCICONF 126 pci_write_config(dev, PCIR_INTLINE, 0x9, 1); 127 pci_write_config(dev, PCI_HST_CFG_SMB, 128 PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1); 129#endif 130 value = pci_read_config(dev, PCI_HST_CFG_SMB, 1); 131 switch (value & 0xe) { 132 case PCI_INTR_SMB_SMI: 133 str = "SMI"; 134 break; 135 case PCI_INTR_SMB_IRQ9: 136 str = "IRQ 9"; 137 break; 138 default: 139 str = "BOGUS"; 140 } 141 device_printf(dev, "intr %s %s ", str, 142 (value & 1) ? "enabled" : "disabled"); 143 value = pci_read_config(dev, PCI_REVID_SMB, 1); 144 printf("revision %d\n", value); |
|
126 | 145 |
127struct intsmb_softc { 128 struct intpm_pci_softc *pci_sc; 129 bus_space_tag_t st; 130 bus_space_handle_t sh; 131 device_t smbus; 132 int isbusy; 133}; | 146 if ((value & 0xe) != PCI_INTR_SMB_IRQ9) { 147 device_printf(dev, "Unsupported interrupt mode\n"); 148 error = ENXIO; 149 goto fail; 150 } |
134 | 151 |
135static driver_t intpm_driver = { 136 "intsmb", 137 intpm_methods, 138 sizeof(struct intsmb_softc), 139}; | 152 /* Force IRQ 9. */ 153 rid = 0; 154 bus_set_resource(dev, SYS_RES_IRQ, rid, 9, 1); 155 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 156 RF_SHAREABLE | RF_ACTIVE); 157 if (sc->irq_res == NULL) { 158 device_printf(dev, "Could not allocate irq\n"); 159 error = ENXIO; 160 goto fail; 161 } |
140 | 162 |
141static devclass_t intpm_devclass; | 163 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, intsmb_rawintr, 164 sc, &sc->irq_hand); 165 if (error) { 166 device_printf(dev, "Failed to map intr\n"); 167 goto fail; 168 } |
142 | 169 |
143static device_method_t intpm_pci_methods[] = { 144 DEVMETHOD(device_probe, intpm_probe), 145 DEVMETHOD(device_attach, intpm_attach), | 170 value = pci_read_config(dev, PCI_BASE_ADDR_PM, 4); 171 device_printf(dev, "PM %s %x\n", (value & 1) ? "I/O mapped" : "Memory", 172 value & 0xfffe); |
146 | 173 |
147 { 0, 0 } 148}; | 174 sc->isbusy = 0; 175 sc->smbus = device_add_child(dev, "smbus", -1); 176 if (sc->smbus == NULL) { 177 error = ENXIO; 178 goto fail; 179 } 180 error = device_probe_and_attach(sc->smbus); 181 if (error) 182 goto fail; |
149 | 183 |
150static driver_t intpm_pci_driver = { 151 "intpm", 152 intpm_pci_methods, 153 sizeof(struct intpm_pci_softc) 154}; | 184#ifdef ENABLE_ALART 185 /* Enable Arart */ 186 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); 187#endif 188 return (0); |
155 | 189 |
190fail: 191 intsmb_detach(dev); 192 return (error); 193} 194 |
|
156static int | 195static int |
157intsmb_probe(device_t dev) | 196intsmb_detach(device_t dev) |
158{ 159 struct intsmb_softc *sc = device_get_softc(dev); | 197{ 198 struct intsmb_softc *sc = device_get_softc(dev); |
199 int error; |
|
160 | 200 |
161 sc->smbus = device_add_child(dev, "smbus", -1); 162 if (!sc->smbus) 163 return (EINVAL); /* XXX don't know what to return else */ 164 device_set_desc(dev, "Intel PIIX4 SMBUS Interface"); | 201 error = bus_generic_detach(dev); 202 if (error) 203 return (error); |
165 | 204 |
166 return (BUS_PROBE_DEFAULT); /* XXX don't know what to return else */ | 205 if (sc->smbus) 206 device_delete_child(dev, sc->smbus); 207 if (sc->irq_hand) 208 bus_teardown_intr(dev, sc->irq_res, sc->irq_hand); 209 if (sc->irq_res) 210 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 211 if (sc->io_res) 212 bus_release_resource(dev, SYS_RES_IOPORT, PCI_BASE_ADDR_SMB, 213 sc->io_res); 214 mtx_destroy(&sc->lock); 215 return (0); |
167} | 216} |
168static int 169intsmb_attach(device_t dev) | 217 218static void 219intsmb_rawintr(void *arg) |
170{ | 220{ |
171 struct intsmb_softc *sc = device_get_softc(dev); | 221 struct intsmb_softc *sc = arg; |
172 | 222 |
173 sc->pci_sc = device_get_softc(device_get_parent(dev)); 174 sc->isbusy = 0; 175 sc->sh = sc->pci_sc->smbsh; 176 sc->st = sc->pci_sc->smbst; 177 sc->pci_sc->smbus = dev; 178 device_probe_and_attach(sc->smbus); 179#ifdef ENABLE_ALART 180 /*Enable Arart*/ 181 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, 182 PIIX4_SMBSLVCNT_ALTEN); 183#endif 184 return (0); | 223 INTSMB_LOCK(sc); 224 intsmb_intr(sc); 225 intsmb_slvintr(sc); 226 INTSMB_UNLOCK(sc); |
185} 186 187static int 188intsmb_callback(device_t dev, int index, void *data) 189{ 190 int error = 0; | 227} 228 229static int 230intsmb_callback(device_t dev, int index, void *data) 231{ 232 int error = 0; |
191 intrmask_t s; | |
192 | 233 |
193 s = splnet(); | |
194 switch (index) { 195 case SMB_REQUEST_BUS: 196 break; 197 case SMB_RELEASE_BUS: 198 break; 199 default: 200 error = EINVAL; 201 } | 234 switch (index) { 235 case SMB_REQUEST_BUS: 236 break; 237 case SMB_RELEASE_BUS: 238 break; 239 default: 240 error = EINVAL; 241 } |
202 splx(s); | |
203 204 return (error); 205} 206 207/* Counterpart of smbtx_smb_free(). */ 208static int | 242 243 return (error); 244} 245 246/* Counterpart of smbtx_smb_free(). */ 247static int |
209intsmb_free(device_t dev) | 248intsmb_free(struct intsmb_softc *sc) |
210{ | 249{ |
211 struct intsmb_softc *sc = device_get_softc(dev); 212 intrmask_t s; | |
213 | 250 |
214 if ((bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS) & 215 PIIX4_SMBHSTSTAT_BUSY) || | 251 INTSMB_LOCK_ASSERT(sc); 252 if ((bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & PIIX4_SMBHSTSTAT_BUSY) || |
216#ifdef ENABLE_ALART | 253#ifdef ENABLE_ALART |
217 (bus_space_read_1(sc->st, sc->sh, PIIX4_SMBSLVSTS) & 218 PIIX4_SMBSLVSTS_BUSY) || | 254 (bus_read_1(sc->io_res, PIIX4_SMBSLVSTS) & PIIX4_SMBSLVSTS_BUSY) || |
219#endif 220 sc->isbusy) | 255#endif 256 sc->isbusy) |
221 return (EBUSY); 222 s = splhigh(); | 257 return (SMB_EBUSY); 258 |
223 sc->isbusy = 1; 224 /* Disable Interrupt in slave part. */ 225#ifndef ENABLE_ALART | 259 sc->isbusy = 1; 260 /* Disable Interrupt in slave part. */ 261#ifndef ENABLE_ALART |
226 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, 0); | 262 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 0); |
227#endif 228 /* Reset INTR Flag to prepare INTR. */ | 263#endif 264 /* Reset INTR Flag to prepare INTR. */ |
229 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTSTS, 230 (PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | 231 PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL)); 232 splx(s); | 265 bus_write_1(sc->io_res, PIIX4_SMBHSTSTS, 266 PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | 267 PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL); |
233 return (0); 234} 235 236static int | 268 return (0); 269} 270 271static int |
237intsmb_intr(device_t dev) | 272intsmb_intr(struct intsmb_softc *sc) |
238{ | 273{ |
239 struct intsmb_softc *sc = device_get_softc(dev); 240 int status; | 274 int status, tmp; |
241 | 275 |
242 status = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS); | 276 status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); |
243 if (status & PIIX4_SMBHSTSTAT_BUSY) 244 return (1); 245 246 if (status & (PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | 247 PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL)) { | 277 if (status & PIIX4_SMBHSTSTAT_BUSY) 278 return (1); 279 280 if (status & (PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR | 281 PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL)) { |
248 int tmp; | |
249 | 282 |
250 tmp = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); 251 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCNT, | 283 tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 284 bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, |
252 tmp & ~PIIX4_SMBHSTCNT_INTREN); 253 if (sc->isbusy) { 254 sc->isbusy = 0; 255 wakeup(sc); 256 } 257 return (0); 258 } 259 return (1); /* Not Completed */ 260} 261 262static int | 285 tmp & ~PIIX4_SMBHSTCNT_INTREN); 286 if (sc->isbusy) { 287 sc->isbusy = 0; 288 wakeup(sc); 289 } 290 return (0); 291 } 292 return (1); /* Not Completed */ 293} 294 295static int |
263intsmb_slvintr(device_t dev) | 296intsmb_slvintr(struct intsmb_softc *sc) |
264{ | 297{ |
265 struct intsmb_softc *sc = device_get_softc(dev); 266 int status, retval; | 298 int status; |
267 | 299 |
268 retval = 1; 269 status = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBSLVSTS); | 300 status = bus_read_1(sc->io_res, PIIX4_SMBSLVSTS); |
270 if (status & PIIX4_SMBSLVSTS_BUSY) | 301 if (status & PIIX4_SMBSLVSTS_BUSY) |
271 return (retval); 272 if (status & PIIX4_SMBSLVSTS_ALART) { 273 intsmb_alrintr(dev); 274 retval = 0; 275 } else if (status & ~(PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 | 302 return (1); 303 if (status & PIIX4_SMBSLVSTS_ALART) 304 intsmb_alrintr(sc); 305 else if (status & ~(PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 |
276 | PIIX4_SMBSLVSTS_SDW1)) { | 306 | PIIX4_SMBSLVSTS_SDW1)) { |
277 retval = 0; | |
278 } 279 280 /* Reset Status Register */ | 307 } 308 309 /* Reset Status Register */ |
281 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVSTS, | 310 bus_write_1(sc->io_res, PIIX4_SMBSLVSTS, |
282 PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 | 283 PIIX4_SMBSLVSTS_SDW1 | PIIX4_SMBSLVSTS_SLV); | 311 PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 | 312 PIIX4_SMBSLVSTS_SDW1 | PIIX4_SMBSLVSTS_SLV); |
284 return (retval); | 313 return (0); |
285} 286 287static void | 314} 315 316static void |
288intsmb_alrintr(device_t dev) | 317intsmb_alrintr(struct intsmb_softc *sc) |
289{ | 318{ |
290 struct intsmb_softc *sc = device_get_softc(dev); | |
291 int slvcnt; 292#ifdef ENABLE_ALART 293 int error; | 319 int slvcnt; 320#ifdef ENABLE_ALART 321 int error; |
322 uint8_t addr; |
|
294#endif 295 296 /* Stop generating INTR from ALART. */ | 323#endif 324 325 /* Stop generating INTR from ALART. */ |
297 slvcnt = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBSLVCNT); | 326 slvcnt = bus_read_1(sc->io_res, PIIX4_SMBSLVCNT); |
298#ifdef ENABLE_ALART | 327#ifdef ENABLE_ALART |
299 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, | 328 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, |
300 slvcnt & ~PIIX4_SMBSLVCNT_ALTEN); 301#endif 302 DELAY(5); 303 304 /* Ask bus who asserted it and then ask it what's the matter. */ 305#ifdef ENABLE_ALART | 329 slvcnt & ~PIIX4_SMBSLVCNT_ALTEN); 330#endif 331 DELAY(5); 332 333 /* Ask bus who asserted it and then ask it what's the matter. */ 334#ifdef ENABLE_ALART |
306 error = intsmb_free(dev); 307 if (!error) { 308 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, 309 SMBALTRESP | LSB); 310 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BYTE, 1); 311 if (!(error = intsmb_stop_poll(dev))) { 312 u_int8_t addr; | 335 error = intsmb_free(sc); 336 if (error) 337 return; |
313 | 338 |
314 addr = bus_space_read_1(sc->st, sc->sh, 315 PIIX4_SMBHSTDAT0); 316 printf("ALART_RESPONSE: 0x%x\n", addr); 317 } 318 } else 319 printf("ERROR\n"); | 339 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, SMBALTRESP | LSB); 340 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 1); 341 error = intsmb_stop_poll(sc); 342 if (error) 343 device_printf(sc->dev, "ALART: ERROR\n"); 344 else { 345 addr = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 346 device_printf(sc->dev, "ALART_RESPONSE: 0x%x\n", addr); 347 } |
320 321 /* Re-enable INTR from ALART. */ | 348 349 /* Re-enable INTR from ALART. */ |
322 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, | 350 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, |
323 slvcnt | PIIX4_SMBSLVCNT_ALTEN); 324 DELAY(5); 325#endif 326} 327 328static void | 351 slvcnt | PIIX4_SMBSLVCNT_ALTEN); 352 DELAY(5); 353#endif 354} 355 356static void |
329intsmb_start(device_t dev, unsigned char cmd, int nointr) | 357intsmb_start(struct intsmb_softc *sc, unsigned char cmd, int nointr) |
330{ | 358{ |
331 struct intsmb_softc *sc = device_get_softc(dev); | |
332 unsigned char tmp; 333 | 359 unsigned char tmp; 360 |
334 tmp = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); | 361 INTSMB_LOCK_ASSERT(sc); 362 tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); |
335 tmp &= 0xe0; 336 tmp |= cmd; 337 tmp |= PIIX4_SMBHSTCNT_START; 338 339 /* While not in autoconfiguration enable interrupts. */ 340 if (!cold || !nointr) 341 tmp |= PIIX4_SMBHSTCNT_INTREN; | 363 tmp &= 0xe0; 364 tmp |= cmd; 365 tmp |= PIIX4_SMBHSTCNT_START; 366 367 /* While not in autoconfiguration enable interrupts. */ 368 if (!cold || !nointr) 369 tmp |= PIIX4_SMBHSTCNT_INTREN; |
342 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCNT, tmp); | 370 bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp); |
343} 344 | 371} 372 |
373static int 374intsmb_error(int status) 375{ 376 int error = 0; 377 378 if (status & PIIX4_SMBHSTSTAT_ERR) 379 error |= SMB_EBUSERR; 380 if (status & PIIX4_SMBHSTSTAT_BUSC) 381 error |= SMB_ECOLLI; 382 if (status & PIIX4_SMBHSTSTAT_FAIL) 383 error |= SMB_ENOACK; 384 return (error); 385} 386 |
|
345/* 346 * Polling Code. 347 * 348 * Polling is not encouraged because it requires waiting for the 349 * device if it is busy. 350 * (29063505.pdf from Intel) But during boot, interrupt cannot be used, so use 351 * polling code then. 352 */ 353static int | 387/* 388 * Polling Code. 389 * 390 * Polling is not encouraged because it requires waiting for the 391 * device if it is busy. 392 * (29063505.pdf from Intel) But during boot, interrupt cannot be used, so use 393 * polling code then. 394 */ 395static int |
354intsmb_stop_poll(device_t dev) | 396intsmb_stop_poll(struct intsmb_softc *sc) |
355{ | 397{ |
356 struct intsmb_softc *sc = device_get_softc(dev); 357 int error, i; 358 int tmp; | 398 int error, i, status, tmp; |
359 | 399 |
360 /* 361 * In smbtx driver, Simply waiting. 362 * This loops 100-200 times. 363 */ | 400 INTSMB_LOCK_ASSERT(sc); 401 402 /* First, wait for busy to be set. */ |
364 for (i = 0; i < 0x7fff; i++) | 403 for (i = 0; i < 0x7fff; i++) |
365 if (bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS) & | 404 if (bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & |
366 PIIX4_SMBHSTSTAT_BUSY) 367 break; 368 | 405 PIIX4_SMBHSTSTAT_BUSY) 406 break; 407 |
408 /* Wait for busy to clear. */ |
|
369 for (i = 0; i < 0x7fff; i++) { | 409 for (i = 0; i < 0x7fff; i++) { |
370 int status; 371 372 status = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS); | 410 status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); |
373 if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { 374 sc->isbusy = 0; | 411 if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { 412 sc->isbusy = 0; |
375 error = (status & PIIX4_SMBHSTSTAT_ERR) ? EIO : 376 (status & PIIX4_SMBHSTSTAT_BUSC) ? EBUSY : 377 (status & PIIX4_SMBHSTSTAT_FAIL) ? EIO : 0; | 413 error = intsmb_error(status); |
378 if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR)) | 414 if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR)) |
379 printf("unknown cause why?"); | 415 device_printf(sc->dev, "unknown cause why?"); |
380 return (error); 381 } 382 } 383 | 416 return (error); 417 } 418 } 419 |
420 /* Timed out waiting for busy to clear. */ |
|
384 sc->isbusy = 0; | 421 sc->isbusy = 0; |
385 tmp = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); 386 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCNT, 387 tmp & ~PIIX4_SMBHSTCNT_INTREN); 388 return (EIO); | 422 tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 423 bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp & ~PIIX4_SMBHSTCNT_INTREN); 424 return (SMB_ETIMEOUT); |
389} 390 391/* 392 * Wait for completion and return result. 393 */ 394static int | 425} 426 427/* 428 * Wait for completion and return result. 429 */ 430static int |
395intsmb_stop(device_t dev) | 431intsmb_stop(struct intsmb_softc *sc) |
396{ | 432{ |
397 struct intsmb_softc *sc = device_get_softc(dev); 398 int error; 399 intrmask_t s; | 433 int error, status; |
400 | 434 |
401 if (cold) { | 435 INTSMB_LOCK_ASSERT(sc); 436 437 if (cold) |
402 /* So that it can use device during device probe on SMBus. */ | 438 /* So that it can use device during device probe on SMBus. */ |
403 error = intsmb_stop_poll(dev); 404 return (error); 405 } | 439 return (intsmb_stop_poll(sc)); |
406 | 440 |
407 if (!tsleep(sc, (PWAIT) | PCATCH, "SMBWAI", hz/8)) { 408 int status; 409 410 status = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTSTS); | 441 error = tsleep(sc, PWAIT | PCATCH, "SMBWAI", hz / 8); 442 if (error == 0) { 443 status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS); |
411 if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { | 444 if (!(status & PIIX4_SMBHSTSTAT_BUSY)) { |
412 error = (status & PIIX4_SMBHSTSTAT_ERR) ? EIO : 413 (status & PIIX4_SMBHSTSTAT_BUSC) ? EBUSY : 414 (status & PIIX4_SMBHSTSTAT_FAIL) ? EIO : 0; | 445 error = intsmb_error(status); |
415 if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR)) | 446 if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR)) |
416 printf("intsmb%d: unknown cause why?\n", 417 device_get_unit(dev)); | 447 device_printf(sc->dev, "unknown cause why?\n"); |
418#ifdef ENABLE_ALART | 448#ifdef ENABLE_ALART |
419 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, | 449 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, |
420 PIIX4_SMBSLVCNT_ALTEN); 421#endif 422 return (error); 423 } 424 } 425 426 /* Timeout Procedure. */ | 450 PIIX4_SMBSLVCNT_ALTEN); 451#endif 452 return (error); 453 } 454 } 455 456 /* Timeout Procedure. */ |
427 s = splhigh(); | |
428 sc->isbusy = 0; 429 430 /* Re-enable supressed interrupt from slave part. */ | 457 sc->isbusy = 0; 458 459 /* Re-enable supressed interrupt from slave part. */ |
431 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBSLVCNT, 432 PIIX4_SMBSLVCNT_ALTEN); 433 splx(s); 434 return (EIO); | 460 bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN); 461 if (error == EWOULDBLOCK) 462 return (SMB_ETIMEOUT); 463 else 464 return (SMB_EABORT); |
435} 436 437static int 438intsmb_quick(device_t dev, u_char slave, int how) 439{ 440 struct intsmb_softc *sc = device_get_softc(dev); | 465} 466 467static int 468intsmb_quick(device_t dev, u_char slave, int how) 469{ 470 struct intsmb_softc *sc = device_get_softc(dev); |
441 int error = 0; | 471 int error; |
442 u_char data; 443 444 data = slave; 445 446 /* Quick command is part of Address, I think. */ 447 switch(how) { 448 case SMB_QWRITE: 449 data &= ~LSB; 450 break; 451 case SMB_QREAD: 452 data |= LSB; 453 break; 454 default: | 472 u_char data; 473 474 data = slave; 475 476 /* Quick command is part of Address, I think. */ 477 switch(how) { 478 case SMB_QWRITE: 479 data &= ~LSB; 480 break; 481 case SMB_QREAD: 482 data |= LSB; 483 break; 484 default: |
455 error = EINVAL; | 485 return (EINVAL); |
456 } | 486 } |
457 if (!error) { 458 error = intsmb_free(dev); 459 if (!error) { 460 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, 461 data); 462 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_QUICK, 0); 463 error = intsmb_stop(dev); 464 } 465 } | |
466 | 487 |
488 INTSMB_LOCK(sc); 489 error = intsmb_free(sc); 490 if (error) { 491 INTSMB_UNLOCK(sc); 492 return (error); 493 } 494 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, data); 495 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_QUICK, 0); 496 error = intsmb_stop(sc); 497 INTSMB_UNLOCK(sc); |
|
467 return (error); 468} 469 470static int 471intsmb_sendb(device_t dev, u_char slave, char byte) 472{ 473 struct intsmb_softc *sc = device_get_softc(dev); 474 int error; 475 | 498 return (error); 499} 500 501static int 502intsmb_sendb(device_t dev, u_char slave, char byte) 503{ 504 struct intsmb_softc *sc = device_get_softc(dev); 505 int error; 506 |
476 error = intsmb_free(dev); 477 if (!error) { 478 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, 479 slave & ~LSB); 480 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, byte); 481 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BYTE, 0); 482 error = intsmb_stop(dev); | 507 INTSMB_LOCK(sc); 508 error = intsmb_free(sc); 509 if (error) { 510 INTSMB_UNLOCK(sc); 511 return (error); |
483 } | 512 } |
513 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 514 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, byte); 515 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0); 516 error = intsmb_stop(sc); 517 INTSMB_UNLOCK(sc); |
|
484 return (error); 485} 486 487static int 488intsmb_recvb(device_t dev, u_char slave, char *byte) 489{ 490 struct intsmb_softc *sc = device_get_softc(dev); 491 int error; 492 | 518 return (error); 519} 520 521static int 522intsmb_recvb(device_t dev, u_char slave, char *byte) 523{ 524 struct intsmb_softc *sc = device_get_softc(dev); 525 int error; 526 |
493 error = intsmb_free(dev); 494 if (!error) { 495 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, slave | LSB); 496 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BYTE, 0); 497 if (!(error = intsmb_stop(dev))) { | 527 INTSMB_LOCK(sc); 528 error = intsmb_free(sc); 529 if (error) { 530 INTSMB_UNLOCK(sc); 531 return (error); 532 } 533 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 534 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0); 535 error = intsmb_stop(sc); 536 if (error == 0) { |
498#ifdef RECV_IS_IN_CMD | 537#ifdef RECV_IS_IN_CMD |
499 /* 500 * Linux SMBus stuff also troubles 501 * Because Intel's datasheet does not make clear. 502 */ 503 *byte = bus_space_read_1(sc->st, sc->sh, 504 PIIX4_SMBHSTCMD); | 538 /* 539 * Linux SMBus stuff also troubles 540 * Because Intel's datasheet does not make clear. 541 */ 542 *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTCMD); |
505#else | 543#else |
506 *byte = bus_space_read_1(sc->st, sc->sh, 507 PIIX4_SMBHSTDAT0); | 544 *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); |
508#endif | 545#endif |
509 } | |
510 } | 546 } |
547 INTSMB_UNLOCK(sc); |
|
511 return (error); 512} 513 514static int 515intsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 516{ 517 struct intsmb_softc *sc = device_get_softc(dev); 518 int error; 519 | 548 return (error); 549} 550 551static int 552intsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 553{ 554 struct intsmb_softc *sc = device_get_softc(dev); 555 int error; 556 |
520 error = intsmb_free(dev); 521 if (!error) { 522 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, 523 slave & ~LSB); 524 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); 525 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, byte); 526 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BDATA, 0); 527 error = intsmb_stop(dev); | 557 INTSMB_LOCK(sc); 558 error = intsmb_free(sc); 559 if (error) { 560 INTSMB_UNLOCK(sc); 561 return (error); |
528 } | 562 } |
563 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 564 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 565 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, byte); 566 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0); 567 error = intsmb_stop(sc); 568 INTSMB_UNLOCK(sc); |
|
529 return (error); 530} 531 532static int 533intsmb_writew(device_t dev, u_char slave, char cmd, short word) 534{ 535 struct intsmb_softc *sc = device_get_softc(dev); 536 int error; 537 | 569 return (error); 570} 571 572static int 573intsmb_writew(device_t dev, u_char slave, char cmd, short word) 574{ 575 struct intsmb_softc *sc = device_get_softc(dev); 576 int error; 577 |
538 error = intsmb_free(dev); 539 if (!error) { 540 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, 541 slave & ~LSB); 542 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); 543 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, 544 word & 0xff); 545 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT1, 546 (word >> 8) & 0xff); 547 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 548 error = intsmb_stop(dev); | 578 INTSMB_LOCK(sc); 579 error = intsmb_free(sc); 580 if (error) { 581 INTSMB_UNLOCK(sc); 582 return (error); |
549 } | 583 } |
584 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 585 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 586 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, word & 0xff); 587 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (word >> 8) & 0xff); 588 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 589 error = intsmb_stop(sc); 590 INTSMB_UNLOCK(sc); |
|
550 return (error); 551} 552 553static int 554intsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 555{ 556 struct intsmb_softc *sc = device_get_softc(dev); 557 int error; 558 | 591 return (error); 592} 593 594static int 595intsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 596{ 597 struct intsmb_softc *sc = device_get_softc(dev); 598 int error; 599 |
559 error = intsmb_free(dev); 560 if (!error) { 561 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, slave | LSB); 562 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); 563 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BDATA, 0); 564 if (!(error = intsmb_stop(dev))) 565 *byte = bus_space_read_1(sc->st, sc->sh, 566 PIIX4_SMBHSTDAT0); | 600 INTSMB_LOCK(sc); 601 error = intsmb_free(sc); 602 if (error) { 603 INTSMB_UNLOCK(sc); 604 return (error); |
567 } | 605 } |
606 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 607 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 608 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0); 609 error = intsmb_stop(sc); 610 if (error == 0) 611 *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 612 INTSMB_UNLOCK(sc); |
|
568 return (error); 569} | 613 return (error); 614} |
615 |
|
570static int 571intsmb_readw(device_t dev, u_char slave, char cmd, short *word) 572{ 573 struct intsmb_softc *sc = device_get_softc(dev); 574 int error; 575 | 616static int 617intsmb_readw(device_t dev, u_char slave, char cmd, short *word) 618{ 619 struct intsmb_softc *sc = device_get_softc(dev); 620 int error; 621 |
576 error = intsmb_free(dev); 577 if (!error) { 578 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, slave | LSB); 579 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); 580 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 581 if (!(error = intsmb_stop(dev))) { 582 *word = bus_space_read_1(sc->st, sc->sh, 583 PIIX4_SMBHSTDAT0); 584 *word |= bus_space_read_1(sc->st, sc->sh, 585 PIIX4_SMBHSTDAT1) << 8; 586 } | 622 INTSMB_LOCK(sc); 623 error = intsmb_free(sc); 624 if (error) { 625 INTSMB_UNLOCK(sc); 626 return (error); |
587 } | 627 } |
628 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 629 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 630 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 631 error = intsmb_stop(sc); 632 if (error == 0) { 633 *word = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 634 *word |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8; 635 } 636 INTSMB_UNLOCK(sc); |
|
588 return (error); 589} 590 591/* 592 * Data sheet claims that it implements all function, but also claims 593 * that it implements 7 function and not mention PCALL. So I don't know 594 * whether it will work. 595 */ 596static int 597intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) 598{ 599#ifdef PROCCALL_TEST 600 struct intsmb_softc *sc = device_get_softc(dev); 601 int error; 602 | 637 return (error); 638} 639 640/* 641 * Data sheet claims that it implements all function, but also claims 642 * that it implements 7 function and not mention PCALL. So I don't know 643 * whether it will work. 644 */ 645static int 646intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) 647{ 648#ifdef PROCCALL_TEST 649 struct intsmb_softc *sc = device_get_softc(dev); 650 int error; 651 |
603 error = intsmb_free(dev); 604 if (!error) { 605 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, 606 slave & ~LSB); 607 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); 608 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, 609 sdata & 0xff); 610 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT1, 611 (sdata & 0xff) >> 8); 612 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_WDATA, 0); | 652 INTSMB_LOCK(sc); 653 error = intsmb_free(sc); 654 if (error) { 655 INTSMB_UNLOCK(sc); 656 return (error); |
613 } | 657 } |
614 if (!(error = intsmb_stop(dev))) { 615 *rdata = bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0); 616 *rdata |= bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTDAT1) << 617 8; | 658 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 659 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 660 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, sdata & 0xff); 661 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (sdata & 0xff) >> 8); 662 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0); 663 error = intsmb_stop(sc); 664 if (error == 0) { 665 *rdata = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 666 *rdata |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8; |
618 } | 667 } |
668 INTSMB_UNLOCK(sc); |
|
619 return (error); 620#else | 669 return (error); 670#else |
621 return (0); | 671 return (SMB_ENOTSUPP); |
622#endif 623} 624 625static int 626intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 627{ 628 struct intsmb_softc *sc = device_get_softc(dev); 629 int error, i; 630 | 672#endif 673} 674 675static int 676intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 677{ 678 struct intsmb_softc *sc = device_get_softc(dev); 679 int error, i; 680 |
631 error = intsmb_free(dev); | |
632 if (count > SMBBLOCKTRANS_MAX || count == 0) | 681 if (count > SMBBLOCKTRANS_MAX || count == 0) |
633 error = SMB_EINVAL; 634 if (!error) { 635 /* Reset internal array index. */ 636 bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); | 682 return (SMB_EINVAL); |
637 | 683 |
638 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, 639 slave & ~LSB); 640 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); 641 for (i = 0; i < count; i++) 642 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBBLKDAT, 643 buf[i]); 644 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, count); 645 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); 646 error = intsmb_stop(dev); | 684 INTSMB_LOCK(sc); 685 error = intsmb_free(sc); 686 if (error) { 687 INTSMB_UNLOCK(sc); 688 return (error); |
647 } | 689 } |
690 691 /* Reset internal array index. */ 692 bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 693 694 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB); 695 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 696 for (i = 0; i < count; i++) 697 bus_write_1(sc->io_res, PIIX4_SMBBLKDAT, buf[i]); 698 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, count); 699 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); 700 error = intsmb_stop(sc); 701 INTSMB_UNLOCK(sc); |
|
648 return (error); 649} 650 651static int 652intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 653{ 654 struct intsmb_softc *sc = device_get_softc(dev); 655 int error, i; 656 u_char data, nread; 657 | 702 return (error); 703} 704 705static int 706intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) 707{ 708 struct intsmb_softc *sc = device_get_softc(dev); 709 int error, i; 710 u_char data, nread; 711 |
658 error = intsmb_free(dev); | |
659 if (*count > SMBBLOCKTRANS_MAX || *count == 0) | 712 if (*count > SMBBLOCKTRANS_MAX || *count == 0) |
660 error = SMB_EINVAL; 661 if (!error) { 662 /* Reset internal array index. */ 663 bus_space_read_1(sc->st, sc->sh, PIIX4_SMBHSTCNT); | 713 return (SMB_EINVAL); |
664 | 714 |
665 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTADD, slave | LSB); 666 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTCMD, cmd); 667 bus_space_write_1(sc->st, sc->sh, PIIX4_SMBHSTDAT0, *count); 668 intsmb_start(dev, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); 669 error = intsmb_stop(dev); 670 if (!error) { 671 nread= bus_space_read_1(sc->st, sc->sh, 672 PIIX4_SMBHSTDAT0); 673 if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) { 674 for (i = 0; i < nread; i++) { 675 data = bus_space_read_1(sc->st, sc->sh, 676 PIIX4_SMBBLKDAT); 677 if (i < *count) 678 buf[i] = data; 679 } 680 *count = nread; 681 } else { 682 error = EIO; | 715 INTSMB_LOCK(sc); 716 error = intsmb_free(sc); 717 if (error) { 718 INTSMB_UNLOCK(sc); 719 return (error); 720 } 721 722 /* Reset internal array index. */ 723 bus_read_1(sc->io_res, PIIX4_SMBHSTCNT); 724 725 bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB); 726 bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd); 727 bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, *count); 728 intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0); 729 error = intsmb_stop(sc); 730 if (error == 0) { 731 nread = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0); 732 if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) { 733 for (i = 0; i < nread; i++) { 734 data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT); 735 if (i < *count) 736 buf[i] = data; |
683 } | 737 } |
684 } | 738 *count = nread; 739 } else 740 error = EIO; |
685 } | 741 } |
742 INTSMB_UNLOCK(sc); |
|
686 return (error); 687} 688 | 743 return (error); 744} 745 |
689DRIVER_MODULE(intsmb, intpm, intpm_driver, intsmb_devclass, 0, 0); | 746static devclass_t intsmb_devclass; |
690 | 747 |
691static int 692intpm_attach(device_t dev) 693{ 694 struct intpm_pci_softc *sc; 695 struct resource *res; 696 device_t smbinterface; 697 void *ih; 698 char *str; 699 int error, rid, value; 700 int unit = device_get_unit(dev); | 748static device_method_t intsmb_methods[] = { 749 /* Device interface */ 750 DEVMETHOD(device_probe, intsmb_probe), 751 DEVMETHOD(device_attach, intsmb_attach), 752 DEVMETHOD(device_detach, intsmb_detach), |
701 | 753 |
702 sc = device_get_softc(dev); 703 if (sc == NULL) 704 return (ENOMEM); | 754 /* Bus interface */ 755 DEVMETHOD(bus_print_child, bus_generic_print_child), |
705 | 756 |
706 rid = PCI_BASE_ADDR_SMB; 707 res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 708 if (res == NULL) { 709 device_printf(dev, "Could not allocate Bus space\n"); 710 return (ENXIO); 711 } 712 sc->smbst = rman_get_bustag(res); 713 sc->smbsh = rman_get_bushandle(res); | 757 /* SMBus interface */ 758 DEVMETHOD(smbus_callback, intsmb_callback), 759 DEVMETHOD(smbus_quick, intsmb_quick), 760 DEVMETHOD(smbus_sendb, intsmb_sendb), 761 DEVMETHOD(smbus_recvb, intsmb_recvb), 762 DEVMETHOD(smbus_writeb, intsmb_writeb), 763 DEVMETHOD(smbus_writew, intsmb_writew), 764 DEVMETHOD(smbus_readb, intsmb_readb), 765 DEVMETHOD(smbus_readw, intsmb_readw), 766 DEVMETHOD(smbus_pcall, intsmb_pcall), 767 DEVMETHOD(smbus_bwrite, intsmb_bwrite), 768 DEVMETHOD(smbus_bread, intsmb_bread), |
714 | 769 |
715#ifdef __i386__ 716 device_printf(dev, "%s %lx\n", (sc->smbst == I386_BUS_SPACE_IO) ? 717 "I/O mapped" : "Memory", rman_get_start(res)); 718#endif | 770 { 0, 0 } 771}; |
719 | 772 |
720#ifndef NO_CHANGE_PCICONF 721 pci_write_config(dev, PCIR_INTLINE, 0x9, 1); 722 pci_write_config(dev, PCI_HST_CFG_SMB, 723 PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1); 724#endif 725 value = pci_read_config(dev, PCI_HST_CFG_SMB, 1); 726 switch (value & 0xe) { 727 case PCI_INTR_SMB_SMI: 728 str = "SMI"; 729 break; 730 case PCI_INTR_SMB_IRQ9: 731 str = "IRQ 9"; 732 break; 733 default: 734 str = "BOGUS"; 735 } 736 device_printf(dev, "intr %s %s ", str, 737 (value & 1) ? "enabled" : "disabled"); 738 value = pci_read_config(dev, PCI_REVID_SMB, 1); 739 printf("revision %d\n", value); | 773static driver_t intsmb_driver = { 774 "intsmb", 775 intsmb_methods, 776 sizeof(struct intsmb_softc), 777}; |
740 | 778 |
741 /* Install interrupt handler. */ 742 rid = 0; 743 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 9, 9, 1, 744 RF_SHAREABLE | RF_ACTIVE); 745 if (res == NULL) { 746 device_printf(dev, "could not allocate irq"); 747 return (ENOMEM); 748 } 749 error = bus_setup_intr(dev, res, INTR_TYPE_MISC, intpm_intr, sc, &ih); 750 if (error) { 751 device_printf(dev, "Failed to map intr\n"); 752 return (error); 753 } 754 smbinterface = device_add_child(dev, "intsmb", unit); 755 if (!smbinterface) 756 printf("intsmb%d: could not add SMBus device\n", unit); 757 device_probe_and_attach(smbinterface); 758 759 value = pci_read_config(dev, PCI_BASE_ADDR_PM, 4); 760 printf("intpm%d: PM %s %x \n", unit, 761 (value & 1) ? "I/O mapped" : "Memory", value & 0xfffe); 762 return (0); 763} 764 765static int 766intpm_probe(device_t dev) 767{ 768 struct _pcsid *ep = pci_ids; 769 uint32_t device_id = pci_get_devid(dev); 770 771 while (ep->type && ep->type != device_id) 772 ++ep; 773 if (ep->desc != NULL) { 774 device_set_desc(dev, ep->desc); 775 bus_set_resource(dev, SYS_RES_IRQ, 0, 9, 1); /* XXX setup intr resource */ 776 return (BUS_PROBE_DEFAULT); 777 } else { 778 return (ENXIO); 779 } 780} 781 782static void 783intpm_intr(void *arg) 784{ 785 struct intpm_pci_softc *sc = arg; 786 787 intsmb_intr(sc->smbus); 788 intsmb_slvintr(sc->smbus); 789} 790 791DRIVER_MODULE(intpm, pci , intpm_pci_driver, intpm_devclass, 0, 0); | 779DRIVER_MODULE(intsmb, pci, intsmb_driver, intsmb_devclass, 0, 0); |
792DRIVER_MODULE(smbus, intsmb, smbus_driver, smbus_devclass, 0, 0); | 780DRIVER_MODULE(smbus, intsmb, smbus_driver, smbus_devclass, 0, 0); |
793MODULE_DEPEND(intpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 794MODULE_VERSION(intpm, 1); | 781MODULE_DEPEND(intsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 782MODULE_VERSION(intsmb, 1); |