📄 farsync.c
字号:
break; default: printk_err ("intr: unknown card event code. ignored\n"); break; } /* Bump and wrap the index */ if ( ++rdidx >= MAX_CIRBUFF ) rdidx = 0; } FST_WRB ( card, interruptEvent.rdindex, rdidx ); for ( pi = 0, port = card->ports ; pi < card->nports ; pi++, port++ ) { if ( ! port->run ) continue; /* Check for rx completions */ while ( ! ( FST_RDB ( card, rxDescrRing[pi][port->rxpos].bits ) & DMA_OWN )) { fst_intr_rx ( card, port ); } /* Check for Tx completions */ while ( port->txcnt > 0 && ! ( FST_RDB ( card, txDescrRing[pi][port->txipos].bits ) & DMA_OWN )) { --port->txcnt; if ( ++port->txipos >= NUM_TX_BUFFER ) port->txipos = 0; netif_wake_queue ( port_to_dev ( port )); } } spin_unlock ( &card->card_lock );}/* Check that the shared memory configuration is one that we can handle * 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 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. * Several of the old options have been invalidated/replaced by the * generic HDLC package. */ err = 0; if ( info->valid & FSTVAL_PROTO ) err = -EINVAL; if ( info->valid & FSTVAL_CABLE ) err = -EINVAL; if ( info->valid & FSTVAL_SPEED ) err = -EINVAL; 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 = FST_GEN_HDLC; 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_set_iface ( struct fst_card_info *card, struct fst_port_info *port, struct ifreq *ifr ){ sync_serial_settings sync; int i; if (copy_from_user (&sync, ifr->ifr_settings.ifs_ifsu.sync, sizeof (sync))) return -EFAULT; if ( sync.loopback ) return -EINVAL; i = port->index; switch (ifr->ifr_settings.type) { case IF_IFACE_V35: FST_WRW ( card, portConfig[i].lineInterface, V35 ); port->hwif = V35; break; case IF_IFACE_V24: FST_WRW ( card, portConfig[i].lineInterface, V24 ); port->hwif = V24; break; case IF_IFACE_X21: FST_WRW ( card, portConfig[i].lineInterface, X21 ); port->hwif = X21; break; case IF_IFACE_SYNC_SERIAL: break; default: return -EINVAL; } switch ( sync.clock_type ) { case CLOCK_EXT: FST_WRB ( card, portConfig[i].internalClock, EXTCLK ); break; case CLOCK_INT: FST_WRB ( card, portConfig[i].internalClock, INTCLK ); break; default: return -EINVAL; } FST_WRL ( card, portConfig[i].lineSpeed, sync.clock_rate ); return 0;}static intfst_get_iface ( struct fst_card_info *card, struct fst_port_info *port, struct ifreq *ifr ){ sync_serial_settings sync; int i; /* First check what line type is set, we'll default to reporting X.21 * if nothing is set as IF_IFACE_SYNC_SERIAL implies it can't be * changed */ switch ( port->hwif ) { case V35: ifr->ifr_settings.type = IF_IFACE_V35; break; case V24: ifr->ifr_settings.type = IF_IFACE_V24; break; case X21: default: ifr->ifr_settings.type = IF_IFACE_X21; break; } if (ifr->ifr_settings.size < sizeof(sync)) { ifr->ifr_settings.size = sizeof(sync); /* data size wanted */ return -ENOBUFS; } i = port->index; sync.clock_rate = FST_RDL ( card, portConfig[i].lineSpeed ); /* Lucky card and linux use same encoding here */ sync.clock_type = FST_RDB ( card, portConfig[i].internalClock ); sync.loopback = 0; if (copy_to_user (ifr->ifr_settings.ifs_ifsu.sync, &sync, sizeof(sync))) return -EFAULT; return 0;}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_to_port ( dev ); 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: /* Most of the setting have been moved to the generic ioctls * this just covers debug and board ident mode now */ if ( copy_from_user ( &info, ifr->ifr_data, sizeof ( info ))) { return -EFAULT; } return set_conf_from_info ( card, port, &info ); case SIOCWANDEV: switch (ifr->ifr_settings.type) { case IF_GET_IFACE: return fst_get_iface ( card, port, ifr ); case IF_IFACE_SYNC_SERIAL: case IF_IFACE_V35: case IF_IFACE_V24: case IF_IFACE_X21: return fst_set_iface ( card, port, ifr ); default: return hdlc_ioctl ( dev, ifr, cmd ); } default: /* Not one of ours. Pass through to HDLC package */ return hdlc_ioctl ( dev, ifr, cmd ); }}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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -