📄 lat_hic.c
字号:
*/int lat_pathlen(path)caddr_t path;{ int count; count = 1; while (*path != '\0' && *path != ':') count++, path++; return (count);}/****maserver****//* * For the server, a few 'quick and dirty' kludges need to be fixed: * - add a bit/byte to lat_vc for master indicator, instead of using * lvc_dgsize (<= 60 implied as a master). * - add a master keep_alive byte to lat_vc, instead of using * lvc_dgsize (timer count up to 60 for 30 seconds keep alive interval). * - lvc_rcvact in lat_vc is used as multiple bit filed: * 1000 0000 - outgoing data waiting for master vc * 0100 0000 - master vc in balance mode * 0000 0001 - vc receiver active * - add a byte filed to lat_slot for credit count for master side, instead * of using ls1_attsize. * * The master timer (defined in lat_mtick, set to 80 milliseconds) is * used to check if the tty input queue is empty so credit can be granted * to the remote slave. Without checking for empty tty queue can easily * cause the queue to overflow. * Master mode also ensures no more outgoing message unless ack queue is * empty. Unack sequence number greater than 1 seems to get acknowledgement * handshaking into chaos. See traces. *//****maserver****/int lat_debug = 0;int lat_mtick = 0x08;int lat_msize = 0x0ff;int lat_mflag = 0;#define LAT_MASTIMER 1/* * m v c s t a r t */mvcstart(unit){#ifndef LATMASTER return(0);#else extern int lat_mtimer(); extern struct lat_vc *vcduplicate(); register struct mbuf *m; register struct lat_vc *vcir; struct ecb *ecbp = &(statable[unit]); struct hic_entity *h = &(lat_obj[unit]); struct vc_hdr *hdr; struct vc_start *vst; struct lat_slot *slot; struct slot_hdr *slhdr; struct slot_start *ssl; struct mbuf *page; caddr_t sptr,nptr; char ch; struct ifnet *ifp = ifnet; struct proc *pp = u.u_procp; int i,s; /* * if lat not running, return error */ if (!sclass[1] || (sclass[1]->scl_state != LST_RUNNING)) return(ENOPROTOOPT); /* * if host-initiated connection not defined, return */ if (ecbp->ecb_hostinit != LAT_HIC) return(0); /* * if not defined as master, return */ if (h->status & OBJPORT) return(0); /* * if host master initiated connection not fully defined, return error */ if ((h->status & MHIC) != MHIC) return (EDESTADDRREQ); /* * host_initiated open should be exclusive * unless multiplexing has been added */ if ((ecbp->ecb_inuse & ECB_INUSE) || lata[unit].t_addr) return(EBUSY); /* set up id for signals */ lata[unit].t_pgrp = pp->p_pgrp; s = splnet(); /* see if vc exists */ if (vcir = vcduplicate(h)) goto startslot1; /* get vc block */ if (vcir = newvc()) { bcopy(h->obj_port, vcir->lvc_addr.lat_addr, 6); vcir->lvc_addr.lat_family = AF_LAT; vcir->lvc_ack = 255; vcir->lvc_dgsize = 0; } else goto nobuf; ecbp->ecb_inuse |= ECB_INUSE; while (ifp) { if ((ifp->if_flags & (IFF_BROADCAST|IFF_DYNPROTO|IFF_UP)) == (IFF_BROADCAST|IFF_DYNPROTO|IFF_UP)) { if (m = m_get(M_DONTWAIT, MT_DATA)) { MCLGET(m,page); if (page) { hdr = (struct vc_hdr *)page; vcir->lvc_state = VST_RUNNING; vcir->lvc_if = ifp; sptr = buildvchdr(vcir, (struct vc_hdr *)page, 0, MSG_START, 0); hdr->vhd_mas = 1; bcopy((char *)&startvc, (char *)sptr, sizeof(struct vc_start)); vst = (struct vc_start *)sptr; vst->vst_dgsize = 1518; vst->vst_slots = 0x30; vst->vst_product = 0x102; vst->vst_stimer = 8; vst->vst_kalive = vcir->lvc_kalive = 30; sptr += sizeof(struct vc_start); if (*sptr++ = h->obj_namelen) { nptr = (caddr_t)h->obj_name; while (ch = *nptr++) { if (('a' <= ch) && (ch <= 'z')) ch = ch -'a' + 'A'; *sptr++ = ch; } } if (*sptr++ = hostnamelen) { nptr = hostname; while (ch = *nptr++) { if (('a' <= ch) && (ch <= 'z')) ch = ch -'a' + 'A'; *sptr++ = ch; } } /* Terminate the parameters */ *sptr++ = 0; m->m_len = (int)sptr - (int)page; INC(lco_xmtframes); ENQUEUE(&vcir->lvc_xmtq, m); latsend(vcir); sleep(m, TTIPRI); /* check if timeout */ if (vcir->lvc_remid) goto startslot; break; } m_free(m); ecbp->ecb_inuse &= ~ECB_INUSE; goto nobuf; } else { ecbp->ecb_inuse &= ~ECB_INUSE; goto nobuf; } } ifp = ifp->if_next; } ecbp->ecb_inuse &= ~ECB_INUSE; splx(s); return (ENETUNREACH);nobuf: splx(s); return (ENOBUFS);startslot: vcir->lvc_state = VST_RUNNING;startslot1: /* get a slot table entry */ for (slot = sl, i = 0; i < LAT_MAXSLOTS; slot++, i++) if (slot->lsl_state == SST_FREE) break; /* Initialise the new slot database */ slotsinuse++; vcir->lvc_act++; slot->lsl_vc = vcir; slot->lsl_class = 1; slot->lsl_state = SST_STARTING; slot->lsl_locid = i + 1; slot->lsl_remid = 0; slot->lsl_remcredits = 0; slot->lsl_loccredits = 0; slot->lsl_attsize = 0; slot->lsl_scl = sclass[1]; lata[unit].t_addr = (caddr_t)slot; lata[unit].t_state |= TS_CARR_ON; lata[unit].t_flags &= ~ECHO; slot->lsl_data = (caddr_t) &lata[unit]; slot->lsl_bslot = 0; ttyflush(&lata[i], FREAD|FWRITE); if (m = m_get(M_DONTWAIT, MT_DATA)) { MCLGET(m,page); if (page) { hdr = (struct vc_hdr *)page; sptr = buildvchdr(vcir, (struct vc_hdr *)page, 1, MSG_RUN, 0); hdr->vhd_mas = 1; slhdr = (struct slot_hdr *)sptr; slhdr->shd_dstid = 0; slhdr->shd_srcid = slot->lsl_locid; slhdr->shd_count = 4; slhdr->shd_credits = 0; slhdr->shd_type = SLOT_START; sptr += sizeof(struct slot_hdr); ssl = (struct slot_start *)sptr; ssl->sst_class = slot->lsl_class = 1; ssl->sst_minAsize = ssl->sst_minDsize =slot->lsl_datasize=lat_msize; sptr += sizeof(struct slot_start); if (*sptr++ = h->obj_namelen) { nptr = (caddr_t)h->obj_name; while (ch = *nptr++) { if (('a' <= ch) && (ch <= 'z')) ch = ch -'a' + 'A'; *sptr++ = ch; } } slhdr->shd_count += h->obj_namelen + 1; if (*sptr++ = h->subj_portlen) { nptr = (caddr_t)h->subj_port; while (ch = *nptr++) { if (('a' <= ch) && (ch <= 'z')) ch = ch -'a' + 'A'; *sptr++ = ch; } } slhdr->shd_count += h->subj_portlen + 1; /* add group code ??????? */ *sptr++ = 0; m->m_len = (int)sptr - (int)page; INC(lco_xmtframes); ENQUEUE(&vcir->lvc_xmtq, m); latsend(vcir); sleep(m, TTIPRI); /* check for timeout */ if (!slot->lsl_remid) { ecbp->ecb_inuse &= ~ECB_INUSE; splx(s); return (ENETUNREACH); } lat_mack(vcir); if (!(lat_mflag & LAT_MASTIMER)) timeout(lat_mtimer, 0, lat_mtick); } splx(s); return(0); } splx(s); return(ENOBUFS);#endif}/* * l a t _ m a c k */lat_mack(vcir)struct lat_vc *vcir;{#ifdef LATMASTER vcir->lvc_rrf = 0; vcrun(vcir);#endif}/* * m v c s t a r t 1 */mvcstart1(m,vhdr)struct mbuf *m;struct vc_hdr *vhdr;{#ifndef LATMASTER return(0);#else register struct lat_vc *vcir; struct mbuf *m0; int index; index = vhdr->vhd_dstid & 0377; vcir = vc[index]; vcir->lvc_remid = vhdr->vhd_srcid; vcir->lvc_ack++; DEQUEUE(&vcir->lvc_ackq, m0); if (m0) { wakeup(m0); m_freem(m0); } m_freem(m);#endif}/* * m s l o t s t a r t */mslotstart(slothdr)struct slot_hdr *slothdr;{#ifndef LATMASTER return(0);#else register struct lat_vc *vcir; register struct lat_slot *slot; struct mbuf *m0; if (vcir = findvc()) { vcir->lvc_ack++; vcir->lvc_lxmt++; slot = &sl[slothdr->shd_dstid-1]; slot->lsl_remid = slothdr->shd_srcid; slot->lsl_loccredits += slothdr->shd_credits; slot->lsl_remcredits = 1; /* set credit to 1 for now */ slot->lsl_state = SST_RUNNING; DEQUEUE(&vcir->lvc_ackq, m0); if (m0) { wakeup(m0); m_freem(m0); } }#endif}lat_master(vcir)register struct lat_vc *vcir;{#ifdef LATMASTER if (vcir->lvc_dgsize <= 60) return (1);#endif return(0);}#ifdef LATMASTER/* * l a t _ m t i m e r * * LAT master 80 millisecond timer (in lat_mtick) * */lat_mtimer(){ register struct lat_vc *vcir; register struct lat_slot *slot; register struct tty *tp; int s = splnet(); int i, j, cr; lat_mflag &= ~LAT_MASTIMER; for (i=1; i<nLAT1; i++) { if (vcir = vc[i]) { if (!lat_master(vcir)) continue; lat_mflag |= LAT_MASTIMER; /* * If there are more than 1 unacked sequence number, * the whole acknowledgement hand shaking may become * chaos unless some coding changes in process_vc_run(). * For now, do not send if ack queue not empty */ if (vcir->lvc_ackq.q_head) continue; cr = 0; for (slot=sl,j=0; j<nLAT1; slot++,j++) { if ((slot->lsl_vc == vcir) && (slot->lsl_state == SST_RUNNING)) { tp = (struct tty *)slot->lsl_data; /* grant credit only if tty queue is empty */ if (slot->lsl_attsize && !tp->t_rawq.c_cc) { slot->lsl_remcredits = slot->lsl_attsize; slot->lsl_attsize = 0; cr = 1; } /* check if anything can be sent out */ else if (tp->t_outq.c_cc) { /* if no credit, set flag for data waiting */ if (!slot->lsl_loccredits) vcir->lvc_rcvact |= 0x80; else cr = 1; } } } if (cr) lat_mack(vcir); } } /* start timer if there is master virtual circuit */ if (lat_mflag & LAT_MASTIMER) timeout(lat_mtimer, 0, lat_mtick); splx(s);}#endiflat_alive(vcir)struct lat_vc *vcir;{#ifdef LATMASTER if (lat_master(vcir)) { /* * latmaster - vms: a possible bug in vms driver not returning * credit in time, send a message as reminder * if output data waiting */ if ((vcir->lvc_dgsize == 60) || (vcir->lvc_rcvact & 0x80)) { vcir->lvc_rcvact &= 0x0bf; if (!(vcir->lvc_ackq.q_head)) lat_mack(vcir); vcir->lvc_dgsize = 0; } else vcir->lvc_dgsize++; }#endif}#ifdef LATMASTERstruct lat_vc *vcduplicate(hptr)struct hic_entity *hptr;{ register struct lat_vc *vcir; register int index; for (index = 1; index < LAT_MAXVC; index++) { if (vcir = vc[index]) if (lat_master(vcir)) if (bcmp(hptr->obj_port, vcir->lvc_addr.lat_addr, 6) == 0) return (vcir); } return (0);}#endif/* * Input: flag = 1: add multicast address * = 0: delete multicast address */lat_multi(flag)int flag;{ register struct ifnet *ifp = ifnet; struct ifreq dreq; /* * enable LAT Multicast Address on each device. */ bzero(dreq.ifr_addr.sa_data, 6); dreq.ifr_addr.sa_data[0] = 0x09; dreq.ifr_addr.sa_data[2] = 0x2b; dreq.ifr_addr.sa_data[5] = 0x0f; while ( ifp ) { if ((ifp->if_flags & (IFF_BROADCAST|IFF_DYNPROTO)) == (IFF_BROADCAST|IFF_DYNPROTO)) { if (flag) (*ifp->if_ioctl)(ifp, SIOCADDMULTI, &dreq); else (*ifp->if_ioctl)(ifp, SIOCDELMULTI, &dreq); } ifp = ifp->if_next; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -