usb_serial.c (233774) | usb_serial.c (239179) |
---|---|
1/* $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 2001-2003, 2005, 2008 5 * Shunsuke Akiyama <akiyama@jp.FreeBSD.org>. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 14 unchanged lines hidden (view full) --- 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> | 1/* $NetBSD: ucom.c,v 1.40 2001/11/13 06:24:54 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 2001-2003, 2005, 2008 5 * Shunsuke Akiyama <akiyama@jp.FreeBSD.org>. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 14 unchanged lines hidden (view full) --- 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/dev/usb/serial/usb_serial.c 233774 2012-04-02 10:50:42Z hselasky $"); | 31__FBSDID("$FreeBSD: head/sys/dev/usb/serial/usb_serial.c 239179 2012-08-10 15:21:12Z hselasky $"); |
32 33/*- 34 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 35 * All rights reserved. 36 * 37 * This code is derived from software contributed to The NetBSD Foundation 38 * by Lennart Augustsson (lennart@augustsson.net) at 39 * Carlstedt Research & Technology. --- 101 unchanged lines hidden (view full) --- 141static usb_proc_callback_t ucom_cfg_close; 142static usb_proc_callback_t ucom_cfg_line_state; 143static usb_proc_callback_t ucom_cfg_status_change; 144static usb_proc_callback_t ucom_cfg_param; 145 146static int ucom_unit_alloc(void); 147static void ucom_unit_free(int); 148static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *); | 32 33/*- 34 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 35 * All rights reserved. 36 * 37 * This code is derived from software contributed to The NetBSD Foundation 38 * by Lennart Augustsson (lennart@augustsson.net) at 39 * Carlstedt Research & Technology. --- 101 unchanged lines hidden (view full) --- 141static usb_proc_callback_t ucom_cfg_close; 142static usb_proc_callback_t ucom_cfg_line_state; 143static usb_proc_callback_t ucom_cfg_status_change; 144static usb_proc_callback_t ucom_cfg_param; 145 146static int ucom_unit_alloc(void); 147static void ucom_unit_free(int); 148static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *); |
149static void ucom_detach_tty(struct ucom_softc *); | 149static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *); |
150static void ucom_queue_command(struct ucom_softc *, 151 usb_proc_callback_t *, struct termios *pt, 152 struct usb_proc_msg *t0, struct usb_proc_msg *t1); 153static void ucom_shutdown(struct ucom_softc *); 154static void ucom_ring(struct ucom_softc *, uint8_t); 155static void ucom_break(struct ucom_softc *, uint8_t); 156static void ucom_dtr(struct ucom_softc *, uint8_t); 157static void ucom_rts(struct ucom_softc *, uint8_t); --- 15 unchanged lines hidden (view full) --- 173 .tsw_param = ucom_param, 174 .tsw_modem = ucom_modem, 175 .tsw_free = ucom_free, 176}; 177 178MODULE_DEPEND(ucom, usb, 1, 1, 1); 179MODULE_VERSION(ucom, 1); 180 | 150static void ucom_queue_command(struct ucom_softc *, 151 usb_proc_callback_t *, struct termios *pt, 152 struct usb_proc_msg *t0, struct usb_proc_msg *t1); 153static void ucom_shutdown(struct ucom_softc *); 154static void ucom_ring(struct ucom_softc *, uint8_t); 155static void ucom_break(struct ucom_softc *, uint8_t); 156static void ucom_dtr(struct ucom_softc *, uint8_t); 157static void ucom_rts(struct ucom_softc *, uint8_t); --- 15 unchanged lines hidden (view full) --- 173 .tsw_param = ucom_param, 174 .tsw_modem = ucom_modem, 175 .tsw_free = ucom_free, 176}; 177 178MODULE_DEPEND(ucom, usb, 1, 1, 1); 179MODULE_VERSION(ucom, 1); 180 |
181#define UCOM_UNIT_MAX 128 /* limits size of ucom_bitmap */ | 181#define UCOM_UNIT_MAX 128 /* maximum number of units */ 182#define UCOM_TTY_PREFIX "U" |
182 | 183 |
183static uint8_t ucom_bitmap[(UCOM_UNIT_MAX + 7) / 8]; 184static struct mtx ucom_bitmap_mtx; 185MTX_SYSINIT(ucom_bitmap_mtx, &ucom_bitmap_mtx, "ucom bitmap", MTX_DEF); | 184static struct unrhdr *ucom_unrhdr; 185static struct mtx ucom_mtx; 186static int ucom_close_refs; |
186 | 187 |
187#define UCOM_TTY_PREFIX "U" | 188static void 189ucom_init(void *arg) 190{ 191 DPRINTF("\n"); 192 ucom_unrhdr = new_unrhdr(0, UCOM_UNIT_MAX - 1, NULL); 193 mtx_init(&ucom_mtx, "UCOM MTX", NULL, MTX_DEF); 194} 195SYSINIT(ucom_init, SI_SUB_KLD - 1, SI_ORDER_ANY, ucom_init, NULL); |
188 | 196 |
197static void 198ucom_uninit(void *arg) 199{ 200 struct unrhdr *hdr; 201 hdr = ucom_unrhdr; 202 ucom_unrhdr = NULL; 203 204 DPRINTF("\n"); 205 206 if (hdr != NULL) 207 delete_unrhdr(hdr); 208 209 mtx_destroy(&ucom_mtx); 210} 211SYSUNINIT(ucom_uninit, SI_SUB_KLD - 2, SI_ORDER_ANY, ucom_uninit, NULL); 212 |
|
189/* 190 * Mark a unit number (the X in cuaUX) as in use. 191 * 192 * Note that devices using a different naming scheme (see ucom_tty_name() 193 * callback) still use this unit allocation. 194 */ 195static int 196ucom_unit_alloc(void) 197{ 198 int unit; 199 | 213/* 214 * Mark a unit number (the X in cuaUX) as in use. 215 * 216 * Note that devices using a different naming scheme (see ucom_tty_name() 217 * callback) still use this unit allocation. 218 */ 219static int 220ucom_unit_alloc(void) 221{ 222 int unit; 223 |
200 mtx_lock(&ucom_bitmap_mtx); 201 202 for (unit = 0; unit < UCOM_UNIT_MAX; unit++) { 203 if ((ucom_bitmap[unit / 8] & (1 << (unit % 8))) == 0) { 204 ucom_bitmap[unit / 8] |= (1 << (unit % 8)); 205 break; 206 } | 224 /* sanity checks */ 225 if (ucom_unrhdr == NULL) { 226 DPRINTF("ucom_unrhdr is NULL\n"); 227 return (-1); |
207 } | 228 } |
208 209 mtx_unlock(&ucom_bitmap_mtx); 210 211 if (unit == UCOM_UNIT_MAX) 212 return -1; 213 else 214 return unit; | 229 unit = alloc_unr(ucom_unrhdr); 230 DPRINTF("unit %d is allocated\n", unit); 231 return (unit); |
215} 216 217/* 218 * Mark the unit number as not in use. 219 */ 220static void 221ucom_unit_free(int unit) 222{ | 232} 233 234/* 235 * Mark the unit number as not in use. 236 */ 237static void 238ucom_unit_free(int unit) 239{ |
223 mtx_lock(&ucom_bitmap_mtx); 224 225 ucom_bitmap[unit / 8] &= ~(1 << (unit % 8)); 226 227 mtx_unlock(&ucom_bitmap_mtx); | 240 /* sanity checks */ 241 if (unit < 0 || unit >= UCOM_UNIT_MAX || ucom_unrhdr == NULL) { 242 DPRINTF("cannot free unit number\n"); 243 return; 244 } 245 DPRINTF("unit %d is freed\n", unit); 246 free_unr(ucom_unrhdr, unit); |
228} 229 230/* 231 * Setup a group of one or more serial ports. 232 * 233 * The mutex pointed to by "mtx" is applied before all 234 * callbacks are called back. Also "mtx" must be applied 235 * before calling into the ucom-layer! 236 */ 237int 238ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc, 239 int subunits, void *parent, 240 const struct ucom_callback *callback, struct mtx *mtx) 241{ 242 int subunit; 243 int error = 0; 244 245 if ((sc == NULL) || 246 (subunits <= 0) || | 247} 248 249/* 250 * Setup a group of one or more serial ports. 251 * 252 * The mutex pointed to by "mtx" is applied before all 253 * callbacks are called back. Also "mtx" must be applied 254 * before calling into the ucom-layer! 255 */ 256int 257ucom_attach(struct ucom_super_softc *ssc, struct ucom_softc *sc, 258 int subunits, void *parent, 259 const struct ucom_callback *callback, struct mtx *mtx) 260{ 261 int subunit; 262 int error = 0; 263 264 if ((sc == NULL) || 265 (subunits <= 0) || |
247 (callback == NULL)) { | 266 (callback == NULL) || 267 (mtx == NULL)) { |
248 return (EINVAL); 249 } 250 251 /* allocate a uniq unit number */ 252 ssc->sc_unit = ucom_unit_alloc(); 253 if (ssc->sc_unit == -1) 254 return (ENOMEM); 255 --- 4 unchanged lines hidden (view full) --- 260 /* create USB request handling process */ 261 error = usb_proc_create(&ssc->sc_tq, mtx, "ucom", USB_PRI_MED); 262 if (error) { 263 ucom_unit_free(ssc->sc_unit); 264 return (error); 265 } 266 ssc->sc_subunits = subunits; 267 | 268 return (EINVAL); 269 } 270 271 /* allocate a uniq unit number */ 272 ssc->sc_unit = ucom_unit_alloc(); 273 if (ssc->sc_unit == -1) 274 return (ENOMEM); 275 --- 4 unchanged lines hidden (view full) --- 280 /* create USB request handling process */ 281 error = usb_proc_create(&ssc->sc_tq, mtx, "ucom", USB_PRI_MED); 282 if (error) { 283 ucom_unit_free(ssc->sc_unit); 284 return (error); 285 } 286 ssc->sc_subunits = subunits; 287 |
288 if (callback->ucom_free == NULL) { 289 ssc->sc_wait_refs = 1; 290 ucom_ref(ssc); 291 } 292 |
|
268 for (subunit = 0; subunit < ssc->sc_subunits; subunit++) { 269 sc[subunit].sc_subunit = subunit; 270 sc[subunit].sc_super = ssc; 271 sc[subunit].sc_mtx = mtx; 272 sc[subunit].sc_parent = parent; 273 sc[subunit].sc_callback = callback; 274 275 error = ucom_attach_tty(ssc, &sc[subunit]); 276 if (error) { 277 ucom_detach(ssc, &sc[0]); 278 return (error); 279 } | 293 for (subunit = 0; subunit < ssc->sc_subunits; subunit++) { 294 sc[subunit].sc_subunit = subunit; 295 sc[subunit].sc_super = ssc; 296 sc[subunit].sc_mtx = mtx; 297 sc[subunit].sc_parent = parent; 298 sc[subunit].sc_callback = callback; 299 300 error = ucom_attach_tty(ssc, &sc[subunit]); 301 if (error) { 302 ucom_detach(ssc, &sc[0]); 303 return (error); 304 } |
305 /* increment reference count */ 306 ucom_ref(ssc); 307 308 /* set subunit attached */ |
|
280 sc[subunit].sc_flag |= UCOM_FLAG_ATTACHED; 281 } 282 283 DPRINTF("tp = %p, unit = %d, subunits = %d\n", 284 sc->sc_tty, ssc->sc_unit, ssc->sc_subunits); 285 286 return (0); 287} --- 20 unchanged lines hidden (view full) --- 308 ssc->sc_sysctl_ttyports = NULL; 309 } 310 311 usb_proc_drain(&ssc->sc_tq); 312 313 for (subunit = 0; subunit < ssc->sc_subunits; subunit++) { 314 if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) { 315 | 309 sc[subunit].sc_flag |= UCOM_FLAG_ATTACHED; 310 } 311 312 DPRINTF("tp = %p, unit = %d, subunits = %d\n", 313 sc->sc_tty, ssc->sc_unit, ssc->sc_subunits); 314 315 return (0); 316} --- 20 unchanged lines hidden (view full) --- 337 ssc->sc_sysctl_ttyports = NULL; 338 } 339 340 usb_proc_drain(&ssc->sc_tq); 341 342 for (subunit = 0; subunit < ssc->sc_subunits; subunit++) { 343 if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) { 344 |
316 ucom_detach_tty(&sc[subunit]); | 345 ucom_detach_tty(ssc, &sc[subunit]); |
317 318 /* avoid duplicate detach */ 319 sc[subunit].sc_flag &= ~UCOM_FLAG_ATTACHED; 320 } 321 } | 346 347 /* avoid duplicate detach */ 348 sc[subunit].sc_flag &= ~UCOM_FLAG_ATTACHED; 349 } 350 } |
322 ucom_unit_free(ssc->sc_unit); | |
323 usb_proc_free(&ssc->sc_tq); | 351 usb_proc_free(&ssc->sc_tq); |
352 353 if (ssc->sc_wait_refs != 0) { 354 ucom_unref(ssc); 355 ucom_drain(ssc); 356 } |
|
324} 325 | 357} 358 |
359void 360ucom_drain(struct ucom_super_softc *ssc) 361{ 362 mtx_lock(&ucom_mtx); 363 while (ssc->sc_refs >= 2) { 364 printf("ucom: Waiting for a TTY device to close.\n"); 365 usb_pause_mtx(&ucom_mtx, hz); 366 } 367 mtx_unlock(&ucom_mtx); 368} 369 370void 371ucom_drain_all(void *arg) 372{ 373 mtx_lock(&ucom_mtx); 374 while (ucom_close_refs > 0) { 375 printf("ucom: Waiting for all detached TTY " 376 "devices to have open fds closed.\n"); 377 usb_pause_mtx(&ucom_mtx, hz); 378 } 379 mtx_unlock(&ucom_mtx); 380} 381 |
|
326static int 327ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) 328{ 329 struct tty *tp; 330 char buf[32]; /* temporary TTY device name buffer */ 331 332 tp = tty_alloc_mutex(&ucom_class, sc, sc->sc_mtx); 333 if (tp == NULL) --- 17 unchanged lines hidden (view full) --- 351 ssc->sc_unit); 352 } 353 } 354 tty_makedev(tp, NULL, "%s", buf); 355 356 sc->sc_tty = tp; 357 358 DPRINTF("ttycreate: %s\n", buf); | 382static int 383ucom_attach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) 384{ 385 struct tty *tp; 386 char buf[32]; /* temporary TTY device name buffer */ 387 388 tp = tty_alloc_mutex(&ucom_class, sc, sc->sc_mtx); 389 if (tp == NULL) --- 17 unchanged lines hidden (view full) --- 407 ssc->sc_unit); 408 } 409 } 410 tty_makedev(tp, NULL, "%s", buf); 411 412 sc->sc_tty = tp; 413 414 DPRINTF("ttycreate: %s\n", buf); |
359 cv_init(&sc->sc_cv, "ucom"); | |
360 361 /* Check if this device should be a console */ 362 if ((ucom_cons_softc == NULL) && 363 (ssc->sc_unit == ucom_cons_unit) && 364 (sc->sc_subunit == ucom_cons_subunit)) { 365 struct termios t; 366 367 DPRINTF("unit %d subunit %d is console", ssc->sc_unit, sc->sc_subunit); 368 369 ucom_cons_softc = sc; 370 371 memset(&t, 0, sizeof(t)); 372 t.c_ispeed = ucom_cons_baud; 373 t.c_ospeed = t.c_ispeed; 374 t.c_cflag = CS8; 375 | 415 416 /* Check if this device should be a console */ 417 if ((ucom_cons_softc == NULL) && 418 (ssc->sc_unit == ucom_cons_unit) && 419 (sc->sc_subunit == ucom_cons_subunit)) { 420 struct termios t; 421 422 DPRINTF("unit %d subunit %d is console", ssc->sc_unit, sc->sc_subunit); 423 424 ucom_cons_softc = sc; 425 426 memset(&t, 0, sizeof(t)); 427 t.c_ispeed = ucom_cons_baud; 428 t.c_ospeed = t.c_ispeed; 429 t.c_cflag = CS8; 430 |
376 mtx_lock(ucom_cons_softc->sc_mtx); | 431 UCOM_MTX_LOCK(ucom_cons_softc); |
377 ucom_cons_rx_low = 0; 378 ucom_cons_rx_high = 0; 379 ucom_cons_tx_low = 0; 380 ucom_cons_tx_high = 0; 381 sc->sc_flag |= UCOM_FLAG_CONSOLE; 382 ucom_open(ucom_cons_softc->sc_tty); 383 ucom_param(ucom_cons_softc->sc_tty, &t); | 432 ucom_cons_rx_low = 0; 433 ucom_cons_rx_high = 0; 434 ucom_cons_tx_low = 0; 435 ucom_cons_tx_high = 0; 436 sc->sc_flag |= UCOM_FLAG_CONSOLE; 437 ucom_open(ucom_cons_softc->sc_tty); 438 ucom_param(ucom_cons_softc->sc_tty, &t); |
384 mtx_unlock(ucom_cons_softc->sc_mtx); | 439 UCOM_MTX_UNLOCK(ucom_cons_softc); |
385 } 386 387 return (0); 388} 389 390static void | 440 } 441 442 return (0); 443} 444 445static void |
391ucom_detach_tty(struct ucom_softc *sc) | 446ucom_detach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc) |
392{ 393 struct tty *tp = sc->sc_tty; 394 395 DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty); 396 397 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { | 447{ 448 struct tty *tp = sc->sc_tty; 449 450 DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty); 451 452 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { |
398 mtx_lock(ucom_cons_softc->sc_mtx); | 453 UCOM_MTX_LOCK(ucom_cons_softc); |
399 ucom_close(ucom_cons_softc->sc_tty); 400 sc->sc_flag &= ~UCOM_FLAG_CONSOLE; | 454 ucom_close(ucom_cons_softc->sc_tty); 455 sc->sc_flag &= ~UCOM_FLAG_CONSOLE; |
401 mtx_unlock(ucom_cons_softc->sc_mtx); | 456 UCOM_MTX_UNLOCK(ucom_cons_softc); |
402 ucom_cons_softc = NULL; 403 } 404 405 /* the config thread has been stopped when we get here */ 406 | 457 ucom_cons_softc = NULL; 458 } 459 460 /* the config thread has been stopped when we get here */ 461 |
407 mtx_lock(sc->sc_mtx); | 462 UCOM_MTX_LOCK(sc); |
408 sc->sc_flag |= UCOM_FLAG_GONE; 409 sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_LL_READY); | 463 sc->sc_flag |= UCOM_FLAG_GONE; 464 sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_LL_READY); |
410 mtx_unlock(sc->sc_mtx); | 465 UCOM_MTX_UNLOCK(sc); 466 |
411 if (tp) { | 467 if (tp) { |
468 mtx_lock(&ucom_mtx); 469 ucom_close_refs++; 470 mtx_unlock(&ucom_mtx); 471 |
|
412 tty_lock(tp); 413 414 ucom_close(tp); /* close, if any */ 415 416 tty_rel_gone(tp); 417 | 472 tty_lock(tp); 473 474 ucom_close(tp); /* close, if any */ 475 476 tty_rel_gone(tp); 477 |
418 mtx_lock(sc->sc_mtx); 419 /* Wait for the callback after the TTY is torn down */ 420 while (sc->sc_ttyfreed == 0) 421 cv_wait(&sc->sc_cv, sc->sc_mtx); | 478 UCOM_MTX_LOCK(sc); |
422 /* 423 * make sure that read and write transfers are stopped 424 */ | 479 /* 480 * make sure that read and write transfers are stopped 481 */ |
425 if (sc->sc_callback->ucom_stop_read) { | 482 if (sc->sc_callback->ucom_stop_read) |
426 (sc->sc_callback->ucom_stop_read) (sc); | 483 (sc->sc_callback->ucom_stop_read) (sc); |
427 } 428 if (sc->sc_callback->ucom_stop_write) { | 484 if (sc->sc_callback->ucom_stop_write) |
429 (sc->sc_callback->ucom_stop_write) (sc); | 485 (sc->sc_callback->ucom_stop_write) (sc); |
430 } 431 mtx_unlock(sc->sc_mtx); | 486 UCOM_MTX_UNLOCK(sc); |
432 } | 487 } |
433 cv_destroy(&sc->sc_cv); | |
434} 435 436void 437ucom_set_pnpinfo_usb(struct ucom_super_softc *ssc, device_t dev) 438{ 439 char buf[64]; 440 uint8_t iface_index; 441 struct usb_attach_arg *uaa; --- 29 unchanged lines hidden (view full) --- 471static void 472ucom_queue_command(struct ucom_softc *sc, 473 usb_proc_callback_t *fn, struct termios *pt, 474 struct usb_proc_msg *t0, struct usb_proc_msg *t1) 475{ 476 struct ucom_super_softc *ssc = sc->sc_super; 477 struct ucom_param_task *task; 478 | 488} 489 490void 491ucom_set_pnpinfo_usb(struct ucom_super_softc *ssc, device_t dev) 492{ 493 char buf[64]; 494 uint8_t iface_index; 495 struct usb_attach_arg *uaa; --- 29 unchanged lines hidden (view full) --- 525static void 526ucom_queue_command(struct ucom_softc *sc, 527 usb_proc_callback_t *fn, struct termios *pt, 528 struct usb_proc_msg *t0, struct usb_proc_msg *t1) 529{ 530 struct ucom_super_softc *ssc = sc->sc_super; 531 struct ucom_param_task *task; 532 |
479 mtx_assert(sc->sc_mtx, MA_OWNED); | 533 UCOM_MTX_ASSERT(sc, MA_OWNED); |
480 481 if (usb_proc_is_gone(&ssc->sc_tq)) { 482 DPRINTF("proc is gone\n"); 483 return; /* nothing to do */ 484 } 485 /* 486 * NOTE: The task cannot get executed before we drop the 487 * "sc_mtx" mutex. It is safe to update fields in the message --- 27 unchanged lines hidden (view full) --- 515 sc->sc_last_start_xfer = &task->hdr; 516} 517 518static void 519ucom_shutdown(struct ucom_softc *sc) 520{ 521 struct tty *tp = sc->sc_tty; 522 | 534 535 if (usb_proc_is_gone(&ssc->sc_tq)) { 536 DPRINTF("proc is gone\n"); 537 return; /* nothing to do */ 538 } 539 /* 540 * NOTE: The task cannot get executed before we drop the 541 * "sc_mtx" mutex. It is safe to update fields in the message --- 27 unchanged lines hidden (view full) --- 569 sc->sc_last_start_xfer = &task->hdr; 570} 571 572static void 573ucom_shutdown(struct ucom_softc *sc) 574{ 575 struct tty *tp = sc->sc_tty; 576 |
523 mtx_assert(sc->sc_mtx, MA_OWNED); | 577 UCOM_MTX_ASSERT(sc, MA_OWNED); |
524 525 DPRINTF("\n"); 526 527 /* 528 * Hang up if necessary: 529 */ 530 if (tp->t_termios.c_cflag & HUPCL) { 531 ucom_modem(tp, 0, SER_DTR); --- 84 unchanged lines hidden (view full) --- 616} 617 618static int 619ucom_open(struct tty *tp) 620{ 621 struct ucom_softc *sc = tty_softc(tp); 622 int error; 623 | 578 579 DPRINTF("\n"); 580 581 /* 582 * Hang up if necessary: 583 */ 584 if (tp->t_termios.c_cflag & HUPCL) { 585 ucom_modem(tp, 0, SER_DTR); --- 84 unchanged lines hidden (view full) --- 670} 671 672static int 673ucom_open(struct tty *tp) 674{ 675 struct ucom_softc *sc = tty_softc(tp); 676 int error; 677 |
624 mtx_assert(sc->sc_mtx, MA_OWNED); | 678 UCOM_MTX_ASSERT(sc, MA_OWNED); |
625 626 if (sc->sc_flag & UCOM_FLAG_GONE) { 627 return (ENXIO); 628 } 629 if (sc->sc_flag & UCOM_FLAG_HL_READY) { 630 /* already opened */ 631 return (0); 632 } --- 61 unchanged lines hidden (view full) --- 694 } 695} 696 697static void 698ucom_close(struct tty *tp) 699{ 700 struct ucom_softc *sc = tty_softc(tp); 701 | 679 680 if (sc->sc_flag & UCOM_FLAG_GONE) { 681 return (ENXIO); 682 } 683 if (sc->sc_flag & UCOM_FLAG_HL_READY) { 684 /* already opened */ 685 return (0); 686 } --- 61 unchanged lines hidden (view full) --- 748 } 749} 750 751static void 752ucom_close(struct tty *tp) 753{ 754 struct ucom_softc *sc = tty_softc(tp); 755 |
702 mtx_assert(sc->sc_mtx, MA_OWNED); | 756 UCOM_MTX_ASSERT(sc, MA_OWNED); |
703 704 DPRINTF("tp=%p\n", tp); 705 706 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 707 DPRINTF("tp=%p already closed\n", tp); 708 return; 709 } 710 ucom_shutdown(sc); --- 10 unchanged lines hidden (view full) --- 721} 722 723static int 724ucom_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 725{ 726 struct ucom_softc *sc = tty_softc(tp); 727 int error; 728 | 757 758 DPRINTF("tp=%p\n", tp); 759 760 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 761 DPRINTF("tp=%p already closed\n", tp); 762 return; 763 } 764 ucom_shutdown(sc); --- 10 unchanged lines hidden (view full) --- 775} 776 777static int 778ucom_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 779{ 780 struct ucom_softc *sc = tty_softc(tp); 781 int error; 782 |
729 mtx_assert(sc->sc_mtx, MA_OWNED); | 783 UCOM_MTX_ASSERT(sc, MA_OWNED); |
730 731 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 732 return (EIO); 733 } 734 DPRINTF("cmd = 0x%08lx\n", cmd); 735 736 switch (cmd) { 737#if 0 --- 27 unchanged lines hidden (view full) --- 765} 766 767static int 768ucom_modem(struct tty *tp, int sigon, int sigoff) 769{ 770 struct ucom_softc *sc = tty_softc(tp); 771 uint8_t onoff; 772 | 784 785 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 786 return (EIO); 787 } 788 DPRINTF("cmd = 0x%08lx\n", cmd); 789 790 switch (cmd) { 791#if 0 --- 27 unchanged lines hidden (view full) --- 819} 820 821static int 822ucom_modem(struct tty *tp, int sigon, int sigoff) 823{ 824 struct ucom_softc *sc = tty_softc(tp); 825 uint8_t onoff; 826 |
773 mtx_assert(sc->sc_mtx, MA_OWNED); | 827 UCOM_MTX_ASSERT(sc, MA_OWNED); |
774 775 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 776 return (0); 777 } 778 if ((sigon == 0) && (sigoff == 0)) { 779 780 if (sc->sc_mcr & SER_DTR) { 781 sigon |= SER_DTR; --- 102 unchanged lines hidden (view full) --- 884 sc->sc_callback->ucom_cfg_set_ring(sc, 885 (last_value & UCOM_LS_RING) ? 1 : 0); 886} 887 888static void 889ucom_line_state(struct ucom_softc *sc, 890 uint8_t set_bits, uint8_t clear_bits) 891{ | 828 829 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 830 return (0); 831 } 832 if ((sigon == 0) && (sigoff == 0)) { 833 834 if (sc->sc_mcr & SER_DTR) { 835 sigon |= SER_DTR; --- 102 unchanged lines hidden (view full) --- 938 sc->sc_callback->ucom_cfg_set_ring(sc, 939 (last_value & UCOM_LS_RING) ? 1 : 0); 940} 941 942static void 943ucom_line_state(struct ucom_softc *sc, 944 uint8_t set_bits, uint8_t clear_bits) 945{ |
892 mtx_assert(sc->sc_mtx, MA_OWNED); | 946 UCOM_MTX_ASSERT(sc, MA_OWNED); |
893 894 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 895 return; 896 } 897 898 DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits); 899 900 /* update current programmed line state */ --- 61 unchanged lines hidden (view full) --- 962 struct tty *tp; 963 uint8_t new_msr; 964 uint8_t new_lsr; 965 uint8_t onoff; 966 uint8_t lsr_delta; 967 968 tp = sc->sc_tty; 969 | 947 948 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 949 return; 950 } 951 952 DPRINTF("on=0x%02x, off=0x%02x\n", set_bits, clear_bits); 953 954 /* update current programmed line state */ --- 61 unchanged lines hidden (view full) --- 1016 struct tty *tp; 1017 uint8_t new_msr; 1018 uint8_t new_lsr; 1019 uint8_t onoff; 1020 uint8_t lsr_delta; 1021 1022 tp = sc->sc_tty; 1023 |
970 mtx_assert(sc->sc_mtx, MA_OWNED); | 1024 UCOM_MTX_ASSERT(sc, MA_OWNED); |
971 972 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 973 return; 974 } 975 if (sc->sc_callback->ucom_cfg_get_status == NULL) { 976 return; 977 } 978 /* get status */ --- 45 unchanged lines hidden (view full) --- 1024 ttydisc_rint(tp, 0, TRE_PARITY); 1025 ttydisc_rint_done(tp); 1026 } 1027} 1028 1029void 1030ucom_status_change(struct ucom_softc *sc) 1031{ | 1025 1026 if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) { 1027 return; 1028 } 1029 if (sc->sc_callback->ucom_cfg_get_status == NULL) { 1030 return; 1031 } 1032 /* get status */ --- 45 unchanged lines hidden (view full) --- 1078 ttydisc_rint(tp, 0, TRE_PARITY); 1079 ttydisc_rint_done(tp); 1080 } 1081} 1082 1083void 1084ucom_status_change(struct ucom_softc *sc) 1085{ |
1032 mtx_assert(sc->sc_mtx, MA_OWNED); | 1086 UCOM_MTX_ASSERT(sc, MA_OWNED); |
1033 1034 if (sc->sc_flag & UCOM_FLAG_CONSOLE) 1035 return; /* not supported */ 1036 1037 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1038 return; 1039 } 1040 DPRINTF("\n"); --- 25 unchanged lines hidden (view full) --- 1066 1067static int 1068ucom_param(struct tty *tp, struct termios *t) 1069{ 1070 struct ucom_softc *sc = tty_softc(tp); 1071 uint8_t opened; 1072 int error; 1073 | 1087 1088 if (sc->sc_flag & UCOM_FLAG_CONSOLE) 1089 return; /* not supported */ 1090 1091 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1092 return; 1093 } 1094 DPRINTF("\n"); --- 25 unchanged lines hidden (view full) --- 1120 1121static int 1122ucom_param(struct tty *tp, struct termios *t) 1123{ 1124 struct ucom_softc *sc = tty_softc(tp); 1125 uint8_t opened; 1126 int error; 1127 |
1074 mtx_assert(sc->sc_mtx, MA_OWNED); | 1128 UCOM_MTX_ASSERT(sc, MA_OWNED); |
1075 1076 opened = 0; 1077 error = 0; 1078 1079 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1080 1081 /* XXX the TTY layer should call "open()" first! */ 1082 --- 50 unchanged lines hidden (view full) --- 1133 return (error); 1134} 1135 1136static void 1137ucom_outwakeup(struct tty *tp) 1138{ 1139 struct ucom_softc *sc = tty_softc(tp); 1140 | 1129 1130 opened = 0; 1131 error = 0; 1132 1133 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1134 1135 /* XXX the TTY layer should call "open()" first! */ 1136 --- 50 unchanged lines hidden (view full) --- 1187 return (error); 1188} 1189 1190static void 1191ucom_outwakeup(struct tty *tp) 1192{ 1193 struct ucom_softc *sc = tty_softc(tp); 1194 |
1141 mtx_assert(sc->sc_mtx, MA_OWNED); | 1195 UCOM_MTX_ASSERT(sc, MA_OWNED); |
1142 1143 DPRINTF("sc = %p\n", sc); 1144 1145 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1146 /* The higher layer is not ready */ 1147 return; 1148 } 1149 ucom_start_transfers(sc); --- 10 unchanged lines hidden (view full) --- 1160ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc, 1161 uint32_t offset, uint32_t len, uint32_t *actlen) 1162{ 1163 struct usb_page_search res; 1164 struct tty *tp = sc->sc_tty; 1165 uint32_t cnt; 1166 uint32_t offset_orig; 1167 | 1196 1197 DPRINTF("sc = %p\n", sc); 1198 1199 if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { 1200 /* The higher layer is not ready */ 1201 return; 1202 } 1203 ucom_start_transfers(sc); --- 10 unchanged lines hidden (view full) --- 1214ucom_get_data(struct ucom_softc *sc, struct usb_page_cache *pc, 1215 uint32_t offset, uint32_t len, uint32_t *actlen) 1216{ 1217 struct usb_page_search res; 1218 struct tty *tp = sc->sc_tty; 1219 uint32_t cnt; 1220 uint32_t offset_orig; 1221 |
1168 mtx_assert(sc->sc_mtx, MA_OWNED); | 1222 UCOM_MTX_ASSERT(sc, MA_OWNED); |
1169 1170 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 1171 unsigned int temp; 1172 1173 /* get total TX length */ 1174 1175 temp = ucom_cons_tx_high - ucom_cons_tx_low; 1176 temp %= UCOM_CONS_BUFSIZE; --- 62 unchanged lines hidden (view full) --- 1239ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc, 1240 uint32_t offset, uint32_t len) 1241{ 1242 struct usb_page_search res; 1243 struct tty *tp = sc->sc_tty; 1244 char *buf; 1245 uint32_t cnt; 1246 | 1223 1224 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 1225 unsigned int temp; 1226 1227 /* get total TX length */ 1228 1229 temp = ucom_cons_tx_high - ucom_cons_tx_low; 1230 temp %= UCOM_CONS_BUFSIZE; --- 62 unchanged lines hidden (view full) --- 1293ucom_put_data(struct ucom_softc *sc, struct usb_page_cache *pc, 1294 uint32_t offset, uint32_t len) 1295{ 1296 struct usb_page_search res; 1297 struct tty *tp = sc->sc_tty; 1298 char *buf; 1299 uint32_t cnt; 1300 |
1247 mtx_assert(sc->sc_mtx, MA_OWNED); | 1301 UCOM_MTX_ASSERT(sc, MA_OWNED); |
1248 1249 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 1250 unsigned int temp; 1251 1252 /* get maximum RX length */ 1253 1254 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_rx_high + ucom_cons_rx_low; 1255 temp %= UCOM_CONS_BUFSIZE; --- 64 unchanged lines hidden (view full) --- 1320 ttydisc_rint_done(tp); 1321} 1322 1323static void 1324ucom_free(void *xsc) 1325{ 1326 struct ucom_softc *sc = xsc; 1327 | 1302 1303 if (sc->sc_flag & UCOM_FLAG_CONSOLE) { 1304 unsigned int temp; 1305 1306 /* get maximum RX length */ 1307 1308 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_rx_high + ucom_cons_rx_low; 1309 temp %= UCOM_CONS_BUFSIZE; --- 64 unchanged lines hidden (view full) --- 1374 ttydisc_rint_done(tp); 1375} 1376 1377static void 1378ucom_free(void *xsc) 1379{ 1380 struct ucom_softc *sc = xsc; 1381 |
1328 mtx_lock(sc->sc_mtx); 1329 sc->sc_ttyfreed = 1; 1330 cv_signal(&sc->sc_cv); 1331 mtx_unlock(sc->sc_mtx); | 1382 if (sc->sc_callback->ucom_free != NULL) 1383 sc->sc_callback->ucom_free(sc); 1384 else 1385 ucom_unref(sc->sc_super); 1386 1387 mtx_lock(&ucom_mtx); 1388 ucom_close_refs--; 1389 mtx_unlock(&ucom_mtx); |
1332} 1333 1334static cn_probe_t ucom_cnprobe; 1335static cn_init_t ucom_cninit; 1336static cn_term_t ucom_cnterm; 1337static cn_getc_t ucom_cngetc; 1338static cn_putc_t ucom_cnputc; 1339static cn_grab_t ucom_cngrab; --- 36 unchanged lines hidden (view full) --- 1376ucom_cngetc(struct consdev *cd) 1377{ 1378 struct ucom_softc *sc = ucom_cons_softc; 1379 int c; 1380 1381 if (sc == NULL) 1382 return (-1); 1383 | 1390} 1391 1392static cn_probe_t ucom_cnprobe; 1393static cn_init_t ucom_cninit; 1394static cn_term_t ucom_cnterm; 1395static cn_getc_t ucom_cngetc; 1396static cn_putc_t ucom_cnputc; 1397static cn_grab_t ucom_cngrab; --- 36 unchanged lines hidden (view full) --- 1434ucom_cngetc(struct consdev *cd) 1435{ 1436 struct ucom_softc *sc = ucom_cons_softc; 1437 int c; 1438 1439 if (sc == NULL) 1440 return (-1); 1441 |
1384 mtx_lock(sc->sc_mtx); | 1442 UCOM_MTX_LOCK(sc); |
1385 1386 if (ucom_cons_rx_low != ucom_cons_rx_high) { 1387 c = ucom_cons_rx_buf[ucom_cons_rx_low]; 1388 ucom_cons_rx_low ++; 1389 ucom_cons_rx_low %= UCOM_CONS_BUFSIZE; 1390 } else { 1391 c = -1; 1392 } 1393 1394 /* start USB transfers */ 1395 ucom_outwakeup(sc->sc_tty); 1396 | 1443 1444 if (ucom_cons_rx_low != ucom_cons_rx_high) { 1445 c = ucom_cons_rx_buf[ucom_cons_rx_low]; 1446 ucom_cons_rx_low ++; 1447 ucom_cons_rx_low %= UCOM_CONS_BUFSIZE; 1448 } else { 1449 c = -1; 1450 } 1451 1452 /* start USB transfers */ 1453 ucom_outwakeup(sc->sc_tty); 1454 |
1397 mtx_unlock(sc->sc_mtx); | 1455 UCOM_MTX_UNLOCK(sc); |
1398 1399 /* poll if necessary */ 1400 if (kdb_active && sc->sc_callback->ucom_poll) 1401 (sc->sc_callback->ucom_poll) (sc); 1402 1403 return (c); 1404} 1405 1406static void 1407ucom_cnputc(struct consdev *cd, int c) 1408{ 1409 struct ucom_softc *sc = ucom_cons_softc; 1410 unsigned int temp; 1411 1412 if (sc == NULL) 1413 return; 1414 1415 repeat: 1416 | 1456 1457 /* poll if necessary */ 1458 if (kdb_active && sc->sc_callback->ucom_poll) 1459 (sc->sc_callback->ucom_poll) (sc); 1460 1461 return (c); 1462} 1463 1464static void 1465ucom_cnputc(struct consdev *cd, int c) 1466{ 1467 struct ucom_softc *sc = ucom_cons_softc; 1468 unsigned int temp; 1469 1470 if (sc == NULL) 1471 return; 1472 1473 repeat: 1474 |
1417 mtx_lock(sc->sc_mtx); | 1475 UCOM_MTX_LOCK(sc); |
1418 1419 /* compute maximum TX length */ 1420 1421 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_tx_high + ucom_cons_tx_low; 1422 temp %= UCOM_CONS_BUFSIZE; 1423 1424 if (temp) { 1425 ucom_cons_tx_buf[ucom_cons_tx_high] = c; 1426 ucom_cons_tx_high ++; 1427 ucom_cons_tx_high %= UCOM_CONS_BUFSIZE; 1428 } 1429 1430 /* start USB transfers */ 1431 ucom_outwakeup(sc->sc_tty); 1432 | 1476 1477 /* compute maximum TX length */ 1478 1479 temp = (UCOM_CONS_BUFSIZE - 1) - ucom_cons_tx_high + ucom_cons_tx_low; 1480 temp %= UCOM_CONS_BUFSIZE; 1481 1482 if (temp) { 1483 ucom_cons_tx_buf[ucom_cons_tx_high] = c; 1484 ucom_cons_tx_high ++; 1485 ucom_cons_tx_high %= UCOM_CONS_BUFSIZE; 1486 } 1487 1488 /* start USB transfers */ 1489 ucom_outwakeup(sc->sc_tty); 1490 |
1433 mtx_unlock(sc->sc_mtx); | 1491 UCOM_MTX_UNLOCK(sc); |
1434 1435 /* poll if necessary */ 1436 if (kdb_active && sc->sc_callback->ucom_poll) { 1437 (sc->sc_callback->ucom_poll) (sc); 1438 /* simple flow control */ 1439 if (temp == 0) 1440 goto repeat; 1441 } 1442} 1443 | 1492 1493 /* poll if necessary */ 1494 if (kdb_active && sc->sc_callback->ucom_poll) { 1495 (sc->sc_callback->ucom_poll) (sc); 1496 /* simple flow control */ 1497 if (temp == 0) 1498 goto repeat; 1499 } 1500} 1501 |
1502/*------------------------------------------------------------------------* 1503 * ucom_ref 1504 * 1505 * This function will increment the super UCOM reference count. 1506 *------------------------------------------------------------------------*/ 1507void 1508ucom_ref(struct ucom_super_softc *ssc) 1509{ 1510 mtx_lock(&ucom_mtx); 1511 ssc->sc_refs++; 1512 mtx_unlock(&ucom_mtx); 1513} 1514 1515/*------------------------------------------------------------------------* 1516 * ucom_unref 1517 * 1518 * This function will decrement the super UCOM reference count. 1519 * 1520 * Return values: 1521 * 0: UCOM structures are still referenced. 1522 * Else: UCOM structures are no longer referenced. 1523 *------------------------------------------------------------------------*/ 1524int 1525ucom_unref(struct ucom_super_softc *ssc) 1526{ 1527 int retval; 1528 int free_unit; 1529 1530 mtx_lock(&ucom_mtx); 1531 retval = (ssc->sc_refs < 2); 1532 free_unit = (ssc->sc_refs == 1); 1533 ssc->sc_refs--; 1534 mtx_unlock(&ucom_mtx); 1535 1536 /* 1537 * This function might be called when the "ssc" is only zero 1538 * initialized and in that case the unit number should not be 1539 * freed. 1540 */ 1541 if (free_unit) 1542 ucom_unit_free(ssc->sc_unit); 1543 return (retval); 1544} 1545 |
|
1444#if defined(GDB) 1445 1446#include <gdb/gdb.h> 1447 1448static gdb_probe_f ucom_gdbprobe; 1449static gdb_init_f ucom_gdbinit; 1450static gdb_term_f ucom_gdbterm; 1451static gdb_getc_f ucom_gdbgetc; --- 33 unchanged lines hidden --- | 1546#if defined(GDB) 1547 1548#include <gdb/gdb.h> 1549 1550static gdb_probe_f ucom_gdbprobe; 1551static gdb_init_f ucom_gdbinit; 1552static gdb_term_f ucom_gdbterm; 1553static gdb_getc_f ucom_gdbgetc; --- 33 unchanged lines hidden --- |