Files
Arquivotheca.AIX-4.1.3/bos/kernel/sys/tty.h
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

678 lines
24 KiB
C

/* @(#)26 1.48.1.1 src/bos/kernel/sys/tty.h, cmdtty, bos411, 9428A410j 2/10/93 11:57:07 */
/*
* COMPONENT_NAME: (sysxtty) System Extension for tty support
*
* FUNCTIONS:
*
* ORIGINS: 3, 9, 27
*
* (C) COPYRIGHT International Business Machines Corp. 1989
* All Rights Reserved
* Licensed Materials - Property of IBM
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#ifndef _H_TTY
#define _H_TTY
#include <sys/cblock.h>
#include <sys/ioctl.h>
#include <sys/lock_def.h>
enum csize { /* bits per character */
bits5, bits6, bits7, bits8};
enum parity { /* parity */
nopar, oddpar, markpar, evenpar, spacepar};
enum stopbits { /* stop bits */
stop1, stop2};
enum status {
good_char, overrun, parity_error, framing_error, break_interrupt,
cts_on, cts_off, dsr_on, dsr_off, ri_on, ri_off, cd_on, cd_off,
cblock_buf, other_buf};
typedef unsigned int baud_t;
typedef int csize_t;
typedef int parity_t;
typedef int stop_t;
#define TTY_BAUD_ERROR_LIMIT 2 /* 2% slop permitted in baud rates */
struct ccblock {
void *c_vptr; /* pointer untouched by hardware */
char *c_ptr; /* buf address used by hardware */
ushort c_count; /* char count altered by hardware */
ushort c_size; /* buffer size used by discipline */
};
/* ttydd init structure */
struct ttyddinit {
mid_t kmid; /* mid_t for ttydd */
dev_t devno; /* device number for device */
chan_t chan; /* channel number for device */
char linedisp[64]; /* name of line discipline to use */
char opendisp[64]; /* name of open discipline to use */
char mapdisp[64]; /* name of mapping discipline to use */
char flowdisp[10][64]; /* name of flow disciplines to use */
int flowdispcnt; /* nuber of control disciplines */
};
/* Discipline structure, etc */
/* The following determine how the disciplines will stack */
enum disp_type {
hard_disp = 0, /* hardware is first */
open_disp = 50, /* open discipline */
flow_disp = 100, /* xon/xoff or rts/ctr */
map_disp = 150, /* NLS/kanji */
line_disp = 255 /* line disp should be last */
};
/* service commands */
enum service_commands {
TS_PROC, /* old proc commands */
TS_SCONTROL, /* set control lines */
TS_GCONTROL, /* get control lines */
TS_GSTATUS, /* get status lines */
TS_SBAUD, /* set baud rate (in and out) */
TS_GBAUD, /* get output baud rate */
TS_SIBAUD, /* set input baud rate */
TS_GIBAUD, /* get input baud rate */
TS_SBPC, /* set bits per character */
TS_GBPC, /* get bits per character */
TS_SPARITY, /* set parity */
TS_GPARITY, /* get parity */
TS_SSTOPS, /* set stop bits */
TS_GSTOPS, /* get stop bits */
TS_SBREAK, /* start break condition */
TS_CBREAK, /* clear break condition */
TS_OPEN, /* local/remote style on next open */
TS_DOPACE, /* do pacing */
TS_SOFTPACE, /* software pacing */
TS_SOFTRCHAR, /* define software pacing chars */
TS_SOFTLCHAR, /* define software pacing chars */
TS_SOFTRSTR, /* define software pacing strings */
TS_SOFTLSTR, /* define software pacing strings */
TS_HARDRBITS, /* define hardware pacing bits */
TS_HARDLBITS, /* define hardware pacing bits */
TS_LOOP, /* enter/exit loop mode */
TS_NEGOTIATE /* negotiate who does what */
};
/* proc commands */
enum proc_commands {
T_OUTPUT, /* start output flowing */
T_SUSPEND, /* suspend output */
T_RESUME, /* resume output */
T_BLOCK, /* block input */
T_UNBLOCK, /* unblock input */
T_RFLUSH, /* flush read buffers */
T_WFLUSH /* flush write buffers */
};
/* Bits defines for TS_SCONTROL, TS_GCONTROL, and TS_GSTATUS */
#define TSDTR 0x01
#define TSRTS 0x02
#define TSCTS 0x04
#define TSDSR 0x08
#define TSRI 0x10
#define TSCD 0x20
/*
* TS_DOPACE is sent to the hardware with the particular type of
* pacing being requested. If the hardware can perform the function,
* the request should return with 0. After this point, all pacing
* commands will be sent on to the service routine.
*/
enum ts_dopace { /* used with TS_DOPACE */
DOPACE_AGAIN, /* renegotiate the pacing */
DOPACE_XON, /* do xon/xoff flow control */
DOPACE_STR, /* string style flow control */
DOPACE_DTR, /* do dtr flow control */
DOPACE_RTS /* do rts flow control */
};
/*
* The service requests for softpace are sent down from the line
* discipline. An application will frequently require all 256
* possible characters be sent up to it in which case the line
* discipline will send down a SOFTPACE_OFF command. In the case
* where the application does not care, then the line discipline will
* send down a SOFTPACE_ANY, ON, or STR depending upon the startup
* conditions. The design currently permits multi character sequences
* for software pacing by using the STR option. The other two use
* only single chars to improve throughput. ANY permits any character
* for the remote start character. Hardware pacing should ignore
* these commands.
*/
enum ts_softpace { /* in line software pacing */
SOFTPACE_ROFF, /* permit all data to pass through */
SOFTPACE_RANY, /* xon/xoff with any char for resume */
SOFTPACE_RON, /* xon/xoff */
SOFTPACE_RSTR, /* string based flow control */
SOFTPACE_LOFF, /* local pacing off */
SOFTPACE_LON, /* local pacing on (char) */
SOFTPACE_LSTR /* local pacing string */
};
/* Used with TS_OPEN to control how the next open will work */
enum ts_open {
OPEN_LOCAL, /* do not wait for carrier */
OPEN_REMOTE /* wait for carrier detect */
};
/*
* TS_SOFTRCHAR and TS_SOFTLCHAR arg is a pointer to an array of 2
* chars. The first is the stop character and the second is the start
* character. The local chars are sent out to do local pacing. The
* input is scanned for the remote chars to do remote pacing. (Local
* pacing is pacing generated locally to control the input from the
* other host. Remote pacing is generated on the other host to
* control the output to it. Usually a person sitting at a terminal
* wants remote pacing but not local pacing. When the first
* DOPACE_XON request is sent down (upon the very first open), ^Q/^S
* is assumed.
*/
/* TS_SOFTRSTR and TS_SOFTLSTR arg is a uio strcture with 2 iovec's.
* The first is for block (or suspend) while the second is for unblock
* (or resume). The local strings are sent out by the host if
* everything else is enabled. The remote strings are matched up.
* During a multi-byte remote search, there is no timeout implemented
* (on purpose). Currently this is not implemented.
*/
/*
* The arg for TS_HARDRBITS and TS_HARDLBITS is a pointer to an array
* of 4 chars. Each char contains a set of TSxxx bits and are grouped
* in pairs. The characters for TS_HARDLBITS is defined as follows.
* The first pair is for block (or stop) while the second pair is for
* unblock (or start). The first character in the group is an OR
* mask, the second char is an AND mask. When the host wants to block
* the other side (as an example) it will set the modem status lines
* to their ((current settings|OR)&AND). The same is true with
* unblock. Usually only one bit is set but multiple bits are
* allowed.
*
* The characters for TS_HARDRBITS are defined as follows. The first
* pair used for suspend (or stop) and the second pair used for resume
* (or start). The first char of each pair is the set of bits which
* must be SET and the second char is the one's complement of the set
* of bits which must be CLEAR for the output to be suspended or
* resumed. Thus to suspend output, the condition (((current settings
* & SET) == SET) && ((current settings | CLEAR) == CLEAR)) must be
* true. This condition is tested only when a modem status change
* occurs. This is currently used only by the hardware pacing
* discipline.
*/
/* Used with TS_LOOP command */
enum ts_loop {
LOOP_ENTER, /* Enter Loop mode */
LOOP_EXIT /* Exit Loop mode */
};
/*
* TS_NEGOTIATE uses the following structure. The n_oflag, n_iflag,
* and n_lflag are from are from the termios c_oflag, c_iflag, and
* c_lflag. The c_cflag is passed around and IXON, IXOFF, and IXANY
* are stripped out of the n_iflag since all of those attributes are
* negotiated using other service calls. The n_cc array matches the
* c_cc array of the termios structure but VSTART and VSTOP should be
* ignored. Note a very important catch is that these bits are
* defined by the SVID 5.4 spec and not by Posix. The 5.4 spec is a
* super set of Posix.
*
* The n_xflag is for bits not in 5.4. The current implementation has
* only IMAP and OMAP which are set when the nls mapping discipline
* are pushed onto the stack. The IMAP means that input mapping as
* well as the associated ioctls must be done and OMAP means that
* output mapping must be done.
*
* The process will start from the current line discipline and a
* TS_NEGOTIATE will be passed down. As the request is passed down
* other disciplines may add bits into the structure. The hardware
* will then have first change to assume any of the responsibilities
* that it wants to. It will do this by turning off the appropriate
* bits in the structure. As the service call returns back up the
* stack, the higher level disciplines can assume responsibilities in
* the same fashion by stripping out bits. They must also check to
* see if someone else below them assumed the responsibilities of what
* they were asking for.
*
* A discipline must start the negotiation by calling the top level
* service routine in their open and close routines if they perform
* any of the duties represented in the negotiate structure.
*
* N_VERS_NUM will change whenever the structure changes but it will
* always be in the same place in the xflag which will always be the
* first field in the structure. N_VERS_NUM will not change if new
* bits are added to the xflag. So if a discipline discovers an
* unknown version or an unknown bit in the xflag, it should not
* assume any responsibilities.
*
* Note that for those disciplines that want to use this structure and
* service, termios.h must be included before tty.h. Otherwise the
* negotiate structure is not defined.
*
* This service is called at INT_TTY since it all need to sync up
* atomicly. The line discipline ignores the argument.
*/
#ifdef NCCS
struct negotiate {
tcflag_t n_xflag;
tcflag_t n_iflag;
tcflag_t n_oflag;
tcflag_t n_lflag;
cc_t *n_cc;
};
/* Current version of negotiate structure */
#define N_VERS_NUM 1
/* bits for the n_xflag */
#define N_VERS 0x000000FF /* what vers. of negotiate struct */
#define N_IMAP 0x00000100 /* do input nls mapping */
#define N_OMAP 0x00000200 /* do output nls mapping */
#define N_KNOWN (N_VERS|N_IMAP|N_OMAP)
#endif
enum alloc_commands {
alloc_push, /* discipline being pushed in */
alloc_pop, /* discipline being popped out */
alloc_unconfig /* tty is being unconfigured */
};
typedef struct ctlpath ctlpath_t;
typedef struct disp disp_t;
typedef struct dispx dispx_t;
typedef struct line_disp ldisp_t;
typedef struct tty *ttyp_t;
struct ctlpath {
ctlpath_t *ctl_next, *ctl_prev; /* doubly linked list */
ttyp_t ctl_tp; /* back to tty structure */
disp_t *ctl_disp; /* original pacing structure */
int (*ctl_input)(ttyp_t tp, /* receive interrupt routine */
ctlpath_t *ctl, /* pointer to ctlpath record */
char c, /* character received */
enum status s); /* status of character */
ctlpath_t *ctl_ipath; /* next on input path */
int (*ctl_output)(ttyp_t tp, /* output routine */
ctlpath_t *ctl); /* pointer to ctlpath record */
ctlpath_t *ctl_opath; /* next on output path */
int (*ctl_service)(ttyp_t tp, /* service entry */
ctlpath_t *ctl, /* pointer to ctlpath record */
enum service_commands cmd,
void *arg);
ctlpath_t *ctl_spath; /* next on service path */
};
struct disp {
disp_t *ds_next; /* local/remote pacing lists */
char *ds_name; /* pacing name */
int (*ds_init)(int cmd, /* command */
struct uio *uio); /* data */
int (*ds_alloc)(ttyp_t tp, /* allocate routine */
ctlpath_t **ctlp, /* pointer to ctl pointer */
enum alloc_commands cmd); /* what to do */
int (*ds_open)(ttyp_t tp, /* open routine */
ctlpath_t *ctl, /* ctlpath ptr */
int mode, /* FREAD, etc */
int ext); /* openx parameter */
int (*ds_close)(ttyp_t tp, /* close routine */
ctlpath_t *ctl, /* ctlpath ptr */
int ext); /* closex parameter */
int (*ds_ioctl)(ttyp_t tp, /* ioctl routine */
ctlpath_t *ctl, /* pointer to ctlpath record */
int cmd, /* second arg to ioctl sys call */
void *arg, /* third arg to ioctl sys call */
int mode, /* open mode FREAD, etc */
int ext); /* ioctlx parameter */
int (*ds_print)(ttyp_t tp, /* print routine */
ctlpath_t *ctl, /* ctl pointer */
int v); /* verbose flag */
uchar ds_type; /* type of discipline */
mid_t ds_kmid;
};
struct dispx {
int dsx_npush; /* system wide push count */
lock_t dsx_lock; /* lock to protect dsx_npush */
int (*dsx_alloc)(ttyp_t tp, /* allocate routine */
ctlpath_t **ctlp, /* pointer to ctl pointer */
enum alloc_commands cmd); /* what to do */
void (*dsx_pin)(); /* argument to (un)pincode */
};
struct line_disp {
disp_t ld_disp;
int (*ld_read)(ttyp_t tp, /* read routine */
ctlpath_t *ctl, /* ctl pointer */
struct uio *uio, /* uio struct */
int ext); /* readx parameter */
int (*ld_write)(ttyp_t tp, /* write routine */
ctlpath_t *ctl, /* ctl pointer */
struct uio *uio, /* uio struct */
int ext); /* writex parameter */
int (*ld_select)(ttyp_t tp, /* select routine */
ctlpath_t *ctl, /* ctl pointer */
short events, /* events to select for */
short *revents); /* ptr to events selected for */
int (*ld_revoke)(ttyp_t tp, /* revoke routine */
ctlpath_t *ctl, /* ctl pointer */
int flag); /* 0 if frevoke, 1 if revoke */
};
struct tty {
char t_name[16]; /* resource name for this tty */
dev_t t_dev; /* major/minor number */
chan_t t_channel; /* channel number */
pid_t t_sid; /* controlling process, session id */
pid_t t_pgrp; /* foreground process group id */
pid_t t_tsm; /* terminal state manager's id */
int t_id; /* tty id */
struct winsize t_winsize; /* window struct */
struct ccblock t_rbuf; /* used only for compatability */
struct ccblock t_tbuf; /* transmit buffer */
struct clist t_rawq; /* Raw queue */
struct clist t_canq; /* canonical queue */
struct clist t_outq; /* output queue */
signed char *t_cmap; /* character mapping tables */
ctlpath_t *t_ctl; /* control path stack */
ctlpath_t *t_lctl; /* control path for line discipline */
void *t_hptr; /* hardware storage */
/* other things */
int t_ihog; /* input hog limit for this tty */
int t_ohog; /* output hog limit for this tty */
int t_event; /* event list for e_sleep */
int t_lock; /* lock per tty */
int t_ccnt; /* closing count */
/* Bits and things */
baud_t t_ospeed; /* output speed */
baud_t t_ispeed; /* input speed */
/* non-disabled flags */
stop_t t_stopbits : 2; /* number of stop bits */
parity_t t_parity : 3; /* parity style */
csize_t t_csize : 2; /* character size */
/* hardware state flags */
uint t_carrier : 1; /* carrier flag */
uint t_wopen : 1; /* waiting for open */
uint t_isopen : 1; /* tty is open */
uint t_iclose : 1; /* tty is closing */
uint t_trust : 1; /* trusted path */
uint t_cons : 1; /* console redirection active */
uint t_stack : 1; /* stack change pending */
uint t_wstack : 1; /* entry point waiting stack change */
ushort unused0; /* filler */
/* disabled INT_TTY flags */
uint t_busy : 1; /* output in progress */
uint t_stop : 1; /* output is stopped, remote pacing */
uint t_block : 1; /* input is stopped, local pacing */
uint t_ctlx : 1; /* got a control X */
uint t_sak : 1; /* sak is enabled */
uint t_kep : 1; /* kep test */
uint t_async : 1; /* FASYNC mode */
uint t_nbio : 1; /* FNDELAY mode */
/* always sleep on t_event now. */
uint t_iaslp : 1; /* asleep for input */
uint t_oaslp : 1; /* asleep for output, process pacing */
uint t_iow : 1; /* waiting for flush */
};
/*
* The t_cmap pointer actually points to a csmap structure which
* contains a width array and a length array. See TCLEN & TCWIDTH below.
*/
struct csmap {
char csmap_length[256];
char csmap_width[256];
};
/*
* TCLEN is the length in bytes of the character with "c" as its first
* byte
*/
#define TCLEN(tp, c) ((tp)->t_cmap[(unsigned int)(c)])
/*
* TCWIDTH is the display width in columns of the character with "c"
* as its first byte
*/
#define TCWIDTH(tp, c) ((tp)->t_cmap[(unsigned int)(c)+256])
/*
* Files used to build code set maps are kept in the following directory.
*/
#define CSMAP_DIR "/usr/lib/nls/csmap/"
/*
* To get work done initiated by a timeout to be done at INT_TTY, the
* func in the trb is set to ttyofflevel and func_data should point to
* a struct tty_timer. The tttmr_func should point to the function
* which needs to get called at offlevel time, tttmr_data is the
* parameter passed to it (probably the control stack structure for
* the discipline). (ipri in the trb should be INT_TTY -- although
* that does little good.
*/
struct tty_timer {
struct tty_timer *tttmr_next; /* used by ttyofflevel */
struct trb *tttmr_trb; /* trb pointer */
void (*tttmr_func)(); /* offlevel functin to call */
void *tttmr_data;
};
/* These two must track each other */
/* interrupt priority for tty's from offlevel up */
#define INT_TTY INTOFFL0
/* Initialize a intr struct for a tty offlevel */
#define INIT_TTY_OFFL(a, b, c) INIT_OFFL0(a, b, c)
/* hi and low water marks for flow control */
#define TTLOWAT(tp) (tp->t_ihog >> 2)
#define TTHIWAT(tp) (tp->t_ihog - (tp->t_ihog >> 2))
/* hi and low water marks for controling output data from process */
#define TTLOPWAT(tp) ((tp->t_ospeed / 100) + 30)
#define TTHIPWAT(tp) ((tp->t_ospeed / 20) + 100)
/* Simple macro for sleeps in all the tty code */
#define TTY_SLEEP(tp) \
(e_sleepl(&tp->t_lock, &tp->t_event, EVENT_SIGRET) == EVENT_SIG)
#define TTY_WAKE(tp) e_wakeup(&tp->t_event)
#define ttyread(tp, uio, ext) \
(((tp)->t_lctl) ? \
(*((ldisp_t *)(tp)->t_lctl->ctl_disp)->ld_read) \
((tp), (tp)->t_lctl, (uio), (ext)) : \
0)
#define ttywrite(tp, uio, ext) \
(((tp)->t_lctl) ? \
(*((ldisp_t *)(tp)->t_lctl->ctl_disp)->ld_write) \
((tp), (tp)->t_lctl, (uio), (ext)) : \
0)
#define ttyselect(tp, evt, revt) \
(((tp)->t_lctl) ? \
(*((ldisp_t *)(tp)->t_lctl->ctl_disp)->ld_select) \
((tp), (tp)->t_lctl, (evt), (revt)) : \
0)
#define ttyrevoke(tp, flag) \
(((tp)->t_lctl) ? \
(*((ldisp_t *)(tp)->t_lctl->ctl_disp)->ld_revoke) \
((tp), (tp)->t_lctl, (flag)) : \
0)
#define ttyinput(tp, ctl, c, s) \
((*(ctl)->ctl_ipath->ctl_input)((tp), (ctl)->ctl_ipath, (c), (s)))
#define ttyoutput(tp, ctl) \
((*(ctl)->ctl_opath->ctl_output)((tp), (ctl)->ctl_opath))
#define ttyservice(tp, ctl, cmd, arg) \
((*(ctl)->ctl_spath->ctl_service)((tp), (ctl)->ctl_spath, (cmd), \
(void *)(arg)))
/*
* True when the input path past the current discipline is fed to tty
* null
*/
#define tty_noinput(ctl) ((ctl)->ctl_ipath->ctl_input == (void *)ttynull)
/* True when the current path is the last close of the tty */
#define tty_lclose(tp) ((tp)->t_ccnt == 1 && (tp)->t_iclose)
/* Definitions of common tty variables */
extern disp_t *disp_list;
/* Definitions of common tty routines */
extern int ttyioctl(ttyp_t tp, int cmd, void *arg, int mode, int ext);
extern int ttyinit(ttyp_t tp, disp_t *disp);
extern int ttyfree(ttyp_t tp);
extern int ttyalloc(ttyp_t tp, ctlpath_t **cinp,
enum alloc_commands cmd, dispx_t *d);
extern int ttyopen(ttyp_t tp, int mode, int ext);
extern int ttyclose(ttyp_t tp, int ext);
extern int ttynull();
extern int ttysak(ttyp_t tp);
extern int ttrevoke(ttyp_t tp, ctlpath_t *ctl, int flag);
extern int ttcwait(ttyp_t tp);
extern int ttypath(ctlpath_t *ctl, int which, int (*f)());
extern int stack_ctl(ttyp_t tp, disp_t *disp, int mode, int ext);
extern int unstack_ctl(ttyp_t tp, ctlpath_t *ctl, int mode, int ext);
extern ctlpath_t *getctlbytype(ttyp_t tp, enum disp_type type);
extern ctlpath_t *getctlbyname(ttyp_t tp, char *name);
extern disp_t *getdispbyname(char *name);
extern disp_t *getdispbytype(enum disp_type type);
extern int disp_add(disp_t *d);
extern int disp_del(disp_t *d);
extern void dbg_clist(char *s, struct clist *cl);
extern void ttyofflevel(struct trb *trb);
extern ttyp_t ttydev2tp(dev_t devno, chan_t channel);
#define _TTYHKID(w) ((TTY_TRCID)|w)
enum tty_trctypes {
TTY_CONFIG, TTY_ALLOC, TTY_OPEN, TTY_CLOSE, TTY_READ, TTY_WRITE,
TTY_IOCTL, TTY_SELECT, TTY_REVOKE, TTY_MPX, TTY_INPUT, TTY_OUTPUT,
TTY_SERVICE, TTY_PROC, TTY_SLIH, TTY_OFF, TTY_LAST };
#ifdef _KERNEL
/*
* Allocate and realease pinned memory.
*/
#define pinmalloc(x) xmalloc((x), 3, pinned_heap)
#define pinfree(x) xmfree((x), pinned_heap)
/*
* General entry/exit trace hooks -- probably don't want to use this
* for the ioctl entries.
* The names of the variables used by Enter/Return/Exit are different than
* the names used in Enterv/Returnv/Exitv to prevent uses of the wrong
* macros.
*/
#define Enter(type, w, dev, chan, a, b, c) \
type Func; \
dev_t Dev; \
chan_t Chan; \
int Flag1; \
int Flag2; \
int Line; \
int Which = !TRC_ISON(0) ? (Flag1 = Flag2 = 0) : \
((Dev = dev), \
(Chan = chan), \
(Flag1 = TTY_TRCMK[0]&(1<<w)), \
(Flag2 = TTY_TRCMK[1]&(1<<w)), \
(Flag1 && (TRCHKGT(_TTYHKID(w), Dev, Chan, a, b, c), 0)), w)
#define Enterv(w, dev, chan, a, b, c) \
dev_t Dev; \
chan_t Chan; \
int Flag1; \
int Line; \
int Which = !TRC_ISON(0) ? (Flag1 = 0) : \
((Dev = dev), \
(Chan = chan), \
(Flag1 = TTY_TRCMK[0]&(1<<w)), \
(Flag1 && (TRCHKGT(_TTYHKID(w), Dev, Chan, a, b, c), 0)), w)
#define Return(val) { \
Func = (val); \
Line = __LINE__; \
goto ExitLabel; \
}
#define Returnv { \
Line = __LINE__; \
goto vExitLabel; \
}
#define Exit() { \
ExitLabel: \
if (Flag1 || (Flag2 && Func)) \
TRCHKGT(_TTYHKID((Which|0x80)), Dev, Chan, Func, Line, 0); \
return Func; \
}
#define Exitv() { \
vExitLabel: \
if (Flag1) \
TRCHKGT(_TTYHKID((Which|0x80)), Dev, Chan, 0, Line, 0); \
return; \
}
#define Data(xxx, a, b, c) \
(Flag1 ? TRCHKGT(_TTYHKID((Which|0x40)), Dev, Chan, a, b, c), 0 : 0)
#define ttputc(ch, p) \
((!((p)->c_cl) || (CLSIZE == (p)->c_cl->c_last)) ? \
putc(ch, p) : \
((p)->c_cl->c_data[(p)->c_cl->c_last++] = ch, \
(p)->c_cc++, \
0) \
)
#define ttgetc(p) \
((p)->c_cc > 0 ? \
((p)->c_cf->c_first + 1 == (p)->c_cf->c_last ? \
getc(p) : \
((p)->c_cc--, (p)->c_cf->c_data[(p)->c_cf->c_first++])) \
: -1)
#define ttgetcb(bp, p) \
{ \
if (bp = (p)->c_cf) { \
(p)->c_cc -= bp->c_last - bp->c_first; \
if (!((p)->c_cf = bp->c_next)) \
(p)->c_cl = 0; \
bp->c_next = 0; \
} \
}
#define ttputcb(bp, p) \
{ \
if (!(p)->c_cl) \
(p)->c_cf = bp; \
else \
(p)->c_cl->c_next = bp; \
p->c_cl = bp; \
bp->c_next = 0; \
p->c_cc += bp->c_last - bp->c_first; \
}
#endif _KERNEL
#endif /* _H_TTY */