Example 9–6 shows the interrupt handling for the printer driver.
lpintr is the driver-interrupt handler registered by the attach routine.
lpout takes a single character from the queue and sends it to the printer. For convenience, the message currently being output is stored in lp->msg in the per-instance structure. This assumes that the message is called with the mutex held.
lpoutchar sends a single character to the printer (in this case the system console using cmn_err(9F)) and interrupts when complete. Of course, hardware would generate a hard interrupt, so the call to ddi_trigger_softintr(9F) would be unnecessary.
/* Device interrupt routine */static uint
lpintr(caddr_t lp) /* minor device number of lp */
{
struct lp *lpp = (struct lp *)lp;
mutex_enter(&lpp->lp_lock);
if (!(lpp->flags & BUSY)) {
mutex_exit(&lpp->lp_lock);
return (DDI_INTR_UNCLAIMED);
}
lpp->flags &= ~BUSY;
lpout(lpp);
mutex_exit(&lpp->lp_lock);
return (DDI_INTR_CLAIMED);
}
/* Start output to device - used by put procedure and driver */
static void
lpout(
struct lp *lp)
{
mblk_t *bp;
queue_t *q;
q = lp->qptr;
loop:
if ((bp = lp->msg) == NULL) { /*no current message*/
if ((bp = getq(q)) == NULL) {
lp->flags &= ~BUSY;
return;
}
if (bp->b_datap->db_type == M_IOCTL) {
/* lpdoioctl(lp, bp); */
goto loop;
}
lp->msg = bp; /* new message */
}
if (bp->b_rptr >= bp->b_wptr) { /* validate message */
bp = lp->msg->b_cont;
lp->msg->b_cont = NULL;
freeb(lp->msg);
lp->msg = bp;
goto loop;
}
lpoutchar(lp, *bp->b_rptr++); /*output one character*/
lp->flags |= BUSY;
}
static void
lpoutchar(
struct lp *lp,
char c)
{
cmn_err(CE_CONT, “%c”, c);
ddi_trigger_softintr(lp->siid);
}