summaryrefslogtreecommitdiffstats
path: root/sys/dev/cx/if_cx.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-10-13 09:27:18 +0000
committerphk <phk@FreeBSD.org>2004-10-13 09:27:18 +0000
commit47c2584ada884664c7b47583d0e7a0ad0d73ae43 (patch)
tree84cfc745ec0d232d77abacea0f293d21c3000229 /sys/dev/cx/if_cx.c
parentf44657f5f49be1a3d30def17d9c49393e32a24da (diff)
downloadFreeBSD-src-47c2584ada884664c7b47583d0e7a0ad0d73ae43.zip
FreeBSD-src-47c2584ada884664c7b47583d0e7a0ad0d73ae43.tar.gz
Use generic tty code instead of local copy.
Diffstat (limited to 'sys/dev/cx/if_cx.c')
-rw-r--r--sys/dev/cx/if_cx.c357
1 files changed, 80 insertions, 277 deletions
diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c
index 0a512c7..d72a4f2 100644
--- a/sys/dev/cx/if_cx.c
+++ b/sys/dev/cx/if_cx.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/conf.h>
#include <sys/errno.h>
+#include <sys/serial.h>
#include <sys/tty.h>
#include <sys/bus.h>
#include <machine/bus.h>
@@ -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: <Cronyx-Sigma-%s>\n", b->num, b->name);
for (c=b->chan; c<b->chan+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,
};
OpenPOWER on IntegriCloud