📄 sdla_ppp.c
字号:
} } else { /* If the source network is 0, make it ours */ if (pnetwork_number == 0) { sendpacket[18] = (unsigned char) (network_number >> 24); sendpacket[19] = (unsigned char) ((network_number & 0x00FF0000) >> 16); sendpacket[20] = (unsigned char) ((network_number & 0x0000FF00) >> 8); sendpacket[21] = (unsigned char) (network_number & 0x000000FF); } }} /* switch_net_numbers *//*============================================================================ * Get Ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */static struct enet_statistics *if_stats(struct device *dev){ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card; /* * Device is down:No statistics */ if(ppp_priv_area==NULL) return NULL; card = ppp_priv_area->card; return &card->wandev.stats;}/****** PPP Firmware Interface Functions ************************************//*============================================================================ * Read firmware code version. * Put code version as ASCII string in str. */static int ppp_read_version(sdla_t * card, char *str){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_READ_CODE_VERSION; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); else if (str) { int len = mb->cmd.length; memcpy(str, mb->data, len); str[len] = '\0'; } return err;}/*============================================================================ * Configure PPP firmware. */static int ppp_configure(sdla_t * card, void *data){ ppp_mbox_t *mb = card->mbox; int data_len = (card->hw.fwid == SFID_PPP502) ? sizeof(ppp502_conf_t) : sizeof(ppp508_conf_t); int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); memcpy(mb->data, data, data_len); mb->cmd.length = data_len; mb->cmd.command = PPP_SET_CONFIG; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); return err;}/*============================================================================ * Set interrupt mode. */static int ppp_set_intr_mode(sdla_t * card, unsigned mode){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->data[0] = mode; switch (card->hw.fwid) { case SFID_PPP502: mb->cmd.length = 1; break; case SFID_PPP508: default: mb->data[1] = card->hw.irq; mb->cmd.length = 2; } mb->cmd.command = PPP_SET_INTR_FLAGS; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); return err;}/*============================================================================ * Enable communications. */static int ppp_comm_enable(sdla_t * card){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_COMM_ENABLE; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); return err;}/*============================================================================ * Disable communications. */static int ppp_comm_disable(sdla_t * card){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_COMM_DISABLE; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err != CMD_OK) ppp_error(card, err, mb); return err;}/*============================================================================ * Get communications error statistics. */static int ppp_get_err_stats(sdla_t * card){ ppp_mbox_t *mb = card->mbox; int err; memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); mb->cmd.command = PPP_READ_ERROR_STATS; err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; if (err == CMD_OK) { ppp_err_stats_t *stats = (void *) mb->data; card->wandev.stats.rx_over_errors = stats->rx_overrun; card->wandev.stats.rx_crc_errors = stats->rx_bad_crc; card->wandev.stats.rx_missed_errors = stats->rx_abort; card->wandev.stats.rx_length_errors = stats->rx_lost; card->wandev.stats.tx_aborted_errors = stats->tx_abort; } else ppp_error(card, err, mb); return err;}/*============================================================================ * Send packet. * Return: 0 - o.k. * 1 - no transmit buffers available */static int ppp_send(sdla_t * card, void *data, unsigned len, unsigned proto){ ppp_buf_ctl_t *txbuf = card->u.p.txbuf; unsigned long addr; if (txbuf->flag) return 1 ; if (card->hw.fwid == SFID_PPP502) addr = (txbuf->buf.o_p[1] << 8) + txbuf->buf.o_p[0]; else addr = txbuf->buf.ptr; sdla_poke(&card->hw, addr, data, len); txbuf->length = len; /* frame length */ if (proto == ETH_P_IPX) txbuf->proto = 0x01; /* protocol ID */ txbuf->flag = 1; /* start transmission */ /* Update transmit buffer control fields */ card->u.p.txbuf = ++txbuf; if ((void *) txbuf > card->u.p.txbuf_last) card->u.p.txbuf = card->u.p.txbuf_base; return 0;}/****** Firmware Error Handler **********************************************//*============================================================================ * Firmware error handler. * This routine is called whenever firmware command returns non-zero * return code. * * Return zero if previous command has to be cancelled. */static int ppp_error(sdla_t * card, int err, ppp_mbox_t * mb){ unsigned cmd = mb->cmd.command; switch (err) { case CMD_TIMEOUT: printk(KERN_ERR "%s: command 0x%02X timed out!\n", card->devname, cmd); break; default: printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n" ,card->devname, cmd, err); } return 0;}/****** Interrupt Handlers **************************************************//*============================================================================ * PPP interrupt service routine. */STATIC void wpp_isr(sdla_t * card){ ppp_flags_t *flags = card->flags; char *ptr = &flags->iflag; unsigned long host_cpu_flags; struct device *dev = card->wandev.dev; int i; card->in_isr = 1; ++card->statistics.isr_entry; if (test_and_set_bit(0, (void *) &card->wandev.critical)) { ++card->statistics.isr_already_critical; printk(KERN_INFO "%s: Critical while in ISR!\n", card->devname); card->in_isr = 0; return; } /* For all interrupts set the critical flag to CRITICAL_IN_ISR. * If the if_send routine is called with this flag set it will set * the enable transmit flag to 1. (for a delayed interrupt) */ card->wandev.critical = CRITICAL_IN_ISR; card->buff_int_mode_unbusy = 0; switch (flags->iflag) { case 0x01: /* receive interrupt */ ++card->statistics.isr_rx; rx_intr(card); break; case 0x02: /* transmit interrupt */ ++card->statistics.isr_tx; flags->imask &= ~0x02; dev->tbusy = 0; card->buff_int_mode_unbusy = 1; break; case 0x08: ++Intr_test_counter; ++card->statistics.isr_intr_test; break; default: /* unexpected interrupt */ ++card->statistics.isr_spurious; printk(KERN_INFO "%s: spurious interrupt 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"); } /* The critical flag is set to CRITICAL_INTR_HANDLED to let the * if_send call know that the interrupt is handled so that * transmit interrupts are not enabled again. */ card->wandev.critical = CRITICAL_INTR_HANDLED; /* If the enable transmit interrupt flag is set then enable transmit * interrupt on the board. This only goes through if if_send is called * and the critical flag is set due to an Interrupt. */ if (card->wandev.enable_tx_int) { flags->imask |= 0x02; card->wandev.enable_tx_int = 0; ++card->statistics.isr_enable_tx_int; } save_flags(host_cpu_flags); cli(); card->in_isr = 0; flags->iflag = 0; card->wandev.critical = 0; restore_flags(host_cpu_flags); if (card->buff_int_mode_unbusy) mark_bh(NET_BH);}/*============================================================================ * Receive interrupt handler. */static void rx_intr(sdla_t * card){ ppp_buf_ctl_t *rxbuf = card->rxmb; struct device *dev = card->wandev.dev; ppp_private_area_t *ppp_priv_area; struct sk_buff *skb; unsigned len; void *buf; int i, err; ppp_flags_t *flags = card->flags; char *ptr = &flags->iflag; int udp_type; if (rxbuf->flag != 0x01) { printk(KERN_INFO "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", card->devname, (unsigned) rxbuf, rxbuf->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; return; } if (dev && dev->start) { len = rxbuf->length; ppp_priv_area = dev->priv; /* Allocate socket buffer */ skb = dev_alloc_skb(len); if (skb != NULL) { /* Copy data to the socket buffer */ if (card->hw.fwid == SFID_PPP502) { unsigned addr = (rxbuf->buf.o_p[1] << 8) + rxbuf->buf.o_p[0]; buf = skb_put(skb, len); sdla_peek(&card->hw, addr, buf, len); } else { unsigned addr = rxbuf->buf.ptr; if ((addr + len) > card->u.p.rx_top + 1) { unsigned tmp = card->u.p.rx_top - addr + 1; buf = skb_put(skb, tmp); sdla_peek(&card->hw, addr, buf, tmp); addr = card->u.p.rx_base; len -= tmp; } buf = skb_put(skb, len); sdla_peek(&card->hw, addr, buf, len); } /* Decapsulate packet */ switch (rxbuf->proto) { case 0x00: skb->protocol = htons(ETH_P_IP); break; case 0x01: skb->protocol = htons(ETH_P_IPX); break; } udp_type = udp_pkt_type(skb, card); if (udp_type == UDP_DRVSTATS_TYPE) { ++ppp_priv_area->rx_intr_DRVSTATS_request; process_udp_driver_call( UDP_PKT_FRM_NETWORK, card, skb, dev, ppp_priv_area); dev_kfree_skb(skb); } else if (udp_type == UDP_PTPIPE_TYPE) { ++ppp_priv_area->rx_intr_PTPIPE_request; err = process_udp_mgmt_pkt( UDP_PKT_FRM_NETWORK, card, skb, dev, ppp_priv_area); dev_kfree_skb(skb); } else if (handle_IPXWAN(skb->data, card->devname, card->wandev.enable_IPX, card->wandev.network_number, skb->protocol)) { if (card->wandev.enable_IPX) { ppp_send(card, skb->data, skb->len, ETH_P_IPX); dev_kfree_skb(skb); } else { ++card->wandev.stats.rx_dropped; } } else { /* Pass it up the protocol stack */ skb->dev = dev; skb->mac.raw = skb->data; netif_rx(skb); ++card->wandev.stats.rx_packets; card->wandev.stats.rx_bytes += skb->len; ++ppp_priv_area->rx_intr_bfr_passed_to_stack; } } else { printk(KERN_INFO "%s: no socket buffers available!\n", card->devname); ++card->wandev.stats.rx_dropped; ++ppp_priv_area->rx_intr_no_socket; } } else ++card->statistics.rx_intr_dev_not_started; /* Release buffer element and calculate a pointer to the next one */ rxbuf->flag = (card->hw.fwid == SFID_PPP502) ? 0xFF : 0x00; card->rxmb = ++rxbuf; if ((void *) rxbuf > card->u.p.rxbuf_last) card->rxmb = card->u.p.rxbuf_base;}/*============================================================================ * Transmit interrupt handler. */static void tx_intr(sdla_t * card){ struct device *dev = card->wandev.dev; if (!dev || !dev->start) { ++card->statistics.tx_intr_dev_not_started; return; } dev->tbusy = 0; mark_bh(NET_BH);}static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto){ int i; if (proto == htons(ETH_P_IPX)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -