/* * dm2s_start - Start transmission function. * * Send all queued messages. If the mailbox is busy, then * start a timeout as a polling mechanism. The timeout is useful * to not rely entirely on the SCF_MB_SPACE event. */ void dm2s_start(queue_t *wq, dm2s_t *dm2sp) { mblk_t *mp; int ret; DPRINTF(DBG_DRV, ("dm2s_start: called\n")); ASSERT(dm2sp != NULL); ASSERT(MUTEX_HELD(&dm2sp->ms_lock)); while ((mp = getq(wq)) != NULL) { switch (mp->b_datap->db_type) { case M_DATA: ret = dm2s_transmit(wq, mp, dm2sp->ms_target, dm2sp->ms_key); if (ret == EBUSY || ret == ENOSPC || ret == EAGAIN) { DPRINTF(DBG_MBOX, ("dm2s_start: recoverable err=%d\n", ret)); /* * Start a timeout to retry again. */ if (dm2sp->ms_wq_timeoutid == 0) { DTRACE_PROBE1(dm2s_wqtimeout__start, dm2s_t, dm2sp); dm2sp->ms_wq_timeoutid = qtimeout(wq, dm2s_wq_timeout, (void *)dm2sp, dm2s_timeout_val(ret)); } return; } else if (ret != 0) { mutex_exit(&dm2sp->ms_lock); /* * An error occurred with the transmission, * flush pending messages and initiate a * hangup. */ flushq(wq, FLUSHDATA); (void) putnextctl(RD(wq), M_HANGUP); DTRACE_PROBE1(dm2s_hangup, dm2s_t, dm2sp); DPRINTF(DBG_WARN, ("dm2s_start: hangup transmit err=%d\n", ret)); mutex_enter(&dm2sp->ms_lock); } break; default: /* * At this point, we don't expect any other messages. */ freemsg(mp); break; } } }
static void recover(queue_t *q, mblk_t *mp, size_t size) { bufcall_id_t bid; timeout_id_t tid; struct telmod_info *tmip = (struct telmod_info *)q->q_ptr; ASSERT(mp->b_datap->db_type < QPCTL); noenable(q); (void) putbq(q, mp); /* * Make sure there is at most one outstanding request per queue. */ if (q->q_flag & QREADR) { if (tmip->rtimoutid || tmip->rbufcid) { return; } } else { if (tmip->wtimoutid || tmip->wbufcid) { return; } } if (!(bid = qbufcall(RD(q), size, BPRI_MED, telmod_buffer, q))) { tid = qtimeout(RD(q), telmod_timer, q, SIMWAIT); if (q->q_flag & QREADR) tmip->rtimoutid = tid; else tmip->wtimoutid = tid; } else { if (q->q_flag & QREADR) tmip->rbufcid = bid; else tmip->wbufcid = bid; } }
/* * dm2s_receive - Read all messages from the mailbox. * * This function is called from the read service procedure, to * receive the messages awaiting in the mailbox. */ void dm2s_receive(dm2s_t *dm2sp) { queue_t *rq = dm2sp->ms_rq; mblk_t *mp; int ret; uint32_t len; DPRINTF(DBG_DRV, ("dm2s_receive: called\n")); ASSERT(dm2sp != NULL); ASSERT(MUTEX_HELD(&dm2sp->ms_lock)); if (rq == NULL) { return; } /* * As the number of messages in the mailbox are pretty limited, * it is safe to process all messages in one loop. */ while (DM2S_MBOX_READY(dm2sp) && ((ret = scf_mb_canget(dm2sp->ms_target, dm2sp->ms_key, &len)) == 0)) { DPRINTF(DBG_MBOX, ("dm2s_receive: mb_canget len=%d\n", len)); if (len == 0) { break; } mp = allocb(len, BPRI_MED); if (mp == NULL) { DPRINTF(DBG_WARN, ("dm2s_receive: allocb failed\n")); /* * Start a bufcall so that we can retry again * when memory becomes available. */ dm2sp->ms_rbufcid = qbufcall(rq, len, BPRI_MED, dm2s_bufcall_rcv, dm2sp); if (dm2sp->ms_rbufcid == 0) { DPRINTF(DBG_WARN, ("dm2s_receive: qbufcall failed\n")); /* * if bufcall fails, start a timeout to * initiate a re-try after some time. */ DTRACE_PROBE1(dm2s_rqtimeout__start, dm2s_t, dm2sp); dm2sp->ms_rq_timeoutid = qtimeout(rq, dm2s_rq_timeout, (void *)dm2sp, drv_usectohz(DM2S_SM_TOUT)); } break; } /* * Only a single scatter/gather element is enough here. */ dm2sp->ms_sg_rcv.msc_dptr = (caddr_t)mp->b_wptr; dm2sp->ms_sg_rcv.msc_len = len; DPRINTF(DBG_MBOX, ("dm2s_receive: calling getmsg\n")); ret = scf_mb_getmsg(dm2sp->ms_target, dm2sp->ms_key, len, 1, &dm2sp->ms_sg_rcv, 0); DPRINTF(DBG_MBOX, ("dm2s_receive: getmsg ret=%d\n", ret)); if (ret != 0) { freemsg(mp); break; } DMPBYTES("dm2s: Getmsg: ", len, 1, &dm2sp->ms_sg_rcv); mp->b_wptr += len; /* * Queue the messages in the rq, so that the service * procedure handles sending the messages up the stream. */ putq(rq, mp); } if ((!DM2S_MBOX_READY(dm2sp)) || (ret != ENOMSG && ret != EMSGSIZE)) { /* * Some thing went wrong, flush pending messages * and initiate a hangup. * Note: flushing the wq initiates a faster close. */ mutex_exit(&dm2sp->ms_lock); flushq(WR(rq), FLUSHDATA); (void) putnextctl(rq, M_HANGUP); DTRACE_PROBE1(dm2s_hangup, dm2s_t, dm2sp); mutex_enter(&dm2sp->ms_lock); DPRINTF(DBG_WARN, ("dm2s_receive: encountered unknown " "condition - hangup ret=%d\n", ret)); } }
/* * Returns 1 if the caller should put the message (bp) back on the queue */ static int mouse8042_initiate_reset(queue_t *q, mblk_t *mp, struct mouse_state *state) { mutex_enter(&state->reset_mutex); /* * If we're in the middle of a reset, put the message back on the queue * for processing later. */ if (state->reset_state != MSE_RESET_IDLE) { /* * We noenable the queue again here in case it was backenabled * by an upper-level module. */ noenable(q); mutex_exit(&state->reset_mutex); return (1); } /* * Drop the reset state lock before allocating the response message and * grabbing the 8042 exclusive-access lock (since those operations * may take an extended period of time to complete). */ mutex_exit(&state->reset_mutex); if (state->reply_mp == NULL) state->reply_mp = allocb(2, BPRI_MED); if (state->reset_ack_mp == NULL) state->reset_ack_mp = allocb(1, BPRI_MED); if (state->reply_mp == NULL || state->reset_ack_mp == NULL) { /* * Allocation failed -- set up a bufcall to enable the queue * whenever there is enough memory to allocate the response * message. */ state->bc_id = qbufcall(q, (state->reply_mp == NULL) ? 2 : 1, BPRI_MED, (void (*)(void *))qenable, q); if (state->bc_id == 0) { /* * If the qbufcall failed, we cannot proceed, so use the * message we were sent to respond with an error. */ *mp->b_rptr = MSEERROR; mp->b_wptr = mp->b_rptr + 1; qreply(q, mp); return (0); } return (1); } else { /* Bufcall completed successfully (or wasn't needed) */ state->bc_id = 0; } /* * Gain exclusive access to the 8042 for the duration of the reset. * The unlock will occur when the reset has either completed or timed * out. */ (void) ddi_get8(state->ms_handle, state->ms_addr + I8042_LOCK); mutex_enter(&state->reset_mutex); state->reset_state = MSE_RESET_PRE; noenable(q); state->reset_tid = qtimeout(q, mouse8042_reset_timeout, state, drv_usectohz( MOUSE8042_RESET_TIMEOUT_USECS)); ddi_put8(state->ms_handle, state->ms_addr + I8042_INT_OUTPUT_DATA, MSERESET); mp->b_rptr++; mutex_exit(&state->reset_mutex); return (1); }