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

📄 aic94xx_seq.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	sas_addr = asd_ha->phys[lseq].phy_desc->sas_addr;	for (i = 0; i < SAS_ADDR_SIZE; i++)		asd_write_reg_byte(asd_ha, LmWWN(lseq) + i, sas_addr[i]);	/* Set the Transmit Size to 1024 bytes, 0 = 256 Dwords. */	asd_write_reg_byte(asd_ha, LmMnXMTSIZE(lseq, 1), 0);	/* Set the Bus Inactivity Time Limit Timer. */	asd_write_reg_word(asd_ha, LmBITL_TIMER(lseq), 9);	/* Enable SATA Port Multiplier. */	asd_write_reg_byte(asd_ha, LmMnSATAFS(lseq, 1), 0x80);	/* Initialize Interrupt Vector[0-10] address in Mode 3.	 * See the comment on CSEQ_INT_* */	asd_write_reg_word(asd_ha, LmM3INTVEC0(lseq), lseq_vecs[0]);	asd_write_reg_word(asd_ha, LmM3INTVEC1(lseq), lseq_vecs[1]);	asd_write_reg_word(asd_ha, LmM3INTVEC2(lseq), lseq_vecs[2]);	asd_write_reg_word(asd_ha, LmM3INTVEC3(lseq), lseq_vecs[3]);	asd_write_reg_word(asd_ha, LmM3INTVEC4(lseq), lseq_vecs[4]);	asd_write_reg_word(asd_ha, LmM3INTVEC5(lseq), lseq_vecs[5]);	asd_write_reg_word(asd_ha, LmM3INTVEC6(lseq), lseq_vecs[6]);	asd_write_reg_word(asd_ha, LmM3INTVEC7(lseq), lseq_vecs[7]);	asd_write_reg_word(asd_ha, LmM3INTVEC8(lseq), lseq_vecs[8]);	asd_write_reg_word(asd_ha, LmM3INTVEC9(lseq), lseq_vecs[9]);	asd_write_reg_word(asd_ha, LmM3INTVEC10(lseq), lseq_vecs[10]);	/*	 * Program the Link LED control, applicable only for	 * Chip Rev. B or later.	 */	asd_write_reg_dword(asd_ha, LmCONTROL(lseq),			    (LEDTIMER | LEDMODE_TXRX | LEDTIMERS_100ms));	/* Set the Align Rate for SAS and STP mode. */	asd_write_reg_byte(asd_ha, LmM1SASALIGN(lseq), SAS_ALIGN_DEFAULT);	asd_write_reg_byte(asd_ha, LmM1STPALIGN(lseq), STP_ALIGN_DEFAULT);}/** * asd_post_init_cseq -- clear CSEQ Mode n Int. status and Response mailbox * @asd_ha: pointer to host adapter struct */static void asd_post_init_cseq(struct asd_ha_struct *asd_ha){	int i;	for (i = 0; i < 8; i++)		asd_write_reg_dword(asd_ha, CMnINT(i), 0xFFFFFFFF);	for (i = 0; i < 8; i++)		asd_read_reg_dword(asd_ha, CMnRSPMBX(i));	/* Reset the external interrupt arbiter. */	asd_write_reg_byte(asd_ha, CARP2INTCTL, RSTINTCTL);}/** * asd_init_ddb_0 -- initialize DDB 0 * @asd_ha: pointer to host adapter structure * * Initialize DDB site 0 which is used internally by the sequencer. */static void asd_init_ddb_0(struct asd_ha_struct *asd_ha){	int	i;	/* Zero out the DDB explicitly */	for (i = 0; i < sizeof(struct asd_ddb_seq_shared); i+=4)		asd_ddbsite_write_dword(asd_ha, 0, i, 0);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, q_free_ddb_head), 0);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, q_free_ddb_tail),			       asd_ha->hw_prof.max_ddbs-1);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, q_free_ddb_cnt), 0);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, q_used_ddb_head), 0xFFFF);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, q_used_ddb_tail), 0xFFFF);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, shared_mem_lock), 0);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, smp_conn_tag), 0);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, est_nexus_buf_cnt), 0);	asd_ddbsite_write_word(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, est_nexus_buf_thresh),			       asd_ha->hw_prof.num_phys * 2);	asd_ddbsite_write_byte(asd_ha, 0,		 offsetof(struct asd_ddb_seq_shared, settable_max_contexts),0);	asd_ddbsite_write_byte(asd_ha, 0,	       offsetof(struct asd_ddb_seq_shared, conn_not_active), 0xFF);	asd_ddbsite_write_byte(asd_ha, 0,	       offsetof(struct asd_ddb_seq_shared, phy_is_up), 0x00);	/* DDB 0 is reserved */	set_bit(0, asd_ha->hw_prof.ddb_bitmap);}static void asd_seq_init_ddb_sites(struct asd_ha_struct *asd_ha){	unsigned int i;	unsigned int ddb_site;	for (ddb_site = 0 ; ddb_site < ASD_MAX_DDBS; ddb_site++)		for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4)			asd_ddbsite_write_dword(asd_ha, ddb_site, i, 0);}/** * asd_seq_setup_seqs -- setup and initialize central and link sequencers * @asd_ha: pointer to host adapter structure */static void asd_seq_setup_seqs(struct asd_ha_struct *asd_ha){	int 		lseq;	u8		lseq_mask;	/* Initialize DDB sites */	asd_seq_init_ddb_sites(asd_ha);	/* Initialize SCB sites. Done first to compute some values which	 * the rest of the init code depends on. */	asd_init_scb_sites(asd_ha);	/* Initialize CSEQ Scratch RAM registers. */	asd_init_cseq_scratch(asd_ha);	/* Initialize LmSEQ Scratch RAM registers. */	asd_init_lseq_scratch(asd_ha);	/* Initialize CSEQ CIO registers. */	asd_init_cseq_cio(asd_ha);	asd_init_ddb_0(asd_ha);	/* Initialize LmSEQ CIO registers. */	lseq_mask = asd_ha->hw_prof.enabled_phys;	for_each_sequencer(lseq_mask, lseq_mask, lseq)		asd_init_lseq_cio(asd_ha, lseq);	asd_post_init_cseq(asd_ha);}/** * asd_seq_start_cseq -- start the central sequencer, CSEQ * @asd_ha: pointer to host adapter structure */static int asd_seq_start_cseq(struct asd_ha_struct *asd_ha){	/* Reset the ARP2 instruction to location zero. */	asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop);	/* Unpause the CSEQ  */	return asd_unpause_cseq(asd_ha);}/** * asd_seq_start_lseq -- start a link sequencer * @asd_ha: pointer to host adapter structure * @lseq: the link sequencer of interest */static int asd_seq_start_lseq(struct asd_ha_struct *asd_ha, int lseq){	/* Reset the ARP2 instruction to location zero. */	asd_write_reg_word(asd_ha, LmPRGMCNT(lseq), lseq_idle_loop);	/* Unpause the LmSEQ  */	return asd_seq_unpause_lseq(asd_ha, lseq);}int asd_release_firmware(void){	if (sequencer_fw)		release_firmware(sequencer_fw);	return 0;}static int asd_request_firmware(struct asd_ha_struct *asd_ha){	int err, i;	struct sequencer_file_header header, *hdr_ptr;	u32 csum = 0;	u16 *ptr_cseq_vecs, *ptr_lseq_vecs;	if (sequencer_fw)		/* already loaded */		return 0;	err = request_firmware(&sequencer_fw,			       SAS_RAZOR_SEQUENCER_FW_FILE,			       &asd_ha->pcidev->dev);	if (err)		return err;	hdr_ptr = (struct sequencer_file_header *)sequencer_fw->data;	header.csum = le32_to_cpu(hdr_ptr->csum);	header.major = le32_to_cpu(hdr_ptr->major);	header.minor = le32_to_cpu(hdr_ptr->minor);	header.cseq_table_offset = le32_to_cpu(hdr_ptr->cseq_table_offset);	header.cseq_table_size = le32_to_cpu(hdr_ptr->cseq_table_size);	header.lseq_table_offset = le32_to_cpu(hdr_ptr->lseq_table_offset);	header.lseq_table_size = le32_to_cpu(hdr_ptr->lseq_table_size);	header.cseq_code_offset = le32_to_cpu(hdr_ptr->cseq_code_offset);	header.cseq_code_size = le32_to_cpu(hdr_ptr->cseq_code_size);	header.lseq_code_offset = le32_to_cpu(hdr_ptr->lseq_code_offset);	header.lseq_code_size = le32_to_cpu(hdr_ptr->lseq_code_size);	header.mode2_task = le16_to_cpu(hdr_ptr->mode2_task);	header.cseq_idle_loop = le16_to_cpu(hdr_ptr->cseq_idle_loop);	header.lseq_idle_loop = le16_to_cpu(hdr_ptr->lseq_idle_loop);	for (i = sizeof(header.csum); i < sequencer_fw->size; i++)		csum += sequencer_fw->data[i];	if (csum != header.csum) {		asd_printk("Firmware file checksum mismatch\n");		return -EINVAL;	}	if (header.cseq_table_size != CSEQ_NUM_VECS ||	    header.lseq_table_size != LSEQ_NUM_VECS) {		asd_printk("Firmware file table size mismatch\n");		return -EINVAL;	}	asd_printk("Found sequencer Firmware version %d.%d (%s)\n",		   header.major, header.minor, hdr_ptr->version);	if (header.major != SAS_RAZOR_SEQUENCER_FW_MAJOR) {		asd_printk("Firmware Major Version Mismatch;"			   "driver requires version %d.X",			   SAS_RAZOR_SEQUENCER_FW_MAJOR);		return -EINVAL;	}	ptr_cseq_vecs = (u16 *)&sequencer_fw->data[header.cseq_table_offset];	ptr_lseq_vecs = (u16 *)&sequencer_fw->data[header.lseq_table_offset];	mode2_task = header.mode2_task;	cseq_idle_loop = header.cseq_idle_loop;	lseq_idle_loop = header.lseq_idle_loop;	for (i = 0; i < CSEQ_NUM_VECS; i++)		cseq_vecs[i] = le16_to_cpu(ptr_cseq_vecs[i]);	for (i = 0; i < LSEQ_NUM_VECS; i++)		lseq_vecs[i] = le16_to_cpu(ptr_lseq_vecs[i]);	cseq_code = &sequencer_fw->data[header.cseq_code_offset];	cseq_code_size = header.cseq_code_size;	lseq_code = &sequencer_fw->data[header.lseq_code_offset];	lseq_code_size = header.lseq_code_size;	return 0;}int asd_init_seqs(struct asd_ha_struct *asd_ha){	int err;	err = asd_request_firmware(asd_ha);	if (err) {		asd_printk("Failed to load sequencer firmware file %s, error %d\n",			   SAS_RAZOR_SEQUENCER_FW_FILE, err);		return err;	}	err = asd_seq_download_seqs(asd_ha);	if (err) {		asd_printk("couldn't download sequencers for %s\n",			   pci_name(asd_ha->pcidev));		return err;	}	asd_seq_setup_seqs(asd_ha);	return 0;}int asd_start_seqs(struct asd_ha_struct *asd_ha){	int err;	u8  lseq_mask;	int lseq;	err = asd_seq_start_cseq(asd_ha);	if (err) {		asd_printk("couldn't start CSEQ for %s\n",			   pci_name(asd_ha->pcidev));		return err;	}	lseq_mask = asd_ha->hw_prof.enabled_phys;	for_each_sequencer(lseq_mask, lseq_mask, lseq) {		err = asd_seq_start_lseq(asd_ha, lseq);		if (err) {			asd_printk("coudln't start LSEQ %d for %s\n", lseq,				   pci_name(asd_ha->pcidev));			return err;		}	}	return 0;}/** * asd_update_port_links -- update port_map_by_links and phy_is_up * @sas_phy: pointer to the phy which has been added to a port * * 1) When a link reset has completed and we got BYTES DMAED with a * valid frame we call this function for that phy, to indicate that * the phy is up, i.e. we update the phy_is_up in DDB 0.  The * sequencer checks phy_is_up when pending SCBs are to be sent, and * when an open address frame has been received. * * 2) When we know of ports, we call this function to update the map * of phys participaing in that port, i.e. we update the * port_map_by_links in DDB 0.  When a HARD_RESET primitive has been * received, the sequencer disables all phys in that port. * port_map_by_links is also used as the conn_mask byte in the * initiator/target port DDB. */void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy){	const u8 phy_mask = (u8) phy->asd_port->phy_mask;	u8  phy_is_up;	u8  mask;	int i, err;	unsigned long flags;	spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags);	for_each_phy(phy_mask, mask, i)		asd_ddbsite_write_byte(asd_ha, 0,				       offsetof(struct asd_ddb_seq_shared,						port_map_by_links)+i,phy_mask);	for (i = 0; i < 12; i++) {		phy_is_up = asd_ddbsite_read_byte(asd_ha, 0,			  offsetof(struct asd_ddb_seq_shared, phy_is_up));		err = asd_ddbsite_update_byte(asd_ha, 0,				offsetof(struct asd_ddb_seq_shared, phy_is_up),				phy_is_up,				phy_is_up | phy_mask);		if (!err)			break;		else if (err == -EFAULT) {			asd_printk("phy_is_up: parity error in DDB 0\n");			break;		}	}	spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags);	if (err)		asd_printk("couldn't update DDB 0:error:%d\n", err);}MODULE_FIRMWARE(SAS_RAZOR_SEQUENCER_FW_FILE);

⌨️ 快捷键说明

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