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

📄 nsp_cs.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	{0x5,  2, 0x20, 0x25},  /*   7.5 : 150ns,  75ns */	{0x6,  2, 0x26, 0x31},  /*   5.71: 175ns,  75ns */	{0x7,  3, 0x32, 0x32},  /*   5.0 : 200ns, 100ns */	{0x8,  3, 0x33, 0x38},  /*   4.44: 225ns, 100ns */	{0x9,  3, 0x39, 0x3e},  /*   4.0 : 250ns, 100ns */	{0xa,  3, 0x3f, 0x44},  /*   3.64: 275ns, 100ns */	{0xb,  3, 0x45, 0x4b},  /*   3.33: 300ns, 100ns */	{0xc,  3, 0x4c, 0x53},  /*   3.01: 325ns, 100ns */	{0xd,  3, 0x54, 0x57},  /*   2.86: 350ns, 100ns */	{0xe,  3, 0x58, 0x5d},  /*   2.67: 375ns, 100ns */	{0xf,  3, 0x5e, 0x64},  /*   2.5 : 400ns, 100ns */	{0,0,0,0},};static struct nsp_sync_table nsp_sync_table_20M[] = {	{0x1,  0, 0x19, 0x19},  /* 10.0 : 100ns,  50ns */	{0x2,  0, 0x1a, 0x25},  /*  6.7 : 150ns,  50ns */	{0x3,  1, 0x26, 0x32},  /*  5.0 : 200ns, 100ns */	{0x4,  1, 0x33, 0x3e},  /*  4.0 : 250ns, 100ns */	{0x5,  2, 0x3f, 0x4b},  /*  3.3 : 300ns, 150ns */	{0x6,  2, 0x4c, 0x57},  /*  2.8 : 350ns, 150ns */	{0x7,  3, 0x58, 0x64},  /*  2.5 : 400ns, 200ns */	{0x8,  3, 0x65, 0x70},  /*  2.2 : 450ns, 200ns */	{0x9,  3, 0x71, 0x7d},  /*  2.0 : 500ns, 200ns */	{0xa,  3, 0x7e, 0x89},  /*  1.82: 550ns, 200ns */	{0xb,  3, 0x8a, 0x95},  /*  1.67: 550ns, 200ns */	{0xc,  3, 0x96, 0xa2},  /*  1.54: 550ns, 200ns */	{0xd,  3, 0xa3, 0xae},  /*  1.43: 550ns, 200ns */	{0xe,  3, 0xaf, 0xbb},  /*  1.33: 550ns, 200ns */	{0xf,  3, 0xbc, 0xc8},  /*  1.25: 550ns, 200ns */	{0,0,0,0},};/* * setup synchronous data transfer mode */static int nsp_analyze_sdtr(Scsi_Cmnd *SCpnt){	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]);	struct nsp_sync_table *sync_table;	unsigned int	       period, offset;	int		       i;	nsp_dbg(NSP_DEBUG_SYNC, "in");	period = sync->SyncPeriod;	offset = sync->SyncOffset;	nsp_dbg(NSP_DEBUG_SYNC, "period=0x%x, offset=0x%x", period, offset);	switch (data->ScsiClockDiv) {	case CLOCK_20M:	case CLOCK_40M:		sync_table = nsp_sync_table_20M;		break;	case CLOCK_40M | FAST_20:		sync_table = nsp_sync_table_40M;		break;	default:		nsp_msg(KERN_WARNING,			"Invalid clock div is selected, set 20M.");		sync_table = nsp_sync_table_20M;		break;	}	for ( i = 0; sync_table->max_period != 0; i++, sync_table++) {		if ( period >= sync_table->min_period &&		     period <= sync_table->max_period	 ) {			break;		}	}	if (period != 0 && sync_table->max_period == 0) {		/*		 * No proper period/offset found		 */		nsp_dbg(NSP_DEBUG_SYNC, "no proper period/offset");		sync->SyncPeriod      = 0;		sync->SyncOffset      = 0;		sync->SyncRegister    = 0;		sync->AckWidth	      = 0;		return FALSE;	}	sync->SyncRegister    = (sync_table->chip_period << SYNCREG_PERIOD_SHIFT) |		                (offset & SYNCREG_OFFSET_MASK);	sync->AckWidth	      = sync_table->ack_width;	nsp_dbg(NSP_DEBUG_SYNC, "sync_reg=0x%x, ack_width=0x%x", sync->SyncRegister, sync->AckWidth);	return TRUE;}/* * start ninja hardware timer */static void nsp_start_timer(Scsi_Cmnd *SCpnt, int time){	unsigned int base = SCpnt->device->host->io_port;	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;	//nsp_dbg(NSP_DEBUG_INTR, "in SCpnt=0x%p, time=%d", SCpnt, time);	data->TimerCount = time;	nsp_index_write(base, TIMERCOUNT, time);}/* * wait for bus phase change */static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str){	unsigned int  base = SCpnt->device->host->io_port;	unsigned char reg;	int	      time_out;	//nsp_dbg(NSP_DEBUG_INTR, "in");	time_out = 100;	do {		reg = nsp_index_read(base, SCSIBUSMON);		if (reg == 0xff) {			break;		}	} while ((time_out-- != 0) && (reg & mask) != 0);	if (time_out == 0) {		nsp_msg(KERN_DEBUG, " %s signal off timeut", str);	}	return 0;}/* * expect Ninja Irq */static int nsp_expect_signal(Scsi_Cmnd	   *SCpnt,			     unsigned char  current_phase,			     unsigned char  mask){	unsigned int  base	 = SCpnt->device->host->io_port;	int	      time_out;	unsigned char phase, i_src;	//nsp_dbg(NSP_DEBUG_INTR, "current_phase=0x%x, mask=0x%x", current_phase, mask);	time_out = 100;	do {		phase = nsp_index_read(base, SCSIBUSMON);		if (phase == 0xff) {			//nsp_dbg(NSP_DEBUG_INTR, "ret -1");			return -1;		}		i_src = nsp_read(base, IRQSTATUS);		if (i_src & IRQSTATUS_SCSI) {			//nsp_dbg(NSP_DEBUG_INTR, "ret 0 found scsi signal");			return 0;		}		if ((phase & mask) != 0 && (phase & BUSMON_PHASE_MASK) == current_phase) {			//nsp_dbg(NSP_DEBUG_INTR, "ret 1 phase=0x%x", phase);			return 1;		}	} while(time_out-- != 0);	//nsp_dbg(NSP_DEBUG_INTR, "timeout");	return -1;}/* * transfer SCSI message */static int nsp_xfer(Scsi_Cmnd *SCpnt, int phase){	unsigned int  base = SCpnt->device->host->io_port;	nsp_hw_data  *data = (nsp_hw_data *)SCpnt->device->host->hostdata;	char	     *buf  = data->MsgBuffer;	int	      len  = MIN(MSGBUF_SIZE, data->MsgLen);	int	      ptr;	int	      ret;	//nsp_dbg(NSP_DEBUG_DATA_IO, "in");	for (ptr = 0; len > 0; len--, ptr++) {		ret = nsp_expect_signal(SCpnt, phase, BUSMON_REQ);		if (ret <= 0) {			nsp_dbg(NSP_DEBUG_DATA_IO, "xfer quit");			return 0;		}		/* if last byte, negate ATN */		if (len == 1 && SCpnt->SCp.phase == PH_MSG_OUT) {			nsp_index_write(base, SCSIBUSCTRL, AUTODIRECTION | ACKENB);		}		/* read & write message */		if (phase & BUSMON_IO) {			nsp_dbg(NSP_DEBUG_DATA_IO, "read msg");			buf[ptr] = nsp_index_read(base, SCSIDATAWITHACK);		} else {			nsp_dbg(NSP_DEBUG_DATA_IO, "write msg");			nsp_index_write(base, SCSIDATAWITHACK, buf[ptr]);		}		nsp_negate_signal(SCpnt, BUSMON_ACK, "xfer<ack>");	}	return len;}/* * get extra SCSI data from fifo */static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt){	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;	unsigned int count;	//nsp_dbg(NSP_DEBUG_DATA_IO, "in");	if (SCpnt->SCp.have_data_in != IO_IN) {		return 0;	}	count = nsp_fifo_count(SCpnt);	if (data->FifoCount == count) {		//nsp_dbg(NSP_DEBUG_DATA_IO, "not use bypass quirk");		return 0;	}	/*	 * XXX: NSP_QUIRK	 * data phase skip only occures in case of SCSI_LOW_READ	 */	nsp_dbg(NSP_DEBUG_DATA_IO, "use bypass quirk");	SCpnt->SCp.phase = PH_DATA;	nsp_pio_read(SCpnt);	nsp_setup_fifo(data, FALSE);	return 0;}/* * accept reselection */static int nsp_reselected(Scsi_Cmnd *SCpnt){	unsigned int  base    = SCpnt->device->host->io_port;	unsigned int  host_id = SCpnt->device->host->this_id;	//nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;	unsigned char bus_reg;	unsigned char id_reg, tmp;	int target;	nsp_dbg(NSP_DEBUG_RESELECTION, "in");	id_reg = nsp_index_read(base, RESELECTID);	tmp    = id_reg & (~BIT(host_id));	target = 0;	while(tmp != 0) {		if (tmp & BIT(0)) {			break;		}		tmp >>= 1;		target++;	}	if (SCpnt->device->id != target) {		nsp_msg(KERN_ERR, "XXX: reselect ID must be %d in this implementation.", target);	}	nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>");	nsp_nexus(SCpnt);	bus_reg = nsp_index_read(base, SCSIBUSCTRL) & ~(SCSI_BSY | SCSI_ATN);	nsp_index_write(base, SCSIBUSCTRL, bus_reg);	nsp_index_write(base, SCSIBUSCTRL, bus_reg | AUTODIRECTION | ACKENB);	return TRUE;}/* * count how many data transferd */static int nsp_fifo_count(Scsi_Cmnd *SCpnt){	unsigned int base = SCpnt->device->host->io_port;	unsigned int count;	unsigned int l, m, h, dummy;	nsp_index_write(base, POINTERCLR, POINTER_CLEAR | ACK_COUNTER);	l     = nsp_index_read(base, TRANSFERCOUNT);	m     = nsp_index_read(base, TRANSFERCOUNT);	h     = nsp_index_read(base, TRANSFERCOUNT);	dummy = nsp_index_read(base, TRANSFERCOUNT); /* required this! */	count = (h << 16) | (m << 8) | (l << 0);	//nsp_dbg(NSP_DEBUG_DATA_IO, "count=0x%x", 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){	unsigned int  base      = SCpnt->device->host->io_port;	unsigned long mmio_base = SCpnt->device->host->base;	nsp_hw_data  *data      = (nsp_hw_data *)SCpnt->device->host->hostdata;	long	      time_out;	int	      ocount, res;	unsigned char stat, fifo_stat;	ocount = data->FifoCount;	nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p resid=%d ocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d",		SCpnt, SCpnt->resid, ocount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual);	time_out = 1000;	while ((time_out-- != 0) &&	       (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;		//nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x ocount=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount, res);		if (res == 0) { /* if some data avilable ? */			if (stat == BUSPHASE_DATA_IN) { /* phase changed? */				//nsp_dbg(NSP_DEBUG_DATA_IO, " wait for data this=%d", SCpnt->SCp.this_residual);				continue;			} else {				nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x", 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;		case MODE_MEM32:			res &= ~(BIT(1)|BIT(0)); /* align 4 */			nsp_mmio_fifo32_read(mmio_base, SCpnt->SCp.ptr, res >> 2);			break;		default:			nsp_dbg(NSP_DEBUG_DATA_IO, "unknown read mode");			return;		}		SCpnt->resid	       	 -= res;		SCpnt->SCp.ptr		 += res;		SCpnt->SCp.this_residual -= res;		ocount			 += res;		//nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this_residual=0x%x ocount=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount);		/* 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 timeout=%d", time_out);			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;			//nsp_dbg(NSP_DEBUG_DATA_IO, "page: 0x%p, off: 0x%x", SCpnt->SCp.buffer->page, SCpnt->SCp.buffer->offset);		}	}	data->FifoCount = ocount;	if (time_out == 0) {		nsp_msg(KERN_DEBUG, "pio read timeout resid=%d this_residual=%d buffers_residual=%d",			SCpnt->resid, SCpnt->SCp.this_residual, SCpnt->SCp.buffers_residual);	}	nsp_dbg(NSP_DEBUG_DATA_IO, "read ocount=0x%x", ocount);	nsp_dbg(NSP_DEBUG_DATA_IO, "r cmd=%d resid=0x%x\n", data->CmdId, SCpnt->resid);}/* * write data in DATA OUT phase */static void nsp_pio_write(Scsi_Cmnd *SCpnt){	unsigned int  base      = SCpnt->device->host->io_port;	unsigned long mmio_base = SCpnt->device->host->base;	nsp_hw_data  *data      = (nsp_hw_data *)SCpnt->device->host->hostdata;	int	      time_out;	int           ocount, res;	unsigned char stat;	ocount	 = data->FifoCount;	nsp_dbg(NSP_DEBUG_DATA_IO, "in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x",		data->FifoCount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual, SCpnt->resid);	time_out = 1000;	while ((time_out-- != 0) &&	       (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) {			res = ocount - nsp_fifo_count(SCpnt);			nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x, res=%d\n", stat, res);			/* Put back pointer */			SCpnt->resid	       	 += res;			SCpnt->SCp.ptr		 -= res;			SCpnt->SCp.this_residual += res;			ocount			 -= res;			break;		}		res = ocount - nsp_fifo_count(SCpnt);		if (res > 0) { /* write all data? */			nsp_dbg(NSP_DEBUG_DATA_IO, "wait for all data out. ocount=0x%x res=%d", ocount, res);			continue;		}		res = MIN(SCpnt->SCp.this_residual, WFIFO_CRIT);		//nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, res);		switch (data->TransferMode) {

⌨️ 快捷键说明

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