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