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

📄 dpt_i2o.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	adpt_hba* pHba=NULL;	u32 m;	ulong reply;	u32 status=0;	u32 context;	ulong flags = 0;	pHba = dev_id;	if (pHba == NULL ){		printk(KERN_WARNING"adpt_isr: NULL dev_id\n");		return;	}	spin_lock_irqsave(&io_request_lock, flags);	while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) {		m = readl(pHba->reply_port);		if(m == EMPTY_QUEUE){			// Try twice then give up			rmb();			m = readl(pHba->reply_port);			if(m == EMPTY_QUEUE){ 				// This really should not happen				printk(KERN_ERR"dpti: Could not get reply frame\n");				spin_unlock_irqrestore(&io_request_lock,flags);				return;			}		}		reply = (ulong)bus_to_virt(m);		if (readl(reply) & MSG_FAIL) {			u32 old_m = readl(reply+28); 			ulong msg;			u32 old_context;			PDEBUG("%s: Failed message\n",pHba->name);			if(old_m >= 0x100000){				printk(KERN_ERR"%s: Bad preserved MFA (%x)- dropping frame\n",pHba->name,old_m);				writel(m,pHba->reply_port);				continue;			}			// Transaction context is 0 in failed reply frame			msg = (ulong)(pHba->msg_addr_virt + old_m);			old_context = readl(msg+12);			writel(old_context, reply+12);			adpt_send_nop(pHba, old_m);		} 		context = readl(reply+8);		if(context & 0x40000000){ // IOCTL			ulong p = (ulong)(readl(reply+12));			if( p != 0) {				memcpy((void*)p, (void*)reply, REPLY_FRAME_SIZE * 4);			}			// All IOCTLs will also be post wait		}		if(context & 0x80000000){ // Post wait message			status = readl(reply+16);			if(status  >> 24){				status &=  0xffff; /* Get detail status */			} else {				status = I2O_POST_WAIT_OK;			}			if(!(context & 0x40000000)) {				cmd = (Scsi_Cmnd*) readl(reply+12); 				if(cmd != NULL) {					printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context);				}			}			adpt_i2o_post_wait_complete(context, status);		} else { // SCSI message			cmd = (Scsi_Cmnd*) readl(reply+12); 			if(cmd != NULL){				if(cmd->serial_number != 0) { // If not timedout					adpt_i2o_to_scsi(reply, cmd);				}			}		}		writel(m, pHba->reply_port);		wmb();		rmb();	}	spin_unlock_irqrestore(&io_request_lock, flags);	return;}static s32 adpt_scsi_to_i2o(adpt_hba* pHba, Scsi_Cmnd* cmd, struct adpt_device* d){	int i;	u32 msg[MAX_MESSAGE_SIZE];	u32* mptr;	u32 *lenptr;	int direction;	int scsidir;	u32 len;	u32 reqlen;	s32 rcode;	memset(msg, 0 , sizeof(msg));	len = cmd->request_bufflen;	direction = 0x00000000;			scsidir = 0x00000000;			// DATA NO XFER	if(len) {		/*		 * Set SCBFlags to indicate if data is being transferred		 * in or out, or no data transfer		 * Note:  Do not have to verify index is less than 0 since		 * cmd->cmnd[0] is an unsigned char		 */		switch(cmd->sc_data_direction){		case SCSI_DATA_READ:			scsidir  =0x40000000;	// DATA IN  (iop<--dev)			break;		case SCSI_DATA_WRITE:			direction=0x04000000;	// SGL OUT			scsidir  =0x80000000;	// DATA OUT (iop-->dev)			break;		case SCSI_DATA_NONE:			break;		case SCSI_DATA_UNKNOWN:			scsidir  =0x40000000;	// DATA IN  (iop<--dev)			// Assume In - and continue;			break;		default:			printk(KERN_WARNING"%s: scsi opcode 0x%x not supported.\n",			     pHba->name, cmd->cmnd[0]);			cmd->result = (DID_OK <<16) | (INITIATOR_ERROR << 8);			cmd->scsi_done(cmd);			return 	0;		}	}	// msg[0] is set later	// I2O_CMD_SCSI_EXEC	msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid);	msg[2] = 0;	msg[3] = (u32)cmd;	/* We want the SCSI control block back */	// Our cards use the transaction context as the tag for queueing	// Adaptec/DPT Private stuff 	msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16);	msg[5] = d->tid;	/* Direction, disconnect ok | sense data | simple queue , CDBLen */	// I2O_SCB_FLAG_ENABLE_DISCONNECT | 	// I2O_SCB_FLAG_SIMPLE_QUEUE_TAG | 	// I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;	msg[6] = scsidir|0x20a00000|cmd->cmd_len;	mptr=msg+7;	// Write SCSI command into the message - always 16 byte block 	memset(mptr, 0,  16);	memcpy(mptr, cmd->cmnd, cmd->cmd_len);	mptr+=4;	lenptr=mptr++;		/* Remember me - fill in when we know */	reqlen = 14;		// SINGLE SGE	/* Now fill in the SGList and command */	if(cmd->use_sg) {		struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer;		len = 0;		for(i = 0 ; i < cmd->use_sg; i++) {			*mptr++ = direction|0x10000000|sg->length;			len+=sg->length;			*mptr++ = virt_to_bus(sg->address);			sg++;		}		/* Make this an end of list */		mptr[-2] = direction|0xD0000000|(sg-1)->length;		reqlen = mptr - msg;		*lenptr = len;				if(cmd->underflow && len != cmd->underflow){			printk(KERN_WARNING"Cmd len %08X Cmd underflow %08X\n",				len, cmd->underflow);		}	} else {		*lenptr = len = cmd->request_bufflen;		if(len == 0) {			reqlen = 12;		} else {			*mptr++ = 0xD0000000|direction|cmd->request_bufflen;			*mptr++ = virt_to_bus(cmd->request_buffer);		}	}		/* Stick the headers on */	msg[0] = reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0);		// Send it on it's way	rcode = adpt_i2o_post_this(pHba, msg, reqlen<<2);	if (rcode == 0) {		return 0;	}	return rcode;}static s32 adpt_scsi_register(adpt_hba* pHba,Scsi_Host_Template * sht){	struct Scsi_Host *host = NULL;	host = scsi_register(sht, sizeof(adpt_hba*));	if (host == NULL) {		printk ("%s: scsi_register returned NULL\n",pHba->name);		return -1;	}	(adpt_hba*)(host->hostdata[0]) = pHba;	pHba->host = host;	host->irq = pHba->pDev->irq;;	/* no IO ports, so don't have to set host->io_port and 	 * host->n_io_port	 */	host->io_port = 0;	host->n_io_port = 0;				/* see comments in hosts.h */	host->max_id = 16;	host->max_lun = 256;	host->max_channel = pHba->top_scsi_channel + 1;	host->cmd_per_lun = 256;	host->unique_id = (uint) pHba;	host->sg_tablesize = pHba->sg_tablesize;	host->can_queue = pHba->post_fifo_size;	host->select_queue_depths = adpt_select_queue_depths;	return 0;}static s32 adpt_i2o_to_scsi(ulong reply, Scsi_Cmnd* cmd){	adpt_hba* pHba;	u32 hba_status;	u32 dev_status;	u32 reply_flags = readl(reply) & 0xff00; // Leave it shifted up 8 bits 	// I know this would look cleaner if I just read bytes	// but the model I have been using for all the rest of the	// io is in 4 byte words - so I keep that model	u16 detailed_status = readl(reply+16) &0xffff;	dev_status = (detailed_status & 0xff);	hba_status = detailed_status >> 8;	// calculate resid for sg 	cmd->resid = cmd->request_bufflen - readl(reply+5);	pHba = (adpt_hba*) cmd->host->hostdata[0];	cmd->sense_buffer[0] = '\0';  // initialize sense valid flag to false	if(!(reply_flags & MSG_FAIL)) {		switch(detailed_status & I2O_SCSI_DSC_MASK) {		case I2O_SCSI_DSC_SUCCESS:			cmd->result = (DID_OK << 16);			// handle underflow			if(readl(reply+5) < cmd->underflow ) {				cmd->result = (DID_ERROR <<16);				printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name);			}			break;		case I2O_SCSI_DSC_REQUEST_ABORTED:			cmd->result = (DID_ABORT << 16);			break;		case I2O_SCSI_DSC_PATH_INVALID:		case I2O_SCSI_DSC_DEVICE_NOT_PRESENT:		case I2O_SCSI_DSC_SELECTION_TIMEOUT:		case I2O_SCSI_DSC_COMMAND_TIMEOUT:		case I2O_SCSI_DSC_NO_ADAPTER:		case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE:			printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%d) hba status=0x%x, dev status=0x%x, cmd=0x%x\n",				pHba->name, (u32)cmd->channel, (u32)cmd->target, (u32)cmd->lun, hba_status, dev_status, cmd->cmnd[0]);			cmd->result = (DID_TIME_OUT << 16);			break;		case I2O_SCSI_DSC_ADAPTER_BUSY:		case I2O_SCSI_DSC_BUS_BUSY:			cmd->result = (DID_BUS_BUSY << 16);			break;		case I2O_SCSI_DSC_SCSI_BUS_RESET:		case I2O_SCSI_DSC_BDR_MESSAGE_SENT:			cmd->result = (DID_RESET << 16);			break;		case I2O_SCSI_DSC_PARITY_ERROR_FAILURE:			printk(KERN_WARNING"%s: SCSI CMD parity error\n",pHba->name);			cmd->result = (DID_PARITY << 16);			break;		case I2O_SCSI_DSC_UNABLE_TO_ABORT:		case I2O_SCSI_DSC_COMPLETE_WITH_ERROR:		case I2O_SCSI_DSC_UNABLE_TO_TERMINATE:		case I2O_SCSI_DSC_MR_MESSAGE_RECEIVED:		case I2O_SCSI_DSC_AUTOSENSE_FAILED:		case I2O_SCSI_DSC_DATA_OVERRUN:		case I2O_SCSI_DSC_UNEXPECTED_BUS_FREE:		case I2O_SCSI_DSC_SEQUENCE_FAILURE:		case I2O_SCSI_DSC_REQUEST_LENGTH_ERROR:		case I2O_SCSI_DSC_PROVIDE_FAILURE:		case I2O_SCSI_DSC_REQUEST_TERMINATED:		case I2O_SCSI_DSC_IDE_MESSAGE_SENT:		case I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT:		case I2O_SCSI_DSC_MESSAGE_RECEIVED:		case I2O_SCSI_DSC_INVALID_CDB:		case I2O_SCSI_DSC_LUN_INVALID:		case I2O_SCSI_DSC_SCSI_TID_INVALID:		case I2O_SCSI_DSC_FUNCTION_UNAVAILABLE:		case I2O_SCSI_DSC_NO_NEXUS:		case I2O_SCSI_DSC_CDB_RECEIVED:		case I2O_SCSI_DSC_LUN_ALREADY_ENABLED:		case I2O_SCSI_DSC_QUEUE_FROZEN:		case I2O_SCSI_DSC_REQUEST_INVALID:		default:			printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",				pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->channel, (u32)cmd->target, (u32)cmd-> lun,			       hba_status, dev_status, cmd->cmnd[0]);			cmd->result = (DID_ERROR << 16);			break;		}		// copy over the request sense data if it was a check		// condition status		if(dev_status == 0x02 /*CHECK_CONDITION*/) {			u32 len = sizeof(cmd->sense_buffer);			len = (len > 40) ?  40 : len;			// Copy over the sense data			memcpy(cmd->sense_buffer, (void*)(reply+28) , len);			if(cmd->sense_buffer[0] == 0x70 /* class 7 */ && 			   cmd->sense_buffer[2] == DATA_PROTECT ){				/* This is to handle an array failed */				cmd->result = (DID_TIME_OUT << 16);				printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n",					pHba->name, (u32)cmd->channel, (u32)cmd->target, (u32)cmd->lun, 					hba_status, dev_status, cmd->cmnd[0]);			}		}	} else {		/* In this condtion we could not talk to the tid		 * the card rejected it.  We should signal a retry		 * for a limitted number of retries.		 */		cmd->result = (DID_TIME_OUT << 16);		printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%d) tid=%d, cmd=0x%x\n",			pHba->name, (u32)cmd->channel, (u32)cmd->target, (u32)cmd-> lun,			((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]);	}	cmd->result |= (dev_status);	if(cmd->scsi_done != NULL){		cmd->scsi_done(cmd);	} 	return cmd->result;}static s32 adpt_rescan(adpt_hba* pHba){	s32 rcode;	ulong flags;	spin_lock_irqsave(&io_request_lock, flags);	if ((rcode=adpt_i2o_lct_get(pHba)) < 0){		spin_unlock_irqrestore(&io_request_lock, flags);		return rcode;	}	if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){		spin_unlock_irqrestore(&io_request_lock, flags);		return rcode;	}	spin_unlock_irqrestore(&io_request_lock, flags);	return 0;}static s32 adpt_i2o_reparse_lct(adpt_hba* pHba){	int i;	int max;	int tid;	struct i2o_device *d;	i2o_lct *lct = pHba->lct;	u8 bus_no = 0;	s16 scsi_id;	s16 scsi_lun;	u32 buf[10]; // at least 8 u32's	struct adpt_device* pDev = NULL;	struct i2o_device* pI2o_dev = NULL;		if (lct == NULL) {		printk(KERN_ERR "%s: LCT is empty???\n",pHba->name);		return -1;	}		max = lct->table_size;		max -= 3;	max /= 9;	// Mark each drive as unscanned	for (d = pHba->devices; d; d = d->next) {		pDev =(struct adpt_device*) d->owner;		if(!pDev){			continue;		}		pDev->state |= DPTI_DEV_UNSCANNED;	}	printk(KERN_INFO "%s: LCT has %d entries.\n", pHba->name,max);		for(i=0;i<max;i++) {		if( lct->lct_entry[i].user_tid != 0xfff){			continue;		}		if( lct->lct_entry[i].class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE ||		    lct->lct_entry[i].class_id == I2O_CLASS_SCSI_PERIPHERAL ||		    lct->lct_entry[i].class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){			tid = lct->lct_entry[i].tid;			if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) {				printk(KERN_ERR"%s: Could not query device\n",pHba->name);				continue;			}			bus_no = buf[0]>>16;			scsi_id = buf[1];			scsi_lun = (buf[2]>>8 )&0xff;			pDev = pHba->channel[bus_no].device[scsi_id];			/* da lun */			while(pDev) {				if(pDev->scsi_lun == scsi_lun) {					break;				}				pDev = pDev->next_lun;			}			if(!pDev ) { // Something new add it				d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);				if(d==NULL)				{					printk(KERN_CRIT "Out of memory for I2O device data.\n");					return -ENOMEM;				}								d->controller = (void*)pHba;				d->next = NULL;				memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));				d->flags = 0;				adpt_i2o_report_hba_unit(pHba, d);				adpt_i2o_install_device(pHba, d);					if(bus_no >= MAX_CHANNEL) {	// Something wrong skip it					printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no);					continue;				}				pDev = pHba->channel[bus_no].device[scsi_id];					if( pDev == NULL){					pDev =  kmalloc(sizeof(struct adpt_device),GFP_KERNEL);					if(pDev == NULL) {						return -ENOMEM;					}					pHba->channel[bus_no].device[scsi_id] = pDev;				} else {					while (pDev->next_lun) {						pDev = pDev->next_lun;					}					pDev = pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);					if(pDev == NULL) {						return -ENOMEM;					}				}				memset(pDev,0,sizeof(struct adpt_device));				pDev->tid = d->lct_data.tid;				pDev->scsi_channel = bus_no;				pDev->scsi_id = scsi_id;				pDev->scsi_lun = scsi_lun;				pDev->pI2o_dev = d;				d->owner = pDev;				pDev->type = (buf[0])&0xff;				pDev->flags = (buf[0]>>8)&0xff;				// Too late, SCSI system has made up it's mind, but what the hey ...				if(scsi_id > pHba->top_scsi_id){					pHba->top_scsi_id = scsi_id;				}				if(scsi_lun > pHba->top_scsi_lun){					pHba->top_scsi_lun = scsi_lun;				}				continue;			} // end of new i2o device			// We found an old device - check it			while(pDev) {				if(pDev->scsi_lun == scsi_lun) {					if(pDev->pScsi_dev->online == FALSE) {						printk(KERN_WARNING"%s: Setting device (%d,%d,%d) back online\n",								pHba->name,bus_no,scsi_id,scsi_lun);						if (pDev->pScsi_dev) {							pDev->pScsi_dev->online = TRUE;						}					}					d = pDev->pI2o_dev;					

⌨️ 快捷键说明

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