Deleted Added
full compact
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 ---