/* * cvc_register() * called from cvcredir to register it's queues. cvc * receives data from cn via the streamhead and sends it to cvcredir * via pointers to cvcredir's queues. */ int cvc_register(queue_t *q) { int error = -1; if (cvcinput_q == NULL) cmn_err(CE_WARN, "cvc_register: register w/ no console open!"); rw_enter(&cvclock, RW_WRITER); if (cvcoutput_q == NULL) { cvcoutput_q = RD(q); /* Make sure its the upstream q */ qprocson(cvcoutput_q); /* must be done within cvclock */ error = 0; } else { /* * cmn_err will call us, so release lock. */ rw_exit(&cvclock); if (cvcoutput_q == q) cmn_err(CE_WARN, "cvc_register: duplicate q!"); else cmn_err(CE_WARN, "cvc_register: nondup q = 0x%p", q); return (error); } rw_exit(&cvclock); return (error); }
/* ARGSUSED1 */ static int dropen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) { struct drstate *dsp; if (sflag != MODOPEN) { /* must be a pushed module */ return (EINVAL); } if (secpolicy_net_rawaccess(crp) != 0) { return (EPERM); } if (q->q_ptr != NULL) { return (0); /* already open */ } dsp = kmem_zalloc(sizeof (*dsp), KM_SLEEP); dsp->dr_major = getmajor(*devp); mutex_init(&dsp->dr_lock, NULL, MUTEX_DEFAULT, NULL); q->q_ptr = OTHERQ(q)->q_ptr = dsp; qprocson(q); ddi_assoc_queue_with_devi(q, NULL); return (0); }
/* There are two minors 0 is the /dev/sad/admin driver and 1 is the /dev/sad/user driver. Permission for access to the /dev/sad/admin minor is performed by filesystem permission on the character device and a check on open. */ static streamscall int sad_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) { major_t major = getmajor(*devp); minor_t minor = getminor(*devp); if (q->q_ptr) return (0); /* already open */ switch (sflag) { case CLONEOPEN: minor = 1; if (sads[minor].assigned != 0) break; case DRVOPEN: if (minor != 0 && minor != 1) break; #ifdef HAVE_KMEMB_STRUCT_CRED_UID_VAL if (minor == 0 && crp->cr_uid.val != 0 && crp->cr_ruid.val != 0) return (-EACCES); #else if (minor == 0 && crp->cr_uid != 0 && crp->cr_ruid != 0) return (-EACCES); #endif *devp = makedevice(major, minor); sads[minor].assigned |= 1; q->q_ptr = WR(q)->q_ptr = &sads[minor]; qprocson(q); return (0); } return (-ENXIO); }
/*ARGSUSED*/ static int nca_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) { /* Reopen supported */ if (q->q_ptr != NULL) return (0); /* * NCA is not supported in non-global zones; we enforce this restriction * here. */ if (credp != NULL && crgetzoneid(credp) != GLOBAL_ZONEID) { return (ENOTSUP); } if (! (sflag & MODOPEN)) { /* Device instance */ RD(q)->q_ptr = (void *)B_TRUE; WR(q)->q_ptr = (void *)B_TRUE; } else { /* Modopen just pass through */ RD(q)->q_ptr = (void *)B_FALSE; WR(q)->q_ptr = (void *)B_FALSE; } qprocson(q); return (0); }
/*ARGSUSED*/ static int sdp_gen_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) { qprocson(q); qenable(q); return (0); }
/* ARGSUSED */ static int log_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cr) { log_t *lp; minor_t minor; if (sflag & (MODOPEN | CLONEOPEN)) return (ENXIO); switch (minor = getminor(*devp)) { case LOG_CONSMIN: /* clone open of /dev/conslog */ if (flag & FREAD) return (EINVAL); /* write-only device */ if (q->q_ptr) return (0); break; case LOG_LOGMIN: /* clone open of /dev/log */ break; default: return (ENXIO); } lp = log_alloc(minor); if (lp == NULL) return (ENXIO); *devp = makedevice(getmajor(*devp), lp->log_minor); q->q_ptr = lp; WR(q)->q_ptr = lp; lp->log_inuse = 1; qprocson(q); return (0); }
static int audio_stropen(queue_t *rq, dev_t *devp, int oflag, int sflag, cred_t *credp) { int rv; audio_client_t *c; if (sflag != 0) { /* no direct clone or module opens */ return (ENXIO); } /* * Make sure its a STREAMS personality - only legacy Sun API uses * STREAMS. */ switch (AUDIO_MN_TYPE_MASK & getminor(*devp)) { case AUDIO_MINOR_DEVAUDIO: case AUDIO_MINOR_DEVAUDIOCTL: break; default: return (ENOSTR); } if ((c = auimpl_client_create(*devp)) == NULL) { audio_dev_warn(NULL, "client create failed"); return (ENXIO); } rq->q_ptr = WR(rq)->q_ptr = c; c->c_omode = oflag; c->c_pid = ddi_get_pid(); c->c_cred = credp; c->c_rq = rq; c->c_wq = WR(rq); /* * Call client/personality specific open handler. Note that * we "insist" that there is an open. The personality layer * will initialize/allocate any engines required. * * Hmm... do we need to pass in the cred? */ if ((rv = c->c_open(c, oflag)) != 0) { audio_dev_warn(c->c_dev, "open failed (rv %d)", rv); auimpl_client_destroy(c); return (rv); } /* we do device cloning! */ *devp = makedevice(c->c_major, c->c_minor); qprocson(rq); /* now we can receive upcalls */ auimpl_client_activate(c); atomic_inc_uint(&c->c_dev->d_serial); return (0); }
/* ARGSUSED */ static int wcmopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred) { if (sflag != MODOPEN) return (EINVAL); qprocson(q); return (0); }
/*ARGSUSED*/ static int zc_master_open(zc_state_t *zcs, queue_t *rqp, /* pointer to the read side queue */ dev_t *devp, /* pointer to stream tail's dev */ int oflag, /* the user open(2) supplied flags */ int sflag, /* open state flag */ cred_t *credp) /* credentials */ { mblk_t *mop; struct stroptions *sop; /* * Enforce exclusivity on the master side; the only consumer should * be the zoneadmd for the zone. */ if ((zcs->zc_state & ZC_STATE_MOPEN) != 0) return (EBUSY); if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) { DBG("zc_master_open(): mop allocation failed\n"); return (ENOMEM); } zcs->zc_state |= ZC_STATE_MOPEN; /* * q_ptr stores driver private data; stash the soft state data on both * read and write sides of the queue. */ WR(rqp)->q_ptr = rqp->q_ptr = zcs; qprocson(rqp); /* * Following qprocson(), the master side is fully plumbed into the * STREAM and may send/receive messages. Setting zcs->zc_master_rdq * will allow the slave to send messages to us (the master). * This cannot occur before qprocson() because the master is not * ready to process them until that point. */ zcs->zc_master_rdq = rqp; /* * set up hi/lo water marks on stream head read queue and add * controlling tty as needed. */ mop->b_datap->db_type = M_SETOPTS; mop->b_wptr += sizeof (struct stroptions); sop = (struct stroptions *)(void *)mop->b_rptr; if (oflag & FNOCTTY) sop->so_flags = SO_HIWAT | SO_LOWAT; else sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY; sop->so_hiwat = _TTY_BUFSIZ; sop->so_lowat = 256; putnext(rqp, mop); return (0); }
/* ARGSUSED3 */ int ip_helper_stream_setup(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp, boolean_t isv6) { major_t maj; ip_helper_minfo_t *ip_minfop; ASSERT((flag & ~(FKLYR)) == IP_HELPER_STR); ASSERT(RD(q) == q); ip_minfop = kmem_alloc(sizeof (ip_helper_minfo_t), KM_SLEEP); ASSERT(ip_minfop != NULL); ip_minfop->ip_minfo_dev = 0; ip_minfop->ip_minfo_arena = NULL; /* * Clone the device, allocate minor device number */ if (ip_minor_arena_la != NULL) ip_minfop->ip_minfo_dev = inet_minor_alloc(ip_minor_arena_la); if (ip_minfop->ip_minfo_dev == 0) { /* * numbers in the large arena are exhausted * Try small arena. * Or this is a 32 bit system, 32 bit systems do not have * ip_minor_arena_la */ ip_minfop->ip_minfo_dev = inet_minor_alloc(ip_minor_arena_sa); if (ip_minfop->ip_minfo_dev == 0) { return (EBUSY); } ip_minfop->ip_minfo_arena = ip_minor_arena_sa; } else { ip_minfop->ip_minfo_arena = ip_minor_arena_la; } ASSERT(ip_minfop->ip_minfo_dev != 0); ASSERT(ip_minfop->ip_minfo_arena != NULL); RD(q)->q_ptr = WR(q)->q_ptr = ip_minfop; maj = getemajor(*devp); *devp = makedevice(maj, (ulong_t)(ip_minfop->ip_minfo_dev)); q->q_qinfo = &ip_helper_stream_rinit; WR(q)->q_qinfo = &ip_helper_stream_winit; qprocson(q); return (0); }
/*ARGSUSED*/ static int zc_slave_open(zc_state_t *zcs, queue_t *rqp, /* pointer to the read side queue */ dev_t *devp, /* pointer to stream tail's dev */ int oflag, /* the user open(2) supplied flags */ int sflag, /* open state flag */ cred_t *credp) /* credentials */ { mblk_t *mop; struct stroptions *sop; /* * The slave side can be opened as many times as needed. */ if ((zcs->zc_state & ZC_STATE_SOPEN) != 0) { ASSERT((rqp != NULL) && (WR(rqp)->q_ptr == zcs)); return (0); } if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) { DBG("zc_slave_open(): mop allocation failed\n"); return (ENOMEM); } zcs->zc_state |= ZC_STATE_SOPEN; /* * q_ptr stores driver private data; stash the soft state data on both * read and write sides of the queue. */ WR(rqp)->q_ptr = rqp->q_ptr = zcs; qprocson(rqp); /* * Must follow qprocson(), since we aren't ready to process until then. */ zcs->zc_slave_rdq = rqp; /* * set up hi/lo water marks on stream head read queue and add * controlling tty as needed. */ mop->b_datap->db_type = M_SETOPTS; mop->b_wptr += sizeof (struct stroptions); sop = (struct stroptions *)mop->b_rptr; sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY; sop->so_hiwat = 512; sop->so_lowat = 256; putnext(rqp, mop); return (0); }
/*ARGSUSED2*/ static int kb8042_open(queue_t *qp, dev_t *devp, int flag, int sflag, cred_t *credp) { struct kb8042 *kb8042; int err; int initial_leds; int initial_led_mask; kb8042 = &Kdws; kb8042->w_dev = *devp; if (qp->q_ptr) { return (0); } qp->q_ptr = (caddr_t)kb8042; WR(qp)->q_ptr = qp->q_ptr; if (!kb8042->w_qp) kb8042->w_qp = qp; kb8042_get_initial_leds(kb8042, &initial_leds, &initial_led_mask); err = kbtrans_streams_init(qp, sflag, credp, (struct kbtrans_hardware *)kb8042, &kb8042_callbacks, &kb8042->hw_kbtrans, initial_leds, initial_led_mask); if (err != 0) return (err); kbtrans_streams_set_keyboard(kb8042->hw_kbtrans, KB_PC, &keyindex_pc); kb8042->polledio.cons_polledio_version = CONSPOLLEDIO_V1; kb8042->polledio.cons_polledio_argument = (cons_polledio_arg_t)kb8042; kb8042->polledio.cons_polledio_putchar = NULL; kb8042->polledio.cons_polledio_getchar = (int (*)(cons_polledio_arg_t))kb8042_polled_getchar; kb8042->polledio.cons_polledio_ischar = (boolean_t (*)(cons_polledio_arg_t))kb8042_polled_ischar; kb8042->polledio.cons_polledio_enter = NULL; kb8042->polledio.cons_polledio_exit = NULL; kb8042->polledio.cons_polledio_setled = (void (*)(cons_polledio_arg_t, int))kb8042_polled_setled; kb8042->polledio.cons_polledio_keycheck = (boolean_t (*)(cons_polledio_arg_t, int *, enum keystate *))kb8042_polled_keycheck; qprocson(qp); kbtrans_streams_enable(kb8042->hw_kbtrans); return (0); }
/* ARGSUSED */ static int cvc_open(register queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp) { register int unit = getminor(*devp); register int err = DDI_SUCCESS; tty_common_t *tty; cvc_t *cp; if (unit != 0) return (ENXIO); if (q->q_ptr) return (0); cp = (cvc_t *)&cvc_common_tty; bzero((caddr_t)cp, sizeof (cvc_t)); cp->cvc_wbufcid = 0; tty = &cp->cvc_tty; tty->t_readq = q; tty->t_writeq = WR(q); WR(q)->q_ptr = q->q_ptr = (caddr_t)cp; cvcinput_q = RD(q); /* save for cvc_redir */ qprocson(q); mutex_enter(&cvcmutex); input_ok = 1; /* * Start the thread that handles input polling if it hasn't been started * previously. */ if (!input_daemon_started) { input_daemon_started = 1; mutex_exit(&cvcmutex); cvc_input_daemon_thread = thread_create(NULL, 0, cvc_input_daemon, NULL, 0, &p0, TS_RUN, minclsyspri); CVC_DBG0(CVC_DBG_IOSRAM_RD, "Started input daemon"); } else { mutex_exit(&cvcmutex); } /* * Set the console window size. */ mutex_enter(&cvc_iosram_input_mutex); cvc_win_resize(FALSE); mutex_exit(&cvc_iosram_input_mutex); CVC_DBG0(CVC_DBG_OPEN, "Plumbed successfully"); return (err); }
/*ARGSUSED2*/ static int logiopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cred_p) { struct strmseinfo *logiptr; int unit; dev_info_t *dip; #ifdef LOGI_DEBUG if (logi_debug) printf("logiopen:entered\n"); #endif if (((unit = LOGIUNIT(*devp)) >= LOGI_MAXUNIT) || (dip = logiunits[unit]) == NULL) return (ENODEV); if (!mse_config.present) return (EIO); if ((logiptr = ddi_get_driver_private(dip)) == NULL) return (EIO); if (logiptr->state & M_OPEN) return (EBUSY); mutex_enter(&logiptr->lock); if (q->q_ptr != NULL) { #ifdef LOGI_DEBUG if (logi_debug) printf("logiopen:already open\n"); #endif mutex_exit(&logiptr->lock); return (EBUSY); /* already attached */ } q->q_ptr = (caddr_t)logiptr; WR(q)->q_ptr = (caddr_t)logiptr; logiptr->rqp = q; logiptr->wqp = WR(q); qprocson(q); #ifdef LOGI_DEBUG if (logi_debug) printf("logiopen:Enable interrupts ioaddr %x\n", BASE_IOA); #endif control_port(0); /* Enable interrupts */ #ifdef LOGI_DEBUG if (logi_debug) printf("logiopen:leaving\n"); #endif oldbuttons = 0; logiptr->state = M_OPEN; mutex_exit(&logiptr->lock); return (0); }
/** * ptem_qopen - STREAMS module open routine * @q: read queue * @devp: number of device * @oflag: flags to open(2s) call * @sflag: STREAMS flag * @crp: credentials pointer * * When ptem is pushed successfully, it assigns this Stream as a controlling * terminal if one has not already been assigend by sending a M_SETOPTS * message to the Stream head with the SO_ISTTY flag set. (The Stream head * determines whether the process already has a controlling tty.) If, * however, the O_NOCTTY flag was set to open (and appears in oflag as * FNOCTTY), then no controlling tty should be assigned. It is the job of the * Stream head to detect this too. * * When the module is pushed, if we are using old TTY semantics we need to * send SO_NDELON to the Stream head in an M_SETOPTS. It is typical to change * the Stream head water marks and packet sizes using SO_MINPSZ, SO_MAXPSZ, * SO_HIWAT and SO_LOWAT in the M_SETOPTS. * * As we don't know (and can't query) the state of the Stream head, we need to * set several options that should be correct if the Stream head started in * the default state (which it might not have). SO_MREADOFF should be set as * we default to canonical mode and do not want read notifications. Also * RMSGN mode to SO_RDOPT for canonical mode (RNORM for non-canonical). * SO_NODELIM should probably be set, but see the discussion under * M_SETOPTS(9). SO_WROFF should be set to zero. We may or may not want to * set the SO_STRHOLD feature. Do not set it for now and see if we can get a * performance gain from it. */ static streamscall int ptem_qopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) { if (q->q_ptr) return (0); /* already open */ if (sflag == MODOPEN && WR(q)->q_next != NULL) { struct stroptions *so; struct ptem *p; mblk_t *mp, *hp; if (!(hp = allocb(0, BPRI_WAITOK))) goto openfail; /* zero-length message block is good as it is */ if (!(mp = allocb(sizeof(*so), BPRI_WAITOK))) { freeb(hp); goto openfail; } /* I don't really know what the point of this is, ldterm() will do this again. Everything except the read options and SO_ISTTY the water marks and SO_READOPT are defaults. */ mp->b_datap->db_type = M_SETOPTS; so = (struct stroptions *) mp->b_rptr; mp->b_wptr += sizeof(*so); so->so_flags = SO_ISTTY; if (!(p = kmem_alloc(sizeof(*p), KM_SLEEP))) { freeb(mp); freeb(hp); goto openfail; } bzero(p, sizeof(*p)); p->zero = hp; p->c.c_iflag = BRKINT | ICRNL | IXON | ISTRIP | IXANY; p->c.c_oflag = OPOST | ONLCR | TAB3; p->c.c_cflag = 0; p->c.c_lflag = ISIG | ICANON | ECHO | ECHOK; q->q_ptr = WR(q)->q_ptr = (void *) p; qprocson(q); putnext(q, mp); return (0); } openfail: return (OPENFAIL); }
/* ARGSUSED */ int dm2s_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr) { dm2s_t *dm2sp; int instance = getminor(*dev); int ret = 0; DPRINTF(DBG_DRV, ("dm2s_open: called\n")); if (sflag == CLONEOPEN) { /* Clone open not supported */ DPRINTF(DBG_WARN, ("dm2s_open: clone open not supported\n")); return (ENOTSUP); } if (rq->q_ptr != NULL) { DPRINTF(DBG_WARN, ("dm2s_open: already opened\n")); return (EBUSY); } if ((dm2sp = ddi_get_soft_state(dm2s_softstate, instance)) == NULL) { DPRINTF(DBG_WARN, ("dm2s_open: instance not found\n")); return (ENODEV); } mutex_enter(&dm2sp->ms_lock); if (dm2sp->ms_state & DM2S_OPENED) { /* Only one open supported */ mutex_exit(&dm2sp->ms_lock); DPRINTF(DBG_WARN, ("dm2s_open: already opened\n")); return (EBUSY); } dm2sp->ms_state |= DM2S_OPENED; /* Initialize the mailbox. */ if ((ret = dm2s_mbox_init(dm2sp)) != 0) { dm2sp->ms_state = 0; mutex_exit(&dm2sp->ms_lock); return (ret); } rq->q_ptr = WR(rq)->q_ptr = (void *)dm2sp; dm2sp->ms_rq = rq; dm2sp->ms_wq = WR(rq); mutex_exit(&dm2sp->ms_lock); if (ret == 0) { qprocson(rq); /* now schedule our queue */ } DPRINTF(DBG_DRV, ("dm2s_open: ret=%d\n", ret)); return (ret); }
/* ARGSUSED */ static int sadopen( queue_t *qp, /* pointer to read queue */ dev_t *devp, /* major/minor device of stream */ int flag, /* file open flags */ int sflag, /* stream open flags */ cred_t *credp) /* user credentials */ { int i; if (sflag) /* no longer called from clone driver */ return (EINVAL); /* * Both USRMIN and ADMMIN are clone interfaces. */ for (i = 0; i < sadcnt; i++) if (saddev[i].sa_qp == NULL) break; if (i >= sadcnt) /* no such device */ return (ENXIO); switch (getminor(*devp)) { case USRMIN: /* mere mortal */ saddev[i].sa_flags = 0; break; case ADMMIN: /* privileged user */ saddev[i].sa_flags = SADPRIV; break; default: return (EINVAL); } saddev[i].sa_qp = qp; qp->q_ptr = (caddr_t)&saddev[i]; WR(qp)->q_ptr = (caddr_t)&saddev[i]; /* * NOTE: should the ADMMIN or USRMIN minors change * then so should the offset of 2 below * Both USRMIN and ADMMIN are clone interfaces and * therefore their minor numbers (0 and 1) are reserved. */ *devp = makedevice(getemajor(*devp), i + 2); qprocson(qp); return (0); }
static int dlpi_open( queue_t *q, dev_t *dev, int oflag, int sflag, cred_t *cred ) { struct atif_data *aid; int err = 0; if (( err = drv_priv( cred )) != 0 ) { return( err ); } if (( aid = if_alloc( q )) == NULL ) { return( ENOMEM ); } q->q_ptr = (void *)aid; qprocson( q ); return( err ); }
/*ARGSUSED*/ int connopen(queue_t *rqp, dev_t *devp, int flag, int sflag, cred_t *crp) { int error = 0; vnode_t *streamvp; fifonode_t *streamfnp; if ((streamvp = strq2vp(rqp)) == NULL) { return (EINVAL); } /* * CONNLD is only allowed to be pushed onto a "pipe" that has both * of its ends open. */ if (streamvp->v_type != VFIFO) { error = EINVAL; goto out; } streamfnp = VTOF(streamvp); if (!(streamfnp->fn_flag & ISPIPE) || streamfnp->fn_dest->fn_open == 0) { error = EPIPE; goto out; } /* * If this is the first time CONNLD was opened while on this stream, * it is being pushed. Therefore, set a flag and return 0. */ if (rqp->q_ptr == 0) { if (streamfnp->fn_flag & FIFOCONNLD) { error = ENXIO; goto out; } rqp->q_ptr = (caddr_t)1; streamfnp->fn_flag |= FIFOCONNLD; qprocson(rqp); } out: VN_RELE(streamvp); return (error); }
/* * ------------------------------------------------------------------------- * * OPEN and CLOSE * * ------------------------------------------------------------------------- */ STATIC streamscall int srvmod_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) { queue_t *wq; if (q->q_ptr != NULL) { return (0); /* already open */ } wq = WR(q); if (sflag == MODOPEN || wq->q_next != NULL) { /* inherit packet sizes of what we are pushed over */ wq->q_minpsz = wq->q_next->q_minpsz; wq->q_maxpsz = wq->q_next->q_maxpsz; q->q_ptr = wq->q_ptr = q; /* just set it to something */ qprocson(q); return (0); } return (EIO); /* can't be opened as driver */ }
/* * ------------------------------------------------------------------------- * * OPEN and CLOSE * * ------------------------------------------------------------------------- */ static streamscall int pckt_qopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) { if (q->q_ptr) return (0); /* already open */ if (sflag == MODOPEN && WR(q)->q_next != NULL) { struct pckt *p; if ((p = kmem_alloc(sizeof(*p), KM_SLEEP))) { bzero(p, sizeof(*p)); p->flags = oflag; /* to test later for data model */ q->q_ptr = WR(q)->q_ptr = (void *) p; qprocson(q); return (0); } return (OPENFAIL); } return (OPENFAIL); /* can't be opened as driver */ }
static streamscall __unlikely int ch_qopen(queue_t *q, dev_t *devp, int oflags, int sflag, cred_t *crp) { struct ch *ch; int err; if (!SAMESTR(_WR(q))) { strlog(modid, 0, 15, SL_ERROR, "%s: can only push on pipe or fifo", MOD_NAME); return (ENXIO); /* can only be pushed on pipe or fifo */ } if ((err = mi_open_comm(&ch_head, sizeof(*ch), q, devp, oflags, sflag, crp))) return (err); ch = CH_PRIV(q); bzero(ch, sizeof(*ch)); ch->sid = atomic_add_return(&ch_numb, 1); /* FIXME initialize structure */ qprocson(q); return (0); }
/*ARGSUSED*/ static int pfopen(queue_t *rq, dev_t *dev, int oflag, int sflag, cred_t *crp) { struct epacketfilt *pfp; ASSERT(rq); if (sflag != MODOPEN) return (EINVAL); if (rq->q_ptr) return (0); /* * Allocate and initialize per-Stream structure. */ pfp = kmem_alloc(sizeof (struct epacketfilt), KM_SLEEP); rq->q_ptr = WR(rq)->q_ptr = (char *)pfp; qprocson(rq); return (0); }
/* ARGSUSED */ static int ptemopen( queue_t *q, /* pointer to the read side queue */ dev_t *devp, /* pointer to stream tail's dev */ int oflag, /* the user open(2) supplied flags */ int sflag, /* open state flag */ cred_t *credp) /* credentials */ { struct ptem *ntp; /* ptem entry for this PTEM module */ mblk_t *mop; /* an setopts mblk */ struct stroptions *sop; struct termios *termiosp; int len; if (sflag != MODOPEN) return (EINVAL); if (q->q_ptr != NULL) { /* It's already attached. */ return (0); } /* * Allocate state structure. */ ntp = kmem_alloc(sizeof (*ntp), KM_SLEEP); /* * Allocate a message block, used to pass the zero length message for * "stty 0". * * NOTE: it's better to find out if such a message block can be * allocated before it's needed than to not be able to * deliver (for possible lack of buffers) when a hang-up * occurs. */ if ((ntp->dack_ptr = allocb(4, BPRI_MED)) == NULL) { kmem_free(ntp, sizeof (*ntp)); return (EAGAIN); } /* * Initialize an M_SETOPTS message to set up hi/lo water marks on * stream head read queue and add controlling tty if not set. */ mop = allocb(sizeof (struct stroptions), BPRI_MED); if (mop == NULL) { freemsg(ntp->dack_ptr); kmem_free(ntp, sizeof (*ntp)); return (EAGAIN); } mop->b_datap->db_type = M_SETOPTS; mop->b_wptr += sizeof (struct stroptions); sop = (struct stroptions *)mop->b_rptr; sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY; sop->so_hiwat = 512; sop->so_lowat = 256; /* * Cross-link. */ ntp->q_ptr = q; q->q_ptr = ntp; WR(q)->q_ptr = ntp; /* * Get termios defaults. These are stored as * a property in the "options" node. */ if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), 0, "ttymodes", (caddr_t)&termiosp, &len) == DDI_PROP_SUCCESS && len == sizeof (struct termios)) { ntp->cflags = termiosp->c_cflag; kmem_free(termiosp, len); } else { /* * Gack! Whine about it. */ cmn_err(CE_WARN, "ptem: Couldn't get ttymodes property!"); } ntp->wsz.ws_row = 0; ntp->wsz.ws_col = 0; ntp->wsz.ws_xpixel = 0; ntp->wsz.ws_ypixel = 0; ntp->state = 0; /* * Commit to the open and send the M_SETOPTS off to the stream head. */ qprocson(q); putnext(q, mop); return (0); }
/*ARGSUSED*/ static int parseopen( queue_t *q, dev_t *dev, int flag, int sflag, cred_t *credp ) { register parsestream_t *parse; static int notice = 0; pprintf(DD_OPEN, "parse: OPEN - q=%x\n", q); if (sflag != MODOPEN) { /* open only for modules */ pprintf(DD_OPEN, "parse: OPEN - FAILED - not MODOPEN\n"); return EIO; } if (q->q_ptr != (caddr_t)NULL) { pprintf(DD_OPEN, "parse: OPEN - FAILED - EXCLUSIVE ONLY\n"); return EBUSY; } q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t), KM_SLEEP); if (q->q_ptr == (caddr_t)0) { return ENOMEM; } pprintf(DD_OPEN, "parse: OPEN - parse area q=%x, q->q_ptr=%x\n", q, q->q_ptr); WR(q)->q_ptr = q->q_ptr; pprintf(DD_OPEN, "parse: OPEN - WQ parse area q=%x, q->q_ptr=%x\n", WR(q), WR(q)->q_ptr); parse = (parsestream_t *) q->q_ptr; bzero((caddr_t)parse, sizeof(*parse)); parse->parse_queue = q; parse->parse_status = PARSE_ENABLE; parse->parse_ppsclockev.tv.tv_sec = 0; parse->parse_ppsclockev.tv.tv_usec = 0; parse->parse_ppsclockev.serial = 0; qprocson(q); pprintf(DD_OPEN, "parse: OPEN - initializing io subsystem q=%x\n", q); if (!parse_ioinit(&parse->parse_io)) { /* * ok guys - beat it */ qprocsoff(q); kmem_free((caddr_t)parse, sizeof(parsestream_t)); return EIO; } pprintf(DD_OPEN, "parse: OPEN - initializing stream q=%x\n", q); if (setup_stream(q, M_PARSE)) { (void) init_linemon(q); /* hook up PPS ISR routines if possible */ pprintf(DD_OPEN, "parse: OPEN - SUCCEEDED\n"); /* * I know that you know the delete key, but you didn't write this * code, did you ? - So, keep the message in here. */ if (!notice) { cmn_err(CE_CONT, "?%s: Copyright (c) 1993-2005, Frank Kardel\n", modlstrmod.strmod_linkinfo); notice = 1; } return 0; } else { qprocsoff(q); kmem_free((caddr_t)parse, sizeof(parsestream_t)); return EIO; } }
/** * socksys_qopen - SOCKSYS driver STREAMS open routine * @q: read queue of opened Stream * @devp: pointer to device number opened * @oflag: flags to the open call * @sflag: STREAMS flag: DRVOPEN, MODOPEN or CLONEOPEN * @crp: pointer to opener's credentials */ STATIC streamscall int socksys_qopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) { int mindex = 0; int type = 0; major_t cmajor = getmajor(*devp); minor_t cminor = getminor(*devp); struct ssys **sp = &socksys_opens; unsigned long flags; if (q->q_ptr != NULL) { return (0); /* already open */ } if (sflag == MODOPEN || WR(q)->q_next) { ptrace(("%s: ERROR: cannot push as module\n", DRV_NAME)); return (EIO); } /* Linux Fast-STREAMS always passes internal major device number (module id). Note also, however, that strconf-sh attempts to allocate module ids that are identical to the base major device number anyway. */ /* Linux Fast-STREAMS always passes internal major device numbers (module ids) */ if (cmajor != DRV_ID) return (ENXIO); /* sorry, you cannot open by minor device */ if (cminor > LAST_CMINOR) { return (ENXIO); } type = cminor; #if 0 if (sflag == CLONEOPEN) #endif cminor = FREE_CMINOR; write_lock_str2(&socksys_lock, flags); for (; *sp; sp = &(*sp)->next) { if (cmajor != (*sp)->dev.cmajor) break; if (cmajor == (*sp)->dev.cmajor) { if (cminor < (*sp)->dev.cminor) break; if (cminor == (*sp)->dev.cminor) { if (++cminor >= NMINORS) { if (++mindex >= CMAJORS || !(cmajor = ssys_majors[mindex])) break; cminor = 0; /* start next major */ } continue; } } } if (mindex >= CMAJORS || !cmajor) { ptrace(("%s: ERROR: no device numbers available\n", DRV_NAME)); write_unlock_str2(&socksys_lock, flags); return (ENXIO); } _printd(("%s: opened character device %d:%d\n", DRV_NAME, cmajor, cminor)); *devp = makedevice(cmajor, cminor); if (!ssys_alloc_priv(q, sp, type, devp, crp)) { ptrace(("%s: ERROR: No memory\n", DRV_NAME)); write_unlock_str2(&socksys_lock, flags); return (ENOMEM); } write_unlock_str2(&socksys_lock, flags); qprocson(q); return (0); }
/* * ------------------------------------------------------------------------- * * OPEN and CLOSE * * ------------------------------------------------------------------------- */ static streamscall int spx_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp) { struct spx *p, **pp = &spx_list; major_t cmajor = getmajor(*devp); minor_t cminor = getminor(*devp); if (q->q_ptr != NULL) return (0); /* already open */ if (sflag == MODOPEN || WR(q)->q_next) return (ENXIO); /* can't open as module */ if (!(p = kmem_alloc(sizeof(*p), KM_NOSLEEP))) /* we could sleep */ return (ENOMEM); /* no memory */ bzero(p, sizeof(*p)); switch (sflag) { case CLONEOPEN: if (cminor < 1) cminor = 1; case DRVOPEN: { major_t dmajor = cmajor; if (cminor < 1) return (ENXIO); spin_lock(&spx_lock); for (; *pp && (dmajor = getmajor((*pp)->dev)) < cmajor; pp = &(*pp)->next) ; for (; *pp && dmajor == getmajor((*pp)->dev) && getminor(makedevice(cmajor, cminor)) != 0; pp = &(*pp)->next) { minor_t dminor = getminor((*pp)->dev); if (cminor < dminor) break; if (cminor == dminor) { if (sflag == CLONEOPEN) cminor++; else { spin_unlock(&spx_lock); kmem_free(p, sizeof(*p)); return (EIO); /* bad error */ } } } if (getminor(makedevice(cmajor, cminor)) == 0) { spin_unlock(&spx_lock); kmem_free(p, sizeof(*p)); return (EBUSY); /* no minors left */ } p->dev = *devp = makedevice(cmajor, cminor); p->init = 0; p->q = q; if ((p->next = *pp)) p->next->prev = &p->next; p->prev = pp; *pp = p; q->q_ptr = OTHERQ(q)->q_ptr = p; spin_unlock(&spx_lock); qprocson(q); return (0); } } return (ENXIO); }
/*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); }
/*ARGSUSED*/ static int zc_slave_open(zc_state_t *zcs, queue_t *rqp, /* pointer to the read side queue */ dev_t *devp, /* pointer to stream tail's dev */ int oflag, /* the user open(2) supplied flags */ int sflag, /* open state flag */ cred_t *credp) /* credentials */ { mblk_t *mop; struct stroptions *sop; major_t major; minor_t minor; minor_t lastminor; uint_t anchorindex; /* * The slave side can be opened as many times as needed. */ if ((zcs->zc_state & ZC_STATE_SOPEN) != 0) { ASSERT((rqp != NULL) && (WR(rqp)->q_ptr == zcs)); return (0); } /* * Set up sad(7D) so that the necessary STREAMS modules will be in * place. A wrinkle is that 'ptem' must be anchored * in place (see streamio(7i)) because we always want the console to * have terminal semantics. */ minor = ddi_get_instance(zcs->zc_devinfo) << 1 | ZC_SLAVE_MINOR; major = ddi_driver_major(zcs->zc_devinfo); lastminor = 0; anchorindex = 1; if (kstr_autopush(SET_AUTOPUSH, &major, &minor, &lastminor, &anchorindex, zcons_mods) != 0) { DBG("zc_slave_open(): kstr_autopush() failed\n"); return (EIO); } if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) { DBG("zc_slave_open(): mop allocation failed\n"); return (ENOMEM); } zcs->zc_state |= ZC_STATE_SOPEN; /* * q_ptr stores driver private data; stash the soft state data on both * read and write sides of the queue. */ WR(rqp)->q_ptr = rqp->q_ptr = zcs; qprocson(rqp); /* * Must follow qprocson(), since we aren't ready to process until then. */ zcs->zc_slave_rdq = rqp; /* * set up hi/lo water marks on stream head read queue and add * controlling tty as needed. */ mop->b_datap->db_type = M_SETOPTS; mop->b_wptr += sizeof (struct stroptions); sop = (struct stroptions *)(void *)mop->b_rptr; sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY; sop->so_hiwat = _TTY_BUFSIZ; sop->so_lowat = 256; putnext(rqp, mop); return (0); }
static streamscall int ll_qopen(queue_t *q, dev_t *devp, int oflags, int sflag, cred_t *crp) { struct priv *p; struct ll *llw; struct ll *llr; int err; if (q->q_ptr != NULL) return (0); /* already open */ if ((err = mi_open_comm(&ll_opens, sizeof(*p), q, devp, oflags, sflag, crp))) return (err); p = PRIV(q); llw = &p->w_priv; llr = &p->r_priv; /* initialize private structure */ llw->priv = p; llw->ll = llr; llw->oq = q; llw->state = CD_DISABLED; llw->oldstate = CD_DISABLED; llw->proto.info.cd_primitive = CD_INFO_ACK; llw->proto.info.cd_state = CD_DISABLED; llw->proto.info.cd_max_sdu = STRMAXPSZ; llw->proto.info.cd_min_sdu = STRMINPSZ; llw->proto.info.cd_class = CD_HDLC; llw->proto.info.cd_duplex = CD_FULLDUPLEX; llw->proto.info.cd_output_style = CD_UNACKEDOUTPUT; llw->proto.info.cd_features = (CD_CANREAD | CD_AUTOALLOW); llw->proto.info.cd_addr_length = 0; llw->proto.info.cd_ppa_style = CD_STYLE1; llw->sigs = CD_DSR; llw->alen = 0; llr->priv = p; llr->ll = llw; llr->oq = WR(q); llr->state = CD_DISABLED; llr->oldstate = CD_DISABLED; llr->proto.info.cd_primitive = CD_INFO_ACK; llr->proto.info.cd_state = CD_DISABLED; llr->proto.info.cd_max_sdu = STRMAXPSZ; llr->proto.info.cd_min_sdu = STRMINPSZ; llr->proto.info.cd_class = CD_HDLC; llr->proto.info.cd_duplex = CD_FULLDUPLEX; llr->proto.info.cd_output_style = CD_UNACKEDOUTPUT; llr->proto.info.cd_features = (CD_CANREAD | CD_AUTOALLOW); llr->proto.info.cd_addr_length = 0; llr->proto.info.cd_ppa_style = CD_STYLE1; llr->sigs = CD_DSR; llr->alen = 0; qprocson(q); return (0); }