xref: /illumos-gate/usr/src/uts/common/io/usb/clients/usbser/usbser.c (revision 1a220b56b93ff1dc80855691548503117af4cc10)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  *
30  * USB generic serial driver (GSD)
31  *
32  */
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/stream.h>
36 #include <sys/stropts.h>
37 #include <sys/errno.h>
38 #include <sys/cred.h>
39 #include <sys/conf.h>
40 #include <sys/stat.h>
41 #include <sys/modctl.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44 #include <sys/sunndi.h>
45 #include <sys/termio.h>
46 #include <sys/termiox.h>
47 #include <sys/stropts.h>
48 #include <sys/stream.h>
49 #include <sys/strsubr.h>
50 #include <sys/strsun.h>
51 #include <sys/strtty.h>
52 #include <sys/policy.h>
53 #include <sys/consdev.h>
54 
55 #include <sys/usb/usba.h>
56 #include <sys/usb/clients/usbser/usbser_var.h>
57 #include <sys/usb/clients/usbser/usbser_dsdi.h>
58 #include <sys/usb/clients/usbser/usbser_rseq.h>
59 #include <sys/usb/usba/genconsole.h>
60 
61 /* autoconfiguration subroutines */
62 static int	usbser_rseq_do_cb(rseq_t *, int, uintptr_t);
63 static int	usbser_free_soft_state(usbser_state_t *);
64 static int	usbser_init_soft_state(usbser_state_t *);
65 static int	usbser_fini_soft_state(usbser_state_t *);
66 static int	usbser_attach_dev(usbser_state_t *);
67 static void	usbser_detach_dev(usbser_state_t *);
68 static int	usbser_attach_ports(usbser_state_t *);
69 static int	usbser_create_port_minor_nodes(usbser_state_t *, int);
70 static void	usbser_detach_ports(usbser_state_t *);
71 static int	usbser_create_taskq(usbser_state_t *);
72 static void	usbser_destroy_taskq(usbser_state_t *);
73 static void	usbser_set_dev_state_init(usbser_state_t *);
74 
75 /* hotplugging and power management */
76 static int	usbser_disconnect_cb(dev_info_t *);
77 static int	usbser_reconnect_cb(dev_info_t *);
78 static void	usbser_disconnect_ports(usbser_state_t *);
79 static int	usbser_cpr_suspend(dev_info_t *);
80 static int	usbser_suspend_ports(usbser_state_t *);
81 static void	usbser_cpr_resume(dev_info_t *);
82 static int	usbser_restore_device_state(usbser_state_t *);
83 static void	usbser_restore_ports_state(usbser_state_t *);
84 
85 /* STREAMS subroutines */
86 static int	usbser_open_setup(queue_t *, usbser_port_t *, int, int,
87 		cred_t *);
88 static int	usbser_open_init(usbser_port_t *, int);
89 static void	usbser_check_port_props(usbser_port_t *);
90 static void	usbser_open_fini(usbser_port_t *);
91 static int	usbser_open_line_setup(usbser_port_t *, int, int);
92 static int	usbser_open_carrier_check(usbser_port_t *, int, int);
93 static void	usbser_open_queues_init(usbser_port_t *, queue_t *);
94 static void	usbser_open_queues_fini(usbser_port_t *);
95 static void	usbser_close_drain(usbser_port_t *);
96 static void	usbser_close_cancel_break(usbser_port_t *);
97 static void	usbser_close_hangup(usbser_port_t *);
98 static void	usbser_close_cleanup(usbser_port_t *);
99 
100 /* threads */
101 static void	usbser_thr_dispatch(usbser_thread_t *);
102 static void	usbser_thr_cancel(usbser_thread_t *);
103 static void	usbser_thr_wake(usbser_thread_t *);
104 static void	usbser_wq_thread(void *);
105 static void	usbser_rq_thread(void *);
106 
107 /* DSD callbacks */
108 static void	usbser_tx_cb(caddr_t);
109 static void	usbser_rx_cb(caddr_t);
110 static void	usbser_rx_massage_data(usbser_port_t *, mblk_t *);
111 static void	usbser_rx_massage_mbreak(usbser_port_t *, mblk_t *);
112 static void	usbser_rx_cb_put(usbser_port_t *, queue_t *, queue_t *,
113 		mblk_t *);
114 static void	usbser_status_cb(caddr_t);
115 static void	usbser_status_proc_cb(usbser_port_t *);
116 
117 /* serial support */
118 static void	usbser_wmsg(usbser_port_t *);
119 static int	usbser_data(usbser_port_t *, mblk_t *);
120 static int	usbser_ioctl(usbser_port_t *, mblk_t *);
121 static void	usbser_iocdata(usbser_port_t *, mblk_t *);
122 static void	usbser_stop(usbser_port_t *, mblk_t *);
123 static void	usbser_start(usbser_port_t *, mblk_t *);
124 static void	usbser_stopi(usbser_port_t *, mblk_t *);
125 static void	usbser_starti(usbser_port_t *, mblk_t *);
126 static void	usbser_flush(usbser_port_t *, mblk_t *);
127 static void	usbser_break(usbser_port_t *, mblk_t *);
128 static void	usbser_delay(usbser_port_t *, mblk_t *);
129 static void	usbser_restart(void *);
130 static int	usbser_port_program(usbser_port_t *);
131 static void	usbser_inbound_flow_ctl(usbser_port_t *);
132 
133 /* misc */
134 static int	usbser_dev_is_online(usbser_state_t *);
135 static void	usbser_serialize_port_act(usbser_port_t *, int);
136 static void	usbser_release_port_act(usbser_port_t *, int);
137 static char	*usbser_msgtype2str(int);
138 static char	*usbser_ioctl2str(int);
139 
140 
141 /* USBA events */
142 usb_event_t usbser_usb_events = {
143 	usbser_disconnect_cb,	/* disconnect */
144 	usbser_reconnect_cb,	/* reconnect */
145 	NULL,			/* pre-suspend */
146 	NULL,			/* pre-resume */
147 };
148 
149 /* debug support */
150 uint_t   usbser_errlevel = USB_LOG_L4;
151 uint_t   usbser_errmask = DPRINT_MASK_ALL;
152 uint_t   usbser_instance_debug = (uint_t)-1;
153 
154 /* usb serial console */
155 static struct usbser_state *usbser_list;
156 static kmutex_t usbser_lock;
157 static int usbser_console_abort;
158 static usb_console_info_t console_input, console_output;
159 static uchar_t *console_input_buf;
160 static uchar_t *console_input_start, *console_input_end;
161 
162 static void usbser_putchar(cons_polledio_arg_t, uchar_t);
163 static int usbser_getchar(cons_polledio_arg_t);
164 static boolean_t usbser_ischar(cons_polledio_arg_t);
165 static void usbser_polledio_enter(cons_polledio_arg_t);
166 static void usbser_polledio_exit(cons_polledio_arg_t);
167 static int usbser_polledio_init(usbser_port_t *);
168 static void usbser_polledio_fini(usbser_port_t *);
169 
170 static struct cons_polledio usbser_polledio = {
171 	CONSPOLLEDIO_V1,
172 	NULL,	/* to be set later */
173 	usbser_putchar,
174 	usbser_getchar,
175 	usbser_ischar,
176 	usbser_polledio_enter,
177 	usbser_polledio_exit
178 };
179 
180 /* various statistics. TODO: replace with kstats */
181 static int usbser_st_tx_data_loss = 0;
182 static int usbser_st_rx_data_loss = 0;
183 static int usbser_st_put_stopi = 0;
184 static int usbser_st_mstop = 0;
185 static int usbser_st_mstart = 0;
186 static int usbser_st_mstopi = 0;
187 static int usbser_st_mstarti = 0;
188 static int usbser_st_rsrv = 0;
189 _NOTE(SCHEME_PROTECTS_DATA("monotonic stats", usbser_st_{
190 	tx_data_loss rx_data_loss put_stopi mstop mstart mstopi mstarti rsrv}))
191 _NOTE(SCHEME_PROTECTS_DATA("unshared", usb_bulk_req_t))
192 _NOTE(SCHEME_PROTECTS_DATA("unshared", usb_intr_req_t))
193 
194 /* taskq parameter */
195 extern pri_t minclsyspri;
196 
197 /*
198  * tell warlock not to worry about STREAMS structures
199  */
200 _NOTE(SCHEME_PROTECTS_DATA("unique per call", iocblk datab msgb queue copyreq))
201 
202 /*
203  * modload support
204  */
205 extern struct mod_ops mod_miscops;
206 
207 static struct modlmisc modlmisc = {
208 	&mod_miscops,	/* Type of module */
209 	"USB generic serial module %I%"
210 };
211 
212 static struct modlinkage modlinkage = {
213 	MODREV_1, (void *)&modlmisc, NULL
214 };
215 
216 
217 #define	RSEQ(f1, f2) RSEQE(f1, usbser_rseq_do_cb, f2, NULL)
218 
219 
220 /*
221  * loadable module entry points
222  * ----------------------------
223  */
224 
225 int
226 _init(void)
227 {
228 	int err;
229 
230 	mutex_init(&usbser_lock, NULL, MUTEX_DRIVER, (void *)NULL);
231 	if (err = mod_install(&modlinkage))
232 		mutex_destroy(&usbser_lock);
233 
234 	return (err);
235 }
236 
237 
238 int
239 _fini(void)
240 {
241 	int err;
242 
243 	if (err = mod_remove(&modlinkage))
244 
245 		return (err);
246 
247 	mutex_destroy(&usbser_lock);
248 
249 	return (0);
250 }
251 
252 
253 int
254 _info(struct modinfo *modinfop)
255 {
256 	return (mod_info(&modlinkage, modinfop));
257 }
258 
259 
260 /*
261  * soft state size
262  */
263 int
264 usbser_soft_state_size()
265 {
266 	return (sizeof (usbser_state_t));
267 }
268 
269 
270 /*
271  * autoconfiguration entry points
272  * ------------------------------
273  */
274 
275 /*ARGSUSED*/
276 int
277 usbser_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
278 		void **result, void *statep)
279 {
280 	int		instance;
281 	int		ret = DDI_FAILURE;
282 	usbser_state_t	*usbserp;
283 
284 	instance = USBSER_MINOR2INST(getminor((dev_t)arg));
285 
286 	switch (infocmd) {
287 	case DDI_INFO_DEVT2DEVINFO:
288 		*result = NULL;
289 		usbserp = ddi_get_soft_state(statep, instance);
290 		if (usbserp != NULL) {
291 			*result = usbserp->us_dip;
292 			if (*result != NULL) {
293 				ret = DDI_SUCCESS;
294 			}
295 		}
296 
297 		break;
298 	case DDI_INFO_DEVT2INSTANCE:
299 		*result = (void *)(uintptr_t)instance;
300 		ret = DDI_SUCCESS;
301 
302 		break;
303 	default:
304 		break;
305 	}
306 
307 	return (ret);
308 }
309 
310 /*
311  * device attach
312  */
313 static rseq_t rseq_att[] = {
314 	RSEQ(NULL,			usbser_free_soft_state),
315 	RSEQ(usbser_init_soft_state,	usbser_fini_soft_state),
316 	RSEQ(usbser_attach_dev,		usbser_detach_dev),
317 	RSEQ(usbser_attach_ports,	usbser_detach_ports),
318 	RSEQ(usbser_create_taskq,	usbser_destroy_taskq),
319 	RSEQ(NULL,			usbser_set_dev_state_init)
320 };
321 
322 static void
323 usbser_insert(struct usbser_state *usp)
324 {
325 	struct usbser_state *tmp;
326 
327 	mutex_enter(&usbser_lock);
328 	tmp = usbser_list;
329 	if (tmp == NULL)
330 		usbser_list = usp;
331 	else {
332 		while (tmp->us_next)
333 			tmp = tmp->us_next;
334 		tmp->us_next = usp;
335 	}
336 	mutex_exit(&usbser_lock);
337 }
338 
339 static void
340 usbser_remove(struct usbser_state *usp)
341 {
342 	struct usbser_state *tmp, *prev = NULL;
343 
344 	mutex_enter(&usbser_lock);
345 	tmp = usbser_list;
346 	while (tmp != usp) {
347 		prev = tmp;
348 		tmp = tmp->us_next;
349 	}
350 	ASSERT(tmp == usp);	/* must exist, else attach/detach wrong */
351 	if (prev)
352 		prev->us_next = usp->us_next;
353 	else
354 		usbser_list = usp->us_next;
355 	usp->us_next = NULL;
356 	mutex_exit(&usbser_lock);
357 }
358 
359 /*
360  * Return the first serial device, with dip held. This is called
361  * from the console subsystem to place console on usb serial device.
362  */
363 dev_info_t *
364 usbser_first_device(void)
365 {
366 	dev_info_t *dip = NULL;
367 
368 	mutex_enter(&usbser_lock);
369 	if (usbser_list) {
370 		dip = usbser_list->us_dip;
371 		ndi_hold_devi(dip);
372 	}
373 	mutex_exit(&usbser_lock);
374 
375 	return (dip);
376 }
377 
378 int
379 usbser_attach(dev_info_t *dip, ddi_attach_cmd_t cmd,
380 		void *statep, ds_ops_t *ds_ops)
381 {
382 	int		instance;
383 	usbser_state_t	*usp;
384 
385 	instance = ddi_get_instance(dip);
386 
387 	switch (cmd) {
388 	case DDI_ATTACH:
389 
390 		break;
391 	case DDI_RESUME:
392 		usbser_cpr_resume(dip);
393 
394 		return (DDI_SUCCESS);
395 	default:
396 
397 		return (DDI_FAILURE);
398 	}
399 
400 	/* allocate and get soft state */
401 	if (ddi_soft_state_zalloc(statep, instance) != DDI_SUCCESS) {
402 
403 		return (DDI_FAILURE);
404 	}
405 	if ((usp = ddi_get_soft_state(statep, instance)) == NULL) {
406 		ddi_soft_state_free(statep, instance);
407 
408 		return (DDI_FAILURE);
409 	}
410 
411 	usp->us_statep = statep;
412 	usp->us_dip = dip;
413 	usp->us_instance = instance;
414 	usp->us_ds_ops = ds_ops;
415 
416 	if (rseq_do(rseq_att, NELEM(rseq_att), (uintptr_t)usp, 0) == RSEQ_OK) {
417 		ddi_report_dev(dip);
418 		usbser_insert(usp);
419 
420 		return (DDI_SUCCESS);
421 	} else {
422 
423 		return (DDI_FAILURE);
424 	}
425 }
426 
427 /*
428  * device detach
429  */
430 int
431 usbser_detach(dev_info_t *dip, ddi_detach_cmd_t cmd, void *statep)
432 {
433 	int		instance = ddi_get_instance(dip);
434 	usbser_state_t	*usp;
435 	int		rval;
436 
437 	usp = ddi_get_soft_state(statep, instance);
438 
439 	switch (cmd) {
440 	case DDI_DETACH:
441 		USB_DPRINTF_L4(DPRINT_DETACH, usp->us_lh, "usbser_detach");
442 		usbser_remove(usp);
443 		(void) rseq_undo(rseq_att, NELEM(rseq_att), (uintptr_t)usp, 0);
444 		USB_DPRINTF_L4(DPRINT_DETACH, NULL,
445 			"usbser_detach.%d: end", instance);
446 
447 		return (DDI_SUCCESS);
448 	case DDI_SUSPEND:
449 		rval = usbser_cpr_suspend(dip);
450 
451 		return ((rval == USB_SUCCESS)? DDI_SUCCESS : DDI_FAILURE);
452 	default:
453 
454 		return (DDI_FAILURE);
455 	}
456 }
457 
458 /*
459  * STREAMS entry points
460  * --------------------
461  *
462  *
463  * port open
464  */
465 /*ARGSUSED*/
466 int
467 usbser_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr,
468 		void *statep)
469 {
470 	usbser_state_t	*usp;
471 	usbser_port_t	*pp;
472 	int		minor = getminor(*dev);
473 	int		instance;
474 	uint_t		port_num;
475 	int		rval;
476 
477 	instance = USBSER_MINOR2INST(minor);
478 	if (instance < 0) {
479 
480 		return (ENXIO);
481 	}
482 
483 	usp = ddi_get_soft_state(statep, instance);
484 	if (usp == NULL) {
485 
486 		return (ENXIO);
487 	}
488 
489 	/* don't allow to open disconnected device */
490 	mutex_enter(&usp->us_mutex);
491 	if (usp->us_dev_state == USB_DEV_DISCONNECTED) {
492 		mutex_exit(&usp->us_mutex);
493 
494 		return (ENXIO);
495 	}
496 	mutex_exit(&usp->us_mutex);
497 
498 	/* get port soft state */
499 	port_num = USBSER_MINOR2PORT(minor);
500 	if (port_num >= usp->us_port_cnt) {
501 
502 		return (ENXIO);
503 	}
504 	pp = &usp->us_ports[port_num];
505 
506 	/* set up everything for open */
507 	rval = usbser_open_setup(rq, pp, minor, flag, cr);
508 
509 	USB_DPRINTF_L4(DPRINT_OPEN, pp->port_lh, "usbser_open: rval=%d", rval);
510 
511 	return (rval);
512 }
513 
514 
515 /*
516  * port close
517  *
518  * some things driver should do when the last app closes the line:
519  *
520  *	drain data;
521  *	cancel break/delay;
522  *	hangup line (if necessary);
523  *	DSD close;
524  *	cleanup soft state;
525  */
526 /*ARGSUSED*/
527 int
528 usbser_close(queue_t *rq, int flag, cred_t *cr)
529 {
530 	usbser_port_t	*pp = (usbser_port_t *)rq->q_ptr;
531 	int		online;
532 
533 	if (pp == NULL) {
534 
535 		return (ENXIO);
536 	}
537 
538 	online = usbser_dev_is_online(pp->port_usp);
539 
540 	/*
541 	 * in the closing state new activities will not be initiated
542 	 */
543 	mutex_enter(&pp->port_mutex);
544 	pp->port_state = USBSER_PORT_CLOSING;
545 
546 	if (online) {
547 		/* drain the data */
548 		usbser_close_drain(pp);
549 	}
550 
551 	/* stop break/delay */
552 	usbser_close_cancel_break(pp);
553 
554 	if (online) {
555 		/* hangup line */
556 		usbser_close_hangup(pp);
557 	}
558 
559 	/*
560 	 * close DSD, cleanup state and transition to 'closed' state
561 	 */
562 	usbser_close_cleanup(pp);
563 	mutex_exit(&pp->port_mutex);
564 
565 	USB_DPRINTF_L4(DPRINT_CLOSE, pp->port_lh, "usbser_close: end");
566 
567 	return (0);
568 }
569 
570 
571 /*
572  * read side service routine: send as much as possible messages upstream
573  * and if there is still place on the queue, enable receive (if not already)
574  */
575 int
576 usbser_rsrv(queue_t *q)
577 {
578 	usbser_port_t	*pp = (usbser_port_t *)q->q_ptr;
579 	mblk_t		*mp;
580 
581 	usbser_st_rsrv++;
582 	USB_DPRINTF_L4(DPRINT_RQ, pp->port_lh, "usbser_rsrv");
583 
584 	while (canputnext(q) && (mp = getq(q))) {
585 		putnext(q, mp);
586 	}
587 
588 	if (canputnext(q)) {
589 		mutex_enter(&pp->port_mutex);
590 		ASSERT(pp->port_state != USBSER_PORT_CLOSED);
591 
592 		if (USBSER_PORT_ACCESS_OK(pp)) {
593 			usbser_thr_wake(&pp->port_rq_thread);
594 		}
595 		mutex_exit(&pp->port_mutex);
596 	}
597 
598 	return (0);
599 }
600 
601 
602 /*
603  * wput: put message on the queue and wake wq thread
604  */
605 int
606 usbser_wput(queue_t *q, mblk_t *mp)
607 {
608 	usbser_port_t	*pp = (usbser_port_t *)q->q_ptr;
609 
610 	USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wput");
611 
612 	mutex_enter(&pp->port_mutex);
613 	ASSERT(pp->port_state != USBSER_PORT_CLOSED);
614 
615 	/* ignore new messages if port is already closing */
616 	if (pp->port_state == USBSER_PORT_CLOSING) {
617 		freemsg(mp);
618 	} else if (putq(q, mp)) {
619 		/*
620 		 * this counter represents amount of tx data on the wq.
621 		 * each time the data is passed to DSD for transmission,
622 		 * the counter is decremented accordingly
623 		 */
624 		pp->port_wq_data_cnt += msgdsize(mp);
625 	} else {
626 		usbser_st_tx_data_loss++;
627 	}
628 	mutex_exit(&pp->port_mutex);
629 
630 	return (0);
631 }
632 
633 
634 /*
635  * we need wsrv() routine to take advantage of STREAMS flow control:
636  * without it the framework will consider we are always able to process msgs
637  */
638 int
639 usbser_wsrv(queue_t *q)
640 {
641 	usbser_port_t	*pp = (usbser_port_t *)q->q_ptr;
642 
643 	USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wsrv");
644 
645 	mutex_enter(&pp->port_mutex);
646 	ASSERT(pp->port_state != USBSER_PORT_CLOSED);
647 
648 	if (USBSER_PORT_ACCESS_OK(pp)) {
649 		usbser_thr_wake(&pp->port_wq_thread);
650 	}
651 	mutex_exit(&pp->port_mutex);
652 
653 	return (0);
654 }
655 
656 
657 /*
658  * power entry point
659  */
660 int
661 usbser_power(dev_info_t *dip, int comp, int level)
662 {
663 	void		*statep;
664 	usbser_state_t	*usp;
665 	int		new_state;
666 	int		rval;
667 
668 	statep = ddi_get_driver_private(dip);
669 	usp = ddi_get_soft_state(statep, ddi_get_instance(dip));
670 
671 	USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh,
672 	    "usbser_power: dip=0x%p, comp=%d, level=%d", dip, comp, level);
673 
674 	mutex_enter(&usp->us_mutex);
675 	new_state = usp->us_dev_state;
676 	mutex_exit(&usp->us_mutex);
677 
678 	/* let DSD do the job */
679 	rval = USBSER_DS_USB_POWER(usp, comp, level, &new_state);
680 
681 	/* stay in sync with DSD */
682 	mutex_enter(&usp->us_mutex);
683 	usp->us_dev_state = new_state;
684 	mutex_exit(&usp->us_mutex);
685 
686 	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
687 }
688 
689 
690 /*
691  *
692  * configuration entry point subroutines
693  * -------------------------------------
694  *
695  * rseq callback
696  */
697 static int
698 usbser_rseq_do_cb(rseq_t *rseq, int num, uintptr_t arg)
699 {
700 	usbser_state_t *usp = (usbser_state_t *)arg;
701 	int	rval = rseq[num].r_do.s_rval;
702 	char	*name = rseq[num].r_do.s_name;
703 
704 	if (rval != DDI_SUCCESS) {
705 		USB_DPRINTF_L2(DPRINT_ATTACH, usp->us_lh,
706 		    "do %s failed (%d)", name, rval);
707 
708 		return (RSEQ_UNDO);
709 	} else {
710 
711 		return (RSEQ_OK);
712 	}
713 }
714 
715 
716 /*
717  * free soft state
718  */
719 static int
720 usbser_free_soft_state(usbser_state_t *usp)
721 {
722 	ddi_soft_state_free(usp->us_statep, usp->us_instance);
723 
724 	return (USB_SUCCESS);
725 }
726 
727 /*
728  * init instance soft state
729  */
730 static int
731 usbser_init_soft_state(usbser_state_t *usp)
732 {
733 	usp->us_lh = usb_alloc_log_hdl(usp->us_dip, "usbs[*].",
734 		&usbser_errlevel, &usbser_errmask, &usbser_instance_debug,
735 		0);
736 	mutex_init(&usp->us_mutex, NULL, MUTEX_DRIVER, (void *)NULL);
737 
738 	/* save state pointer for use in event callbacks */
739 	ddi_set_driver_private(usp->us_dip, usp->us_statep);
740 
741 	usp->us_dev_state = USBSER_DEV_INIT;
742 
743 	return (DDI_SUCCESS);
744 }
745 
746 /*
747  * fini instance soft state
748  */
749 static int
750 usbser_fini_soft_state(usbser_state_t *usp)
751 {
752 	usb_free_log_hdl(usp->us_lh);
753 	mutex_destroy(&usp->us_mutex);
754 	ddi_set_driver_private(usp->us_dip, NULL);
755 
756 	return (DDI_SUCCESS);
757 }
758 
759 /*
760  * attach entire device
761  */
762 static int
763 usbser_attach_dev(usbser_state_t *usp)
764 {
765 	ds_attach_info_t ai;
766 	int		rval;
767 
768 	usp->us_dev_state = USB_DEV_ONLINE;
769 
770 	ai.ai_dip = usp->us_dip;
771 	ai.ai_usb_events = &usbser_usb_events;
772 	ai.ai_hdl = &usp->us_ds_hdl;
773 	ai.ai_port_cnt = &usp->us_port_cnt;
774 
775 	rval = USBSER_DS_ATTACH(usp, &ai);
776 
777 	if ((rval != USB_SUCCESS) || (usp->us_ds_hdl == NULL) ||
778 	    (usp->us_port_cnt == 0)) {
779 		USB_DPRINTF_L4(DPRINT_ATTACH, usp->us_lh, "usbser_attach_dev: "
780 		    "failed %d %p %d", rval, usp->us_ds_hdl, usp->us_port_cnt);
781 
782 		return (DDI_FAILURE);
783 	}
784 
785 	USB_DPRINTF_L4(DPRINT_ATTACH, usp->us_lh,
786 	    "usbser_attach_dev: port_cnt = %d", usp->us_port_cnt);
787 
788 	return (DDI_SUCCESS);
789 }
790 
791 
792 /*
793  * detach entire device
794  */
795 static void
796 usbser_detach_dev(usbser_state_t *usp)
797 {
798 	USBSER_DS_DETACH(usp);
799 }
800 
801 
802 /*
803  * attach each individual port
804  */
805 static int
806 usbser_attach_ports(usbser_state_t *usp)
807 {
808 	int		i;
809 	usbser_port_t	*pp;
810 	ds_cb_t		ds_cb;
811 
812 	/*
813 	 * allocate port array
814 	 */
815 	usp->us_ports = kmem_zalloc(usp->us_port_cnt *
816 					sizeof (usbser_port_t), KM_SLEEP);
817 
818 	/* callback handlers */
819 	ds_cb.cb_tx = usbser_tx_cb;
820 	ds_cb.cb_rx = usbser_rx_cb;
821 	ds_cb.cb_status = usbser_status_cb;
822 
823 	/*
824 	 * initialize each port
825 	 */
826 	for (i = 0; i < usp->us_port_cnt; i++) {
827 		pp = &usp->us_ports[i];
828 
829 		/*
830 		 * initialize data
831 		 */
832 		pp->port_num = i;
833 		pp->port_usp = usp;
834 		pp->port_ds_ops = usp->us_ds_ops;
835 		pp->port_ds_hdl = usp->us_ds_hdl;
836 
837 		/* allocate log handle */
838 		(void) sprintf(pp->port_lh_name, "usbs[%d].", i);
839 		pp->port_lh = usb_alloc_log_hdl(usp->us_dip,
840 			pp->port_lh_name, &usbser_errlevel, &usbser_errmask,
841 			&usbser_instance_debug, 0);
842 
843 		mutex_init(&pp->port_mutex, NULL, MUTEX_DRIVER, (void *)NULL);
844 		cv_init(&pp->port_state_cv, NULL, CV_DEFAULT, NULL);
845 		cv_init(&pp->port_act_cv, NULL, CV_DEFAULT, NULL);
846 		cv_init(&pp->port_car_cv, NULL, CV_DEFAULT, NULL);
847 
848 		/*
849 		 * init threads
850 		 */
851 		pp->port_wq_thread.thr_port = pp;
852 		pp->port_wq_thread.thr_func = usbser_wq_thread;
853 		pp->port_wq_thread.thr_arg = (void *)&pp->port_wq_thread;
854 		cv_init(&pp->port_wq_thread.thr_cv, NULL, CV_DEFAULT, NULL);
855 
856 		pp->port_rq_thread.thr_port = pp;
857 		pp->port_rq_thread.thr_func = usbser_rq_thread;
858 		pp->port_rq_thread.thr_arg = (void *)&pp->port_rq_thread;
859 		cv_init(&pp->port_rq_thread.thr_cv, NULL, CV_DEFAULT, NULL);
860 
861 		/*
862 		 * register callbacks
863 		 */
864 		ds_cb.cb_arg = (caddr_t)pp;
865 		USBSER_DS_REGISTER_CB(usp, i, &ds_cb);
866 
867 		pp->port_state = USBSER_PORT_CLOSED;
868 
869 		if (usbser_create_port_minor_nodes(usp, i) != USB_SUCCESS) {
870 			usbser_detach_ports(usp);
871 
872 			return (DDI_FAILURE);
873 		}
874 	}
875 
876 	return (DDI_SUCCESS);
877 }
878 
879 
880 /*
881  * create a pair of minor nodes for the port
882  */
883 static int
884 usbser_create_port_minor_nodes(usbser_state_t *usp, int port_num)
885 {
886 	int	instance = usp->us_instance;
887 	minor_t	minor;
888 	char	name[16];
889 
890 	/*
891 	 * tty node
892 	 */
893 	(void) sprintf(name, "%d", port_num);
894 	minor = USBSER_MAKEMINOR(instance, port_num, 0);
895 
896 	if (ddi_create_minor_node(usp->us_dip, name,
897 	    S_IFCHR, minor, DDI_NT_SERIAL, NULL) != DDI_SUCCESS) {
898 
899 		return (USB_FAILURE);
900 	}
901 
902 	/*
903 	 * dial-out node
904 	 */
905 	(void) sprintf(name, "%d,cu", port_num);
906 	minor = USBSER_MAKEMINOR(instance, port_num, OUTLINE);
907 
908 	if (ddi_create_minor_node(usp->us_dip, name,
909 	    S_IFCHR, minor, DDI_NT_SERIAL_DO, NULL) != DDI_SUCCESS) {
910 
911 		return (USB_FAILURE);
912 	}
913 
914 	return (USB_SUCCESS);
915 }
916 
917 
918 /*
919  * detach each port individually
920  */
921 static void
922 usbser_detach_ports(usbser_state_t *usp)
923 {
924 	int		i;
925 	int		sz;
926 	usbser_port_t	*pp;
927 
928 	/*
929 	 * remove all minor nodes
930 	 */
931 	ddi_remove_minor_node(usp->us_dip, NULL);
932 
933 	for (i = 0; i < usp->us_port_cnt; i++) {
934 		pp = &usp->us_ports[i];
935 
936 		if (pp->port_state != USBSER_PORT_CLOSED) {
937 			ASSERT(pp->port_state == USBSER_PORT_NOT_INIT);
938 
939 			continue;
940 		}
941 
942 		USBSER_DS_UNREGISTER_CB(usp, i);
943 
944 		mutex_destroy(&pp->port_mutex);
945 		cv_destroy(&pp->port_state_cv);
946 		cv_destroy(&pp->port_act_cv);
947 		cv_destroy(&pp->port_car_cv);
948 
949 		cv_destroy(&pp->port_wq_thread.thr_cv);
950 		cv_destroy(&pp->port_rq_thread.thr_cv);
951 
952 		usb_free_log_hdl(pp->port_lh);
953 	}
954 
955 	/*
956 	 * free memory
957 	 */
958 	sz = usp->us_port_cnt * sizeof (usbser_port_t);
959 	kmem_free(usp->us_ports, sz);
960 	usp->us_ports = NULL;
961 }
962 
963 
964 /*
965  * create a taskq with two threads per port (read and write sides)
966  */
967 static int
968 usbser_create_taskq(usbser_state_t *usp)
969 {
970 	int	nthr = usp->us_port_cnt * 2;
971 
972 	usp->us_taskq = ddi_taskq_create(usp->us_dip, "usbser_taskq",
973 	    nthr, TASKQ_DEFAULTPRI, 0);
974 
975 	return ((usp->us_taskq == NULL) ? DDI_FAILURE : DDI_SUCCESS);
976 }
977 
978 
979 static void
980 usbser_destroy_taskq(usbser_state_t *usp)
981 {
982 	ddi_taskq_destroy(usp->us_taskq);
983 }
984 
985 
986 static void
987 usbser_set_dev_state_init(usbser_state_t *usp)
988 {
989 	mutex_enter(&usp->us_mutex);
990 	usp->us_dev_state = USBSER_DEV_INIT;
991 	mutex_exit(&usp->us_mutex);
992 }
993 
994 /*
995  * hotplugging and power management
996  * ---------------------------------
997  *
998  * disconnect event callback
999  */
1000 /*ARGSUSED*/
1001 static int
1002 usbser_disconnect_cb(dev_info_t *dip)
1003 {
1004 	void		*statep;
1005 	usbser_state_t	*usp;
1006 
1007 	statep = ddi_get_driver_private(dip);
1008 	usp = ddi_get_soft_state(statep, ddi_get_instance(dip));
1009 
1010 	USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh,
1011 	    "usbser_disconnect_cb: dip=%p", dip);
1012 
1013 	mutex_enter(&usp->us_mutex);
1014 	/* safety check in case we're called before attach is complete */
1015 	if (usp->us_dev_state != USB_DEV_ONLINE) {
1016 		mutex_exit(&usp->us_mutex);
1017 
1018 		return (USB_SUCCESS);
1019 	}
1020 	/* prevent further activity */
1021 	usp->us_dev_state = USB_DEV_DISCONNECTED;
1022 	mutex_exit(&usp->us_mutex);
1023 
1024 	/* see if any of the ports are open and do necessary handling */
1025 	usbser_disconnect_ports(usp);
1026 
1027 	/* call DSD to do any necessary work */
1028 	if (USBSER_DS_DISCONNECT(usp) != USB_DEV_DISCONNECTED) {
1029 		USB_DPRINTF_L2(DPRINT_EVENTS, usp->us_lh,
1030 		    "usbser_disconnect_cb: ds_disconnect failed");
1031 	}
1032 
1033 	return (USB_SUCCESS);
1034 }
1035 
1036 
1037 /*
1038  * reconnect event callback
1039  */
1040 /*ARGSUSED*/
1041 static int
1042 usbser_reconnect_cb(dev_info_t *dip)
1043 {
1044 	void		*statep;
1045 	usbser_state_t	*usp;
1046 
1047 	statep = ddi_get_driver_private(dip);
1048 	usp = ddi_get_soft_state(statep, ddi_get_instance(dip));
1049 
1050 	USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh,
1051 	    "usbser_reconnect_cb: dip=%p", dip);
1052 
1053 	(void) usbser_restore_device_state(usp);
1054 
1055 	return (USB_SUCCESS);
1056 }
1057 
1058 
1059 /*
1060  * if any of the ports is open during disconnect,
1061  * send M_HANGUP message upstream and log a warning
1062  */
1063 static void
1064 usbser_disconnect_ports(usbser_state_t *usp)
1065 {
1066 	usbser_port_t	*pp;
1067 	queue_t		*rq;
1068 	int		complain = 0;
1069 	int		hangup = 0;
1070 	timeout_id_t	delay_id = 0;
1071 	int		i;
1072 
1073 	if (usp->us_ports == NULL) {
1074 		return;
1075 	}
1076 
1077 	for (i = 0; i < usp->us_port_cnt; i++) {
1078 		pp = &usp->us_ports[i];
1079 
1080 		mutex_enter(&pp->port_mutex);
1081 		if (pp->port_state == USBSER_PORT_OPEN ||
1082 		    USBSER_IS_OPENING(pp) ||
1083 		    pp->port_state == USBSER_PORT_CLOSING) {
1084 			complain = 1;
1085 		}
1086 
1087 		if (pp->port_state == USBSER_PORT_OPEN) {
1088 			rq = pp->port_ttycommon.t_readq;
1089 
1090 			/*
1091 			 * hangup the stream; will send actual
1092 			 * M_HANGUP message after releasing mutex
1093 			 */
1094 			pp->port_flags |= USBSER_FL_HUNGUP;
1095 			hangup = 1;
1096 
1097 			/*
1098 			 * cancel all activities
1099 			 */
1100 			usbser_release_port_act(pp, USBSER_ACT_ALL);
1101 
1102 			delay_id = pp->port_delay_id;
1103 			pp->port_delay_id = 0;
1104 
1105 			/* mark disconnected */
1106 			pp->port_state = USBSER_PORT_DISCONNECTED;
1107 			cv_broadcast(&pp->port_state_cv);
1108 		}
1109 		mutex_exit(&pp->port_mutex);
1110 
1111 		if (hangup) {
1112 			(void) putnextctl(rq, M_HANGUP);
1113 			hangup = 0;
1114 		}
1115 
1116 		/*
1117 		 * we couldn't untimeout while holding the mutex - do it now
1118 		 */
1119 		if (delay_id) {
1120 			(void) untimeout(delay_id);
1121 			delay_id = 0;
1122 		}
1123 	}
1124 
1125 	/*
1126 	 * complain about disconnecting device while open
1127 	 */
1128 	if (complain) {
1129 		USB_DPRINTF_L0(DPRINT_EVENTS, usp->us_lh, "device was "
1130 		    "disconnected while open. Data may have been lost");
1131 	}
1132 }
1133 
1134 
1135 /*
1136  * do CPR suspend
1137  *
1138  * We use a trivial CPR strategy - fail if any of the device's ports are open.
1139  * The problem with more sophisticated strategies is that each open port uses
1140  * two threads that sit in the loop until the port is closed, while CPR has to
1141  * stop all kernel threads to succeed. Stopping port threads is a rather
1142  * intrusive and delicate procedure; I leave it as an RFE for now.
1143  *
1144  */
1145 static int
1146 usbser_cpr_suspend(dev_info_t *dip)
1147 {
1148 	void		*statep;
1149 	usbser_state_t	*usp;
1150 	int		new_state;
1151 	int		rval;
1152 
1153 	statep = ddi_get_driver_private(dip);
1154 	usp = ddi_get_soft_state(statep, ddi_get_instance(dip));
1155 
1156 	USB_DPRINTF_L4(DPRINT_EVENTS, usp->us_lh, "usbser_cpr_suspend");
1157 
1158 	/* suspend each port first */
1159 	if (usbser_suspend_ports(usp) != USB_SUCCESS) {
1160 		USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh,
1161 		    "usbser_cpr_suspend: GSD failure");
1162 
1163 		return (USB_FAILURE);
1164 	}
1165 
1166 	new_state = USBSER_DS_SUSPEND(usp);	/* let DSD do its part */
1167 
1168 	mutex_enter(&usp->us_mutex);
1169 	if (new_state == USB_DEV_SUSPENDED) {
1170 		rval = USB_SUCCESS;
1171 	} else {
1172 		ASSERT(new_state == USB_DEV_ONLINE);
1173 		rval = USB_FAILURE;
1174 	}
1175 	usp->us_dev_state = new_state;
1176 	mutex_exit(&usp->us_mutex);
1177 
1178 	return (rval);
1179 }
1180 
1181 
1182 static int
1183 usbser_suspend_ports(usbser_state_t *usp)
1184 {
1185 	usbser_port_t	*pp;
1186 	int		i;
1187 
1188 	for (i = 0; i < usp->us_port_cnt; i++) {
1189 		pp = &usp->us_ports[i];
1190 
1191 		mutex_enter(&pp->port_mutex);
1192 		if (pp->port_state != USBSER_PORT_CLOSED) {
1193 			mutex_exit(&pp->port_mutex);
1194 
1195 			return (USB_FAILURE);
1196 		}
1197 		mutex_exit(&pp->port_mutex);
1198 	}
1199 
1200 	return (USB_SUCCESS);
1201 }
1202 
1203 
1204 /*
1205  * do CPR resume
1206  *
1207  * DSD will return USB_DEV_ONLINE in case of success
1208  */
1209 static void
1210 usbser_cpr_resume(dev_info_t *dip)
1211 {
1212 	void		*statep;
1213 	usbser_state_t	*usp;
1214 
1215 	statep = ddi_get_driver_private(dip);
1216 	usp = ddi_get_soft_state(statep, ddi_get_instance(dip));
1217 
1218 	USB_DPRINTF_L3(DPRINT_EVENTS, usp->us_lh, "usbser_cpr_resume");
1219 
1220 	(void) usbser_restore_device_state(usp);
1221 }
1222 
1223 
1224 /*
1225  * restore device state after CPR resume or reconnect
1226  */
1227 static int
1228 usbser_restore_device_state(usbser_state_t *usp)
1229 {
1230 	int	new_state, current_state;
1231 
1232 	mutex_enter(&usp->us_mutex);
1233 	current_state = usp->us_dev_state;
1234 	mutex_exit(&usp->us_mutex);
1235 
1236 	ASSERT((current_state == USB_DEV_DISCONNECTED) ||
1237 		(current_state == USB_DEV_SUSPENDED));
1238 
1239 	/*
1240 	 * call DSD to perform device-specific work
1241 	 */
1242 	if (current_state == USB_DEV_DISCONNECTED) {
1243 		new_state = USBSER_DS_RECONNECT(usp);
1244 	} else {
1245 		new_state = USBSER_DS_RESUME(usp);
1246 	}
1247 
1248 	mutex_enter(&usp->us_mutex);
1249 	usp->us_dev_state = new_state;
1250 	mutex_exit(&usp->us_mutex);
1251 
1252 	if (new_state == USB_DEV_ONLINE) {
1253 		/*
1254 		 * restore ports state
1255 		 */
1256 		usbser_restore_ports_state(usp);
1257 	}
1258 
1259 	return (USB_SUCCESS);
1260 }
1261 
1262 
1263 /*
1264  * restore ports state after device reconnect/resume
1265  */
1266 static void
1267 usbser_restore_ports_state(usbser_state_t *usp)
1268 {
1269 	usbser_port_t	*pp;
1270 	queue_t		*rq;
1271 	int		i;
1272 
1273 	for (i = 0; i < usp->us_port_cnt; i++) {
1274 		pp = &usp->us_ports[i];
1275 
1276 		mutex_enter(&pp->port_mutex);
1277 		/*
1278 		 * only care about ports that are open
1279 		 */
1280 		if ((pp->port_state != USBSER_PORT_SUSPENDED) &&
1281 		    (pp->port_state != USBSER_PORT_DISCONNECTED)) {
1282 			mutex_exit(&pp->port_mutex);
1283 
1284 			continue;
1285 		}
1286 
1287 		pp->port_state = USBSER_PORT_OPEN;
1288 
1289 		/*
1290 		 * if the stream was hung up during disconnect, restore it
1291 		 */
1292 		if (pp->port_flags & USBSER_FL_HUNGUP) {
1293 			pp->port_flags &= ~USBSER_FL_HUNGUP;
1294 			rq = pp->port_ttycommon.t_readq;
1295 
1296 			mutex_exit(&pp->port_mutex);
1297 			(void) putnextctl(rq, M_UNHANGUP);
1298 			mutex_enter(&pp->port_mutex);
1299 		}
1300 
1301 		/*
1302 		 * restore serial parameters
1303 		 */
1304 		(void) usbser_port_program(pp);
1305 
1306 		/*
1307 		 * wake anything that might be sleeping
1308 		 */
1309 		cv_broadcast(&pp->port_state_cv);
1310 		cv_broadcast(&pp->port_act_cv);
1311 		usbser_thr_wake(&pp->port_wq_thread);
1312 		usbser_thr_wake(&pp->port_rq_thread);
1313 		mutex_exit(&pp->port_mutex);
1314 	}
1315 }
1316 
1317 
1318 /*
1319  * STREAMS subroutines
1320  * -------------------
1321  *
1322  *
1323  * port open state machine
1324  *
1325  * here's a list of things that the driver has to do while open;
1326  * because device can be opened any number of times,
1327  * initial open has additional responsibilities:
1328  *
1329  *	if (initial_open) {
1330  *		initialize soft state;	\
1331  *		DSD open;		- see usbser_open_init()
1332  *		dispatch threads;	/
1333  *	}
1334  *	raise DTR;
1335  *	wait for carrier (if necessary);
1336  *
1337  * we should also take into consideration that two threads can try to open
1338  * the same physical port simultaneously (/dev/term/N and /dev/cua/N).
1339  *
1340  * return values:
1341  *	0	- success;
1342  *	>0	- fail with this error code;
1343  */
1344 static int
1345 usbser_open_setup(queue_t *rq, usbser_port_t *pp, int minor, int flag,
1346 		cred_t *cr)
1347 {
1348 	int	rval = USBSER_CONTINUE;
1349 
1350 	mutex_enter(&pp->port_mutex);
1351 	/*
1352 	 * refer to port state diagram in the header file
1353 	 */
1354 loop:
1355 	switch (pp->port_state) {
1356 	case USBSER_PORT_CLOSED:
1357 		/*
1358 		 * initial open
1359 		 */
1360 		rval = usbser_open_init(pp, minor);
1361 
1362 		break;
1363 	case USBSER_PORT_OPENING_TTY:
1364 		/*
1365 		 * dial-out thread can overtake the port
1366 		 * if tty open thread is sleeping waiting for carrier
1367 		 */
1368 		if ((minor & OUTLINE) && (pp->port_flags & USBSER_FL_WOPEN)) {
1369 			pp->port_state = USBSER_PORT_OPENING_OUT;
1370 
1371 			USB_DPRINTF_L3(DPRINT_OPEN, pp->port_lh,
1372 			    "usbser_open_state: overtake");
1373 		}
1374 
1375 		/* FALLTHRU */
1376 	case USBSER_PORT_OPENING_OUT:
1377 		/*
1378 		 * if no other open in progress, setup the line
1379 		 */
1380 		if (USBSER_NO_OTHER_OPEN(pp, minor)) {
1381 			rval = usbser_open_line_setup(pp, minor, flag);
1382 
1383 			break;
1384 		}
1385 
1386 		/* FALLTHRU */
1387 	case USBSER_PORT_CLOSING:
1388 		/*
1389 		 * wait until close active phase ends
1390 		 */
1391 		if (cv_wait_sig(&pp->port_state_cv, &pp->port_mutex) == 0) {
1392 			rval = EINTR;
1393 		}
1394 
1395 		break;
1396 	case USBSER_PORT_OPEN:
1397 		if ((pp->port_ttycommon.t_flags & TS_XCLUDE) &&
1398 			secpolicy_excl_open(cr) != 0) {
1399 			/*
1400 			 * exclusive use
1401 			 */
1402 			rval = EBUSY;
1403 		} else if (USBSER_OPEN_IN_OTHER_MODE(pp, minor)) {
1404 			/*
1405 			 * tty and dial-out modes are mutually exclusive
1406 			 */
1407 			rval = EBUSY;
1408 		} else {
1409 			/*
1410 			 * port is being re-open in the same mode
1411 			 */
1412 			rval = usbser_open_line_setup(pp, minor, flag);
1413 		}
1414 
1415 		break;
1416 	default:
1417 		rval = ENXIO;
1418 
1419 		break;
1420 	}
1421 
1422 	if (rval == USBSER_CONTINUE) {
1423 
1424 		goto loop;
1425 	}
1426 
1427 	/*
1428 	 * initial open requires additional handling
1429 	 */
1430 	if (USBSER_IS_OPENING(pp)) {
1431 		if (rval == USBSER_COMPLETE) {
1432 			if (pp->port_state == USBSER_PORT_OPENING_OUT) {
1433 				pp->port_flags |= USBSER_FL_OUT;
1434 			}
1435 			pp->port_state = USBSER_PORT_OPEN;
1436 			cv_broadcast(&pp->port_state_cv);
1437 
1438 			usbser_open_queues_init(pp, rq);
1439 		} else {
1440 			usbser_open_fini(pp);
1441 		}
1442 	}
1443 	mutex_exit(&pp->port_mutex);
1444 
1445 	return (rval);
1446 }
1447 
1448 
1449 /*
1450  * initialize the port when opened for the first time
1451  */
1452 static int
1453 usbser_open_init(usbser_port_t *pp, int minor)
1454 {
1455 	usbser_state_t	*usp = pp->port_usp;
1456 	tty_common_t	*tp = &pp->port_ttycommon;
1457 	int		rval = ENXIO;
1458 
1459 	ASSERT(pp->port_state == USBSER_PORT_CLOSED);
1460 
1461 	/*
1462 	 * init state
1463 	 */
1464 	pp->port_act = 0;
1465 	pp->port_flags &= USBSER_FL_PRESERVE;
1466 	pp->port_flowc = '\0';
1467 	pp->port_wq_data_cnt = 0;
1468 
1469 	if (minor & OUTLINE) {
1470 		pp->port_state = USBSER_PORT_OPENING_OUT;
1471 	} else {
1472 		pp->port_state = USBSER_PORT_OPENING_TTY;
1473 	}
1474 
1475 	/*
1476 	 * init termios settings
1477 	 */
1478 	tp->t_iflag = 0;
1479 	tp->t_iocpending = NULL;
1480 	tp->t_size.ws_row = tp->t_size.ws_col = 0;
1481 	tp->t_size.ws_xpixel = tp->t_size.ws_ypixel = 0;
1482 	tp->t_startc = CSTART;
1483 	tp->t_stopc = CSTOP;
1484 
1485 	usbser_check_port_props(pp);
1486 
1487 	/*
1488 	 * dispatch wq and rq threads:
1489 	 * although queues are not enabled at this point,
1490 	 * we will need wq to run status processing callback
1491 	 */
1492 	usbser_thr_dispatch(&pp->port_wq_thread);
1493 	usbser_thr_dispatch(&pp->port_rq_thread);
1494 
1495 	/*
1496 	 * open DSD port
1497 	 */
1498 	mutex_exit(&pp->port_mutex);
1499 	rval = USBSER_DS_OPEN_PORT(usp, pp->port_num);
1500 	mutex_enter(&pp->port_mutex);
1501 
1502 	if (rval != USB_SUCCESS) {
1503 
1504 		return (ENXIO);
1505 	}
1506 	pp->port_flags |= USBSER_FL_DSD_OPEN;
1507 
1508 	/*
1509 	 * program port with default parameters
1510 	 */
1511 	if ((rval = usbser_port_program(pp)) != 0) {
1512 
1513 		return (ENXIO);
1514 	}
1515 
1516 	return (USBSER_CONTINUE);
1517 }
1518 
1519 
1520 /*
1521  * create a pair of minor nodes for the port
1522  */
1523 static void
1524 usbser_check_port_props(usbser_port_t *pp)
1525 {
1526 	dev_info_t	*dip = pp->port_usp->us_dip;
1527 	tty_common_t	*tp = &pp->port_ttycommon;
1528 	struct termios 	*termiosp;
1529 	uint_t		len;
1530 	char		name[20];
1531 
1532 	/*
1533 	 * take default modes from "ttymodes" property if it exists
1534 	 */
1535 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, ddi_root_node(), 0,
1536 	    "ttymodes", (uchar_t **)&termiosp, &len) == DDI_PROP_SUCCESS) {
1537 
1538 		if (len == sizeof (struct termios)) {
1539 			tp->t_cflag = termiosp->c_cflag;
1540 
1541 			if (termiosp->c_iflag & (IXON | IXANY)) {
1542 				tp->t_iflag =
1543 					termiosp->c_iflag & (IXON | IXANY);
1544 				tp->t_startc = termiosp->c_cc[VSTART];
1545 				tp->t_stopc = termiosp->c_cc[VSTOP];
1546 			}
1547 		}
1548 		ddi_prop_free(termiosp);
1549 	}
1550 
1551 	/*
1552 	 * look for "ignore-cd" or "port-N-ignore-cd" property
1553 	 */
1554 	(void) sprintf(name, "port-%d-ignore-cd", pp->port_num);
1555 	if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1556 	    "ignore-cd", 0) ||
1557 	    ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, name, 0)) {
1558 		pp->port_flags |= USBSER_FL_IGNORE_CD;
1559 	} else {
1560 		pp->port_flags &= ~USBSER_FL_IGNORE_CD;
1561 	}
1562 }
1563 
1564 
1565 /*
1566  * undo what was done in usbser_open_init()
1567  */
1568 static void
1569 usbser_open_fini(usbser_port_t *pp)
1570 {
1571 	uint_t		port_num = pp->port_num;
1572 	usbser_state_t	*usp = pp->port_usp;
1573 
1574 	/*
1575 	 * close DSD if it is open
1576 	 */
1577 	if (pp->port_flags & USBSER_FL_DSD_OPEN) {
1578 		mutex_exit(&pp->port_mutex);
1579 		if (USBSER_DS_CLOSE_PORT(usp, port_num) != USB_SUCCESS) {
1580 			USB_DPRINTF_L2(DPRINT_CLOSE, pp->port_lh,
1581 			    "usbser_open_fini: CLOSE_PORT fail");
1582 		}
1583 		mutex_enter(&pp->port_mutex);
1584 	}
1585 
1586 	/*
1587 	 * cancel threads
1588 	 */
1589 	usbser_thr_cancel(&pp->port_wq_thread);
1590 	usbser_thr_cancel(&pp->port_rq_thread);
1591 
1592 	/*
1593 	 * unpdate soft state
1594 	 */
1595 	pp->port_state = USBSER_PORT_CLOSED;
1596 	cv_broadcast(&pp->port_state_cv);
1597 	cv_broadcast(&pp->port_car_cv);
1598 }
1599 
1600 
1601 /*
1602  * setup serial line
1603  */
1604 static int
1605 usbser_open_line_setup(usbser_port_t *pp, int minor, int flag)
1606 {
1607 	int	rval;
1608 
1609 	mutex_exit(&pp->port_mutex);
1610 	/*
1611 	 * prevent opening a disconnected device
1612 	 */
1613 	if (!usbser_dev_is_online(pp->port_usp)) {
1614 		mutex_enter(&pp->port_mutex);
1615 
1616 		return (ENXIO);
1617 	}
1618 
1619 	/* raise DTR on every open */
1620 	(void) USBSER_DS_SET_MODEM_CTL(pp, TIOCM_DTR, TIOCM_DTR);
1621 
1622 	mutex_enter(&pp->port_mutex);
1623 	/*
1624 	 * check carrier
1625 	 */
1626 	rval = usbser_open_carrier_check(pp, minor, flag);
1627 
1628 	return (rval);
1629 }
1630 
1631 
1632 /*
1633  * check carrier and wait if needed
1634  */
1635 static int
1636 usbser_open_carrier_check(usbser_port_t *pp, int minor, int flag)
1637 {
1638 	tty_common_t	*tp = &pp->port_ttycommon;
1639 	int		val = 0;
1640 	int		rval;
1641 
1642 	if (pp->port_flags & USBSER_FL_IGNORE_CD) {
1643 		tp->t_flags |= TS_SOFTCAR;
1644 	}
1645 
1646 	/*
1647 	 * check carrier
1648 	 */
1649 	if (tp->t_flags & TS_SOFTCAR) {
1650 		pp->port_flags |= USBSER_FL_CARR_ON;
1651 	} else if (USBSER_DS_GET_MODEM_CTL(pp, TIOCM_CD, &val) != USB_SUCCESS) {
1652 
1653 		return (ENXIO);
1654 	} else if (val & TIOCM_CD) {
1655 		pp->port_flags |= USBSER_FL_CARR_ON;
1656 	} else {
1657 		pp->port_flags &= ~USBSER_FL_CARR_ON;
1658 	}
1659 
1660 	/*
1661 	 * don't block if 1) not allowed to, 2) this is a local device,
1662 	 * 3) opening in dial-out mode, or 4) carrier is already on
1663 	 */
1664 	if ((flag & (FNDELAY | FNONBLOCK)) || (tp->t_cflag & CLOCAL) ||
1665 	    (minor & OUTLINE) || (pp->port_flags & USBSER_FL_CARR_ON)) {
1666 
1667 		return (USBSER_COMPLETE);
1668 	}
1669 
1670 	/*
1671 	 * block until carrier up (only in tty mode)
1672 	 */
1673 	USB_DPRINTF_L4(DPRINT_OPEN, pp->port_lh,
1674 	    "usbser_open_carrier_check: waiting for carrier...");
1675 
1676 	pp->port_flags |= USBSER_FL_WOPEN;
1677 
1678 	rval = cv_wait_sig(&pp->port_car_cv, &pp->port_mutex);
1679 
1680 	pp->port_flags &= ~USBSER_FL_WOPEN;
1681 
1682 	if (rval == 0) {
1683 		/*
1684 		 * interrupted with a signal
1685 		 */
1686 		return (EINTR);
1687 	} else {
1688 		/*
1689 		 * try again
1690 		 */
1691 		return (USBSER_CONTINUE);
1692 	}
1693 }
1694 
1695 
1696 /*
1697  * during open, setup queues and message processing
1698  */
1699 static void
1700 usbser_open_queues_init(usbser_port_t *pp, queue_t *rq)
1701 {
1702 	pp->port_ttycommon.t_readq = rq;
1703 	pp->port_ttycommon.t_writeq = WR(rq);
1704 	rq->q_ptr = WR(rq)->q_ptr = (caddr_t)pp;
1705 
1706 	qprocson(rq);
1707 }
1708 
1709 
1710 /*
1711  * clean up queues and message processing
1712  */
1713 static void
1714 usbser_open_queues_fini(usbser_port_t *pp)
1715 {
1716 	queue_t	*rq = pp->port_ttycommon.t_readq;
1717 
1718 	mutex_exit(&pp->port_mutex);
1719 	/*
1720 	 * clean up queues
1721 	 */
1722 	qprocsoff(rq);
1723 
1724 	/*
1725 	 * free unused messages
1726 	 */
1727 	flushq(rq, FLUSHALL);
1728 	flushq(WR(rq), FLUSHALL);
1729 
1730 	rq->q_ptr = WR(rq)->q_ptr = NULL;
1731 	ttycommon_close(&pp->port_ttycommon);
1732 	mutex_enter(&pp->port_mutex);
1733 }
1734 
1735 
1736 /*
1737  * during close, wait until pending data is gone or the signal is sent
1738  */
1739 static void
1740 usbser_close_drain(usbser_port_t *pp)
1741 {
1742 	int	need_drain;
1743 	clock_t	until;
1744 	int	rval;
1745 
1746 	/*
1747 	 * port_wq_data_cnt indicates amount of data on the write queue,
1748 	 * which becomes zero when all data is submitted to DSD. But usbser
1749 	 * stays busy until it gets tx callback from DSD, signalling that
1750 	 * data has been sent over USB. To be continued in the next comment...
1751 	 */
1752 	until = ddi_get_lbolt() +
1753 		drv_usectohz(USBSER_WQ_DRAIN_TIMEOUT * 1000000);
1754 
1755 	while ((pp->port_wq_data_cnt > 0) && USBSER_PORT_IS_BUSY(pp)) {
1756 		if ((rval = cv_timedwait_sig(&pp->port_act_cv, &pp->port_mutex,
1757 		    until)) <= 0) {
1758 
1759 			break;
1760 		}
1761 	}
1762 
1763 	/* don't drain if timed out or received a signal */
1764 	need_drain = (pp->port_wq_data_cnt == 0) || !USBSER_PORT_IS_BUSY(pp) ||
1765 			(rval != 0);
1766 
1767 	mutex_exit(&pp->port_mutex);
1768 	/*
1769 	 * Once the data reaches USB serial box, it may still be stored in its
1770 	 * internal output buffer (FIFO). We call DSD drain to ensure that all
1771 	 * the data is transmitted transmitted over the serial line.
1772 	 */
1773 	if (need_drain) {
1774 		rval = USBSER_DS_FIFO_DRAIN(pp, USBSER_TX_FIFO_DRAIN_TIMEOUT);
1775 		if (rval != USB_SUCCESS) {
1776 			(void) USBSER_DS_FIFO_FLUSH(pp, DS_TX);
1777 		}
1778 	} else {
1779 		(void) USBSER_DS_FIFO_FLUSH(pp, DS_TX);
1780 	}
1781 	mutex_enter(&pp->port_mutex);
1782 }
1783 
1784 
1785 /*
1786  * during close, cancel break/delay
1787  */
1788 static void
1789 usbser_close_cancel_break(usbser_port_t *pp)
1790 {
1791 	timeout_id_t	delay_id;
1792 
1793 	if (pp->port_act & USBSER_ACT_BREAK) {
1794 		delay_id = pp->port_delay_id;
1795 		pp->port_delay_id = 0;
1796 
1797 		mutex_exit(&pp->port_mutex);
1798 		(void) untimeout(delay_id);
1799 		(void) USBSER_DS_BREAK_CTL(pp, DS_OFF);
1800 		mutex_enter(&pp->port_mutex);
1801 
1802 		pp->port_act &= ~USBSER_ACT_BREAK;
1803 	}
1804 }
1805 
1806 
1807 /*
1808  * during close, drop RTS/DTR if necessary
1809  */
1810 static void
1811 usbser_close_hangup(usbser_port_t *pp)
1812 {
1813 	/*
1814 	 * drop DTR and RTS if HUPCL is set
1815 	 */
1816 	if (pp->port_ttycommon.t_cflag & HUPCL) {
1817 		mutex_exit(&pp->port_mutex);
1818 		(void) USBSER_DS_SET_MODEM_CTL(pp, TIOCM_RTS | TIOCM_DTR, 0);
1819 		mutex_enter(&pp->port_mutex);
1820 	}
1821 }
1822 
1823 
1824 /*
1825  * state cleanup during close
1826  */
1827 static void
1828 usbser_close_cleanup(usbser_port_t *pp)
1829 {
1830 	usbser_open_queues_fini(pp);
1831 
1832 	usbser_open_fini(pp);
1833 }
1834 
1835 
1836 /*
1837  *
1838  * thread management
1839  * -----------------
1840  *
1841  *
1842  * dispatch a thread
1843  */
1844 static void
1845 usbser_thr_dispatch(usbser_thread_t *thr)
1846 {
1847 	usbser_port_t	*pp = thr->thr_port;
1848 	usbser_state_t	*usp = pp->port_usp;
1849 	int		rval;
1850 
1851 	ASSERT(mutex_owned(&pp->port_mutex));
1852 	ASSERT((thr->thr_flags & USBSER_THR_RUNNING) == 0);
1853 
1854 	thr->thr_flags = USBSER_THR_RUNNING;
1855 
1856 	rval = ddi_taskq_dispatch(usp->us_taskq, thr->thr_func, thr->thr_arg,
1857 			DDI_SLEEP);
1858 	ASSERT(rval == DDI_SUCCESS);
1859 }
1860 
1861 
1862 /*
1863  * cancel a thread
1864  */
1865 static void
1866 usbser_thr_cancel(usbser_thread_t *thr)
1867 {
1868 	usbser_port_t	*pp = thr->thr_port;
1869 
1870 	ASSERT(mutex_owned(&pp->port_mutex));
1871 
1872 	thr->thr_flags &= ~USBSER_THR_RUNNING;
1873 	cv_signal(&thr->thr_cv);
1874 
1875 	/* wait until the thread actually exits */
1876 	do {
1877 		cv_wait(&thr->thr_cv, &pp->port_mutex);
1878 
1879 	} while ((thr->thr_flags & USBSER_THR_EXITED) == 0);
1880 }
1881 
1882 
1883 /*
1884  * wake thread
1885  */
1886 static void
1887 usbser_thr_wake(usbser_thread_t *thr)
1888 {
1889 	usbser_port_t	*pp = thr->thr_port;
1890 
1891 	ASSERT(mutex_owned(&pp->port_mutex));
1892 
1893 	thr->thr_flags |= USBSER_THR_WAKE;
1894 	cv_signal(&thr->thr_cv);
1895 }
1896 
1897 
1898 /*
1899  * thread handling write queue requests
1900  */
1901 static void
1902 usbser_wq_thread(void *arg)
1903 {
1904 	usbser_thread_t	*thr = (usbser_thread_t *)arg;
1905 	usbser_port_t	*pp = thr->thr_port;
1906 
1907 	USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wq_thread: enter");
1908 
1909 	mutex_enter(&pp->port_mutex);
1910 	while (thr->thr_flags & USBSER_THR_RUNNING) {
1911 		/*
1912 		 * when woken, see what we should do
1913 		 */
1914 		if (thr->thr_flags & USBSER_THR_WAKE) {
1915 			thr->thr_flags &= ~USBSER_THR_WAKE;
1916 
1917 			/*
1918 			 * status callback pending?
1919 			 */
1920 			if (pp->port_flags & USBSER_FL_STATUS_CB) {
1921 				usbser_status_proc_cb(pp);
1922 			}
1923 
1924 			usbser_wmsg(pp);
1925 		} else {
1926 			/*
1927 			 * sleep until woken up to do some work, e.g:
1928 			 * - new message arrives;
1929 			 * - data transmit completes;
1930 			 * - status callback pending;
1931 			 * - wq thread is cancelled;
1932 			 */
1933 			cv_wait(&thr->thr_cv, &pp->port_mutex);
1934 			USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh,
1935 			    "usbser_wq_thread: wakeup");
1936 		}
1937 	}
1938 	thr->thr_flags |= USBSER_THR_EXITED;
1939 	cv_signal(&thr->thr_cv);
1940 	USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wq_thread: exit");
1941 	mutex_exit(&pp->port_mutex);
1942 }
1943 
1944 
1945 /*
1946  * thread handling read queue requests
1947  */
1948 static void
1949 usbser_rq_thread(void *arg)
1950 {
1951 	usbser_thread_t	*thr = (usbser_thread_t *)arg;
1952 	usbser_port_t	*pp = thr->thr_port;
1953 
1954 	USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_rq_thread: enter");
1955 
1956 	mutex_enter(&pp->port_mutex);
1957 	while (thr->thr_flags & USBSER_THR_RUNNING) {
1958 		/*
1959 		 * read service routine will wake us when
1960 		 * more space is available on the read queue
1961 		 */
1962 		if (thr->thr_flags & USBSER_THR_WAKE) {
1963 			thr->thr_flags &= ~USBSER_THR_WAKE;
1964 
1965 			/*
1966 			 * don't process messages until queue is enabled
1967 			 */
1968 			if (!pp->port_ttycommon.t_readq) {
1969 
1970 				continue;
1971 			}
1972 
1973 			/*
1974 			 * check whether we need to resume receive
1975 			 */
1976 			if (pp->port_flags & USBSER_FL_RX_STOPPED) {
1977 				pp->port_flowc = pp->port_ttycommon.t_startc;
1978 				usbser_inbound_flow_ctl(pp);
1979 			}
1980 
1981 			/*
1982 			 * grab more data if available
1983 			 */
1984 			mutex_exit(&pp->port_mutex);
1985 			usbser_rx_cb((caddr_t)pp);
1986 			mutex_enter(&pp->port_mutex);
1987 		} else {
1988 			cv_wait(&thr->thr_cv, &pp->port_mutex);
1989 			USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh,
1990 			    "usbser_rq_thread: wakeup");
1991 		}
1992 	}
1993 	thr->thr_flags |= USBSER_THR_EXITED;
1994 	cv_signal(&thr->thr_cv);
1995 	USB_DPRINTF_L4(DPRINT_RQ, pp->port_lh, "usbser_rq_thread: exit");
1996 	mutex_exit(&pp->port_mutex);
1997 }
1998 
1999 
2000 /*
2001  * DSD callbacks
2002  * -------------
2003  *
2004  * Note: to avoid deadlocks with DSD, these callbacks
2005  * should not call DSD functions that can block.
2006  *
2007  *
2008  * transmit callback
2009  *
2010  * invoked by DSD when the last byte of data is transmitted over USB
2011  */
2012 static void
2013 usbser_tx_cb(caddr_t arg)
2014 {
2015 	usbser_port_t	*pp = (usbser_port_t *)arg;
2016 	int		online;
2017 
2018 	online = usbser_dev_is_online(pp->port_usp);
2019 
2020 	mutex_enter(&pp->port_mutex);
2021 	USB_DPRINTF_L4(DPRINT_TX_CB, pp->port_lh,
2022 	    "usbser_tx_cb: act=%x curthread=%p", pp->port_act, curthread);
2023 
2024 	usbser_release_port_act(pp, USBSER_ACT_TX);
2025 
2026 	if (online && USBSER_PORT_ACCESS_OK(pp) && !USBSER_PORT_IS_BUSY(pp)) {
2027 		/*
2028 		 * wake wq thread for further data/ioctl processing
2029 		 */
2030 		usbser_thr_wake(&pp->port_wq_thread);
2031 	}
2032 	mutex_exit(&pp->port_mutex);
2033 }
2034 
2035 
2036 /*
2037  * receive callback
2038  *
2039  * invoked by DSD when there is more data for us to pick
2040  */
2041 static void
2042 usbser_rx_cb(caddr_t arg)
2043 {
2044 	usbser_port_t	*pp = (usbser_port_t *)arg;
2045 	queue_t		*rq, *wq;
2046 	mblk_t		*mp;		/* current mblk */
2047 	mblk_t		*data, *data_tail; /* M_DATA mblk list and its tail */
2048 	mblk_t		*emp;		/* error (M_BREAK) mblk */
2049 
2050 	USB_DPRINTF_L4(DPRINT_RX_CB, pp->port_lh, "usbser_rx_cb");
2051 
2052 	if (!usbser_dev_is_online(pp->port_usp)) {
2053 
2054 		return;
2055 	}
2056 
2057 	/* get data from DSD */
2058 	if ((mp = USBSER_DS_RX(pp)) == NULL) {
2059 
2060 		return;
2061 	}
2062 
2063 	mutex_enter(&pp->port_mutex);
2064 	if ((!USBSER_PORT_ACCESS_OK(pp)) ||
2065 	    ((pp->port_ttycommon.t_cflag & CREAD) == 0)) {
2066 		freemsg(mp);
2067 		mutex_exit(&pp->port_mutex);
2068 		USB_DPRINTF_L3(DPRINT_RX_CB, pp->port_lh,
2069 		    "usbser_rx_cb: access not ok or receiver disabled");
2070 
2071 		return;
2072 	}
2073 
2074 	usbser_serialize_port_act(pp, USBSER_ACT_RX);
2075 
2076 	rq = pp->port_ttycommon.t_readq;
2077 	wq = pp->port_ttycommon.t_writeq;
2078 	mutex_exit(&pp->port_mutex);
2079 
2080 	/*
2081 	 * DSD data is a b_cont-linked list of M_DATA and M_BREAK blocks.
2082 	 * M_DATA is correctly received data.
2083 	 * M_BREAK is a character with either framing or parity error.
2084 	 *
2085 	 * this loop runs through the list of mblks. when it meets an M_BREAK,
2086 	 * it sends all leading M_DATA's in one shot, then sends M_BREAK.
2087 	 * in the trivial case when list contains only M_DATA's, the loop
2088 	 * does nothing but set data variable.
2089 	 */
2090 	data = data_tail = NULL;
2091 	while (mp) {
2092 		/*
2093 		 * skip data until we meet M_BREAK or end of list
2094 		 */
2095 		if (DB_TYPE(mp) == M_DATA) {
2096 			if (data == NULL) {
2097 				data = mp;
2098 			}
2099 			data_tail = mp;
2100 			mp = mp->b_cont;
2101 
2102 			continue;
2103 		}
2104 
2105 		/* detach data list from mp */
2106 		if (data_tail) {
2107 			data_tail->b_cont = NULL;
2108 		}
2109 		/* detach emp from the list */
2110 		emp = mp;
2111 		mp = mp->b_cont;
2112 		emp->b_cont = NULL;
2113 
2114 		/* DSD shouldn't send anything but M_DATA or M_BREAK */
2115 		if ((DB_TYPE(emp) != M_BREAK) || (MBLKL(emp) != 2)) {
2116 			freemsg(emp);
2117 			USB_DPRINTF_L2(DPRINT_RX_CB, pp->port_lh,
2118 			    "usbser_rx_cb: bad message");
2119 
2120 			continue;
2121 		}
2122 
2123 		/*
2124 		 * first tweak and send M_DATA's
2125 		 */
2126 		if (data) {
2127 			usbser_rx_massage_data(pp, data);
2128 			usbser_rx_cb_put(pp, rq, wq, data);
2129 			data = data_tail = NULL;
2130 		}
2131 
2132 		/*
2133 		 * now tweak and send M_BREAK
2134 		 */
2135 		mutex_enter(&pp->port_mutex);
2136 		usbser_rx_massage_mbreak(pp, emp);
2137 		mutex_exit(&pp->port_mutex);
2138 		usbser_rx_cb_put(pp, rq, wq, emp);
2139 	}
2140 
2141 	/* send the rest of the data, if any */
2142 	if (data) {
2143 		usbser_rx_massage_data(pp, data);
2144 		usbser_rx_cb_put(pp, rq, wq, data);
2145 	}
2146 
2147 	mutex_enter(&pp->port_mutex);
2148 	usbser_release_port_act(pp, USBSER_ACT_RX);
2149 	mutex_exit(&pp->port_mutex);
2150 }
2151 
2152 /*
2153  * the joys of termio -- this is to accomodate Unix98 assertion:
2154  *
2155  *   If PARENB is supported and is set, when PARMRK is set, and CSIZE is
2156  *   set to CS8, and IGNPAR is clear, and ISTRIP is clear, a valid
2157  *   character of '\377' is read as '\377', '\377'.
2158  *
2159  *   Posix Ref: Assertion 7.1.2.2-16(C)
2160  *
2161  * this requires the driver to scan every incoming valid character
2162  */
2163 static void
2164 usbser_rx_massage_data(usbser_port_t *pp, mblk_t *mp)
2165 {
2166 	tty_common_t	*tp = &pp->port_ttycommon;
2167 	uchar_t		*p;
2168 	mblk_t		*newmp;
2169 	int		tailsz;
2170 
2171 	/* avoid scanning if possible */
2172 	mutex_enter(&pp->port_mutex);
2173 	if (!((tp->t_cflag & PARENB) && (tp->t_iflag & PARMRK) &&
2174 	    ((tp->t_cflag & CSIZE) == CS8) &&
2175 	    ((tp->t_iflag & (IGNPAR|ISTRIP)) == 0))) {
2176 		mutex_exit(&pp->port_mutex);
2177 
2178 		return;
2179 	}
2180 	mutex_exit(&pp->port_mutex);
2181 
2182 	while (mp) {
2183 		for (p = mp->b_rptr; p < mp->b_wptr; ) {
2184 			if (*p++ != 0377) {
2185 
2186 				continue;
2187 			}
2188 			USB_DPRINTF_L4(DPRINT_RX_CB, pp->port_lh,
2189 			    "usbser_rx_massage_data: mp=%p off=%d(%d)",
2190 			    mp, p - mp->b_rptr - 1, MBLKL(mp));
2191 
2192 			/*
2193 			 * insert another 0377 after this one. all data after
2194 			 * the original 0377 have to be copied to the new mblk
2195 			 */
2196 			tailsz = mp->b_wptr - p;
2197 			if ((newmp = allocb(tailsz + 1, BPRI_HI)) == NULL) {
2198 				USB_DPRINTF_L2(DPRINT_RX_CB, pp->port_lh,
2199 				    "usbser_rx_massage_data: allocb failed");
2200 
2201 				continue;
2202 			}
2203 
2204 			/* fill in the new mblk */
2205 			*newmp->b_wptr++ = 0377;
2206 			if (tailsz > 0) {
2207 				bcopy(p, newmp->b_wptr, tailsz);
2208 				newmp->b_wptr += tailsz;
2209 			}
2210 			/* shrink the original mblk */
2211 			mp->b_wptr = p;
2212 
2213 			newmp->b_cont = mp->b_cont;
2214 			mp->b_cont = newmp;
2215 			p = newmp->b_rptr + 1;
2216 			mp = newmp;
2217 		}
2218 		mp = mp->b_cont;
2219 	}
2220 }
2221 
2222 /*
2223  * more joys of termio
2224  */
2225 static void
2226 usbser_rx_massage_mbreak(usbser_port_t *pp, mblk_t *mp)
2227 {
2228 	tty_common_t	*tp = &pp->port_ttycommon;
2229 	uchar_t		err, c;
2230 
2231 	err = *mp->b_rptr;
2232 	c = *(mp->b_rptr + 1);
2233 
2234 	if ((err & (DS_FRAMING_ERR | DS_BREAK_ERR)) && (c == 0)) {
2235 		/* break */
2236 		mp->b_rptr += 2;
2237 	} else if (!(tp->t_iflag & INPCK) && (err & (DS_PARITY_ERR))) {
2238 		/* Posix Ref: Assertion 7.1.2.2-20(C) */
2239 		mp->b_rptr++;
2240 		DB_TYPE(mp) = M_DATA;
2241 	} else {
2242 		/* for ldterm to handle */
2243 		mp->b_rptr++;
2244 	}
2245 
2246 	USB_DPRINTF_L4(DPRINT_RX_CB, pp->port_lh,
2247 	    "usbser_rx_massage_mbreak: type=%x len=%d [0]=0%o",
2248 	    DB_TYPE(mp), MBLKL(mp), (MBLKL(mp) > 0) ? *mp->b_rptr : 45);
2249 }
2250 
2251 
2252 /*
2253  * in rx callback, try to send an mblk upstream
2254  */
2255 static void
2256 usbser_rx_cb_put(usbser_port_t *pp, queue_t *rq, queue_t *wq, mblk_t *mp)
2257 {
2258 	if (canputnext(rq)) {
2259 		putnext(rq, mp);
2260 	} else if (canput(rq) && putq(rq, mp)) {
2261 		/*
2262 		 * full queue indicates the need for inbound flow control
2263 		 */
2264 		(void) putctl(wq, M_STOPI);
2265 		usbser_st_put_stopi++;
2266 
2267 		USB_DPRINTF_L3(DPRINT_RX_CB, pp->port_lh,
2268 		    "usbser_rx_cb: cannot putnext, flow ctl");
2269 	} else {
2270 		freemsg(mp);
2271 		usbser_st_rx_data_loss++;
2272 		(void) putctl(wq, M_STOPI);
2273 		usbser_st_put_stopi++;
2274 
2275 		USB_DPRINTF_L1(DPRINT_RX_CB, pp->port_lh,
2276 		    "input overrun");
2277 	}
2278 }
2279 
2280 
2281 /*
2282  * modem status change callback
2283  *
2284  * each time external status lines are changed, DSD calls this routine
2285  */
2286 static void
2287 usbser_status_cb(caddr_t arg)
2288 {
2289 	usbser_port_t	*pp = (usbser_port_t *)arg;
2290 
2291 	USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh, "usbser_status_cb");
2292 
2293 	if (!usbser_dev_is_online(pp->port_usp)) {
2294 
2295 		return;
2296 	}
2297 
2298 	/*
2299 	 * actual processing will be done in usbser_status_proc_cb()
2300 	 * running in wq thread
2301 	 */
2302 	mutex_enter(&pp->port_mutex);
2303 	if (USBSER_PORT_ACCESS_OK(pp) || USBSER_IS_OPENING(pp)) {
2304 		pp->port_flags |= USBSER_FL_STATUS_CB;
2305 		usbser_thr_wake(&pp->port_wq_thread);
2306 	}
2307 	mutex_exit(&pp->port_mutex);
2308 }
2309 
2310 
2311 /*
2312  * modem status change
2313  */
2314 static void
2315 usbser_status_proc_cb(usbser_port_t *pp)
2316 {
2317 	tty_common_t	*tp = &pp->port_ttycommon;
2318 	queue_t		*rq, *wq;
2319 	int		status;
2320 	int		drop_dtr = 0;
2321 	int		rq_msg = 0, wq_msg = 0;
2322 
2323 	USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh, "usbser_status_proc_cb");
2324 
2325 	pp->port_flags &= ~USBSER_FL_STATUS_CB;
2326 
2327 	mutex_exit(&pp->port_mutex);
2328 	if (!usbser_dev_is_online(pp->port_usp)) {
2329 		mutex_enter(&pp->port_mutex);
2330 
2331 		return;
2332 	}
2333 
2334 	/* get modem status */
2335 	if (USBSER_DS_GET_MODEM_CTL(pp, -1, &status) != USB_SUCCESS) {
2336 		mutex_enter(&pp->port_mutex);
2337 
2338 		return;
2339 	}
2340 
2341 	mutex_enter(&pp->port_mutex);
2342 	usbser_serialize_port_act(pp, USBSER_ACT_CTL);
2343 
2344 	rq = pp->port_ttycommon.t_readq;
2345 	wq = pp->port_ttycommon.t_writeq;
2346 
2347 	/*
2348 	 * outbound flow control
2349 	 */
2350 	if (tp->t_cflag & CRTSCTS) {
2351 		if (!(status & TIOCM_CTS)) {
2352 			/*
2353 			 * CTS dropped, stop xmit
2354 			 */
2355 			if (!(pp->port_flags & USBSER_FL_TX_STOPPED)) {
2356 				wq_msg = M_STOP;
2357 			}
2358 		} else if (pp->port_flags & USBSER_FL_TX_STOPPED) {
2359 			/*
2360 			 * CTS raised, resume xmit
2361 			 */
2362 			wq_msg = M_START;
2363 		}
2364 	}
2365 
2366 	/*
2367 	 * check carrier
2368 	 */
2369 	if ((status & TIOCM_CD) || (tp->t_flags & TS_SOFTCAR)) {
2370 		/*
2371 		 * carrier present
2372 		 */
2373 		if ((pp->port_flags & USBSER_FL_CARR_ON) == 0) {
2374 			pp->port_flags |= USBSER_FL_CARR_ON;
2375 
2376 			rq_msg = M_UNHANGUP;
2377 			/*
2378 			 * wake open
2379 			 */
2380 			if (pp->port_flags & USBSER_FL_WOPEN) {
2381 				cv_broadcast(&pp->port_car_cv);
2382 			}
2383 
2384 			USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh,
2385 			    "usbser_status_cb: carr on");
2386 		}
2387 	} else if (pp->port_flags & USBSER_FL_CARR_ON) {
2388 		pp->port_flags &= ~USBSER_FL_CARR_ON;
2389 		/*
2390 		 * carrier went away: if not local line, drop DTR
2391 		 */
2392 		if (!(tp->t_cflag & CLOCAL)) {
2393 			drop_dtr = 1;
2394 			rq_msg = M_HANGUP;
2395 		}
2396 		if ((pp->port_flags & USBSER_FL_TX_STOPPED) && (wq_msg == 0)) {
2397 			wq_msg = M_START;
2398 		}
2399 
2400 		USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh,
2401 		    "usbser_status_cb: carr off");
2402 	}
2403 	mutex_exit(&pp->port_mutex);
2404 
2405 	USB_DPRINTF_L4(DPRINT_STATUS_CB, pp->port_lh,
2406 	    "usbser_status_cb: rq_msg=%d wq_msg=%d", rq_msg, wq_msg);
2407 
2408 	/*
2409 	 * commit postponed actions now
2410 	 * do so only if port is fully open (queues are enabled)
2411 	 */
2412 	if (rq) {
2413 		if (rq_msg) {
2414 			(void) putnextctl(rq, rq_msg);
2415 		}
2416 		if (drop_dtr) {
2417 			(void) USBSER_DS_SET_MODEM_CTL(pp, TIOCM_DTR, 0);
2418 		}
2419 		if (wq_msg) {
2420 			(void) putctl(wq, wq_msg);
2421 		}
2422 	}
2423 
2424 	mutex_enter(&pp->port_mutex);
2425 	usbser_release_port_act(pp, USBSER_ACT_CTL);
2426 }
2427 
2428 
2429 /*
2430  * serial support
2431  * --------------
2432  *
2433  *
2434  * this routine is run by wq thread every time it's woken,
2435  * i.e. when the queue contains messages to process
2436  */
2437 static void
2438 usbser_wmsg(usbser_port_t *pp)
2439 {
2440 	queue_t		*q = pp->port_ttycommon.t_writeq;
2441 	mblk_t		*mp;
2442 	int		msgtype;
2443 
2444 	ASSERT(mutex_owned(&pp->port_mutex));
2445 
2446 	if (q == NULL) {
2447 		USB_DPRINTF_L3(DPRINT_WQ, pp->port_lh, "usbser_wmsg: q=NULL");
2448 
2449 		return;
2450 	}
2451 	USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wmsg: q=%p act=%x 0x%x",
2452 	    q, pp->port_act, q->q_first ? DB_TYPE(q->q_first) : 0xff);
2453 
2454 	while ((mp = getq(q)) != NULL) {
2455 		msgtype = DB_TYPE(mp);
2456 		USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_wmsg: "
2457 		    "type=%s (0x%x)", usbser_msgtype2str(msgtype), msgtype);
2458 
2459 		switch (msgtype) {
2460 		/*
2461 		 * high-priority messages
2462 		 */
2463 		case M_STOP:
2464 			usbser_stop(pp, mp);
2465 
2466 			break;
2467 		case M_START:
2468 			usbser_start(pp, mp);
2469 
2470 			break;
2471 		case M_STOPI:
2472 			usbser_stopi(pp, mp);
2473 
2474 			break;
2475 		case M_STARTI:
2476 			usbser_starti(pp, mp);
2477 
2478 			break;
2479 		case M_IOCDATA:
2480 			usbser_iocdata(pp, mp);
2481 
2482 			break;
2483 		case M_FLUSH:
2484 			usbser_flush(pp, mp);
2485 
2486 			break;
2487 		/*
2488 		 * normal-priority messages
2489 		 */
2490 		case M_BREAK:
2491 			usbser_break(pp, mp);
2492 
2493 			break;
2494 		case M_DELAY:
2495 			usbser_delay(pp, mp);
2496 
2497 			break;
2498 		case M_DATA:
2499 			if (usbser_data(pp, mp) != USB_SUCCESS) {
2500 				(void) putbq(q, mp);
2501 
2502 				return;
2503 			}
2504 
2505 			break;
2506 		case M_IOCTL:
2507 			if (usbser_ioctl(pp, mp) != USB_SUCCESS) {
2508 				(void) putbq(q, mp);
2509 
2510 				return;
2511 			}
2512 
2513 			break;
2514 		default:
2515 			freemsg(mp);
2516 
2517 			break;
2518 		}
2519 	}
2520 }
2521 
2522 
2523 /*
2524  * process M_DATA message
2525  */
2526 static int
2527 usbser_data(usbser_port_t *pp, mblk_t *mp)
2528 {
2529 	/* put off until current transfer ends or delay is over */
2530 	if ((pp->port_act & USBSER_ACT_TX) ||
2531 	    (pp->port_act & USBSER_ACT_DELAY)) {
2532 
2533 		return (USB_FAILURE);
2534 	}
2535 	if ((MBLKL(mp) <= 0)) {
2536 		freemsg(mp);
2537 
2538 		return (USB_SUCCESS);
2539 	}
2540 
2541 	pp->port_act |= USBSER_ACT_TX;
2542 	pp->port_wq_data_cnt -= msgdsize(mp);
2543 
2544 	mutex_exit(&pp->port_mutex);
2545 	/* DSD is required to accept data block in any case */
2546 	(void) USBSER_DS_TX(pp, mp);
2547 	mutex_enter(&pp->port_mutex);
2548 
2549 	return (USB_SUCCESS);
2550 }
2551 
2552 
2553 /*
2554  * process an M_IOCTL message
2555  */
2556 static int
2557 usbser_ioctl(usbser_port_t *pp, mblk_t *mp)
2558 {
2559 	tty_common_t	*tp = &pp->port_ttycommon;
2560 	queue_t		*q = tp->t_writeq;
2561 	struct iocblk	*iocp;
2562 	int		cmd;
2563 	mblk_t		*datamp;
2564 	int		error = 0, rval;
2565 	int		val;
2566 
2567 	ASSERT(mutex_owned(&pp->port_mutex));
2568 	ASSERT(DB_TYPE(mp) == M_IOCTL);
2569 
2570 	iocp = (struct iocblk *)mp->b_rptr;
2571 	cmd = iocp->ioc_cmd;
2572 
2573 	USB_DPRINTF_L4(DPRINT_IOCTL, pp->port_lh, "usbser_ioctl: "
2574 	    "mp=%p %s (0x%x)", mp, usbser_ioctl2str(cmd), cmd);
2575 
2576 	if (tp->t_iocpending != NULL) {
2577 		/*
2578 		 * We were holding an ioctl response pending the
2579 		 * availability of an mblk to hold data to be passed up;
2580 		 * another ioctl came through, which means that ioctl
2581 		 * must have timed out or been aborted.
2582 		 */
2583 		freemsg(tp->t_iocpending);
2584 		tp->t_iocpending = NULL;
2585 	}
2586 
2587 	switch (cmd) {
2588 	case TIOCMGET:
2589 	case TIOCMBIC:
2590 	case TIOCMBIS:
2591 	case TIOCMSET:
2592 	case CONSOPENPOLLEDIO:
2593 	case CONSCLOSEPOLLEDIO:
2594 	case CONSSETABORTENABLE:
2595 	case CONSGETABORTENABLE:
2596 		/*
2597 		 * For the above ioctls do not call ttycommon_ioctl() because
2598 		 * this function frees up the message block (mp->b_cont) that
2599 		 * contains the address of the user variable where we need to
2600 		 * pass back the bit array.
2601 		 */
2602 		error = -1;
2603 		usbser_serialize_port_act(pp, USBSER_ACT_CTL);
2604 		mutex_exit(&pp->port_mutex);
2605 
2606 		break;
2607 	case TCSBRK:
2608 		/* serialize breaks */
2609 		if (pp->port_act & USBSER_ACT_BREAK) {
2610 
2611 			return (USB_FAILURE);
2612 		}
2613 	default:
2614 		usbser_serialize_port_act(pp, USBSER_ACT_CTL);
2615 		mutex_exit(&pp->port_mutex);
2616 		(void) ttycommon_ioctl(tp, q, mp, &error);
2617 	}
2618 
2619 	if (error == 0) {
2620 		/*
2621 		 * ttycommon_ioctl() did most of the work
2622 		 * we just use the data it set up
2623 		 */
2624 		switch (cmd) {
2625 		case TCSETSF:
2626 		case TCSETSW:
2627 		case TCSETA:
2628 		case TCSETAW:
2629 		case TCSETAF:
2630 			(void) USBSER_DS_FIFO_DRAIN(pp, DS_TX);
2631 
2632 			/* FALLTHRU */
2633 		case TCSETS:
2634 			mutex_enter(&pp->port_mutex);
2635 			error = usbser_port_program(pp);
2636 			mutex_exit(&pp->port_mutex);
2637 
2638 			break;
2639 		}
2640 
2641 		goto end;
2642 	} else if (error > 0) {
2643 		USB_DPRINTF_L3(DPRINT_IOCTL, pp->port_lh, "usbser_ioctl: "
2644 		    "ttycommon_ioctl returned %d", error);
2645 
2646 		goto end;
2647 	}
2648 
2649 	/*
2650 	 * error < 0: ttycommon_ioctl() didn't do anything, we process it here
2651 	 */
2652 	error = 0;
2653 	switch (cmd) {
2654 	case TCSBRK:
2655 		if ((error = miocpullup(mp, sizeof (int))) != 0) {
2656 
2657 			break;
2658 		}
2659 		/* drain output */
2660 		(void) USBSER_DS_FIFO_DRAIN(pp, USBSER_TX_FIFO_DRAIN_TIMEOUT);
2661 		/*
2662 		 * if required, set break
2663 		 */
2664 		if (*(int *)mp->b_cont->b_rptr == 0) {
2665 			if (USBSER_DS_BREAK_CTL(pp, DS_ON) != USB_SUCCESS) {
2666 				error = EIO;
2667 
2668 				break;
2669 			}
2670 			mutex_enter(&pp->port_mutex);
2671 			pp->port_act |= USBSER_ACT_BREAK;
2672 			pp->port_delay_id = timeout(usbser_restart, pp,
2673 							drv_usectohz(250000));
2674 			mutex_exit(&pp->port_mutex);
2675 		}
2676 
2677 		break;
2678 	case TIOCSBRK:
2679 		/* set break */
2680 		if (USBSER_DS_BREAK_CTL(pp, DS_ON) != USB_SUCCESS) {
2681 			error = EIO;
2682 		}
2683 
2684 		break;
2685 	case TIOCCBRK:
2686 		/* clear break */
2687 		if (USBSER_DS_BREAK_CTL(pp, DS_OFF) != USB_SUCCESS) {
2688 			error = EIO;
2689 		}
2690 
2691 		break;
2692 	case TIOCMSET:
2693 	case TIOCMBIS:
2694 	case TIOCMBIC:
2695 		if (iocp->ioc_count == TRANSPARENT) {
2696 			mcopyin(mp, NULL, sizeof (int), NULL);
2697 
2698 			break;
2699 		}
2700 		if ((error = miocpullup(mp, sizeof (int))) != 0) {
2701 
2702 			break;
2703 		}
2704 
2705 		val = *(int *)mp->b_cont->b_rptr;
2706 		if (cmd == TIOCMSET) {
2707 			rval = USBSER_DS_SET_MODEM_CTL(pp, -1, val);
2708 		} else if (cmd == TIOCMBIS) {
2709 			rval = USBSER_DS_SET_MODEM_CTL(pp, val, -1);
2710 		} else if (cmd == TIOCMBIC) {
2711 			rval = USBSER_DS_SET_MODEM_CTL(pp, val, 0);
2712 		}
2713 		if (rval != USB_SUCCESS) {
2714 			error = EIO;
2715 		}
2716 
2717 		break;
2718 	case (tIOC | 109):		/* TIOCSILOOP */
2719 		if (USBSER_DS_LOOPBACK_SUPPORTED(pp)) {
2720 			if (USBSER_DS_LOOPBACK(pp, DS_ON) != USB_SUCCESS) {
2721 				error = EIO;
2722 			} else {
2723 				iocp->ioc_error = 0;
2724 				mp->b_datap->db_type = M_IOCACK;
2725 			}
2726 		} else {
2727 			error = EINVAL;
2728 		}
2729 
2730 		break;
2731 	case (tIOC | 108):		/* TIOCCILOOP */
2732 		if (USBSER_DS_LOOPBACK_SUPPORTED(pp)) {
2733 			if (USBSER_DS_LOOPBACK(pp, DS_OFF) != USB_SUCCESS) {
2734 				error = EIO;
2735 			} else {
2736 				iocp->ioc_error = 0;
2737 				mp->b_datap->db_type = M_IOCACK;
2738 			}
2739 		} else {
2740 			error = EINVAL;
2741 		}
2742 
2743 		break;
2744 	case TIOCMGET:
2745 		datamp = allocb(sizeof (int), BPRI_MED);
2746 		if (datamp == NULL) {
2747 			error = EAGAIN;
2748 
2749 			break;
2750 		}
2751 
2752 		rval = USBSER_DS_GET_MODEM_CTL(pp, -1, (int *)datamp->b_rptr);
2753 		if (rval != USB_SUCCESS) {
2754 			error = EIO;
2755 
2756 			break;
2757 		}
2758 
2759 		if (iocp->ioc_count == TRANSPARENT) {
2760 			mcopyout(mp, NULL, sizeof (int), NULL, datamp);
2761 		} else {
2762 			if (mp->b_cont != NULL) {
2763 				freemsg(mp->b_cont);
2764 			}
2765 			mp->b_cont = datamp;
2766 			mp->b_cont->b_wptr += sizeof (int);
2767 			iocp->ioc_count = sizeof (int);
2768 		}
2769 
2770 		break;
2771 	case CONSOPENPOLLEDIO:
2772 		error = usbser_polledio_init(pp);
2773 		if (error != 0)
2774 
2775 			break;
2776 
2777 		error = miocpullup(mp, sizeof (struct cons_polledio *));
2778 		if (error != 0)
2779 
2780 			break;
2781 
2782 		*(struct cons_polledio **)mp->b_cont->b_rptr = &usbser_polledio;
2783 
2784 		mp->b_datap->db_type = M_IOCACK;
2785 
2786 		break;
2787 	case CONSCLOSEPOLLEDIO:
2788 		usbser_polledio_fini(pp);
2789 		mp->b_datap->db_type = M_IOCACK;
2790 		mp->b_datap->db_type = M_IOCACK;
2791 		iocp->ioc_error = 0;
2792 		iocp->ioc_rval = 0;
2793 
2794 		break;
2795 	case CONSSETABORTENABLE:
2796 		error = secpolicy_console(iocp->ioc_cr);
2797 		if (error != 0)
2798 
2799 			break;
2800 
2801 		if (iocp->ioc_count != TRANSPARENT) {
2802 			error = EINVAL;
2803 
2804 			break;
2805 		}
2806 
2807 		/*
2808 		 * To do: implement console abort support
2809 		 * This involves adding a console flag to usbser
2810 		 * state structure. If flag is set, parse input stream
2811 		 * for abort sequence (see asy for example).
2812 		 *
2813 		 * For now, run mdb -K to get kmdb prompt.
2814 		 */
2815 		if (*(intptr_t *)mp->b_cont->b_rptr)
2816 			usbser_console_abort = 1;
2817 		else
2818 			usbser_console_abort = 0;
2819 
2820 		mp->b_datap->db_type = M_IOCACK;
2821 		iocp->ioc_error = 0;
2822 		iocp->ioc_rval = 0;
2823 
2824 		break;
2825 	case CONSGETABORTENABLE:
2826 		/*CONSTANTCONDITION*/
2827 		ASSERT(sizeof (boolean_t) <= sizeof (boolean_t *));
2828 		/*
2829 		 * Store the return value right in the payload
2830 		 * we were passed.  Crude.
2831 		 */
2832 		mcopyout(mp, NULL, sizeof (boolean_t), NULL, NULL);
2833 		*(boolean_t *)mp->b_cont->b_rptr = (usbser_console_abort != 0);
2834 
2835 		break;
2836 	default:
2837 		error = EINVAL;
2838 
2839 		break;
2840 	}
2841 end:
2842 	if (error != 0) {
2843 		iocp->ioc_error = error;
2844 		mp->b_datap->db_type = M_IOCNAK;
2845 	}
2846 	qreply(q, mp);
2847 
2848 	mutex_enter(&pp->port_mutex);
2849 	usbser_release_port_act(pp, USBSER_ACT_CTL);
2850 
2851 	return (USB_SUCCESS);
2852 }
2853 
2854 
2855 /*
2856  * process M_IOCDATA message
2857  */
2858 static void
2859 usbser_iocdata(usbser_port_t *pp, mblk_t *mp)
2860 {
2861 	tty_common_t	*tp = &pp->port_ttycommon;
2862 	queue_t		*q = tp->t_writeq;
2863 	struct iocblk	*ip;
2864 	struct copyresp	*csp;
2865 	int		cmd;
2866 	int		val;
2867 	int		rval;
2868 
2869 	ASSERT(mutex_owned(&pp->port_mutex));
2870 
2871 	ip = (struct iocblk *)mp->b_rptr;
2872 	csp = (struct copyresp *)mp->b_rptr;
2873 	cmd = csp->cp_cmd;
2874 
2875 	if (csp->cp_rval != 0) {
2876 		freemsg(mp);
2877 
2878 		return;
2879 	}
2880 
2881 	switch (cmd) {
2882 	case TIOCMSET:
2883 	case TIOCMBIS:
2884 	case TIOCMBIC:
2885 		if ((mp->b_cont == NULL) ||
2886 		    (MBLKL(mp->b_cont) < sizeof (int))) {
2887 			miocnak(q, mp, 0, EINVAL);
2888 
2889 			break;
2890 		}
2891 		val = *(int *)mp->b_cont->b_rptr;
2892 
2893 		usbser_serialize_port_act(pp, USBSER_ACT_CTL);
2894 
2895 		mutex_exit(&pp->port_mutex);
2896 		if (cmd == TIOCMSET) {
2897 			rval = USBSER_DS_SET_MODEM_CTL(pp, -1, val);
2898 		} else if (cmd == TIOCMBIS) {
2899 			rval = USBSER_DS_SET_MODEM_CTL(pp, val, -1);
2900 		} else if (cmd == TIOCMBIC) {
2901 			rval = USBSER_DS_SET_MODEM_CTL(pp, val, 0);
2902 		}
2903 
2904 		if (mp->b_cont) {
2905 			freemsg(mp->b_cont);
2906 			mp->b_cont = NULL;
2907 		}
2908 		ip->ioc_rval = 0;
2909 		if (rval == USB_SUCCESS) {
2910 			miocack(q, mp, 0, 0);
2911 		} else {
2912 			miocnak(q, mp, 0, EIO);
2913 		}
2914 		mutex_enter(&pp->port_mutex);
2915 
2916 		usbser_release_port_act(pp, USBSER_ACT_CTL);
2917 
2918 		break;
2919 	case TIOCMGET:
2920 		mutex_exit(&pp->port_mutex);
2921 		if (mp->b_cont) {
2922 			freemsg(mp->b_cont);
2923 			mp->b_cont = NULL;
2924 		}
2925 		ip->ioc_rval = 0;
2926 		miocack(q, mp, 0, 0);
2927 		mutex_enter(&pp->port_mutex);
2928 
2929 		break;
2930 	default:
2931 		mutex_exit(&pp->port_mutex);
2932 		miocnak(q, mp, 0, EINVAL);
2933 		mutex_enter(&pp->port_mutex);
2934 
2935 		break;
2936 	}
2937 }
2938 
2939 
2940 /*
2941  * handle M_START[I]/M_STOP[I] messages
2942  */
2943 static void
2944 usbser_stop(usbser_port_t *pp, mblk_t *mp)
2945 {
2946 	usbser_st_mstop++;
2947 	if (!(pp->port_flags & USBSER_FL_TX_STOPPED)) {
2948 		usbser_serialize_port_act(pp, USBSER_ACT_CTL);
2949 		pp->port_flags |= USBSER_FL_TX_STOPPED;
2950 
2951 		mutex_exit(&pp->port_mutex);
2952 		USBSER_DS_STOP(pp, DS_TX);
2953 		mutex_enter(&pp->port_mutex);
2954 
2955 		usbser_release_port_act(pp, USBSER_ACT_TX);
2956 		usbser_release_port_act(pp, USBSER_ACT_CTL);
2957 	}
2958 	freemsg(mp);
2959 }
2960 
2961 
2962 static void
2963 usbser_start(usbser_port_t *pp, mblk_t *mp)
2964 {
2965 	usbser_st_mstart++;
2966 	if (pp->port_flags & USBSER_FL_TX_STOPPED) {
2967 		usbser_serialize_port_act(pp, USBSER_ACT_CTL);
2968 		pp->port_flags &= ~USBSER_FL_TX_STOPPED;
2969 
2970 		mutex_exit(&pp->port_mutex);
2971 		USBSER_DS_START(pp, DS_TX);
2972 		mutex_enter(&pp->port_mutex);
2973 		usbser_release_port_act(pp, USBSER_ACT_CTL);
2974 	}
2975 	freemsg(mp);
2976 }
2977 
2978 
2979 static void
2980 usbser_stopi(usbser_port_t *pp, mblk_t *mp)
2981 {
2982 	usbser_st_mstopi++;
2983 	usbser_serialize_port_act(pp, USBSER_ACT_CTL);
2984 	pp->port_flowc = pp->port_ttycommon.t_stopc;
2985 	usbser_inbound_flow_ctl(pp);
2986 	usbser_release_port_act(pp, USBSER_ACT_CTL);
2987 	freemsg(mp);
2988 }
2989 
2990 static void
2991 usbser_starti(usbser_port_t *pp, mblk_t *mp)
2992 {
2993 	usbser_st_mstarti++;
2994 	usbser_serialize_port_act(pp, USBSER_ACT_CTL);
2995 	pp->port_flowc = pp->port_ttycommon.t_startc;
2996 	usbser_inbound_flow_ctl(pp);
2997 	usbser_release_port_act(pp, USBSER_ACT_CTL);
2998 	freemsg(mp);
2999 }
3000 
3001 /*
3002  * process M_FLUSH message
3003  */
3004 static void
3005 usbser_flush(usbser_port_t *pp, mblk_t *mp)
3006 {
3007 	queue_t	*q = pp->port_ttycommon.t_writeq;
3008 
3009 	if (*mp->b_rptr & FLUSHW) {
3010 		mutex_exit(&pp->port_mutex);
3011 		(void) USBSER_DS_FIFO_FLUSH(pp, DS_TX);	/* flush FIFO buffers */
3012 		flushq(q, FLUSHDATA);			/* flush write queue */
3013 		mutex_enter(&pp->port_mutex);
3014 
3015 		usbser_release_port_act(pp, USBSER_ACT_TX);
3016 
3017 		*mp->b_rptr &= ~FLUSHW;
3018 	}
3019 	if (*mp->b_rptr & FLUSHR) {
3020 		/*
3021 		 * flush FIFO buffers
3022 		 */
3023 		mutex_exit(&pp->port_mutex);
3024 		(void) USBSER_DS_FIFO_FLUSH(pp, DS_RX);
3025 		flushq(RD(q), FLUSHDATA);
3026 		qreply(q, mp);
3027 		mutex_enter(&pp->port_mutex);
3028 	} else {
3029 		freemsg(mp);
3030 	}
3031 }
3032 
3033 /*
3034  * process M_BREAK message
3035  */
3036 static void
3037 usbser_break(usbser_port_t *pp, mblk_t *mp)
3038 {
3039 	int	rval;
3040 
3041 	/*
3042 	 * set the break and arrange for usbser_restart() to be called in 1/4 s
3043 	 */
3044 	mutex_exit(&pp->port_mutex);
3045 	rval = USBSER_DS_BREAK_CTL(pp, DS_ON);
3046 	mutex_enter(&pp->port_mutex);
3047 
3048 	if (rval == USB_SUCCESS) {
3049 		pp->port_act |= USBSER_ACT_BREAK;
3050 		pp->port_delay_id = timeout(usbser_restart, pp,
3051 						drv_usectohz(250000));
3052 	}
3053 	freemsg(mp);
3054 }
3055 
3056 
3057 /*
3058  * process M_DELAY message
3059  */
3060 static void
3061 usbser_delay(usbser_port_t *pp, mblk_t *mp)
3062 {
3063 	/*
3064 	 * arrange for usbser_restart() to be called when the delay expires
3065 	 */
3066 	pp->port_act |= USBSER_ACT_DELAY;
3067 	pp->port_delay_id = timeout(usbser_restart, pp,
3068 			(clock_t)(*(uchar_t *)mp->b_rptr + 6));
3069 	freemsg(mp);
3070 }
3071 
3072 
3073 /*
3074  * restart output on a line after a delay or break timer expired
3075  */
3076 static void
3077 usbser_restart(void *arg)
3078 {
3079 	usbser_port_t	*pp = (usbser_port_t *)arg;
3080 
3081 	USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh, "usbser_restart");
3082 
3083 	mutex_enter(&pp->port_mutex);
3084 	/* if cancelled, return immediately */
3085 	if (pp->port_delay_id == 0) {
3086 		mutex_exit(&pp->port_mutex);
3087 
3088 		return;
3089 	}
3090 	pp->port_delay_id = 0;
3091 
3092 	/* clear break if necessary */
3093 	if (pp->port_act & USBSER_ACT_BREAK) {
3094 		mutex_exit(&pp->port_mutex);
3095 		(void) USBSER_DS_BREAK_CTL(pp, DS_OFF);
3096 		mutex_enter(&pp->port_mutex);
3097 	}
3098 
3099 	usbser_release_port_act(pp, USBSER_ACT_BREAK | USBSER_ACT_DELAY);
3100 
3101 	/* wake wq thread to resume message processing */
3102 	usbser_thr_wake(&pp->port_wq_thread);
3103 	mutex_exit(&pp->port_mutex);
3104 }
3105 
3106 
3107 /*
3108  * program port hardware with the chosen parameters
3109  * most of the operation is based on the values of 'c_iflag' and 'c_cflag'
3110  */
3111 static int
3112 usbser_port_program(usbser_port_t *pp)
3113 {
3114 	tty_common_t		*tp = &pp->port_ttycommon;
3115 	int			baudrate;
3116 	int			c_flag;
3117 	ds_port_param_entry_t	pe[6];
3118 	ds_port_params_t	params;
3119 	int			flow_ctl, ctl_val;
3120 	int			err = 0;
3121 
3122 	baudrate = tp->t_cflag & CBAUD;
3123 	if (tp->t_cflag & CBAUDEXT) {
3124 		baudrate += 16;
3125 	}
3126 
3127 	/*
3128 	 * set input speed same as output, as split speed not supported
3129 	 */
3130 	if (tp->t_cflag & (CIBAUD|CIBAUDEXT)) {
3131 		tp->t_cflag &= ~(CIBAUD);
3132 		if (baudrate > CBAUD) {
3133 			tp->t_cflag |= CIBAUDEXT;
3134 			tp->t_cflag |=
3135 				(((baudrate - CBAUD - 1) << IBSHIFT) & CIBAUD);
3136 		} else {
3137 			tp->t_cflag &= ~CIBAUDEXT;
3138 			tp->t_cflag |= ((baudrate << IBSHIFT) & CIBAUD);
3139 		}
3140 	}
3141 
3142 	c_flag = tp->t_cflag;
3143 
3144 	/*
3145 	 * flow control
3146 	 */
3147 	flow_ctl = tp->t_iflag & (IXON | IXANY | IXOFF);
3148 	if (c_flag & CRTSCTS) {
3149 		flow_ctl |= CTSXON;
3150 	}
3151 	if (c_flag & CRTSXOFF) {
3152 		flow_ctl |= RTSXOFF;
3153 	}
3154 
3155 	/*
3156 	 * fill in port parameters we need to set:
3157 	 *
3158 	 * baud rate
3159 	 */
3160 	pe[0].param = DS_PARAM_BAUD;
3161 	pe[0].val.ui = baudrate;
3162 
3163 	/* stop bits */
3164 	pe[1].param = DS_PARAM_STOPB;
3165 	pe[1].val.ui = c_flag & CSTOPB;
3166 
3167 	/* parity */
3168 	pe[2].param = DS_PARAM_PARITY;
3169 	pe[2].val.ui = c_flag & (PARENB | PARODD);
3170 
3171 	/* char size */
3172 	pe[3].param = DS_PARAM_CHARSZ;
3173 	pe[3].val.ui = c_flag & CSIZE;
3174 
3175 	/* start & stop chars */
3176 	pe[4].param = DS_PARAM_XON_XOFF;
3177 	pe[4].val.uc[0] = tp->t_startc;
3178 	pe[4].val.uc[1] = tp->t_stopc;
3179 
3180 	/* flow control */
3181 	pe[5].param = DS_PARAM_FLOW_CTL;
3182 	pe[5].val.ui = flow_ctl;
3183 
3184 	params.tp_entries = &pe[0];
3185 	params.tp_cnt = 6;
3186 
3187 	/* control signals */
3188 	ctl_val = TIOCM_DTR | TIOCM_RTS;
3189 	if (baudrate == 0) {
3190 		ctl_val &= ~TIOCM_DTR;	/* zero baudrate means drop DTR */
3191 	}
3192 	if (pp->port_flags & USBSER_FL_RX_STOPPED) {
3193 		ctl_val &= ~TIOCM_RTS;
3194 	}
3195 
3196 	/* submit */
3197 	mutex_exit(&pp->port_mutex);
3198 	err = USBSER_DS_SET_PORT_PARAMS(pp, &params);
3199 	if (err != USB_SUCCESS) {
3200 		mutex_enter(&pp->port_mutex);
3201 
3202 		return (EINVAL);
3203 	}
3204 
3205 	err = USBSER_DS_SET_MODEM_CTL(pp, TIOCM_DTR | TIOCM_RTS, ctl_val);
3206 	mutex_enter(&pp->port_mutex);
3207 
3208 	return ((err == USB_SUCCESS) ? 0 : EIO);
3209 }
3210 
3211 
3212 /*
3213  * check if any inbound flow control action needed
3214  */
3215 static void
3216 usbser_inbound_flow_ctl(usbser_port_t *pp)
3217 {
3218 	tcflag_t	need_hw;
3219 	int		rts;
3220 	char		c = pp->port_flowc;
3221 	mblk_t		*mp = NULL;
3222 
3223 	USB_DPRINTF_L4(DPRINT_WQ, pp->port_lh,
3224 	    "usbser_inbound_flow_ctl: c=%x cflag=%x port_flags=%x",
3225 	    c, pp->port_ttycommon.t_cflag, pp->port_flags);
3226 
3227 	if (c == '\0') {
3228 
3229 		return;
3230 	}
3231 	pp->port_flowc = '\0';
3232 
3233 	/*
3234 	 * if inbound hardware flow control enabled, we need to frob RTS
3235 	 */
3236 	need_hw = (pp->port_ttycommon.t_cflag & CRTSXOFF);
3237 	if (c == pp->port_ttycommon.t_startc) {
3238 		rts = TIOCM_RTS;
3239 		pp->port_flags &= ~USBSER_FL_RX_STOPPED;
3240 	} else {
3241 		rts = 0;
3242 		pp->port_flags |= USBSER_FL_RX_STOPPED;
3243 	}
3244 
3245 	/*
3246 	 * if character flow control active, transmit a start or stop char,
3247 	 */
3248 	if (pp->port_ttycommon.t_iflag & IXOFF) {
3249 		if ((mp = allocb(1, BPRI_LO)) == NULL) {
3250 			USB_DPRINTF_L2(DPRINT_WQ, pp->port_lh,
3251 			    "usbser_inbound_flow_ctl: allocb failed");
3252 		} else {
3253 			*mp->b_wptr++ = c;
3254 			pp->port_flags |= USBSER_ACT_TX;
3255 		}
3256 	}
3257 
3258 	mutex_exit(&pp->port_mutex);
3259 	if (need_hw) {
3260 		(void) USBSER_DS_SET_MODEM_CTL(pp, TIOCM_RTS, rts);
3261 	}
3262 	if (mp) {
3263 		(void) USBSER_DS_TX(pp, mp);
3264 	}
3265 	mutex_enter(&pp->port_mutex);
3266 }
3267 
3268 
3269 /*
3270  * misc
3271  * ----
3272  *
3273  *
3274  * returns !=0 if device is online, 0 otherwise
3275  */
3276 static int
3277 usbser_dev_is_online(usbser_state_t *usp)
3278 {
3279 	int	rval;
3280 
3281 	mutex_enter(&usp->us_mutex);
3282 	rval = (usp->us_dev_state == USB_DEV_ONLINE);
3283 	mutex_exit(&usp->us_mutex);
3284 
3285 	return (rval);
3286 }
3287 
3288 /*
3289  * serialize port activities defined by 'act' mask
3290  */
3291 static void
3292 usbser_serialize_port_act(usbser_port_t *pp, int act)
3293 {
3294 	while (pp->port_act & act) {
3295 		cv_wait(&pp->port_act_cv, &pp->port_mutex);
3296 	}
3297 
3298 	pp->port_act |= act;
3299 }
3300 
3301 
3302 /*
3303  * indicate that port activity is finished
3304  */
3305 static void
3306 usbser_release_port_act(usbser_port_t *pp, int act)
3307 {
3308 	pp->port_act &= ~act;
3309 	cv_broadcast(&pp->port_act_cv);
3310 }
3311 
3312 
3313 /*
3314  * message type to string and back conversion.
3315  *
3316  * pardon breaks on the same line, but as long as cstyle doesn't
3317  * complain, I'd like to keep this form for trivial cases like this.
3318  * associative arrays in the kernel, anyone?
3319  */
3320 static char *
3321 usbser_msgtype2str(int type)
3322 {
3323 	char	*str;
3324 
3325 	switch (type) {
3326 	case M_STOP:	str = "M_STOP";		break;
3327 	case M_START:	str = "M_START";	break;
3328 	case M_STOPI:	str = "M_STOPI";	break;
3329 	case M_STARTI:	str = "M_STARTI";	break;
3330 	case M_DATA:	str = "M_DATA";		break;
3331 	case M_DELAY:	str = "M_DELAY";	break;
3332 	case M_BREAK:	str = "M_BREAK";	break;
3333 	case M_IOCTL:	str = "M_IOCTL";	break;
3334 	case M_IOCDATA:	str = "M_IOCDATA";	break;
3335 	case M_FLUSH:	str = "M_FLUSH";	break;
3336 	case M_CTL:	str = "M_CTL";		break;
3337 	case M_READ:	str = "M_READ";		break;
3338 	default:	str = "unknown";	break;
3339 	}
3340 
3341 	return (str);
3342 }
3343 
3344 
3345 static char *
3346 usbser_ioctl2str(int ioctl)
3347 {
3348 	char	*str;
3349 
3350 	switch (ioctl) {
3351 	case TCGETA:	str = "TCGETA";		break;
3352 	case TCSETA:	str = "TCSETA";		break;
3353 	case TCSETAF:	str = "TCSETAF";	break;
3354 	case TCSETAW:	str = "TCSETAW";	break;
3355 	case TCSBRK:	str = "TCSBRK";		break;
3356 	case TCXONC:	str = "TCXONC";		break;
3357 	case TCFLSH:	str = "TCFLSH";		break;
3358 	case TCGETS:	str = "TCGETS";		break;
3359 	case TCSETS:	str = "TCSETS";		break;
3360 	case TCSETSF:	str = "TCSETSF";	break;
3361 	case TCSETSW:	str = "TCSETSW";	break;
3362 	case TIOCSBRK:	str = "TIOCSBRK";	break;
3363 	case TIOCCBRK:	str = "TIOCCBRK";	break;
3364 	case TIOCMSET:	str = "TIOCMSET";	break;
3365 	case TIOCMBIS:	str = "TIOCMBIS";	break;
3366 	case TIOCMBIC:	str = "TIOCMBIC";	break;
3367 	case TIOCMGET:	str = "TIOCMGET";	break;
3368 	case (tIOC | 109): str = "TIOCSILOOP";	break;
3369 	case (tIOC | 108): str = "TIOCCILOOP";	break;
3370 	case TCGETX:	str = "TCGETX";		break;
3371 	case TCSETX:	str = "TCGETX";		break;
3372 	case TCSETXW:	str = "TCGETX";		break;
3373 	case TCSETXF:	str = "TCGETX";		break;
3374 	default:	str = "unknown";	break;
3375 	}
3376 
3377 	return (str);
3378 }
3379 
3380 /*
3381  * Polled IO support
3382  */
3383 
3384 /* called once  by consconfig() when polledio is opened */
3385 static int
3386 usbser_polledio_init(usbser_port_t *pp)
3387 {
3388 	int err;
3389 	usb_pipe_handle_t hdl;
3390 	ds_ops_t *ds_ops = pp->port_ds_ops;
3391 
3392 	/* only one serial line console supported */
3393 	if (console_input != NULL)
3394 
3395 		return (USB_FAILURE);
3396 
3397 	/* check if underlying driver supports polled io */
3398 	if (ds_ops->ds_version < DS_OPS_VERSION_V1 ||
3399 	    ds_ops->ds_out_pipe == NULL || ds_ops->ds_in_pipe == NULL)
3400 
3401 		return (USB_FAILURE);
3402 
3403 	/* init polled input pipe */
3404 	hdl = ds_ops->ds_in_pipe(pp->port_ds_hdl, pp->port_num);
3405 	err = usb_console_input_init(pp->port_usp->us_dip, hdl,
3406 	    &console_input_buf, &console_input);
3407 	if (err)
3408 
3409 		return (USB_FAILURE);
3410 
3411 	/* init polled output pipe */
3412 	hdl = ds_ops->ds_out_pipe(pp->port_ds_hdl, pp->port_num);
3413 	err = usb_console_output_init(pp->port_usp->us_dip, hdl,
3414 	    &console_output);
3415 	if (err) {
3416 		(void) usb_console_input_fini(console_input);
3417 		console_input = NULL;
3418 
3419 		return (USB_FAILURE);
3420 	}
3421 
3422 	return (USB_SUCCESS);
3423 }
3424 
3425 /* called once  by consconfig() when polledio is closed */
3426 /*ARGSUSED*/
3427 static void usbser_polledio_fini(usbser_port_t *pp)
3428 {
3429 	/* Since we can't move the console, there is nothing to do. */
3430 }
3431 
3432 /*ARGSUSED*/
3433 static void
3434 usbser_polledio_enter(cons_polledio_arg_t arg)
3435 {
3436 	(void) usb_console_input_enter(console_input);
3437 	(void) usb_console_output_enter(console_output);
3438 }
3439 
3440 /*ARGSUSED*/
3441 static void
3442 usbser_polledio_exit(cons_polledio_arg_t arg)
3443 {
3444 	(void) usb_console_output_exit(console_output);
3445 	(void) usb_console_input_exit(console_input);
3446 }
3447 
3448 /*ARGSUSED*/
3449 static void
3450 usbser_putchar(cons_polledio_arg_t arg, uchar_t c)
3451 {
3452 	static uchar_t cr[2] = {'\r', '\n'};
3453 	uint_t nout;
3454 
3455 	if (c == '\n')
3456 		(void) usb_console_write(console_output, cr, 2, &nout);
3457 	else
3458 		(void) usb_console_write(console_output, &c, 1, &nout);
3459 }
3460 
3461 /*ARGSUSED*/
3462 static int
3463 usbser_getchar(cons_polledio_arg_t arg)
3464 {
3465 	while (!usbser_ischar(arg))
3466 		;
3467 
3468 	return (*console_input_start++);
3469 }
3470 
3471 /*ARGSUSED*/
3472 static boolean_t
3473 usbser_ischar(cons_polledio_arg_t arg)
3474 {
3475 	uint_t num_bytes;
3476 
3477 	if (console_input_start < console_input_end)
3478 
3479 		return (1);
3480 
3481 	if (usb_console_read(console_input, &num_bytes) != USB_SUCCESS)
3482 
3483 		return (0);
3484 
3485 	console_input_start = console_input_buf;
3486 	console_input_end = console_input_buf + num_bytes;
3487 
3488 	return (num_bytes != 0);
3489 }
3490