10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56898Sfb209375 * Common Development and Distribution License (the "License").
66898Sfb209375 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate *
21*8688SRaymond.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
220Sstevel@tonic-gate * Use is subject to license terms.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Printer Class Driver for USB
280Sstevel@tonic-gate *
290Sstevel@tonic-gate * This driver supports devices that adhere to the USB Printer Class
300Sstevel@tonic-gate * specification 1.0.
310Sstevel@tonic-gate *
320Sstevel@tonic-gate * NOTE: This driver is not DDI compliant in that it uses undocumented
330Sstevel@tonic-gate * functions for logging (USB_DPRINTF_L*, usb_alloc_log_hdl, usb_free_log_hdl),
340Sstevel@tonic-gate * and serialization (usb_serialize_access, usb_release_access,
350Sstevel@tonic-gate * usb_init_serialization, usb_fini_serialization)
360Sstevel@tonic-gate *
370Sstevel@tonic-gate * Undocumented functions may go away in a future Solaris OS release.
380Sstevel@tonic-gate *
390Sstevel@tonic-gate * Please see the DDK for sample code of these functions, and for the usbskel
400Sstevel@tonic-gate * skeleton template driver which contains scaled-down versions of these
410Sstevel@tonic-gate * functions written in a DDI-compliant way.
420Sstevel@tonic-gate */
430Sstevel@tonic-gate
440Sstevel@tonic-gate #if defined(lint) && !defined(DEBUG)
450Sstevel@tonic-gate #define DEBUG
460Sstevel@tonic-gate #endif
470Sstevel@tonic-gate #ifdef __lock_lint
480Sstevel@tonic-gate #define _MULTI_DATAMODEL
490Sstevel@tonic-gate #endif
500Sstevel@tonic-gate
510Sstevel@tonic-gate #define USBDRV_MAJOR_VER 2
520Sstevel@tonic-gate #define USBDRV_MINOR_VER 0
530Sstevel@tonic-gate
540Sstevel@tonic-gate #include <sys/usb/usba.h>
550Sstevel@tonic-gate #include <sys/usb/usba/usba_ugen.h>
560Sstevel@tonic-gate #include <sys/bpp_io.h>
570Sstevel@tonic-gate #include <sys/ecppsys.h>
580Sstevel@tonic-gate #include <sys/prnio.h>
590Sstevel@tonic-gate #include <sys/errno.h>
600Sstevel@tonic-gate #include <sys/usb/clients/printer/usb_printer.h>
610Sstevel@tonic-gate #include <sys/usb/clients/printer/usbprn.h>
627492SZhigang.Lu@Sun.COM #include <sys/strsun.h>
630Sstevel@tonic-gate
640Sstevel@tonic-gate /* Debugging support */
65880Sfrits uint_t usbprn_errmask = (uint_t)PRINT_MASK_ALL;
66880Sfrits uint_t usbprn_errlevel = USB_LOG_L4;
67880Sfrits uint_t usbprn_instance_debug = (uint_t)-1;
680Sstevel@tonic-gate
690Sstevel@tonic-gate /* local variables */
700Sstevel@tonic-gate static uint_t usbprn_ifcap =
710Sstevel@tonic-gate PRN_HOTPLUG | PRN_1284_DEVID | PRN_1284_STATUS | PRN_TIMEOUTS;
720Sstevel@tonic-gate
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate * Function Prototypes
750Sstevel@tonic-gate */
760Sstevel@tonic-gate static int usbprn_attach(dev_info_t *, ddi_attach_cmd_t);
770Sstevel@tonic-gate static int usbprn_detach(dev_info_t *, ddi_detach_cmd_t);
780Sstevel@tonic-gate static int usbprn_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
790Sstevel@tonic-gate static void usbprn_cleanup(dev_info_t *, usbprn_state_t *);
800Sstevel@tonic-gate
810Sstevel@tonic-gate static int usbprn_get_descriptors(usbprn_state_t *);
820Sstevel@tonic-gate static int usbprn_get_device_id(usbprn_state_t *);
830Sstevel@tonic-gate static int usbprn_get_port_status(usbprn_state_t *);
840Sstevel@tonic-gate
850Sstevel@tonic-gate static int usbprn_open(dev_t *, int, int, cred_t *);
860Sstevel@tonic-gate static int usbprn_close(dev_t, int, int, cred_t *);
870Sstevel@tonic-gate static int usbprn_open_usb_pipes(usbprn_state_t *);
880Sstevel@tonic-gate static void usbprn_close_usb_pipes(usbprn_state_t *);
890Sstevel@tonic-gate static int usbprn_write(dev_t, struct uio *, cred_t *);
900Sstevel@tonic-gate static int usbprn_read(dev_t, struct uio *, cred_t *);
910Sstevel@tonic-gate static int usbprn_poll(dev_t, short, int, short *, struct pollhead **);
920Sstevel@tonic-gate
930Sstevel@tonic-gate static int usbprn_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
940Sstevel@tonic-gate static void usbprn_minphys(struct buf *);
950Sstevel@tonic-gate static int usbprn_strategy(struct buf *);
960Sstevel@tonic-gate static int usbprn_setparms(usbprn_state_t *, intptr_t arg, int);
970Sstevel@tonic-gate static int usbprn_getparms(usbprn_state_t *, intptr_t, int);
980Sstevel@tonic-gate static void usbprn_geterr(usbprn_state_t *, intptr_t, int);
990Sstevel@tonic-gate static int usbprn_testio(usbprn_state_t *, int);
1000Sstevel@tonic-gate static int usbprn_ioctl_get_status(usbprn_state_t *);
1010Sstevel@tonic-gate static int usbprn_prnio_get_status(usbprn_state_t *, intptr_t, int);
1020Sstevel@tonic-gate static int usbprn_prnio_get_1284_status(usbprn_state_t *, intptr_t, int);
1030Sstevel@tonic-gate static int usbprn_prnio_get_ifcap(usbprn_state_t *, intptr_t, int);
1040Sstevel@tonic-gate static int usbprn_prnio_set_ifcap(usbprn_state_t *, intptr_t, int);
1050Sstevel@tonic-gate static int usbprn_prnio_get_ifinfo(usbprn_state_t *, intptr_t, int);
1060Sstevel@tonic-gate static int usbprn_prnio_get_1284_devid(usbprn_state_t *, intptr_t, int);
1070Sstevel@tonic-gate static int usbprn_prnio_get_timeouts(usbprn_state_t *, intptr_t, int);
1080Sstevel@tonic-gate static int usbprn_prnio_set_timeouts(usbprn_state_t *, intptr_t, int);
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate static void usbprn_send_async_bulk_data(usbprn_state_t *);
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate static void usbprn_bulk_xfer_cb(usb_pipe_handle_t, usb_bulk_req_t *);
1130Sstevel@tonic-gate static void usbprn_bulk_xfer_exc_cb(usb_pipe_handle_t,
1140Sstevel@tonic-gate usb_bulk_req_t *);
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate static void usbprn_biodone(usbprn_state_t *, int, int);
1170Sstevel@tonic-gate static char usbprn_error_state(uchar_t);
1180Sstevel@tonic-gate static void usbprn_print_long(usbprn_state_t *, char *, int);
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate /* event handling */
1210Sstevel@tonic-gate static void usbprn_restore_device_state(dev_info_t *, usbprn_state_t *);
1220Sstevel@tonic-gate static int usbprn_disconnect_event_cb(dev_info_t *);
1230Sstevel@tonic-gate static int usbprn_reconnect_event_cb(dev_info_t *);
1240Sstevel@tonic-gate static int usbprn_cpr_suspend(dev_info_t *);
1250Sstevel@tonic-gate static void usbprn_cpr_resume(dev_info_t *);
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate static usb_event_t usbprn_events = {
1280Sstevel@tonic-gate usbprn_disconnect_event_cb,
1290Sstevel@tonic-gate usbprn_reconnect_event_cb,
1300Sstevel@tonic-gate NULL, NULL
1310Sstevel@tonic-gate };
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate /* PM handling */
1340Sstevel@tonic-gate static void usbprn_create_pm_components(dev_info_t *, usbprn_state_t *);
1350Sstevel@tonic-gate static int usbprn_power(dev_info_t *, int comp, int level);
1360Sstevel@tonic-gate static int usbprn_pwrlvl0(usbprn_state_t *);
1370Sstevel@tonic-gate static int usbprn_pwrlvl1(usbprn_state_t *);
1380Sstevel@tonic-gate static int usbprn_pwrlvl2(usbprn_state_t *);
1390Sstevel@tonic-gate static int usbprn_pwrlvl3(usbprn_state_t *);
1400Sstevel@tonic-gate static void usbprn_pm_busy_component(usbprn_state_t *);
1410Sstevel@tonic-gate static void usbprn_pm_idle_component(usbprn_state_t *);
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* module loading stuff */
1440Sstevel@tonic-gate struct cb_ops usbprn_cb_ops = {
1450Sstevel@tonic-gate usbprn_open, /* open */
1460Sstevel@tonic-gate usbprn_close, /* close */
1470Sstevel@tonic-gate nulldev, /* strategy */
1480Sstevel@tonic-gate nulldev, /* print */
1490Sstevel@tonic-gate nulldev, /* dump */
1500Sstevel@tonic-gate usbprn_read, /* read */
1510Sstevel@tonic-gate usbprn_write, /* write */
1520Sstevel@tonic-gate usbprn_ioctl, /* ioctl */
1530Sstevel@tonic-gate nulldev, /* devmap */
1540Sstevel@tonic-gate nulldev, /* mmap */
1550Sstevel@tonic-gate nulldev, /* segmap */
1560Sstevel@tonic-gate usbprn_poll, /* poll */
1570Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */
1580Sstevel@tonic-gate NULL, /* streamtab */
1590Sstevel@tonic-gate D_64BIT | D_MP
1600Sstevel@tonic-gate };
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate static struct dev_ops usbprn_ops = {
1630Sstevel@tonic-gate DEVO_REV, /* devo_rev, */
1640Sstevel@tonic-gate 0, /* refcnt */
1650Sstevel@tonic-gate usbprn_info, /* info */
1660Sstevel@tonic-gate nulldev, /* identify */
1670Sstevel@tonic-gate nulldev, /* probe */
1680Sstevel@tonic-gate usbprn_attach, /* attach */
1690Sstevel@tonic-gate usbprn_detach, /* detach */
1700Sstevel@tonic-gate nodev, /* reset */
1710Sstevel@tonic-gate &usbprn_cb_ops, /* driver operations */
1720Sstevel@tonic-gate NULL, /* bus operations */
1737656SSherry.Moore@Sun.COM usbprn_power, /* power */
174*8688SRaymond.Chen@Sun.COM ddi_quiesce_not_needed, /* devo_quiesce */
1750Sstevel@tonic-gate };
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate static struct modldrv usbprnmodldrv = {
1780Sstevel@tonic-gate &mod_driverops,
1797425SGongtian.Zhao@Sun.COM "USB printer client driver",
1800Sstevel@tonic-gate &usbprn_ops
1810Sstevel@tonic-gate };
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate static struct modlinkage modlinkage = {
1840Sstevel@tonic-gate MODREV_1,
1850Sstevel@tonic-gate &usbprnmodldrv,
1860Sstevel@tonic-gate NULL,
1870Sstevel@tonic-gate };
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate /* local variables */
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /* soft state structures */
1920Sstevel@tonic-gate #define USBPRN_INITIAL_SOFT_SPACE 1
1930Sstevel@tonic-gate static void *usbprn_statep;
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate static int usbprn_max_xfer_size = USBPRN_MAX_XFER_SIZE;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate /* prnio support */
1980Sstevel@tonic-gate static const char usbprn_prnio_ifinfo[] = PRN_USB;
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate int
_init(void)2020Sstevel@tonic-gate _init(void)
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate int rval;
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate if ((rval = ddi_soft_state_init(&usbprn_statep,
2070Sstevel@tonic-gate sizeof (usbprn_state_t), USBPRN_INITIAL_SOFT_SPACE)) != 0) {
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate return (rval);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate if ((rval = mod_install(&modlinkage)) != 0) {
2130Sstevel@tonic-gate ddi_soft_state_fini(&usbprn_statep);
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate return (rval);
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate int
_fini(void)2210Sstevel@tonic-gate _fini(void)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate int rval;
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate if ((rval = mod_remove(&modlinkage)) != 0) {
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate return (rval);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate ddi_soft_state_fini(&usbprn_statep);
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate return (rval);
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2370Sstevel@tonic-gate _info(struct modinfo *modinfop)
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate /*
2440Sstevel@tonic-gate * usbprn_info:
2450Sstevel@tonic-gate * Get minor number, soft state structure, etc.
2460Sstevel@tonic-gate */
2470Sstevel@tonic-gate /*ARGSUSED*/
2480Sstevel@tonic-gate static int
usbprn_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)2490Sstevel@tonic-gate usbprn_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
2500Sstevel@tonic-gate void *arg, void **result)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate usbprn_state_t *usbprnp;
2530Sstevel@tonic-gate int error = DDI_FAILURE;
2540Sstevel@tonic-gate minor_t minor = getminor((dev_t)arg);
2550Sstevel@tonic-gate int instance = USBPRN_MINOR_TO_INSTANCE(minor);
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate switch (infocmd) {
2580Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO:
2590Sstevel@tonic-gate if ((usbprnp = ddi_get_soft_state(usbprn_statep,
2600Sstevel@tonic-gate instance)) != NULL) {
2610Sstevel@tonic-gate *result = usbprnp->usbprn_dip;
2620Sstevel@tonic-gate if (*result != NULL) {
2630Sstevel@tonic-gate error = DDI_SUCCESS;
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate } else {
2660Sstevel@tonic-gate *result = NULL;
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate break;
2700Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE:
2710Sstevel@tonic-gate *result = (void *)(uintptr_t)instance;
2720Sstevel@tonic-gate error = DDI_SUCCESS;
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate break;
2750Sstevel@tonic-gate default:
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate break;
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate return (error);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate /*
2850Sstevel@tonic-gate * usbprn_attach:
2860Sstevel@tonic-gate * Attach driver
2870Sstevel@tonic-gate * Get the descriptor information
2880Sstevel@tonic-gate * Get the device id
2890Sstevel@tonic-gate * Reset the device
2900Sstevel@tonic-gate * Get the port status
2910Sstevel@tonic-gate */
2920Sstevel@tonic-gate static int
usbprn_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2930Sstevel@tonic-gate usbprn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2940Sstevel@tonic-gate {
2950Sstevel@tonic-gate int instance = ddi_get_instance(dip);
2960Sstevel@tonic-gate usbprn_state_t *usbprnp = NULL;
2970Sstevel@tonic-gate size_t sz;
2980Sstevel@tonic-gate usb_ugen_info_t usb_ugen_info;
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate switch (cmd) {
3010Sstevel@tonic-gate case DDI_ATTACH:
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate break;
3040Sstevel@tonic-gate case DDI_RESUME:
3050Sstevel@tonic-gate usbprn_cpr_resume(dip);
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate return (DDI_SUCCESS);
3080Sstevel@tonic-gate default:
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate return (DDI_FAILURE);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate if (ddi_soft_state_zalloc(usbprn_statep, instance) == DDI_SUCCESS) {
3140Sstevel@tonic-gate usbprnp = ddi_get_soft_state(usbprn_statep, instance);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate if (usbprnp == NULL) {
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate return (DDI_FAILURE);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate usbprnp->usbprn_instance = instance;
3220Sstevel@tonic-gate usbprnp->usbprn_dip = dip;
3230Sstevel@tonic-gate usbprnp->usbprn_log_handle = usb_alloc_log_hdl(dip,
3246898Sfb209375 "prn", &usbprn_errlevel,
3256898Sfb209375 &usbprn_errmask, &usbprn_instance_debug, 0);
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3280Sstevel@tonic-gate "usbprn_attach: cmd=%x", cmd);
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
3310Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3320Sstevel@tonic-gate "usb_client_attach failed");
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate goto fail;
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate if (usb_get_dev_data(dip, &usbprnp->usbprn_dev_data,
3370Sstevel@tonic-gate USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
3380Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3390Sstevel@tonic-gate "usb_get_dev_data failed");
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate goto fail;
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /* Initialize locks and conditional variables */
3450Sstevel@tonic-gate mutex_init(&usbprnp->usbprn_mutex, NULL, MUTEX_DRIVER,
3466898Sfb209375 usbprnp->usbprn_dev_data->dev_iblock_cookie);
3470Sstevel@tonic-gate usbprnp->usbprn_write_acc = usb_init_serialization(dip,
3486898Sfb209375 USB_INIT_SER_CHECK_SAME_THREAD);
3490Sstevel@tonic-gate usbprnp->usbprn_ser_acc = usb_init_serialization(dip,
3500Sstevel@tonic-gate USB_INIT_SER_CHECK_SAME_THREAD);
3510Sstevel@tonic-gate usbprnp->usbprn_dev_acc = usb_init_serialization(dip, 0);
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate usbprnp->usbprn_flags |= USBPRN_LOCKS_INIT_DONE;
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate /* Obtain all the relevant descriptors */
3560Sstevel@tonic-gate if (usbprn_get_descriptors(usbprnp) != USB_SUCCESS) {
3570Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3580Sstevel@tonic-gate "usb get descriptors failed");
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate goto fail;
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate usbprnp->usbprn_def_ph = usbprnp->usbprn_dev_data->dev_default_ph;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate /* Obtain the device id */
3660Sstevel@tonic-gate (void) usbprn_get_device_id(usbprnp);
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate /* Get the port status */
3690Sstevel@tonic-gate if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
3700Sstevel@tonic-gate /* some printers fail on the first */
3710Sstevel@tonic-gate if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
3720Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA,
3730Sstevel@tonic-gate usbprnp->usbprn_log_handle,
3740Sstevel@tonic-gate "usb get port status failed");
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate goto fail;
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3810Sstevel@tonic-gate "usbprn_attach: printer status=0x%x", usbprnp->usbprn_last_status);
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate if ((usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR) == 0) {
3840Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3850Sstevel@tonic-gate "usbprn_attach: error occurred with the printer");
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate /*
3890Sstevel@tonic-gate * Create minor node based on information from the
3900Sstevel@tonic-gate * descriptors
3910Sstevel@tonic-gate */
3920Sstevel@tonic-gate if ((ddi_create_minor_node(dip, "printer", S_IFCHR,
3930Sstevel@tonic-gate instance << USBPRN_MINOR_INSTANCE_SHIFT,
3940Sstevel@tonic-gate DDI_NT_PRINTER, 0)) != DDI_SUCCESS) {
395978Sfrits USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3960Sstevel@tonic-gate "usbprn_attach: cannot create minor node");
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate goto fail;
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate usbprnp->usbprn_setparms.write_timeout = USBPRN_XFER_TIMEOUT;
4020Sstevel@tonic-gate usbprnp->usbprn_setparms.mode = ECPP_CENTRONICS;
4030Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate if (usb_pipe_get_max_bulk_transfer_size(usbprnp->usbprn_dip, &sz)) {
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate goto fail;
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate usbprnp->usbprn_max_bulk_xfer_size = sz;
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
4130Sstevel@tonic-gate "usbprn_attach: xfer_size=0x%lx", sz);
4140Sstevel@tonic-gate
4150Sstevel@tonic-gate /* enable PM */
4160Sstevel@tonic-gate usbprn_create_pm_components(dip, usbprnp);
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate /* Register for events */
4190Sstevel@tonic-gate if (usb_register_event_cbs(dip, &usbprn_events, 0) != USB_SUCCESS) {
420978Sfrits USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
4210Sstevel@tonic-gate "usbprn_attach: usb_register_event_cbs failed");
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate goto fail;
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate usb_free_dev_data(dip, usbprnp->usbprn_dev_data);
4270Sstevel@tonic-gate usbprnp->usbprn_dev_data = NULL;
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate if (usb_owns_device(dip)) {
4300Sstevel@tonic-gate /* get a ugen handle */
4310Sstevel@tonic-gate bzero(&usb_ugen_info, sizeof (usb_ugen_info));
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate usb_ugen_info.usb_ugen_flags = 0;
4340Sstevel@tonic-gate usb_ugen_info.usb_ugen_minor_node_ugen_bits_mask =
4356898Sfb209375 (dev_t)USBPRN_MINOR_UGEN_BITS_MASK;
4360Sstevel@tonic-gate usb_ugen_info.usb_ugen_minor_node_instance_mask =
4376898Sfb209375 (dev_t)~USBPRN_MINOR_UGEN_BITS_MASK;
4380Sstevel@tonic-gate usbprnp->usbprn_ugen_hdl =
4396898Sfb209375 usb_ugen_get_hdl(dip, &usb_ugen_info);
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate if (usb_ugen_attach(usbprnp->usbprn_ugen_hdl, cmd) !=
4420Sstevel@tonic-gate USB_SUCCESS) {
4430Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA,
4440Sstevel@tonic-gate usbprnp->usbprn_log_handle,
4450Sstevel@tonic-gate "usb_ugen_attach failed");
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate usb_ugen_release_hdl(usbprnp->usbprn_ugen_hdl);
4480Sstevel@tonic-gate usbprnp->usbprn_ugen_hdl = NULL;
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate /* Report device */
4530Sstevel@tonic-gate ddi_report_dev(dip);
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
4560Sstevel@tonic-gate "usbprn_attach: done");
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate return (DDI_SUCCESS);
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate fail:
4610Sstevel@tonic-gate if (usbprnp) {
4620Sstevel@tonic-gate usbprn_cleanup(dip, usbprnp);
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate return (DDI_FAILURE);
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate /*
4700Sstevel@tonic-gate * usbprn_detach:
4710Sstevel@tonic-gate * detach or suspend driver instance
4720Sstevel@tonic-gate */
4730Sstevel@tonic-gate static int
usbprn_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)4740Sstevel@tonic-gate usbprn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
4750Sstevel@tonic-gate {
4760Sstevel@tonic-gate int instance = ddi_get_instance(dip);
4770Sstevel@tonic-gate usbprn_state_t *usbprnp;
4780Sstevel@tonic-gate int rval = DDI_FAILURE;
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate usbprnp = ddi_get_soft_state(usbprn_statep, instance);
4810Sstevel@tonic-gate
4820Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
4830Sstevel@tonic-gate "usbprn_detach: cmd=%x", cmd);
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate switch (cmd) {
4860Sstevel@tonic-gate case DDI_DETACH:
4870Sstevel@tonic-gate ASSERT((usbprnp->usbprn_flags & USBPRN_OPEN) == 0);
4880Sstevel@tonic-gate usbprn_cleanup(dip, usbprnp);
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate return (DDI_SUCCESS);
4910Sstevel@tonic-gate case DDI_SUSPEND:
4920Sstevel@tonic-gate rval = usbprn_cpr_suspend(dip);
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate return ((rval == USB_SUCCESS) ? DDI_SUCCESS :
4950Sstevel@tonic-gate DDI_FAILURE);
4960Sstevel@tonic-gate default:
4970Sstevel@tonic-gate
4980Sstevel@tonic-gate return (rval);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate /*
5040Sstevel@tonic-gate * usbprn_cleanup:
5050Sstevel@tonic-gate * clean up the driver state
5060Sstevel@tonic-gate */
5070Sstevel@tonic-gate static void
usbprn_cleanup(dev_info_t * dip,usbprn_state_t * usbprnp)5080Sstevel@tonic-gate usbprn_cleanup(dev_info_t *dip, usbprn_state_t *usbprnp)
5090Sstevel@tonic-gate {
5100Sstevel@tonic-gate usbprn_power_t *usbprnpm = usbprnp->usbprn_pm;
5110Sstevel@tonic-gate int rval = 0;
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
5140Sstevel@tonic-gate "usbprn_cleanup: Start");
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate ASSERT(usbprnp != NULL);
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_LOCKS_INIT_DONE) {
5190Sstevel@tonic-gate /*
5200Sstevel@tonic-gate * Disable the event callbacks first, after this point, event
5210Sstevel@tonic-gate * callbacks will never get called. Note we shouldn't hold
5220Sstevel@tonic-gate * mutex while unregistering events because there may be a
5230Sstevel@tonic-gate * competing event callback thread. Event callbacks are done
5240Sstevel@tonic-gate * with ndi mutex held and this can cause a potential deadlock.
5250Sstevel@tonic-gate */
5260Sstevel@tonic-gate usb_unregister_event_cbs(dip, &usbprn_events);
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
5290Sstevel@tonic-gate if ((usbprnpm) &&
5300Sstevel@tonic-gate (usbprnp->usbprn_dev_state != USB_DEV_DISCONNECTED)) {
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
5330Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
5340Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate if (usbprnpm->usbprn_wakeup_enabled) {
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate (void) pm_raise_power(dip, 0,
5410Sstevel@tonic-gate USB_DEV_OS_FULL_PWR);
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate if ((rval = usb_handle_remote_wakeup(dip,
5440Sstevel@tonic-gate USB_REMOTE_WAKEUP_DISABLE)) !=
5450Sstevel@tonic-gate USB_SUCCESS) {
5460Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL,
5470Sstevel@tonic-gate usbprnp->usbprn_log_handle,
5480Sstevel@tonic-gate "usbprn_cleanup: "
5490Sstevel@tonic-gate "disable remote wakeup "
5500Sstevel@tonic-gate "failed, rval=%d", rval);
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate } else {
5530Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
5570Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
5600Sstevel@tonic-gate }
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL);
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate if (usbprnp->usbprn_device_id) {
5670Sstevel@tonic-gate kmem_free(usbprnp->usbprn_device_id,
5680Sstevel@tonic-gate usbprnp->usbprn_device_id_len + 1);
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate mutex_destroy(&usbprnp->usbprn_mutex);
5720Sstevel@tonic-gate usb_fini_serialization(usbprnp->usbprn_dev_acc);
5730Sstevel@tonic-gate usb_fini_serialization(usbprnp->usbprn_ser_acc);
5740Sstevel@tonic-gate usb_fini_serialization(usbprnp->usbprn_write_acc);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate if (usbprnpm) {
5780Sstevel@tonic-gate kmem_free(usbprnpm, sizeof (usbprn_power_t));
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
5820Sstevel@tonic-gate "usbprn_cleanup: End");
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate if (usbprnp->usbprn_ugen_hdl) {
5850Sstevel@tonic-gate (void) usb_ugen_detach(usbprnp->usbprn_ugen_hdl, DDI_DETACH);
5860Sstevel@tonic-gate usb_ugen_release_hdl(usbprnp->usbprn_ugen_hdl);
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate
5890Sstevel@tonic-gate /* unregister with USBA */
5900Sstevel@tonic-gate usb_client_detach(dip, usbprnp->usbprn_dev_data);
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate usb_free_log_hdl(usbprnp->usbprn_log_handle);
5930Sstevel@tonic-gate ddi_prop_remove_all(dip);
5940Sstevel@tonic-gate ddi_soft_state_free(usbprn_statep, usbprnp->usbprn_instance);
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate /*
5990Sstevel@tonic-gate * usbprn_cpr_suspend:
6000Sstevel@tonic-gate * prepare to be suspended
6010Sstevel@tonic-gate */
6020Sstevel@tonic-gate static int
usbprn_cpr_suspend(dev_info_t * dip)6030Sstevel@tonic-gate usbprn_cpr_suspend(dev_info_t *dip)
6040Sstevel@tonic-gate {
6050Sstevel@tonic-gate usbprn_state_t *usbprnp;
6060Sstevel@tonic-gate int instance = ddi_get_instance(dip);
6070Sstevel@tonic-gate int rval = USB_FAILURE;
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate usbprnp = ddi_get_soft_state(usbprn_statep, instance);
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
6120Sstevel@tonic-gate "usbprn_cpr_suspend");
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate if ((usbprnp->usbprn_flags & USBPRN_OPEN) != 0) {
6190Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_CPR,
6220Sstevel@tonic-gate usbprnp->usbprn_log_handle,
6230Sstevel@tonic-gate "usbprn_cpr_suspend: "
6240Sstevel@tonic-gate "Device is open. Can't suspend");
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate } else {
6270Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_SUSPENDED;
6280Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
6310Sstevel@tonic-gate "usbprn_cpr_suspend: SUCCESS");
6320Sstevel@tonic-gate rval = USB_SUCCESS;
6330Sstevel@tonic-gate }
6340Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate if ((rval == USB_SUCCESS) && usbprnp->usbprn_ugen_hdl) {
6370Sstevel@tonic-gate rval = usb_ugen_detach(usbprnp->usbprn_ugen_hdl,
6386898Sfb209375 DDI_SUSPEND);
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate return (rval);
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate static void
usbprn_cpr_resume(dev_info_t * dip)6460Sstevel@tonic-gate usbprn_cpr_resume(dev_info_t *dip)
6470Sstevel@tonic-gate {
6480Sstevel@tonic-gate int instance = ddi_get_instance(dip);
6490Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep, instance);
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
6520Sstevel@tonic-gate "usbprn_cpr_resume");
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate /* Needed as power up state of dev is "unknown" to system */
6550Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
6560Sstevel@tonic-gate (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate usbprn_restore_device_state(dip, usbprnp);
6590Sstevel@tonic-gate
6600Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
6610Sstevel@tonic-gate
6620Sstevel@tonic-gate if (usbprnp->usbprn_ugen_hdl) {
6630Sstevel@tonic-gate (void) usb_ugen_attach(usbprnp->usbprn_ugen_hdl,
6646898Sfb209375 DDI_RESUME);
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate /*
6700Sstevel@tonic-gate * usbprn_get_descriptors:
6710Sstevel@tonic-gate * Obtain all the descriptors for the device
6720Sstevel@tonic-gate */
6730Sstevel@tonic-gate static int
usbprn_get_descriptors(usbprn_state_t * usbprnp)6740Sstevel@tonic-gate usbprn_get_descriptors(usbprn_state_t *usbprnp)
6750Sstevel@tonic-gate {
6760Sstevel@tonic-gate int interface;
6770Sstevel@tonic-gate usb_client_dev_data_t *dev_data =
6786898Sfb209375 usbprnp->usbprn_dev_data;
6790Sstevel@tonic-gate usb_alt_if_data_t *altif_data;
6800Sstevel@tonic-gate usb_cfg_data_t *cfg_data;
6810Sstevel@tonic-gate usb_ep_data_t *ep_data;
6820Sstevel@tonic-gate dev_info_t *dip = usbprnp->usbprn_dip;
6830Sstevel@tonic-gate int alt, rval;
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate /*
6880Sstevel@tonic-gate * Section 4.2.1 of the spec says the printer could have
6890Sstevel@tonic-gate * multiple configurations. This driver is just for one
6900Sstevel@tonic-gate * configuration interface and one interface.
6910Sstevel@tonic-gate */
6920Sstevel@tonic-gate interface = dev_data->dev_curr_if;
6930Sstevel@tonic-gate cfg_data = dev_data->dev_curr_cfg;
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate /* find alternate that supports BI/UNI protocol */
6960Sstevel@tonic-gate for (alt = 0; alt < cfg_data->cfg_if[interface].if_n_alt; alt++) {
6970Sstevel@tonic-gate altif_data = &cfg_data->cfg_if[interface].if_alt[alt];
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate if ((altif_data->altif_descr.bInterfaceProtocol ==
7000Sstevel@tonic-gate USB_PROTO_PRINTER_UNI) ||
7010Sstevel@tonic-gate (altif_data->altif_descr.bInterfaceProtocol ==
7020Sstevel@tonic-gate USB_PROTO_PRINTER_BI)) {
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate break;
7050Sstevel@tonic-gate } else {
7060Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ATTA,
7070Sstevel@tonic-gate usbprnp->usbprn_log_handle,
7080Sstevel@tonic-gate "alternate %d not supported", alt);
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate
7120Sstevel@tonic-gate if (alt == cfg_data->cfg_if[interface].if_n_alt) {
7130Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
7140Sstevel@tonic-gate "usbprn_get_descriptors: no alternate");
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate return (USB_FAILURE);
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate if ((rval = usb_set_alt_if(dip, interface, alt, USB_FLAGS_SLEEP,
7210Sstevel@tonic-gate NULL, NULL)) != USB_SUCCESS) {
7220Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
7230Sstevel@tonic-gate "usbprn_get_descriptors: set alternate failed (%d)",
7240Sstevel@tonic-gate rval);
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate return (rval);
7270Sstevel@tonic-gate }
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate usbprnp->usbprn_config_descr = cfg_data->cfg_descr;
7300Sstevel@tonic-gate usbprnp->usbprn_if_descr = altif_data->altif_descr;
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate /*
7330Sstevel@tonic-gate * find the endpoint descriptors. There will be a bulk-out endpoint
7340Sstevel@tonic-gate * and an optional bulk-in endpoint.
7350Sstevel@tonic-gate */
7360Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, alt, 0,
7370Sstevel@tonic-gate USB_EP_ATTR_BULK, USB_EP_DIR_OUT)) != NULL) {
7380Sstevel@tonic-gate usbprnp->usbprn_bulk_out.ps_ept_descr = ep_data->ep_descr;
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, alt, 0,
7410Sstevel@tonic-gate USB_EP_ATTR_BULK, USB_EP_DIR_IN)) != NULL) {
7420Sstevel@tonic-gate usbprnp->usbprn_bulk_in.ps_ept_descr = ep_data->ep_descr;
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate return (USB_SUCCESS);
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate
7490Sstevel@tonic-gate /*
7500Sstevel@tonic-gate * usbprn_get_device_id:
7510Sstevel@tonic-gate * Get the device id as described in 4.2.1 of the specification
7520Sstevel@tonic-gate * Lexmark printer returns 2 bytes when asked for 8 bytes
7530Sstevel@tonic-gate * We are ignoring data over and underrun.
7540Sstevel@tonic-gate * This is a synchronous function
7550Sstevel@tonic-gate */
7560Sstevel@tonic-gate static int
usbprn_get_device_id(usbprn_state_t * usbprnp)7570Sstevel@tonic-gate usbprn_get_device_id(usbprn_state_t *usbprnp)
7580Sstevel@tonic-gate {
7590Sstevel@tonic-gate int len, n;
7600Sstevel@tonic-gate mblk_t *data = NULL;
7610Sstevel@tonic-gate usb_cr_t completion_reason;
7620Sstevel@tonic-gate usb_cb_flags_t cb_flags;
7630Sstevel@tonic-gate int rval = USB_FAILURE;
7640Sstevel@tonic-gate usb_ctrl_setup_t setup = {
7650Sstevel@tonic-gate USB_DEV_REQ_DEV_TO_HOST | /* bmRequestType */
7666898Sfb209375 USB_DEV_REQ_TYPE_CLASS |
7676898Sfb209375 USB_DEV_REQ_RCPT_IF,
7680Sstevel@tonic-gate USB_PRINTER_GET_DEVICE_ID, /* bRequest */
7690Sstevel@tonic-gate 0, /* wValue: fill in later */
7700Sstevel@tonic-gate 0, /* wIndex: fill in later */
7710Sstevel@tonic-gate 0, /* wLength: fill in later */
7720Sstevel@tonic-gate 0 /* attributes */
7736898Sfb209375 };
7740Sstevel@tonic-gate void *ptr;
7750Sstevel@tonic-gate
7760Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
7770Sstevel@tonic-gate "usbprn_get_device_id: Begin");
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate setup.wIndex = (usbprnp->usbprn_if_descr.bInterfaceNumber << 0x8) |
7826898Sfb209375 (usbprnp->usbprn_if_descr.bAlternateSetting);
7830Sstevel@tonic-gate setup.wLength = USBPRN_MAX_DEVICE_ID_LENGTH;
7840Sstevel@tonic-gate setup.wValue = usbprnp->usbprn_config_descr.iConfiguration;
7850Sstevel@tonic-gate
7860Sstevel@tonic-gate /*
7870Sstevel@tonic-gate * This is always a sync request as this will never
7880Sstevel@tonic-gate * be called in interrupt context.
7890Sstevel@tonic-gate * First get the first two bytes that gives the length
7900Sstevel@tonic-gate * of the device id string; then get the whole string
7910Sstevel@tonic-gate */
7920Sstevel@tonic-gate if (usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph, &setup,
7930Sstevel@tonic-gate &data, &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
7940Sstevel@tonic-gate
7950Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
7960Sstevel@tonic-gate "usbprn_get_device_id: First sync command failed, cr=%d ",
7970Sstevel@tonic-gate completion_reason);
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate /*
8000Sstevel@tonic-gate * some devices return more than requested. as long as
8010Sstevel@tonic-gate * we get the first two bytes, we can continue
8020Sstevel@tonic-gate */
8030Sstevel@tonic-gate if (((completion_reason != USB_CR_DATA_OVERRUN) &&
8040Sstevel@tonic-gate (completion_reason != USB_CR_DATA_UNDERRUN)) ||
8050Sstevel@tonic-gate (data == NULL)) {
8060Sstevel@tonic-gate
8070Sstevel@tonic-gate goto done;
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate }
8100Sstevel@tonic-gate
8110Sstevel@tonic-gate ASSERT(data);
8127492SZhigang.Lu@Sun.COM n = MBLKL(data);
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate if (n < 2) {
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate goto done;
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate len = (((*data->b_rptr) << 0x8) | (*(data->b_rptr+1)));
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate /*
8220Sstevel@tonic-gate * Std 1284-1994, chapter 7.6:
8230Sstevel@tonic-gate * Length values of x'0000', x'0001' and x'0002' are reserved
8240Sstevel@tonic-gate */
8250Sstevel@tonic-gate if (len < 3) {
8260Sstevel@tonic-gate
8270Sstevel@tonic-gate goto done;
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
8310Sstevel@tonic-gate "usbprn_get_device_id: device id length=%d", len);
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate /* did we get enough data */
8340Sstevel@tonic-gate if (len > n) {
8350Sstevel@tonic-gate freemsg(data);
8360Sstevel@tonic-gate data = NULL;
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate setup.wLength = (uint16_t)len;
8390Sstevel@tonic-gate if ((rval = usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph,
8400Sstevel@tonic-gate &setup, &data, &completion_reason, &cb_flags, 0)) !=
8410Sstevel@tonic-gate USB_SUCCESS) {
8420Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA,
8430Sstevel@tonic-gate usbprnp->usbprn_log_handle,
8440Sstevel@tonic-gate "usbprn_get_device_id: 2nd command failed "
8450Sstevel@tonic-gate "cr=%d cb_flags=0x%x",
8460Sstevel@tonic-gate completion_reason, cb_flags);
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate goto done;
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate
8517492SZhigang.Lu@Sun.COM ASSERT(len == MBLKL(data));
8520Sstevel@tonic-gate }
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
8556898Sfb209375 "usbprn_get_device_id: returned data length=%ld",
8567492SZhigang.Lu@Sun.COM (long)(MBLKL(data)));
8570Sstevel@tonic-gate
8580Sstevel@tonic-gate ptr = kmem_zalloc(len + 1, KM_SLEEP);
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
8610Sstevel@tonic-gate usbprnp->usbprn_device_id_len = len;
8620Sstevel@tonic-gate usbprnp->usbprn_device_id = ptr;
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate bcopy(data->b_rptr, usbprnp->usbprn_device_id,
8656898Sfb209375 usbprnp->usbprn_device_id_len);
8660Sstevel@tonic-gate usbprnp->usbprn_device_id[usbprnp->usbprn_device_id_len] = '\0';
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate /* Length is in the first two bytes, dump string in logbuf */
8690Sstevel@tonic-gate usbprn_print_long(usbprnp, usbprnp->usbprn_device_id + 2,
8700Sstevel@tonic-gate usbprnp->usbprn_device_id_len - 2);
8710Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
8720Sstevel@tonic-gate
8730Sstevel@tonic-gate rval = USB_SUCCESS;
8740Sstevel@tonic-gate done:
8750Sstevel@tonic-gate freemsg(data);
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
8780Sstevel@tonic-gate "usbprn_get_device_id: rval=%d", rval);
8790Sstevel@tonic-gate
8800Sstevel@tonic-gate return (rval);
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate /*
8850Sstevel@tonic-gate * usbprn_get_port_status:
8860Sstevel@tonic-gate * Get the port status.
8870Sstevel@tonic-gate * This is a synchronous function
8880Sstevel@tonic-gate */
8890Sstevel@tonic-gate static int
usbprn_get_port_status(usbprn_state_t * usbprnp)8900Sstevel@tonic-gate usbprn_get_port_status(usbprn_state_t *usbprnp)
8910Sstevel@tonic-gate {
8920Sstevel@tonic-gate mblk_t *data = NULL;
8930Sstevel@tonic-gate usb_cr_t completion_reason;
8940Sstevel@tonic-gate usb_cb_flags_t cb_flags;
8950Sstevel@tonic-gate usb_ctrl_setup_t setup = {
8960Sstevel@tonic-gate USB_DEV_REQ_DEV_TO_HOST | /* bmRequestType */
8976898Sfb209375 USB_DEV_REQ_TYPE_CLASS |
8986898Sfb209375 USB_DEV_REQ_RCPT_IF,
8990Sstevel@tonic-gate USB_PRINTER_GET_PORT_STATUS, /* bRequest */
9000Sstevel@tonic-gate 0, /* wValue */
9010Sstevel@tonic-gate 0, /* wIndex: fill in later */
9020Sstevel@tonic-gate 1, /* wLength */
9030Sstevel@tonic-gate 0 /* attributes */
9046898Sfb209375 };
9050Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
9060Sstevel@tonic-gate
9070Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
9080Sstevel@tonic-gate "usbprn_get_port_status: Begin");
9090Sstevel@tonic-gate
9100Sstevel@tonic-gate setup.wIndex = usbprnp->usbprn_if_descr.bInterfaceNumber;
9110Sstevel@tonic-gate if (usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph,
9120Sstevel@tonic-gate &setup, &data, &completion_reason, &cb_flags, 0) !=
9130Sstevel@tonic-gate USB_SUCCESS) {
9140Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
9150Sstevel@tonic-gate "usbprn_get_port_status: Sync command failed "
9160Sstevel@tonic-gate "cr=%d cb_flags=0x%x", completion_reason, cb_flags);
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate freemsg(data);
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate return (USB_FAILURE);
9210Sstevel@tonic-gate } else {
9220Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate ASSERT(data);
9257492SZhigang.Lu@Sun.COM ASSERT(MBLKL(data) == 1);
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate usbprnp->usbprn_last_status = *data->b_rptr;
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
9300Sstevel@tonic-gate "usbprn_get_port_status(sync): status=0x%x",
9310Sstevel@tonic-gate usbprnp->usbprn_last_status);
9320Sstevel@tonic-gate
9330Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9340Sstevel@tonic-gate freemsg(data);
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate return (USB_SUCCESS);
9370Sstevel@tonic-gate }
9380Sstevel@tonic-gate }
9390Sstevel@tonic-gate
9400Sstevel@tonic-gate
9410Sstevel@tonic-gate /*
9420Sstevel@tonic-gate * usbprn_open:
9430Sstevel@tonic-gate * Open the pipes
9440Sstevel@tonic-gate */
9450Sstevel@tonic-gate /*ARGSUSED*/
9460Sstevel@tonic-gate static int
usbprn_open(dev_t * devp,int flag,int sflag,cred_t * credp)9470Sstevel@tonic-gate usbprn_open(dev_t *devp, int flag, int sflag, cred_t *credp)
9480Sstevel@tonic-gate {
9490Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
9506898Sfb209375 USBPRN_MINOR_TO_INSTANCE(getminor(*devp)));
9510Sstevel@tonic-gate int rval = 0;
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate if (usbprnp == NULL) {
9540Sstevel@tonic-gate
9550Sstevel@tonic-gate return (ENXIO);
9560Sstevel@tonic-gate }
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
9590Sstevel@tonic-gate "usbprn_open:");
9600Sstevel@tonic-gate
9610Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
9620Sstevel@tonic-gate
9630Sstevel@tonic-gate /* Fail open on a disconnected device */
9640Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
9650Sstevel@tonic-gate if (usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED) {
9660Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9670Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate return (ENODEV);
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate /* cannot happen? but just in case */
9730Sstevel@tonic-gate if (usbprnp->usbprn_dev_state == USB_DEV_SUSPENDED) {
9740Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9750Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate return (EIO);
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate if (getminor(*devp) & USBPRN_MINOR_UGEN_BITS_MASK) {
9810Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9820Sstevel@tonic-gate
9830Sstevel@tonic-gate rval = usb_ugen_open(usbprnp->usbprn_ugen_hdl,
9846898Sfb209375 devp, flag, sflag, credp);
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate return (rval);
9890Sstevel@tonic-gate }
9900Sstevel@tonic-gate
9910Sstevel@tonic-gate /* Exit if this instance is already open */
9920Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_OPEN) {
9930Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9940Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
9950Sstevel@tonic-gate
9960Sstevel@tonic-gate return (EBUSY);
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate /* raise power */
10010Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
10020Sstevel@tonic-gate (void) pm_raise_power(usbprnp->usbprn_dip,
10036898Sfb209375 0, USB_DEV_OS_FULL_PWR);
10040Sstevel@tonic-gate /* initialize some softstate data */
10050Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
10060Sstevel@tonic-gate usbprnp->usbprn_prn_timeouts.tmo_forward =
10076898Sfb209375 usbprnp->usbprn_setparms.write_timeout;
10080Sstevel@tonic-gate usbprnp->usbprn_prn_timeouts.tmo_reverse = 0;
10090Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
10100Sstevel@tonic-gate
10110Sstevel@tonic-gate if (usbprn_open_usb_pipes(usbprnp) != USB_SUCCESS) {
10120Sstevel@tonic-gate
1013978Sfrits USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
10140Sstevel@tonic-gate "usbprn_open: pipe open failed");
10150Sstevel@tonic-gate
10160Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
10170Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate return (EIO);
10200Sstevel@tonic-gate }
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
10230Sstevel@tonic-gate usbprnp->usbprn_flags |= USBPRN_OPEN;
10240Sstevel@tonic-gate
10250Sstevel@tonic-gate /* set last status to online */
10260Sstevel@tonic-gate usbprnp->usbprn_last_status &= ~USB_PRINTER_PORT_NO_SELECT;
10270Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
10280Sstevel@tonic-gate
10290Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
10320Sstevel@tonic-gate "usbprn_open: End");
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate return (rval);
10350Sstevel@tonic-gate }
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate /*
10390Sstevel@tonic-gate * usbprn_close:
10400Sstevel@tonic-gate * Close the pipes
10410Sstevel@tonic-gate */
10420Sstevel@tonic-gate /*ARGSUSED*/
10430Sstevel@tonic-gate static int
usbprn_close(dev_t dev,int flag,int otyp,cred_t * credp)10440Sstevel@tonic-gate usbprn_close(dev_t dev, int flag, int otyp, cred_t *credp)
10450Sstevel@tonic-gate {
10460Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
10476898Sfb209375 USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
10480Sstevel@tonic-gate int rval = 0;
10490Sstevel@tonic-gate
10500Sstevel@tonic-gate if (usbprnp == NULL) {
10510Sstevel@tonic-gate
10520Sstevel@tonic-gate return (ENXIO);
10530Sstevel@tonic-gate }
10540Sstevel@tonic-gate
10550Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbprnp->usbprn_log_handle,
10560Sstevel@tonic-gate "usbprn_close:");
10570Sstevel@tonic-gate
10580Sstevel@tonic-gate if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
10590Sstevel@tonic-gate rval = usb_ugen_close(usbprnp->usbprn_ugen_hdl,
10606898Sfb209375 dev, flag, otyp, credp);
10610Sstevel@tonic-gate
10620Sstevel@tonic-gate return (rval);
10630Sstevel@tonic-gate }
10640Sstevel@tonic-gate
10650Sstevel@tonic-gate /* avoid races with connect/disconnect */
10660Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
10670Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_dev_acc, USB_WAIT, 0);
10680Sstevel@tonic-gate
10690Sstevel@tonic-gate /* Close all usb pipes */
10700Sstevel@tonic-gate usbprn_close_usb_pipes(usbprnp);
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate /* prevent any accesses by setting flags to closed */
10730Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
10740Sstevel@tonic-gate usbprnp->usbprn_flags &= ~USBPRN_OPEN;
10750Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_dev_acc);
10780Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
10810Sstevel@tonic-gate
10820Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbprnp->usbprn_log_handle,
10830Sstevel@tonic-gate "usbprn_close: End");
10840Sstevel@tonic-gate
10850Sstevel@tonic-gate return (rval);
10860Sstevel@tonic-gate }
10870Sstevel@tonic-gate
10880Sstevel@tonic-gate
10890Sstevel@tonic-gate /*
10900Sstevel@tonic-gate * usbprn_read:
10910Sstevel@tonic-gate * Read entry point (TBD)
10920Sstevel@tonic-gate */
10930Sstevel@tonic-gate /* ARGSUSED */
10940Sstevel@tonic-gate static int
usbprn_read(dev_t dev,struct uio * uiop,cred_t * credp)10950Sstevel@tonic-gate usbprn_read(dev_t dev, struct uio *uiop, cred_t *credp)
10960Sstevel@tonic-gate {
10970Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
10986898Sfb209375 USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
10990Sstevel@tonic-gate
11000Sstevel@tonic-gate if (usbprnp == NULL) {
11010Sstevel@tonic-gate
11020Sstevel@tonic-gate return (ENXIO);
11030Sstevel@tonic-gate }
11040Sstevel@tonic-gate
11050Sstevel@tonic-gate if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
11060Sstevel@tonic-gate int rval;
11070Sstevel@tonic-gate
11080Sstevel@tonic-gate /* raise power */
11090Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
11100Sstevel@tonic-gate (void) pm_raise_power(usbprnp->usbprn_dip,
11116898Sfb209375 0, USB_DEV_OS_FULL_PWR);
11120Sstevel@tonic-gate
11130Sstevel@tonic-gate if (usb_serialize_access(usbprnp->usbprn_write_acc,
11140Sstevel@tonic-gate USB_WAIT_SIG, 0) == 0) {
11150Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate return (EINTR);
11180Sstevel@tonic-gate }
11190Sstevel@tonic-gate
11200Sstevel@tonic-gate rval = usb_ugen_read(usbprnp->usbprn_ugen_hdl, dev,
11216898Sfb209375 uiop, credp);
11220Sstevel@tonic-gate
11230Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_write_acc);
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate return (rval);
11280Sstevel@tonic-gate }
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate /* Do a bulk-in from the printer */
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate return (EIO);
11330Sstevel@tonic-gate }
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate
11360Sstevel@tonic-gate /*
11370Sstevel@tonic-gate * usbprn_write:
11380Sstevel@tonic-gate * Write to the printer
11390Sstevel@tonic-gate */
11400Sstevel@tonic-gate /* ARGSUSED2 */
11410Sstevel@tonic-gate static int
usbprn_write(dev_t dev,struct uio * uiop,cred_t * credp)11420Sstevel@tonic-gate usbprn_write(dev_t dev, struct uio *uiop, cred_t *credp)
11430Sstevel@tonic-gate {
11440Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
11456898Sfb209375 USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
11460Sstevel@tonic-gate usbprn_ps_t *bulk_in = &usbprnp->usbprn_bulk_in;
11470Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
11480Sstevel@tonic-gate int rval;
11490Sstevel@tonic-gate
11500Sstevel@tonic-gate if (usbprnp == NULL) {
11510Sstevel@tonic-gate
11520Sstevel@tonic-gate return (ENXIO);
11530Sstevel@tonic-gate }
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
11566898Sfb209375 "usbprn_write: Begin usbprnp=0x%p ", (void *)usbprnp);
11570Sstevel@tonic-gate
11580Sstevel@tonic-gate if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
11590Sstevel@tonic-gate /* raise power */
11600Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
11610Sstevel@tonic-gate (void) pm_raise_power(usbprnp->usbprn_dip,
11626898Sfb209375 0, USB_DEV_OS_FULL_PWR);
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate if (usb_serialize_access(usbprnp->usbprn_write_acc,
11650Sstevel@tonic-gate USB_WAIT_SIG, 0) == 0) {
11660Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate return (EINTR);
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate rval = usb_ugen_write(usbprnp->usbprn_ugen_hdl, dev,
11726898Sfb209375 uiop, credp);
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_write_acc);
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
11770Sstevel@tonic-gate
11780Sstevel@tonic-gate return (rval);
11790Sstevel@tonic-gate }
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate /*
11820Sstevel@tonic-gate * serialize writes
11830Sstevel@tonic-gate * we cannot use usbprn_ser_acc sync object at this point because
11840Sstevel@tonic-gate * that would block out the ioctls for the full duration of the write.
11850Sstevel@tonic-gate */
11860Sstevel@tonic-gate if (usb_serialize_access(usbprnp->usbprn_write_acc,
11870Sstevel@tonic-gate USB_WAIT_SIG, 0) == 0) {
11880Sstevel@tonic-gate
11890Sstevel@tonic-gate return (EINTR);
11900Sstevel@tonic-gate }
11910Sstevel@tonic-gate
11920Sstevel@tonic-gate /*
11930Sstevel@tonic-gate * Check the status of the pipe. If it's not idle,
11940Sstevel@tonic-gate * then wait.
11950Sstevel@tonic-gate */
11960Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
11970Sstevel@tonic-gate
11980Sstevel@tonic-gate /* if device is disconnected or pipes closed, fail immediately */
11990Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
12000Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
12030Sstevel@tonic-gate "usbprn_write: device can't be accessed");
12040Sstevel@tonic-gate
12050Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_write_acc);
12060Sstevel@tonic-gate
12070Sstevel@tonic-gate return (EIO);
12080Sstevel@tonic-gate }
12090Sstevel@tonic-gate
12100Sstevel@tonic-gate /* all pipes must be idle */
12110Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
12120Sstevel@tonic-gate ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
12130Sstevel@tonic-gate
12140Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate /*
12170Sstevel@tonic-gate * Call physio to do the transfer. physio will
12180Sstevel@tonic-gate * call the strategy routine, and then call
12190Sstevel@tonic-gate * biowait() to block until the transfer completes.
12200Sstevel@tonic-gate */
12210Sstevel@tonic-gate rval = physio(usbprn_strategy, (struct buf *)0, dev,
12220Sstevel@tonic-gate B_WRITE, usbprn_minphys, uiop);
12230Sstevel@tonic-gate
12240Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_write_acc);
12250Sstevel@tonic-gate
12260Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
12270Sstevel@tonic-gate "usbprn_write: End");
12280Sstevel@tonic-gate
12290Sstevel@tonic-gate return (rval);
12300Sstevel@tonic-gate }
12310Sstevel@tonic-gate
12320Sstevel@tonic-gate
12330Sstevel@tonic-gate /*
12340Sstevel@tonic-gate * usbprn_poll
12350Sstevel@tonic-gate */
12360Sstevel@tonic-gate static int
usbprn_poll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)12370Sstevel@tonic-gate usbprn_poll(dev_t dev, short events,
12380Sstevel@tonic-gate int anyyet, short *reventsp, struct pollhead **phpp)
12390Sstevel@tonic-gate {
12400Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
12416898Sfb209375 USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
12420Sstevel@tonic-gate
12430Sstevel@tonic-gate if (usbprnp == NULL) {
12440Sstevel@tonic-gate
12450Sstevel@tonic-gate return (ENXIO);
12460Sstevel@tonic-gate }
12470Sstevel@tonic-gate
12480Sstevel@tonic-gate if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
12490Sstevel@tonic-gate return (usb_ugen_poll(usbprnp->usbprn_ugen_hdl, dev, events,
12506898Sfb209375 anyyet, reventsp, phpp));
12510Sstevel@tonic-gate }
12520Sstevel@tonic-gate
12530Sstevel@tonic-gate return (ENXIO);
12540Sstevel@tonic-gate }
12550Sstevel@tonic-gate
12560Sstevel@tonic-gate
12570Sstevel@tonic-gate /*
12580Sstevel@tonic-gate * usbprn_strategy:
12590Sstevel@tonic-gate * service a request to the device.
12600Sstevel@tonic-gate */
12610Sstevel@tonic-gate static int
usbprn_strategy(struct buf * bp)12620Sstevel@tonic-gate usbprn_strategy(struct buf *bp)
12630Sstevel@tonic-gate {
12640Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
12656898Sfb209375 USBPRN_MINOR_TO_INSTANCE(getminor(bp->b_edev)));
12660Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
12670Sstevel@tonic-gate
12680Sstevel@tonic-gate bp_mapin(bp);
12690Sstevel@tonic-gate
12700Sstevel@tonic-gate /*
12710Sstevel@tonic-gate * serialize to avoid races
12720Sstevel@tonic-gate * access is released in usbprn_biodone()
12730Sstevel@tonic-gate */
12740Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_dev_acc, USB_WAIT, 0);
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
12770Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
12780Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
12790Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
12820Sstevel@tonic-gate "usbprn_strategy: device can't be accessed");
12830Sstevel@tonic-gate
12840Sstevel@tonic-gate return (0);
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_NEED_TO_XFER;
12880Sstevel@tonic-gate
12890Sstevel@tonic-gate ASSERT(usbprnp->usbprn_bp == NULL);
12900Sstevel@tonic-gate usbprnp->usbprn_bp = bp;
12910Sstevel@tonic-gate
12920Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
12930Sstevel@tonic-gate "usbprn_strategy: usbprnp=0x%p bp=0x%p count=%lu",
12946898Sfb209375 (void *)usbprnp, (void *)bp, bp->b_bcount);
12950Sstevel@tonic-gate
12960Sstevel@tonic-gate ASSERT(usbprnp->usbprn_bulk_mp == NULL);
12970Sstevel@tonic-gate
12980Sstevel@tonic-gate usbprnp->usbprn_bulk_mp = allocb(bp->b_bcount, BPRI_HI);
12990Sstevel@tonic-gate
13000Sstevel@tonic-gate if (usbprnp->usbprn_bulk_mp == NULL) {
13010Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
13020Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
13030Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
13040Sstevel@tonic-gate
13050Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
13060Sstevel@tonic-gate "usbprn_strategy: allocb failed");
13070Sstevel@tonic-gate
13080Sstevel@tonic-gate return (0);
13090Sstevel@tonic-gate }
13100Sstevel@tonic-gate
13110Sstevel@tonic-gate bcopy((caddr_t)bp->b_un.b_addr,
13126898Sfb209375 usbprnp->usbprn_bulk_mp->b_datap->db_base, bp->b_bcount);
13130Sstevel@tonic-gate usbprnp->usbprn_bulk_mp->b_wptr += bp->b_bcount;
13140Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
13150Sstevel@tonic-gate
13160Sstevel@tonic-gate usbprn_send_async_bulk_data(usbprnp);
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate return (0);
13190Sstevel@tonic-gate }
13200Sstevel@tonic-gate
13210Sstevel@tonic-gate
13220Sstevel@tonic-gate /*
13230Sstevel@tonic-gate * usbprn_ioctl:
13240Sstevel@tonic-gate * handle the ioctl
13250Sstevel@tonic-gate */
13260Sstevel@tonic-gate /*ARGSUSED4*/
13270Sstevel@tonic-gate static int
usbprn_ioctl(dev_t dev,int cmd,intptr_t arg,int flag,cred_t * credp,int * rvalp)13280Sstevel@tonic-gate usbprn_ioctl(dev_t dev, int cmd, intptr_t arg, int flag,
13290Sstevel@tonic-gate cred_t *credp, int *rvalp)
13300Sstevel@tonic-gate {
13310Sstevel@tonic-gate int err = 0;
13320Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
13336898Sfb209375 USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
13340Sstevel@tonic-gate struct ecpp_device_id usbprn_devid;
13350Sstevel@tonic-gate int len;
13360Sstevel@tonic-gate
13370Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
13380Sstevel@tonic-gate "usbprn_ioctl: Begin ");
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
13410Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate /*
13440Sstevel@tonic-gate * only for PRNIOC_GET_STATUS cmd:
13450Sstevel@tonic-gate * if device is disconnected or pipes closed, fail immediately
13460Sstevel@tonic-gate */
13470Sstevel@tonic-gate if ((cmd == PRNIOC_GET_STATUS) &&
13480Sstevel@tonic-gate !(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
13490Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
13500Sstevel@tonic-gate
13510Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
13520Sstevel@tonic-gate "usbprn_write: device can't be accessed");
13530Sstevel@tonic-gate
13540Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
13550Sstevel@tonic-gate
13560Sstevel@tonic-gate return (EIO);
13570Sstevel@tonic-gate }
13580Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
13590Sstevel@tonic-gate
13600Sstevel@tonic-gate switch (cmd) {
13610Sstevel@tonic-gate case ECPPIOC_GETDEVID:
13620Sstevel@tonic-gate /*
13630Sstevel@tonic-gate * With genericized ioctls this interface should change.
13640Sstevel@tonic-gate * We ignore the mode in USB printer driver because
13650Sstevel@tonic-gate * it need not be in nibble mode in usb driver unlike
13660Sstevel@tonic-gate * ecpp to retrieve the device id string. Also we do
13670Sstevel@tonic-gate * not expect the application to call this twice since
13680Sstevel@tonic-gate * it doesn't change since attach time and we take care
13690Sstevel@tonic-gate * of calling it twice: once for getting the length and
13700Sstevel@tonic-gate * once for getting the actual device id string. So we
13710Sstevel@tonic-gate * set both the lengths to actual device id string length.
13720Sstevel@tonic-gate * Ref: PSARC/2000/018
13730Sstevel@tonic-gate */
13740Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
13750Sstevel@tonic-gate "usbprn_ioctl: ECPPIOC_GETDEVID(0x%x)", cmd);
13760Sstevel@tonic-gate
13770Sstevel@tonic-gate bzero(&usbprn_devid, sizeof (usbprn_devid));
13780Sstevel@tonic-gate
13790Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
13800Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
13810Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) {
13820Sstevel@tonic-gate case DDI_MODEL_ILP32: {
13830Sstevel@tonic-gate struct ecpp_device_id32 usbprn_devid32;
13840Sstevel@tonic-gate
13850Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &usbprn_devid32,
13860Sstevel@tonic-gate sizeof (struct ecpp_device_id32), flag)) {
13870Sstevel@tonic-gate err = EFAULT;
13880Sstevel@tonic-gate
13890Sstevel@tonic-gate break;
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate
13920Sstevel@tonic-gate if (usbprnp->usbprn_device_id == NULL) {
13930Sstevel@tonic-gate err = EIO;
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate break;
13960Sstevel@tonic-gate }
13970Sstevel@tonic-gate ASSERT(usbprnp->usbprn_device_id_len > 2);
13980Sstevel@tonic-gate
13990Sstevel@tonic-gate usbprn_devid32.rlen = usbprnp->usbprn_device_id_len - 2;
14000Sstevel@tonic-gate len = min(usbprn_devid32.len, usbprn_devid32.rlen);
14010Sstevel@tonic-gate
14020Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
14030Sstevel@tonic-gate (caddr_t)(uintptr_t)usbprn_devid32.addr,
14040Sstevel@tonic-gate len, flag)) {
14050Sstevel@tonic-gate err = EFAULT;
14060Sstevel@tonic-gate
14070Sstevel@tonic-gate break;
14080Sstevel@tonic-gate }
14090Sstevel@tonic-gate
14100Sstevel@tonic-gate if (ddi_copyout(&usbprn_devid32, (caddr_t)arg,
14110Sstevel@tonic-gate sizeof (struct ecpp_device_id32), flag)) {
14120Sstevel@tonic-gate err = EFAULT;
14130Sstevel@tonic-gate
14140Sstevel@tonic-gate break;
14150Sstevel@tonic-gate }
14160Sstevel@tonic-gate
14170Sstevel@tonic-gate break;
14180Sstevel@tonic-gate }
14190Sstevel@tonic-gate case DDI_MODEL_NONE:
14200Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &usbprn_devid,
14210Sstevel@tonic-gate sizeof (struct ecpp_device_id), flag)) {
14220Sstevel@tonic-gate err = EFAULT;
14230Sstevel@tonic-gate
14240Sstevel@tonic-gate break;
14250Sstevel@tonic-gate }
14260Sstevel@tonic-gate
14270Sstevel@tonic-gate if (usbprnp->usbprn_device_id == NULL) {
14280Sstevel@tonic-gate err = EIO;
14290Sstevel@tonic-gate
14300Sstevel@tonic-gate break;
14310Sstevel@tonic-gate }
14320Sstevel@tonic-gate ASSERT(usbprnp->usbprn_device_id_len > 2);
14330Sstevel@tonic-gate
14340Sstevel@tonic-gate usbprn_devid.rlen = usbprnp->usbprn_device_id_len - 2;
14350Sstevel@tonic-gate len = min(usbprn_devid.len, usbprn_devid.rlen);
14360Sstevel@tonic-gate
14370Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
14380Sstevel@tonic-gate usbprn_devid.addr, len, flag)) {
14390Sstevel@tonic-gate err = EFAULT;
14400Sstevel@tonic-gate
14410Sstevel@tonic-gate break;
14420Sstevel@tonic-gate }
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate if (ddi_copyout(&usbprn_devid, (caddr_t)arg,
14450Sstevel@tonic-gate sizeof (struct ecpp_device_id), flag)) {
14460Sstevel@tonic-gate err = EFAULT;
14470Sstevel@tonic-gate
14480Sstevel@tonic-gate break;
14490Sstevel@tonic-gate }
14500Sstevel@tonic-gate
14510Sstevel@tonic-gate break;
14520Sstevel@tonic-gate }
14530Sstevel@tonic-gate
14540Sstevel@tonic-gate break;
14550Sstevel@tonic-gate #else
14560Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &usbprn_devid,
14570Sstevel@tonic-gate sizeof (struct ecpp_device_id), flag)) {
14580Sstevel@tonic-gate err = EFAULT;
14590Sstevel@tonic-gate
14600Sstevel@tonic-gate break;
14610Sstevel@tonic-gate }
14620Sstevel@tonic-gate
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate if (usbprnp->usbprn_device_id == NULL) {
14650Sstevel@tonic-gate err = EIO;
14660Sstevel@tonic-gate
14670Sstevel@tonic-gate break;
14680Sstevel@tonic-gate }
14690Sstevel@tonic-gate ASSERT(usbprnp->usbprn_device_id_len > 2);
14700Sstevel@tonic-gate
14710Sstevel@tonic-gate usbprn_devid.rlen = usbprnp->usbprn_device_id_len - 2;
14720Sstevel@tonic-gate len = min(usbprn_devid.len, usbprn_devid.rlen);
14730Sstevel@tonic-gate
14740Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
14750Sstevel@tonic-gate usbprn_devid.addr, len, flag)) {
14760Sstevel@tonic-gate err = EFAULT;
14770Sstevel@tonic-gate
14780Sstevel@tonic-gate break;
14790Sstevel@tonic-gate }
14800Sstevel@tonic-gate
14810Sstevel@tonic-gate if (ddi_copyout(&usbprn_devid, (caddr_t)arg,
14820Sstevel@tonic-gate sizeof (struct ecpp_device_id), flag)) {
14830Sstevel@tonic-gate err = EFAULT;
14840Sstevel@tonic-gate
14850Sstevel@tonic-gate break;
14860Sstevel@tonic-gate }
14870Sstevel@tonic-gate
14880Sstevel@tonic-gate break;
14890Sstevel@tonic-gate #endif
14900Sstevel@tonic-gate case ECPPIOC_SETPARMS:
14910Sstevel@tonic-gate err = usbprn_setparms(usbprnp, arg, flag);
14920Sstevel@tonic-gate
14930Sstevel@tonic-gate break;
14940Sstevel@tonic-gate case ECPPIOC_GETPARMS:
14950Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
14960Sstevel@tonic-gate "usbprn_ioctl: ECPPIOC_GETPARMS(0x%x)", cmd);
14970Sstevel@tonic-gate
14980Sstevel@tonic-gate /* Get the parameters */
14990Sstevel@tonic-gate err = usbprn_getparms(usbprnp, arg, flag);
15000Sstevel@tonic-gate
15010Sstevel@tonic-gate break;
15020Sstevel@tonic-gate case BPPIOC_GETERR:
15030Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15040Sstevel@tonic-gate "usbprn_ioctl: ECPPIOC_GETERR(0x%x)", cmd);
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate /* Get the error state */
15070Sstevel@tonic-gate usbprn_geterr(usbprnp, arg, flag);
15080Sstevel@tonic-gate
15090Sstevel@tonic-gate break;
15100Sstevel@tonic-gate case BPPIOC_TESTIO:
15110Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15120Sstevel@tonic-gate "usbprn_ioctl: BPPIOC_TESTIO(0x%x)", cmd);
15130Sstevel@tonic-gate
15140Sstevel@tonic-gate /* Get the port status */
15150Sstevel@tonic-gate err = usbprn_testio(usbprnp, flag);
15160Sstevel@tonic-gate
15170Sstevel@tonic-gate break;
15180Sstevel@tonic-gate case PRNIOC_GET_IFCAP:
15190Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15200Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_IFCAP(0x%x)", cmd);
15210Sstevel@tonic-gate
15220Sstevel@tonic-gate /* get interface capabilities */
15230Sstevel@tonic-gate err = usbprn_prnio_get_ifcap(usbprnp, arg, flag);
15240Sstevel@tonic-gate
15250Sstevel@tonic-gate break;
15260Sstevel@tonic-gate case PRNIOC_SET_IFCAP:
15270Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15280Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_SET_IFCAP(0x%x)", cmd);
15290Sstevel@tonic-gate
15300Sstevel@tonic-gate /* get interface capabilities */
15310Sstevel@tonic-gate err = usbprn_prnio_set_ifcap(usbprnp, arg, flag);
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate break;
15340Sstevel@tonic-gate case PRNIOC_GET_IFINFO:
15350Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15360Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_IFINFO(0x%x)", cmd);
15370Sstevel@tonic-gate
15380Sstevel@tonic-gate /* get interface information */
15390Sstevel@tonic-gate err = usbprn_prnio_get_ifinfo(usbprnp, arg, flag);
15400Sstevel@tonic-gate
15410Sstevel@tonic-gate break;
15420Sstevel@tonic-gate case PRNIOC_GET_STATUS:
15430Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15440Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_STATUS(0x%x)", cmd);
15450Sstevel@tonic-gate
15460Sstevel@tonic-gate /* get prnio status */
15470Sstevel@tonic-gate err = usbprn_prnio_get_status(usbprnp, arg, flag);
15480Sstevel@tonic-gate
15490Sstevel@tonic-gate break;
15500Sstevel@tonic-gate case PRNIOC_GET_1284_DEVID:
15510Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15520Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_1284_DEVID(0x%x)", cmd);
15530Sstevel@tonic-gate
15540Sstevel@tonic-gate /* get device ID */
15550Sstevel@tonic-gate err = usbprn_prnio_get_1284_devid(usbprnp, arg, flag);
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate break;
15580Sstevel@tonic-gate case PRNIOC_GET_1284_STATUS:
15590Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15600Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_1284_STATUS(0x%x)", cmd);
15610Sstevel@tonic-gate
15620Sstevel@tonic-gate /* get prnio status */
15630Sstevel@tonic-gate err = usbprn_prnio_get_1284_status(usbprnp, arg, flag);
15640Sstevel@tonic-gate
15650Sstevel@tonic-gate break;
15660Sstevel@tonic-gate case PRNIOC_GET_TIMEOUTS:
15670Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15680Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_TIMEOUTS(0x%x)", cmd);
15690Sstevel@tonic-gate
15700Sstevel@tonic-gate /* Get the parameters */
15710Sstevel@tonic-gate err = usbprn_prnio_get_timeouts(usbprnp, arg, flag);
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate break;
15740Sstevel@tonic-gate case PRNIOC_SET_TIMEOUTS:
15750Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15760Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_SET_TIMEOUTS(0x%x)", cmd);
15770Sstevel@tonic-gate
15780Sstevel@tonic-gate /* Get the parameters */
15790Sstevel@tonic-gate err = usbprn_prnio_set_timeouts(usbprnp, arg, flag);
15800Sstevel@tonic-gate
15810Sstevel@tonic-gate break;
15820Sstevel@tonic-gate case PRNIOC_RESET:
15830Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15840Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_RESET(0x%x)", cmd);
15850Sstevel@tonic-gate
15860Sstevel@tonic-gate /* nothing */
15870Sstevel@tonic-gate err = 0;
15880Sstevel@tonic-gate
15890Sstevel@tonic-gate break;
15900Sstevel@tonic-gate default:
15910Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15920Sstevel@tonic-gate "usbprn_ioctl: unknown(0x%x)", cmd);
15930Sstevel@tonic-gate err = EINVAL;
15940Sstevel@tonic-gate }
15950Sstevel@tonic-gate
15960Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
15970Sstevel@tonic-gate
15980Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15990Sstevel@tonic-gate "usbprn_ioctl: End ");
16000Sstevel@tonic-gate
16010Sstevel@tonic-gate return (err);
16020Sstevel@tonic-gate }
16030Sstevel@tonic-gate
16040Sstevel@tonic-gate
16050Sstevel@tonic-gate /*
16060Sstevel@tonic-gate * breakup by physio
16070Sstevel@tonic-gate */
16080Sstevel@tonic-gate static void
usbprn_minphys(struct buf * bp)16090Sstevel@tonic-gate usbprn_minphys(struct buf *bp)
16100Sstevel@tonic-gate {
16110Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
16126898Sfb209375 USBPRN_MINOR_TO_INSTANCE(getminor(bp->b_edev)));
16130Sstevel@tonic-gate
16140Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
16150Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
16160Sstevel@tonic-gate "usbprn_minphys: bcount=%lu", bp->b_bcount);
16170Sstevel@tonic-gate
16180Sstevel@tonic-gate if (bp->b_bcount > usbprnp->usbprn_max_bulk_xfer_size) {
16190Sstevel@tonic-gate bp->b_bcount = min(usbprn_max_xfer_size,
16200Sstevel@tonic-gate usbprnp->usbprn_max_bulk_xfer_size);
16210Sstevel@tonic-gate } else {
16220Sstevel@tonic-gate bp->b_bcount = min(usbprn_max_xfer_size, bp->b_bcount);
16230Sstevel@tonic-gate }
16240Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate
16270Sstevel@tonic-gate
16280Sstevel@tonic-gate /*
16290Sstevel@tonic-gate * usbprn_open_usb_pipes:
16300Sstevel@tonic-gate * Open all pipes on the device
16310Sstevel@tonic-gate */
16320Sstevel@tonic-gate static int
usbprn_open_usb_pipes(usbprn_state_t * usbprnp)16330Sstevel@tonic-gate usbprn_open_usb_pipes(usbprn_state_t *usbprnp)
16340Sstevel@tonic-gate {
16350Sstevel@tonic-gate usb_pipe_policy_t *policy;
16360Sstevel@tonic-gate usbprn_ps_t *bulk_in = &usbprnp->usbprn_bulk_in;
16370Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
16380Sstevel@tonic-gate
16390Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
16400Sstevel@tonic-gate "usbprn_open_usb_pipes:");
16410Sstevel@tonic-gate
16420Sstevel@tonic-gate /*
16430Sstevel@tonic-gate * Intitialize the pipe policy for the bulk out pipe
16440Sstevel@tonic-gate */
16450Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
16460Sstevel@tonic-gate policy = &(bulk_out->ps_policy);
16470Sstevel@tonic-gate policy->pp_max_async_reqs = 1;
16480Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16490Sstevel@tonic-gate
16500Sstevel@tonic-gate /* Open bulk_out pipe */
16510Sstevel@tonic-gate if (usb_pipe_open(usbprnp->usbprn_dip, &bulk_out->ps_ept_descr,
16520Sstevel@tonic-gate policy, USB_FLAGS_SLEEP, &bulk_out->ps_handle) != USB_SUCCESS) {
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate return (USB_FAILURE);
16550Sstevel@tonic-gate }
16560Sstevel@tonic-gate
16570Sstevel@tonic-gate #ifdef LATER
16580Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
16590Sstevel@tonic-gate /* Open the bulk in pipe if one exists */
16600Sstevel@tonic-gate if (bulk_in->ps_ept_descr->bLength) {
16610Sstevel@tonic-gate /*
16620Sstevel@tonic-gate * Initialize the pipe policy for the Bulk In pipe
16630Sstevel@tonic-gate */
16640Sstevel@tonic-gate policy = &bulk_in->ps_policy;
16650Sstevel@tonic-gate bulk_in->ps_flags = USBPRN_PS_IDLE;
16660Sstevel@tonic-gate policy->pp_max_async_reqs = 1;
16670Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate /* Open bulk_in pipe */
16700Sstevel@tonic-gate if (usb_pipe_open(usbprnp->usbprn_dip, bulk_in->ps_ept_descr,
16710Sstevel@tonic-gate policy, USB_FLAGS_SLEEP, &bulk_in->ps_handle) !=
16720Sstevel@tonic-gate USB_SUCCESS) {
16730Sstevel@tonic-gate
16740Sstevel@tonic-gate return (USB_FAILURE);
16750Sstevel@tonic-gate }
16760Sstevel@tonic-gate } else {
16770Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16780Sstevel@tonic-gate }
16790Sstevel@tonic-gate #else
16800Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
16810Sstevel@tonic-gate bulk_in->ps_flags = USBPRN_PS_IDLE;
16820Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16830Sstevel@tonic-gate #endif
16840Sstevel@tonic-gate
16850Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
16860Sstevel@tonic-gate "usbprn_open_usb_pipes: success");
16870Sstevel@tonic-gate
16880Sstevel@tonic-gate return (USB_SUCCESS);
16890Sstevel@tonic-gate }
16900Sstevel@tonic-gate
16910Sstevel@tonic-gate
16920Sstevel@tonic-gate /*
16930Sstevel@tonic-gate * usbprn_close_usb_pipes:
16940Sstevel@tonic-gate * Close the default/bulk in/out pipes synchronously
16950Sstevel@tonic-gate */
16960Sstevel@tonic-gate static void
usbprn_close_usb_pipes(usbprn_state_t * usbprnp)16970Sstevel@tonic-gate usbprn_close_usb_pipes(usbprn_state_t *usbprnp)
16980Sstevel@tonic-gate {
16990Sstevel@tonic-gate usbprn_ps_t *bulk_in = &usbprnp->usbprn_bulk_in;
17000Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
17010Sstevel@tonic-gate
17020Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
17030Sstevel@tonic-gate "usbprn_close_usb_pipes:");
17040Sstevel@tonic-gate #ifdef DEBUG
17050Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
17060Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
17070Sstevel@tonic-gate ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
17080Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
17090Sstevel@tonic-gate #endif
17100Sstevel@tonic-gate
17110Sstevel@tonic-gate /*
17120Sstevel@tonic-gate * close the pipe, if another thread is already closing the
17130Sstevel@tonic-gate * pipe, we get USB_INVALID_PIPE
17140Sstevel@tonic-gate */
17150Sstevel@tonic-gate if (bulk_out->ps_handle) {
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
17180Sstevel@tonic-gate "usbprn_close_usb_pipes: Closing bulk out pipe");
17190Sstevel@tonic-gate
17200Sstevel@tonic-gate usb_pipe_close(usbprnp->usbprn_dip, bulk_out->ps_handle,
17216898Sfb209375 USB_FLAGS_SLEEP, NULL, NULL);
17220Sstevel@tonic-gate bulk_out->ps_handle = NULL;
17230Sstevel@tonic-gate }
17240Sstevel@tonic-gate if (bulk_in->ps_handle) {
17250Sstevel@tonic-gate
17260Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
17270Sstevel@tonic-gate "usbprn_close_usb_pipes: Closing bulk in pipe");
17280Sstevel@tonic-gate
17290Sstevel@tonic-gate usb_pipe_close(usbprnp->usbprn_dip, bulk_in->ps_handle,
17306898Sfb209375 USB_FLAGS_SLEEP, NULL, NULL);
17310Sstevel@tonic-gate bulk_in->ps_handle = NULL;
17320Sstevel@tonic-gate }
17330Sstevel@tonic-gate }
17340Sstevel@tonic-gate
17350Sstevel@tonic-gate
17360Sstevel@tonic-gate /*
17370Sstevel@tonic-gate * usbprn_getparms:
17380Sstevel@tonic-gate * Get the parameters for the device
17390Sstevel@tonic-gate */
17400Sstevel@tonic-gate static int
usbprn_getparms(usbprn_state_t * usbprnp,intptr_t arg,int flag)17410Sstevel@tonic-gate usbprn_getparms(usbprn_state_t *usbprnp, intptr_t arg, int flag)
17420Sstevel@tonic-gate {
17430Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
17440Sstevel@tonic-gate
17450Sstevel@tonic-gate if (ddi_copyout(&usbprnp->usbprn_setparms,
17460Sstevel@tonic-gate (caddr_t)arg, sizeof (struct ecpp_transfer_parms), flag)) {
17470Sstevel@tonic-gate
17480Sstevel@tonic-gate return (EFAULT);
17490Sstevel@tonic-gate }
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate return (0);
17520Sstevel@tonic-gate }
17530Sstevel@tonic-gate
17540Sstevel@tonic-gate
17550Sstevel@tonic-gate /*
17560Sstevel@tonic-gate * usbprn_setparms:
17570Sstevel@tonic-gate * Set the parameters for the device
17580Sstevel@tonic-gate */
17590Sstevel@tonic-gate static int
usbprn_setparms(usbprn_state_t * usbprnp,intptr_t arg,int flag)17600Sstevel@tonic-gate usbprn_setparms(usbprn_state_t *usbprnp, intptr_t arg, int flag)
17610Sstevel@tonic-gate {
17620Sstevel@tonic-gate struct ecpp_transfer_parms xfer;
17630Sstevel@tonic-gate
17640Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
17650Sstevel@tonic-gate
17660Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &xfer,
17670Sstevel@tonic-gate sizeof (struct ecpp_transfer_parms), flag)) {
17680Sstevel@tonic-gate
17690Sstevel@tonic-gate return (EFAULT);
17700Sstevel@tonic-gate }
17710Sstevel@tonic-gate if ((xfer.write_timeout < USBPRN_XFER_TIMEOUT_MIN) ||
17720Sstevel@tonic-gate (xfer.write_timeout > USBPRN_XFER_TIMEOUT_MAX)) {
17730Sstevel@tonic-gate
17740Sstevel@tonic-gate return (EINVAL);
17750Sstevel@tonic-gate }
17760Sstevel@tonic-gate if (!((xfer.mode == ECPP_CENTRONICS) ||
17770Sstevel@tonic-gate (xfer.mode == ECPP_COMPAT_MODE) ||
17780Sstevel@tonic-gate (xfer.mode == ECPP_NIBBLE_MODE) ||
17790Sstevel@tonic-gate (xfer.mode == ECPP_ECP_MODE) ||
17800Sstevel@tonic-gate (xfer.mode == ECPP_DIAG_MODE))) {
17810Sstevel@tonic-gate
17820Sstevel@tonic-gate return (EINVAL);
17830Sstevel@tonic-gate
17840Sstevel@tonic-gate }
17850Sstevel@tonic-gate if (xfer.mode != ECPP_CENTRONICS) {
17860Sstevel@tonic-gate
17870Sstevel@tonic-gate return (EPROTONOSUPPORT);
17880Sstevel@tonic-gate }
17890Sstevel@tonic-gate
17900Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
17910Sstevel@tonic-gate usbprnp->usbprn_setparms = xfer;
17920Sstevel@tonic-gate usbprnp->usbprn_prn_timeouts.tmo_forward = xfer.write_timeout;
17930Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
17940Sstevel@tonic-gate
17950Sstevel@tonic-gate return (0);
17960Sstevel@tonic-gate }
17970Sstevel@tonic-gate
17980Sstevel@tonic-gate
17990Sstevel@tonic-gate /*
18000Sstevel@tonic-gate * usbprn_geterr:
18010Sstevel@tonic-gate * Return the any device error state
18020Sstevel@tonic-gate */
18030Sstevel@tonic-gate static void
usbprn_geterr(usbprn_state_t * usbprnp,intptr_t arg,int flag)18040Sstevel@tonic-gate usbprn_geterr(usbprn_state_t *usbprnp, intptr_t arg, int flag)
18050Sstevel@tonic-gate {
18060Sstevel@tonic-gate struct bpp_error_status bpp_status;
18070Sstevel@tonic-gate
18080Sstevel@tonic-gate bzero(&bpp_status, sizeof (bpp_status));
18090Sstevel@tonic-gate
18100Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
18110Sstevel@tonic-gate bpp_status.bus_error = 0;
18120Sstevel@tonic-gate bpp_status.timeout_occurred = 0;
18130Sstevel@tonic-gate bpp_status.pin_status = usbprn_error_state(usbprnp->usbprn_last_status);
18140Sstevel@tonic-gate
18150Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
18160Sstevel@tonic-gate "usbprn_geterr: status=0x%x", usbprnp->usbprn_last_status);
18170Sstevel@tonic-gate
18180Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
18190Sstevel@tonic-gate
18200Sstevel@tonic-gate (void) ddi_copyout(&bpp_status,
18210Sstevel@tonic-gate (caddr_t)arg, sizeof (struct bpp_error_status), flag);
18220Sstevel@tonic-gate }
18230Sstevel@tonic-gate
18240Sstevel@tonic-gate
18250Sstevel@tonic-gate /*
18260Sstevel@tonic-gate * usbprn_error_state:
18270Sstevel@tonic-gate * Map the driver error state to that of the application
18280Sstevel@tonic-gate */
18290Sstevel@tonic-gate static char
usbprn_error_state(uchar_t status)18300Sstevel@tonic-gate usbprn_error_state(uchar_t status)
18310Sstevel@tonic-gate {
18320Sstevel@tonic-gate uchar_t app_err_status = 0;
18330Sstevel@tonic-gate
18340Sstevel@tonic-gate if (!(status & USB_PRINTER_PORT_NO_ERROR)) {
18350Sstevel@tonic-gate app_err_status |= USB_PRINTER_ERR_ERR;
18360Sstevel@tonic-gate }
18370Sstevel@tonic-gate if (status & USB_PRINTER_PORT_EMPTY) {
18380Sstevel@tonic-gate app_err_status |= USB_PRINTER_PE_ERR;
18390Sstevel@tonic-gate }
18400Sstevel@tonic-gate if (!(status & USB_PRINTER_PORT_NO_SELECT)) {
18410Sstevel@tonic-gate app_err_status |= USB_PRINTER_SLCT_ERR;
18420Sstevel@tonic-gate }
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate return (app_err_status);
18450Sstevel@tonic-gate }
18460Sstevel@tonic-gate
18470Sstevel@tonic-gate
18480Sstevel@tonic-gate static int
usbprn_ioctl_get_status(usbprn_state_t * usbprnp)18490Sstevel@tonic-gate usbprn_ioctl_get_status(usbprn_state_t *usbprnp)
18500Sstevel@tonic-gate {
18510Sstevel@tonic-gate /* Check the transfer mode */
18520Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
18530Sstevel@tonic-gate
18540Sstevel@tonic-gate /* if device is disconnected or pipes closed, fail immediately */
18550Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
18560Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
18570Sstevel@tonic-gate
18580Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
18590Sstevel@tonic-gate "usbprn_ioctl_get_status: device can't be accessed");
18600Sstevel@tonic-gate
18610Sstevel@tonic-gate return (EIO);
18620Sstevel@tonic-gate }
18630Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
18640Sstevel@tonic-gate
18650Sstevel@tonic-gate if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
18660Sstevel@tonic-gate
18670Sstevel@tonic-gate return (EIO);
18680Sstevel@tonic-gate }
18690Sstevel@tonic-gate
18700Sstevel@tonic-gate return (0);
18710Sstevel@tonic-gate }
18720Sstevel@tonic-gate
18730Sstevel@tonic-gate
18740Sstevel@tonic-gate /*
18750Sstevel@tonic-gate * usbprn_testio:
18760Sstevel@tonic-gate * Execute the ECPP_TESTIO ioctl
18770Sstevel@tonic-gate */
18780Sstevel@tonic-gate /* ARGSUSED1 */
18790Sstevel@tonic-gate static int
usbprn_testio(usbprn_state_t * usbprnp,int flag)18800Sstevel@tonic-gate usbprn_testio(usbprn_state_t *usbprnp, int flag)
18810Sstevel@tonic-gate {
18820Sstevel@tonic-gate int err;
18830Sstevel@tonic-gate
18840Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
18850Sstevel@tonic-gate "usbprn_testio: begin");
18860Sstevel@tonic-gate
18870Sstevel@tonic-gate if ((err = usbprn_ioctl_get_status(usbprnp)) != 0) {
18880Sstevel@tonic-gate
18890Sstevel@tonic-gate return (err);
18900Sstevel@tonic-gate }
18910Sstevel@tonic-gate
18920Sstevel@tonic-gate /* There is an error. Return it to the user */
18930Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
18940Sstevel@tonic-gate
18950Sstevel@tonic-gate if (usbprn_error_state(usbprnp->usbprn_last_status) != 0) {
18960Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
18970Sstevel@tonic-gate
18980Sstevel@tonic-gate return (EIO);
18990Sstevel@tonic-gate
19000Sstevel@tonic-gate } else {
19010Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
19020Sstevel@tonic-gate
19030Sstevel@tonic-gate return (0);
19040Sstevel@tonic-gate }
19050Sstevel@tonic-gate }
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate
19080Sstevel@tonic-gate /*
19090Sstevel@tonic-gate * usbprn_prnio_get_status:
19100Sstevel@tonic-gate * Execute the PRNIOC_GET_STATUS ioctl
19110Sstevel@tonic-gate */
19120Sstevel@tonic-gate static int
usbprn_prnio_get_status(usbprn_state_t * usbprnp,intptr_t arg,int flag)19130Sstevel@tonic-gate usbprn_prnio_get_status(usbprn_state_t *usbprnp, intptr_t arg, int flag)
19140Sstevel@tonic-gate {
19150Sstevel@tonic-gate uint_t prnio_status = 0;
19160Sstevel@tonic-gate int err;
19170Sstevel@tonic-gate
19180Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
19190Sstevel@tonic-gate "usbprn_prnio_get_status: begin");
19200Sstevel@tonic-gate
19210Sstevel@tonic-gate /* capture printer status */
19220Sstevel@tonic-gate err = usbprn_ioctl_get_status(usbprnp);
19230Sstevel@tonic-gate
19240Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
19250Sstevel@tonic-gate
19260Sstevel@tonic-gate if (usbprnp->usbprn_dev_state == USB_DEV_ONLINE) {
19270Sstevel@tonic-gate prnio_status |= PRN_ONLINE;
19280Sstevel@tonic-gate }
19290Sstevel@tonic-gate if ((err == 0) &&
19300Sstevel@tonic-gate (usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR)) {
19310Sstevel@tonic-gate prnio_status |= PRN_READY;
19320Sstevel@tonic-gate }
19330Sstevel@tonic-gate
19340Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
19350Sstevel@tonic-gate
19360Sstevel@tonic-gate if (ddi_copyout(&prnio_status,
19370Sstevel@tonic-gate (caddr_t)arg, sizeof (prnio_status), flag)) {
19380Sstevel@tonic-gate
19390Sstevel@tonic-gate return (EFAULT);
19400Sstevel@tonic-gate }
19410Sstevel@tonic-gate
19420Sstevel@tonic-gate return (0);
19430Sstevel@tonic-gate }
19440Sstevel@tonic-gate
19450Sstevel@tonic-gate
19460Sstevel@tonic-gate /*
19470Sstevel@tonic-gate * usbprn_prnio_get_1284_status:
19480Sstevel@tonic-gate * Execute the PRNIOC_GET_1284_STATUS ioctl
19490Sstevel@tonic-gate */
19500Sstevel@tonic-gate static int
usbprn_prnio_get_1284_status(usbprn_state_t * usbprnp,intptr_t arg,int flag)19510Sstevel@tonic-gate usbprn_prnio_get_1284_status(usbprn_state_t *usbprnp, intptr_t arg, int flag)
19520Sstevel@tonic-gate {
19530Sstevel@tonic-gate uchar_t status;
19540Sstevel@tonic-gate int err;
19550Sstevel@tonic-gate
19560Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
19570Sstevel@tonic-gate "usbprn_prnio_get_1284_status: begin");
19580Sstevel@tonic-gate
19590Sstevel@tonic-gate if ((err = usbprn_ioctl_get_status(usbprnp)) != 0) {
19600Sstevel@tonic-gate
19610Sstevel@tonic-gate return (err);
19620Sstevel@tonic-gate }
19630Sstevel@tonic-gate
19640Sstevel@tonic-gate /* status was captured successfully */
19650Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
19660Sstevel@tonic-gate
19670Sstevel@tonic-gate status = usbprnp->usbprn_last_status & (USB_PRINTER_PORT_NO_ERROR |
19686898Sfb209375 USB_PRINTER_PORT_NO_SELECT | USB_PRINTER_PORT_EMPTY);
19690Sstevel@tonic-gate
19700Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
19710Sstevel@tonic-gate
19720Sstevel@tonic-gate if (ddi_copyout(&status, (caddr_t)arg, sizeof (status), flag)) {
19730Sstevel@tonic-gate
19740Sstevel@tonic-gate return (EFAULT);
19750Sstevel@tonic-gate }
19760Sstevel@tonic-gate
19770Sstevel@tonic-gate return (0);
19780Sstevel@tonic-gate }
19790Sstevel@tonic-gate
19800Sstevel@tonic-gate
19810Sstevel@tonic-gate /*
19820Sstevel@tonic-gate * usbprn_prnio_get_ifcap:
19830Sstevel@tonic-gate * Execute the PRNIOC_GET_IFCAP ioctl
19840Sstevel@tonic-gate */
19850Sstevel@tonic-gate /* ARGSUSED */
19860Sstevel@tonic-gate static int
usbprn_prnio_get_ifcap(usbprn_state_t * usbprnp,intptr_t arg,int flag)19870Sstevel@tonic-gate usbprn_prnio_get_ifcap(usbprn_state_t *usbprnp, intptr_t arg, int flag)
19880Sstevel@tonic-gate {
19890Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
19900Sstevel@tonic-gate
19910Sstevel@tonic-gate if (ddi_copyout(&usbprn_ifcap, (caddr_t)arg, sizeof (usbprn_ifcap),
19920Sstevel@tonic-gate flag)) {
19930Sstevel@tonic-gate
19940Sstevel@tonic-gate return (EFAULT);
19950Sstevel@tonic-gate }
19960Sstevel@tonic-gate
19970Sstevel@tonic-gate return (0);
19980Sstevel@tonic-gate }
19990Sstevel@tonic-gate
20000Sstevel@tonic-gate
20010Sstevel@tonic-gate /*
20020Sstevel@tonic-gate * usbprn_prnio_get_ifcap:
20030Sstevel@tonic-gate * Execute the PRNIOC_SET_IFCAP ioctl
20040Sstevel@tonic-gate */
20050Sstevel@tonic-gate /* ARGSUSED */
20060Sstevel@tonic-gate static int
usbprn_prnio_set_ifcap(usbprn_state_t * usbprnp,intptr_t arg,int flag)20070Sstevel@tonic-gate usbprn_prnio_set_ifcap(usbprn_state_t *usbprnp, intptr_t arg, int flag)
20080Sstevel@tonic-gate {
20090Sstevel@tonic-gate uint_t new_ifcap;
20100Sstevel@tonic-gate
20110Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
20120Sstevel@tonic-gate
20130Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &new_ifcap, sizeof (new_ifcap), flag)) {
20140Sstevel@tonic-gate
20150Sstevel@tonic-gate return (EFAULT);
20160Sstevel@tonic-gate }
20170Sstevel@tonic-gate
20180Sstevel@tonic-gate /* no settable capabilities */
20190Sstevel@tonic-gate if (usbprn_ifcap != new_ifcap) {
20200Sstevel@tonic-gate
20210Sstevel@tonic-gate return (EINVAL);
20220Sstevel@tonic-gate }
20230Sstevel@tonic-gate
20240Sstevel@tonic-gate return (0);
20250Sstevel@tonic-gate }
20260Sstevel@tonic-gate
20270Sstevel@tonic-gate
20280Sstevel@tonic-gate /*
20290Sstevel@tonic-gate * usbprn_prnio_get_ifinfo:
20300Sstevel@tonic-gate * Execute the PRNIOC_GET_IFINFO ioctl
20310Sstevel@tonic-gate */
20320Sstevel@tonic-gate /* ARGSUSED */
20330Sstevel@tonic-gate static int
usbprn_prnio_get_ifinfo(usbprn_state_t * usbprnp,intptr_t arg,int flag)20340Sstevel@tonic-gate usbprn_prnio_get_ifinfo(usbprn_state_t *usbprnp, intptr_t arg, int flag)
20350Sstevel@tonic-gate {
20360Sstevel@tonic-gate struct prn_interface_info prn_info;
20370Sstevel@tonic-gate int rlen, len;
20380Sstevel@tonic-gate
20390Sstevel@tonic-gate rlen = strlen(usbprn_prnio_ifinfo);
20400Sstevel@tonic-gate
20410Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
20420Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
20430Sstevel@tonic-gate
20440Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) {
20450Sstevel@tonic-gate case DDI_MODEL_ILP32: {
20460Sstevel@tonic-gate struct prn_interface_info32 prn_info32;
20470Sstevel@tonic-gate
20480Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_info32,
20490Sstevel@tonic-gate sizeof (struct prn_interface_info32), flag)) {
20500Sstevel@tonic-gate
20510Sstevel@tonic-gate return (EFAULT);
20520Sstevel@tonic-gate }
20530Sstevel@tonic-gate
20540Sstevel@tonic-gate prn_info32.if_rlen = rlen;
20550Sstevel@tonic-gate len = min(rlen, prn_info32.if_len);
20560Sstevel@tonic-gate
20570Sstevel@tonic-gate if (ddi_copyout(&usbprn_prnio_ifinfo[0],
20580Sstevel@tonic-gate (caddr_t)(uintptr_t)prn_info32.if_data, len, flag)) {
20590Sstevel@tonic-gate
20600Sstevel@tonic-gate return (EFAULT);
20610Sstevel@tonic-gate }
20620Sstevel@tonic-gate
20630Sstevel@tonic-gate if (ddi_copyout(&prn_info32, (caddr_t)arg,
20640Sstevel@tonic-gate sizeof (struct prn_interface_info32), flag)) {
20650Sstevel@tonic-gate
20660Sstevel@tonic-gate return (EFAULT);
20670Sstevel@tonic-gate }
20680Sstevel@tonic-gate
20690Sstevel@tonic-gate break;
20700Sstevel@tonic-gate }
20710Sstevel@tonic-gate case DDI_MODEL_NONE:
20720Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
20730Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
20740Sstevel@tonic-gate
20750Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_info,
20760Sstevel@tonic-gate sizeof (struct prn_interface_info), flag)) {
20770Sstevel@tonic-gate
20780Sstevel@tonic-gate return (EFAULT);
20790Sstevel@tonic-gate }
20800Sstevel@tonic-gate
20810Sstevel@tonic-gate prn_info.if_rlen = rlen;
20820Sstevel@tonic-gate len = min(rlen, prn_info.if_len);
20830Sstevel@tonic-gate
20840Sstevel@tonic-gate if (ddi_copyout(&usbprn_prnio_ifinfo[0],
20850Sstevel@tonic-gate prn_info.if_data, len, flag)) {
20860Sstevel@tonic-gate
20870Sstevel@tonic-gate return (EFAULT);
20880Sstevel@tonic-gate }
20890Sstevel@tonic-gate
20900Sstevel@tonic-gate if (ddi_copyout(&prn_info, (caddr_t)arg,
20910Sstevel@tonic-gate sizeof (struct prn_interface_info), flag)) {
20920Sstevel@tonic-gate
20930Sstevel@tonic-gate return (EFAULT);
20940Sstevel@tonic-gate }
20950Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
20960Sstevel@tonic-gate
20970Sstevel@tonic-gate break;
20980Sstevel@tonic-gate }
20990Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
21000Sstevel@tonic-gate
21010Sstevel@tonic-gate return (0);
21020Sstevel@tonic-gate }
21030Sstevel@tonic-gate
21040Sstevel@tonic-gate
21050Sstevel@tonic-gate /*
21060Sstevel@tonic-gate * usbprn_prnio_getdevid:
21070Sstevel@tonic-gate * Execute the PRNIOC_GET_1284_DEVID ioctl
21080Sstevel@tonic-gate */
21090Sstevel@tonic-gate static int
usbprn_prnio_get_1284_devid(usbprn_state_t * usbprnp,intptr_t arg,int flag)21100Sstevel@tonic-gate usbprn_prnio_get_1284_devid(usbprn_state_t *usbprnp, intptr_t arg, int flag)
21110Sstevel@tonic-gate {
21120Sstevel@tonic-gate struct prn_1284_device_id prn_devid;
21130Sstevel@tonic-gate int len;
21140Sstevel@tonic-gate
21150Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
21160Sstevel@tonic-gate
21170Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
21180Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) {
21190Sstevel@tonic-gate case DDI_MODEL_ILP32: {
21200Sstevel@tonic-gate struct prn_1284_device_id32 prn_devid32;
21210Sstevel@tonic-gate
21220Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_devid32,
21230Sstevel@tonic-gate sizeof (struct prn_1284_device_id32), flag)) {
21240Sstevel@tonic-gate
21250Sstevel@tonic-gate return (EFAULT);
21260Sstevel@tonic-gate }
21270Sstevel@tonic-gate
21280Sstevel@tonic-gate prn_devid32.id_rlen = usbprnp->usbprn_device_id_len - 2;
21290Sstevel@tonic-gate len = min(prn_devid32.id_rlen, prn_devid32.id_len);
21300Sstevel@tonic-gate
21310Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
21320Sstevel@tonic-gate (caddr_t)(uintptr_t)prn_devid32.id_data, len, flag)) {
21330Sstevel@tonic-gate
21340Sstevel@tonic-gate return (EFAULT);
21350Sstevel@tonic-gate }
21360Sstevel@tonic-gate
21370Sstevel@tonic-gate if (ddi_copyout(&prn_devid32, (caddr_t)arg,
21380Sstevel@tonic-gate sizeof (struct prn_1284_device_id32), flag)) {
21390Sstevel@tonic-gate
21400Sstevel@tonic-gate return (EFAULT);
21410Sstevel@tonic-gate }
21420Sstevel@tonic-gate
21430Sstevel@tonic-gate break;
21440Sstevel@tonic-gate }
21450Sstevel@tonic-gate case DDI_MODEL_NONE:
21460Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
21470Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_devid,
21480Sstevel@tonic-gate sizeof (struct prn_1284_device_id), flag)) {
21490Sstevel@tonic-gate
21500Sstevel@tonic-gate return (EFAULT);
21510Sstevel@tonic-gate }
21520Sstevel@tonic-gate
21530Sstevel@tonic-gate prn_devid.id_rlen = usbprnp->usbprn_device_id_len - 2;
21540Sstevel@tonic-gate len = min(prn_devid.id_rlen, prn_devid.id_len);
21550Sstevel@tonic-gate
21560Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
21570Sstevel@tonic-gate prn_devid.id_data, len, flag)) {
21580Sstevel@tonic-gate
21590Sstevel@tonic-gate return (EFAULT);
21600Sstevel@tonic-gate }
21610Sstevel@tonic-gate
21620Sstevel@tonic-gate if (ddi_copyout(&prn_devid, (caddr_t)arg,
21630Sstevel@tonic-gate sizeof (struct prn_1284_device_id), flag)) {
21640Sstevel@tonic-gate
21650Sstevel@tonic-gate return (EFAULT);
21660Sstevel@tonic-gate }
21670Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
21680Sstevel@tonic-gate
21690Sstevel@tonic-gate break;
21700Sstevel@tonic-gate }
21710Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
21720Sstevel@tonic-gate
21730Sstevel@tonic-gate return (0);
21740Sstevel@tonic-gate }
21750Sstevel@tonic-gate
21760Sstevel@tonic-gate
21770Sstevel@tonic-gate /*
21780Sstevel@tonic-gate * usbprn_prnio_get_timeouts:
21790Sstevel@tonic-gate * Return timeout
21800Sstevel@tonic-gate */
21810Sstevel@tonic-gate static int
usbprn_prnio_get_timeouts(usbprn_state_t * usbprnp,intptr_t arg,int flag)21820Sstevel@tonic-gate usbprn_prnio_get_timeouts(usbprn_state_t *usbprnp, intptr_t arg, int flag)
21830Sstevel@tonic-gate {
21840Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
21850Sstevel@tonic-gate
21860Sstevel@tonic-gate if (ddi_copyout(&usbprnp->usbprn_prn_timeouts,
21870Sstevel@tonic-gate (caddr_t)arg, sizeof (struct prn_timeouts), flag)) {
21880Sstevel@tonic-gate
21890Sstevel@tonic-gate return (EFAULT);
21900Sstevel@tonic-gate }
21910Sstevel@tonic-gate
21920Sstevel@tonic-gate return (0);
21930Sstevel@tonic-gate }
21940Sstevel@tonic-gate
21950Sstevel@tonic-gate
21960Sstevel@tonic-gate /*
21970Sstevel@tonic-gate * usbprn_prnio_set_timeouts:
21980Sstevel@tonic-gate * Set write timeout and prn timeout
21990Sstevel@tonic-gate */
22000Sstevel@tonic-gate static int
usbprn_prnio_set_timeouts(usbprn_state_t * usbprnp,intptr_t arg,int flag)22010Sstevel@tonic-gate usbprn_prnio_set_timeouts(usbprn_state_t *usbprnp, intptr_t arg, int flag)
22020Sstevel@tonic-gate {
22030Sstevel@tonic-gate struct prn_timeouts prn_timeouts;
22040Sstevel@tonic-gate
22050Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
22060Sstevel@tonic-gate
22070Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_timeouts,
22080Sstevel@tonic-gate sizeof (struct prn_timeouts), flag)) {
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate return (EFAULT);
22110Sstevel@tonic-gate }
22120Sstevel@tonic-gate
22130Sstevel@tonic-gate if ((prn_timeouts.tmo_forward < USBPRN_XFER_TIMEOUT_MIN) ||
22140Sstevel@tonic-gate (prn_timeouts.tmo_forward > USBPRN_XFER_TIMEOUT_MAX)) {
22150Sstevel@tonic-gate
22160Sstevel@tonic-gate return (EINVAL);
22170Sstevel@tonic-gate }
22180Sstevel@tonic-gate
22190Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
22200Sstevel@tonic-gate
22210Sstevel@tonic-gate usbprnp->usbprn_prn_timeouts = prn_timeouts;
22220Sstevel@tonic-gate usbprnp->usbprn_setparms.write_timeout = prn_timeouts.tmo_forward;
22230Sstevel@tonic-gate
22240Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
22250Sstevel@tonic-gate
22260Sstevel@tonic-gate return (0);
22270Sstevel@tonic-gate }
22280Sstevel@tonic-gate
22290Sstevel@tonic-gate
22300Sstevel@tonic-gate /*
22310Sstevel@tonic-gate * usbprn_biodone:
22320Sstevel@tonic-gate * If there is a bp, complete it
22330Sstevel@tonic-gate */
22340Sstevel@tonic-gate static void
usbprn_biodone(usbprn_state_t * usbprnp,int err,int bytes_remaining)22350Sstevel@tonic-gate usbprn_biodone(usbprn_state_t *usbprnp, int err, int bytes_remaining)
22360Sstevel@tonic-gate {
22370Sstevel@tonic-gate struct buf *bp = usbprnp->usbprn_bp;
22380Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
22390Sstevel@tonic-gate usbprn_ps_t *bulk_in = &usbprnp->usbprn_bulk_in;
22400Sstevel@tonic-gate
22410Sstevel@tonic-gate ASSERT(mutex_owned(&usbprnp->usbprn_mutex));
22420Sstevel@tonic-gate
22430Sstevel@tonic-gate /* all pipes must be idle now */
22440Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
22450Sstevel@tonic-gate ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
22460Sstevel@tonic-gate
22470Sstevel@tonic-gate if (bp) {
22480Sstevel@tonic-gate bp->b_resid = bytes_remaining;
22490Sstevel@tonic-gate
22500Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
22510Sstevel@tonic-gate "usbprn_biodone: "
22520Sstevel@tonic-gate "bp=0x%p bcount=0x%lx resid=0x%lx remaining=0x%x err=%d",
22530Sstevel@tonic-gate (void *)bp, bp->b_bcount, bp->b_resid, bytes_remaining,
22540Sstevel@tonic-gate err);
22550Sstevel@tonic-gate
22560Sstevel@tonic-gate if (err) {
22570Sstevel@tonic-gate bioerror(bp, err);
22580Sstevel@tonic-gate }
22590Sstevel@tonic-gate
22600Sstevel@tonic-gate usbprnp->usbprn_bp = NULL;
22610Sstevel@tonic-gate biodone(bp);
22620Sstevel@tonic-gate }
22630Sstevel@tonic-gate
22640Sstevel@tonic-gate /* release access */
22650Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_dev_acc);
22660Sstevel@tonic-gate }
22670Sstevel@tonic-gate
22680Sstevel@tonic-gate
22690Sstevel@tonic-gate /*
22700Sstevel@tonic-gate * usbprn_send_async_bulk_data:
22710Sstevel@tonic-gate * Send bulk data down to the device through the bulk out pipe
22720Sstevel@tonic-gate */
22730Sstevel@tonic-gate static void
usbprn_send_async_bulk_data(usbprn_state_t * usbprnp)22740Sstevel@tonic-gate usbprn_send_async_bulk_data(usbprn_state_t *usbprnp)
22750Sstevel@tonic-gate {
22760Sstevel@tonic-gate int rval;
22770Sstevel@tonic-gate int timeout;
22780Sstevel@tonic-gate mblk_t *mp;
22790Sstevel@tonic-gate size_t max_xfer_count, xfer_count;
22800Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
22810Sstevel@tonic-gate usb_bulk_req_t *req;
22820Sstevel@tonic-gate
22830Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
22840Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
22850Sstevel@tonic-gate
22860Sstevel@tonic-gate timeout = usbprnp->usbprn_setparms.write_timeout;
22870Sstevel@tonic-gate max_xfer_count = usbprnp->usbprn_bp->b_bcount;
22880Sstevel@tonic-gate mp = usbprnp->usbprn_bulk_mp;
22890Sstevel@tonic-gate ASSERT(mp != NULL);
22907492SZhigang.Lu@Sun.COM xfer_count = MBLKL(mp);
22910Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
22920Sstevel@tonic-gate
22930Sstevel@tonic-gate req = usb_alloc_bulk_req(usbprnp->usbprn_dip, 0, USB_FLAGS_SLEEP);
22947492SZhigang.Lu@Sun.COM req->bulk_len = (uint_t)xfer_count;
22950Sstevel@tonic-gate req->bulk_data = mp;
22960Sstevel@tonic-gate req->bulk_timeout = timeout;
22970Sstevel@tonic-gate req->bulk_cb = usbprn_bulk_xfer_cb;
22980Sstevel@tonic-gate req->bulk_exc_cb = usbprn_bulk_xfer_exc_cb;
22990Sstevel@tonic-gate req->bulk_client_private = (usb_opaque_t)usbprnp;
23000Sstevel@tonic-gate req->bulk_attributes = USB_ATTRS_AUTOCLEARING;
23010Sstevel@tonic-gate
23020Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23030Sstevel@tonic-gate "usbprn_send_async_bulk_data: req = 0x%p "
23040Sstevel@tonic-gate "max_bulk_xfer_size=%lu mp=0x%p xfer_cnt=%lu timeout=%x",
23056898Sfb209375 (void *)req, max_xfer_count, (void *)mp, xfer_count, timeout);
23060Sstevel@tonic-gate
23070Sstevel@tonic-gate ASSERT(xfer_count <= max_xfer_count);
23080Sstevel@tonic-gate
23090Sstevel@tonic-gate
23100Sstevel@tonic-gate if ((rval = usb_pipe_bulk_xfer(bulk_out->ps_handle, req, 0)) !=
23110Sstevel@tonic-gate USB_SUCCESS) {
23120Sstevel@tonic-gate
23130Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23140Sstevel@tonic-gate "usbprn_send_async_bulk_data: Bulk mp=0x%p "
23156898Sfb209375 "rval=%d", (void *)mp, rval);
23160Sstevel@tonic-gate
23170Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
23180Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
23190Sstevel@tonic-gate usbprnp->usbprn_bulk_mp = NULL;
23200Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
23210Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
23220Sstevel@tonic-gate
23230Sstevel@tonic-gate usb_free_bulk_req(req);
23240Sstevel@tonic-gate } else {
23250Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
23260Sstevel@tonic-gate usbprnp->usbprn_bulk_mp = NULL;
23270Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
23280Sstevel@tonic-gate }
23290Sstevel@tonic-gate }
23300Sstevel@tonic-gate
23310Sstevel@tonic-gate
23320Sstevel@tonic-gate /*
23330Sstevel@tonic-gate * usbprn_bulk_xfer_cb
23340Sstevel@tonic-gate * Callback for a normal transfer for both bulk pipes.
23350Sstevel@tonic-gate */
23360Sstevel@tonic-gate /*ARGSUSED*/
23370Sstevel@tonic-gate static void
usbprn_bulk_xfer_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)23380Sstevel@tonic-gate usbprn_bulk_xfer_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
23390Sstevel@tonic-gate {
23400Sstevel@tonic-gate usbprn_state_t *usbprnp = (usbprn_state_t *)req->bulk_client_private;
23410Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
23420Sstevel@tonic-gate
23430Sstevel@tonic-gate ASSERT(usbprnp != NULL);
23440Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
23450Sstevel@tonic-gate
23460Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
23470Sstevel@tonic-gate
23480Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23496898Sfb209375 "usbprn_bulk_xfer_cb: mp=0x%p ", (void *)usbprnp->usbprn_bulk_mp);
23500Sstevel@tonic-gate
23510Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
23520Sstevel@tonic-gate ASSERT(usbprnp->usbprn_bp != NULL);
23530Sstevel@tonic-gate ASSERT((req->bulk_cb_flags & USB_CB_INTR_CONTEXT) == 0);
23540Sstevel@tonic-gate
23550Sstevel@tonic-gate /*
23560Sstevel@tonic-gate * if device is disconnected or driver close called, return
23570Sstevel@tonic-gate * The pipe could be closed, or a timeout could have
23580Sstevel@tonic-gate * come in and the pipe is being reset. If the
23590Sstevel@tonic-gate * state isn't transferring, then return
23600Sstevel@tonic-gate */
23610Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp)) ||
23620Sstevel@tonic-gate (bulk_out->ps_flags != USBPRN_PS_NEED_TO_XFER)) {
23630Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23640Sstevel@tonic-gate "usbprn_bulk_xfer_cb: no access or pipe closed");
23650Sstevel@tonic-gate
23660Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
23670Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
23680Sstevel@tonic-gate } else {
23690Sstevel@tonic-gate
23700Sstevel@tonic-gate /*
23710Sstevel@tonic-gate * data has been xferred, complete the bp.
23720Sstevel@tonic-gate */
23730Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23740Sstevel@tonic-gate "usbprn_bulk_xfer_cb: transaction over");
23750Sstevel@tonic-gate
23760Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
23770Sstevel@tonic-gate usbprn_biodone(usbprnp, 0, 0);
23780Sstevel@tonic-gate }
23790Sstevel@tonic-gate
23800Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
23810Sstevel@tonic-gate
23820Sstevel@tonic-gate usb_free_bulk_req(req);
23830Sstevel@tonic-gate }
23840Sstevel@tonic-gate
23850Sstevel@tonic-gate
23860Sstevel@tonic-gate /*
23870Sstevel@tonic-gate * usbprn_bulk_xfer_exc_cb:
23880Sstevel@tonic-gate * Exception callback for the bulk pipes
23890Sstevel@tonic-gate */
23900Sstevel@tonic-gate static void
usbprn_bulk_xfer_exc_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)23910Sstevel@tonic-gate usbprn_bulk_xfer_exc_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
23920Sstevel@tonic-gate {
23930Sstevel@tonic-gate usbprn_state_t *usbprnp = (usbprn_state_t *)req->bulk_client_private;
23940Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
23950Sstevel@tonic-gate int bytes_remaining = 0;
23960Sstevel@tonic-gate mblk_t *data = req->bulk_data;
23970Sstevel@tonic-gate usb_cr_t completion_reason = req->bulk_completion_reason;
23980Sstevel@tonic-gate usb_cb_flags_t cb_flags = req->bulk_cb_flags;
23990Sstevel@tonic-gate
24000Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
24010Sstevel@tonic-gate "usbprn_bulk_xfer_exc_cb: "
24020Sstevel@tonic-gate "pipe=0x%p req=0x%p cr=%d cb_flags=0x%x data=0x%p",
24036898Sfb209375 (void *)pipe, (void *)req, completion_reason, cb_flags,
24046898Sfb209375 (void *)data);
24050Sstevel@tonic-gate
24060Sstevel@tonic-gate ASSERT((req->bulk_cb_flags & USB_CB_INTR_CONTEXT) == 0);
24070Sstevel@tonic-gate ASSERT(data != NULL);
24080Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
24090Sstevel@tonic-gate
24100Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
24110Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
24120Sstevel@tonic-gate bulk_out->ps_cr = completion_reason;
24130Sstevel@tonic-gate
24140Sstevel@tonic-gate if (data) {
24157492SZhigang.Lu@Sun.COM bytes_remaining = MBLKL(data);
24160Sstevel@tonic-gate }
24170Sstevel@tonic-gate
24180Sstevel@tonic-gate /*
24190Sstevel@tonic-gate * If the pipe is closed or device not responding or not in
24200Sstevel@tonic-gate * need of transfer, just give up on this bp.
24210Sstevel@tonic-gate */
24220Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp)) ||
24230Sstevel@tonic-gate (req->bulk_completion_reason == USB_CR_DEV_NOT_RESP)) {
24240Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
24250Sstevel@tonic-gate "usbprn_bulk_xfer_exc_cb: "
24260Sstevel@tonic-gate "device not accesible or wrong state");
24270Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
24280Sstevel@tonic-gate } else {
24290Sstevel@tonic-gate if (completion_reason == USB_CR_TIMEOUT) {
24300Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL,
24310Sstevel@tonic-gate usbprnp->usbprn_log_handle,
24320Sstevel@tonic-gate "usbprn_bulk_xfer_exc_cb: timeout error, "
24330Sstevel@tonic-gate "xferred %lu bytes",
24340Sstevel@tonic-gate ((usbprnp->usbprn_bp->b_bcount) -
24350Sstevel@tonic-gate bytes_remaining));
24360Sstevel@tonic-gate usbprn_biodone(usbprnp, 0, bytes_remaining);
24370Sstevel@tonic-gate } else {
24380Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
24390Sstevel@tonic-gate }
24400Sstevel@tonic-gate
24410Sstevel@tonic-gate }
24420Sstevel@tonic-gate
24430Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
24440Sstevel@tonic-gate
24450Sstevel@tonic-gate usb_free_bulk_req(req);
24460Sstevel@tonic-gate }
24470Sstevel@tonic-gate
24480Sstevel@tonic-gate
24490Sstevel@tonic-gate /*
24500Sstevel@tonic-gate * usbprn_reconnect_event_cb:
24510Sstevel@tonic-gate * Called upon when the device is hotplugged back; event handling
24520Sstevel@tonic-gate */
24530Sstevel@tonic-gate /*ARGSUSED*/
24540Sstevel@tonic-gate static int
usbprn_reconnect_event_cb(dev_info_t * dip)24550Sstevel@tonic-gate usbprn_reconnect_event_cb(dev_info_t *dip)
24560Sstevel@tonic-gate {
24570Sstevel@tonic-gate usbprn_state_t *usbprnp =
24586898Sfb209375 (usbprn_state_t *)ddi_get_soft_state(usbprn_statep,
24596898Sfb209375 ddi_get_instance(dip));
24600Sstevel@tonic-gate
24610Sstevel@tonic-gate ASSERT(usbprnp != NULL);
24620Sstevel@tonic-gate
24630Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
24640Sstevel@tonic-gate "usbprn_reconnect_event_cb:");
24650Sstevel@tonic-gate
24660Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
24670Sstevel@tonic-gate
24680Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
24690Sstevel@tonic-gate ASSERT(usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED);
24700Sstevel@tonic-gate
24710Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
24720Sstevel@tonic-gate
24730Sstevel@tonic-gate usbprn_restore_device_state(dip, usbprnp);
24740Sstevel@tonic-gate
24750Sstevel@tonic-gate if (usbprnp->usbprn_ugen_hdl) {
24760Sstevel@tonic-gate (void) usb_ugen_reconnect_ev_cb(usbprnp->usbprn_ugen_hdl);
24770Sstevel@tonic-gate }
24780Sstevel@tonic-gate
24790Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
24800Sstevel@tonic-gate
24810Sstevel@tonic-gate return (USB_SUCCESS);
24820Sstevel@tonic-gate }
24830Sstevel@tonic-gate
24840Sstevel@tonic-gate
24850Sstevel@tonic-gate /*
24860Sstevel@tonic-gate * usbprn_disconnect_event_cb:
24870Sstevel@tonic-gate * callback for disconnect events
24880Sstevel@tonic-gate */
24890Sstevel@tonic-gate /*ARGSUSED*/
24900Sstevel@tonic-gate static int
usbprn_disconnect_event_cb(dev_info_t * dip)24910Sstevel@tonic-gate usbprn_disconnect_event_cb(dev_info_t *dip)
24920Sstevel@tonic-gate {
24930Sstevel@tonic-gate usbprn_state_t *usbprnp = (usbprn_state_t *)ddi_get_soft_state(
24946898Sfb209375 usbprn_statep, ddi_get_instance(dip));
24950Sstevel@tonic-gate
24960Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
24970Sstevel@tonic-gate "usbprn_disconnect_event_cb: Begin");
24980Sstevel@tonic-gate
24990Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
25000Sstevel@tonic-gate
25010Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25020Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_DISCONNECTED;
25030Sstevel@tonic-gate
25040Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_OPEN) {
25050Sstevel@tonic-gate USB_DPRINTF_L0(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
25060Sstevel@tonic-gate "device was disconnected while open. "
25070Sstevel@tonic-gate "Data may have been lost");
25080Sstevel@tonic-gate }
25090Sstevel@tonic-gate
25100Sstevel@tonic-gate /* For now, we set the offline bit in usbprn_last_status */
25110Sstevel@tonic-gate usbprnp->usbprn_last_status |= USB_PRINTER_PORT_NO_SELECT;
25120Sstevel@tonic-gate
25130Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25140Sstevel@tonic-gate
25150Sstevel@tonic-gate if (usbprnp->usbprn_ugen_hdl) {
25160Sstevel@tonic-gate (void) usb_ugen_disconnect_ev_cb(usbprnp->usbprn_ugen_hdl);
25170Sstevel@tonic-gate }
25180Sstevel@tonic-gate
25190Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
25200Sstevel@tonic-gate
25210Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
25220Sstevel@tonic-gate "usbprn_disconnect_event_cb: End");
25230Sstevel@tonic-gate
25240Sstevel@tonic-gate return (USB_SUCCESS);
25250Sstevel@tonic-gate }
25260Sstevel@tonic-gate
25270Sstevel@tonic-gate
25280Sstevel@tonic-gate /*
25290Sstevel@tonic-gate * usbprn_restore_device_state:
25300Sstevel@tonic-gate * set original configuration of the device
25310Sstevel@tonic-gate * Restores data xfer
25320Sstevel@tonic-gate */
25330Sstevel@tonic-gate static void
usbprn_restore_device_state(dev_info_t * dip,usbprn_state_t * usbprnp)25340Sstevel@tonic-gate usbprn_restore_device_state(dev_info_t *dip, usbprn_state_t *usbprnp)
25350Sstevel@tonic-gate {
25360Sstevel@tonic-gate int alt, rval, iface;
25370Sstevel@tonic-gate
25380Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
25390Sstevel@tonic-gate "usbprn_restore_device_state:");
25400Sstevel@tonic-gate
25410Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25420Sstevel@tonic-gate ASSERT((usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED) ||
25436898Sfb209375 (usbprnp->usbprn_dev_state == USB_DEV_SUSPENDED));
25440Sstevel@tonic-gate
25450Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25460Sstevel@tonic-gate
25470Sstevel@tonic-gate /* Check if we are talking to the same device */
25480Sstevel@tonic-gate if (usb_check_same_device(dip, usbprnp->usbprn_log_handle,
2549978Sfrits USB_LOG_L0, PRINT_MASK_ALL,
25500Sstevel@tonic-gate USB_CHK_ALL, NULL) != USB_SUCCESS) {
25510Sstevel@tonic-gate
25520Sstevel@tonic-gate /* change the device state from suspended to disconnected */
25530Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25540Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_DISCONNECTED;
25550Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25560Sstevel@tonic-gate
25570Sstevel@tonic-gate return;
25580Sstevel@tonic-gate }
25590Sstevel@tonic-gate
25600Sstevel@tonic-gate USB_DPRINTF_L0(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
25610Sstevel@tonic-gate "Printer has been reconnected but data may have been lost");
25620Sstevel@tonic-gate
25630Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25640Sstevel@tonic-gate
25650Sstevel@tonic-gate /* set last status to online */
25660Sstevel@tonic-gate usbprnp->usbprn_last_status &= ~USB_PRINTER_PORT_NO_SELECT;
25670Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25680Sstevel@tonic-gate
25690Sstevel@tonic-gate /* Get the port status */
25700Sstevel@tonic-gate if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
25710Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
25720Sstevel@tonic-gate "usbprn_restore_device_state: port status failed");
25730Sstevel@tonic-gate
25740Sstevel@tonic-gate return;
25750Sstevel@tonic-gate }
25760Sstevel@tonic-gate
25770Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25780Sstevel@tonic-gate
25790Sstevel@tonic-gate if ((usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR) == 0) {
25800Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
25810Sstevel@tonic-gate "usbprn_restore_device_state: An error with the printer");
25820Sstevel@tonic-gate }
25830Sstevel@tonic-gate
25840Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_OPEN) {
25850Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25860Sstevel@tonic-gate usbprn_close_usb_pipes(usbprnp);
25870Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25880Sstevel@tonic-gate }
25890Sstevel@tonic-gate
25900Sstevel@tonic-gate /* restore alternate */
25910Sstevel@tonic-gate alt = usbprnp->usbprn_if_descr.bAlternateSetting,
25926898Sfb209375 mutex_exit(&usbprnp->usbprn_mutex);
25930Sstevel@tonic-gate
25940Sstevel@tonic-gate iface = usb_owns_device(dip) ? 0 : usb_get_if_number(dip);
25950Sstevel@tonic-gate if ((rval = usb_set_alt_if(dip, iface, alt,
25960Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL)) != USB_SUCCESS) {
25970Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
25980Sstevel@tonic-gate "usbprn_restore_device_state: set alternate failed (%d)",
25990Sstevel@tonic-gate rval);
26000Sstevel@tonic-gate
26010Sstevel@tonic-gate return;
26020Sstevel@tonic-gate }
26030Sstevel@tonic-gate
26040Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
26050Sstevel@tonic-gate
26060Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_OPEN) {
26070Sstevel@tonic-gate
26080Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
26090Sstevel@tonic-gate (void) usbprn_open_usb_pipes(usbprnp);
26100Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
26110Sstevel@tonic-gate }
26120Sstevel@tonic-gate
26130Sstevel@tonic-gate if (usbprnp->usbprn_pm && usbprnp->usbprn_pm->usbprn_wakeup_enabled) {
26140Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
26150Sstevel@tonic-gate (void) usb_handle_remote_wakeup(usbprnp->usbprn_dip,
26160Sstevel@tonic-gate USB_REMOTE_WAKEUP_ENABLE);
26170Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
26180Sstevel@tonic-gate }
26190Sstevel@tonic-gate
26200Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
26210Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
26220Sstevel@tonic-gate
26230Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
26240Sstevel@tonic-gate "usbprn_restore_device_state: End");
26250Sstevel@tonic-gate }
26260Sstevel@tonic-gate
26270Sstevel@tonic-gate
26280Sstevel@tonic-gate /*
26290Sstevel@tonic-gate * Create power managements components
26300Sstevel@tonic-gate */
26310Sstevel@tonic-gate static void
usbprn_create_pm_components(dev_info_t * dip,usbprn_state_t * usbprnp)26320Sstevel@tonic-gate usbprn_create_pm_components(dev_info_t *dip, usbprn_state_t *usbprnp)
26330Sstevel@tonic-gate {
26340Sstevel@tonic-gate usbprn_power_t *usbprnpm;
26350Sstevel@tonic-gate uint_t pwr_states;
26360Sstevel@tonic-gate
26370Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
26380Sstevel@tonic-gate "usbprn_create_pm_components: Begin");
26390Sstevel@tonic-gate
26400Sstevel@tonic-gate /* Allocate the state structure */
26410Sstevel@tonic-gate usbprnpm = kmem_zalloc(sizeof (usbprn_power_t),
26426898Sfb209375 KM_SLEEP);
26430Sstevel@tonic-gate usbprnp->usbprn_pm = usbprnpm;
26440Sstevel@tonic-gate usbprnpm->usbprn_pm_capabilities = 0;
26450Sstevel@tonic-gate usbprnpm->usbprn_current_power = USB_DEV_OS_FULL_PWR;
26460Sstevel@tonic-gate
26470Sstevel@tonic-gate if (usb_create_pm_components(dip, &pwr_states) ==
26480Sstevel@tonic-gate USB_SUCCESS) {
26490Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM,
26500Sstevel@tonic-gate usbprnp->usbprn_log_handle,
26510Sstevel@tonic-gate "usbprn_create_pm_components: "
26520Sstevel@tonic-gate "created PM components");
26530Sstevel@tonic-gate
26540Sstevel@tonic-gate if (usb_handle_remote_wakeup(dip,
26550Sstevel@tonic-gate USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
26560Sstevel@tonic-gate usbprnpm->usbprn_wakeup_enabled = 1;
26570Sstevel@tonic-gate }
26580Sstevel@tonic-gate usbprnpm->usbprn_pwr_states = (uint8_t)pwr_states;
26590Sstevel@tonic-gate (void) pm_raise_power(usbprnp->usbprn_dip, 0,
26606898Sfb209375 USB_DEV_OS_FULL_PWR);
26610Sstevel@tonic-gate } else {
26620Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_PM,
26630Sstevel@tonic-gate usbprnp->usbprn_log_handle,
26640Sstevel@tonic-gate "usbprn_create_pm_components: Failed");
26650Sstevel@tonic-gate }
26660Sstevel@tonic-gate
26670Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
26680Sstevel@tonic-gate "usbprn_create_pm_components: END");
26690Sstevel@tonic-gate }
26700Sstevel@tonic-gate
26710Sstevel@tonic-gate
26720Sstevel@tonic-gate /*
26730Sstevel@tonic-gate * usbprn_pwrlvl0:
26740Sstevel@tonic-gate * Functions to handle power transition for OS levels 0 -> 3
26750Sstevel@tonic-gate */
26760Sstevel@tonic-gate static int
usbprn_pwrlvl0(usbprn_state_t * usbprnp)26770Sstevel@tonic-gate usbprn_pwrlvl0(usbprn_state_t *usbprnp)
26780Sstevel@tonic-gate {
26790Sstevel@tonic-gate int rval;
26800Sstevel@tonic-gate
26810Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
26820Sstevel@tonic-gate "usbprn_pwrlvl0:");
26830Sstevel@tonic-gate
26840Sstevel@tonic-gate switch (usbprnp->usbprn_dev_state) {
26850Sstevel@tonic-gate case USB_DEV_ONLINE:
26860Sstevel@tonic-gate /* Deny the powerdown request if the device is busy */
26870Sstevel@tonic-gate if (usbprnp->usbprn_pm->usbprn_pm_busy != 0) {
26880Sstevel@tonic-gate
26890Sstevel@tonic-gate return (USB_FAILURE);
26900Sstevel@tonic-gate }
26910Sstevel@tonic-gate
26920Sstevel@tonic-gate /* Issue USB D3 command to the device here */
26930Sstevel@tonic-gate rval = usb_set_device_pwrlvl3(usbprnp->usbprn_dip);
26940Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS);
26950Sstevel@tonic-gate
26960Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_PWRED_DOWN;
26970Sstevel@tonic-gate usbprnp->usbprn_pm->usbprn_current_power =
26986898Sfb209375 USB_DEV_OS_PWR_OFF;
26990Sstevel@tonic-gate /* FALLTHRU */
27000Sstevel@tonic-gate case USB_DEV_DISCONNECTED:
27010Sstevel@tonic-gate case USB_DEV_SUSPENDED:
27020Sstevel@tonic-gate /* allow a disconnect/cpr'ed device to go to lower power */
27030Sstevel@tonic-gate
27040Sstevel@tonic-gate return (USB_SUCCESS);
27050Sstevel@tonic-gate case USB_DEV_PWRED_DOWN:
27060Sstevel@tonic-gate default:
27070Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27080Sstevel@tonic-gate "usbprn_pwrlvl0: illegal dev state");
27090Sstevel@tonic-gate
27100Sstevel@tonic-gate return (USB_FAILURE);
27110Sstevel@tonic-gate }
27120Sstevel@tonic-gate }
27130Sstevel@tonic-gate
27140Sstevel@tonic-gate
27150Sstevel@tonic-gate /*
27160Sstevel@tonic-gate * usbprn_pwrlvl1:
27170Sstevel@tonic-gate * Functions to handle power transition to OS levels -> 2
27180Sstevel@tonic-gate */
27190Sstevel@tonic-gate static int
usbprn_pwrlvl1(usbprn_state_t * usbprnp)27200Sstevel@tonic-gate usbprn_pwrlvl1(usbprn_state_t *usbprnp)
27210Sstevel@tonic-gate {
27220Sstevel@tonic-gate int rval;
27230Sstevel@tonic-gate
27240Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27250Sstevel@tonic-gate "usbprn_pwrlvl1:");
27260Sstevel@tonic-gate
27270Sstevel@tonic-gate /* Issue USB D2 command to the device here */
27280Sstevel@tonic-gate rval = usb_set_device_pwrlvl2(usbprnp->usbprn_dip);
27290Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS);
27300Sstevel@tonic-gate
27310Sstevel@tonic-gate return (USB_FAILURE);
27320Sstevel@tonic-gate }
27330Sstevel@tonic-gate
27340Sstevel@tonic-gate
27350Sstevel@tonic-gate /*
27360Sstevel@tonic-gate * usbprn_pwrlvl2:
27370Sstevel@tonic-gate * Functions to handle power transition to OS levels -> 1
27380Sstevel@tonic-gate */
27390Sstevel@tonic-gate static int
usbprn_pwrlvl2(usbprn_state_t * usbprnp)27400Sstevel@tonic-gate usbprn_pwrlvl2(usbprn_state_t *usbprnp)
27410Sstevel@tonic-gate {
27420Sstevel@tonic-gate int rval;
27430Sstevel@tonic-gate
27440Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27450Sstevel@tonic-gate "usbprn_pwrlvl2:");
27460Sstevel@tonic-gate
27470Sstevel@tonic-gate /* Issue USB D1 command to the device here */
27480Sstevel@tonic-gate rval = usb_set_device_pwrlvl1(usbprnp->usbprn_dip);
27490Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS);
27500Sstevel@tonic-gate
27510Sstevel@tonic-gate return (USB_FAILURE);
27520Sstevel@tonic-gate }
27530Sstevel@tonic-gate
27540Sstevel@tonic-gate
27550Sstevel@tonic-gate /*
27560Sstevel@tonic-gate * usbprn_pwrlvl3:
27570Sstevel@tonic-gate * Functions to handle power transition to OS level -> 0
27580Sstevel@tonic-gate */
27590Sstevel@tonic-gate static int
usbprn_pwrlvl3(usbprn_state_t * usbprnp)27600Sstevel@tonic-gate usbprn_pwrlvl3(usbprn_state_t *usbprnp)
27610Sstevel@tonic-gate {
27620Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27630Sstevel@tonic-gate "usbprn_pwrlvl3:");
27640Sstevel@tonic-gate
27650Sstevel@tonic-gate switch (usbprnp->usbprn_dev_state) {
27660Sstevel@tonic-gate case USB_DEV_PWRED_DOWN:
27670Sstevel@tonic-gate /* Issue USB D0 command to the device here */
27680Sstevel@tonic-gate (void) usb_set_device_pwrlvl0(usbprnp->usbprn_dip);
27690Sstevel@tonic-gate
27700Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
27710Sstevel@tonic-gate usbprnp->usbprn_pm->usbprn_current_power =
27720Sstevel@tonic-gate USB_DEV_OS_FULL_PWR;
27730Sstevel@tonic-gate
27740Sstevel@tonic-gate /* FALLTHRU */
27750Sstevel@tonic-gate case USB_DEV_ONLINE:
27760Sstevel@tonic-gate /* we are already in full power */
27770Sstevel@tonic-gate /* FALLTHRU */
27780Sstevel@tonic-gate case USB_DEV_DISCONNECTED:
27790Sstevel@tonic-gate case USB_DEV_SUSPENDED:
27800Sstevel@tonic-gate /*
27810Sstevel@tonic-gate * PM framework tries to put us in full power
27820Sstevel@tonic-gate * during system shutdown. If we are disconnected/cpr'ed
27830Sstevel@tonic-gate * return success anyways
27840Sstevel@tonic-gate */
27850Sstevel@tonic-gate
27860Sstevel@tonic-gate return (USB_SUCCESS);
27870Sstevel@tonic-gate default:
27880Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27890Sstevel@tonic-gate "usbprn_pwrlvl3:");
27900Sstevel@tonic-gate
27910Sstevel@tonic-gate
27920Sstevel@tonic-gate return (USB_FAILURE);
27930Sstevel@tonic-gate }
27940Sstevel@tonic-gate }
27950Sstevel@tonic-gate
27960Sstevel@tonic-gate
27970Sstevel@tonic-gate /*
27980Sstevel@tonic-gate * usbprn_power :
27990Sstevel@tonic-gate * Power entry point
28000Sstevel@tonic-gate */
28010Sstevel@tonic-gate /* ARGSUSED */
28020Sstevel@tonic-gate static int
usbprn_power(dev_info_t * dip,int comp,int level)28030Sstevel@tonic-gate usbprn_power(dev_info_t *dip, int comp, int level)
28040Sstevel@tonic-gate {
28050Sstevel@tonic-gate usbprn_state_t *usbprnp;
28060Sstevel@tonic-gate usbprn_power_t *pm;
28070Sstevel@tonic-gate int rval = USB_FAILURE;
28080Sstevel@tonic-gate
28090Sstevel@tonic-gate usbprnp = (usbprn_state_t *)ddi_get_soft_state(usbprn_statep,
28106898Sfb209375 ddi_get_instance(dip));
28110Sstevel@tonic-gate
28120Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
28130Sstevel@tonic-gate "usbprn_power: Begin: level=%d", level);
28140Sstevel@tonic-gate
28150Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
28160Sstevel@tonic-gate
28170Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
28180Sstevel@tonic-gate pm = usbprnp->usbprn_pm;
28190Sstevel@tonic-gate ASSERT(pm != NULL);
28200Sstevel@tonic-gate
28210Sstevel@tonic-gate /* Check if we are transitioning to a legal power level */
28220Sstevel@tonic-gate if (USB_DEV_PWRSTATE_OK(pm->usbprn_pwr_states, level)) {
28230Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
28240Sstevel@tonic-gate "usbprn_power: illegal power level=%d "
28250Sstevel@tonic-gate "pwr_states=0x%x", level, pm->usbprn_pwr_states);
28260Sstevel@tonic-gate
28270Sstevel@tonic-gate goto done;
28280Sstevel@tonic-gate }
28290Sstevel@tonic-gate
28300Sstevel@tonic-gate switch (level) {
28310Sstevel@tonic-gate case USB_DEV_OS_PWR_OFF :
28320Sstevel@tonic-gate rval = usbprn_pwrlvl0(usbprnp);
28330Sstevel@tonic-gate
28340Sstevel@tonic-gate break;
28350Sstevel@tonic-gate case USB_DEV_OS_PWR_1 :
28360Sstevel@tonic-gate rval = usbprn_pwrlvl1(usbprnp);
28370Sstevel@tonic-gate
28380Sstevel@tonic-gate break;
28390Sstevel@tonic-gate case USB_DEV_OS_PWR_2 :
28400Sstevel@tonic-gate rval = usbprn_pwrlvl2(usbprnp);
28410Sstevel@tonic-gate
28420Sstevel@tonic-gate break;
28430Sstevel@tonic-gate case USB_DEV_OS_FULL_PWR :
28440Sstevel@tonic-gate rval = usbprn_pwrlvl3(usbprnp);
28450Sstevel@tonic-gate
28460Sstevel@tonic-gate break;
28470Sstevel@tonic-gate }
28480Sstevel@tonic-gate
28490Sstevel@tonic-gate done:
28500Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
28510Sstevel@tonic-gate
28520Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
28530Sstevel@tonic-gate
28540Sstevel@tonic-gate return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
28550Sstevel@tonic-gate }
28560Sstevel@tonic-gate
28570Sstevel@tonic-gate
28580Sstevel@tonic-gate /*
28590Sstevel@tonic-gate * usbprn_print_long:
28600Sstevel@tonic-gate * Breakup a string which is > USBPRN_PRINT_MAXLINE and print it
28610Sstevel@tonic-gate */
28620Sstevel@tonic-gate static void
usbprn_print_long(usbprn_state_t * usbprnp,char * str,int len)28630Sstevel@tonic-gate usbprn_print_long(usbprn_state_t *usbprnp, char *str, int len)
28640Sstevel@tonic-gate {
28650Sstevel@tonic-gate char *tmp = str;
28660Sstevel@tonic-gate char pbuf[USBPRN_PRINT_MAXLINE];
28670Sstevel@tonic-gate
28680Sstevel@tonic-gate for (;;) {
28690Sstevel@tonic-gate if (len <= USBPRN_PRINT_MAXLINE) {
28700Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA,
28710Sstevel@tonic-gate usbprnp->usbprn_log_handle, "%s", tmp);
28720Sstevel@tonic-gate
28730Sstevel@tonic-gate break;
28740Sstevel@tonic-gate } else {
28750Sstevel@tonic-gate bcopy(tmp, pbuf, USBPRN_PRINT_MAXLINE);
28760Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA,
28770Sstevel@tonic-gate usbprnp->usbprn_log_handle, "%s", pbuf);
28780Sstevel@tonic-gate tmp += USBPRN_PRINT_MAXLINE;
28790Sstevel@tonic-gate len -= USBPRN_PRINT_MAXLINE;
28800Sstevel@tonic-gate }
28810Sstevel@tonic-gate }
28820Sstevel@tonic-gate }
28830Sstevel@tonic-gate
28840Sstevel@tonic-gate
28850Sstevel@tonic-gate static void
usbprn_pm_busy_component(usbprn_state_t * usbprn_statep)28860Sstevel@tonic-gate usbprn_pm_busy_component(usbprn_state_t *usbprn_statep)
28870Sstevel@tonic-gate {
28880Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprn_statep->usbprn_mutex));
28890Sstevel@tonic-gate if (usbprn_statep->usbprn_pm != NULL) {
28900Sstevel@tonic-gate mutex_enter(&usbprn_statep->usbprn_mutex);
28910Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy++;
28920Sstevel@tonic-gate
28930Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprn_statep->usbprn_log_handle,
28940Sstevel@tonic-gate "usbprn_pm_busy_component: %d",
28950Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy);
28960Sstevel@tonic-gate
28970Sstevel@tonic-gate mutex_exit(&usbprn_statep->usbprn_mutex);
28980Sstevel@tonic-gate
28990Sstevel@tonic-gate if (pm_busy_component(usbprn_statep->usbprn_dip, 0) !=
29000Sstevel@tonic-gate DDI_SUCCESS) {
29010Sstevel@tonic-gate mutex_enter(&usbprn_statep->usbprn_mutex);
29020Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy--;
29030Sstevel@tonic-gate
29040Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_PM,
29050Sstevel@tonic-gate usbprn_statep->usbprn_log_handle,
29060Sstevel@tonic-gate "usbprn_pm_busy_component: %d",
29070Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy);
29080Sstevel@tonic-gate
29090Sstevel@tonic-gate mutex_exit(&usbprn_statep->usbprn_mutex);
29100Sstevel@tonic-gate }
29110Sstevel@tonic-gate
29120Sstevel@tonic-gate }
29130Sstevel@tonic-gate }
29140Sstevel@tonic-gate
29150Sstevel@tonic-gate
29160Sstevel@tonic-gate static void
usbprn_pm_idle_component(usbprn_state_t * usbprn_statep)29170Sstevel@tonic-gate usbprn_pm_idle_component(usbprn_state_t *usbprn_statep)
29180Sstevel@tonic-gate {
29190Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprn_statep->usbprn_mutex));
29200Sstevel@tonic-gate if (usbprn_statep->usbprn_pm != NULL) {
29210Sstevel@tonic-gate if (pm_idle_component(usbprn_statep->usbprn_dip, 0) ==
29220Sstevel@tonic-gate DDI_SUCCESS) {
29230Sstevel@tonic-gate mutex_enter(&usbprn_statep->usbprn_mutex);
29240Sstevel@tonic-gate ASSERT(usbprn_statep->usbprn_pm->usbprn_pm_busy > 0);
29250Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy--;
29260Sstevel@tonic-gate
29270Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM,
29280Sstevel@tonic-gate usbprn_statep->usbprn_log_handle,
29290Sstevel@tonic-gate "usbprn_pm_idle_component: %d",
29300Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy);
29310Sstevel@tonic-gate
29320Sstevel@tonic-gate mutex_exit(&usbprn_statep->usbprn_mutex);
29330Sstevel@tonic-gate }
29340Sstevel@tonic-gate
29350Sstevel@tonic-gate }
29360Sstevel@tonic-gate }
2937