5 * Author: Archie Cobbs <archie@freebsd.org>
6 * Copyright (c) 2000 Whistle Communications, Inc.
9 * Subject to the following obligations and disclaimer of warranty, use and
10 * redistribution of this software, in source or object code forms, with or
11 * without modifications are expressly permitted by Whistle Communications;
12 * provided, however, that:
13 * 1. Any and all reproductions of the source or object code must include the
14 * copyright notice above and the following disclaimer of warranties; and
15 * 2. No rights are granted, in any manner or form, to use Whistle
16 * Communications, Inc. trademarks, including the mark "WHISTLE
17 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
18 * such appears in the above copyright notice or in the software.
20 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
21 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
22 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
23 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
25 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
26 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
27 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
28 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
29 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
30 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
43 * Support for the SMBus controller logical device which is part of the
44 * Intel 81801AA (ICH) and 81801AB (ICH0) I/O controller hub chips.
46 * This driver assumes that the generic SMBus code will ensure that
47 * at most one process at a time calls into the SMBus methods below.
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/kernel.h>
53 #include <sys/errno.h>
55 #include <sys/mutex.h>
56 #include <sys/syslog.h>
59 #include <machine/bus.h>
61 #include <machine/resource.h>
63 #include <dev/smbus/smbconf.h>
65 #include <dev/ichsmb/ichsmb_var.h>
66 #include <dev/ichsmb/ichsmb_reg.h>
69 * Enable debugging by defining ICHSMB_DEBUG to a non-zero value.
71 #define ICHSMB_DEBUG 0
72 #if ICHSMB_DEBUG != 0 && (defined(__GNUC__) || defined(__INTEL_COMPILER))
73 #define DBG(fmt, args...) \
74 do { log(LOG_DEBUG, "%s: " fmt, __func__ , ## args); } while (0)
76 #define DBG(fmt, args...) do { } while (0)
80 * Our child device driver name
82 #define DRIVER_SMBUS "smbus"
87 static int ichsmb_wait(sc_p sc);
89 /********************************************************************
90 BUS-INDEPENDENT BUS METHODS
91 ********************************************************************/
94 * Handle probe-time duties that are independent of the bus
95 * our device lives on.
98 ichsmb_probe(device_t dev)
102 /* Add child: an instance of the "smbus" device */
103 if ((smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) {
104 log(LOG_ERR, "%s: no \"%s\" child found\n",
105 device_get_nameunit(dev), DRIVER_SMBUS);
112 * Handle attach-time duties that are independent of the bus
113 * our device lives on.
116 ichsmb_attach(device_t dev)
118 const sc_p sc = device_get_softc(dev);
121 /* Clear interrupt conditions */
122 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, 0xff);
124 /* Add "smbus" child */
125 if ((error = bus_generic_attach(dev)) != 0) {
126 log(LOG_ERR, "%s: failed to attach child: %d\n",
127 device_get_nameunit(dev), error);
132 mtx_init(&sc->mutex, device_get_nameunit(dev), "ichsmb", MTX_DEF);
136 /********************************************************************
138 ********************************************************************/
141 ichsmb_callback(device_t dev, int index, caddr_t data)
145 DBG("index=%d how=%d\n", index, data ? *(int *)data : -1);
147 case SMB_REQUEST_BUS:
149 case SMB_RELEASE_BUS:
152 smb_error = SMB_EABORT; /* XXX */
155 DBG("smb_error=%d\n", smb_error);
160 ichsmb_quick(device_t dev, u_char slave, int how)
162 const sc_p sc = device_get_softc(dev);
165 DBG("slave=0x%02x how=%d\n", slave, how);
166 KASSERT(sc->ich_cmd == -1,
167 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
171 mtx_lock(&sc->mutex);
172 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_QUICK;
173 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
174 (slave << 1) | (how == SMB_QREAD ?
175 ICH_XMIT_SLVA_READ : ICH_XMIT_SLVA_WRITE));
176 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
177 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
178 smb_error = ichsmb_wait(sc);
179 mtx_unlock(&sc->mutex);
182 smb_error = SMB_ENOTSUPP;
184 DBG("smb_error=%d\n", smb_error);
189 ichsmb_sendb(device_t dev, u_char slave, char byte)
191 const sc_p sc = device_get_softc(dev);
194 DBG("slave=0x%02x byte=0x%02x\n", slave, (u_char)byte);
195 KASSERT(sc->ich_cmd == -1,
196 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
197 mtx_lock(&sc->mutex);
198 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE;
199 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
200 (slave << 1) | ICH_XMIT_SLVA_WRITE);
201 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, byte);
202 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
203 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
204 smb_error = ichsmb_wait(sc);
205 mtx_unlock(&sc->mutex);
206 DBG("smb_error=%d\n", smb_error);
211 ichsmb_recvb(device_t dev, u_char slave, char *byte)
213 const sc_p sc = device_get_softc(dev);
216 DBG("slave=0x%02x\n", slave);
217 KASSERT(sc->ich_cmd == -1,
218 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
219 mtx_lock(&sc->mutex);
220 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE;
221 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
222 (slave << 1) | ICH_XMIT_SLVA_READ);
223 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
224 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
225 if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
226 *byte = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_D0);
227 mtx_unlock(&sc->mutex);
228 DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte);
233 ichsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
235 const sc_p sc = device_get_softc(dev);
238 DBG("slave=0x%02x cmd=0x%02x byte=0x%02x\n",
239 slave, (u_char)cmd, (u_char)byte);
240 KASSERT(sc->ich_cmd == -1,
241 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
242 mtx_lock(&sc->mutex);
243 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE_DATA;
244 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
245 (slave << 1) | ICH_XMIT_SLVA_WRITE);
246 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
247 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, byte);
248 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
249 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
250 smb_error = ichsmb_wait(sc);
251 mtx_unlock(&sc->mutex);
252 DBG("smb_error=%d\n", smb_error);
257 ichsmb_writew(device_t dev, u_char slave, char cmd, short word)
259 const sc_p sc = device_get_softc(dev);
262 DBG("slave=0x%02x cmd=0x%02x word=0x%04x\n",
263 slave, (u_char)cmd, (u_int16_t)word);
264 KASSERT(sc->ich_cmd == -1,
265 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
266 mtx_lock(&sc->mutex);
267 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_WORD_DATA;
268 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
269 (slave << 1) | ICH_XMIT_SLVA_WRITE);
270 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
271 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, word & 0xff);
272 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D1, word >> 8);
273 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
274 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
275 smb_error = ichsmb_wait(sc);
276 mtx_unlock(&sc->mutex);
277 DBG("smb_error=%d\n", smb_error);
282 ichsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
284 const sc_p sc = device_get_softc(dev);
287 DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd);
288 KASSERT(sc->ich_cmd == -1,
289 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
290 mtx_lock(&sc->mutex);
291 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE_DATA;
292 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
293 (slave << 1) | ICH_XMIT_SLVA_READ);
294 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
295 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
296 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
297 if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
298 *byte = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_D0);
299 mtx_unlock(&sc->mutex);
300 DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte);
305 ichsmb_readw(device_t dev, u_char slave, char cmd, short *word)
307 const sc_p sc = device_get_softc(dev);
310 DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd);
311 KASSERT(sc->ich_cmd == -1,
312 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
313 mtx_lock(&sc->mutex);
314 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_WORD_DATA;
315 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
316 (slave << 1) | ICH_XMIT_SLVA_READ);
317 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
318 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
319 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
320 if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) {
321 *word = (bus_space_read_1(sc->io_bst,
322 sc->io_bsh, ICH_D0) & 0xff)
323 | (bus_space_read_1(sc->io_bst,
324 sc->io_bsh, ICH_D1) << 8);
326 mtx_unlock(&sc->mutex);
327 DBG("smb_error=%d word=0x%04x\n", smb_error, (u_int16_t)*word);
332 ichsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata)
334 const sc_p sc = device_get_softc(dev);
337 DBG("slave=0x%02x cmd=0x%02x sdata=0x%04x\n",
338 slave, (u_char)cmd, (u_int16_t)sdata);
339 KASSERT(sc->ich_cmd == -1,
340 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
341 mtx_lock(&sc->mutex);
342 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_PROC_CALL;
343 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
344 (slave << 1) | ICH_XMIT_SLVA_WRITE);
345 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
346 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, sdata & 0xff);
347 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D1, sdata >> 8);
348 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
349 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
350 if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) {
351 *rdata = (bus_space_read_1(sc->io_bst,
352 sc->io_bsh, ICH_D0) & 0xff)
353 | (bus_space_read_1(sc->io_bst,
354 sc->io_bsh, ICH_D1) << 8);
356 mtx_unlock(&sc->mutex);
357 DBG("smb_error=%d rdata=0x%04x\n", smb_error, (u_int16_t)*rdata);
362 ichsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
364 const sc_p sc = device_get_softc(dev);
367 DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave, (u_char)cmd, count);
369 #define DISP(ch) (((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch))
373 for (p = (u_char *)buf; p - (u_char *)buf < 32; p += 8) {
374 DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x"
375 " %c%c%c%c%c%c%c%c", (p - (u_char *)buf),
376 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
377 DISP(p[0]), DISP(p[1]), DISP(p[2]), DISP(p[3]),
378 DISP(p[4]), DISP(p[5]), DISP(p[6]), DISP(p[7]));
383 KASSERT(sc->ich_cmd == -1,
384 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
385 if (count < 1 || count > 32)
387 bcopy(buf, sc->block_data, count);
388 sc->block_count = count;
392 mtx_lock(&sc->mutex);
393 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK;
394 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
395 (slave << 1) | ICH_XMIT_SLVA_WRITE);
396 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
397 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, count);
398 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_BLOCK_DB, buf[0]);
399 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
400 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
401 smb_error = ichsmb_wait(sc);
402 mtx_unlock(&sc->mutex);
403 DBG("smb_error=%d\n", smb_error);
408 ichsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
410 const sc_p sc = device_get_softc(dev);
413 DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave, (u_char)cmd, count);
414 KASSERT(sc->ich_cmd == -1,
415 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
416 if (count < 1 || count > 32)
418 bzero(sc->block_data, sizeof(sc->block_data));
419 sc->block_count = count;
423 mtx_lock(&sc->mutex);
424 sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK;
425 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
426 (slave << 1) | ICH_XMIT_SLVA_READ);
427 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
428 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, count); /* XXX? */
429 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
430 ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
431 if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
432 bcopy(sc->block_data, buf, sc->block_count);
433 mtx_unlock(&sc->mutex);
434 DBG("smb_error=%d\n", smb_error);
436 #define DISP(ch) (((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch))
440 for (p = (u_char *)buf; p - (u_char *)buf < 32; p += 8) {
441 DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x"
442 " %c%c%c%c%c%c%c%c", (p - (u_char *)buf),
443 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
444 DISP(p[0]), DISP(p[1]), DISP(p[2]), DISP(p[3]),
445 DISP(p[4]), DISP(p[5]), DISP(p[6]), DISP(p[7]));
453 /********************************************************************
455 ********************************************************************/
458 * This table describes what interrupts we should ever expect to
459 * see after each ICH command, not including the SMBALERT interrupt.
461 static const u_int8_t ichsmb_state_irqs[] = {
463 (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
465 (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
467 (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
469 (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
471 (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR),
473 (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR
474 | ICH_HST_STA_BYTE_DONE_STS),
475 /* i2c read (not used) */
476 (ICH_HST_STA_BUS_ERR | ICH_HST_STA_DEV_ERR | ICH_HST_STA_INTR
477 | ICH_HST_STA_BYTE_DONE_STS)
481 * Interrupt handler. This handler is bus-independent. Note that our
482 * interrupt may be shared, so we must handle "false" interrupts.
485 ichsmb_device_intr(void *cookie)
487 const sc_p sc = cookie;
488 const device_t dev = sc->dev;
489 const int maxloops = 16;
495 mtx_lock(&sc->mutex);
496 for (count = 0; count < maxloops; count++) {
498 /* Get and reset status bits */
499 status = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA);
501 if ((status & ~(ICH_HST_STA_INUSE_STS | ICH_HST_STA_HOST_BUSY))
503 DBG("%d stat=0x%02x\n", count, status);
506 status &= ~(ICH_HST_STA_INUSE_STS | ICH_HST_STA_HOST_BUSY);
510 /* Check for unexpected interrupt */
511 ok_bits = ICH_HST_STA_SMBALERT_STS;
512 cmd_index = sc->ich_cmd >> 2;
513 if (sc->ich_cmd != -1) {
514 KASSERT(cmd_index < sizeof(ichsmb_state_irqs),
515 ("%s: ich_cmd=%d", device_get_nameunit(dev),
517 ok_bits |= ichsmb_state_irqs[cmd_index];
519 if ((status & ~ok_bits) != 0) {
520 log(LOG_ERR, "%s: irq 0x%02x during %d\n",
521 device_get_nameunit(dev), status, cmd_index);
522 bus_space_write_1(sc->io_bst, sc->io_bsh,
523 ICH_HST_STA, (status & ~ok_bits));
527 /* Handle SMBALERT interrupt */
528 if (status & ICH_HST_STA_SMBALERT_STS) {
529 static int smbalert_count = 16;
530 if (smbalert_count > 0) {
531 log(LOG_WARNING, "%s: SMBALERT# rec'd\n",
532 device_get_nameunit(dev));
533 if (--smbalert_count == 0) {
535 "%s: not logging anymore\n",
536 device_get_nameunit(dev));
541 /* Check for bus error */
542 if (status & ICH_HST_STA_BUS_ERR) {
543 sc->smb_error = SMB_ECOLLI; /* XXX SMB_EBUSERR? */
547 /* Check for device error */
548 if (status & ICH_HST_STA_DEV_ERR) {
549 sc->smb_error = SMB_ENOACK; /* or SMB_ETIMEOUT? */
553 /* Check for byte completion in block transfer */
554 if (status & ICH_HST_STA_BYTE_DONE_STS) {
555 if (sc->block_write) {
556 if (sc->block_index < sc->block_count) {
558 /* Write next byte */
559 bus_space_write_1(sc->io_bst,
560 sc->io_bsh, ICH_BLOCK_DB,
561 sc->block_data[sc->block_index++]);
565 /* First interrupt, get the count also */
566 if (sc->block_index == 0) {
567 sc->block_count = bus_space_read_1(
568 sc->io_bst, sc->io_bsh, ICH_D0);
571 /* Get next byte, if any */
572 if (sc->block_index < sc->block_count) {
575 sc->block_data[sc->block_index++] =
576 bus_space_read_1(sc->io_bst,
577 sc->io_bsh, ICH_BLOCK_DB);
579 /* Set "LAST_BYTE" bit before reading
580 the last byte of block data */
582 >= sc->block_count - 1) {
583 bus_space_write_1(sc->io_bst,
584 sc->io_bsh, ICH_HST_CNT,
585 ICH_HST_CNT_LAST_BYTE
593 /* Check command completion */
594 if (status & ICH_HST_STA_INTR) {
595 sc->smb_error = SMB_ENOERR;
598 bus_space_write_1(sc->io_bst, sc->io_bsh,
599 ICH_HST_STA, status);
604 /* Clear status bits and try again */
605 bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, status);
607 mtx_unlock(&sc->mutex);
609 /* Too many loops? */
610 if (count == maxloops) {
611 log(LOG_ERR, "%s: interrupt loop, status=0x%02x\n",
612 device_get_nameunit(dev),
613 bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA));
618 * Wait for command completion. Assumes mutex is held.
619 * Returns an SMB_* error code.
624 const device_t dev = sc->dev;
625 int error, smb_error;
627 KASSERT(sc->ich_cmd != -1,
628 ("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
629 mtx_assert(&sc->mutex, MA_OWNED);
631 error = msleep(sc, &sc->mutex, PZERO | PCATCH, "ichsmb", hz / 4);
632 DBG("msleep -> %d\n", error);
635 if (sc->ich_cmd != -1)
639 smb_error = sc->smb_error;
642 log(LOG_ERR, "%s: device timeout, status=0x%02x\n",
643 device_get_nameunit(dev),
644 bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA));
646 smb_error = SMB_ETIMEOUT;
649 smb_error = SMB_EABORT;
656 * Release resources associated with device.
659 ichsmb_release_resources(sc_p sc)
661 const device_t dev = sc->dev;
663 if (sc->irq_handle != NULL) {
664 bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
665 sc->irq_handle = NULL;
667 if (sc->irq_res != NULL) {
668 bus_release_resource(dev,
669 SYS_RES_IRQ, sc->irq_rid, sc->irq_res);
672 if (sc->io_res != NULL) {
673 bus_release_resource(dev,
674 SYS_RES_IOPORT, sc->io_rid, sc->io_res);