1
0
Files
2022-09-29 17:59:04 +03:00

322 lines
10 KiB
C

/* TCP over FDDI SMT/CMT definitions
*
*
* Copyright 1989 Silicon Graphics, Inc. All rights reserved.
*/
#ident "$Revision: 1.1 $"
#pragma once
#define MSEC_PER_HZ (1000/HZ)
#define USEC_PER_HZ (1000000/HZ)
#define SMT_USEC2HZ(val) (((val)+USEC_PER_HZ-1)/USEC_PER_HZ)
#define SMT_MSEC2HZ(val) (((val)+MSEC_PER_HZ-1)/MSEC_PER_HZ)
#define TPC_RESET(smt) ((smt)->smt_ops->reset_tpc((smt), (smt)->smt_pdata))
#define SMT_USEC_TIMER(smt,val) smt_timeout(smt,SMT_USEC2HZ(val))
#define SMT_MSEC_TIMER(smt,val) smt_timeout(smt,SMT_MSEC2HZ(val))
#define PCM_BIT(n) (1<<(n))
#define PCM_R_BIT(smt,n) (0 != ((smt)->smt_st.r_val & PCM_BIT(n)))
/* driver facilities used by CMT
*/
struct smt_ops {
void (*reset_tpc)(); /* reset TPC timer */
time_t (*get_tpc)(); /* get value of TPC timer */
void (*off)(); /* everything off */
void (*setls)(); /* set PHY state */
void (*lct_on)(); /* start LCT */
int (*lct_off)(); /* stop LCT and return result */
void (*join)(); /* join the ring */
struct smt*(*trace)(); /* propagate trace */
int (*st_get)(); /* get current counter values */
int (*conf_set)(); /* set new configuration */
void (*alarm)(); /* awaken deamon */
void (*d_bec)(); /* start directed beacon */
};
enum rt_ls {
R_PCM_QLS=0, R_PCM_ILS=1, R_PCM_MLS=2, R_PCM_HLS=3,
R_PCM_ALS=4, R_PCM_ULS, R_PCM_NLS, R_PCM_LSU,
T_PCM_QLS=16, T_PCM_ILS, T_PCM_MLS, T_PCM_HLS,
T_PCM_ALS, T_PCM_ULS, T_PCM_NLS, T_PCM_LSU,
T_PCM_REP, /* repeat as a cheap bypass */
T_PCM_SIG, /* CMT signalling */
T_PCM_THRU, /* THRU_{A,B} */
T_PCM_WRAP, /* WRAP_ {A,B} */
T_PCM_WRAP_AB, /* WRAP_AB */
T_PCM_LCT, /* doing LCT */
T_PCM_LCTOFF, /* turn off LCT */
T_PCM_BREAK /* seem to have entered BREAK */
};
#define SMT_LOG_LEN 128 /* should be a power of 2 */
#define SMT_LSLOG(smt,tr,newls) { \
int lptr = (smt)->smt_st.log_ptr; \
(smt)->smt_st.log[lptr].ls = ((newls)|(tr)*16); \
(smt)->smt_st.log[lptr].lbolt = lbolt; \
(smt)->smt_st.log_ptr = (lptr + 1) % SMT_LOG_LEN; \
}
/* configuration values for the kernel and the deamon parts of SMT
*/
struct smt_conf {
SMT_MANUF_DATA mnfdat;
fdditimer2c t_max; /* FDDI timers */
fdditimer2c t_min;
fdditimer2c t_req;
fdditimer2c tvx;
uint ler_cut; /* cut off link if LER exceeds this */
enum fddi_st_type type; /* our type */
enum fddi_pc_type pc_type;
u_char debug; /* debugging level */
u_char ip_pri; /* LLC "priority" for IP frames */
enum pcm_tgt pcm_tgt;
};
/* Counters should have enough bits so that they will not "wrap" in less than
* one month or about 10**7 seconds. This means that at least some
* counters, such as the count of total frames seen, should have
* more than 32 significant bits. The FDDI SMT standard does not
* require counters to have more than 32 bits. However, by additional
* significant bits here, we can make it possible to allow more useful
* counters in the future.
*/
struct smt_lcntr { /* the shape of kernel SMT counters */
unsigned long hi;
unsigned long lo;
};
/* State, statistics and history */
struct smt_st {
LFDDI_ADDR addr; /* station address--FDDI order */
fdditimer2c t_neg; /* negoticated token rotation time */
enum mac_states mac_state; /* recent MAC state */
enum fddi_pc_type npc_type; /* neighbor type */
enum pcm_state pcm_state;
enum rt_ls tls; /* currently transmitted line state */
enum pcm_ls rls; /* recently received line state */
unsigned long t_next; /* signalling delay */
unsigned long flags;
unsigned long alarm;
uint n; /* CMT bit number, "n" */
unsigned long r_val;
unsigned long t_val;
uint ler; /* long term LER */
uint ler2; /* recent, short term LER */
unsigned long lct_fail; /* current LCT failures */
unsigned long lct_tot_fail; /* total LCT failures */
unsigned long connects; /* times thru BREAK without joining */
int log_ptr;
struct smt_log { /* log of line states */
unsigned ls:5;
unsigned lbolt:27;
} log[SMT_LOG_LEN];
/* many of these substantially under-count their events
*/
struct smt_lcntr rngop; /* ring went non-RingOP to RingOP */
struct smt_lcntr rngbroke; /* ring went RingOP to non-RingOP */
struct smt_lcntr multda; /* frames with my DA & A set */
struct smt_lcntr misfrm; /* missed frame */
struct smt_lcntr xmtabt; /* line state change during xmit */
struct smt_lcntr tkerr; /* token received & MAC in T2 or T3 */
struct smt_lcntr clm; /* entered MAC T4 */
struct smt_lcntr bec; /* entered MAC T5 */
struct smt_lcntr tvxexp; /* TVX expired */
struct smt_lcntr trtexp; /* TRT expired and late count != 0 */
struct smt_lcntr tkiss; /* tokens issued */
struct smt_lcntr myclm; /* my CLAIM frames received */
struct smt_lcntr loclm; /* lower CLAIM frames received */
struct smt_lcntr hiclm; /* higher CLAIM frames received */
struct smt_lcntr mybec; /* my beacon frames received */
struct smt_lcntr otrbec; /* other beacon frames */
struct smt_lcntr dup_mac; /* forged MAC frames with our DA */
struct smt_lcntr frame_ct; /* total frames seen */
struct smt_lcntr tok_ct; /* token count */
struct smt_lcntr err_ct; /* bad CRC or len; E-bit set here */
struct smt_lcntr lost_ct; /* FORMAC lost pulses */
/* Errors in frames for us */
struct smt_lcntr flsh; /* flushed frames */
struct smt_lcntr abort; /* aborted frames */
struct smt_lcntr miss; /* gap too small */
struct smt_lcntr error; /* bad CRC or length */
struct smt_lcntr e; /* received E bit */
struct smt_lcntr a; /* received A bit */
struct smt_lcntr c; /* received C bit */
struct smt_lcntr tot_junk; /* discarded frames */
struct smt_lcntr junk_void; /* discarded void frames */
struct smt_lcntr junk_bec; /* discarded beacon frames */
struct smt_lcntr shorterr; /* packet unreasonably short */
struct smt_lcntr longerr; /* packet unreasonably long */
struct smt_lcntr rx_ovf; /* receive FIFO overrun */
struct smt_lcntr buf_ovf; /* out of receive buffers */
struct smt_lcntr tx_under; /* transmit FIFO underrun */
struct smt_lcntr eovf; /* elasticity buffer overflow */
struct smt_lcntr noise; /* bad line state for a while */
struct smt_lcntr spare_cntr[7]; /* for future expansion */
unsigned long ring_latency; /* ring latency in byte clocks */
unsigned long lem_count; /* total LEM errors seen */
};
/* official flag bits found in smt_st.flags */
#define PCM_BS_FLAG 0x00000001 /* BS_Flag */
#define PCM_LS_FLAG 0x00000002 /* LS_Flag */
#define PCM_TC_FLAG 0x00000004 /* TC_Flag */
#define PCM_TD_FLAG 0x00000008 /* TD_Flag */
#define PCM_RC_FLAG 0x00000010 /* RC_Flag */
#define PCM_CF_JOIN 0x00000020 /* CF_Join */
#define PCM_WITHHOLD 0x00000040 /* do not attach */
#define PCM_THRU_FLAG 0x00000080 /* THRU */
#define PCM_PC_DISABLE 0x00000100 /* stay in PC_MAINT */
#define PCM_WA_FLAG 0x00000200 /* withhold A port connection */
#define PCM_WAT_FLAG 0x00000400 /* withhold A port connection to M */
#define PCM_LEM_FAIL 0x80000000 /* recently suffered LER_Cutoff */
/* less official */
#define PCM_NE 0x40000000 /* TNE>NS_Max happened */
#define PCM_TIMER 0x20000000 /* have a callout waiting */
#define PCM_RNGOP 0x10000000 /* ring is operational */
#define PCM_HAVE_BYPASS 0x08000000 /* have a bypass switch */
#define PCM_CON_U 0x04000000 /* undesirable connection */
#define PCM_CON_X 0x02000000 /* M to M connection */
/* #define unused 0x01000000 */
#define PCM_DEBUG 0x00800000 /* turn on printf()s */
#define PCM_TRACE_REQ 0x00400000 /* have received a TRACE request */
#define PCM_TRACE_OTR 0x00200000 /* propagating TRACE from other PCM */
#define PCM_DRAG 0x00100000 /* dragging our heels in BREAK */
/* do not reset these */
#define PCM_SAVE_FLAGS (PCM_WA_FLAG | PCM_WAT_FLAG | PCM_LEM_FAIL \
| PCM_DEBUG | PCM_HAVE_BYPASS)
#define PCM_SET(smt,b) (0 != ((smt)->smt_st.flags & (b)))
/* synthetic PC_Mode bit, since we never have M ports ourself */
#define PC_MODE_P(smt) ((smt)->smt_st.npc_type != PC_M)
#define PC_MODE_T(smt) ((smt)->smt_st.npc_type == PC_M)
/* alarm bits to awaken demon */
#define SMT_ALARM_RNGOP 0x00000001 /* ring died or recovered */
#define SMT_ALARM_LEM 0x00000002 /* many link errors seen */
#define SMT_ALARM_BS 0x00000004 /* stuck in BREAK */
#define SMT_ALARM_CON_X 0x00000008 /* illegal connection topology */
#define SMT_ALARM_CON_U 0x00000010 /* undesirable connection topology */
#define SMT_ALARM_CON_W 0x00000020 /* connection withheld */
#define SMT_ALARM_TFIN 0x00000040 /* PC-Trace finished */
#define SMT_ALARM_TBEG 0x00000080 /* PC-Trace started by neighbor */
#define SMT_ALARM_SICK 0x00000100 /* the hardware is sick */
/* lenght of mbuf used to awaken smt deamon */
#define SMT_LEN_ALARM (sizeof(FDDIBUFLLC)+4)
/* pointer to user buffers for counters or configuration
*/
typedef struct smt_sioc {
int phy; /* for configuration and state */
union {
struct smt_conf *conf;
struct smt_st *st;
unsigned long alarm;
enum pcm_ls ls; /* MAINT line state or ALS */
u_char *d_bec; /* directed beacon INFO field */
} smt_ptr_u;
uint len;
} SMT_SIOC;
#define SIOC_SMTGET_CONF _IOW('S', 1, SMT_SIOC)
#define SIOC_SMTSET_CONF _IOW('S', 2, SMT_SIOC)
#define SIOC_SMTGET_ST _IOW('S', 3, SMT_SIOC)
#define SIOC_SMT_TRACE _IOW('S', 4, SMT_SIOC) /* force PC-Trace */
#define SIOC_SMT_ARM _IOWR('S',5, SMT_SIOC) /* arm SMT notification */
#define SIOC_SMT_MAINT _IOW('S', 6, SMT_SIOC) /* send a line state */
#define SIOC_SMT_LEM_FAIL _IOW('S', 7, SMT_SIOC) /* reject line for LEM */
#define SIOC_SMT_DIRECT_BEC _IOW('S', 8, SMT_SIOC) /* set special beacon */
/* everything needed by CMT and the kernel portion of SMT
*/
struct smt {
caddr_t smt_pdata; /* board private data */
struct smt_ops *smt_ops;
struct smt_conf smt_conf; /* general configuration values */
struct mbuf *smt_alarm_mbuf; /* drained to awaken deamon */
int smt_ktid; /* current timer-ID for killing */
int smt_tid; /* timer-ID for validating */
struct smt_st smt_st; /* current state */
};
#ifdef _KERNEL
/* SMT/PCM functions called by drivers
*/
extern void smt_off(struct smt *smt);
extern void smt_clear(struct smt *smt);
extern uint smt_ler(struct timeval* lem_time, unsigned long ct);
extern int smt_ioctl(struct ifnet *ifp,
struct smt *smt1, struct smt *smt2,
int, struct smt_sioc* sioc);
extern void smt_pcm(struct smt *smt);
#define SMTDEBUGPRINT(smt,lvl,a) {if ((smt)->smt_conf.debug > (lvl) \
&& PCM_SET(smt,PCM_DEBUG)) printf a;}
#endif /* _KERNEL */