1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28 /*
29 *
30 * DSD code for keyspan usb2serial adapters
31 *
32 */
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/conf.h>
36 #include <sys/stream.h>
37 #include <sys/strsun.h>
38 #include <sys/termio.h>
39 #include <sys/termiox.h>
40 #include <sys/ddi.h>
41 #include <sys/sunddi.h>
42
43 #define USBDRV_MAJOR_VER 2
44 #define USBDRV_MINOR_VER 0
45
46 #include <sys/usb/usba.h>
47
48 #include <sys/usb/clients/usbser/usbser_dsdi.h>
49 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_var.h>
50 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_pipe.h>
51
52 #include <sys/usb/clients/usbser/usbser_keyspan/usa90msg.h>
53 #include <sys/usb/clients/usbser/usbser_keyspan/usa49msg.h>
54
55 /*
56 * DSD operations which are filled in ds_ops structure.
57 */
58 static int keyspan_attach(ds_attach_info_t *);
59 static void keyspan_detach(ds_hdl_t);
60 static int keyspan_register_cb(ds_hdl_t, uint_t, ds_cb_t *);
61 static void keyspan_unregister_cb(ds_hdl_t, uint_t);
62 static int keyspan_open_port(ds_hdl_t, uint_t);
63 static int keyspan_close_port(ds_hdl_t, uint_t);
64
65 /* power management */
66 static int keyspan_usb_power(ds_hdl_t, int, int, int *);
67 static int keyspan_suspend(ds_hdl_t);
68 static int keyspan_resume(ds_hdl_t);
69
70 /* hotplug */
71 static int keyspan_disconnect(ds_hdl_t);
72 static int keyspan_reconnect(ds_hdl_t);
73
74 /* standard UART operations */
75 static int keyspan_set_port_params(ds_hdl_t, uint_t, ds_port_params_t *);
76 static int keyspan_set_modem_ctl(ds_hdl_t, uint_t, int, int);
77 static int keyspan_get_modem_ctl(ds_hdl_t, uint_t, int, int *);
78 static int keyspan_break_ctl(ds_hdl_t, uint_t, int);
79 static int keyspan_loopback(ds_hdl_t, uint_t, int);
80
81 /* data xfer */
82 static int keyspan_tx(ds_hdl_t, uint_t, mblk_t *);
83 static mblk_t *keyspan_rx(ds_hdl_t, uint_t);
84 static void keyspan_stop(ds_hdl_t, uint_t, int);
85 static void keyspan_start(ds_hdl_t, uint_t, int);
86 static int keyspan_fifo_flush(ds_hdl_t, uint_t, int);
87 static int keyspan_fifo_drain(ds_hdl_t, uint_t, int);
88
89 /*
90 * Sub-routines
91 */
92
93 /* configuration routines */
94 static void keyspan_free_soft_state(keyspan_state_t *);
95 static void keyspan_init_sync_objs(keyspan_state_t *);
96 static void keyspan_fini_sync_objs(keyspan_state_t *);
97 static int keyspan_usb_register(keyspan_state_t *);
98 static void keyspan_usb_unregister(keyspan_state_t *);
99 static int keyspan_attach_dev(keyspan_state_t *);
100 static void keyspan_attach_ports(keyspan_state_t *);
101 static void keyspan_detach_ports(keyspan_state_t *);
102 static void keyspan_init_port_params(keyspan_state_t *);
103 static void keyspan_free_descr_tree(keyspan_state_t *);
104 static int keyspan_register_events(keyspan_state_t *);
105 static void keyspan_unregister_events(keyspan_state_t *);
106 static void keyspan_set_dev_state_online(keyspan_state_t *);
107
108 /* hotplug */
109 static int keyspan_restore_device_state(keyspan_state_t *);
110 static int keyspan_restore_ports_state(keyspan_state_t *);
111
112 /* power management */
113 static int keyspan_create_pm_components(keyspan_state_t *);
114 static void keyspan_destroy_pm_components(keyspan_state_t *);
115 static int keyspan_pm_set_busy(keyspan_state_t *);
116 static void keyspan_pm_set_idle(keyspan_state_t *);
117 static int keyspan_pwrlvl0(keyspan_state_t *);
118 static int keyspan_pwrlvl1(keyspan_state_t *);
119 static int keyspan_pwrlvl2(keyspan_state_t *);
120 static int keyspan_pwrlvl3(keyspan_state_t *);
121
122 /* pipe operations */
123 static int keyspan_attach_pipes(keyspan_state_t *);
124 static void keyspan_detach_pipes(keyspan_state_t *);
125 static void keyspan_disconnect_pipes(keyspan_state_t *);
126 static int keyspan_reconnect_pipes(keyspan_state_t *);
127
128 /* data transfer routines */
129 static int keyspan_wait_tx_drain(keyspan_port_t *, int);
130
131 /* misc */
132 static void keyspan_default_port_params(keyspan_port_t *);
133 static void keyspan_build_cmd_msg(keyspan_port_t *, ds_port_params_t *);
134 static void keyspan_save_port_params(keyspan_port_t *);
135
136 /*
137 * Model specific functions.
138 */
139
140 /* usa19hs specific functions */
141 static void keyspan_build_cmd_msg_usa19hs(keyspan_port_t *,
142 ds_port_params_t *);
143 static void keyspan_default_port_params_usa19hs(keyspan_port_t *);
144 static void keyspan_save_port_params_usa19hs(keyspan_port_t *);
145
146
147 /* usa49 specific functions */
148 static void keyspan_build_cmd_msg_usa49(keyspan_port_t *,
149 ds_port_params_t *);
150 static void keyspan_default_port_params_usa49(keyspan_port_t *);
151 static void keyspan_save_port_params_usa49(keyspan_port_t *);
152
153
154 /*
155 * DSD ops structure
156 */
157 ds_ops_t keyspan_ds_ops = {
158 DS_OPS_VERSION,
159 keyspan_attach,
160 keyspan_detach,
161 keyspan_register_cb,
162 keyspan_unregister_cb,
163 keyspan_open_port,
164 keyspan_close_port,
165 keyspan_usb_power,
166 keyspan_suspend,
167 keyspan_resume,
168 keyspan_disconnect,
169 keyspan_reconnect,
170 keyspan_set_port_params,
171 keyspan_set_modem_ctl,
172 keyspan_get_modem_ctl,
173 keyspan_break_ctl,
174 keyspan_loopback,
175 keyspan_tx,
176 keyspan_rx,
177 keyspan_stop,
178 keyspan_start,
179 keyspan_fifo_flush,
180 keyspan_fifo_drain
181 };
182
183 /*
184 * For USA19HS baud speed, precalculated using the following algorithm:
185 *
186 * speed = (uint16_t)(14769231L / baud);
187 */
188 static uint16_t keyspan_speedtab_usa19hs[] = {
189 0x0, /* B0 */
190 0x481d, /* B50 */
191 0x3013, /* B75 */
192 0x20c7, /* B110 */
193 0x1ae8, /* B134 */
194 0x1809, /* B150 */
195 0x1207, /* B200 */
196 0xc04, /* B300 */
197 0x602, /* B600 */
198 0x301, /* B1200 */
199 0x200, /* B1800 */
200 0x180, /* B2400 */
201 0xc0, /* B4800 */
202 0x60, /* B9600 */
203 0x30, /* B19200 */
204 0x18, /* B38400 */
205 0x10, /* B57600 */
206 0xc, /* B76800 */
207 0x8, /* B115200 */
208 0x6, /* B153600 */
209 0x4, /* B230400 */
210 };
211
212 /*
213 * For USA49WLC baud speed, precalculated.
214 */
215 static uint16_t keyspan_speedtab_usa49[] = {
216 0x0, /* B0 */
217 0x7530, /* B50 */
218 0x4e20, /* B75 */
219 0x3544, /* B110 */
220 0x2bba, /* B134 */
221 0x2710, /* B150 */
222 0x1d4c, /* B200 */
223 0x1388, /* B300 */
224 0x9c4, /* B600 */
225 0x4e2, /* B1200 */
226 0x25e, /* B1800 */
227 0x271, /* B2400 */
228 0xfa, /* B4800 */
229 0x7d, /* B9600 */
230 0x19, /* B19200 */
231 0x27, /* B38400 */
232 0x1a, /* B57600 */
233 0xd, /* B76800 */
234 0xd, /* B115200 */
235 0x6, /* B153600 */
236 0x4, /* B230400 */
237 };
238
239 /*
240 * For USA49WLC prescaler, precalculated.
241 */
242 static uint8_t keyspan_prescaler_49wlc[] = {
243 0x0, /* B0 */
244 0x8, /* B50 */
245 0x8, /* B75 */
246 0x8, /* B110 */
247 0x8, /* B134 */
248 0x8, /* B150 */
249 0x8, /* B200 */
250 0x8, /* B300 */
251 0x8, /* B600 */
252 0x8, /* B1200 */
253 0xb, /* B1800 */
254 0x8, /* B2400 */
255 0xa, /* B4800 */
256 0xa, /* B9600 */
257 0x19, /* B19200 */
258 0x8, /* B38400 */
259 0x8, /* B57600 */
260 0xc, /* B76800 */
261 0x8, /* B115200 */
262 0xd, /* B153600 */
263 0xd, /* B230400 */
264 };
265
266
267 /* convert baud code into baud rate */
268 static int keyspan_speed2baud[] = {
269 0, /* B0 */
270 50, /* B50 */
271 75, /* B75 */
272 110, /* B110 */
273 134, /* B134 */
274 150, /* B150 */
275 200, /* B200 */
276 300, /* B300 */
277 600, /* B600 */
278 1200, /* B1200 */
279 1800, /* B1800 */
280 2400, /* B2400 */
281 4800, /* B4800 */
282 9600, /* B9600 */
283 19200, /* B19200 */
284 38400, /* B38400 */
285 57600, /* B57600 */
286 76800, /* B76800 */
287 115200, /* B115200 */
288 153600, /* B153600 */
289 230400, /* B230400 */
290 };
291
292
293 /* debug support */
294 static uint_t keyspan_errlevel = USB_LOG_L4;
295 static uint_t keyspan_errmask = DPRINT_MASK_ALL;
296 static uint_t keyspan_instance_debug = (uint_t)-1;
297
298 static int
keyspan_attach(ds_attach_info_t * aip)299 keyspan_attach(ds_attach_info_t *aip)
300 {
301 keyspan_state_t *ksp;
302 int rval = USB_SUCCESS;
303
304 ksp = (keyspan_state_t *)kmem_zalloc(sizeof (keyspan_state_t),
305 KM_SLEEP);
306 ksp->ks_dip = aip->ai_dip;
307 ksp->ks_usb_events = aip->ai_usb_events;
308 *aip->ai_hdl = (ds_hdl_t)ksp;
309
310 if (keyspan_usb_register(ksp) != USB_SUCCESS) {
311
312 goto fail_register;
313 }
314
315 /* init mutex and semaphore */
316 keyspan_init_sync_objs(ksp);
317
318 /* get device specific parameters */
319 if (keyspan_attach_dev(ksp) != USB_SUCCESS) {
320 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, "fail attach dev ");
321
322 goto fail_attach_dev;
323 }
324
325 keyspan_attach_ports(ksp);
326
327 switch (ksp->ks_dev_spec.id_product) {
328 case KEYSPAN_USA19HS_PID:
329 case KEYSPAN_USA49WLC_PID:
330 rval = keyspan_init_pipes(ksp);
331
332 break;
333
334 case KEYSPAN_USA49WG_PID:
335 rval = keyspan_init_pipes_usa49wg(ksp);
336
337 break;
338
339 default:
340 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh, "keyspan_attach:"
341 "the device's product id can't be recognized");
342
343 return (USB_FAILURE);
344 }
345
346 if (rval != USB_SUCCESS) {
347 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
348 "keyspan_init_pipes: failed.");
349
350 goto fail_init_pipes;
351 }
352
353 keyspan_init_port_params(ksp);
354 keyspan_free_descr_tree(ksp);
355 keyspan_set_dev_state_online(ksp);
356
357 if (keyspan_create_pm_components(ksp) != USB_SUCCESS) {
358 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
359 "keyspan_create_pm_components: failed.");
360
361 goto fail_pm;
362 }
363
364 if (keyspan_register_events(ksp) != USB_SUCCESS) {
365
366 goto fail_events;
367 }
368
369 /* open the global pipes */
370 if (keyspan_attach_pipes(ksp) != USB_SUCCESS) {
371 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
372 "keyspan_attach_pipes: failed.");
373
374 goto fail_attach_pipes;
375 }
376
377 *aip->ai_port_cnt = ksp->ks_dev_spec.port_cnt;
378
379 return (USB_SUCCESS);
380
381 fail_attach_pipes:
382 keyspan_unregister_events(ksp);
383 fail_events:
384 keyspan_destroy_pm_components(ksp);
385 fail_pm:
386 keyspan_fini_pipes(ksp);
387 fail_init_pipes:
388 keyspan_detach_ports(ksp);
389 fail_attach_dev:
390 keyspan_fini_sync_objs(ksp);
391 keyspan_usb_unregister(ksp);
392 fail_register:
393 keyspan_free_soft_state(ksp);
394
395 return (USB_FAILURE);
396 }
397
398
399 /*
400 * ds_detach
401 */
402 static void
keyspan_detach(ds_hdl_t hdl)403 keyspan_detach(ds_hdl_t hdl)
404 {
405 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
406
407 keyspan_detach_pipes(ksp);
408 keyspan_unregister_events(ksp);
409 keyspan_destroy_pm_components(ksp);
410 keyspan_fini_pipes(ksp);
411 keyspan_detach_ports(ksp);
412 keyspan_fini_sync_objs(ksp);
413 keyspan_usb_unregister(ksp);
414 keyspan_free_soft_state(ksp);
415 }
416
417 /*
418 * ds_register_cb
419 */
420 static int
keyspan_register_cb(ds_hdl_t hdl,uint_t port_num,ds_cb_t * cb)421 keyspan_register_cb(ds_hdl_t hdl, uint_t port_num, ds_cb_t *cb)
422 {
423 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
424 keyspan_port_t *kp;
425
426 if (port_num >= ksp->ks_dev_spec.port_cnt) {
427
428 return (USB_FAILURE);
429 }
430 kp = &ksp->ks_ports[port_num];
431 kp->kp_cb = *cb;
432
433 return (USB_SUCCESS);
434 }
435
436 /*
437 * ds_unregister_cb
438 */
439 static void
keyspan_unregister_cb(ds_hdl_t hdl,uint_t port_num)440 keyspan_unregister_cb(ds_hdl_t hdl, uint_t port_num)
441 {
442 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
443 keyspan_port_t *kp;
444
445 if (port_num < ksp->ks_dev_spec.port_cnt) {
446 kp = &ksp->ks_ports[port_num];
447 bzero(&kp->kp_cb, sizeof (kp->kp_cb));
448 }
449 }
450
451 /*
452 * initialize hardware serial port
453 *
454 * 'open_pipes' specifies whether to open USB pipes or not
455 */
456 int
keyspan_open_hw_port(keyspan_port_t * kp,boolean_t open_pipes)457 keyspan_open_hw_port(keyspan_port_t *kp, boolean_t open_pipes)
458 {
459 int rval;
460 keyspan_state_t *ksp = kp->kp_ksp;
461
462 USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh,
463 "keyspan_open_hw_port: [%d]", kp->kp_port_num);
464
465 if (open_pipes) {
466
467 /* open r/w pipes for this port */
468 if ((rval = keyspan_open_port_pipes(kp)) != USB_SUCCESS) {
469
470 return (rval);
471 }
472 }
473
474 mutex_enter(&kp->kp_mutex);
475 kp->kp_state = KEYSPAN_PORT_OPEN;
476 mutex_exit(&kp->kp_mutex);
477
478 switch (ksp->ks_dev_spec.id_product) {
479 case KEYSPAN_USA19HS_PID:
480 case KEYSPAN_USA49WLC_PID:
481 if ((rval = keyspan_receive_data(&kp->kp_datain_pipe,
482 kp->kp_read_len, kp)) != USB_SUCCESS) {
483
484 goto fail;
485 }
486
487 break;
488
489 case KEYSPAN_USA49WG_PID:
490 mutex_enter(&ksp->ks_mutex);
491 /* open data in pipe the first time, start receiving data */
492 if ((ksp->ks_datain_open_cnt == 1) && open_pipes) {
493 mutex_exit(&ksp->ks_mutex);
494 if ((rval = keyspan_receive_data(&kp->kp_datain_pipe,
495 kp->kp_read_len, kp)) != USB_SUCCESS) {
496
497 goto fail;
498 }
499 /* the device is reconnected to host, restart receiving data */
500 } else if ((ksp->ks_reconnect_flag) && (!open_pipes)) {
501 mutex_exit(&ksp->ks_mutex);
502 if ((rval = keyspan_receive_data(&kp->kp_datain_pipe,
503 kp->kp_read_len, kp)) != USB_SUCCESS) {
504
505 goto fail;
506 }
507 mutex_enter(&ksp->ks_mutex);
508 ksp->ks_reconnect_flag = 0;
509 mutex_exit(&ksp->ks_mutex);
510
511 } else {
512 mutex_exit(&ksp->ks_mutex);
513 }
514
515 break;
516
517 default:
518 USB_DPRINTF_L2(DPRINT_OPEN, ksp->ks_lh, "keyspan_open_hw_port:"
519 "the device's product id can't be recognized");
520
521 return (USB_FAILURE);
522 }
523
524 /* set the default port parameters and send cmd msg to enable port */
525 mutex_enter(&kp->kp_mutex);
526 keyspan_default_port_params(kp);
527 mutex_exit(&kp->kp_mutex);
528
529 (void) keyspan_send_cmd(kp);
530
531 USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh,
532 "keyspan_open_hw_port: [%d] finished", kp->kp_port_num);
533
534 return (rval);
535
536 fail:
537
538 mutex_enter(&kp->kp_mutex);
539 kp->kp_state = KEYSPAN_PORT_CLOSED;
540 mutex_exit(&kp->kp_mutex);
541
542 if (open_pipes) {
543
544 /* close all ports' data pipes */
545 keyspan_close_port_pipes(kp);
546 }
547
548 USB_DPRINTF_L2(DPRINT_OPEN, kp->kp_lh,
549 "keyspan_open_hw_port: failed. This port can't be used.");
550
551 return (rval);
552 }
553
554 /*
555 * ds_open_port
556 */
557 static int
keyspan_open_port(ds_hdl_t hdl,uint_t port_num)558 keyspan_open_port(ds_hdl_t hdl, uint_t port_num)
559 {
560 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
561 keyspan_port_t *kp = &ksp->ks_ports[port_num];
562 int rval;
563
564 if (port_num >= ksp->ks_dev_spec.port_cnt) {
565
566 return (USB_FAILURE);
567 }
568 USB_DPRINTF_L4(DPRINT_OPEN, kp->kp_lh, "keyspan_open_port");
569
570 mutex_enter(&ksp->ks_mutex);
571 if (ksp->ks_dev_state == USB_DEV_DISCONNECTED) {
572 mutex_exit(&ksp->ks_mutex);
573
574 return (USB_FAILURE);
575 }
576 mutex_exit(&ksp->ks_mutex);
577
578 if (keyspan_pm_set_busy(ksp) != USB_SUCCESS) {
579
580 return (USB_FAILURE);
581 }
582
583 /*
584 * initialize state
585 */
586 mutex_enter(&kp->kp_mutex);
587 ASSERT(kp->kp_state == KEYSPAN_PORT_CLOSED);
588 ASSERT((kp->kp_rx_mp == NULL) && (kp->kp_tx_mp == NULL));
589
590 kp->kp_state = KEYSPAN_PORT_OPENING;
591 kp->kp_flags = 0;
592 mutex_exit(&kp->kp_mutex);
593
594 /*
595 * initialize hardware serial port, B_TRUE means open pipes
596 */
597 sema_p(&ksp->ks_pipes_sema);
598 rval = keyspan_open_hw_port(kp, B_TRUE);
599 if (rval != USB_SUCCESS) {
600 keyspan_pm_set_idle(ksp);
601 }
602 sema_v(&ksp->ks_pipes_sema);
603
604 return (rval);
605 }
606
607
608 /*
609 * close hardware serial port
610 */
611 void
keyspan_close_hw_port(keyspan_port_t * kp)612 keyspan_close_hw_port(keyspan_port_t *kp)
613 {
614 keyspan_state_t *ksp = kp->kp_ksp;
615
616 ASSERT(!mutex_owned(&kp->kp_mutex));
617
618 USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh,
619 "keyspan_close_hw_port");
620
621 /*
622 * The bulk IN/OUT pipes might have got closed due to
623 * a device disconnect event. So its required to check the
624 * pipe handle and proceed if it is not NULL
625 */
626
627 mutex_enter(&kp->kp_mutex);
628 if ((kp->kp_datain_pipe.pipe_handle == NULL) &&
629 (kp->kp_dataout_pipe.pipe_handle == NULL)) {
630 mutex_exit(&kp->kp_mutex);
631
632 return;
633 }
634
635 switch (ksp->ks_dev_spec.id_product) {
636 case KEYSPAN_USA19HS_PID:
637 keyspan_build_cmd_msg_usa19hs(kp, NULL);
638 kp->kp_ctrl_msg.usa19hs.portEnabled = 0;
639 kp->kp_ctrl_msg.usa19hs.rxFlush = 0;
640 kp->kp_ctrl_msg.usa19hs.txFlush = 0;
641 kp->kp_ctrl_msg.usa19hs.returnStatus = 0;
642 kp->kp_ctrl_msg.usa19hs.setRts = 1;
643 kp->kp_ctrl_msg.usa19hs.rts = 0;
644 kp->kp_ctrl_msg.usa19hs.setDtr = 1;
645 kp->kp_ctrl_msg.usa19hs.dtr = 0;
646 kp->kp_ctrl_msg.usa19hs.setTxFlowControl = 1;
647 kp->kp_ctrl_msg.usa19hs.txFlowControl = 0;
648 kp->kp_ctrl_msg.usa19hs.setRxFlowControl = 1;
649 kp->kp_ctrl_msg.usa19hs.rxFlowControl = 0;
650 kp->kp_ctrl_msg.usa19hs.rxForwardingTimeout = 0;
651 kp->kp_ctrl_msg.usa19hs.rxForwardingLength = 0;
652
653 break;
654
655
656 case KEYSPAN_USA49WLC_PID:
657 case KEYSPAN_USA49WG_PID:
658 keyspan_build_cmd_msg_usa49(kp, NULL);
659 kp->kp_ctrl_msg.usa49._txOn = 0;
660 kp->kp_ctrl_msg.usa49._txOff = 1;
661 kp->kp_ctrl_msg.usa49.txFlush = 0;
662 kp->kp_ctrl_msg.usa49.txBreak = 0;
663 kp->kp_ctrl_msg.usa49.rxOn = 0;
664 kp->kp_ctrl_msg.usa49.rxOff = 1;
665 kp->kp_ctrl_msg.usa49.rxFlush = 0;
666 kp->kp_ctrl_msg.usa49.rxForward = 0;
667 kp->kp_ctrl_msg.usa49.returnStatus = 0;
668 kp->kp_ctrl_msg.usa49.resetDataToggle = 0;
669 kp->kp_ctrl_msg.usa49.enablePort = 0;
670 kp->kp_ctrl_msg.usa49.disablePort = 1;
671
672 break;
673
674 default:
675 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
676 "keyspan_close_hw_port:"
677 "the device's product id can't be recognized");
678 mutex_exit(&kp->kp_mutex);
679
680 return;
681 }
682
683 mutex_exit(&kp->kp_mutex);
684 /* send close port cmd to this port */
685 if (keyspan_send_cmd(kp) != USB_SUCCESS) {
686 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
687 "keyspan_close_hw_port: closing hw port, send cmd FAILED");
688 }
689
690 /* blow away bulkin requests or pipe close will wait until timeout */
691 switch (ksp->ks_dev_spec.id_product) {
692 case KEYSPAN_USA19HS_PID:
693 case KEYSPAN_USA49WLC_PID:
694 usb_pipe_reset(ksp->ks_dip,
695 kp->kp_datain_pipe.pipe_handle,
696 USB_FLAGS_SLEEP, NULL, NULL);
697
698 break;
699 case KEYSPAN_USA49WG_PID:
700 mutex_enter(&ksp->ks_mutex);
701 /*
702 * if only this port is opened, shared data in pipe
703 * can be reset.
704 */
705 if (ksp->ks_datain_open_cnt == 1) {
706 mutex_exit(&ksp->ks_mutex);
707
708 usb_pipe_reset(ksp->ks_dip,
709 kp->kp_datain_pipe.pipe_handle,
710 USB_FLAGS_SLEEP, NULL, NULL);
711 } else {
712 mutex_exit(&ksp->ks_mutex);
713 }
714
715 break;
716 default:
717 USB_DPRINTF_L2(DPRINT_CLOSE, kp->kp_lh,
718 "keyspan_close_hw_port: the device's"
719 " product id can't be recognized");
720 }
721
722 (void) keyspan_close_port_pipes(kp);
723 }
724
725 /*
726 * ds_close_port
727 */
728 static int
keyspan_close_port(ds_hdl_t hdl,uint_t port_num)729 keyspan_close_port(ds_hdl_t hdl, uint_t port_num)
730 {
731 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
732 keyspan_port_t *kp = &ksp->ks_ports[port_num];
733
734 if (port_num >= ksp->ks_dev_spec.port_cnt) {
735
736 return (USB_FAILURE);
737 }
738 USB_DPRINTF_L4(DPRINT_CLOSE, kp->kp_lh, "keyspan_close_port");
739
740 sema_p(&ksp->ks_pipes_sema);
741 mutex_enter(&kp->kp_mutex);
742 kp->kp_no_more_reads = B_TRUE;
743
744 /* close hardware serial port */
745 mutex_exit(&kp->kp_mutex);
746
747 keyspan_close_hw_port(kp);
748 mutex_enter(&kp->kp_mutex);
749
750 /*
751 * free resources and finalize state
752 */
753 if (kp->kp_rx_mp) {
754 freemsg(kp->kp_rx_mp);
755 kp->kp_rx_mp = NULL;
756 }
757 if (kp->kp_tx_mp) {
758 freemsg(kp->kp_tx_mp);
759 kp->kp_tx_mp = NULL;
760 }
761
762 kp->kp_no_more_reads = B_FALSE;
763 kp->kp_state = KEYSPAN_PORT_CLOSED;
764 mutex_exit(&kp->kp_mutex);
765
766 keyspan_pm_set_idle(ksp);
767
768 sema_v(&ksp->ks_pipes_sema);
769
770 return (USB_SUCCESS);
771 }
772
773 /*
774 * power management
775 *
776 * ds_usb_power
777 */
778 /*ARGSUSED*/
779 static int
keyspan_usb_power(ds_hdl_t hdl,int comp,int level,int * new_state)780 keyspan_usb_power(ds_hdl_t hdl, int comp, int level, int *new_state)
781 {
782 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
783 keyspan_pm_t *pm = ksp->ks_pm;
784 int rval;
785
786 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_usb_power");
787
788 mutex_enter(&ksp->ks_mutex);
789
790 /*
791 * check if we are transitioning to a legal power level
792 */
793 if (USB_DEV_PWRSTATE_OK(pm->pm_pwr_states, level)) {
794 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh, "keyspan_usb_power:"
795 "illegal power level %d, pwr_states=%x",
796 level, pm->pm_pwr_states);
797 mutex_exit(&ksp->ks_mutex);
798
799 return (USB_FAILURE);
800 }
801
802 /*
803 * if we are about to raise power and asked to lower power, fail
804 */
805 if (pm->pm_raise_power && (level < (int)pm->pm_cur_power)) {
806 mutex_exit(&ksp->ks_mutex);
807
808 return (USB_FAILURE);
809 }
810
811 switch (level) {
812 case USB_DEV_OS_PWR_OFF:
813 rval = keyspan_pwrlvl0(ksp);
814
815 break;
816 case USB_DEV_OS_PWR_1:
817 rval = keyspan_pwrlvl1(ksp);
818
819 break;
820 case USB_DEV_OS_PWR_2:
821 rval = keyspan_pwrlvl2(ksp);
822
823 break;
824 case USB_DEV_OS_FULL_PWR:
825 rval = keyspan_pwrlvl3(ksp);
826 /*
827 * If usbser dev_state is DISCONNECTED or SUSPENDED, it shows
828 * that the usb serial device is disconnected/suspended while it
829 * is under power down state, now the device is powered up
830 * before it is reconnected/resumed. xxx_pwrlvl3() will set dev
831 * state to ONLINE, we need to set the dev state back to
832 * DISCONNECTED/SUSPENDED.
833 */
834 if ((rval == USB_SUCCESS) &&
835 ((*new_state == USB_DEV_DISCONNECTED) ||
836 (*new_state == USB_DEV_SUSPENDED))) {
837 ksp->ks_dev_state = *new_state;
838 }
839
840 break;
841 default:
842 ASSERT(0); /* cannot happen */
843 }
844
845 *new_state = ksp->ks_dev_state;
846 mutex_exit(&ksp->ks_mutex);
847
848 return (rval);
849 }
850
851
852 /*
853 * ds_suspend
854 */
855 static int
keyspan_suspend(ds_hdl_t hdl)856 keyspan_suspend(ds_hdl_t hdl)
857 {
858 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
859 int state = USB_DEV_SUSPENDED;
860
861 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_suspend");
862
863 /*
864 * If the device is suspended while it is under PWRED_DOWN state, we
865 * need to keep the PWRED_DOWN state so that it could be powered up
866 * later. In the mean while, usbser dev state will be changed to
867 * SUSPENDED state.
868 */
869 mutex_enter(&ksp->ks_mutex);
870 if (ksp->ks_dev_state != USB_DEV_PWRED_DOWN) {
871 ksp->ks_dev_state = USB_DEV_SUSPENDED;
872 }
873 mutex_exit(&ksp->ks_mutex);
874
875 keyspan_disconnect_pipes(ksp);
876
877 return (state);
878 }
879
880
881 /*
882 * ds_resume
883 */
884 static int
keyspan_resume(ds_hdl_t hdl)885 keyspan_resume(ds_hdl_t hdl)
886 {
887 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
888 int current_state;
889 int rval;
890
891 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_resume");
892
893 mutex_enter(&ksp->ks_mutex);
894 current_state = ksp->ks_dev_state;
895 mutex_exit(&ksp->ks_mutex);
896
897 if (current_state != USB_DEV_ONLINE) {
898 rval = keyspan_restore_device_state(ksp);
899 } else {
900 rval = USB_SUCCESS;
901 }
902
903 return (rval);
904 }
905
906
907 /*
908 * ds_disconnect
909 */
910 static int
keyspan_disconnect(ds_hdl_t hdl)911 keyspan_disconnect(ds_hdl_t hdl)
912 {
913 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
914 int state = USB_DEV_DISCONNECTED;
915
916 USB_DPRINTF_L4(DPRINT_HOTPLUG, ksp->ks_lh, "keyspan_disconnect");
917
918 /*
919 * If the device is disconnected while it is under PWRED_DOWN state, we
920 * need to keep the PWRED_DOWN state so that it could be powered up
921 * later. In the mean while, usbser dev state will be changed to
922 * DISCONNECTED state.
923 */
924 mutex_enter(&ksp->ks_mutex);
925 if (ksp->ks_dev_state != USB_DEV_PWRED_DOWN) {
926 ksp->ks_dev_state = USB_DEV_DISCONNECTED;
927 }
928 mutex_exit(&ksp->ks_mutex);
929
930 keyspan_disconnect_pipes(ksp);
931
932 return (state);
933 }
934
935
936 /*
937 * ds_reconnect
938 */
939 static int
keyspan_reconnect(ds_hdl_t hdl)940 keyspan_reconnect(ds_hdl_t hdl)
941 {
942 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
943
944 USB_DPRINTF_L4(DPRINT_HOTPLUG, ksp->ks_lh, "keyspan_reconnect");
945
946 return (keyspan_restore_device_state(ksp));
947 }
948
949 /*
950 * ds_set_port_params
951 */
952 static int
keyspan_set_port_params(ds_hdl_t hdl,uint_t port_num,ds_port_params_t * tp)953 keyspan_set_port_params(ds_hdl_t hdl, uint_t port_num, ds_port_params_t *tp)
954 {
955 int cnt = tp->tp_cnt;
956 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
957 keyspan_port_t *kp = &ksp->ks_ports[port_num];
958
959 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
960 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
961 "keyspan_set_port_params: port: %d params", cnt);
962
963 if (cnt <= 0) {
964
965 return (USB_SUCCESS);
966 }
967
968 mutex_enter(&kp->kp_mutex);
969 ASSERT((kp->kp_state == KEYSPAN_PORT_OPENING) ||
970 (kp->kp_state == KEYSPAN_PORT_OPEN));
971 keyspan_build_cmd_msg(kp, tp);
972 mutex_exit(&kp->kp_mutex);
973
974 if (keyspan_send_cmd(kp) != USB_SUCCESS) {
975 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
976 "keyspan_send_cmd() FAILED");
977
978 return (USB_FAILURE);
979 }
980
981 return (USB_SUCCESS);
982 }
983
984
985 /*
986 * ds_set_modem_ctl
987 */
988 static int
keyspan_set_modem_ctl(ds_hdl_t hdl,uint_t port_num,int mask,int val)989 keyspan_set_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int val)
990 {
991 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
992 keyspan_port_t *kp = &ksp->ks_ports[port_num];
993
994 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
995
996 mutex_enter(&kp->kp_mutex);
997 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_set_modem_ctl: "
998 "mask=%x, val=%x", mask, val);
999
1000 keyspan_build_cmd_msg(kp, NULL);
1001
1002 switch (ksp->ks_dev_spec.id_product) {
1003 case KEYSPAN_USA19HS_PID:
1004 if (mask & TIOCM_RTS) {
1005
1006 kp->kp_ctrl_msg.usa19hs.setRts = 0x01;
1007
1008 if (val & TIOCM_RTS) {
1009 kp->kp_ctrl_msg.usa19hs.rts = 0x1;
1010 } else {
1011 kp->kp_ctrl_msg.usa19hs.rts = 0x0;
1012 }
1013
1014 } else {
1015 kp->kp_ctrl_msg.usa19hs.setRts = 0x0;
1016 }
1017
1018 if (mask & TIOCM_DTR) {
1019 kp->kp_ctrl_msg.usa19hs.setDtr = 0x01;
1020
1021 if (val & TIOCM_DTR) {
1022 kp->kp_ctrl_msg.usa19hs.dtr = 0x1;
1023 } else {
1024 kp->kp_ctrl_msg.usa19hs.dtr = 0x0;
1025 }
1026
1027 } else {
1028 kp->kp_ctrl_msg.usa19hs.setDtr = 0x0;
1029 }
1030
1031 break;
1032
1033
1034 case KEYSPAN_USA49WLC_PID:
1035 case KEYSPAN_USA49WG_PID:
1036 if (mask & TIOCM_RTS) {
1037
1038 kp->kp_ctrl_msg.usa49.setRts = 0x1;
1039
1040 if (val & TIOCM_RTS) {
1041 kp->kp_ctrl_msg.usa49.rts = 0x1;
1042 } else {
1043 kp->kp_ctrl_msg.usa49.rts = 0x0;
1044 }
1045
1046 } else {
1047 kp->kp_ctrl_msg.usa49.setRts = 0x0;
1048 }
1049
1050 if (mask & TIOCM_DTR) {
1051 kp->kp_ctrl_msg.usa49.setDtr = 0x1;
1052
1053 if (val & TIOCM_DTR) {
1054 kp->kp_ctrl_msg.usa49.dtr = 0x1;
1055 } else {
1056 kp->kp_ctrl_msg.usa49.dtr = 0x0;
1057 }
1058
1059 } else {
1060 kp->kp_ctrl_msg.usa49.setDtr = 0x0;
1061 }
1062
1063 break;
1064
1065 default:
1066 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
1067 "keyspan_get_modem_ctl:"
1068 "the device's product id can't be recognized");
1069 mutex_exit(&kp->kp_mutex);
1070
1071 return (USB_FAILURE);
1072 }
1073
1074 mutex_exit(&kp->kp_mutex);
1075
1076 if (keyspan_send_cmd(kp) != USB_SUCCESS) {
1077 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
1078 "keyspan_send_cmd() FAILED");
1079
1080 return (USB_FAILURE);
1081 }
1082
1083 return (USB_SUCCESS);
1084 }
1085
1086 /*
1087 * ds_get_modem_ctl
1088 */
1089 static int
keyspan_get_modem_ctl(ds_hdl_t hdl,uint_t port_num,int mask,int * valp)1090 keyspan_get_modem_ctl(ds_hdl_t hdl, uint_t port_num, int mask, int *valp)
1091 {
1092 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1093 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1094 int val = 0;
1095
1096 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1097
1098 mutex_enter(&kp->kp_mutex);
1099
1100 /*
1101 * rts and dtr are not in status_msg, but we can get it from
1102 * status_flag since it represents what we set the device last time.
1103 */
1104 if (kp->kp_status_flag & KEYSPAN_PORT_RTS) {
1105 val |= TIOCM_RTS;
1106 }
1107 if (kp->kp_status_flag & KEYSPAN_PORT_DTR) {
1108 val |= TIOCM_DTR;
1109 }
1110
1111 /* usbser don't deal with TIOCM_RI status */
1112 switch (ksp->ks_dev_spec.id_product) {
1113 case KEYSPAN_USA19HS_PID:
1114 if (kp->kp_status_msg.usa19hs.dcd) {
1115 val |= TIOCM_CD;
1116 }
1117 if (kp->kp_status_msg.usa19hs.cts) {
1118 val |= TIOCM_CTS;
1119 }
1120 if (kp->kp_status_msg.usa19hs.dsr) {
1121 val |= TIOCM_DSR;
1122 }
1123 break;
1124
1125
1126 case KEYSPAN_USA49WLC_PID:
1127 case KEYSPAN_USA49WG_PID:
1128 if (kp->kp_status_msg.usa49.dcd) {
1129 val |= TIOCM_CD;
1130 }
1131 if (kp->kp_status_msg.usa49.cts) {
1132 val |= TIOCM_CTS;
1133 }
1134 if (kp->kp_status_msg.usa49.dsr) {
1135 val |= TIOCM_DSR;
1136 }
1137 break;
1138
1139 default:
1140 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
1141 "keyspan_get_modem_ctl:"
1142 "the device's product id can't be recognized");
1143 mutex_exit(&kp->kp_mutex);
1144
1145 return (USB_FAILURE);
1146 }
1147
1148 *valp = val & mask;
1149
1150 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_get_modem_ctl:"
1151 "success. status_flag = %x, val=0%o",
1152 kp->kp_status_flag, *valp);
1153
1154 mutex_exit(&kp->kp_mutex);
1155
1156 return (USB_SUCCESS);
1157 }
1158
1159
1160 /*
1161 * ds_break_ctl
1162 */
1163 static int
keyspan_break_ctl(ds_hdl_t hdl,uint_t port_num,int ctl)1164 keyspan_break_ctl(ds_hdl_t hdl, uint_t port_num, int ctl)
1165 {
1166 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1167 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1168 int is_break;
1169 int rval = USB_SUCCESS;
1170
1171 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1172 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
1173 "keyspan_break_ctl: ctl = %s", (ctl == DS_ON) ? "on" : "off");
1174
1175 mutex_enter(&kp->kp_mutex);
1176 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN);
1177 ASSERT(ctl == DS_ON || ctl == DS_OFF);
1178
1179 is_break = kp->kp_status_flag & KEYSPAN_PORT_TXBREAK;
1180
1181 if ((ctl == DS_ON) && !is_break) {
1182
1183 keyspan_build_cmd_msg(kp, NULL);
1184
1185 switch (ksp->ks_dev_spec.id_product) {
1186 case KEYSPAN_USA19HS_PID:
1187 kp->kp_ctrl_msg.usa19hs.txBreak = 1;
1188
1189 break;
1190
1191 case KEYSPAN_USA49WLC_PID:
1192 case KEYSPAN_USA49WG_PID:
1193 kp->kp_ctrl_msg.usa49.txBreak = 1;
1194
1195 break;
1196
1197 default:
1198 mutex_exit(&kp->kp_mutex);
1199 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
1200 "keyspan_break_ctl:"
1201 "the device's product id can't be recognized");
1202
1203 return (USB_FAILURE);
1204 }
1205
1206 mutex_exit(&kp->kp_mutex);
1207 rval = keyspan_send_cmd(kp);
1208 return (rval);
1209 }
1210
1211 if ((ctl == DS_OFF) && is_break) {
1212 keyspan_build_cmd_msg(kp, NULL);
1213
1214 switch (ksp->ks_dev_spec.id_product) {
1215 case KEYSPAN_USA19HS_PID:
1216 kp->kp_ctrl_msg.usa19hs.txBreak = 0;
1217
1218 break;
1219
1220 case KEYSPAN_USA49WLC_PID:
1221 case KEYSPAN_USA49WG_PID:
1222 kp->kp_ctrl_msg.usa49._txOn = 1;
1223 kp->kp_ctrl_msg.usa49.txBreak = 0;
1224
1225 break;
1226
1227 default:
1228 mutex_exit(&kp->kp_mutex);
1229 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
1230 "keyspan_break_ctl:"
1231 "the device's product id can't be recognized");
1232
1233 return (USB_FAILURE);
1234 }
1235
1236 mutex_exit(&kp->kp_mutex);
1237 rval = keyspan_send_cmd(kp);
1238 if (rval == USB_SUCCESS) {
1239 mutex_enter(&kp->kp_mutex);
1240
1241 /* resume transmit */
1242 keyspan_tx_start(kp, NULL);
1243 mutex_exit(&kp->kp_mutex);
1244 }
1245
1246 return (rval);
1247 }
1248
1249 mutex_exit(&kp->kp_mutex);
1250 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
1251 "keyspan_break_ctl: not necessary to set break, is_break = %d",
1252 is_break);
1253
1254 return (rval);
1255 }
1256
1257
1258 /*
1259 * ds_loopback
1260 */
1261 static int
keyspan_loopback(ds_hdl_t hdl,uint_t port_num,int ctl)1262 keyspan_loopback(ds_hdl_t hdl, uint_t port_num, int ctl)
1263 {
1264 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1265 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1266 int is_loop;
1267 int rval = USB_SUCCESS;
1268
1269 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1270 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
1271 "keyspan_loopback: %s", (ctl == DS_ON) ? "on" : "off");
1272
1273 mutex_enter(&kp->kp_mutex);
1274 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN);
1275 ASSERT(ctl == DS_ON || ctl == DS_OFF);
1276
1277 /* check bit indicating internal loopback state */
1278 is_loop = kp->kp_status_flag & KEYSPAN_PORT_LOOPBACK;
1279
1280 if ((ctl == DS_ON) && !is_loop) {
1281
1282 keyspan_build_cmd_msg(kp, NULL);
1283 switch (ksp->ks_dev_spec.id_product) {
1284 case KEYSPAN_USA19HS_PID:
1285 kp->kp_ctrl_msg.usa19hs.loopbackMode = 0;
1286
1287 break;
1288
1289 case KEYSPAN_USA49WLC_PID:
1290 case KEYSPAN_USA49WG_PID:
1291 kp->kp_ctrl_msg.usa49.loopbackMode = 0;
1292
1293 break;
1294
1295 default:
1296 mutex_exit(&kp->kp_mutex);
1297 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
1298 "keyspan_loopback:"
1299 "the device's product id can't be recognized");
1300
1301 return (USB_FAILURE);
1302 }
1303 mutex_exit(&kp->kp_mutex);
1304 rval = keyspan_send_cmd(kp);
1305 } else if ((ctl == DS_OFF) && is_loop) {
1306
1307 keyspan_build_cmd_msg(kp, NULL);
1308 switch (ksp->ks_dev_spec.id_product) {
1309 case KEYSPAN_USA19HS_PID:
1310 kp->kp_ctrl_msg.usa19hs.loopbackMode = 1;
1311
1312 break;
1313
1314 case KEYSPAN_USA49WLC_PID:
1315 case KEYSPAN_USA49WG_PID:
1316 kp->kp_ctrl_msg.usa49.loopbackMode = 1;
1317
1318 break;
1319
1320 default:
1321 mutex_exit(&kp->kp_mutex);
1322 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
1323 "keyspan_loopback:"
1324 "the device's product id can't be recognized");
1325
1326 return (USB_FAILURE);
1327 }
1328 mutex_exit(&kp->kp_mutex);
1329 rval = keyspan_send_cmd(kp);
1330 } else {
1331 mutex_exit(&kp->kp_mutex);
1332 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
1333 "keyspan_loopback: not necessary to set loopback,"
1334 "is_loop = %d", is_loop);
1335 }
1336
1337 return (rval);
1338 }
1339
1340
1341 /*
1342 * ds_tx
1343 */
1344 static int
keyspan_tx(ds_hdl_t hdl,uint_t port_num,mblk_t * mp)1345 keyspan_tx(ds_hdl_t hdl, uint_t port_num, mblk_t *mp)
1346 {
1347 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1348 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1349 int xferd;
1350
1351 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1352 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_tx");
1353
1354 /*
1355 * sanity checks
1356 */
1357 if (mp == NULL) {
1358 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh, "keyspan_tx: mp=NULL");
1359
1360 return (USB_SUCCESS);
1361 }
1362
1363 kp = &ksp->ks_ports[port_num];
1364
1365 mutex_enter(&kp->kp_mutex);
1366
1367 keyspan_put_tail(&kp->kp_tx_mp, mp); /* add to the chain */
1368
1369 keyspan_tx_start(kp, &xferd); /* go! */
1370
1371 mutex_exit(&kp->kp_mutex);
1372
1373 return (USB_SUCCESS);
1374 }
1375
1376
1377 /*
1378 * ds_rx. the real data receiving is in keyspan_open_hw_port
1379 */
1380 static mblk_t *
keyspan_rx(ds_hdl_t hdl,uint_t port_num)1381 keyspan_rx(ds_hdl_t hdl, uint_t port_num)
1382 {
1383 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1384 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1385 mblk_t *mp;
1386
1387 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1388 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_rx");
1389
1390 mutex_enter(&kp->kp_mutex);
1391 mp = kp->kp_rx_mp;
1392 kp->kp_rx_mp = NULL;
1393 mutex_exit(&kp->kp_mutex);
1394
1395 return (mp);
1396 }
1397
1398
1399 /*
1400 * ds_stop
1401 */
1402 static void
keyspan_stop(ds_hdl_t hdl,uint_t port_num,int dir)1403 keyspan_stop(ds_hdl_t hdl, uint_t port_num, int dir)
1404 {
1405 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1406 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1407
1408 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1409 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_stop");
1410
1411 if (dir & DS_TX) {
1412 mutex_enter(&kp->kp_mutex);
1413 kp->kp_flags |= KEYSPAN_PORT_TX_STOPPED;
1414 mutex_exit(&kp->kp_mutex);
1415 }
1416 }
1417
1418
1419 /*
1420 * ds_start
1421 */
1422 static void
keyspan_start(ds_hdl_t hdl,uint_t port_num,int dir)1423 keyspan_start(ds_hdl_t hdl, uint_t port_num, int dir)
1424 {
1425 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1426 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1427
1428 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1429 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_start");
1430
1431 if (dir & DS_TX) {
1432 mutex_enter(&kp->kp_mutex);
1433 if (kp->kp_flags & KEYSPAN_PORT_TX_STOPPED) {
1434 kp->kp_flags &= ~KEYSPAN_PORT_TX_STOPPED;
1435 keyspan_tx_start(kp, NULL);
1436 }
1437 mutex_exit(&kp->kp_mutex);
1438 }
1439 }
1440
1441
1442 /*
1443 * ds_fifo_flush
1444 * send flush cmd and wait for completion, then turn off the flush.
1445 */
1446 static int
keyspan_fifo_flush(ds_hdl_t hdl,uint_t port_num,int dir)1447 keyspan_fifo_flush(ds_hdl_t hdl, uint_t port_num, int dir)
1448 {
1449 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1450 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1451
1452 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1453 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
1454 "keyspan_fifo_flush: dir=%x", dir);
1455
1456 mutex_enter(&kp->kp_mutex);
1457 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN);
1458
1459 /* discard the data in DSD buffers */
1460 if ((dir & DS_TX) && kp->kp_tx_mp) {
1461 freemsg(kp->kp_tx_mp);
1462 kp->kp_tx_mp = NULL;
1463 }
1464 if ((dir & DS_RX) && kp->kp_rx_mp) {
1465 freemsg(kp->kp_rx_mp);
1466 kp->kp_rx_mp = NULL;
1467 }
1468
1469 mutex_exit(&kp->kp_mutex);
1470
1471 return (USB_SUCCESS);
1472 }
1473
1474 /*
1475 * ds_fifo_drain
1476 *
1477 * it is the caller's responsibility to cease submitting new tx data
1478 * while this function executes
1479 */
1480 static int
keyspan_fifo_drain(ds_hdl_t hdl,uint_t port_num,int timeout)1481 keyspan_fifo_drain(ds_hdl_t hdl, uint_t port_num, int timeout)
1482 {
1483 keyspan_state_t *ksp = (keyspan_state_t *)hdl;
1484 keyspan_port_t *kp = &ksp->ks_ports[port_num];
1485 int rval = USB_SUCCESS;
1486
1487 ASSERT(port_num < ksp->ks_dev_spec.port_cnt);
1488 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
1489 "keyspan_fifo_drain, timeout = %d", timeout);
1490
1491 mutex_enter(&kp->kp_mutex);
1492 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN);
1493
1494 /* wait until local data drains */
1495 if (keyspan_wait_tx_drain(kp, 0) != USB_SUCCESS) {
1496 mutex_exit(&kp->kp_mutex);
1497
1498 return (USB_FAILURE);
1499 }
1500 mutex_exit(&kp->kp_mutex);
1501
1502 /* wait until hw fifo drains */
1503 delay(drv_usectohz(500*1000));
1504
1505 return (rval);
1506 }
1507
1508
1509 /*
1510 * configuration routines
1511 * ----------------------
1512 *
1513 */
1514
1515 /*
1516 * free state structure
1517 */
1518 static void
keyspan_free_soft_state(keyspan_state_t * ksp)1519 keyspan_free_soft_state(keyspan_state_t *ksp)
1520 {
1521 kmem_free(ksp, sizeof (keyspan_state_t));
1522 }
1523
1524
1525 /*
1526 * register/unregister USBA client
1527 */
1528 static int
keyspan_usb_register(keyspan_state_t * ksp)1529 keyspan_usb_register(keyspan_state_t *ksp)
1530 {
1531 int rval;
1532
1533 rval = usb_client_attach(ksp->ks_dip, USBDRV_VERSION, 0);
1534 if (rval == USB_SUCCESS) {
1535 rval = usb_get_dev_data(ksp->ks_dip, &ksp->ks_dev_data,
1536 USB_PARSE_LVL_IF, 0);
1537 if (rval == USB_SUCCESS) {
1538 ksp->ks_lh =
1539 usb_alloc_log_hdl(ksp->ks_dip, "keyspan[*].",
1540 &keyspan_errlevel, &keyspan_errmask,
1541 &keyspan_instance_debug, 0);
1542
1543 ksp->ks_def_pipe.pipe_handle =
1544 ksp->ks_dev_data->dev_default_ph;
1545 ksp->ks_def_pipe.pipe_ksp = ksp;
1546 ksp->ks_def_pipe.pipe_lh = ksp->ks_lh;
1547 }
1548 }
1549
1550 return (rval);
1551 }
1552
1553
1554 static void
keyspan_usb_unregister(keyspan_state_t * ksp)1555 keyspan_usb_unregister(keyspan_state_t *ksp)
1556 {
1557 usb_free_log_hdl(ksp->ks_lh);
1558 ksp->ks_lh = NULL;
1559 usb_client_detach(ksp->ks_dip, ksp->ks_dev_data);
1560 ksp->ks_def_pipe.pipe_handle = NULL;
1561 ksp->ks_dev_data = NULL;
1562 }
1563
1564
1565 /*
1566 * init/fini soft state during attach
1567 */
1568 static void
keyspan_init_sync_objs(keyspan_state_t * ksp)1569 keyspan_init_sync_objs(keyspan_state_t *ksp)
1570 {
1571 mutex_init(&ksp->ks_mutex, NULL, MUTEX_DRIVER,
1572 ksp->ks_dev_data->dev_iblock_cookie);
1573 sema_init(&ksp->ks_pipes_sema, 1, NULL, SEMA_DRIVER, NULL);
1574 }
1575
1576
1577 static void
keyspan_fini_sync_objs(keyspan_state_t * ksp)1578 keyspan_fini_sync_objs(keyspan_state_t *ksp)
1579 {
1580 mutex_destroy(&ksp->ks_mutex);
1581 sema_destroy(&ksp->ks_pipes_sema);
1582 }
1583
1584
1585 /*
1586 * device specific attributes
1587 */
1588 static int
keyspan_attach_dev(keyspan_state_t * ksp)1589 keyspan_attach_dev(keyspan_state_t *ksp)
1590 {
1591
1592 mutex_enter(&ksp->ks_mutex);
1593 switch (ksp->ks_dev_data->dev_descr->idProduct) {
1594 case KEYSPAN_USA19HS_PID:
1595 ksp->ks_dev_spec.id_product = KEYSPAN_USA19HS_PID;
1596 ksp->ks_dev_spec.port_cnt = 1;
1597 ksp->ks_dev_spec.ctrl_ep_addr = 0x02;
1598 ksp->ks_dev_spec.stat_ep_addr = 0x82;
1599 ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01;
1600 ksp->ks_dev_spec.datain_ep_addr[0] = 0x81;
1601
1602 break;
1603
1604 case KEYSPAN_USA49WLC_PID:
1605 ksp->ks_dev_spec.id_product = KEYSPAN_USA49WLC_PID;
1606 ksp->ks_dev_spec.port_cnt = 4;
1607 ksp->ks_dev_spec.ctrl_ep_addr = 0x07;
1608 ksp->ks_dev_spec.stat_ep_addr = 0x87;
1609 ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01;
1610 ksp->ks_dev_spec.dataout_ep_addr[1] = 0x02;
1611 ksp->ks_dev_spec.dataout_ep_addr[2] = 0x03;
1612 ksp->ks_dev_spec.dataout_ep_addr[3] = 0x04;
1613 ksp->ks_dev_spec.datain_ep_addr[0] = 0x81;
1614 ksp->ks_dev_spec.datain_ep_addr[1] = 0x82;
1615 ksp->ks_dev_spec.datain_ep_addr[2] = 0x83;
1616 ksp->ks_dev_spec.datain_ep_addr[3] = 0x84;
1617
1618 break;
1619
1620 case KEYSPAN_USA49WG_PID:
1621 ksp->ks_dev_spec.id_product = KEYSPAN_USA49WG_PID;
1622 ksp->ks_dev_spec.port_cnt = 4;
1623 ksp->ks_dev_spec.stat_ep_addr = 0x81;
1624 ksp->ks_dev_spec.dataout_ep_addr[0] = 0x01;
1625 ksp->ks_dev_spec.dataout_ep_addr[1] = 0x02;
1626 ksp->ks_dev_spec.dataout_ep_addr[2] = 0x04;
1627 ksp->ks_dev_spec.dataout_ep_addr[3] = 0x06;
1628 ksp->ks_dev_spec.datain_ep_addr[0] = 0x88;
1629 ksp->ks_dev_spec.datain_ep_addr[1] = 0x88;
1630 ksp->ks_dev_spec.datain_ep_addr[2] = 0x88;
1631 ksp->ks_dev_spec.datain_ep_addr[3] = 0x88;
1632
1633 break;
1634
1635 default:
1636 mutex_exit(&ksp->ks_mutex);
1637 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
1638 "keyspan_attach_dev:"
1639 "the device's product id can't be recognized");
1640
1641 return (USB_FAILURE);
1642 }
1643
1644 mutex_exit(&ksp->ks_mutex);
1645
1646 return (USB_SUCCESS);
1647 }
1648
1649 /*
1650 * allocate and initialize per port resources.
1651 */
1652 static void
keyspan_attach_ports(keyspan_state_t * ksp)1653 keyspan_attach_ports(keyspan_state_t *ksp)
1654 {
1655 int i;
1656 keyspan_port_t *kp;
1657
1658 ksp->ks_ports = kmem_zalloc(ksp->ks_dev_spec.port_cnt *
1659 sizeof (keyspan_port_t), KM_SLEEP);
1660
1661 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
1662 kp = &ksp->ks_ports[i];
1663 kp->kp_port_num = i;
1664 kp->kp_ksp = ksp;
1665
1666 (void) sprintf(kp->kp_lh_name, "keyspan[%d].", i);
1667 kp->kp_lh = usb_alloc_log_hdl(ksp->ks_dip, kp->kp_lh_name,
1668 &keyspan_errlevel, &keyspan_errmask,
1669 &keyspan_instance_debug, 0);
1670
1671 kp->kp_state = KEYSPAN_PORT_CLOSED;
1672 mutex_init(&kp->kp_mutex, NULL, MUTEX_DRIVER,
1673 ksp->ks_dev_data->dev_iblock_cookie);
1674 cv_init(&kp->kp_tx_cv, NULL, CV_DRIVER, NULL);
1675 }
1676 }
1677
1678
1679 /*
1680 * free per port resources
1681 */
1682 static void
keyspan_detach_ports(keyspan_state_t * ksp)1683 keyspan_detach_ports(keyspan_state_t *ksp)
1684 {
1685 int i;
1686 keyspan_port_t *kp;
1687
1688 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
1689 kp = &ksp->ks_ports[i];
1690 if (kp->kp_state != KEYSPAN_PORT_NOT_INIT) {
1691 ASSERT(kp->kp_state == KEYSPAN_PORT_CLOSED);
1692
1693 mutex_destroy(&kp->kp_mutex);
1694 cv_destroy(&kp->kp_tx_cv);
1695 usb_free_log_hdl(kp->kp_lh);
1696 }
1697 }
1698 kmem_free(ksp->ks_ports,
1699 ksp->ks_dev_spec.port_cnt * sizeof (keyspan_port_t));
1700 }
1701
1702 static void
keyspan_init_port_params(keyspan_state_t * ksp)1703 keyspan_init_port_params(keyspan_state_t *ksp)
1704 {
1705 int i;
1706 size_t sz;
1707 uint_t read_len;
1708 uint_t write_len;
1709
1710 /* the max data len of every bulk in req. */
1711 if (usb_pipe_get_max_bulk_transfer_size(ksp->ks_dip, &sz) ==
1712 USB_SUCCESS) {
1713 if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) {
1714 read_len = (uint_t)min(sz, KEYSPAN_BULKIN_MAX_LEN_49WG);
1715 } else {
1716 read_len = (uint_t)min(sz, KEYSPAN_BULKIN_MAX_LEN);
1717 }
1718 } else {
1719 if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) {
1720 read_len = KEYSPAN_BULKIN_MAX_LEN_49WG;
1721 } else {
1722 read_len = KEYSPAN_BULKIN_MAX_LEN;
1723 }
1724 }
1725
1726 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
1727 ksp->ks_ports[i].kp_read_len = read_len;
1728 /* the max data len of every bulk out req. */
1729 switch (ksp->ks_dev_spec.id_product) {
1730 case KEYSPAN_USA19HS_PID:
1731 ksp->ks_ports[i].kp_write_len =
1732 KEYSPAN_BULKOUT_MAX_LEN_19HS;
1733
1734 break;
1735 case KEYSPAN_USA49WLC_PID:
1736 ksp->ks_ports[i].kp_write_len =
1737 KEYSPAN_BULKOUT_MAX_LEN_49WLC;
1738
1739 break;
1740 case KEYSPAN_USA49WG_PID:
1741 /*
1742 * USA49WG port0 uses intr out pipe send data while
1743 * other ports use bulk out pipes, so port0's max
1744 * packet length for "bulk out" is different from other
1745 * ports' while the same as USA49WLC.
1746 */
1747 write_len = ((i == 0) ? KEYSPAN_BULKOUT_MAX_LEN_49WLC :
1748 KEYSPAN_BULKOUT_MAX_LEN_49WG);
1749 ksp->ks_ports[i].kp_write_len = write_len;
1750
1751 break;
1752 default:
1753 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
1754 "keyspan_init_port_params:"
1755 "the device's product id can't be recognized");
1756
1757 return;
1758 }
1759 }
1760 }
1761
1762
1763 /*
1764 * free descriptor tree
1765 */
1766 static void
keyspan_free_descr_tree(keyspan_state_t * ksp)1767 keyspan_free_descr_tree(keyspan_state_t *ksp)
1768 {
1769 usb_free_descr_tree(ksp->ks_dip, ksp->ks_dev_data);
1770
1771 }
1772
1773
1774 /*
1775 * register/unregister USB event callbacks
1776 */
1777 static int
keyspan_register_events(keyspan_state_t * ksp)1778 keyspan_register_events(keyspan_state_t *ksp)
1779 {
1780 return (usb_register_event_cbs(ksp->ks_dip, ksp->ks_usb_events, 0));
1781 }
1782
1783
1784 static void
keyspan_unregister_events(keyspan_state_t * ksp)1785 keyspan_unregister_events(keyspan_state_t *ksp)
1786 {
1787 usb_unregister_event_cbs(ksp->ks_dip, ksp->ks_usb_events);
1788 }
1789
1790
1791 static void
keyspan_set_dev_state_online(keyspan_state_t * ksp)1792 keyspan_set_dev_state_online(keyspan_state_t *ksp)
1793 {
1794 ksp->ks_dev_state = USB_DEV_ONLINE;
1795 }
1796
1797 /*
1798 * send command to the port and save the params after its completion for
1799 * USA19HS and USA49WLC
1800 */
1801 int
keyspan_send_cmd_usa49(keyspan_port_t * kp)1802 keyspan_send_cmd_usa49(keyspan_port_t *kp)
1803 {
1804 keyspan_state_t *ksp = kp->kp_ksp;
1805 mblk_t *mp;
1806 int rval = USB_SUCCESS;
1807 int size;
1808 usb_bulk_req_t *br;
1809
1810 ASSERT(!mutex_owned(&kp->kp_mutex));
1811 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49");
1812
1813 switch (ksp->ks_dev_spec.id_product) {
1814 case KEYSPAN_USA19HS_PID:
1815 size = sizeof (keyspan_usa19hs_port_ctrl_msg_t);
1816
1817 break;
1818
1819
1820 case KEYSPAN_USA49WLC_PID:
1821 size = sizeof (keyspan_usa49_port_ctrl_msg_t);
1822
1823 break;
1824
1825 default:
1826 USB_DPRINTF_L2(DPRINT_CTLOP, ksp->ks_lh,
1827 "keyspan_send_cmd_usa49:"
1828 "the device's product id can't be recognized");
1829 return (USB_FAILURE);
1830 }
1831
1832 if ((mp = allocb(size, BPRI_LO)) == NULL) {
1833
1834 return (USB_FAILURE);
1835 }
1836 bcopy(&kp->kp_ctrl_msg, mp->b_rptr, size);
1837
1838 br = usb_alloc_bulk_req(ksp->ks_dip, 0, USB_FLAGS_SLEEP);
1839 br->bulk_len = size;
1840 br->bulk_data = mp;
1841 br->bulk_timeout = KEYSPAN_BULK_TIMEOUT;
1842 br->bulk_client_private = (void *)kp;
1843 br->bulk_attributes = USB_ATTRS_AUTOCLEARING;
1844
1845 rval = usb_pipe_bulk_xfer(ksp->ks_ctrlout_pipe.pipe_handle, br,
1846 USB_FLAGS_SLEEP);
1847 if (rval == USB_SUCCESS) {
1848 mutex_enter(&kp->kp_mutex);
1849 keyspan_save_port_params(kp);
1850 mutex_exit(&kp->kp_mutex);
1851 } else {
1852 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49"
1853 ": failure, rval=%d", rval);
1854 }
1855
1856 usb_free_bulk_req(br);
1857
1858 return (rval);
1859 }
1860
1861 /*
1862 * send command to the port and save the params after its completion for
1863 * USA_49WG only
1864 */
1865 int
keyspan_send_cmd_usa49wg(keyspan_port_t * kp)1866 keyspan_send_cmd_usa49wg(keyspan_port_t *kp)
1867 {
1868 keyspan_state_t *ksp = kp->kp_ksp;
1869 mblk_t *mp;
1870 int rval = USB_SUCCESS;
1871 uint16_t size = sizeof (keyspan_usa49_port_ctrl_msg_t);
1872 usb_cb_flags_t cb_flags;
1873 usb_cr_t cr;
1874 usb_ctrl_setup_t setup;
1875
1876 ASSERT(!mutex_owned(&kp->kp_mutex));
1877 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh, "keyspan_send_cmd_usa49wg");
1878
1879 if ((mp = allocb(size, BPRI_LO)) == NULL) {
1880
1881 return (USB_FAILURE);
1882 }
1883 bcopy(&kp->kp_ctrl_msg, mp->b_rptr, size);
1884
1885 setup.bmRequestType = USB_DEV_REQ_TYPE_VENDOR;
1886 setup.bRequest = KEYSPAN_SET_CONTROL_REQUEST;
1887 setup.wValue = 0;
1888 setup.wIndex = 0;
1889 setup.wLength = size;
1890 setup.attrs = 0;
1891
1892 rval = usb_pipe_ctrl_xfer_wait(ksp->ks_def_pipe.pipe_handle, &setup,
1893 &mp, &cr, &cb_flags, 0);
1894
1895 if (rval == USB_SUCCESS) {
1896 mutex_enter(&kp->kp_mutex);
1897 keyspan_save_port_params(kp);
1898 mutex_exit(&kp->kp_mutex);
1899 } else {
1900 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
1901 "keyspan_send_cmd_usa49wg: failure, rval=%d", rval);
1902 }
1903 if (mp) {
1904 freemsg(mp);
1905 }
1906
1907 return (rval);
1908 }
1909
1910 /*
1911 * send command to the port and save the params after its completion
1912 */
1913 int
keyspan_send_cmd(keyspan_port_t * kp)1914 keyspan_send_cmd(keyspan_port_t *kp)
1915 {
1916 keyspan_state_t *ksp = kp->kp_ksp;
1917 int rval = USB_FAILURE;
1918
1919 switch (ksp->ks_dev_spec.id_product) {
1920 case KEYSPAN_USA19HS_PID:
1921 case KEYSPAN_USA49WLC_PID:
1922 rval = keyspan_send_cmd_usa49(kp);
1923
1924 break;
1925 case KEYSPAN_USA49WG_PID:
1926 rval = keyspan_send_cmd_usa49wg(kp);
1927
1928 break;
1929 default:
1930 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
1931 "keyspan_send_cmd: "
1932 "the device's product id can't be recognized");
1933 }
1934
1935 if (rval != USB_SUCCESS) {
1936 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
1937 "keyspan_send_cmd() FAILED");
1938
1939 return (rval);
1940 }
1941
1942 return (USB_SUCCESS);
1943
1944 }
1945
1946 /*
1947 * hotplug
1948 * -------
1949 *
1950 * restore device state after CPR resume or reconnect
1951 */
1952 static int
keyspan_restore_device_state(keyspan_state_t * ksp)1953 keyspan_restore_device_state(keyspan_state_t *ksp)
1954 {
1955 int state;
1956
1957 mutex_enter(&ksp->ks_mutex);
1958 state = ksp->ks_dev_state;
1959 mutex_exit(&ksp->ks_mutex);
1960
1961 if ((state != USB_DEV_DISCONNECTED) && (state != USB_DEV_SUSPENDED)) {
1962
1963 return (state);
1964 }
1965
1966 if (usb_check_same_device(ksp->ks_dip, ksp->ks_lh, USB_LOG_L0,
1967 DPRINT_MASK_ALL, USB_CHK_ALL, NULL) != USB_SUCCESS) {
1968 mutex_enter(&ksp->ks_mutex);
1969 state = ksp->ks_dev_state = USB_DEV_DISCONNECTED;
1970 mutex_exit(&ksp->ks_mutex);
1971
1972 return (state);
1973 }
1974
1975 if (state == USB_DEV_DISCONNECTED) {
1976 USB_DPRINTF_L0(DPRINT_HOTPLUG, ksp->ks_lh,
1977 "device has been reconnected but data may have been lost");
1978 }
1979
1980 if (keyspan_reconnect_pipes(ksp) != USB_SUCCESS) {
1981
1982 return (state);
1983 }
1984
1985 /*
1986 * init device state
1987 */
1988 mutex_enter(&ksp->ks_mutex);
1989 state = ksp->ks_dev_state = USB_DEV_ONLINE;
1990 ksp->ks_reconnect_flag = 1;
1991 mutex_exit(&ksp->ks_mutex);
1992
1993 /*
1994 * now restore each open port
1995 */
1996 (void) keyspan_restore_ports_state(ksp);
1997
1998 return (state);
1999 }
2000
2001 /*
2002 * restore ports state after CPR resume or reconnect
2003 */
2004 static int
keyspan_restore_ports_state(keyspan_state_t * ksp)2005 keyspan_restore_ports_state(keyspan_state_t *ksp)
2006 {
2007 keyspan_port_t *kp;
2008 int rval = USB_SUCCESS;
2009 int err;
2010 int i;
2011
2012 for (i = 0; i < ksp->ks_dev_spec.port_cnt; i++) {
2013 kp = &ksp->ks_ports[i];
2014 /*
2015 * only care about open ports
2016 */
2017 mutex_enter(&kp->kp_mutex);
2018 if (kp->kp_state != KEYSPAN_PORT_OPEN) {
2019 mutex_exit(&kp->kp_mutex);
2020 continue;
2021 }
2022 mutex_exit(&kp->kp_mutex);
2023
2024 sema_p(&ksp->ks_pipes_sema);
2025 /* open hardware serial port */
2026 err = keyspan_open_hw_port(kp, B_FALSE);
2027 sema_v(&ksp->ks_pipes_sema);
2028 if (err != USB_SUCCESS) {
2029 USB_DPRINTF_L2(DPRINT_HOTPLUG, kp->kp_lh,
2030 "keyspan_restore_ports_state: failed");
2031 rval = err;
2032 }
2033 }
2034
2035 return (rval);
2036 }
2037
2038
2039 /*
2040 * power management
2041 * ----------------
2042 *
2043 *
2044 * create PM components
2045 */
2046 static int
keyspan_create_pm_components(keyspan_state_t * ksp)2047 keyspan_create_pm_components(keyspan_state_t *ksp)
2048 {
2049 dev_info_t *dip = ksp->ks_dip;
2050 keyspan_pm_t *pm;
2051 uint_t pwr_states;
2052
2053 pm = ksp->ks_pm = kmem_zalloc(sizeof (keyspan_pm_t), KM_SLEEP);
2054 pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
2055
2056 if (usb_create_pm_components(dip, &pwr_states) != USB_SUCCESS) {
2057 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh,
2058 "keyspan_create_pm_components: failed");
2059
2060 return (USB_SUCCESS);
2061 }
2062
2063 pm->pm_wakeup_enabled = (usb_handle_remote_wakeup(dip,
2064 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS);
2065 pm->pm_pwr_states = (uint8_t)pwr_states;
2066
2067 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2068
2069 return (USB_SUCCESS);
2070 }
2071
2072
2073 /*
2074 * destroy PM components
2075 */
2076 static void
keyspan_destroy_pm_components(keyspan_state_t * ksp)2077 keyspan_destroy_pm_components(keyspan_state_t *ksp)
2078 {
2079 keyspan_pm_t *pm = ksp->ks_pm;
2080 dev_info_t *dip = ksp->ks_dip;
2081 int rval;
2082
2083 if (ksp->ks_dev_state != USB_DEV_DISCONNECTED) {
2084 if (pm->pm_wakeup_enabled) {
2085 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2086
2087 rval = usb_handle_remote_wakeup(dip,
2088 USB_REMOTE_WAKEUP_DISABLE);
2089 if (rval != USB_SUCCESS) {
2090 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh,
2091 "keyspan_destroy_pm_components: disable "
2092 "remote wakeup failed, rval=%d", rval);
2093 }
2094 }
2095
2096 (void) pm_lower_power(dip, 0, USB_DEV_OS_PWR_OFF);
2097 }
2098 kmem_free(pm, sizeof (keyspan_pm_t));
2099 ksp->ks_pm = NULL;
2100 }
2101
2102
2103 /*
2104 * mark device busy and raise power
2105 */
2106 static int
keyspan_pm_set_busy(keyspan_state_t * ksp)2107 keyspan_pm_set_busy(keyspan_state_t *ksp)
2108 {
2109 keyspan_pm_t *pm = ksp->ks_pm;
2110 dev_info_t *dip = ksp->ks_dip;
2111
2112 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_busy");
2113
2114 mutex_enter(&ksp->ks_mutex);
2115 /* if already marked busy, just increment the counter */
2116 if (pm->pm_busy_cnt++ > 0) {
2117 USB_DPRINTF_L3(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_busy:"
2118 "already busy, busy_cnt = %d", pm->pm_busy_cnt);
2119 mutex_exit(&ksp->ks_mutex);
2120
2121 return (USB_SUCCESS);
2122 }
2123
2124 (void) pm_busy_component(dip, 0);
2125
2126 if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) {
2127 mutex_exit(&ksp->ks_mutex);
2128
2129 return (USB_SUCCESS);
2130 }
2131
2132 /* need to raise power */
2133 pm->pm_raise_power = B_TRUE;
2134 mutex_exit(&ksp->ks_mutex);
2135
2136 USB_DPRINTF_L3(DPRINT_PM, ksp->ks_lh,
2137 "keyspan_pm_set_busy: raise power");
2138 (void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
2139
2140 mutex_enter(&ksp->ks_mutex);
2141 pm->pm_raise_power = B_FALSE;
2142 mutex_exit(&ksp->ks_mutex);
2143
2144 return (USB_SUCCESS);
2145 }
2146
2147
2148 /*
2149 * mark device idle
2150 */
2151 static void
keyspan_pm_set_idle(keyspan_state_t * ksp)2152 keyspan_pm_set_idle(keyspan_state_t *ksp)
2153 {
2154 keyspan_pm_t *pm = ksp->ks_pm;
2155 dev_info_t *dip = ksp->ks_dip;
2156
2157 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_idle");
2158
2159 /*
2160 * if more ports use the device, do not mark as yet
2161 */
2162 mutex_enter(&ksp->ks_mutex);
2163 if (--pm->pm_busy_cnt > 0) {
2164 mutex_exit(&ksp->ks_mutex);
2165
2166 return;
2167 }
2168
2169 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pm_set_idle: set idle");
2170 (void) pm_idle_component(dip, 0);
2171
2172 mutex_exit(&ksp->ks_mutex);
2173 }
2174
2175
2176 /*
2177 * Functions to handle power transition for OS levels 0 -> 3
2178 */
2179 static int
keyspan_pwrlvl0(keyspan_state_t * ksp)2180 keyspan_pwrlvl0(keyspan_state_t *ksp)
2181 {
2182 int rval;
2183 keyspan_pipe_t *statin = &ksp->ks_statin_pipe;
2184
2185 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl0");
2186
2187 switch (ksp->ks_dev_state) {
2188 case USB_DEV_ONLINE:
2189 /* issue USB D3 command to the device */
2190 rval = usb_set_device_pwrlvl3(ksp->ks_dip);
2191 ASSERT(rval == USB_SUCCESS);
2192
2193 if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) {
2194 mutex_exit(&ksp->ks_mutex);
2195 usb_pipe_stop_intr_polling(statin->pipe_handle,
2196 USB_FLAGS_SLEEP);
2197 mutex_enter(&ksp->ks_mutex);
2198
2199 mutex_enter(&statin->pipe_mutex);
2200 statin->pipe_state = KEYSPAN_PIPE_CLOSED;
2201 mutex_exit(&statin->pipe_mutex);
2202 }
2203 ksp->ks_dev_state = USB_DEV_PWRED_DOWN;
2204 ksp->ks_pm->pm_cur_power = USB_DEV_OS_PWR_OFF;
2205
2206 /* FALLTHRU */
2207 case USB_DEV_DISCONNECTED:
2208 case USB_DEV_SUSPENDED:
2209 /* allow a disconnect/cpr'ed device to go to lower power */
2210
2211 return (USB_SUCCESS);
2212 case USB_DEV_PWRED_DOWN:
2213 default:
2214 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh,
2215 "keyspan_pwrlvl0: illegal device state");
2216
2217 return (USB_FAILURE);
2218 }
2219 }
2220
2221
2222 static int
keyspan_pwrlvl1(keyspan_state_t * ksp)2223 keyspan_pwrlvl1(keyspan_state_t *ksp)
2224 {
2225 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl1");
2226
2227 /* issue USB D2 command to the device */
2228 (void) usb_set_device_pwrlvl2(ksp->ks_dip);
2229
2230 return (USB_FAILURE);
2231 }
2232
2233
2234 static int
keyspan_pwrlvl2(keyspan_state_t * ksp)2235 keyspan_pwrlvl2(keyspan_state_t *ksp)
2236 {
2237 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl2");
2238
2239 /* issue USB D1 command to the device */
2240 (void) usb_set_device_pwrlvl1(ksp->ks_dip);
2241
2242 return (USB_FAILURE);
2243 }
2244
2245
2246 static int
keyspan_pwrlvl3(keyspan_state_t * ksp)2247 keyspan_pwrlvl3(keyspan_state_t *ksp)
2248 {
2249 int rval;
2250
2251 USB_DPRINTF_L4(DPRINT_PM, ksp->ks_lh, "keyspan_pwrlvl3");
2252
2253 switch (ksp->ks_dev_state) {
2254 case USB_DEV_PWRED_DOWN:
2255 /* Issue USB D0 command to the device here */
2256 rval = usb_set_device_pwrlvl0(ksp->ks_dip);
2257 ASSERT(rval == USB_SUCCESS);
2258
2259 if (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID) {
2260 mutex_exit(&ksp->ks_mutex);
2261 keyspan_pipe_start_polling(&ksp->ks_statin_pipe);
2262 mutex_enter(&ksp->ks_mutex);
2263 }
2264
2265 ksp->ks_dev_state = USB_DEV_ONLINE;
2266 ksp->ks_pm->pm_cur_power = USB_DEV_OS_FULL_PWR;
2267
2268 /* FALLTHRU */
2269 case USB_DEV_ONLINE:
2270 /* we are already in full power */
2271
2272 /* FALLTHRU */
2273 case USB_DEV_DISCONNECTED:
2274 case USB_DEV_SUSPENDED:
2275
2276 return (USB_SUCCESS);
2277 default:
2278 USB_DPRINTF_L2(DPRINT_PM, ksp->ks_lh,
2279 "keyspan_pwrlvl3: illegal device state");
2280
2281 return (USB_FAILURE);
2282 }
2283 }
2284
2285
2286 /*
2287 * pipe operations
2288 * ---------------
2289 *
2290 * XXX keyspan seem to malfunction after the pipes are closed
2291 * and reopened again (does not respond to OPEN_PORT command).
2292 * so we open them once in attach
2293 */
2294 static int
keyspan_attach_pipes(keyspan_state_t * ksp)2295 keyspan_attach_pipes(keyspan_state_t *ksp)
2296 {
2297 return (keyspan_open_dev_pipes(ksp));
2298 }
2299
2300 void
keyspan_detach_pipes(keyspan_state_t * ksp)2301 keyspan_detach_pipes(keyspan_state_t *ksp)
2302 {
2303
2304 /*
2305 * Blow away status bulk in requests or
2306 * pipe close will wait until timeout.
2307 */
2308 if (ksp->ks_statin_pipe.pipe_handle) {
2309 usb_pipe_stop_intr_polling(ksp->ks_statin_pipe.pipe_handle,
2310 USB_FLAGS_SLEEP);
2311 }
2312
2313 /* Close the globle pipes */
2314 keyspan_close_dev_pipes(ksp);
2315 }
2316
2317
2318 /*
2319 * during device disconnect/suspend, close pipes if they are open.
2320 */
2321 static void
keyspan_disconnect_pipes(keyspan_state_t * ksp)2322 keyspan_disconnect_pipes(keyspan_state_t *ksp)
2323 {
2324 sema_p(&ksp->ks_pipes_sema);
2325 keyspan_close_pipes(ksp);
2326 sema_v(&ksp->ks_pipes_sema);
2327 }
2328
2329
2330 /*
2331 * during device reconnect/resume, reopen pipes if they were open.
2332 */
2333 static int
keyspan_reconnect_pipes(keyspan_state_t * ksp)2334 keyspan_reconnect_pipes(keyspan_state_t *ksp)
2335 {
2336 int rval = USB_SUCCESS;
2337
2338 sema_p(&ksp->ks_pipes_sema);
2339 rval = keyspan_reopen_pipes(ksp);
2340 sema_v(&ksp->ks_pipes_sema);
2341
2342 return (rval);
2343 }
2344
2345 /*
2346 * data transfer routines
2347 * ----------------------
2348 *
2349 *
2350 * start data transmit
2351 */
2352 void
keyspan_tx_start(keyspan_port_t * kp,int * xferd)2353 keyspan_tx_start(keyspan_port_t *kp, int *xferd)
2354 {
2355 keyspan_state_t *ksp = kp->kp_ksp;
2356 int len; /* # of bytes we can transmit */
2357 mblk_t *data; /* data to be transmitted */
2358 int data_len = 0; /* # of bytes in 'data' */
2359 int tran_len;
2360 int rval;
2361 int status_len = 0;
2362
2363 ASSERT(!mutex_owned(&ksp->ks_mutex));
2364 ASSERT(mutex_owned(&kp->kp_mutex));
2365 ASSERT(kp->kp_state != KEYSPAN_PORT_CLOSED);
2366
2367 USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start");
2368
2369 if (xferd) {
2370 *xferd = 0;
2371 }
2372 if ((kp->kp_flags & KEYSPAN_PORT_TX_STOPPED) ||
2373 (kp->kp_tx_mp == NULL)) {
2374
2375 return;
2376 }
2377
2378 len = min(msgdsize(kp->kp_tx_mp), kp->kp_write_len);
2379 USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start:"
2380 "len = %d, tx_mp_len = %d", len, (int)msgdsize(kp->kp_tx_mp));
2381
2382 mutex_exit(&kp->kp_mutex);
2383
2384 /*
2385 * Some keyspan adapters, such as usa49wlc,
2386 * need use the first byte as flag.
2387 */
2388 switch (ksp->ks_dev_spec.id_product) {
2389 case KEYSPAN_USA19HS_PID:
2390
2391 if ((data = allocb(len, BPRI_LO)) == NULL) {
2392 mutex_enter(&kp->kp_mutex);
2393
2394 return;
2395 }
2396 mutex_enter(&kp->kp_mutex);
2397
2398 /* copy at most 'len' bytes from mblk chain for transmission */
2399 data_len = keyspan_tx_copy_data(kp, data, len);
2400 if (data_len <= 0) {
2401 USB_DPRINTF_L3(DPRINT_OUT_PIPE, kp->kp_lh,
2402 "keyspan_tx_start:keyspan_tx_copy_data copied"
2403 " zero bytes");
2404 }
2405
2406 break;
2407
2408 case KEYSPAN_USA49WLC_PID:
2409 case KEYSPAN_USA49WG_PID:
2410 status_len = len / 64 + 1;
2411 if ((data = allocb(len + status_len, BPRI_LO)) == NULL) {
2412 mutex_enter(&kp->kp_mutex);
2413
2414 return;
2415 }
2416 mutex_enter(&kp->kp_mutex);
2417 /*
2418 * the data format is [status byte][63 data bytes][...][status]
2419 * byte][up to 63 bytes] according to keyspan spec
2420 */
2421 while (data_len < len) {
2422 /* Add status byte per 63 data bytes */
2423 *(data->b_wptr++) = 0;
2424 /* copy at most 63 bytes from mblk chain for trans */
2425 tran_len = keyspan_tx_copy_data(kp, data, 63);
2426 if (tran_len <= 0) {
2427 USB_DPRINTF_L3(DPRINT_OUT_PIPE, kp->kp_lh,
2428 "keyspan_tx_start:keyspan_tx_copy_data"
2429 " copied zero bytes");
2430
2431 break;
2432 }
2433 data_len += tran_len;
2434 }
2435
2436 break;
2437 default:
2438
2439 mutex_enter(&kp->kp_mutex);
2440 USB_DPRINTF_L2(DPRINT_OUT_PIPE, ksp->ks_lh, "keyspan_tx_start:"
2441 "the device's product id can't be recognized");
2442
2443 return;
2444 }
2445
2446 mutex_exit(&kp->kp_mutex);
2447
2448 /*
2449 * For USA-49WG, the port0 uses intr out pipe as data out pipe, while
2450 * other ports use bulk out pipe.
2451 */
2452
2453 if ((kp->kp_port_num == 0) &&
2454 (ksp->ks_dev_spec.id_product == KEYSPAN_USA49WG_PID)) {
2455 rval = keyspan_send_data_port0(&kp->kp_dataout_pipe, &data, kp);
2456 } else {
2457 rval = keyspan_send_data(&kp->kp_dataout_pipe, &data, kp);
2458 }
2459 mutex_enter(&kp->kp_mutex);
2460
2461 /*
2462 * if send failed, put data back
2463 */
2464 if (rval != USB_SUCCESS) {
2465 ASSERT(data);
2466 keyspan_put_head(&kp->kp_tx_mp, data, kp);
2467 } else if (xferd) {
2468 *xferd = data_len;
2469 }
2470
2471 USB_DPRINTF_L4(DPRINT_OUT_PIPE, kp->kp_lh, "keyspan_tx_start[%d]: over"
2472 "(%d) rval=%d", kp->kp_port_num, data_len, rval);
2473
2474 }
2475
2476
2477 /*
2478 * copy no more than 'len' bytes from mblk chain to transmit mblk 'data'.
2479 * return number of bytes copied
2480 */
2481 int
keyspan_tx_copy_data(keyspan_port_t * kp,mblk_t * data,int len)2482 keyspan_tx_copy_data(keyspan_port_t *kp, mblk_t *data, int len)
2483 {
2484 mblk_t *mp; /* current msgblk */
2485 int copylen; /* # of bytes to copy from 'mp' to 'data' */
2486 int data_len = 0;
2487
2488 ASSERT(mutex_owned(&kp->kp_mutex));
2489
2490 if (msgdsize(kp->kp_tx_mp) == 0) {
2491 data->b_wptr = data->b_rptr;
2492 freeb(kp->kp_tx_mp);
2493 kp->kp_tx_mp = NULL;
2494
2495 return (data_len);
2496 }
2497
2498 while ((data_len < len) && kp->kp_tx_mp) {
2499 mp = kp->kp_tx_mp;
2500 copylen = min(MBLKL(mp), len - data_len);
2501 bcopy(mp->b_rptr, data->b_wptr, copylen);
2502
2503 mp->b_rptr += copylen;
2504 data->b_wptr += copylen;
2505 data_len += copylen;
2506
2507 if (MBLKL(mp) < 1) {
2508 kp->kp_tx_mp = unlinkb(mp);
2509 freeb(mp);
2510 } else {
2511 ASSERT(data_len == len);
2512 }
2513 }
2514 USB_DPRINTF_L3(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_tx_copy_data:"
2515 "copied data_len = %d", data_len);
2516
2517 return (data_len);
2518 }
2519
2520
2521 /*
2522 * wait until local tx buffer drains.
2523 * 'timeout' is in seconds, zero means wait forever
2524 */
2525 static int
keyspan_wait_tx_drain(keyspan_port_t * kp,int timeout)2526 keyspan_wait_tx_drain(keyspan_port_t *kp, int timeout)
2527 {
2528 clock_t until;
2529 int over = 0;
2530
2531 USB_DPRINTF_L4(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_wait_tx_drain:"
2532 "timeout = %d", timeout);
2533 until = ddi_get_lbolt() + drv_usectohz(1000000 * timeout);
2534
2535 while (kp->kp_tx_mp && !over) {
2536 if (timeout > 0) {
2537 over = (cv_timedwait_sig(&kp->kp_tx_cv,
2538 &kp->kp_mutex, until) <= 0);
2539 } else {
2540 over = (cv_wait_sig(&kp->kp_tx_cv, &kp->kp_mutex) == 0);
2541 }
2542 }
2543
2544 return ((kp->kp_tx_mp == NULL) ? USB_SUCCESS : USB_FAILURE);
2545 }
2546
2547 /*
2548 * returns 0 if device is not online, != 0 otherwise
2549 */
2550 int
keyspan_dev_is_online(keyspan_state_t * ksp)2551 keyspan_dev_is_online(keyspan_state_t *ksp)
2552 {
2553 int rval;
2554
2555 mutex_enter(&ksp->ks_mutex);
2556 rval = (ksp->ks_dev_state == USB_DEV_ONLINE);
2557 mutex_exit(&ksp->ks_mutex);
2558
2559 return (rval);
2560 }
2561
2562 /*
2563 * link a message block to tail of message
2564 * account for the case when message is null
2565 */
2566 void
keyspan_put_tail(mblk_t ** mpp,mblk_t * bp)2567 keyspan_put_tail(mblk_t **mpp, mblk_t *bp)
2568 {
2569 if (*mpp) {
2570 linkb(*mpp, bp);
2571 } else {
2572 *mpp = bp;
2573 }
2574 }
2575
2576 /*
2577 * put a message block at the head of the message
2578 * account for the case when message is null
2579 */
2580 void
keyspan_put_head(mblk_t ** mpp,mblk_t * bp,keyspan_port_t * kp)2581 keyspan_put_head(mblk_t **mpp, mblk_t *bp, keyspan_port_t *kp)
2582 {
2583 switch (kp->kp_ksp->ks_dev_spec.id_product) {
2584 case KEYSPAN_USA19HS_PID:
2585 if (*mpp) {
2586 linkb(bp, *mpp);
2587 }
2588 *mpp = bp;
2589
2590 break;
2591
2592
2593 case KEYSPAN_USA49WLC_PID:
2594 case KEYSPAN_USA49WG_PID:
2595
2596 /* get rid of the first byte of the msg data which is a flag */
2597 if (*mpp) {
2598 linkb(bp, *mpp);
2599 }
2600 bp->b_rptr = bp->b_datap->db_base + 1;
2601 *mpp = bp;
2602
2603 break;
2604
2605 default:
2606 USB_DPRINTF_L2(DPRINT_OUT_DATA, kp->kp_lh, "keyspan_put_head:"
2607 "the device's product id can't be recognized");
2608
2609 return;
2610 }
2611
2612 }
2613
2614 /*
2615 * Set the port parameters to default values
2616 */
2617 static void
keyspan_default_port_params(keyspan_port_t * kp)2618 keyspan_default_port_params(keyspan_port_t *kp)
2619 {
2620 keyspan_state_t *ksp = kp->kp_ksp;
2621
2622 ASSERT(mutex_owned(&kp->kp_mutex));
2623
2624 switch (ksp->ks_dev_spec.id_product) {
2625 case KEYSPAN_USA19HS_PID:
2626 keyspan_default_port_params_usa19hs(kp);
2627
2628 break;
2629
2630
2631 case KEYSPAN_USA49WLC_PID:
2632 case KEYSPAN_USA49WG_PID:
2633 keyspan_default_port_params_usa49(kp);
2634
2635 break;
2636
2637 default:
2638 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
2639 "keyspan_default_port_params:"
2640 "the device's product id can't be recognized");
2641 }
2642
2643 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2644 "keyspan_default_port_params: setted.");
2645 }
2646
2647 /*
2648 * Build the command message according to the params from usbser.
2649 * The message will then be sent to deivce by keyspan_send_cmd.
2650 */
2651 static void
keyspan_build_cmd_msg(keyspan_port_t * kp,ds_port_params_t * tp)2652 keyspan_build_cmd_msg(keyspan_port_t *kp, ds_port_params_t *tp)
2653 {
2654 keyspan_state_t *ksp = kp->kp_ksp;
2655
2656 switch (ksp->ks_dev_spec.id_product) {
2657 case KEYSPAN_USA19HS_PID:
2658 keyspan_build_cmd_msg_usa19hs(kp, tp);
2659
2660 break;
2661
2662
2663 case KEYSPAN_USA49WLC_PID:
2664 case KEYSPAN_USA49WG_PID:
2665 keyspan_build_cmd_msg_usa49(kp, tp);
2666
2667 break;
2668
2669 default:
2670 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
2671 "keyspan_build_cmd_msg:"
2672 "the device's product id can't be recognized");
2673 }
2674 }
2675
2676 /* save the port params after send cmd successfully */
2677 static void
keyspan_save_port_params(keyspan_port_t * kp)2678 keyspan_save_port_params(keyspan_port_t *kp)
2679 {
2680 keyspan_state_t *ksp = kp->kp_ksp;
2681
2682 ASSERT(mutex_owned(&kp->kp_mutex));
2683
2684 switch (ksp->ks_dev_spec.id_product) {
2685 case KEYSPAN_USA19HS_PID:
2686 keyspan_save_port_params_usa19hs(kp);
2687
2688 break;
2689
2690
2691 case KEYSPAN_USA49WLC_PID:
2692 case KEYSPAN_USA49WG_PID:
2693 keyspan_save_port_params_usa49(kp);
2694
2695 break;
2696
2697 default:
2698 USB_DPRINTF_L2(DPRINT_ATTACH, ksp->ks_lh,
2699 "keyspan_save_port_params:"
2700 "the device's product id can't be recognized");
2701 }
2702
2703 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2704 "keyspan_save_port_params: baud = %x, lcr = %x,"
2705 "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag);
2706
2707 }
2708
2709 /* save the port params after send cmd successfully */
2710 static void
keyspan_save_port_params_usa19hs(keyspan_port_t * kp)2711 keyspan_save_port_params_usa19hs(keyspan_port_t *kp)
2712 {
2713 keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs);
2714
2715 ASSERT(mutex_owned(&kp->kp_mutex));
2716
2717 if (ctrl_msg->setClocking) {
2718 kp->kp_baud = ctrl_msg->baudHi;
2719 kp->kp_baud = (kp->kp_baud << 8);
2720 kp->kp_baud |= ctrl_msg->baudLo;
2721 }
2722 if (ctrl_msg->setLcr) {
2723 kp->kp_lcr = ctrl_msg->lcr;
2724 }
2725 if (ctrl_msg->setRts) {
2726 if (ctrl_msg->rts) {
2727 kp->kp_status_flag |= KEYSPAN_PORT_RTS;
2728 } else {
2729 kp->kp_status_flag &= ~KEYSPAN_PORT_RTS;
2730 }
2731 }
2732 if (ctrl_msg->setDtr) {
2733 if (ctrl_msg->dtr) {
2734 kp->kp_status_flag |= KEYSPAN_PORT_DTR;
2735 } else {
2736 kp->kp_status_flag &= ~KEYSPAN_PORT_DTR;
2737 }
2738 }
2739
2740 if (ctrl_msg->portEnabled) {
2741 kp->kp_status_flag |= KEYSPAN_PORT_ENABLE;
2742 } else {
2743 kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE;
2744 }
2745
2746 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2747 "keyspan_save_port_params: baud = %x, lcr = %x,"
2748 "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag);
2749
2750 }
2751
2752 /*
2753 * Set the port parameters to default values
2754 */
2755 static void
keyspan_default_port_params_usa19hs(keyspan_port_t * kp)2756 keyspan_default_port_params_usa19hs(keyspan_port_t *kp)
2757 {
2758 keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs);
2759 ASSERT(mutex_owned(&kp->kp_mutex));
2760
2761 keyspan_build_cmd_msg(kp, NULL);
2762
2763 ctrl_msg->setRts = 0x01;
2764 ctrl_msg->rts = 0x1;
2765 ctrl_msg->setDtr = 0x01;
2766 ctrl_msg->dtr = 0x1;
2767
2768 ctrl_msg->setClocking = 1;
2769 ctrl_msg->setRxMode = 1;
2770 ctrl_msg->setTxMode = 1;
2771
2772 /* set baud rate to 9600 */
2773 ctrl_msg->baudLo = keyspan_speedtab_usa19hs[13] & 0xff;
2774 ctrl_msg->baudHi = (keyspan_speedtab_usa19hs[13] >> 8) & 0xff;
2775 ctrl_msg->rxMode = RXMODE_BYHAND;
2776 ctrl_msg->txMode = TXMODE_BYHAND;
2777
2778 ctrl_msg->lcr = 0x3;
2779 ctrl_msg->setLcr = 0x1;
2780
2781 ctrl_msg->xonChar = CSTART;
2782 ctrl_msg->xoffChar = CSTOP;
2783 ctrl_msg->setTxFlowControl = 1;
2784 ctrl_msg->txFlowControl = TXFLOW_CTS;
2785 ctrl_msg->setRxFlowControl = 1;
2786 ctrl_msg->rxFlowControl = RXFLOW_RTS;
2787 ctrl_msg->rxFlush = 0;
2788
2789 }
2790
2791 /*
2792 * Build the command message according to the params from usbser.
2793 * The message will then be sent to deivce by keyspan_send_cmd.
2794 */
2795 static void
keyspan_build_cmd_msg_usa19hs(keyspan_port_t * kp,ds_port_params_t * tp)2796 keyspan_build_cmd_msg_usa19hs(keyspan_port_t *kp, ds_port_params_t *tp)
2797 {
2798 int cnt, i;
2799 uint_t ui;
2800 ds_port_param_entry_t *pe;
2801 keyspan_usa19hs_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa19hs);
2802
2803 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
2804 "keyspan_build_cmd_msg_usa19hs: tp = %p", (void *)tp);
2805
2806 ASSERT(mutex_owned(&kp->kp_mutex));
2807 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN ||
2808 kp->kp_state == KEYSPAN_PORT_OPENING);
2809
2810 /* bzero all elements */
2811 bzero(ctrl_msg, sizeof (keyspan_usa19hs_port_ctrl_msg_t));
2812
2813 /* it is usaually 16, according to Keyspan spec */
2814 ctrl_msg->rxForwardingLength = 16;
2815 /* from 1ms to 31ms, according to Keyspan spec. */
2816 ctrl_msg->rxForwardingTimeout = 16;
2817
2818 ctrl_msg->portEnabled = 1;
2819 ctrl_msg->returnStatus = 1;
2820
2821 if (tp == NULL) {
2822
2823 return;
2824 }
2825
2826 cnt = tp->tp_cnt;
2827 pe = tp->tp_entries;
2828
2829 /* translate tp parameters into cmd_msg elements */
2830 for (i = 0; i < cnt; i++, pe++) {
2831 switch (pe->param) {
2832 case DS_PARAM_BAUD:
2833 ui = pe->val.ui;
2834
2835 /*
2836 * if we don't support this speed,
2837 * then return failure.
2838 */
2839 if ((ui >= NELEM(keyspan_speedtab_usa19hs)) ||
2840 ((ui > 0) && (keyspan_speedtab_usa19hs[ui] == 0))) {
2841
2842 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2843 "keyspan_build_cmd_msg_usa19hs:"
2844 " bad baud %d", ui);
2845
2846 break;
2847 }
2848
2849 /* if the same as the old rate, need not set the rate */
2850 if (kp->kp_baud == keyspan_speedtab_usa19hs[ui]) {
2851
2852 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2853 "keyspan_build_cmd_msg_usa19hs:"
2854 " same as old baud setting, baud = %d",
2855 keyspan_speed2baud[ui]);
2856
2857 break;
2858 }
2859 ctrl_msg->setClocking = 1; /* enable the setting */
2860 ctrl_msg->setRxMode = 1;
2861 ctrl_msg->setTxMode = 1;
2862
2863 ctrl_msg->baudLo = keyspan_speedtab_usa19hs[ui] & 0xff;
2864 ctrl_msg->baudHi = (keyspan_speedtab_usa19hs[ui] >> 8)
2865 & 0xff;
2866
2867 ctrl_msg->rxMode = RXMODE_BYHAND;
2868 ctrl_msg->txMode = TXMODE_BYHAND;
2869
2870 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2871 "keyspan_build_cmd_msg_usa19hs: baud=%d",
2872 keyspan_speed2baud[ui]);
2873
2874 break;
2875 case DS_PARAM_PARITY:
2876 if (pe->val.ui & PARENB) {
2877
2878 /*
2879 * Since USA_PARITY_NONE == 0, it's not
2880 * necessary to or it in here.
2881 */
2882 if (pe->val.ui & PARODD) {
2883 ctrl_msg->lcr |= USA_PARITY_ODD;
2884 } else {
2885 ctrl_msg->lcr |= USA_PARITY_EVEN;
2886 }
2887 }
2888 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2889 "keyspan_build_cmd_msg_usa19hs: parity=%x,lcr = %x",
2890 pe->val.ui, ctrl_msg->lcr);
2891
2892 break;
2893 case DS_PARAM_STOPB:
2894 if (pe->val.ui & CSTOPB) {
2895 ctrl_msg->lcr |= STOPBITS_678_2;
2896 } else {
2897
2898 /*
2899 * STOPBITS_5678_1 equals zero,
2900 * so it's not necessary to or it in.
2901 */
2902 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2903 "keyspan_build_cmd_msg_usa19hs:"
2904 " STOPBITS_5678_1");
2905 }
2906
2907 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2908 "keyspan_build_cmd_msg_usa19hs: stopb=%x, lcr = %x",
2909 pe->val.ui, ctrl_msg->lcr);
2910
2911 break;
2912 case DS_PARAM_CHARSZ:
2913 switch (pe->val.ui) {
2914 case CS5:
2915
2916 /*
2917 * USA_DATABITS_5 equals zero,
2918 * not necessary to or it in.
2919 */
2920 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2921 "keyspan_build_cmd_msg_usa19hs:"
2922 " USA_DATABITS_5");
2923
2924 break;
2925 case CS6:
2926 ctrl_msg->lcr |= USA_DATABITS_6;
2927
2928 break;
2929 case CS7:
2930 ctrl_msg->lcr |= USA_DATABITS_7;
2931
2932 break;
2933 case CS8:
2934 default:
2935 /*
2936 * The default value is USA_DATABITS_8. It is
2937 * safe to set to the default one here.
2938 */
2939 ctrl_msg->lcr |= USA_DATABITS_8;
2940
2941 break;
2942 }
2943
2944 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2945 "keyspan_build_cmd_msg_usa19hs: cs=%x, lcr = %x",
2946 pe->val.ui, ctrl_msg->lcr);
2947
2948 break;
2949 case DS_PARAM_XON_XOFF:
2950 ctrl_msg->xonChar = pe->val.uc[0]; /* init to CSTART */
2951 ctrl_msg->xoffChar = pe->val.uc[1]; /* init to CSTOP */
2952
2953 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2954 "keyspan_build_cmd_msg_usa19hs: xonChar=%x, "
2955 "xoffChar = %x", ctrl_msg->xonChar,
2956 ctrl_msg->xoffChar);
2957
2958 break;
2959 case DS_PARAM_FLOW_CTL:
2960 if (pe->val.ui & CTSXON) {
2961 ctrl_msg->txFlowControl = TXFLOW_CTS;
2962 ctrl_msg->setTxFlowControl = 1;
2963 } else {
2964 /* Clear the tx flow control setting */
2965 ctrl_msg->txFlowControl = 0;
2966 ctrl_msg->setTxFlowControl = 1;
2967 }
2968 if (pe->val.ui & RTSXOFF) {
2969 ctrl_msg->rxFlowControl = RXFLOW_RTS;
2970 ctrl_msg->setRxFlowControl = 1;
2971 } else {
2972 /* Clear the rx flow control setting */
2973 ctrl_msg->rxFlowControl = 0;
2974 ctrl_msg->setRxFlowControl = 1;
2975 }
2976
2977 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
2978 "keyspan_build_cmd_msg_usa19hs: txFlowControl = %x,"
2979 "rxFlowControl = %x", ctrl_msg->txFlowControl,
2980 ctrl_msg->rxFlowControl);
2981
2982 break;
2983 default:
2984 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
2985 "keyspan_build_cmd_msg_usa19hs: bad param %d",
2986 pe->param);
2987
2988 break;
2989 }
2990
2991 }
2992
2993 /*
2994 * Enable the lcr settings only if they are different
2995 * with the existing settings.
2996 */
2997 ctrl_msg->setLcr = (ctrl_msg->lcr == kp->kp_lcr) ? 0 : 1;
2998
2999 }
3000
3001
3002 /*
3003 * Build the command message according to the params from usbser.
3004 * The message will then be sent to deivce by keyspan_send_cmd.
3005 */
3006 static void
keyspan_build_cmd_msg_usa49(keyspan_port_t * kp,ds_port_params_t * tp)3007 keyspan_build_cmd_msg_usa49(keyspan_port_t *kp, ds_port_params_t *tp)
3008 {
3009 int cnt, i;
3010 uint_t ui;
3011 ds_port_param_entry_t *pe;
3012 keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49);
3013
3014 USB_DPRINTF_L4(DPRINT_CTLOP, kp->kp_lh,
3015 "keyspan_build_cmd_msg_usa49: tp = %p", (void *)tp);
3016
3017 ASSERT(mutex_owned(&kp->kp_mutex));
3018 ASSERT(kp->kp_state == KEYSPAN_PORT_OPEN ||
3019 kp->kp_state == KEYSPAN_PORT_OPENING);
3020
3021 /* bzero all elements */
3022 bzero(ctrl_msg, sizeof (keyspan_usa49_port_ctrl_msg_t));
3023
3024 ctrl_msg->portNumber = kp->kp_port_num;
3025
3026 /* it is usaually 16, according to Keyspan spec */
3027 ctrl_msg->forwardingLength = 16;
3028
3029 ctrl_msg->enablePort = 1;
3030 ctrl_msg->returnStatus = 1;
3031
3032 if (tp == NULL) {
3033
3034 return;
3035 }
3036
3037 cnt = tp->tp_cnt;
3038 pe = tp->tp_entries;
3039
3040 /* translate tp parameters into cmd_msg elements */
3041 for (i = 0; i < cnt; i++, pe++) {
3042 switch (pe->param) {
3043 case DS_PARAM_BAUD:
3044 ui = pe->val.ui;
3045
3046 /*
3047 * If we don't support this speed,
3048 * then return failure.
3049 */
3050 if ((ui >= NELEM(keyspan_speedtab_usa49)) ||
3051 ((ui > 0) && (keyspan_speedtab_usa49[ui] == 0))) {
3052
3053 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3054 "keyspan_build_cmd_msg_usa49:"
3055 " bad baud %d", ui);
3056
3057 break;
3058 }
3059
3060 /* if the same as the old rate, need not set the rate */
3061 if (kp->kp_baud == keyspan_speedtab_usa49[ui]) {
3062
3063 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3064 "keyspan_build_cmd_msg_usa49: "
3065 "same as old baud setting, baud = %d",
3066 keyspan_speed2baud[ui]);
3067
3068 break;
3069 }
3070 ctrl_msg->setClocking = 0xff; /* enable the setting */
3071 ctrl_msg->baudLo = keyspan_speedtab_usa49[ui] & 0xff;
3072 ctrl_msg->baudHi = (keyspan_speedtab_usa49[ui] >> 8)
3073 & 0xff;
3074 ctrl_msg->prescaler = keyspan_prescaler_49wlc[ui];
3075
3076 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3077 "keyspan_build_cmd_msg_usa49: baud=%d",
3078 keyspan_speed2baud[ui]);
3079
3080 break;
3081 case DS_PARAM_PARITY:
3082 if (pe->val.ui & PARENB) {
3083
3084 /*
3085 * Since USA_PARITY_NONE == 0,
3086 * it's not necessary to or it in here.
3087 */
3088 if (pe->val.ui & PARODD) {
3089 ctrl_msg->lcr |= USA_PARITY_ODD;
3090 } else {
3091 ctrl_msg->lcr |= USA_PARITY_EVEN;
3092 }
3093 }
3094 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3095 "keyspan_build_cmd_msg_usa49: parity=%x, lcr = %x",
3096 pe->val.ui, ctrl_msg->lcr);
3097
3098 break;
3099 case DS_PARAM_STOPB:
3100 if (pe->val.ui & CSTOPB) {
3101 ctrl_msg->lcr |= STOPBITS_678_2;
3102 } else {
3103
3104 /*
3105 * STOPBITS_5678_1 equals zero,
3106 * not necessary to or it in.
3107 */
3108 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3109 "keyspan_build_cmd_msg_usa49: "
3110 "STOPBITS_5678_1");
3111 }
3112
3113 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3114 "keyspan_build_cmd_msg_usa49: stopb=%x, lcr = %x",
3115 pe->val.ui, ctrl_msg->lcr);
3116
3117 break;
3118 case DS_PARAM_CHARSZ:
3119 switch (pe->val.ui) {
3120 case CS5:
3121
3122 /*
3123 * USA_DATABITS_5 equals zero,
3124 * not necessary to or it in.
3125 */
3126 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3127 "keyspan_build_cmd_msg_usa49:"
3128 " USA_DATABITS_5");
3129
3130 break;
3131 case CS6:
3132 ctrl_msg->lcr |= USA_DATABITS_6;
3133
3134 break;
3135 case CS7:
3136 ctrl_msg->lcr |= USA_DATABITS_7;
3137
3138 break;
3139 case CS8:
3140 default:
3141 ctrl_msg->lcr |= USA_DATABITS_8;
3142
3143 break;
3144 }
3145
3146 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3147 "keyspan_build_cmd_msg_usa49: cs=%x, lcr = %x",
3148 pe->val.ui, ctrl_msg->lcr);
3149
3150 break;
3151 case DS_PARAM_XON_XOFF:
3152 ctrl_msg->xonChar = pe->val.uc[0]; /* init to CSTART */
3153 ctrl_msg->xoffChar = pe->val.uc[1]; /* init to CSTOP */
3154
3155 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3156 "keyspan_build_cmd_msg_usa49: xonChar=%x, "
3157 "xoffChar = %x", ctrl_msg->xonChar,
3158 ctrl_msg->xoffChar);
3159
3160 break;
3161 case DS_PARAM_FLOW_CTL:
3162 if (pe->val.ui & CTSXON) {
3163 ctrl_msg->ctsFlowControl = 1;
3164 ctrl_msg->setFlowControl = 1;
3165 } else {
3166 ctrl_msg->ctsFlowControl = 0;
3167 ctrl_msg->setFlowControl = 1;
3168 }
3169 if (pe->val.ui & RTSXOFF) {
3170 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3171 "keyspan_build_cmd_msg_usa49: "
3172 "pe->val.ui = %x, flow_ctl: RTSXOFF, "
3173 "no hardware support", pe->val.ui);
3174 }
3175
3176 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3177 "keyspan_build_cmd_msg_usa49: ctsFlowControl = %x,"
3178 "dsrFlowControl = %x", ctrl_msg->ctsFlowControl,
3179 ctrl_msg->dsrFlowControl);
3180
3181 break;
3182 default:
3183 USB_DPRINTF_L2(DPRINT_CTLOP, kp->kp_lh,
3184 "keyspan_build_cmd_msg_usa49: bad param %d",
3185 pe->param);
3186
3187 break;
3188 }
3189 }
3190
3191 /*
3192 * enable the lcr settings only if they are different
3193 * with the existing settings.
3194 */
3195 ctrl_msg->setLcr = (ctrl_msg->lcr == kp->kp_lcr) ? 0 : 1;
3196
3197 }
3198
3199
3200 /*
3201 * Set the port parameters to default values
3202 */
3203 static void
keyspan_default_port_params_usa49(keyspan_port_t * kp)3204 keyspan_default_port_params_usa49(keyspan_port_t *kp)
3205 {
3206 keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49);
3207 ASSERT(mutex_owned(&kp->kp_mutex));
3208
3209 keyspan_build_cmd_msg(kp, NULL);
3210
3211 ctrl_msg->setRts = 1;
3212 ctrl_msg->rts = 1;
3213 ctrl_msg->setDtr = 1;
3214 ctrl_msg->dtr = 1;
3215
3216 ctrl_msg->_txOn = 1;
3217 ctrl_msg->_txOff = 0;
3218 ctrl_msg->txFlush = 0;
3219 ctrl_msg->txBreak = 0;
3220 ctrl_msg->rxOn = 1;
3221 ctrl_msg->rxOff = 0;
3222 ctrl_msg->rxFlush = 0;
3223 ctrl_msg->rxForward = 0;
3224 ctrl_msg->returnStatus = 1;
3225 ctrl_msg->resetDataToggle = 0;
3226 ctrl_msg->enablePort = 1;
3227 ctrl_msg->disablePort = 0;
3228
3229 /* set baud rate to 9600 */
3230 ctrl_msg->setClocking = 1;
3231 ctrl_msg->baudLo = keyspan_speedtab_usa49[13] & 0xff;
3232 ctrl_msg->baudHi = (keyspan_speedtab_usa49[13] >> 8) & 0xff;
3233 ctrl_msg->prescaler = keyspan_prescaler_49wlc[13];
3234
3235 ctrl_msg->lcr = 0x3;
3236 ctrl_msg->setLcr = 1;
3237
3238 ctrl_msg->xonChar = CSTART;
3239 ctrl_msg->xoffChar = CSTOP;
3240 ctrl_msg->ctsFlowControl = 1;
3241 ctrl_msg->setFlowControl = 1;
3242
3243 }
3244
3245
3246 /* save the port params after send cmd successfully */
3247 static void
keyspan_save_port_params_usa49(keyspan_port_t * kp)3248 keyspan_save_port_params_usa49(keyspan_port_t *kp)
3249 {
3250 keyspan_usa49_port_ctrl_msg_t *ctrl_msg = &(kp->kp_ctrl_msg.usa49);
3251
3252 ASSERT(mutex_owned(&kp->kp_mutex));
3253
3254 if (ctrl_msg->setClocking) {
3255 kp->kp_baud = ctrl_msg->baudHi;
3256 kp->kp_baud = (kp->kp_baud << 8);
3257 kp->kp_baud |= ctrl_msg->baudLo;
3258 }
3259 if (ctrl_msg->setLcr) {
3260 kp->kp_lcr = ctrl_msg->lcr;
3261 }
3262 if (ctrl_msg->setRts) {
3263 if (ctrl_msg->rts) {
3264 kp->kp_status_flag |= KEYSPAN_PORT_RTS;
3265 } else {
3266 kp->kp_status_flag &= ~KEYSPAN_PORT_RTS;
3267 }
3268 }
3269 if (ctrl_msg->setDtr) {
3270 if (ctrl_msg->dtr) {
3271 kp->kp_status_flag |= KEYSPAN_PORT_DTR;
3272 } else {
3273 kp->kp_status_flag &= ~KEYSPAN_PORT_DTR;
3274 }
3275 }
3276
3277 if (ctrl_msg->enablePort) {
3278 kp->kp_status_flag |= KEYSPAN_PORT_ENABLE;
3279 } else {
3280 kp->kp_status_flag &= ~KEYSPAN_PORT_ENABLE;
3281 }
3282
3283 /*
3284 * There are no flags in status msg (49wlc) can indicate the
3285 * break status, so we make use of ctrl_msg->txBreak here.
3286 */
3287 if (ctrl_msg->txBreak) {
3288 kp->kp_status_flag |= KEYSPAN_PORT_TXBREAK;
3289 } else {
3290 kp->kp_status_flag &= ~KEYSPAN_PORT_TXBREAK;
3291 }
3292
3293 USB_DPRINTF_L3(DPRINT_CTLOP, kp->kp_lh,
3294 "keyspan_save_port_params: baud = %x, lcr = %x,"
3295 "status_flag = %x", kp->kp_baud, kp->kp_lcr, kp->kp_status_flag);
3296
3297 }
3298