Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/nmdm/nmdm.c
Show First 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
nmdm_close(struct tty *tp) | nmdm_close(struct tty *tp) | ||||
{ | { | ||||
struct nmdmpart *np; | struct nmdmpart *np; | ||||
struct nmdmpart *onp; | struct nmdmpart *onp; | ||||
struct tty *otp; | struct tty *otp; | ||||
ttydisc_assert_locked(tp); | |||||
np = tty_softc(tp); | np = tty_softc(tp); | ||||
onp = np->np_other; | onp = np->np_other; | ||||
otp = onp->np_tty; | otp = onp->np_tty; | ||||
/* If second part is opened, do not destroy ourselves. */ | /* If second part is opened, do not destroy ourselves. */ | ||||
if (tty_opened(otp)) | if (tty_opened(otp)) | ||||
return; | return; | ||||
/* Shut down self. */ | /* Shut down self. */ | ||||
tty_rel_gone(tp); | tty_rel_gone(tp); | ||||
/* Shut down second part. */ | /* Shut down second part. */ | ||||
tty_lock(tp); | tty_lock(otp); | ||||
onp = np->np_other; | onp = np->np_other; | ||||
if (onp == NULL) | if (onp == NULL) | ||||
return; | return; | ||||
otp = onp->np_tty; | otp = onp->np_tty; | ||||
tty_rel_gone(otp); | tty_rel_gone(otp); | ||||
tty_lock(tp); | tty_lock(tp); | ||||
ttydisc_lock(tp); | |||||
} | } | ||||
static void | static void | ||||
nmdm_free(void *softc) | nmdm_free(void *softc) | ||||
{ | { | ||||
struct nmdmpart *np = (struct nmdmpart *)softc; | struct nmdmpart *np = (struct nmdmpart *)softc; | ||||
struct nmdmsoftc *ns = np->np_pair; | struct nmdmsoftc *ns = np->np_pair; | ||||
callout_drain(&np->np_callout); | callout_drain(&np->np_callout); | ||||
kevans: This is also fixed in my local draft... unsure why I did this. | |||||
taskqueue_drain(taskqueue_swi, &np->np_task); | taskqueue_drain(taskqueue_swi, &np->np_task); | ||||
/* | /* | ||||
* The function is called on both parts simultaneously. We serialize | * The function is called on both parts simultaneously. We serialize | ||||
* with help of ns_mtx. The first invocation should return and | * with help of ns_mtx. The first invocation should return and | ||||
* delegate freeing of resources to the second. | * delegate freeing of resources to the second. | ||||
*/ | */ | ||||
mtx_lock(&ns->ns_mtx); | mtx_lock(&ns->ns_mtx); | ||||
Show All 39 Lines | nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen, | ||||
TASK_INIT(&ns->ns_part1.np_task, 0, nmdm_task_tty, &ns->ns_part1); | TASK_INIT(&ns->ns_part1.np_task, 0, nmdm_task_tty, &ns->ns_part1); | ||||
callout_init_mtx(&ns->ns_part1.np_callout, &ns->ns_mtx, 0); | callout_init_mtx(&ns->ns_part1.np_callout, &ns->ns_mtx, 0); | ||||
ns->ns_part2.np_pair = ns; | ns->ns_part2.np_pair = ns; | ||||
ns->ns_part2.np_other = &ns->ns_part1; | ns->ns_part2.np_other = &ns->ns_part1; | ||||
TASK_INIT(&ns->ns_part2.np_task, 0, nmdm_task_tty, &ns->ns_part2); | TASK_INIT(&ns->ns_part2.np_task, 0, nmdm_task_tty, &ns->ns_part2); | ||||
callout_init_mtx(&ns->ns_part2.np_callout, &ns->ns_mtx, 0); | callout_init_mtx(&ns->ns_part2.np_callout, &ns->ns_mtx, 0); | ||||
/* Create device nodes. */ | /* | ||||
* Create device nodes. Both sides can have distinct tty locks, as | |||||
* long as they share a ttydisc lock. | |||||
*/ | |||||
tp = ns->ns_part1.np_tty = tty_alloc_mutex(&nmdm_class, &ns->ns_part1, | tp = ns->ns_part1.np_tty = tty_alloc_mutex(&nmdm_class, &ns->ns_part1, | ||||
&ns->ns_mtx); | &ns->ns_mtx); | ||||
*end = 'A'; | *end = 'A'; | ||||
error = tty_makedevf(tp, cred, endc == 'A' ? TTYMK_CLONING : 0, | error = tty_makedevf(tp, cred, endc == 'A' ? TTYMK_CLONING : 0, | ||||
"%s", name); | "%s", name); | ||||
if (error) { | if (error) { | ||||
*end = endc; | *end = endc; | ||||
mtx_destroy(&ns->ns_mtx); | mtx_destroy(&ns->ns_mtx); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
nmdm_task_tty(void *arg, int pending __unused) | nmdm_task_tty(void *arg, int pending __unused) | ||||
{ | { | ||||
struct tty *tp, *otp; | struct tty *tp, *otp; | ||||
struct nmdmpart *np = arg; | struct nmdmpart *np = arg; | ||||
char c; | char c; | ||||
tp = np->np_tty; | tp = np->np_tty; | ||||
tty_lock(tp); | ttydisc_lock(tp); | ||||
if (tty_gone(tp)) { | if (tty_gone(tp)) { | ||||
tty_unlock(tp); | ttydisc_unlock(tp); | ||||
return; | return; | ||||
} | } | ||||
/* | |||||
* We'll be operating on otp while maintaining the tp ttydisc lock; this | |||||
* is OK, since they share the same ttydisc lock. | |||||
*/ | |||||
otp = np->np_other->np_tty; | otp = np->np_other->np_tty; | ||||
KASSERT(otp != NULL, ("NULL otp in nmdmstart")); | KASSERT(otp != NULL, ("NULL otp in nmdmstart")); | ||||
KASSERT(otp != tp, ("NULL otp == tp nmdmstart")); | KASSERT(otp != tp, ("NULL otp == tp nmdmstart")); | ||||
if (np->np_other->np_dcd) { | if (np->np_other->np_dcd) { | ||||
if (!tty_opened(tp)) { | if (!tty_opened(tp)) { | ||||
np->np_other->np_dcd = 0; | np->np_other->np_dcd = 0; | ||||
ttydisc_modem(otp, 0); | ttydisc_modem(otp, 0); | ||||
} | } | ||||
} else { | } else { | ||||
if (tty_opened(tp)) { | if (tty_opened(tp)) { | ||||
np->np_other->np_dcd = 1; | np->np_other->np_dcd = 1; | ||||
ttydisc_modem(otp, 1); | ttydisc_modem(otp, 1); | ||||
} | } | ||||
} | } | ||||
/* This may happen when we are in detach process. */ | /* This may happen when we are in detach process. */ | ||||
if (tty_gone(otp)) { | if (tty_gone(otp)) { | ||||
tty_unlock(otp); | ttydisc_unlock(tp); | ||||
return; | return; | ||||
} | } | ||||
while (ttydisc_rint_poll(otp) > 0) { | while (ttydisc_rint_poll(otp) > 0) { | ||||
if (np->np_rate && !np->np_quota) | if (np->np_rate && !np->np_quota) | ||||
break; | break; | ||||
if (ttydisc_getc(tp, &c, 1) != 1) | if (ttydisc_getc(tp, &c, 1) != 1) | ||||
break; | break; | ||||
np->np_quota--; | np->np_quota--; | ||||
ttydisc_rint(otp, c, 0); | ttydisc_rint(otp, c, 0); | ||||
} | } | ||||
ttydisc_rint_done(otp); | ttydisc_rint_done(otp); | ||||
ttydisc_unlock(tp); | |||||
tty_unlock(tp); | |||||
} | } | ||||
static int | static int | ||||
bits_per_char(struct termios *t) | bits_per_char(struct termios *t) | ||||
{ | { | ||||
int bits; | int bits; | ||||
bits = 1; /* start bit */ | bits = 1; /* start bit */ | ||||
Show All 13 Lines | |||||
static int | static int | ||||
nmdm_param(struct tty *tp, struct termios *t) | nmdm_param(struct tty *tp, struct termios *t) | ||||
{ | { | ||||
struct nmdmpart *np = tty_softc(tp); | struct nmdmpart *np = tty_softc(tp); | ||||
struct tty *tp2; | struct tty *tp2; | ||||
int bpc, rate, speed, i; | int bpc, rate, speed, i; | ||||
/* Must be true for callout manipulation down below. */ | |||||
ttydisc_assert_locked(tp); | |||||
tp2 = np->np_other->np_tty; | tp2 = np->np_other->np_tty; | ||||
if (!((t->c_cflag | tp2->t_termios.c_cflag) & CDSR_OFLOW)) { | if (!((t->c_cflag | tp2->t_termios.c_cflag) & CDSR_OFLOW)) { | ||||
np->np_rate = 0; | np->np_rate = 0; | ||||
np->np_other->np_rate = 0; | np->np_other->np_rate = 0; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
nmdm_modem(struct tty *tp, int sigon, int sigoff) | nmdm_modem(struct tty *tp, int sigon, int sigoff) | ||||
{ | { | ||||
struct nmdmpart *np = tty_softc(tp); | struct nmdmpart *np = tty_softc(tp); | ||||
int i = 0; | int i = 0; | ||||
ttydisc_assert_locked(tp); | |||||
if (sigon || sigoff) { | if (sigon || sigoff) { | ||||
if (sigon & SER_DTR) | if (sigon & SER_DTR) | ||||
np->np_other->np_dcd = 1; | np->np_other->np_dcd = 1; | ||||
if (sigoff & SER_DTR) | if (sigoff & SER_DTR) | ||||
np->np_other->np_dcd = 0; | np->np_other->np_dcd = 0; | ||||
ttydisc_modem(np->np_other->np_tty, np->np_other->np_dcd); | ttydisc_modem(np->np_other->np_tty, np->np_other->np_dcd); | ||||
return (0); | return (0); | ||||
} else { | } else { | ||||
if (np->np_dcd) | if (np->np_dcd) | ||||
i |= SER_DCD; | i |= SER_DCD; | ||||
if (np->np_other->np_dcd) | if (np->np_other->np_dcd) | ||||
i |= SER_DTR; | i |= SER_DTR; | ||||
return (i); | return (i); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
nmdm_inwakeup(struct tty *tp) | nmdm_inwakeup(struct tty *tp) | ||||
{ | { | ||||
struct nmdmpart *np = tty_softc(tp); | struct nmdmpart *np = tty_softc(tp); | ||||
▲ Show 20 Lines • Show All 46 Lines • Show Last 20 Lines |
This is also fixed in my local draft... unsure why I did this.