📄 farsync.c
字号:
* and that some basic parameters are correct */static voidcheck_started_ok ( struct fst_card_info *card ){ int i; /* Check structure version and end marker */ if ( FST_RDW ( card, smcVersion ) != SMC_VERSION ) { printk_err ("Bad shared memory version %d expected %d\n", FST_RDW ( card, smcVersion ), SMC_VERSION ); card->state = FST_BADVERSION; return; } if ( FST_RDL ( card, endOfSmcSignature ) != END_SIG ) { printk_err ("Missing shared memory signature\n"); card->state = FST_BADVERSION; return; } /* Firmware status flag, 0x00 = initialising, 0x01 = OK, 0xFF = fail */ if (( i = FST_RDB ( card, taskStatus )) == 0x01 ) { card->state = FST_RUNNING; } else if ( i == 0xFF ) { printk_err ("Firmware initialisation failed. Card halted\n"); card->state = FST_HALTED; return; } else if ( i != 0x00 ) { printk_err ("Unknown firmware status 0x%x\n", i ); card->state = FST_HALTED; return; } /* Finally check the number of ports reported by firmware against the * number we assumed at card detection. Should never happen with * existing firmware etc so we just report it for the moment. */ if ( FST_RDL ( card, numberOfPorts ) != card->nports ) { printk_warn ("Port count mismatch." " Firmware thinks %d we say %d\n", FST_RDL ( card, numberOfPorts ), card->nports ); }}static intfst_change_mtu ( struct net_device *dev, int new_mtu ){ if ( new_mtu < 128 || new_mtu > FST_MAX_MTU ) return -EINVAL; dev->mtu = new_mtu; return 0;}/* Sooner or later you can't avoid a forward declaration */static int fst_ioctl ( struct net_device *dev, struct ifreq *ifr, int cmd );static intswitch_proto ( struct fst_port_info *port, int new_proto ){ int err; int orig_mtu; struct net_device *dev; dev = port->dev; /* Turn off sPPP module ? */ if (( new_proto != FST_HDLC && new_proto != FST_PPP ) && ( port->proto == FST_HDLC || port->proto == FST_PPP )) { sppp_close ( port->pppdev.dev ); sppp_detach ( port->pppdev.dev ); /* Reset some fields overwritten by sPPP */ dev->hard_header = NULL; dev->rebuild_header = NULL; dev->tx_queue_len = FST_TX_QUEUE_LEN; dev->type = ARPHRD_MYTYPE; dev->addr_len = 0; dev->hard_header_len = 0; dev->do_ioctl = fst_ioctl; dev->change_mtu = fst_change_mtu; dev->flags = IFF_POINTOPOINT|IFF_NOARP; return 0; } /* Turn on sPPP ? */ if (( new_proto == FST_HDLC || new_proto == FST_PPP ) && ( port->proto != FST_HDLC && port->proto != FST_PPP )) { orig_mtu = dev->mtu; /* Attach to sync PPP module */ port->pppdev.dev = dev; sppp_attach ( &port->pppdev ); if ( orig_mtu < dev->mtu ) dev->change_mtu ( dev, orig_mtu ); /* Claw back the ioctl routine. We promise to be good and call * the sync PPP routines once we've eliminated our functions. */ dev->do_ioctl = fst_ioctl; /* Set the mode */ if ( new_proto == FST_HDLC ) { err = sppp_do_ioctl ( port->pppdev.dev, NULL, SPPPIOCCISCO ); } else { err = sppp_do_ioctl ( port->pppdev.dev, NULL, SPPPIOCPPP ); } /* Open the device */ if ( err == 0 ) { (void) sppp_open ( port->dev ); } return err; } /* Switch sPPP mode to that desired */ err = 0; if ( new_proto == FST_HDLC && port->pppdev.dev != NULL ) { err = sppp_do_ioctl ( port->pppdev.dev, NULL, SPPPIOCCISCO ); } else if ( new_proto == FST_PPP && port->pppdev.dev != NULL ) { err = sppp_do_ioctl ( port->pppdev.dev, NULL, SPPPIOCPPP ); } /* Anything else is switching from one raw mode to another which is * basically a NOP */ return err;}static intset_conf_from_info ( struct fst_card_info *card, struct fst_port_info *port, struct fstioc_info *info ){ int err; /* Set things according to the user set valid flags */ err = 0; if ( info->valid & FSTVAL_PROTO ) { if ( port->proto != info->proto ) { err = switch_proto ( port, info->proto ); if ( err == 0 ) port->proto = info->proto; } } if ( info->valid & FSTVAL_CABLE ) { FST_WRB ( card, portConfig[port->index].lineInterface, info->lineInterface ); port->hwif = info->lineInterface; } if ( info->valid & FSTVAL_SPEED ) { FST_WRL ( card, portConfig[port->index].lineSpeed, info->lineSpeed ); FST_WRB ( card, portConfig[port->index].internalClock, info->internalClock ); } if ( info->valid & FSTVAL_MODE ) { FST_WRW ( card, cardMode, info->cardMode ); }#if FST_DEBUG if ( info->valid & FSTVAL_DEBUG ) { fst_debug_mask = info->debug; }#endif return err;}static voidgather_conf_info ( struct fst_card_info *card, struct fst_port_info *port, struct fstioc_info *info ){ int i; memset ( info, 0, sizeof ( struct fstioc_info )); i = port->index; info->nports = card->nports; info->type = card->type; info->state = card->state; info->proto = port->proto; info->index = i;#if FST_DEBUG info->debug = fst_debug_mask;#endif /* Only mark information as valid if card is running. * Copy the data anyway in case it is useful for diagnostics */ info->valid = (( card->state == FST_RUNNING ) ? FSTVAL_ALL : FSTVAL_CARD )#if FST_DEBUG | FSTVAL_DEBUG#endif ; info->lineInterface = FST_RDW ( card, portConfig[i].lineInterface ); info->internalClock = FST_RDB ( card, portConfig[i].internalClock ); info->lineSpeed = FST_RDL ( card, portConfig[i].lineSpeed ); info->v24IpSts = FST_RDL ( card, v24IpSts[i] ); info->v24OpSts = FST_RDL ( card, v24OpSts[i] ); info->clockStatus = FST_RDW ( card, clockStatus[i] ); info->cableStatus = FST_RDW ( card, cableStatus ); info->cardMode = FST_RDW ( card, cardMode ); info->smcFirmwareVersion = FST_RDL ( card, smcFirmwareVersion );}static intfst_ioctl ( struct net_device *dev, struct ifreq *ifr, int cmd ){ struct fst_card_info *card; struct fst_port_info *port; struct fstioc_write wrthdr; struct fstioc_info info; unsigned long flags; dbg ( DBG_IOCTL,"ioctl: %x, %p\n", cmd, ifr->ifr_data ); port = dev->priv; card = port->card; if ( !capable ( CAP_NET_ADMIN )) return -EPERM; switch ( cmd ) { case FSTCPURESET: fst_cpureset ( card ); card->state = FST_RESET; return 0; case FSTCPURELEASE: fst_cpurelease ( card ); card->state = FST_STARTING; return 0; case FSTWRITE: /* Code write (download) */ /* First copy in the header with the length and offset of data * to write */ if ( ifr->ifr_data == NULL ) { return -EINVAL; } if ( copy_from_user ( &wrthdr, ifr->ifr_data, sizeof ( struct fstioc_write ))) { return -EFAULT; } /* Sanity check the parameters. We don't support partial writes * when going over the top */ if ( wrthdr.size > FST_MEMSIZE || wrthdr.offset > FST_MEMSIZE || wrthdr.size + wrthdr.offset > FST_MEMSIZE ) { return -ENXIO; } /* Now copy the data to the card. * This will probably break on some architectures. * I'll fix it when I have something to test on. */ if ( copy_from_user ( card->mem + wrthdr.offset, ifr->ifr_data + sizeof ( struct fstioc_write ), wrthdr.size )) { return -EFAULT; } /* Writes to the memory of a card in the reset state constitute * a download */ if ( card->state == FST_RESET ) { card->state = FST_DOWNLOAD; } return 0; case FSTGETCONF: /* If card has just been started check the shared memory config * version and marker */ if ( card->state == FST_STARTING ) { check_started_ok ( card ); /* If everything checked out enable card interrupts */ if ( card->state == FST_RUNNING ) { spin_lock_irqsave ( &card->card_lock, flags ); fst_clear_intr ( card ); FST_WRB ( card, interruptHandshake, 0xEE ); spin_unlock_irqrestore ( &card->card_lock, flags ); } } if ( ifr->ifr_data == NULL ) { return -EINVAL; } gather_conf_info ( card, port, &info ); if ( copy_to_user ( ifr->ifr_data, &info, sizeof ( info ))) { return -EFAULT; } return 0; case FSTSETCONF: if ( copy_from_user ( &info, ifr->ifr_data, sizeof ( info ))) { return -EFAULT; } return set_conf_from_info ( card, port, &info ); default: /* Not one of ours. Pass it through to sPPP package */ if ( port->proto == FST_HDLC || port->proto == FST_PPP ) return sppp_do_ioctl ( dev, ifr, cmd ); else return -EINVAL; }}static voidfst_openport ( struct fst_port_info *port ){ int signals; /* Only init things if card is actually running. This allows open to * succeed for downloads etc. */ if ( port->card->state == FST_RUNNING ) { if ( port->run ) { dbg ( DBG_OPEN,"open: found port already running\n"); fst_issue_cmd ( port, STOPPORT ); port->run = 0; } fst_rx_config ( port ); fst_tx_config ( port ); fst_op_raise ( port, OPSTS_RTS | OPSTS_DTR ); fst_issue_cmd ( port, STARTPORT ); port->run = 1; signals = FST_RDL ( port->card, v24DebouncedSts[port->index]); if ( signals & (( port->hwif == X21 ) ? IPSTS_INDICATE : IPSTS_DCD )) netif_carrier_on ( port->dev ); else netif_carrier_off ( port->dev ); }}static voidfst_closeport ( struct fst_port_info *port ){ if ( port->card->state == FST_RUNNING ) { if ( port->run ) { port->run = 0; fst_op_lower ( port, OPSTS_RTS | OPSTS_DTR ); fst_issue_cmd ( port, STOPPORT ); } else { dbg ( DBG_OPEN,"close: port not running\n"); } }}static intfst_open ( struct net_device *dev ){ struct fst_card_info *card; struct fst_port_info *port; int orig_mtu; int err; MOD_INC_USE_COUNT; port = dev->priv; card = port->card; switch ( port->proto ) { case FST_HDLC: case FST_PPP: orig_mtu = dev->mtu; /* Attach to sync PPP module */ port->pppdev.dev = dev; sppp_attach ( &port->pppdev ); if ( orig_mtu < dev->mtu ) dev->change_mtu ( dev, orig_mtu ); /* Claw back the ioctl routine. We promise to be good and call * the sync PPP routines once we've eliminated our functions. */ dev->do_ioctl = fst_ioctl; err = sppp_do_ioctl ( dev, NULL, port->proto == FST_HDLC ? SPPPIOCCISCO : SPPPIOCPPP ); if ( err ) { sppp_detach ( dev ); MOD_DEC_USE_COUNT; return err; } err = sppp_open ( dev ); if ( err )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -