qla_init.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,528 行 · 第 1/5 页

C
2,528
字号
	pci_write_config_word(ha->pdev, PCI_COMMAND, cmd);	/* Disable RISC pause on FPM parity error. */	if (!IS_QLA2100(ha))		WRT_REG_WORD(&reg->hccr, HCCR_DISABLE_PARITY_PAUSE);	spin_unlock_irqrestore(&ha->hardware_lock, flags);}/** * qla2x00_chip_diag() - Test chip for proper operation. * @ha: HA context * * Returns 0 on success. */static intqla2x00_chip_diag(scsi_qla_host_t *ha){	int		rval;	device_reg_t	*reg = ha->iobase;	unsigned long	flags = 0;	uint16_t	data;	uint32_t	cnt;	uint16_t	mb[5];	/* Assume a failed state */	rval = QLA_FUNCTION_FAILED;	DEBUG3(printk("scsi(%ld): Testing device at %lx.\n",	    ha->host_no, (u_long)&reg->flash_address));	spin_lock_irqsave(&ha->hardware_lock, flags);	/* Reset ISP chip. */	WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);	/*	 * We need to have a delay here since the card will not respond while	 * in reset causing an MCA on some architectures.	 */	udelay(20);	data = qla2x00_debounce_register(&reg->ctrl_status);	for (cnt = 6000000 ; cnt && (data & CSR_ISP_SOFT_RESET); cnt--) {		udelay(5);		data = RD_REG_WORD(&reg->ctrl_status);		barrier();	}	if (!cnt)		goto chip_diag_failed;	DEBUG3(printk("scsi(%ld): Reset register cleared by chip reset\n",	    ha->host_no));	/* Reset RISC processor. */	WRT_REG_WORD(&reg->hccr, HCCR_RESET_RISC);	WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);	/* Workaround for QLA2312 PCI parity error */	if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {		data = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 0));		for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) {			udelay(5);			data = RD_MAILBOX_REG(ha, reg, 0);			barrier(); 		}	} else		udelay(10);	if (!cnt)		goto chip_diag_failed;	/* Check product ID of chip */	DEBUG3(printk("scsi(%ld): Checking product ID of chip\n", ha->host_no));	mb[1] = RD_MAILBOX_REG(ha, reg, 1);	mb[2] = RD_MAILBOX_REG(ha, reg, 2);	mb[3] = RD_MAILBOX_REG(ha, reg, 3);	mb[4] = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 4));	if (mb[1] != PROD_ID_1 || (mb[2] != PROD_ID_2 && mb[2] != PROD_ID_2a) ||	    mb[3] != PROD_ID_3) {		qla_printk(KERN_WARNING, ha,		    "Wrong product ID = 0x%x,0x%x,0x%x\n", mb[1], mb[2], mb[3]);		goto chip_diag_failed;	}	ha->product_id[0] = mb[1];	ha->product_id[1] = mb[2];	ha->product_id[2] = mb[3];	ha->product_id[3] = mb[4];	/* Adjust fw RISC transfer size */	if (ha->request_q_length > 1024)		ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024;	else		ha->fw_transfer_size = REQUEST_ENTRY_SIZE *		    ha->request_q_length;	if (IS_QLA2200(ha) &&	    RD_MAILBOX_REG(ha, reg, 7) == QLA2200A_RISC_ROM_VER) {		/* Limit firmware transfer size with a 2200A */		DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n",		    ha->host_no));		ha->fw_transfer_size = 128;	}	/* Wrap Incoming Mailboxes Test. */	spin_unlock_irqrestore(&ha->hardware_lock, flags);	DEBUG3(printk("scsi(%ld): Checking mailboxes.\n", ha->host_no));	rval = qla2x00_mbx_reg_test(ha);	if (rval) {		DEBUG(printk("scsi(%ld): Failed mailbox send register test\n",		    ha->host_no));		qla_printk(KERN_WARNING, ha,		    "Failed mailbox send register test\n");	}	else {		/* Flag a successful rval */		rval = QLA_SUCCESS;	}	spin_lock_irqsave(&ha->hardware_lock, flags);chip_diag_failed:	if (rval)		DEBUG2_3(printk("scsi(%ld): Chip diagnostics **** FAILED "		    "****\n", ha->host_no));	spin_unlock_irqrestore(&ha->hardware_lock, flags);	return (rval);}/** * qla2x00_setup_chip() - Load and start RISC firmware. * @ha: HA context * * Returns 0 on success. */static intqla2x00_setup_chip(scsi_qla_host_t *ha){	int		rval;	uint16_t	cnt;	uint16_t	*risc_code;	unsigned long	risc_address;	unsigned long	risc_code_size;	int		num;	int		i;	uint16_t	*req_ring;	struct qla_fw_info *fw_iter;	rval = QLA_SUCCESS;	/* Load firmware sequences */	fw_iter = ha->brd_info->fw_info;	while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {		risc_code = fw_iter->fwcode;		risc_code_size = *fw_iter->fwlen;		if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {			risc_address = *fw_iter->fwstart;		} else {			/* Extended address */			risc_address = *fw_iter->lfwstart;		}		num = 0;		rval = 0;		while (risc_code_size > 0 && !rval) {			cnt = (uint16_t)(ha->fw_transfer_size >> 1);			if (cnt > risc_code_size)				cnt = risc_code_size;			DEBUG7(printk("scsi(%ld): Loading risc segment@ "			    "addr %p, number of bytes 0x%x, offset 0x%lx.\n",			    ha->host_no, risc_code, cnt, risc_address));			req_ring = (uint16_t *)ha->request_ring;			for (i = 0; i < cnt; i++)				req_ring[i] = cpu_to_le16(risc_code[i]);			if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {				rval = qla2x00_load_ram(ha,				    ha->request_dma, risc_address, cnt);			} else {				rval = qla2x00_load_ram_ext(ha,				    ha->request_dma, risc_address, cnt);			}			if (rval) {				DEBUG(printk("scsi(%ld): [ERROR] Failed to "				    "load segment %d of firmware\n",				    ha->host_no, num));				qla_printk(KERN_WARNING, ha,				    "[ERROR] Failed to load "				    "segment %d of firmware\n", num);				qla2x00_dump_regs(ha);				break;			}			risc_code += cnt;			risc_address += cnt;			risc_code_size -= cnt;			num++;		}		/* Next firmware sequence */		fw_iter++;	}	/* Verify checksum of loaded RISC code. */	if (!rval) {		DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC "		    "code.\n", ha->host_no));		rval = qla2x00_verify_checksum(ha);		if (rval == QLA_SUCCESS) {			/* Start firmware execution. */			DEBUG(printk("scsi(%ld): Checksum OK, start "			    "firmware.\n", ha->host_no));			rval = qla2x00_execute_fw(ha);			/* Retrieve firmware information. */			if (rval == QLA_SUCCESS && ha->fw_major_version == 0) {				qla2x00_get_fw_version(ha,				    &ha->fw_major_version,				    &ha->fw_minor_version,				    &ha->fw_subminor_version,				    &ha->fw_attributes, &ha->fw_memory_size);			}		}		else {			DEBUG2(printk(KERN_INFO			    "scsi(%ld): ISP Firmware failed checksum.\n",			    ha->host_no));		}	}	if (rval) {		DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",		    ha->host_no));	}	return (rval);}/** * qla2x00_init_response_q_entries() - Initializes response queue entries. * @ha: HA context * * Beginning of request ring has initialization control block already built * by nvram config routine. * * Returns 0 on success. */static voidqla2x00_init_response_q_entries(scsi_qla_host_t *ha){	uint16_t cnt;	response_t *pkt;	pkt = ha->response_ring_ptr;	for (cnt = 0; cnt < ha->response_q_length; cnt++) {		pkt->signature = RESPONSE_PROCESSED;		pkt++;	}}/** * qla2x00_update_fw_options() - Read and process firmware options. * @ha: HA context * * Returns 0 on success. */static voidqla2x00_update_fw_options(scsi_qla_host_t *ha){	/* Setup seriallink options */	uint16_t swing, emphasis;	memset(ha->fw_options, 0, sizeof(ha->fw_options));	qla2x00_get_fw_options(ha, ha->fw_options);	if (IS_QLA2100(ha) || IS_QLA2200(ha))		return;	/* Serial Link options. */	DEBUG3(printk("scsi(%ld): Serial link options:\n",	    ha->host_no));	DEBUG3(qla2x00_dump_buffer((uint8_t *)&ha->fw_seriallink_options,	    sizeof(ha->fw_seriallink_options)));	ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;	if (ha->fw_seriallink_options[1] & BIT_2)		ha->fw_options[1] |= FO1_SET_EMPHASIS_SWING;	/*  1G settings */	swing = ha->fw_seriallink_options[0] & (BIT_2 | BIT_1 | BIT_0);	emphasis = ha->fw_seriallink_options[0] & (BIT_4 | BIT_3);	emphasis >>= 3;	ha->fw_options[10] = (emphasis << 14) | (swing << 8) | 0x3;	/*  2G settings */	swing = ha->fw_seriallink_options[0] & (BIT_7 | BIT_6 | BIT_5);	swing >>= 5;	emphasis = ha->fw_seriallink_options[1] & (BIT_1 | BIT_0);	ha->fw_options[11] = (emphasis << 14) | (swing << 8) | 0x3;	/* FCP2 options. */	/*  Return command IOCBs without waiting for an ABTS to complete. */	ha->fw_options[3] |= BIT_13;	/* Update Serial Link options. */	qla2x00_set_fw_options(ha, ha->fw_options);}/** * qla2x00_init_rings() - Initializes firmware. * @ha: HA context * * Beginning of request ring has initialization control block already built * by nvram config routine. * * Returns 0 on success. */static intqla2x00_init_rings(scsi_qla_host_t *ha){	int	rval;	unsigned long flags = 0;	int cnt;	device_reg_t *reg = ha->iobase;	spin_lock_irqsave(&ha->hardware_lock, flags);	/* Clear outstanding commands array. */	for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)		ha->outstanding_cmds[cnt] = 0;	ha->current_outstanding_cmd = 0;	/* Clear RSCN queue. */	ha->rscn_in_ptr = 0;	ha->rscn_out_ptr = 0;	/* Initialize firmware. */	ha->request_ring_ptr  = ha->request_ring;	ha->req_ring_index    = 0;	ha->req_q_cnt         = ha->request_q_length;	ha->response_ring_ptr = ha->response_ring;	ha->rsp_ring_index    = 0;	/* Initialize response queue entries */	qla2x00_init_response_q_entries(ha); 	WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0); 	WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0); 	WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0); 	WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0);	RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg));	spin_unlock_irqrestore(&ha->hardware_lock, flags);	DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));	rval = qla2x00_init_firmware(ha, sizeof(init_cb_t));	if (rval) {		DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",		    ha->host_no));	} else {		/* Update any ISP specific firmware options. */		qla2x00_update_fw_options(ha);		DEBUG3(printk("scsi(%ld): Init firmware -- success.\n",		    ha->host_no));	}	return (rval);}/** * qla2x00_fw_ready() - Waits for firmware ready. * @ha: HA context * * Returns 0 on success. */static intqla2x00_fw_ready(scsi_qla_host_t *ha){	int		rval;	unsigned long	wtime, mtime;	uint16_t	min_wait;	/* Minimum wait time if loop is down */	uint16_t	wait_time;	/* Wait time if loop is coming ready */	uint16_t	fw_state;	rval = QLA_SUCCESS;	/* 20 seconds for loop down. */	min_wait = 20;			/*	 * Firmware should take at most one RATOV to login, plus 5 seconds for	 * our own processing.	 */	if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) {		wait_time = min_wait;	}	/* Min wait time if loop down */	mtime = jiffies + (min_wait * HZ);	/* wait time before firmware ready */	wtime = jiffies + (wait_time * HZ);	/* Wait for ISP to finish LIP */	if (!ha->flags.init_done) 		qla_printk(KERN_INFO, ha, "Waiting for LIP to complete...\n");	DEBUG3(printk("scsi(%ld): Waiting for LIP to complete...\n",	    ha->host_no));	do {		rval = qla2x00_get_firmware_state(ha, &fw_state);		if (rval == QLA_SUCCESS) {			if (fw_state < FSTATE_LOSS_OF_SYNC) {				ha->device_flags &= ~DFLG_NO_CABLE;			}			if (fw_state == FSTATE_READY) {				DEBUG(printk("scsi(%ld): F/W Ready - OK \n",				    ha->host_no));				qla2x00_get_retry_cnt(ha, &ha->retry_count,				    &ha->login_timeout, &ha->r_a_tov);				rval = QLA_SUCCESS;				break;			}			rval = QLA_FUNCTION_FAILED;			if (atomic_read(&ha->loop_down_timer) &&			    (fw_state >= FSTATE_LOSS_OF_SYNC ||				fw_state == FSTATE_WAIT_AL_PA)) {				/* Loop down. Timeout on min_wait for states				 * other than Wait for Login. 				 */					if (time_after_eq(jiffies, mtime)) {					qla_printk(KERN_INFO, ha,					    "Cable is unplugged...\n");					ha->device_flags |= DFLG_NO_CABLE;					break;				}			}		} else {			/* Mailbox cmd failed. Timeout on min_wait. */			if (time_after_eq(jiffies, mtime))				break;		}		if (time_after_eq(jiffies, wtime))			break;		/* Delay for a while */		set_current_state(TASK_UNINTERRUPTIBLE);		schedule_timeout(HZ / 2);		DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",		    ha->host_no, fw_state, jiffies));	} while (1);	DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n",	    ha->host_no, fw_state, jiffies));	if (rval) {		DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n",		    ha->host_no));	}	return (rval);}/**  qla2x00_configure_hba*      Setup adapter context.** Input:*      ha = adapter state pointer.** Returns:*      0 = success** Context:*      Kernel context.*/static intqla2x00_configure_hba(scsi_qla_host_t *ha){	int       rval;	uint16_t      loop_id;	uint16_t      topo;	uint8_t       al_pa;	uint8_t       area;	uint8_t       domain;	char		connect_type[22];

⌨️ 快捷键说明

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