From 47c2584ada884664c7b47583d0e7a0ad0d73ae43 Mon Sep 17 00:00:00 2001 From: phk Date: Wed, 13 Oct 2004 09:27:18 +0000 Subject: [PATCH] Use generic tty code instead of local copy. --- sys/dev/cx/if_cx.c | 357 ++++++++++----------------------------------- 1 file changed, 80 insertions(+), 277 deletions(-) diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c index 0a512c7885b..d72a4f26b65 100644 --- a/sys/dev/cx/if_cx.c +++ b/sys/dev/cx/if_cx.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -79,12 +80,6 @@ __FBSDID("$FreeBSD$"); #define CX_DEBUG2(d,s) ({if (d->chan->debug>1) {\ printf ("%s: ", d->name); printf s;}}) -#define UNIT(d) (minor(d) & 0x3f) -#define IF_CUNIT(d) (minor(d) & 0x40) -#define UNIT_CTL 0x3f -#define CALLOUT(d) (minor(d) & 0x80) -#define CDEV_MAJOR 42 - typedef struct _async_q { int beg; int end; @@ -102,6 +97,9 @@ static void cx_identify __P((driver_t *, device_t)); static int cx_probe __P((device_t)); static int cx_attach __P((device_t)); static int cx_detach __P((device_t)); +static t_open_t cx_topen; +static t_modem_t cx_tmodem; +static t_close_t cx_tclose; static device_method_t cx_isa_methods [] = { DEVMETHOD(device_identify, cx_identify), @@ -143,7 +141,7 @@ typedef struct _drv_t { #else struct sppp pp; #endif - struct cdev *devt[3]; + struct cdev *devt; async_q aqueue; #define CX_READ 1 #define CX_WRITE 2 @@ -733,8 +731,6 @@ static int cx_attach (device_t dev) printf ("cx%d: \n", b->num, b->name); for (c=b->chan; cchan+NCHAN; ++c) { - char *dnmt="tty %x"; - char *dnmc="cua %x"; if (c->type == T_NONE) continue; d = &bd->channel[c->num]; @@ -798,16 +794,23 @@ static int cx_attach (device_t dev) bpfattach (&d->pp.pp_if, DLT_PPP, 4); #endif /*NETGRAPH*/ } + d->tty = ttyalloc (); + d->tty->t_open = cx_topen; + d->tty->t_close = cx_tclose; + d->tty->t_param = cx_param; + d->tty->t_stop = cx_stop; + d->tty->t_modem = cx_tmodem; + d->tty->t_sc = d; cx_start_chan (c, d->dmamem.virt, d->dmamem.phys); cx_register_receive (c, &cx_receive); cx_register_transmit (c, &cx_transmit); cx_register_error (c, &cx_error); cx_register_modem (c, &cx_modem); - dnmt[3] = 'x'+b->num; - dnmc[3] = 'x'+b->num; - d->devt[0] = make_dev (&cx_cdevsw, b->num*NCHAN + c->num, UID_ROOT, GID_WHEEL, 0644, dnmt, b->num*NCHAN + c->num); - d->devt[1] = make_dev (&cx_cdevsw, b->num*NCHAN + c->num + 64, UID_ROOT, GID_WHEEL, 0600, "cx%d", b->num*NCHAN + c->num); - d->devt[2] = make_dev (&cx_cdevsw, b->num*NCHAN + c->num + 128, UID_ROOT, GID_WHEEL, 0660, dnmc, b->num*NCHAN + c->num); + + ttycreate(d->tty, NULL, 0, MINOR_CALLOUT, + "x%r%r", b->num, c->num); + d->devt = make_dev (&cx_cdevsw, b->num*NCHAN + c->num + 64, UID_ROOT, GID_WHEEL, 0600, "cx%d", b->num*NCHAN + c->num); + d->devt->si_drv1 = d; } splx (s); @@ -875,7 +878,7 @@ static int cx_detach (device_t dev) continue; if (d->tty) { - ttyrel (d->tty); + ttyfree (d->tty); d->tty = NULL; } @@ -895,9 +898,7 @@ static int cx_detach (device_t dev) if_detach (&d->pp.pp_if); #endif - destroy_dev (d->devt[0]); - destroy_dev (d->devt[1]); - destroy_dev (d->devt[2]); + destroy_dev (d->devt); } cx_led_off (b); @@ -1346,217 +1347,92 @@ static void cx_error (cx_chan_t *c, int data) } } -static int cx_open (struct cdev *dev, int flag, int mode, struct thread *td) +static int cx_topen (struct tty *tp, struct cdev *dev) { - int unit = UNIT (dev); drv_t *d; - int error; - - if (unit >= NCX*NCHAN || ! (d = channel[unit])) - return ENXIO; - CX_DEBUG2 (d, ("cx_open unit=%d, flag=0x%x, mode=0x%x\n", - unit, flag, mode)); - - if (d->chan->mode != M_ASYNC || IF_CUNIT(dev)) { - d->open_dev |= 0x1; - return 0; - } - if (!d->tty) { - d->tty = ttymalloc (d->tty); - d->tty->t_oproc = cx_oproc; - d->tty->t_param = cx_param; - d->tty->t_stop = cx_stop; - } - dev->si_tty = d->tty; - d->tty->t_dev = dev; -again: - error = ttydtrwaitsleep(d->tty); - if (error) - return error; - - if ((d->tty->t_state & TS_ISOPEN) && (d->tty->t_state & TS_XCLUDE) && - suser (td)) - return EBUSY; - - if (d->tty->t_state & TS_ISOPEN) { - /* - * Cannot open /dev/cua if /dev/tty already opened. - */ - if (CALLOUT (dev) && ! d->callout) - return EBUSY; - - /* - * Opening /dev/tty when /dev/cua is already opened. - * Wait for close, then try again. - */ - if (! CALLOUT (dev) && d->callout) { - if (flag & O_NONBLOCK) - return EBUSY; - error = tsleep (d, TTIPRI | PCATCH, "cxbi", 0); - if (error) - return error; - goto again; - } - } else if (d->lock && ! CALLOUT (dev) && (flag & O_NONBLOCK)) - /* - * We try to open /dev/tty in non-blocking mode - * while somebody is already waiting for carrier on it. - */ - return EBUSY; - else { - ttychars (d->tty); - if (d->tty->t_ispeed == 0) { - d->tty->t_iflag = 0; - d->tty->t_oflag = 0; - d->tty->t_lflag = 0; - d->tty->t_cflag = CREAD | CS8 | HUPCL; - d->tty->t_ispeed = d->chan->rxbaud; - d->tty->t_ospeed = d->chan->txbaud; - } - if (CALLOUT (dev)) - d->tty->t_cflag |= CLOCAL; - else - d->tty->t_cflag &= ~CLOCAL; - cx_param (d->tty, &d->tty->t_termios); - ttsetwater (d->tty); - } - - splhigh (); - if (! (d->tty->t_state & TS_ISOPEN)) { - cx_start_chan (d->chan, 0, 0); - cx_set_dtr (d->chan, 1); - cx_set_rts (d->chan, 1); - d->cd = cx_get_cd (d->chan); - if (CALLOUT (dev) || cx_get_cd (d->chan)) - ttyld_modem(d->tty, 1); - } - - if (! (flag & O_NONBLOCK) && ! (d->tty->t_cflag & CLOCAL) && - ! (d->tty->t_state & TS_CARR_ON)) { - /* Lock the channel against cxconfig while we are - * waiting for carrier. */ - d->lock++; - error = tsleep (&d->tty->t_rawq, TTIPRI | PCATCH, "cxdcd", 0); - /* Unlock the channel. */ - d->lock--; - spl0 (); - if (error) - goto failed; - goto again; - } - - error = ttyld_open (d->tty, dev); - ttyldoptim (d->tty); - spl0 (); - if (error) { -failed: if (! (d->tty->t_state & TS_ISOPEN)) { - splhigh (); - cx_set_dtr (d->chan, 0); - cx_set_rts (d->chan, 0); - ttydtrwaitstart(d->tty); - spl0 (); - } - return error; - } - - if (d->tty->t_state & TS_ISOPEN) - d->callout = CALLOUT (dev) ? 1 : 0; + d = tp->t_sc; + if (d->chan->mode != M_ASYNC) + return (EBUSY); d->open_dev |= 0x2; - CX_DEBUG2 (d, ("cx_open done\n")); - return 0; + cx_start_chan (d->chan, 0, 0); + cx_set_dtr (d->chan, 1); + cx_set_rts (d->chan, 1); + d->cd = cx_get_cd (d->chan); + return (0); } -static int cx_close (struct cdev *dev, int flag, int mode, struct thread *td) +static void cx_tclose (struct tty *tp) { - drv_t *d = channel [UNIT (dev)]; - int s; - - CX_DEBUG2 (d, ("cx_close\n")); - if ((!(d->open_dev&0x2)) || IF_CUNIT(dev)){ - d->open_dev &= ~0x1; - return 0; - } - s = splhigh (); - ttyld_close(d->tty, flag); - ttyldoptim (d->tty); + drv_t *d; + d = tp->t_sc; /* Disable receiver. * Transmitter continues sending the queued data. */ cx_enable_receive (d->chan, 0); - - /* Clear DTR and RTS. */ - if ((d->tty->t_cflag & HUPCL) || ! (d->tty->t_state & TS_ISOPEN)) { - cx_set_dtr (d->chan, 0); - cx_set_rts (d->chan, 0); - ttydtrwaitstart(d->tty); - } - tty_close (d->tty); - splx (s); - d->callout = 0; - - /* - * Wake up bidirectional opens. - * Since we may be opened twice we couldn't call ttyrel() here. - * So just keep d->tty for future use. It would be freed by - * ttyrel() at cx_detach(). - */ - - wakeup (d); d->open_dev &= ~0x2; - - return 0; } -static int cx_read (struct cdev *dev, struct uio *uio, int flag) +static int cx_tmodem (struct tty *tp, int sigon, int sigoff) { - drv_t *d = channel [UNIT (dev)]; + drv_t *d; - if (d) CX_DEBUG2 (d, ("cx_read\n")); - if (!d || d->chan->mode != M_ASYNC || IF_CUNIT(dev) || !d->tty) - return EBADF; + d = tp->t_sc; - return ttyld_read (d->tty, uio, flag); + if (!sigon && !sigoff) { + if (cx_get_dsr (d->chan)) sigon |= SER_DSR; + if (cx_get_cd (d->chan)) sigon |= SER_DCD; + if (cx_get_cts (d->chan)) sigon |= SER_CTS; + if (d->chan->dtr) sigon |= SER_DTR; + if (d->chan->rts) sigon |= SER_RTS; + return sigon; + } + + if (sigon & SER_DTR) + cx_set_dtr (d->chan, 1); + if (sigoff & SER_DTR) + cx_set_dtr (d->chan, 0); + if (sigon & SER_RTS) + cx_set_rts (d->chan, 1); + if (sigoff & SER_RTS) + cx_set_rts (d->chan, 0); + return (0); } -static int cx_write (struct cdev *dev, struct uio *uio, int flag) +static int cx_open (struct cdev *dev, int flag, int mode, struct thread *td) { - drv_t *d = channel [UNIT (dev)]; + int unit; + drv_t *d; - if (d) CX_DEBUG2 (d, ("cx_write\n")); - if (!d || d->chan->mode != M_ASYNC || IF_CUNIT(dev) || !d->tty) - return EBADF; + d = dev->si_drv1; + unit = d->chan->num; + CX_DEBUG2 (d, ("cx_open unit=%d, flag=0x%x, mode=0x%x\n", + unit, flag, mode)); - return ttyld_write (d->tty, uio, flag); + d->open_dev |= 0x1; + return 0; } -static int cx_modem_status (drv_t *d) +static int cx_close (struct cdev *dev, int flag, int mode, struct thread *td) { - int status = 0, s = splhigh (); - /* Already opened by someone or network interface is up? */ - if ((d->chan->mode == M_ASYNC && d->tty && (d->tty->t_state & TS_ISOPEN) && - (d->open_dev|0x2)) || (d->chan->mode != M_ASYNC && d->running)) - status = TIOCM_LE; /* always enabled while open */ - - if (cx_get_dsr (d->chan)) status |= TIOCM_DSR; - if (cx_get_cd (d->chan)) status |= TIOCM_CD; - if (cx_get_cts (d->chan)) status |= TIOCM_CTS; - if (d->chan->dtr) status |= TIOCM_DTR; - if (d->chan->rts) status |= TIOCM_RTS; - splx (s); - return status; + drv_t *d; + + d = dev->si_drv1; + CX_DEBUG2 (d, ("cx_close\n")); + d->open_dev &= ~0x1; + return 0; } static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) { - drv_t *d = channel [UNIT (dev)]; + drv_t *d; cx_chan_t *c; struct serial_statistics *st; int error, s; char mask[16]; - if (!d || !(c = d->chan)) - return EINVAL; + d = dev->si_drv1; + c = d->chan; switch (cmd) { case SERIAL_GETREGISTERED: @@ -1842,72 +1718,6 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc return 0; } - if (c->mode == M_ASYNC && !IF_CUNIT(dev) && d->tty) { - error = ttyioctl (dev, cmd, data, flag, td); - ttyldoptim (d->tty); - if (error != ENOTTY) { - if (error) - CX_DEBUG2 (d, ("ttioctl: 0x%lx, error %d\n", cmd, error)); - return error; - } - } - - switch (cmd) { - case TIOCSBRK: /* Start sending line break */ - CX_DEBUG2 (d, ("ioctl: tiocsbrk\n")); - s = splhigh (); - cx_send_break (c, 500); - splx (s); - return 0; - - case TIOCCBRK: /* Stop sending line break */ - CX_DEBUG2 (d, ("ioctl: tioccbrk\n")); - return 0; - - case TIOCSDTR: /* Set DTR */ - CX_DEBUG2 (d, ("ioctl: tiocsdtr\n")); - s = splhigh (); - cx_set_dtr (c, 1); - splx (s); - return 0; - - case TIOCCDTR: /* Clear DTR */ - CX_DEBUG2 (d, ("ioctl: tioccdtr\n")); - s = splhigh (); - cx_set_dtr (c, 0); - splx (s); - return 0; - - case TIOCMSET: /* Set DTR/RTS */ - CX_DEBUG2 (d, ("ioctl: tiocmset\n")); - s = splhigh (); - cx_set_dtr (c, (*(int*)data & TIOCM_DTR) ? 1 : 0); - cx_set_rts (c, (*(int*)data & TIOCM_RTS) ? 1 : 0); - splx (s); - return 0; - - case TIOCMBIS: /* Add DTR/RTS */ - CX_DEBUG2 (d, ("ioctl: tiocmbis\n")); - s = splhigh (); - if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 1); - if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 1); - splx (s); - return 0; - - case TIOCMBIC: /* Clear DTR/RTS */ - CX_DEBUG2 (d, ("ioctl: tiocmbic\n")); - s = splhigh (); - if (*(int*)data & TIOCM_DTR) cx_set_dtr (c, 0); - if (*(int*)data & TIOCM_RTS) cx_set_rts (c, 0); - splx (s); - return 0; - - case TIOCMGET: /* Get modem status */ - CX_DEBUG2 (d, ("ioctl: tiocmget\n")); - *(int*)data = cx_modem_status (d); - return 0; - - } CX_DEBUG2 (d, ("ioctl: 0x%lx\n", cmd)); return ENOTTY; } @@ -1985,16 +1795,15 @@ void cx_softintr (void *unused) */ static void cx_oproc (struct tty *tp) { - int s = splhigh (), k; - drv_t *d = channel [UNIT (tp->t_dev)]; + int s, k; + drv_t *d; static u_char buf[DMABUFSZ]; u_char *p; u_short len = 0, sublen = 0; - if (!d) { - splx (s); - return; - } + s = splhigh(); + + d = tp->t_sc; CX_DEBUG2 (d, ("cx_oproc\n")); if (tp->t_cflag & CRTSCTS && (tp->t_state & TS_TBLOCK) && d->chan->rts) @@ -2049,11 +1858,10 @@ static void cx_oproc (struct tty *tp) static int cx_param (struct tty *tp, struct termios *t) { - drv_t *d = channel [UNIT (tp->t_dev)]; + drv_t *d; int s, bits, parity; - if (!d) - return EINVAL; + d = tp->t_sc; s = splhigh (); if (t->c_ospeed == 0) { @@ -2109,12 +1917,10 @@ static int cx_param (struct tty *tp, struct termios *t) */ static void cx_stop (struct tty *tp, int flag) { - drv_t *d = channel [UNIT (tp->t_dev)]; + drv_t *d; int s; - if (!d) - return; - + d = tp->t_sc; s = splhigh (); if (tp->t_state & TS_BUSY) { @@ -2173,11 +1979,8 @@ static struct cdevsw cx_cdevsw = { .d_version = D_VERSION, .d_open = cx_open, .d_close = cx_close, - .d_read = cx_read, - .d_write = cx_write, .d_ioctl = cx_ioctl, .d_name = "cx", - .d_maj = CDEV_MAJOR, .d_flags = D_TTY | D_NEEDGIANT, }; -- 2.45.2