📄 bsc_states.c
字号:
so = bsc->bscp_socket; crcloc(); bmtmp = mtod(so->so_snd.sb_mb, struct bsc_data *); if (bmtmp->data[0] == DLE) d_flag = 1; else d_flag = 0; m_head = m_getclr(M_DONTWAIT, MT_DATA); if ( m_head == (struct mbuf *)NULL ){ return(ENOBUFS); } m_head->m_len = MLEN; m_head->m_off = MMAXOFF - m_head->m_len; bmtmp = mtod(m_head, struct bsc_data *); if (d_flag){ /* transparent */ bmtmp->data[i++] = DLE; bmtmp->data[i++] = STX; m_head->m_len = (unsigned)i; j = 1; }else{ /* nontransparent */ bmtmp->data[i++] = STX; m_head->m_len = (unsigned)i; j = 0; } m_head->m_next = m_copy(so->so_snd.sb_mb, j, M_COPYALL); m = m_head->m_next; bm = mtod(m, struct bsc_data *); len = m->m_len; j = 0;loop: for ( j; j < len; j++ ){ c = bm->data[j]; if ((c==ETX) && (bm->data[j-1]!=DLE) && (m->m_next==NULL)){ state = SENDBLKLAST; break; } /* We've seen the ETB indicator in the buffer so escape. */ if ((c== ETB) && (bm->data[j-1]!=DLE)) break; if (( c == DLE) || (c == SYNC)) continue; crc16(c); if (( c == ITB) && (d_flag == 0)) break; } if ( c == ITB ){ j++; m->m_len = j; m_new = m_getclr(M_DONTWAIT, MT_DATA); if ( m_new == (struct mbuf *)NULL ) return(ENOBUFS); m_new->m_len = MLEN; m_new->m_off = MMAXOFF - m_new->m_len; bmtmp = mtod(m_new, struct bsc_data *); bmtmp->data[0] = crc[0]; bmtmp->data[1] = crc[1]; crcloc(); /* if (d_flag){ * bmtmp->data[2] = SYN; * bmtmp->data[3] = SYN; * bmtmp->data[4] = DLE; * crc16(c); * bmtmp->data[5] = STX; * crc16(c); * i = 6; * }else{ * bmtmp->data[2] = SYN; * bmtmp->data[3] = SYN; * i = 4; * } */ i = 2; for (j; j<len; j++) bmtmp->data[i++] = bm->data[j]; m_new->m_len = i; if (m->m_next == NULL){ m->m_next = m_new; m_new->m_next = NULL; m = m->m_next; len = m->m_len; bm = mtod(m, struct bsc_data *); j = 2; goto loop; } if (m->m_next != NULL){ mp = m->m_next; m->m_next = m_new; m_new->m_next = mp; m = m->m_next; len = m->m_len; bm = mtod(m, struct bsc_data *); j = 2; goto loop; } } if ( (m->m_next != NULL) ){ mp = m->m_next; len = mp->m_len; bm = mtod(mp, struct bsc_data *); m = mp; if ( c != ITB) j = 0; goto loop; } /* Delete the marker in the buffer indicating EOF or EOB */ m->m_len = m->m_len - 1; m->m_next = m_getclr(M_DONTWAIT, MT_DATA); if ( m->m_next == (struct mbuf *)NULL ){ return(ENOBUFS); } m->m_next->m_len = MLEN; m->m_next->m_off = MMAXOFF - m->m_next->m_len; bmtmp = mtod(m->m_next, struct bsc_data *); i = 0; if (state == SENDBLKLAST){ if (d_flag){ bmtmp->data[i++] = DLE; bmtmp->data[i++] = ETX; crc16(ETX); }else{ bmtmp->data[i++] = ETX; crc16(ETX); } }else{ if (d_flag){ bmtmp->data[i++] = DLE; bmtmp->data[i++] = ETB; crc16(ETB); }else{ bmtmp->data[i++] = ETB; crc16(ETB); } } bmtmp->data[i++] = crc[0]; bmtmp->data[i++] = crc[1]; m->m_next->m_len = i; CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity); error = (*ifp->if_output)(ifp, m_head, (struct sockaddr *)dst); RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity); m_freem(m_head); return(error);} /* * Xmtctl is a generic routine that generates and transmits a message * containing one or two control characters plus sync and ending pad * characters. Use this routine to transmit, for example, an EOT message. */xmtctl(byte1, byte2, ifp) char byte1, byte2; register struct ifnet *ifp;{ struct mbuf *m_tmp; /* Temp mbuf for control characters */ int i = 0; struct sockaddr_bsc *dst; int error; struct bsc_data *bdat; int saveaffinity; m_tmp = m_getclr(M_DONTWAIT, MT_DATA); if ( m_tmp == (struct mbuf *)NULL ){ return(ENOBUFS); } m_tmp->m_len = MLEN; m_tmp->m_off = MMAXOFF - m_tmp->m_len; bdat = mtod(m_tmp, struct bsc_data *); bdat->data[i++] = byte1; if ( byte2 != NULL ) bdat->data[i++] = byte2; bdat->data[i++] = PAD; bdat->data[i++] = PAD; m_tmp->m_len = (unsigned)i; CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity); error = (*ifp->if_output)(ifp, m_tmp, (struct sockaddr *)dst); RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity); m_free(m_tmp); return(error);}/* * Rec() is a key routine on the receive side. Bscrcv tells what the data is * and rec processes that data. For control messages coming in, rec * sees if the message is okay and returns either success or failure * to the case statements in bsc_input. For data coming in, rec() calls * routines to get a clean mbuf (getrbuf) to write only the * data to and then rec() calls a routine to 'put()' the data to the * clean mbuf. */rec(){ crcloc(); dat_dvr = mtod(m_dvr, struct bsc_data *); rsom(SYNC); bscrcv(); switch(byte){ case EOT: return(EOT); break; case ENQ: return(ENQ); break; case NAK: return(R_NAK); break; case STX: getrbuf(); byte = rcvdat(); compress(); while ((byte != ETB) && (byte != ETX)){ if (flag == 1){ break; } if((byte&0x05) == 0x05){ punch = 1; put(); }else{ punch = 0; put(); } /* if(byte == 0){ * break; * } */ byte = rcvdat(); compress(); while ((byte != ETB) && (byte != ETX)){ if (flag == 1){ break; } if ( byte == IUS){ rcvcrc(0); if(crc[0] != 0){ return(R_ERBLK); } rcvcrc(1); if(crc[1] != 0){ return(R_ERBLK); } crcloc(); } /* if(byte == 0){ * break; * } */ put(); byte = rcvdat(); compress(); } } rcvcrc(0); rcvcrc(1); bscrcv(); if(crc[0] != 0){ return(R_ERBLK); } if(crc[1] != 0){ return(R_ERBLK); } return(R_OKBLK); break; case DLE: bscrcv(); switch(byte){ case X70: if (ackseq != X70) return(R_SEQ); /* If timers need to kick in while state is SENDACK0 * the following if statement will prevent the ackseq * from being bumped. Without this if statement you * would always be out of sequence. */ if ( state == SENDACK0) return(R_ACK); ackseq = 0x61; return(R_ACK); /* else * return(R_ERROR); */ break; case 0x61: if (ackseq != 0x61) return(R_SEQ); ackseq = X70; return(R_ACK); /* else * return(R_ERROR); */ break; case 0X7c: /* bsc_pulloutofband(bsc); */ return(R_RVI); break; case ENQ: /* bsc_pulloutofband(bsc); */ return(ENQ); break; case STX: getrbuf(); byte = rcvdat(); compress(); while ((byte != ETB) && (byte != ETX)){ if (flag == 1){ break; } if((byte&0x05) == 0x05){ punch = 1; put(); }else{ punch = 0; put(); } /* if(byte == 0){ * break; * } */ byte = rcvdat(); compress(); while ((byte != ETB) && (byte != ETX)){ if (flag == 1){ break; } if ( byte == IUS){ rcvcrc(0); if(crc[0] != 0){ return(R_ERBLK); } rcvcrc(1); if(crc[1] != 0){ return(R_ERBLK); } crcloc(); } /* if(byte == 0){ * break; * } */ put(); byte = rcvdat(); compress(); } } rcvcrc(0); rcvcrc(1); bscrcv(); if(crc[0] != 0){ return(R_ERBLK); } if(crc[1] != 0){ return(R_ERBLK); } return(R_OKBLK); break; default: return(R_ERROR); } break; default: return(R_ERROR); }}/* Do all compression interpretation here except for HT. HT in a format * record is handled by the daemon. */compress(){ char byte_save;loopss: if (byte==ESC){ byte = rcvdat(); switch(byte){ case 0x61: /* / */ byte = LF; put(); break; case 0xe2: /* S */ byte = LF; put(); byte = LF; put(); break; case 0xe3: /* T */ byte = 0x40; put(); byte = 0x40; put(); byte = 0x40; put(); break; case 0xc1: /* A */ byte = 0x0c; put(); break; default: byte_save = byte; byte = ESC; put(); byte = byte_save; put(); break; } byte = rcvdat(); if (byte == ESC) goto loopss; } /* if */ else return;}rcvcrc(i)int i;{ bscrcv(); crc[i] = crc[i] - (unsigned)byte; return(0);}rcvdat(){ for (;;){ bscrcv(); if(byte != DLE) { if(byte == SYNC) continue; crc16(byte); return(byte); } else { bscrcv(); if(byte == SYNC) continue; crc16(byte); return(byte); } } }xmtack(bsc) struct bscpcb *bsc;{ struct ifnet *ifp; struct sockaddr_bsc *sin = &bsc->bscp_laddr; struct mbuf *m_tmp; struct sockaddr_bsc *dst; struct bsc_data *bdat; int error; int i = 0; int saveaffinity; ifp = (struct ifnet *)bsc_ifpfinder( sin ); if (ifp == 0) return(EADDRNOTAVAIL); m_tmp = m_getclr(M_DONTWAIT, MT_DATA); if ( m_tmp == (struct mbuf *)NULL ){ return(ENOBUFS); } m_tmp->m_len = MLEN; m_tmp->m_off = MMAXOFF - m_tmp->m_len; bdat = mtod(m_tmp, struct bsc_data *); bdat->data[i++] = DLE; bdat->data[i++] = ackseq; bdat->data[i++] = PAD; m_tmp->m_len = (unsigned)i; CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity); error = (*ifp->if_output)(ifp, m_tmp, (struct sockaddr *)dst); RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity); m_free(m_tmp); return(error);}crcloc( ){ crc[0]=0; crc[1]=0; }/* * Strip off the leading rec_ch (sync) characters from the mbuf you get * from the driver. */rsom( rec_ch ) char rec_ch;{ int i = 0; data_loc_dvr = 0; while ( dat_dvr->data[i] == rec_ch ){ i++; } data_loc_dvr = i; flag = 0; return (0);}/* * Get a character from the mbuf you get from the driver. */bscrcv(){ if ( m_dvr->m_len == data_loc_dvr){ if (m_dvr->m_next == NULL){ if ( byte == ETX) flag = 1; if (byte == ETB) flag = 1; return(0); } m_dvr = m_dvr->m_next; data_loc_dvr = 0; dat_dvr = mtod(m_dvr, struct bsc_data *); } byte = dat_dvr->data[data_loc_dvr++]; flag = 0; return(0);}/* * Get an mbuf that will be used only for the purpose of collecting incoming * data that has been stripped of bisync control characters. */getrbuf(){ int i; m_up = m_get(M_DONTWAIT, MT_DATA); if ( m_up == (struct mbuf *)NULL ){ return(ENOBUFS); } m_up->m_len = MLEN; m_up->m_off = MMAXOFF - m_up->m_len; bsc_mbuf_len = m_up->m_len; data_loc_up = 0; dat_up = mtod(m_up, struct bsc_data *); /* Before storing data, be sure entire buffer is clean */ for (i=0; i<bsc_mbuf_len; i++) dat_up->data[i] = 0x40; m_up_ptr = m_up; /* save a pointer to the head of the * receive queue. The pointer you save * is what gets passed up to the socket * receive queue. */ return(0);}/* * Now write only data characters to m_up. Put data characters only from m_dvr * the mbuf you get from the driver, into m_up. You may want to do some buffer * size checking in here. */put(){ struct mbuf *m_temp; int i; if (bsc_mbuf_len == data_loc_up){ m_temp = m_get(M_DONTWAIT, MT_DATA); if ( m_temp == (struct mbuf *)NULL ) return(ENOBUFS); m_temp->m_len = MLEN; m_temp->m_off = MMAXOFF - m_temp->m_len; data_loc_up = 0; bsc_mbuf_len = m_temp->m_len; /* Now link m_temp into the m_up chain and reset * m_up_ptr to point to the new mbuf. */ m_up_ptr->m_next = m_temp; m_up_ptr = m_up_ptr->m_next; dat_up = mtod(m_up_ptr, struct bsc_data *); /* Before storing data, be sure entire buffer is clean */ for (i=0; i<bsc_mbuf_len; i++) dat_up->data[i] = 0x40; } dat_up->data[data_loc_up++] = byte; return(0);}/* crc16 takes 1 character as input and updates the CRC[] for the whole message */crc16(crc_ch) char crc_ch;{ unsigned short tmp,result; result= (crc[1] & 0x00ff) << 8; /* put crc[] into result, */ result |= (crc[0] & 0x00ff); /* ie result=crc[0-1] */ tmp= (0xffff & result) ^ (0xff & crc_ch); /* next 3 - calc. new crc */ tmp= (0xfff & (tmp >> 4)) ^ crctable[tmp & 0xf]; result= (0xfff & (tmp >>4)) ^ crctable[tmp & 0xf]; crc[0]=(result & 0x00ff); /* put new crc in crc[] */ crc[1]=(result & 0xff00) >> 8;}/* * Pull out of band byte out of a segment. */bsc_pulloutofband(bsc) struct bscpcb *bsc;{ struct socket *so; register struct mbuf *m; so = bsc->bscp_socket; bsc->b_iobc = byte; so->so_oobmark = so->so_rcv.sb_cc + 1;}bscintr(){/* * This is where the driver input routine returns. * It calls the mother routine, bsc_states to respond to the incoming * message. */ register struct mbuf *m; int s; struct sockaddr_bsc *sin; struct ifnet *ifp; int saveaffinity; saveaffinity = switch_affinity(boot_cpu_mask); /* * Get datagram off input queue. */ s = splimp(); IF_DEQUEUE(&bscintrq, m); splx(s); if (ifp) sin = (struct sockaddr_bsc *)&ifp->if_addr; (*bscnetsw[1].pr_input)(m, sin);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -