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

📄 iph5526.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * that has been allocated for SCSI, will be called a Bad	 * SCSI frame if the Exchange is not valid any more.	 *	 * We will also get a Bad SCSI frame interrupt if we receive	 * a XFER_RDY with offset != 0. Tachyon washes its hands off	 * this Exchange. We have to take care of ourselves. Grrr...	 */	if (rctl == DATA_DESCRIPTOR) {	struct fc_node_info *q = fi->node_info_list;		while (q != NULL) {			if (q->d_id == s_id) {				target_id = q->target_id;				mtu = q->mtu;				break;			}			else				q = q->next;		}		frame_class = target_id;		transfered_len = ntohl(*(buff_addr + 8));		burst_len = ntohl(*(buff_addr + 9));		build_ODB(fi, fi->g.seq_id, s_id, burst_len, 0, mtu, ox_id, rx_id, 0, 0, frame_class << 16);		/* Update the SEQ_ID and Relative Offset in the 		 * Tachyon Header Structure.		 */		tach_header = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 5)));		*(tach_header + 5) = htonl(fi->g.seq_id << 24);		*(tach_header + 7) = htonl(transfered_len);		fi->g.odb.hdr_addr = *(fi->q.ptr_sest[x_id] + 5);		/* Invalidate the EDBs used 		 */		ptr_edb = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 7)));		for (i = 0; i < EDB_LEN; i++)			if (fi->q.ptr_edb[i] == ptr_edb)				break;		ptr_edb--;					if (i < EDB_LEN) {		int j;			do {				ptr_edb += 2;				len += (htonl(*ptr_edb) & 0xFFFF);				j = i;				fi->q.free_edb_list[i++] = EDB_FREE;				if (i == EDB_LEN) {					i = 0;					ptr_edb = fi->q.ptr_edb_base - 1;				}			} while (len < transfered_len);			if (len > transfered_len) {				ptr_edb--;				fi->q.free_edb_list[j] = EDB_BUSY;			}			else				ptr_edb++;		}		else {			T_MSG("EDB not found while freeing");			if (offset == (NO_OF_ENTRIES - 1))				update_SFSBQ_indx(fi);			return;		}		/* Update the EDB pointer in the ODB.		 */		fi->g.odb.edb_addr = htonl(virt_to_bus(ptr_edb));		memcpy(fi->q.ptr_odb[fi->q.ocq_prod_indx], &(fi->g.odb), sizeof(ODB));		/* Update the EDB pointer in the SEST entry. We might need		 * this if get another XFER_RDY for the same Exchange.		 */		*(fi->q.ptr_sest[x_id] + 7) = htonl(virt_to_bus(ptr_edb));		update_OCQ_indx(fi);		if (fi->g.seq_id == MAX_SEQ_ID)			fi->g.seq_id = 0;		else			fi->g.seq_id++;	}	else 	/* Could be a BA_ACC or a BA_RJT.	 */	if (rctl == RCTL_BASIC_ACC) {	u_int bls_type = remove_from_ox_id_list(fi, ox_id);		DPRINTK1("BA_ACC received from S_ID 0x%x with OX_ID = %x in response to %x", s_id, ox_id, bls_type);		if (bls_type == RCTL_BASIC_ABTS) {		u_int STE_bit;			/* Invalidate resources for that Exchange.			 */			STE_bit = ntohl(*fi->q.ptr_sest[x_id]);			if (STE_bit & SEST_V) {				*(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);				invalidate_SEST_entry(fi, ox_id);			}		}	}	else	if (rctl == RCTL_BASIC_RJT) {	u_int bls_type = remove_from_ox_id_list(fi, ox_id);		DPRINTK1("BA_RJT received from S_ID 0x%x with OX_ID = %x in response to %x", s_id, ox_id, bls_type);		if (bls_type == RCTL_BASIC_ABTS) {		u_int STE_bit;			/* Invalidate resources for that Exchange.			 */			STE_bit = ntohl(*fi->q.ptr_sest[x_id]);			if (STE_bit & SEST_V) {				*(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);				invalidate_SEST_entry(fi, ox_id);			}		}	}	else		DPRINTK1("Frame with R_CTL = %x received from S_ID 0x%x with OX_ID %x", rctl, s_id, ox_id);	/* Else, discard the "Bad" SCSI frame.	 */	/* provide Tachyon will another set of buffers 	 */	if (offset == (NO_OF_ENTRIES - 1))		update_SFSBQ_indx(fi);	LEAVE("handle_Bad_SCSI_Frame_interrupt");}static void handle_Inbound_SCSI_Status_interrupt(struct fc_info *fi){struct Scsi_Host *host = fi->host;struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;u_int *ptr_imq_entry, *buff_addr, *ptr_rsp_info, *ptr_sense_info = NULL;int queue_indx, offset, payload_size;u_short received_ox_id, x_id;Scsi_Cmnd *Cmnd;u_int fcp_status, fcp_rsp_info_len = 0, fcp_sense_info_len = 0, s_id;	ENTER("handle_SCSI_status_interrupt");	ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];	offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;	queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;	queue_indx = queue_indx >> 16;	buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_sfsbq_base + queue_indx*NO_OF_ENTRIES + offset)));	payload_size = ntohl(*(ptr_imq_entry + 2));	received_ox_id = ntohl(*(buff_addr + 6)) >> 16;	buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_sfsbq_base + queue_indx*NO_OF_ENTRIES + offset)));	fcp_status = ntohl(*(buff_addr + 10));	ptr_rsp_info = buff_addr + 14;	if (fcp_status & FCP_STATUS_RSP_LEN)		fcp_rsp_info_len = ntohl(*(buff_addr + 13));			if (fcp_status & FCP_STATUS_SENSE_LEN) {		ptr_sense_info = ptr_rsp_info + fcp_rsp_info_len / 4;		fcp_sense_info_len = ntohl(*(buff_addr + 12));		DPRINTK("sense_info = %x", (u_int)ntohl(*ptr_sense_info));	}	DPRINTK("fcp_status = %x, fcp_rsp_len = %x", fcp_status, fcp_rsp_info_len);	x_id = received_ox_id & MAX_SCSI_XID;	Cmnd = hostdata->cmnd_handler[x_id];	hostdata->cmnd_handler[x_id] = NULL;	if (Cmnd != NULL) {		memset(Cmnd->sense_buffer, 0, sizeof(Cmnd->sense_buffer));		/* Check if there is a Sense field */		if (fcp_status & FCP_STATUS_SENSE_LEN) {		int size = sizeof(Cmnd->sense_buffer);			if (fcp_sense_info_len < size)				size = fcp_sense_info_len;			memcpy(Cmnd->sense_buffer, (char *)ptr_sense_info, size);		}		Cmnd->result = fcp_status & FCP_STATUS_MASK;		(*Cmnd->scsi_done) (Cmnd);	}	else		T_MSG("NULL Command out of handler!");	invalidate_SEST_entry(fi, received_ox_id);	s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;	fi->q.free_scsi_oxid[x_id] = OXID_AVAILABLE;	/* provide Tachyon will another set of buffers */	if (offset == (NO_OF_ENTRIES - 1))		update_SFSBQ_indx(fi);	LEAVE("handle_SCSI_status_interrupt");}static void invalidate_SEST_entry(struct fc_info *fi, u_short received_ox_id){u_short x_id = received_ox_id & MAX_SCSI_XID;	/* Invalidate SEST entry if it is an OutBound SEST Entry 	 */	if (!(received_ox_id & SCSI_READ_BIT)) {	u_int *ptr_tach_header, *ptr_edb;	u_short temp_ox_id = NOT_SCSI_XID;	int i;		*(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);		/* Invalidate the Tachyon Header structure 		 */		ptr_tach_header = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 5)));		for (i = 0; i < NO_OF_TACH_HEADERS; i++) 			if(fi->q.ptr_tachyon_header[i] == ptr_tach_header)				break;		if (i < NO_OF_TACH_HEADERS) 			memset(ptr_tach_header, 0xFF, 32);		else			T_MSG("Tachyon Header not found while freeing in invalidate_SEST_entry()");		/* Invalidate the EDB used 		 */		ptr_edb = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 7)));		for (i = 0; i < EDB_LEN; i++)			if (fi->q.ptr_edb[i] == ptr_edb)				break;		ptr_edb--;			if (i < EDB_LEN) {			do {				ptr_edb += 2;				fi->q.free_edb_list[i++] = EDB_FREE;				if (i == EDB_LEN) {					i = 0;					ptr_edb = fi->q.ptr_edb_base - 1;				}			} while ((htonl(*ptr_edb) & 0x80000000) != 0x80000000);		}		else			T_MSG("EDB not found while freeing in invalidate_SEST_entry()");				/* Search for its other header structure and destroy it! 		 */		if ((ptr_tach_header + 16) < (fi->q.ptr_tachyon_header_base + (MY_PAGE_SIZE/4)))			ptr_tach_header += 16;		else			ptr_tach_header = fi->q.ptr_tachyon_header_base;		while (temp_ox_id != x_id) {			temp_ox_id = ntohl(*(ptr_tach_header + 6)) >> 16;			if (temp_ox_id == x_id) {				/* Paranoid checking...				 */				for (i = 0; i < NO_OF_TACH_HEADERS; i++) 					if(fi->q.ptr_tachyon_header[i] == ptr_tach_header)						break;				if (i < NO_OF_TACH_HEADERS)					memset(ptr_tach_header, 0xFF, 32);				else					T_MSG("Tachyon Header not found while freeing in invalidate_SEST_entry()");				break;			}			else {				if ((ptr_tach_header + 16) < (fi->q.ptr_tachyon_header_base + (MY_PAGE_SIZE/4)))					ptr_tach_header += 16;				else					ptr_tach_header = fi->q.ptr_tachyon_header_base;			}		}	}	else {	u_short sdb_table_indx;		/* An Inbound Command has completed or needs to be Aborted. 	 	 * Clear up the SDB buffers.		 */		sdb_table_indx = *(fi->q.ptr_sest[x_id] + 5);		fi->q.sdb_slot_status[sdb_table_indx] = SDB_FREE;	}}static void handle_Inbound_SCSI_Command_interrupt(struct fc_info *fi){u_int *ptr_imq_entry;int queue_indx, offset;	ENTER("handle_Inbound_SCSI_Command_interrupt");	ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];	offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;	queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;	queue_indx = queue_indx >> 16;	/* We discard the SCSI frame as we shouldn't be receiving	 * a SCSI Command in the first place 	 */	/* provide Tachyon will another set of buffers */	if (offset == (NO_OF_ENTRIES - 1))		update_SFSBQ_indx(fi);	LEAVE("handle_Inbound_SCSI_Command_interrupt");}static void handle_SFS_interrupt(struct fc_info *fi){u_int *ptr_imq_entry, *buff_addr;u_int class_of_frame, type_of_frame, s_id, els_type = 0, rctl;int queue_indx, offset, payload_size, login_state;u_short received_ox_id, fs_cmnd_code;	ENTER("handle_SFS_interrupt");	ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];	offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;	queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;	queue_indx = queue_indx >> 16;	DPRINTK("queue_indx = %d, offset  = %d\n", queue_indx, offset);	payload_size = ntohl(*(ptr_imq_entry + 2));	DPRINTK("payload_size = %d", payload_size);	buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_sfsbq_base + queue_indx*NO_OF_ENTRIES + offset)));	/* extract Type of Frame */	type_of_frame = ntohl(*(buff_addr + 4)) & 0xFF000000;	s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;	received_ox_id = ntohl(*(buff_addr + 6)) >> 16;	switch(type_of_frame) {		case TYPE_BLS:			rctl = ntohl(*(buff_addr + 2)) & 0xFF000000;			switch(rctl) {				case RCTL_BASIC_ABTS:					/* As an Initiator, we should never be receiving 					 * this.		 			 */					DPRINTK1("ABTS received from S_ID 0x%x with OX_ID = %x", s_id, received_ox_id);					break;			}			break;		case TYPE_ELS:			class_of_frame = ntohl(*(buff_addr + 8));			login_state = sid_logged_in(fi, s_id);			switch(class_of_frame & 0xFF000000) {				case ELS_PLOGI:					if (s_id != fi->g.my_id) {						u_int ret_code;						DPRINTK1("PLOGI received from D_ID 0x%x with 0X_ID = %x", s_id, received_ox_id);						if ((ret_code = plogi_ok(fi, buff_addr, payload_size)) == 0){							tx_logi_acc(fi, ELS_ACC, s_id, received_ox_id);							add_to_address_cache(fi, buff_addr);						}						else {							u_short cmnd_code = ret_code >> 16;							u_short expln_code =  ret_code;							tx_ls_rjt(fi, s_id, received_ox_id, cmnd_code, expln_code);						}					}					break;				case ELS_ACC:					els_type = remove_from_ox_id_list(fi, received_ox_id);					DPRINTK1("ELS_ACC received from D_ID 0x%x in response to ELS %x", s_id, els_type);					switch(els_type) {						case ELS_PLOGI:							add_to_address_cache(fi, buff_addr);							tx_prli(fi, ELS_PRLI, s_id, OX_ID_FIRST_SEQUENCE);							break;						case ELS_FLOGI:							add_to_address_cache(fi, buff_addr);							fi->g.my_id = ntohl(*(buff_addr + 2)) & 0x00FFFFFF;							fi->g.fabric_present = TRUE;							fi->g.my_ddaa = fi->g.my_id & 0xFFFF00;							/* Login to the Name Server 							 */							tx_logi(fi, ELS_PLOGI, DIRECTORY_SERVER); 							break;						case ELS_NS_PLOGI:							fi->g.name_server = TRUE;							add_to_address_cache(fi, buff_addr);							tx_name_server_req(fi, FCS_RFC_4);							tx_scr(fi);							/* Some devices have a delay before 							 * registering with the Name Server 							 */							udelay(500); 							tx_name_server_req(fi, FCS_GP_ID4);							break;						case ELS_PRLI:							mark_scsi_sid(fi, buff_addr, ADD_ENTRY);							break;						case ELS_ADISC:							if (!(validate_login(fi, buff_addr)))								tx_logo(fi, s_id, OX_ID_FIRST_SEQUENCE);							break;					}					break;				case ELS_PDISC:					DPRINTK1("ELS_PDISC received from D_ID 0x%x", s_id);					tx_logo(fi, s_id, received_ox_id);					break;				case ELS_ADISC:					DPRINTK1("ELS_ADISC received from D_ID 0x%x", s_id);					if (node_logged_in_prev(fi, buff_addr))						tx_adisc(fi, ELS_ACC, s_id, received_ox_id);					else

⌨️ 快捷键说明

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