160b08185Syz /*
260b08185Syz * CDDL HEADER START
360b08185Syz *
460b08185Syz * The contents of this file are subject to the terms of the
5688b07c5Sgc * Common Development and Distribution License (the "License").
6688b07c5Sgc * You may not use this file except in compliance with the License.
760b08185Syz *
860b08185Syz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
960b08185Syz * or http://www.opensolaris.org/os/licensing.
1060b08185Syz * See the License for the specific language governing permissions
1160b08185Syz * and limitations under the License.
1260b08185Syz *
1360b08185Syz * When distributing Covered Code, include this CDDL HEADER in each
1460b08185Syz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1560b08185Syz * If applicable, add the following below this CDDL HEADER, with the
1660b08185Syz * fields enclosed by brackets "[]" replaced with your own identifying
1760b08185Syz * information: Portions Copyright [yyyy] [name of copyright owner]
1860b08185Syz *
1960b08185Syz * CDDL HEADER END
2060b08185Syz */
2160b08185Syz
2260b08185Syz /*
2322eb7cb5Sgd * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2460b08185Syz * Use is subject to license terms.
2560b08185Syz */
2660b08185Syz
2760b08185Syz
2860b08185Syz /*
2960b08185Syz *
3060b08185Syz * DSD code for keyspan usb2serial adapters
3160b08185Syz *
3260b08185Syz */
3360b08185Syz #include <sys/types.h>
3460b08185Syz #include <sys/param.h>
3560b08185Syz #include <sys/conf.h>
3660b08185Syz #include <sys/stream.h>
3760b08185Syz #include <sys/strsun.h>
3860b08185Syz #include <sys/termio.h>
3960b08185Syz #include <sys/termiox.h>
4060b08185Syz #include <sys/ddi.h>
4160b08185Syz #include <sys/sunddi.h>
4260b08185Syz
4360b08185Syz #define USBDRV_MAJOR_VER 2
4460b08185Syz #define USBDRV_MINOR_VER 0
4560b08185Syz
4660b08185Syz #include <sys/usb/usba.h>
4760b08185Syz
4860b08185Syz #include <sys/usb/clients/usbser/usbser_dsdi.h>
4960b08185Syz #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_var.h>
5060b08185Syz #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_pipe.h>
5160b08185Syz
5260b08185Syz #include <sys/usb/clients/usbser/usbser_keyspan/usa90msg.h>
5360b08185Syz #include <sys/usb/clients/usbser/usbser_keyspan/usa49msg.h>
5460b08185Syz
5560b08185Syz /*
5660b08185Syz * DSD operations which are filled in ds_ops structure.
5760b08185Syz */
5860b08185Syz static int keyspan_attach(ds_attach_info_t *);
5960b08185Syz static void keyspan_detach(ds_hdl_t);
6060b08185Syz static int keyspan_register_cb(ds_hdl_t, uint_t, ds_cb_t *);
6160b08185Syz static void keyspan_unregister_cb(ds_hdl_t, uint_t);
6260b08185Syz static int keyspan_open_port(ds_hdl_t, uint_t);
6360b08185Syz static int keyspan_close_port(ds_hdl_t, uint_t);
6460b08185Syz
6560b08185Syz /* power management */
6660b08185Syz static int keyspan_usb_power(ds_hdl_t, int, int, int *);
6760b08185Syz static int keyspan_suspend(ds_hdl_t);
6860b08185Syz static int keyspan_resume(ds_hdl_t);
6960b08185Syz
7060b08185Syz /* hotplug */
7160b08185Syz static int keyspan_disconnect(ds_hdl_t);
7260b08185Syz static int keyspan_reconnect(ds_hdl_t);
7360b08185Syz
7460b08185Syz /* standard UART operations */
7560b08185Syz static int keyspan_set_port_params(ds_hdl_t, uint_t, ds_port_params_t *);
7660b08185Syz static int keyspan_set_modem_ctl(ds_hdl_t, uint_t, int, int);
7760b08185Syz static int keyspan_get_modem_ctl(ds_hdl_t, uint_t, int, int *);
7860b08185Syz static int keyspan_break_ctl(ds_hdl_t, uint_t, int);
7960b08185Syz static int keyspan_loopback(ds_hdl_t, uint_t, int);
8060b08185Syz
8160b08185Syz /* data xfer */
8260b08185Syz static int keyspan_tx(ds_hdl_t, uint_t, mblk_t *);
8360b08185Syz static mblk_t *keyspan_rx(ds_hdl_t, uint_t);
8460b08185Syz static void keyspan_stop(ds_hdl_t, uint_t, int);
8560b08185Syz static void keyspan_start(ds_hdl_t, uint_t, int);
8660b08185Syz static int keyspan_fifo_flush(ds_hdl_t, uint_t, int);
8760b08185Syz static int keyspan_fifo_drain(ds_hdl_t, uint_t, int);
8860b08185Syz
8960b08185Syz /*
9060b08185Syz * Sub-routines
9160b08185Syz */
9260b08185Syz
9360b08185Syz /* configuration routines */
9460b08185Syz static void keyspan_free_soft_state(keyspan_state_t *);
9560b08185Syz static void keyspan_init_sync_objs(keyspan_state_t *);
9660b08185Syz static void keyspan_fini_sync_objs(keyspan_state_t *);
9760b08185Syz static int keyspan_usb_register(keyspan_state_t *);
9860b08185Syz static void keyspan_usb_unregister(keyspan_state_t *);
9960b08185Syz static int keyspan_attach_dev(keyspan_state_t *);
10060b08185Syz static void keyspan_attach_ports(keyspan_state_t *);
10160b08185Syz static void keyspan_detach_ports(keyspan_state_t *);
10260b08185Syz static void keyspan_init_port_params(keyspan_state_t *);
10360b08185Syz static void keyspan_free_descr_tree(keyspan_state_t *);
10460b08185Syz static int keyspan_register_events(keyspan_state_t *);
10560b08185Syz static void keyspan_unregister_events(keyspan_state_t *);
10660b08185Syz static void keyspan_set_dev_state_online(keyspan_state_t *);
10760b08185Syz
10860b08185Syz /* hotplug */
10960b08185Syz static int keyspan_restore_device_state(keyspan_state_t *);
11060b08185Syz static int keyspan_restore_ports_state(keyspan_state_t *);
11160b08185Syz
11260b08185Syz /* power management */
11360b08185Syz static int keyspan_create_pm_components(keyspan_state_t *);
11460b08185Syz static void keyspan_destroy_pm_components(keyspan_state_t *);
11560b08185Syz static int keyspan_pm_set_busy(keyspan_state_t *);
11660b08185Syz static void keyspan_pm_set_idle(keyspan_state_t *);
11760b08185Syz static int keyspan_pwrlvl0(keyspan_state_t *);
11860b08185Syz static int keyspan_pwrlvl1(keyspan_state_t *);
11960b08185Syz static int keyspan_pwrlvl2(keyspan_state_t *);
12060b08185Syz static int keyspan_pwrlvl3(keyspan_state_t *);
12160b08185Syz
12260b08185Syz /* pipe operations */
12360b08185Syz static int keyspan_attach_pipes(keyspan_state_t *);
12460b08185Syz static void keyspan_detach_pipes(keyspan_state_t *);
12560b08185Syz static void keyspan_disconnect_pipes(keyspan_state_t *);
12660b08185Syz static int keyspan_reconnect_pipes(keyspan_state_t *);
12760b08185Syz
12860b08185Syz /* data transfer routines */
12960b08185Syz static int keyspan_wait_tx_drain(keyspan_port_t *, int);
13060b08185Syz
13160b08185Syz /* misc */
13260b08185Syz static void keyspan_default_port_params(keyspan_port_t *);
13360b08185Syz static void keyspan_build_cmd_msg(keyspan_port_t *, ds_port_params_t *);
13460b08185Syz static void keyspan_save_port_params(keyspan_port_t *);
13560b08185Syz
13660b08185Syz /*
13760b08185Syz * Model specific functions.
13860b08185Syz */
13960b08185Syz
14060b08185Syz /* usa19hs specific functions */
14160b08185Syz static void keyspan_build_cmd_msg_usa19hs(keyspan_port_t *,
14260b08185Syz ds_port_params_t *);
14360b08185Syz static void keyspan_default_port_params_usa19hs(keyspan_port_t *);
14460b08185Syz static void keyspan_save_port_params_usa19hs(keyspan_port_t *);
14560b08185Syz
146c138f478Syz
14760b08185Syz /* usa49 specific functions */
14860b08185Syz static void keyspan_build_cmd_msg_usa49(keyspan_port_t *,
14960b08185Syz ds_port_params_t *);
15060b08185Syz static void keyspan_default_port_params_usa49(keyspan_port_t *);
15160b08185Syz static void keyspan_save_port_params_usa49(keyspan_port_t *);
152c138f478Syz
15360b08185Syz
15460b08185Syz /*
15560b08185Syz * DSD ops structure
15660b08185Syz */
157*e8ed0869SJohn Beck ds_ops_t keyspan_ds_ops = {
15860b08185Syz DS_OPS_VERSION,
15960b08185Syz keyspan_attach,
16060b08185Syz keyspan_detach,
16160b08185Syz keyspan_register_cb,
16260b08185Syz keyspan_unregister_cb,
16360b08185Syz keyspan_open_port,
16460b08185Syz keyspan_close_port,
16560b08185Syz keyspan_usb_power,
16660b08185Syz keyspan_suspend,
16760b08185Syz keyspan_resume,
16860b08185Syz keyspan_disconnect,
16960b08185Syz keyspan_reconnect,
17060b08185Syz keyspan_set_port_params,
17160b08185Syz keyspan_set_modem_ctl,
17260b08185Syz keyspan_get_modem_ctl,
17360b08185Syz keyspan_break_ctl,
17460b08185Syz keyspan_loopback,
17560b08185Syz keyspan_tx,
17660b08185Syz keyspan_rx,
17760b08185Syz keyspan_stop,
17860b08185Syz keyspan_start,
17960b08185Syz keyspan_fifo_flush,
18060b08185Syz keyspan_fifo_drain
18160b08185Syz };
18260b08185Syz
18360b08185Syz /*
18460b08185Syz * For USA19HS baud speed, precalculated using the following algorithm:
18560b08185Syz *
18660b08185Syz * speed = (uint16_t)(14769231L / baud);
18760b08185Syz */
18860b08185Syz static uint16_t keyspan_speedtab_usa19hs[] = {
18960b08185Syz 0x0, /* B0 */
19060b08185Syz 0x481d, /* B50 */
19160b08185Syz 0x3013, /* B75 */
19260b08185Syz 0x20c7, /* B110 */
19360b08185Syz 0x1ae8, /* B134 */
19460b08185Syz 0x1809, /* B150 */
19560b08185Syz 0x1207, /* B200 */
19660b08185Syz 0xc04, /* B300 */
19760b08185Syz 0x602, /* B600 */
19860b08185Syz 0x301, /* B1200 */
19960b08185Syz 0x200, /* B1800 */
20060b08185Syz 0x180, /* B2400 */
20160b08185Syz 0xc0, /* B4800 */
20260b08185Syz 0x60, /* B9600 */
20360b08185Syz 0x30, /* B19200 */
20460b08185Syz 0x18, /* B38400 */
20560b08185Syz 0x10, /* B57600 */
20660b08185Syz 0xc, /* B76800 */
20760b08185Syz 0x8, /* B115200 */
20860b08185Syz 0x6, /* B153600 */
20960b08185Syz 0x4, /* B230400 */
21060b08185Syz };
211c138f478Syz
21260b08185Syz /*
21360b08185Syz * For USA49WLC baud speed, precalculated.
21460b08185Syz */
21560b08185Syz static uint16_t keyspan_speedtab_usa49[] = {
21660b08185Syz 0x0, /* B0 */
21760b08185Syz 0x7530, /* B50 */
21860b08185Syz 0x4e20, /* B75 */
21960b08185Syz 0x3544, /* B110 */
22060b08185Syz 0x2bba, /* B134 */
22160b08185Syz 0x2710, /* B150 */
22260b08185Syz 0x1d4c, /* B200 */
22360b08185Syz 0x1388, /* B300 */
22460b08185Syz 0x9c4, /* B600 */
22560b08185Syz 0x4e2, /* B1200 */
22660b08185Syz 0x25e, /* B1800 */
22760b08185Syz 0x271, /* B2400 */
22860b08185Syz 0xfa, /* B4800 */
22960b08185Syz 0x7d, /* B9600 */
23060b08185Syz 0x19, /* B19200 */
23160b08185Syz 0x27, /* B38400 */
23260b08185Syz 0x1a, /* B57600 */
23360b08185Syz 0xd, /* B76800 */
23460b08185Syz 0xd, /* B115200 */
23560b08185Syz 0x6, /* B153600 */
23660b08185Syz 0x4, /* B230400 */
23760b08185Syz };
23860b08185Syz
23960b08185Syz /*
24060b08185Syz * For USA49WLC prescaler, precalculated.
24160b08185Syz */
24260b08185Syz static uint8_t keyspan_prescaler_49wlc[] = {
24360b08185Syz 0x0, /* B0 */
24460b08185Syz 0x8, /* B50 */
24560b08185Syz 0x8, /* B75 */
24660b08185Syz 0x8, /* B110 */
24760b08185Syz 0x8, /* B134 */
24860b08185Syz 0x8, /* B150 */
24960b08185Syz 0x8, /* B200 */
25060b08185Syz 0x8, /* B300 */
25160b08185Syz 0x8, /* B600 */
25260b08185Syz 0x8, /* B1200 */
25360b08185Syz 0xb, /* B1800 */
25460b08185Syz 0x8, /* B2400 */
25560b08185Syz 0xa, /* B4800 */
25660b08185Syz 0xa, /* B9600 */
25760b08185Syz 0x19, /* B19200 */
25860b08185Syz 0x8, /* B38400 */
25960b08185Syz 0x8, /* B57600 */
26060b08185Syz 0xc, /* B76800 */
26160b08185Syz 0x8, /* B115200 */
26260b08185Syz 0xd, /* B153600 */
26360b08185Syz 0xd, /* B230400 */
26460b08185Syz };
265c138f478Syz
26660b08185Syz
26760b08185Syz /* convert baud code into baud rate */
26860b08185Syz static int keyspan_speed2baud[] = {
26960b08185Syz 0, /* B0 */
27060b08185Syz 50, /* B50 */
27160b08185Syz 75, /* B75 */
27260b08185Syz 110, /* B110 */
27360b08185Syz 134, /* B134 */
27460b08185Syz 150, /* B150 */
27560b08185Syz 200, /* B200 */
27660b08185Syz 300, /* B300 */
27760b08185Syz 600, /* B600 */
27860b08185Syz 1200, /* B1200 */
27960b08185Syz 1800, /* B1800 */
28060b08185Syz 2400, /* B2400 */
28160b08185Syz 4800, /* B4800 */
28260b08185Syz 9600, /* B9600 */
28360b08185Syz 19200, /* B19200 */
28460b08185Syz 38400, /* B38400 */
28560b08185Syz 57600, /* B57600 */
28660b08185Syz 76800, /* B76800 */
28760b08185Syz 115200, /* B115200 */
28860b08185Syz 153600, /* B153600 */
28960b08185Syz 230400, /* B230400 */
29060b08185Syz };
29160b08185Syz
29260b08185Syz
29360b08185Syz /* debug support */
29460b08185Syz static uint_t keyspan_errlevel = USB_LOG_L4;
29560b08185Syz static uint_t keyspan_errmask = DPRINT_MASK_ALL;
29660b08185Syz static uint_t keyspan_instance_debug = (uint_t)-1;
29760b08185Syz
29860b08185Syz static int
keyspan_attach(ds_attach_info_t * aip)29960b08185Syz keyspan_attach(ds_attach_info_t *aip)
30060b08185Syz {
30160b08185Syz keyspan_state_t *ksp;
30202dd2108Slg int rval = USB_SUCCESS;
30360b08185Syz
30460b08185Syz ksp = (keyspan_state_t *)kmem_zalloc(sizeof (keyspan_state_t),
30560b08185Syz KM_SLEEP);
30660b08185Syz ksp->ks_dip = aip->ai_dip;
30760b08185Syz ksp->ks_usb_events = aip->ai_usb_events;
30860b08185Syz *aip->ai_hdl = (ds_hdl_t)ksp;
30960b08185Syz
31060b08185Syz if (keyspan_usb_register(ksp) != USB_SUCCESS) {
31160b08185Syz
31260b08185Syz goto fail_register;
31360b08185Syz }
31460b08185Syz
31560b08185Syz /* init mutex and semaphore */
31660b08185Syz keyspan_init_sync_objs(ksp);
31760b08185Syz
31860b08185Syz /* get device specific parameters */
31960b08185Syz if (keyspan_attach_dev(ksp) != USB_SUCCESS) {
320d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, "fail attach dev ");
32160b08185Syz
32260b08185Syz goto fail_attach_dev;
32360b08185Syz }
32460b08185Syz
32560b08185Syz keyspan_attach_ports(ksp);
32660b08185Syz
32702dd2108Slg switch (ksp->ks_dev_spec.id_product) {
32802dd2108Slg case KEYSPAN_USA19HS_PID:
32902dd2108Slg case KEYSPAN_USA49WLC_PID:
33002dd2108Slg rval = keyspan_init_pipes(ksp);
33102dd2108Slg
33202dd2108Slg break;
33302dd2108Slg
33402dd2108Slg case KEYSPAN_USA49WG_PID:
33502dd2108Slg rval = keyspan_init_pipes_usa49wg(ksp);
33602dd2108Slg
33702dd2108Slg break;
33802dd2108Slg
33902dd2108Slg default:
34002dd2108Slg USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, "keyspan_attach:"
34102dd2108Slg "the device's product id can't be recognized");
34202dd2108Slg
34302dd2108Slg return (USB_FAILURE);
34402dd2108Slg }
34502dd2108Slg
34602dd2108Slg if (rval != USB_SUCCESS) {
347d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
34860b08185Syz "keyspan_init_pipes: failed.");
34960b08185Syz
35060b08185Syz goto fail_init_pipes;
35160b08185Syz }
35260b08185Syz
35360b08185Syz keyspan_init_port_params(ksp);
35460b08185Syz keyspan_free_descr_tree(ksp);
35560b08185Syz keyspan_set_dev_state_online(ksp);
35660b08185Syz
35760b08185Syz if (keyspan_create_pm_components(ksp) != USB_SUCCESS) {
358d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
35960b08185Syz "keyspan_create_pm_components: failed.");
36060b08185Syz
36160b08185Syz goto fail_pm;
36260b08185Syz }
36360b08185Syz
36460b08185Syz if (keyspan_register_events(ksp) != USB_SUCCESS) {
36560b08185Syz
36660b08185Syz goto fail_events;
36760b08185Syz }
36860b08185Syz
36960b08185Syz /* open the global pipes */
37060b08185Syz if (keyspan_attach_pipes(ksp) != USB_SUCCESS) {
371d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
37260b08185Syz "keyspan_attach_pipes: failed.");
37360b08185Syz
37460b08185Syz goto fail_attach_pipes;
37560b08185Syz }
37660b08185Syz
37760b08185Syz *aip->ai_port_cnt = ksp->ks_dev_spec.port_cnt;
37860b08185Syz
37960b08185Syz return (USB_SUCCESS);
38060b08185Syz
38160b08185Syz fail_attach_pipes:
38260b08185Syz keyspan_unregister_events(ksp);
38360b08185Syz fail_events:
38460b08185Syz keyspan_destroy_pm_components(ksp);
38560b08185Syz fail_pm:
38660b08185Syz keyspan_fini_pipes(ksp);
38760b08185Syz fail_init_pipes:
38860b08185Syz keyspan_detach_ports(ksp);
38960b08185Syz fail_attach_dev:
39060b08185Syz keyspan_fini_sync_objs(ksp);
39160b08185Syz keyspan_usb_unregister(ksp);
39260b08185Syz fail_register:
39360b08185Syz keyspan_free_soft_state(ksp);
39460b08185Syz
39560b08185Syz return (USB_FAILURE);
39660b08185Syz }
39760b08185Syz
39860b08185Syz
39960b08185Syz /*
40060b08185Syz * ds_detach
40160b08185Syz */
40260b08185Syz static void
keyspan_detach(ds_hdl_t hdl)40360b08185Syz keyspan_detach(ds_hdl_t hdl)
40460b08185Syz {
40560b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
40660b08185Syz
40760b08185Syz keyspan_detach_pipes(ksp);
40860b08185Syz keyspan_unregister_events(ksp);
40960b08185Syz keyspan_destroy_pm_components(ksp);
41060b08185Syz keyspan_fini_pipes(ksp);
41160b08185Syz keyspan_detach_ports(ksp);
41260b08185Syz keyspan_fini_sync_objs(ksp);
41360b08185Syz keyspan_usb_unregister(ksp);
41460b08185Syz keyspan_free_soft_state(ksp);
41560b08185Syz }
41660b08185Syz
41760b08185Syz /*
41860b08185Syz * ds_register_cb
41960b08185Syz */
42060b08185Syz static int
keyspan_register_cb(ds_hdl_t hdl,uint_t port_num,ds_cb_t * cb)42160b08185Syz keyspan_register_cb(ds_hdl_t hdl, uint_t port_num, ds_cb_t *cb)
42260b08185Syz {
42360b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
42460b08185Syz keyspan_port_t *kp;
42560b08185Syz
42660b08185Syz if (port_num >= ksp->ks_dev_spec.port_cnt) {
42760b08185Syz
42860b08185Syz return (USB_FAILURE);
42960b08185Syz }
43060b08185Syz kp = &ksp->ks_ports[port_num];
43160b08185Syz kp->kp_cb = *cb;
43260b08185Syz
43360b08185Syz return (USB_SUCCESS);
43460b08185Syz }
43560b08185Syz
43660b08185Syz /*
43760b08185Syz * ds_unregister_cb
43860b08185Syz */
43960b08185Syz static void
keyspan_unregister_cb(ds_hdl_t hdl,uint_t port_num)44060b08185Syz keyspan_unregister_cb(ds_hdl_t hdl, uint_t port_num)
44160b08185Syz {
44260b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
44360b08185Syz keyspan_port_t *kp;
44460b08185Syz
44560b08185Syz if (port_num < ksp->ks_dev_spec.port_cnt) {
44660b08185Syz kp = &ksp->ks_ports[port_num];
44760b08185Syz bzero(&kp->kp_cb, sizeof (kp->kp_cb));
44860b08185Syz }
44960b08185Syz }
45060b08185Syz
45160b08185Syz /*
45260b08185Syz * initialize hardware serial port
45360b08185Syz *
45460b08185Syz * 'open_pipes' specifies whether to open USB pipes or not
45560b08185Syz */
45660b08185Syz int
keyspan_open_hw_port(keyspan_port_t * kp,boolean_t open_pipes)45760b08185Syz keyspan_open_hw_port(keyspan_port_t *kp, boolean_t open_pipes)
45860b08185Syz {
45960b08185Syz int rval;
46002dd2108Slg keyspan_state_t *ksp = kp->kp_ksp;
46160b08185Syz
46260b08185Syz USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh,
46360b08185Syz "keyspan_open_hw_port: [%d]", kp->kp_port_num);
46460b08185Syz
46560b08185Syz if (open_pipes) {
46660b08185Syz
46760b08185Syz /* open r/w pipes for this port */
46860b08185Syz if ((rval = keyspan_open_port_pipes(kp)) != USB_SUCCESS) {
46960b08185Syz
47060b08185Syz return (rval);
47160b08185Syz }
47260b08185Syz }
47360b08185Syz
47460b08185Syz mutex_enter(&kp->kp_mutex);
47560b08185Syz kp->kp_state = KEYSPAN_PORT_OPEN;
47660b08185Syz mutex_exit(&kp->kp_mutex);
47760b08185Syz
47802dd2108Slg switch (ksp->ks_dev_spec.id_product) {
47902dd2108Slg case KEYSPAN_USA19HS_PID:
48002dd2108Slg case KEYSPAN_USA49WLC_PID:
48102dd2108Slg if ((rval = keyspan_receive_data(&kp->kp_datain_pipe,
4824ee52f77Slg kp->kp_read_len, kp)) != USB_SUCCESS) {
48360b08185Syz
48402dd2108Slg goto fail;
48502dd2108Slg }
48602dd2108Slg
48702dd2108Slg break;
48802dd2108Slg
48902dd2108Slg case KEYSPAN_USA49WG_PID:
49002dd2108Slg mutex_enter(&ksp->ks_mutex);
49102dd2108Slg /* open data in pipe the first time, start receiving data */
49202dd2108Slg if ((ksp->ks_datain_open_cnt == 1) && open_pipes) {
49302dd2108Slg mutex_exit(&ksp->ks_mutex);
49402dd2108Slg if ((rval = keyspan_receive_data(&kp->kp_datain_pipe,
4954ee52f77Slg kp->kp_read_len, kp)) != USB_SUCCESS) {
49602dd2108Slg
49702dd2108Slg goto fail;
49802dd2108Slg }
49902dd2108Slg /* the device is reconnected to host, restart receiving data */
50002dd2108Slg } else if ((ksp->ks_reconnect_flag) && (!open_pipes)) {
50102dd2108Slg mutex_exit(&ksp->ks_mutex);
50202dd2108Slg if ((rval = keyspan_receive_data(&kp->kp_datain_pipe,
5034ee52f77Slg kp->kp_read_len, kp)) != USB_SUCCESS) {
50402dd2108Slg
50502dd2108Slg goto fail;
50602dd2108Slg }
50702dd2108Slg mutex_enter(&ksp->ks_mutex);
50802dd2108Slg ksp->ks_reconnect_flag = 0;
50902dd2108Slg mutex_exit(&ksp->ks_mutex);
51002dd2108Slg
51102dd2108Slg } else {
51202dd2108Slg mutex_exit(&ksp->ks_mutex);
51302dd2108Slg }
51402dd2108Slg
51502dd2108Slg break;
51602dd2108Slg
51702dd2108Slg default:
51802dd2108Slg USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, "keyspan_open_hw_port:"
51902dd2108Slg "the device's product id can't be recognized");
52002dd2108Slg
52102dd2108Slg return (USB_FAILURE);
52260b08185Syz }
52360b08185Syz
52460b08185Syz /* set the default port parameters and send cmd msg to enable port */
52560b08185Syz mutex_enter(&kp->kp_mutex);
52660b08185Syz keyspan_default_port_params(kp);
52760b08185Syz mutex_exit(&kp->kp_mutex);
52860b08185Syz
52960b08185Syz (void) keyspan_send_cmd(kp);
53060b08185Syz
53160b08185Syz USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh,
53260b08185Syz "keyspan_open_hw_port: [%d] finished", kp->kp_port_num);
53360b08185Syz
53460b08185Syz return (rval);
53560b08185Syz
53660b08185Syz fail:
53760b08185Syz
53860b08185Syz mutex_enter(&kp->kp_mutex);
53960b08185Syz kp->kp_state = KEYSPAN_PORT_CLOSED;
54060b08185Syz mutex_exit(&kp->kp_mutex);
54160b08185Syz
54260b08185Syz if (open_pipes) {
54360b08185Syz
54460b08185Syz /* close all ports' data pipes */
54560b08185Syz keyspan_close_port_pipes(kp);
54660b08185Syz }
54760b08185Syz
548d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_OPEN, kp->kp_lh,
54960b08185Syz "keyspan_open_hw_port: failed. This port can't be used.");
55060b08185Syz
55160b08185Syz return (rval);
55260b08185Syz }
55360b08185Syz
55460b08185Syz /*
55560b08185Syz * ds_open_port
55660b08185Syz */
55760b08185Syz static int
keyspan_open_port(ds_hdl_t hdl,uint_t port_num)55860b08185Syz keyspan_open_port(ds_hdl_t hdl, uint_t port_num)
55960b08185Syz {
56060b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
56160b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
56260b08185Syz int rval;
56360b08185Syz
56460b08185Syz if (port_num >= ksp->ks_dev_spec.port_cnt) {
56560b08185Syz
56660b08185Syz return (USB_FAILURE);
56760b08185Syz }
56860b08185Syz USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh, "keyspan_open_port");
56960b08185Syz
57060b08185Syz mutex_enter(&ksp->ks_mutex);
57160b08185Syz if (ksp->ks_dev_state == USB_DEV_DISCONNECTED) {
57260b08185Syz mutex_exit(&ksp->ks_mutex);
57360b08185Syz
57460b08185Syz return (USB_FAILURE);
57560b08185Syz }
57660b08185Syz mutex_exit(&ksp->ks_mutex);
57760b08185Syz
57860b08185Syz if (keyspan_pm_set_busy(ksp) != USB_SUCCESS) {
57960b08185Syz
58060b08185Syz return (USB_FAILURE);
58160b08185Syz }
58260b08185Syz
58360b08185Syz /*
58460b08185Syz * initialize state
58560b08185Syz */
58660b08185Syz mutex_enter(&kp->kp_mutex);
58760b08185Syz ASSERT(kp->kp_state == KEYSPAN_PORT_CLOSED);
58860b08185Syz ASSERT((kp->kp_rx_mp == NULL) && (kp->kp_tx_mp == NULL));
58960b08185Syz
59060b08185Syz kp->kp_state = KEYSPAN_PORT_OPENING;
59160b08185Syz kp->kp_flags = 0;
59260b08185Syz mutex_exit(&kp->kp_mutex);
59360b08185Syz
59460b08185Syz /*
59560b08185Syz * initialize hardware serial port, B_TRUE means open pipes
59660b08185Syz */
59760b08185Syz sema_p(&ksp->ks_pipes_sema);
59860b08185Syz rval = keyspan_open_hw_port(kp, B_TRUE);
59960b08185Syz if (rval != USB_SUCCESS) {
60060b08185Syz keyspan_pm_set_idle(ksp);
60160b08185Syz }
60260b08185Syz sema_v(&ksp->ks_pipes_sema);
60360b08185Syz
60460b08185Syz return (rval);
60560b08185Syz }
60660b08185Syz
60760b08185Syz
60860b08185Syz /*
60960b08185Syz * close hardware serial port
61060b08185Syz */
61160b08185Syz void
keyspan_close_hw_port(keyspan_port_t * kp)61260b08185Syz keyspan_close_hw_port(keyspan_port_t *kp)
61360b08185Syz {
61460b08185Syz keyspan_state_t *ksp = kp->kp_ksp;
61560b08185Syz
61660b08185Syz ASSERT(!mutex_owned(&kp->kp_mutex));
61760b08185Syz
61860b08185Syz USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh,
61960b08185Syz "keyspan_close_hw_port");
62060b08185Syz
62160b08185Syz /*
62260b08185Syz * The bulk IN/OUT pipes might have got closed due to
62360b08185Syz * a device disconnect event. So its required to check the
62460b08185Syz * pipe handle and proceed if it is not NULL
62560b08185Syz */
62660b08185Syz
62760b08185Syz mutex_enter(&kp->kp_mutex);
62860b08185Syz if ((kp->kp_datain_pipe.pipe_handle == NULL) &&
62960b08185Syz (kp->kp_dataout_pipe.pipe_handle == NULL)) {
63060b08185Syz mutex_exit(&kp->kp_mutex);
63160b08185Syz
63260b08185Syz return;
63360b08185Syz }
63460b08185Syz
63560b08185Syz switch (ksp->ks_dev_spec.id_product) {
63660b08185Syz case KEYSPAN_USA19HS_PID:
63760b08185Syz keyspan_build_cmd_msg_usa19hs(kp, NULL);
63860b08185Syz kp->kp_ctrl_msg.usa19hs.portEnabled = 0;
63960b08185Syz kp->kp_ctrl_msg.usa19hs.rxFlush = 0;
64060b08185Syz kp->kp_ctrl_msg.usa19hs.txFlush = 0;
64160b08185Syz kp->kp_ctrl_msg.usa19hs.returnStatus = 0;
64260b08185Syz kp->kp_ctrl_msg.usa19hs.setRts = 1;
64360b08185Syz kp->kp_ctrl_msg.usa19hs.rts = 0;
64460b08185Syz kp->kp_ctrl_msg.usa19hs.setDtr = 1;
64560b08185Syz kp->kp_ctrl_msg.usa19hs.dtr = 0;
64660b08185Syz kp->kp_ctrl_msg.usa19hs.setTxFlowControl = 1;
64760b08185Syz kp->kp_ctrl_msg.usa19hs.txFlowControl = 0;
64860b08185Syz kp->kp_ctrl_msg.usa19hs.setRxFlowControl = 1;
64960b08185Syz kp->kp_ctrl_msg.usa19hs.rxFlowControl = 0;
65060b08185Syz kp->kp_ctrl_msg.usa19hs.rxForwardingTimeout = 0;
65160b08185Syz kp->kp_ctrl_msg.usa19hs.rxForwardingLength = 0;
65260b08185Syz
65360b08185Syz break;
65460b08185Syz
655c138f478Syz
65660b08185Syz case KEYSPAN_USA49WLC_PID:
65702dd2108Slg case KEYSPAN_USA49WG_PID:
65860b08185Syz keyspan_build_cmd_msg_usa49(kp, NULL);
65960b08185Syz kp->kp_ctrl_msg.usa49._txOn = 0;
66060b08185Syz kp->kp_ctrl_msg.usa49._txOff = 1;
66160b08185Syz kp->kp_ctrl_msg.usa49.txFlush = 0;
66260b08185Syz kp->kp_ctrl_msg.usa49.txBreak = 0;
66360b08185Syz kp->kp_ctrl_msg.usa49.rxOn = 0;
66460b08185Syz kp->kp_ctrl_msg.usa49.rxOff = 1;
66560b08185Syz kp->kp_ctrl_msg.usa49.rxFlush = 0;
66660b08185Syz kp->kp_ctrl_msg.usa49.rxForward = 0;
66760b08185Syz kp->kp_ctrl_msg.usa49.returnStatus = 0;
66860b08185Syz kp->kp_ctrl_msg.usa49.resetDataToggle = 0;
66960b08185Syz kp->kp_ctrl_msg.usa49.enablePort = 0;
67060b08185Syz kp->kp_ctrl_msg.usa49.disablePort = 1;
67160b08185Syz
67260b08185Syz break;
673c138f478Syz
67460b08185Syz default:
67560b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
67660b08185Syz "keyspan_close_hw_port:"
67760b08185Syz "the device's product id can't be recognized");
67860b08185Syz mutex_exit(&kp->kp_mutex);
67960b08185Syz
68060b08185Syz return;
68160b08185Syz }
68260b08185Syz
68360b08185Syz mutex_exit(&kp->kp_mutex);
68460b08185Syz /* send close port cmd to this port */
68560b08185Syz if (keyspan_send_cmd(kp) != USB_SUCCESS) {
68660b08185Syz USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
6874ee52f77Slg "keyspan_close_hw_port: closing hw port, send cmd FAILED");
68860b08185Syz }
68960b08185Syz
69060b08185Syz /* blow away bulkin requests or pipe close will wait until timeout */
69102dd2108Slg switch (ksp->ks_dev_spec.id_product) {
69202dd2108Slg case KEYSPAN_USA19HS_PID:
69302dd2108Slg case KEYSPAN_USA49WLC_PID:
69402dd2108Slg usb_pipe_reset(ksp->ks_dip,
6954ee52f77Slg kp->kp_datain_pipe.pipe_handle,
6964ee52f77Slg USB_FLAGS_SLEEP, NULL, NULL);
69702dd2108Slg
69802dd2108Slg break;
69902dd2108Slg case KEYSPAN_USA49WG_PID:
70002dd2108Slg mutex_enter(&ksp->ks_mutex);
70102dd2108Slg /*
70202dd2108Slg * if only this port is opened, shared data in pipe
70302dd2108Slg * can be reset.
70402dd2108Slg */
70502dd2108Slg if (ksp->ks_datain_open_cnt == 1) {
70602dd2108Slg mutex_exit(&ksp->ks_mutex);
70702dd2108Slg
70802dd2108Slg usb_pipe_reset(ksp->ks_dip,
7094ee52f77Slg kp->kp_datain_pipe.pipe_handle,
7104ee52f77Slg USB_FLAGS_SLEEP, NULL, NULL);
71102dd2108Slg } else {
71202dd2108Slg mutex_exit(&ksp->ks_mutex);
71302dd2108Slg }
71402dd2108Slg
71502dd2108Slg break;
71602dd2108Slg default:
71702dd2108Slg USB_DPRINTF_L2(DPRINT_CLOSE, kp->kp_lh,
7184ee52f77Slg "keyspan_close_hw_port: the device's"
7194ee52f77Slg " product id can't be recognized");
72002dd2108Slg }
72160b08185Syz
72260b08185Syz (void) keyspan_close_port_pipes(kp);
72360b08185Syz }
72460b08185Syz
72560b08185Syz /*
72660b08185Syz * ds_close_port
72760b08185Syz */
72860b08185Syz static int
keyspan_close_port(ds_hdl_t hdl,uint_t port_num)72960b08185Syz keyspan_close_port(ds_hdl_t hdl, uint_t port_num)
73060b08185Syz {
73160b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
73260b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
73360b08185Syz
73460b08185Syz if (port_num >= ksp->ks_dev_spec.port_cnt) {
73560b08185Syz
73660b08185Syz return (USB_FAILURE);
73760b08185Syz }
73860b08185Syz USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh, "keyspan_close_port");
73960b08185Syz
74060b08185Syz sema_p(&ksp->ks_pipes_sema);
74160b08185Syz mutex_enter(&kp->kp_mutex);
74260b08185Syz kp->kp_no_more_reads = B_TRUE;
74360b08185Syz
74460b08185Syz /* close hardware serial port */
74560b08185Syz mutex_exit(&kp->kp_mutex);
74660b08185Syz
74760b08185Syz keyspan_close_hw_port(kp);
74860b08185Syz mutex_enter(&kp->kp_mutex);
74960b08185Syz
75060b08185Syz /*
75160b08185Syz * free resources and finalize state
75260b08185Syz */
75360b08185Syz if (kp->kp_rx_mp) {
75460b08185Syz freemsg(kp->kp_rx_mp);
75560b08185Syz kp->kp_rx_mp = NULL;
75660b08185Syz }
75760b08185Syz if (kp->kp_tx_mp) {
75860b08185Syz freemsg(kp->kp_tx_mp);
75960b08185Syz kp->kp_tx_mp = NULL;
76060b08185Syz }
76160b08185Syz
76260b08185Syz kp->kp_no_more_reads = B_FALSE;
76360b08185Syz kp->kp_state = KEYSPAN_PORT_CLOSED;
76460b08185Syz mutex_exit(&kp->kp_mutex);
76560b08185Syz
76660b08185Syz keyspan_pm_set_idle(ksp);
76760b08185Syz
76860b08185Syz sema_v(&ksp->ks_pipes_sema);
76960b08185Syz
77060b08185Syz return (USB_SUCCESS);
77160b08185Syz }
77260b08185Syz
77360b08185Syz /*
77460b08185Syz * power management
77560b08185Syz *
77660b08185Syz * ds_usb_power
77760b08185Syz */
77860b08185Syz /*ARGSUSED*/
77960b08185Syz static int
keyspan_usb_power(ds_hdl_t hdl,int comp,int level,int * new_state)78060b08185Syz keyspan_usb_power(ds_hdl_t hdl, int comp, int level, int *new_state)
78160b08185Syz {
78260b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
78360b08185Syz keyspan_pm_t *pm = ksp->ks_pm;
78460b08185Syz int rval;
78560b08185Syz
78660b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_usb_power");
78760b08185Syz
78860b08185Syz mutex_enter(&ksp->ks_mutex);
78960b08185Syz
79060b08185Syz /*
79160b08185Syz * check if we are transitioning to a legal power level
79260b08185Syz */
79360b08185Syz if (USB_DEV_PWRSTATE_OK(pm->pm_pwr_states, level)) {
79460b08185Syz USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh, "keyspan_usb_power:"
79560b08185Syz "illegal power level %d, pwr_states=%x",
79660b08185Syz level, pm->pm_pwr_states);
79760b08185Syz mutex_exit(&ksp->ks_mutex);
79860b08185Syz
79960b08185Syz return (USB_FAILURE);
80060b08185Syz }
80160b08185Syz
80260b08185Syz /*
80360b08185Syz * if we are about to raise power and asked to lower power, fail
80460b08185Syz */
80560b08185Syz if (pm->pm_raise_power && (level < (int)pm->pm_cur_power)) {
80660b08185Syz mutex_exit(&ksp->ks_mutex);
80760b08185Syz
80860b08185Syz return (USB_FAILURE);
80960b08185Syz }
81060b08185Syz
81160b08185Syz switch (level) {
81260b08185Syz case USB_DEV_OS_PWR_OFF:
81360b08185Syz rval = keyspan_pwrlvl0(ksp);
81460b08185Syz
81560b08185Syz break;
81660b08185Syz case USB_DEV_OS_PWR_1:
81760b08185Syz rval = keyspan_pwrlvl1(ksp);
81860b08185Syz
81960b08185Syz break;
82060b08185Syz case USB_DEV_OS_PWR_2:
82160b08185Syz rval = keyspan_pwrlvl2(ksp);
82260b08185Syz
82360b08185Syz break;
82460b08185Syz case USB_DEV_OS_FULL_PWR:
82560b08185Syz rval = keyspan_pwrlvl3(ksp);
8264ee52f77Slg /*
8274ee52f77Slg * If usbser dev_state is DISCONNECTED or SUSPENDED, it shows
8284ee52f77Slg * that the usb serial device is disconnected/suspended while it
8294ee52f77Slg * is under power down state, now the device is powered up
8304ee52f77Slg * before it is reconnected/resumed. xxx_pwrlvl3() will set dev
8314ee52f77Slg * state to ONLINE, we need to set the dev state back to
8324ee52f77Slg * DISCONNECTED/SUSPENDED.
8334ee52f77Slg */
8344ee52f77Slg if ((rval == USB_SUCCESS) &&
8354ee52f77Slg ((*new_state == USB_DEV_DISCONNECTED) ||
8364ee52f77Slg (*new_state == USB_DEV_SUSPENDED))) {
8374ee52f77Slg ksp->ks_dev_state = *new_state;
8384ee52f77Slg }
83960b08185Syz
84060b08185Syz break;
84160b08185Syz default:
84260b08185Syz ASSERT(0); /* cannot happen */
84360b08185Syz }
84460b08185Syz
84560b08185Syz *new_state = ksp->ks_dev_state;
84660b08185Syz mutex_exit(&ksp->ks_mutex);
84760b08185Syz
84860b08185Syz return (rval);
84960b08185Syz }
85060b08185Syz
85160b08185Syz
85260b08185Syz /*
85360b08185Syz * ds_suspend
85460b08185Syz */
85560b08185Syz static int
keyspan_suspend(ds_hdl_t hdl)85660b08185Syz keyspan_suspend(ds_hdl_t hdl)
85760b08185Syz {
85860b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
8594ee52f77Slg int state = USB_DEV_SUSPENDED;
86060b08185Syz
86160b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_suspend");
86260b08185Syz
8634ee52f77Slg /*
8644ee52f77Slg * If the device is suspended while it is under PWRED_DOWN state, we
8654ee52f77Slg * need to keep the PWRED_DOWN state so that it could be powered up
8664ee52f77Slg * later. In the mean while, usbser dev state will be changed to
8674ee52f77Slg * SUSPENDED state.
8684ee52f77Slg */
86960b08185Syz mutex_enter(&ksp->ks_mutex);
8704ee52f77Slg if (ksp->ks_dev_state != USB_DEV_PWRED_DOWN) {
8714ee52f77Slg ksp->ks_dev_state = USB_DEV_SUSPENDED;
8724ee52f77Slg }
87360b08185Syz mutex_exit(&ksp->ks_mutex);
87460b08185Syz
87560b08185Syz keyspan_disconnect_pipes(ksp);
87660b08185Syz
87760b08185Syz return (state);
87860b08185Syz }
87960b08185Syz
88060b08185Syz
88160b08185Syz /*
88260b08185Syz * ds_resume
88360b08185Syz */
88460b08185Syz static int
keyspan_resume(ds_hdl_t hdl)88560b08185Syz keyspan_resume(ds_hdl_t hdl)
88660b08185Syz {
88760b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
88860b08185Syz int current_state;
88960b08185Syz int rval;
89060b08185Syz
89160b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_resume");
89260b08185Syz
89360b08185Syz mutex_enter(&ksp->ks_mutex);
89460b08185Syz current_state = ksp->ks_dev_state;
89560b08185Syz mutex_exit(&ksp->ks_mutex);
89660b08185Syz
89760b08185Syz if (current_state != USB_DEV_ONLINE) {
89860b08185Syz rval = keyspan_restore_device_state(ksp);
89960b08185Syz } else {
90060b08185Syz rval = USB_SUCCESS;
90160b08185Syz }
90260b08185Syz
90360b08185Syz return (rval);
90460b08185Syz }
90560b08185Syz
90660b08185Syz
90760b08185Syz /*
90860b08185Syz * ds_disconnect
90960b08185Syz */
91060b08185Syz static int
keyspan_disconnect(ds_hdl_t hdl)91160b08185Syz keyspan_disconnect(ds_hdl_t hdl)
91260b08185Syz {
91360b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
9144ee52f77Slg int state = USB_DEV_DISCONNECTED;
91560b08185Syz
91660b08185Syz USB_DPRINTF_L4(DPRINT_HOTPLUG, ksp->ks_lh, "keyspan_disconnect");
91760b08185Syz
9184ee52f77Slg /*
9194ee52f77Slg * If the device is disconnected while it is under PWRED_DOWN state, we
9204ee52f77Slg * need to keep the PWRED_DOWN state so that it could be powered up
9214ee52f77Slg * later. In the mean while, usbser dev state will be changed to
9224ee52f77Slg * DISCONNECTED state.
9234ee52f77Slg */
92460b08185Syz mutex_enter(&ksp->ks_mutex);
9254ee52f77Slg if (ksp->ks_dev_state != USB_DEV_PWRED_DOWN) {
9264ee52f77Slg ksp->ks_dev_state = USB_DEV_DISCONNECTED;
9274ee52f77Slg }
92860b08185Syz mutex_exit(&ksp->ks_mutex);
92960b08185Syz
93060b08185Syz keyspan_disconnect_pipes(ksp);
93160b08185Syz
93260b08185Syz return (state);
93360b08185Syz }
93460b08185Syz
93560b08185Syz
93660b08185Syz /*
93760b08185Syz * ds_reconnect
93860b08185Syz */
93960b08185Syz static int
keyspan_reconnect(ds_hdl_t hdl)94060b08185Syz keyspan_reconnect(ds_hdl_t hdl)
94160b08185Syz {
94260b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
94360b08185Syz
94460b08185Syz USB_DPRINTF_L4(DPRINT_HOTPLUG, ksp->ks_lh, "keyspan_reconnect");
94560b08185Syz
94660b08185Syz return (keyspan_restore_device_state(ksp));
94760b08185Syz }
94860b08185Syz
94960b08185Syz /*
95060b08185Syz * ds_set_port_params
95160b08185Syz */
95260b08185Syz static int
keyspan_set_port_params(ds_hdl_t hdl,uint_t port_num,ds_port_params_t * tp)95360b08185Syz keyspan_set_port_params(ds_hdl_t hdl, uint_t port_num, ds_port_params_t *tp)
95460b08185Syz {
95560b08185Syz int cnt = tp->tp_cnt;
95660b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
95760b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
95860b08185Syz
95960b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
96060b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
96160b08185Syz "keyspan_set_port_params: port: %d params", cnt);
96260b08185Syz
96360b08185Syz if (cnt <= 0) {
96460b08185Syz
96560b08185Syz return (USB_SUCCESS);
96660b08185Syz }
96760b08185Syz
96860b08185Syz mutex_enter(&kp->kp_mutex);
96960b08185Syz ASSERT((kp->kp_state == KEYSPAN_PORT_OPENING) ||
97060b08185Syz (kp->kp_state == KEYSPAN_PORT_OPEN));
97160b08185Syz keyspan_build_cmd_msg(kp, tp);
97260b08185Syz mutex_exit(&kp->kp_mutex);
97360b08185Syz
97460b08185Syz if (keyspan_send_cmd(kp) != USB_SUCCESS) {
97502dd2108Slg USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
97602dd2108Slg "keyspan_send_cmd() FAILED");
97760b08185Syz
97802dd2108Slg return (USB_FAILURE);
97960b08185Syz }
98060b08185Syz
98160b08185Syz return (USB_SUCCESS);
98260b08185Syz }
98360b08185Syz
98460b08185Syz
98560b08185Syz /*
98660b08185Syz * ds_set_modem_ctl
98760b08185Syz */
98860b08185Syz static int
keyspan_set_modem_ctl(ds_hdl_t hdl,uint_t port_num,int mask,int val)98960b08185Syz keyspan_set_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int val)
99060b08185Syz {
99160b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
99260b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
99360b08185Syz
99460b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
99560b08185Syz
99660b08185Syz mutex_enter(&kp->kp_mutex);
99760b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_set_modem_ctl: "
99860b08185Syz "mask=%x, val=%x", mask, val);
99960b08185Syz
100060b08185Syz keyspan_build_cmd_msg(kp, NULL);
100160b08185Syz
100260b08185Syz switch (ksp->ks_dev_spec.id_product) {
100360b08185Syz case KEYSPAN_USA19HS_PID:
100460b08185Syz if (mask & TIOCM_RTS) {
100560b08185Syz
100660b08185Syz kp->kp_ctrl_msg.usa19hs.setRts = 0x01;
100760b08185Syz
100860b08185Syz if (val & TIOCM_RTS) {
100960b08185Syz kp->kp_ctrl_msg.usa19hs.rts = 0x1;
101060b08185Syz } else {
101160b08185Syz kp->kp_ctrl_msg.usa19hs.rts = 0x0;
101260b08185Syz }
101360b08185Syz
101460b08185Syz } else {
101560b08185Syz kp->kp_ctrl_msg.usa19hs.setRts = 0x0;
101660b08185Syz }
101760b08185Syz
101860b08185Syz if (mask & TIOCM_DTR) {
101960b08185Syz kp->kp_ctrl_msg.usa19hs.setDtr = 0x01;
102060b08185Syz
102160b08185Syz if (val & TIOCM_DTR) {
102260b08185Syz kp->kp_ctrl_msg.usa19hs.dtr = 0x1;
102360b08185Syz } else {
102460b08185Syz kp->kp_ctrl_msg.usa19hs.dtr = 0x0;
102560b08185Syz }
102660b08185Syz
102760b08185Syz } else {
102860b08185Syz kp->kp_ctrl_msg.usa19hs.setDtr = 0x0;
102960b08185Syz }
103060b08185Syz
103160b08185Syz break;
103260b08185Syz
1033c138f478Syz
103460b08185Syz case KEYSPAN_USA49WLC_PID:
103502dd2108Slg case KEYSPAN_USA49WG_PID:
103660b08185Syz if (mask & TIOCM_RTS) {
103760b08185Syz
103860b08185Syz kp->kp_ctrl_msg.usa49.setRts = 0x1;
103960b08185Syz
104060b08185Syz if (val & TIOCM_RTS) {
104160b08185Syz kp->kp_ctrl_msg.usa49.rts = 0x1;
104260b08185Syz } else {
104360b08185Syz kp->kp_ctrl_msg.usa49.rts = 0x0;
104460b08185Syz }
104560b08185Syz
104660b08185Syz } else {
104760b08185Syz kp->kp_ctrl_msg.usa49.setRts = 0x0;
104860b08185Syz }
104960b08185Syz
105060b08185Syz if (mask & TIOCM_DTR) {
105160b08185Syz kp->kp_ctrl_msg.usa49.setDtr = 0x1;
105260b08185Syz
105360b08185Syz if (val & TIOCM_DTR) {
105460b08185Syz kp->kp_ctrl_msg.usa49.dtr = 0x1;
105560b08185Syz } else {
105660b08185Syz kp->kp_ctrl_msg.usa49.dtr = 0x0;
105760b08185Syz }
105860b08185Syz
105960b08185Syz } else {
106060b08185Syz kp->kp_ctrl_msg.usa49.setDtr = 0x0;
106160b08185Syz }
106260b08185Syz
106360b08185Syz break;
1064c138f478Syz
106560b08185Syz default:
106660b08185Syz USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
106760b08185Syz "keyspan_get_modem_ctl:"
106860b08185Syz "the device's product id can't be recognized");
106960b08185Syz mutex_exit(&kp->kp_mutex);
107060b08185Syz
107160b08185Syz return (USB_FAILURE);
107260b08185Syz }
107360b08185Syz
107460b08185Syz mutex_exit(&kp->kp_mutex);
107560b08185Syz
107660b08185Syz if (keyspan_send_cmd(kp) != USB_SUCCESS) {
107702dd2108Slg USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
107802dd2108Slg "keyspan_send_cmd() FAILED");
107960b08185Syz
108002dd2108Slg return (USB_FAILURE);
108160b08185Syz }
108260b08185Syz
108360b08185Syz return (USB_SUCCESS);
108460b08185Syz }
108560b08185Syz
108660b08185Syz /*
108760b08185Syz * ds_get_modem_ctl
108860b08185Syz */
108960b08185Syz static int
keyspan_get_modem_ctl(ds_hdl_t hdl,uint_t port_num,int mask,int * valp)109060b08185Syz keyspan_get_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int *valp)
109160b08185Syz {
109260b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
109360b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
109460b08185Syz int val = 0;
109560b08185Syz
109660b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
109760b08185Syz
109860b08185Syz mutex_enter(&kp->kp_mutex);
109960b08185Syz
110060b08185Syz /*
110160b08185Syz * rts and dtr are not in status_msg, but we can get it from
110260b08185Syz * status_flag since it represents what we set the device last time.
110360b08185Syz */
110460b08185Syz if (kp->kp_status_flag & KEYSPAN_PORT_RTS) {
110560b08185Syz val |= TIOCM_RTS;
110660b08185Syz }
110760b08185Syz if (kp->kp_status_flag & KEYSPAN_PORT_DTR) {
110860b08185Syz val |= TIOCM_DTR;
110960b08185Syz }
111060b08185Syz
111160b08185Syz /* usbser don't deal with TIOCM_RI status */
111260b08185Syz switch (ksp->ks_dev_spec.id_product) {
111360b08185Syz case KEYSPAN_USA19HS_PID:
111460b08185Syz if (kp->kp_status_msg.usa19hs.dcd) {
111560b08185Syz val |= TIOCM_CD;
111660b08185Syz }
111760b08185Syz if (kp->kp_status_msg.usa19hs.cts) {
111860b08185Syz val |= TIOCM_CTS;
111960b08185Syz }
112060b08185Syz if (kp->kp_status_msg.usa19hs.dsr) {
112160b08185Syz val |= TIOCM_DSR;
112260b08185Syz }
112360b08185Syz break;
112460b08185Syz
1125c138f478Syz
112660b08185Syz case KEYSPAN_USA49WLC_PID:
112702dd2108Slg case KEYSPAN_USA49WG_PID:
112860b08185Syz if (kp->kp_status_msg.usa49.dcd) {
112960b08185Syz val |= TIOCM_CD;
113060b08185Syz }
113160b08185Syz if (kp->kp_status_msg.usa49.cts) {
113260b08185Syz val |= TIOCM_CTS;
113360b08185Syz }
113460b08185Syz if (kp->kp_status_msg.usa49.dsr) {
113560b08185Syz val |= TIOCM_DSR;
113660b08185Syz }
113760b08185Syz break;
1138c138f478Syz
113960b08185Syz default:
114060b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
114160b08185Syz "keyspan_get_modem_ctl:"
114260b08185Syz "the device's product id can't be recognized");
114360b08185Syz mutex_exit(&kp->kp_mutex);
114460b08185Syz
114560b08185Syz return (USB_FAILURE);
114660b08185Syz }
114760b08185Syz
114860b08185Syz *valp = val & mask;
114960b08185Syz
115060b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_get_modem_ctl:"
115160b08185Syz "success. status_flag = %x, val=0%o",
115260b08185Syz kp->kp_status_flag, *valp);
115360b08185Syz
115460b08185Syz mutex_exit(&kp->kp_mutex);
115560b08185Syz
115660b08185Syz return (USB_SUCCESS);
115760b08185Syz }
115860b08185Syz
115960b08185Syz
116060b08185Syz /*
116160b08185Syz * ds_break_ctl
116260b08185Syz */
116360b08185Syz static int
keyspan_break_ctl(ds_hdl_t hdl,uint_t port_num,int ctl)116460b08185Syz keyspan_break_ctl(ds_hdl_t hdl, uint_t port_num, int ctl)
116560b08185Syz {
116660b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
116760b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
116860b08185Syz int is_break;
116960b08185Syz int rval = USB_SUCCESS;
117060b08185Syz
117160b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
117260b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
117360b08185Syz "keyspan_break_ctl: ctl = %s", (ctl == DS_ON) ? "on" : "off");
117460b08185Syz
117560b08185Syz mutex_enter(&kp->kp_mutex);
117660b08185Syz ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN);
117760b08185Syz ASSERT(ctl == DS_ON || ctl == DS_OFF);
117860b08185Syz
117960b08185Syz is_break = kp->kp_status_flag & KEYSPAN_PORT_TXBREAK;
118060b08185Syz
118160b08185Syz if ((ctl == DS_ON) && !is_break) {
118260b08185Syz
118360b08185Syz keyspan_build_cmd_msg(kp, NULL);
118460b08185Syz
118560b08185Syz switch (ksp->ks_dev_spec.id_product) {
118660b08185Syz case KEYSPAN_USA19HS_PID:
118760b08185Syz kp->kp_ctrl_msg.usa19hs.txBreak = 1;
118860b08185Syz
118960b08185Syz break;
119060b08185Syz
119160b08185Syz case KEYSPAN_USA49WLC_PID:
119202dd2108Slg case KEYSPAN_USA49WG_PID:
119360b08185Syz kp->kp_ctrl_msg.usa49.txBreak = 1;
119460b08185Syz
119560b08185Syz break;
1196c138f478Syz
119760b08185Syz default:
119860b08185Syz mutex_exit(&kp->kp_mutex);
119960b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
120060b08185Syz "keyspan_break_ctl:"
120160b08185Syz "the device's product id can't be recognized");
120260b08185Syz
120360b08185Syz return (USB_FAILURE);
120460b08185Syz }
120560b08185Syz
120660b08185Syz mutex_exit(&kp->kp_mutex);
120760b08185Syz rval = keyspan_send_cmd(kp);
120860b08185Syz return (rval);
120960b08185Syz }
121060b08185Syz
121160b08185Syz if ((ctl == DS_OFF) && is_break) {
121260b08185Syz keyspan_build_cmd_msg(kp, NULL);
121360b08185Syz
121460b08185Syz switch (ksp->ks_dev_spec.id_product) {
121560b08185Syz case KEYSPAN_USA19HS_PID:
121660b08185Syz kp->kp_ctrl_msg.usa19hs.txBreak = 0;
121760b08185Syz
121860b08185Syz break;
1219c138f478Syz
122060b08185Syz case KEYSPAN_USA49WLC_PID:
122102dd2108Slg case KEYSPAN_USA49WG_PID:
122260b08185Syz kp->kp_ctrl_msg.usa49._txOn = 1;
122360b08185Syz kp->kp_ctrl_msg.usa49.txBreak = 0;
122460b08185Syz
122560b08185Syz break;
1226c138f478Syz
122760b08185Syz default:
122860b08185Syz mutex_exit(&kp->kp_mutex);
122960b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
123060b08185Syz "keyspan_break_ctl:"
123160b08185Syz "the device's product id can't be recognized");
123260b08185Syz
123360b08185Syz return (USB_FAILURE);
123460b08185Syz }
123560b08185Syz
123660b08185Syz mutex_exit(&kp->kp_mutex);
123760b08185Syz rval = keyspan_send_cmd(kp);
123860b08185Syz if (rval == USB_SUCCESS) {
123960b08185Syz mutex_enter(&kp->kp_mutex);
124060b08185Syz
124160b08185Syz /* resume transmit */
124260b08185Syz keyspan_tx_start(kp, NULL);
124360b08185Syz mutex_exit(&kp->kp_mutex);
124460b08185Syz }
124560b08185Syz
124660b08185Syz return (rval);
124760b08185Syz }
124860b08185Syz
124960b08185Syz mutex_exit(&kp->kp_mutex);
125060b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
125160b08185Syz "keyspan_break_ctl: not necessary to set break, is_break = %d",
125260b08185Syz is_break);
125360b08185Syz
125460b08185Syz return (rval);
125560b08185Syz }
125660b08185Syz
125760b08185Syz
125860b08185Syz /*
125960b08185Syz * ds_loopback
126060b08185Syz */
126160b08185Syz static int
keyspan_loopback(ds_hdl_t hdl,uint_t port_num,int ctl)126260b08185Syz keyspan_loopback(ds_hdl_t hdl, uint_t port_num, int ctl)
126360b08185Syz {
126460b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
126560b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
126660b08185Syz int is_loop;
126760b08185Syz int rval = USB_SUCCESS;
126860b08185Syz
126960b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
127060b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
127160b08185Syz "keyspan_loopback: %s", (ctl == DS_ON) ? "on" : "off");
127260b08185Syz
127360b08185Syz mutex_enter(&kp->kp_mutex);
127460b08185Syz ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN);
127560b08185Syz ASSERT(ctl == DS_ON || ctl == DS_OFF);
127660b08185Syz
127760b08185Syz /* check bit indicating internal loopback state */
127860b08185Syz is_loop = kp->kp_status_flag & KEYSPAN_PORT_LOOPBACK;
127960b08185Syz
128060b08185Syz if ((ctl == DS_ON) && !is_loop) {
128160b08185Syz
128260b08185Syz keyspan_build_cmd_msg(kp, NULL);
128360b08185Syz switch (ksp->ks_dev_spec.id_product) {
128460b08185Syz case KEYSPAN_USA19HS_PID:
128560b08185Syz kp->kp_ctrl_msg.usa19hs.loopbackMode = 0;
128660b08185Syz
128760b08185Syz break;
128860b08185Syz
128960b08185Syz case KEYSPAN_USA49WLC_PID:
129002dd2108Slg case KEYSPAN_USA49WG_PID:
129160b08185Syz kp->kp_ctrl_msg.usa49.loopbackMode = 0;
129260b08185Syz
129360b08185Syz break;
1294c138f478Syz
129560b08185Syz default:
129660b08185Syz mutex_exit(&kp->kp_mutex);
129760b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
129860b08185Syz "keyspan_loopback:"
129960b08185Syz "the device's product id can't be recognized");
130060b08185Syz
130160b08185Syz return (USB_FAILURE);
130260b08185Syz }
130360b08185Syz mutex_exit(&kp->kp_mutex);
130460b08185Syz rval = keyspan_send_cmd(kp);
130560b08185Syz } else if ((ctl == DS_OFF) && is_loop) {
130660b08185Syz
130760b08185Syz keyspan_build_cmd_msg(kp, NULL);
130860b08185Syz switch (ksp->ks_dev_spec.id_product) {
130960b08185Syz case KEYSPAN_USA19HS_PID:
131060b08185Syz kp->kp_ctrl_msg.usa19hs.loopbackMode = 1;
131160b08185Syz
131260b08185Syz break;
131360b08185Syz
131460b08185Syz case KEYSPAN_USA49WLC_PID:
131502dd2108Slg case KEYSPAN_USA49WG_PID:
131660b08185Syz kp->kp_ctrl_msg.usa49.loopbackMode = 1;
131760b08185Syz
131860b08185Syz break;
1319c138f478Syz
132060b08185Syz default:
132160b08185Syz mutex_exit(&kp->kp_mutex);
132260b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
132360b08185Syz "keyspan_loopback:"
132460b08185Syz "the device's product id can't be recognized");
132560b08185Syz
132660b08185Syz return (USB_FAILURE);
132760b08185Syz }
132860b08185Syz mutex_exit(&kp->kp_mutex);
132960b08185Syz rval = keyspan_send_cmd(kp);
133060b08185Syz } else {
133160b08185Syz mutex_exit(&kp->kp_mutex);
133260b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
133360b08185Syz "keyspan_loopback: not necessary to set loopback,"
133460b08185Syz "is_loop = %d", is_loop);
133560b08185Syz }
133660b08185Syz
133760b08185Syz return (rval);
133860b08185Syz }
133960b08185Syz
134060b08185Syz
134160b08185Syz /*
134260b08185Syz * ds_tx
134360b08185Syz */
134460b08185Syz static int
keyspan_tx(ds_hdl_t hdl,uint_t port_num,mblk_t * mp)134560b08185Syz keyspan_tx(ds_hdl_t hdl, uint_t port_num, mblk_t *mp)
134660b08185Syz {
134760b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
134860b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
134960b08185Syz int xferd;
135060b08185Syz
135160b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
135260b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_tx");
135360b08185Syz
135460b08185Syz /*
135560b08185Syz * sanity checks
135660b08185Syz */
135760b08185Syz if (mp == NULL) {
135860b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, "keyspan_tx: mp=NULL");
135960b08185Syz
136060b08185Syz return (USB_SUCCESS);
136160b08185Syz }
136260b08185Syz
136360b08185Syz kp = &ksp->ks_ports[port_num];
136460b08185Syz
136560b08185Syz mutex_enter(&kp->kp_mutex);
136660b08185Syz
136760b08185Syz keyspan_put_tail(&kp->kp_tx_mp, mp); /* add to the chain */
136860b08185Syz
136960b08185Syz keyspan_tx_start(kp, &xferd); /* go! */
137060b08185Syz
137160b08185Syz mutex_exit(&kp->kp_mutex);
137260b08185Syz
137360b08185Syz return (USB_SUCCESS);
137460b08185Syz }
137560b08185Syz
137660b08185Syz
137760b08185Syz /*
137860b08185Syz * ds_rx. the real data receiving is in keyspan_open_hw_port
137960b08185Syz */
138060b08185Syz static mblk_t *
keyspan_rx(ds_hdl_t hdl,uint_t port_num)138160b08185Syz keyspan_rx(ds_hdl_t hdl, uint_t port_num)
138260b08185Syz {
138360b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
138460b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
138560b08185Syz mblk_t *mp;
138660b08185Syz
138760b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
138860b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_rx");
138960b08185Syz
139060b08185Syz mutex_enter(&kp->kp_mutex);
139160b08185Syz mp = kp->kp_rx_mp;
139260b08185Syz kp->kp_rx_mp = NULL;
139360b08185Syz mutex_exit(&kp->kp_mutex);
139460b08185Syz
139560b08185Syz return (mp);
139660b08185Syz }
139760b08185Syz
139860b08185Syz
139960b08185Syz /*
140060b08185Syz * ds_stop
140160b08185Syz */
140260b08185Syz static void
keyspan_stop(ds_hdl_t hdl,uint_t port_num,int dir)140360b08185Syz keyspan_stop(ds_hdl_t hdl, uint_t port_num, int dir)
140460b08185Syz {
140560b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
140660b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
140760b08185Syz
140860b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
140960b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_stop");
141060b08185Syz
141160b08185Syz if (dir & DS_TX) {
141260b08185Syz mutex_enter(&kp->kp_mutex);
141360b08185Syz kp->kp_flags |= KEYSPAN_PORT_TX_STOPPED;
141460b08185Syz mutex_exit(&kp->kp_mutex);
141560b08185Syz }
141660b08185Syz }
141760b08185Syz
141860b08185Syz
141960b08185Syz /*
142060b08185Syz * ds_start
142160b08185Syz */
142260b08185Syz static void
keyspan_start(ds_hdl_t hdl,uint_t port_num,int dir)142360b08185Syz keyspan_start(ds_hdl_t hdl, uint_t port_num, int dir)
142460b08185Syz {
142560b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
142660b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
142760b08185Syz
142860b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
142960b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_start");
143060b08185Syz
143160b08185Syz if (dir & DS_TX) {
143260b08185Syz mutex_enter(&kp->kp_mutex);
143360b08185Syz if (kp->kp_flags & KEYSPAN_PORT_TX_STOPPED) {
143460b08185Syz kp->kp_flags &= ~KEYSPAN_PORT_TX_STOPPED;
143560b08185Syz keyspan_tx_start(kp, NULL);
143660b08185Syz }
143760b08185Syz mutex_exit(&kp->kp_mutex);
143860b08185Syz }
143960b08185Syz }
144060b08185Syz
144160b08185Syz
144260b08185Syz /*
144360b08185Syz * ds_fifo_flush
144460b08185Syz * send flush cmd and wait for completion, then turn off the flush.
144560b08185Syz */
144660b08185Syz static int
keyspan_fifo_flush(ds_hdl_t hdl,uint_t port_num,int dir)144760b08185Syz keyspan_fifo_flush(ds_hdl_t hdl, uint_t port_num, int dir)
144860b08185Syz {
144960b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
145060b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
145160b08185Syz
145260b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
145360b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
145460b08185Syz "keyspan_fifo_flush: dir=%x", dir);
145560b08185Syz
145660b08185Syz mutex_enter(&kp->kp_mutex);
145760b08185Syz ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN);
145860b08185Syz
145960b08185Syz /* discard the data in DSD buffers */
146060b08185Syz if ((dir & DS_TX) && kp->kp_tx_mp) {
146160b08185Syz freemsg(kp->kp_tx_mp);
146260b08185Syz kp->kp_tx_mp = NULL;
146360b08185Syz }
146460b08185Syz if ((dir & DS_RX) && kp->kp_rx_mp) {
146560b08185Syz freemsg(kp->kp_rx_mp);
146660b08185Syz kp->kp_rx_mp = NULL;
146760b08185Syz }
146860b08185Syz
146960b08185Syz mutex_exit(&kp->kp_mutex);
147060b08185Syz
147160b08185Syz return (USB_SUCCESS);
147260b08185Syz }
147360b08185Syz
147460b08185Syz /*
147560b08185Syz * ds_fifo_drain
147660b08185Syz *
147760b08185Syz * it is the caller's responsibility to cease submitting new tx data
147860b08185Syz * while this function executes
147960b08185Syz */
148060b08185Syz static int
keyspan_fifo_drain(ds_hdl_t hdl,uint_t port_num,int timeout)148160b08185Syz keyspan_fifo_drain(ds_hdl_t hdl, uint_t port_num, int timeout)
148260b08185Syz {
148360b08185Syz keyspan_state_t *ksp = (keyspan_state_t *)hdl;
148460b08185Syz keyspan_port_t *kp = &ksp->ks_ports[port_num];
148560b08185Syz int rval = USB_SUCCESS;
148660b08185Syz
148760b08185Syz ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
148860b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
148960b08185Syz "keyspan_fifo_drain, timeout = %d", timeout);
149060b08185Syz
149160b08185Syz mutex_enter(&kp->kp_mutex);
149260b08185Syz ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN);
149360b08185Syz
149460b08185Syz /* wait until local data drains */
149560b08185Syz if (keyspan_wait_tx_drain(kp, 0) != USB_SUCCESS) {
149660b08185Syz mutex_exit(&kp->kp_mutex);
149760b08185Syz
149860b08185Syz return (USB_FAILURE);
149960b08185Syz }
150060b08185Syz mutex_exit(&kp->kp_mutex);
150160b08185Syz
150260b08185Syz /* wait until hw fifo drains */
150360b08185Syz delay(drv_usectohz(500*1000));
150460b08185Syz
150560b08185Syz return (rval);
150660b08185Syz }
150760b08185Syz
150860b08185Syz
150960b08185Syz /*
151060b08185Syz * configuration routines
151160b08185Syz * ----------------------
151260b08185Syz *
151360b08185Syz */
151460b08185Syz
151560b08185Syz /*
151660b08185Syz * free state structure
151760b08185Syz */
151860b08185Syz static void
keyspan_free_soft_state(keyspan_state_t * ksp)151960b08185Syz keyspan_free_soft_state(keyspan_state_t *ksp)
152060b08185Syz {
152160b08185Syz kmem_free(ksp, sizeof (keyspan_state_t));
152260b08185Syz }
152360b08185Syz
152460b08185Syz
152560b08185Syz /*
152660b08185Syz * register/unregister USBA client
152760b08185Syz */
152860b08185Syz static int
keyspan_usb_register(keyspan_state_t * ksp)152960b08185Syz keyspan_usb_register(keyspan_state_t *ksp)
153060b08185Syz {
153160b08185Syz int rval;
153260b08185Syz
153360b08185Syz rval = usb_client_attach(ksp->ks_dip, USBDRV_VERSION, 0);
153460b08185Syz if (rval == USB_SUCCESS) {
153560b08185Syz rval = usb_get_dev_data(ksp->ks_dip, &ksp->ks_dev_data,
153660b08185Syz USB_PARSE_LVL_IF, 0);
153760b08185Syz if (rval == USB_SUCCESS) {
153860b08185Syz ksp->ks_lh =
153960b08185Syz usb_alloc_log_hdl(ksp->ks_dip, "keyspan[*].",
154060b08185Syz &keyspan_errlevel, &keyspan_errmask,
154160b08185Syz &keyspan_instance_debug, 0);
154260b08185Syz
154360b08185Syz ksp->ks_def_pipe.pipe_handle =
154460b08185Syz ksp->ks_dev_data->dev_default_ph;
154560b08185Syz ksp->ks_def_pipe.pipe_ksp = ksp;
154660b08185Syz ksp->ks_def_pipe.pipe_lh = ksp->ks_lh;
154760b08185Syz }
154860b08185Syz }
154960b08185Syz
155060b08185Syz return (rval);
155160b08185Syz }
155260b08185Syz
155360b08185Syz
155460b08185Syz static void
keyspan_usb_unregister(keyspan_state_t * ksp)155560b08185Syz keyspan_usb_unregister(keyspan_state_t *ksp)
155660b08185Syz {
155760b08185Syz usb_free_log_hdl(ksp->ks_lh);
155860b08185Syz ksp->ks_lh = NULL;
155960b08185Syz usb_client_detach(ksp->ks_dip, ksp->ks_dev_data);
156060b08185Syz ksp->ks_def_pipe.pipe_handle = NULL;
156160b08185Syz ksp->ks_dev_data = NULL;
156260b08185Syz }
156360b08185Syz
156460b08185Syz
156560b08185Syz /*
156660b08185Syz * init/fini soft state during attach
156760b08185Syz */
156860b08185Syz static void
keyspan_init_sync_objs(keyspan_state_t * ksp)156960b08185Syz keyspan_init_sync_objs(keyspan_state_t *ksp)
157060b08185Syz {
157160b08185Syz mutex_init(&ksp->ks_mutex, NULL, MUTEX_DRIVER,
15724ee52f77Slg ksp->ks_dev_data->dev_iblock_cookie);
157360b08185Syz sema_init(&ksp->ks_pipes_sema, 1, NULL, SEMA_DRIVER, NULL);
157460b08185Syz }
157560b08185Syz
157660b08185Syz
157760b08185Syz static void
keyspan_fini_sync_objs(keyspan_state_t * ksp)157860b08185Syz keyspan_fini_sync_objs(keyspan_state_t *ksp)
157960b08185Syz {
158060b08185Syz mutex_destroy(&ksp->ks_mutex);
158160b08185Syz sema_destroy(&ksp->ks_pipes_sema);
158260b08185Syz }
158360b08185Syz
158460b08185Syz
158560b08185Syz /*
158660b08185Syz * device specific attributes
158760b08185Syz */
158860b08185Syz static int
keyspan_attach_dev(keyspan_state_t * ksp)158960b08185Syz keyspan_attach_dev(keyspan_state_t *ksp)
159060b08185Syz {
159160b08185Syz
159260b08185Syz mutex_enter(&ksp->ks_mutex);
159360b08185Syz switch (ksp->ks_dev_data->dev_descr->idProduct) {
159460b08185Syz case KEYSPAN_USA19HS_PID:
159560b08185Syz ksp->ks_dev_spec.id_product = KEYSPAN_USA19HS_PID;
159660b08185Syz ksp->ks_dev_spec.port_cnt = 1;
159760b08185Syz ksp->ks_dev_spec.ctrl_ep_addr = 0x02;
159860b08185Syz ksp->ks_dev_spec.stat_ep_addr = 0x82;
159960b08185Syz ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01;
160060b08185Syz ksp->ks_dev_spec.datain_ep_addr[0] = 0x81;
160160b08185Syz
160260b08185Syz break;
160360b08185Syz
160460b08185Syz case KEYSPAN_USA49WLC_PID:
160560b08185Syz ksp->ks_dev_spec.id_product = KEYSPAN_USA49WLC_PID;
160660b08185Syz ksp->ks_dev_spec.port_cnt = 4;
160760b08185Syz ksp->ks_dev_spec.ctrl_ep_addr = 0x07;
160860b08185Syz ksp->ks_dev_spec.stat_ep_addr = 0x87;
160960b08185Syz ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01;
161060b08185Syz ksp->ks_dev_spec.dataout_ep_addr[1] = 0x02;
161160b08185Syz ksp->ks_dev_spec.dataout_ep_addr[2] = 0x03;
161260b08185Syz ksp->ks_dev_spec.dataout_ep_addr[3] = 0x04;
161360b08185Syz ksp->ks_dev_spec.datain_ep_addr[0] = 0x81;
161460b08185Syz ksp->ks_dev_spec.datain_ep_addr[1] = 0x82;
161560b08185Syz ksp->ks_dev_spec.datain_ep_addr[2] = 0x83;
161660b08185Syz ksp->ks_dev_spec.datain_ep_addr[3] = 0x84;
161760b08185Syz
161860b08185Syz break;
1619c138f478Syz
162002dd2108Slg case KEYSPAN_USA49WG_PID:
162102dd2108Slg ksp->ks_dev_spec.id_product = KEYSPAN_USA49WG_PID;
162202dd2108Slg ksp->ks_dev_spec.port_cnt = 4;
162302dd2108Slg ksp->ks_dev_spec.stat_ep_addr = 0x81;
162402dd2108Slg ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01;
162502dd2108Slg ksp->ks_dev_spec.dataout_ep_addr[1] = 0x02;
162602dd2108Slg ksp->ks_dev_spec.dataout_ep_addr[2] = 0x04;
162702dd2108Slg ksp->ks_dev_spec.dataout_ep_addr[3] = 0x06;
162802dd2108Slg ksp->ks_dev_spec.datain_ep_addr[0] = 0x88;
162902dd2108Slg ksp->ks_dev_spec.datain_ep_addr[1] = 0x88;
163002dd2108Slg ksp->ks_dev_spec.datain_ep_addr[2] = 0x88;
163102dd2108Slg ksp->ks_dev_spec.datain_ep_addr[3] = 0x88;
163202dd2108Slg
163302dd2108Slg break;
163402dd2108Slg
163560b08185Syz default:
163660b08185Syz mutex_exit(&ksp->ks_mutex);
1637d291d9f2Sfrits USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
163860b08185Syz "keyspan_attach_dev:"
163960b08185Syz "the device's product id can't be recognized");
164060b08185Syz
164160b08185Syz return (USB_FAILURE);
164260b08185Syz }
164360b08185Syz
164460b08185Syz mutex_exit(&ksp->ks_mutex);
164560b08185Syz
164660b08185Syz return (USB_SUCCESS);
164760b08185Syz }
164860b08185Syz
164960b08185Syz /*
165060b08185Syz * allocate and initialize per port resources.
165160b08185Syz */
165260b08185Syz static void
keyspan_attach_ports(keyspan_state_t * ksp)165360b08185Syz keyspan_attach_ports(keyspan_state_t *ksp)
165460b08185Syz {
165560b08185Syz int i;
165660b08185Syz keyspan_port_t *kp;
165760b08185Syz
165860b08185Syz ksp->ks_ports = kmem_zalloc(ksp->ks_dev_spec.port_cnt *
16594ee52f77Slg sizeof (keyspan_port_t), KM_SLEEP);
166060b08185Syz
166160b08185Syz for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
166260b08185Syz kp = &ksp->ks_ports[i];
166360b08185Syz kp->kp_port_num = i;
166460b08185Syz kp->kp_ksp = ksp;
166560b08185Syz
166660b08185Syz (void) sprintf(kp->kp_lh_name, "keyspan[%d].", i);
166760b08185Syz kp->kp_lh = usb_alloc_log_hdl(ksp->ks_dip, kp->kp_lh_name,
16684ee52f77Slg &keyspan_errlevel, &keyspan_errmask,
16694ee52f77Slg &keyspan_instance_debug, 0);
167060b08185Syz
167160b08185Syz kp->kp_state = KEYSPAN_PORT_CLOSED;
167260b08185Syz mutex_init(&kp->kp_mutex, NULL, MUTEX_DRIVER,
16734ee52f77Slg ksp->ks_dev_data->dev_iblock_cookie);
167460b08185Syz cv_init(&kp->kp_tx_cv, NULL, CV_DRIVER, NULL);
167560b08185Syz }
167660b08185Syz }
167760b08185Syz
167860b08185Syz
167960b08185Syz /*
168060b08185Syz * free per port resources
168160b08185Syz */
168260b08185Syz static void
keyspan_detach_ports(keyspan_state_t * ksp)168360b08185Syz keyspan_detach_ports(keyspan_state_t *ksp)
168460b08185Syz {
168560b08185Syz int i;
168660b08185Syz keyspan_port_t *kp;
168760b08185Syz
168860b08185Syz for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
168960b08185Syz kp = &ksp->ks_ports[i];
169060b08185Syz if (kp->kp_state != KEYSPAN_PORT_NOT_INIT) {
169160b08185Syz ASSERT(kp->kp_state == KEYSPAN_PORT_CLOSED);
169260b08185Syz
169360b08185Syz mutex_destroy(&kp->kp_mutex);
169460b08185Syz cv_destroy(&kp->kp_tx_cv);
169560b08185Syz usb_free_log_hdl(kp->kp_lh);
169660b08185Syz }
169760b08185Syz }
169860b08185Syz kmem_free(ksp->ks_ports,
169960b08185Syz ksp->ks_dev_spec.port_cnt * sizeof (keyspan_port_t));
170060b08185Syz }
170160b08185Syz
170260b08185Syz static void
keyspan_init_port_params(keyspan_state_t * ksp)170360b08185Syz keyspan_init_port_params(keyspan_state_t *ksp)
170460b08185Syz {
170560b08185Syz int i;
170660b08185Syz size_t sz;
170702dd2108Slg uint_t read_len;
170802dd2108Slg uint_t write_len;
170902dd2108Slg
171002dd2108Slg /* the max data len of every bulk in req. */
171102dd2108Slg if (usb_pipe_get_max_bulk_transfer_size(ksp->ks_dip, &sz) ==
17124ee52f77Slg USB_SUCCESS) {
171302dd2108Slg if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) {
1714d29f5a71Szhigang lu - Sun Microsystems - Beijing China read_len = (uint_t)min(sz, KEYSPAN_BULKIN_MAX_LEN_49WG);
171502dd2108Slg } else {
1716d29f5a71Szhigang lu - Sun Microsystems - Beijing China read_len = (uint_t)min(sz, KEYSPAN_BULKIN_MAX_LEN);
171702dd2108Slg }
171802dd2108Slg } else {
171902dd2108Slg if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) {
172002dd2108Slg read_len = KEYSPAN_BULKIN_MAX_LEN_49WG;
172160b08185Syz } else {
172202dd2108Slg read_len = KEYSPAN_BULKIN_MAX_LEN;
172360b08185Syz }
172402dd2108Slg }
172560b08185Syz
172602dd2108Slg for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
172702dd2108Slg ksp->ks_ports[i].kp_read_len = read_len;
172860b08185Syz /* the max data len of every bulk out req. */
172902dd2108Slg switch (ksp->ks_dev_spec.id_product) {
173002dd2108Slg case KEYSPAN_USA19HS_PID:
173102dd2108Slg ksp->ks_ports[i].kp_write_len =
17324ee52f77Slg KEYSPAN_BULKOUT_MAX_LEN_19HS;
173302dd2108Slg
173402dd2108Slg break;
173502dd2108Slg case KEYSPAN_USA49WLC_PID:
173602dd2108Slg ksp->ks_ports[i].kp_write_len =
17374ee52f77Slg KEYSPAN_BULKOUT_MAX_LEN_49WLC;
173802dd2108Slg
173902dd2108Slg break;
174002dd2108Slg case KEYSPAN_USA49WG_PID:
174102dd2108Slg /*
174202dd2108Slg * USA49WG port0 uses intr out pipe send data while
174302dd2108Slg * other ports use bulk out pipes, so port0's max
174402dd2108Slg * packet length for "bulk out" is different from other
174502dd2108Slg * ports' while the same as USA49WLC.
174602dd2108Slg */
174702dd2108Slg write_len = ((i == 0) ? KEYSPAN_BULKOUT_MAX_LEN_49WLC :
17484ee52f77Slg KEYSPAN_BULKOUT_MAX_LEN_49WG);
174902dd2108Slg ksp->ks_ports[i].kp_write_len = write_len;
175002dd2108Slg
175102dd2108Slg break;
175202dd2108Slg default:
175302dd2108Slg USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
17544ee52f77Slg "keyspan_init_port_params:"
17554ee52f77Slg "the device's product id can't be recognized");
175602dd2108Slg
175702dd2108Slg return;
175802dd2108Slg }
175960b08185Syz }
176060b08185Syz }
176160b08185Syz
176260b08185Syz
176360b08185Syz /*
176460b08185Syz * free descriptor tree
176560b08185Syz */
176660b08185Syz static void
keyspan_free_descr_tree(keyspan_state_t * ksp)176760b08185Syz keyspan_free_descr_tree(keyspan_state_t *ksp)
176860b08185Syz {
176960b08185Syz usb_free_descr_tree(ksp->ks_dip, ksp->ks_dev_data);
177060b08185Syz
177160b08185Syz }
177260b08185Syz
177360b08185Syz
177460b08185Syz /*
177560b08185Syz * register/unregister USB event callbacks
177660b08185Syz */
177760b08185Syz static int
keyspan_register_events(keyspan_state_t * ksp)177860b08185Syz keyspan_register_events(keyspan_state_t *ksp)
177960b08185Syz {
178060b08185Syz return (usb_register_event_cbs(ksp->ks_dip, ksp->ks_usb_events, 0));
178160b08185Syz }
178260b08185Syz
178360b08185Syz
178460b08185Syz static void
keyspan_unregister_events(keyspan_state_t * ksp)178560b08185Syz keyspan_unregister_events(keyspan_state_t *ksp)
178660b08185Syz {
178760b08185Syz usb_unregister_event_cbs(ksp->ks_dip, ksp->ks_usb_events);
178860b08185Syz }
178960b08185Syz
179060b08185Syz
179160b08185Syz static void
keyspan_set_dev_state_online(keyspan_state_t * ksp)179260b08185Syz keyspan_set_dev_state_online(keyspan_state_t *ksp)
179360b08185Syz {
179460b08185Syz ksp->ks_dev_state = USB_DEV_ONLINE;
179560b08185Syz }
179660b08185Syz
179760b08185Syz /*
179802dd2108Slg * send command to the port and save the params after its completion for
179902dd2108Slg * USA19HS and USA49WLC
180060b08185Syz */
180160b08185Syz int
keyspan_send_cmd_usa49(keyspan_port_t * kp)180202dd2108Slg keyspan_send_cmd_usa49(keyspan_port_t *kp)
180360b08185Syz {
180460b08185Syz keyspan_state_t *ksp = kp->kp_ksp;
180560b08185Syz mblk_t *mp;
180660b08185Syz int rval = USB_SUCCESS;
180760b08185Syz int size;
180860b08185Syz usb_bulk_req_t *br;
180960b08185Syz
181060b08185Syz ASSERT(!mutex_owned(&kp->kp_mutex));
181102dd2108Slg USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49");
181260b08185Syz
181360b08185Syz switch (ksp->ks_dev_spec.id_product) {
181460b08185Syz case KEYSPAN_USA19HS_PID:
181560b08185Syz size = sizeof (keyspan_usa19hs_port_ctrl_msg_t);
181660b08185Syz
181760b08185Syz break;
181860b08185Syz
1819c138f478Syz
182060b08185Syz case KEYSPAN_USA49WLC_PID:
182160b08185Syz size = sizeof (keyspan_usa49_port_ctrl_msg_t);
182260b08185Syz
182360b08185Syz break;
1824c138f478Syz
182560b08185Syz default:
182602dd2108Slg USB_DPRINTF_L2(DPRINT_CTLOP, ksp->ks_lh,
18274ee52f77Slg "keyspan_send_cmd_usa49:"
18284ee52f77Slg "the device's product id can't be recognized");
182960b08185Syz return (USB_FAILURE);
183060b08185Syz }
183160b08185Syz
183260b08185Syz if ((mp = allocb(size, BPRI_LO)) == NULL) {
183360b08185Syz
183460b08185Syz return (USB_FAILURE);
183560b08185Syz }
183660b08185Syz bcopy(&kp->kp_ctrl_msg, mp->b_rptr, size);
183760b08185Syz
183860b08185Syz br = usb_alloc_bulk_req(ksp->ks_dip, 0, USB_FLAGS_SLEEP);
183960b08185Syz br->bulk_len = size;
184060b08185Syz br->bulk_data = mp;
184160b08185Syz br->bulk_timeout = KEYSPAN_BULK_TIMEOUT;
184260b08185Syz br->bulk_client_private = (void *)kp;
184360b08185Syz br->bulk_attributes = USB_ATTRS_AUTOCLEARING;
184460b08185Syz
184560b08185Syz rval = usb_pipe_bulk_xfer(ksp->ks_ctrlout_pipe.pipe_handle, br,
184660b08185Syz USB_FLAGS_SLEEP);
184760b08185Syz if (rval == USB_SUCCESS) {
184860b08185Syz mutex_enter(&kp->kp_mutex);
184960b08185Syz keyspan_save_port_params(kp);
185060b08185Syz mutex_exit(&kp->kp_mutex);
185160b08185Syz } else {
185202dd2108Slg USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49"
18534ee52f77Slg ": failure, rval=%d", rval);
185460b08185Syz }
185560b08185Syz
185660b08185Syz usb_free_bulk_req(br);
185760b08185Syz
185860b08185Syz return (rval);
185960b08185Syz }
186060b08185Syz
186102dd2108Slg /*
186202dd2108Slg * send command to the port and save the params after its completion for
186302dd2108Slg * USA_49WG only
186402dd2108Slg */
186502dd2108Slg int
keyspan_send_cmd_usa49wg(keyspan_port_t * kp)186602dd2108Slg keyspan_send_cmd_usa49wg(keyspan_port_t *kp)
186702dd2108Slg {
186802dd2108Slg keyspan_state_t *ksp = kp->kp_ksp;
186902dd2108Slg mblk_t *mp;
187002dd2108Slg int rval = USB_SUCCESS;
1871d29f5a71Szhigang lu - Sun Microsystems - Beijing China uint16_t size = sizeof (keyspan_usa49_port_ctrl_msg_t);
187202dd2108Slg usb_cb_flags_t cb_flags;
187302dd2108Slg usb_cr_t cr;
187402dd2108Slg usb_ctrl_setup_t setup;
187502dd2108Slg
187602dd2108Slg ASSERT(!mutex_owned(&kp->kp_mutex));
187702dd2108Slg USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49wg");
187802dd2108Slg
187902dd2108Slg if ((mp = allocb(size, BPRI_LO)) == NULL) {
188002dd2108Slg
188102dd2108Slg return (USB_FAILURE);
188202dd2108Slg }
188302dd2108Slg bcopy(&kp->kp_ctrl_msg, mp->b_rptr, size);
188402dd2108Slg
188502dd2108Slg setup.bmRequestType = USB_DEV_REQ_TYPE_VENDOR;
188602dd2108Slg setup.bRequest = KEYSPAN_SET_CONTROL_REQUEST;
188702dd2108Slg setup.wValue = 0;
188802dd2108Slg setup.wIndex = 0;
188902dd2108Slg setup.wLength = size;
189002dd2108Slg setup.attrs = 0;
189102dd2108Slg
189202dd2108Slg rval = usb_pipe_ctrl_xfer_wait(ksp->ks_def_pipe.pipe_handle, &setup,
189302dd2108Slg &mp, &cr, &cb_flags, 0);
189402dd2108Slg
189502dd2108Slg if (rval == USB_SUCCESS) {
189602dd2108Slg mutex_enter(&kp->kp_mutex);
189702dd2108Slg keyspan_save_port_params(kp);
189802dd2108Slg mutex_exit(&kp->kp_mutex);
189902dd2108Slg } else {
190002dd2108Slg USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
19014ee52f77Slg "keyspan_send_cmd_usa49wg: failure, rval=%d", rval);
190202dd2108Slg }
190302dd2108Slg if (mp) {
190402dd2108Slg freemsg(mp);
190502dd2108Slg }
190602dd2108Slg
190702dd2108Slg return (rval);
190802dd2108Slg }
190902dd2108Slg
191002dd2108Slg /*
191102dd2108Slg * send command to the port and save the params after its completion
191202dd2108Slg */
191302dd2108Slg int
keyspan_send_cmd(keyspan_port_t * kp)191402dd2108Slg keyspan_send_cmd(keyspan_port_t *kp)
191502dd2108Slg {
191602dd2108Slg keyspan_state_t *ksp = kp->kp_ksp;
191702dd2108Slg int rval = USB_FAILURE;
191802dd2108Slg
191902dd2108Slg switch (ksp->ks_dev_spec.id_product) {
192002dd2108Slg case KEYSPAN_USA19HS_PID:
192102dd2108Slg case KEYSPAN_USA49WLC_PID:
192202dd2108Slg rval = keyspan_send_cmd_usa49(kp);
192302dd2108Slg
192402dd2108Slg break;
192502dd2108Slg case KEYSPAN_USA49WG_PID:
192602dd2108Slg rval = keyspan_send_cmd_usa49wg(kp);
192702dd2108Slg
192802dd2108Slg break;
192902dd2108Slg default:
193002dd2108Slg USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
19314ee52f77Slg "keyspan_send_cmd: "
19324ee52f77Slg "the device's product id can't be recognized");
193302dd2108Slg }
193402dd2108Slg
193502dd2108Slg if (rval != USB_SUCCESS) {
193602dd2108Slg USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
193702dd2108Slg "keyspan_send_cmd() FAILED");
193802dd2108Slg
193902dd2108Slg return (rval);
194002dd2108Slg }
194102dd2108Slg
194202dd2108Slg return (USB_SUCCESS);
194302dd2108Slg
194402dd2108Slg }
194502dd2108Slg
194660b08185Syz /*
194760b08185Syz * hotplug
194860b08185Syz * -------
194960b08185Syz *
195060b08185Syz * restore device state after CPR resume or reconnect
195160b08185Syz */
195260b08185Syz static int
keyspan_restore_device_state(keyspan_state_t * ksp)195360b08185Syz keyspan_restore_device_state(keyspan_state_t *ksp)
195460b08185Syz {
195560b08185Syz int state;
195660b08185Syz
195760b08185Syz mutex_enter(&ksp->ks_mutex);
195860b08185Syz state = ksp->ks_dev_state;
195960b08185Syz mutex_exit(&ksp->ks_mutex);
196060b08185Syz
196160b08185Syz if ((state != USB_DEV_DISCONNECTED) && (state != USB_DEV_SUSPENDED)) {
196260b08185Syz
196360b08185Syz return (state);
196460b08185Syz }
196560b08185Syz
1966d291d9f2Sfrits if (usb_check_same_device(ksp->ks_dip, ksp->ks_lh, USB_LOG_L0,
196760b08185Syz DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) {
196860b08185Syz mutex_enter(&ksp->ks_mutex);
196960b08185Syz state = ksp->ks_dev_state = USB_DEV_DISCONNECTED;
197060b08185Syz mutex_exit(&ksp->ks_mutex);
197160b08185Syz
197260b08185Syz return (state);
197360b08185Syz }
197460b08185Syz
197560b08185Syz if (state == USB_DEV_DISCONNECTED) {
197660b08185Syz USB_DPRINTF_L0(DPRINT_HOTPLUG, ksp->ks_lh,
197760b08185Syz "device has been reconnected but data may have been lost");
197860b08185Syz }
197960b08185Syz
198060b08185Syz if (keyspan_reconnect_pipes(ksp) != USB_SUCCESS) {
198160b08185Syz
198260b08185Syz return (state);
198360b08185Syz }
198460b08185Syz
198560b08185Syz /*
198660b08185Syz * init device state
198760b08185Syz */
198860b08185Syz mutex_enter(&ksp->ks_mutex);
198960b08185Syz state = ksp->ks_dev_state = USB_DEV_ONLINE;
199002dd2108Slg ksp->ks_reconnect_flag = 1;
199160b08185Syz mutex_exit(&ksp->ks_mutex);
199260b08185Syz
199360b08185Syz /*
199460b08185Syz * now restore each open port
199560b08185Syz */
199660b08185Syz (void) keyspan_restore_ports_state(ksp);
199760b08185Syz
199860b08185Syz return (state);
199960b08185Syz }
200060b08185Syz
200160b08185Syz /*
200260b08185Syz * restore ports state after CPR resume or reconnect
200360b08185Syz */
200460b08185Syz static int
keyspan_restore_ports_state(keyspan_state_t * ksp)200560b08185Syz keyspan_restore_ports_state(keyspan_state_t *ksp)
200660b08185Syz {
200760b08185Syz keyspan_port_t *kp;
200860b08185Syz int rval = USB_SUCCESS;
200960b08185Syz int err;
201060b08185Syz int i;
201160b08185Syz
201260b08185Syz for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
201360b08185Syz kp = &ksp->ks_ports[i];
201460b08185Syz /*
201560b08185Syz * only care about open ports
201660b08185Syz */
201760b08185Syz mutex_enter(&kp->kp_mutex);
201860b08185Syz if (kp->kp_state != KEYSPAN_PORT_OPEN) {
201960b08185Syz mutex_exit(&kp->kp_mutex);
202060b08185Syz continue;
202160b08185Syz }
202260b08185Syz mutex_exit(&kp->kp_mutex);
202360b08185Syz
202460b08185Syz sema_p(&ksp->ks_pipes_sema);
202560b08185Syz /* open hardware serial port */
202660b08185Syz err = keyspan_open_hw_port(kp, B_FALSE);
202760b08185Syz sema_v(&ksp->ks_pipes_sema);
202860b08185Syz if (err != USB_SUCCESS) {
202960b08185Syz USB_DPRINTF_L2(DPRINT_HOTPLUG, kp->kp_lh,
203060b08185Syz "keyspan_restore_ports_state: failed");
203160b08185Syz rval = err;
203260b08185Syz }
203360b08185Syz }
203460b08185Syz
203560b08185Syz return (rval);
203660b08185Syz }
203760b08185Syz
203860b08185Syz
203960b08185Syz /*
204060b08185Syz * power management
204160b08185Syz * ----------------
204260b08185Syz *
204360b08185Syz *
204460b08185Syz * create PM components
204560b08185Syz */
204660b08185Syz static int
keyspan_create_pm_components(keyspan_state_t * ksp)204760b08185Syz keyspan_create_pm_components(keyspan_state_t *ksp)
204860b08185Syz {
204960b08185Syz dev_info_t *dip = ksp->ks_dip;
205060b08185Syz keyspan_pm_t *pm;
205160b08185Syz uint_t pwr_states;
205260b08185Syz
205360b08185Syz pm = ksp->ks_pm = kmem_zalloc(sizeof (keyspan_pm_t), KM_SLEEP);
205460b08185Syz pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
205560b08185Syz
205660b08185Syz if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) {
205760b08185Syz USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh,
205860b08185Syz "keyspan_create_pm_components: failed");
205960b08185Syz
206060b08185Syz return (USB_SUCCESS);
206160b08185Syz }
206260b08185Syz
206360b08185Syz pm->pm_wakeup_enabled = (usb_handle_remote_wakeup(dip,
20644ee52f77Slg USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS);
206560b08185Syz pm->pm_pwr_states = (uint8_t)pwr_states;
206660b08185Syz
206760b08185Syz (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
206860b08185Syz
206960b08185Syz return (USB_SUCCESS);
207060b08185Syz }
207160b08185Syz
207260b08185Syz
207360b08185Syz /*
207460b08185Syz * destroy PM components
207560b08185Syz */
207660b08185Syz static void
keyspan_destroy_pm_components(keyspan_state_t * ksp)207760b08185Syz keyspan_destroy_pm_components(keyspan_state_t *ksp)
207860b08185Syz {
207960b08185Syz keyspan_pm_t *pm = ksp->ks_pm;
208060b08185Syz dev_info_t *dip = ksp->ks_dip;
208160b08185Syz int rval;
208260b08185Syz
208360b08185Syz if (ksp->ks_dev_state != USB_DEV_DISCONNECTED) {
208460b08185Syz if (pm->pm_wakeup_enabled) {
208560b08185Syz (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
208660b08185Syz
208760b08185Syz rval = usb_handle_remote_wakeup(dip,
208860b08185Syz USB_REMOTE_WAKEUP_DISABLE);
208960b08185Syz if (rval != USB_SUCCESS) {
209060b08185Syz USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh,
209160b08185Syz "keyspan_destroy_pm_components: disable "
209260b08185Syz "remote wakeup failed, rval=%d", rval);
209360b08185Syz }
209460b08185Syz }
209560b08185Syz
209660b08185Syz (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
209760b08185Syz }
209860b08185Syz kmem_free(pm, sizeof (keyspan_pm_t));
209960b08185Syz ksp->ks_pm = NULL;
210060b08185Syz }
210160b08185Syz
210260b08185Syz
210360b08185Syz /*
210460b08185Syz * mark device busy and raise power
210560b08185Syz */
210660b08185Syz static int
keyspan_pm_set_busy(keyspan_state_t * ksp)210760b08185Syz keyspan_pm_set_busy(keyspan_state_t *ksp)
210860b08185Syz {
210960b08185Syz keyspan_pm_t *pm = ksp->ks_pm;
211060b08185Syz dev_info_t *dip = ksp->ks_dip;
211160b08185Syz
211260b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_busy");
211360b08185Syz
211460b08185Syz mutex_enter(&ksp->ks_mutex);
211560b08185Syz /* if already marked busy, just increment the counter */
211660b08185Syz if (pm->pm_busy_cnt++ > 0) {
211760b08185Syz USB_DPRINTF_L3(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_busy:"
211860b08185Syz "already busy, busy_cnt = %d", pm->pm_busy_cnt);
211960b08185Syz mutex_exit(&ksp->ks_mutex);
212060b08185Syz
212160b08185Syz return (USB_SUCCESS);
212260b08185Syz }
212360b08185Syz
212460b08185Syz (void) pm_busy_component(dip, 0);
212560b08185Syz
212660b08185Syz if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) {
212760b08185Syz mutex_exit(&ksp->ks_mutex);
212860b08185Syz
212960b08185Syz return (USB_SUCCESS);
213060b08185Syz }
213160b08185Syz
213260b08185Syz /* need to raise power */
213360b08185Syz pm->pm_raise_power = B_TRUE;
213460b08185Syz mutex_exit(&ksp->ks_mutex);
213560b08185Syz
213660b08185Syz USB_DPRINTF_L3(DPRINT_PM, ksp->ks_lh,
213760b08185Syz "keyspan_pm_set_busy: raise power");
213860b08185Syz (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
213960b08185Syz
214060b08185Syz mutex_enter(&ksp->ks_mutex);
214160b08185Syz pm->pm_raise_power = B_FALSE;
214260b08185Syz mutex_exit(&ksp->ks_mutex);
214360b08185Syz
214460b08185Syz return (USB_SUCCESS);
214560b08185Syz }
214660b08185Syz
214760b08185Syz
214860b08185Syz /*
214960b08185Syz * mark device idle
215060b08185Syz */
215160b08185Syz static void
keyspan_pm_set_idle(keyspan_state_t * ksp)215260b08185Syz keyspan_pm_set_idle(keyspan_state_t *ksp)
215360b08185Syz {
215460b08185Syz keyspan_pm_t *pm = ksp->ks_pm;
215560b08185Syz dev_info_t *dip = ksp->ks_dip;
215660b08185Syz
215760b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_idle");
215860b08185Syz
215960b08185Syz /*
216060b08185Syz * if more ports use the device, do not mark as yet
216160b08185Syz */
216260b08185Syz mutex_enter(&ksp->ks_mutex);
216360b08185Syz if (--pm->pm_busy_cnt > 0) {
216460b08185Syz mutex_exit(&ksp->ks_mutex);
216560b08185Syz
216660b08185Syz return;
216760b08185Syz }
216860b08185Syz
216960b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_idle: set idle");
217060b08185Syz (void) pm_idle_component(dip, 0);
217160b08185Syz
217260b08185Syz mutex_exit(&ksp->ks_mutex);
217360b08185Syz }
217460b08185Syz
217560b08185Syz
217660b08185Syz /*
217760b08185Syz * Functions to handle power transition for OS levels 0 -> 3
217860b08185Syz */
217960b08185Syz static int
keyspan_pwrlvl0(keyspan_state_t * ksp)218060b08185Syz keyspan_pwrlvl0(keyspan_state_t *ksp)
218160b08185Syz {
218260b08185Syz int rval;
218302dd2108Slg keyspan_pipe_t *statin = &ksp->ks_statin_pipe;
218460b08185Syz
218560b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl0");
218660b08185Syz
218760b08185Syz switch (ksp->ks_dev_state) {
218860b08185Syz case USB_DEV_ONLINE:
218960b08185Syz /* issue USB D3 command to the device */
219060b08185Syz rval = usb_set_device_pwrlvl3(ksp->ks_dip);
219160b08185Syz ASSERT(rval == USB_SUCCESS);
219202dd2108Slg
219302dd2108Slg if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) {
219402dd2108Slg mutex_exit(&ksp->ks_mutex);
219502dd2108Slg usb_pipe_stop_intr_polling(statin->pipe_handle,
21964ee52f77Slg USB_FLAGS_SLEEP);
219702dd2108Slg mutex_enter(&ksp->ks_mutex);
219802dd2108Slg
219902dd2108Slg mutex_enter(&statin->pipe_mutex);
220002dd2108Slg statin->pipe_state = KEYSPAN_PIPE_CLOSED;
220102dd2108Slg mutex_exit(&statin->pipe_mutex);
220202dd2108Slg }
220360b08185Syz ksp->ks_dev_state = USB_DEV_PWRED_DOWN;
220460b08185Syz ksp->ks_pm->pm_cur_power = USB_DEV_OS_PWR_OFF;
220560b08185Syz
220660b08185Syz /* FALLTHRU */
220760b08185Syz case USB_DEV_DISCONNECTED:
220860b08185Syz case USB_DEV_SUSPENDED:
220960b08185Syz /* allow a disconnect/cpr'ed device to go to lower power */
221060b08185Syz
221160b08185Syz return (USB_SUCCESS);
221260b08185Syz case USB_DEV_PWRED_DOWN:
221360b08185Syz default:
221460b08185Syz USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh,
221560b08185Syz "keyspan_pwrlvl0: illegal device state");
221660b08185Syz
221760b08185Syz return (USB_FAILURE);
221860b08185Syz }
221960b08185Syz }
222060b08185Syz
222160b08185Syz
222260b08185Syz static int
keyspan_pwrlvl1(keyspan_state_t * ksp)222360b08185Syz keyspan_pwrlvl1(keyspan_state_t *ksp)
222460b08185Syz {
222560b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl1");
222660b08185Syz
222760b08185Syz /* issue USB D2 command to the device */
222860b08185Syz (void) usb_set_device_pwrlvl2(ksp->ks_dip);
222960b08185Syz
223060b08185Syz return (USB_FAILURE);
223160b08185Syz }
223260b08185Syz
223360b08185Syz
223460b08185Syz static int
keyspan_pwrlvl2(keyspan_state_t * ksp)223560b08185Syz keyspan_pwrlvl2(keyspan_state_t *ksp)
223660b08185Syz {
223760b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl2");
223860b08185Syz
223960b08185Syz /* issue USB D1 command to the device */
224060b08185Syz (void) usb_set_device_pwrlvl1(ksp->ks_dip);
224160b08185Syz
224260b08185Syz return (USB_FAILURE);
224360b08185Syz }
224460b08185Syz
224560b08185Syz
224660b08185Syz static int
keyspan_pwrlvl3(keyspan_state_t * ksp)224760b08185Syz keyspan_pwrlvl3(keyspan_state_t *ksp)
224860b08185Syz {
224960b08185Syz int rval;
225060b08185Syz
225160b08185Syz USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl3");
225260b08185Syz
225360b08185Syz switch (ksp->ks_dev_state) {
225460b08185Syz case USB_DEV_PWRED_DOWN:
225560b08185Syz /* Issue USB D0 command to the device here */
225660b08185Syz rval = usb_set_device_pwrlvl0(ksp->ks_dip);
225760b08185Syz ASSERT(rval == USB_SUCCESS);
225802dd2108Slg
225902dd2108Slg if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) {
226002dd2108Slg mutex_exit(&ksp->ks_mutex);
226102dd2108Slg keyspan_pipe_start_polling(&ksp->ks_statin_pipe);
226202dd2108Slg mutex_enter(&ksp->ks_mutex);
226302dd2108Slg }
226402dd2108Slg
226560b08185Syz ksp->ks_dev_state = USB_DEV_ONLINE;
226660b08185Syz ksp->ks_pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
226760b08185Syz
226860b08185Syz /* FALLTHRU */
226960b08185Syz case USB_DEV_ONLINE:
227060b08185Syz /* we are already in full power */
227160b08185Syz
227260b08185Syz /* FALLTHRU */
227360b08185Syz case USB_DEV_DISCONNECTED:
227460b08185Syz case USB_DEV_SUSPENDED:
227560b08185Syz
227660b08185Syz return (USB_SUCCESS);
227760b08185Syz default:
227860b08185Syz USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh,
227960b08185Syz "keyspan_pwrlvl3: illegal device state");
228060b08185Syz
228160b08185Syz return (USB_FAILURE);
228260b08185Syz }
228360b08185Syz }
228460b08185Syz
228560b08185Syz
228660b08185Syz /*
228760b08185Syz * pipe operations
228860b08185Syz * ---------------
228960b08185Syz *
229060b08185Syz * XXX keyspan seem to malfunction after the pipes are closed
229160b08185Syz * and reopened again (does not respond to OPEN_PORT command).
229260b08185Syz * so we open them once in attach
229360b08185Syz */
229460b08185Syz static int
keyspan_attach_pipes(keyspan_state_t * ksp)229560b08185Syz keyspan_attach_pipes(keyspan_state_t *ksp)
229660b08185Syz {
229760b08185Syz return (keyspan_open_dev_pipes(ksp));
229860b08185Syz }
229960b08185Syz
230060b08185Syz void
keyspan_detach_pipes(keyspan_state_t * ksp)230160b08185Syz keyspan_detach_pipes(keyspan_state_t *ksp)
230260b08185Syz {
230360b08185Syz
230460b08185Syz /*
230560b08185Syz * Blow away status bulk in requests or
230660b08185Syz * pipe close will wait until timeout.
230760b08185Syz */
230860b08185Syz if (ksp->ks_statin_pipe.pipe_handle) {
230902dd2108Slg usb_pipe_stop_intr_polling(ksp->ks_statin_pipe.pipe_handle,
23104ee52f77Slg USB_FLAGS_SLEEP);
231160b08185Syz }
231260b08185Syz
231360b08185Syz /* Close the globle pipes */
231460b08185Syz keyspan_close_dev_pipes(ksp);
231560b08185Syz }
231660b08185Syz
231760b08185Syz
231860b08185Syz /*
231960b08185Syz * during device disconnect/suspend, close pipes if they are open.
232060b08185Syz */
232160b08185Syz static void
keyspan_disconnect_pipes(keyspan_state_t * ksp)232260b08185Syz keyspan_disconnect_pipes(keyspan_state_t *ksp)
232360b08185Syz {
232460b08185Syz sema_p(&ksp->ks_pipes_sema);
232560b08185Syz keyspan_close_pipes(ksp);
232660b08185Syz sema_v(&ksp->ks_pipes_sema);
232760b08185Syz }
232860b08185Syz
232960b08185Syz
233060b08185Syz /*
233160b08185Syz * during device reconnect/resume, reopen pipes if they were open.
233260b08185Syz */
233360b08185Syz static int
keyspan_reconnect_pipes(keyspan_state_t * ksp)233460b08185Syz keyspan_reconnect_pipes(keyspan_state_t *ksp)
233560b08185Syz {
233660b08185Syz int rval = USB_SUCCESS;
233760b08185Syz
233860b08185Syz sema_p(&ksp->ks_pipes_sema);
233960b08185Syz rval = keyspan_reopen_pipes(ksp);
234060b08185Syz sema_v(&ksp->ks_pipes_sema);
234160b08185Syz
234260b08185Syz return (rval);
234360b08185Syz }
234460b08185Syz
234560b08185Syz /*
234660b08185Syz * data transfer routines
234760b08185Syz * ----------------------
234860b08185Syz *
234960b08185Syz *
235060b08185Syz * start data transmit
235160b08185Syz */
235260b08185Syz void
keyspan_tx_start(keyspan_port_t * kp,int * xferd)235360b08185Syz keyspan_tx_start(keyspan_port_t *kp, int *xferd)
235460b08185Syz {
235560b08185Syz keyspan_state_t *ksp = kp->kp_ksp;
235660b08185Syz int len; /* # of bytes we can transmit */
235760b08185Syz mblk_t *data; /* data to be transmitted */
235802dd2108Slg int data_len = 0; /* # of bytes in 'data' */
235902dd2108Slg int tran_len;
236060b08185Syz int rval;
236102dd2108Slg int status_len = 0;
236260b08185Syz
236360b08185Syz ASSERT(!mutex_owned(&ksp->ks_mutex));
236460b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
236560b08185Syz ASSERT(kp->kp_state != KEYSPAN_PORT_CLOSED);
236660b08185Syz
236760b08185Syz USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start");
236860b08185Syz
236960b08185Syz if (xferd) {
237060b08185Syz *xferd = 0;
237160b08185Syz }
237260b08185Syz if ((kp->kp_flags & KEYSPAN_PORT_TX_STOPPED) ||
237360b08185Syz (kp->kp_tx_mp == NULL)) {
237460b08185Syz
237560b08185Syz return;
237660b08185Syz }
237760b08185Syz
237860b08185Syz len = min(msgdsize(kp->kp_tx_mp), kp->kp_write_len);
237960b08185Syz USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start:"
238060b08185Syz "len = %d, tx_mp_len = %d", len, (int)msgdsize(kp->kp_tx_mp));
238160b08185Syz
238260b08185Syz mutex_exit(&kp->kp_mutex);
238360b08185Syz
238460b08185Syz /*
238560b08185Syz * Some keyspan adapters, such as usa49wlc,
238660b08185Syz * need use the first byte as flag.
238760b08185Syz */
238860b08185Syz switch (ksp->ks_dev_spec.id_product) {
238960b08185Syz case KEYSPAN_USA19HS_PID:
239060b08185Syz
239160b08185Syz if ((data = allocb(len, BPRI_LO)) == NULL) {
239260b08185Syz mutex_enter(&kp->kp_mutex);
239360b08185Syz
239460b08185Syz return;
239560b08185Syz }
239660b08185Syz mutex_enter(&kp->kp_mutex);
239760b08185Syz
239802dd2108Slg /* copy at most 'len' bytes from mblk chain for transmission */
239902dd2108Slg data_len = keyspan_tx_copy_data(kp, data, len);
240002dd2108Slg if (data_len <= 0) {
240102dd2108Slg USB_DPRINTF_L3(DPRINT_OUT_PIPE, kp->kp_lh,
24024ee52f77Slg "keyspan_tx_start:keyspan_tx_copy_data copied"
24034ee52f77Slg " zero bytes");
240402dd2108Slg }
240560b08185Syz
240602dd2108Slg break;
2407c138f478Syz
240860b08185Syz case KEYSPAN_USA49WLC_PID:
240902dd2108Slg case KEYSPAN_USA49WG_PID:
241002dd2108Slg status_len = len / 64 + 1;
241102dd2108Slg if ((data = allocb(len + status_len, BPRI_LO)) == NULL) {
241260b08185Syz mutex_enter(&kp->kp_mutex);
241360b08185Syz
241402dd2108Slg return;
241502dd2108Slg }
241602dd2108Slg mutex_enter(&kp->kp_mutex);
241702dd2108Slg /*
241802dd2108Slg * the data format is [status byte][63 data bytes][...][status]
241902dd2108Slg * byte][up to 63 bytes] according to keyspan spec
242002dd2108Slg */
242102dd2108Slg while (data_len < len) {
242202dd2108Slg /* Add status byte per 63 data bytes */
242302dd2108Slg *(data->b_wptr++) = 0;
242402dd2108Slg /* copy at most 63 bytes from mblk chain for trans */
242502dd2108Slg tran_len = keyspan_tx_copy_data(kp, data, 63);
242602dd2108Slg if (tran_len <= 0) {
242702dd2108Slg USB_DPRINTF_L3(DPRINT_OUT_PIPE, kp->kp_lh,
24284ee52f77Slg "keyspan_tx_start:keyspan_tx_copy_data"
24294ee52f77Slg " copied zero bytes");
243002dd2108Slg
243102dd2108Slg break;
243260b08185Syz }
243302dd2108Slg data_len += tran_len;
243460b08185Syz }
243560b08185Syz
243660b08185Syz break;
243760b08185Syz default:
243860b08185Syz
243960b08185Syz mutex_enter(&kp->kp_mutex);
244060b08185Syz USB_DPRINTF_L2(DPRINT_OUT_PIPE, ksp->ks_lh, "keyspan_tx_start:"
244160b08185Syz "the device's product id can't be recognized");
244260b08185Syz
244360b08185Syz return;
244460b08185Syz }
244560b08185Syz
244602dd2108Slg mutex_exit(&kp->kp_mutex);
244760b08185Syz
244802dd2108Slg /*
244902dd2108Slg * For USA-49WG, the port0 uses intr out pipe as data out pipe, while
245002dd2108Slg * other ports use bulk out pipe.
245102dd2108Slg */
245202dd2108Slg
245302dd2108Slg if ((kp->kp_port_num == 0) &&
24544ee52f77Slg (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID)) {
245502dd2108Slg rval = keyspan_send_data_port0(&kp->kp_dataout_pipe, &data, kp);
245602dd2108Slg } else {
245702dd2108Slg rval = keyspan_send_data(&kp->kp_dataout_pipe, &data, kp);
245860b08185Syz }
245960b08185Syz mutex_enter(&kp->kp_mutex);
246060b08185Syz
246160b08185Syz /*
246260b08185Syz * if send failed, put data back
246360b08185Syz */
246460b08185Syz if (rval != USB_SUCCESS) {
246560b08185Syz ASSERT(data);
246660b08185Syz keyspan_put_head(&kp->kp_tx_mp, data, kp);
246760b08185Syz } else if (xferd) {
246860b08185Syz *xferd = data_len;
246960b08185Syz }
247060b08185Syz
247160b08185Syz USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start[%d]: over"
247260b08185Syz "(%d) rval=%d", kp->kp_port_num, data_len, rval);
247360b08185Syz
247460b08185Syz }
247560b08185Syz
247660b08185Syz
247760b08185Syz /*
247860b08185Syz * copy no more than 'len' bytes from mblk chain to transmit mblk 'data'.
247960b08185Syz * return number of bytes copied
248060b08185Syz */
248160b08185Syz int
keyspan_tx_copy_data(keyspan_port_t * kp,mblk_t * data,int len)248260b08185Syz keyspan_tx_copy_data(keyspan_port_t *kp, mblk_t *data, int len)
248360b08185Syz {
248460b08185Syz mblk_t *mp; /* current msgblk */
248560b08185Syz int copylen; /* # of bytes to copy from 'mp' to 'data' */
248660b08185Syz int data_len = 0;
248760b08185Syz
248860b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
248960b08185Syz
2490688b07c5Sgc if (msgdsize(kp->kp_tx_mp) == 0) {
2491688b07c5Sgc data->b_wptr = data->b_rptr;
2492688b07c5Sgc freeb(kp->kp_tx_mp);
2493688b07c5Sgc kp->kp_tx_mp = NULL;
2494688b07c5Sgc
2495688b07c5Sgc return (data_len);
2496688b07c5Sgc }
2497688b07c5Sgc
249860b08185Syz while ((data_len < len) && kp->kp_tx_mp) {
249960b08185Syz mp = kp->kp_tx_mp;
250060b08185Syz copylen = min(MBLKL(mp), len - data_len);
250160b08185Syz bcopy(mp->b_rptr, data->b_wptr, copylen);
250260b08185Syz
250360b08185Syz mp->b_rptr += copylen;
250460b08185Syz data->b_wptr += copylen;
250560b08185Syz data_len += copylen;
250660b08185Syz
250722eb7cb5Sgd if (MBLKL(mp) < 1) {
250860b08185Syz kp->kp_tx_mp = unlinkb(mp);
250960b08185Syz freeb(mp);
251060b08185Syz } else {
251160b08185Syz ASSERT(data_len == len);
251260b08185Syz }
251360b08185Syz }
251460b08185Syz USB_DPRINTF_L3(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_tx_copy_data:"
251560b08185Syz "copied data_len = %d", data_len);
251660b08185Syz
251760b08185Syz return (data_len);
251860b08185Syz }
251960b08185Syz
252060b08185Syz
252160b08185Syz /*
252260b08185Syz * wait until local tx buffer drains.
252360b08185Syz * 'timeout' is in seconds, zero means wait forever
252460b08185Syz */
252560b08185Syz static int
keyspan_wait_tx_drain(keyspan_port_t * kp,int timeout)252660b08185Syz keyspan_wait_tx_drain(keyspan_port_t *kp, int timeout)
252760b08185Syz {
252860b08185Syz clock_t until;
252960b08185Syz int over = 0;
253060b08185Syz
253160b08185Syz USB_DPRINTF_L4(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_wait_tx_drain:"
253260b08185Syz "timeout = %d", timeout);
253360b08185Syz until = ddi_get_lbolt() + drv_usectohz(1000000 * timeout);
253460b08185Syz
253560b08185Syz while (kp->kp_tx_mp && !over) {
253660b08185Syz if (timeout > 0) {
253760b08185Syz over = (cv_timedwait_sig(&kp->kp_tx_cv,
25384ee52f77Slg &kp->kp_mutex, until) <= 0);
253960b08185Syz } else {
254060b08185Syz over = (cv_wait_sig(&kp->kp_tx_cv, &kp->kp_mutex) == 0);
254160b08185Syz }
254260b08185Syz }
254360b08185Syz
254460b08185Syz return ((kp->kp_tx_mp == NULL) ? USB_SUCCESS : USB_FAILURE);
254560b08185Syz }
254660b08185Syz
254760b08185Syz /*
254860b08185Syz * returns 0 if device is not online, != 0 otherwise
254960b08185Syz */
255060b08185Syz int
keyspan_dev_is_online(keyspan_state_t * ksp)255160b08185Syz keyspan_dev_is_online(keyspan_state_t *ksp)
255260b08185Syz {
255360b08185Syz int rval;
255460b08185Syz
255560b08185Syz mutex_enter(&ksp->ks_mutex);
255660b08185Syz rval = (ksp->ks_dev_state == USB_DEV_ONLINE);
255760b08185Syz mutex_exit(&ksp->ks_mutex);
255860b08185Syz
255960b08185Syz return (rval);
256060b08185Syz }
256160b08185Syz
256260b08185Syz /*
256360b08185Syz * link a message block to tail of message
256460b08185Syz * account for the case when message is null
256560b08185Syz */
256660b08185Syz void
keyspan_put_tail(mblk_t ** mpp,mblk_t * bp)256760b08185Syz keyspan_put_tail(mblk_t **mpp, mblk_t *bp)
256860b08185Syz {
256960b08185Syz if (*mpp) {
257060b08185Syz linkb(*mpp, bp);
257160b08185Syz } else {
257260b08185Syz *mpp = bp;
257360b08185Syz }
257460b08185Syz }
257560b08185Syz
257660b08185Syz /*
257760b08185Syz * put a message block at the head of the message
257860b08185Syz * account for the case when message is null
257960b08185Syz */
258060b08185Syz void
keyspan_put_head(mblk_t ** mpp,mblk_t * bp,keyspan_port_t * kp)258160b08185Syz keyspan_put_head(mblk_t **mpp, mblk_t *bp, keyspan_port_t *kp)
258260b08185Syz {
258360b08185Syz switch (kp->kp_ksp->ks_dev_spec.id_product) {
258460b08185Syz case KEYSPAN_USA19HS_PID:
258560b08185Syz if (*mpp) {
258660b08185Syz linkb(bp, *mpp);
258760b08185Syz }
258860b08185Syz *mpp = bp;
258960b08185Syz
259060b08185Syz break;
259160b08185Syz
2592c138f478Syz
259360b08185Syz case KEYSPAN_USA49WLC_PID:
259402dd2108Slg case KEYSPAN_USA49WG_PID:
259560b08185Syz
259660b08185Syz /* get rid of the first byte of the msg data which is a flag */
259760b08185Syz if (*mpp) {
259860b08185Syz linkb(bp, *mpp);
259960b08185Syz }
260060b08185Syz bp->b_rptr = bp->b_datap->db_base + 1;
260160b08185Syz *mpp = bp;
260260b08185Syz
260360b08185Syz break;
2604c138f478Syz
260560b08185Syz default:
260660b08185Syz USB_DPRINTF_L2(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_put_head:"
260760b08185Syz "the device's product id can't be recognized");
260860b08185Syz
260960b08185Syz return;
261060b08185Syz }
261160b08185Syz
261260b08185Syz }
261360b08185Syz
261460b08185Syz /*
261560b08185Syz * Set the port parameters to default values
261660b08185Syz */
261760b08185Syz static void
keyspan_default_port_params(keyspan_port_t * kp)261860b08185Syz keyspan_default_port_params(keyspan_port_t *kp)
261960b08185Syz {
262060b08185Syz keyspan_state_t *ksp = kp->kp_ksp;
262160b08185Syz
262260b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
262360b08185Syz
262460b08185Syz switch (ksp->ks_dev_spec.id_product) {
262560b08185Syz case KEYSPAN_USA19HS_PID:
262660b08185Syz keyspan_default_port_params_usa19hs(kp);
262760b08185Syz
262860b08185Syz break;
262960b08185Syz
2630c138f478Syz
263160b08185Syz case KEYSPAN_USA49WLC_PID:
263202dd2108Slg case KEYSPAN_USA49WG_PID:
263360b08185Syz keyspan_default_port_params_usa49(kp);
263460b08185Syz
263560b08185Syz break;
2636c138f478Syz
263760b08185Syz default:
263860b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
263960b08185Syz "keyspan_default_port_params:"
264060b08185Syz "the device's product id can't be recognized");
264160b08185Syz }
264260b08185Syz
264360b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
264460b08185Syz "keyspan_default_port_params: setted.");
264560b08185Syz }
264660b08185Syz
264760b08185Syz /*
264860b08185Syz * Build the command message according to the params from usbser.
264960b08185Syz * The message will then be sent to deivce by keyspan_send_cmd.
265060b08185Syz */
265160b08185Syz static void
keyspan_build_cmd_msg(keyspan_port_t * kp,ds_port_params_t * tp)265260b08185Syz keyspan_build_cmd_msg(keyspan_port_t *kp, ds_port_params_t *tp)
265360b08185Syz {
265460b08185Syz keyspan_state_t *ksp = kp->kp_ksp;
265560b08185Syz
265660b08185Syz switch (ksp->ks_dev_spec.id_product) {
265760b08185Syz case KEYSPAN_USA19HS_PID:
265860b08185Syz keyspan_build_cmd_msg_usa19hs(kp, tp);
265960b08185Syz
266060b08185Syz break;
266160b08185Syz
2662c138f478Syz
266360b08185Syz case KEYSPAN_USA49WLC_PID:
266402dd2108Slg case KEYSPAN_USA49WG_PID:
266560b08185Syz keyspan_build_cmd_msg_usa49(kp, tp);
266660b08185Syz
266760b08185Syz break;
2668c138f478Syz
266960b08185Syz default:
267060b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
267160b08185Syz "keyspan_build_cmd_msg:"
267260b08185Syz "the device's product id can't be recognized");
267360b08185Syz }
267460b08185Syz }
267560b08185Syz
267660b08185Syz /* save the port params after send cmd successfully */
267760b08185Syz static void
keyspan_save_port_params(keyspan_port_t * kp)267860b08185Syz keyspan_save_port_params(keyspan_port_t *kp)
267960b08185Syz {
268060b08185Syz keyspan_state_t *ksp = kp->kp_ksp;
268160b08185Syz
268260b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
268360b08185Syz
268460b08185Syz switch (ksp->ks_dev_spec.id_product) {
268560b08185Syz case KEYSPAN_USA19HS_PID:
268660b08185Syz keyspan_save_port_params_usa19hs(kp);
268760b08185Syz
268860b08185Syz break;
268960b08185Syz
2690c138f478Syz
269160b08185Syz case KEYSPAN_USA49WLC_PID:
269202dd2108Slg case KEYSPAN_USA49WG_PID:
269360b08185Syz keyspan_save_port_params_usa49(kp);
269460b08185Syz
269560b08185Syz break;
2696c138f478Syz
269760b08185Syz default:
269860b08185Syz USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
269960b08185Syz "keyspan_save_port_params:"
270060b08185Syz "the device's product id can't be recognized");
270160b08185Syz }
270260b08185Syz
270360b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
270460b08185Syz "keyspan_save_port_params: baud = %x, lcr = %x,"
270560b08185Syz "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag);
270660b08185Syz
270760b08185Syz }
270860b08185Syz
270960b08185Syz /* save the port params after send cmd successfully */
271060b08185Syz static void
keyspan_save_port_params_usa19hs(keyspan_port_t * kp)271160b08185Syz keyspan_save_port_params_usa19hs(keyspan_port_t *kp)
271260b08185Syz {
271360b08185Syz keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs);
271460b08185Syz
271560b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
271660b08185Syz
271760b08185Syz if (ctrl_msg->setClocking) {
271860b08185Syz kp->kp_baud = ctrl_msg->baudHi;
271960b08185Syz kp->kp_baud = (kp->kp_baud << 8);
272060b08185Syz kp->kp_baud |= ctrl_msg->baudLo;
272160b08185Syz }
272260b08185Syz if (ctrl_msg->setLcr) {
272360b08185Syz kp->kp_lcr = ctrl_msg->lcr;
272460b08185Syz }
272560b08185Syz if (ctrl_msg->setRts) {
272660b08185Syz if (ctrl_msg->rts) {
272760b08185Syz kp->kp_status_flag |= KEYSPAN_PORT_RTS;
272860b08185Syz } else {
272960b08185Syz kp->kp_status_flag &= ~KEYSPAN_PORT_RTS;
273060b08185Syz }
273160b08185Syz }
273260b08185Syz if (ctrl_msg->setDtr) {
273360b08185Syz if (ctrl_msg->dtr) {
273460b08185Syz kp->kp_status_flag |= KEYSPAN_PORT_DTR;
273560b08185Syz } else {
273660b08185Syz kp->kp_status_flag &= ~KEYSPAN_PORT_DTR;
273760b08185Syz }
273860b08185Syz }
273960b08185Syz
274060b08185Syz if (ctrl_msg->portEnabled) {
274160b08185Syz kp->kp_status_flag |= KEYSPAN_PORT_ENABLE;
274260b08185Syz } else {
274360b08185Syz kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE;
274460b08185Syz }
274560b08185Syz
274660b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
274760b08185Syz "keyspan_save_port_params: baud = %x, lcr = %x,"
274860b08185Syz "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag);
274960b08185Syz
275060b08185Syz }
275160b08185Syz
275260b08185Syz /*
275360b08185Syz * Set the port parameters to default values
275460b08185Syz */
275560b08185Syz static void
keyspan_default_port_params_usa19hs(keyspan_port_t * kp)275660b08185Syz keyspan_default_port_params_usa19hs(keyspan_port_t *kp)
275760b08185Syz {
275860b08185Syz keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs);
275960b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
276060b08185Syz
276160b08185Syz keyspan_build_cmd_msg(kp, NULL);
276260b08185Syz
276360b08185Syz ctrl_msg->setRts = 0x01;
276460b08185Syz ctrl_msg->rts = 0x1;
276560b08185Syz ctrl_msg->setDtr = 0x01;
276660b08185Syz ctrl_msg->dtr = 0x1;
276760b08185Syz
276860b08185Syz ctrl_msg->setClocking = 1;
276960b08185Syz ctrl_msg->setRxMode = 1;
277060b08185Syz ctrl_msg->setTxMode = 1;
277160b08185Syz
277260b08185Syz /* set baud rate to 9600 */
277360b08185Syz ctrl_msg->baudLo = keyspan_speedtab_usa19hs[13] & 0xff;
277460b08185Syz ctrl_msg->baudHi = (keyspan_speedtab_usa19hs[13] >> 8) & 0xff;
277560b08185Syz ctrl_msg->rxMode = RXMODE_BYHAND;
277660b08185Syz ctrl_msg->txMode = TXMODE_BYHAND;
277760b08185Syz
277860b08185Syz ctrl_msg->lcr = 0x3;
277960b08185Syz ctrl_msg->setLcr = 0x1;
278060b08185Syz
278160b08185Syz ctrl_msg->xonChar = CSTART;
278260b08185Syz ctrl_msg->xoffChar = CSTOP;
278360b08185Syz ctrl_msg->setTxFlowControl = 1;
278460b08185Syz ctrl_msg->txFlowControl = TXFLOW_CTS;
278560b08185Syz ctrl_msg->setRxFlowControl = 1;
278660b08185Syz ctrl_msg->rxFlowControl = RXFLOW_RTS;
278760b08185Syz ctrl_msg->rxFlush = 0;
278860b08185Syz
278960b08185Syz }
279060b08185Syz
279160b08185Syz /*
279260b08185Syz * Build the command message according to the params from usbser.
279360b08185Syz * The message will then be sent to deivce by keyspan_send_cmd.
279460b08185Syz */
279560b08185Syz static void
keyspan_build_cmd_msg_usa19hs(keyspan_port_t * kp,ds_port_params_t * tp)279660b08185Syz keyspan_build_cmd_msg_usa19hs(keyspan_port_t *kp, ds_port_params_t *tp)
279760b08185Syz {
279860b08185Syz int cnt, i;
279960b08185Syz uint_t ui;
280060b08185Syz ds_port_param_entry_t *pe;
280160b08185Syz keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs);
280260b08185Syz
280360b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
280460b08185Syz "keyspan_build_cmd_msg_usa19hs: tp = %p", (void *)tp);
280560b08185Syz
280660b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
280760b08185Syz ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN ||
280860b08185Syz kp->kp_state == KEYSPAN_PORT_OPENING);
280960b08185Syz
281060b08185Syz /* bzero all elements */
281160b08185Syz bzero(ctrl_msg, sizeof (keyspan_usa19hs_port_ctrl_msg_t));
281260b08185Syz
281360b08185Syz /* it is usaually 16, according to Keyspan spec */
281460b08185Syz ctrl_msg->rxForwardingLength = 16;
281560b08185Syz /* from 1ms to 31ms, according to Keyspan spec. */
281660b08185Syz ctrl_msg->rxForwardingTimeout = 16;
281760b08185Syz
281860b08185Syz ctrl_msg->portEnabled = 1;
281960b08185Syz ctrl_msg->returnStatus = 1;
282060b08185Syz
282160b08185Syz if (tp == NULL) {
282260b08185Syz
282360b08185Syz return;
282460b08185Syz }
282560b08185Syz
282660b08185Syz cnt = tp->tp_cnt;
282760b08185Syz pe = tp->tp_entries;
282860b08185Syz
282960b08185Syz /* translate tp parameters into cmd_msg elements */
283060b08185Syz for (i = 0; i < cnt; i++, pe++) {
283160b08185Syz switch (pe->param) {
283260b08185Syz case DS_PARAM_BAUD:
283360b08185Syz ui = pe->val.ui;
283460b08185Syz
283560b08185Syz /*
283660b08185Syz * if we don't support this speed,
283760b08185Syz * then return failure.
283860b08185Syz */
283960b08185Syz if ((ui >= NELEM(keyspan_speedtab_usa19hs)) ||
284060b08185Syz ((ui > 0) && (keyspan_speedtab_usa19hs[ui] == 0))) {
284160b08185Syz
284260b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
284360b08185Syz "keyspan_build_cmd_msg_usa19hs:"
284460b08185Syz " bad baud %d", ui);
284560b08185Syz
284660b08185Syz break;
284760b08185Syz }
284860b08185Syz
284960b08185Syz /* if the same as the old rate, need not set the rate */
285060b08185Syz if (kp->kp_baud == keyspan_speedtab_usa19hs[ui]) {
285160b08185Syz
285260b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
285360b08185Syz "keyspan_build_cmd_msg_usa19hs:"
285460b08185Syz " same as old baud setting, baud = %d",
285560b08185Syz keyspan_speed2baud[ui]);
285660b08185Syz
285760b08185Syz break;
285860b08185Syz }
285960b08185Syz ctrl_msg->setClocking = 1; /* enable the setting */
286060b08185Syz ctrl_msg->setRxMode = 1;
286160b08185Syz ctrl_msg->setTxMode = 1;
286260b08185Syz
286360b08185Syz ctrl_msg->baudLo = keyspan_speedtab_usa19hs[ui] & 0xff;
286460b08185Syz ctrl_msg->baudHi = (keyspan_speedtab_usa19hs[ui] >> 8)
286560b08185Syz & 0xff;
286660b08185Syz
286760b08185Syz ctrl_msg->rxMode = RXMODE_BYHAND;
286860b08185Syz ctrl_msg->txMode = TXMODE_BYHAND;
286960b08185Syz
287060b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
287160b08185Syz "keyspan_build_cmd_msg_usa19hs: baud=%d",
287260b08185Syz keyspan_speed2baud[ui]);
287360b08185Syz
287460b08185Syz break;
287560b08185Syz case DS_PARAM_PARITY:
287660b08185Syz if (pe->val.ui & PARENB) {
287760b08185Syz
287860b08185Syz /*
287960b08185Syz * Since USA_PARITY_NONE == 0, it's not
288060b08185Syz * necessary to or it in here.
288160b08185Syz */
288260b08185Syz if (pe->val.ui & PARODD) {
288360b08185Syz ctrl_msg->lcr |= USA_PARITY_ODD;
288460b08185Syz } else {
288560b08185Syz ctrl_msg->lcr |= USA_PARITY_EVEN;
288660b08185Syz }
288760b08185Syz }
288860b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
288960b08185Syz "keyspan_build_cmd_msg_usa19hs: parity=%x,lcr = %x",
289060b08185Syz pe->val.ui, ctrl_msg->lcr);
289160b08185Syz
289260b08185Syz break;
289360b08185Syz case DS_PARAM_STOPB:
289460b08185Syz if (pe->val.ui & CSTOPB) {
289560b08185Syz ctrl_msg->lcr |= STOPBITS_678_2;
289660b08185Syz } else {
289760b08185Syz
289860b08185Syz /*
289960b08185Syz * STOPBITS_5678_1 equals zero,
290060b08185Syz * so it's not necessary to or it in.
290160b08185Syz */
290260b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
290360b08185Syz "keyspan_build_cmd_msg_usa19hs:"
290460b08185Syz " STOPBITS_5678_1");
290560b08185Syz }
290660b08185Syz
290760b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
290860b08185Syz "keyspan_build_cmd_msg_usa19hs: stopb=%x, lcr = %x",
290960b08185Syz pe->val.ui, ctrl_msg->lcr);
291060b08185Syz
291160b08185Syz break;
291260b08185Syz case DS_PARAM_CHARSZ:
291360b08185Syz switch (pe->val.ui) {
291460b08185Syz case CS5:
291560b08185Syz
291660b08185Syz /*
291760b08185Syz * USA_DATABITS_5 equals zero,
291860b08185Syz * not necessary to or it in.
291960b08185Syz */
292060b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
292160b08185Syz "keyspan_build_cmd_msg_usa19hs:"
292260b08185Syz " USA_DATABITS_5");
292360b08185Syz
292460b08185Syz break;
292560b08185Syz case CS6:
292660b08185Syz ctrl_msg->lcr |= USA_DATABITS_6;
292760b08185Syz
292860b08185Syz break;
292960b08185Syz case CS7:
293060b08185Syz ctrl_msg->lcr |= USA_DATABITS_7;
293160b08185Syz
293260b08185Syz break;
293360b08185Syz case CS8:
293460b08185Syz default:
293560b08185Syz /*
293660b08185Syz * The default value is USA_DATABITS_8. It is
293760b08185Syz * safe to set to the default one here.
293860b08185Syz */
293960b08185Syz ctrl_msg->lcr |= USA_DATABITS_8;
294060b08185Syz
294160b08185Syz break;
294260b08185Syz }
294360b08185Syz
294460b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
294560b08185Syz "keyspan_build_cmd_msg_usa19hs: cs=%x, lcr = %x",
294660b08185Syz pe->val.ui, ctrl_msg->lcr);
294760b08185Syz
294860b08185Syz break;
294960b08185Syz case DS_PARAM_XON_XOFF:
295060b08185Syz ctrl_msg->xonChar = pe->val.uc[0]; /* init to CSTART */
295160b08185Syz ctrl_msg->xoffChar = pe->val.uc[1]; /* init to CSTOP */
295260b08185Syz
295360b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
295460b08185Syz "keyspan_build_cmd_msg_usa19hs: xonChar=%x, "
295560b08185Syz "xoffChar = %x", ctrl_msg->xonChar,
295660b08185Syz ctrl_msg->xoffChar);
295760b08185Syz
295860b08185Syz break;
295960b08185Syz case DS_PARAM_FLOW_CTL:
296060b08185Syz if (pe->val.ui & CTSXON) {
296160b08185Syz ctrl_msg->txFlowControl = TXFLOW_CTS;
296260b08185Syz ctrl_msg->setTxFlowControl = 1;
296360b08185Syz } else {
296460b08185Syz /* Clear the tx flow control setting */
296560b08185Syz ctrl_msg->txFlowControl = 0;
296660b08185Syz ctrl_msg->setTxFlowControl = 1;
296760b08185Syz }
296860b08185Syz if (pe->val.ui & RTSXOFF) {
296960b08185Syz ctrl_msg->rxFlowControl = RXFLOW_RTS;
297060b08185Syz ctrl_msg->setRxFlowControl = 1;
297160b08185Syz } else {
297260b08185Syz /* Clear the rx flow control setting */
297360b08185Syz ctrl_msg->rxFlowControl = 0;
297460b08185Syz ctrl_msg->setRxFlowControl = 1;
297560b08185Syz }
297660b08185Syz
297760b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
297860b08185Syz "keyspan_build_cmd_msg_usa19hs: txFlowControl = %x,"
297960b08185Syz "rxFlowControl = %x", ctrl_msg->txFlowControl,
298060b08185Syz ctrl_msg->rxFlowControl);
298160b08185Syz
298260b08185Syz break;
298360b08185Syz default:
298460b08185Syz USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
298560b08185Syz "keyspan_build_cmd_msg_usa19hs: bad param %d",
298660b08185Syz pe->param);
298760b08185Syz
298860b08185Syz break;
298960b08185Syz }
299060b08185Syz
299160b08185Syz }
299260b08185Syz
299360b08185Syz /*
299460b08185Syz * Enable the lcr settings only if they are different
299560b08185Syz * with the existing settings.
299660b08185Syz */
299760b08185Syz ctrl_msg->setLcr = (ctrl_msg->lcr == kp->kp_lcr) ? 0 : 1;
299860b08185Syz
299960b08185Syz }
300060b08185Syz
3001c138f478Syz
300260b08185Syz /*
300360b08185Syz * Build the command message according to the params from usbser.
300460b08185Syz * The message will then be sent to deivce by keyspan_send_cmd.
300560b08185Syz */
300660b08185Syz static void
keyspan_build_cmd_msg_usa49(keyspan_port_t * kp,ds_port_params_t * tp)300760b08185Syz keyspan_build_cmd_msg_usa49(keyspan_port_t *kp, ds_port_params_t *tp)
300860b08185Syz {
300960b08185Syz int cnt, i;
301060b08185Syz uint_t ui;
301160b08185Syz ds_port_param_entry_t *pe;
301260b08185Syz keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49);
301360b08185Syz
301460b08185Syz USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
301560b08185Syz "keyspan_build_cmd_msg_usa49: tp = %p", (void *)tp);
301660b08185Syz
301760b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
301860b08185Syz ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN ||
301960b08185Syz kp->kp_state == KEYSPAN_PORT_OPENING);
302060b08185Syz
302160b08185Syz /* bzero all elements */
302260b08185Syz bzero(ctrl_msg, sizeof (keyspan_usa49_port_ctrl_msg_t));
302360b08185Syz
302460b08185Syz ctrl_msg->portNumber = kp->kp_port_num;
302560b08185Syz
302660b08185Syz /* it is usaually 16, according to Keyspan spec */
302760b08185Syz ctrl_msg->forwardingLength = 16;
302860b08185Syz
302960b08185Syz ctrl_msg->enablePort = 1;
303060b08185Syz ctrl_msg->returnStatus = 1;
303160b08185Syz
303260b08185Syz if (tp == NULL) {
303360b08185Syz
303460b08185Syz return;
303560b08185Syz }
303660b08185Syz
303760b08185Syz cnt = tp->tp_cnt;
303860b08185Syz pe = tp->tp_entries;
303960b08185Syz
304060b08185Syz /* translate tp parameters into cmd_msg elements */
304160b08185Syz for (i = 0; i < cnt; i++, pe++) {
304260b08185Syz switch (pe->param) {
304360b08185Syz case DS_PARAM_BAUD:
304460b08185Syz ui = pe->val.ui;
304560b08185Syz
304660b08185Syz /*
304760b08185Syz * If we don't support this speed,
304860b08185Syz * then return failure.
304960b08185Syz */
305060b08185Syz if ((ui >= NELEM(keyspan_speedtab_usa49)) ||
305160b08185Syz ((ui > 0) && (keyspan_speedtab_usa49[ui] == 0))) {
305260b08185Syz
305360b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
305460b08185Syz "keyspan_build_cmd_msg_usa49:"
305560b08185Syz " bad baud %d", ui);
305660b08185Syz
305760b08185Syz break;
305860b08185Syz }
305960b08185Syz
306060b08185Syz /* if the same as the old rate, need not set the rate */
306160b08185Syz if (kp->kp_baud == keyspan_speedtab_usa49[ui]) {
306260b08185Syz
306360b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
30644ee52f77Slg "keyspan_build_cmd_msg_usa49: "
30654ee52f77Slg "same as old baud setting, baud = %d",
30664ee52f77Slg keyspan_speed2baud[ui]);
306760b08185Syz
306860b08185Syz break;
306960b08185Syz }
307060b08185Syz ctrl_msg->setClocking = 0xff; /* enable the setting */
307160b08185Syz ctrl_msg->baudLo = keyspan_speedtab_usa49[ui] & 0xff;
307260b08185Syz ctrl_msg->baudHi = (keyspan_speedtab_usa49[ui] >> 8)
307360b08185Syz & 0xff;
307460b08185Syz ctrl_msg->prescaler = keyspan_prescaler_49wlc[ui];
307560b08185Syz
307660b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
307760b08185Syz "keyspan_build_cmd_msg_usa49: baud=%d",
307860b08185Syz keyspan_speed2baud[ui]);
307960b08185Syz
308060b08185Syz break;
308160b08185Syz case DS_PARAM_PARITY:
308260b08185Syz if (pe->val.ui & PARENB) {
308360b08185Syz
308460b08185Syz /*
308560b08185Syz * Since USA_PARITY_NONE == 0,
308660b08185Syz * it's not necessary to or it in here.
308760b08185Syz */
308860b08185Syz if (pe->val.ui & PARODD) {
308960b08185Syz ctrl_msg->lcr |= USA_PARITY_ODD;
309060b08185Syz } else {
309160b08185Syz ctrl_msg->lcr |= USA_PARITY_EVEN;
309260b08185Syz }
309360b08185Syz }
309460b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
309560b08185Syz "keyspan_build_cmd_msg_usa49: parity=%x, lcr = %x",
309660b08185Syz pe->val.ui, ctrl_msg->lcr);
309760b08185Syz
309860b08185Syz break;
309960b08185Syz case DS_PARAM_STOPB:
310060b08185Syz if (pe->val.ui & CSTOPB) {
310160b08185Syz ctrl_msg->lcr |= STOPBITS_678_2;
310260b08185Syz } else {
310360b08185Syz
310460b08185Syz /*
310560b08185Syz * STOPBITS_5678_1 equals zero,
310660b08185Syz * not necessary to or it in.
310760b08185Syz */
310860b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
310960b08185Syz "keyspan_build_cmd_msg_usa49: "
311060b08185Syz "STOPBITS_5678_1");
311160b08185Syz }
311260b08185Syz
311360b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
311460b08185Syz "keyspan_build_cmd_msg_usa49: stopb=%x, lcr = %x",
311560b08185Syz pe->val.ui, ctrl_msg->lcr);
311660b08185Syz
311760b08185Syz break;
311860b08185Syz case DS_PARAM_CHARSZ:
311960b08185Syz switch (pe->val.ui) {
312060b08185Syz case CS5:
312160b08185Syz
312260b08185Syz /*
312360b08185Syz * USA_DATABITS_5 equals zero,
312460b08185Syz * not necessary to or it in.
312560b08185Syz */
312660b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
312760b08185Syz "keyspan_build_cmd_msg_usa49:"
312860b08185Syz " USA_DATABITS_5");
312960b08185Syz
313060b08185Syz break;
313160b08185Syz case CS6:
313260b08185Syz ctrl_msg->lcr |= USA_DATABITS_6;
313360b08185Syz
313460b08185Syz break;
313560b08185Syz case CS7:
313660b08185Syz ctrl_msg->lcr |= USA_DATABITS_7;
313760b08185Syz
313860b08185Syz break;
313960b08185Syz case CS8:
314060b08185Syz default:
314160b08185Syz ctrl_msg->lcr |= USA_DATABITS_8;
314260b08185Syz
314360b08185Syz break;
314460b08185Syz }
314560b08185Syz
314660b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
314760b08185Syz "keyspan_build_cmd_msg_usa49: cs=%x, lcr = %x",
314860b08185Syz pe->val.ui, ctrl_msg->lcr);
314960b08185Syz
315060b08185Syz break;
315160b08185Syz case DS_PARAM_XON_XOFF:
315260b08185Syz ctrl_msg->xonChar = pe->val.uc[0]; /* init to CSTART */
315360b08185Syz ctrl_msg->xoffChar = pe->val.uc[1]; /* init to CSTOP */
315460b08185Syz
315560b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
315660b08185Syz "keyspan_build_cmd_msg_usa49: xonChar=%x, "
315760b08185Syz "xoffChar = %x", ctrl_msg->xonChar,
315860b08185Syz ctrl_msg->xoffChar);
315960b08185Syz
316060b08185Syz break;
316160b08185Syz case DS_PARAM_FLOW_CTL:
316260b08185Syz if (pe->val.ui & CTSXON) {
316360b08185Syz ctrl_msg->ctsFlowControl = 1;
316460b08185Syz ctrl_msg->setFlowControl = 1;
316560b08185Syz } else {
316660b08185Syz ctrl_msg->ctsFlowControl = 0;
316760b08185Syz ctrl_msg->setFlowControl = 1;
316860b08185Syz }
316960b08185Syz if (pe->val.ui & RTSXOFF) {
317060b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
317160b08185Syz "keyspan_build_cmd_msg_usa49: "
317260b08185Syz "pe->val.ui = %x, flow_ctl: RTSXOFF, "
317360b08185Syz "no hardware support", pe->val.ui);
317460b08185Syz }
317560b08185Syz
317660b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
317760b08185Syz "keyspan_build_cmd_msg_usa49: ctsFlowControl = %x,"
317860b08185Syz "dsrFlowControl = %x", ctrl_msg->ctsFlowControl,
317960b08185Syz ctrl_msg->dsrFlowControl);
318060b08185Syz
318160b08185Syz break;
318260b08185Syz default:
318360b08185Syz USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
318460b08185Syz "keyspan_build_cmd_msg_usa49: bad param %d",
318560b08185Syz pe->param);
318660b08185Syz
318760b08185Syz break;
318860b08185Syz }
318960b08185Syz }
319060b08185Syz
319160b08185Syz /*
319260b08185Syz * enable the lcr settings only if they are different
319360b08185Syz * with the existing settings.
319460b08185Syz */
319560b08185Syz ctrl_msg->setLcr = (ctrl_msg->lcr == kp->kp_lcr) ? 0 : 1;
319660b08185Syz
319760b08185Syz }
319860b08185Syz
319960b08185Syz
320060b08185Syz /*
320160b08185Syz * Set the port parameters to default values
320260b08185Syz */
320360b08185Syz static void
keyspan_default_port_params_usa49(keyspan_port_t * kp)320460b08185Syz keyspan_default_port_params_usa49(keyspan_port_t *kp)
320560b08185Syz {
320660b08185Syz keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49);
320760b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
320860b08185Syz
320960b08185Syz keyspan_build_cmd_msg(kp, NULL);
321060b08185Syz
321160b08185Syz ctrl_msg->setRts = 1;
321260b08185Syz ctrl_msg->rts = 1;
321360b08185Syz ctrl_msg->setDtr = 1;
321460b08185Syz ctrl_msg->dtr = 1;
321560b08185Syz
321660b08185Syz ctrl_msg->_txOn = 1;
321760b08185Syz ctrl_msg->_txOff = 0;
321860b08185Syz ctrl_msg->txFlush = 0;
321960b08185Syz ctrl_msg->txBreak = 0;
322060b08185Syz ctrl_msg->rxOn = 1;
322160b08185Syz ctrl_msg->rxOff = 0;
322260b08185Syz ctrl_msg->rxFlush = 0;
322360b08185Syz ctrl_msg->rxForward = 0;
322460b08185Syz ctrl_msg->returnStatus = 1;
322560b08185Syz ctrl_msg->resetDataToggle = 0;
322660b08185Syz ctrl_msg->enablePort = 1;
322760b08185Syz ctrl_msg->disablePort = 0;
322860b08185Syz
322960b08185Syz /* set baud rate to 9600 */
323060b08185Syz ctrl_msg->setClocking = 1;
323160b08185Syz ctrl_msg->baudLo = keyspan_speedtab_usa49[13] & 0xff;
323260b08185Syz ctrl_msg->baudHi = (keyspan_speedtab_usa49[13] >> 8) & 0xff;
323360b08185Syz ctrl_msg->prescaler = keyspan_prescaler_49wlc[13];
323460b08185Syz
323560b08185Syz ctrl_msg->lcr = 0x3;
323660b08185Syz ctrl_msg->setLcr = 1;
323760b08185Syz
323860b08185Syz ctrl_msg->xonChar = CSTART;
323960b08185Syz ctrl_msg->xoffChar = CSTOP;
324060b08185Syz ctrl_msg->ctsFlowControl = 1;
324160b08185Syz ctrl_msg->setFlowControl = 1;
324260b08185Syz
324360b08185Syz }
324460b08185Syz
324560b08185Syz
324660b08185Syz /* save the port params after send cmd successfully */
324760b08185Syz static void
keyspan_save_port_params_usa49(keyspan_port_t * kp)324860b08185Syz keyspan_save_port_params_usa49(keyspan_port_t *kp)
324960b08185Syz {
325060b08185Syz keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49);
325160b08185Syz
325260b08185Syz ASSERT(mutex_owned(&kp->kp_mutex));
325360b08185Syz
325460b08185Syz if (ctrl_msg->setClocking) {
325560b08185Syz kp->kp_baud = ctrl_msg->baudHi;
325660b08185Syz kp->kp_baud = (kp->kp_baud << 8);
325760b08185Syz kp->kp_baud |= ctrl_msg->baudLo;
325860b08185Syz }
325960b08185Syz if (ctrl_msg->setLcr) {
326060b08185Syz kp->kp_lcr = ctrl_msg->lcr;
326160b08185Syz }
326260b08185Syz if (ctrl_msg->setRts) {
326360b08185Syz if (ctrl_msg->rts) {
326460b08185Syz kp->kp_status_flag |= KEYSPAN_PORT_RTS;
326560b08185Syz } else {
326660b08185Syz kp->kp_status_flag &= ~KEYSPAN_PORT_RTS;
326760b08185Syz }
326860b08185Syz }
326960b08185Syz if (ctrl_msg->setDtr) {
327060b08185Syz if (ctrl_msg->dtr) {
327160b08185Syz kp->kp_status_flag |= KEYSPAN_PORT_DTR;
327260b08185Syz } else {
327360b08185Syz kp->kp_status_flag &= ~KEYSPAN_PORT_DTR;
327460b08185Syz }
327560b08185Syz }
327660b08185Syz
327760b08185Syz if (ctrl_msg->enablePort) {
327860b08185Syz kp->kp_status_flag |= KEYSPAN_PORT_ENABLE;
327960b08185Syz } else {
328060b08185Syz kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE;
328160b08185Syz }
328260b08185Syz
328360b08185Syz /*
328460b08185Syz * There are no flags in status msg (49wlc) can indicate the
328560b08185Syz * break status, so we make use of ctrl_msg->txBreak here.
328660b08185Syz */
328760b08185Syz if (ctrl_msg->txBreak) {
328860b08185Syz kp->kp_status_flag |= KEYSPAN_PORT_TXBREAK;
328960b08185Syz } else {
329060b08185Syz kp->kp_status_flag &= ~KEYSPAN_PORT_TXBREAK;
329160b08185Syz }
329260b08185Syz
329360b08185Syz USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
329460b08185Syz "keyspan_save_port_params: baud = %x, lcr = %x,"
329560b08185Syz "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag);
329660b08185Syz
329760b08185Syz }
3298