📄 sdla_fr.c
字号:
offs = frbuf->offset; /* Find network interface for this packet */ dev = find_channel(card, dlci); if (dev == NULL) { /* unconfigured DLCI, so discard packet */ printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n", card->devname, dlci); ++card->statistics.rx_intr_on_orphaned_DLCI; } else { chan = dev->priv; skb = dev_alloc_skb(len); if (!netif_running(dev) || (skb == NULL)) { ++chan->ifstats.rx_dropped; if(netif_running(dev)) { printk(KERN_INFO "%s: no socket buffers available!\n", card->devname); chan->drvstats_rx_intr.rx_intr_no_socket ++; } else chan->drvstats_rx_intr. rx_intr_dev_not_started ++; } else { /* Copy data to 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); udp_type = udp_pkt_type( skb, card ); if(udp_type != UDP_INVALID_TYPE) { 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->usedby == API) { 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(0x16); skb->pkt_type = PACKET_HOST; /* Pass it up the protocol stack */ skb->dev = dev; skb->mac.raw = skb->data; netif_rx(skb); } else if (handle_IPXWAN(skb->data,chan->name, chan->enable_IPX, chan->network_number)) { if (chan->enable_IPX) { fr_send(card, dlci, 0, skb->len, skb->data); } dev_kfree_skb(skb);/*FIXME: Fix the ARPS in next release } else if (is_arp(skb->data)) { if (process_ARP((arphdr_1490_t *)skb->data, card, dev)) { printk (KERN_INFO "%s: Error processing ARP Packet.\n", card->devname); } dev_kfree_skb(skb);*/ } else if ( skb->data[0] != 0x03) { printk(KERN_INFO "%s: Non IETF packet discarded.\n", card->devname); dev_kfree_skb(skb); } else { len_incl_hdr = skb->len; /* Decapsulate packet and pass it up the protocol stack */ skb->dev = dev; /* remove hardware header */ buf = skb_pull(skb, 1); if (!wanrouter_type_trans(skb, dev)) { /* can't decapsulate packet */ dev_kfree_skb(skb); chan->drvstats_rx_intr. rx_intr_bfr_not_passed_to_stack ++; ++ chan->ifstats.rx_errors; ++ card->wandev.stats.rx_errors; } else { netif_rx(skb); chan->drvstats_rx_intr. rx_intr_bfr_passed_to_stack ++; ++ chan->ifstats.rx_packets; ++ card->wandev.stats.rx_packets; chan->ifstats.rx_bytes += len_incl_hdr; card->wandev.stats.rx_bytes += len_incl_hdr; } } } } /* Release buffer element and calculate a pointer to the next one */ frbuf->flag = 0; card->rxmb = ++frbuf; if ((void*)frbuf > card->u.f.rxmb_last) card->rxmb = card->u.f.rxmb_base;}/*============================================================================ * Transmit interrupt handler. */static void tx_intr(sdla_t *card){ fr508_flags_t* flags = card->flags; fr_tx_buf_ctl_t* bctl; struct net_device* dev = card->wandev.dev; fr_channel_t* chan; if(card->hw.type == SDLA_S514){ bctl = (void*)(flags->tse_offs + card->hw.dpmbase); }else{ bctl = (void*)(flags->tse_offs - FR_MB_VECTOR + card->hw.dpmbase); } /* Find the structure and make it unbusy */ dev = find_channel(card, flags->dlci); chan = dev->priv; if(!chan->transmit_length) { printk(KERN_INFO "%s: tx int error - transmit length zero\n", card->wandev.name); return; } /* If the 'if_send()' procedure is currently checking the 'tbusy' status, then we cannot transmit. Instead, we configure the microcode so as to re-issue this transmit interrupt at a later stage. */ if (test_bit(2, (void*)&card->wandev.critical)) { fr_dlci_interface_t* dlci_interface = chan->dlci_int_interface; bctl->flag = 0xA0; dlci_interface->gen_interrupt |= FR_INTR_TXRDY; printk(KERN_INFO "%s: TX Interrupt Detected busy if_send\n",card->devname); } else { bctl->dlci = flags->dlci; bctl->length = chan->transmit_length; sdla_poke(&card->hw, bctl->offset, chan->transmit_buffer, chan->transmit_length); bctl->flag = 0xC0; ++chan->ifstats.tx_packets; ++card->wandev.stats.tx_packets; chan->ifstats.tx_bytes += chan->transmit_length; card->wandev.stats.tx_bytes += chan->transmit_length; chan->transmit_length = 0; /* if any other interfaces have transmit interrupts pending, */ /* do not disable the global transmit interrupt */ if(!(-- card->u.f.tx_interrupts_pending)) flags->imask &= ~FR_INTR_TXRDY; netif_wake_queue (dev); }}/*============================================================================ * Timer interrupt handler. FIXME: update comments as we modify the code * The timer interrupt is used for three purposes: * 1) Processing udp calls from 'fpipemon'. * 2) Processing update calls from /proc file system * 2) Reading board-level statistics for updating the proc file system. * 3) Sending inverse ARP request packets. */static void timer_intr(sdla_t *card){ fr508_flags_t* flags = card->flags; if(card->u.f.timer_int_enabled & TMR_INT_ENABLED_UDP) { if(card->u.f.udp_type == UDP_FPIPE_TYPE) { if(process_udp_mgmt_pkt(card)) { card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UDP; } } } if(card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE) { fr_get_err_stats(card); fr_get_stats(card); card->u.f.update_comms_stats = 0; card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; }//FIXME: Fix the dynamic IP addressing/*goto L4; // Used to send inarp request at given interval if (card->wandev.state == WAN_CONNECTED) { int num_remaining = 0; dev = card->wandev.dev; while (dev) { fr_channel_t *chan = dev->priv; if (chan->inarp == INARP_REQUEST && chan->state == WAN_CONNECTED) { num_remaining++; if ((jiffies - chan->inarp_tick) > (chan->inarp_interval * HZ)) { send_inarp_request(card,dev); chan->inarp_tick = jiffies; } } dev = chan->slave; } if (!num_remaining) { // no more to process flags->imask &= ~FR_INTR_TIMER; } }L4: ;*/ if(!card->u.f.timer_int_enabled) flags->imask &= ~FR_INTR_TIMER;}/*============================================================================ * Spurious interrupt handler. * o print a warning * o */static void spur_intr (sdla_t* card){ printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);}//FIXME: Fix the IPX in next version/*=========================================================================== * Return 0 for non-IPXWAN packet * 1 for IPXWAN packet or IPX is not enabled! * FIXME: Use a IPX structure here not offsets */static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number){ int i; if( sendpacket[1] == 0x00 && sendpacket[2] == 0x80 && sendpacket[6] == 0x81 && sendpacket[7] == 0x37) { /* It's an IPX packet */ if(!enable_IPX) { /* Return 1 so we don't pass it up the stack. */ //FIXME: Take this out when IPX is fixed printk (KERN_INFO "%s: WARNING: Unsupported IPX packet received and dropped\n", devname); return 1; } } else { /* It's not IPX so return and pass it up the stack. */ return 0; } if( sendpacket[24] == 0x90 && sendpacket[25] == 0x04) { /* It's IPXWAN */ if( sendpacket[10] == 0x02 && sendpacket[42] == 0x00) { /* It's a timer request packet */ printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname); /* Go through the routing options and answer no to every * option except Unnumbered RIP/SAP */ for(i = 49; sendpacket[i] == 0x00; i += 5) { /* 0x02 is the option for Unnumbered RIP/SAP */ if( sendpacket[i + 4] != 0x02) { sendpacket[i + 1] = 0; } } /* Skip over the extended Node ID option */ if( sendpacket[i] == 0x04 ) { i += 8; } /* We also want to turn off all header compression opt. */ for(; sendpacket[i] == 0x80 ;) { sendpacket[i + 1] = 0; i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; } /* Set the packet type to timer response */ sendpacket[42] = 0x01; printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname); } else if( sendpacket[42] == 0x02 ) { /* This is an information request packet */ printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname); /* Set the packet type to information response */ sendpacket[42] = 0x03; /* Set the router name */ sendpacket[59] = 'F'; sendpacket[60] = 'P'; sendpacket[61] = 'I'; sendpacket[62] = 'P'; sendpacket[63] = 'E'; sendpacket[64] = '-'; sendpacket[65] = CVHexToAscii(network_number >> 28); sendpacket[66] = CVHexToAscii((network_number & 0x0F000000)>> 24); sendpacket[67] = CVHexToAscii((network_number & 0x00F00000)>> 20); sendpacket[68] = CVHexToAscii((network_number & 0x000F0000)>> 16); sendpacket[69] = CVHexToAscii((network_number & 0x0000F000)>> 12); sendpacket[70] = CVHexToAscii((network_number & 0x00000F00)>> 8); sendpacket[71] = CVHexToAscii((network_number & 0x000000F0)>> 4); sendpacket[72] = CVHexToAscii(network_number & 0x0000000F); for(i = 73; i < 107; i+= 1) { sendpacket[i] = 0; } printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname); } else { printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); return 0; } /* Set the WNodeID to our network address */ sendpacket[43] = (unsigned char)(network_number >> 24); sendpacket[44] = (unsigned char)((network_number & 0x00FF0000) >> 16); sendpacket[45] = (unsigned char)((network_number & 0x0000FF00) >> 8); sendpacket[46] = (unsigned char)(network_number & 0x000000FF); return 1; } /* If we get here, its an IPX-data packet so it'll get passed up the * stack. * switch the network numbers */ switch_net_numbers(sendpacket, network_number ,1); return 0;}/*============================================================================ * Process Route. * This routine is called as a polling routine to dynamically add/delete routes * negotiated by inverse ARP. It is in this "task" because we don't want routes * to be added while in interrupt context.*/static void process_route (sdla_t* card){ struct net_device* dev; struct in_device *in_dev; struct rtentry route; int err = 0; mm_segment_t fs; /* Dynamic Route adding/removing */ dev = card->wandev.dev; while (dev) { fr_channel_t *chan = dev->priv; if (chan->route_flag == ADD_ROUTE || chan->route_flag == REMOVE_ROUTE ) { fs = get_fs(); in_dev = dev->ip_ptr; if( in_dev != NULL && in_dev->ifa_list != NULL) { memset(&route, 0, sizeof(route)); route.rt_dev = dev->name; route.rt_flags = 0; ((str
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -