⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  drivers/s390/net/ctc.c  *    CTC / ESCON network driver * *  S390 version *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation *    Author(s): Dieter Wellerdiek (wel@de.ibm.com) * *     2.3 Updates Martin Schwidefsky (schwidefsky@de.ibm.com) *                 Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) * * *  Description of the Kernel Parameter *    Normally the CTC driver selects the channels in order (automatic channel  *    selection). If your installation needs to use the channels in a different  *    order or doesn't want to have automatic channel selection on, you can do  *    this with the "ctc= kernel keyword".  * *       ctc=0,0xrrrr,0xwwww,ddddd * *     Where: * *       "rrrr" is the read channel address *       "wwww" is the write channel address *       "dddd" is the network device (ctc0 to ctc7 for a parallel channel, escon0 *              to escon7 for ESCON channels). * *     To switch the automatic channel selection off use the ctc= keyword with  *     parameter "noauto". This may be necessary if you 3271 devices or other devices  *     which use the ctc device type and model, but operate with a different protocol.  *      *       ctc=noauto * *  Change History *    0.50  Initial release shipped *    0.51  Bug fixes *          - CTC / ESCON network device can now handle up to 64 channels  *          - 3088-61 info message supperssed - CISCO 7206 - CLAW - ESCON  *          - 3088-62 info message suppressed - OSA/D    *          - channel: def ffffffed ... error message suppressed  *          - CTC / ESCON device was not recoverable after a lost connection with  *            IFCONFIG dev DOWN and IFCONFIG dev UP  *          - Possibility to switch the automatic selection off *          - Minor bug fixes  */#include <linux/version.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/malloc.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/interrupt.h>#include <linux/timer.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/string.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/ip.h>#include <linux/if_arp.h>#include <linux/tcp.h>#include <linux/skbuff.h>#include <asm/io.h>#include <asm/bitops.h> #include <asm/irq.h>//#define DEBUG /* Redefine message level, so that all messages occur on 3215 console in DEBUG mode */#ifdef DEBUG                        #undef  KERN_INFO        #undef  KERN_WARNING        #undef  KERN_DEBUG        #define KERN_INFO    KERN_EMERG        #define KERN_WARNING KERN_EMERG        #define KERN_DEBUG   KERN_EMERG#endif  //#undef DEBUG#define CCW_CMD_WRITE           0x01#define CCW_CMD_READ            0x02#define CCW_CMD_SET_EXTENDED    0xc3#define CCW_CMD_PREPARE         0xe3#define MAX_CHANNEL_DEVICES     64 #define MAX_ADAPTERS            8#define CTC_DEFAULT_MTU_SIZE    1500#define READ                    0#define WRITE                   1#define CTC                     0#define ESCON                   1#define CHANNEL_MEDIA           2#define CTC_BLOCKS              8          /* 8 blocks * 2 times * 64k = 1M */#define TB_TX                   0          /* sk buffer handling in process */#define TB_STOP                 1          /* network device stop in process */#define TB_RETRY                2          /* retry in process */#define TB_NOBUFFER             3          /* no buffer on free queue */ /* state machine codes used in ctc_irq_handler */#define CTC_STOP                0#define CTC_START_HALT_IO       1#define CTC_START_SET_X_MODE    2#define CTC_START_SELECT        4 #define CTC_START_READ_TEST     32#define CTC_START_READ          33#define CTC_START_WRITE_TEST    64#define CTC_START_WRITE         65typedef enum {         channel_type_none,           /* Device is not a channel */        channel_type_undefined,      /* Device is a channel but we don't know anything about it */        channel_type_ctca,           /* Device is a CTC/A and we can deal with it */        channel_type_escon,          /* Device is a ESCON channel and we can deal with it */        channel_type_unsupported     /* Device is a unsupported model */} channel_type_t;   /*  *   Structures needed in the initial phase  * */  static int channel_tab_initialized = 0;     /* channel[] structure initialized */struct devicelist {          unsigned int  devno;        __u8          flag;#define CHANNEL_IN_USE   0x08               /* - Show that channel is in use */}; static struct {        struct devicelist  list[MAX_CHANNEL_DEVICES];         int                count;        int                left;} channel[CHANNEL_MEDIA];static int ctc_no_auto = 0;struct adapterlist{         unsigned int       devno[2];        __u16              protocol;};static struct adapterlist ctc_adapter[CHANNEL_MEDIA][MAX_ADAPTERS];  /* 0 = CTC  / 1 = ESCON *//*  *   Structure used after the initial phase  * */    struct buffer {        struct buffer       *next;        int                 packets;        struct block        *block;};#if LINUX_VERSION_CODE>=0x020300typedef struct net_device  net_device;#elsetypedef struct device  net_device;typedef struct wait_queue* wait_queue_head_t;#define DECLARE_WAITQUEUE(waitqname,waitqtask) struct wait_queue  waitqname = {waitqtask, NULL }#define init_waitqueue_head(nothing)#endifstruct channel {        unsigned int        devno;        int                 irq;        unsigned long       IO_active;        ccw1_t              ccw[3];        __u32               state;         int                 buffer_count;        struct buffer       *free_anchor;        struct buffer       *proc_anchor;        devstat_t           *devstat;        net_device   *dev;      /* backward pointer to the network device */ 	wait_queue_head_t   wait;        struct tq_struct    tq;        struct timer_list   timer;        unsigned long       flag_a;    /* atomic flags */#define CTC_BH_ACTIVE       0           __u8                last_dstat;        __u8                flag;#define CTC_WRITE            0x01      /* - Set if this is a write channel */#define CTC_TIMER            0x80      /* - Set if timer made the wake_up  */ };struct ctc_priv {                                                                            struct net_device_stats  stats;#if LINUX_VERSION_CODE>=0x02032D	int                      tbusy;#endif        struct channel           channel[2];         __u16                    protocol;};  /* *   This structure works as shuttle between two systems  *    - A block can contain one or more packets  */#define PACKET_HEADER_LENGTH  6struct packet {        __u16         length;        __u16         type;        __u16         unused;        __u8          data;}; #define BLOCK_HEADER_LENGTH   2struct block {        __u16         length;        struct packet data;};#if LINUX_VERSION_CODE>=0x02032D#define ctc_protect_busy(dev) \s390irq_spin_lock(((struct ctc_priv *)dev->priv)->channel[WRITE].irq)#define ctc_unprotect_busy(dev) \s390irq_spin_unlock(((struct ctc_priv *)dev->priv)->channel[WRITE].irq)#define ctc_protect_busy_irqsave(dev,flags) \s390irq_spin_lock_irqsave(((struct ctc_priv *)dev->priv)->channel[WRITE].irq,flags)#define ctc_unprotect_busy_irqrestore(dev,flags) \s390irq_spin_unlock_irqrestore(((struct ctc_priv *)dev->priv)->channel[WRITE].irq,flags)static __inline__ void ctc_set_busy(net_device *dev){	((struct ctc_priv *)dev->priv)->tbusy=1;	netif_stop_queue(dev);}static __inline__ void ctc_clear_busy(net_device *dev){	((struct ctc_priv *)dev->priv)->tbusy=0;	netif_start_queue(dev);}static __inline__ int ctc_check_busy(net_device *dev){	eieio();	return(((struct ctc_priv *)dev->priv)->tbusy);}static __inline__ void ctc_setbit_busy(int nr,net_device *dev){	set_bit(nr,&(((struct ctc_priv *)dev->priv)->tbusy));	netif_stop_queue(dev);	}static __inline__ void ctc_clearbit_busy(int nr,net_device *dev){	clear_bit(nr,&(((struct ctc_priv *)dev->priv)->tbusy));	if(((struct ctc_priv *)dev->priv)->tbusy==0)		netif_start_queue(dev);}static __inline__ int ctc_test_and_setbit_busy(int nr,net_device *dev){	netif_stop_queue(dev);	return(test_and_set_bit(nr,&((struct ctc_priv *)dev->priv)->tbusy));}#else#define ctc_protect_busy(dev)#define ctc_unprotect_busy(dev)#define ctc_protect_busy_irqsave(dev,flags)#define ctc_unprotect_busy_irqrestore(dev,flags)static __inline__ void ctc_set_busy(net_device *dev){	dev->tbusy=1;	eieio();}static __inline__ void ctc_clear_busy(net_device *dev){	dev->tbusy=0;	eieio();}static __inline__ int ctc_check_busy(net_device *dev){	eieio();	return(dev->tbusy);}static __inline__ void ctc_setbit_busy(int nr,net_device *dev){	set_bit(nr,(void *)&dev->tbusy);}static __inline__ void ctc_clearbit_busy(int nr,net_device *dev){	clear_bit(nr,(void *)&dev->tbusy);}static __inline__ int ctc_test_and_setbit_busy(int nr,net_device *dev){	return(test_and_set_bit(nr,(void *)&dev->tbusy));}#endif/* Interrupt handler */static void ctc_irq_handler(int irq, void *initparm, struct pt_regs *regs);static void ctc_irq_bh(struct channel *ctc); static void ctc_read_retry (struct channel *ctc);static void ctc_write_retry (struct channel *ctc);/* Functions for the DEV methods */int ctc_probe(net_device *dev); static int ctc_open(net_device *dev); static void ctc_timer (struct channel *ctc);static int ctc_release(net_device *dev);static int ctc_tx(struct sk_buff *skb, net_device *dev);static int ctc_change_mtu(net_device *dev, int new_mtu);struct net_device_stats* ctc_stats(net_device *dev); /* *   Channel Routines  * */ static void channel_init(void);static void channel_scan(void);static int channel_get(int media, int devno);static int channel_get_next(int media); static int channel_free(int media, int devno);static channel_type_t channel_check_for_type (senseid_t *id);static void channel_sort(struct devicelist list[], int n);/* * initialize the channel[].list  */   static void channel_init(void) {        int     m;#ifdef DEBUG        int     c;#endif        if (!test_and_set_bit(0, (void *)& channel_tab_initialized)){                channel_scan();                 for (m = 0; m < CHANNEL_MEDIA; m++) {                         channel_sort (channel[m].list, MAX_CHANNEL_DEVICES);                         channel[m].left = channel[m].count;                   }                if (channel[CTC].count == 0 && channel[ESCON].count == 0)                         printk(KERN_INFO "channel: no Channel devices recognized\n");                else                        printk(KERN_INFO "channel: %d Parallel channel found - %d ESCON channel found\n",                            channel[CTC].count, channel[ESCON].count);  #ifdef DEBUG                 for (m = 0; m < CHANNEL_MEDIA;  m++) {                         for (c = 0; c < MAX_CHANNEL_DEVICES; c++){                                printk(KERN_DEBUG "channel: Adapter=%x Entry=%x devno=%04x\n",                                      m, c, channel[m].list[c].devno);                        }                }#endif         }}/** scan for all channels and put the device numbers into the channel[].list */  static void channel_scan(void){        int        m;        int        c;        int        irq;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -