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

📄 nsp_cs.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (data->FifoCount == count) {		//DEBUG(0, " not use bypass quirk\n");		return 0;	}	/*	 * XXX: NSP_QUIRK	 * data phase skip only occures in case of SCSI_LOW_READ	 */	SCpnt->SCp.phase = PH_DATA;	nsp_pio_read(SCpnt, data);	nsp_setup_fifo(data, FALSE);	DEBUG(0, " use bypass quirk\n");	return 0;}/* * accept reselection */static int nsp_reselected(Scsi_Cmnd *SCpnt, nsp_hw_data *data){	unsigned int  base = SCpnt->host->io_port;	unsigned char reg;	//DEBUG(0, __FUNCTION__ "()\n");	nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>");	nsp_nexus(SCpnt, data);	reg = nsp_index_read(base, SCSIBUSCTRL) & ~(SCSI_BSY | SCSI_ATN);	nsp_index_write(base, SCSIBUSCTRL, reg);	nsp_index_write(base, SCSIBUSCTRL, reg | AUTODIRECTION | ACKENB);	return TRUE;}/* * count how many data transferd */static int nsp_fifo_count(Scsi_Cmnd *SCpnt){	unsigned int base = SCpnt->host->io_port;	unsigned int count;	unsigned int l, m, h;	nsp_index_write(base, POINTERCLR, POINTER_CLEAR);        l = (unsigned int)nsp_read(base, DATAREG);        m = (unsigned int)nsp_read(base, DATAREG);        h = (unsigned int)nsp_read(base, DATAREG);	count = (h << 16) | (m << 8) | (l << 0);	//DEBUG(0, __FUNCTION__ "() =0x%x\n", count);	return count;}/* fifo size */#define RFIFO_CRIT 64#define WFIFO_CRIT 64/* * read data in DATA IN phase */static void nsp_pio_read(Scsi_Cmnd *SCpnt, nsp_hw_data *data){	unsigned int  base     = SCpnt->host->io_port;	int	      time_out, i;	int	      ocount, res;	unsigned char stat, fifo_stat;	ocount = data->FifoCount;	DEBUG(0, __FUNCTION__ "() in SCpnt=0x%p resid=%d ocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d\n", SCpnt, RESID, ocount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual);	time_out = jiffies + 10 * HZ;	while ((i = time_before(jiffies,time_out)) &&	       (SCpnt->SCp.this_residual > 0 || SCpnt->SCp.buffers_residual > 0 ) ) {		stat = nsp_index_read(base, SCSIBUSMON);		stat &= BUSMON_PHASE_MASK;		res = nsp_fifo_count(SCpnt) - ocount;		//DEBUG(0, " ptr=0x%p this=0x%x ocount=0x%x res=0x%x\n", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount, res);		if (res == 0) { /* if some data avilable ? */			if (stat == BUSPHASE_DATA_IN) { /* phase changed? */				//DEBUG(0, " wait for data this=%d\n", SCpnt->SCp.this_residual);				continue;			} else {				DEBUG(0, " phase changed stat=0x%x\n", stat);				break;			}		}		fifo_stat = nsp_read(base, FIFOSTATUS);		if ((fifo_stat & FIFOSTATUS_FULL_EMPTY) == 0 &&		    stat                                == BUSPHASE_DATA_IN) {			continue;		}		res = MIN(res, SCpnt->SCp.this_residual);		switch (data->TransferMode) {		case MODE_IO32:			res &= ~(BIT(1)|BIT(0)); /* align 4 */			nsp_fifo32_read(base, SCpnt->SCp.ptr, res >> 2);			break;		case MODE_IO8:			nsp_fifo8_read (base, SCpnt->SCp.ptr, res     );			break;		default:			DEBUG(0, "unknown read mode\n");			break;		}		RESID			 -= res;		SCpnt->SCp.ptr		 += res;		SCpnt->SCp.this_residual -= res;		ocount			 += res;		//DEBUG(0, " ptr=0x%p this_residual=0x%x ocount=0x%x\n", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount);		/* go to next scatter list if availavle */		if (SCpnt->SCp.this_residual	== 0 &&		    SCpnt->SCp.buffers_residual != 0 ) {			//DEBUG(0, " scatterlist next timeout=%d\n", time_out);			SCpnt->SCp.buffers_residual--;			SCpnt->SCp.buffer++;			SCpnt->SCp.ptr		 = SCpnt->SCp.buffer->address;			SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;		}		time_out = jiffies + 10 * HZ;	}	data->FifoCount = ocount;	if (!i) {		printk(KERN_DEBUG __FUNCTION__ "() pio read timeout resid=%d this_residual=%d buffers_residual=%d\n", RESID, SCpnt->SCp.this_residual, SCpnt->SCp.buffers_residual);	}	DEBUG(0, " read ocount=0x%x\n", ocount);}/* * write data in DATA OUT phase */static void nsp_pio_write(Scsi_Cmnd *SCpnt, nsp_hw_data *data){	unsigned int  base     = SCpnt->host->io_port;	int	      time_out, i;	unsigned int  ocount, res;	unsigned char stat;	ocount	 = data->FifoCount;	DEBUG(0, __FUNCTION__ "() in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x\n", data->FifoCount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual, RESID);	time_out = jiffies + 10 * HZ;	while ((i = time_before(jiffies, time_out))                             &&	       (SCpnt->SCp.this_residual > 0 || SCpnt->SCp.buffers_residual > 0)) {		stat = nsp_index_read(base, SCSIBUSMON);		stat &= BUSMON_PHASE_MASK;		if (stat != BUSPHASE_DATA_OUT) {			DEBUG(0, " phase changed stat=0x%x\n", stat);			break;		}		res = ocount - nsp_fifo_count(SCpnt);		if (res > 0) { /* write all data? */			DEBUG(0, " wait for all data out. ocount=0x%x res=%d\n", ocount, res);			continue;		}		res = MIN(SCpnt->SCp.this_residual, WFIFO_CRIT);		//DEBUG(0, " ptr=0x%p this=0x%x res=0x%x\n", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, res);		switch (data->TransferMode) {		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;		default:			DEBUG(0, "unknown write mode\n");			break;		}		RESID			 -= res;		SCpnt->SCp.ptr		 += res;		SCpnt->SCp.this_residual -= res;		ocount			 += res;		/* go to next scatter list if availavle */		if (SCpnt->SCp.this_residual	== 0 &&		    SCpnt->SCp.buffers_residual != 0 ) {			//DEBUG(0, " scatterlist next\n");			SCpnt->SCp.buffers_residual--;			SCpnt->SCp.buffer++;			SCpnt->SCp.ptr		 = SCpnt->SCp.buffer->address;			SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;		}		time_out = jiffies + 10 * HZ;	}	data->FifoCount = ocount;	if (!i) {		printk(KERN_DEBUG __FUNCTION__ "() pio write timeout resid=%d\n", RESID);	}	//DEBUG(0, " write ocount=%d\n", ocount);}#undef RFIFO_CRIT#undef WFIFO_CRIT/* * setup synchronous/asynchronous data transfer mode */static int nsp_nexus(Scsi_Cmnd *SCpnt, nsp_hw_data *data){	unsigned int   base   = SCpnt->host->io_port;	unsigned char  target = SCpnt->target;	unsigned char  lun    = SCpnt->lun;	sync_data     *sync   = &(data->Sync[target][lun]);	//DEBUG(0, __FUNCTION__ "() in SCpnt=0x%p\n", SCpnt);	/* setup synch transfer registers */	nsp_index_write(base, SYNCREG,	sync->SyncRegister);	nsp_index_write(base, ACKWIDTH, sync->AckWidth);	if (RESID % 4 != 0   ||	    RESID     <= 256 ) {		data->TransferMode = MODE_IO8;	} else {		data->TransferMode = MODE_IO32;	}	/* 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 void nspintr(int irq, void *dev_id, struct pt_regs *regs){	unsigned int   base;	unsigned char  i_src, irq_phase, phase;	Scsi_Cmnd     *tmpSC;	int            len;	unsigned char  target, lun;	unsigned int  *sync_neg;	int            i, tmp;	nsp_hw_data   *data;	//printk("&nsp_data=0x%p, dev_id=0x%p\n", &nsp_data, dev_id);	/* sanity check */	if (&nsp_data != dev_id) {		DEBUG(0, " irq conflict? this can't happen\n");		return;	}	data = dev_id;	if (irq != data->IrqNumber) {		return;	}	base = data->BaseAddress;	//DEBUG(0, " base=0x%x\n", base);	/*	 * interrupt check	 */	nsp_write(base, IRQCONTROL, IRQCONTROL_IRQDISABLE);	i_src = nsp_read(base, IRQSTATUS);	if (i_src == 0xff || (i_src & IRQSTATUS_MASK) == 0) {		nsp_write(base, IRQCONTROL, 0);		//DEBUG(0, " no irq\n");		return;	}	//DEBUG(0, " i_src=0x%x\n", i_src);	/* 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((i_src & IRQSTATUS_SCSI) != 0) {		irq_phase = nsp_index_read(base, IRQPHASESENCE);	} else {		irq_phase = 0;	}	//DEBUG(0, " irq_phase=0x%x\n", irq_phase);	/*	 * timer interrupt handler (scsi vs timer interrupts)	 */	//DEBUG(0, " timercount=%d\n", data->TimerCount);	if (data->TimerCount != 0) {		//DEBUG(0, " stop timer\n");		nsp_index_write(base, TIMERCOUNT, 0);		nsp_index_write(base, TIMERCOUNT, 0);		data->TimerCount = 0;	}	if ((i_src & IRQSTATUS_MASK) == IRQSTATUS_TIMER &&	    data->SelectionTimeOut == 0) {		//DEBUG(0, " timer start\n");		nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR);		return;	}	nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR | IRQCONTROL_FIFO_CLEAR);	if (data->CurrentSC == NULL) {		printk(KERN_DEBUG __FUNCTION__ " CurrentSC==NULL irq_status=0x%x phase=0x%x irq_phase=0x%x this can't be happen\n", i_src, phase, irq_phase);		return;	} else {		tmpSC    = data->CurrentSC;		target   = tmpSC->target;		lun      = tmpSC->lun;		sync_neg = &(data->Sync[target][lun].SyncNegotiation);	}	/*	 * parse hardware SCSI irq reasons register	 */	if ((i_src & IRQSTATUS_SCSI) != 0) {		if ((irq_phase & SCSI_RESET_IRQ) != 0) {			printk(KERN_DEBUG " " __FUNCTION__ "() bus reset (power off?)\n");			*sync_neg          = SYNC_NOT_YET;			data->CurrentSC    = NULL;			tmpSC->result	   = DID_RESET << 16;			tmpSC->scsi_done(tmpSC);			return;		}		if ((irq_phase & RESELECT_IRQ) != 0) {			DEBUG(0, " reselect\n");			nsp_write(base, IRQCONTROL, IRQCONTROL_RESELECT_CLEAR);			if (nsp_reselected(tmpSC, data) != FALSE) {				return;			}		}		if ((irq_phase & (PHASE_CHANGE_IRQ | LATCHED_BUS_FREE)) == 0) {			return; 		}	}	//show_phase(tmpSC);	switch(tmpSC->SCp.phase) {	case PH_SELSTART:		*sync_neg = SYNC_NOT_YET;		if ((phase & BUSMON_BSY) == 0) {			//DEBUG(0, " selection count=%d\n", data->SelectionTimeOut);			if (data->SelectionTimeOut >= NSP_SELTIMEOUT) {				DEBUG(0, " selection time out\n");				data->SelectionTimeOut = 0;				nsp_index_write(base, SCSIBUSCTRL, 0);				data->CurrentSC = NULL;				tmpSC->result   = DID_NO_CONNECT << 16;				tmpSC->scsi_done(tmpSC);				return;			}			data->SelectionTimeOut += 1;			nsp_start_timer(tmpSC, data, 1000/51);			return;		}		/* attention assert */		//DEBUG(0, " attention assert\n");		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);		return;		break;	case PH_RESELECT:		//DEBUG(0, " phase reselect\n");		*sync_neg = SYNC_NOT_YET;		if ((phase & BUSMON_PHASE_MASK) != BUSPHASE_MESSAGE_IN) {			data->CurrentSC = NULL;			tmpSC->result	= DID_ABORT << 16;			tmpSC->scsi_done(tmpSC);			return;		}		/* fall thru */	default:		if ((i_src & (IRQSTATUS_SCSI | IRQSTATUS_FIFO)) == 0) {			return;		}		break;	}	/*	 * SCSI sequencer	 */	//DEBUG(0, " start scsi seq\n");	/* normal disconnect */	if ((irq_phase & LATCHED_BUS_FREE) != 0) {		//DEBUG(0, " normal disconnect i_src=0x%x, phase=0x%x, irq_phase=0x%x\n", i_src, phase, irq_phase);		if ((tmpSC->SCp.Message == MSG_COMMAND_COMPLETE)) {     /* all command complete and return status */			*sync_neg       = SYNC_NOT_YET;			data->CurrentSC = NULL;			tmpSC->result = (DID_OK		    << 16) |					(tmpSC->SCp.Message <<	8) |					(tmpSC->SCp.Status  <<	0);			DEBUG(0, " command complete result=0x%x\n", tmpSC->result);			tmpSC->scsi_done(tmpSC);			return;		}		return;	}	/* check unexpected bus free state */	if (phase == 0) {		printk(KERN_DEBUG " " __FUNCTION__ " unexpected bus free. i_src=0x%x, phase=0x%x, irq_phase=0x%x\n", i_src, phase, irq_phase);		*sync_neg       = SYNC_NOT_YET;		data->CurrentSC = NULL;		tmpSC->result   = DID_ERROR << 16;		tmpSC->scsi_done(tmpSC);		return;	}	switch (phase & BUSMON_PHASE_MASK) {	case BUSPHASE_COMMAND:		DEBUG(0, " BUSPHASE_COMMAND\n");		if ((phase & BUSMON_REQ) == 0) {			DEBUG(0, " REQ == 0\n");			return;		}		tmpSC->SCp.phase = PH_COMMAND;		nsp_nexus(tmpSC, data);		/* write scsi command */		nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER);		for (len = 0; len < COMMAND_SIZE(tmpSC->cmnd[0]); len++) {			nsp_index_write(base, COMMANDDATA, tmpSC->cmnd[len]);		}		nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER | AUTO_COMMAND_GO);		break;	case BUSPHASE_DATA_OUT:		DEBUG(0, " BUSPHASE_DATA_OUT\n");		tmpSC->SCp.phase = PH_DATA;		tmpSC->SCp.have_data_in = IO_OUT;		nsp_pio_write(tmpSC, data);		break;	case BUSPHASE_DATA_IN:		DEBUG(0, " BUSPHASE_DATA_IN\n");		tmpSC->SCp.phase = PH_DATA;		tmpSC->SCp.have_data_in = IO_IN;		nsp_pio_read(tmpSC, data);		break;	case BUSPHASE_STATUS:		nsp_dataphase_bypass(tmpSC, data);		DEBUG(0, " BUSPHASE_STATUS\n");		tmpSC->SCp.phase = PH_STATUS;		tmpSC->SCp.Status = nsp_index_read(base, SCSIDATAWITHACK);		//DEBUG(0, " message=0x%x status=0x%x\n", tmpSC->SCp.Message, tmpSC->SCp.Status);		break;	case BUSPHASE_MESSAGE_OUT:		DEBUG(0, " BUSPHASE_MESSAGE_OUT\n");		if ((phase & BUSMON_REQ) == 0) {			goto timer_out;		}		tmpSC->SCp.phase = PH_MSG_OUT;		data->MsgLen = len = 0;		if (*sync_neg == SYNC_NOT_YET) {			data->Sync[target][lun].SyncPeriod = 0;			data->Sync[target][lun].SyncOffset = 0;			nsp_msg(tmpSC, data);			data->MsgBuffer[len] = IDENTIFY(TRUE, lun); len++;			/*			data->MsgBuffer[len] = MSG_EXTENDED;        len++;			data->MsgBuffer[len] = 3;                   len++;			data->MsgBuffer[len] = MSG_EXT_SDTR;        len++;			data->MsgBuffer[len] = 0x0c;                len++;			data->MsgBuffer[len] = 15;                  len++;			*/		}		if (len == 0) {			data->MsgBuffer[len] = MSG_NO_OPERATION; len++;		}		data->MsgLen = len;		show_message(data);		nsp_message_out(tmpSC, data);		break;	case BUSPHASE_MESSAGE_IN:		nsp_dataphase_bypass(tmpSC, data);		DEBUG(0, " BUSPHASE_MESSAGE_IN\n");		if ((phase & BUSMON_REQ) == 0) {			goto timer_out;		}		tmpSC->SCp.phase = PH_MSG_IN;		nsp_message_in(tmpSC, data);		/*		if (data->MsgLen       >= 5            &&		    data->MsgBuffer[0] == MSG_EXTENDED &&		    data->MsgBuffer[1] == 3            &&		    data->MsgBuffer[2] == MSG_EXT_SDTR ) {			data->Sync[target][lun].SyncPeriod = data->MsgBuffer[3];			data->Sync[target][lun].SyncOffset = data->MsgBuffer[4];			nsp_msg(tmpSC, data);		}		*/		/* 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;		DEBUG(0, " message=0x%x len=%d\n", tmpSC->SCp.Message, data->MsgLen);		show_message(data);		break;	case BUSPHASE_SELECT:	default:		DEBUG(0, " BUSPHASE other\n");		break;	}	//DEBUG(0, __FUNCTION__ "() out\n");	return;	

⌨️ 快捷键说明

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