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)); } }
/*ARGSUSED*/ static int telmodopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *credp) { struct telmod_info *tmip; mblk_t *bp; union T_primitives *tp; int error; if (sflag != MODOPEN) return (EINVAL); if (q->q_ptr != NULL) { /* It's already attached. */ return (0); } /* * Allocate state structure. */ tmip = kmem_zalloc(sizeof (*tmip), KM_SLEEP); /* * Cross-link. */ q->q_ptr = tmip; WR(q)->q_ptr = tmip; noenable(q); tmip->flags |= TEL_STOPPED; qprocson(q); /* * Since TCP operates in the TLI-inspired brain-dead fashion, * the connection will revert to bound state if the connection * is reset by the client. We must send a T_UNBIND_REQ in * that case so the port doesn't get "wedged" (preventing * inetd from being able to restart the listener). Allocate * it here, so that we don't need to worry about allocb() * failures later. */ while ((tmip->unbind_mp = allocb(sizeof (union T_primitives), BPRI_HI)) == NULL) { bufcall_id_t id = qbufcall(q, sizeof (union T_primitives), BPRI_HI, dummy_callback, NULL); if (!qwait_sig(q)) { qunbufcall(q, id); error = EINTR; goto fail; } qunbufcall(q, id); } tmip->unbind_mp->b_wptr = tmip->unbind_mp->b_rptr + sizeof (struct T_unbind_req); tmip->unbind_mp->b_datap->db_type = M_PROTO; tp = (union T_primitives *)tmip->unbind_mp->b_rptr; tp->type = T_UNBIND_REQ; /* * Send a M_PROTO msg of type T_DATA_REQ (this is unique for * read queue since only write queue can get T_DATA_REQ). * Readstream routine in telnet daemon will do a getmsg() till * it receives this proto message */ while ((bp = allocb(sizeof (union T_primitives), BPRI_HI)) == NULL) { bufcall_id_t id = qbufcall(q, sizeof (union T_primitives), BPRI_HI, dummy_callback, NULL); if (!qwait_sig(q)) { qunbufcall(q, id); error = EINTR; goto fail; } qunbufcall(q, id); } bp->b_datap->db_type = M_PROTO; bp->b_wptr = bp->b_rptr + sizeof (union T_primitives); tp = (union T_primitives *)bp->b_rptr; tp->type = T_DATA_REQ; tp->data_req.MORE_flag = 0; putnext(q, bp); return (0); fail: qprocsoff(q); if (tmip->unbind_mp != NULL) { freemsg(tmip->unbind_mp); } kmem_free(tmip, sizeof (struct telmod_info)); q->q_ptr = NULL; WR(q)->q_ptr = NULL; return (error); }
/* * 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); }