149757Smarc /*
249757Smarc *
349757Smarc * X.29 option for dda driver for UNIX and Ultrix
449757Smarc * ________________________________________________________
549757Smarc * / \
649757Smarc * | AAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC |
749757Smarc * | AAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC |
849757Smarc * | AAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC |
949757Smarc * | AAAA AAAA CCCC CCCC |
1049757Smarc * | AAAA AAAA CCCC CCCC |
1149757Smarc * | AAAA AAAA CCCC CCCC |
1249757Smarc * | AAAA AAAA CCCC CCCC |
1349757Smarc * | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC |
1449757Smarc * | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC |
1549757Smarc * | AAAA AAAAAAAAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC |
1649757Smarc * \________________________________________________________/
1749757Smarc *
1849757Smarc * Copyright (c) 1987 by Advanced Computer Communications
1949757Smarc * 720 Santa Barbara Street, Santa Barbara, California 93101
2049757Smarc * (805) 963-9431
2149757Smarc *
2249757Smarc * File:
2349757Smarc * if_x29.c
2449757Smarc *
2549757Smarc * Author:
2649757Smarc *
2749757Smarc * Project:
2849757Smarc * Development of PAD on 6250 software.
2949757Smarc *
3049757Smarc * Function:
3149757Smarc * To enable network connections on ACP_XX to communicate with UNIX.
3249757Smarc *
3349757Smarc * Components:
3449757Smarc * - files if_x29.c
3549757Smarc *
3649757Smarc * Configuration Entry:
3749757Smarc *
3849757Smarc * device dda0 at uba? csr 0166740 vector ddainta ddaintb
3949757Smarc *
4049757Smarc * Usage Notes:
4149757Smarc *
4249757Smarc * - make devices in /dev and edit /etc/ttys for those x29
4349757Smarc * devices which you want in your configuration
4449757Smarc *
4549757Smarc * System Notes:
4649757Smarc *
4749757Smarc * Refer to the installation instructions, readme.txt, which
4849757Smarc * are included on the driver distribution medium.
4949757Smarc *
5049757Smarc * Revision History at end of file
5149757Smarc */
5249757Smarc
5349757Smarc /*
5449757Smarc * For efficiency, it is a good idea to modify XXBOARDS when using
5549757Smarc * less than 4 boards with the X29 option. If using more than 32
5649757Smarc * lines per board, you should modify XXBOARDS, XXLPERBRD, LOG2_XXBOARDS
5749757Smarc * and LOG2_XXLPERBRD.
5849757Smarc *
5949757Smarc * Minor numbers are laid out as follows (by default):
6049757Smarc * (MSB) PBBLLLLL (LSB)
6149757Smarc * Where P is a flag to determine if the line is outbound (pad) or
6249757Smarc * inbound (tty). BB is the board number (0-3), and LLLLL is the
6349757Smarc * X29 line on a board (0-31). Some customers may need more than
6449757Smarc * 32 lines/board. If there are less than 2 boards, one may shift
6549757Smarc * the break-point between lines and boards:
6649757Smarc *
6749757Smarc * up to 4 boards, 32 lines/board (default)
6849757Smarc * (MSB) PBBLLLLL (LSB)
6949757Smarc * XXBOARDS = 4, LOG2_XXBOARDS = 2
7049757Smarc * XXLPERBRD = 32, LOG2_XXLPERBRD = 5
7149757Smarc * up to 2 boards, 64 lines/board:
7249757Smarc * (MSB) PBLLLLLL (LSB)
7349757Smarc * XXBOARDS = 2, LOG2_XXBOARDS = 1
7449757Smarc * XXLPERBRD = 64, LOG2_XXLPERBRD = 6
7549757Smarc * only 1 board, 128 (actually, 126, as 126 = max svc):
7649757Smarc * (MSB) PLLLLLLL (LSB)
7749757Smarc * XXBOARDS = 1, LOG2_XXBOARDS = 0
7849757Smarc * XXLPERBRD = 128, LOG2_XXLPERBRD = 7
7949757Smarc *
8049757Smarc * (obviously, these are all powers of two)
8149757Smarc */
8249757Smarc
8349757Smarc #define XXBOARDS 4 /* # boards running x29 */
8449757Smarc #define LOG2_XXBOARDS 2 /* # bits of board info */
8549757Smarc
8649757Smarc #define XXLPERBRD 32 /* # lines per board */
8749757Smarc #define LOG2_XXLPERBRD 5 /* # bits of line info */
8849757Smarc
8949757Smarc /*
9049757Smarc * If you require an 8-bit data path and have no parity misconfigurations,
9149757Smarc * you may change PARITY_MASKs to 0377. This will leave parity stripping
9249757Smarc * to the ttdriver. However, the ttdriver won't strip parity when in
9349757Smarc * raw mode (e.g. at the Password: prompt), so one symptom of a parity
9449757Smarc * misconfiguration is that users can't login (CR gets received as 0x8D).
9549757Smarc */
9649757Smarc
9749757Smarc #define INPUT_PARITY_MASK 0177 /* strip off the 8th bit */
9849757Smarc #define OUTPUT_PARITY_MASK 0377 /* don't strip off the 8th bit */
9949757Smarc
10049757Smarc /*
10149757Smarc * macro to translate a device number to the unit (i.e. ACP_n250)
10249757Smarc * with which it is associated and the port on said unit
10349757Smarc */
10449757Smarc
10549757Smarc #define UNIT(x) ((minor(x) >> LOG2_XXLPERBRD) & LOG2_XXBOARDS)
10649757Smarc
10749757Smarc #define LINE(x) (minor(x) & 0177) /* index into line table */
10849757Smarc #define XXSHOW(x) (minor(x) == 255) /* special "show" device */
10949757Smarc #define IS_PAD(x) (minor(x) & 0200) /* msb is the pad/tty selector */
11049757Smarc #define MAJLINE(x) ((x) & ~0x80) /* major plus corrected minor # */
11149757Smarc
11249757Smarc #define NXXLINES (XXBOARDS * XXLPERBRD) /* number of total x29 lines */
11349757Smarc
11449757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
11549757Smarc /*%% %%*/
11649757Smarc /*%% LOCAL FUNCTIONS %%*/
11749757Smarc /*%% %%*/
11849757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
11949757Smarc
12049757Smarc PRIVATE void xxcntl();
12149757Smarc PRIVATE void xxclear();
12249757Smarc PRIVATE void xxshow();
12349757Smarc PRIVATE void xxpadhandle();
12449757Smarc PRIVATE int xxpadparse();
12549757Smarc PRIVATE int xxpadcall();
12649757Smarc PRIVATE void xxpadmsg();
12749757Smarc PRIVATE void xx_qbit_msg();
12849757Smarc PRIVATE void xx_tp_hangup();
12949757Smarc PRIVATE void x29_init();
13049757Smarc PRIVATE void x29_dhandle();
13149757Smarc PRIVATE int x29_break_reply_is_required();
13249757Smarc
13349757Smarc #if ACC_ULTRIX >= 30
13449757Smarc static int ttbreakc(); /* always keep this private */
13549757Smarc #endif
13649757Smarc
13749757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
13849757Smarc /*%% %%*/
13949757Smarc /*%% LOCAL VARIABLES %%*/
14049757Smarc /*%% %%*/
14149757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
14249757Smarc
14349757Smarc #define SET_PAD 2
14449757Smarc #define READ_PAD 4
14549757Smarc #define SET_READ_PAD 6
14649757Smarc #define PAR_INDICATION 0
14749757Smarc #define INVITE_CLEAR 1
14849757Smarc #define BREAK_INDIC 3
14949757Smarc #define PAD_ERROR 5
15049757Smarc
15149757Smarc /* command codes */
15249757Smarc #define XX_C_BREAK 001
15349757Smarc #define XX_C_PAD 002
15449757Smarc #define XX_C_CLOSE 003
15549757Smarc #define XX_C_HOST 004
15649757Smarc
15749757Smarc struct tty xx_tty[NXXLINES]; /* tty structures */
15849757Smarc
15949757Smarc #define MODE_UNUSED 0 /* !just for sanity checks only! */
16049757Smarc #define MODE_HOST 1 /* port in host mode (incoming) */
16149757Smarc #define MODE_PAD 2 /* port in pad mode (outgoing) */
16249757Smarc
16349757Smarc char xxmode[NXXLINES]; /* mode of port */
16449757Smarc
16549757Smarc int xxstart();
16649757Smarc
16749757Smarc typedef struct {
16849757Smarc char ref;
16949757Smarc char val;
17049757Smarc } x29_pad_pair;
17149757Smarc
17249757Smarc PRIVATE x29_pad_pair x29_break_ack_params[] =
17349757Smarc {
17449757Smarc 8, 0 /* ref 8 -- normal output to terminal */
17549757Smarc };
17649757Smarc
17749757Smarc PRIVATE x29_pad_pair x29_callout_params[] =
17849757Smarc {
17949757Smarc 1, 0 /* ref 1 -- no recall char */
18049757Smarc };
18149757Smarc
18249757Smarc PRIVATE x29_pad_pair x29_callin_setparams[] =
18349757Smarc { /* these are the preferred paramters when calling in to Unix */
18449757Smarc 2, 0, /* ref 2 -- no echo */
18549757Smarc 3, 127, /* ref 3 -- forward data on any char */
18649757Smarc 8, 0, /* ref 8 -- normal data delivery to terminal */
18749757Smarc 9, 0, /* ref 9 -- no padding after carriage return */
18849757Smarc 10, 0, /* ref 10 -- no line folding */
18949757Smarc 13, 0, /* ref 13 -- no line feed after CR */
19049757Smarc 15, 0 /* ref 15 -- no local edit */
19149757Smarc };
19249757Smarc
19349757Smarc /******************************************************************************
19449757Smarc * PAD CONTROL INFORMATION AND DEFINITIONS
19549757Smarc ******************************************************************************/
19649757Smarc
19749757Smarc /* definitions for the pad state field p_state */
19849757Smarc #define PS_IDLE 0 /* not opened state */
19949757Smarc #define PS_COM 1 /* the pad for this line is in command state */
20049757Smarc #define PS_PAD 2 /* this line has data passing though the pad */
20149757Smarc #define PS_WAIT 3 /* waiting state */
20249757Smarc #define PS_XFR 4 /* data transfer state */
20349757Smarc
20449757Smarc #define P_LINELEN 20
20549757Smarc #define P_NOBLOCK 0
20649757Smarc
20749757Smarc typedef struct padinfo {
20849757Smarc short p_state; /* pad state */
20949757Smarc char p_line[P_LINELEN]; /* built up line */
21049757Smarc char p_idx; /* index into p_line */
21149757Smarc int p_flow; /* index into mbuf when flow off,
21249757Smarc P_NOBLOCK if not flowed off */
21349757Smarc struct mbuf *p_msav; /* place to hang mbuf when flow controlled */
21449757Smarc struct mbuf *p_mchsav; /* place to save mbuf chain '' '' '' */
21549757Smarc } padinfo;
21649757Smarc padinfo xx_padinfo[NXXLINES];
21749757Smarc
21849757Smarc
21949757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
22049757Smarc /*%% %%*/
22149757Smarc /*%% GLOBAL ROUTINES %%*/
22249757Smarc /*%% %%*/
22349757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
22449757Smarc
22549757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
22649757Smarc /*%% XXOPEN() %%*/
22749757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
22849757Smarc /* */
22949757Smarc /* Purpose: */
23049757Smarc /* */
23149757Smarc /* Open a line. */
23249757Smarc /* */
23349757Smarc /* Call: xxopen(dev, flag) */
23449757Smarc /* Argument: dev: device */
23549757Smarc /* flag: indicates type of open, "nonblocking" */
23649757Smarc /* "or block if in use" */
23749757Smarc /* Returns: 0 for success, else nonzero error code */
23849757Smarc /* Called by: kernel software software, this routine is in */
23949757Smarc /* the cdevsw table */
24049757Smarc /* */
24149757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
24249757Smarc
24349757Smarc /*ARGSUSED*/
xxopen(dev,flag)24449757Smarc xxopen(dev, flag)
24549757Smarc dev_t dev;
24649757Smarc int flag;
24749757Smarc {
24849757Smarc register struct tty *tp;
24949757Smarc register d;
25049757Smarc register s;
25149757Smarc int unit,
25249757Smarc i;
25349757Smarc #if ACC_ULTRIX > 00
25449757Smarc int inuse; /* store inuse bit while sleeping */
25549757Smarc #endif
25649757Smarc
25749757Smarc unit = UNIT(dev);
25849757Smarc d = LINE(dev);
25949757Smarc
26049757Smarc if (XXSHOW(dev)) { /* minor device 255 */
26149757Smarc xxshow();
26249757Smarc return (EPIPE);
26349757Smarc }
26449757Smarc
26549757Smarc /* PST NOTE TO SELF: change the test as follows:
26649757Smarc * make this d >= NXXLINES, then check to see if unit is present,
26749757Smarc * Keep that sleep() in the thingy below, so we don't get bouncing
26849757Smarc * gettys eating up cpu time.
26949757Smarc */
27049757Smarc if ((d >= NXXLINES))
27149757Smarc return (ENXIO);
27249757Smarc
27349757Smarc /* wait for interface to come up */
27449757Smarc while (dda_softc[unit].dda_state != S_LINK_UP)
27549757Smarc sleep(&dda_softc[unit].dda_state, TTIPRI);
27649757Smarc
27749757Smarc tp = &xx_tty[d];
27849757Smarc if ((tp->t_state & TS_XCLUDE) && u.u_uid != 0)
27949757Smarc return EBUSY;
28049757Smarc
28149757Smarc /* make sure the port isn't already open in a conflicting manner */
28249757Smarc /* i.e. can't open /dev/padJ0 and /dev/ttyJ0 at the same time */
28349757Smarc if (tp->t_state & (TS_WOPEN | TS_ISOPEN)) {
28449757Smarc if ((IS_PAD(dev) && (xxmode[d] == MODE_HOST)) ||
28549757Smarc ((!IS_PAD(dev)) && (xxmode[d] == MODE_PAD)))
28649757Smarc return EBUSY;
28749757Smarc }
28849757Smarc
28949757Smarc #ifdef DDADEBUG
29049757Smarc if (DDADBCH(96, unit)) {
29149757Smarc DDALOG(LOG_DEBUG)
29249757Smarc "dda%d:(x29) open line %d flag %o in %s mode\n",
29349757Smarc unit, d, flag, (IS_PAD(dev) ? "pad" : "host")
29449757Smarc DDAELOG;
29549757Smarc }
29649757Smarc #endif DDADEBUG
29749757Smarc
29849757Smarc tp->t_oproc = xxstart;
29949757Smarc tp->t_state |= TS_WOPEN;
30049757Smarc
30149757Smarc /* if first open initialize state */
30249757Smarc if ((tp->t_state & TS_ISOPEN) == 0) {
30349757Smarc ttychars(tp);
30449757Smarc
30549757Smarc #if ACC_ULTRIX >= 30 /* posix compliant tty driver */
30649757Smarc if (tp->t_cflag & CBAUD == 0) {
30749757Smarc tp->t_iflag = IGNPAR | ICRNL | IXON | IXANY | IXOFF;
30849757Smarc tp->t_oflag = OPOST | ONLCR;
30949757Smarc tp->t_cflag = B9600 | CS8 | CREAD | HUPCL;
31049757Smarc tp->t_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL;
31149757Smarc tp->t_line = 0;
31249757Smarc }
31349757Smarc #else /* v7 tty driver */
31449757Smarc if (tp->t_ispeed == 0) {
31549757Smarc tp->t_ispeed = B9600;
31649757Smarc tp->t_ospeed = B9600;
31749757Smarc tp->t_flags = CRMOD | ANYP;
31849757Smarc }
31949757Smarc #endif
32049757Smarc xxparam(dev);
32149757Smarc }
32249757Smarc if (IS_PAD(dev)) {
32349757Smarc tp->t_state |= TS_CARR_ON;
32449757Smarc xxmode[d] = MODE_PAD;
32549757Smarc xxcntl(tp, XX_C_PAD, unit);
32649757Smarc } else {
32749757Smarc if ((tp->t_state & TS_CARR_ON) == 0) {
32849757Smarc xxmode[d] = MODE_HOST;
32949757Smarc xxcntl(tp, XX_C_HOST, unit);
33049757Smarc tp->t_flags |= ECHO;
33149757Smarc #if ACC_ULTRIX < 31 /* on everything other than Ultrix 3.1 */
33249757Smarc /* on close tell ACP_XX to drop line */
33349757Smarc tp->t_state |= TS_HUPCLS;
33449757Smarc #endif
33549757Smarc }
33649757Smarc }
33749757Smarc /* if xxcntl did not get called (state had carrier off) or xxcntl's
33849757Smarc * search for a free lcn failed, then t_addr will be 0, so punt */
33949757Smarc if (tp->t_addr == 0) {
34049757Smarc tp->t_pgrp = 0;
34149757Smarc tp->t_state = 0;
34249757Smarc xxmode[d] = MODE_UNUSED;
34349757Smarc return (EBUSY);
34449757Smarc }
34549757Smarc xx_padinfo[d].p_flow = P_NOBLOCK;
34649757Smarc s = splimp();
34749757Smarc
34849757Smarc #if ACC_ULTRIX > 00
34949757Smarc if (flag & O_NDELAY) {
35049757Smarc if (!IS_PAD(dev))
35149757Smarc tp->t_state |= TS_ONDELAY;
35249757Smarc } else
35349757Smarc #endif
35449757Smarc while ((tp->t_state & TS_CARR_ON) == 0) {
35549757Smarc tp->t_state |= TS_WOPEN;
35649757Smarc #if ACC_ULTRIX > 00
35749757Smarc inuse = tp->t_state & TS_INUSE;
35849757Smarc #endif
35949757Smarc sleep(&tp->t_rawq, TTIPRI);
36049757Smarc
36149757Smarc /* wakeup came from xxclear */
36249757Smarc if ((tp->t_state & TS_WOPEN) == 0) {
36349757Smarc splx(s);
36449757Smarc return (EPIPE);
36549757Smarc }
36649757Smarc #if ACC_ULTRIX > 00
36749757Smarc /* if port became "inuse" while we slept, return */
36849757Smarc if ((flag & O_BLKINUSE) && (!inuse) &&
36949757Smarc (tp->t_state & TS_INUSE)) {
37049757Smarc splx(s);
37149757Smarc return (EALREADY);
37249757Smarc }
37349757Smarc #endif
37449757Smarc }
37549757Smarc
37649757Smarc splx(s);
37749757Smarc i = ((*linesw[tp->t_line].l_open) (dev, tp));
37849757Smarc if (tp->t_pgrp == 0)
37949757Smarc tp->t_pgrp = u.u_procp->p_pid;
38049757Smarc return (i);
38149757Smarc }
38249757Smarc
38349757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
38449757Smarc /*%% XXCLOSE() %%*/
38549757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
38649757Smarc /* */
38749757Smarc /* Purpose: */
38849757Smarc /* */
38949757Smarc /* Close a line. */
39049757Smarc /* */
39149757Smarc /* Call: xxclose(dev, flag) */
39249757Smarc /* Argument: dev: device */
39349757Smarc /* flag: unused */
39449757Smarc /* Returns: nothing */
39549757Smarc /* Called by: kernel software, this routine is in the */
39649757Smarc /* cdevsw table */
39749757Smarc /* */
39849757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39949757Smarc
40049757Smarc /*ARGSUSED*/
xxclose(dev,flag,mode,p)401*49758Smarc xxclose(dev, flag, mode, p)
40249757Smarc dev_t dev;
403*49758Smarc int flag, mode;
404*49758Smarc struct proc *p;
40549757Smarc {
40649757Smarc register struct tty *tp;
40749757Smarc register d;
40849757Smarc d = LINE(dev);
40949757Smarc tp = &xx_tty[d];
41049757Smarc
41149757Smarc #ifdef DDADEBUG
41249757Smarc if (DDADBCH(97, UNIT(dev))) {
41349757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) closing line %d\n", UNIT(dev), d
41449757Smarc DDAELOG;
41549757Smarc }
41649757Smarc #endif DDADEBUG
41749757Smarc
41849757Smarc /* PST NOTE TO SELF:
41949757Smarc * Add the 629 driver code for timing out the close below,
42049757Smarc * because the line could be flowed off and it would hang
42149757Smarc * forever */
42249757Smarc
423*49758Smarc (*linesw[tp->t_line].l_close) (tp, flag);
42449757Smarc
42549757Smarc #if ACC_ULTRIX >= 31
42649757Smarc if ((tp->t_cflag & HUPCL) || ((tp->t_state & TS_ISOPEN) == 0)) {
42749757Smarc #else
42849757Smarc if ((tp->t_state & TS_HUPCLS) || ((tp->t_state & TS_ISOPEN) == 0)) {
42949757Smarc #endif
43049757Smarc
43149757Smarc #ifdef DDADEBUG
43249757Smarc if (DDADBCH(97, UNIT(dev))) {
43349757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) close: tp->t_state = %x\n",
43449757Smarc UNIT(dev), tp->t_state
43549757Smarc DDAELOG;
43649757Smarc }
43749757Smarc #endif DDADEBUG
43849757Smarc
43949757Smarc if (tp->t_state & TS_CARR_ON)
44049757Smarc xxcntl(tp, XX_C_CLOSE, UNIT(dev));
44149757Smarc tp->t_state &= ~TS_CARR_ON;
44249757Smarc xxmode[d] = MODE_UNUSED;
44349757Smarc }
44449757Smarc ttyclose(tp);
44549757Smarc }
44649757Smarc
44749757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
44849757Smarc /*%% XXREAD() %%*/
44949757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
45049757Smarc /* */
45149757Smarc /* Purpose: */
45249757Smarc /* */
45349757Smarc /* Read from a line. */
45449757Smarc /* */
45549757Smarc /* Call: xxread(dev, uio) */
45649757Smarc /* Argument: dev: device */
45749757Smarc /* uio: pointer to uio structure */
45849757Smarc /* Returns: 0 for success, else nonzero error code */
45949757Smarc /* Called by: kernel software, this routine is in */
46049757Smarc /* the cdevsw table */
46149757Smarc /* */
46249757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
46349757Smarc
xxread(dev,uio)46449757Smarc xxread(dev, uio)
46549757Smarc dev_t dev;
46649757Smarc struct uio *uio;
46749757Smarc {
46849757Smarc register struct tty *tp;
46949757Smarc register int l,
47049757Smarc error;
47149757Smarc
47249757Smarc if (dda_softc[UNIT(dev)].dda_state != S_LINK_UP)
47349757Smarc return (ENXIO);
47449757Smarc
47549757Smarc l = LINE(dev);
47649757Smarc tp = &xx_tty[l];
47749757Smarc error = (*linesw[tp->t_line].l_read)(tp, uio);
47849757Smarc
47949757Smarc if (xx_padinfo[l].p_flow != P_NOBLOCK) { /* currently blocked? */
48049757Smarc if (tp->t_flags & (RAW | CBREAK)) { /* using raw q? */
48149757Smarc if (tp->t_rawq.c_cc < TTYHOG / 8) { /* if rawq is low, then
48249757Smarc * it's time to unblock */
48349757Smarc x29_dhandle(&dda_softc[UNIT(dev)],
48449757Smarc (struct dda_cb *) (tp->t_addr), 1);
48549757Smarc }
48649757Smarc /* else cooked mode, different test */
48749757Smarc /* canonical q empty? then it's time to unblock */
48849757Smarc } else if (tp->t_canq.c_cc == 0) {
48949757Smarc x29_dhandle(&dda_softc[UNIT(dev)],
49049757Smarc (struct dda_cb *) (tp->t_addr), 1);
49149757Smarc }
49249757Smarc }
49349757Smarc return (error);
49449757Smarc }
49549757Smarc
49649757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
49749757Smarc /*%% XXWRITE() %%*/
49849757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
49949757Smarc /* */
50049757Smarc /* Purpose: */
50149757Smarc /* */
50249757Smarc /* Write on a line. */
50349757Smarc /* */
50449757Smarc /* Call: xxwrite(dev, uio) */
50549757Smarc /* Argument: dev: device */
50649757Smarc /* uio: pointer to uio structure */
50749757Smarc /* Returns: 0 for success, else nonzero error code */
50849757Smarc /* Called by: kernel software software, this routine is in */
50949757Smarc /* the cdevsw table */
51049757Smarc /* */
51149757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
51249757Smarc
xxwrite(dev,uio)51349757Smarc xxwrite(dev, uio)
51449757Smarc dev_t dev;
51549757Smarc struct uio *uio;
51649757Smarc {
51749757Smarc register struct tty *tp;
51849757Smarc if (dda_softc[UNIT(dev)].dda_state != S_LINK_UP)
51949757Smarc return (ENXIO);
52049757Smarc tp = &xx_tty[LINE(dev)];
52149757Smarc return (*linesw[tp->t_line].l_write)(tp, uio);
52249757Smarc }
52349757Smarc
52449757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
52549757Smarc /*%% XXIOCTL() %%*/
52649757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
52749757Smarc /* */
52849757Smarc /* Purpose: */
52949757Smarc /* */
53049757Smarc /* Process ioctl request. */
53149757Smarc /* */
53249757Smarc /* Call: xxioctl(dev, cmd, data, flag) */
53349757Smarc /* Argument: dev: device */
53449757Smarc /* cmd: ioctl command */
53549757Smarc /* data: pointer to data */
53649757Smarc /* flag: ignored */
53749757Smarc /* Returns: 0 for sucess, else nonzero error code */
53849757Smarc /* Called by: kernel software software, this routine is in */
53949757Smarc /* the cdevsw table */
54049757Smarc /* */
54149757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
54249757Smarc
54349757Smarc #define TIOACCQBIT (int)(0x80800000|('t'<<8)|125)
54449757Smarc
xxioctl(dev,cmd,data,flag)54549757Smarc xxioctl(dev, cmd, data, flag)
54649757Smarc dev_t dev;
54749757Smarc caddr_t data;
54849757Smarc {
54949757Smarc register struct tty *tp;
55049757Smarc int error;
55149757Smarc tp = &xx_tty[LINE(dev)];
55249757Smarc if (cmd == TIOACCQBIT) {
55349757Smarc #ifdef DDADEBUG
55449757Smarc if (DDADBCH(98, UNIT(dev))) {
55549757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) ioctl qbit msg: cmd=%x ACC=%x\n",
55649757Smarc UNIT(dev), cmd, TIOACCQBIT
55749757Smarc DDAELOG;
55849757Smarc }
55949757Smarc #endif DDADEBUG
56049757Smarc xx_qbit_msg(tp, UNIT(dev), data);
56149757Smarc return (0);
56249757Smarc }
56349757Smarc error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag);
56449757Smarc if (error >= 0)
56549757Smarc return (error);
56649757Smarc error = ttioctl(tp, cmd, data, flag);
56749757Smarc if (error >= 0) {
56849757Smarc if (cmd == TIOCSETP || cmd == TIOCSETN)
56949757Smarc xxparam(dev);
57049757Smarc return (error);
57149757Smarc }
57249757Smarc switch (cmd) {
57349757Smarc case TIOCREMOTE:
57449757Smarc if (xxmode[LINE(dev)] == 0)
57549757Smarc return (EBUSY);
57649757Smarc xxcntl(tp, XX_C_PAD, UNIT(dev));
57749757Smarc break;
57849757Smarc case TIOCSBRK:
57949757Smarc xxcntl(tp, XX_C_BREAK, UNIT(dev));
58049757Smarc break;
58149757Smarc case TIOCCBRK:
58249757Smarc case TIOCSDTR:
58349757Smarc case TIOCCDTR:
58449757Smarc break;
58549757Smarc default:
58649757Smarc return (ENOTTY);
58749757Smarc }
58849757Smarc return (0);
58949757Smarc }
59049757Smarc
59149757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59249757Smarc /*%% XXPARAM() %%*/
59349757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59449757Smarc /* */
59549757Smarc /* Purpose: */
59649757Smarc /* */
59749757Smarc /* Set parameters from open or stty. */
59849757Smarc /* This routine is being left in as a dummy in case in the future */
59949757Smarc /* there is a mechanism for the host to send information i.e. */
60049757Smarc /* "hangup line" to the ACP _XX */
60149757Smarc /* */
60249757Smarc /* Call: xxparam(dev) */
60349757Smarc /* Argument: dev: device */
60449757Smarc /* Returns: none */
60549757Smarc /* Called by: none */
60649757Smarc /* */
60749757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
60849757Smarc /*ARGSUSED*/
xxparam(dev)60949757Smarc xxparam(dev)
61049757Smarc dev_t dev;
61149757Smarc {
61249757Smarc }
61349757Smarc
61449757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
61549757Smarc /*%% XXSTART() %%*/
61649757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
61749757Smarc /* */
61849757Smarc /* Purpose: */
61949757Smarc /* */
62049757Smarc /* Start (restart) transmission on a given line. This is the */
62149757Smarc /* start routine which is called from above by the tty driver and */
62249757Smarc /* from below on a transmission complete interrupt for a given */
62349757Smarc /* line. */
62449757Smarc /* */
62549757Smarc /* Call: xxstart(tp) */
62649757Smarc /* Argument: tp: pointer to tty structure */
62749757Smarc /* Returns: none */
62849757Smarc /* Called by: tty driver */
62949757Smarc /* xxreset() */
63049757Smarc /* */
63149757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
63249757Smarc
xxstart(tp)63349757Smarc xxstart(tp)
63449757Smarc register struct tty *tp;
63549757Smarc {
63649757Smarc register struct dda_softc *ds;
63749757Smarc register int nch,
63849757Smarc cc,
63949757Smarc k;
64049757Smarc register struct dda_cb *dc;
64149757Smarc register char *cp,
64249757Smarc *p;
64349757Smarc struct ifqueue *oq;
64449757Smarc struct mbuf *m;
64549757Smarc padinfo *pp;
64649757Smarc int unit,
64749757Smarc line,
64849757Smarc s,
64949757Smarc j;
65049757Smarc extern int ttrstrt();
65149757Smarc
65249757Smarc line = tp - xx_tty;
65349757Smarc unit = UNIT(line);
65449757Smarc dc = (struct dda_cb *) tp->t_addr;
65549757Smarc ds = &dda_softc[unit];
65649757Smarc pp = &xx_padinfo[line];
65749757Smarc
65849757Smarc s = splimp();
65949757Smarc
66049757Smarc #ifdef DDADEBUG
66149757Smarc if (DDADBCH(99, unit)) {
66249757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) xxstart: line %d t_state = %x\n",
66349757Smarc unit, line, tp->t_state
66449757Smarc DDAELOG;
66549757Smarc }
66649757Smarc #endif DDADEBUG
66749757Smarc
66849757Smarc /* If it's currently active, or delaying, no need to do anything. */
66949757Smarc if ((tp->t_state & TS_CARR_ON) == 0) {
67049757Smarc tp->t_state &= ~(TS_TTSTOP | TS_BUSY);
67149757Smarc ttyflush(tp, FREAD | FWRITE);
67249757Smarc tp->t_state &= ~TS_ASLEEP;
67349757Smarc wakeup((caddr_t) &tp->t_outq);
67449757Smarc goto out;
67549757Smarc }
67649757Smarc if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
67749757Smarc goto out;
67849757Smarc
67949757Smarc /* wait for free */
68049757Smarc if (dda_softc[unit].dda_state != S_LINK_UP) {
68149757Smarc ttyflush(tp, FREAD | FWRITE);
68249757Smarc DMESG(unit, 96, (DDALOG(LOG_ERR)
68349757Smarc "dda%d:(x29) xxstart: unit offline\n", unit DDAELOG) );
68449757Smarc goto out;
68549757Smarc }
68649757Smarc /* If the writer was sleeping on output overflow, wake him when low tide
68749757Smarc * is reached. */
68849757Smarc if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
68949757Smarc if (tp->t_state & TS_ASLEEP) {
69049757Smarc tp->t_state &= ~TS_ASLEEP;
69149757Smarc wakeup((caddr_t) &tp->t_outq);
69249757Smarc }
69349757Smarc if (tp->t_wsel) {
69449757Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
69549757Smarc tp->t_wsel = 0;
69649757Smarc tp->t_state &= ~TS_WCOLL;
69749757Smarc }
69849757Smarc }
69949757Smarc /* restart transmission unless output queue is empty */
70049757Smarc if (tp->t_outq.c_cc == 0)
70149757Smarc goto out;
70249757Smarc
70349757Smarc /* if this is an outbound pad line and it's in command mode */
70449757Smarc if (pp->p_state == PS_COM) {
70549757Smarc xxpadhandle(ds, tp, pp);
70649757Smarc goto out;
70749757Smarc }
70849757Smarc
70949757Smarc /* Allocate an mbuf to stuff the chars into */
71049757Smarc m = 0;
71149757Smarc MGET(m, M_DONTWAIT, MT_DATA);
71249757Smarc if (m == 0) {
71349757Smarc DMESG(unit, 97, (DDALOG(LOG_ERR)
71449757Smarc "dda%d:(x29) xxstart: could not get mbuf\n",
71549757Smarc unit DDAELOG) );
71649757Smarc goto out;
71749757Smarc }
71849757Smarc cp = mtod(m, char *);
71949757Smarc cc = 0;
72049757Smarc
72149757Smarc /* copy at most MLEN-1 chars out -- must save one byte for subfunc */
72249757Smarc while ((cc < MLEN - 1) && (tp->t_outq.c_cc > 0)) {
72349757Smarc if (tp->t_flags & (RAW | LITOUT))
72449757Smarc nch = ndqb(&tp->t_outq, 0);
72549757Smarc else {
72649757Smarc nch = ndqb(&tp->t_outq, 0200);
72749757Smarc if (nch == 0) { /* if first item was a delay */
72849757Smarc (void) getc(&tp->t_outq); /* discard the character */
72949757Smarc continue;
73049757Smarc }
73149757Smarc }
73249757Smarc if (nch > (MLEN - 1) - cc)
73349757Smarc nch = (MLEN - 1) - cc;
73449757Smarc
73549757Smarc /* If any characters were set up, start transmission; */
73649757Smarc if (nch) {
73749757Smarc j = q_to_b(&tp->t_outq, cp, nch);
73849757Smarc
73949757Smarc #if OUTPUT_PARITY_MASK != 0377
74049757Smarc /* strip all characters as desired */
74149757Smarc for (p = cp, k = j; k; k--, p++)
74249757Smarc *p &= OUTPUT_PARITY_MASK;
74349757Smarc #endif
74449757Smarc
74549757Smarc #ifdef DDADEBUG
74649757Smarc if (DDADBCH(100, unit) && j != nch) {
74749757Smarc DDALOG(LOG_DEBUG)
74849757Smarc "dda%d:(x29) xxstart: asked for %d got %d chars\n",
74949757Smarc unit, nch, j
75049757Smarc DDAELOG;
75149757Smarc }
75249757Smarc #endif DDADEBUG
75349757Smarc
75449757Smarc cc += nch;
75549757Smarc cp += nch;
75649757Smarc } else
75749757Smarc break;
75849757Smarc }
75949757Smarc
76049757Smarc #ifdef DDADEBUG
76149757Smarc if (DDADBCH(101, unit)) {
76249757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) xxstart: mbuf %x len %d\n",
76349757Smarc unit, m, m->m_len
76449757Smarc DDAELOG;
76549757Smarc }
76649757Smarc #endif
76749757Smarc
76849757Smarc /* if any data was stuffed into the mbuf then send it */
76949757Smarc if (cc) {
77049757Smarc m->m_dat[MLEN - 1] = 0; /* subfunction: no Q-bit */
77149757Smarc m->m_len = cc;
77249757Smarc oq = &(dc->dc_oq); /* point to output queue */
77349757Smarc if (IF_QFULL(oq)) { /* if q full */
77449757Smarc IF_DROP(oq); /* drop the data */
77549757Smarc m_freem(m);
77649757Smarc ds->dda_if.if_collisions++; /* for netstat display */
77749757Smarc splx(s);
77849757Smarc return (ENOBUFS);
77949757Smarc }
78049757Smarc IF_ENQUEUE(oq, m); /* otherwise queue it */
78149757Smarc tp->t_state |= TS_BUSY;
78249757Smarc dda_start(ds, dc); /* and try to output */
78349757Smarc } else
78449757Smarc m_freem(m);
78549757Smarc
78649757Smarc out:
78749757Smarc if (dc->dc_lcn != 0) /* something left in oq? */
78849757Smarc dda_start(ds, dc); /* restart output */
78949757Smarc splx(s);
79049757Smarc return (0);
79149757Smarc }
79249757Smarc
79349757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
79449757Smarc /*%% XXRESET() %%*/
79549757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
79649757Smarc /* */
79749757Smarc /* Purpose: */
79849757Smarc /* */
79949757Smarc /* In response to UNIBUS reset, reset state and restart */
80049757Smarc /* transmitters. */
80149757Smarc /* */
80249757Smarc /* Call: xxreset(uban) */
80349757Smarc /* Argument: uban: UNIBUS adaptor number */
80449757Smarc /* Returns: none */
80549757Smarc /* Called by: kernel software in response to UNIBUS reset */
80649757Smarc /* */
80749757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
80849757Smarc /*ARGSUSED*/
xxreset(uban)80949757Smarc xxreset(uban)
81049757Smarc int uban;
81149757Smarc {
81249757Smarc }
81349757Smarc
81449757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
81549757Smarc /*%% XXSTOP() %%*/
81649757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
81749757Smarc /* */
81849757Smarc /* Purpose: */
81949757Smarc /* */
82049757Smarc /* Dummy stop routine. */
82149757Smarc /* */
82249757Smarc /* Call: xxstop(tp, flag) */
82349757Smarc /* Argument: tp: pointer to tty structure */
82449757Smarc /* flag: indicates */
82549757Smarc /* Returns: none */
82649757Smarc /* Called by: none */
82749757Smarc /* */
82849757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
82949757Smarc /*ARGSUSED*/
83049757Smarc xxstop(tp, flag)
83149757Smarc struct tty *tp;
83249757Smarc int flag;
83349757Smarc {
83449757Smarc }
83549757Smarc
83649757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
83749757Smarc /*%% XXSELECT() %%*/
83849757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
83949757Smarc /* */
84049757Smarc /* Purpose: */
84149757Smarc /* */
84249757Smarc /* Circumvent bug in our bastardized design which causes ttselect */
84349757Smarc /* to fail. */
84449757Smarc /* */
84549757Smarc /* Call: xxselect(dev, rw) */
84649757Smarc /* Argument: dev: device */
84749757Smarc /* rw: read or write indicator */
84849757Smarc /* Returns: 0 or 1 */
84949757Smarc /* Called by: none */
85049757Smarc /* */
85149757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
85249757Smarc
xxselect(dev,rw)85349757Smarc xxselect(dev, rw)
85449757Smarc dev_t dev;
85549757Smarc int rw;
85649757Smarc {
85749757Smarc #ifdef DDADEBUG
85849757Smarc int unit = UNIT(dev);
85949757Smarc if (DDADBCH(102, unit))
86049757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) select()\n", unit DDAELOG;
86149757Smarc #endif DDADEBUG
86249757Smarc
86349757Smarc return (ttselect(MAJLINE(dev), rw));
86449757Smarc }
86549757Smarc
86649757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
86749757Smarc /*%% %%*/
86849757Smarc /*%% LOCAL FUNCTIONS %%*/
86949757Smarc /*%% %%*/
87049757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
87149757Smarc
87249757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
87349757Smarc /*%% X29_SUPR() %%*/
87449757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
87549757Smarc /* */
87649757Smarc /* Purpose: */
87749757Smarc /* */
87849757Smarc /* This routine processes received supervisor messages. */
87949757Smarc /* Depending on the message type, the appropriate action is */
88049757Smarc /* taken. */
88149757Smarc /* */
88249757Smarc /* Call: x29_supr(ds, p) */
88349757Smarc /* Arguments: ds: pointer to dev control block struct */
88449757Smarc /* p: pointer to a character array */
88549757Smarc /* containing the supervisor message */
88649757Smarc /* Returns: nothing */
88749757Smarc /* Called by: dda_supr() */
88849757Smarc /* */
88949757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
89049757Smarc
89149757Smarc PRIVATE void
x29_supr(ds,p)89249757Smarc x29_supr(ds, p)
89349757Smarc struct dda_softc *ds;
89449757Smarc u_char p[];
89549757Smarc {
89649757Smarc register struct dda_cb *dc;
89749757Smarc register struct tty *tp;
89849757Smarc register int lcn;
89949757Smarc int maxlcn;
90049757Smarc int line;
90149757Smarc
90249757Smarc #ifdef DDADEBUG
90349757Smarc if (DDADBCH(103, ds->dda_if.if_unit)) {
90449757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) x29_supr()\n", ds->dda_if.if_unit
90549757Smarc DDAELOG;
90649757Smarc }
90749757Smarc #endif DDADEBUG
90849757Smarc
90949757Smarc switch (p[0]) {
91049757Smarc case LINE_STATUS: /* link status msg */
91149757Smarc case RESTART: /* restart received */
91249757Smarc case RSTRT_ACK: /* restart ack */
91349757Smarc case STATRESP: /* Statistics Response from FEP */
91449757Smarc DMESG(ds->dda_if.if_unit, 98, (DDALOG(LOG_ERR)
91549757Smarc "dda%d:(x29) x29_supr: unexpected message type\n",
91649757Smarc ds->dda_if.if_unit DDAELOG));
91749757Smarc break;
91849757Smarc case ANSWER: /* call answered */
91949757Smarc lcn = p[1] / 2;
92049757Smarc dc = &(ds->dda_cb[lcn]);
92149757Smarc if (dc->dc_state == LC_CALL_PENDING) { /* if a call pending */
92249757Smarc decode_answer(p, dc);
92349757Smarc dc->dc_state = LC_DATA_IDLE; /* set state */
92449757Smarc dc->dc_flags = DC_X29;
92549757Smarc line = dc->dc_line; /* which line are we? */
92649757Smarc #ifdef DDADEBUG
92749757Smarc if (DDADBCH(114, ds->dda_if.if_unit)) {
92849757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) x29_supr: answer: line=%d\n",
92949757Smarc ds->dda_if.if_unit, line
93049757Smarc DDAELOG;
93149757Smarc }
93249757Smarc #endif DDADEBUG
93349757Smarc
93449757Smarc if (line == -1) { /* fubar! */
93549757Smarc DMESG(ds->dda_if.if_unit, 107, (DDALOG(LOG_ERR)
93649757Smarc "dda%d:(x29) x29_supr: answer: line was -1, VC 0x%x\n",
93749757Smarc ds->dda_if.if_unit, p[1] DDAELOG));
93849757Smarc }
93949757Smarc
94049757Smarc xx_padinfo[line].p_state = PS_PAD;
94149757Smarc xxstart(&xx_tty[line]);
94249757Smarc } else {
94349757Smarc DMESG(ds->dda_if.if_unit, 108, (DDALOG(LOG_ERR)
94449757Smarc "dda%d:(x29) x29_supr: unexpected answer on LCN %d\n",
94549757Smarc ds->dda_if.if_unit, lcn DDAELOG));
94649757Smarc }
94749757Smarc if (LOG_CALLS) {
94849757Smarc DDALOG(LOG_INFO) "dda%d:(x29) LCN %d: connected\n",
94949757Smarc ds->dda_if.if_unit, lcn
95049757Smarc DDAELOG;
95149757Smarc }
95249757Smarc break;
95349757Smarc
95449757Smarc case RING: /* incoming call */
95549757Smarc if (decode_ring(p)) {
95649757Smarc /* find a free lcn associated with a XX_HOST open */
95749757Smarc dc = &ds->dda_cb[1];
95849757Smarc maxlcn = nddach[ds->dda_if.if_unit];
95949757Smarc for (lcn = 1; lcn <= maxlcn; lcn++) {
96049757Smarc if (dc->dc_state == LC_IDLE && dc->dc_flags & DC_X29W)
96149757Smarc break;
96249757Smarc dc++;
96349757Smarc }
96449757Smarc if (lcn > maxlcn) { /* if no free lcn's */
96549757Smarc if (LOG_BUSY) {
96649757Smarc DDALOG(LOG_ERR)
96749757Smarc "dda%d:(x29) no free X29W lcns, call rejected, vc=0x%x\n",
96849757Smarc ds->dda_if.if_unit, p[1]
96949757Smarc DDAELOG;
97049757Smarc }
97149757Smarc send_supr(ds, CLEARVC, p[2], 0); /* clear call */
97249757Smarc break; /* exit case */
97349757Smarc }
97449757Smarc
97549757Smarc /* got a good lcn, now use it */
97649757Smarc
97749757Smarc #ifdef DDADEBUG
97849757Smarc if (DDADBCH(103, ds->dda_if.if_unit)) {
97949757Smarc DDALOG(LOG_ERR) "dda%d:(x29) supr_msg: call from 0x%0x\n",
98049757Smarc ds->dda_if.if_unit, (u_long) dc->dc_inaddr.s_addr
98149757Smarc DDAELOG;
98249757Smarc }
98349757Smarc #endif DDADEBUG
98449757Smarc
98549757Smarc dc->dc_state = LC_DATA_IDLE; /* set state */
98649757Smarc dc->dc_pktsizein = 0;
98749757Smarc dc->dc_pktsizeout = 0;
98849757Smarc dc->dc_wsizein = 0;
98949757Smarc dc->dc_wsizeout = 0;
99049757Smarc dc->dc_flags = DC_X29;
99149757Smarc send_supr(ds, ANSWER, lcn * 2, p[2]); /* send answer */
99249757Smarc if (LOG_CALLS) {
99349757Smarc DDALOG(LOG_INFO) "dda%d:(x29) Call accepted LCN %d\n",
99449757Smarc ds->dda_if.if_unit, dc->dc_lcn
99549757Smarc DDAELOG;
99649757Smarc }
99749757Smarc
99849757Smarc line = dc->dc_line;
99949757Smarc
100049757Smarc #ifdef DDADEBUG
100149757Smarc if (DDADBCH(114, ds->dda_if.if_unit)) {
100249757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) x29_supr: ring: line=%d\n",
100349757Smarc ds->dda_if.if_unit, line
100449757Smarc DDAELOG;
100549757Smarc }
100649757Smarc #endif DDADEBUG
100749757Smarc
100849757Smarc if (line == -1) { /* fubar! */
100949757Smarc DMESG(ds->dda_if.if_unit, 107, (DDALOG(LOG_ERR)
101049757Smarc "dda%d:(x29) x29_supr: ring: line was -1, VC 0x%x\n",
101149757Smarc ds->dda_if.if_unit, p[1] DDAELOG));
101249757Smarc break;
101349757Smarc }
101449757Smarc
101549757Smarc tp = &xx_tty[line];
101649757Smarc xx_padinfo[line].p_state = PS_XFR;
101749757Smarc wakeup((caddr_t) &tp->t_rawq);
101849757Smarc tp->t_state |= TS_CARR_ON;
101949757Smarc #if ACC_ULTRIX > 00
102049757Smarc tp->t_state &= ~TS_ONDELAY;
102149757Smarc #endif
102249757Smarc /* I would prefer to wait a bit before sending this */
102349757Smarc send_x29_param_msg(ds, dc, SET_PAD,
102449757Smarc x29_callin_setparams,
102549757Smarc sizeof(x29_callin_setparams));
102649757Smarc } else { /* bad decode */
102749757Smarc send_supr(ds, CLEARVC, p[2], 0); /* clear call */
102849757Smarc DMESG(ds->dda_if.if_unit, 100, (DDALOG(LOG_ERR)
102949757Smarc "dda%d:(x29) Bad decode, call REJECTED VC 0x%x\n",
103049757Smarc ds->dda_if.if_unit, p[1] DDAELOG));
103149757Smarc }
103249757Smarc break;
103349757Smarc
103449757Smarc case CLEARLC: /* clear by LCN */
103549757Smarc lcn = p[1] / 2; /* get LCN */
103649757Smarc dc = &(ds->dda_cb[lcn]);
103749757Smarc if (dc->dc_state != LC_CLR_PENDING) { /* if no clear pending */
103849757Smarc send_supr(ds, CLEARLC, p[1], 0); /* ack the clear */
103949757Smarc }
104049757Smarc if (dc->dc_state == LC_CALL_PENDING) /* call is cleared */
104149757Smarc DMESG(ds->dda_if.if_unit, 101, (DDALOG(LOG_ERR)
104249757Smarc "dda%d:(x29) Call cleared LCN %d (%x %x)\n",
104349757Smarc ds->dda_if.if_unit, dc->dc_lcn, p[2], p[4] DDAELOG));
104449757Smarc
104549757Smarc hist_lcn_state(ds->dda_if.if_unit, dc->dc_state, LC_IDLE);
104649757Smarc dc->dc_state = LC_IDLE;
104749757Smarc dc->dc_timer = TMO_OFF; /* stop timer */
104849757Smarc dc->dc_wsizein = dc->dc_wsizeout = 0;
104949757Smarc dc->dc_pktsizein = dc->dc_pktsizeout = 0;
105049757Smarc abort_io(ds->dda_if.if_unit, lcn);
105149757Smarc xx_tp_hangup(ds, dc); /* will clear flags */
105249757Smarc break;
105349757Smarc
105449757Smarc case CLEARVC: /* clear by VCN */
105549757Smarc send_supr(ds, CLEARVC, p[1], 0); /* send clear ack */
105649757Smarc if (LOG_CALLS) {
105749757Smarc DDALOG(LOG_INFO)
105849757Smarc "dda%d:(x29) Network cleared VC %x (%x %x)\n",
105949757Smarc ds->dda_if.if_unit, p[1], p[2], p[4]
106049757Smarc DDAELOG;
106149757Smarc }
106249757Smarc break;
106349757Smarc
106449757Smarc case RESET: /* X25 reset */
106549757Smarc send_supr(ds, RESET_ACK, p[1], 0); /* send reset ack */
106649757Smarc abort_io(ds->dda_if.if_unit, (int) p[1] / 2);
106749757Smarc DMESG(ds->dda_if.if_unit, 102, (DDALOG(LOG_ERR)
106849757Smarc "dda%d:(x29) X25 RESET on LCN %d (%x %x)\n",
106949757Smarc ds->dda_if.if_unit, p[1] / 2, p[2], p[4] DDAELOG));
107049757Smarc break;
107149757Smarc
107249757Smarc case INTERRUPT: /* X25 interrupt */
107349757Smarc #ifdef INDICATE_BREAK_ON_INTERRUPT
107449757Smarc lcn = p[1] / 2;
107549757Smarc dc = &(ds->dda_cb[lcn]);
107649757Smarc
107749757Smarc line = dc->dc_line;
107849757Smarc
107949757Smarc if (line == -1) { /* fubar! */
108049757Smarc DMESG(ds->dda_if.if_unit, 107, (DDALOG(LOG_ERR)
108149757Smarc "dda%d:(x29) x29_supr: break: line was -1, VC 0x%x\n",
108249757Smarc ds->dda_if.if_unit, p[1] DDAELOG));
108349757Smarc break;
108449757Smarc }
108549757Smarc
108649757Smarc tp = &xx_tty[line];
108749757Smarc
108849757Smarc if (tp->t_flags & RAW)
108949757Smarc c = 0;
109049757Smarc else
109149757Smarc #if ACC_ULTRIX >= 30
109249757Smarc c = tp->c_cc[VINTR];/* else make it the interrupt */
109349757Smarc #else
109449757Smarc c = tp->t_intrc; /* else make it the interrupt */
109549757Smarc #endif
109649757Smarc #if NBK > 0
109749757Smarc if (tp->t_line == NETLDISC) {
109849757Smarc BKINPUT(c, tp);
109949757Smarc } else
110049757Smarc #endif
110149757Smarc (*linesw[tp->t_line].l_rint) (c, tp);
110249757Smarc /* send_supr (ds, INTR_ACK, p[1], 0); not needed -- done by FE */
110349757Smarc #endif
110449757Smarc break;
110549757Smarc
110649757Smarc case INTR_ACK:
110749757Smarc /* quietly drop the acknowledgement */
110849757Smarc break;
110949757Smarc default:
111049757Smarc DMESG(ds->dda_if.if_unit, 104, (DDALOG(LOG_ERR)
111149757Smarc "dda%d:(x29) supervisor error (%x %x %x %x)\n",
111249757Smarc ds->dda_if.if_unit, p[0], p[1], p[2], p[3] DDAELOG));
111349757Smarc }
111449757Smarc }
111549757Smarc
111649757Smarc /* hangup any attached processes */
111749757Smarc PRIVATE void
xx_tp_hangup(ds,dc)111849757Smarc xx_tp_hangup(ds, dc)
111949757Smarc struct dda_softc *ds;
112049757Smarc register struct dda_cb *dc;
112149757Smarc {
112249757Smarc register struct tty *tp;
112349757Smarc register padinfo *pp;
112449757Smarc register int line;
112549757Smarc
112649757Smarc line = dc->dc_line;
112749757Smarc
112849757Smarc if (line == -1) { /* fubar! */
112949757Smarc DMESG(ds->dda_if.if_unit, 107, (DDALOG(LOG_ERR)
113049757Smarc "dda%d:(x29) xx_tp_hangup: line was -1\n",
113149757Smarc ds->dda_if.if_unit DDAELOG));
113249757Smarc return;
113349757Smarc }
113449757Smarc
113549757Smarc tp = &xx_tty[line];
113649757Smarc pp = &xx_padinfo[line];
113749757Smarc
113849757Smarc if (pp->p_flow != P_NOBLOCK) { /* currently blocked? */
113949757Smarc register struct hdx_chan *hc;
114049757Smarc hc = (struct hdx_chan *) & dc->dc_rchan;
114149757Smarc dda_rrq(ds, hc); /* make sure we hang a read */
114249757Smarc }
114349757Smarc pp->p_flow = P_NOBLOCK;
114449757Smarc tp->t_state &= ~(TS_CARR_ON | TS_ASLEEP | TS_BUSY);
114549757Smarc ttyflush(tp, FREAD | FWRITE);
114649757Smarc gsignal(tp->t_pgrp, SIGHUP);
114749757Smarc gsignal(tp->t_pgrp, SIGCONT);
114849757Smarc tp->t_state &= ~TS_ASLEEP;
114949757Smarc wakeup((caddr_t) &tp->t_outq);
115049757Smarc xxmode[line] = MODE_UNUSED;
115149757Smarc tp->t_addr = (caddr_t) NULL;
115249757Smarc pp->p_state = PS_IDLE;
115349757Smarc if (pp->p_mchsav) {
115449757Smarc m_freem(pp->p_mchsav);
115549757Smarc pp->p_msav = pp->p_mchsav = (struct mbuf *) NULL;
115649757Smarc }
115749757Smarc dc->dc_flags &= ~(DC_X29 | DC_X29W); /* release to others */
115849757Smarc }
115949757Smarc
116049757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
116149757Smarc /*%% X29_DATA() %%*/
116249757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
116349757Smarc /* */
116449757Smarc /* Purpose: */
116549757Smarc /* */
116649757Smarc /* This routine is called when a data channel I/O completes. */
116749757Smarc /* If the completion was for a write, an attempt is made to */
116849757Smarc /* start output on the next packet waiting for output on that */
116949757Smarc /* LCN. If the completion was for a read, the received packet */
117049757Smarc /* is sent to the IP input queue (if no error) and another read */
117149757Smarc /* is started on the LCN. */
117249757Smarc /* */
117349757Smarc /* Call: x29_data(ds, hc, cc, cnt) */
117449757Smarc /* Argument: ds: device control block */
117549757Smarc /* hc: half duplex channel control block */
117649757Smarc /* cc: Mailbox I/O completion status */
117749757Smarc /* cnt: byte count */
117849757Smarc /* Returns: nothing */
117949757Smarc /* Called by: ddainta() */
118049757Smarc /* */
118149757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
118249757Smarc
118349757Smarc #define QBIT 0x80
118449757Smarc
118549757Smarc PRIVATE void
x29_data(ds,hc,cc,cnt,subcc)118649757Smarc x29_data(ds, hc, cc, cnt, subcc)
118749757Smarc register struct dda_softc *ds;
118849757Smarc register struct hdx_chan *hc;
118949757Smarc int cc,
119049757Smarc cnt,
119149757Smarc subcc;
119249757Smarc {
119349757Smarc register struct dda_cb *dc = &(ds->dda_cb[hc->hc_chan / 2]);
119449757Smarc register struct tty *tp;
119549757Smarc
119649757Smarc #ifdef DDADEBUG
119749757Smarc if (DDADBCH(104, ds->dda_if.if_unit)) {
119849757Smarc DDALOG(LOG_DEBUG)
119949757Smarc "dda%d:(x29) x29_data: chan=%x cc=%x cnt=%x subcc=%x\n",
120049757Smarc ds->dda_if.if_unit, hc->hc_chan, cc, cnt, subcc
120149757Smarc DDAELOG;
120249757Smarc }
120349757Smarc #endif DDADEBUG
120449757Smarc
120549757Smarc if (hc->hc_chan & 0x01) { /* if write, fire up next output */
120649757Smarc #ifdef DDADEBUG
120749757Smarc dc->dc_out_t = TMO_OFF; /* turn off output completion timer */
120849757Smarc #endif
120949757Smarc
121049757Smarc if ((hc->hc_func != DDAABT) && (hc->hc_curr = hc->hc_curr->m_next))
121149757Smarc dda_wrq(ds, hc, 0);
121249757Smarc else {
121349757Smarc /* it is abort | no more data left */
121449757Smarc char qbit_indicator;
121549757Smarc qbit_indicator = hc->hc_mbuf->m_dat[MLEN - 1];
121649757Smarc m_freem(hc->hc_mbuf);
121749757Smarc hc->hc_mbuf = hc->hc_curr = (struct mbuf *) 0;
121849757Smarc if (hc->hc_func == DDAABT) {
121949757Smarc hc->hc_func &= ~DDAABT;
122049757Smarc hc->hc_inv &= ~INVALID_MBUF;
122149757Smarc } else
122249757Smarc ds->dda_if.if_opackets++;
122349757Smarc dc->dc_flags &= ~DC_OBUSY;
122449757Smarc
122549757Smarc if (qbit_indicator == QBIT) { /* Q-bit packet? */
122649757Smarc dda_start(ds, dc); /* restart output */
122749757Smarc } else {
122849757Smarc tp = &xx_tty[dc->dc_line];
122949757Smarc tp->t_state &= ~TS_BUSY;
123049757Smarc xxstart(tp); /* restart tty output */
123149757Smarc }
123249757Smarc }
123349757Smarc
123449757Smarc /* it's a packet coming in from the front end to the host */
123549757Smarc } else {
123649757Smarc #ifdef DDADEBUG
123749757Smarc dc->dc_flags &= ~DC_IPEND;
123849757Smarc #endif
123949757Smarc hc = &dc->dc_rchan;
124049757Smarc
124149757Smarc #ifdef DDADEBUG
124249757Smarc if (DDADBCH(105, ds->dda_if.if_unit)) {
124349757Smarc u_char *p;
124449757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) ", ds->dda_if.if_unit DDAELOG;
124549757Smarc p = mtod(hc->hc_curr, u_char *);
124649757Smarc prt_bytes(ds->dda_if.if_unit, "received data", p, (cnt < 64 ? cnt : 64));
124749757Smarc }
124849757Smarc if (DDADBCH(106, ds->dda_if.if_unit)) {
124949757Smarc DDALOG(LOG_DEBUG)
125049757Smarc "dda%d:(x29) x29_data: read complete mbuf=%x curr=%x\n",
125149757Smarc ds->dda_if.if_unit, hc->hc_mbuf, hc->hc_curr
125249757Smarc DDAELOG;
125349757Smarc }
125449757Smarc #endif DDADEBUG
125549757Smarc
125649757Smarc if (dc->dc_state != LC_DATA_IDLE) {
125749757Smarc m_freem(hc->hc_mbuf); /* toss the packet, lcn is dead */
125849757Smarc hc->hc_mbuf = hc->hc_curr = (struct mbuf *) 0;
125949757Smarc } else if (cc == DDAIOCOK || (cc == DDAIOCOKP && !(subcc & QBIT))) {
126049757Smarc /* Queue up I/O completion OK transfers and I/O OK with more data
126149757Smarc * pending transfers (as long as it's not a Qbit message).
126249757Smarc * This algorythm operates differently than the IP handler due
126349757Smarc * to the fact that we don't need to wait for the entire X.25
126449757Smarc * packet to arrive on the host before we assemble it. To do
126549757Smarc * so should be OK, but unfortunately it seems some brain-dead
126649757Smarc * PAD's generate packets with the M-bit set if they have more
126749757Smarc * data in their internal buffers. This can cause the system
126849757Smarc * to burn up mbufs waiting for us to finally receive a packet
126949757Smarc * with the M-bit not set. However, we should hold up on processing
127049757Smarc * packets with both the Q-bit and the M-bit set until we receive
127149757Smarc * the entire Q-bit message. If we get 30k Q-bit packets, we will
127249757Smarc * die, but that is obscenely absurd in the first place.
127349757Smarc * (sigh) -- pst 7-19-89
127449757Smarc */
127549757Smarc
127649757Smarc #ifdef DDADEBUG
127749757Smarc if (DDADBCH(107, ds->dda_if.if_unit)) {
127849757Smarc DDALOG(LOG_DEBUG)
127949757Smarc "dda%d:(x29) x29_data: chan=%x DDAIOCOK\n",
128049757Smarc ds->dda_if.if_unit, hc->hc_chan
128149757Smarc DDAELOG;
128249757Smarc }
128349757Smarc #endif DDADEBUG
128449757Smarc hc->hc_curr->m_len += cnt; /* update byte count */
128549757Smarc
128649757Smarc ds->dda_if.if_ipackets++;
128749757Smarc /* HANDLE THE DATA HERE */
128849757Smarc if (subcc & QBIT) {
128949757Smarc int len;
129049757Smarc char *mcp;
129149757Smarc mcp = mtod(hc->hc_curr, char *);
129249757Smarc len = hc->hc_curr->m_len;
129349757Smarc
129449757Smarc #ifdef DDADEBUG
129549757Smarc if (DDADBCH(108, ds->dda_if.if_unit))
129649757Smarc prt_bytes(ds->dda_if.if_unit,
129749757Smarc "(x29) Qbit:", mcp, (len < 64 ? len : 64));
129849757Smarc #endif DDADEBUG
129949757Smarc
130049757Smarc if (*mcp == BREAK_INDIC) { /* Break indication? */
130149757Smarc register struct tty *tp;
130249757Smarc if (x29_break_reply_is_required(mcp, len)) {
130349757Smarc /* tell pad to stop discarding output */
130449757Smarc send_x29_param_msg(ds, dc, SET_PAD,
130549757Smarc x29_break_ack_params, 2);
130649757Smarc }
130749757Smarc hc->hc_curr->m_len = 1; /* change data to single byte */
130849757Smarc tp = &xx_tty[dc->dc_line];
130949757Smarc if (tp->t_flags & RAW) /* if port is in raw mode, */
131049757Smarc *mcp = 0; /* make the byte a null */
131149757Smarc else
131249757Smarc #if ACC_ULTRIX >= 30
131349757Smarc *mcp = tp->t_cc[VINTR]; /* else make it the interrupt */
131449757Smarc #else
131549757Smarc *mcp = tp->t_intrc; /* else make it the interrupt */
131649757Smarc #endif
131749757Smarc x29_dhandle(ds, dc, 0);
131849757Smarc return;
131949757Smarc } else if (*mcp & READ_PAD) {
132049757Smarc if (len == 1) /* just a message, no params? */
132149757Smarc send_x29_param_msg(ds, dc, PAR_INDICATION,
132249757Smarc x29_callout_params,
132349757Smarc sizeof(x29_callout_params));
132449757Smarc else
132549757Smarc send_x29_param_msg(ds, dc, PAR_INDICATION, mcp + 1, len - 1);
132649757Smarc m_freem(hc->hc_mbuf);
132749757Smarc hc->hc_mbuf = hc->hc_curr = (struct mbuf *) 0;
132849757Smarc } else {
132949757Smarc m_freem(hc->hc_mbuf);
133049757Smarc hc->hc_mbuf = hc->hc_curr = (struct mbuf *) 0;
133149757Smarc }
133249757Smarc } else { /* not Qbit data, process normally */
133349757Smarc x29_dhandle(ds, dc, 0);
133449757Smarc return;
133549757Smarc }
133649757Smarc } else if (cc == DDAIOCOKP) { /* good completion, more data pending */
133749757Smarc hc->hc_curr->m_len += cnt;
133849757Smarc } else { /* toss packet */
133949757Smarc m_freem(hc->hc_mbuf);
134049757Smarc hc->hc_mbuf = hc->hc_curr = (struct mbuf *) 0;
134149757Smarc }
134249757Smarc /* hang a new data read */
134349757Smarc #ifdef DDADEBUG
134449757Smarc dc->dc_flags |= DC_IPEND;
134549757Smarc #endif
134649757Smarc dda_rrq(ds, hc);
134749757Smarc }
134849757Smarc }
134949757Smarc
135049757Smarc /* this routine copies chars from the dc_rchan mbuf to the upper
135149757Smarc * level software. If all the characters are read then the mbuf is
135249757Smarc * freed and a new read is hung on the channel.
135349757Smarc *
135449757Smarc * This routine is called from below by the int A handler and from above
135549757Smarc * by the device read routine.
135649757Smarc */
135749757Smarc
135849757Smarc PRIVATE void
x29_dhandle(ds,dc,restart)135949757Smarc x29_dhandle(ds, dc, restart)
136049757Smarc register struct dda_softc *ds;
136149757Smarc register struct dda_cb *dc;
136249757Smarc int restart;
136349757Smarc {
136449757Smarc register struct tty *tp;
136549757Smarc register struct hdx_chan *hc;
136649757Smarc register padinfo *pp;
136749757Smarc u_char *cp,
136849757Smarc c;
136949757Smarc struct mbuf *m2,
137049757Smarc *m;
137149757Smarc int s,
137249757Smarc line;
137349757Smarc register int j;
137449757Smarc static int recurse = 0;
137549757Smarc
137649757Smarc s = splimp();
137749757Smarc
137849757Smarc if (recurse) { /* don't allow ourselves to be called recursively */
137949757Smarc splx(s);
138049757Smarc return;
138149757Smarc } else
138249757Smarc recurse = 1;
138349757Smarc
138449757Smarc hc = (struct hdx_chan *) &dc->dc_rchan;
138549757Smarc
138649757Smarc line = dc->dc_line;
138749757Smarc
138849757Smarc tp = &xx_tty[line];
138949757Smarc pp = &xx_padinfo[line];
139049757Smarc
139149757Smarc if (restart) { /* trying to restart input? */
139249757Smarc j = pp->p_flow;
139349757Smarc m = pp->p_mchsav;
139449757Smarc m2 = pp->p_msav;
139549757Smarc
139649757Smarc #ifdef DDADEBUG
139749757Smarc if (DDADBCH(109, ds->dda_if.if_unit)) {
139849757Smarc DDALOG(LOG_DEBUG)
139949757Smarc "dda%d:(x29) flow restart [%d] in %x\n",
140049757Smarc ds->dda_if.if_unit, j, m
140149757Smarc DDAELOG;
140249757Smarc }
140349757Smarc #endif DDADEBUG
140449757Smarc
140549757Smarc } else {
140649757Smarc j = P_NOBLOCK;
140749757Smarc m2 = m = hc->hc_mbuf; /* que mbuf chain */
140849757Smarc }
140949757Smarc
141049757Smarc if (m == 0) {
141149757Smarc DMESG(ds->dda_if.if_unit, 105, (DDALOG(LOG_ERR)
141249757Smarc "dda%d:(x29) x29_dhandle: null mbuf\n",
141349757Smarc ds->dda_if.if_unit DDAELOG));
141449757Smarc hc->hc_mbuf = hc->hc_curr = (struct mbuf *) NULL;
141549757Smarc dda_rrq(ds, hc);
141649757Smarc goto out;
141749757Smarc }
141849757Smarc while (m2) {
141949757Smarc cp = mtod(m2, u_char *);
142049757Smarc for (; j < m2->m_len; j++) {
142149757Smarc c = cp[j] & INPUT_PARITY_MASK;
142249757Smarc if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG - 2)
142349757Smarc if (!ttbreakc(c, tp))
142449757Smarc continue; /* dump the character */
142549757Smarc #if NBK > 0
142649757Smarc if (tp->t_line == NETLDISC) {
142749757Smarc BKINPUT(c, tp);
142849757Smarc } else
142949757Smarc #endif
143049757Smarc (*linesw[tp->t_line].l_rint) (c, tp);
143149757Smarc
143249757Smarc
143349757Smarc /* Block further input iff: Current input > threshold AND input
143449757Smarc * is available to user program */
143549757Smarc
143649757Smarc if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG / 4 &&
143749757Smarc ((tp->t_flags & (RAW | CBREAK)) || (tp->t_canq.c_cc > 0))) {
143849757Smarc #ifdef DDADEBUG
143949757Smarc if (DDADBCH(109, ds->dda_if.if_unit)) {
144049757Smarc DDALOG(LOG_DEBUG)
144149757Smarc "dda%d:(x29) flow on [%d] in %x of %d\n",
144249757Smarc ds->dda_if.if_unit, j, m2, m2->m_len
144349757Smarc DDAELOG;
144449757Smarc }
144549757Smarc #endif DDADEBUG
144649757Smarc pp->p_flow = j + 1;
144749757Smarc pp->p_msav = m2;
144849757Smarc pp->p_mchsav = m;
144949757Smarc if (restart == 0)
145049757Smarc hc->hc_mbuf = hc->hc_curr = (struct mbuf *) NULL;
145149757Smarc goto out;
145249757Smarc }
145349757Smarc }
145449757Smarc m2 = m2->m_next;
145549757Smarc j = P_NOBLOCK;
145649757Smarc }
145749757Smarc if (restart)
145849757Smarc pp->p_msav = pp->p_mchsav = (struct mbuf *) NULL;
145949757Smarc
146049757Smarc m_freem(m);
146149757Smarc hc->hc_mbuf = hc->hc_curr = (struct mbuf *) NULL;
146249757Smarc pp->p_flow = P_NOBLOCK;
146349757Smarc
146449757Smarc #ifdef DDADEBUG
146549757Smarc dc->dc_flags |= DC_IPEND;
146649757Smarc #endif
146749757Smarc
146849757Smarc dda_rrq(ds, hc);
146949757Smarc
147049757Smarc out:
147149757Smarc recurse = 0;
147249757Smarc splx(s);
147349757Smarc }
147449757Smarc
147549757Smarc PRIVATE void
xx_qbit_msg(tp,unit,msg)147649757Smarc xx_qbit_msg(tp, unit, msg)
147749757Smarc register struct tty *tp;
147849757Smarc int unit;
147949757Smarc char *msg;
148049757Smarc {
148149757Smarc register struct dda_cb *dc;
148249757Smarc register struct dda_softc *ds;
148349757Smarc int s;
148449757Smarc
148549757Smarc ds = &dda_softc[unit];
148649757Smarc dc = (struct dda_cb *) tp->t_addr;
148749757Smarc s = splimp();
148849757Smarc
148949757Smarc #ifdef DDADEBUG
149049757Smarc if (DDADBCH(110, unit)) {
149149757Smarc DDALOG(LOG_DEBUG)
149249757Smarc "dda%d:(x29) xx_qbit_msg: %d %d %d\n",
149349757Smarc unit, msg[0], msg[1], msg[2]
149449757Smarc DDAELOG;
149549757Smarc }
149649757Smarc #endif DDADEBUG
149749757Smarc
149849757Smarc if (msg[1] < (MLEN - 4))
149949757Smarc send_x29_param_msg(ds, dc, msg[0], msg + 2, msg[1]);
150049757Smarc splx(s);
150149757Smarc }
150249757Smarc
150349757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
150449757Smarc /*%% XXCNTL() %%*/
150549757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
150649757Smarc /* */
150749757Smarc /* Purpose: */
150849757Smarc /* */
150949757Smarc /* Do modem control functions on a line. */
151049757Smarc /* */
151149757Smarc /* Call: xxcntl(tp, c, d) */
151249757Smarc /* Argument: tp: pointer to tty structure */
151349757Smarc /* c: function code */
151449757Smarc /* unit: for unit number */
151549757Smarc /* Returns: none */
151649757Smarc /* Called by: xxopen() */
151749757Smarc /* xxclose() */
151849757Smarc /* xxread() */
151949757Smarc /* xxint() */
152049757Smarc /* */
152149757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
152249757Smarc
152349757Smarc PRIVATE void
xxcntl(tp,c,unit)152449757Smarc xxcntl(tp, c, unit)
152549757Smarc register struct tty *tp;
152649757Smarc int c,
152749757Smarc unit;
152849757Smarc {
152949757Smarc register struct dda_cb *dc;
153049757Smarc register struct dda_softc *ds;
153149757Smarc register padinfo *pp;
153249757Smarc int s,
153349757Smarc l;
153449757Smarc
153549757Smarc l = tp - xx_tty;
153649757Smarc ds = &dda_softc[unit];
153749757Smarc pp = &xx_padinfo[l];
153849757Smarc s = splimp();
153949757Smarc
154049757Smarc #ifdef DDADEBUG
154149757Smarc if (DDADBCH(111, unit)) {
154249757Smarc DDALOG(LOG_DEBUG)
154349757Smarc "dda%d:(x29) xxcntl: tp=0x%x line=%d\n", unit, tp, l
154449757Smarc DDAELOG;
154549757Smarc }
154649757Smarc #endif DDADEBUG
154749757Smarc
154849757Smarc switch (c) {
154949757Smarc case XX_C_PAD:
155049757Smarc if (tp->t_addr)
155149757Smarc break;
155249757Smarc if (dc = find_free_lcn(ds)) { /* race against locate_x25_lcn */
155349757Smarc dc->dc_flags = DC_X29;
155449757Smarc dc->dc_line = l;
155549757Smarc pp->p_state = PS_COM;
155649757Smarc tp->t_addr = (caddr_t) dc;
155749757Smarc tp->t_flags &= ~ECHO;
155849757Smarc pp->p_flow = P_NOBLOCK;
155949757Smarc pp->p_msav = pp->p_mchsav = (struct mbuf *) NULL;
156049757Smarc pp->p_idx = 0;
156149757Smarc pp->p_line[0] = '\0';
156249757Smarc } else
156349757Smarc tp->t_addr = (caddr_t) NULL;
156449757Smarc break;
156549757Smarc case XX_C_HOST:
156649757Smarc if (tp->t_addr)
156749757Smarc break;
156849757Smarc if (dc = find_free_lcn(ds)) { /* race against locate_x25_lcn */
156949757Smarc dc->dc_flags = DC_X29W;
157049757Smarc dc->dc_line = l;
157149757Smarc pp->p_state = PS_WAIT;
157249757Smarc pp->p_flow = P_NOBLOCK;
157349757Smarc pp->p_msav = pp->p_mchsav = (struct mbuf *) NULL;
157449757Smarc tp->t_addr = (caddr_t) dc;
157549757Smarc } else
157649757Smarc tp->t_addr = (caddr_t) NULL;
157749757Smarc break;
157849757Smarc case XX_C_CLOSE:
157949757Smarc pp->p_state = PS_IDLE;
158049757Smarc if (pp->p_mchsav) {
158149757Smarc m_freem(pp->p_mchsav);
158249757Smarc pp->p_msav = pp->p_mchsav = (struct mbuf *) NULL;
158349757Smarc }
158449757Smarc dc = (struct dda_cb *) tp->t_addr;
158549757Smarc if (dc == 0)
158649757Smarc break;
158749757Smarc if (pp->p_flow != P_NOBLOCK) { /* currently blocked? */
158849757Smarc register struct hdx_chan *hc;
158949757Smarc hc = (struct hdx_chan *) &dc->dc_rchan;
159049757Smarc dda_rrq(ds, hc); /* make sure we hang a read */
159149757Smarc }
159249757Smarc #ifdef DDADEBUG
159349757Smarc if (DDADBCH(111, unit)) {
159449757Smarc static char *st[] = { "lcn down", "lcn restart", "idle",
159549757Smarc "call pending", "data idle", "clear pending"
159649757Smarc };
159749757Smarc DDALOG(LOG_DEBUG)
159849757Smarc "dda%d:(x29) xxcntl: close state: %s\n", unit, st[dc->dc_state]
159949757Smarc DDAELOG;
160049757Smarc }
160149757Smarc #endif DDADEBUG
160249757Smarc
160349757Smarc if (dc->dc_state == LC_DATA_IDLE || dc->dc_state == LC_CALL_PENDING)
160449757Smarc clear_lcn(ds, dc); /* send clear & set state to clr_pending */
160549757Smarc /* timers will convert it to LC_IDLE later */
160649757Smarc
160749757Smarc #ifdef DDADEBUG
160849757Smarc else
160949757Smarc if (DDADBCH(111, unit)) {
161049757Smarc DDALOG(LOG_DEBUG)
161149757Smarc "dda%d:(x29) xxcntl: warning: state not data_idle\n", unit
161249757Smarc DDAELOG;
161349757Smarc }
161449757Smarc #endif
161549757Smarc
161649757Smarc dc->dc_flags &= ~(DC_X29 | DC_X29W); /* release to others */
161749757Smarc tp->t_addr = (caddr_t) NULL;
161849757Smarc break;
161949757Smarc case XX_C_BREAK:
162049757Smarc
162149757Smarc /* really should look at X.3 parameters to decide if an interrupt
162249757Smarc * packet should be sent. instead, we take an action which assumes
162349757Smarc * PAD parameter 7 has value 21 */
162449757Smarc dc = (struct dda_cb *) tp->t_addr;
162549757Smarc send_supr(ds, INTERRUPT, dc->dc_lcn * 2, 0);
162649757Smarc send_x29_param_msg(ds, dc, BREAK_INDIC, 0, 0);
162749757Smarc break;
162849757Smarc }
162949757Smarc splx(s);
163049757Smarc }
163149757Smarc
163249757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
163349757Smarc /*%% X29_INIT() %%*/
163449757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
163549757Smarc /* */
163649757Smarc /* Purpose: */
163749757Smarc /* */
163849757Smarc /* Software reset, clear lines. */
163949757Smarc /* */
164049757Smarc /* Call: x29_init(unit, active); */
164149757Smarc /* Argument: unit: ACP _XX device */
164249757Smarc /* Returns: none */
164349757Smarc /* Called by: none */
164449757Smarc /* */
164549757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
164649757Smarc
164749757Smarc PRIVATE void
x29_init(unit,active)164849757Smarc x29_init(unit, active)
164949757Smarc int unit,
165049757Smarc active;
165149757Smarc {
165249757Smarc register int i;
165349757Smarc register padinfo *pp;
165449757Smarc
165549757Smarc #ifdef DDADEBUG
165649757Smarc if (DDADBCH(113, unit)) {
165749757Smarc DDALOG(LOG_DEBUG) "dda%d:(x29) x29_init() active=%d\n",
165849757Smarc unit, active
165949757Smarc DDAELOG;
166049757Smarc }
166149757Smarc #endif DDADEBUG
166249757Smarc
166349757Smarc if (active)
166449757Smarc xxclear(unit);
166549757Smarc else {
166649757Smarc for (i = 0; i < XXLPERBRD; i++) {
166749757Smarc xx_tty[unit * XXLPERBRD + i].t_state = PS_IDLE;
166849757Smarc pp = &xx_padinfo[unit * XXLPERBRD + i];
166949757Smarc pp->p_state = PS_IDLE;
167049757Smarc pp->p_flow = P_NOBLOCK;
167149757Smarc pp->p_msav = pp ->p_mchsav = (struct mbuf *) NULL;
167249757Smarc }
167349757Smarc }
167449757Smarc }
167549757Smarc
167649757Smarc PRIVATE void
xxclear(unit)167749757Smarc xxclear(unit)
167849757Smarc int unit;
167949757Smarc {
168049757Smarc register struct tty *tp;
168149757Smarc register struct dda_softc *ds;
168249757Smarc register struct dda_cb *dc;
168349757Smarc int i,
168449757Smarc state;
168549757Smarc
168649757Smarc ds = &dda_softc[unit];
168749757Smarc for (i = 0, tp = &xx_tty[unit * XXLPERBRD]; i < XXLPERBRD; i++, tp++) {
168849757Smarc state = tp->t_state;
168949757Smarc #ifdef DDADEBUG
169049757Smarc if (DDADBCH(112, unit) && state) {
169149757Smarc DDALOG(LOG_DEBUG)
169249757Smarc "dda%d:(x29) xxclear: line=%d pgrp=%d state=%d\n",
169349757Smarc unit, i, tp->t_pgrp, state
169449757Smarc DDAELOG;
169549757Smarc }
169649757Smarc #endif DDADEBUG
169749757Smarc if (state & TS_WOPEN) {
169849757Smarc tp->t_state &= ~TS_WOPEN;
169949757Smarc wakeup(&tp->t_rawq);
170049757Smarc }
170149757Smarc if (tp->t_state) {
170249757Smarc dc = (struct dda_cb *) tp->t_addr;
170349757Smarc if (dc) {
170449757Smarc xx_tp_hangup(ds, dc);
170549757Smarc dc->dc_line = -1; /* break correspondence */
170649757Smarc }
170749757Smarc }
170849757Smarc }
170949757Smarc }
171049757Smarc
171149757Smarc /*@@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
171249757Smarc /*%% XXSHOW() %%*/
171349757Smarc /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
171449757Smarc /* */
171549757Smarc /* Purpose: */
171649757Smarc /* */
171749757Smarc /* Show status of each active unit */
171849757Smarc /* */
171949757Smarc /* Call: xxshow() */
172049757Smarc /* Argument: none */
172149757Smarc /* Returns: none */
172249757Smarc /* Called by: none */
172349757Smarc /* */
172449757Smarc /*##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
172549757Smarc
172649757Smarc PRIVATE void
xxshow()172749757Smarc xxshow()
172849757Smarc {
172949757Smarc register struct tty *tp;
173049757Smarc register padinfo *pp;
173149757Smarc int unit,
173249757Smarc i;
173349757Smarc static char *st[] = { "idle", " com", " pad", "wait", "xfer" };
173449757Smarc
173549757Smarc
173649757Smarc for (unit = 0; unit < (NDDA < XXBOARDS ? NDDA : XXBOARDS); unit++) {
173749757Smarc uprintf("\nACP5250/6250 X29 driver: state of unit %d -\n", unit);
173849757Smarc uprintf("line\tstate\tlcn\tflow\ttstate\ttflags\n");
173949757Smarc
174049757Smarc for (i = 0, tp = &xx_tty[unit * XXLPERBRD]; i < XXLPERBRD; i++, tp++) {
174149757Smarc if (tp->t_state) {
174249757Smarc pp = &xx_padinfo[i];
174349757Smarc uprintf("%d:\t%s\t%d\t%d\t%x\t%x\n", i, st[pp->p_state],
174449757Smarc (struct dda_cb *) (tp->t_addr) - dda_softc[unit].dda_cb,
174549757Smarc pp->p_flow, tp->t_state, tp->t_flags);
174649757Smarc }
174749757Smarc }
174849757Smarc }
174949757Smarc uprintf("remaining lines free\n");
175049757Smarc }
175149757Smarc
175249757Smarc /******************************************************************************
175349757Smarc * PAD CODE
175449757Smarc ******************************************************************************/
175549757Smarc /* PADCHARUP - Pass a character up towards the user */
175649757Smarc #define PADCHARUP(c,tp) (*linesw[(tp)->t_line].l_rint) ((c), (tp))
175749757Smarc
175849757Smarc PRIVATE void
xxpadhandle(ds,tp,pi)175949757Smarc xxpadhandle(ds, tp, pi)
176049757Smarc struct dda_softc *ds;
176149757Smarc struct tty *tp; /* pointer to relevant tty structure */
176249757Smarc padinfo *pi; /* pointer to relevant padinfo structure */
176349757Smarc {
176449757Smarc register int i;
176549757Smarc register char c;
176649757Smarc register struct dda_cb *dc;
176749757Smarc int nch;
176849757Smarc char tbuf[CBSIZE]; /* CBSIZE is number of char in a
176949757Smarc * cblock */
177049757Smarc nch = q_to_b(&tp->t_outq, tbuf, CBSIZE);
177149757Smarc
177249757Smarc /* handle characters in command state. Its OK if were slow here because
177349757Smarc * there is a person on the other end of the discussion */
177449757Smarc dc = (struct dda_cb *) tp->t_addr;
177549757Smarc for (i = 0; i < nch; i++) {
177649757Smarc if (pi->p_idx >= P_LINELEN) {
177749757Smarc xxpadmsg("\r\ncommand too long\r\n@", tp);
177849757Smarc pi->p_idx = 0;
177949757Smarc return;
178049757Smarc }
178149757Smarc c = pi->p_line[pi->p_idx] = tbuf[i] & INPUT_PARITY_MASK;
178249757Smarc if (c == '\r' || c == '\n') {
178349757Smarc PADCHARUP('\r', tp);
178449757Smarc PADCHARUP('\n', tp);
178549757Smarc pi->p_line[pi->p_idx] = '\0';
178649757Smarc if (dc && dc->dc_state != LC_IDLE) {
178749757Smarc xxpadmsg("cannot call, line is in transition\r\n", tp);
178849757Smarc if (dc && dc->dc_state == LC_CALL_PENDING)
178949757Smarc xxpadmsg("previous call still pending\r\n", tp);
179049757Smarc } else if (xxpadparse(ds, pi, tp) == 0)
179149757Smarc PADCHARUP('@', tp);
179249757Smarc pi->p_idx = 0;
179349757Smarc } else if (c == '\b' || c == '\177') {
179449757Smarc if (pi->p_idx) {
179549757Smarc pi->p_idx--;
179649757Smarc xxpadmsg("\b \b", tp);
179749757Smarc }
179849757Smarc } else {
179949757Smarc pi->p_idx++;
180049757Smarc PADCHARUP(c, tp);
180149757Smarc }
180249757Smarc }
180349757Smarc }
180449757Smarc
180549757Smarc PRIVATE int
xxpadparse(ds,pi,tp)180649757Smarc xxpadparse(ds, pi, tp)
180749757Smarc struct dda_softc *ds;
180849757Smarc padinfo *pi;
180949757Smarc struct tty *tp;
181049757Smarc {
181149757Smarc char *p = pi->p_line;
181249757Smarc
181349757Smarc if (*p == 'c' || *p == 'C') { /* connect command */
181449757Smarc for (p++; *p == ' '; *p++);
181549757Smarc if (*p < '0' || *p > '9')
181649757Smarc xxpadmsg("???\r\n", tp);
181749757Smarc else /* place a call */
181849757Smarc return xxpadcall(ds, p, tp);
181949757Smarc } else if (*p)
182049757Smarc xxpadmsg("invalid command\r\n", tp);
182149757Smarc return 0;
182249757Smarc }
182349757Smarc
182449757Smarc PRIVATE int
xxpadcall(ds,addr,tp)182549757Smarc xxpadcall(ds, addr, tp)
182649757Smarc struct dda_softc *ds;
182749757Smarc char *addr;
182849757Smarc struct tty *tp;
182949757Smarc {
183049757Smarc register int i = 0;
183149757Smarc struct in_addr in;
183249757Smarc
183349757Smarc while (addr[i]) {
183449757Smarc if (addr[i] < '0' || addr[i] > '9') {
183549757Smarc xxpadmsg("invalid address\r\n", tp);
183649757Smarc return 0;
183749757Smarc }
183849757Smarc i++;
183949757Smarc }
184049757Smarc ddacb_called_addr[0] = i;
184149757Smarc bcopy(addr, ddacb_called_addr + 1, i);
184249757Smarc ddacb_user_data[0] = (u_char) 0; /* no user data for now */
184349757Smarc in.s_addr = 0;
184449757Smarc return make_x25_call(ds, (struct dda_cb *) tp->t_addr, in, X25_PROTO_X29);
184549757Smarc }
184649757Smarc
184749757Smarc PRIVATE void
xxpadmsg(s,tp)184849757Smarc xxpadmsg(s, tp)
184949757Smarc char *s;
185049757Smarc struct tty *tp;
185149757Smarc {
185249757Smarc while (*s) {
185349757Smarc PADCHARUP(*s, tp);
185449757Smarc s++;
185549757Smarc }
185649757Smarc }
185749757Smarc
185849757Smarc /*
185949757Smarc * This routine is used to respond to
186049757Smarc * READ_PARAMS and SET_READ_PARAMS requests, and also
186149757Smarc * to send out a SET_PARAMS request for incoming calls.
186249757Smarc * The outgoing pad supports NO parameters.
186349757Smarc */
send_x29_param_msg(ds,dc,type,msg,len)186449757Smarc send_x29_param_msg(ds, dc, type, msg, len)
186549757Smarc register struct dda_cb *dc;
186649757Smarc register struct dda_softc *ds;
186749757Smarc x29_pad_pair *msg;
186849757Smarc {
186949757Smarc struct mbuf *m;
187049757Smarc u_char *p;
187149757Smarc short i;
187249757Smarc register struct ifqueue *oq;
187349757Smarc m = 0; /* Allocate an mbuf to stuff the chars into */
187449757Smarc MGET(m, M_DONTWAIT, MT_DATA);
187549757Smarc if (m == 0) {
187649757Smarc DMESG(ds->dda_if.if_unit, 106, (DDALOG(LOG_ERR)
187749757Smarc "dda%d:(x29) couldn't get mbuf for QBIT message\n",
187849757Smarc ds->dda_if.if_unit DDAELOG));
187949757Smarc return;
188049757Smarc }
188149757Smarc m->m_dat[MLEN - 1] = QBIT; /* set Q-bit */
188249757Smarc p = mtod(m, u_char *);
188349757Smarc len = len / 2;
188449757Smarc *p++ = type;
188549757Smarc if (type == PAR_INDICATION) { /* our pad supports NO parameters */
188649757Smarc for (i = 0; i < len; i++) {
188749757Smarc *p++ = msg[i].ref | 0x80; /* set invalid bit */
188849757Smarc *p++ = 1; /* not implemented */
188949757Smarc }
189049757Smarc } else { /* BREAK_INDIC, SET_PAD to ack break */
189149757Smarc for (i = 0; i < len; i++) {
189249757Smarc *p++ = msg[i].ref;
189349757Smarc *p++ = msg[i].val;
189449757Smarc }
189549757Smarc }
189649757Smarc m->m_len = 1 + 2 * len;
189749757Smarc oq = &(dc->dc_oq); /* point to output queue */
189849757Smarc if (IF_QFULL(oq)) { /* if q full */
189949757Smarc IF_DROP(oq); /* drop the data */
190049757Smarc m_freem(m);
190149757Smarc ds->dda_if.if_collisions++; /* for netstat display */
190249757Smarc } else {
190349757Smarc IF_ENQUEUE(oq, m); /* otherwise queue it */
190449757Smarc dda_start(ds, dc); /* and try to output */
190549757Smarc }
190649757Smarc }
190749757Smarc
190849757Smarc PRIVATE int
x29_break_reply_is_required(mcp,len)190949757Smarc x29_break_reply_is_required(mcp, len)
191049757Smarc char *mcp;
191149757Smarc int len;
191249757Smarc {
191349757Smarc mcp++; /* skip over break indication msg */
191449757Smarc while (len > 1) { /* while there are parameters left, */
191549757Smarc if ((*mcp == 8) && (mcp[1] == 1)) /* paramter 8 set to 1? */
191649757Smarc return 1; /* yes */
191749757Smarc mcp += 2;
191849757Smarc len -= 2;
191949757Smarc }
192049757Smarc return 0;
192149757Smarc }
192249757Smarc
192349757Smarc /*
192449757Smarc * Ultrix 3.0 removed the old ttbreakc() kernel routine when moving to
192549757Smarc * a posix compliant driver. Here it is again, (for our local use only!!!)
192649757Smarc *
192749757Smarc */
192849757Smarc #if ACC_ULTRIX >= 30
192949757Smarc static int
ttbreakc(c,tp)193049757Smarc ttbreakc(c, tp)
193149757Smarc register c;
193249757Smarc register struct tty *tp;
193349757Smarc {
193449757Smarc return (c == tp->t_cc[VEOL] || c == tp->t_cc[VEOF] ||
193549757Smarc c == tp->t_cc[VEOL2] || c == '\r' && (tp->t_flags & CRMOD));
193649757Smarc }
193749757Smarc #endif
193849757Smarc
193949757Smarc
194049757Smarc /*
194149757Smarc Revision History:
194249757Smarc
194349757Smarc 09-Jun-1988: Unknown (Brad?)
194449757Smarc Initial implementation.
194549757Smarc 15-Feb-1989: Paul Traina
194649757Smarc Fixed point bug in send_x29_prm_msg
194749757Smarc 08-Mar-1989: Steve Johnson
194849757Smarc Fixed bug in xx_flow logic
194949757Smarc 24-May-1989: Paul Traina
195049757Smarc Upgraded for Ultrix 3.0
195149757Smarc 28-May-1989: Paul Traina
195249757Smarc Added more driver intelligence to disable pad durring call pending
195349757Smarc 31-May-1989: Paul Traina
195449757Smarc Added flexible mapping for # of boards per unit
195549757Smarc 04-Jun-1989: Paul Traina
195649757Smarc Fixed driver to dequeue Q-bit X29 packets from the mbuf chain properly.
195749757Smarc 19-Jun-1989: Paul Traina
195849757Smarc Fixed previous fix-- will need to go over if-elseif logic more
195949757Smarc carefully to make sure we're doing the right thing. It should be
196049757Smarc recoded.
196149757Smarc Modernized entire debug code suite, changed xxshow functionality to
196249757Smarc use the uprintf() kernel call to display data on user's terminal for
196349757Smarc the xxshow hack.
196449757Smarc 12-Jul-1989: Paul Traina
196549757Smarc Changed format of some debug messages. Removed LOCAL_VOID in
196649757Smarc favor of PRIVATE routine to aid in debugging. Simplified some
196749757Smarc chunky logic.
196849757Smarc 18-Jul-1989: Paul Traina
196949757Smarc Flipped search order for finding a free X29W lcn at RING time.
197049757Smarc Moved the dc_key.ttyline field out of the union and made it dc_line.
197149757Smarc This fixed the Dartmouth singleuser bug.
197249757Smarc 19-Jul-1989: Paul Traina
197349757Smarc Changed the packet decode logic in x29_data to immediately process
197449757Smarc packets with more data pending (i.e. the M-bit) right away, instead
197549757Smarc of queuing them up. (Note: it still queues up Q-bit packets) This
197649757Smarc may fix the Dartmouth mbuf problem with blasting uploads.
197749757Smarc 27-Jul-1989: Paul Traina
197849757Smarc Removed 8-bit strip in x29_dhandle.
197949757Smarc 01-Aug-1989: Paul Traina
198049757Smarc Added additional two parameters to make_x25_call for userdata/length
198149757Smarc for merge with new pad software.
198249757Smarc 02-Aug-1989: Paul Traina
198349757Smarc Reinserted 8-bit strip on data received from the net. (uses
198449757Smarc PARITY_MASK define for easy change).
198549757Smarc Fixed forward declaration of ttbreakc().
198649757Smarc Improved readability of xxshow output.
198749757Smarc Removed "super" pad code.
198849757Smarc Modified ps_state to be a real state variable.
198949757Smarc 03-Aug-1989: Paul Traina
199049757Smarc Reversed earlier change to xxselect which didn't pass major #.
199149757Smarc Modified xxshow output to not use %nd which isn't supported in BSD.
199249757Smarc 28-Aug-1989: Paul Traina
199349757Smarc Changed parameters of make_x25_call -- plug user data field directly.
199449757Smarc 14-Nov-1989: Paul Traina
199549757Smarc Added support for Ultrix 3.1 which uses HUPCL instead of HUPCLS
199649757Smarc because of that stupid termio interface (sigh).
199749757Smarc 16-Nov-1989: Paul Traina
199849757Smarc Changed parity mask to input_parity_mask, added output_parity_mask.
199949757Smarc */
2000