usbprn.c revision 7656:2621e50fdf4a
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 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
22 * Use is subject to license terms.
23 */
24
25
26/*
27 * Printer Class Driver for USB
28 *
29 * This driver supports devices that adhere to the USB Printer Class
30 * specification 1.0.
31 *
32 * NOTE: This driver is not DDI compliant in that it uses undocumented
33 * functions for logging (USB_DPRINTF_L*, usb_alloc_log_hdl, usb_free_log_hdl),
34 * and serialization (usb_serialize_access, usb_release_access,
35 * usb_init_serialization, usb_fini_serialization)
36 *
37 * Undocumented functions may go away in a future Solaris OS release.
38 *
39 * Please see the DDK for sample code of these functions, and for the usbskel
40 * skeleton template driver which contains scaled-down versions of these
41 * functions written in a DDI-compliant way.
42 */
43
44#if defined(lint) && !defined(DEBUG)
45#define	DEBUG
46#endif
47#ifdef __lock_lint
48#define	_MULTI_DATAMODEL
49#endif
50
51#define	USBDRV_MAJOR_VER	2
52#define	USBDRV_MINOR_VER	0
53
54#include <sys/usb/usba.h>
55#include <sys/usb/usba/usba_ugen.h>
56#include <sys/bpp_io.h>
57#include <sys/ecppsys.h>
58#include <sys/prnio.h>
59#include <sys/errno.h>
60#include <sys/usb/clients/printer/usb_printer.h>
61#include <sys/usb/clients/printer/usbprn.h>
62#include <sys/strsun.h>
63
64/* Debugging support */
65uint_t	usbprn_errmask		= (uint_t)PRINT_MASK_ALL;
66uint_t	usbprn_errlevel 	= USB_LOG_L4;
67uint_t	usbprn_instance_debug	= (uint_t)-1;
68
69/* local variables */
70static uint_t usbprn_ifcap =
71	PRN_HOTPLUG | PRN_1284_DEVID | PRN_1284_STATUS | PRN_TIMEOUTS;
72
73/*
74 * Function Prototypes
75 */
76static int	usbprn_attach(dev_info_t *, ddi_attach_cmd_t);
77static int	usbprn_detach(dev_info_t *, ddi_detach_cmd_t);
78static int	usbprn_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
79static void	usbprn_cleanup(dev_info_t *, usbprn_state_t *);
80
81static int	usbprn_get_descriptors(usbprn_state_t *);
82static int	usbprn_get_device_id(usbprn_state_t *);
83static int	usbprn_get_port_status(usbprn_state_t *);
84
85static int	usbprn_open(dev_t *, int, int, cred_t *);
86static int	usbprn_close(dev_t, int, int, cred_t *);
87static int	usbprn_open_usb_pipes(usbprn_state_t *);
88static void	usbprn_close_usb_pipes(usbprn_state_t *);
89static int	usbprn_write(dev_t, struct uio *, cred_t *);
90static int	usbprn_read(dev_t, struct uio *, cred_t *);
91static int	usbprn_poll(dev_t, short, int, short *, struct pollhead **);
92
93static int	usbprn_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
94static void	usbprn_minphys(struct buf *);
95static int	usbprn_strategy(struct buf *);
96static int	usbprn_setparms(usbprn_state_t *, intptr_t arg, int);
97static int	usbprn_getparms(usbprn_state_t *, intptr_t, int);
98static void	usbprn_geterr(usbprn_state_t *, intptr_t, int);
99static int	usbprn_testio(usbprn_state_t  *, int);
100static int	usbprn_ioctl_get_status(usbprn_state_t *);
101static int	usbprn_prnio_get_status(usbprn_state_t *, intptr_t, int);
102static int	usbprn_prnio_get_1284_status(usbprn_state_t *, intptr_t, int);
103static int	usbprn_prnio_get_ifcap(usbprn_state_t *, intptr_t, int);
104static int	usbprn_prnio_set_ifcap(usbprn_state_t *, intptr_t, int);
105static int	usbprn_prnio_get_ifinfo(usbprn_state_t *, intptr_t, int);
106static int	usbprn_prnio_get_1284_devid(usbprn_state_t *, intptr_t, int);
107static int	usbprn_prnio_get_timeouts(usbprn_state_t *, intptr_t, int);
108static int	usbprn_prnio_set_timeouts(usbprn_state_t *, intptr_t, int);
109
110static void	usbprn_send_async_bulk_data(usbprn_state_t *);
111
112static void	usbprn_bulk_xfer_cb(usb_pipe_handle_t, usb_bulk_req_t *);
113static void	usbprn_bulk_xfer_exc_cb(usb_pipe_handle_t,
114		    usb_bulk_req_t *);
115
116static void	usbprn_biodone(usbprn_state_t *, int, int);
117static char	usbprn_error_state(uchar_t);
118static void	usbprn_print_long(usbprn_state_t *, char *, int);
119
120/* event handling */
121static	void	usbprn_restore_device_state(dev_info_t *, usbprn_state_t *);
122static	int	usbprn_disconnect_event_cb(dev_info_t *);
123static	int	usbprn_reconnect_event_cb(dev_info_t *);
124static	int	usbprn_cpr_suspend(dev_info_t *);
125static	void	usbprn_cpr_resume(dev_info_t *);
126
127static usb_event_t usbprn_events = {
128	usbprn_disconnect_event_cb,
129	usbprn_reconnect_event_cb,
130	NULL, NULL
131};
132
133/* PM handling */
134static	void	usbprn_create_pm_components(dev_info_t *, usbprn_state_t *);
135static	int	usbprn_power(dev_info_t *, int comp, int level);
136static	int	usbprn_pwrlvl0(usbprn_state_t *);
137static	int	usbprn_pwrlvl1(usbprn_state_t *);
138static	int	usbprn_pwrlvl2(usbprn_state_t *);
139static	int	usbprn_pwrlvl3(usbprn_state_t *);
140static	void	usbprn_pm_busy_component(usbprn_state_t *);
141static	void	usbprn_pm_idle_component(usbprn_state_t *);
142
143/* module loading stuff */
144struct cb_ops usbprn_cb_ops = {
145	usbprn_open,		/* open  */
146	usbprn_close,		/* close */
147	nulldev,		/* strategy */
148	nulldev,		/* print */
149	nulldev,		/* dump */
150	usbprn_read,		/* read */
151	usbprn_write,		/* write */
152	usbprn_ioctl,		/* ioctl */
153	nulldev,		/* devmap */
154	nulldev,		/* mmap */
155	nulldev,		/* segmap */
156	usbprn_poll,		/* poll */
157	ddi_prop_op,		/* cb_prop_op */
158	NULL,			/* streamtab  */
159	D_64BIT | D_MP
160};
161
162static struct dev_ops usbprn_ops = {
163	DEVO_REV,		/* devo_rev, */
164	0,			/* refcnt  */
165	usbprn_info,		/* info */
166	nulldev,		/* identify */
167	nulldev,		/* probe */
168	usbprn_attach,		/* attach */
169	usbprn_detach,		/* detach */
170	nodev,			/* reset */
171	&usbprn_cb_ops,		/* driver operations */
172	NULL,			/* bus operations */
173	usbprn_power,		/* power */
174	ddi_quiesce_not_supported,	/* devo_quiesce */
175};
176
177static struct modldrv usbprnmodldrv =	{
178	&mod_driverops,
179	"USB printer client driver",
180	&usbprn_ops
181};
182
183static struct modlinkage modlinkage = {
184	MODREV_1,
185	&usbprnmodldrv,
186	NULL,
187};
188
189/* local variables */
190
191/* soft state structures */
192#define	USBPRN_INITIAL_SOFT_SPACE	1
193static void *usbprn_statep;
194
195static int usbprn_max_xfer_size = USBPRN_MAX_XFER_SIZE;
196
197/* prnio support */
198static const char usbprn_prnio_ifinfo[] = PRN_USB;
199
200
201int
202_init(void)
203{
204	int rval;
205
206	if ((rval = ddi_soft_state_init(&usbprn_statep,
207	    sizeof (usbprn_state_t), USBPRN_INITIAL_SOFT_SPACE)) != 0) {
208
209		return (rval);
210	}
211
212	if ((rval = mod_install(&modlinkage)) != 0) {
213		ddi_soft_state_fini(&usbprn_statep);
214	}
215
216	return (rval);
217}
218
219
220int
221_fini(void)
222{
223	int rval;
224
225	if ((rval = mod_remove(&modlinkage)) != 0) {
226
227		return (rval);
228	}
229
230	ddi_soft_state_fini(&usbprn_statep);
231
232	return (rval);
233}
234
235
236int
237_info(struct modinfo *modinfop)
238{
239	return (mod_info(&modlinkage, modinfop));
240}
241
242
243/*
244 * usbprn_info:
245 *	Get minor number, soft state structure, etc.
246 */
247/*ARGSUSED*/
248static int
249usbprn_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
250			void *arg, void **result)
251{
252	usbprn_state_t	*usbprnp;
253	int		error = DDI_FAILURE;
254	minor_t		minor = getminor((dev_t)arg);
255	int		instance = USBPRN_MINOR_TO_INSTANCE(minor);
256
257	switch (infocmd) {
258	case DDI_INFO_DEVT2DEVINFO:
259		if ((usbprnp = ddi_get_soft_state(usbprn_statep,
260		    instance)) != NULL) {
261			*result = usbprnp->usbprn_dip;
262			if (*result != NULL) {
263				error = DDI_SUCCESS;
264			}
265		} else {
266			*result = NULL;
267		}
268
269		break;
270	case DDI_INFO_DEVT2INSTANCE:
271		*result = (void *)(uintptr_t)instance;
272		error = DDI_SUCCESS;
273
274		break;
275	default:
276
277		break;
278	}
279
280	return (error);
281}
282
283
284/*
285 * usbprn_attach:
286 *	Attach driver
287 *	Get the descriptor information
288 *	Get the device id
289 *	Reset the device
290 *	Get the port status
291 */
292static int
293usbprn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
294{
295	int			instance = ddi_get_instance(dip);
296	usbprn_state_t		*usbprnp = NULL;
297	size_t			sz;
298	usb_ugen_info_t 	usb_ugen_info;
299
300	switch (cmd) {
301	case DDI_ATTACH:
302
303		break;
304	case DDI_RESUME:
305		usbprn_cpr_resume(dip);
306
307		return (DDI_SUCCESS);
308	default:
309
310		return (DDI_FAILURE);
311	}
312
313	if (ddi_soft_state_zalloc(usbprn_statep, instance) == DDI_SUCCESS) {
314		usbprnp = ddi_get_soft_state(usbprn_statep, instance);
315	}
316	if (usbprnp == NULL)  {
317
318		return (DDI_FAILURE);
319	}
320
321	usbprnp->usbprn_instance = instance;
322	usbprnp->usbprn_dip	= dip;
323	usbprnp->usbprn_log_handle = usb_alloc_log_hdl(dip,
324	    "prn", &usbprn_errlevel,
325	    &usbprn_errmask, &usbprn_instance_debug, 0);
326
327	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
328	    "usbprn_attach: cmd=%x", cmd);
329
330	if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
331		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
332		    "usb_client_attach failed");
333
334		goto fail;
335	}
336	if (usb_get_dev_data(dip, &usbprnp->usbprn_dev_data,
337	    USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
338		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
339		    "usb_get_dev_data failed");
340
341		goto fail;
342	}
343
344	/* Initialize locks and conditional variables */
345	mutex_init(&usbprnp->usbprn_mutex, NULL, MUTEX_DRIVER,
346	    usbprnp->usbprn_dev_data->dev_iblock_cookie);
347	usbprnp->usbprn_write_acc = usb_init_serialization(dip,
348	    USB_INIT_SER_CHECK_SAME_THREAD);
349	usbprnp->usbprn_ser_acc = usb_init_serialization(dip,
350	    USB_INIT_SER_CHECK_SAME_THREAD);
351	usbprnp->usbprn_dev_acc = usb_init_serialization(dip, 0);
352
353	usbprnp->usbprn_flags |= USBPRN_LOCKS_INIT_DONE;
354
355	/* Obtain all the relevant descriptors */
356	if (usbprn_get_descriptors(usbprnp) != USB_SUCCESS) {
357		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
358		    "usb get descriptors failed");
359
360		goto fail;
361	}
362
363	usbprnp->usbprn_def_ph = usbprnp->usbprn_dev_data->dev_default_ph;
364
365	/* Obtain the device id */
366	(void) usbprn_get_device_id(usbprnp);
367
368	/* Get the port status */
369	if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
370		/* some printers fail on the first */
371		if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
372			USB_DPRINTF_L2(PRINT_MASK_ATTA,
373			    usbprnp->usbprn_log_handle,
374			    "usb get port status failed");
375
376			goto fail;
377		}
378	}
379
380	USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
381	    "usbprn_attach: printer status=0x%x", usbprnp->usbprn_last_status);
382
383	if ((usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR) == 0) {
384		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
385		    "usbprn_attach: error occurred with the printer");
386	}
387
388	/*
389	 * Create minor node based on information from the
390	 * descriptors
391	 */
392	if ((ddi_create_minor_node(dip, "printer", S_IFCHR,
393	    instance << USBPRN_MINOR_INSTANCE_SHIFT,
394	    DDI_NT_PRINTER, 0)) != DDI_SUCCESS) {
395		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
396		    "usbprn_attach: cannot create minor node");
397
398		goto fail;
399	}
400
401	usbprnp->usbprn_setparms.write_timeout = USBPRN_XFER_TIMEOUT;
402	usbprnp->usbprn_setparms.mode =  ECPP_CENTRONICS;
403	usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
404
405	if (usb_pipe_get_max_bulk_transfer_size(usbprnp->usbprn_dip, &sz)) {
406
407		goto fail;
408	}
409
410	usbprnp->usbprn_max_bulk_xfer_size = sz;
411
412	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
413	    "usbprn_attach: xfer_size=0x%lx", sz);
414
415	/* enable PM */
416	usbprn_create_pm_components(dip, usbprnp);
417
418	/* Register for events */
419	if (usb_register_event_cbs(dip, &usbprn_events, 0) != USB_SUCCESS) {
420		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
421		    "usbprn_attach: usb_register_event_cbs failed");
422
423		goto fail;
424	}
425
426	usb_free_dev_data(dip, usbprnp->usbprn_dev_data);
427	usbprnp->usbprn_dev_data = NULL;
428
429	if (usb_owns_device(dip)) {
430		/* get a ugen handle */
431		bzero(&usb_ugen_info, sizeof (usb_ugen_info));
432
433		usb_ugen_info.usb_ugen_flags = 0;
434		usb_ugen_info.usb_ugen_minor_node_ugen_bits_mask =
435		    (dev_t)USBPRN_MINOR_UGEN_BITS_MASK;
436		usb_ugen_info.usb_ugen_minor_node_instance_mask =
437		    (dev_t)~USBPRN_MINOR_UGEN_BITS_MASK;
438		usbprnp->usbprn_ugen_hdl =
439		    usb_ugen_get_hdl(dip, &usb_ugen_info);
440
441		if (usb_ugen_attach(usbprnp->usbprn_ugen_hdl, cmd) !=
442		    USB_SUCCESS) {
443			USB_DPRINTF_L2(PRINT_MASK_ATTA,
444			    usbprnp->usbprn_log_handle,
445			    "usb_ugen_attach failed");
446
447			usb_ugen_release_hdl(usbprnp->usbprn_ugen_hdl);
448			usbprnp->usbprn_ugen_hdl = NULL;
449		}
450	}
451
452	/* Report device */
453	ddi_report_dev(dip);
454
455	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
456	    "usbprn_attach: done");
457
458	return (DDI_SUCCESS);
459
460fail:
461	if (usbprnp) {
462		usbprn_cleanup(dip, usbprnp);
463	}
464
465	return (DDI_FAILURE);
466}
467
468
469/*
470 * usbprn_detach:
471 *	detach or suspend driver instance
472 */
473static int
474usbprn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
475{
476	int		instance = ddi_get_instance(dip);
477	usbprn_state_t	*usbprnp;
478	int		rval = DDI_FAILURE;
479
480	usbprnp = ddi_get_soft_state(usbprn_statep, instance);
481
482	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
483	    "usbprn_detach: cmd=%x", cmd);
484
485	switch (cmd) {
486	case DDI_DETACH:
487		ASSERT((usbprnp->usbprn_flags & USBPRN_OPEN) == 0);
488		usbprn_cleanup(dip, usbprnp);
489
490		return (DDI_SUCCESS);
491	case DDI_SUSPEND:
492		rval = usbprn_cpr_suspend(dip);
493
494		return ((rval == USB_SUCCESS) ? DDI_SUCCESS :
495		    DDI_FAILURE);
496	default:
497
498		return (rval);
499	}
500}
501
502
503/*
504 * usbprn_cleanup:
505 *	clean up the driver state
506 */
507static void
508usbprn_cleanup(dev_info_t *dip, usbprn_state_t *usbprnp)
509{
510	usbprn_power_t	*usbprnpm = usbprnp->usbprn_pm;
511	int		rval = 0;
512
513	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
514	    "usbprn_cleanup: Start");
515
516	ASSERT(usbprnp != NULL);
517
518	if (usbprnp->usbprn_flags & USBPRN_LOCKS_INIT_DONE) {
519		/*
520		 * Disable the event callbacks first, after this point, event
521		 * callbacks will never get called. Note we shouldn't hold
522		 * mutex while unregistering events because there may be a
523		 * competing event callback thread. Event callbacks are done
524		 * with ndi mutex held and this can cause a potential deadlock.
525		 */
526		usb_unregister_event_cbs(dip, &usbprn_events);
527
528		mutex_enter(&usbprnp->usbprn_mutex);
529		if ((usbprnpm) &&
530		    (usbprnp->usbprn_dev_state != USB_DEV_DISCONNECTED)) {
531
532			mutex_exit(&usbprnp->usbprn_mutex);
533			usbprn_pm_busy_component(usbprnp);
534			mutex_enter(&usbprnp->usbprn_mutex);
535
536			if (usbprnpm->usbprn_wakeup_enabled) {
537
538				mutex_exit(&usbprnp->usbprn_mutex);
539
540				(void) pm_raise_power(dip, 0,
541				    USB_DEV_OS_FULL_PWR);
542
543				if ((rval = usb_handle_remote_wakeup(dip,
544				    USB_REMOTE_WAKEUP_DISABLE)) !=
545				    USB_SUCCESS) {
546					USB_DPRINTF_L2(PRINT_MASK_ALL,
547					    usbprnp->usbprn_log_handle,
548					    "usbprn_cleanup: "
549					    "disable remote wakeup "
550					    "failed, rval=%d", rval);
551				}
552			} else {
553				mutex_exit(&usbprnp->usbprn_mutex);
554			}
555
556			(void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
557			usbprn_pm_idle_component(usbprnp);
558
559			mutex_enter(&usbprnp->usbprn_mutex);
560		}
561
562		ddi_remove_minor_node(dip, NULL);
563
564		mutex_exit(&usbprnp->usbprn_mutex);
565
566		if (usbprnp->usbprn_device_id) {
567			kmem_free(usbprnp->usbprn_device_id,
568			    usbprnp->usbprn_device_id_len + 1);
569		}
570
571		mutex_destroy(&usbprnp->usbprn_mutex);
572		usb_fini_serialization(usbprnp->usbprn_dev_acc);
573		usb_fini_serialization(usbprnp->usbprn_ser_acc);
574		usb_fini_serialization(usbprnp->usbprn_write_acc);
575	}
576
577	if (usbprnpm) {
578		kmem_free(usbprnpm, sizeof (usbprn_power_t));
579	}
580
581	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
582	    "usbprn_cleanup: End");
583
584	if (usbprnp->usbprn_ugen_hdl) {
585		(void) usb_ugen_detach(usbprnp->usbprn_ugen_hdl, DDI_DETACH);
586		usb_ugen_release_hdl(usbprnp->usbprn_ugen_hdl);
587	}
588
589	/* unregister with USBA */
590	usb_client_detach(dip, usbprnp->usbprn_dev_data);
591
592	usb_free_log_hdl(usbprnp->usbprn_log_handle);
593	ddi_prop_remove_all(dip);
594	ddi_soft_state_free(usbprn_statep, usbprnp->usbprn_instance);
595}
596
597
598/*
599 * usbprn_cpr_suspend:
600 *	prepare to be suspended
601 */
602static int
603usbprn_cpr_suspend(dev_info_t *dip)
604{
605	usbprn_state_t	*usbprnp;
606	int		instance = ddi_get_instance(dip);
607	int		rval = USB_FAILURE;
608
609	usbprnp = ddi_get_soft_state(usbprn_statep, instance);
610
611	USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
612	    "usbprn_cpr_suspend");
613
614	(void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
615
616	mutex_enter(&usbprnp->usbprn_mutex);
617
618	if ((usbprnp->usbprn_flags & USBPRN_OPEN) != 0) {
619		mutex_exit(&usbprnp->usbprn_mutex);
620
621		USB_DPRINTF_L2(PRINT_MASK_CPR,
622		    usbprnp->usbprn_log_handle,
623		    "usbprn_cpr_suspend: "
624		    "Device is open.  Can't suspend");
625
626	} else {
627		usbprnp->usbprn_dev_state = USB_DEV_SUSPENDED;
628		mutex_exit(&usbprnp->usbprn_mutex);
629
630		USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
631		    "usbprn_cpr_suspend: SUCCESS");
632		rval = USB_SUCCESS;
633	}
634	usb_release_access(usbprnp->usbprn_ser_acc);
635
636	if ((rval == USB_SUCCESS) && usbprnp->usbprn_ugen_hdl) {
637		rval = usb_ugen_detach(usbprnp->usbprn_ugen_hdl,
638		    DDI_SUSPEND);
639	}
640
641	return (rval);
642}
643
644
645static void
646usbprn_cpr_resume(dev_info_t *dip)
647{
648	int		instance = ddi_get_instance(dip);
649	usbprn_state_t	*usbprnp = ddi_get_soft_state(usbprn_statep, instance);
650
651	USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
652	    "usbprn_cpr_resume");
653
654	/* Needed as power up state of dev is "unknown" to system */
655	usbprn_pm_busy_component(usbprnp);
656	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
657
658	usbprn_restore_device_state(dip, usbprnp);
659
660	usbprn_pm_idle_component(usbprnp);
661
662	if (usbprnp->usbprn_ugen_hdl) {
663		(void) usb_ugen_attach(usbprnp->usbprn_ugen_hdl,
664		    DDI_RESUME);
665	}
666}
667
668
669/*
670 * usbprn_get_descriptors:
671 *	Obtain all the descriptors for the device
672 */
673static int
674usbprn_get_descriptors(usbprn_state_t *usbprnp)
675{
676	int			interface;
677	usb_client_dev_data_t	*dev_data =
678	    usbprnp->usbprn_dev_data;
679	usb_alt_if_data_t	*altif_data;
680	usb_cfg_data_t		*cfg_data;
681	usb_ep_data_t		*ep_data;
682	dev_info_t		*dip = usbprnp->usbprn_dip;
683	int			alt, rval;
684
685	ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
686
687	/*
688	 * Section 4.2.1 of the spec says the printer could have
689	 * multiple configurations.  This driver is just for one
690	 * configuration interface and one interface.
691	 */
692	interface = dev_data->dev_curr_if;
693	cfg_data = dev_data->dev_curr_cfg;
694
695	/* find alternate that supports BI/UNI protocol */
696	for (alt = 0; alt < cfg_data->cfg_if[interface].if_n_alt; alt++) {
697		altif_data = &cfg_data->cfg_if[interface].if_alt[alt];
698
699		if ((altif_data->altif_descr.bInterfaceProtocol ==
700		    USB_PROTO_PRINTER_UNI) ||
701		    (altif_data->altif_descr.bInterfaceProtocol ==
702		    USB_PROTO_PRINTER_BI)) {
703
704			break;
705		} else {
706			USB_DPRINTF_L3(PRINT_MASK_ATTA,
707			    usbprnp->usbprn_log_handle,
708			    "alternate %d not supported", alt);
709		}
710	}
711
712	if (alt == cfg_data->cfg_if[interface].if_n_alt) {
713		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
714		    "usbprn_get_descriptors: no alternate");
715
716		return (USB_FAILURE);
717	}
718
719
720	if ((rval = usb_set_alt_if(dip, interface, alt, USB_FLAGS_SLEEP,
721	    NULL, NULL)) != USB_SUCCESS) {
722		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
723		    "usbprn_get_descriptors: set alternate failed (%d)",
724		    rval);
725
726		return (rval);
727	}
728
729	usbprnp->usbprn_config_descr = cfg_data->cfg_descr;
730	usbprnp->usbprn_if_descr = altif_data->altif_descr;
731
732	/*
733	 * find the endpoint descriptors. There will be a bulk-out endpoint
734	 * and an optional bulk-in endpoint.
735	 */
736	if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, alt, 0,
737	    USB_EP_ATTR_BULK, USB_EP_DIR_OUT)) != NULL) {
738		usbprnp->usbprn_bulk_out.ps_ept_descr = ep_data->ep_descr;
739	}
740	if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, alt, 0,
741	    USB_EP_ATTR_BULK, USB_EP_DIR_IN)) != NULL) {
742		usbprnp->usbprn_bulk_in.ps_ept_descr = ep_data->ep_descr;
743	}
744
745	return (USB_SUCCESS);
746}
747
748
749/*
750 * usbprn_get_device_id:
751 *	Get the device id as described in 4.2.1 of the specification
752 *	Lexmark printer returns 2 bytes when asked for 8 bytes
753 *	We are ignoring data over and underrun.
754 *	This is a synchronous function
755 */
756static int
757usbprn_get_device_id(usbprn_state_t *usbprnp)
758{
759	int			len, n;
760	mblk_t			*data = NULL;
761	usb_cr_t		completion_reason;
762	usb_cb_flags_t		cb_flags;
763	int			rval = USB_FAILURE;
764	usb_ctrl_setup_t setup = {
765	    USB_DEV_REQ_DEV_TO_HOST |	/* bmRequestType */
766	    USB_DEV_REQ_TYPE_CLASS |
767	    USB_DEV_REQ_RCPT_IF,
768	    USB_PRINTER_GET_DEVICE_ID,	/* bRequest */
769	    0,				/* wValue: fill in later */
770	    0,				/* wIndex: fill in later  */
771	    0,				/* wLength: fill in later */
772	    0				/* attributes */
773	    };
774	void			*ptr;
775
776	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
777	    "usbprn_get_device_id: Begin");
778
779	ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
780
781	setup.wIndex = (usbprnp->usbprn_if_descr.bInterfaceNumber << 0x8) |
782	    (usbprnp->usbprn_if_descr.bAlternateSetting);
783	setup.wLength = USBPRN_MAX_DEVICE_ID_LENGTH;
784	setup.wValue = usbprnp->usbprn_config_descr.iConfiguration;
785
786	/*
787	 * This is always a sync request as this will never
788	 * be called in interrupt context.
789	 * First get the first two bytes that gives the length
790	 * of the device id string; then get the whole string
791	 */
792	if (usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph, &setup,
793	    &data, &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
794
795		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
796		    "usbprn_get_device_id: First sync command failed, cr=%d ",
797		    completion_reason);
798
799		/*
800		 * some devices return more than requested. as long as
801		 * we get the first two bytes, we can continue
802		 */
803		if (((completion_reason != USB_CR_DATA_OVERRUN) &&
804		    (completion_reason != USB_CR_DATA_UNDERRUN)) ||
805		    (data == NULL)) {
806
807			goto done;
808		}
809	}
810
811	ASSERT(data);
812	n = MBLKL(data);
813
814	if (n < 2) {
815
816		goto done;
817	}
818
819	len = (((*data->b_rptr) << 0x8) | (*(data->b_rptr+1)));
820
821	/*
822	 * Std 1284-1994, chapter 7.6:
823	 *	Length values of x'0000', x'0001' and x'0002' are reserved
824	 */
825	if (len < 3) {
826
827		goto done;
828	}
829
830	USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
831	    "usbprn_get_device_id: device id length=%d", len);
832
833	/* did we get enough data */
834	if (len > n) {
835		freemsg(data);
836		data = NULL;
837
838		setup.wLength = (uint16_t)len;
839		if ((rval = usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph,
840		    &setup, &data, &completion_reason, &cb_flags, 0)) !=
841		    USB_SUCCESS) {
842			USB_DPRINTF_L2(PRINT_MASK_ATTA,
843			    usbprnp->usbprn_log_handle,
844			    "usbprn_get_device_id: 2nd command failed "
845			    "cr=%d cb_flags=0x%x",
846			    completion_reason, cb_flags);
847
848			goto done;
849		}
850
851		ASSERT(len == MBLKL(data));
852	}
853
854	USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
855	    "usbprn_get_device_id: returned data length=%ld",
856	    (long)(MBLKL(data)));
857
858	ptr = kmem_zalloc(len + 1, KM_SLEEP);
859
860	mutex_enter(&usbprnp->usbprn_mutex);
861	usbprnp->usbprn_device_id_len = len;
862	usbprnp->usbprn_device_id = ptr;
863
864	bcopy(data->b_rptr, usbprnp->usbprn_device_id,
865	    usbprnp->usbprn_device_id_len);
866	usbprnp->usbprn_device_id[usbprnp->usbprn_device_id_len] = '\0';
867
868	/* Length is in the first two bytes, dump string in logbuf */
869	usbprn_print_long(usbprnp, usbprnp->usbprn_device_id + 2,
870	    usbprnp->usbprn_device_id_len - 2);
871	mutex_exit(&usbprnp->usbprn_mutex);
872
873	rval = USB_SUCCESS;
874done:
875	freemsg(data);
876
877	USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
878	    "usbprn_get_device_id: rval=%d", rval);
879
880	return (rval);
881}
882
883
884/*
885 * usbprn_get_port_status:
886 *	Get the port status.
887 *	This is a synchronous function
888 */
889static int
890usbprn_get_port_status(usbprn_state_t  *usbprnp)
891{
892	mblk_t			*data = NULL;
893	usb_cr_t		completion_reason;
894	usb_cb_flags_t		cb_flags;
895	usb_ctrl_setup_t setup = {
896	    USB_DEV_REQ_DEV_TO_HOST |	/* bmRequestType */
897	    USB_DEV_REQ_TYPE_CLASS |
898	    USB_DEV_REQ_RCPT_IF,
899	    USB_PRINTER_GET_PORT_STATUS, /* bRequest */
900	    0,				/* wValue */
901	    0,				/* wIndex: fill in later  */
902	    1,				/* wLength */
903	    0				/* attributes */
904	    };
905	ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
906
907	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
908	    "usbprn_get_port_status: Begin");
909
910	setup.wIndex = usbprnp->usbprn_if_descr.bInterfaceNumber;
911	if (usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph,
912	    &setup, &data, &completion_reason, &cb_flags, 0) !=
913	    USB_SUCCESS) {
914		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
915		    "usbprn_get_port_status: Sync command failed "
916		    "cr=%d cb_flags=0x%x", completion_reason, cb_flags);
917
918		freemsg(data);
919
920		return (USB_FAILURE);
921	} else {
922		mutex_enter(&usbprnp->usbprn_mutex);
923
924		ASSERT(data);
925		ASSERT(MBLKL(data) == 1);
926
927		usbprnp->usbprn_last_status = *data->b_rptr;
928
929		USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
930		    "usbprn_get_port_status(sync): status=0x%x",
931		    usbprnp->usbprn_last_status);
932
933		mutex_exit(&usbprnp->usbprn_mutex);
934		freemsg(data);
935
936		return (USB_SUCCESS);
937	}
938}
939
940
941/*
942 * usbprn_open:
943 *	Open the pipes
944 */
945/*ARGSUSED*/
946static int
947usbprn_open(dev_t *devp, int flag, int sflag, cred_t *credp)
948{
949	usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
950	    USBPRN_MINOR_TO_INSTANCE(getminor(*devp)));
951	int rval = 0;
952
953	if (usbprnp == NULL) {
954
955		return (ENXIO);
956	}
957
958	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
959	    "usbprn_open:");
960
961	(void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
962
963	/* Fail open on a disconnected device */
964	mutex_enter(&usbprnp->usbprn_mutex);
965	if (usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED) {
966		mutex_exit(&usbprnp->usbprn_mutex);
967		usb_release_access(usbprnp->usbprn_ser_acc);
968
969		return (ENODEV);
970	}
971
972	/* cannot happen? but just in case */
973	if (usbprnp->usbprn_dev_state == USB_DEV_SUSPENDED) {
974		mutex_exit(&usbprnp->usbprn_mutex);
975		usb_release_access(usbprnp->usbprn_ser_acc);
976
977		return (EIO);
978	}
979
980	if (getminor(*devp) & USBPRN_MINOR_UGEN_BITS_MASK) {
981		mutex_exit(&usbprnp->usbprn_mutex);
982
983		rval = usb_ugen_open(usbprnp->usbprn_ugen_hdl,
984		    devp, flag, sflag, credp);
985
986		usb_release_access(usbprnp->usbprn_ser_acc);
987
988		return (rval);
989	}
990
991	/* Exit if this instance is already open */
992	if (usbprnp->usbprn_flags & USBPRN_OPEN) {
993		mutex_exit(&usbprnp->usbprn_mutex);
994		usb_release_access(usbprnp->usbprn_ser_acc);
995
996		return (EBUSY);
997	}
998	mutex_exit(&usbprnp->usbprn_mutex);
999
1000	/* raise power */
1001	usbprn_pm_busy_component(usbprnp);
1002	(void) pm_raise_power(usbprnp->usbprn_dip,
1003	    0, USB_DEV_OS_FULL_PWR);
1004	/* initialize some softstate data */
1005	mutex_enter(&usbprnp->usbprn_mutex);
1006	usbprnp->usbprn_prn_timeouts.tmo_forward =
1007	    usbprnp->usbprn_setparms.write_timeout;
1008	usbprnp->usbprn_prn_timeouts.tmo_reverse = 0;
1009	mutex_exit(&usbprnp->usbprn_mutex);
1010
1011	if (usbprn_open_usb_pipes(usbprnp) != USB_SUCCESS) {
1012
1013		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
1014		    "usbprn_open: pipe open failed");
1015
1016		usb_release_access(usbprnp->usbprn_ser_acc);
1017		usbprn_pm_idle_component(usbprnp);
1018
1019		return (EIO);
1020	}
1021
1022	mutex_enter(&usbprnp->usbprn_mutex);
1023	usbprnp->usbprn_flags |= USBPRN_OPEN;
1024
1025	/* set last status to online */
1026	usbprnp->usbprn_last_status &= ~USB_PRINTER_PORT_NO_SELECT;
1027	mutex_exit(&usbprnp->usbprn_mutex);
1028
1029	usb_release_access(usbprnp->usbprn_ser_acc);
1030
1031	USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
1032	    "usbprn_open: End");
1033
1034	return (rval);
1035}
1036
1037
1038/*
1039 * usbprn_close:
1040 *	Close the pipes
1041 */
1042/*ARGSUSED*/
1043static int
1044usbprn_close(dev_t dev, int flag, int otyp, cred_t *credp)
1045{
1046	usbprn_state_t	*usbprnp = ddi_get_soft_state(usbprn_statep,
1047	    USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
1048	int		rval = 0;
1049
1050	if (usbprnp == NULL) {
1051
1052		return (ENXIO);
1053	}
1054
1055	USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbprnp->usbprn_log_handle,
1056	    "usbprn_close:");
1057
1058	if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
1059		rval = usb_ugen_close(usbprnp->usbprn_ugen_hdl,
1060		    dev, flag, otyp, credp);
1061
1062		return (rval);
1063	}
1064
1065	/* avoid races with connect/disconnect */
1066	(void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
1067	(void) usb_serialize_access(usbprnp->usbprn_dev_acc, USB_WAIT, 0);
1068
1069	/* Close all usb pipes */
1070	usbprn_close_usb_pipes(usbprnp);
1071
1072	/* prevent any accesses by setting flags to closed */
1073	mutex_enter(&usbprnp->usbprn_mutex);
1074	usbprnp->usbprn_flags &= ~USBPRN_OPEN;
1075	mutex_exit(&usbprnp->usbprn_mutex);
1076
1077	usb_release_access(usbprnp->usbprn_dev_acc);
1078	usb_release_access(usbprnp->usbprn_ser_acc);
1079
1080	usbprn_pm_idle_component(usbprnp);
1081
1082	USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbprnp->usbprn_log_handle,
1083	    "usbprn_close: End");
1084
1085	return (rval);
1086}
1087
1088
1089/*
1090 * usbprn_read:
1091 *	Read entry point (TBD)
1092 */
1093/* ARGSUSED */
1094static int
1095usbprn_read(dev_t dev, struct uio *uiop, cred_t *credp)
1096{
1097	usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1098	    USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
1099
1100	if (usbprnp == NULL) {
1101
1102		return (ENXIO);
1103	}
1104
1105	if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
1106		int rval;
1107
1108		/* raise power */
1109		usbprn_pm_busy_component(usbprnp);
1110		(void) pm_raise_power(usbprnp->usbprn_dip,
1111		    0, USB_DEV_OS_FULL_PWR);
1112
1113		if (usb_serialize_access(usbprnp->usbprn_write_acc,
1114		    USB_WAIT_SIG, 0) == 0) {
1115			usbprn_pm_idle_component(usbprnp);
1116
1117			return (EINTR);
1118		}
1119
1120		rval = usb_ugen_read(usbprnp->usbprn_ugen_hdl, dev,
1121		    uiop, credp);
1122
1123		usb_release_access(usbprnp->usbprn_write_acc);
1124
1125		usbprn_pm_idle_component(usbprnp);
1126
1127		return (rval);
1128	}
1129
1130	/* Do a bulk-in from the printer */
1131
1132	return (EIO);
1133}
1134
1135
1136/*
1137 * usbprn_write:
1138 *	Write to the printer
1139 */
1140/* ARGSUSED2 */
1141static int
1142usbprn_write(dev_t dev, struct uio *uiop, cred_t *credp)
1143{
1144	usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1145	    USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
1146	usbprn_ps_t	*bulk_in = &usbprnp->usbprn_bulk_in;
1147	usbprn_ps_t	*bulk_out = &usbprnp->usbprn_bulk_out;
1148	int		rval;
1149
1150	if (usbprnp == NULL) {
1151
1152		return (ENXIO);
1153	}
1154
1155	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1156	    "usbprn_write: Begin usbprnp=0x%p ", (void *)usbprnp);
1157
1158	if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
1159		/* raise power */
1160		usbprn_pm_busy_component(usbprnp);
1161		(void) pm_raise_power(usbprnp->usbprn_dip,
1162		    0, USB_DEV_OS_FULL_PWR);
1163
1164		if (usb_serialize_access(usbprnp->usbprn_write_acc,
1165		    USB_WAIT_SIG, 0) == 0) {
1166			usbprn_pm_idle_component(usbprnp);
1167
1168			return (EINTR);
1169		}
1170
1171		rval = usb_ugen_write(usbprnp->usbprn_ugen_hdl, dev,
1172		    uiop, credp);
1173
1174		usb_release_access(usbprnp->usbprn_write_acc);
1175
1176		usbprn_pm_idle_component(usbprnp);
1177
1178		return (rval);
1179	}
1180
1181	/*
1182	 * serialize writes
1183	 * we cannot use usbprn_ser_acc sync object at this point because
1184	 * that would block out the ioctls for the full duration of the write.
1185	 */
1186	if (usb_serialize_access(usbprnp->usbprn_write_acc,
1187	    USB_WAIT_SIG, 0) == 0) {
1188
1189		return (EINTR);
1190	}
1191
1192	/*
1193	 * Check the status of the pipe.  If it's not idle,
1194	 * then wait.
1195	 */
1196	mutex_enter(&usbprnp->usbprn_mutex);
1197
1198	/* if device is disconnected or pipes closed, fail immediately */
1199	if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
1200		mutex_exit(&usbprnp->usbprn_mutex);
1201
1202		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1203		    "usbprn_write: device can't be accessed");
1204
1205		usb_release_access(usbprnp->usbprn_write_acc);
1206
1207		return (EIO);
1208	}
1209
1210	/* all pipes must be idle */
1211	ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
1212	ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
1213
1214	mutex_exit(&usbprnp->usbprn_mutex);
1215
1216	/*
1217	 * Call physio to do the transfer.  physio will
1218	 * call the strategy routine, and then call
1219	 * biowait() to block until the transfer completes.
1220	 */
1221	rval = physio(usbprn_strategy, (struct buf *)0, dev,
1222	    B_WRITE, usbprn_minphys, uiop);
1223
1224	usb_release_access(usbprnp->usbprn_write_acc);
1225
1226	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1227	    "usbprn_write: End");
1228
1229	return (rval);
1230}
1231
1232
1233/*
1234 * usbprn_poll
1235 */
1236static int
1237usbprn_poll(dev_t dev, short events,
1238    int anyyet,  short *reventsp, struct pollhead **phpp)
1239{
1240	usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1241	    USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
1242
1243	if (usbprnp == NULL) {
1244
1245		return (ENXIO);
1246	}
1247
1248	if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
1249		return (usb_ugen_poll(usbprnp->usbprn_ugen_hdl, dev, events,
1250		    anyyet, reventsp, phpp));
1251	}
1252
1253	return (ENXIO);
1254}
1255
1256
1257/*
1258 * usbprn_strategy:
1259 *	service a request to the device.
1260 */
1261static int
1262usbprn_strategy(struct buf *bp)
1263{
1264	usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1265	    USBPRN_MINOR_TO_INSTANCE(getminor(bp->b_edev)));
1266	usbprn_ps_t	*bulk_out = &usbprnp->usbprn_bulk_out;
1267
1268	bp_mapin(bp);
1269
1270	/*
1271	 * serialize to avoid races
1272	 * access is released in usbprn_biodone()
1273	 */
1274	(void) usb_serialize_access(usbprnp->usbprn_dev_acc, USB_WAIT, 0);
1275
1276	mutex_enter(&usbprnp->usbprn_mutex);
1277	if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
1278		usbprn_biodone(usbprnp, EIO, 0);
1279		mutex_exit(&usbprnp->usbprn_mutex);
1280
1281		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1282		    "usbprn_strategy: device can't be accessed");
1283
1284		return (0);
1285	}
1286
1287	bulk_out->ps_flags = USBPRN_PS_NEED_TO_XFER;
1288
1289	ASSERT(usbprnp->usbprn_bp == NULL);
1290	usbprnp->usbprn_bp = bp;
1291
1292	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1293	    "usbprn_strategy: usbprnp=0x%p bp=0x%p count=%lu",
1294	    (void *)usbprnp, (void *)bp, bp->b_bcount);
1295
1296	ASSERT(usbprnp->usbprn_bulk_mp == NULL);
1297
1298	usbprnp->usbprn_bulk_mp = allocb(bp->b_bcount, BPRI_HI);
1299
1300	if (usbprnp->usbprn_bulk_mp == NULL) {
1301		bulk_out->ps_flags = USBPRN_PS_IDLE;
1302		usbprn_biodone(usbprnp, EIO, 0);
1303		mutex_exit(&usbprnp->usbprn_mutex);
1304
1305		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1306		    "usbprn_strategy: allocb failed");
1307
1308		return (0);
1309	}
1310
1311	bcopy((caddr_t)bp->b_un.b_addr,
1312	    usbprnp->usbprn_bulk_mp->b_datap->db_base, bp->b_bcount);
1313	usbprnp->usbprn_bulk_mp->b_wptr += bp->b_bcount;
1314	mutex_exit(&usbprnp->usbprn_mutex);
1315
1316	usbprn_send_async_bulk_data(usbprnp);
1317
1318	return (0);
1319}
1320
1321
1322/*
1323 * usbprn_ioctl:
1324 *	handle the ioctl
1325 */
1326/*ARGSUSED4*/
1327static int
1328usbprn_ioctl(dev_t dev, int cmd, intptr_t arg, int flag,
1329		cred_t *credp, int *rvalp)
1330{
1331	int		err = 0;
1332	usbprn_state_t	*usbprnp = ddi_get_soft_state(usbprn_statep,
1333	    USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
1334	struct ecpp_device_id	usbprn_devid;
1335	int		len;
1336
1337	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1338	    "usbprn_ioctl: Begin ");
1339
1340	(void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
1341	mutex_enter(&usbprnp->usbprn_mutex);
1342
1343	/*
1344	 * only for PRNIOC_GET_STATUS cmd:
1345	 * if device is disconnected or pipes closed, fail immediately
1346	 */
1347	if ((cmd == PRNIOC_GET_STATUS) &&
1348	    !(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
1349		mutex_exit(&usbprnp->usbprn_mutex);
1350
1351		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1352		    "usbprn_write: device can't be accessed");
1353
1354		usb_release_access(usbprnp->usbprn_ser_acc);
1355
1356		return (EIO);
1357	}
1358	mutex_exit(&usbprnp->usbprn_mutex);
1359
1360	switch (cmd) {
1361	case ECPPIOC_GETDEVID:
1362		/*
1363		 * With genericized ioctls this interface should change.
1364		 * We ignore the mode in USB printer driver because
1365		 * it need not be in nibble mode in usb driver unlike
1366		 * ecpp to retrieve the device id string. Also we do
1367		 * not expect the application to call this twice since
1368		 * it doesn't change since attach time and we take care
1369		 * of calling it twice: once for getting the length and
1370		 * once for getting the actual device id string. So we
1371		 * set both the lengths to actual device id string length.
1372		 * Ref: PSARC/2000/018
1373		 */
1374		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1375		    "usbprn_ioctl: ECPPIOC_GETDEVID(0x%x)", cmd);
1376
1377		bzero(&usbprn_devid, sizeof (usbprn_devid));
1378
1379		ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
1380#ifdef _MULTI_DATAMODEL
1381		switch (ddi_model_convert_from(flag & FMODELS)) {
1382		case DDI_MODEL_ILP32: {
1383			struct ecpp_device_id32	usbprn_devid32;
1384
1385			if (ddi_copyin((caddr_t)arg, &usbprn_devid32,
1386			    sizeof (struct ecpp_device_id32), flag)) {
1387				err = EFAULT;
1388
1389				break;
1390			}
1391
1392			if (usbprnp->usbprn_device_id == NULL) {
1393				err = EIO;
1394
1395				break;
1396			}
1397			ASSERT(usbprnp->usbprn_device_id_len > 2);
1398
1399			usbprn_devid32.rlen = usbprnp->usbprn_device_id_len - 2;
1400			len = min(usbprn_devid32.len, usbprn_devid32.rlen);
1401
1402			if (ddi_copyout(usbprnp->usbprn_device_id + 2,
1403			    (caddr_t)(uintptr_t)usbprn_devid32.addr,
1404			    len, flag)) {
1405				err = EFAULT;
1406
1407				break;
1408			}
1409
1410			if (ddi_copyout(&usbprn_devid32, (caddr_t)arg,
1411			    sizeof (struct ecpp_device_id32), flag)) {
1412				err = EFAULT;
1413
1414				break;
1415			}
1416
1417			break;
1418		}
1419		case DDI_MODEL_NONE:
1420			if (ddi_copyin((caddr_t)arg, &usbprn_devid,
1421			    sizeof (struct ecpp_device_id), flag)) {
1422				err = EFAULT;
1423
1424				break;
1425			}
1426
1427			if (usbprnp->usbprn_device_id == NULL) {
1428				err = EIO;
1429
1430				break;
1431			}
1432			ASSERT(usbprnp->usbprn_device_id_len > 2);
1433
1434			usbprn_devid.rlen = usbprnp->usbprn_device_id_len - 2;
1435			len = min(usbprn_devid.len, usbprn_devid.rlen);
1436
1437			if (ddi_copyout(usbprnp->usbprn_device_id + 2,
1438			    usbprn_devid.addr, len, flag)) {
1439				err = EFAULT;
1440
1441				break;
1442			}
1443
1444			if (ddi_copyout(&usbprn_devid, (caddr_t)arg,
1445			    sizeof (struct ecpp_device_id), flag)) {
1446				err = EFAULT;
1447
1448				break;
1449			}
1450
1451			break;
1452		}
1453
1454		break;
1455#else
1456		if (ddi_copyin((caddr_t)arg, &usbprn_devid,
1457		    sizeof (struct ecpp_device_id), flag)) {
1458			err = EFAULT;
1459
1460			break;
1461		}
1462
1463
1464		if (usbprnp->usbprn_device_id == NULL) {
1465			err = EIO;
1466
1467			break;
1468		}
1469		ASSERT(usbprnp->usbprn_device_id_len > 2);
1470
1471		usbprn_devid.rlen = usbprnp->usbprn_device_id_len - 2;
1472		len = min(usbprn_devid.len, usbprn_devid.rlen);
1473
1474		if (ddi_copyout(usbprnp->usbprn_device_id + 2,
1475		    usbprn_devid.addr, len, flag)) {
1476			err = EFAULT;
1477
1478			break;
1479		}
1480
1481		if (ddi_copyout(&usbprn_devid, (caddr_t)arg,
1482		    sizeof (struct ecpp_device_id), flag)) {
1483			err = EFAULT;
1484
1485			break;
1486		}
1487
1488		break;
1489#endif
1490	case ECPPIOC_SETPARMS:
1491		err = usbprn_setparms(usbprnp, arg, flag);
1492
1493		break;
1494	case ECPPIOC_GETPARMS:
1495		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1496		    "usbprn_ioctl: ECPPIOC_GETPARMS(0x%x)", cmd);
1497
1498		/* Get the parameters */
1499		err = usbprn_getparms(usbprnp, arg, flag);
1500
1501		break;
1502	case BPPIOC_GETERR:
1503		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1504		    "usbprn_ioctl: ECPPIOC_GETERR(0x%x)", cmd);
1505
1506		/* Get the error state */
1507		usbprn_geterr(usbprnp, arg, flag);
1508
1509		break;
1510	case BPPIOC_TESTIO:
1511		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1512		    "usbprn_ioctl: BPPIOC_TESTIO(0x%x)",  cmd);
1513
1514		/* Get the port status */
1515		err = usbprn_testio(usbprnp, flag);
1516
1517		break;
1518	case PRNIOC_GET_IFCAP:
1519		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1520		    "usbprn_ioctl : PRNIOC_GET_IFCAP(0x%x)",  cmd);
1521
1522		/* get interface capabilities */
1523		err = usbprn_prnio_get_ifcap(usbprnp, arg, flag);
1524
1525		break;
1526	case PRNIOC_SET_IFCAP:
1527		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1528		    "usbprn_ioctl : PRNIOC_SET_IFCAP(0x%x)",  cmd);
1529
1530		/* get interface capabilities */
1531		err = usbprn_prnio_set_ifcap(usbprnp, arg, flag);
1532
1533		break;
1534	case PRNIOC_GET_IFINFO:
1535		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1536		    "usbprn_ioctl : PRNIOC_GET_IFINFO(0x%x)",  cmd);
1537
1538		/* get interface information */
1539		err = usbprn_prnio_get_ifinfo(usbprnp, arg, flag);
1540
1541		break;
1542	case PRNIOC_GET_STATUS:
1543		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1544		    "usbprn_ioctl : PRNIOC_GET_STATUS(0x%x)",  cmd);
1545
1546		/* get prnio status */
1547		err = usbprn_prnio_get_status(usbprnp, arg, flag);
1548
1549		break;
1550	case PRNIOC_GET_1284_DEVID:
1551		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1552		    "usbprn_ioctl : PRNIOC_GET_1284_DEVID(0x%x)",  cmd);
1553
1554		/* get device ID */
1555		err = usbprn_prnio_get_1284_devid(usbprnp, arg, flag);
1556
1557		break;
1558	case PRNIOC_GET_1284_STATUS:
1559		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1560		    "usbprn_ioctl : PRNIOC_GET_1284_STATUS(0x%x)",  cmd);
1561
1562		/* get prnio status */
1563		err = usbprn_prnio_get_1284_status(usbprnp, arg, flag);
1564
1565		break;
1566	case PRNIOC_GET_TIMEOUTS:
1567		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1568		    "usbprn_ioctl : PRNIOC_GET_TIMEOUTS(0x%x)", cmd);
1569
1570		/* Get the parameters */
1571		err = usbprn_prnio_get_timeouts(usbprnp, arg, flag);
1572
1573		break;
1574	case PRNIOC_SET_TIMEOUTS:
1575		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1576		    "usbprn_ioctl : PRNIOC_SET_TIMEOUTS(0x%x)", cmd);
1577
1578		/* Get the parameters */
1579		err = usbprn_prnio_set_timeouts(usbprnp, arg, flag);
1580
1581		break;
1582	case PRNIOC_RESET:
1583		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1584		    "usbprn_ioctl : PRNIOC_RESET(0x%x)",  cmd);
1585
1586		/* nothing */
1587		err = 0;
1588
1589		break;
1590	default:
1591		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1592		    "usbprn_ioctl: unknown(0x%x)", cmd);
1593		err = EINVAL;
1594	}
1595
1596	usb_release_access(usbprnp->usbprn_ser_acc);
1597
1598	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1599	    "usbprn_ioctl: End ");
1600
1601	return (err);
1602}
1603
1604
1605/*
1606 * breakup by physio
1607 */
1608static void
1609usbprn_minphys(struct buf *bp)
1610{
1611	usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1612	    USBPRN_MINOR_TO_INSTANCE(getminor(bp->b_edev)));
1613
1614	mutex_enter(&usbprnp->usbprn_mutex);
1615	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1616	    "usbprn_minphys: bcount=%lu", bp->b_bcount);
1617
1618	if (bp->b_bcount > usbprnp->usbprn_max_bulk_xfer_size) {
1619		bp->b_bcount = min(usbprn_max_xfer_size,
1620		    usbprnp->usbprn_max_bulk_xfer_size);
1621	} else {
1622		bp->b_bcount = min(usbprn_max_xfer_size, bp->b_bcount);
1623	}
1624	mutex_exit(&usbprnp->usbprn_mutex);
1625}
1626
1627
1628/*
1629 * usbprn_open_usb_pipes:
1630 *	Open all pipes on the device
1631 */
1632static int
1633usbprn_open_usb_pipes(usbprn_state_t *usbprnp)
1634{
1635	usb_pipe_policy_t *policy;
1636	usbprn_ps_t	*bulk_in = &usbprnp->usbprn_bulk_in;
1637	usbprn_ps_t	*bulk_out = &usbprnp->usbprn_bulk_out;
1638
1639	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1640	    "usbprn_open_usb_pipes:");
1641
1642	/*
1643	 * Intitialize the pipe policy for the bulk out pipe
1644	 */
1645	mutex_enter(&usbprnp->usbprn_mutex);
1646	policy = &(bulk_out->ps_policy);
1647	policy->pp_max_async_reqs = 1;
1648	mutex_exit(&usbprnp->usbprn_mutex);
1649
1650	/* Open bulk_out pipe */
1651	if (usb_pipe_open(usbprnp->usbprn_dip, &bulk_out->ps_ept_descr,
1652	    policy, USB_FLAGS_SLEEP, &bulk_out->ps_handle) != USB_SUCCESS) {
1653
1654		return (USB_FAILURE);
1655	}
1656
1657#ifdef LATER
1658	mutex_enter(&usbprnp->usbprn_mutex);
1659	/* Open the bulk in pipe if one exists */
1660	if (bulk_in->ps_ept_descr->bLength) {
1661		/*
1662		 * Initialize the pipe policy for the Bulk In pipe
1663		 */
1664		policy = &bulk_in->ps_policy;
1665		bulk_in->ps_flags = USBPRN_PS_IDLE;
1666		policy->pp_max_async_reqs = 1;
1667		mutex_exit(&usbprnp->usbprn_mutex);
1668
1669		/* Open bulk_in pipe */
1670		if (usb_pipe_open(usbprnp->usbprn_dip, bulk_in->ps_ept_descr,
1671		    policy, USB_FLAGS_SLEEP, &bulk_in->ps_handle) !=
1672		    USB_SUCCESS) {
1673
1674			return (USB_FAILURE);
1675		}
1676	} else {
1677		mutex_exit(&usbprnp->usbprn_mutex);
1678	}
1679#else
1680	mutex_enter(&usbprnp->usbprn_mutex);
1681	bulk_in->ps_flags = USBPRN_PS_IDLE;
1682	mutex_exit(&usbprnp->usbprn_mutex);
1683#endif
1684
1685	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1686	    "usbprn_open_usb_pipes: success");
1687
1688	return (USB_SUCCESS);
1689}
1690
1691
1692/*
1693 * usbprn_close_usb_pipes:
1694 *	Close the default/bulk in/out pipes synchronously
1695 */
1696static void
1697usbprn_close_usb_pipes(usbprn_state_t *usbprnp)
1698{
1699	usbprn_ps_t	*bulk_in = &usbprnp->usbprn_bulk_in;
1700	usbprn_ps_t	*bulk_out = &usbprnp->usbprn_bulk_out;
1701
1702	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1703	    "usbprn_close_usb_pipes:");
1704#ifdef DEBUG
1705	mutex_enter(&usbprnp->usbprn_mutex);
1706	ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
1707	ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
1708	mutex_exit(&usbprnp->usbprn_mutex);
1709#endif
1710
1711	/*
1712	 * close the pipe, if another thread is already closing the
1713	 * pipe, we get USB_INVALID_PIPE
1714	 */
1715	if (bulk_out->ps_handle) {
1716
1717		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1718		    "usbprn_close_usb_pipes: Closing bulk out pipe");
1719
1720		usb_pipe_close(usbprnp->usbprn_dip, bulk_out->ps_handle,
1721		    USB_FLAGS_SLEEP, NULL, NULL);
1722		bulk_out->ps_handle = NULL;
1723	}
1724	if (bulk_in->ps_handle) {
1725
1726		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1727		    "usbprn_close_usb_pipes: Closing bulk in pipe");
1728
1729		usb_pipe_close(usbprnp->usbprn_dip, bulk_in->ps_handle,
1730		    USB_FLAGS_SLEEP, NULL, NULL);
1731		bulk_in->ps_handle = NULL;
1732	}
1733}
1734
1735
1736/*
1737 * usbprn_getparms:
1738 *	Get the parameters for the device
1739 */
1740static int
1741usbprn_getparms(usbprn_state_t *usbprnp, intptr_t arg, int flag)
1742{
1743	ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
1744
1745	if (ddi_copyout(&usbprnp->usbprn_setparms,
1746	    (caddr_t)arg, sizeof (struct ecpp_transfer_parms), flag)) {
1747
1748		return (EFAULT);
1749	}
1750
1751	return (0);
1752}
1753
1754
1755/*
1756 * usbprn_setparms:
1757 *	Set the parameters for the device
1758 */
1759static int
1760usbprn_setparms(usbprn_state_t *usbprnp, intptr_t arg, int flag)
1761{
1762	struct ecpp_transfer_parms xfer;
1763
1764	ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
1765
1766	if (ddi_copyin((caddr_t)arg, &xfer,
1767	    sizeof (struct ecpp_transfer_parms), flag)) {
1768
1769		return (EFAULT);
1770	}
1771	if ((xfer.write_timeout < USBPRN_XFER_TIMEOUT_MIN) ||
1772	    (xfer.write_timeout > USBPRN_XFER_TIMEOUT_MAX)) {
1773
1774		return (EINVAL);
1775	}
1776	if (!((xfer.mode == ECPP_CENTRONICS) ||
1777	    (xfer.mode == ECPP_COMPAT_MODE) ||
1778	    (xfer.mode == ECPP_NIBBLE_MODE) ||
1779	    (xfer.mode == ECPP_ECP_MODE) ||
1780	    (xfer.mode == ECPP_DIAG_MODE))) {
1781
1782		return (EINVAL);
1783
1784	}
1785	if (xfer.mode != ECPP_CENTRONICS) {
1786
1787		return (EPROTONOSUPPORT);
1788	}
1789
1790	mutex_enter(&usbprnp->usbprn_mutex);
1791	usbprnp->usbprn_setparms = xfer;
1792	usbprnp->usbprn_prn_timeouts.tmo_forward = xfer.write_timeout;
1793	mutex_exit(&usbprnp->usbprn_mutex);
1794
1795	return (0);
1796}
1797
1798
1799/*
1800 * usbprn_geterr:
1801 *	Return the any device error state
1802 */
1803static void
1804usbprn_geterr(usbprn_state_t *usbprnp, intptr_t arg, int flag)
1805{
1806	struct bpp_error_status bpp_status;
1807
1808	bzero(&bpp_status, sizeof (bpp_status));
1809
1810	mutex_enter(&usbprnp->usbprn_mutex);
1811	bpp_status.bus_error = 0;
1812	bpp_status.timeout_occurred = 0;
1813	bpp_status.pin_status = usbprn_error_state(usbprnp->usbprn_last_status);
1814
1815	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1816	    "usbprn_geterr: status=0x%x", usbprnp->usbprn_last_status);
1817
1818	mutex_exit(&usbprnp->usbprn_mutex);
1819
1820	(void) ddi_copyout(&bpp_status,
1821	    (caddr_t)arg, sizeof (struct bpp_error_status), flag);
1822}
1823
1824
1825/*
1826 * usbprn_error_state:
1827 *	Map the driver error state to that of the application
1828 */
1829static char
1830usbprn_error_state(uchar_t status)
1831{
1832	uchar_t app_err_status = 0;
1833
1834	if (!(status & USB_PRINTER_PORT_NO_ERROR)) {
1835		app_err_status |= USB_PRINTER_ERR_ERR;
1836	}
1837	if (status & USB_PRINTER_PORT_EMPTY) {
1838		app_err_status |= USB_PRINTER_PE_ERR;
1839	}
1840	if (!(status & USB_PRINTER_PORT_NO_SELECT)) {
1841		app_err_status |= USB_PRINTER_SLCT_ERR;
1842	}
1843
1844	return (app_err_status);
1845}
1846
1847
1848static int
1849usbprn_ioctl_get_status(usbprn_state_t *usbprnp)
1850{
1851	/* Check the transfer mode */
1852	mutex_enter(&usbprnp->usbprn_mutex);
1853
1854	/* if device is disconnected or pipes closed, fail immediately */
1855	if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
1856		mutex_exit(&usbprnp->usbprn_mutex);
1857
1858		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1859		    "usbprn_ioctl_get_status: device can't be accessed");
1860
1861		return (EIO);
1862	}
1863	mutex_exit(&usbprnp->usbprn_mutex);
1864
1865	if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
1866
1867		return (EIO);
1868	}
1869
1870	return (0);
1871}
1872
1873
1874/*
1875 * usbprn_testio:
1876 *	Execute the ECPP_TESTIO ioctl
1877 */
1878/* ARGSUSED1 */
1879static int
1880usbprn_testio(usbprn_state_t *usbprnp, int flag)
1881{
1882	int	err;
1883
1884	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1885	    "usbprn_testio: begin");
1886
1887	if ((err = usbprn_ioctl_get_status(usbprnp)) != 0) {
1888
1889		return (err);
1890	}
1891
1892	/* There is an error.  Return it to the user */
1893	mutex_enter(&usbprnp->usbprn_mutex);
1894
1895	if (usbprn_error_state(usbprnp->usbprn_last_status) != 0) {
1896		mutex_exit(&usbprnp->usbprn_mutex);
1897
1898		return (EIO);
1899
1900	} else {
1901		mutex_exit(&usbprnp->usbprn_mutex);
1902
1903		return (0);
1904	}
1905}
1906
1907
1908/*
1909 * usbprn_prnio_get_status:
1910 *	Execute the PRNIOC_GET_STATUS ioctl
1911 */
1912static int
1913usbprn_prnio_get_status(usbprn_state_t *usbprnp, intptr_t arg, int flag)
1914{
1915	uint_t	prnio_status = 0;
1916	int	err;
1917
1918	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1919	    "usbprn_prnio_get_status: begin");
1920
1921	/* capture printer status */
1922	err = usbprn_ioctl_get_status(usbprnp);
1923
1924	mutex_enter(&usbprnp->usbprn_mutex);
1925
1926	if (usbprnp->usbprn_dev_state == USB_DEV_ONLINE) {
1927		prnio_status |= PRN_ONLINE;
1928	}
1929	if ((err == 0) &&
1930	    (usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR)) {
1931		prnio_status |= PRN_READY;
1932	}
1933
1934	mutex_exit(&usbprnp->usbprn_mutex);
1935
1936	if (ddi_copyout(&prnio_status,
1937	    (caddr_t)arg, sizeof (prnio_status), flag)) {
1938
1939		return (EFAULT);
1940	}
1941
1942	return (0);
1943}
1944
1945
1946/*
1947 * usbprn_prnio_get_1284_status:
1948 *	Execute the PRNIOC_GET_1284_STATUS ioctl
1949 */
1950static int
1951usbprn_prnio_get_1284_status(usbprn_state_t *usbprnp, intptr_t arg, int flag)
1952{
1953	uchar_t		status;
1954	int		err;
1955
1956	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1957	    "usbprn_prnio_get_1284_status: begin");
1958
1959	if ((err = usbprn_ioctl_get_status(usbprnp)) != 0) {
1960
1961		return (err);
1962	}
1963
1964	/* status was captured successfully */
1965	mutex_enter(&usbprnp->usbprn_mutex);
1966
1967	status = usbprnp->usbprn_last_status & (USB_PRINTER_PORT_NO_ERROR |
1968	    USB_PRINTER_PORT_NO_SELECT | USB_PRINTER_PORT_EMPTY);
1969
1970	mutex_exit(&usbprnp->usbprn_mutex);
1971
1972	if (ddi_copyout(&status, (caddr_t)arg, sizeof (status), flag)) {
1973
1974		return (EFAULT);
1975	}
1976
1977	return (0);
1978}
1979
1980
1981/*
1982 * usbprn_prnio_get_ifcap:
1983 *	Execute the PRNIOC_GET_IFCAP ioctl
1984 */
1985/* ARGSUSED */
1986static int
1987usbprn_prnio_get_ifcap(usbprn_state_t *usbprnp, intptr_t arg, int flag)
1988{
1989	ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
1990
1991	if (ddi_copyout(&usbprn_ifcap, (caddr_t)arg, sizeof (usbprn_ifcap),
1992	    flag)) {
1993
1994		return (EFAULT);
1995	}
1996
1997	return (0);
1998}
1999
2000
2001/*
2002 * usbprn_prnio_get_ifcap:
2003 *	Execute the PRNIOC_SET_IFCAP ioctl
2004 */
2005/* ARGSUSED */
2006static int
2007usbprn_prnio_set_ifcap(usbprn_state_t *usbprnp, intptr_t arg, int flag)
2008{
2009	uint_t	new_ifcap;
2010
2011	ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
2012
2013	if (ddi_copyin((caddr_t)arg, &new_ifcap, sizeof (new_ifcap), flag)) {
2014
2015		return (EFAULT);
2016	}
2017
2018	/* no settable capabilities */
2019	if (usbprn_ifcap != new_ifcap) {
2020
2021		return (EINVAL);
2022	}
2023
2024	return (0);
2025}
2026
2027
2028/*
2029 * usbprn_prnio_get_ifinfo:
2030 *	Execute the PRNIOC_GET_IFINFO ioctl
2031 */
2032/* ARGSUSED */
2033static int
2034usbprn_prnio_get_ifinfo(usbprn_state_t *usbprnp, intptr_t arg, int flag)
2035{
2036	struct prn_interface_info	prn_info;
2037	int	rlen, len;
2038
2039	rlen = strlen(usbprn_prnio_ifinfo);
2040
2041#ifdef _MULTI_DATAMODEL
2042	ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
2043
2044	switch (ddi_model_convert_from(flag & FMODELS)) {
2045	case DDI_MODEL_ILP32: {
2046		struct prn_interface_info32	prn_info32;
2047
2048		if (ddi_copyin((caddr_t)arg, &prn_info32,
2049		    sizeof (struct prn_interface_info32), flag)) {
2050
2051			return (EFAULT);
2052		}
2053
2054		prn_info32.if_rlen = rlen;
2055		len = min(rlen, prn_info32.if_len);
2056
2057		if (ddi_copyout(&usbprn_prnio_ifinfo[0],
2058		    (caddr_t)(uintptr_t)prn_info32.if_data, len, flag)) {
2059
2060			return (EFAULT);
2061		}
2062
2063		if (ddi_copyout(&prn_info32, (caddr_t)arg,
2064		    sizeof (struct prn_interface_info32), flag)) {
2065
2066			return (EFAULT);
2067		}
2068
2069		break;
2070	}
2071	case DDI_MODEL_NONE:
2072#endif /* _MULTI_DATAMODEL */
2073		ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
2074
2075		if (ddi_copyin((caddr_t)arg, &prn_info,
2076		    sizeof (struct prn_interface_info), flag)) {
2077
2078			return (EFAULT);
2079		}
2080
2081		prn_info.if_rlen = rlen;
2082		len = min(rlen, prn_info.if_len);
2083
2084		if (ddi_copyout(&usbprn_prnio_ifinfo[0],
2085		    prn_info.if_data, len, flag)) {
2086
2087			return (EFAULT);
2088		}
2089
2090		if (ddi_copyout(&prn_info, (caddr_t)arg,
2091		    sizeof (struct prn_interface_info), flag)) {
2092
2093			return (EFAULT);
2094		}
2095#ifdef _MULTI_DATAMODEL
2096
2097		break;
2098	}
2099#endif /* _MULTI_DATAMODEL */
2100
2101	return (0);
2102}
2103
2104
2105/*
2106 * usbprn_prnio_getdevid:
2107 *	Execute the PRNIOC_GET_1284_DEVID ioctl
2108 */
2109static int
2110usbprn_prnio_get_1284_devid(usbprn_state_t *usbprnp, intptr_t arg, int flag)
2111{
2112	struct prn_1284_device_id prn_devid;
2113	int	len;
2114
2115	ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
2116
2117#ifdef _MULTI_DATAMODEL
2118	switch (ddi_model_convert_from(flag & FMODELS)) {
2119	case DDI_MODEL_ILP32: {
2120		struct prn_1284_device_id32	prn_devid32;
2121
2122		if (ddi_copyin((caddr_t)arg, &prn_devid32,
2123		    sizeof (struct prn_1284_device_id32), flag)) {
2124
2125			return (EFAULT);
2126		}
2127
2128		prn_devid32.id_rlen = usbprnp->usbprn_device_id_len - 2;
2129		len = min(prn_devid32.id_rlen, prn_devid32.id_len);
2130
2131		if (ddi_copyout(usbprnp->usbprn_device_id + 2,
2132		    (caddr_t)(uintptr_t)prn_devid32.id_data, len, flag)) {
2133
2134			return (EFAULT);
2135		}
2136
2137		if (ddi_copyout(&prn_devid32, (caddr_t)arg,
2138		    sizeof (struct prn_1284_device_id32), flag)) {
2139
2140			return (EFAULT);
2141		}
2142
2143		break;
2144	}
2145	case DDI_MODEL_NONE:
2146#endif /* _MULTI_DATAMODEL */
2147		if (ddi_copyin((caddr_t)arg, &prn_devid,
2148		    sizeof (struct prn_1284_device_id), flag)) {
2149
2150			return (EFAULT);
2151		}
2152
2153		prn_devid.id_rlen = usbprnp->usbprn_device_id_len - 2;
2154		len = min(prn_devid.id_rlen, prn_devid.id_len);
2155
2156		if (ddi_copyout(usbprnp->usbprn_device_id + 2,
2157		    prn_devid.id_data, len, flag)) {
2158
2159			return (EFAULT);
2160		}
2161
2162		if (ddi_copyout(&prn_devid, (caddr_t)arg,
2163		    sizeof (struct prn_1284_device_id), flag)) {
2164
2165			return (EFAULT);
2166		}
2167#ifdef _MULTI_DATAMODEL
2168
2169		break;
2170	}
2171#endif /* _MULTI_DATAMODEL */
2172
2173	return (0);
2174}
2175
2176
2177/*
2178 * usbprn_prnio_get_timeouts:
2179 *	Return timeout
2180 */
2181static int
2182usbprn_prnio_get_timeouts(usbprn_state_t *usbprnp, intptr_t arg, int flag)
2183{
2184	ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
2185
2186	if (ddi_copyout(&usbprnp->usbprn_prn_timeouts,
2187	    (caddr_t)arg, sizeof (struct prn_timeouts), flag)) {
2188
2189		return (EFAULT);
2190	}
2191
2192	return (0);
2193}
2194
2195
2196/*
2197 * usbprn_prnio_set_timeouts:
2198 *	Set write timeout and prn timeout
2199 */
2200static int
2201usbprn_prnio_set_timeouts(usbprn_state_t *usbprnp, intptr_t arg, int flag)
2202{
2203	struct prn_timeouts prn_timeouts;
2204
2205	ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
2206
2207	if (ddi_copyin((caddr_t)arg, &prn_timeouts,
2208	    sizeof (struct prn_timeouts), flag)) {
2209
2210		return (EFAULT);
2211	}
2212
2213	if ((prn_timeouts.tmo_forward < USBPRN_XFER_TIMEOUT_MIN) ||
2214	    (prn_timeouts.tmo_forward > USBPRN_XFER_TIMEOUT_MAX)) {
2215
2216		return (EINVAL);
2217	}
2218
2219	mutex_enter(&usbprnp->usbprn_mutex);
2220
2221	usbprnp->usbprn_prn_timeouts = prn_timeouts;
2222	usbprnp->usbprn_setparms.write_timeout = prn_timeouts.tmo_forward;
2223
2224	mutex_exit(&usbprnp->usbprn_mutex);
2225
2226	return (0);
2227}
2228
2229
2230/*
2231 * usbprn_biodone:
2232 *	If there is a bp, complete it
2233 */
2234static void
2235usbprn_biodone(usbprn_state_t *usbprnp, int err, int bytes_remaining)
2236{
2237	struct buf *bp = usbprnp->usbprn_bp;
2238	usbprn_ps_t	*bulk_out = &usbprnp->usbprn_bulk_out;
2239	usbprn_ps_t	*bulk_in = &usbprnp->usbprn_bulk_in;
2240
2241	ASSERT(mutex_owned(&usbprnp->usbprn_mutex));
2242
2243	/* all pipes must be idle now */
2244	ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
2245	ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
2246
2247	if (bp) {
2248		bp->b_resid = bytes_remaining;
2249
2250		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2251		    "usbprn_biodone: "
2252		    "bp=0x%p bcount=0x%lx resid=0x%lx remaining=0x%x err=%d",
2253		    (void *)bp, bp->b_bcount, bp->b_resid, bytes_remaining,
2254		    err);
2255
2256		if (err) {
2257			bioerror(bp, err);
2258		}
2259
2260		usbprnp->usbprn_bp = NULL;
2261		biodone(bp);
2262	}
2263
2264	/* release access */
2265	usb_release_access(usbprnp->usbprn_dev_acc);
2266}
2267
2268
2269/*
2270 * usbprn_send_async_bulk_data:
2271 *	Send bulk data down to the device through the bulk out pipe
2272 */
2273static void
2274usbprn_send_async_bulk_data(usbprn_state_t *usbprnp)
2275{
2276	int		rval;
2277	int		timeout;
2278	mblk_t		*mp;
2279	size_t		max_xfer_count, xfer_count;
2280	usbprn_ps_t	*bulk_out = &usbprnp->usbprn_bulk_out;
2281	usb_bulk_req_t *req;
2282
2283	mutex_enter(&usbprnp->usbprn_mutex);
2284	ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
2285
2286	timeout = usbprnp->usbprn_setparms.write_timeout;
2287	max_xfer_count = usbprnp->usbprn_bp->b_bcount;
2288	mp = usbprnp->usbprn_bulk_mp;
2289	ASSERT(mp != NULL);
2290	xfer_count = MBLKL(mp);
2291	mutex_exit(&usbprnp->usbprn_mutex);
2292
2293	req = usb_alloc_bulk_req(usbprnp->usbprn_dip, 0, USB_FLAGS_SLEEP);
2294	req->bulk_len		= (uint_t)xfer_count;
2295	req->bulk_data		= mp;
2296	req->bulk_timeout	= timeout;
2297	req->bulk_cb		= usbprn_bulk_xfer_cb;
2298	req->bulk_exc_cb	= usbprn_bulk_xfer_exc_cb;
2299	req->bulk_client_private = (usb_opaque_t)usbprnp;
2300	req->bulk_attributes	= USB_ATTRS_AUTOCLEARING;
2301
2302	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2303	    "usbprn_send_async_bulk_data: req = 0x%p "
2304	    "max_bulk_xfer_size=%lu mp=0x%p xfer_cnt=%lu timeout=%x",
2305	    (void *)req, max_xfer_count, (void *)mp, xfer_count, timeout);
2306
2307	ASSERT(xfer_count <= max_xfer_count);
2308
2309
2310	if ((rval = usb_pipe_bulk_xfer(bulk_out->ps_handle, req, 0)) !=
2311	    USB_SUCCESS) {
2312
2313		USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2314		    "usbprn_send_async_bulk_data: Bulk mp=0x%p "
2315		    "rval=%d", (void *)mp, rval);
2316
2317		mutex_enter(&usbprnp->usbprn_mutex);
2318		bulk_out->ps_flags = USBPRN_PS_IDLE;
2319		usbprnp->usbprn_bulk_mp = NULL;
2320		usbprn_biodone(usbprnp, EIO, 0);
2321		mutex_exit(&usbprnp->usbprn_mutex);
2322
2323		usb_free_bulk_req(req);
2324	} else {
2325		mutex_enter(&usbprnp->usbprn_mutex);
2326		usbprnp->usbprn_bulk_mp = NULL;
2327		mutex_exit(&usbprnp->usbprn_mutex);
2328	}
2329}
2330
2331
2332/*
2333 * usbprn_bulk_xfer_cb
2334 *	Callback for a normal transfer for both bulk pipes.
2335 */
2336/*ARGSUSED*/
2337static void
2338usbprn_bulk_xfer_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
2339{
2340	usbprn_state_t	*usbprnp = (usbprn_state_t *)req->bulk_client_private;
2341	usbprn_ps_t	*bulk_out = &usbprnp->usbprn_bulk_out;
2342
2343	ASSERT(usbprnp != NULL);
2344	ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
2345
2346	mutex_enter(&usbprnp->usbprn_mutex);
2347
2348	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2349	    "usbprn_bulk_xfer_cb: mp=0x%p ", (void *)usbprnp->usbprn_bulk_mp);
2350
2351	ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
2352	ASSERT(usbprnp->usbprn_bp != NULL);
2353	ASSERT((req->bulk_cb_flags & USB_CB_INTR_CONTEXT) == 0);
2354
2355	/*
2356	 * if device is disconnected or driver close called, return
2357	 * The pipe could be closed, or a timeout could have
2358	 * come in and the pipe is being reset.  If the
2359	 * state isn't transferring, then return
2360	 */
2361	if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp)) ||
2362	    (bulk_out->ps_flags != USBPRN_PS_NEED_TO_XFER)) {
2363		USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2364		    "usbprn_bulk_xfer_cb: no access or pipe closed");
2365
2366		bulk_out->ps_flags = USBPRN_PS_IDLE;
2367		usbprn_biodone(usbprnp, EIO, 0);
2368	} else {
2369
2370		/*
2371		 * data has been xferred, complete the bp.
2372		 */
2373		USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2374		    "usbprn_bulk_xfer_cb: transaction over");
2375
2376		bulk_out->ps_flags = USBPRN_PS_IDLE;
2377		usbprn_biodone(usbprnp, 0, 0);
2378	}
2379
2380	mutex_exit(&usbprnp->usbprn_mutex);
2381
2382	usb_free_bulk_req(req);
2383}
2384
2385
2386/*
2387 * usbprn_bulk_xfer_exc_cb:
2388 *	Exception callback for the bulk pipes
2389 */
2390static void
2391usbprn_bulk_xfer_exc_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
2392{
2393	usbprn_state_t	*usbprnp = (usbprn_state_t *)req->bulk_client_private;
2394	usbprn_ps_t	*bulk_out = &usbprnp->usbprn_bulk_out;
2395	int		bytes_remaining = 0;
2396	mblk_t		*data = req->bulk_data;
2397	usb_cr_t	completion_reason = req->bulk_completion_reason;
2398	usb_cb_flags_t	cb_flags = req->bulk_cb_flags;
2399
2400	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2401	    "usbprn_bulk_xfer_exc_cb: "
2402	    "pipe=0x%p req=0x%p cr=%d cb_flags=0x%x data=0x%p",
2403	    (void *)pipe, (void *)req, completion_reason, cb_flags,
2404	    (void *)data);
2405
2406	ASSERT((req->bulk_cb_flags & USB_CB_INTR_CONTEXT) == 0);
2407	ASSERT(data != NULL);
2408	mutex_enter(&usbprnp->usbprn_mutex);
2409
2410	ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
2411	bulk_out->ps_flags = USBPRN_PS_IDLE;
2412	bulk_out->ps_cr = completion_reason;
2413
2414	if (data) {
2415		bytes_remaining = MBLKL(data);
2416	}
2417
2418	/*
2419	 * If the pipe is closed or device not responding or not in
2420	 * need of transfer, just give up on this bp.
2421	 */
2422	if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp)) ||
2423	    (req->bulk_completion_reason == USB_CR_DEV_NOT_RESP)) {
2424		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2425		    "usbprn_bulk_xfer_exc_cb: "
2426		    "device not accesible or wrong state");
2427		usbprn_biodone(usbprnp, EIO, 0);
2428	} else {
2429		if (completion_reason == USB_CR_TIMEOUT) {
2430			USB_DPRINTF_L2(PRINT_MASK_ALL,
2431			    usbprnp->usbprn_log_handle,
2432			    "usbprn_bulk_xfer_exc_cb: timeout error, "
2433			    "xferred %lu bytes",
2434			    ((usbprnp->usbprn_bp->b_bcount) -
2435			    bytes_remaining));
2436			usbprn_biodone(usbprnp, 0, bytes_remaining);
2437		} else {
2438			usbprn_biodone(usbprnp, EIO, 0);
2439		}
2440
2441	}
2442
2443	mutex_exit(&usbprnp->usbprn_mutex);
2444
2445	usb_free_bulk_req(req);
2446}
2447
2448
2449/*
2450 * usbprn_reconnect_event_cb:
2451 *	Called upon when the device is hotplugged back; event handling
2452 */
2453/*ARGSUSED*/
2454static int
2455usbprn_reconnect_event_cb(dev_info_t *dip)
2456{
2457	usbprn_state_t	*usbprnp =
2458	    (usbprn_state_t *)ddi_get_soft_state(usbprn_statep,
2459	    ddi_get_instance(dip));
2460
2461	ASSERT(usbprnp != NULL);
2462
2463	USB_DPRINTF_L3(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
2464	    "usbprn_reconnect_event_cb:");
2465
2466	(void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
2467
2468	mutex_enter(&usbprnp->usbprn_mutex);
2469	ASSERT(usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED);
2470
2471	mutex_exit(&usbprnp->usbprn_mutex);
2472
2473	usbprn_restore_device_state(dip, usbprnp);
2474
2475	if (usbprnp->usbprn_ugen_hdl) {
2476		(void) usb_ugen_reconnect_ev_cb(usbprnp->usbprn_ugen_hdl);
2477	}
2478
2479	usb_release_access(usbprnp->usbprn_ser_acc);
2480
2481	return (USB_SUCCESS);
2482}
2483
2484
2485/*
2486 * usbprn_disconnect_event_cb:
2487 *	callback for disconnect events
2488 */
2489/*ARGSUSED*/
2490static int
2491usbprn_disconnect_event_cb(dev_info_t *dip)
2492{
2493	usbprn_state_t	*usbprnp = (usbprn_state_t *)ddi_get_soft_state(
2494	    usbprn_statep, ddi_get_instance(dip));
2495
2496	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2497	    "usbprn_disconnect_event_cb: Begin");
2498
2499	(void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
2500
2501	mutex_enter(&usbprnp->usbprn_mutex);
2502	usbprnp->usbprn_dev_state = USB_DEV_DISCONNECTED;
2503
2504	if (usbprnp->usbprn_flags & USBPRN_OPEN) {
2505		USB_DPRINTF_L0(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
2506		    "device was disconnected while open. "
2507		    "Data may have been lost");
2508	}
2509
2510	/* For now, we set the offline bit in usbprn_last_status */
2511	usbprnp->usbprn_last_status |= USB_PRINTER_PORT_NO_SELECT;
2512
2513	mutex_exit(&usbprnp->usbprn_mutex);
2514
2515	if (usbprnp->usbprn_ugen_hdl) {
2516		(void) usb_ugen_disconnect_ev_cb(usbprnp->usbprn_ugen_hdl);
2517	}
2518
2519	usb_release_access(usbprnp->usbprn_ser_acc);
2520
2521	USB_DPRINTF_L4(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
2522	    "usbprn_disconnect_event_cb: End");
2523
2524	return (USB_SUCCESS);
2525}
2526
2527
2528/*
2529 * usbprn_restore_device_state:
2530 *	set original configuration of the device
2531 *	Restores data xfer
2532 */
2533static void
2534usbprn_restore_device_state(dev_info_t *dip, usbprn_state_t *usbprnp)
2535{
2536	int alt, rval, iface;
2537
2538	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2539	    "usbprn_restore_device_state:");
2540
2541	mutex_enter(&usbprnp->usbprn_mutex);
2542	ASSERT((usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED) ||
2543	    (usbprnp->usbprn_dev_state == USB_DEV_SUSPENDED));
2544
2545	mutex_exit(&usbprnp->usbprn_mutex);
2546
2547	/* Check if we are talking to the same device */
2548	if (usb_check_same_device(dip, usbprnp->usbprn_log_handle,
2549	    USB_LOG_L0, PRINT_MASK_ALL,
2550	    USB_CHK_ALL, NULL) != USB_SUCCESS) {
2551
2552		/* change the device state from suspended to disconnected */
2553		mutex_enter(&usbprnp->usbprn_mutex);
2554		usbprnp->usbprn_dev_state = USB_DEV_DISCONNECTED;
2555		mutex_exit(&usbprnp->usbprn_mutex);
2556
2557		return;
2558	}
2559
2560	USB_DPRINTF_L0(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2561	    "Printer has been reconnected but data may have been lost");
2562
2563	mutex_enter(&usbprnp->usbprn_mutex);
2564
2565	/* set last status to online */
2566	usbprnp->usbprn_last_status &= ~USB_PRINTER_PORT_NO_SELECT;
2567	mutex_exit(&usbprnp->usbprn_mutex);
2568
2569	/* Get the port status */
2570	if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
2571		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
2572		    "usbprn_restore_device_state: port status failed");
2573
2574		return;
2575	}
2576
2577	mutex_enter(&usbprnp->usbprn_mutex);
2578
2579	if ((usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR) == 0) {
2580		USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2581		    "usbprn_restore_device_state: An error with the printer");
2582	}
2583
2584	if (usbprnp->usbprn_flags & USBPRN_OPEN) {
2585		mutex_exit(&usbprnp->usbprn_mutex);
2586		usbprn_close_usb_pipes(usbprnp);
2587		mutex_enter(&usbprnp->usbprn_mutex);
2588	}
2589
2590	/* restore alternate */
2591	alt = usbprnp->usbprn_if_descr.bAlternateSetting,
2592	    mutex_exit(&usbprnp->usbprn_mutex);
2593
2594	iface = usb_owns_device(dip) ? 0 :  usb_get_if_number(dip);
2595	if ((rval = usb_set_alt_if(dip, iface, alt,
2596	    USB_FLAGS_SLEEP, NULL, NULL)) != USB_SUCCESS) {
2597		USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
2598		    "usbprn_restore_device_state: set alternate failed (%d)",
2599		    rval);
2600
2601		return;
2602	}
2603
2604	mutex_enter(&usbprnp->usbprn_mutex);
2605
2606	if (usbprnp->usbprn_flags & USBPRN_OPEN) {
2607
2608		mutex_exit(&usbprnp->usbprn_mutex);
2609		(void) usbprn_open_usb_pipes(usbprnp);
2610		mutex_enter(&usbprnp->usbprn_mutex);
2611	}
2612
2613	if (usbprnp->usbprn_pm && usbprnp->usbprn_pm->usbprn_wakeup_enabled) {
2614		mutex_exit(&usbprnp->usbprn_mutex);
2615		(void) usb_handle_remote_wakeup(usbprnp->usbprn_dip,
2616		    USB_REMOTE_WAKEUP_ENABLE);
2617		mutex_enter(&usbprnp->usbprn_mutex);
2618	}
2619
2620	usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
2621	mutex_exit(&usbprnp->usbprn_mutex);
2622
2623	USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2624	    "usbprn_restore_device_state: End");
2625}
2626
2627
2628/*
2629 *	Create power managements components
2630 */
2631static void
2632usbprn_create_pm_components(dev_info_t *dip, usbprn_state_t *usbprnp)
2633{
2634	usbprn_power_t	*usbprnpm;
2635	uint_t		pwr_states;
2636
2637	USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2638	    "usbprn_create_pm_components: Begin");
2639
2640	/* Allocate the state structure */
2641	usbprnpm = kmem_zalloc(sizeof (usbprn_power_t),
2642	    KM_SLEEP);
2643	usbprnp->usbprn_pm = usbprnpm;
2644	usbprnpm->usbprn_pm_capabilities = 0;
2645	usbprnpm->usbprn_current_power = USB_DEV_OS_FULL_PWR;
2646
2647	if (usb_create_pm_components(dip, &pwr_states) ==
2648	    USB_SUCCESS) {
2649		USB_DPRINTF_L4(PRINT_MASK_PM,
2650		    usbprnp->usbprn_log_handle,
2651		    "usbprn_create_pm_components: "
2652		    "created PM components");
2653
2654		if (usb_handle_remote_wakeup(dip,
2655		    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
2656			usbprnpm->usbprn_wakeup_enabled = 1;
2657		}
2658		usbprnpm->usbprn_pwr_states = (uint8_t)pwr_states;
2659		(void) pm_raise_power(usbprnp->usbprn_dip, 0,
2660		    USB_DEV_OS_FULL_PWR);
2661	} else {
2662		USB_DPRINTF_L2(PRINT_MASK_PM,
2663		    usbprnp->usbprn_log_handle,
2664		    "usbprn_create_pm_components: Failed");
2665	}
2666
2667	USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2668	    "usbprn_create_pm_components: END");
2669}
2670
2671
2672/*
2673 * usbprn_pwrlvl0:
2674 * Functions to handle power transition for OS levels 0 -> 3
2675 */
2676static int
2677usbprn_pwrlvl0(usbprn_state_t *usbprnp)
2678{
2679	int	rval;
2680
2681	USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2682	    "usbprn_pwrlvl0:");
2683
2684	switch (usbprnp->usbprn_dev_state) {
2685	case USB_DEV_ONLINE:
2686		/* Deny the powerdown request if the device is busy */
2687		if (usbprnp->usbprn_pm->usbprn_pm_busy != 0) {
2688
2689			return (USB_FAILURE);
2690		}
2691
2692		/* Issue USB D3 command to the device here */
2693		rval = usb_set_device_pwrlvl3(usbprnp->usbprn_dip);
2694		ASSERT(rval == USB_SUCCESS);
2695
2696		usbprnp->usbprn_dev_state = USB_DEV_PWRED_DOWN;
2697		usbprnp->usbprn_pm->usbprn_current_power =
2698		    USB_DEV_OS_PWR_OFF;
2699		/* FALLTHRU */
2700	case USB_DEV_DISCONNECTED:
2701	case USB_DEV_SUSPENDED:
2702		/* allow a disconnect/cpr'ed device to go to lower power */
2703
2704		return (USB_SUCCESS);
2705	case USB_DEV_PWRED_DOWN:
2706	default:
2707		USB_DPRINTF_L2(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2708		    "usbprn_pwrlvl0: illegal dev state");
2709
2710		return (USB_FAILURE);
2711	}
2712}
2713
2714
2715/*
2716 * usbprn_pwrlvl1:
2717 *	Functions to handle power transition to OS levels -> 2
2718 */
2719static int
2720usbprn_pwrlvl1(usbprn_state_t *usbprnp)
2721{
2722	int	rval;
2723
2724	USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2725	    "usbprn_pwrlvl1:");
2726
2727	/* Issue USB D2 command to the device here */
2728	rval = usb_set_device_pwrlvl2(usbprnp->usbprn_dip);
2729	ASSERT(rval == USB_SUCCESS);
2730
2731	return (USB_FAILURE);
2732}
2733
2734
2735/*
2736 * usbprn_pwrlvl2:
2737 *	Functions to handle power transition to OS levels -> 1
2738 */
2739static int
2740usbprn_pwrlvl2(usbprn_state_t *usbprnp)
2741{
2742	int	rval;
2743
2744	USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2745	    "usbprn_pwrlvl2:");
2746
2747	/* Issue USB D1 command to the device here */
2748	rval = usb_set_device_pwrlvl1(usbprnp->usbprn_dip);
2749	ASSERT(rval == USB_SUCCESS);
2750
2751	return (USB_FAILURE);
2752}
2753
2754
2755/*
2756 * usbprn_pwrlvl3:
2757 *	Functions to handle power transition to OS level -> 0
2758 */
2759static int
2760usbprn_pwrlvl3(usbprn_state_t *usbprnp)
2761{
2762	USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2763	    "usbprn_pwrlvl3:");
2764
2765	switch (usbprnp->usbprn_dev_state) {
2766	case USB_DEV_PWRED_DOWN:
2767		/* Issue USB D0 command to the device here */
2768		(void) usb_set_device_pwrlvl0(usbprnp->usbprn_dip);
2769
2770		usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
2771		usbprnp->usbprn_pm->usbprn_current_power =
2772		    USB_DEV_OS_FULL_PWR;
2773
2774		/* FALLTHRU */
2775	case USB_DEV_ONLINE:
2776		/* we are already in full power */
2777		/* FALLTHRU */
2778	case USB_DEV_DISCONNECTED:
2779	case USB_DEV_SUSPENDED:
2780		/*
2781		 * PM framework tries to put us in full power
2782		 * during system shutdown. If we are disconnected/cpr'ed
2783		 * return success anyways
2784		 */
2785
2786		return (USB_SUCCESS);
2787	default:
2788		USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2789		    "usbprn_pwrlvl3:");
2790
2791
2792		return (USB_FAILURE);
2793	}
2794}
2795
2796
2797/*
2798 * usbprn_power :
2799 *	Power entry point
2800 */
2801/* ARGSUSED */
2802static int
2803usbprn_power(dev_info_t *dip, int comp, int level)
2804{
2805	usbprn_state_t	*usbprnp;
2806	usbprn_power_t	*pm;
2807	int		rval = USB_FAILURE;
2808
2809	usbprnp = (usbprn_state_t *)ddi_get_soft_state(usbprn_statep,
2810	    ddi_get_instance(dip));
2811
2812	USB_DPRINTF_L3(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2813	    "usbprn_power: Begin: level=%d", level);
2814
2815	(void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
2816
2817	mutex_enter(&usbprnp->usbprn_mutex);
2818	pm = usbprnp->usbprn_pm;
2819	ASSERT(pm != NULL);
2820
2821	/* Check if we are transitioning to a legal power level */
2822	if (USB_DEV_PWRSTATE_OK(pm->usbprn_pwr_states, level)) {
2823		USB_DPRINTF_L2(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
2824		    "usbprn_power: illegal power level=%d "
2825		    "pwr_states=0x%x", level, pm->usbprn_pwr_states);
2826
2827		goto done;
2828	}
2829
2830	switch (level) {
2831	case USB_DEV_OS_PWR_OFF :
2832		rval = usbprn_pwrlvl0(usbprnp);
2833
2834		break;
2835	case USB_DEV_OS_PWR_1 :
2836		rval = usbprn_pwrlvl1(usbprnp);
2837
2838		break;
2839	case USB_DEV_OS_PWR_2 :
2840		rval = usbprn_pwrlvl2(usbprnp);
2841
2842		break;
2843	case USB_DEV_OS_FULL_PWR :
2844		rval = usbprn_pwrlvl3(usbprnp);
2845
2846		break;
2847	}
2848
2849done:
2850	mutex_exit(&usbprnp->usbprn_mutex);
2851
2852	usb_release_access(usbprnp->usbprn_ser_acc);
2853
2854	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
2855}
2856
2857
2858/*
2859 * usbprn_print_long:
2860 *	Breakup a string which is > USBPRN_PRINT_MAXLINE and print it
2861 */
2862static void
2863usbprn_print_long(usbprn_state_t *usbprnp, char *str, int len)
2864{
2865	char *tmp = str;
2866	char pbuf[USBPRN_PRINT_MAXLINE];
2867
2868	for (;;) {
2869		if (len <= USBPRN_PRINT_MAXLINE) {
2870			USB_DPRINTF_L4(PRINT_MASK_ATTA,
2871			    usbprnp->usbprn_log_handle, "%s", tmp);
2872
2873			break;
2874		} else {
2875			bcopy(tmp, pbuf, USBPRN_PRINT_MAXLINE);
2876			USB_DPRINTF_L4(PRINT_MASK_ATTA,
2877			    usbprnp->usbprn_log_handle, "%s", pbuf);
2878			tmp += USBPRN_PRINT_MAXLINE;
2879			len -= USBPRN_PRINT_MAXLINE;
2880		}
2881	}
2882}
2883
2884
2885static void
2886usbprn_pm_busy_component(usbprn_state_t *usbprn_statep)
2887{
2888	ASSERT(!mutex_owned(&usbprn_statep->usbprn_mutex));
2889	if (usbprn_statep->usbprn_pm != NULL) {
2890		mutex_enter(&usbprn_statep->usbprn_mutex);
2891		usbprn_statep->usbprn_pm->usbprn_pm_busy++;
2892
2893		USB_DPRINTF_L4(PRINT_MASK_PM, usbprn_statep->usbprn_log_handle,
2894		    "usbprn_pm_busy_component: %d",
2895		    usbprn_statep->usbprn_pm->usbprn_pm_busy);
2896
2897		mutex_exit(&usbprn_statep->usbprn_mutex);
2898
2899		if (pm_busy_component(usbprn_statep->usbprn_dip, 0) !=
2900		    DDI_SUCCESS) {
2901			mutex_enter(&usbprn_statep->usbprn_mutex);
2902			usbprn_statep->usbprn_pm->usbprn_pm_busy--;
2903
2904			USB_DPRINTF_L2(PRINT_MASK_PM,
2905			    usbprn_statep->usbprn_log_handle,
2906			    "usbprn_pm_busy_component: %d",
2907			    usbprn_statep->usbprn_pm->usbprn_pm_busy);
2908
2909			mutex_exit(&usbprn_statep->usbprn_mutex);
2910		}
2911
2912	}
2913}
2914
2915
2916static void
2917usbprn_pm_idle_component(usbprn_state_t *usbprn_statep)
2918{
2919	ASSERT(!mutex_owned(&usbprn_statep->usbprn_mutex));
2920	if (usbprn_statep->usbprn_pm != NULL) {
2921		if (pm_idle_component(usbprn_statep->usbprn_dip, 0) ==
2922		    DDI_SUCCESS) {
2923			mutex_enter(&usbprn_statep->usbprn_mutex);
2924			ASSERT(usbprn_statep->usbprn_pm->usbprn_pm_busy > 0);
2925			usbprn_statep->usbprn_pm->usbprn_pm_busy--;
2926
2927			USB_DPRINTF_L4(PRINT_MASK_PM,
2928			    usbprn_statep->usbprn_log_handle,
2929			    "usbprn_pm_idle_component: %d",
2930			    usbprn_statep->usbprn_pm->usbprn_pm_busy);
2931
2932			mutex_exit(&usbprn_statep->usbprn_mutex);
2933		}
2934
2935	}
2936}
2937