5 * Copyright (c) 2000 Whistle Communications, Inc.
8 * Subject to the following obligations and disclaimer of warranty, use and
9 * redistribution of this software, in source or object code forms, with or
10 * without modifications are expressly permitted by Whistle Communications;
11 * provided, however, that:
12 * 1. Any and all reproductions of the source or object code must include the
13 * copyright notice above and the following disclaimer of warranties; and
14 * 2. No rights are granted, in any manner or form, to use Whistle
15 * Communications, Inc. trademarks, including the mark "WHISTLE
16 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17 * such appears in the above copyright notice or in the software.
19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
37 * Author: Archie Cobbs <archie@freebsd.org>
39 * $FreeBSD: src/sys/dev/ichsmb/ichsmb.c,v 1.1.2.1 2000/10/09 00:52:43 archie Exp $
40 * $DragonFly: src/sys/dev/powermng/ichsmb/ichsmb.c,v 1.7 2006/10/25 20:56:00 dillon Exp $
44 * Support for the SMBus controller logical device which is part of the
45 * Intel 81801AA (ICH) and 81801AB (ICH0) I/O controller hub chips.
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/errno.h>
52 #include <sys/syslog.h>
55 #include <sys/thread2.h>
57 #include <bus/smbus/smbconf.h>
59 #include "ichsmb_var.h"
60 #include "ichsmb_reg.h"
63 * Enable debugging by defining ICHSMB_DEBUG to a non-zero value.
65 #define ICHSMB_DEBUG 0
66 #if ICHSMB_DEBUG != 0 && defined(__GNUC__)
67 #define DBG(fmt, args...) \
68 do { log(LOG_DEBUG, "%s: " fmt, __func__ , ## args); } while (0)
70 #define DBG(fmt, args...) do { } while (0)
74 * Our child device driver name
76 #define DRIVER_SMBUS "smbus"
81 static int ichsmb_wait(sc_p sc
);
83 /********************************************************************
84 BUS-INDEPENDENT BUS METHODS
85 ********************************************************************/
88 * Handle probe-time duties that are independent of the bus
89 * our device lives on.
92 ichsmb_probe(device_t dev
)
96 /* Add child: an instance of the "smbus" device */
97 if ((smb
= device_add_child(dev
, DRIVER_SMBUS
, -1)) == NULL
) {
98 log(LOG_ERR
, "%s: no \"%s\" child found\n",
99 device_get_nameunit(dev
), DRIVER_SMBUS
);
106 * Handle attach-time duties that are independent of the bus
107 * our device lives on.
110 ichsmb_attach(device_t dev
)
112 const sc_p sc
= device_get_softc(dev
);
115 /* Clear interrupt conditions */
116 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_STA
, 0xff);
118 /* Add "smbus" child */
119 if ((error
= bus_generic_attach(dev
)) != 0) {
120 log(LOG_ERR
, "%s: failed to attach child: %d\n",
121 device_get_nameunit(dev
), error
);
129 /********************************************************************
131 ********************************************************************/
134 ichsmb_callback(device_t dev
, int index
, caddr_t data
)
138 DBG("index=%d how=%d\n", index
, data
? *(int *)data
: -1);
140 case SMB_REQUEST_BUS
:
142 case SMB_RELEASE_BUS
:
145 smb_error
= SMB_EABORT
; /* XXX */
148 DBG("smb_error=%d\n", smb_error
);
153 ichsmb_quick(device_t dev
, u_char slave
, int how
)
155 const sc_p sc
= device_get_softc(dev
);
158 DBG("slave=0x%02x how=%d\n", slave
, how
);
159 KASSERT(sc
->ich_cmd
== -1,
160 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
165 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_QUICK
;
166 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
167 (slave
<< 1) | (how
== SMB_QREAD
?
168 ICH_XMIT_SLVA_READ
: ICH_XMIT_SLVA_WRITE
));
169 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
170 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
171 smb_error
= ichsmb_wait(sc
);
175 smb_error
= SMB_ENOTSUPP
;
177 DBG("smb_error=%d\n", smb_error
);
182 ichsmb_sendb(device_t dev
, u_char slave
, char byte
)
184 const sc_p sc
= device_get_softc(dev
);
187 DBG("slave=0x%02x byte=0x%02x\n", slave
, (u_char
)byte
);
188 KASSERT(sc
->ich_cmd
== -1,
189 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
191 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_BYTE
;
192 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
193 (slave
<< 1) | ICH_XMIT_SLVA_WRITE
);
194 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CMD
, byte
);
195 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
196 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
197 smb_error
= ichsmb_wait(sc
);
199 DBG("smb_error=%d\n", smb_error
);
204 ichsmb_recvb(device_t dev
, u_char slave
, char *byte
)
206 const sc_p sc
= device_get_softc(dev
);
209 DBG("slave=0x%02x\n", slave
);
210 KASSERT(sc
->ich_cmd
== -1,
211 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
213 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_BYTE
;
214 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
215 (slave
<< 1) | ICH_XMIT_SLVA_READ
);
216 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
217 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
218 if ((smb_error
= ichsmb_wait(sc
)) == SMB_ENOERR
)
219 *byte
= bus_space_read_1(sc
->io_bst
, sc
->io_bsh
, ICH_D0
);
221 DBG("smb_error=%d byte=0x%02x\n", smb_error
, (u_char
)*byte
);
226 ichsmb_writeb(device_t dev
, u_char slave
, char cmd
, char byte
)
228 const sc_p sc
= device_get_softc(dev
);
231 DBG("slave=0x%02x cmd=0x%02x byte=0x%02x\n",
232 slave
, (u_char
)cmd
, (u_char
)byte
);
233 KASSERT(sc
->ich_cmd
== -1,
234 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
236 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_BYTE_DATA
;
237 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
238 (slave
<< 1) | ICH_XMIT_SLVA_WRITE
);
239 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CMD
, cmd
);
240 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_D0
, byte
);
241 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
242 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
243 smb_error
= ichsmb_wait(sc
);
245 DBG("smb_error=%d\n", smb_error
);
250 ichsmb_writew(device_t dev
, u_char slave
, char cmd
, short word
)
252 const sc_p sc
= device_get_softc(dev
);
255 DBG("slave=0x%02x cmd=0x%02x word=0x%04x\n",
256 slave
, (u_char
)cmd
, (u_int16_t
)word
);
257 KASSERT(sc
->ich_cmd
== -1,
258 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
260 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_WORD_DATA
;
261 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
262 (slave
<< 1) | ICH_XMIT_SLVA_WRITE
);
263 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CMD
, cmd
);
264 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_D0
, word
& 0xff);
265 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_D1
, word
>> 8);
266 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
267 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
268 smb_error
= ichsmb_wait(sc
);
270 DBG("smb_error=%d\n", smb_error
);
275 ichsmb_readb(device_t dev
, u_char slave
, char cmd
, char *byte
)
277 const sc_p sc
= device_get_softc(dev
);
280 DBG("slave=0x%02x cmd=0x%02x\n", slave
, (u_char
)cmd
);
281 KASSERT(sc
->ich_cmd
== -1,
282 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
284 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_BYTE_DATA
;
285 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
286 (slave
<< 1) | ICH_XMIT_SLVA_READ
);
287 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CMD
, cmd
);
288 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
289 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
290 if ((smb_error
= ichsmb_wait(sc
)) == SMB_ENOERR
)
291 *byte
= bus_space_read_1(sc
->io_bst
, sc
->io_bsh
, ICH_D0
);
293 DBG("smb_error=%d byte=0x%02x\n", smb_error
, (u_char
)*byte
);
298 ichsmb_readw(device_t dev
, u_char slave
, char cmd
, short *word
)
300 const sc_p sc
= device_get_softc(dev
);
303 DBG("slave=0x%02x cmd=0x%02x\n", slave
, (u_char
)cmd
);
304 KASSERT(sc
->ich_cmd
== -1,
305 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
307 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_WORD_DATA
;
308 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
309 (slave
<< 1) | ICH_XMIT_SLVA_READ
);
310 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CMD
, cmd
);
311 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
312 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
313 if ((smb_error
= ichsmb_wait(sc
)) == SMB_ENOERR
) {
314 *word
= (bus_space_read_1(sc
->io_bst
,
315 sc
->io_bsh
, ICH_D0
) & 0xff)
316 | (bus_space_read_1(sc
->io_bst
,
317 sc
->io_bsh
, ICH_D1
) << 8);
320 DBG("smb_error=%d word=0x%04x\n", smb_error
, (u_int16_t
)*word
);
325 ichsmb_pcall(device_t dev
, u_char slave
, char cmd
, short sdata
, short *rdata
)
327 const sc_p sc
= device_get_softc(dev
);
330 DBG("slave=0x%02x cmd=0x%02x sdata=0x%04x\n",
331 slave
, (u_char
)cmd
, (u_int16_t
)sdata
);
332 KASSERT(sc
->ich_cmd
== -1,
333 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
335 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_PROC_CALL
;
336 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
337 (slave
<< 1) | ICH_XMIT_SLVA_WRITE
);
338 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CMD
, cmd
);
339 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_D0
, sdata
& 0xff);
340 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_D1
, sdata
>> 8);
341 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
342 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
343 if ((smb_error
= ichsmb_wait(sc
)) == SMB_ENOERR
) {
344 *rdata
= (bus_space_read_1(sc
->io_bst
,
345 sc
->io_bsh
, ICH_D0
) & 0xff)
346 | (bus_space_read_1(sc
->io_bst
,
347 sc
->io_bsh
, ICH_D1
) << 8);
350 DBG("smb_error=%d rdata=0x%04x\n", smb_error
, (u_int16_t
)*rdata
);
355 ichsmb_bwrite(device_t dev
, u_char slave
, char cmd
, u_char count
, char *buf
)
357 const sc_p sc
= device_get_softc(dev
);
360 DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave
, (u_char
)cmd
, count
);
362 #define DISP(ch) (((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch))
366 for (p
= (u_char
*)buf
; p
- (u_char
*)buf
< 32; p
+= 8) {
367 DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x"
368 " %c%c%c%c%c%c%c%c", (p
- (u_char
*)buf
),
369 p
[0], p
[1], p
[2], p
[3], p
[4], p
[5], p
[6], p
[7],
370 DISP(p
[0]), DISP(p
[1]), DISP(p
[2]), DISP(p
[3]),
371 DISP(p
[4]), DISP(p
[5]), DISP(p
[6]), DISP(p
[7]));
376 KASSERT(sc
->ich_cmd
== -1,
377 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
378 if (count
< 1 || count
> 32)
380 bcopy(buf
, sc
->block_data
, count
);
381 sc
->block_count
= count
;
386 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_BLOCK
;
387 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
388 (slave
<< 1) | ICH_XMIT_SLVA_WRITE
);
389 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CMD
, cmd
);
390 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_D0
, count
);
391 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_BLOCK_DB
, buf
[0]);
392 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
393 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
394 smb_error
= ichsmb_wait(sc
);
396 DBG("smb_error=%d\n", smb_error
);
401 ichsmb_bread(device_t dev
, u_char slave
, char cmd
, u_char count
, char *buf
)
403 const sc_p sc
= device_get_softc(dev
);
406 DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave
, (u_char
)cmd
, count
);
407 KASSERT(sc
->ich_cmd
== -1,
408 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
409 if (count
< 1 || count
> 32)
411 bzero(sc
->block_data
, sizeof(sc
->block_data
));
412 sc
->block_count
= count
;
417 sc
->ich_cmd
= ICH_HST_CNT_SMB_CMD_BLOCK
;
418 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_XMIT_SLVA
,
419 (slave
<< 1) | ICH_XMIT_SLVA_READ
);
420 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CMD
, cmd
);
421 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_D0
, count
); /* XXX? */
422 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_CNT
,
423 ICH_HST_CNT_START
| ICH_HST_CNT_INTREN
| sc
->ich_cmd
);
424 if ((smb_error
= ichsmb_wait(sc
)) == SMB_ENOERR
)
425 bcopy(sc
->block_data
, buf
, sc
->block_count
);
427 DBG("smb_error=%d\n", smb_error
);
429 #define DISP(ch) (((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch))
433 for (p
= (u_char
*)buf
; p
- (u_char
*)buf
< 32; p
+= 8) {
434 DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x"
435 " %c%c%c%c%c%c%c%c", (p
- (u_char
*)buf
),
436 p
[0], p
[1], p
[2], p
[3], p
[4], p
[5], p
[6], p
[7],
437 DISP(p
[0]), DISP(p
[1]), DISP(p
[2]), DISP(p
[3]),
438 DISP(p
[4]), DISP(p
[5]), DISP(p
[6]), DISP(p
[7]));
446 /********************************************************************
448 ********************************************************************/
451 * This table describes what interrupts we should ever expect to
452 * see after each ICH command, not including the SMBALERT interrupt.
454 static const u_int8_t ichsmb_state_irqs
[] = {
456 (ICH_HST_STA_BUS_ERR
| ICH_HST_STA_DEV_ERR
| ICH_HST_STA_INTR
),
458 (ICH_HST_STA_BUS_ERR
| ICH_HST_STA_DEV_ERR
| ICH_HST_STA_INTR
),
460 (ICH_HST_STA_BUS_ERR
| ICH_HST_STA_DEV_ERR
| ICH_HST_STA_INTR
),
462 (ICH_HST_STA_BUS_ERR
| ICH_HST_STA_DEV_ERR
| ICH_HST_STA_INTR
),
464 (ICH_HST_STA_BUS_ERR
| ICH_HST_STA_DEV_ERR
| ICH_HST_STA_INTR
),
466 (ICH_HST_STA_BUS_ERR
| ICH_HST_STA_DEV_ERR
| ICH_HST_STA_INTR
467 | ICH_HST_STA_BYTE_DONE_STS
),
468 /* i2c read (not used) */
469 (ICH_HST_STA_BUS_ERR
| ICH_HST_STA_DEV_ERR
| ICH_HST_STA_INTR
470 | ICH_HST_STA_BYTE_DONE_STS
)
474 * Interrupt handler. This handler is bus-independent. Note that our
475 * interrupt may be shared, so we must handle "false" interrupts.
478 ichsmb_device_intr(void *cookie
)
480 const sc_p sc
= cookie
;
481 const device_t dev
= sc
->dev
;
482 const int maxloops
= 16;
489 for (count
= 0; count
< maxloops
; count
++) {
491 /* Get and reset status bits */
492 status
= bus_space_read_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_STA
);
494 if ((status
& ~(ICH_HST_STA_INUSE_STS
| ICH_HST_STA_HOST_BUSY
))
496 DBG("%d stat=0x%02x\n", count
, status
);
499 status
&= ~(ICH_HST_STA_INUSE_STS
| ICH_HST_STA_HOST_BUSY
);
503 /* Check for unexpected interrupt */
504 ok_bits
= ICH_HST_STA_SMBALERT_STS
;
505 cmd_index
= sc
->ich_cmd
>> 2;
506 if (sc
->ich_cmd
!= -1) {
507 KASSERT(cmd_index
< sizeof(ichsmb_state_irqs
),
508 ("%s: ich_cmd=%d", device_get_nameunit(dev
),
510 ok_bits
|= ichsmb_state_irqs
[cmd_index
];
512 if ((status
& ~ok_bits
) != 0) {
513 log(LOG_ERR
, "%s: irq 0x%02x during %d\n",
514 device_get_nameunit(dev
), status
, cmd_index
);
515 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
,
516 ICH_HST_STA
, (status
& ~ok_bits
));
520 /* Handle SMBALERT interrupt */
521 if (status
& ICH_HST_STA_SMBALERT_STS
) {
522 static int smbalert_count
= 16;
523 if (smbalert_count
> 0) {
524 log(LOG_WARNING
, "%s: SMBALERT# rec'd\n",
525 device_get_nameunit(dev
));
526 if (--smbalert_count
== 0) {
528 "%s: not logging anymore\n",
529 device_get_nameunit(dev
));
534 /* Check for bus error */
535 if (status
& ICH_HST_STA_BUS_ERR
) {
536 sc
->smb_error
= SMB_ECOLLI
; /* XXX SMB_EBUSERR? */
540 /* Check for device error */
541 if (status
& ICH_HST_STA_DEV_ERR
) {
542 sc
->smb_error
= SMB_ENOACK
; /* or SMB_ETIMEOUT? */
546 /* Check for byte completion in block transfer */
547 if (status
& ICH_HST_STA_BYTE_DONE_STS
) {
548 if (sc
->block_write
) {
549 if (sc
->block_index
< sc
->block_count
) {
551 /* Write next byte */
552 bus_space_write_1(sc
->io_bst
,
553 sc
->io_bsh
, ICH_BLOCK_DB
,
554 sc
->block_data
[sc
->block_index
++]);
558 /* First interrupt, get the count also */
559 if (sc
->block_index
== 0) {
560 sc
->block_count
= bus_space_read_1(
561 sc
->io_bst
, sc
->io_bsh
, ICH_D0
);
564 /* Get next byte, if any */
565 if (sc
->block_index
< sc
->block_count
) {
568 sc
->block_data
[sc
->block_index
++] =
569 bus_space_read_1(sc
->io_bst
,
570 sc
->io_bsh
, ICH_BLOCK_DB
);
572 /* Set "LAST_BYTE" bit before reading
573 the last byte of block data */
575 >= sc
->block_count
- 1) {
576 bus_space_write_1(sc
->io_bst
,
577 sc
->io_bsh
, ICH_HST_CNT
,
578 ICH_HST_CNT_LAST_BYTE
586 /* Check command completion */
587 if (status
& ICH_HST_STA_INTR
) {
588 sc
->smb_error
= SMB_ENOERR
;
591 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
,
592 ICH_HST_STA
, status
);
597 /* Clear status bits and try again */
598 bus_space_write_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_STA
, status
);
602 /* Too many loops? */
603 if (count
== maxloops
) {
604 log(LOG_ERR
, "%s: interrupt loop, status=0x%02x\n",
605 device_get_nameunit(dev
),
606 bus_space_read_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_STA
));
611 * Wait for command completion. Assumes a critical section.
612 * Returns an SMB_* error code.
617 const device_t dev
= sc
->dev
;
618 int error
, smb_error
;
620 KASSERT(sc
->ich_cmd
!= -1,
621 ("%s: ich_cmd=%d\n", __func__
, sc
->ich_cmd
));
623 error
= tsleep(sc
, PCATCH
, "ichsmb", hz
/ 4);
624 DBG("tsleep -> %d\n", error
);
627 if (sc
->ich_cmd
!= -1)
631 smb_error
= sc
->smb_error
;
634 log(LOG_ERR
, "%s: device timeout, status=0x%02x\n",
635 device_get_nameunit(dev
),
636 bus_space_read_1(sc
->io_bst
, sc
->io_bsh
, ICH_HST_STA
));
638 smb_error
= SMB_ETIMEOUT
;
641 smb_error
= SMB_EABORT
;
648 * Release resources associated with device.
651 ichsmb_release_resources(sc_p sc
)
653 const device_t dev
= sc
->dev
;
655 if (sc
->irq_handle
!= NULL
) {
656 bus_teardown_intr(dev
, sc
->irq_res
, sc
->irq_handle
);
657 sc
->irq_handle
= NULL
;
659 if (sc
->irq_res
!= NULL
) {
660 bus_release_resource(dev
,
661 SYS_RES_IRQ
, sc
->irq_rid
, sc
->irq_res
);
664 if (sc
->io_res
!= NULL
) {
665 bus_release_resource(dev
,
666 SYS_RES_IOPORT
, sc
->io_rid
, sc
->io_res
);