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

📄 iph5526.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/********************************************************************** * iph5526.c: IP/SCSI driver for the Interphase 5526 PCI Fibre Channel *			  Card. * Copyright (C) 1999 Vineet M Abraham <vmabraham@hotmail.com> * * 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. *********************************************************************//**********************************************************************Log:Vineet M Abraham02.12.99 Support multiple cards.03.15.99 Added Fabric support.04.04.99 Added N_Port support.04.15.99 Added SCSI support.06.18.99 Added ABTS Protocol.06.24.99 Fixed data corruption when multiple XFER_RDYs are received.07.07.99 Can be loaded as part of the Kernel. Changed semaphores. Added         more checks before invalidating SEST entries.07.08.99 Added Broadcast IP stuff and fixed an unicast timeout bug.***********************************************************************//* TODO:	R_T_TOV set to 15msec in Loop topology. Need to be 100 msec.    SMP testing.	Fix ADISC Tx before completing FLOGI. */	static const char *version =    "iph5526.c:v1.0 07.08.99 Vineet Abraham (vmabraham@hotmail.com)\n";#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/mm.h>#include <linux/delay.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/timer.h>#include <linux/spinlock.h>#include <linux/netdevice.h>#include <linux/fcdevice.h> /* had the declarations for init_fcdev among			       others + includes if_fcdevice.h */#include "../../scsi/scsi.h"#include <scsi/scsi_host.h>#include "../../fc4/fcp.h"#include <asm/system.h>#include <asm/io.h>/* driver specific header files */#include "tach.h"#include "tach_structs.h"#include "iph5526_ip.h"#include "iph5526_scsi.h"#include "iph5526_novram.c"#define RUN_AT(x) (jiffies + (x))#define DEBUG_5526_0 0#define DEBUG_5526_1 0#define DEBUG_5526_2 0#if DEBUG_5526_0#define DPRINTK(format, a...) {printk("%s: ", fi->name); \							   printk(format, ##a); \							   printk("\n");}#define ENTER(x)	{printk("%s: ", fi->name); \					 printk("iph5526.c : entering %s()\n", x);}#define LEAVE(x)	{printk("%s: ", fi->name); \					 printk("iph5526.c : leaving %s()\n",x);}#else#define DPRINTK(format, a...) {}#define ENTER(x)	{}#define LEAVE(x)	{}#endif#if DEBUG_5526_1#define DPRINTK1(format, a...) {printk("%s: ", fi->name); \							   printk(format, ##a); \							   printk("\n");}#else#define DPRINTK1(format, a...) {}#endif#if DEBUG_5526_2#define DPRINTK2(format, a...) {printk("%s: ", fi->name); \							   printk(format, ##a); \							   printk("\n");}#else#define DPRINTK2(format, a...) {}#endif#define T_MSG(format, a...) {printk("%s: ", fi->name); \							 printk(format, ##a);\							 printk("\n");}#define ALIGNED_SFS_ADDR(addr) ((((unsigned long)(addr) + (SFS_BUFFER_SIZE - 1)) & ~(SFS_BUFFER_SIZE - 1)) - (unsigned long)(addr))#define ALIGNED_ADDR(addr, len) ((((unsigned long)(addr) + (len - 1)) & ~(len - 1)) - (unsigned long)(addr))static struct pci_device_id iph5526_pci_tbl[] = {	{ PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_5526, PCI_ANY_ID, PCI_ANY_ID, },	{ PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_55x6, PCI_ANY_ID, PCI_ANY_ID, },	{ }			/* Terminating entry */};MODULE_DEVICE_TABLE(pci, iph5526_pci_tbl);MODULE_LICENSE("GPL");#define MAX_FC_CARDS 2static struct fc_info *fc[MAX_FC_CARDS+1];static unsigned int pci_irq_line;static struct {	unsigned short vendor_id;	unsigned short device_id;	char *name;}clone_list[] __initdata  = {	{PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_5526, "Interphase Fibre Channel HBA"},	{PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_55x6, "Interphase Fibre Channel HBA"},	{0,}};static irqreturn_t tachyon_interrupt(int irq, void *dev_id, struct pt_regs *regs);static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs);static int initialize_register_pointers(struct fc_info *fi);void clean_up_memory(struct fc_info *fi);static int tachyon_init(struct fc_info *fi);static int build_queues(struct fc_info *fi);static void build_tachyon_header(struct fc_info *fi, u_int my_id, u_int r_ctl, u_int d_id, u_int type, u_char seq_id, u_char df_ctl, u_short ox_id, u_short rx_id, char *data);static int get_free_header(struct fc_info *fi);static void build_EDB(struct fc_info *fi, char *data, u_short flags, u_short len);static int get_free_EDB(struct fc_info *fi);static void build_ODB(struct fc_info *fi, u_char seq_id, u_int d_id, u_int len, u_int cntl, u_short mtu, u_short ox_id, u_short rx_id, int NW_header, int int_required, u_int frame_class);static void write_to_tachyon_registers(struct fc_info *fi);static void reset_latch(struct fc_info *fi);static void reset_tachyon(struct fc_info *fi, u_int value);static void take_tachyon_offline(struct fc_info *fi);static void read_novram(struct fc_info *fi);static void reset_ichip(struct fc_info *fi);static void update_OCQ_indx(struct fc_info *fi);static void update_IMQ_indx(struct fc_info *fi, int count);static void update_SFSBQ_indx(struct fc_info *fi);static void update_MFSBQ_indx(struct fc_info *fi, int count);static void update_tachyon_header_indx(struct fc_info *fi);static void update_EDB_indx(struct fc_info *fi);static void handle_FM_interrupt(struct fc_info *fi);static void handle_MFS_interrupt(struct fc_info *fi);static void handle_OOO_interrupt(struct fc_info *fi);static void handle_SFS_interrupt(struct fc_info *fi);static void handle_OCI_interrupt(struct fc_info *fi);static void handle_SFS_BUF_WARN_interrupt(struct fc_info *fi);static void handle_MFS_BUF_WARN_interrupt(struct fc_info *fi);static void handle_IMQ_BUF_WARN_interrupt(struct fc_info *fi);static void handle_Unknown_Frame_interrupt(struct fc_info *fi);static void handle_Busied_Frame_interrupt(struct fc_info *fi);static void handle_Bad_SCSI_Frame_interrupt(struct fc_info *fi);static void handle_Inbound_SCSI_Status_interrupt(struct fc_info *fi);static void handle_Inbound_SCSI_Command_interrupt(struct fc_info *fi);static void completion_message_handler(struct fc_info *fi, u_int imq_int_type);static void fill_login_frame(struct fc_info *fi, u_int logi);static int tx_exchange(struct fc_info *fi, char *data, u_int len, u_int r_ctl, u_int type, u_int d_id, u_int mtu, int int_required, u_short ox_id, u_int frame_class);static int tx_sequence(struct fc_info *fi, char *data, u_int len, u_int mtu, u_int d_id, u_short ox_id, u_short rx_id, u_char seq_id, int NW_flag, int int_required, u_int frame_class);static int validate_login(struct fc_info *fi, u_int *base_ptr);static void add_to_address_cache(struct fc_info *fi, u_int *base_ptr);static void remove_from_address_cache(struct fc_info *fi, u_int *data, u_int cmnd_code);static int node_logged_in_prev(struct fc_info *fi, u_int *buff_addr);static int sid_logged_in(struct fc_info *fi, u_int s_id);static struct fc_node_info *look_up_cache(struct fc_info *fi, char *data);static int display_cache(struct fc_info *fi);static void tx_logi(struct fc_info *fi, u_int logi, u_int d_id);static void tx_logi_acc(struct fc_info *fi, u_int logi, u_int d_id, u_short received_ox_id);static void tx_prli(struct fc_info *fi, u_int command_code, u_int d_id, u_short received_ox_id);static void tx_logo(struct fc_info *fi, u_int d_id, u_short received_ox_id);static void tx_adisc(struct fc_info *fi, u_int cmnd_code, u_int d_id, u_short received_ox_id);static void tx_ls_rjt(struct fc_info *fi, u_int d_id, u_short received_ox_id, u_short reason_code, u_short expln_code);static u_int plogi_ok(struct fc_info *fi, u_int *buff_addr, int size);static void tx_acc(struct fc_info *fi, u_int d_id, u_short received_ox_id);static void tx_name_server_req(struct fc_info *fi, u_int req);static void rscn_handler(struct fc_info *fi, u_int node_id);static void tx_scr(struct fc_info *fi);static void scr_timer(unsigned long data);static void explore_fabric(struct fc_info *fi, u_int *buff_addr);static void perform_adisc(struct fc_info *fi);static void local_port_discovery(struct fc_info *fi);static void add_to_ox_id_list(struct fc_info *fi, u_int transaction_id, u_int cmnd_code);static u_int remove_from_ox_id_list(struct fc_info *fi, u_short received_ox_id);static void add_display_cache_timer(struct fc_info *fi);/* Timers... */static void nos_ols_timer(unsigned long data);static void loop_timer(unsigned long data);static void fabric_explore_timer(unsigned long data);static void port_discovery_timer(unsigned long data);static void display_cache_timer(unsigned long data);/* SCSI Stuff */static int add_to_sest(struct fc_info *fi, Scsi_Cmnd *Cmnd, struct fc_node_info *ni);static struct fc_node_info *resolve_target(struct fc_info *fi, u_char target);static void update_FCP_CMND_indx(struct fc_info *fi);static int get_free_SDB(struct fc_info *fi);static void update_SDB_indx(struct fc_info *fi);static void mark_scsi_sid(struct fc_info *fi, u_int *buff_addr, u_char action);static void invalidate_SEST_entry(struct fc_info *fi, u_short received_ox_id);static int abort_exchange(struct fc_info *fi, u_short ox_id);static void flush_tachyon_cache(struct fc_info *fi, u_short ox_id);static int get_scsi_oxid(struct fc_info *fi);static void update_scsi_oxid(struct fc_info *fi);static Scsi_Host_Template driver_template = IPH5526_SCSI_FC;static void iph5526_timeout(struct net_device *dev);static int iph5526_probe_pci(struct net_device *dev);int __init iph5526_probe(struct net_device *dev){	if (iph5526_probe_pci(dev) == 0)		return 0;	return -ENODEV;}static int __init iph5526_probe_pci(struct net_device *dev){	struct fc_info *fi = dev->priv;	fi->dev = dev;	dev->base_addr = fi->base_addr;	dev->irq = fi->irq;	if (dev->priv == NULL) 		dev->priv = fi; 	fcdev_init(dev);	/* Assign ur MAC address.	 */	dev->dev_addr[0] = (fi->g.my_port_name_high & 0x0000FF00) >> 8;	dev->dev_addr[1] = fi->g.my_port_name_high;	dev->dev_addr[2] = (fi->g.my_port_name_low & 0xFF000000) >> 24;	dev->dev_addr[3] = (fi->g.my_port_name_low & 0x00FF0000) >> 16;	dev->dev_addr[4] = (fi->g.my_port_name_low & 0x0000FF00) >> 8;	dev->dev_addr[5] = fi->g.my_port_name_low;	display_cache(fi);	return 0;}static int __init fcdev_init(struct net_device *dev){	SET_MODULE_OWNER(dev);	dev->open = iph5526_open;	dev->stop = iph5526_close;	dev->hard_start_xmit = iph5526_send_packet;	dev->get_stats = iph5526_get_stats;	dev->set_multicast_list = NULL;	dev->change_mtu = iph5526_change_mtu; 	dev->tx_timeout = iph5526_timeout;	dev->watchdog_timeo = 5*HZ;	return 0;}/* initialize tachyon and take it OnLine */static int tachyon_init(struct fc_info *fi){	ENTER("tachyon_init");	if (build_queues(fi) == 0) {		T_MSG("build_queues() failed");		return 0;	}	/* Retrieve your port/node name.	 */	read_novram(fi);	reset_ichip(fi);	reset_tachyon(fi, SOFTWARE_RESET);	LEAVE("tachyon_init");	return 1;}/* Build the 4 Qs - IMQ, OCQ, MFSBQ, SFSBQ *//* Lots of dma_pages needed as Tachyon DMAs almost everything into  * host memory. */static int build_queues(struct fc_info *fi){int i,j;u_char *addr;	ENTER("build_queues");	/* Initializing Queue Variables.	 */	fi->q.ptr_host_ocq_cons_indx = NULL;	fi->q.ptr_host_hpcq_cons_indx = NULL;	fi->q.ptr_host_imq_prod_indx = NULL;	fi->q.ptr_ocq_base = NULL;	fi->q.ocq_len = 0;	fi->q.ocq_end = 0;	fi->q.ocq_prod_indx = 0;	fi->q.ptr_imq_base = NULL;	fi->q.imq_len = 0;	fi->q.imq_end = 0;	fi->q.imq_cons_indx = 0;	fi->q.imq_prod_indx = 0;	fi->q.ptr_mfsbq_base = NULL;	fi->q.mfsbq_len = 0;	fi->q.mfsbq_end = 0;	fi->q.mfsbq_prod_indx = 0;	fi->q.mfsbq_cons_indx = 0;	fi->q.mfsbuff_len = 0;	fi->q.mfsbuff_end = 0;	fi->g.mfs_buffer_count = 0;	fi->q.ptr_sfsbq_base = NULL;	fi->q.sfsbq_len = 0;	fi->q.sfsbq_end = 0;	fi->q.sfsbq_prod_indx = 0;	fi->q.sfsbq_cons_indx = 0;	fi->q.sfsbuff_len = 0;	fi->q.sfsbuff_end = 0;	fi->q.sdb_indx = 0;	fi->q.fcp_cmnd_indx = 0;	fi->q.ptr_edb_base = NULL;	fi->q.edb_buffer_indx = 0;	fi->q.ptr_tachyon_header_base = NULL;	fi->q.tachyon_header_indx = 0;	fi->node_info_list = NULL;	fi->ox_id_list = NULL;	fi->g.loop_up = FALSE;	fi->g.ptp_up = FALSE;	fi->g.link_up = FALSE;	fi->g.fabric_present = FALSE;	fi->g.n_port_try = FALSE;	fi->g.dont_init = FALSE;	fi->g.nport_timer_set = FALSE;	fi->g.lport_timer_set = FALSE;	fi->g.no_of_targets = 0;	fi->g.sem = 0;	fi->g.perform_adisc = FALSE;	fi->g.e_i = 0;	/* build OCQ */	if ( (fi->q.ptr_ocq_base = (u_int *)__get_free_pages(GFP_KERNEL, 0)) == 0) {		T_MSG("failed to get OCQ page");		return 0;	}	/* set up the OCQ structures */	for (i = 0; i < OCQ_LENGTH; i++)		fi->q.ptr_odb[i] = fi->q.ptr_ocq_base + NO_OF_ENTRIES*i;	/* build IMQ */	if ( (fi->q.ptr_imq_base = (u_int *)__get_free_pages(GFP_KERNEL, 0)) == 0) {		T_MSG("failed to get IMQ page");		return 0;	}	for (i = 0; i < IMQ_LENGTH; i++)		fi->q.ptr_imqe[i] = fi->q.ptr_imq_base + NO_OF_ENTRIES*i;	/* build MFSBQ */	if ( (fi->q.ptr_mfsbq_base = (u_int *)__get_free_pages(GFP_KERNEL, 0)) == 0) {		T_MSG("failed to get MFSBQ page");		return 0;	}	memset((char *)fi->q.ptr_mfsbq_base, 0, MFSBQ_LENGTH * 32);

⌨️ 快捷键说明

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