17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5112116d8Sfb * Common Development and Distribution License (the "License").
6112116d8Sfb * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate *
21*be529ebcSRaymond Chen * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
227c478bd9Sstevel@tonic-gate * Use is subject to license terms.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * Printer Class Driver for USB
287c478bd9Sstevel@tonic-gate *
297c478bd9Sstevel@tonic-gate * This driver supports devices that adhere to the USB Printer Class
307c478bd9Sstevel@tonic-gate * specification 1.0.
317c478bd9Sstevel@tonic-gate *
327c478bd9Sstevel@tonic-gate * NOTE: This driver is not DDI compliant in that it uses undocumented
337c478bd9Sstevel@tonic-gate * functions for logging (USB_DPRINTF_L*, usb_alloc_log_hdl, usb_free_log_hdl),
347c478bd9Sstevel@tonic-gate * and serialization (usb_serialize_access, usb_release_access,
357c478bd9Sstevel@tonic-gate * usb_init_serialization, usb_fini_serialization)
367c478bd9Sstevel@tonic-gate *
377c478bd9Sstevel@tonic-gate * Undocumented functions may go away in a future Solaris OS release.
387c478bd9Sstevel@tonic-gate *
397c478bd9Sstevel@tonic-gate * Please see the DDK for sample code of these functions, and for the usbskel
407c478bd9Sstevel@tonic-gate * skeleton template driver which contains scaled-down versions of these
417c478bd9Sstevel@tonic-gate * functions written in a DDI-compliant way.
427c478bd9Sstevel@tonic-gate */
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate #if defined(lint) && !defined(DEBUG)
457c478bd9Sstevel@tonic-gate #define DEBUG
467c478bd9Sstevel@tonic-gate #endif
477c478bd9Sstevel@tonic-gate #ifdef __lock_lint
487c478bd9Sstevel@tonic-gate #define _MULTI_DATAMODEL
497c478bd9Sstevel@tonic-gate #endif
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate #define USBDRV_MAJOR_VER 2
527c478bd9Sstevel@tonic-gate #define USBDRV_MINOR_VER 0
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate #include <sys/usb/usba.h>
557c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usba_ugen.h>
567c478bd9Sstevel@tonic-gate #include <sys/bpp_io.h>
577c478bd9Sstevel@tonic-gate #include <sys/ecppsys.h>
587c478bd9Sstevel@tonic-gate #include <sys/prnio.h>
597c478bd9Sstevel@tonic-gate #include <sys/errno.h>
607c478bd9Sstevel@tonic-gate #include <sys/usb/clients/printer/usb_printer.h>
617c478bd9Sstevel@tonic-gate #include <sys/usb/clients/printer/usbprn.h>
62d29f5a71Szhigang lu - Sun Microsystems - Beijing China #include <sys/strsun.h>
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate /* Debugging support */
654610e4a0Sfrits uint_t usbprn_errmask = (uint_t)PRINT_MASK_ALL;
664610e4a0Sfrits uint_t usbprn_errlevel = USB_LOG_L4;
674610e4a0Sfrits uint_t usbprn_instance_debug = (uint_t)-1;
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /* local variables */
707c478bd9Sstevel@tonic-gate static uint_t usbprn_ifcap =
717c478bd9Sstevel@tonic-gate PRN_HOTPLUG | PRN_1284_DEVID | PRN_1284_STATUS | PRN_TIMEOUTS;
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate * Function Prototypes
757c478bd9Sstevel@tonic-gate */
767c478bd9Sstevel@tonic-gate static int usbprn_attach(dev_info_t *, ddi_attach_cmd_t);
777c478bd9Sstevel@tonic-gate static int usbprn_detach(dev_info_t *, ddi_detach_cmd_t);
787c478bd9Sstevel@tonic-gate static int usbprn_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
797c478bd9Sstevel@tonic-gate static void usbprn_cleanup(dev_info_t *, usbprn_state_t *);
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate static int usbprn_get_descriptors(usbprn_state_t *);
827c478bd9Sstevel@tonic-gate static int usbprn_get_device_id(usbprn_state_t *);
837c478bd9Sstevel@tonic-gate static int usbprn_get_port_status(usbprn_state_t *);
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate static int usbprn_open(dev_t *, int, int, cred_t *);
867c478bd9Sstevel@tonic-gate static int usbprn_close(dev_t, int, int, cred_t *);
877c478bd9Sstevel@tonic-gate static int usbprn_open_usb_pipes(usbprn_state_t *);
887c478bd9Sstevel@tonic-gate static void usbprn_close_usb_pipes(usbprn_state_t *);
897c478bd9Sstevel@tonic-gate static int usbprn_write(dev_t, struct uio *, cred_t *);
907c478bd9Sstevel@tonic-gate static int usbprn_read(dev_t, struct uio *, cred_t *);
917c478bd9Sstevel@tonic-gate static int usbprn_poll(dev_t, short, int, short *, struct pollhead **);
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate static int usbprn_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
947c478bd9Sstevel@tonic-gate static void usbprn_minphys(struct buf *);
957c478bd9Sstevel@tonic-gate static int usbprn_strategy(struct buf *);
967c478bd9Sstevel@tonic-gate static int usbprn_setparms(usbprn_state_t *, intptr_t arg, int);
977c478bd9Sstevel@tonic-gate static int usbprn_getparms(usbprn_state_t *, intptr_t, int);
987c478bd9Sstevel@tonic-gate static void usbprn_geterr(usbprn_state_t *, intptr_t, int);
997c478bd9Sstevel@tonic-gate static int usbprn_testio(usbprn_state_t *, int);
1007c478bd9Sstevel@tonic-gate static int usbprn_ioctl_get_status(usbprn_state_t *);
1017c478bd9Sstevel@tonic-gate static int usbprn_prnio_get_status(usbprn_state_t *, intptr_t, int);
1027c478bd9Sstevel@tonic-gate static int usbprn_prnio_get_1284_status(usbprn_state_t *, intptr_t, int);
1037c478bd9Sstevel@tonic-gate static int usbprn_prnio_get_ifcap(usbprn_state_t *, intptr_t, int);
1047c478bd9Sstevel@tonic-gate static int usbprn_prnio_set_ifcap(usbprn_state_t *, intptr_t, int);
1057c478bd9Sstevel@tonic-gate static int usbprn_prnio_get_ifinfo(usbprn_state_t *, intptr_t, int);
1067c478bd9Sstevel@tonic-gate static int usbprn_prnio_get_1284_devid(usbprn_state_t *, intptr_t, int);
1077c478bd9Sstevel@tonic-gate static int usbprn_prnio_get_timeouts(usbprn_state_t *, intptr_t, int);
1087c478bd9Sstevel@tonic-gate static int usbprn_prnio_set_timeouts(usbprn_state_t *, intptr_t, int);
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate static void usbprn_send_async_bulk_data(usbprn_state_t *);
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate static void usbprn_bulk_xfer_cb(usb_pipe_handle_t, usb_bulk_req_t *);
1137c478bd9Sstevel@tonic-gate static void usbprn_bulk_xfer_exc_cb(usb_pipe_handle_t,
1147c478bd9Sstevel@tonic-gate usb_bulk_req_t *);
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate static void usbprn_biodone(usbprn_state_t *, int, int);
1177c478bd9Sstevel@tonic-gate static char usbprn_error_state(uchar_t);
1187c478bd9Sstevel@tonic-gate static void usbprn_print_long(usbprn_state_t *, char *, int);
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate /* event handling */
1217c478bd9Sstevel@tonic-gate static void usbprn_restore_device_state(dev_info_t *, usbprn_state_t *);
1227c478bd9Sstevel@tonic-gate static int usbprn_disconnect_event_cb(dev_info_t *);
1237c478bd9Sstevel@tonic-gate static int usbprn_reconnect_event_cb(dev_info_t *);
1247c478bd9Sstevel@tonic-gate static int usbprn_cpr_suspend(dev_info_t *);
1257c478bd9Sstevel@tonic-gate static void usbprn_cpr_resume(dev_info_t *);
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate static usb_event_t usbprn_events = {
1287c478bd9Sstevel@tonic-gate usbprn_disconnect_event_cb,
1297c478bd9Sstevel@tonic-gate usbprn_reconnect_event_cb,
1307c478bd9Sstevel@tonic-gate NULL, NULL
1317c478bd9Sstevel@tonic-gate };
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /* PM handling */
1347c478bd9Sstevel@tonic-gate static void usbprn_create_pm_components(dev_info_t *, usbprn_state_t *);
1357c478bd9Sstevel@tonic-gate static int usbprn_power(dev_info_t *, int comp, int level);
1367c478bd9Sstevel@tonic-gate static int usbprn_pwrlvl0(usbprn_state_t *);
1377c478bd9Sstevel@tonic-gate static int usbprn_pwrlvl1(usbprn_state_t *);
1387c478bd9Sstevel@tonic-gate static int usbprn_pwrlvl2(usbprn_state_t *);
1397c478bd9Sstevel@tonic-gate static int usbprn_pwrlvl3(usbprn_state_t *);
1407c478bd9Sstevel@tonic-gate static void usbprn_pm_busy_component(usbprn_state_t *);
1417c478bd9Sstevel@tonic-gate static void usbprn_pm_idle_component(usbprn_state_t *);
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate /* module loading stuff */
1447c478bd9Sstevel@tonic-gate struct cb_ops usbprn_cb_ops = {
1457c478bd9Sstevel@tonic-gate usbprn_open, /* open */
1467c478bd9Sstevel@tonic-gate usbprn_close, /* close */
1477c478bd9Sstevel@tonic-gate nulldev, /* strategy */
1487c478bd9Sstevel@tonic-gate nulldev, /* print */
1497c478bd9Sstevel@tonic-gate nulldev, /* dump */
1507c478bd9Sstevel@tonic-gate usbprn_read, /* read */
1517c478bd9Sstevel@tonic-gate usbprn_write, /* write */
1527c478bd9Sstevel@tonic-gate usbprn_ioctl, /* ioctl */
1537c478bd9Sstevel@tonic-gate nulldev, /* devmap */
1547c478bd9Sstevel@tonic-gate nulldev, /* mmap */
1557c478bd9Sstevel@tonic-gate nulldev, /* segmap */
1567c478bd9Sstevel@tonic-gate usbprn_poll, /* poll */
1577c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */
1587c478bd9Sstevel@tonic-gate NULL, /* streamtab */
1597c478bd9Sstevel@tonic-gate D_64BIT | D_MP
1607c478bd9Sstevel@tonic-gate };
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate static struct dev_ops usbprn_ops = {
1637c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */
1647c478bd9Sstevel@tonic-gate 0, /* refcnt */
1657c478bd9Sstevel@tonic-gate usbprn_info, /* info */
1667c478bd9Sstevel@tonic-gate nulldev, /* identify */
1677c478bd9Sstevel@tonic-gate nulldev, /* probe */
1687c478bd9Sstevel@tonic-gate usbprn_attach, /* attach */
1697c478bd9Sstevel@tonic-gate usbprn_detach, /* detach */
1707c478bd9Sstevel@tonic-gate nodev, /* reset */
1717c478bd9Sstevel@tonic-gate &usbprn_cb_ops, /* driver operations */
1727c478bd9Sstevel@tonic-gate NULL, /* bus operations */
17319397407SSherry Moore usbprn_power, /* power */
174*be529ebcSRaymond Chen ddi_quiesce_not_needed, /* devo_quiesce */
1757c478bd9Sstevel@tonic-gate };
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate static struct modldrv usbprnmodldrv = {
1787c478bd9Sstevel@tonic-gate &mod_driverops,
17977e51571Sgongtian zhao - Sun Microsystems - Beijing China "USB printer client driver",
1807c478bd9Sstevel@tonic-gate &usbprn_ops
1817c478bd9Sstevel@tonic-gate };
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1847c478bd9Sstevel@tonic-gate MODREV_1,
1857c478bd9Sstevel@tonic-gate &usbprnmodldrv,
1867c478bd9Sstevel@tonic-gate NULL,
1877c478bd9Sstevel@tonic-gate };
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /* local variables */
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate /* soft state structures */
1927c478bd9Sstevel@tonic-gate #define USBPRN_INITIAL_SOFT_SPACE 1
1937c478bd9Sstevel@tonic-gate static void *usbprn_statep;
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate static int usbprn_max_xfer_size = USBPRN_MAX_XFER_SIZE;
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate /* prnio support */
1987c478bd9Sstevel@tonic-gate static const char usbprn_prnio_ifinfo[] = PRN_USB;
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate int
_init(void)2027c478bd9Sstevel@tonic-gate _init(void)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate int rval;
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate if ((rval = ddi_soft_state_init(&usbprn_statep,
2077c478bd9Sstevel@tonic-gate sizeof (usbprn_state_t), USBPRN_INITIAL_SOFT_SPACE)) != 0) {
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate return (rval);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate if ((rval = mod_install(&modlinkage)) != 0) {
2137c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&usbprn_statep);
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate return (rval);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate int
_fini(void)2217c478bd9Sstevel@tonic-gate _fini(void)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate int rval;
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate if ((rval = mod_remove(&modlinkage)) != 0) {
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate return (rval);
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&usbprn_statep);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate return (rval);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2377c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate /*
2447c478bd9Sstevel@tonic-gate * usbprn_info:
2457c478bd9Sstevel@tonic-gate * Get minor number, soft state structure, etc.
2467c478bd9Sstevel@tonic-gate */
2477c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2487c478bd9Sstevel@tonic-gate static int
usbprn_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)2497c478bd9Sstevel@tonic-gate usbprn_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
2507c478bd9Sstevel@tonic-gate void *arg, void **result)
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp;
2537c478bd9Sstevel@tonic-gate int error = DDI_FAILURE;
2547c478bd9Sstevel@tonic-gate minor_t minor = getminor((dev_t)arg);
2557c478bd9Sstevel@tonic-gate int instance = USBPRN_MINOR_TO_INSTANCE(minor);
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate switch (infocmd) {
2587c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO:
2597c478bd9Sstevel@tonic-gate if ((usbprnp = ddi_get_soft_state(usbprn_statep,
2607c478bd9Sstevel@tonic-gate instance)) != NULL) {
2617c478bd9Sstevel@tonic-gate *result = usbprnp->usbprn_dip;
2627c478bd9Sstevel@tonic-gate if (*result != NULL) {
2637c478bd9Sstevel@tonic-gate error = DDI_SUCCESS;
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate } else {
2667c478bd9Sstevel@tonic-gate *result = NULL;
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate break;
2707c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE:
2717c478bd9Sstevel@tonic-gate *result = (void *)(uintptr_t)instance;
2727c478bd9Sstevel@tonic-gate error = DDI_SUCCESS;
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate break;
2757c478bd9Sstevel@tonic-gate default:
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate break;
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate return (error);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * usbprn_attach:
2867c478bd9Sstevel@tonic-gate * Attach driver
2877c478bd9Sstevel@tonic-gate * Get the descriptor information
2887c478bd9Sstevel@tonic-gate * Get the device id
2897c478bd9Sstevel@tonic-gate * Reset the device
2907c478bd9Sstevel@tonic-gate * Get the port status
2917c478bd9Sstevel@tonic-gate */
2927c478bd9Sstevel@tonic-gate static int
usbprn_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2937c478bd9Sstevel@tonic-gate usbprn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip);
2967c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = NULL;
2977c478bd9Sstevel@tonic-gate size_t sz;
2987c478bd9Sstevel@tonic-gate usb_ugen_info_t usb_ugen_info;
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate switch (cmd) {
3017c478bd9Sstevel@tonic-gate case DDI_ATTACH:
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate break;
3047c478bd9Sstevel@tonic-gate case DDI_RESUME:
3057c478bd9Sstevel@tonic-gate usbprn_cpr_resume(dip);
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
3087c478bd9Sstevel@tonic-gate default:
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(usbprn_statep, instance) == DDI_SUCCESS) {
3147c478bd9Sstevel@tonic-gate usbprnp = ddi_get_soft_state(usbprn_statep, instance);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate if (usbprnp == NULL) {
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate usbprnp->usbprn_instance = instance;
3227c478bd9Sstevel@tonic-gate usbprnp->usbprn_dip = dip;
3237c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle = usb_alloc_log_hdl(dip,
324112116d8Sfb "prn", &usbprn_errlevel,
325112116d8Sfb &usbprn_errmask, &usbprn_instance_debug, 0);
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3287c478bd9Sstevel@tonic-gate "usbprn_attach: cmd=%x", cmd);
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
3317c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3327c478bd9Sstevel@tonic-gate "usb_client_attach failed");
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate goto fail;
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate if (usb_get_dev_data(dip, &usbprnp->usbprn_dev_data,
3377c478bd9Sstevel@tonic-gate USB_PARSE_LVL_IF, 0) != USB_SUCCESS) {
3387c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3397c478bd9Sstevel@tonic-gate "usb_get_dev_data failed");
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate goto fail;
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /* Initialize locks and conditional variables */
3457c478bd9Sstevel@tonic-gate mutex_init(&usbprnp->usbprn_mutex, NULL, MUTEX_DRIVER,
346112116d8Sfb usbprnp->usbprn_dev_data->dev_iblock_cookie);
3477c478bd9Sstevel@tonic-gate usbprnp->usbprn_write_acc = usb_init_serialization(dip,
348112116d8Sfb USB_INIT_SER_CHECK_SAME_THREAD);
3497c478bd9Sstevel@tonic-gate usbprnp->usbprn_ser_acc = usb_init_serialization(dip,
3507c478bd9Sstevel@tonic-gate USB_INIT_SER_CHECK_SAME_THREAD);
3517c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_acc = usb_init_serialization(dip, 0);
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate usbprnp->usbprn_flags |= USBPRN_LOCKS_INIT_DONE;
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate /* Obtain all the relevant descriptors */
3567c478bd9Sstevel@tonic-gate if (usbprn_get_descriptors(usbprnp) != USB_SUCCESS) {
3577c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3587c478bd9Sstevel@tonic-gate "usb get descriptors failed");
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate goto fail;
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate usbprnp->usbprn_def_ph = usbprnp->usbprn_dev_data->dev_default_ph;
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate /* Obtain the device id */
3667c478bd9Sstevel@tonic-gate (void) usbprn_get_device_id(usbprnp);
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate /* Get the port status */
3697c478bd9Sstevel@tonic-gate if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
3707c478bd9Sstevel@tonic-gate /* some printers fail on the first */
3717c478bd9Sstevel@tonic-gate if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
3727c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA,
3737c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
3747c478bd9Sstevel@tonic-gate "usb get port status failed");
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate goto fail;
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3817c478bd9Sstevel@tonic-gate "usbprn_attach: printer status=0x%x", usbprnp->usbprn_last_status);
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate if ((usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR) == 0) {
3847c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3857c478bd9Sstevel@tonic-gate "usbprn_attach: error occurred with the printer");
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate /*
3897c478bd9Sstevel@tonic-gate * Create minor node based on information from the
3907c478bd9Sstevel@tonic-gate * descriptors
3917c478bd9Sstevel@tonic-gate */
3927c478bd9Sstevel@tonic-gate if ((ddi_create_minor_node(dip, "printer", S_IFCHR,
3937c478bd9Sstevel@tonic-gate instance << USBPRN_MINOR_INSTANCE_SHIFT,
3947c478bd9Sstevel@tonic-gate DDI_NT_PRINTER, 0)) != DDI_SUCCESS) {
395d291d9f2Sfrits USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
3967c478bd9Sstevel@tonic-gate "usbprn_attach: cannot create minor node");
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate goto fail;
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate usbprnp->usbprn_setparms.write_timeout = USBPRN_XFER_TIMEOUT;
4027c478bd9Sstevel@tonic-gate usbprnp->usbprn_setparms.mode = ECPP_CENTRONICS;
4037c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate if (usb_pipe_get_max_bulk_transfer_size(usbprnp->usbprn_dip, &sz)) {
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate goto fail;
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate usbprnp->usbprn_max_bulk_xfer_size = sz;
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
4137c478bd9Sstevel@tonic-gate "usbprn_attach: xfer_size=0x%lx", sz);
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate /* enable PM */
4167c478bd9Sstevel@tonic-gate usbprn_create_pm_components(dip, usbprnp);
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate /* Register for events */
4197c478bd9Sstevel@tonic-gate if (usb_register_event_cbs(dip, &usbprn_events, 0) != USB_SUCCESS) {
420d291d9f2Sfrits USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
4217c478bd9Sstevel@tonic-gate "usbprn_attach: usb_register_event_cbs failed");
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate goto fail;
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate usb_free_dev_data(dip, usbprnp->usbprn_dev_data);
4277c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_data = NULL;
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate if (usb_owns_device(dip)) {
4307c478bd9Sstevel@tonic-gate /* get a ugen handle */
4317c478bd9Sstevel@tonic-gate bzero(&usb_ugen_info, sizeof (usb_ugen_info));
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate usb_ugen_info.usb_ugen_flags = 0;
4347c478bd9Sstevel@tonic-gate usb_ugen_info.usb_ugen_minor_node_ugen_bits_mask =
435112116d8Sfb (dev_t)USBPRN_MINOR_UGEN_BITS_MASK;
4367c478bd9Sstevel@tonic-gate usb_ugen_info.usb_ugen_minor_node_instance_mask =
437112116d8Sfb (dev_t)~USBPRN_MINOR_UGEN_BITS_MASK;
4387c478bd9Sstevel@tonic-gate usbprnp->usbprn_ugen_hdl =
439112116d8Sfb usb_ugen_get_hdl(dip, &usb_ugen_info);
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate if (usb_ugen_attach(usbprnp->usbprn_ugen_hdl, cmd) !=
4427c478bd9Sstevel@tonic-gate USB_SUCCESS) {
4437c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA,
4447c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
4457c478bd9Sstevel@tonic-gate "usb_ugen_attach failed");
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate usb_ugen_release_hdl(usbprnp->usbprn_ugen_hdl);
4487c478bd9Sstevel@tonic-gate usbprnp->usbprn_ugen_hdl = NULL;
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate /* Report device */
4537c478bd9Sstevel@tonic-gate ddi_report_dev(dip);
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
4567c478bd9Sstevel@tonic-gate "usbprn_attach: done");
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate fail:
4617c478bd9Sstevel@tonic-gate if (usbprnp) {
4627c478bd9Sstevel@tonic-gate usbprn_cleanup(dip, usbprnp);
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate * usbprn_detach:
4717c478bd9Sstevel@tonic-gate * detach or suspend driver instance
4727c478bd9Sstevel@tonic-gate */
4737c478bd9Sstevel@tonic-gate static int
usbprn_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)4747c478bd9Sstevel@tonic-gate usbprn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
4757c478bd9Sstevel@tonic-gate {
4767c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip);
4777c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp;
4787c478bd9Sstevel@tonic-gate int rval = DDI_FAILURE;
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate usbprnp = ddi_get_soft_state(usbprn_statep, instance);
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
4837c478bd9Sstevel@tonic-gate "usbprn_detach: cmd=%x", cmd);
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate switch (cmd) {
4867c478bd9Sstevel@tonic-gate case DDI_DETACH:
4877c478bd9Sstevel@tonic-gate ASSERT((usbprnp->usbprn_flags & USBPRN_OPEN) == 0);
4887c478bd9Sstevel@tonic-gate usbprn_cleanup(dip, usbprnp);
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
4917c478bd9Sstevel@tonic-gate case DDI_SUSPEND:
4927c478bd9Sstevel@tonic-gate rval = usbprn_cpr_suspend(dip);
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate return ((rval == USB_SUCCESS) ? DDI_SUCCESS :
4957c478bd9Sstevel@tonic-gate DDI_FAILURE);
4967c478bd9Sstevel@tonic-gate default:
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate return (rval);
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate
5037c478bd9Sstevel@tonic-gate /*
5047c478bd9Sstevel@tonic-gate * usbprn_cleanup:
5057c478bd9Sstevel@tonic-gate * clean up the driver state
5067c478bd9Sstevel@tonic-gate */
5077c478bd9Sstevel@tonic-gate static void
usbprn_cleanup(dev_info_t * dip,usbprn_state_t * usbprnp)5087c478bd9Sstevel@tonic-gate usbprn_cleanup(dev_info_t *dip, usbprn_state_t *usbprnp)
5097c478bd9Sstevel@tonic-gate {
5107c478bd9Sstevel@tonic-gate usbprn_power_t *usbprnpm = usbprnp->usbprn_pm;
5117c478bd9Sstevel@tonic-gate int rval = 0;
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
5147c478bd9Sstevel@tonic-gate "usbprn_cleanup: Start");
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate ASSERT(usbprnp != NULL);
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_LOCKS_INIT_DONE) {
5197c478bd9Sstevel@tonic-gate /*
5207c478bd9Sstevel@tonic-gate * Disable the event callbacks first, after this point, event
5217c478bd9Sstevel@tonic-gate * callbacks will never get called. Note we shouldn't hold
5227c478bd9Sstevel@tonic-gate * mutex while unregistering events because there may be a
5237c478bd9Sstevel@tonic-gate * competing event callback thread. Event callbacks are done
5247c478bd9Sstevel@tonic-gate * with ndi mutex held and this can cause a potential deadlock.
5257c478bd9Sstevel@tonic-gate */
5267c478bd9Sstevel@tonic-gate usb_unregister_event_cbs(dip, &usbprn_events);
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
5297c478bd9Sstevel@tonic-gate if ((usbprnpm) &&
5307c478bd9Sstevel@tonic-gate (usbprnp->usbprn_dev_state != USB_DEV_DISCONNECTED)) {
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
5337c478bd9Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
5347c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
5357c478bd9Sstevel@tonic-gate
5367c478bd9Sstevel@tonic-gate if (usbprnpm->usbprn_wakeup_enabled) {
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate (void) pm_raise_power(dip, 0,
5417c478bd9Sstevel@tonic-gate USB_DEV_OS_FULL_PWR);
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate if ((rval = usb_handle_remote_wakeup(dip,
5447c478bd9Sstevel@tonic-gate USB_REMOTE_WAKEUP_DISABLE)) !=
5457c478bd9Sstevel@tonic-gate USB_SUCCESS) {
5467c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL,
5477c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
5487c478bd9Sstevel@tonic-gate "usbprn_cleanup: "
5497c478bd9Sstevel@tonic-gate "disable remote wakeup "
5507c478bd9Sstevel@tonic-gate "failed, rval=%d", rval);
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate } else {
5537c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate
5567c478bd9Sstevel@tonic-gate (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
5577c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL);
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_device_id) {
5677c478bd9Sstevel@tonic-gate kmem_free(usbprnp->usbprn_device_id,
5687c478bd9Sstevel@tonic-gate usbprnp->usbprn_device_id_len + 1);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate mutex_destroy(&usbprnp->usbprn_mutex);
5727c478bd9Sstevel@tonic-gate usb_fini_serialization(usbprnp->usbprn_dev_acc);
5737c478bd9Sstevel@tonic-gate usb_fini_serialization(usbprnp->usbprn_ser_acc);
5747c478bd9Sstevel@tonic-gate usb_fini_serialization(usbprnp->usbprn_write_acc);
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate if (usbprnpm) {
5787c478bd9Sstevel@tonic-gate kmem_free(usbprnpm, sizeof (usbprn_power_t));
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
5827c478bd9Sstevel@tonic-gate "usbprn_cleanup: End");
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_ugen_hdl) {
5857c478bd9Sstevel@tonic-gate (void) usb_ugen_detach(usbprnp->usbprn_ugen_hdl, DDI_DETACH);
5867c478bd9Sstevel@tonic-gate usb_ugen_release_hdl(usbprnp->usbprn_ugen_hdl);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate /* unregister with USBA */
5907c478bd9Sstevel@tonic-gate usb_client_detach(dip, usbprnp->usbprn_dev_data);
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate usb_free_log_hdl(usbprnp->usbprn_log_handle);
5937c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip);
5947c478bd9Sstevel@tonic-gate ddi_soft_state_free(usbprn_statep, usbprnp->usbprn_instance);
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate
5987c478bd9Sstevel@tonic-gate /*
5997c478bd9Sstevel@tonic-gate * usbprn_cpr_suspend:
6007c478bd9Sstevel@tonic-gate * prepare to be suspended
6017c478bd9Sstevel@tonic-gate */
6027c478bd9Sstevel@tonic-gate static int
usbprn_cpr_suspend(dev_info_t * dip)6037c478bd9Sstevel@tonic-gate usbprn_cpr_suspend(dev_info_t *dip)
6047c478bd9Sstevel@tonic-gate {
6057c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp;
6067c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip);
6077c478bd9Sstevel@tonic-gate int rval = USB_FAILURE;
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate usbprnp = ddi_get_soft_state(usbprn_statep, instance);
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
6127c478bd9Sstevel@tonic-gate "usbprn_cpr_suspend");
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate if ((usbprnp->usbprn_flags & USBPRN_OPEN) != 0) {
6197c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_CPR,
6227c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
6237c478bd9Sstevel@tonic-gate "usbprn_cpr_suspend: "
6247c478bd9Sstevel@tonic-gate "Device is open. Can't suspend");
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate } else {
6277c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_SUSPENDED;
6287c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
6317c478bd9Sstevel@tonic-gate "usbprn_cpr_suspend: SUCCESS");
6327c478bd9Sstevel@tonic-gate rval = USB_SUCCESS;
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate if ((rval == USB_SUCCESS) && usbprnp->usbprn_ugen_hdl) {
6377c478bd9Sstevel@tonic-gate rval = usb_ugen_detach(usbprnp->usbprn_ugen_hdl,
638112116d8Sfb DDI_SUSPEND);
6397c478bd9Sstevel@tonic-gate }
6407c478bd9Sstevel@tonic-gate
6417c478bd9Sstevel@tonic-gate return (rval);
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate static void
usbprn_cpr_resume(dev_info_t * dip)6467c478bd9Sstevel@tonic-gate usbprn_cpr_resume(dev_info_t *dip)
6477c478bd9Sstevel@tonic-gate {
6487c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip);
6497c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep, instance);
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CPR, usbprnp->usbprn_log_handle,
6527c478bd9Sstevel@tonic-gate "usbprn_cpr_resume");
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate /* Needed as power up state of dev is "unknown" to system */
6557c478bd9Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
6567c478bd9Sstevel@tonic-gate (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate usbprn_restore_device_state(dip, usbprnp);
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_ugen_hdl) {
6637c478bd9Sstevel@tonic-gate (void) usb_ugen_attach(usbprnp->usbprn_ugen_hdl,
664112116d8Sfb DDI_RESUME);
6657c478bd9Sstevel@tonic-gate }
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate /*
6707c478bd9Sstevel@tonic-gate * usbprn_get_descriptors:
6717c478bd9Sstevel@tonic-gate * Obtain all the descriptors for the device
6727c478bd9Sstevel@tonic-gate */
6737c478bd9Sstevel@tonic-gate static int
usbprn_get_descriptors(usbprn_state_t * usbprnp)6747c478bd9Sstevel@tonic-gate usbprn_get_descriptors(usbprn_state_t *usbprnp)
6757c478bd9Sstevel@tonic-gate {
6767c478bd9Sstevel@tonic-gate int interface;
6777c478bd9Sstevel@tonic-gate usb_client_dev_data_t *dev_data =
678112116d8Sfb usbprnp->usbprn_dev_data;
6797c478bd9Sstevel@tonic-gate usb_alt_if_data_t *altif_data;
6807c478bd9Sstevel@tonic-gate usb_cfg_data_t *cfg_data;
6817c478bd9Sstevel@tonic-gate usb_ep_data_t *ep_data;
6827c478bd9Sstevel@tonic-gate dev_info_t *dip = usbprnp->usbprn_dip;
6837c478bd9Sstevel@tonic-gate int alt, rval;
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate /*
6887c478bd9Sstevel@tonic-gate * Section 4.2.1 of the spec says the printer could have
6897c478bd9Sstevel@tonic-gate * multiple configurations. This driver is just for one
6907c478bd9Sstevel@tonic-gate * configuration interface and one interface.
6917c478bd9Sstevel@tonic-gate */
6927c478bd9Sstevel@tonic-gate interface = dev_data->dev_curr_if;
6937c478bd9Sstevel@tonic-gate cfg_data = dev_data->dev_curr_cfg;
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate /* find alternate that supports BI/UNI protocol */
6967c478bd9Sstevel@tonic-gate for (alt = 0; alt < cfg_data->cfg_if[interface].if_n_alt; alt++) {
6977c478bd9Sstevel@tonic-gate altif_data = &cfg_data->cfg_if[interface].if_alt[alt];
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate if ((altif_data->altif_descr.bInterfaceProtocol ==
7007c478bd9Sstevel@tonic-gate USB_PROTO_PRINTER_UNI) ||
7017c478bd9Sstevel@tonic-gate (altif_data->altif_descr.bInterfaceProtocol ==
7027c478bd9Sstevel@tonic-gate USB_PROTO_PRINTER_BI)) {
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate break;
7057c478bd9Sstevel@tonic-gate } else {
7067c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ATTA,
7077c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
7087c478bd9Sstevel@tonic-gate "alternate %d not supported", alt);
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate if (alt == cfg_data->cfg_if[interface].if_n_alt) {
7137c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
7147c478bd9Sstevel@tonic-gate "usbprn_get_descriptors: no alternate");
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate return (USB_FAILURE);
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate if ((rval = usb_set_alt_if(dip, interface, alt, USB_FLAGS_SLEEP,
7217c478bd9Sstevel@tonic-gate NULL, NULL)) != USB_SUCCESS) {
7227c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
7237c478bd9Sstevel@tonic-gate "usbprn_get_descriptors: set alternate failed (%d)",
7247c478bd9Sstevel@tonic-gate rval);
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate return (rval);
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate usbprnp->usbprn_config_descr = cfg_data->cfg_descr;
7307c478bd9Sstevel@tonic-gate usbprnp->usbprn_if_descr = altif_data->altif_descr;
7317c478bd9Sstevel@tonic-gate
7327c478bd9Sstevel@tonic-gate /*
7337c478bd9Sstevel@tonic-gate * find the endpoint descriptors. There will be a bulk-out endpoint
7347c478bd9Sstevel@tonic-gate * and an optional bulk-in endpoint.
7357c478bd9Sstevel@tonic-gate */
7367c478bd9Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, alt, 0,
7377c478bd9Sstevel@tonic-gate USB_EP_ATTR_BULK, USB_EP_DIR_OUT)) != NULL) {
7387c478bd9Sstevel@tonic-gate usbprnp->usbprn_bulk_out.ps_ept_descr = ep_data->ep_descr;
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate if ((ep_data = usb_lookup_ep_data(dip, dev_data, interface, alt, 0,
7417c478bd9Sstevel@tonic-gate USB_EP_ATTR_BULK, USB_EP_DIR_IN)) != NULL) {
7427c478bd9Sstevel@tonic-gate usbprnp->usbprn_bulk_in.ps_ept_descr = ep_data->ep_descr;
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate return (USB_SUCCESS);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate
7497c478bd9Sstevel@tonic-gate /*
7507c478bd9Sstevel@tonic-gate * usbprn_get_device_id:
7517c478bd9Sstevel@tonic-gate * Get the device id as described in 4.2.1 of the specification
7527c478bd9Sstevel@tonic-gate * Lexmark printer returns 2 bytes when asked for 8 bytes
7537c478bd9Sstevel@tonic-gate * We are ignoring data over and underrun.
7547c478bd9Sstevel@tonic-gate * This is a synchronous function
7557c478bd9Sstevel@tonic-gate */
7567c478bd9Sstevel@tonic-gate static int
usbprn_get_device_id(usbprn_state_t * usbprnp)7577c478bd9Sstevel@tonic-gate usbprn_get_device_id(usbprn_state_t *usbprnp)
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate int len, n;
7607c478bd9Sstevel@tonic-gate mblk_t *data = NULL;
7617c478bd9Sstevel@tonic-gate usb_cr_t completion_reason;
7627c478bd9Sstevel@tonic-gate usb_cb_flags_t cb_flags;
7637c478bd9Sstevel@tonic-gate int rval = USB_FAILURE;
7647c478bd9Sstevel@tonic-gate usb_ctrl_setup_t setup = {
7657c478bd9Sstevel@tonic-gate USB_DEV_REQ_DEV_TO_HOST | /* bmRequestType */
766112116d8Sfb USB_DEV_REQ_TYPE_CLASS |
767112116d8Sfb USB_DEV_REQ_RCPT_IF,
7687c478bd9Sstevel@tonic-gate USB_PRINTER_GET_DEVICE_ID, /* bRequest */
7697c478bd9Sstevel@tonic-gate 0, /* wValue: fill in later */
7707c478bd9Sstevel@tonic-gate 0, /* wIndex: fill in later */
7717c478bd9Sstevel@tonic-gate 0, /* wLength: fill in later */
7727c478bd9Sstevel@tonic-gate 0 /* attributes */
773112116d8Sfb };
7747c478bd9Sstevel@tonic-gate void *ptr;
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
7777c478bd9Sstevel@tonic-gate "usbprn_get_device_id: Begin");
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate setup.wIndex = (usbprnp->usbprn_if_descr.bInterfaceNumber << 0x8) |
782112116d8Sfb (usbprnp->usbprn_if_descr.bAlternateSetting);
7837c478bd9Sstevel@tonic-gate setup.wLength = USBPRN_MAX_DEVICE_ID_LENGTH;
7847c478bd9Sstevel@tonic-gate setup.wValue = usbprnp->usbprn_config_descr.iConfiguration;
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate /*
7877c478bd9Sstevel@tonic-gate * This is always a sync request as this will never
7887c478bd9Sstevel@tonic-gate * be called in interrupt context.
7897c478bd9Sstevel@tonic-gate * First get the first two bytes that gives the length
7907c478bd9Sstevel@tonic-gate * of the device id string; then get the whole string
7917c478bd9Sstevel@tonic-gate */
7927c478bd9Sstevel@tonic-gate if (usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph, &setup,
7937c478bd9Sstevel@tonic-gate &data, &completion_reason, &cb_flags, 0) != USB_SUCCESS) {
7947c478bd9Sstevel@tonic-gate
7957c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
7967c478bd9Sstevel@tonic-gate "usbprn_get_device_id: First sync command failed, cr=%d ",
7977c478bd9Sstevel@tonic-gate completion_reason);
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate /*
8007c478bd9Sstevel@tonic-gate * some devices return more than requested. as long as
8017c478bd9Sstevel@tonic-gate * we get the first two bytes, we can continue
8027c478bd9Sstevel@tonic-gate */
8037c478bd9Sstevel@tonic-gate if (((completion_reason != USB_CR_DATA_OVERRUN) &&
8047c478bd9Sstevel@tonic-gate (completion_reason != USB_CR_DATA_UNDERRUN)) ||
8057c478bd9Sstevel@tonic-gate (data == NULL)) {
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate goto done;
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate ASSERT(data);
812d29f5a71Szhigang lu - Sun Microsystems - Beijing China n = MBLKL(data);
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate if (n < 2) {
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate goto done;
8177c478bd9Sstevel@tonic-gate }
8187c478bd9Sstevel@tonic-gate
8197c478bd9Sstevel@tonic-gate len = (((*data->b_rptr) << 0x8) | (*(data->b_rptr+1)));
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate /*
8227c478bd9Sstevel@tonic-gate * Std 1284-1994, chapter 7.6:
8237c478bd9Sstevel@tonic-gate * Length values of x'0000', x'0001' and x'0002' are reserved
8247c478bd9Sstevel@tonic-gate */
8257c478bd9Sstevel@tonic-gate if (len < 3) {
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate goto done;
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
8317c478bd9Sstevel@tonic-gate "usbprn_get_device_id: device id length=%d", len);
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate /* did we get enough data */
8347c478bd9Sstevel@tonic-gate if (len > n) {
8357c478bd9Sstevel@tonic-gate freemsg(data);
8367c478bd9Sstevel@tonic-gate data = NULL;
8377c478bd9Sstevel@tonic-gate
8387c478bd9Sstevel@tonic-gate setup.wLength = (uint16_t)len;
8397c478bd9Sstevel@tonic-gate if ((rval = usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph,
8407c478bd9Sstevel@tonic-gate &setup, &data, &completion_reason, &cb_flags, 0)) !=
8417c478bd9Sstevel@tonic-gate USB_SUCCESS) {
8427c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA,
8437c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
8447c478bd9Sstevel@tonic-gate "usbprn_get_device_id: 2nd command failed "
8457c478bd9Sstevel@tonic-gate "cr=%d cb_flags=0x%x",
8467c478bd9Sstevel@tonic-gate completion_reason, cb_flags);
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate goto done;
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate
851d29f5a71Szhigang lu - Sun Microsystems - Beijing China ASSERT(len == MBLKL(data));
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate
8547c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
855112116d8Sfb "usbprn_get_device_id: returned data length=%ld",
856d29f5a71Szhigang lu - Sun Microsystems - Beijing China (long)(MBLKL(data)));
8577c478bd9Sstevel@tonic-gate
8587c478bd9Sstevel@tonic-gate ptr = kmem_zalloc(len + 1, KM_SLEEP);
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
8617c478bd9Sstevel@tonic-gate usbprnp->usbprn_device_id_len = len;
8627c478bd9Sstevel@tonic-gate usbprnp->usbprn_device_id = ptr;
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate bcopy(data->b_rptr, usbprnp->usbprn_device_id,
865112116d8Sfb usbprnp->usbprn_device_id_len);
8667c478bd9Sstevel@tonic-gate usbprnp->usbprn_device_id[usbprnp->usbprn_device_id_len] = '\0';
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate /* Length is in the first two bytes, dump string in logbuf */
8697c478bd9Sstevel@tonic-gate usbprn_print_long(usbprnp, usbprnp->usbprn_device_id + 2,
8707c478bd9Sstevel@tonic-gate usbprnp->usbprn_device_id_len - 2);
8717c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
8727c478bd9Sstevel@tonic-gate
8737c478bd9Sstevel@tonic-gate rval = USB_SUCCESS;
8747c478bd9Sstevel@tonic-gate done:
8757c478bd9Sstevel@tonic-gate freemsg(data);
8767c478bd9Sstevel@tonic-gate
8777c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
8787c478bd9Sstevel@tonic-gate "usbprn_get_device_id: rval=%d", rval);
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate return (rval);
8817c478bd9Sstevel@tonic-gate }
8827c478bd9Sstevel@tonic-gate
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate /*
8857c478bd9Sstevel@tonic-gate * usbprn_get_port_status:
8867c478bd9Sstevel@tonic-gate * Get the port status.
8877c478bd9Sstevel@tonic-gate * This is a synchronous function
8887c478bd9Sstevel@tonic-gate */
8897c478bd9Sstevel@tonic-gate static int
usbprn_get_port_status(usbprn_state_t * usbprnp)8907c478bd9Sstevel@tonic-gate usbprn_get_port_status(usbprn_state_t *usbprnp)
8917c478bd9Sstevel@tonic-gate {
8927c478bd9Sstevel@tonic-gate mblk_t *data = NULL;
8937c478bd9Sstevel@tonic-gate usb_cr_t completion_reason;
8947c478bd9Sstevel@tonic-gate usb_cb_flags_t cb_flags;
8957c478bd9Sstevel@tonic-gate usb_ctrl_setup_t setup = {
8967c478bd9Sstevel@tonic-gate USB_DEV_REQ_DEV_TO_HOST | /* bmRequestType */
897112116d8Sfb USB_DEV_REQ_TYPE_CLASS |
898112116d8Sfb USB_DEV_REQ_RCPT_IF,
8997c478bd9Sstevel@tonic-gate USB_PRINTER_GET_PORT_STATUS, /* bRequest */
9007c478bd9Sstevel@tonic-gate 0, /* wValue */
9017c478bd9Sstevel@tonic-gate 0, /* wIndex: fill in later */
9027c478bd9Sstevel@tonic-gate 1, /* wLength */
9037c478bd9Sstevel@tonic-gate 0 /* attributes */
904112116d8Sfb };
9057c478bd9Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
9067c478bd9Sstevel@tonic-gate
9077c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
9087c478bd9Sstevel@tonic-gate "usbprn_get_port_status: Begin");
9097c478bd9Sstevel@tonic-gate
9107c478bd9Sstevel@tonic-gate setup.wIndex = usbprnp->usbprn_if_descr.bInterfaceNumber;
9117c478bd9Sstevel@tonic-gate if (usb_pipe_ctrl_xfer_wait(usbprnp->usbprn_def_ph,
9127c478bd9Sstevel@tonic-gate &setup, &data, &completion_reason, &cb_flags, 0) !=
9137c478bd9Sstevel@tonic-gate USB_SUCCESS) {
9147c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
9157c478bd9Sstevel@tonic-gate "usbprn_get_port_status: Sync command failed "
9167c478bd9Sstevel@tonic-gate "cr=%d cb_flags=0x%x", completion_reason, cb_flags);
9177c478bd9Sstevel@tonic-gate
9187c478bd9Sstevel@tonic-gate freemsg(data);
9197c478bd9Sstevel@tonic-gate
9207c478bd9Sstevel@tonic-gate return (USB_FAILURE);
9217c478bd9Sstevel@tonic-gate } else {
9227c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
9237c478bd9Sstevel@tonic-gate
9247c478bd9Sstevel@tonic-gate ASSERT(data);
925d29f5a71Szhigang lu - Sun Microsystems - Beijing China ASSERT(MBLKL(data) == 1);
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate usbprnp->usbprn_last_status = *data->b_rptr;
9287c478bd9Sstevel@tonic-gate
9297c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
9307c478bd9Sstevel@tonic-gate "usbprn_get_port_status(sync): status=0x%x",
9317c478bd9Sstevel@tonic-gate usbprnp->usbprn_last_status);
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9347c478bd9Sstevel@tonic-gate freemsg(data);
9357c478bd9Sstevel@tonic-gate
9367c478bd9Sstevel@tonic-gate return (USB_SUCCESS);
9377c478bd9Sstevel@tonic-gate }
9387c478bd9Sstevel@tonic-gate }
9397c478bd9Sstevel@tonic-gate
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate /*
9427c478bd9Sstevel@tonic-gate * usbprn_open:
9437c478bd9Sstevel@tonic-gate * Open the pipes
9447c478bd9Sstevel@tonic-gate */
9457c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9467c478bd9Sstevel@tonic-gate static int
usbprn_open(dev_t * devp,int flag,int sflag,cred_t * credp)9477c478bd9Sstevel@tonic-gate usbprn_open(dev_t *devp, int flag, int sflag, cred_t *credp)
9487c478bd9Sstevel@tonic-gate {
9497c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
950112116d8Sfb USBPRN_MINOR_TO_INSTANCE(getminor(*devp)));
9517c478bd9Sstevel@tonic-gate int rval = 0;
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate if (usbprnp == NULL) {
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate return (ENXIO);
9567c478bd9Sstevel@tonic-gate }
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
9597c478bd9Sstevel@tonic-gate "usbprn_open:");
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate /* Fail open on a disconnected device */
9647c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
9657c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED) {
9667c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9677c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
9687c478bd9Sstevel@tonic-gate
9697c478bd9Sstevel@tonic-gate return (ENODEV);
9707c478bd9Sstevel@tonic-gate }
9717c478bd9Sstevel@tonic-gate
9727c478bd9Sstevel@tonic-gate /* cannot happen? but just in case */
9737c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_dev_state == USB_DEV_SUSPENDED) {
9747c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9757c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate return (EIO);
9787c478bd9Sstevel@tonic-gate }
9797c478bd9Sstevel@tonic-gate
9807c478bd9Sstevel@tonic-gate if (getminor(*devp) & USBPRN_MINOR_UGEN_BITS_MASK) {
9817c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9827c478bd9Sstevel@tonic-gate
9837c478bd9Sstevel@tonic-gate rval = usb_ugen_open(usbprnp->usbprn_ugen_hdl,
984112116d8Sfb devp, flag, sflag, credp);
9857c478bd9Sstevel@tonic-gate
9867c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
9877c478bd9Sstevel@tonic-gate
9887c478bd9Sstevel@tonic-gate return (rval);
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate /* Exit if this instance is already open */
9927c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_OPEN) {
9937c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9947c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
9957c478bd9Sstevel@tonic-gate
9967c478bd9Sstevel@tonic-gate return (EBUSY);
9977c478bd9Sstevel@tonic-gate }
9987c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
9997c478bd9Sstevel@tonic-gate
10007c478bd9Sstevel@tonic-gate /* raise power */
10017c478bd9Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
10027c478bd9Sstevel@tonic-gate (void) pm_raise_power(usbprnp->usbprn_dip,
1003112116d8Sfb 0, USB_DEV_OS_FULL_PWR);
10047c478bd9Sstevel@tonic-gate /* initialize some softstate data */
10057c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
10067c478bd9Sstevel@tonic-gate usbprnp->usbprn_prn_timeouts.tmo_forward =
1007112116d8Sfb usbprnp->usbprn_setparms.write_timeout;
10087c478bd9Sstevel@tonic-gate usbprnp->usbprn_prn_timeouts.tmo_reverse = 0;
10097c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate if (usbprn_open_usb_pipes(usbprnp) != USB_SUCCESS) {
10127c478bd9Sstevel@tonic-gate
1013d291d9f2Sfrits USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
10147c478bd9Sstevel@tonic-gate "usbprn_open: pipe open failed");
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
10177c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
10187c478bd9Sstevel@tonic-gate
10197c478bd9Sstevel@tonic-gate return (EIO);
10207c478bd9Sstevel@tonic-gate }
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
10237c478bd9Sstevel@tonic-gate usbprnp->usbprn_flags |= USBPRN_OPEN;
10247c478bd9Sstevel@tonic-gate
10257c478bd9Sstevel@tonic-gate /* set last status to online */
10267c478bd9Sstevel@tonic-gate usbprnp->usbprn_last_status &= ~USB_PRINTER_PORT_NO_SELECT;
10277c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
10307c478bd9Sstevel@tonic-gate
10317c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_OPEN, usbprnp->usbprn_log_handle,
10327c478bd9Sstevel@tonic-gate "usbprn_open: End");
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate return (rval);
10357c478bd9Sstevel@tonic-gate }
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate /*
10397c478bd9Sstevel@tonic-gate * usbprn_close:
10407c478bd9Sstevel@tonic-gate * Close the pipes
10417c478bd9Sstevel@tonic-gate */
10427c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10437c478bd9Sstevel@tonic-gate static int
usbprn_close(dev_t dev,int flag,int otyp,cred_t * credp)10447c478bd9Sstevel@tonic-gate usbprn_close(dev_t dev, int flag, int otyp, cred_t *credp)
10457c478bd9Sstevel@tonic-gate {
10467c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1047112116d8Sfb USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
10487c478bd9Sstevel@tonic-gate int rval = 0;
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate if (usbprnp == NULL) {
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate return (ENXIO);
10537c478bd9Sstevel@tonic-gate }
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbprnp->usbprn_log_handle,
10567c478bd9Sstevel@tonic-gate "usbprn_close:");
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
10597c478bd9Sstevel@tonic-gate rval = usb_ugen_close(usbprnp->usbprn_ugen_hdl,
1060112116d8Sfb dev, flag, otyp, credp);
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate return (rval);
10637c478bd9Sstevel@tonic-gate }
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate /* avoid races with connect/disconnect */
10667c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
10677c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_dev_acc, USB_WAIT, 0);
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate /* Close all usb pipes */
10707c478bd9Sstevel@tonic-gate usbprn_close_usb_pipes(usbprnp);
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate /* prevent any accesses by setting flags to closed */
10737c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
10747c478bd9Sstevel@tonic-gate usbprnp->usbprn_flags &= ~USBPRN_OPEN;
10757c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_dev_acc);
10787c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
10797c478bd9Sstevel@tonic-gate
10807c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
10817c478bd9Sstevel@tonic-gate
10827c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_CLOSE, usbprnp->usbprn_log_handle,
10837c478bd9Sstevel@tonic-gate "usbprn_close: End");
10847c478bd9Sstevel@tonic-gate
10857c478bd9Sstevel@tonic-gate return (rval);
10867c478bd9Sstevel@tonic-gate }
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate
10897c478bd9Sstevel@tonic-gate /*
10907c478bd9Sstevel@tonic-gate * usbprn_read:
10917c478bd9Sstevel@tonic-gate * Read entry point (TBD)
10927c478bd9Sstevel@tonic-gate */
10937c478bd9Sstevel@tonic-gate /* ARGSUSED */
10947c478bd9Sstevel@tonic-gate static int
usbprn_read(dev_t dev,struct uio * uiop,cred_t * credp)10957c478bd9Sstevel@tonic-gate usbprn_read(dev_t dev, struct uio *uiop, cred_t *credp)
10967c478bd9Sstevel@tonic-gate {
10977c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1098112116d8Sfb USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate if (usbprnp == NULL) {
11017c478bd9Sstevel@tonic-gate
11027c478bd9Sstevel@tonic-gate return (ENXIO);
11037c478bd9Sstevel@tonic-gate }
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
11067c478bd9Sstevel@tonic-gate int rval;
11077c478bd9Sstevel@tonic-gate
11087c478bd9Sstevel@tonic-gate /* raise power */
11097c478bd9Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
11107c478bd9Sstevel@tonic-gate (void) pm_raise_power(usbprnp->usbprn_dip,
1111112116d8Sfb 0, USB_DEV_OS_FULL_PWR);
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate if (usb_serialize_access(usbprnp->usbprn_write_acc,
11147c478bd9Sstevel@tonic-gate USB_WAIT_SIG, 0) == 0) {
11157c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate return (EINTR);
11187c478bd9Sstevel@tonic-gate }
11197c478bd9Sstevel@tonic-gate
11207c478bd9Sstevel@tonic-gate rval = usb_ugen_read(usbprnp->usbprn_ugen_hdl, dev,
1121112116d8Sfb uiop, credp);
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_write_acc);
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
11267c478bd9Sstevel@tonic-gate
11277c478bd9Sstevel@tonic-gate return (rval);
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate /* Do a bulk-in from the printer */
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate return (EIO);
11337c478bd9Sstevel@tonic-gate }
11347c478bd9Sstevel@tonic-gate
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate /*
11377c478bd9Sstevel@tonic-gate * usbprn_write:
11387c478bd9Sstevel@tonic-gate * Write to the printer
11397c478bd9Sstevel@tonic-gate */
11407c478bd9Sstevel@tonic-gate /* ARGSUSED2 */
11417c478bd9Sstevel@tonic-gate static int
usbprn_write(dev_t dev,struct uio * uiop,cred_t * credp)11427c478bd9Sstevel@tonic-gate usbprn_write(dev_t dev, struct uio *uiop, cred_t *credp)
11437c478bd9Sstevel@tonic-gate {
11447c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1145112116d8Sfb USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
11467c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_in = &usbprnp->usbprn_bulk_in;
11477c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
11487c478bd9Sstevel@tonic-gate int rval;
11497c478bd9Sstevel@tonic-gate
11507c478bd9Sstevel@tonic-gate if (usbprnp == NULL) {
11517c478bd9Sstevel@tonic-gate
11527c478bd9Sstevel@tonic-gate return (ENXIO);
11537c478bd9Sstevel@tonic-gate }
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
1156112116d8Sfb "usbprn_write: Begin usbprnp=0x%p ", (void *)usbprnp);
11577c478bd9Sstevel@tonic-gate
11587c478bd9Sstevel@tonic-gate if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
11597c478bd9Sstevel@tonic-gate /* raise power */
11607c478bd9Sstevel@tonic-gate usbprn_pm_busy_component(usbprnp);
11617c478bd9Sstevel@tonic-gate (void) pm_raise_power(usbprnp->usbprn_dip,
1162112116d8Sfb 0, USB_DEV_OS_FULL_PWR);
11637c478bd9Sstevel@tonic-gate
11647c478bd9Sstevel@tonic-gate if (usb_serialize_access(usbprnp->usbprn_write_acc,
11657c478bd9Sstevel@tonic-gate USB_WAIT_SIG, 0) == 0) {
11667c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate return (EINTR);
11697c478bd9Sstevel@tonic-gate }
11707c478bd9Sstevel@tonic-gate
11717c478bd9Sstevel@tonic-gate rval = usb_ugen_write(usbprnp->usbprn_ugen_hdl, dev,
1172112116d8Sfb uiop, credp);
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_write_acc);
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprnp);
11777c478bd9Sstevel@tonic-gate
11787c478bd9Sstevel@tonic-gate return (rval);
11797c478bd9Sstevel@tonic-gate }
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate /*
11827c478bd9Sstevel@tonic-gate * serialize writes
11837c478bd9Sstevel@tonic-gate * we cannot use usbprn_ser_acc sync object at this point because
11847c478bd9Sstevel@tonic-gate * that would block out the ioctls for the full duration of the write.
11857c478bd9Sstevel@tonic-gate */
11867c478bd9Sstevel@tonic-gate if (usb_serialize_access(usbprnp->usbprn_write_acc,
11877c478bd9Sstevel@tonic-gate USB_WAIT_SIG, 0) == 0) {
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate return (EINTR);
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate /*
11937c478bd9Sstevel@tonic-gate * Check the status of the pipe. If it's not idle,
11947c478bd9Sstevel@tonic-gate * then wait.
11957c478bd9Sstevel@tonic-gate */
11967c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
11977c478bd9Sstevel@tonic-gate
11987c478bd9Sstevel@tonic-gate /* if device is disconnected or pipes closed, fail immediately */
11997c478bd9Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
12007c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
12017c478bd9Sstevel@tonic-gate
12027c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
12037c478bd9Sstevel@tonic-gate "usbprn_write: device can't be accessed");
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_write_acc);
12067c478bd9Sstevel@tonic-gate
12077c478bd9Sstevel@tonic-gate return (EIO);
12087c478bd9Sstevel@tonic-gate }
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate /* all pipes must be idle */
12117c478bd9Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
12127c478bd9Sstevel@tonic-gate ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
12157c478bd9Sstevel@tonic-gate
12167c478bd9Sstevel@tonic-gate /*
12177c478bd9Sstevel@tonic-gate * Call physio to do the transfer. physio will
12187c478bd9Sstevel@tonic-gate * call the strategy routine, and then call
12197c478bd9Sstevel@tonic-gate * biowait() to block until the transfer completes.
12207c478bd9Sstevel@tonic-gate */
12217c478bd9Sstevel@tonic-gate rval = physio(usbprn_strategy, (struct buf *)0, dev,
12227c478bd9Sstevel@tonic-gate B_WRITE, usbprn_minphys, uiop);
12237c478bd9Sstevel@tonic-gate
12247c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_write_acc);
12257c478bd9Sstevel@tonic-gate
12267c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
12277c478bd9Sstevel@tonic-gate "usbprn_write: End");
12287c478bd9Sstevel@tonic-gate
12297c478bd9Sstevel@tonic-gate return (rval);
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate
12337c478bd9Sstevel@tonic-gate /*
12347c478bd9Sstevel@tonic-gate * usbprn_poll
12357c478bd9Sstevel@tonic-gate */
12367c478bd9Sstevel@tonic-gate static int
usbprn_poll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)12377c478bd9Sstevel@tonic-gate usbprn_poll(dev_t dev, short events,
12387c478bd9Sstevel@tonic-gate int anyyet, short *reventsp, struct pollhead **phpp)
12397c478bd9Sstevel@tonic-gate {
12407c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1241112116d8Sfb USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
12427c478bd9Sstevel@tonic-gate
12437c478bd9Sstevel@tonic-gate if (usbprnp == NULL) {
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate return (ENXIO);
12467c478bd9Sstevel@tonic-gate }
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate if (getminor(dev) & USBPRN_MINOR_UGEN_BITS_MASK) {
12497c478bd9Sstevel@tonic-gate return (usb_ugen_poll(usbprnp->usbprn_ugen_hdl, dev, events,
1250112116d8Sfb anyyet, reventsp, phpp));
12517c478bd9Sstevel@tonic-gate }
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate return (ENXIO);
12547c478bd9Sstevel@tonic-gate }
12557c478bd9Sstevel@tonic-gate
12567c478bd9Sstevel@tonic-gate
12577c478bd9Sstevel@tonic-gate /*
12587c478bd9Sstevel@tonic-gate * usbprn_strategy:
12597c478bd9Sstevel@tonic-gate * service a request to the device.
12607c478bd9Sstevel@tonic-gate */
12617c478bd9Sstevel@tonic-gate static int
usbprn_strategy(struct buf * bp)12627c478bd9Sstevel@tonic-gate usbprn_strategy(struct buf *bp)
12637c478bd9Sstevel@tonic-gate {
12647c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1265112116d8Sfb USBPRN_MINOR_TO_INSTANCE(getminor(bp->b_edev)));
12667c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate bp_mapin(bp);
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate /*
12717c478bd9Sstevel@tonic-gate * serialize to avoid races
12727c478bd9Sstevel@tonic-gate * access is released in usbprn_biodone()
12737c478bd9Sstevel@tonic-gate */
12747c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_dev_acc, USB_WAIT, 0);
12757c478bd9Sstevel@tonic-gate
12767c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
12777c478bd9Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
12787c478bd9Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
12797c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
12807c478bd9Sstevel@tonic-gate
12817c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
12827c478bd9Sstevel@tonic-gate "usbprn_strategy: device can't be accessed");
12837c478bd9Sstevel@tonic-gate
12847c478bd9Sstevel@tonic-gate return (0);
12857c478bd9Sstevel@tonic-gate }
12867c478bd9Sstevel@tonic-gate
12877c478bd9Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_NEED_TO_XFER;
12887c478bd9Sstevel@tonic-gate
12897c478bd9Sstevel@tonic-gate ASSERT(usbprnp->usbprn_bp == NULL);
12907c478bd9Sstevel@tonic-gate usbprnp->usbprn_bp = bp;
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
12937c478bd9Sstevel@tonic-gate "usbprn_strategy: usbprnp=0x%p bp=0x%p count=%lu",
1294112116d8Sfb (void *)usbprnp, (void *)bp, bp->b_bcount);
12957c478bd9Sstevel@tonic-gate
12967c478bd9Sstevel@tonic-gate ASSERT(usbprnp->usbprn_bulk_mp == NULL);
12977c478bd9Sstevel@tonic-gate
12987c478bd9Sstevel@tonic-gate usbprnp->usbprn_bulk_mp = allocb(bp->b_bcount, BPRI_HI);
12997c478bd9Sstevel@tonic-gate
13007c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_bulk_mp == NULL) {
13017c478bd9Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
13027c478bd9Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
13037c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
13047c478bd9Sstevel@tonic-gate
13057c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
13067c478bd9Sstevel@tonic-gate "usbprn_strategy: allocb failed");
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate return (0);
13097c478bd9Sstevel@tonic-gate }
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate bcopy((caddr_t)bp->b_un.b_addr,
1312112116d8Sfb usbprnp->usbprn_bulk_mp->b_datap->db_base, bp->b_bcount);
13137c478bd9Sstevel@tonic-gate usbprnp->usbprn_bulk_mp->b_wptr += bp->b_bcount;
13147c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate usbprn_send_async_bulk_data(usbprnp);
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate return (0);
13197c478bd9Sstevel@tonic-gate }
13207c478bd9Sstevel@tonic-gate
13217c478bd9Sstevel@tonic-gate
13227c478bd9Sstevel@tonic-gate /*
13237c478bd9Sstevel@tonic-gate * usbprn_ioctl:
13247c478bd9Sstevel@tonic-gate * handle the ioctl
13257c478bd9Sstevel@tonic-gate */
13267c478bd9Sstevel@tonic-gate /*ARGSUSED4*/
13277c478bd9Sstevel@tonic-gate static int
usbprn_ioctl(dev_t dev,int cmd,intptr_t arg,int flag,cred_t * credp,int * rvalp)13287c478bd9Sstevel@tonic-gate usbprn_ioctl(dev_t dev, int cmd, intptr_t arg, int flag,
13297c478bd9Sstevel@tonic-gate cred_t *credp, int *rvalp)
13307c478bd9Sstevel@tonic-gate {
13317c478bd9Sstevel@tonic-gate int err = 0;
13327c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1333112116d8Sfb USBPRN_MINOR_TO_INSTANCE(getminor(dev)));
13347c478bd9Sstevel@tonic-gate struct ecpp_device_id usbprn_devid;
13357c478bd9Sstevel@tonic-gate int len;
13367c478bd9Sstevel@tonic-gate
13377c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
13387c478bd9Sstevel@tonic-gate "usbprn_ioctl: Begin ");
13397c478bd9Sstevel@tonic-gate
13407c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
13417c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate /*
13447c478bd9Sstevel@tonic-gate * only for PRNIOC_GET_STATUS cmd:
13457c478bd9Sstevel@tonic-gate * if device is disconnected or pipes closed, fail immediately
13467c478bd9Sstevel@tonic-gate */
13477c478bd9Sstevel@tonic-gate if ((cmd == PRNIOC_GET_STATUS) &&
13487c478bd9Sstevel@tonic-gate !(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
13497c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
13507c478bd9Sstevel@tonic-gate
13517c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
13527c478bd9Sstevel@tonic-gate "usbprn_write: device can't be accessed");
13537c478bd9Sstevel@tonic-gate
13547c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
13557c478bd9Sstevel@tonic-gate
13567c478bd9Sstevel@tonic-gate return (EIO);
13577c478bd9Sstevel@tonic-gate }
13587c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
13597c478bd9Sstevel@tonic-gate
13607c478bd9Sstevel@tonic-gate switch (cmd) {
13617c478bd9Sstevel@tonic-gate case ECPPIOC_GETDEVID:
13627c478bd9Sstevel@tonic-gate /*
13637c478bd9Sstevel@tonic-gate * With genericized ioctls this interface should change.
13647c478bd9Sstevel@tonic-gate * We ignore the mode in USB printer driver because
13657c478bd9Sstevel@tonic-gate * it need not be in nibble mode in usb driver unlike
13667c478bd9Sstevel@tonic-gate * ecpp to retrieve the device id string. Also we do
13677c478bd9Sstevel@tonic-gate * not expect the application to call this twice since
13687c478bd9Sstevel@tonic-gate * it doesn't change since attach time and we take care
13697c478bd9Sstevel@tonic-gate * of calling it twice: once for getting the length and
13707c478bd9Sstevel@tonic-gate * once for getting the actual device id string. So we
13717c478bd9Sstevel@tonic-gate * set both the lengths to actual device id string length.
13727c478bd9Sstevel@tonic-gate * Ref: PSARC/2000/018
13737c478bd9Sstevel@tonic-gate */
13747c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
13757c478bd9Sstevel@tonic-gate "usbprn_ioctl: ECPPIOC_GETDEVID(0x%x)", cmd);
13767c478bd9Sstevel@tonic-gate
13777c478bd9Sstevel@tonic-gate bzero(&usbprn_devid, sizeof (usbprn_devid));
13787c478bd9Sstevel@tonic-gate
13797c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
13807c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
13817c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) {
13827c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: {
13837c478bd9Sstevel@tonic-gate struct ecpp_device_id32 usbprn_devid32;
13847c478bd9Sstevel@tonic-gate
13857c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &usbprn_devid32,
13867c478bd9Sstevel@tonic-gate sizeof (struct ecpp_device_id32), flag)) {
13877c478bd9Sstevel@tonic-gate err = EFAULT;
13887c478bd9Sstevel@tonic-gate
13897c478bd9Sstevel@tonic-gate break;
13907c478bd9Sstevel@tonic-gate }
13917c478bd9Sstevel@tonic-gate
13927c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_device_id == NULL) {
13937c478bd9Sstevel@tonic-gate err = EIO;
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate break;
13967c478bd9Sstevel@tonic-gate }
13977c478bd9Sstevel@tonic-gate ASSERT(usbprnp->usbprn_device_id_len > 2);
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gate usbprn_devid32.rlen = usbprnp->usbprn_device_id_len - 2;
14007c478bd9Sstevel@tonic-gate len = min(usbprn_devid32.len, usbprn_devid32.rlen);
14017c478bd9Sstevel@tonic-gate
14027c478bd9Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
14037c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)usbprn_devid32.addr,
14047c478bd9Sstevel@tonic-gate len, flag)) {
14057c478bd9Sstevel@tonic-gate err = EFAULT;
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate break;
14087c478bd9Sstevel@tonic-gate }
14097c478bd9Sstevel@tonic-gate
14107c478bd9Sstevel@tonic-gate if (ddi_copyout(&usbprn_devid32, (caddr_t)arg,
14117c478bd9Sstevel@tonic-gate sizeof (struct ecpp_device_id32), flag)) {
14127c478bd9Sstevel@tonic-gate err = EFAULT;
14137c478bd9Sstevel@tonic-gate
14147c478bd9Sstevel@tonic-gate break;
14157c478bd9Sstevel@tonic-gate }
14167c478bd9Sstevel@tonic-gate
14177c478bd9Sstevel@tonic-gate break;
14187c478bd9Sstevel@tonic-gate }
14197c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE:
14207c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &usbprn_devid,
14217c478bd9Sstevel@tonic-gate sizeof (struct ecpp_device_id), flag)) {
14227c478bd9Sstevel@tonic-gate err = EFAULT;
14237c478bd9Sstevel@tonic-gate
14247c478bd9Sstevel@tonic-gate break;
14257c478bd9Sstevel@tonic-gate }
14267c478bd9Sstevel@tonic-gate
14277c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_device_id == NULL) {
14287c478bd9Sstevel@tonic-gate err = EIO;
14297c478bd9Sstevel@tonic-gate
14307c478bd9Sstevel@tonic-gate break;
14317c478bd9Sstevel@tonic-gate }
14327c478bd9Sstevel@tonic-gate ASSERT(usbprnp->usbprn_device_id_len > 2);
14337c478bd9Sstevel@tonic-gate
14347c478bd9Sstevel@tonic-gate usbprn_devid.rlen = usbprnp->usbprn_device_id_len - 2;
14357c478bd9Sstevel@tonic-gate len = min(usbprn_devid.len, usbprn_devid.rlen);
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
14387c478bd9Sstevel@tonic-gate usbprn_devid.addr, len, flag)) {
14397c478bd9Sstevel@tonic-gate err = EFAULT;
14407c478bd9Sstevel@tonic-gate
14417c478bd9Sstevel@tonic-gate break;
14427c478bd9Sstevel@tonic-gate }
14437c478bd9Sstevel@tonic-gate
14447c478bd9Sstevel@tonic-gate if (ddi_copyout(&usbprn_devid, (caddr_t)arg,
14457c478bd9Sstevel@tonic-gate sizeof (struct ecpp_device_id), flag)) {
14467c478bd9Sstevel@tonic-gate err = EFAULT;
14477c478bd9Sstevel@tonic-gate
14487c478bd9Sstevel@tonic-gate break;
14497c478bd9Sstevel@tonic-gate }
14507c478bd9Sstevel@tonic-gate
14517c478bd9Sstevel@tonic-gate break;
14527c478bd9Sstevel@tonic-gate }
14537c478bd9Sstevel@tonic-gate
14547c478bd9Sstevel@tonic-gate break;
14557c478bd9Sstevel@tonic-gate #else
14567c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &usbprn_devid,
14577c478bd9Sstevel@tonic-gate sizeof (struct ecpp_device_id), flag)) {
14587c478bd9Sstevel@tonic-gate err = EFAULT;
14597c478bd9Sstevel@tonic-gate
14607c478bd9Sstevel@tonic-gate break;
14617c478bd9Sstevel@tonic-gate }
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate
14647c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_device_id == NULL) {
14657c478bd9Sstevel@tonic-gate err = EIO;
14667c478bd9Sstevel@tonic-gate
14677c478bd9Sstevel@tonic-gate break;
14687c478bd9Sstevel@tonic-gate }
14697c478bd9Sstevel@tonic-gate ASSERT(usbprnp->usbprn_device_id_len > 2);
14707c478bd9Sstevel@tonic-gate
14717c478bd9Sstevel@tonic-gate usbprn_devid.rlen = usbprnp->usbprn_device_id_len - 2;
14727c478bd9Sstevel@tonic-gate len = min(usbprn_devid.len, usbprn_devid.rlen);
14737c478bd9Sstevel@tonic-gate
14747c478bd9Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
14757c478bd9Sstevel@tonic-gate usbprn_devid.addr, len, flag)) {
14767c478bd9Sstevel@tonic-gate err = EFAULT;
14777c478bd9Sstevel@tonic-gate
14787c478bd9Sstevel@tonic-gate break;
14797c478bd9Sstevel@tonic-gate }
14807c478bd9Sstevel@tonic-gate
14817c478bd9Sstevel@tonic-gate if (ddi_copyout(&usbprn_devid, (caddr_t)arg,
14827c478bd9Sstevel@tonic-gate sizeof (struct ecpp_device_id), flag)) {
14837c478bd9Sstevel@tonic-gate err = EFAULT;
14847c478bd9Sstevel@tonic-gate
14857c478bd9Sstevel@tonic-gate break;
14867c478bd9Sstevel@tonic-gate }
14877c478bd9Sstevel@tonic-gate
14887c478bd9Sstevel@tonic-gate break;
14897c478bd9Sstevel@tonic-gate #endif
14907c478bd9Sstevel@tonic-gate case ECPPIOC_SETPARMS:
14917c478bd9Sstevel@tonic-gate err = usbprn_setparms(usbprnp, arg, flag);
14927c478bd9Sstevel@tonic-gate
14937c478bd9Sstevel@tonic-gate break;
14947c478bd9Sstevel@tonic-gate case ECPPIOC_GETPARMS:
14957c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
14967c478bd9Sstevel@tonic-gate "usbprn_ioctl: ECPPIOC_GETPARMS(0x%x)", cmd);
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate /* Get the parameters */
14997c478bd9Sstevel@tonic-gate err = usbprn_getparms(usbprnp, arg, flag);
15007c478bd9Sstevel@tonic-gate
15017c478bd9Sstevel@tonic-gate break;
15027c478bd9Sstevel@tonic-gate case BPPIOC_GETERR:
15037c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15047c478bd9Sstevel@tonic-gate "usbprn_ioctl: ECPPIOC_GETERR(0x%x)", cmd);
15057c478bd9Sstevel@tonic-gate
15067c478bd9Sstevel@tonic-gate /* Get the error state */
15077c478bd9Sstevel@tonic-gate usbprn_geterr(usbprnp, arg, flag);
15087c478bd9Sstevel@tonic-gate
15097c478bd9Sstevel@tonic-gate break;
15107c478bd9Sstevel@tonic-gate case BPPIOC_TESTIO:
15117c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15127c478bd9Sstevel@tonic-gate "usbprn_ioctl: BPPIOC_TESTIO(0x%x)", cmd);
15137c478bd9Sstevel@tonic-gate
15147c478bd9Sstevel@tonic-gate /* Get the port status */
15157c478bd9Sstevel@tonic-gate err = usbprn_testio(usbprnp, flag);
15167c478bd9Sstevel@tonic-gate
15177c478bd9Sstevel@tonic-gate break;
15187c478bd9Sstevel@tonic-gate case PRNIOC_GET_IFCAP:
15197c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15207c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_IFCAP(0x%x)", cmd);
15217c478bd9Sstevel@tonic-gate
15227c478bd9Sstevel@tonic-gate /* get interface capabilities */
15237c478bd9Sstevel@tonic-gate err = usbprn_prnio_get_ifcap(usbprnp, arg, flag);
15247c478bd9Sstevel@tonic-gate
15257c478bd9Sstevel@tonic-gate break;
15267c478bd9Sstevel@tonic-gate case PRNIOC_SET_IFCAP:
15277c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15287c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_SET_IFCAP(0x%x)", cmd);
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate /* get interface capabilities */
15317c478bd9Sstevel@tonic-gate err = usbprn_prnio_set_ifcap(usbprnp, arg, flag);
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate break;
15347c478bd9Sstevel@tonic-gate case PRNIOC_GET_IFINFO:
15357c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15367c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_IFINFO(0x%x)", cmd);
15377c478bd9Sstevel@tonic-gate
15387c478bd9Sstevel@tonic-gate /* get interface information */
15397c478bd9Sstevel@tonic-gate err = usbprn_prnio_get_ifinfo(usbprnp, arg, flag);
15407c478bd9Sstevel@tonic-gate
15417c478bd9Sstevel@tonic-gate break;
15427c478bd9Sstevel@tonic-gate case PRNIOC_GET_STATUS:
15437c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15447c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_STATUS(0x%x)", cmd);
15457c478bd9Sstevel@tonic-gate
15467c478bd9Sstevel@tonic-gate /* get prnio status */
15477c478bd9Sstevel@tonic-gate err = usbprn_prnio_get_status(usbprnp, arg, flag);
15487c478bd9Sstevel@tonic-gate
15497c478bd9Sstevel@tonic-gate break;
15507c478bd9Sstevel@tonic-gate case PRNIOC_GET_1284_DEVID:
15517c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15527c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_1284_DEVID(0x%x)", cmd);
15537c478bd9Sstevel@tonic-gate
15547c478bd9Sstevel@tonic-gate /* get device ID */
15557c478bd9Sstevel@tonic-gate err = usbprn_prnio_get_1284_devid(usbprnp, arg, flag);
15567c478bd9Sstevel@tonic-gate
15577c478bd9Sstevel@tonic-gate break;
15587c478bd9Sstevel@tonic-gate case PRNIOC_GET_1284_STATUS:
15597c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15607c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_1284_STATUS(0x%x)", cmd);
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate /* get prnio status */
15637c478bd9Sstevel@tonic-gate err = usbprn_prnio_get_1284_status(usbprnp, arg, flag);
15647c478bd9Sstevel@tonic-gate
15657c478bd9Sstevel@tonic-gate break;
15667c478bd9Sstevel@tonic-gate case PRNIOC_GET_TIMEOUTS:
15677c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15687c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_GET_TIMEOUTS(0x%x)", cmd);
15697c478bd9Sstevel@tonic-gate
15707c478bd9Sstevel@tonic-gate /* Get the parameters */
15717c478bd9Sstevel@tonic-gate err = usbprn_prnio_get_timeouts(usbprnp, arg, flag);
15727c478bd9Sstevel@tonic-gate
15737c478bd9Sstevel@tonic-gate break;
15747c478bd9Sstevel@tonic-gate case PRNIOC_SET_TIMEOUTS:
15757c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15767c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_SET_TIMEOUTS(0x%x)", cmd);
15777c478bd9Sstevel@tonic-gate
15787c478bd9Sstevel@tonic-gate /* Get the parameters */
15797c478bd9Sstevel@tonic-gate err = usbprn_prnio_set_timeouts(usbprnp, arg, flag);
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate break;
15827c478bd9Sstevel@tonic-gate case PRNIOC_RESET:
15837c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15847c478bd9Sstevel@tonic-gate "usbprn_ioctl : PRNIOC_RESET(0x%x)", cmd);
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate /* nothing */
15877c478bd9Sstevel@tonic-gate err = 0;
15887c478bd9Sstevel@tonic-gate
15897c478bd9Sstevel@tonic-gate break;
15907c478bd9Sstevel@tonic-gate default:
15917c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15927c478bd9Sstevel@tonic-gate "usbprn_ioctl: unknown(0x%x)", cmd);
15937c478bd9Sstevel@tonic-gate err = EINVAL;
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate
15967c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
15977c478bd9Sstevel@tonic-gate
15987c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
15997c478bd9Sstevel@tonic-gate "usbprn_ioctl: End ");
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gate return (err);
16027c478bd9Sstevel@tonic-gate }
16037c478bd9Sstevel@tonic-gate
16047c478bd9Sstevel@tonic-gate
16057c478bd9Sstevel@tonic-gate /*
16067c478bd9Sstevel@tonic-gate * breakup by physio
16077c478bd9Sstevel@tonic-gate */
16087c478bd9Sstevel@tonic-gate static void
usbprn_minphys(struct buf * bp)16097c478bd9Sstevel@tonic-gate usbprn_minphys(struct buf *bp)
16107c478bd9Sstevel@tonic-gate {
16117c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = ddi_get_soft_state(usbprn_statep,
1612112116d8Sfb USBPRN_MINOR_TO_INSTANCE(getminor(bp->b_edev)));
16137c478bd9Sstevel@tonic-gate
16147c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
16157c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
16167c478bd9Sstevel@tonic-gate "usbprn_minphys: bcount=%lu", bp->b_bcount);
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate if (bp->b_bcount > usbprnp->usbprn_max_bulk_xfer_size) {
16197c478bd9Sstevel@tonic-gate bp->b_bcount = min(usbprn_max_xfer_size,
16207c478bd9Sstevel@tonic-gate usbprnp->usbprn_max_bulk_xfer_size);
16217c478bd9Sstevel@tonic-gate } else {
16227c478bd9Sstevel@tonic-gate bp->b_bcount = min(usbprn_max_xfer_size, bp->b_bcount);
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16257c478bd9Sstevel@tonic-gate }
16267c478bd9Sstevel@tonic-gate
16277c478bd9Sstevel@tonic-gate
16287c478bd9Sstevel@tonic-gate /*
16297c478bd9Sstevel@tonic-gate * usbprn_open_usb_pipes:
16307c478bd9Sstevel@tonic-gate * Open all pipes on the device
16317c478bd9Sstevel@tonic-gate */
16327c478bd9Sstevel@tonic-gate static int
usbprn_open_usb_pipes(usbprn_state_t * usbprnp)16337c478bd9Sstevel@tonic-gate usbprn_open_usb_pipes(usbprn_state_t *usbprnp)
16347c478bd9Sstevel@tonic-gate {
16357c478bd9Sstevel@tonic-gate usb_pipe_policy_t *policy;
16367c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_in = &usbprnp->usbprn_bulk_in;
16377c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
16387c478bd9Sstevel@tonic-gate
16397c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
16407c478bd9Sstevel@tonic-gate "usbprn_open_usb_pipes:");
16417c478bd9Sstevel@tonic-gate
16427c478bd9Sstevel@tonic-gate /*
16437c478bd9Sstevel@tonic-gate * Intitialize the pipe policy for the bulk out pipe
16447c478bd9Sstevel@tonic-gate */
16457c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
16467c478bd9Sstevel@tonic-gate policy = &(bulk_out->ps_policy);
16477c478bd9Sstevel@tonic-gate policy->pp_max_async_reqs = 1;
16487c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16497c478bd9Sstevel@tonic-gate
16507c478bd9Sstevel@tonic-gate /* Open bulk_out pipe */
16517c478bd9Sstevel@tonic-gate if (usb_pipe_open(usbprnp->usbprn_dip, &bulk_out->ps_ept_descr,
16527c478bd9Sstevel@tonic-gate policy, USB_FLAGS_SLEEP, &bulk_out->ps_handle) != USB_SUCCESS) {
16537c478bd9Sstevel@tonic-gate
16547c478bd9Sstevel@tonic-gate return (USB_FAILURE);
16557c478bd9Sstevel@tonic-gate }
16567c478bd9Sstevel@tonic-gate
16577c478bd9Sstevel@tonic-gate #ifdef LATER
16587c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
16597c478bd9Sstevel@tonic-gate /* Open the bulk in pipe if one exists */
16607c478bd9Sstevel@tonic-gate if (bulk_in->ps_ept_descr->bLength) {
16617c478bd9Sstevel@tonic-gate /*
16627c478bd9Sstevel@tonic-gate * Initialize the pipe policy for the Bulk In pipe
16637c478bd9Sstevel@tonic-gate */
16647c478bd9Sstevel@tonic-gate policy = &bulk_in->ps_policy;
16657c478bd9Sstevel@tonic-gate bulk_in->ps_flags = USBPRN_PS_IDLE;
16667c478bd9Sstevel@tonic-gate policy->pp_max_async_reqs = 1;
16677c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate /* Open bulk_in pipe */
16707c478bd9Sstevel@tonic-gate if (usb_pipe_open(usbprnp->usbprn_dip, bulk_in->ps_ept_descr,
16717c478bd9Sstevel@tonic-gate policy, USB_FLAGS_SLEEP, &bulk_in->ps_handle) !=
16727c478bd9Sstevel@tonic-gate USB_SUCCESS) {
16737c478bd9Sstevel@tonic-gate
16747c478bd9Sstevel@tonic-gate return (USB_FAILURE);
16757c478bd9Sstevel@tonic-gate }
16767c478bd9Sstevel@tonic-gate } else {
16777c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16787c478bd9Sstevel@tonic-gate }
16797c478bd9Sstevel@tonic-gate #else
16807c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
16817c478bd9Sstevel@tonic-gate bulk_in->ps_flags = USBPRN_PS_IDLE;
16827c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
16837c478bd9Sstevel@tonic-gate #endif
16847c478bd9Sstevel@tonic-gate
16857c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
16867c478bd9Sstevel@tonic-gate "usbprn_open_usb_pipes: success");
16877c478bd9Sstevel@tonic-gate
16887c478bd9Sstevel@tonic-gate return (USB_SUCCESS);
16897c478bd9Sstevel@tonic-gate }
16907c478bd9Sstevel@tonic-gate
16917c478bd9Sstevel@tonic-gate
16927c478bd9Sstevel@tonic-gate /*
16937c478bd9Sstevel@tonic-gate * usbprn_close_usb_pipes:
16947c478bd9Sstevel@tonic-gate * Close the default/bulk in/out pipes synchronously
16957c478bd9Sstevel@tonic-gate */
16967c478bd9Sstevel@tonic-gate static void
usbprn_close_usb_pipes(usbprn_state_t * usbprnp)16977c478bd9Sstevel@tonic-gate usbprn_close_usb_pipes(usbprn_state_t *usbprnp)
16987c478bd9Sstevel@tonic-gate {
16997c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_in = &usbprnp->usbprn_bulk_in;
17007c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
17037c478bd9Sstevel@tonic-gate "usbprn_close_usb_pipes:");
17047c478bd9Sstevel@tonic-gate #ifdef DEBUG
17057c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
17067c478bd9Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
17077c478bd9Sstevel@tonic-gate ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
17087c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
17097c478bd9Sstevel@tonic-gate #endif
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate /*
17127c478bd9Sstevel@tonic-gate * close the pipe, if another thread is already closing the
17137c478bd9Sstevel@tonic-gate * pipe, we get USB_INVALID_PIPE
17147c478bd9Sstevel@tonic-gate */
17157c478bd9Sstevel@tonic-gate if (bulk_out->ps_handle) {
17167c478bd9Sstevel@tonic-gate
17177c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
17187c478bd9Sstevel@tonic-gate "usbprn_close_usb_pipes: Closing bulk out pipe");
17197c478bd9Sstevel@tonic-gate
17207c478bd9Sstevel@tonic-gate usb_pipe_close(usbprnp->usbprn_dip, bulk_out->ps_handle,
1721112116d8Sfb USB_FLAGS_SLEEP, NULL, NULL);
17227c478bd9Sstevel@tonic-gate bulk_out->ps_handle = NULL;
17237c478bd9Sstevel@tonic-gate }
17247c478bd9Sstevel@tonic-gate if (bulk_in->ps_handle) {
17257c478bd9Sstevel@tonic-gate
17267c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
17277c478bd9Sstevel@tonic-gate "usbprn_close_usb_pipes: Closing bulk in pipe");
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate usb_pipe_close(usbprnp->usbprn_dip, bulk_in->ps_handle,
1730112116d8Sfb USB_FLAGS_SLEEP, NULL, NULL);
17317c478bd9Sstevel@tonic-gate bulk_in->ps_handle = NULL;
17327c478bd9Sstevel@tonic-gate }
17337c478bd9Sstevel@tonic-gate }
17347c478bd9Sstevel@tonic-gate
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate /*
17377c478bd9Sstevel@tonic-gate * usbprn_getparms:
17387c478bd9Sstevel@tonic-gate * Get the parameters for the device
17397c478bd9Sstevel@tonic-gate */
17407c478bd9Sstevel@tonic-gate static int
usbprn_getparms(usbprn_state_t * usbprnp,intptr_t arg,int flag)17417c478bd9Sstevel@tonic-gate usbprn_getparms(usbprn_state_t *usbprnp, intptr_t arg, int flag)
17427c478bd9Sstevel@tonic-gate {
17437c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate if (ddi_copyout(&usbprnp->usbprn_setparms,
17467c478bd9Sstevel@tonic-gate (caddr_t)arg, sizeof (struct ecpp_transfer_parms), flag)) {
17477c478bd9Sstevel@tonic-gate
17487c478bd9Sstevel@tonic-gate return (EFAULT);
17497c478bd9Sstevel@tonic-gate }
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate return (0);
17527c478bd9Sstevel@tonic-gate }
17537c478bd9Sstevel@tonic-gate
17547c478bd9Sstevel@tonic-gate
17557c478bd9Sstevel@tonic-gate /*
17567c478bd9Sstevel@tonic-gate * usbprn_setparms:
17577c478bd9Sstevel@tonic-gate * Set the parameters for the device
17587c478bd9Sstevel@tonic-gate */
17597c478bd9Sstevel@tonic-gate static int
usbprn_setparms(usbprn_state_t * usbprnp,intptr_t arg,int flag)17607c478bd9Sstevel@tonic-gate usbprn_setparms(usbprn_state_t *usbprnp, intptr_t arg, int flag)
17617c478bd9Sstevel@tonic-gate {
17627c478bd9Sstevel@tonic-gate struct ecpp_transfer_parms xfer;
17637c478bd9Sstevel@tonic-gate
17647c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
17657c478bd9Sstevel@tonic-gate
17667c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &xfer,
17677c478bd9Sstevel@tonic-gate sizeof (struct ecpp_transfer_parms), flag)) {
17687c478bd9Sstevel@tonic-gate
17697c478bd9Sstevel@tonic-gate return (EFAULT);
17707c478bd9Sstevel@tonic-gate }
17717c478bd9Sstevel@tonic-gate if ((xfer.write_timeout < USBPRN_XFER_TIMEOUT_MIN) ||
17727c478bd9Sstevel@tonic-gate (xfer.write_timeout > USBPRN_XFER_TIMEOUT_MAX)) {
17737c478bd9Sstevel@tonic-gate
17747c478bd9Sstevel@tonic-gate return (EINVAL);
17757c478bd9Sstevel@tonic-gate }
17767c478bd9Sstevel@tonic-gate if (!((xfer.mode == ECPP_CENTRONICS) ||
17777c478bd9Sstevel@tonic-gate (xfer.mode == ECPP_COMPAT_MODE) ||
17787c478bd9Sstevel@tonic-gate (xfer.mode == ECPP_NIBBLE_MODE) ||
17797c478bd9Sstevel@tonic-gate (xfer.mode == ECPP_ECP_MODE) ||
17807c478bd9Sstevel@tonic-gate (xfer.mode == ECPP_DIAG_MODE))) {
17817c478bd9Sstevel@tonic-gate
17827c478bd9Sstevel@tonic-gate return (EINVAL);
17837c478bd9Sstevel@tonic-gate
17847c478bd9Sstevel@tonic-gate }
17857c478bd9Sstevel@tonic-gate if (xfer.mode != ECPP_CENTRONICS) {
17867c478bd9Sstevel@tonic-gate
17877c478bd9Sstevel@tonic-gate return (EPROTONOSUPPORT);
17887c478bd9Sstevel@tonic-gate }
17897c478bd9Sstevel@tonic-gate
17907c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
17917c478bd9Sstevel@tonic-gate usbprnp->usbprn_setparms = xfer;
17927c478bd9Sstevel@tonic-gate usbprnp->usbprn_prn_timeouts.tmo_forward = xfer.write_timeout;
17937c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
17947c478bd9Sstevel@tonic-gate
17957c478bd9Sstevel@tonic-gate return (0);
17967c478bd9Sstevel@tonic-gate }
17977c478bd9Sstevel@tonic-gate
17987c478bd9Sstevel@tonic-gate
17997c478bd9Sstevel@tonic-gate /*
18007c478bd9Sstevel@tonic-gate * usbprn_geterr:
18017c478bd9Sstevel@tonic-gate * Return the any device error state
18027c478bd9Sstevel@tonic-gate */
18037c478bd9Sstevel@tonic-gate static void
usbprn_geterr(usbprn_state_t * usbprnp,intptr_t arg,int flag)18047c478bd9Sstevel@tonic-gate usbprn_geterr(usbprn_state_t *usbprnp, intptr_t arg, int flag)
18057c478bd9Sstevel@tonic-gate {
18067c478bd9Sstevel@tonic-gate struct bpp_error_status bpp_status;
18077c478bd9Sstevel@tonic-gate
18087c478bd9Sstevel@tonic-gate bzero(&bpp_status, sizeof (bpp_status));
18097c478bd9Sstevel@tonic-gate
18107c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
18117c478bd9Sstevel@tonic-gate bpp_status.bus_error = 0;
18127c478bd9Sstevel@tonic-gate bpp_status.timeout_occurred = 0;
18137c478bd9Sstevel@tonic-gate bpp_status.pin_status = usbprn_error_state(usbprnp->usbprn_last_status);
18147c478bd9Sstevel@tonic-gate
18157c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
18167c478bd9Sstevel@tonic-gate "usbprn_geterr: status=0x%x", usbprnp->usbprn_last_status);
18177c478bd9Sstevel@tonic-gate
18187c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
18197c478bd9Sstevel@tonic-gate
18207c478bd9Sstevel@tonic-gate (void) ddi_copyout(&bpp_status,
18217c478bd9Sstevel@tonic-gate (caddr_t)arg, sizeof (struct bpp_error_status), flag);
18227c478bd9Sstevel@tonic-gate }
18237c478bd9Sstevel@tonic-gate
18247c478bd9Sstevel@tonic-gate
18257c478bd9Sstevel@tonic-gate /*
18267c478bd9Sstevel@tonic-gate * usbprn_error_state:
18277c478bd9Sstevel@tonic-gate * Map the driver error state to that of the application
18287c478bd9Sstevel@tonic-gate */
18297c478bd9Sstevel@tonic-gate static char
usbprn_error_state(uchar_t status)18307c478bd9Sstevel@tonic-gate usbprn_error_state(uchar_t status)
18317c478bd9Sstevel@tonic-gate {
18327c478bd9Sstevel@tonic-gate uchar_t app_err_status = 0;
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate if (!(status & USB_PRINTER_PORT_NO_ERROR)) {
18357c478bd9Sstevel@tonic-gate app_err_status |= USB_PRINTER_ERR_ERR;
18367c478bd9Sstevel@tonic-gate }
18377c478bd9Sstevel@tonic-gate if (status & USB_PRINTER_PORT_EMPTY) {
18387c478bd9Sstevel@tonic-gate app_err_status |= USB_PRINTER_PE_ERR;
18397c478bd9Sstevel@tonic-gate }
18407c478bd9Sstevel@tonic-gate if (!(status & USB_PRINTER_PORT_NO_SELECT)) {
18417c478bd9Sstevel@tonic-gate app_err_status |= USB_PRINTER_SLCT_ERR;
18427c478bd9Sstevel@tonic-gate }
18437c478bd9Sstevel@tonic-gate
18447c478bd9Sstevel@tonic-gate return (app_err_status);
18457c478bd9Sstevel@tonic-gate }
18467c478bd9Sstevel@tonic-gate
18477c478bd9Sstevel@tonic-gate
18487c478bd9Sstevel@tonic-gate static int
usbprn_ioctl_get_status(usbprn_state_t * usbprnp)18497c478bd9Sstevel@tonic-gate usbprn_ioctl_get_status(usbprn_state_t *usbprnp)
18507c478bd9Sstevel@tonic-gate {
18517c478bd9Sstevel@tonic-gate /* Check the transfer mode */
18527c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
18537c478bd9Sstevel@tonic-gate
18547c478bd9Sstevel@tonic-gate /* if device is disconnected or pipes closed, fail immediately */
18557c478bd9Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp))) {
18567c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
18577c478bd9Sstevel@tonic-gate
18587c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
18597c478bd9Sstevel@tonic-gate "usbprn_ioctl_get_status: device can't be accessed");
18607c478bd9Sstevel@tonic-gate
18617c478bd9Sstevel@tonic-gate return (EIO);
18627c478bd9Sstevel@tonic-gate }
18637c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
18647c478bd9Sstevel@tonic-gate
18657c478bd9Sstevel@tonic-gate if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
18667c478bd9Sstevel@tonic-gate
18677c478bd9Sstevel@tonic-gate return (EIO);
18687c478bd9Sstevel@tonic-gate }
18697c478bd9Sstevel@tonic-gate
18707c478bd9Sstevel@tonic-gate return (0);
18717c478bd9Sstevel@tonic-gate }
18727c478bd9Sstevel@tonic-gate
18737c478bd9Sstevel@tonic-gate
18747c478bd9Sstevel@tonic-gate /*
18757c478bd9Sstevel@tonic-gate * usbprn_testio:
18767c478bd9Sstevel@tonic-gate * Execute the ECPP_TESTIO ioctl
18777c478bd9Sstevel@tonic-gate */
18787c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
18797c478bd9Sstevel@tonic-gate static int
usbprn_testio(usbprn_state_t * usbprnp,int flag)18807c478bd9Sstevel@tonic-gate usbprn_testio(usbprn_state_t *usbprnp, int flag)
18817c478bd9Sstevel@tonic-gate {
18827c478bd9Sstevel@tonic-gate int err;
18837c478bd9Sstevel@tonic-gate
18847c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
18857c478bd9Sstevel@tonic-gate "usbprn_testio: begin");
18867c478bd9Sstevel@tonic-gate
18877c478bd9Sstevel@tonic-gate if ((err = usbprn_ioctl_get_status(usbprnp)) != 0) {
18887c478bd9Sstevel@tonic-gate
18897c478bd9Sstevel@tonic-gate return (err);
18907c478bd9Sstevel@tonic-gate }
18917c478bd9Sstevel@tonic-gate
18927c478bd9Sstevel@tonic-gate /* There is an error. Return it to the user */
18937c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
18947c478bd9Sstevel@tonic-gate
18957c478bd9Sstevel@tonic-gate if (usbprn_error_state(usbprnp->usbprn_last_status) != 0) {
18967c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
18977c478bd9Sstevel@tonic-gate
18987c478bd9Sstevel@tonic-gate return (EIO);
18997c478bd9Sstevel@tonic-gate
19007c478bd9Sstevel@tonic-gate } else {
19017c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
19027c478bd9Sstevel@tonic-gate
19037c478bd9Sstevel@tonic-gate return (0);
19047c478bd9Sstevel@tonic-gate }
19057c478bd9Sstevel@tonic-gate }
19067c478bd9Sstevel@tonic-gate
19077c478bd9Sstevel@tonic-gate
19087c478bd9Sstevel@tonic-gate /*
19097c478bd9Sstevel@tonic-gate * usbprn_prnio_get_status:
19107c478bd9Sstevel@tonic-gate * Execute the PRNIOC_GET_STATUS ioctl
19117c478bd9Sstevel@tonic-gate */
19127c478bd9Sstevel@tonic-gate static int
usbprn_prnio_get_status(usbprn_state_t * usbprnp,intptr_t arg,int flag)19137c478bd9Sstevel@tonic-gate usbprn_prnio_get_status(usbprn_state_t *usbprnp, intptr_t arg, int flag)
19147c478bd9Sstevel@tonic-gate {
19157c478bd9Sstevel@tonic-gate uint_t prnio_status = 0;
19167c478bd9Sstevel@tonic-gate int err;
19177c478bd9Sstevel@tonic-gate
19187c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
19197c478bd9Sstevel@tonic-gate "usbprn_prnio_get_status: begin");
19207c478bd9Sstevel@tonic-gate
19217c478bd9Sstevel@tonic-gate /* capture printer status */
19227c478bd9Sstevel@tonic-gate err = usbprn_ioctl_get_status(usbprnp);
19237c478bd9Sstevel@tonic-gate
19247c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
19257c478bd9Sstevel@tonic-gate
19267c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_dev_state == USB_DEV_ONLINE) {
19277c478bd9Sstevel@tonic-gate prnio_status |= PRN_ONLINE;
19287c478bd9Sstevel@tonic-gate }
19297c478bd9Sstevel@tonic-gate if ((err == 0) &&
19307c478bd9Sstevel@tonic-gate (usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR)) {
19317c478bd9Sstevel@tonic-gate prnio_status |= PRN_READY;
19327c478bd9Sstevel@tonic-gate }
19337c478bd9Sstevel@tonic-gate
19347c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
19357c478bd9Sstevel@tonic-gate
19367c478bd9Sstevel@tonic-gate if (ddi_copyout(&prnio_status,
19377c478bd9Sstevel@tonic-gate (caddr_t)arg, sizeof (prnio_status), flag)) {
19387c478bd9Sstevel@tonic-gate
19397c478bd9Sstevel@tonic-gate return (EFAULT);
19407c478bd9Sstevel@tonic-gate }
19417c478bd9Sstevel@tonic-gate
19427c478bd9Sstevel@tonic-gate return (0);
19437c478bd9Sstevel@tonic-gate }
19447c478bd9Sstevel@tonic-gate
19457c478bd9Sstevel@tonic-gate
19467c478bd9Sstevel@tonic-gate /*
19477c478bd9Sstevel@tonic-gate * usbprn_prnio_get_1284_status:
19487c478bd9Sstevel@tonic-gate * Execute the PRNIOC_GET_1284_STATUS ioctl
19497c478bd9Sstevel@tonic-gate */
19507c478bd9Sstevel@tonic-gate static int
usbprn_prnio_get_1284_status(usbprn_state_t * usbprnp,intptr_t arg,int flag)19517c478bd9Sstevel@tonic-gate usbprn_prnio_get_1284_status(usbprn_state_t *usbprnp, intptr_t arg, int flag)
19527c478bd9Sstevel@tonic-gate {
19537c478bd9Sstevel@tonic-gate uchar_t status;
19547c478bd9Sstevel@tonic-gate int err;
19557c478bd9Sstevel@tonic-gate
19567c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
19577c478bd9Sstevel@tonic-gate "usbprn_prnio_get_1284_status: begin");
19587c478bd9Sstevel@tonic-gate
19597c478bd9Sstevel@tonic-gate if ((err = usbprn_ioctl_get_status(usbprnp)) != 0) {
19607c478bd9Sstevel@tonic-gate
19617c478bd9Sstevel@tonic-gate return (err);
19627c478bd9Sstevel@tonic-gate }
19637c478bd9Sstevel@tonic-gate
19647c478bd9Sstevel@tonic-gate /* status was captured successfully */
19657c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
19667c478bd9Sstevel@tonic-gate
19677c478bd9Sstevel@tonic-gate status = usbprnp->usbprn_last_status & (USB_PRINTER_PORT_NO_ERROR |
1968112116d8Sfb USB_PRINTER_PORT_NO_SELECT | USB_PRINTER_PORT_EMPTY);
19697c478bd9Sstevel@tonic-gate
19707c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
19717c478bd9Sstevel@tonic-gate
19727c478bd9Sstevel@tonic-gate if (ddi_copyout(&status, (caddr_t)arg, sizeof (status), flag)) {
19737c478bd9Sstevel@tonic-gate
19747c478bd9Sstevel@tonic-gate return (EFAULT);
19757c478bd9Sstevel@tonic-gate }
19767c478bd9Sstevel@tonic-gate
19777c478bd9Sstevel@tonic-gate return (0);
19787c478bd9Sstevel@tonic-gate }
19797c478bd9Sstevel@tonic-gate
19807c478bd9Sstevel@tonic-gate
19817c478bd9Sstevel@tonic-gate /*
19827c478bd9Sstevel@tonic-gate * usbprn_prnio_get_ifcap:
19837c478bd9Sstevel@tonic-gate * Execute the PRNIOC_GET_IFCAP ioctl
19847c478bd9Sstevel@tonic-gate */
19857c478bd9Sstevel@tonic-gate /* ARGSUSED */
19867c478bd9Sstevel@tonic-gate static int
usbprn_prnio_get_ifcap(usbprn_state_t * usbprnp,intptr_t arg,int flag)19877c478bd9Sstevel@tonic-gate usbprn_prnio_get_ifcap(usbprn_state_t *usbprnp, intptr_t arg, int flag)
19887c478bd9Sstevel@tonic-gate {
19897c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
19907c478bd9Sstevel@tonic-gate
19917c478bd9Sstevel@tonic-gate if (ddi_copyout(&usbprn_ifcap, (caddr_t)arg, sizeof (usbprn_ifcap),
19927c478bd9Sstevel@tonic-gate flag)) {
19937c478bd9Sstevel@tonic-gate
19947c478bd9Sstevel@tonic-gate return (EFAULT);
19957c478bd9Sstevel@tonic-gate }
19967c478bd9Sstevel@tonic-gate
19977c478bd9Sstevel@tonic-gate return (0);
19987c478bd9Sstevel@tonic-gate }
19997c478bd9Sstevel@tonic-gate
20007c478bd9Sstevel@tonic-gate
20017c478bd9Sstevel@tonic-gate /*
20027c478bd9Sstevel@tonic-gate * usbprn_prnio_get_ifcap:
20037c478bd9Sstevel@tonic-gate * Execute the PRNIOC_SET_IFCAP ioctl
20047c478bd9Sstevel@tonic-gate */
20057c478bd9Sstevel@tonic-gate /* ARGSUSED */
20067c478bd9Sstevel@tonic-gate static int
usbprn_prnio_set_ifcap(usbprn_state_t * usbprnp,intptr_t arg,int flag)20077c478bd9Sstevel@tonic-gate usbprn_prnio_set_ifcap(usbprn_state_t *usbprnp, intptr_t arg, int flag)
20087c478bd9Sstevel@tonic-gate {
20097c478bd9Sstevel@tonic-gate uint_t new_ifcap;
20107c478bd9Sstevel@tonic-gate
20117c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
20127c478bd9Sstevel@tonic-gate
20137c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &new_ifcap, sizeof (new_ifcap), flag)) {
20147c478bd9Sstevel@tonic-gate
20157c478bd9Sstevel@tonic-gate return (EFAULT);
20167c478bd9Sstevel@tonic-gate }
20177c478bd9Sstevel@tonic-gate
20187c478bd9Sstevel@tonic-gate /* no settable capabilities */
20197c478bd9Sstevel@tonic-gate if (usbprn_ifcap != new_ifcap) {
20207c478bd9Sstevel@tonic-gate
20217c478bd9Sstevel@tonic-gate return (EINVAL);
20227c478bd9Sstevel@tonic-gate }
20237c478bd9Sstevel@tonic-gate
20247c478bd9Sstevel@tonic-gate return (0);
20257c478bd9Sstevel@tonic-gate }
20267c478bd9Sstevel@tonic-gate
20277c478bd9Sstevel@tonic-gate
20287c478bd9Sstevel@tonic-gate /*
20297c478bd9Sstevel@tonic-gate * usbprn_prnio_get_ifinfo:
20307c478bd9Sstevel@tonic-gate * Execute the PRNIOC_GET_IFINFO ioctl
20317c478bd9Sstevel@tonic-gate */
20327c478bd9Sstevel@tonic-gate /* ARGSUSED */
20337c478bd9Sstevel@tonic-gate static int
usbprn_prnio_get_ifinfo(usbprn_state_t * usbprnp,intptr_t arg,int flag)20347c478bd9Sstevel@tonic-gate usbprn_prnio_get_ifinfo(usbprn_state_t *usbprnp, intptr_t arg, int flag)
20357c478bd9Sstevel@tonic-gate {
20367c478bd9Sstevel@tonic-gate struct prn_interface_info prn_info;
20377c478bd9Sstevel@tonic-gate int rlen, len;
20387c478bd9Sstevel@tonic-gate
20397c478bd9Sstevel@tonic-gate rlen = strlen(usbprn_prnio_ifinfo);
20407c478bd9Sstevel@tonic-gate
20417c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
20427c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
20437c478bd9Sstevel@tonic-gate
20447c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) {
20457c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: {
20467c478bd9Sstevel@tonic-gate struct prn_interface_info32 prn_info32;
20477c478bd9Sstevel@tonic-gate
20487c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_info32,
20497c478bd9Sstevel@tonic-gate sizeof (struct prn_interface_info32), flag)) {
20507c478bd9Sstevel@tonic-gate
20517c478bd9Sstevel@tonic-gate return (EFAULT);
20527c478bd9Sstevel@tonic-gate }
20537c478bd9Sstevel@tonic-gate
20547c478bd9Sstevel@tonic-gate prn_info32.if_rlen = rlen;
20557c478bd9Sstevel@tonic-gate len = min(rlen, prn_info32.if_len);
20567c478bd9Sstevel@tonic-gate
20577c478bd9Sstevel@tonic-gate if (ddi_copyout(&usbprn_prnio_ifinfo[0],
20587c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)prn_info32.if_data, len, flag)) {
20597c478bd9Sstevel@tonic-gate
20607c478bd9Sstevel@tonic-gate return (EFAULT);
20617c478bd9Sstevel@tonic-gate }
20627c478bd9Sstevel@tonic-gate
20637c478bd9Sstevel@tonic-gate if (ddi_copyout(&prn_info32, (caddr_t)arg,
20647c478bd9Sstevel@tonic-gate sizeof (struct prn_interface_info32), flag)) {
20657c478bd9Sstevel@tonic-gate
20667c478bd9Sstevel@tonic-gate return (EFAULT);
20677c478bd9Sstevel@tonic-gate }
20687c478bd9Sstevel@tonic-gate
20697c478bd9Sstevel@tonic-gate break;
20707c478bd9Sstevel@tonic-gate }
20717c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE:
20727c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
20737c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
20747c478bd9Sstevel@tonic-gate
20757c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_info,
20767c478bd9Sstevel@tonic-gate sizeof (struct prn_interface_info), flag)) {
20777c478bd9Sstevel@tonic-gate
20787c478bd9Sstevel@tonic-gate return (EFAULT);
20797c478bd9Sstevel@tonic-gate }
20807c478bd9Sstevel@tonic-gate
20817c478bd9Sstevel@tonic-gate prn_info.if_rlen = rlen;
20827c478bd9Sstevel@tonic-gate len = min(rlen, prn_info.if_len);
20837c478bd9Sstevel@tonic-gate
20847c478bd9Sstevel@tonic-gate if (ddi_copyout(&usbprn_prnio_ifinfo[0],
20857c478bd9Sstevel@tonic-gate prn_info.if_data, len, flag)) {
20867c478bd9Sstevel@tonic-gate
20877c478bd9Sstevel@tonic-gate return (EFAULT);
20887c478bd9Sstevel@tonic-gate }
20897c478bd9Sstevel@tonic-gate
20907c478bd9Sstevel@tonic-gate if (ddi_copyout(&prn_info, (caddr_t)arg,
20917c478bd9Sstevel@tonic-gate sizeof (struct prn_interface_info), flag)) {
20927c478bd9Sstevel@tonic-gate
20937c478bd9Sstevel@tonic-gate return (EFAULT);
20947c478bd9Sstevel@tonic-gate }
20957c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
20967c478bd9Sstevel@tonic-gate
20977c478bd9Sstevel@tonic-gate break;
20987c478bd9Sstevel@tonic-gate }
20997c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
21007c478bd9Sstevel@tonic-gate
21017c478bd9Sstevel@tonic-gate return (0);
21027c478bd9Sstevel@tonic-gate }
21037c478bd9Sstevel@tonic-gate
21047c478bd9Sstevel@tonic-gate
21057c478bd9Sstevel@tonic-gate /*
21067c478bd9Sstevel@tonic-gate * usbprn_prnio_getdevid:
21077c478bd9Sstevel@tonic-gate * Execute the PRNIOC_GET_1284_DEVID ioctl
21087c478bd9Sstevel@tonic-gate */
21097c478bd9Sstevel@tonic-gate static int
usbprn_prnio_get_1284_devid(usbprn_state_t * usbprnp,intptr_t arg,int flag)21107c478bd9Sstevel@tonic-gate usbprn_prnio_get_1284_devid(usbprn_state_t *usbprnp, intptr_t arg, int flag)
21117c478bd9Sstevel@tonic-gate {
21127c478bd9Sstevel@tonic-gate struct prn_1284_device_id prn_devid;
21137c478bd9Sstevel@tonic-gate int len;
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
21167c478bd9Sstevel@tonic-gate
21177c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
21187c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) {
21197c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: {
21207c478bd9Sstevel@tonic-gate struct prn_1284_device_id32 prn_devid32;
21217c478bd9Sstevel@tonic-gate
21227c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_devid32,
21237c478bd9Sstevel@tonic-gate sizeof (struct prn_1284_device_id32), flag)) {
21247c478bd9Sstevel@tonic-gate
21257c478bd9Sstevel@tonic-gate return (EFAULT);
21267c478bd9Sstevel@tonic-gate }
21277c478bd9Sstevel@tonic-gate
21287c478bd9Sstevel@tonic-gate prn_devid32.id_rlen = usbprnp->usbprn_device_id_len - 2;
21297c478bd9Sstevel@tonic-gate len = min(prn_devid32.id_rlen, prn_devid32.id_len);
21307c478bd9Sstevel@tonic-gate
21317c478bd9Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
21327c478bd9Sstevel@tonic-gate (caddr_t)(uintptr_t)prn_devid32.id_data, len, flag)) {
21337c478bd9Sstevel@tonic-gate
21347c478bd9Sstevel@tonic-gate return (EFAULT);
21357c478bd9Sstevel@tonic-gate }
21367c478bd9Sstevel@tonic-gate
21377c478bd9Sstevel@tonic-gate if (ddi_copyout(&prn_devid32, (caddr_t)arg,
21387c478bd9Sstevel@tonic-gate sizeof (struct prn_1284_device_id32), flag)) {
21397c478bd9Sstevel@tonic-gate
21407c478bd9Sstevel@tonic-gate return (EFAULT);
21417c478bd9Sstevel@tonic-gate }
21427c478bd9Sstevel@tonic-gate
21437c478bd9Sstevel@tonic-gate break;
21447c478bd9Sstevel@tonic-gate }
21457c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE:
21467c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
21477c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_devid,
21487c478bd9Sstevel@tonic-gate sizeof (struct prn_1284_device_id), flag)) {
21497c478bd9Sstevel@tonic-gate
21507c478bd9Sstevel@tonic-gate return (EFAULT);
21517c478bd9Sstevel@tonic-gate }
21527c478bd9Sstevel@tonic-gate
21537c478bd9Sstevel@tonic-gate prn_devid.id_rlen = usbprnp->usbprn_device_id_len - 2;
21547c478bd9Sstevel@tonic-gate len = min(prn_devid.id_rlen, prn_devid.id_len);
21557c478bd9Sstevel@tonic-gate
21567c478bd9Sstevel@tonic-gate if (ddi_copyout(usbprnp->usbprn_device_id + 2,
21577c478bd9Sstevel@tonic-gate prn_devid.id_data, len, flag)) {
21587c478bd9Sstevel@tonic-gate
21597c478bd9Sstevel@tonic-gate return (EFAULT);
21607c478bd9Sstevel@tonic-gate }
21617c478bd9Sstevel@tonic-gate
21627c478bd9Sstevel@tonic-gate if (ddi_copyout(&prn_devid, (caddr_t)arg,
21637c478bd9Sstevel@tonic-gate sizeof (struct prn_1284_device_id), flag)) {
21647c478bd9Sstevel@tonic-gate
21657c478bd9Sstevel@tonic-gate return (EFAULT);
21667c478bd9Sstevel@tonic-gate }
21677c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL
21687c478bd9Sstevel@tonic-gate
21697c478bd9Sstevel@tonic-gate break;
21707c478bd9Sstevel@tonic-gate }
21717c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */
21727c478bd9Sstevel@tonic-gate
21737c478bd9Sstevel@tonic-gate return (0);
21747c478bd9Sstevel@tonic-gate }
21757c478bd9Sstevel@tonic-gate
21767c478bd9Sstevel@tonic-gate
21777c478bd9Sstevel@tonic-gate /*
21787c478bd9Sstevel@tonic-gate * usbprn_prnio_get_timeouts:
21797c478bd9Sstevel@tonic-gate * Return timeout
21807c478bd9Sstevel@tonic-gate */
21817c478bd9Sstevel@tonic-gate static int
usbprn_prnio_get_timeouts(usbprn_state_t * usbprnp,intptr_t arg,int flag)21827c478bd9Sstevel@tonic-gate usbprn_prnio_get_timeouts(usbprn_state_t *usbprnp, intptr_t arg, int flag)
21837c478bd9Sstevel@tonic-gate {
21847c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
21857c478bd9Sstevel@tonic-gate
21867c478bd9Sstevel@tonic-gate if (ddi_copyout(&usbprnp->usbprn_prn_timeouts,
21877c478bd9Sstevel@tonic-gate (caddr_t)arg, sizeof (struct prn_timeouts), flag)) {
21887c478bd9Sstevel@tonic-gate
21897c478bd9Sstevel@tonic-gate return (EFAULT);
21907c478bd9Sstevel@tonic-gate }
21917c478bd9Sstevel@tonic-gate
21927c478bd9Sstevel@tonic-gate return (0);
21937c478bd9Sstevel@tonic-gate }
21947c478bd9Sstevel@tonic-gate
21957c478bd9Sstevel@tonic-gate
21967c478bd9Sstevel@tonic-gate /*
21977c478bd9Sstevel@tonic-gate * usbprn_prnio_set_timeouts:
21987c478bd9Sstevel@tonic-gate * Set write timeout and prn timeout
21997c478bd9Sstevel@tonic-gate */
22007c478bd9Sstevel@tonic-gate static int
usbprn_prnio_set_timeouts(usbprn_state_t * usbprnp,intptr_t arg,int flag)22017c478bd9Sstevel@tonic-gate usbprn_prnio_set_timeouts(usbprn_state_t *usbprnp, intptr_t arg, int flag)
22027c478bd9Sstevel@tonic-gate {
22037c478bd9Sstevel@tonic-gate struct prn_timeouts prn_timeouts;
22047c478bd9Sstevel@tonic-gate
22057c478bd9Sstevel@tonic-gate ASSERT(!(mutex_owned(&usbprnp->usbprn_mutex)));
22067c478bd9Sstevel@tonic-gate
22077c478bd9Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, &prn_timeouts,
22087c478bd9Sstevel@tonic-gate sizeof (struct prn_timeouts), flag)) {
22097c478bd9Sstevel@tonic-gate
22107c478bd9Sstevel@tonic-gate return (EFAULT);
22117c478bd9Sstevel@tonic-gate }
22127c478bd9Sstevel@tonic-gate
22137c478bd9Sstevel@tonic-gate if ((prn_timeouts.tmo_forward < USBPRN_XFER_TIMEOUT_MIN) ||
22147c478bd9Sstevel@tonic-gate (prn_timeouts.tmo_forward > USBPRN_XFER_TIMEOUT_MAX)) {
22157c478bd9Sstevel@tonic-gate
22167c478bd9Sstevel@tonic-gate return (EINVAL);
22177c478bd9Sstevel@tonic-gate }
22187c478bd9Sstevel@tonic-gate
22197c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
22207c478bd9Sstevel@tonic-gate
22217c478bd9Sstevel@tonic-gate usbprnp->usbprn_prn_timeouts = prn_timeouts;
22227c478bd9Sstevel@tonic-gate usbprnp->usbprn_setparms.write_timeout = prn_timeouts.tmo_forward;
22237c478bd9Sstevel@tonic-gate
22247c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
22257c478bd9Sstevel@tonic-gate
22267c478bd9Sstevel@tonic-gate return (0);
22277c478bd9Sstevel@tonic-gate }
22287c478bd9Sstevel@tonic-gate
22297c478bd9Sstevel@tonic-gate
22307c478bd9Sstevel@tonic-gate /*
22317c478bd9Sstevel@tonic-gate * usbprn_biodone:
22327c478bd9Sstevel@tonic-gate * If there is a bp, complete it
22337c478bd9Sstevel@tonic-gate */
22347c478bd9Sstevel@tonic-gate static void
usbprn_biodone(usbprn_state_t * usbprnp,int err,int bytes_remaining)22357c478bd9Sstevel@tonic-gate usbprn_biodone(usbprn_state_t *usbprnp, int err, int bytes_remaining)
22367c478bd9Sstevel@tonic-gate {
22377c478bd9Sstevel@tonic-gate struct buf *bp = usbprnp->usbprn_bp;
22387c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
22397c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_in = &usbprnp->usbprn_bulk_in;
22407c478bd9Sstevel@tonic-gate
22417c478bd9Sstevel@tonic-gate ASSERT(mutex_owned(&usbprnp->usbprn_mutex));
22427c478bd9Sstevel@tonic-gate
22437c478bd9Sstevel@tonic-gate /* all pipes must be idle now */
22447c478bd9Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_IDLE);
22457c478bd9Sstevel@tonic-gate ASSERT(bulk_in->ps_flags == USBPRN_PS_IDLE);
22467c478bd9Sstevel@tonic-gate
22477c478bd9Sstevel@tonic-gate if (bp) {
22487c478bd9Sstevel@tonic-gate bp->b_resid = bytes_remaining;
22497c478bd9Sstevel@tonic-gate
22507c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
22517c478bd9Sstevel@tonic-gate "usbprn_biodone: "
22527c478bd9Sstevel@tonic-gate "bp=0x%p bcount=0x%lx resid=0x%lx remaining=0x%x err=%d",
22537c478bd9Sstevel@tonic-gate (void *)bp, bp->b_bcount, bp->b_resid, bytes_remaining,
22547c478bd9Sstevel@tonic-gate err);
22557c478bd9Sstevel@tonic-gate
22567c478bd9Sstevel@tonic-gate if (err) {
22577c478bd9Sstevel@tonic-gate bioerror(bp, err);
22587c478bd9Sstevel@tonic-gate }
22597c478bd9Sstevel@tonic-gate
22607c478bd9Sstevel@tonic-gate usbprnp->usbprn_bp = NULL;
22617c478bd9Sstevel@tonic-gate biodone(bp);
22627c478bd9Sstevel@tonic-gate }
22637c478bd9Sstevel@tonic-gate
22647c478bd9Sstevel@tonic-gate /* release access */
22657c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_dev_acc);
22667c478bd9Sstevel@tonic-gate }
22677c478bd9Sstevel@tonic-gate
22687c478bd9Sstevel@tonic-gate
22697c478bd9Sstevel@tonic-gate /*
22707c478bd9Sstevel@tonic-gate * usbprn_send_async_bulk_data:
22717c478bd9Sstevel@tonic-gate * Send bulk data down to the device through the bulk out pipe
22727c478bd9Sstevel@tonic-gate */
22737c478bd9Sstevel@tonic-gate static void
usbprn_send_async_bulk_data(usbprn_state_t * usbprnp)22747c478bd9Sstevel@tonic-gate usbprn_send_async_bulk_data(usbprn_state_t *usbprnp)
22757c478bd9Sstevel@tonic-gate {
22767c478bd9Sstevel@tonic-gate int rval;
22777c478bd9Sstevel@tonic-gate int timeout;
22787c478bd9Sstevel@tonic-gate mblk_t *mp;
22797c478bd9Sstevel@tonic-gate size_t max_xfer_count, xfer_count;
22807c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
22817c478bd9Sstevel@tonic-gate usb_bulk_req_t *req;
22827c478bd9Sstevel@tonic-gate
22837c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
22847c478bd9Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
22857c478bd9Sstevel@tonic-gate
22867c478bd9Sstevel@tonic-gate timeout = usbprnp->usbprn_setparms.write_timeout;
22877c478bd9Sstevel@tonic-gate max_xfer_count = usbprnp->usbprn_bp->b_bcount;
22887c478bd9Sstevel@tonic-gate mp = usbprnp->usbprn_bulk_mp;
22897c478bd9Sstevel@tonic-gate ASSERT(mp != NULL);
2290d29f5a71Szhigang lu - Sun Microsystems - Beijing China xfer_count = MBLKL(mp);
22917c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate req = usb_alloc_bulk_req(usbprnp->usbprn_dip, 0, USB_FLAGS_SLEEP);
2294d29f5a71Szhigang lu - Sun Microsystems - Beijing China req->bulk_len = (uint_t)xfer_count;
22957c478bd9Sstevel@tonic-gate req->bulk_data = mp;
22967c478bd9Sstevel@tonic-gate req->bulk_timeout = timeout;
22977c478bd9Sstevel@tonic-gate req->bulk_cb = usbprn_bulk_xfer_cb;
22987c478bd9Sstevel@tonic-gate req->bulk_exc_cb = usbprn_bulk_xfer_exc_cb;
22997c478bd9Sstevel@tonic-gate req->bulk_client_private = (usb_opaque_t)usbprnp;
23007c478bd9Sstevel@tonic-gate req->bulk_attributes = USB_ATTRS_AUTOCLEARING;
23017c478bd9Sstevel@tonic-gate
23027c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23037c478bd9Sstevel@tonic-gate "usbprn_send_async_bulk_data: req = 0x%p "
23047c478bd9Sstevel@tonic-gate "max_bulk_xfer_size=%lu mp=0x%p xfer_cnt=%lu timeout=%x",
2305112116d8Sfb (void *)req, max_xfer_count, (void *)mp, xfer_count, timeout);
23067c478bd9Sstevel@tonic-gate
23077c478bd9Sstevel@tonic-gate ASSERT(xfer_count <= max_xfer_count);
23087c478bd9Sstevel@tonic-gate
23097c478bd9Sstevel@tonic-gate
23107c478bd9Sstevel@tonic-gate if ((rval = usb_pipe_bulk_xfer(bulk_out->ps_handle, req, 0)) !=
23117c478bd9Sstevel@tonic-gate USB_SUCCESS) {
23127c478bd9Sstevel@tonic-gate
23137c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23147c478bd9Sstevel@tonic-gate "usbprn_send_async_bulk_data: Bulk mp=0x%p "
2315112116d8Sfb "rval=%d", (void *)mp, rval);
23167c478bd9Sstevel@tonic-gate
23177c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
23187c478bd9Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
23197c478bd9Sstevel@tonic-gate usbprnp->usbprn_bulk_mp = NULL;
23207c478bd9Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
23217c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
23227c478bd9Sstevel@tonic-gate
23237c478bd9Sstevel@tonic-gate usb_free_bulk_req(req);
23247c478bd9Sstevel@tonic-gate } else {
23257c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
23267c478bd9Sstevel@tonic-gate usbprnp->usbprn_bulk_mp = NULL;
23277c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
23287c478bd9Sstevel@tonic-gate }
23297c478bd9Sstevel@tonic-gate }
23307c478bd9Sstevel@tonic-gate
23317c478bd9Sstevel@tonic-gate
23327c478bd9Sstevel@tonic-gate /*
23337c478bd9Sstevel@tonic-gate * usbprn_bulk_xfer_cb
23347c478bd9Sstevel@tonic-gate * Callback for a normal transfer for both bulk pipes.
23357c478bd9Sstevel@tonic-gate */
23367c478bd9Sstevel@tonic-gate /*ARGSUSED*/
23377c478bd9Sstevel@tonic-gate static void
usbprn_bulk_xfer_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)23387c478bd9Sstevel@tonic-gate usbprn_bulk_xfer_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
23397c478bd9Sstevel@tonic-gate {
23407c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = (usbprn_state_t *)req->bulk_client_private;
23417c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
23427c478bd9Sstevel@tonic-gate
23437c478bd9Sstevel@tonic-gate ASSERT(usbprnp != NULL);
23447c478bd9Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprnp->usbprn_mutex));
23457c478bd9Sstevel@tonic-gate
23467c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
23477c478bd9Sstevel@tonic-gate
23487c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
2349112116d8Sfb "usbprn_bulk_xfer_cb: mp=0x%p ", (void *)usbprnp->usbprn_bulk_mp);
23507c478bd9Sstevel@tonic-gate
23517c478bd9Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
23527c478bd9Sstevel@tonic-gate ASSERT(usbprnp->usbprn_bp != NULL);
23537c478bd9Sstevel@tonic-gate ASSERT((req->bulk_cb_flags & USB_CB_INTR_CONTEXT) == 0);
23547c478bd9Sstevel@tonic-gate
23557c478bd9Sstevel@tonic-gate /*
23567c478bd9Sstevel@tonic-gate * if device is disconnected or driver close called, return
23577c478bd9Sstevel@tonic-gate * The pipe could be closed, or a timeout could have
23587c478bd9Sstevel@tonic-gate * come in and the pipe is being reset. If the
23597c478bd9Sstevel@tonic-gate * state isn't transferring, then return
23607c478bd9Sstevel@tonic-gate */
23617c478bd9Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp)) ||
23627c478bd9Sstevel@tonic-gate (bulk_out->ps_flags != USBPRN_PS_NEED_TO_XFER)) {
23637c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23647c478bd9Sstevel@tonic-gate "usbprn_bulk_xfer_cb: no access or pipe closed");
23657c478bd9Sstevel@tonic-gate
23667c478bd9Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
23677c478bd9Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
23687c478bd9Sstevel@tonic-gate } else {
23697c478bd9Sstevel@tonic-gate
23707c478bd9Sstevel@tonic-gate /*
23717c478bd9Sstevel@tonic-gate * data has been xferred, complete the bp.
23727c478bd9Sstevel@tonic-gate */
23737c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
23747c478bd9Sstevel@tonic-gate "usbprn_bulk_xfer_cb: transaction over");
23757c478bd9Sstevel@tonic-gate
23767c478bd9Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
23777c478bd9Sstevel@tonic-gate usbprn_biodone(usbprnp, 0, 0);
23787c478bd9Sstevel@tonic-gate }
23797c478bd9Sstevel@tonic-gate
23807c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
23817c478bd9Sstevel@tonic-gate
23827c478bd9Sstevel@tonic-gate usb_free_bulk_req(req);
23837c478bd9Sstevel@tonic-gate }
23847c478bd9Sstevel@tonic-gate
23857c478bd9Sstevel@tonic-gate
23867c478bd9Sstevel@tonic-gate /*
23877c478bd9Sstevel@tonic-gate * usbprn_bulk_xfer_exc_cb:
23887c478bd9Sstevel@tonic-gate * Exception callback for the bulk pipes
23897c478bd9Sstevel@tonic-gate */
23907c478bd9Sstevel@tonic-gate static void
usbprn_bulk_xfer_exc_cb(usb_pipe_handle_t pipe,usb_bulk_req_t * req)23917c478bd9Sstevel@tonic-gate usbprn_bulk_xfer_exc_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
23927c478bd9Sstevel@tonic-gate {
23937c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = (usbprn_state_t *)req->bulk_client_private;
23947c478bd9Sstevel@tonic-gate usbprn_ps_t *bulk_out = &usbprnp->usbprn_bulk_out;
23957c478bd9Sstevel@tonic-gate int bytes_remaining = 0;
23967c478bd9Sstevel@tonic-gate mblk_t *data = req->bulk_data;
23977c478bd9Sstevel@tonic-gate usb_cr_t completion_reason = req->bulk_completion_reason;
23987c478bd9Sstevel@tonic-gate usb_cb_flags_t cb_flags = req->bulk_cb_flags;
23997c478bd9Sstevel@tonic-gate
24007c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
24017c478bd9Sstevel@tonic-gate "usbprn_bulk_xfer_exc_cb: "
24027c478bd9Sstevel@tonic-gate "pipe=0x%p req=0x%p cr=%d cb_flags=0x%x data=0x%p",
2403112116d8Sfb (void *)pipe, (void *)req, completion_reason, cb_flags,
2404112116d8Sfb (void *)data);
24057c478bd9Sstevel@tonic-gate
24067c478bd9Sstevel@tonic-gate ASSERT((req->bulk_cb_flags & USB_CB_INTR_CONTEXT) == 0);
24077c478bd9Sstevel@tonic-gate ASSERT(data != NULL);
24087c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
24097c478bd9Sstevel@tonic-gate
24107c478bd9Sstevel@tonic-gate ASSERT(bulk_out->ps_flags == USBPRN_PS_NEED_TO_XFER);
24117c478bd9Sstevel@tonic-gate bulk_out->ps_flags = USBPRN_PS_IDLE;
24127c478bd9Sstevel@tonic-gate bulk_out->ps_cr = completion_reason;
24137c478bd9Sstevel@tonic-gate
24147c478bd9Sstevel@tonic-gate if (data) {
2415d29f5a71Szhigang lu - Sun Microsystems - Beijing China bytes_remaining = MBLKL(data);
24167c478bd9Sstevel@tonic-gate }
24177c478bd9Sstevel@tonic-gate
24187c478bd9Sstevel@tonic-gate /*
24197c478bd9Sstevel@tonic-gate * If the pipe is closed or device not responding or not in
24207c478bd9Sstevel@tonic-gate * need of transfer, just give up on this bp.
24217c478bd9Sstevel@tonic-gate */
24227c478bd9Sstevel@tonic-gate if (!(USBPRN_DEVICE_ACCESS_OK(usbprnp)) ||
24237c478bd9Sstevel@tonic-gate (req->bulk_completion_reason == USB_CR_DEV_NOT_RESP)) {
24247c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
24257c478bd9Sstevel@tonic-gate "usbprn_bulk_xfer_exc_cb: "
24267c478bd9Sstevel@tonic-gate "device not accesible or wrong state");
24277c478bd9Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
24287c478bd9Sstevel@tonic-gate } else {
24297c478bd9Sstevel@tonic-gate if (completion_reason == USB_CR_TIMEOUT) {
24307c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL,
24317c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
24327c478bd9Sstevel@tonic-gate "usbprn_bulk_xfer_exc_cb: timeout error, "
24337c478bd9Sstevel@tonic-gate "xferred %lu bytes",
24347c478bd9Sstevel@tonic-gate ((usbprnp->usbprn_bp->b_bcount) -
24357c478bd9Sstevel@tonic-gate bytes_remaining));
24367c478bd9Sstevel@tonic-gate usbprn_biodone(usbprnp, 0, bytes_remaining);
24377c478bd9Sstevel@tonic-gate } else {
24387c478bd9Sstevel@tonic-gate usbprn_biodone(usbprnp, EIO, 0);
24397c478bd9Sstevel@tonic-gate }
24407c478bd9Sstevel@tonic-gate
24417c478bd9Sstevel@tonic-gate }
24427c478bd9Sstevel@tonic-gate
24437c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
24447c478bd9Sstevel@tonic-gate
24457c478bd9Sstevel@tonic-gate usb_free_bulk_req(req);
24467c478bd9Sstevel@tonic-gate }
24477c478bd9Sstevel@tonic-gate
24487c478bd9Sstevel@tonic-gate
24497c478bd9Sstevel@tonic-gate /*
24507c478bd9Sstevel@tonic-gate * usbprn_reconnect_event_cb:
24517c478bd9Sstevel@tonic-gate * Called upon when the device is hotplugged back; event handling
24527c478bd9Sstevel@tonic-gate */
24537c478bd9Sstevel@tonic-gate /*ARGSUSED*/
24547c478bd9Sstevel@tonic-gate static int
usbprn_reconnect_event_cb(dev_info_t * dip)24557c478bd9Sstevel@tonic-gate usbprn_reconnect_event_cb(dev_info_t *dip)
24567c478bd9Sstevel@tonic-gate {
24577c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp =
2458112116d8Sfb (usbprn_state_t *)ddi_get_soft_state(usbprn_statep,
2459112116d8Sfb ddi_get_instance(dip));
24607c478bd9Sstevel@tonic-gate
24617c478bd9Sstevel@tonic-gate ASSERT(usbprnp != NULL);
24627c478bd9Sstevel@tonic-gate
24637c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
24647c478bd9Sstevel@tonic-gate "usbprn_reconnect_event_cb:");
24657c478bd9Sstevel@tonic-gate
24667c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
24677c478bd9Sstevel@tonic-gate
24687c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
24697c478bd9Sstevel@tonic-gate ASSERT(usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED);
24707c478bd9Sstevel@tonic-gate
24717c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
24727c478bd9Sstevel@tonic-gate
24737c478bd9Sstevel@tonic-gate usbprn_restore_device_state(dip, usbprnp);
24747c478bd9Sstevel@tonic-gate
24757c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_ugen_hdl) {
24767c478bd9Sstevel@tonic-gate (void) usb_ugen_reconnect_ev_cb(usbprnp->usbprn_ugen_hdl);
24777c478bd9Sstevel@tonic-gate }
24787c478bd9Sstevel@tonic-gate
24797c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
24807c478bd9Sstevel@tonic-gate
24817c478bd9Sstevel@tonic-gate return (USB_SUCCESS);
24827c478bd9Sstevel@tonic-gate }
24837c478bd9Sstevel@tonic-gate
24847c478bd9Sstevel@tonic-gate
24857c478bd9Sstevel@tonic-gate /*
24867c478bd9Sstevel@tonic-gate * usbprn_disconnect_event_cb:
24877c478bd9Sstevel@tonic-gate * callback for disconnect events
24887c478bd9Sstevel@tonic-gate */
24897c478bd9Sstevel@tonic-gate /*ARGSUSED*/
24907c478bd9Sstevel@tonic-gate static int
usbprn_disconnect_event_cb(dev_info_t * dip)24917c478bd9Sstevel@tonic-gate usbprn_disconnect_event_cb(dev_info_t *dip)
24927c478bd9Sstevel@tonic-gate {
24937c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp = (usbprn_state_t *)ddi_get_soft_state(
2494112116d8Sfb usbprn_statep, ddi_get_instance(dip));
24957c478bd9Sstevel@tonic-gate
24967c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
24977c478bd9Sstevel@tonic-gate "usbprn_disconnect_event_cb: Begin");
24987c478bd9Sstevel@tonic-gate
24997c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
25007c478bd9Sstevel@tonic-gate
25017c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25027c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_DISCONNECTED;
25037c478bd9Sstevel@tonic-gate
25047c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_OPEN) {
25057c478bd9Sstevel@tonic-gate USB_DPRINTF_L0(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
25067c478bd9Sstevel@tonic-gate "device was disconnected while open. "
25077c478bd9Sstevel@tonic-gate "Data may have been lost");
25087c478bd9Sstevel@tonic-gate }
25097c478bd9Sstevel@tonic-gate
25107c478bd9Sstevel@tonic-gate /* For now, we set the offline bit in usbprn_last_status */
25117c478bd9Sstevel@tonic-gate usbprnp->usbprn_last_status |= USB_PRINTER_PORT_NO_SELECT;
25127c478bd9Sstevel@tonic-gate
25137c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25147c478bd9Sstevel@tonic-gate
25157c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_ugen_hdl) {
25167c478bd9Sstevel@tonic-gate (void) usb_ugen_disconnect_ev_cb(usbprnp->usbprn_ugen_hdl);
25177c478bd9Sstevel@tonic-gate }
25187c478bd9Sstevel@tonic-gate
25197c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
25207c478bd9Sstevel@tonic-gate
25217c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_EVENTS, usbprnp->usbprn_log_handle,
25227c478bd9Sstevel@tonic-gate "usbprn_disconnect_event_cb: End");
25237c478bd9Sstevel@tonic-gate
25247c478bd9Sstevel@tonic-gate return (USB_SUCCESS);
25257c478bd9Sstevel@tonic-gate }
25267c478bd9Sstevel@tonic-gate
25277c478bd9Sstevel@tonic-gate
25287c478bd9Sstevel@tonic-gate /*
25297c478bd9Sstevel@tonic-gate * usbprn_restore_device_state:
25307c478bd9Sstevel@tonic-gate * set original configuration of the device
25317c478bd9Sstevel@tonic-gate * Restores data xfer
25327c478bd9Sstevel@tonic-gate */
25337c478bd9Sstevel@tonic-gate static void
usbprn_restore_device_state(dev_info_t * dip,usbprn_state_t * usbprnp)25347c478bd9Sstevel@tonic-gate usbprn_restore_device_state(dev_info_t *dip, usbprn_state_t *usbprnp)
25357c478bd9Sstevel@tonic-gate {
25367c478bd9Sstevel@tonic-gate int alt, rval, iface;
25377c478bd9Sstevel@tonic-gate
25387c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
25397c478bd9Sstevel@tonic-gate "usbprn_restore_device_state:");
25407c478bd9Sstevel@tonic-gate
25417c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25427c478bd9Sstevel@tonic-gate ASSERT((usbprnp->usbprn_dev_state == USB_DEV_DISCONNECTED) ||
2543112116d8Sfb (usbprnp->usbprn_dev_state == USB_DEV_SUSPENDED));
25447c478bd9Sstevel@tonic-gate
25457c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25467c478bd9Sstevel@tonic-gate
25477c478bd9Sstevel@tonic-gate /* Check if we are talking to the same device */
25487c478bd9Sstevel@tonic-gate if (usb_check_same_device(dip, usbprnp->usbprn_log_handle,
2549d291d9f2Sfrits USB_LOG_L0, PRINT_MASK_ALL,
25507c478bd9Sstevel@tonic-gate USB_CHK_ALL, NULL) != USB_SUCCESS) {
25517c478bd9Sstevel@tonic-gate
25527c478bd9Sstevel@tonic-gate /* change the device state from suspended to disconnected */
25537c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25547c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_DISCONNECTED;
25557c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25567c478bd9Sstevel@tonic-gate
25577c478bd9Sstevel@tonic-gate return;
25587c478bd9Sstevel@tonic-gate }
25597c478bd9Sstevel@tonic-gate
25607c478bd9Sstevel@tonic-gate USB_DPRINTF_L0(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
25617c478bd9Sstevel@tonic-gate "Printer has been reconnected but data may have been lost");
25627c478bd9Sstevel@tonic-gate
25637c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25647c478bd9Sstevel@tonic-gate
25657c478bd9Sstevel@tonic-gate /* set last status to online */
25667c478bd9Sstevel@tonic-gate usbprnp->usbprn_last_status &= ~USB_PRINTER_PORT_NO_SELECT;
25677c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25687c478bd9Sstevel@tonic-gate
25697c478bd9Sstevel@tonic-gate /* Get the port status */
25707c478bd9Sstevel@tonic-gate if (usbprn_get_port_status(usbprnp) != USB_SUCCESS) {
25717c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
25727c478bd9Sstevel@tonic-gate "usbprn_restore_device_state: port status failed");
25737c478bd9Sstevel@tonic-gate
25747c478bd9Sstevel@tonic-gate return;
25757c478bd9Sstevel@tonic-gate }
25767c478bd9Sstevel@tonic-gate
25777c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25787c478bd9Sstevel@tonic-gate
25797c478bd9Sstevel@tonic-gate if ((usbprnp->usbprn_last_status & USB_PRINTER_PORT_NO_ERROR) == 0) {
25807c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
25817c478bd9Sstevel@tonic-gate "usbprn_restore_device_state: An error with the printer");
25827c478bd9Sstevel@tonic-gate }
25837c478bd9Sstevel@tonic-gate
25847c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_OPEN) {
25857c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
25867c478bd9Sstevel@tonic-gate usbprn_close_usb_pipes(usbprnp);
25877c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
25887c478bd9Sstevel@tonic-gate }
25897c478bd9Sstevel@tonic-gate
25907c478bd9Sstevel@tonic-gate /* restore alternate */
25917c478bd9Sstevel@tonic-gate alt = usbprnp->usbprn_if_descr.bAlternateSetting,
2592112116d8Sfb mutex_exit(&usbprnp->usbprn_mutex);
25937c478bd9Sstevel@tonic-gate
25947c478bd9Sstevel@tonic-gate iface = usb_owns_device(dip) ? 0 : usb_get_if_number(dip);
25957c478bd9Sstevel@tonic-gate if ((rval = usb_set_alt_if(dip, iface, alt,
25967c478bd9Sstevel@tonic-gate USB_FLAGS_SLEEP, NULL, NULL)) != USB_SUCCESS) {
25977c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_ATTA, usbprnp->usbprn_log_handle,
25987c478bd9Sstevel@tonic-gate "usbprn_restore_device_state: set alternate failed (%d)",
25997c478bd9Sstevel@tonic-gate rval);
26007c478bd9Sstevel@tonic-gate
26017c478bd9Sstevel@tonic-gate return;
26027c478bd9Sstevel@tonic-gate }
26037c478bd9Sstevel@tonic-gate
26047c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
26057c478bd9Sstevel@tonic-gate
26067c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_flags & USBPRN_OPEN) {
26077c478bd9Sstevel@tonic-gate
26087c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
26097c478bd9Sstevel@tonic-gate (void) usbprn_open_usb_pipes(usbprnp);
26107c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
26117c478bd9Sstevel@tonic-gate }
26127c478bd9Sstevel@tonic-gate
26137c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_pm && usbprnp->usbprn_pm->usbprn_wakeup_enabled) {
26147c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
26157c478bd9Sstevel@tonic-gate (void) usb_handle_remote_wakeup(usbprnp->usbprn_dip,
26167c478bd9Sstevel@tonic-gate USB_REMOTE_WAKEUP_ENABLE);
26177c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
26187c478bd9Sstevel@tonic-gate }
26197c478bd9Sstevel@tonic-gate
26207c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
26217c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
26227c478bd9Sstevel@tonic-gate
26237c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ALL, usbprnp->usbprn_log_handle,
26247c478bd9Sstevel@tonic-gate "usbprn_restore_device_state: End");
26257c478bd9Sstevel@tonic-gate }
26267c478bd9Sstevel@tonic-gate
26277c478bd9Sstevel@tonic-gate
26287c478bd9Sstevel@tonic-gate /*
26297c478bd9Sstevel@tonic-gate * Create power managements components
26307c478bd9Sstevel@tonic-gate */
26317c478bd9Sstevel@tonic-gate static void
usbprn_create_pm_components(dev_info_t * dip,usbprn_state_t * usbprnp)26327c478bd9Sstevel@tonic-gate usbprn_create_pm_components(dev_info_t *dip, usbprn_state_t *usbprnp)
26337c478bd9Sstevel@tonic-gate {
26347c478bd9Sstevel@tonic-gate usbprn_power_t *usbprnpm;
26357c478bd9Sstevel@tonic-gate uint_t pwr_states;
26367c478bd9Sstevel@tonic-gate
26377c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
26387c478bd9Sstevel@tonic-gate "usbprn_create_pm_components: Begin");
26397c478bd9Sstevel@tonic-gate
26407c478bd9Sstevel@tonic-gate /* Allocate the state structure */
26417c478bd9Sstevel@tonic-gate usbprnpm = kmem_zalloc(sizeof (usbprn_power_t),
2642112116d8Sfb KM_SLEEP);
26437c478bd9Sstevel@tonic-gate usbprnp->usbprn_pm = usbprnpm;
26447c478bd9Sstevel@tonic-gate usbprnpm->usbprn_pm_capabilities = 0;
26457c478bd9Sstevel@tonic-gate usbprnpm->usbprn_current_power = USB_DEV_OS_FULL_PWR;
26467c478bd9Sstevel@tonic-gate
26477c478bd9Sstevel@tonic-gate if (usb_create_pm_components(dip, &pwr_states) ==
26487c478bd9Sstevel@tonic-gate USB_SUCCESS) {
26497c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM,
26507c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
26517c478bd9Sstevel@tonic-gate "usbprn_create_pm_components: "
26527c478bd9Sstevel@tonic-gate "created PM components");
26537c478bd9Sstevel@tonic-gate
26547c478bd9Sstevel@tonic-gate if (usb_handle_remote_wakeup(dip,
26557c478bd9Sstevel@tonic-gate USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
26567c478bd9Sstevel@tonic-gate usbprnpm->usbprn_wakeup_enabled = 1;
26577c478bd9Sstevel@tonic-gate }
26587c478bd9Sstevel@tonic-gate usbprnpm->usbprn_pwr_states = (uint8_t)pwr_states;
26597c478bd9Sstevel@tonic-gate (void) pm_raise_power(usbprnp->usbprn_dip, 0,
2660112116d8Sfb USB_DEV_OS_FULL_PWR);
26617c478bd9Sstevel@tonic-gate } else {
26627c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_PM,
26637c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle,
26647c478bd9Sstevel@tonic-gate "usbprn_create_pm_components: Failed");
26657c478bd9Sstevel@tonic-gate }
26667c478bd9Sstevel@tonic-gate
26677c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
26687c478bd9Sstevel@tonic-gate "usbprn_create_pm_components: END");
26697c478bd9Sstevel@tonic-gate }
26707c478bd9Sstevel@tonic-gate
26717c478bd9Sstevel@tonic-gate
26727c478bd9Sstevel@tonic-gate /*
26737c478bd9Sstevel@tonic-gate * usbprn_pwrlvl0:
26747c478bd9Sstevel@tonic-gate * Functions to handle power transition for OS levels 0 -> 3
26757c478bd9Sstevel@tonic-gate */
26767c478bd9Sstevel@tonic-gate static int
usbprn_pwrlvl0(usbprn_state_t * usbprnp)26777c478bd9Sstevel@tonic-gate usbprn_pwrlvl0(usbprn_state_t *usbprnp)
26787c478bd9Sstevel@tonic-gate {
26797c478bd9Sstevel@tonic-gate int rval;
26807c478bd9Sstevel@tonic-gate
26817c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
26827c478bd9Sstevel@tonic-gate "usbprn_pwrlvl0:");
26837c478bd9Sstevel@tonic-gate
26847c478bd9Sstevel@tonic-gate switch (usbprnp->usbprn_dev_state) {
26857c478bd9Sstevel@tonic-gate case USB_DEV_ONLINE:
26867c478bd9Sstevel@tonic-gate /* Deny the powerdown request if the device is busy */
26877c478bd9Sstevel@tonic-gate if (usbprnp->usbprn_pm->usbprn_pm_busy != 0) {
26887c478bd9Sstevel@tonic-gate
26897c478bd9Sstevel@tonic-gate return (USB_FAILURE);
26907c478bd9Sstevel@tonic-gate }
26917c478bd9Sstevel@tonic-gate
26927c478bd9Sstevel@tonic-gate /* Issue USB D3 command to the device here */
26937c478bd9Sstevel@tonic-gate rval = usb_set_device_pwrlvl3(usbprnp->usbprn_dip);
26947c478bd9Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS);
26957c478bd9Sstevel@tonic-gate
26967c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_PWRED_DOWN;
26977c478bd9Sstevel@tonic-gate usbprnp->usbprn_pm->usbprn_current_power =
2698112116d8Sfb USB_DEV_OS_PWR_OFF;
26997c478bd9Sstevel@tonic-gate /* FALLTHRU */
27007c478bd9Sstevel@tonic-gate case USB_DEV_DISCONNECTED:
27017c478bd9Sstevel@tonic-gate case USB_DEV_SUSPENDED:
27027c478bd9Sstevel@tonic-gate /* allow a disconnect/cpr'ed device to go to lower power */
27037c478bd9Sstevel@tonic-gate
27047c478bd9Sstevel@tonic-gate return (USB_SUCCESS);
27057c478bd9Sstevel@tonic-gate case USB_DEV_PWRED_DOWN:
27067c478bd9Sstevel@tonic-gate default:
27077c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27087c478bd9Sstevel@tonic-gate "usbprn_pwrlvl0: illegal dev state");
27097c478bd9Sstevel@tonic-gate
27107c478bd9Sstevel@tonic-gate return (USB_FAILURE);
27117c478bd9Sstevel@tonic-gate }
27127c478bd9Sstevel@tonic-gate }
27137c478bd9Sstevel@tonic-gate
27147c478bd9Sstevel@tonic-gate
27157c478bd9Sstevel@tonic-gate /*
27167c478bd9Sstevel@tonic-gate * usbprn_pwrlvl1:
27177c478bd9Sstevel@tonic-gate * Functions to handle power transition to OS levels -> 2
27187c478bd9Sstevel@tonic-gate */
27197c478bd9Sstevel@tonic-gate static int
usbprn_pwrlvl1(usbprn_state_t * usbprnp)27207c478bd9Sstevel@tonic-gate usbprn_pwrlvl1(usbprn_state_t *usbprnp)
27217c478bd9Sstevel@tonic-gate {
27227c478bd9Sstevel@tonic-gate int rval;
27237c478bd9Sstevel@tonic-gate
27247c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27257c478bd9Sstevel@tonic-gate "usbprn_pwrlvl1:");
27267c478bd9Sstevel@tonic-gate
27277c478bd9Sstevel@tonic-gate /* Issue USB D2 command to the device here */
27287c478bd9Sstevel@tonic-gate rval = usb_set_device_pwrlvl2(usbprnp->usbprn_dip);
27297c478bd9Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS);
27307c478bd9Sstevel@tonic-gate
27317c478bd9Sstevel@tonic-gate return (USB_FAILURE);
27327c478bd9Sstevel@tonic-gate }
27337c478bd9Sstevel@tonic-gate
27347c478bd9Sstevel@tonic-gate
27357c478bd9Sstevel@tonic-gate /*
27367c478bd9Sstevel@tonic-gate * usbprn_pwrlvl2:
27377c478bd9Sstevel@tonic-gate * Functions to handle power transition to OS levels -> 1
27387c478bd9Sstevel@tonic-gate */
27397c478bd9Sstevel@tonic-gate static int
usbprn_pwrlvl2(usbprn_state_t * usbprnp)27407c478bd9Sstevel@tonic-gate usbprn_pwrlvl2(usbprn_state_t *usbprnp)
27417c478bd9Sstevel@tonic-gate {
27427c478bd9Sstevel@tonic-gate int rval;
27437c478bd9Sstevel@tonic-gate
27447c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27457c478bd9Sstevel@tonic-gate "usbprn_pwrlvl2:");
27467c478bd9Sstevel@tonic-gate
27477c478bd9Sstevel@tonic-gate /* Issue USB D1 command to the device here */
27487c478bd9Sstevel@tonic-gate rval = usb_set_device_pwrlvl1(usbprnp->usbprn_dip);
27497c478bd9Sstevel@tonic-gate ASSERT(rval == USB_SUCCESS);
27507c478bd9Sstevel@tonic-gate
27517c478bd9Sstevel@tonic-gate return (USB_FAILURE);
27527c478bd9Sstevel@tonic-gate }
27537c478bd9Sstevel@tonic-gate
27547c478bd9Sstevel@tonic-gate
27557c478bd9Sstevel@tonic-gate /*
27567c478bd9Sstevel@tonic-gate * usbprn_pwrlvl3:
27577c478bd9Sstevel@tonic-gate * Functions to handle power transition to OS level -> 0
27587c478bd9Sstevel@tonic-gate */
27597c478bd9Sstevel@tonic-gate static int
usbprn_pwrlvl3(usbprn_state_t * usbprnp)27607c478bd9Sstevel@tonic-gate usbprn_pwrlvl3(usbprn_state_t *usbprnp)
27617c478bd9Sstevel@tonic-gate {
27627c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27637c478bd9Sstevel@tonic-gate "usbprn_pwrlvl3:");
27647c478bd9Sstevel@tonic-gate
27657c478bd9Sstevel@tonic-gate switch (usbprnp->usbprn_dev_state) {
27667c478bd9Sstevel@tonic-gate case USB_DEV_PWRED_DOWN:
27677c478bd9Sstevel@tonic-gate /* Issue USB D0 command to the device here */
27687c478bd9Sstevel@tonic-gate (void) usb_set_device_pwrlvl0(usbprnp->usbprn_dip);
27697c478bd9Sstevel@tonic-gate
27707c478bd9Sstevel@tonic-gate usbprnp->usbprn_dev_state = USB_DEV_ONLINE;
27717c478bd9Sstevel@tonic-gate usbprnp->usbprn_pm->usbprn_current_power =
27727c478bd9Sstevel@tonic-gate USB_DEV_OS_FULL_PWR;
27737c478bd9Sstevel@tonic-gate
27747c478bd9Sstevel@tonic-gate /* FALLTHRU */
27757c478bd9Sstevel@tonic-gate case USB_DEV_ONLINE:
27767c478bd9Sstevel@tonic-gate /* we are already in full power */
27777c478bd9Sstevel@tonic-gate /* FALLTHRU */
27787c478bd9Sstevel@tonic-gate case USB_DEV_DISCONNECTED:
27797c478bd9Sstevel@tonic-gate case USB_DEV_SUSPENDED:
27807c478bd9Sstevel@tonic-gate /*
27817c478bd9Sstevel@tonic-gate * PM framework tries to put us in full power
27827c478bd9Sstevel@tonic-gate * during system shutdown. If we are disconnected/cpr'ed
27837c478bd9Sstevel@tonic-gate * return success anyways
27847c478bd9Sstevel@tonic-gate */
27857c478bd9Sstevel@tonic-gate
27867c478bd9Sstevel@tonic-gate return (USB_SUCCESS);
27877c478bd9Sstevel@tonic-gate default:
27887c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
27897c478bd9Sstevel@tonic-gate "usbprn_pwrlvl3:");
27907c478bd9Sstevel@tonic-gate
27917c478bd9Sstevel@tonic-gate
27927c478bd9Sstevel@tonic-gate return (USB_FAILURE);
27937c478bd9Sstevel@tonic-gate }
27947c478bd9Sstevel@tonic-gate }
27957c478bd9Sstevel@tonic-gate
27967c478bd9Sstevel@tonic-gate
27977c478bd9Sstevel@tonic-gate /*
27987c478bd9Sstevel@tonic-gate * usbprn_power :
27997c478bd9Sstevel@tonic-gate * Power entry point
28007c478bd9Sstevel@tonic-gate */
28017c478bd9Sstevel@tonic-gate /* ARGSUSED */
28027c478bd9Sstevel@tonic-gate static int
usbprn_power(dev_info_t * dip,int comp,int level)28037c478bd9Sstevel@tonic-gate usbprn_power(dev_info_t *dip, int comp, int level)
28047c478bd9Sstevel@tonic-gate {
28057c478bd9Sstevel@tonic-gate usbprn_state_t *usbprnp;
28067c478bd9Sstevel@tonic-gate usbprn_power_t *pm;
28077c478bd9Sstevel@tonic-gate int rval = USB_FAILURE;
28087c478bd9Sstevel@tonic-gate
28097c478bd9Sstevel@tonic-gate usbprnp = (usbprn_state_t *)ddi_get_soft_state(usbprn_statep,
2810112116d8Sfb ddi_get_instance(dip));
28117c478bd9Sstevel@tonic-gate
28127c478bd9Sstevel@tonic-gate USB_DPRINTF_L3(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
28137c478bd9Sstevel@tonic-gate "usbprn_power: Begin: level=%d", level);
28147c478bd9Sstevel@tonic-gate
28157c478bd9Sstevel@tonic-gate (void) usb_serialize_access(usbprnp->usbprn_ser_acc, USB_WAIT, 0);
28167c478bd9Sstevel@tonic-gate
28177c478bd9Sstevel@tonic-gate mutex_enter(&usbprnp->usbprn_mutex);
28187c478bd9Sstevel@tonic-gate pm = usbprnp->usbprn_pm;
28197c478bd9Sstevel@tonic-gate ASSERT(pm != NULL);
28207c478bd9Sstevel@tonic-gate
28217c478bd9Sstevel@tonic-gate /* Check if we are transitioning to a legal power level */
28227c478bd9Sstevel@tonic-gate if (USB_DEV_PWRSTATE_OK(pm->usbprn_pwr_states, level)) {
28237c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_PM, usbprnp->usbprn_log_handle,
28247c478bd9Sstevel@tonic-gate "usbprn_power: illegal power level=%d "
28257c478bd9Sstevel@tonic-gate "pwr_states=0x%x", level, pm->usbprn_pwr_states);
28267c478bd9Sstevel@tonic-gate
28277c478bd9Sstevel@tonic-gate goto done;
28287c478bd9Sstevel@tonic-gate }
28297c478bd9Sstevel@tonic-gate
28307c478bd9Sstevel@tonic-gate switch (level) {
28317c478bd9Sstevel@tonic-gate case USB_DEV_OS_PWR_OFF :
28327c478bd9Sstevel@tonic-gate rval = usbprn_pwrlvl0(usbprnp);
28337c478bd9Sstevel@tonic-gate
28347c478bd9Sstevel@tonic-gate break;
28357c478bd9Sstevel@tonic-gate case USB_DEV_OS_PWR_1 :
28367c478bd9Sstevel@tonic-gate rval = usbprn_pwrlvl1(usbprnp);
28377c478bd9Sstevel@tonic-gate
28387c478bd9Sstevel@tonic-gate break;
28397c478bd9Sstevel@tonic-gate case USB_DEV_OS_PWR_2 :
28407c478bd9Sstevel@tonic-gate rval = usbprn_pwrlvl2(usbprnp);
28417c478bd9Sstevel@tonic-gate
28427c478bd9Sstevel@tonic-gate break;
28437c478bd9Sstevel@tonic-gate case USB_DEV_OS_FULL_PWR :
28447c478bd9Sstevel@tonic-gate rval = usbprn_pwrlvl3(usbprnp);
28457c478bd9Sstevel@tonic-gate
28467c478bd9Sstevel@tonic-gate break;
28477c478bd9Sstevel@tonic-gate }
28487c478bd9Sstevel@tonic-gate
28497c478bd9Sstevel@tonic-gate done:
28507c478bd9Sstevel@tonic-gate mutex_exit(&usbprnp->usbprn_mutex);
28517c478bd9Sstevel@tonic-gate
28527c478bd9Sstevel@tonic-gate usb_release_access(usbprnp->usbprn_ser_acc);
28537c478bd9Sstevel@tonic-gate
28547c478bd9Sstevel@tonic-gate return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
28557c478bd9Sstevel@tonic-gate }
28567c478bd9Sstevel@tonic-gate
28577c478bd9Sstevel@tonic-gate
28587c478bd9Sstevel@tonic-gate /*
28597c478bd9Sstevel@tonic-gate * usbprn_print_long:
28607c478bd9Sstevel@tonic-gate * Breakup a string which is > USBPRN_PRINT_MAXLINE and print it
28617c478bd9Sstevel@tonic-gate */
28627c478bd9Sstevel@tonic-gate static void
usbprn_print_long(usbprn_state_t * usbprnp,char * str,int len)28637c478bd9Sstevel@tonic-gate usbprn_print_long(usbprn_state_t *usbprnp, char *str, int len)
28647c478bd9Sstevel@tonic-gate {
28657c478bd9Sstevel@tonic-gate char *tmp = str;
28667c478bd9Sstevel@tonic-gate char pbuf[USBPRN_PRINT_MAXLINE];
28677c478bd9Sstevel@tonic-gate
28687c478bd9Sstevel@tonic-gate for (;;) {
28697c478bd9Sstevel@tonic-gate if (len <= USBPRN_PRINT_MAXLINE) {
28707c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA,
28717c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle, "%s", tmp);
28727c478bd9Sstevel@tonic-gate
28737c478bd9Sstevel@tonic-gate break;
28747c478bd9Sstevel@tonic-gate } else {
28757c478bd9Sstevel@tonic-gate bcopy(tmp, pbuf, USBPRN_PRINT_MAXLINE);
28767c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_ATTA,
28777c478bd9Sstevel@tonic-gate usbprnp->usbprn_log_handle, "%s", pbuf);
28787c478bd9Sstevel@tonic-gate tmp += USBPRN_PRINT_MAXLINE;
28797c478bd9Sstevel@tonic-gate len -= USBPRN_PRINT_MAXLINE;
28807c478bd9Sstevel@tonic-gate }
28817c478bd9Sstevel@tonic-gate }
28827c478bd9Sstevel@tonic-gate }
28837c478bd9Sstevel@tonic-gate
28847c478bd9Sstevel@tonic-gate
28857c478bd9Sstevel@tonic-gate static void
usbprn_pm_busy_component(usbprn_state_t * usbprn_statep)28867c478bd9Sstevel@tonic-gate usbprn_pm_busy_component(usbprn_state_t *usbprn_statep)
28877c478bd9Sstevel@tonic-gate {
28887c478bd9Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprn_statep->usbprn_mutex));
28897c478bd9Sstevel@tonic-gate if (usbprn_statep->usbprn_pm != NULL) {
28907c478bd9Sstevel@tonic-gate mutex_enter(&usbprn_statep->usbprn_mutex);
28917c478bd9Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy++;
28927c478bd9Sstevel@tonic-gate
28937c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM, usbprn_statep->usbprn_log_handle,
28947c478bd9Sstevel@tonic-gate "usbprn_pm_busy_component: %d",
28957c478bd9Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy);
28967c478bd9Sstevel@tonic-gate
28977c478bd9Sstevel@tonic-gate mutex_exit(&usbprn_statep->usbprn_mutex);
28987c478bd9Sstevel@tonic-gate
28997c478bd9Sstevel@tonic-gate if (pm_busy_component(usbprn_statep->usbprn_dip, 0) !=
29007c478bd9Sstevel@tonic-gate DDI_SUCCESS) {
29017c478bd9Sstevel@tonic-gate mutex_enter(&usbprn_statep->usbprn_mutex);
29027c478bd9Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy--;
29037c478bd9Sstevel@tonic-gate
29047c478bd9Sstevel@tonic-gate USB_DPRINTF_L2(PRINT_MASK_PM,
29057c478bd9Sstevel@tonic-gate usbprn_statep->usbprn_log_handle,
29067c478bd9Sstevel@tonic-gate "usbprn_pm_busy_component: %d",
29077c478bd9Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy);
29087c478bd9Sstevel@tonic-gate
29097c478bd9Sstevel@tonic-gate mutex_exit(&usbprn_statep->usbprn_mutex);
29107c478bd9Sstevel@tonic-gate }
29117c478bd9Sstevel@tonic-gate
29127c478bd9Sstevel@tonic-gate }
29137c478bd9Sstevel@tonic-gate }
29147c478bd9Sstevel@tonic-gate
29157c478bd9Sstevel@tonic-gate
29167c478bd9Sstevel@tonic-gate static void
usbprn_pm_idle_component(usbprn_state_t * usbprn_statep)29177c478bd9Sstevel@tonic-gate usbprn_pm_idle_component(usbprn_state_t *usbprn_statep)
29187c478bd9Sstevel@tonic-gate {
29197c478bd9Sstevel@tonic-gate ASSERT(!mutex_owned(&usbprn_statep->usbprn_mutex));
29207c478bd9Sstevel@tonic-gate if (usbprn_statep->usbprn_pm != NULL) {
29217c478bd9Sstevel@tonic-gate if (pm_idle_component(usbprn_statep->usbprn_dip, 0) ==
29227c478bd9Sstevel@tonic-gate DDI_SUCCESS) {
29237c478bd9Sstevel@tonic-gate mutex_enter(&usbprn_statep->usbprn_mutex);
29247c478bd9Sstevel@tonic-gate ASSERT(usbprn_statep->usbprn_pm->usbprn_pm_busy > 0);
29257c478bd9Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy--;
29267c478bd9Sstevel@tonic-gate
29277c478bd9Sstevel@tonic-gate USB_DPRINTF_L4(PRINT_MASK_PM,
29287c478bd9Sstevel@tonic-gate usbprn_statep->usbprn_log_handle,
29297c478bd9Sstevel@tonic-gate "usbprn_pm_idle_component: %d",
29307c478bd9Sstevel@tonic-gate usbprn_statep->usbprn_pm->usbprn_pm_busy);
29317c478bd9Sstevel@tonic-gate
29327c478bd9Sstevel@tonic-gate mutex_exit(&usbprn_statep->usbprn_mutex);
29337c478bd9Sstevel@tonic-gate }
29347c478bd9Sstevel@tonic-gate
29357c478bd9Sstevel@tonic-gate }
29367c478bd9Sstevel@tonic-gate }
2937