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

📄 nsp_cs.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		case MODE_IO32:			res &= ~(BIT(1)|BIT(0)); /* align 4 */			nsp_fifo32_write(base, SCpnt->SCp.ptr, res >> 2);			break;		case MODE_IO8:			nsp_fifo8_write (base, SCpnt->SCp.ptr, res     );			break;		case MODE_MEM32:			res &= ~(BIT(1)|BIT(0)); /* align 4 */			nsp_mmio_fifo32_write(mmio_base, SCpnt->SCp.ptr, res >> 2);			break;		default:			nsp_dbg(NSP_DEBUG_DATA_IO, "unknown write mode");			break;		}		SCpnt->resid	       	 -= res;		SCpnt->SCp.ptr		 += res;		SCpnt->SCp.this_residual -= res;		ocount			 += res;		/* go to next scatter list if available */		if (SCpnt->SCp.this_residual	== 0 &&		    SCpnt->SCp.buffers_residual != 0 ) {			//nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next");			SCpnt->SCp.buffers_residual--;			SCpnt->SCp.buffer++;			SCpnt->SCp.ptr		 = SG_ADDRESS(SCpnt->SCp.buffer);			SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;			time_out = 1000;		}	}	data->FifoCount = ocount;	if (time_out == 0) {		nsp_msg(KERN_DEBUG, "pio write timeout resid=0x%x", SCpnt->resid);	}	nsp_dbg(NSP_DEBUG_DATA_IO, "write ocount=0x%x", ocount);	nsp_dbg(NSP_DEBUG_DATA_IO, "w cmd=%d resid=0x%x\n", data->CmdId, SCpnt->resid);}#undef RFIFO_CRIT#undef WFIFO_CRIT/* * setup synchronous/asynchronous data transfer mode */static int nsp_nexus(Scsi_Cmnd *SCpnt){	unsigned int   base   = SCpnt->device->host->io_port;	unsigned char  target = SCpnt->device->id;//	unsigned char  lun    = SCpnt->device->lun;	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;	sync_data     *sync   = &(data->Sync[target]);	//nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p", SCpnt);	/* setup synch transfer registers */	nsp_index_write(base, SYNCREG,	sync->SyncRegister);	nsp_index_write(base, ACKWIDTH, sync->AckWidth);	if (SCpnt->use_sg    == 0        ||	    SCpnt->resid % 4 != 0        ||	    SCpnt->resid     <= PAGE_SIZE ) {		data->TransferMode = MODE_IO8;	} else if (nsp_burst_mode == BURST_MEM32) {		data->TransferMode = MODE_MEM32;	} else if (nsp_burst_mode == BURST_IO32) {		data->TransferMode = MODE_IO32;	} else {		data->TransferMode = MODE_IO8;	}	/* setup pdma fifo */	nsp_setup_fifo(data, TRUE);	/* clear ack counter */ 	data->FifoCount = 0;	nsp_index_write(base, POINTERCLR, POINTER_CLEAR	    |					  ACK_COUNTER_CLEAR |					  REQ_COUNTER_CLEAR |					  HOST_COUNTER_CLEAR);	return 0;}#include "nsp_message.c"/* * interrupt handler */static irqreturn_t nspintr(int irq, void *dev_id, struct pt_regs *regs){	unsigned int   base;	unsigned char  irq_status, irq_phase, phase;	Scsi_Cmnd     *tmpSC;	unsigned char  target, lun;	unsigned int  *sync_neg;	int            i, tmp;	unsigned long  flags;	nsp_hw_data   *data;	int            handled = 0;	//nsp_dbg(NSP_DEBUG_INTR, "dev_id=0x%p", dev_id);	//nsp_dbg(NSP_DEBUG_INTR, "host=0x%p", ((scsi_info_t *)dev_id)->host);	if (                dev_id        != NULL &&	    ((scsi_info_t *)dev_id)->host != NULL  ) {		scsi_info_t *info = (scsi_info_t *)dev_id;		data = (nsp_hw_data *)(info->host->hostdata);	} else {		nsp_dbg(NSP_DEBUG_INTR, "host data wrong");		return IRQ_NONE;	}        spin_lock_irqsave(HOST_LOCK, flags);	//nsp_dbg(NSP_DEBUG_INTR, "&nsp_data_base=0x%p, dev_id=0x%p", &nsp_data_base, dev_id);	base = data->BaseAddress;	//nsp_dbg(NSP_DEBUG_INTR, "base=0x%x", base);	/*	 * interrupt check	 */	nsp_write(base, IRQCONTROL, IRQCONTROL_ALL_MASK);	irq_status = nsp_read(base, IRQSTATUS);	//nsp_dbg(NSP_DEBUG_INTR, "irq_status=0x%x", irq_status);	if ((irq_status == 0xff) || ((irq_status & IRQSTATUS_MASK) == 0)) {		//nsp_dbg(NSP_DEBUG_INTR, "no irq/shared irq");		goto out;	}	handled = 1;	/* XXX: IMPORTANT	 * Do not read an irq_phase register if no scsi phase interrupt.	 * Unless, you should lose a scsi phase interrupt.	 */	phase = nsp_index_read(base, SCSIBUSMON);	if((irq_status & IRQSTATUS_SCSI) != 0) {		irq_phase = nsp_index_read(base, IRQPHASESENCE);	} else {		irq_phase = 0;	}	//nsp_dbg(NSP_DEBUG_INTR, "irq_phase=0x%x", irq_phase);	/*	 * timer interrupt handler (scsi vs timer interrupts)	 */	//nsp_dbg(NSP_DEBUG_INTR, "timercount=%d", data->TimerCount);	if (data->TimerCount != 0) {		//nsp_dbg(NSP_DEBUG_INTR, "stop timer");		nsp_index_write(base, TIMERCOUNT, 0);		nsp_index_write(base, TIMERCOUNT, 0);		data->TimerCount = 0;	}	if ((irq_status & IRQSTATUS_MASK) == IRQSTATUS_TIMER &&	    data->SelectionTimeOut == 0) {		//nsp_dbg(NSP_DEBUG_INTR, "timer start");		nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR);		goto out;	}	nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR | IRQCONTROL_FIFO_CLEAR);	if ((irq_status & IRQSTATUS_SCSI) &&	    (irq_phase  & SCSI_RESET_IRQ)) {		nsp_msg(KERN_ERR, "bus reset (power off?)");		nsphw_init(data);		nsp_bus_reset(data);		if(data->CurrentSC != NULL) {			tmpSC = data->CurrentSC;			tmpSC->result  = (DID_RESET                   << 16) |				         ((tmpSC->SCp.Message & 0xff) <<  8) |				         ((tmpSC->SCp.Status  & 0xff) <<  0);			nsp_scsi_done(tmpSC);		}		goto out;	}	if (data->CurrentSC == NULL) {		nsp_msg(KERN_ERR, "CurrentSC==NULL irq_status=0x%x phase=0x%x irq_phase=0x%x this can't be happen. reset everything", irq_status, phase, irq_phase);		nsphw_init(data);		nsp_bus_reset(data);		goto out;	}	tmpSC    = data->CurrentSC;	target   = tmpSC->device->id;	lun      = tmpSC->device->lun;	sync_neg = &(data->Sync[target].SyncNegotiation);	/*	 * parse hardware SCSI irq reasons register	 */	if (irq_status & IRQSTATUS_SCSI) {		if (irq_phase & RESELECT_IRQ) {			nsp_dbg(NSP_DEBUG_INTR, "reselect");			nsp_write(base, IRQCONTROL, IRQCONTROL_RESELECT_CLEAR);			if (nsp_reselected(tmpSC) != FALSE) {				goto out;			}		}		if ((irq_phase & (PHASE_CHANGE_IRQ | LATCHED_BUS_FREE)) == 0) {			goto out;		}	}	//show_phase(tmpSC);	switch(tmpSC->SCp.phase) {	case PH_SELSTART:		// *sync_neg = SYNC_NOT_YET;		if ((phase & BUSMON_BSY) == 0) {			//nsp_dbg(NSP_DEBUG_INTR, "selection count=%d", data->SelectionTimeOut);			if (data->SelectionTimeOut >= NSP_SELTIMEOUT) {				nsp_dbg(NSP_DEBUG_INTR, "selection time out");				data->SelectionTimeOut = 0;				nsp_index_write(base, SCSIBUSCTRL, 0);				tmpSC->result   = DID_TIME_OUT << 16;				nsp_scsi_done(tmpSC);				goto out;			}			data->SelectionTimeOut += 1;			nsp_start_timer(tmpSC, 1000/51);			goto out;		}		/* attention assert */		//nsp_dbg(NSP_DEBUG_INTR, "attention assert");		data->SelectionTimeOut = 0;		tmpSC->SCp.phase       = PH_SELECTED;		nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN);		udelay(1);		nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN | AUTODIRECTION | ACKENB);		goto out;		break;	case PH_RESELECT:		//nsp_dbg(NSP_DEBUG_INTR, "phase reselect");		// *sync_neg = SYNC_NOT_YET;		if ((phase & BUSMON_PHASE_MASK) != BUSPHASE_MESSAGE_IN) {			tmpSC->result	= DID_ABORT << 16;			nsp_scsi_done(tmpSC);			goto out;		}		/* fall thru */	default:		if ((irq_status & (IRQSTATUS_SCSI | IRQSTATUS_FIFO)) == 0) {			goto out;		}		break;	}	/*	 * SCSI sequencer	 */	//nsp_dbg(NSP_DEBUG_INTR, "start scsi seq");	/* normal disconnect */	if (((tmpSC->SCp.phase == PH_MSG_IN) || (tmpSC->SCp.phase == PH_MSG_OUT)) &&	    (irq_phase & LATCHED_BUS_FREE) != 0 ) {		nsp_dbg(NSP_DEBUG_INTR, "normal disconnect irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase);		// *sync_neg       = SYNC_NOT_YET;		if ((tmpSC->SCp.Message == MSG_COMMAND_COMPLETE)) {     /* all command complete and return status */			tmpSC->result = (DID_OK		             << 16) |					((tmpSC->SCp.Message & 0xff) <<  8) |					((tmpSC->SCp.Status  & 0xff) <<  0);			nsp_dbg(NSP_DEBUG_INTR, "command complete result=0x%x", tmpSC->result);			nsp_scsi_done(tmpSC);			goto out;		}		goto out;	}	/* check unexpected bus free state */	if (phase == 0) {		nsp_msg(KERN_DEBUG, "unexpected bus free. irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase);		*sync_neg       = SYNC_NG;		tmpSC->result   = DID_ERROR << 16;		nsp_scsi_done(tmpSC);		goto out;	}	switch (phase & BUSMON_PHASE_MASK) {	case BUSPHASE_COMMAND:		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_COMMAND");		if ((phase & BUSMON_REQ) == 0) {			nsp_dbg(NSP_DEBUG_INTR, "REQ == 0");			goto out;		}		tmpSC->SCp.phase = PH_COMMAND;		nsp_nexus(tmpSC);		/* write scsi command */		nsp_dbg(NSP_DEBUG_INTR, "cmd_len=%d", tmpSC->cmd_len);		nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER);		for (i = 0; i < tmpSC->cmd_len; i++) {			nsp_index_write(base, COMMANDDATA, tmpSC->cmnd[i]);		}		nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER | AUTO_COMMAND_GO);		break;	case BUSPHASE_DATA_OUT:		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_OUT");		tmpSC->SCp.phase        = PH_DATA;		tmpSC->SCp.have_data_in = IO_OUT;		nsp_pio_write(tmpSC);		break;	case BUSPHASE_DATA_IN:		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_IN");		tmpSC->SCp.phase        = PH_DATA;		tmpSC->SCp.have_data_in = IO_IN;		nsp_pio_read(tmpSC);		break;	case BUSPHASE_STATUS:		nsp_dataphase_bypass(tmpSC);		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_STATUS");		tmpSC->SCp.phase = PH_STATUS;		tmpSC->SCp.Status = nsp_index_read(base, SCSIDATAWITHACK);		nsp_dbg(NSP_DEBUG_INTR, "message=0x%x status=0x%x", tmpSC->SCp.Message, tmpSC->SCp.Status);		break;	case BUSPHASE_MESSAGE_OUT:		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_OUT");		if ((phase & BUSMON_REQ) == 0) {			goto timer_out;		}		tmpSC->SCp.phase = PH_MSG_OUT;		// *sync_neg = SYNC_NOT_YET;		data->MsgLen = i = 0;		data->MsgBuffer[i] = IDENTIFY(TRUE, lun); i++;		if (*sync_neg == SYNC_NOT_YET) {			data->Sync[target].SyncPeriod = 0;			data->Sync[target].SyncOffset = 0;			/**/			data->MsgBuffer[i] = MSG_EXTENDED; i++;			data->MsgBuffer[i] = 3;            i++;			data->MsgBuffer[i] = MSG_EXT_SDTR; i++;			data->MsgBuffer[i] = 0x0c;         i++;			data->MsgBuffer[i] = 15;           i++;			/**/		}		data->MsgLen = i;		nsp_analyze_sdtr(tmpSC);		show_message(data);		nsp_message_out(tmpSC);		break;	case BUSPHASE_MESSAGE_IN:		nsp_dataphase_bypass(tmpSC);		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_IN");		if ((phase & BUSMON_REQ) == 0) {			goto timer_out;		}		tmpSC->SCp.phase = PH_MSG_IN;		nsp_message_in(tmpSC);		/**/		if (*sync_neg == SYNC_NOT_YET) {			//nsp_dbg(NSP_DEBUG_INTR, "sync target=%d,lun=%d",target,lun);			if (data->MsgLen       >= 5            &&			    data->MsgBuffer[0] == MSG_EXTENDED &&			    data->MsgBuffer[1] == 3            &&			    data->MsgBuffer[2] == MSG_EXT_SDTR ) {				data->Sync[target].SyncPeriod = data->MsgBuffer[3];				data->Sync[target].SyncOffset = data->MsgBuffer[4];				//nsp_dbg(NSP_DEBUG_INTR, "sync ok, %d %d", data->MsgBuffer[3], data->MsgBuffer[4]);				*sync_neg = SYNC_OK;			} else {				data->Sync[target].SyncPeriod = 0;				data->Sync[target].SyncOffset = 0;				*sync_neg = SYNC_NG;			}			nsp_analyze_sdtr(tmpSC);		}		/**/		/* search last messeage byte */		tmp = -1;		for (i = 0; i < data->MsgLen; i++) {			tmp = data->MsgBuffer[i];			if (data->MsgBuffer[i] == MSG_EXTENDED) {				i += (1 + data->MsgBuffer[i+1]);			}		}		tmpSC->SCp.Message = tmp;		nsp_dbg(NSP_DEBUG_INTR, "message=0x%x len=%d", tmpSC->SCp.Message, data->MsgLen);		show_message(data);		break;	case BUSPHASE_SELECT:	default:		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE other");		break;	}	goto out;timer_out:	nsp_start_timer(tmpSC, 1000/102); out:	nsp_write(base, IRQCONTROL, 0); /* clear IRQ mask */        spin_unlock_irqrestore(HOST_LOCK, flags);	//nsp_dbg(NSP_DEBUG_INTR, "out");	return IRQ_RETVAL(handled);}/*----------------------------------------------------------------*//* look for ninja3 card and init if found			  *//*----------------------------------------------------------------*/static struct Scsi_Host *nsp_detect(Scsi_Host_Template *sht)

⌨️ 快捷键说明

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