📄 claw.c
字号:
/* * drivers/s390/net/claw.c * ESCON CLAW network driver * * $Revision: 1.38 $ $Date: 2005/08/29 09:47:04 $ * * Linux for zSeries version * Copyright (C) 2002,2005 IBM Corporation * Author(s) Original code written by: * Kazuo Iimura (iimura@jp.ibm.com) * Rewritten by * Andy Richter (richtera@us.ibm.com) * Marc Price (mwprice@us.ibm.com) * * sysfs parms: * group x.x.rrrr,x.x.wwww * read_buffer nnnnnnn * write_buffer nnnnnn * host_name aaaaaaaa * adapter_name aaaaaaaa * api_type aaaaaaaa * * eg. * group 0.0.0200 0.0.0201 * read_buffer 25 * write_buffer 20 * host_name LINUX390 * adapter_name RS6K * api_type TCPIP * * where * * The device id is decided by the order entries * are added to the group the first is claw0 the second claw1 * up to CLAW_MAX_DEV * * rrrr - the first of 2 consecutive device addresses used for the * CLAW protocol. * The specified address is always used as the input (Read) * channel and the next address is used as the output channel. * * wwww - the second of 2 consecutive device addresses used for * the CLAW protocol. * The specified address is always used as the output * channel and the previous address is used as the input channel. * * read_buffer - specifies number of input buffers to allocate. * write_buffer - specifies number of output buffers to allocate. * host_name - host name * adaptor_name - adaptor name * api_type - API type TCPIP or API will be sent and expected * as ws_name * * Note the following requirements: * 1) host_name must match the configured adapter_name on the remote side * 2) adaptor_name must match the configured host name on the remote side * * Change History * 1.00 Initial release shipped * 1.10 Changes for Buffer allocation * 1.15 Changed for 2.6 Kernel No longer compiles on 2.4 or lower * 1.25 Added Packing support */#include <asm/bitops.h>#include <asm/ccwdev.h>#include <asm/ccwgroup.h>#include <asm/debug.h>#include <asm/idals.h>#include <asm/io.h>#include <linux/ctype.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/if_arp.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/ip.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/proc_fs.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/skbuff.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/tcp.h>#include <linux/timer.h>#include <linux/types.h>#include "cu3088.h"#include "claw.h"MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");MODULE_DESCRIPTION("Linux for zSeries CLAW Driver\n" \ "Copyright 2000,2005 IBM Corporation\n");MODULE_LICENSE("GPL");/* Debugging is based on DEBUGMSG, IOTRACE, or FUNCTRACE options: DEBUGMSG - Enables output of various debug messages in the code IOTRACE - Enables output of CCW and other IO related traces FUNCTRACE - Enables output of function entry/exit trace Define any combination of above options to enable tracing CLAW also uses the s390dbf file system see claw_trace and claw_setup*//* following enables tracing *///#define DEBUGMSG//#define IOTRACE//#define FUNCTRACE#ifdef DEBUGMSG#define DEBUG#endif#ifdef IOTRACE#define DEBUG#endif#ifdef FUNCTRACE#define DEBUG#endif char debug_buffer[255];/** * Debug Facility Stuff */static debug_info_t *claw_dbf_setup;static debug_info_t *claw_dbf_trace;/** * CLAW Debug Facility functions */static voidclaw_unregister_debug_facility(void){ if (claw_dbf_setup) debug_unregister(claw_dbf_setup); if (claw_dbf_trace) debug_unregister(claw_dbf_trace);}static intclaw_register_debug_facility(void){ claw_dbf_setup = debug_register("claw_setup", 2, 1, 8); claw_dbf_trace = debug_register("claw_trace", 2, 2, 8); if (claw_dbf_setup == NULL || claw_dbf_trace == NULL) { printk(KERN_WARNING "Not enough memory for debug facility.\n"); claw_unregister_debug_facility(); return -ENOMEM; } debug_register_view(claw_dbf_setup, &debug_hex_ascii_view); debug_set_level(claw_dbf_setup, 2); debug_register_view(claw_dbf_trace, &debug_hex_ascii_view); debug_set_level(claw_dbf_trace, 2); return 0;}static inline voidclaw_set_busy(struct net_device *dev){ ((struct claw_privbk *) dev->priv)->tbusy=1; eieio();}static inline voidclaw_clear_busy(struct net_device *dev){ clear_bit(0, &(((struct claw_privbk *) dev->priv)->tbusy)); netif_wake_queue(dev); eieio();}static inline intclaw_check_busy(struct net_device *dev){ eieio(); return ((struct claw_privbk *) dev->priv)->tbusy;}static inline voidclaw_setbit_busy(int nr,struct net_device *dev){ netif_stop_queue(dev); set_bit(nr, (void *)&(((struct claw_privbk *)dev->priv)->tbusy));}static inline voidclaw_clearbit_busy(int nr,struct net_device *dev){ clear_bit(nr,(void *)&(((struct claw_privbk *)dev->priv)->tbusy)); netif_wake_queue(dev);}static inline intclaw_test_and_setbit_busy(int nr,struct net_device *dev){ netif_stop_queue(dev); return test_and_set_bit(nr, (void *)&(((struct claw_privbk *) dev->priv)->tbusy));}/* Functions for the DEV methods */static int claw_probe(struct ccwgroup_device *cgdev);static void claw_remove_device(struct ccwgroup_device *cgdev);static void claw_purge_skb_queue(struct sk_buff_head *q);static int claw_new_device(struct ccwgroup_device *cgdev);static int claw_shutdown_device(struct ccwgroup_device *cgdev);static int claw_tx(struct sk_buff *skb, struct net_device *dev);static int claw_change_mtu( struct net_device *dev, int new_mtu);static int claw_open(struct net_device *dev);static void claw_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb);static void claw_irq_tasklet ( unsigned long data );static int claw_release(struct net_device *dev);static void claw_write_retry ( struct chbk * p_ch );static void claw_write_next ( struct chbk * p_ch );static void claw_timer ( struct chbk * p_ch );/* Functions */static int add_claw_reads(struct net_device *dev, struct ccwbk* p_first, struct ccwbk* p_last);static void inline ccw_check_return_code (struct ccw_device *cdev, int return_code);static void inline ccw_check_unit_check (struct chbk * p_ch, unsigned char sense );static int find_link(struct net_device *dev, char *host_name, char *ws_name );static int claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid);static int init_ccw_bk(struct net_device *dev);static void probe_error( struct ccwgroup_device *cgdev);static struct net_device_stats *claw_stats(struct net_device *dev);static int inline pages_to_order_of_mag(int num_of_pages);static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);#ifdef DEBUGstatic void dumpit (char *buf, int len);#endif/* sysfs Functions */static ssize_t claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf);static ssize_t claw_hname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);static ssize_t claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf);static ssize_t claw_adname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);static ssize_t claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf);static ssize_t claw_apname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);static ssize_t claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf);static ssize_t claw_wbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);static ssize_t claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf);static ssize_t claw_rbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);static int claw_add_files(struct device *dev);static void claw_remove_files(struct device *dev);/* Functions for System Validate */static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw);static int claw_send_control(struct net_device *dev, __u8 type, __u8 link, __u8 correlator, __u8 rc , char *local_name, char *remote_name);static int claw_snd_conn_req(struct net_device *dev, __u8 link);static int claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl);static int claw_snd_sys_validate_rsp(struct net_device *dev, struct clawctl * p_ctl, __u32 return_code);static int claw_strt_conn_req(struct net_device *dev );static void claw_strt_read ( struct net_device *dev, int lock );static void claw_strt_out_IO( struct net_device *dev );static void claw_free_wrt_buf( struct net_device *dev );/* Functions for unpack reads */static void unpack_read (struct net_device *dev );/* ccwgroup table */static struct ccwgroup_driver claw_group_driver = { .owner = THIS_MODULE, .name = "claw", .max_slaves = 2, .driver_id = 0xC3D3C1E6, .probe = claw_probe, .remove = claw_remove_device, .set_online = claw_new_device, .set_offline = claw_shutdown_device,};/*** Key functions*//*----------------------------------------------------------------* * claw_probe * * this function is called for each CLAW device. * *----------------------------------------------------------------*/static intclaw_probe(struct ccwgroup_device *cgdev){ int rc; struct claw_privbk *privptr=NULL;#ifdef FUNCTRACE printk(KERN_INFO "%s Enter\n",__FUNCTION__);#endif CLAW_DBF_TEXT(2,setup,"probe"); if (!get_device(&cgdev->dev)) return -ENODEV;#ifdef DEBUGMSG printk(KERN_INFO "claw: variable cgdev =\n"); dumpit((char *)cgdev, sizeof(struct ccwgroup_device));#endif privptr = kmalloc(sizeof(struct claw_privbk), GFP_KERNEL); if (privptr == NULL) { probe_error(cgdev); put_device(&cgdev->dev); printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n", cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__); CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM); return -ENOMEM; } memset(privptr,0x00,sizeof(struct claw_privbk)); privptr->p_mtc_envelope= kmalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL); privptr->p_env = kmalloc(sizeof(struct claw_env), GFP_KERNEL); if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) { probe_error(cgdev); put_device(&cgdev->dev); printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n", cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__); CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM); return -ENOMEM; } memset(privptr->p_mtc_envelope, 0x00, MAX_ENVELOPE_SIZE); memset(privptr->p_env, 0x00, sizeof(struct claw_env)); memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8); memcpy(privptr->p_env->host_name,WS_NAME_NOT_DEF,8); memcpy(privptr->p_env->api_type,WS_NAME_NOT_DEF,8); privptr->p_env->packing = 0; privptr->p_env->write_buffers = 5; privptr->p_env->read_buffers = 5; privptr->p_env->read_size = CLAW_FRAME_SIZE; privptr->p_env->write_size = CLAW_FRAME_SIZE; rc = claw_add_files(&cgdev->dev); if (rc) { probe_error(cgdev); put_device(&cgdev->dev); printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n", cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__); CLAW_DBF_TEXT_(2,setup,"probex%d",rc); return rc; } printk(KERN_INFO "claw: sysfs files added for %s\n",cgdev->cdev[0]->dev.bus_id); privptr->p_env->p_priv = privptr; cgdev->cdev[0]->handler = claw_irq_handler; cgdev->cdev[1]->handler = claw_irq_handler; cgdev->dev.driver_data = privptr;#ifdef FUNCTRACE printk(KERN_INFO "claw:%s exit on line %d, " "rc = 0\n",__FUNCTION__,__LINE__);#endif CLAW_DBF_TEXT(2,setup,"prbext 0"); return 0;} /* end of claw_probe *//*-------------------------------------------------------------------*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -