📄 c7000.c
字号:
/* Cisco/7000 driver -- Copyright (C) 2000 UTS Global LLC. Author: Bob Scardapane (UTS Global LLC). Version: 3. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. To use this driver, run the LINUX command: insmod c7000 base0=0xYYYY lhost0=s1 uhost0=s2 lappl0=s3 uappl0=s4 dbg=x base0=0xYYYY defines the base unit address of the interface. lhost0=s1 defines the local host name. uhost0=s2 defines the unit host name. lappl0=s3 defines the local application name. uappl0=s4 defines the unit application name. dbg=x defines the message level. Higher values will result in additional diagnostic messages. Additional interfaces are defined on insmod by using the variable name groups "base1,lhost1,lappl1,uhost1,uappl1", etc... up to three additional groups. In addition, the module will automatically detect the unit base addresses by scanning all active irq's for a control unit type of 0x3088 and a model of 0x61 (CLAW mode). The noauto parameter can be used to suppress automatic detection. The values of lhostx, lapplx, uhostx and uapplx default to: lapplx - TCPIP lhostx - UTS uapplx - TCPIP uhostx - C7011 Note that the values passed in the insmod command will always override the automatic detection of the unit base addreeses and the default values of lapplx, lhostx, uapplx and uhostx. The parameter noauto can be used to disable automatic detection of devices: noauto=1 (disable automatic detection) noauto=0 (Enable automatic detectio. This is the default value.) The values in base0 - base3 will be copied to the bases array when the module is loaded. To configure the interface(s), run the LINUX command(s): ifconfig ci0 ... ifconfig ci1 ... ifconfig ci2 ... ifconfig ci3 ... There is one device structure for each controller in the c7000_devices array. The base address of each controller is in the bases array. These arrays parallel each other. There is also one c7000_controller structure for each controller. This structure is pointed to by field priv in the individual device structure. In each c7000_controller, there are embedded c7000_unit structures. There is one c7000_unit structure per device number that makes up a controller (currently 2 units per controller).*/#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/slab.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/if_arp.h>#include <linux/tcp.h>#include <linux/skbuff.h>#include <asm/io.h>#include <asm/bitops.h>#include <asm/irq.h> /* Global defines*//* Maximum number of controllers.*/#define MAX_C7000 4/* Number of units per controller.*/#define NUNITS 2/* Define indexes of read and write units in the cunits array.*/#define C7000_RD 0#define C7000_WR 1/* Number of device buffers.*/#define C7000_MAXBUF 40/* Transmission queue length.*/#define C7000_TXQUEUE_LEN 100/* Size of the IP packet data.*/#define C7000_DATAL 4096/* Size of the read header data.*/#define C7000_READHDRL 4/* Size of read flag byte.*/#define C7000_READFFL 1/* Size of a device buffer. This is how it is arranged in memory: 4096 (IP packet data) + 4 (read header) + 1 (read flag) = 4101.*/#define C7000_BUFSIZE C7000_DATAL + C7000_READHDRL + C7000_READFFL/* Size of sigsmod data.*/#define C7000_SIGSMODL 1/* Flag value that indicates a read was completed in the flag field of a c7000_rd_header.*/#define FLAG_FF 0xff/* Size of C7000 sense id data.*/#define SIDL 32/* Maximum number of read and write retries.*/#define C7000_MAX_RETRIES 3/* Define sense byte0 value for a box reset.*/#define C7000_BOX_RESET 0x41/* CCW commands.*/#define C7000_WRITE_CCW 0x01 /* normal write */#define C7000_READ_CCW 0x02 /* normal read */#define C7000_NOOP_CCW 0x03 /* no operation */#define C7000_SIGSMOD_CCW 0x05 /* signal status modifier */#define C7000_TIC_CCW 0x08 /* transfer in channel */#define C7000_READHDR_CCW 0x12 /* read header */#define C7000_READFF_CCW 0x22 /* read FF flag */#define C7000_SID_CCW 0xe4 /* sense identification *//* Control commands.*/#define C7000_SYS_VALIDATE 1#define C7000_SYS_VALIDATE_RESP 2#define C7000_CONN_REQ 33#define C7000_CONN_RESP 34#define C7000_CONN_CONFRM 35#define C7000_DISCONN 36#define C7000_BOXERROR 65/* State machine values.*/#define C7000_INIT 1#define C7000_HALT 2#define C7000_SID 3#define C7000_SYSVAL 4#define C7000_CONNECT 5#define C7000_READY 6#define C7000_READ 7#define C7000_WRITE 8#define C7000_DISC 9#define C7000_STOP 10#define C7000_STOPPED 11#define C7000_ERROR 12/* The lower subchannel is used for read operations and the one that is one higher is used for write operations. Both subchannels are initially in state C7000_INIT. A transition to state C7000_HALT occurs when halt_IO is issued on each. When the halts completes a transition to state C7000_SID occurs and a channel program is issued to do a sense identification on both subchannels. When the sense identification completes, the state C7000_SYSVAL is entered on the read subchannel. A read channel program is issued. When the sense identification completes, the write subchannel enters state C7000_SYSVAL and a system validation request is written. The read subchannel is also put into this state. When both the system validation response is read and an inbound system validation request is read, the inbound system validation request is responded to and both subchannels enter the C7000_CONNECT state. A read channel program is posted to look for the inbound connect request. When that is received a connection confirmation is written. The state of both subchannels is then changed to C7000_READY. A read channel program is then posted and the state is changed to C7000_READ. When a read completes, the packet is sent to the higher layers and the read channel program is restarted. When there is a packet to be written, state C7000_WRITE is entered and a channel program is issued to write the data. The subchannel is in state C7000_READY when there is nothing to be written. When the stop method is executed, a disconnect message is sent and the state is changed to C7000_DISC in both subchannels. A halt_IO will be issued to both subchannels and state C7000_STOP will be entered. When the halt IO completes, state C7000_STOPPED will be set. State C7000_ERROR is set when an error occurs in the interrupt routine. Recycle the interface (ifconfig down / ifconfig up) to reset this state.*//* Results from c7000_check_csw.*/enum c7000_rupt { C7000_NORMAL, C7000_CHANERR, C7000_UCK, C7000_UCK_RESET, C7000_UE, C7000_ATTN, C7000_BUSY, C7000_OTHER};/* Bits set in device structure tbusy field.*/#define TB_TX 0 /* sk buffer handling in progress */#define TB_STOP 1 /* network device stop in progress */#define TB_RETRY 2 /* retry in progress */#define TB_NOBUFFER 3 /* no buffer on free queue *//* Bit in c7000_unit.flag_a that indicates the bh routine is busy.*/#define C7000_BH_ACTIVE 0#define CPrintk(level, args...) \ if (level <= dbg) \ printk(args)/* Maximum length of a system validation string.*/#define NAMLEN 8#define Err_Conn_Confirm 1#define Err_Names_not_Matched 166#define Err_C7000_NOT_READY 167#define Err_Duplicate 170#define Err_Closing 171#define Err_No_Such_App 172#define Err_Host_Not_Ready 173#define Err_CLOSING 174#define Err_Dup_Link 175#define Err_Wrong_Version 179#define Err_Wrong_Frame_Size 180/* Define a macro to extract the logical link identifier from the c7000 read header command field.*/#define C7000_LINKID(cmd) ((unsigned char)cmd >> 3)/* Define the control unit type for a Cisco 7000.*/#define C7000_CU_TYPE 0x3088/* Define the control unit model for a Cisco 7000.*/#define C7000_CU_MODEL 0x61/* Define the default system validate parameters (lapplx, lhostx, uapplx, uhostx).*/#define C7000_DFLT_LAPPL "TCPIP"#define C7000_DFLT_LHOST "UTS"#define C7000_DFLT_UAPPL "TCPIP"#define C7000_DFLT_UHOST "C7011"/* Global variables.*//* Base device addresses of the controllers.*/static int base0 = -1;static int base1 = -1;static int base2 = -1;static int base3 = -1;static int bases[MAX_C7000];/* Local application names.*/static char *lappl0;static char *lappl1;static char *lappl2;static char *lappl3;/* Local host names.*/static char *lhost0;static char *lhost1;static char *lhost2;static char *lhost3;/* Unit application names.*/static char *uappl0;static char *uappl1;static char *uappl2;static char *uappl3;/* Unit hosts names.*/static char *uhost0;static char *uhost1;static char *uhost2;static char *uhost3;/* Debugging level (higher numbers emit lower priority messages).*/static unsigned int dbg = 0;/* Parameter that controls auto detection.*/static int noauto = 0;/* Interface names.*/static char ifnames[MAX_C7000][8] = {"ci0", "ci1", "ci2", "ci3"};/* One device structure per controller.*/struct net_device c7000_devices[MAX_C7000];/* Scratch variable filled in with controller name.*/static char *controller;/* Identify parameters that can be passed on the LINUX insmod command.*/MODULE_AUTHOR("Robert Scardapane (UTS Global)");MODULE_DESCRIPTION("Network module for Cisco 7000 box.");MODULE_LICENSE("GPL");MODULE_PARM(base0, "1i");MODULE_PARM_DESC(base0, "Base unit address for 1st C7000 box.");MODULE_PARM(base1, "1i");MODULE_PARM_DESC(base1, "Base unit address for 2nd C7000 box.");MODULE_PARM(base2, "1i");MODULE_PARM_DESC(base2, "Base unit address for 3rd C7000 box.");MODULE_PARM(base3, "1i");MODULE_PARM_DESC(base3, "Base unit address for 4th C7000 box.");MODULE_PARM(lappl0, "s");MODULE_PARM_DESC(lappl0, "Application name for 1st C7000 box.");MODULE_PARM(lappl1, "s");MODULE_PARM_DESC(lappl1, "Application name for 2nd C7000 box.");MODULE_PARM(lappl2, "s");MODULE_PARM_DESC(lappl2, "Application name for 3rd C7000 box.");MODULE_PARM(lappl3, "s");MODULE_PARM_DESC(lappl3, "Application name for 4th C7000 box.");MODULE_PARM(lhost0, "s");MODULE_PARM_DESC(lhost0, "Host name for 1st C7000 box.");MODULE_PARM(lhost1, "s");MODULE_PARM_DESC(lhost1, "Host name for 2nd C7000 box.");MODULE_PARM(lhost2, "s");MODULE_PARM_DESC(lhost2, "Host name for 3rd C7000 box.");MODULE_PARM(lhost3, "s");MODULE_PARM_DESC(lhost3, "Host name for 4th C7000 box.");MODULE_PARM(uhost0, "s");MODULE_PARM_DESC(uhost0, "Unit name for 1st C7000 box.");MODULE_PARM(uhost1, "s");MODULE_PARM_DESC(uhost1, "Unit name for 2nd C7000 box.");MODULE_PARM(uhost2, "s");MODULE_PARM_DESC(uhost2, "Unit name for 3rd C7000 box.");MODULE_PARM(uhost3, "s");MODULE_PARM_DESC(uhost3, "Unit name for 4th C7000 box.");MODULE_PARM(uappl0, "s");MODULE_PARM_DESC(uappl0, "Unit application name for 1st C7000 box.");MODULE_PARM(uappl1, "s");MODULE_PARM_DESC(uappl1, "Unit application name for 2nd C7000 box.");MODULE_PARM(uappl2, "s");MODULE_PARM_DESC(uappl2, "Unit application name for 3rd C7000 box.");MODULE_PARM(uappl3, "s");MODULE_PARM_DESC(uappl3, "Unit application name for 4th C7000 box.");MODULE_PARM(dbg, "1i");MODULE_PARM_DESC(dbg, "Message level for debugging.");MODULE_PARM(noauto, "1i");MODULE_PARM_DESC(noauto, "Control automatic detection of unit base addresses.");/* Structure used to manage unit buffers.*/struct c7000_buffer { ccw1_t ccws[7]; /* channel program */ struct c7000_buffer *next; /* list pointer */ char *data; /* pointer to actual data */ int len; /* length of the data */};/* C7000 Control Block. */struct c7000_control_blk { unsigned char cmd; unsigned char ver; unsigned char link_id; unsigned char correlator; unsigned char ret_code; unsigned char resvd1[3]; unsigned char unitname[NAMLEN]; unsigned char hostname[NAMLEN]; unsigned short rdsize; /* read frame size */ unsigned short wrtsize; /* write frame size */ unsigned char resvd2[4];};/* Per unit structure contained within the c7000_controller structure.*/struct c7000_unit { ccw1_t ccws[5]; /* control ccws */ int devno; /* device number */ int irq; /* subchannel number */ unsigned long IO_active; /* IO activity flag */ int state; /* fsm state */ int retries; /* retry counter */ unsigned long flag_a; /* bh activity flag */ devstat_t devstat; /* device status */ wait_queue_head_t wait; /* sleep q head */ struct c7000_controller *cntlp; /* controller pointer */ struct c7000_buffer *free; /* free buffer anchor */ struct c7000_buffer *proc_head; /* proc head */ struct c7000_buffer *proc_tail; /* proc tail */ struct c7000_buffer *bh_head; /* bh head */ struct c7000_buffer *bh_tail; /* bh tail */ struct tq_struct tq; /* bh scheduling */ char senseid[SIDL]; /* sense id data */ struct c7000_control_blk control_blk; /* control block */ unsigned char sigsmod; /* sigsmod flag */ unsigned char readhdr[4]; /* read header */ unsigned char readff; /* readff flag */};/* Private structure pointed to by dev->priv.*/struct c7000_controller { struct net_device_stats stats; /* statistics */ struct net_device *dev; /* -> device struct */ unsigned int base_addr; /* base address */ char lappl[NAMLEN]; /* local appl */ char lhost[NAMLEN]; /* local host */ char uappl[NAMLEN]; /* unit appl */ char uhost[NAMLEN]; /* unit host */ unsigned char version; /* version = 2 */ unsigned char linkid; /* link id */ struct c7000_unit cunits[NUNITS]; /* embedded units */ unsigned long tbusy;};/* This is the structure returned by the C7000_READHDR_CCW.*/struct c7000_rd_header { unsigned short len; /* packet length */ unsigned char cmd; /* command code */ unsigned char flag; /* flag */};/* Set the device structure transmission busy flag.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -