60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * CDDL HEADER START
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * The contents of this file are subject to the terms of the
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * Common Development and Distribution License (the "License").
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * You may not use this file except in compliance with the License.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * or http://www.opensolaris.org/os/licensing.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * See the License for the specific language governing permissions
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * and limitations under the License.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * When distributing Covered Code, include this CDDL HEADER in each
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * If applicable, add the following below this CDDL HEADER, with the
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * fields enclosed by brackets "[]" replaced with your own identifying
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * information: Portions Copyright [yyyy] [name of copyright owner]
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * CDDL HEADER END
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
77e515715b61e28fcf0c3f30936492888cecfd8bgongtian zhao - Sun Microsystems - Beijing China * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * Use is subject to license terms.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * This driver includes code for Keyspan USA49WG/USA49WLC/USA19HS adapters. It
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * is a device-specific driver (DSD) working with USB generic serial driver
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * (GSD). It implements the USB-to-serial device-specific driver interface
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * (DSDI) which is offered by GSD. The interface is defined by ds_ops_t
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * structure.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * For USA49WLC, it's necessary to download firmware every time the device is
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * plugged. Before the firmware is downloaded, we say that the device is in
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * "firmware mode", and the attach routin is keyspan_pre_attach(). After
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * downloading, the device's product id will change to 0x12a. Then the device
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * will be enumerated again and another attach for the new product id will
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * begin. No firmware is included in the driver. The functions of USA49WLC is
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * disabled.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * For USA49WG and USA19HS, no need to download firmware since it can be kept
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * in the device's memory.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * For USA49WLC and USA19HS, it's necessary to check and switch their
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * configrations at the beginning of attach, since each of them has two
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * configrations. This driver uses the one whose endpoints are all bulk.
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg *
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * For USA49WG, this driver uses the third configuration which has 6 endpoints,
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * 3 bulk out eps, 1 bulk in ep, 1 intr in ep, 1 intr out ep. Bulk in ep is
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * shared by 4 ports for receiving data.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * Some of Keyspan adapters have only one port, some have two or four ports.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * This driver supports up to four ports. Each port has its own states (traced
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * by keyspan_port structure) and can be operated independently.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * port_state:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * KEYSPAN_PORT_NOT_INIT
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * attach_ports
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * v
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * KEYSPAN_PORT_CLOSED <-----close-------<---- +
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * open_port |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * v |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * KEYSPAN_PORT_OPENING ---open_hw_port---> USBSER_PORT_OPEN
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * Each port has its own data in/out pipes and each pipe also has its own states
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * (traced by keyspan_pipe structure). The pipe states is as following:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * pipe_state:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * KEYSPAN_PIPE_NOT_INIT
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | ^
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * keyspan_init_pipes keyspan_fini_pipes
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * v |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * KEYSPAN_PIPE_CLOSED ------------->-----------+
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * ^ |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | reconnect/resume/open_port
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * disconnect/suspend/close_port |
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * | v
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * +---------<------------------ KEYSPAN_PIPE_OPEN
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * To control the device and get its status in a timely way, this driver makes
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * use of two global bulk endpoints for cmd and status on the device. The pipes
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * for cmd/status will be opened during attach. For multi-port devices, one of
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * the cmd/status message fields will designate which port this message is for.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * This driver can be easily extended to support more Keyspan adapter models.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * You need the following steps to reach the aim:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * 1. Add the model specific data structures, like cmd/status message structure.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * 2. If the device need firmware downloaded, add the firmware code as a header
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * file, and add code to keyspan_pre_attach() as what were done for USA49WLC.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * 3. Add several model specific functions, like keyspan_build_cmd_msg_*,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * keyspan_default_port_params_*, keyspan_save_port_params_*, etc. The functions
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * for USA19HS and USA49WLC can be taken as examples.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * 4. Add model specific code to the "switch (id_product) {...}" sentences.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * keyspan driver glue code
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz *
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/types.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/param.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/stream.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/conf.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/ddi.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/sunddi.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#define USBDRV_MAJOR_VER 2
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#define USBDRV_MINOR_VER 0
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/usb/usba.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/usb/clients/usbser/usbser.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/usb/clients/usbser/usbser_keyspan/keyspan_var.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/byteorder.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz#include <sys/strsun.h>
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/* configuration entry points */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int usbser_keyspan_getinfo(dev_info_t *, ddi_info_cmd_t, void *,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz void **);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int usbser_keyspan_attach(dev_info_t *, ddi_attach_cmd_t);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int usbser_keyspan_detach(dev_info_t *, ddi_detach_cmd_t);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int usbser_keyspan_open(queue_t *, dev_t *, int, int, cred_t *);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/* functions related with set config or firmware download */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int keyspan_pre_attach(dev_info_t *, ddi_attach_cmd_t, void *);
02dd21081e66fa04b4c6f0962352e15edcabfbb0lgstatic int keyspan_set_cfg(dev_info_t *, uint8_t);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int keyspan_pre_detach(dev_info_t *, ddi_detach_cmd_t, void *);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic boolean_t keyspan_need_fw(usb_client_dev_data_t *);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int keyspan_set_reg(keyspan_pipe_t *, uchar_t);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int keyspan_write_memory(keyspan_pipe_t *, uint16_t, uchar_t *,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz uint16_t, uint8_t);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yzstatic int keyspan_download_firmware(keyspan_pre_state_t *);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic void *usbser_keyspan_statep; /* soft state */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
e8ed0869d5c65afe0c37c4755bf81f7381d1f43cJohn Beckextern ds_ops_t keyspan_ds_ops; /* DSD operations */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * STREAMS structures
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstruct module_info usbser_keyspan_modinfo = {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz 0, /* module id */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz "usbsksp", /* module name */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz USBSER_MIN_PKTSZ, /* min pkt size */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz USBSER_MAX_PKTSZ, /* max pkt size */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz USBSER_HIWAT, /* hi watermark */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz USBSER_LOWAT /* low watermark */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz};
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic struct qinit usbser_keyspan_rinit = {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz putq,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_rsrv,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_keyspan_open,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_close,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz NULL,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz &usbser_keyspan_modinfo,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz NULL
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz};
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic struct qinit usbser_keyspan_winit = {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_wput,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_wsrv,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz NULL,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz NULL,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz NULL,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz &usbser_keyspan_modinfo,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz NULL
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz};
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstruct streamtab usbser_keyspan_str_info = {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz &usbser_keyspan_rinit, &usbser_keyspan_winit, NULL, NULL
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz};
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic struct cb_ops usbser_keyspan_cb_ops = {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_open */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_close */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_strategy */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_print */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_dump */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_read */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_write */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_ioctl */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_devmap */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_mmap */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* cb_segmap */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nochpoll, /* cb_chpoll */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz ddi_prop_op, /* cb_prop_op */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz &usbser_keyspan_str_info, /* cb_stream */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz (int)(D_64BIT | D_NEW | D_MP | D_HOTPLUG) /* cb_flag */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz};
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * auto configuration ops
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstruct dev_ops usbser_keyspan_ops = {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz DEVO_REV, /* devo_rev */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz 0, /* devo_refcnt */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_keyspan_getinfo, /* devo_getinfo */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nulldev, /* devo_identify */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nulldev, /* devo_probe */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_keyspan_attach, /* devo_attach */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_keyspan_detach, /* devo_detach */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz nodev, /* devo_reset */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz &usbser_keyspan_cb_ops, /* devo_cb_ops */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz (struct bus_ops *)NULL, /* devo_bus_ops */
193974072f41a843678abf5f61979c748687e66bSherry Moore usbser_power, /* devo_power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* devo_quiesce */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz};
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzextern struct mod_ops mod_driverops;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic struct modldrv modldrv = {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz &mod_driverops, /* type of module - driver */
77e515715b61e28fcf0c3f30936492888cecfd8bgongtian zhao - Sun Microsystems - Beijing China "USB keyspan usb2serial driver",
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz &usbser_keyspan_ops,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz};
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic struct modlinkage modlinkage = {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz MODREV_1, &modldrv, 0
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz};
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz/* debug support */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yzstatic uint_t keyspan_pre_errlevel = USB_LOG_L4;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yzstatic uint_t keyspan_pre_errmask = DPRINT_MASK_ALL;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yzstatic uint_t keyspan_pre_instance_debug = (uint_t)-1;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz/* firmware support for usa49wlc model */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yzextern usbser_keyspan_fw_record_t *keyspan_usa49wlc_fw(void);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz#pragma weak keyspan_usa49wlc_fw
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * configuration entry points
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * --------------------------
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzint
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz_init(void)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz int error;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if ((error = mod_install(&modlinkage)) == 0) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz error = ddi_soft_state_init(&usbser_keyspan_statep,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz max(usbser_soft_state_size(),
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz sizeof (keyspan_pre_state_t)), 1);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (error);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzint
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz_fini(void)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz int error;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if ((error = mod_remove(&modlinkage)) == 0) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz ddi_soft_state_fini(&usbser_keyspan_statep);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (error);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzint
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz_info(struct modinfo *modinfop)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (mod_info(&modlinkage, modinfop));
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*ARGSUSED*/
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzint
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzusbser_keyspan_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz void **result)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (usbser_getinfo(dip, infocmd, arg, result,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usbser_keyspan_statep));
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzusbser_keyspan_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz int rval;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * Once the device is plugged, we need set its cfg. And need download
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * firmware for some of them.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz rval = keyspan_pre_attach(dip, cmd, usbser_keyspan_statep);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * After the cfg is set, and the firmware is downloaded,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * do the real attach.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if (rval == DDI_ECONTEXT) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (usbser_attach(dip, cmd, usbser_keyspan_statep,
e8ed0869d5c65afe0c37c4755bf81f7381d1f43cJohn Beck &keyspan_ds_ops));
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz } else {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (rval);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzusbser_keyspan_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if (ddi_get_driver_private(dip) == NULL) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (keyspan_pre_detach(dip, cmd, usbser_keyspan_statep));
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz } else {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (usbser_detach(dip, cmd, usbser_keyspan_statep));
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzusbser_keyspan_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (usbser_open(rq, dev, flag, sflag, cr, usbser_keyspan_statep));
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * Switch config or download firmware
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*ARGSUSED*/
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzkeyspan_pre_attach(dev_info_t *dip, ddi_attach_cmd_t cmd, void *statep)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz int instance = ddi_get_instance(dip);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz keyspan_pre_state_t *kbp = NULL;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz usb_client_dev_data_t *dev_data = NULL;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz int rval = DDI_FAILURE;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz switch (cmd) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz case DDI_ATTACH:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz break;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz case DDI_RESUME:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (DDI_SUCCESS);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz default:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (DDI_FAILURE);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /* attach driver to USBA */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (usb_client_attach(dip, USBDRV_VERSION, 0) == USB_SUCCESS) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz (void) usb_get_dev_data(dip, &dev_data, USB_PARSE_LVL_IF, 0);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (dev_data == NULL) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz goto fail;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /*
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * If 19HS or 49WG, needn't download firmware, but need check the
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg * current cfg.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * If 49WLC, need check the current cfg before download fw. And after
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz * download, the product id will change to KEYSPAN_USA49WLC_PID.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if (dev_data->dev_descr->idProduct == KEYSPAN_USA19HS_PID ||
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz dev_data->dev_descr->idProduct == KEYSPAN_USA49WLC_PID) {
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg if (keyspan_set_cfg(dip, 1) == USB_SUCCESS) {
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg /* Go to keyspan_attach() by return DDI_ECONTEXT. */
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg rval = DDI_ECONTEXT;
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg }
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg goto fail;
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg } else if (dev_data->dev_descr->idProduct == KEYSPAN_USA49WG_PID) {
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg if (keyspan_set_cfg(dip, 2) == USB_SUCCESS) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz /* Go to keyspan_attach() by return DDI_ECONTEXT. */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz rval = DDI_ECONTEXT;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz goto fail;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /*
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz * By checking KEYSPAN_FW_FLAG, we can check whether the firmware
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz * has been downloaded.
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz * If firmware is already there, then do normal attach.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if (!keyspan_need_fw(dev_data)) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /* Go to keyspan_attach() by return DDI_ECONTEXT. */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz rval = DDI_ECONTEXT;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz goto fail;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz /* Go on to download firmware. */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (ddi_soft_state_zalloc(statep, instance) == DDI_SUCCESS) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz kbp = ddi_get_soft_state(statep, instance);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (kbp) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz kbp->kb_dip = dip;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz kbp->kb_instance = instance;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz kbp->kb_dev_data = dev_data;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz kbp->kb_def_pipe.pipe_handle = kbp->kb_dev_data->dev_default_ph;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz kbp->kb_lh = usb_alloc_log_hdl(kbp->kb_dip, "keyspan[*].",
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz &keyspan_pre_errlevel, &keyspan_pre_errmask,
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz &keyspan_pre_instance_debug, 0);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz kbp->kb_def_pipe.pipe_lh = kbp->kb_lh;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (keyspan_download_firmware(kbp) == USB_SUCCESS) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz USB_DPRINTF_L4(DPRINT_ATTACH, kbp->kb_lh,
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz "keyspan_pre_attach: completed.");
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz /* keyspan download firmware done. */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz return (DDI_SUCCESS);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yzfail:
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (kbp) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz usb_free_log_hdl(kbp->kb_lh);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz ddi_soft_state_free(statep, instance);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usb_client_detach(dip, dev_data);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz return (rval);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzkeyspan_pre_detach(dev_info_t *dip, ddi_detach_cmd_t cmd, void *statep)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz int instance = ddi_get_instance(dip);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz keyspan_pre_state_t *kbp;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz kbp = ddi_get_soft_state(statep, instance);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz switch (cmd) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz case DDI_DETACH:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz break;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz case DDI_SUSPEND:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (DDI_SUCCESS);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz default:
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (DDI_FAILURE);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz usb_free_log_hdl(kbp->kb_lh);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usb_client_detach(dip, kbp->kb_dev_data);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz ddi_soft_state_free(statep, instance);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (DDI_SUCCESS);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/* Set cfg for the device which has more than one cfg */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int
02dd21081e66fa04b4c6f0962352e15edcabfbb0lgkeyspan_set_cfg(dev_info_t *dip, uint8_t cfg_num)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
02dd21081e66fa04b4c6f0962352e15edcabfbb0lg if (usb_set_cfg(dip, cfg_num, USB_FLAGS_SLEEP,
77e515715b61e28fcf0c3f30936492888cecfd8bgongtian zhao - Sun Microsystems - Beijing China NULL, NULL) != USB_SUCCESS) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (USB_FAILURE);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (USB_SUCCESS);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/* Return TRUE if need download firmware to the device. */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic boolean_t
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzkeyspan_need_fw(usb_client_dev_data_t *dev_data)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz uint16_t bcd_descr;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz uint16_t bcd_descr_change;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /* need to convert to Little-Endian */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz bcd_descr = dev_data->dev_descr->bcdDevice;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * According to Keyspan's interface spec, this flag indicates
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * if need download fw.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz bcd_descr_change = bcd_descr & KEYSPAN_FW_FLAG;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (bcd_descr_change == KEYSPAN_FW_FLAG);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/* Set the device's register. */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzkeyspan_set_reg(keyspan_pipe_t *pipe, uchar_t bit)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz int rval;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * (0x7f92) is the reg addr we want to set.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * We set this reg before/after downloading firmware.
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz rval = keyspan_write_memory(pipe, 0x7f92, &bit, 1, KEYSPAN_REQ_SET);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (rval);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz/*
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz * Download firmware or set register to the device by default ctrl pipe
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzstatic int
60b08185ce63023f22fd6b2ed0db8c0d119b2023yzkeyspan_write_memory(keyspan_pipe_t *pipe, uint16_t addr, uchar_t *buf,
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz uint16_t len, uint8_t bRequest)
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz{
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz mblk_t *data;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usb_ctrl_setup_t setup;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usb_cb_flags_t cb_flags;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz usb_cr_t cr;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz uint8_t retry = 0;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /* reuse previous mblk if possible */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if ((data = allocb(len, BPRI_HI)) == NULL) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (USB_FAILURE);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz bcopy(buf, data->b_rptr, len);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz setup.bmRequestType = USB_DEV_REQ_TYPE_VENDOR;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /* This is a req defined by hardware vendor. */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz setup.bRequest = bRequest;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz setup.wValue = addr;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz setup.wIndex = 0;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz setup.wLength = len;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz setup.attrs = 0;
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz while (usb_pipe_ctrl_xfer_wait(pipe->pipe_handle, &setup, &data,
77e515715b61e28fcf0c3f30936492888cecfd8bgongtian zhao - Sun Microsystems - Beijing China &cr, &cb_flags, 0) != USB_SUCCESS) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz /* KEYSPAN_RETRY */
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if (++retry > 3) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if (data) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz freemsg(data);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (USB_FAILURE);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz if (data) {
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz freemsg(data);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz }
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz return (USB_SUCCESS);
60b08185ce63023f22fd6b2ed0db8c0d119b2023yz}
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz/* Download firmware into device */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yzstatic int
c138f478d2bc94e73ab8f6a084e323bec25e62f5yzkeyspan_download_firmware(keyspan_pre_state_t *kbp)
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz{
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz usbser_keyspan_fw_record_t *record = NULL;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz /* If the firmware module exists, then download it to device. */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (&keyspan_usa49wlc_fw) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz record = keyspan_usa49wlc_fw();
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (!record) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz USB_DPRINTF_L1(DPRINT_ATTACH, kbp->kb_lh,
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz "No firmware available for Keyspan usa49wlc"
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz " usb-to-serial adapter. Refer to usbsksp(7D)"
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz " for details.");
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz return (USB_FAILURE);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz /* Set bit 1 before downloading firmware. */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (keyspan_set_reg(&kbp->kb_def_pipe, 1) != USB_SUCCESS) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz USB_DPRINTF_L2(DPRINT_ATTACH, kbp->kb_lh,
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz "keyspan_pre_attach: Set register failed.");
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz return (USB_FAILURE);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz /* Write until the last record of the firmware */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz while (record->address != 0xffff) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (keyspan_write_memory(&kbp->kb_def_pipe,
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz record->address, (uchar_t *)record->data,
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz record->data_len, KEYSPAN_REQ_SET) != USB_SUCCESS) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz USB_DPRINTF_L2(DPRINT_ATTACH, kbp->kb_lh,
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz "keyspan_pre_attach: download firmware failed.");
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz return (USB_FAILURE);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz record++;
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz /*
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz * Set bit 0, device will be enumerated again after a while,
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz * and then go to keyspan_attach()
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz */
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz if (keyspan_set_reg(&kbp->kb_def_pipe, 0) != USB_SUCCESS) {
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz return (USB_FAILURE);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz }
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz return (USB_SUCCESS);
c138f478d2bc94e73ab8f6a084e323bec25e62f5yz}