📄 sdla_ppp.c
字号:
ppp_priv_area->mc = conf->mc; ppp_priv_area->pap = conf->pap; ppp_priv_area->chap = conf->chap; /* If no user ids are specified */ if(!strlen(conf->userid) && (ppp_priv_area->pap||ppp_priv_area->chap)){ kfree(ppp_priv_area); return -EINVAL; } /* If no passwords are specified */ if(!strlen(conf->passwd) && (ppp_priv_area->pap||ppp_priv_area->chap)){ kfree(ppp_priv_area); return -EINVAL; } if(strlen(conf->sysname) > 31){ kfree(ppp_priv_area); return -EINVAL; } /* If no system name is specified */ if(!strlen(conf->sysname) && (card->u.p.authenticator)){ kfree(ppp_priv_area); return -EINVAL; } /* copy the data into the ppp private structure */ memcpy(ppp_priv_area->userid, conf->userid, strlen(conf->userid)); memcpy(ppp_priv_area->passwd, conf->passwd, strlen(conf->passwd)); memcpy(ppp_priv_area->sysname, conf->sysname, strlen(conf->sysname)); ppp_priv_area->enable_IPX = conf->enable_IPX; if (conf->network_number) ppp_priv_area->network_number = conf->network_number; else ppp_priv_area->network_number = 0xDEADBEEF; /* prepare network device data space for registration */ strcpy(dev->name, card->u.p.if_name); dev->init = &if_init; dev->priv = ppp_priv_area; return 0;}/*============================================================================ * Delete logical channel. */static int del_if(wan_device_t *wandev, struct net_device *dev){ if (dev->priv) { kfree(dev->priv); dev->priv = NULL; } return 0;}/****** WANPIPE-specific entry points ***************************************//*============================================================================ * Execute adapter interface command. *///FIXME: Why do we need this ????static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data){ ppp_mbox_t *mbox = card->mbox; int len; if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) return -EFAULT; len = mbox->cmd.length; if (len) { if( copy_from_user((void*)&mbox->data, u_data, len)) return -EFAULT; } /* execute command */ if (!sdla_exec(mbox)) return -EIO; /* return result */ if( copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t))) return -EFAULT; len = mbox->cmd.length; if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)) return -EFAULT; return 0;}/****** Network Device Interface ********************************************//*============================================================================ * Initialize Linux network interface. * * This routine is called only once for each interface, during Linux network * interface registration. Returning anything but zero will fail interface * registration. */static int if_init(struct net_device *dev){ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; wan_device_t *wandev = &card->wandev;#ifndef LINUX_2_1 int i;#endif /* Initialize device driver entry points */ dev->open = &if_open; dev->stop = &if_close; dev->hard_header = &if_header; dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; /* Initialize media-specific parameters */ dev->type = ARPHRD_PPP; /* ARP h/w type */ dev->flags |= IFF_POINTOPOINT; /* Enable Mulitcasting if specified by user*/ if (ppp_priv_area->mc == WANOPT_YES){ dev->flags |= IFF_MULTICAST; }#ifndef LINUX_2_1 dev->family = AF_INET;#endif dev->mtu = wandev->mtu; dev->hard_header_len = PPP_HDR_LEN; /* media header length */ /* Initialize hardware parameters (just for reference) */ dev->irq = wandev->irq; dev->dma = wandev->dma; dev->base_addr = wandev->ioport; dev->mem_start = wandev->maddr; dev->mem_end = wandev->maddr + wandev->msize - 1; /* Set transmit buffer queue length */ dev->tx_queue_len = 100; /* Initialize socket buffers */ dev_init_buffers(dev); return 0;}/*============================================================================ * Open network interface. * o enable communications and interrupts. * o prevent module from unloading by incrementing use count * * Return 0 if O.k. or errno. */static int if_open(struct net_device *dev){ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; ppp_flags_t *flags = card->flags; struct timeval tv; int err = 0; if (netif_running(dev)) return -EBUSY; /* only one open is allowed */ if (test_and_set_bit(0, (void*)&card->wandev.critical)) return -EAGAIN; if (!card->configured){ if (config508(ppp_priv_area, card)){ err = -EIO; card->wandev.critical = 0; return err; } Intr_test_counter = 0; err = intr_test( card ); if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { printk("%s: Interrupt Test Failed, Counter: %i\n", card->devname, Intr_test_counter); printk( "%s: Please choose another interrupt\n",card->devname); err = -EIO; card->wandev.critical = 0; return err; } printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", card->devname, Intr_test_counter); card->configured = 1; } /* Initialize Rx/Tx buffer control fields */ init_ppp_tx_rx_buff( card ); if (ppp_set_intr_mode(card, PPP_INTR_RXRDY| PPP_INTR_TXRDY| PPP_INTR_MODEM| PPP_INTR_CMD | PPP_INTR_DISC | PPP_INTR_OPEN | PPP_INTR_DROP_DTR | PPP_INTR_TIMER)) { err = -EIO; card->wandev.critical = 0; return err; } /* Turn off the transmit and timer interrupt */ flags->imask &= ~(PPP_INTR_TXRDY | PPP_INTR_TIMER) ; /* If you are not the authenticator and any one of the protocol is * enabled then we call the set_out_bound_authentication. */ if ( !card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)) { if ( ppp_set_outbnd_auth(card, ppp_priv_area) ){ err = -EIO; card->wandev.critical = 0; return err; } } /* If you are the authenticator and any one of the protocol is enabled * then we call the set_in_bound_authentication. */ if ( card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)) { if ( ppp_set_inbnd_auth(card, ppp_priv_area) ){ err = -EIO; card->wandev.critical = 0; return err; } } if (ppp_comm_enable(card)) { err = -EIO; card->wandev.critical = 0; return err; } wanpipe_set_state(card, WAN_CONNECTING); wanpipe_open(card); dev->mtu = min(dev->mtu, card->wandev.mtu); netif_start_queue(dev); do_gettimeofday( &tv ); ppp_priv_area->router_start_time = tv.tv_sec; card->wandev.critical = 0; return err;}/*============================================================================ * Close network interface. * o if this is the last open, then disable communications and interrupts. * o reset flags. */static int if_close(struct net_device *dev){ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; if (test_and_set_bit(0, (void*)&card->wandev.critical)) return -EAGAIN; netif_stop_queue(dev); wanpipe_close(card); wanpipe_set_state(card, WAN_DISCONNECTED); ppp_set_intr_mode(card, 0); ppp_comm_disable(card); card->wandev.critical = 0; return 0;}/*============================================================================ * Build media header. * * The trick here is to put packet type (Ethertype) into 'protocol' field of * the socket buffer, so that we don't forget it. If packet type is not * supported, set skb->protocol to 0 and discard packet later. * * Return: media header length. */static int if_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len){ switch (type) { case ETH_P_IP: case ETH_P_IPX: skb->protocol = htons(type); break; default: skb->protocol = 0; } return PPP_HDR_LEN;}/*============================================================================ * Re-build media header. * * Return: 1 physical address resolved. * 0 physical address not resolved */static int if_rebuild_hdr (struct sk_buff *skb){ struct net_device *dev = skb->dev; ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", card->devname, dev->name); return 1;}/*============================================================================ * Handle transmit timeout from netif watchdog */static void if_tx_timeout (struct net_device *dev){ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; /* If our device stays busy for at least 5 seconds then we will * kick start the device by making dev->tbusy = 0. We expect * that our device never stays busy more than 5 seconds. So this * is only used as a last resort. */ ++ppp_priv_area->if_send_stat.if_send_tbusy; ++card->wandev.stats.collisions; printk (KERN_INFO "%s: Transmit times out\n", card->devname); ++ppp_priv_area->if_send_stat.if_send_tbusy_timeout; ++card->wandev.stats.collisions; /* unbusy the card (because only one interface per card) */ netif_start_queue(dev);}/*============================================================================ * Send a packet on a network interface. * o set tbusy flag (marks start of the transmission) to block a timer-based * transmit from overlapping. * o check link state. If link is not up, then drop the packet. * o execute adapter send command. * o free socket buffer * * Return: 0 complete (socket buffer must be freed) * non-0 packet may be re-transmitted (tbusy must be set) * * Notes: * 1. This routine is called either by the protocol stack or by the "net * bottom half" (with interrupts enabled). * 2. Setting tbusy flag will inhibit further transmit requests from the * protocol stack and can be used for flow control with protocol layer. */static int if_send (struct sk_buff *skb, struct net_device *dev){ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; unsigned char *sendpacket; unsigned long smp_flags; ppp_flags_t *flags = card->flags; int retry = 0; int udp_type; ++ppp_priv_area->if_send_stat.if_send_entry; if (skb == NULL) { /* If we get here, some higher layer thinks we've missed an * tx-done interrupt. */ printk(KERN_INFO "%s: interface %s got kicked!\n", card->devname, dev->name); ++ppp_priv_area->if_send_stat.if_send_skb_null; netif_wake_queue(dev); return 0; } sendpacket = skb->data; udp_type = udp_pkt_type( skb, card ); if (udp_type == UDP_PTPIPE_TYPE){ if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, ppp_priv_area)){ flags->imask |= PPP_INTR_TIMER; } ++ppp_priv_area->if_send_stat.if_send_PIPE_request; return 0; } /* Check for broadcast and multicast addresses * If found, drop (deallocate) a packet and return. */ if(chk_bcast_mcast_addr(card, dev, skb)){ return 0; } if(card->hw.type != SDLA_S514){ s508_lock(card,&smp_flags); } if (test_and_set_bit(0, (void*)&card->wandev.critical)) { printk(KERN_INFO "%s: Critical in if_send: %x\n", card->wandev.name,card->wandev.critical); dev_kfree_skb(skb); ++card->wandev.stats.tx_dropped; ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR; if(card->hw.type != SDLA_S514){ s508_unlock(card,&smp_flags); } return 0; } if (card->wandev.state != WAN_CONNECTED) { ++ppp_priv_area->if_send_stat.if_send_wan_disconnected; ++card->wandev.stats.tx_dropped; } else if (!skb->protocol) { ++ppp_priv_area->if_send_stat.if_send_protocol_error; ++card->wandev.stats.tx_errors;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -