Synchronize with sys/i386/isa/fd.c, isa.c and sio.c revisions 1.103,

1.105 and 1.183, respectively.
This commit is contained in:
KATO Takenori 1997-09-22 12:23:49 +00:00
parent 82ed62a794
commit e79c5cf3a8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=29715
5 changed files with 68 additions and 39 deletions

View File

@ -43,7 +43,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91 * from: @(#)fd.c 7.4 (Berkeley) 5/25/91
* $Id: fd.c,v 1.21 1997/09/17 08:01:07 kato Exp $ * $Id: fd.c,v 1.22 1997/09/18 08:10:45 kato Exp $
* *
*/ */
@ -207,6 +207,8 @@ static struct fd_data {
#ifdef notyet #ifdef notyet
int dkunit; /* disk stats unit number */ int dkunit; /* disk stats unit number */
#endif #endif
struct callout_handle toffhandle;
struct callout_handle tohandle;
#ifdef DEVFS #ifdef DEVFS
void *bdevs[1 + NUMDENS + MAXPARTITIONS]; void *bdevs[1 + NUMDENS + MAXPARTITIONS];
void *cdevs[1 + NUMDENS + MAXPARTITIONS]; void *cdevs[1 + NUMDENS + MAXPARTITIONS];
@ -730,7 +732,7 @@ fdattach(struct isa_device *dev)
/* reset controller, turn motor off, clear fdout mirror reg */ /* reset controller, turn motor off, clear fdout mirror reg */
outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); outb(fdc->baseport + FDOUT, ((fdc->fdout = 0)));
#endif #endif
TAILQ_INIT(&fdc->head); bufq_init(&fdc->head);
/* check for each floppy drive */ /* check for each floppy drive */
for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) {
@ -913,6 +915,8 @@ fdattach(struct isa_device *dev)
fd->fdc = fdc; fd->fdc = fdc;
fd->fdsu = fdsu; fd->fdsu = fdsu;
fd->options = 0; fd->options = 0;
callout_handle_init(&fd->toffhandle);
callout_handle_init(&fd->tohandle);
printf("fd%d: ", fdu); printf("fd%d: ", fdu);
switch (fdt) { switch (fdt) {
@ -1142,7 +1146,7 @@ fd_turnoff(void *arg1)
* and nothing is queued on it. * and nothing is queued on it.
*/ */
if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fdu) { if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fdu) {
timeout(fd_turnoff, arg1, 4 * hz); fd->toffhandle = timeout(fd_turnoff, arg1, 4 * hz);
return; return;
} }
@ -1484,8 +1488,8 @@ fdstrategy(struct buf *bp)
} }
bp->b_pblkno = bp->b_blkno; bp->b_pblkno = bp->b_blkno;
s = splbio(); s = splbio();
tqdisksort(&fdc->head, bp); bufqdisksort(&fdc->head, bp);
untimeout(fd_turnoff, (caddr_t)fdu); /* a good idea */ untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); /* a good idea */
fdstart(fdcu); fdstart(fdcu);
splx(s); splx(s);
return; return;
@ -1525,7 +1529,7 @@ fd_timeout(void *arg1)
struct buf *bp; struct buf *bp;
int s; int s;
bp = TAILQ_FIRST(&fdc_data[fdcu].head); bp = bufq_first(&fdc_data[fdcu].head);
/* /*
* Due to IBM's brain-dead design, the FDC has a faked ready * Due to IBM's brain-dead design, the FDC has a faked ready
@ -1613,7 +1617,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
struct fd_formb *finfo = NULL; struct fd_formb *finfo = NULL;
size_t fdblk; size_t fdblk;
bp = TAILQ_FIRST(&fdc->head); bp = bufq_first(&fdc->head);
if(!bp) { if(!bp) {
/***********************************************\ /***********************************************\
* nothing left for this controller to do * * nothing left for this controller to do *
@ -1652,7 +1656,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
TRACE1("fd%d", fdu); TRACE1("fd%d", fdu);
TRACE1("[%s]", fdstates[fdc->state]); TRACE1("[%s]", fdstates[fdc->state]);
TRACE1("(0x%x)", fd->flags); TRACE1("(0x%x)", fd->flags);
untimeout(fd_turnoff, (caddr_t)fdu); untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle);
timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); timeout(fd_turnoff, (caddr_t)fdu, 4 * hz);
switch (fdc->state) switch (fdc->state)
{ {
@ -1905,7 +1909,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
} }
} }
fdc->state = IOCOMPLETE; fdc->state = IOCOMPLETE;
timeout(fd_timeout, (caddr_t)fdcu, hz); fd->tohandle = timeout(fd_timeout, (caddr_t)fdcu, hz);
return(0); /* will return later */ return(0); /* will return later */
#ifdef EPSON_NRDISK #ifdef EPSON_NRDISK
} }
@ -1939,9 +1943,10 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
#endif #endif
case IOCOMPLETE: /* IO DONE, post-analyze */ case IOCOMPLETE: /* IO DONE, post-analyze */
#ifdef EPSON_NRDISK #ifdef EPSON_NRDISK
if (fdu != nrdu) untimeout(fd_timeout, (caddr_t)fdcu); if (fdu != nrdu)
untimeout(fd_timeout, (caddr_t)fdcu, fd->tohandle);
#else #else
untimeout(fd_timeout, (caddr_t)fdcu); untimeout(fd_timeout, (caddr_t)fdcu, fd->tohandle);
#endif #endif
if (fd_read_status(fdc, fd->fdsu)) if (fd_read_status(fdc, fd->fdsu))
@ -1999,7 +2004,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
{ {
/* ALL DONE */ /* ALL DONE */
fd->skip = 0; fd->skip = 0;
TAILQ_REMOVE(&fdc->head, bp, b_act); bufq_remove(&fdc->head, bp);
biodone(bp); biodone(bp);
fdc->fd = (fd_p) 0; fdc->fd = (fd_p) 0;
fdc->fdu = -1; fdc->fdu = -1;
@ -2118,7 +2123,7 @@ retrier(fdcu)
fdc_p fdc = fdc_data + fdcu; fdc_p fdc = fdc_data + fdcu;
register struct buf *bp; register struct buf *bp;
bp = TAILQ_FIRST(&fdc->head); bp = bufq_first(&fdc->head);
if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY)
goto fail; goto fail;
@ -2162,7 +2167,7 @@ retrier(fdcu)
bp->b_flags |= B_ERROR; bp->b_flags |= B_ERROR;
bp->b_error = EIO; bp->b_error = EIO;
bp->b_resid += bp->b_bcount - fdc->fd->skip; bp->b_resid += bp->b_bcount - fdc->fd->skip;
TAILQ_REMOVE(&fdc->head, bp, b_act); bufq_remove(&fdc->head, bp);
fdc->fd->skip = 0; fdc->fd->skip = 0;
biodone(bp); biodone(bp);
fdc->state = FINDWORK; fdc->state = FINDWORK;

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)com.c 7.5 (Berkeley) 5/16/91 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
* $Id: sio.c,v 1.37 1997/09/14 16:27:35 kato Exp $ * $Id: sio.c,v 1.38 1997/09/20 05:28:02 kato Exp $
*/ */
#include "opt_comconsole.h" #include "opt_comconsole.h"
@ -468,6 +468,8 @@ static u_int com_events; /* input chars + weighted output completions */
static Port_t siocniobase; static Port_t siocniobase;
static int sio_timeout; static int sio_timeout;
static int sio_timeouts_until_log; static int sio_timeouts_until_log;
static struct callout_handle sio_timeout_handle
= CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
#if 0 /* XXX */ #if 0 /* XXX */
static struct tty *sio_tty[NSIOTOT]; static struct tty *sio_tty[NSIOTOT];
#else #else
@ -3099,7 +3101,7 @@ siosettimeout()
* Otherwise set it to max(1/200, 1/hz). * Otherwise set it to max(1/200, 1/hz).
* Enable timeouts iff some device is open. * Enable timeouts iff some device is open.
*/ */
untimeout(comwakeup, (void *)NULL); untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
sio_timeout = hz; sio_timeout = hz;
someopen = FALSE; someopen = FALSE;
for (unit = 0; unit < NSIOTOT; ++unit) { for (unit = 0; unit < NSIOTOT; ++unit) {
@ -3115,12 +3117,13 @@ siosettimeout()
} }
if (someopen) { if (someopen) {
sio_timeouts_until_log = hz / sio_timeout; sio_timeouts_until_log = hz / sio_timeout;
timeout(comwakeup, (void *)NULL, sio_timeout); sio_timeout_handle = timeout(comwakeup, (void *)NULL,
sio_timeout);
} else { } else {
/* Flush error messages, if any. */ /* Flush error messages, if any. */
sio_timeouts_until_log = 1; sio_timeouts_until_log = 1;
comwakeup((void *)NULL); comwakeup((void *)NULL);
untimeout(comwakeup, (void *)NULL); untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
} }
} }
@ -3131,7 +3134,7 @@ comwakeup(chan)
struct com_s *com; struct com_s *com;
int unit; int unit;
timeout(comwakeup, (void *)NULL, sio_timeout); sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
/* /*
* Recover from lost output interrupts. * Recover from lost output interrupts.

View File

@ -43,7 +43,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)fd.c 7.4 (Berkeley) 5/25/91 * from: @(#)fd.c 7.4 (Berkeley) 5/25/91
* $Id: fd.c,v 1.21 1997/09/17 08:01:07 kato Exp $ * $Id: fd.c,v 1.22 1997/09/18 08:10:45 kato Exp $
* *
*/ */
@ -207,6 +207,8 @@ static struct fd_data {
#ifdef notyet #ifdef notyet
int dkunit; /* disk stats unit number */ int dkunit; /* disk stats unit number */
#endif #endif
struct callout_handle toffhandle;
struct callout_handle tohandle;
#ifdef DEVFS #ifdef DEVFS
void *bdevs[1 + NUMDENS + MAXPARTITIONS]; void *bdevs[1 + NUMDENS + MAXPARTITIONS];
void *cdevs[1 + NUMDENS + MAXPARTITIONS]; void *cdevs[1 + NUMDENS + MAXPARTITIONS];
@ -730,7 +732,7 @@ fdattach(struct isa_device *dev)
/* reset controller, turn motor off, clear fdout mirror reg */ /* reset controller, turn motor off, clear fdout mirror reg */
outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); outb(fdc->baseport + FDOUT, ((fdc->fdout = 0)));
#endif #endif
TAILQ_INIT(&fdc->head); bufq_init(&fdc->head);
/* check for each floppy drive */ /* check for each floppy drive */
for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) {
@ -913,6 +915,8 @@ fdattach(struct isa_device *dev)
fd->fdc = fdc; fd->fdc = fdc;
fd->fdsu = fdsu; fd->fdsu = fdsu;
fd->options = 0; fd->options = 0;
callout_handle_init(&fd->toffhandle);
callout_handle_init(&fd->tohandle);
printf("fd%d: ", fdu); printf("fd%d: ", fdu);
switch (fdt) { switch (fdt) {
@ -1142,7 +1146,7 @@ fd_turnoff(void *arg1)
* and nothing is queued on it. * and nothing is queued on it.
*/ */
if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fdu) { if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fdu) {
timeout(fd_turnoff, arg1, 4 * hz); fd->toffhandle = timeout(fd_turnoff, arg1, 4 * hz);
return; return;
} }
@ -1484,8 +1488,8 @@ fdstrategy(struct buf *bp)
} }
bp->b_pblkno = bp->b_blkno; bp->b_pblkno = bp->b_blkno;
s = splbio(); s = splbio();
tqdisksort(&fdc->head, bp); bufqdisksort(&fdc->head, bp);
untimeout(fd_turnoff, (caddr_t)fdu); /* a good idea */ untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); /* a good idea */
fdstart(fdcu); fdstart(fdcu);
splx(s); splx(s);
return; return;
@ -1525,7 +1529,7 @@ fd_timeout(void *arg1)
struct buf *bp; struct buf *bp;
int s; int s;
bp = TAILQ_FIRST(&fdc_data[fdcu].head); bp = bufq_first(&fdc_data[fdcu].head);
/* /*
* Due to IBM's brain-dead design, the FDC has a faked ready * Due to IBM's brain-dead design, the FDC has a faked ready
@ -1613,7 +1617,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
struct fd_formb *finfo = NULL; struct fd_formb *finfo = NULL;
size_t fdblk; size_t fdblk;
bp = TAILQ_FIRST(&fdc->head); bp = bufq_first(&fdc->head);
if(!bp) { if(!bp) {
/***********************************************\ /***********************************************\
* nothing left for this controller to do * * nothing left for this controller to do *
@ -1652,7 +1656,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
TRACE1("fd%d", fdu); TRACE1("fd%d", fdu);
TRACE1("[%s]", fdstates[fdc->state]); TRACE1("[%s]", fdstates[fdc->state]);
TRACE1("(0x%x)", fd->flags); TRACE1("(0x%x)", fd->flags);
untimeout(fd_turnoff, (caddr_t)fdu); untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle);
timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); timeout(fd_turnoff, (caddr_t)fdu, 4 * hz);
switch (fdc->state) switch (fdc->state)
{ {
@ -1905,7 +1909,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
} }
} }
fdc->state = IOCOMPLETE; fdc->state = IOCOMPLETE;
timeout(fd_timeout, (caddr_t)fdcu, hz); fd->tohandle = timeout(fd_timeout, (caddr_t)fdcu, hz);
return(0); /* will return later */ return(0); /* will return later */
#ifdef EPSON_NRDISK #ifdef EPSON_NRDISK
} }
@ -1939,9 +1943,10 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
#endif #endif
case IOCOMPLETE: /* IO DONE, post-analyze */ case IOCOMPLETE: /* IO DONE, post-analyze */
#ifdef EPSON_NRDISK #ifdef EPSON_NRDISK
if (fdu != nrdu) untimeout(fd_timeout, (caddr_t)fdcu); if (fdu != nrdu)
untimeout(fd_timeout, (caddr_t)fdcu, fd->tohandle);
#else #else
untimeout(fd_timeout, (caddr_t)fdcu); untimeout(fd_timeout, (caddr_t)fdcu, fd->tohandle);
#endif #endif
if (fd_read_status(fdc, fd->fdsu)) if (fd_read_status(fdc, fd->fdsu))
@ -1999,7 +2004,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc)
{ {
/* ALL DONE */ /* ALL DONE */
fd->skip = 0; fd->skip = 0;
TAILQ_REMOVE(&fdc->head, bp, b_act); bufq_remove(&fdc->head, bp);
biodone(bp); biodone(bp);
fdc->fd = (fd_p) 0; fdc->fd = (fd_p) 0;
fdc->fdu = -1; fdc->fdu = -1;
@ -2118,7 +2123,7 @@ retrier(fdcu)
fdc_p fdc = fdc_data + fdcu; fdc_p fdc = fdc_data + fdcu;
register struct buf *bp; register struct buf *bp;
bp = TAILQ_FIRST(&fdc->head); bp = bufq_first(&fdc->head);
if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY)
goto fail; goto fail;
@ -2162,7 +2167,7 @@ retrier(fdcu)
bp->b_flags |= B_ERROR; bp->b_flags |= B_ERROR;
bp->b_error = EIO; bp->b_error = EIO;
bp->b_resid += bp->b_bcount - fdc->fd->skip; bp->b_resid += bp->b_bcount - fdc->fd->skip;
TAILQ_REMOVE(&fdc->head, bp, b_act); bufq_remove(&fdc->head, bp);
fdc->fd->skip = 0; fdc->fd->skip = 0;
biodone(bp); biodone(bp);
fdc->state = FINDWORK; fdc->state = FINDWORK;

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91 * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
* $Id: pc98.c,v 1.40 1997/08/28 09:15:31 kato Exp $ * $Id: pc98.c,v 1.41 1997/09/20 05:29:03 kato Exp $
*/ */
/* /*
@ -338,6 +338,11 @@ haveseen_isadev(dvp, checkbits)
if (status) if (status)
return status; return status;
} }
for (tmpdvp = isa_devtab_cam; tmpdvp->id_driver; tmpdvp++) {
status |= haveseen(dvp, tmpdvp, checkbits);
if (status)
return status;
}
for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) {
status |= haveseen(dvp, tmpdvp, checkbits); status |= haveseen(dvp, tmpdvp, checkbits);
if (status) if (status)
@ -377,6 +382,9 @@ isa_configure() {
for (dvp = isa_devtab_net; dvp->id_driver; dvp++) for (dvp = isa_devtab_net; dvp->id_driver; dvp++)
if (dvp->id_driver->sensitive_hw) if (dvp->id_driver->sensitive_hw)
config_isadev(dvp, &net_imask); config_isadev(dvp, &net_imask);
for (dvp = isa_devtab_cam; dvp->id_driver; dvp++)
if (dvp->id_driver->sensitive_hw)
config_isadev(dvp, &cam_imask);
for (dvp = isa_devtab_null; dvp->id_driver; dvp++) for (dvp = isa_devtab_null; dvp->id_driver; dvp++)
if (dvp->id_driver->sensitive_hw) if (dvp->id_driver->sensitive_hw)
config_isadev(dvp, (u_int *)NULL); config_isadev(dvp, (u_int *)NULL);
@ -391,6 +399,9 @@ isa_configure() {
for (dvp = isa_devtab_net; dvp->id_driver; dvp++) for (dvp = isa_devtab_net; dvp->id_driver; dvp++)
if (!dvp->id_driver->sensitive_hw) if (!dvp->id_driver->sensitive_hw)
config_isadev(dvp, &net_imask); config_isadev(dvp, &net_imask);
for (dvp = isa_devtab_cam; dvp->id_driver; dvp++)
if (!dvp->id_driver->sensitive_hw)
config_isadev(dvp, &cam_imask);
for (dvp = isa_devtab_null; dvp->id_driver; dvp++) for (dvp = isa_devtab_null; dvp->id_driver; dvp++)
if (!dvp->id_driver->sensitive_hw) if (!dvp->id_driver->sensitive_hw)
config_isadev(dvp, (u_int *)NULL); config_isadev(dvp, (u_int *)NULL);
@ -435,6 +446,8 @@ isa_configure() {
register_imask(dvp, bio_imask); register_imask(dvp, bio_imask);
for (dvp = isa_devtab_net; dvp->id_driver; dvp++) for (dvp = isa_devtab_net; dvp->id_driver; dvp++)
register_imask(dvp, net_imask); register_imask(dvp, net_imask);
for (dvp = isa_devtab_cam; dvp->id_driver; dvp++)
register_imask(dvp, cam_imask);
for (dvp = isa_devtab_null; dvp->id_driver; dvp++) for (dvp = isa_devtab_null; dvp->id_driver; dvp++)
register_imask(dvp, SWI_CLOCK_MASK); register_imask(dvp, SWI_CLOCK_MASK);
spl0(); spl0();

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)com.c 7.5 (Berkeley) 5/16/91 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
* $Id: sio.c,v 1.37 1997/09/14 16:27:35 kato Exp $ * $Id: sio.c,v 1.38 1997/09/20 05:28:02 kato Exp $
*/ */
#include "opt_comconsole.h" #include "opt_comconsole.h"
@ -468,6 +468,8 @@ static u_int com_events; /* input chars + weighted output completions */
static Port_t siocniobase; static Port_t siocniobase;
static int sio_timeout; static int sio_timeout;
static int sio_timeouts_until_log; static int sio_timeouts_until_log;
static struct callout_handle sio_timeout_handle
= CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
#if 0 /* XXX */ #if 0 /* XXX */
static struct tty *sio_tty[NSIOTOT]; static struct tty *sio_tty[NSIOTOT];
#else #else
@ -3099,7 +3101,7 @@ siosettimeout()
* Otherwise set it to max(1/200, 1/hz). * Otherwise set it to max(1/200, 1/hz).
* Enable timeouts iff some device is open. * Enable timeouts iff some device is open.
*/ */
untimeout(comwakeup, (void *)NULL); untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
sio_timeout = hz; sio_timeout = hz;
someopen = FALSE; someopen = FALSE;
for (unit = 0; unit < NSIOTOT; ++unit) { for (unit = 0; unit < NSIOTOT; ++unit) {
@ -3115,12 +3117,13 @@ siosettimeout()
} }
if (someopen) { if (someopen) {
sio_timeouts_until_log = hz / sio_timeout; sio_timeouts_until_log = hz / sio_timeout;
timeout(comwakeup, (void *)NULL, sio_timeout); sio_timeout_handle = timeout(comwakeup, (void *)NULL,
sio_timeout);
} else { } else {
/* Flush error messages, if any. */ /* Flush error messages, if any. */
sio_timeouts_until_log = 1; sio_timeouts_until_log = 1;
comwakeup((void *)NULL); comwakeup((void *)NULL);
untimeout(comwakeup, (void *)NULL); untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
} }
} }
@ -3131,7 +3134,7 @@ comwakeup(chan)
struct com_s *com; struct com_s *com;
int unit; int unit;
timeout(comwakeup, (void *)NULL, sio_timeout); sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
/* /*
* Recover from lost output interrupts. * Recover from lost output interrupts.