📄 sdla_fr.c
字号:
{ unsigned short temp; unsigned long sum=0; int i; for( i = 0; i <len; i+=2 ) { memcpy(&temp,&data[i],2); sum += (unsigned long)temp; } while (sum >> 16 ) { sum = (sum & 0xffffUL) + (sum >> 16); } temp = (unsigned short)sum; temp = ~temp; if( temp == 0 ) temp = 0xffff; return temp; }/* If incoming is 0 (outgoing)- if the net numbers is ours make it 0 if incoming is 1 - if the net number is 0 make it ours */static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming){ unsigned long pnetwork_number; pnetwork_number = (unsigned long)((sendpacket[14] << 24) + (sendpacket[15] << 16) + (sendpacket[16] << 8) + sendpacket[17]); if (!incoming) { /* If the destination network number is ours, make it 0 */ if( pnetwork_number == network_number) { sendpacket[14] = sendpacket[15] = sendpacket[16] = sendpacket[17] = 0x00; } } else { /* If the incoming network is 0, make it ours */ if( pnetwork_number == 0) { sendpacket[14] = (unsigned char)(network_number >> 24); sendpacket[15] = (unsigned char)((network_number & 0x00FF0000) >> 16); sendpacket[16] = (unsigned char)((network_number & 0x0000FF00) >> 8); sendpacket[17] = (unsigned char)(network_number & 0x000000FF); } } pnetwork_number = (unsigned long)((sendpacket[26] << 24) + (sendpacket[27] << 16) + (sendpacket[28] << 8) + sendpacket[29]); if( !incoming ) { /* If the source network is ours, make it 0 */ if( pnetwork_number == network_number) { sendpacket[26] = sendpacket[27] = sendpacket[28] = sendpacket[29] = 0x00; } } else { /* If the source network is 0, make it ours */ if( pnetwork_number == 0 ) { sendpacket[26] = (unsigned char)(network_number >> 24); sendpacket[27] = (unsigned char)((network_number & 0x00FF0000) >> 16); sendpacket[28] = (unsigned char)((network_number & 0x0000FF00) >> 8); sendpacket[29] = (unsigned char)(network_number & 0x000000FF); } }} /* switch_net_numbers *//*============================================================================ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */static struct net_device_stats *if_stats(struct net_device *dev){ fr_channel_t* chan = dev->priv; if(chan == NULL) return NULL; return &chan->ifstats;}/****** Interrupt Handlers **************************************************//*============================================================================ * fr_isr: S508 frame relay interrupt service routine. * * Description: * Frame relay main interrupt service route. This * function check the interrupt type and takes * the appropriate action. */static void fr_isr (sdla_t* card){ fr508_flags_t* flags = card->flags; char *ptr = &flags->iflag; int i,err; fr_mbox_t* mbox = card->mbox; /* This flag prevents nesting of interrupts. See sdla_isr() routine * in sdlamain.c. */ card->in_isr = 1; ++card->statistics.isr_entry; /* All peripheral (configuraiton, re-configuration) events * take presidence over the ISR. Thus, retrigger */ if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { ++card->statistics.isr_already_critical; goto fr_isr_exit; } if(card->hw.type != SDLA_S514) { if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { printk(KERN_INFO "%s: Critical while in ISR: If Send Running!\n", card->devname); ++card->statistics.isr_already_critical; goto fr_isr_exit; } } switch (flags->iflag) { case FR_INTR_RXRDY: /* receive interrupt */ ++card->statistics.isr_rx; rx_intr(card); break; case FR_INTR_TXRDY: /* transmit interrupt */ ++ card->statistics.isr_tx; tx_intr(card); break; case FR_INTR_READY: Intr_test_counter++; ++card->statistics.isr_intr_test; break; case FR_INTR_DLC: /* Event interrupt occurred */ mbox->cmd.command = FR_READ_STATUS; mbox->cmd.length = 0; err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; if (err) fr_event(card, err, mbox); break; case FR_INTR_TIMER: /* Timer interrupt */ timer_intr(card); break; default: ++card->statistics.isr_spurious; spur_intr(card); printk(KERN_INFO "%s: Interrupt Type 0x%02X!\n", card->devname, flags->iflag); printk(KERN_INFO "%s: ID Bytes = ",card->devname); for(i = 0; i < 8; i ++) printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); printk(KERN_INFO "\n"); break; }fr_isr_exit: card->in_isr = 0; flags->iflag = 0; return;}/*=========================================================== * rx_intr Receive interrupt handler. * * Description * Upon receiveing an interrupt: * 1. Check that the firmware is in sync with * the driver. * 2. Find an appropriate network interface * based on the received dlci number. * 3. Check that the netowrk interface exists * and that it's setup properly. * 4. Copy the data into an skb buffer. * 5. Check the packet type and take * appropriate acton: UPD, API, ARP or Data. */static void rx_intr (sdla_t* card){ fr_rx_buf_ctl_t* frbuf = card->rxmb; fr508_flags_t* flags = card->flags; fr_channel_t* chan; char *ptr = &flags->iflag; struct sk_buff* skb; struct net_device* dev; void* buf; unsigned dlci, len, offs, len_incl_hdr; int i, udp_type; /* Check that firmware buffers are in sync */ if (frbuf->flag != 0x01) { printk(KERN_INFO "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", card->devname, (unsigned)frbuf, frbuf->flag); printk(KERN_INFO "%s: ID Bytes = ",card->devname); for(i = 0; i < 8; i ++) printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); printk(KERN_INFO "\n"); ++card->statistics.rx_intr_corrupt_rx_bfr; /* Bug Fix: Mar 6 2000 * If we get a corrupted mailbox, it means that driver * is out of sync with the firmware. There is no recovery. * If we don't turn off all interrupts for this card * the machine will crash. */ printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); printk(KERN_INFO "Please contact Sangoma Technologies !\n"); fr_set_intr_mode(card, 0, 0, 0); return; } len = frbuf->length; dlci = frbuf->dlci; offs = frbuf->offset; /* Find the network interface for this packet */ dev = find_channel(card, dlci); /* Check that the network interface is active and * properly setup */ if (dev == NULL) { if( net_ratelimit()) { printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n", card->devname, dlci); } ++card->statistics.rx_intr_on_orphaned_DLCI; ++card->wandev.stats.rx_dropped; goto rx_done; } if ((chan = dev->priv) == NULL){ if( net_ratelimit()) { printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n", card->devname, dlci); } ++card->statistics.rx_intr_on_orphaned_DLCI; ++card->wandev.stats.rx_dropped; goto rx_done; } skb = dev_alloc_skb(len); if (!netif_running(dev) || (skb == NULL)){ ++chan->ifstats.rx_dropped; if(skb == NULL) { if (net_ratelimit()) { printk(KERN_INFO "%s: no socket buffers available!\n", card->devname); } chan->drvstats_rx_intr.rx_intr_no_socket ++; } if (!netif_running(dev)){ chan->drvstats_rx_intr. rx_intr_dev_not_started ++; if (skb){ dev_kfree_skb_any(skb); } } goto rx_done; } /* Copy data from the board into the socket buffer */ if ((offs + len) > card->u.f.rx_top + 1) { unsigned tmp = card->u.f.rx_top - offs + 1; buf = skb_put(skb, tmp); sdla_peek(&card->hw, offs, buf, tmp); offs = card->u.f.rx_base; len -= tmp; } buf = skb_put(skb, len); sdla_peek(&card->hw, offs, buf, len); /* We got the packet from the bard. * Check the packet type and take appropriate action */ udp_type = udp_pkt_type( skb, card ); if(udp_type != UDP_INVALID_TYPE) { /* UDP Debug packet received, store the * packet and handle it in timer interrupt */ skb_pull(skb, 1); if (wanrouter_type_trans(skb, dev)){ if(store_udp_mgmt_pkt(udp_type,UDP_PKT_FRM_NETWORK,card,skb,dlci)){ flags->imask |= FR_INTR_TIMER; if (udp_type == UDP_FPIPE_TYPE){ ++chan->drvstats_rx_intr.rx_intr_PIPE_request; } } } }else if (chan->common.usedby == API) { /* We are in API mode. * Add an API header to the RAW packet * and queue it into a circular buffer. * Then kick the fr_bh() bottom half handler */ api_rx_hdr_t* api_rx_hdr; chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack ++; chan->ifstats.rx_packets ++; card->wandev.stats.rx_packets ++; chan->ifstats.rx_bytes += skb->len; card->wandev.stats.rx_bytes += skb->len; skb_push(skb, sizeof(api_rx_hdr_t)); api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00]; api_rx_hdr->attr = frbuf->attr; api_rx_hdr->time_stamp = frbuf->tmstamp; skb->protocol = htons(ETH_P_IP); skb->mac.raw = skb->data; skb->dev = dev; skb->pkt_type = WAN_PACKET_DATA; bh_enqueue(dev, skb); trigger_fr_bh(chan); }else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){ //FIXME: Frame Relay IPX is not supported, Yet ! //if (chan->enable_IPX) { // fr_send(card, dlci, 0, skb->len,skb->data); //} dev_kfree_skb_any(skb); } else if (is_arp(skb->data)) { /* ARP support enabled Mar 16 2000 * Process incoming ARP reply/request, setup * dynamic routes. */ if (process_ARP((arphdr_1490_t *)skb->data, card, dev)) { if (net_ratelimit()){ printk (KERN_INFO "%s: Error processing ARP Packet.\n", card->devname); } } dev_kfree_skb_any(skb); } else if (skb->data[0] != 0x03) { if (net_ratelimit()) { printk(KERN_INFO "%s: Non IETF packet discarded.\n", card->devname); } dev_kfree_skb_any(skb); } else { len_incl_hdr = skb->len; /* Decapsulate packet and pass it up the protocol stack */ skb->dev = dev; if (chan->common.usedby == BRIDGE || chan->common.usedby == BRIDGE_NODE){ /* Make sure it's an Ethernet frame, otherwise drop it */ if (!memcmp(skb->data, "\x03\x00\x80\x00\x80\xC2\x00\x07", 8)) { skb_pull(skb, 8); skb->protocol=eth_type_trans(skb,dev); }else{ ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack; ++chan->ifstats.rx_errors; ++card->wandev.stats.rx_errors; goto rx_done; } }else{ /* remove hardware header */ buf = skb_pull(skb, 1); if (!wanrouter_type_trans(skb, dev)) { /* can't decapsulate packet */ dev_kfree_skb_any(skb); ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack; ++chan->ifstats.rx_errors; ++card->wandev.stats.rx_errors; goto rx_done; } skb->mac.raw = skb->data; } /* Send a packet up the IP stack */ skb->dev->last_rx = jiffies; netif_rx(skb); ++chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -