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

📄 qlogicfc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#include "qlogicfc_asm.c"/* Each element in mbox_param is an 8 bit bitmap where each bit indicates   if that mbox should be copied as input.  For example 0x2 would mean   only copy mbox1. */const u_char mbox_param[] ={	0x01,			/* MBOX_NO_OP */	0x1f,			/* MBOX_LOAD_RAM */	0x03,			/* MBOX_EXEC_FIRMWARE */	0x1f,			/* MBOX_DUMP_RAM */	0x07,			/* MBOX_WRITE_RAM_WORD */	0x03,			/* MBOX_READ_RAM_WORD */	0xff,			/* MBOX_MAILBOX_REG_TEST */	0x03,			/* MBOX_VERIFY_CHECKSUM */	0x01,			/* MBOX_ABOUT_FIRMWARE */	0xff,			/* MBOX_LOAD_RISC_RAM */	0xff,			/* MBOX_DUMP_RISC_RAM */	0x00,			/* 0x000b */	0x00,			/* 0x000c */	0x00,			/* 0x000d */	0x01,			/* MBOX_CHECK_FIRMWARE */	0x00,			/* 0x000f */	0x1f,			/* MBOX_INIT_REQ_QUEUE */	0x2f,			/* MBOX_INIT_RES_QUEUE */	0x0f,			/* MBOX_EXECUTE_IOCB */	0x03,			/* MBOX_WAKE_UP */	0x01,			/* MBOX_STOP_FIRMWARE */	0x0f,			/* MBOX_ABORT_IOCB */	0x03,			/* MBOX_ABORT_DEVICE */	0x07,			/* MBOX_ABORT_TARGET */	0x03,			/* MBOX_BUS_RESET */	0x03,			/* MBOX_STOP_QUEUE */	0x03,			/* MBOX_START_QUEUE */	0x03,			/* MBOX_SINGLE_STEP_QUEUE */	0x03,			/* MBOX_ABORT_QUEUE */	0x03,			/* MBOX_GET_DEV_QUEUE_STATUS */	0x00,			/* 0x001e */	0x01,			/* MBOX_GET_FIRMWARE_STATUS */	0x01,			/* MBOX_GET_INIT_SCSI_ID */	0x00,			/* 0x0021 */	0x01,			/* MBOX_GET_RETRY_COUNT */	0x00,			/* 0x0023 */	0x00,			/* 0x0024 */	0x00,			/* 0x0025 */	0x00,			/* 0x0026 */	0x00,			/* 0x0027 */	0x03,			/* MBOX_GET_TARGET_PARAMS */	0x03,			/* MBOX_GET_DEV_QUEUE_PARAMS */	0x00,			/* 0x002a */	0x00,			/* 0x002b */	0x00,			/* 0x002c */	0x00,			/* 0x002d */	0x00,			/* 0x002e */	0x00,			/* 0x002f */	0x00,			/* 0x0030 */	0x00,			/* 0x0031 */	0x07,			/* MBOX_SET_RETRY_COUNT */	0x00,			/* 0x0033 */	0x00,			/* 0x0034 */	0x00,			/* 0x0035 */	0x00,			/* 0x0036 */	0x00,			/* 0x0037 */	0x0f,			/* MBOX_SET_TARGET_PARAMS */	0x0f,			/* MBOX_SET_DEV_QUEUE_PARAMS */	0x00,			/* 0x003a */	0x00,			/* 0x003b */	0x00,			/* 0x003c */	0x00,			/* 0x003d */	0x00,			/* 0x003e */	0x00,			/* 0x003f */	0x00,			/* 0x0040 */	0x00,			/* 0x0041 */	0x00,			/* 0x0042 */	0x00,			/* 0x0043 */	0x00,			/* 0x0044 */	0x00,			/* 0x0045 */	0x00,			/* 0x0046 */	0x00,			/* 0x0047 */	0x00,			/* 0x0048 */	0x00,			/* 0x0049 */	0x00,			/* 0x004a */	0x00,			/* 0x004b */	0x00,			/* 0x004c */	0x00,			/* 0x004d */	0x00,			/* 0x004e */	0x00,			/* 0x004f */	0x00,			/* 0x0050 */	0x00,			/* 0x0051 */	0x00,			/* 0x0052 */	0x00,			/* 0x0053 */	0xcf,			/* MBOX_EXECUTE_IOCB64 */	0x00,			/* 0x0055 */	0x00,			/* 0x0056 */	0x00,			/* 0x0057 */	0x00,			/* 0x0058 */	0x00,			/* 0x0059 */	0x00,			/* 0x005a */	0x00,			/* 0x005b */	0x00,			/* 0x005c */	0x00,			/* 0x005d */	0x00,			/* 0x005e */	0x00,			/* 0x005f */	0xff,			/* MBOX_INIT_FIRMWARE */	0xcd,			/* MBOX_GET_INIT_CB */	0x01,			/* MBOX_INIT_LIP */	0xcd,			/* MBOX_GET_POS_MAP */	0xcf,			/* MBOX_GET_PORT_DB */	0x03,			/* MBOX_CLEAR_ACA */	0x03,			/* MBOX_TARGET_RESET */	0x03,			/* MBOX_CLEAR_TASK_SET */	0x03,			/* MBOX_ABORT_TASK_SET */	0x01,			/* MBOX_GET_FIRMWARE_STATE */	0x03,			/* MBOX_GET_PORT_NAME */	0x00,			/* 0x006b */	0x00,			/* 0x006c */	0x00,			/* 0x006d */	0xcf,			/* MBOX_SEND_SNS */	0x0f,			/* MBOX_PORT_LOGIN */	0x03,			/* MBOX_SEND_CHANGE_REQUEST */	0x03,			/* MBOX_PORT_LOGOUT */};#define MAX_MBOX_COMMAND	(sizeof(mbox_param)/sizeof(u_short))struct id_name_map {	u64 wwn;	u_char loop_id;};struct sns_cb {	u_short len;	u_short res1;	u_int response_low;	u_int response_high;	u_short sub_len;	u_short res2;	u_char data[44];};/* address of instance of this struct is passed to adapter to initialize things */struct init_cb {	u_char version;	u_char reseverd1[1];	u_short firm_opts;	u_short max_frame_len;	u_short max_iocb;	u_short exec_throttle;	u_char retry_cnt;	u_char retry_delay;	u_short node_name[4];	u_short hard_addr;	u_char reserved2[10];	u_short req_queue_out;	u_short res_queue_in;	u_short req_queue_len;	u_short res_queue_len;	u_int req_queue_addr_lo;	u_int req_queue_addr_high;	u_int res_queue_addr_lo;	u_int res_queue_addr_high;        /* the rest of this structure only applies to the isp2200 */        u_short lun_enables;        u_char cmd_resource_cnt;        u_char notify_resource_cnt;        u_short timeout;        u_short reserved3;        u_short add_firm_opts;        u_char res_accum_timer;        u_char irq_delay_timer;        u_short special_options;        u_short reserved4[13];};/* * The result queue can be quite a bit smaller since continuation entries * do not show up there: */#define RES_QUEUE_LEN		((QLOGICFC_REQ_QUEUE_LEN + 1) / 8 - 1)#define QUEUE_ENTRY_LEN		64#if ISP2x00_FABRIC#define QLOGICFC_MAX_ID    0xff#else#define QLOGICFC_MAX_ID    0x7d#endif#define QLOGICFC_MAX_LUN	128#define QLOGICFC_MAX_LOOP_ID	0x7d/* the following connection options only apply to the 2200.  i have only * had success with LOOP_ONLY and P2P_ONLY. */#define LOOP_ONLY              0#define P2P_ONLY               1#define LOOP_PREFERED          2#define P2P_PREFERED           3#define CONNECTION_PREFERENCE  LOOP_ONLY/* adapter_state values */#define AS_FIRMWARE_DEAD      -1#define AS_LOOP_DOWN           0#define AS_LOOP_GOOD           1#define AS_REDO_FABRIC_PORTDB  2#define AS_REDO_LOOP_PORTDB    4#define RES_SIZE	((RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)#define REQ_SIZE	((QLOGICFC_REQ_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)struct isp2x00_hostdata {	u_char revision;	struct pci_dev *pci_dev;	/* result and request queues (shared with isp2x00): */	u_int req_in_ptr;	/* index of next request slot */	u_int res_out_ptr;	/* index of next result slot */	/* this is here so the queues are nicely aligned */	long send_marker;	/* do we need to send a marker? */	char * res;	char * req;	struct init_cb control_block;	int adapter_state;	unsigned long int tag_ages[QLOGICFC_MAX_ID + 1];	Scsi_Cmnd *handle_ptrs[QLOGICFC_REQ_QUEUE_LEN + 1];	unsigned long handle_serials[QLOGICFC_REQ_QUEUE_LEN + 1];	struct id_name_map port_db[QLOGICFC_MAX_ID + 1];	u_char mbox_done;	u64 wwn;	u_int port_id;	u_char queued;	u_char host_id;        struct timer_list explore_timer;};/* queue length's _must_ be power of two: */#define QUEUE_DEPTH(in, out, ql)	((in - out) & (ql))#define REQ_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, 		     \						    QLOGICFC_REQ_QUEUE_LEN)#define RES_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, RES_QUEUE_LEN)static void isp2x00_enable_irqs(struct Scsi_Host *);static void isp2x00_disable_irqs(struct Scsi_Host *);static int isp2x00_init(struct Scsi_Host *);static int isp2x00_reset_hardware(struct Scsi_Host *);static int isp2x00_mbox_command(struct Scsi_Host *, u_short[]);static int isp2x00_return_status(Scsi_Cmnd *, struct Status_Entry *);static void isp2x00_intr_handler(int, void *, struct pt_regs *);static void do_isp2x00_intr_handler(int, void *, struct pt_regs *);static int isp2x00_make_portdb(struct Scsi_Host *);#if ISP2x00_FABRICstatic int isp2x00_init_fabric(struct Scsi_Host *, struct id_name_map *, int);#endif#if USE_NVRAM_DEFAULTSstatic int isp2x00_get_nvram_defaults(struct Scsi_Host *, struct init_cb *);static u_short isp2x00_read_nvram_word(struct Scsi_Host *, u_short);#endif#if DEBUG_ISP2x00static void isp2x00_print_scsi_cmd(Scsi_Cmnd *);#endif#if DEBUG_ISP2x00_INTRstatic void isp2x00_print_status_entry(struct Status_Entry *);#endifstatic inline void isp2x00_enable_irqs(struct Scsi_Host *host){	outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL);}static inline void isp2x00_disable_irqs(struct Scsi_Host *host){	outw(0x0, host->io_port + PCI_INTER_CTL);}int isp2x00_detect(Scsi_Host_Template * tmpt){	int hosts = 0;	int wait_time;	struct Scsi_Host *host = NULL;	struct isp2x00_hostdata *hostdata;	struct pci_dev *pdev = NULL;	unsigned short device_ids[2];	dma64_addr_t busaddr;	int i;	ENTER("isp2x00_detect");       	device_ids[0] = PCI_DEVICE_ID_QLOGIC_ISP2100;	device_ids[1] = PCI_DEVICE_ID_QLOGIC_ISP2200;	tmpt->proc_name = "isp2x00";	if (pci_present() == 0) {		printk("qlogicfc : PCI not present\n");		return 0;	}	for (i=0; i<2; i++){	        while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, device_ids[i], pdev))) {			if (pci_enable_device(pdev))				continue;		        host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));			host->max_id = QLOGICFC_MAX_ID + 1;			host->max_lun = QLOGICFC_MAX_LUN;			host->hostt->use_new_eh_code = 1;			hostdata = (struct isp2x00_hostdata *) host->hostdata;			memset(hostdata, 0, sizeof(struct isp2x00_hostdata));			hostdata->pci_dev = pdev;			hostdata->res = pci64_alloc_consistent(pdev, RES_SIZE + REQ_SIZE, &busaddr);			if (!hostdata->res){			        printk("qlogicfc%d : could not allocate memory for request and response queue.\n", hostdata->host_id);			        scsi_unregister(host);				continue;			}			hostdata->req = hostdata->res + (RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN;			hostdata->queued = 0;			/* set up the control block */			hostdata->control_block.version = 0x1;			hostdata->control_block.firm_opts = cpu_to_le16(0x800e);			hostdata->control_block.max_frame_len = cpu_to_le16(2048);			hostdata->control_block.max_iocb = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN);			hostdata->control_block.exec_throttle = cpu_to_le16(QLOGICFC_CMD_PER_LUN);			hostdata->control_block.retry_delay = 5;			hostdata->control_block.retry_cnt = 1;			hostdata->control_block.node_name[0] = cpu_to_le16(0x0020);			hostdata->control_block.node_name[1] = cpu_to_le16(0xE000);			hostdata->control_block.node_name[2] = cpu_to_le16(0x008B);			hostdata->control_block.node_name[3] = cpu_to_le16(0x0000);			hostdata->control_block.hard_addr = cpu_to_le16(0x0003);			hostdata->control_block.req_queue_len = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN + 1);			hostdata->control_block.res_queue_len = cpu_to_le16(RES_QUEUE_LEN + 1);			hostdata->control_block.res_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr));			hostdata->control_block.res_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr));			hostdata->control_block.req_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr + RES_SIZE));			hostdata->control_block.req_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr + RES_SIZE));			hostdata->control_block.add_firm_opts |= cpu_to_le16(CONNECTION_PREFERENCE<<4);			hostdata->adapter_state = AS_LOOP_DOWN;			hostdata->explore_timer.data = 1;			hostdata->host_id = hosts;			if (isp2x00_init(host) || isp2x00_reset_hardware(host)) {				pci64_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);			        scsi_unregister(host);				continue;			}			host->this_id = 0;			if (request_irq(host->irq, do_isp2x00_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {			        printk("qlogicfc%d : interrupt %d already in use\n",				       hostdata->host_id, host->irq);				pci64_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);				scsi_unregister(host);				continue;			}			if (check_region(host->io_port, 0xff)) {			        printk("qlogicfc%d : i/o region 0x%lx-0x%lx already "				       "in use\n",				       hostdata->host_id, host->io_port, host->io_port + 0xff);				free_irq(host->irq, host);				pci64_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);				scsi_unregister(host);				continue;			}			request_region(host->io_port, 0xff, "qlogicfc");			outw(0x0, host->io_port + PCI_SEMAPHORE);			outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);			isp2x00_enable_irqs(host);			/* wait for the loop to come up */			for (wait_time = jiffies + 10 * HZ; wait_time > jiffies && hostdata->adapter_state == AS_LOOP_DOWN;)			        barrier();			if (hostdata->adapter_state == AS_LOOP_DOWN) {			        printk("qlogicfc%d : link is not up\n", hostdata->host_id);			}			hosts++;			hostdata->explore_timer.data = 0;		}	}	/* this busy loop should not be needed but the isp2x00 seems to need 	   some time before recognizing it is attached to a fabric */#if ISP2x00_FABRIC	for (wait_time = jiffies + 5 * HZ; wait_time > jiffies;)		barrier();#endif	LEAVE("isp2x00_detect");	return hosts;}static int isp2x00_make_portdb(struct Scsi_Host *host){	short param[8];	int i, j;	struct id_name_map temp[QLOGICFC_MAX_ID + 1];	struct isp2x00_hostdata *hostdata;	isp2x00_disable_irqs(host);	memset(temp, 0, sizeof(temp));	hostdata = (struct isp2x00_hostdata *) host->hostdata;#if ISP2x00_FABRIC	for (i = 0x81; i < QLOGICFC_MAX_ID; i++) {		param[0] = MBOX_PORT_LOGOUT;		param[1] = i << 8;		param[2] = 0;		param[3] = 0;		isp2x00_mbox_command(host, param);		if (param[0] != MBOX_COMMAND_COMPLETE) {			DEBUG_FABRIC(printk("qlogicfc%d : logout failed %x  %x\n", hostdata->host_id, i, param[0]));		}	}

⌨️ 快捷键说明

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