brintos

brintos / linux-shallow public Read only

0
0
Text · 45.5 KiB · a5a1406 Raw
1759 lines · c
1/*======================================================================2 3    NinjaSCSI-3 / NinjaSCSI-32Bi PCMCIA SCSI host adapter card driver4      By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>5 6    Ver.2.8   Support 32bit MMIO mode7              Support Synchronous Data Transfer Request (SDTR) mode8    Ver.2.0   Support 32bit PIO mode9    Ver.1.1.2 Fix for scatter list buffer exceeds10    Ver.1.1   Support scatter list11    Ver.0.1   Initial version12 13    This software may be used and distributed according to the terms of14    the GNU General Public License.15 16======================================================================*/17 18/***********************************************************************19    This driver is for these PCcards.20 21	I-O DATA PCSC-F	 (Workbit NinjaSCSI-3)22			"WBT", "NinjaSCSI-3", "R1.0"23	I-O DATA CBSC-II (Workbit NinjaSCSI-32Bi in 16bit mode)24			"IO DATA", "CBSC16	 ", "1"25 26***********************************************************************/27 28#include <linux/module.h>29#include <linux/kernel.h>30#include <linux/init.h>31#include <linux/slab.h>32#include <linux/string.h>33#include <linux/timer.h>34#include <linux/ioport.h>35#include <linux/delay.h>36#include <linux/interrupt.h>37#include <linux/major.h>38#include <linux/blkdev.h>39#include <linux/stat.h>40 41#include <asm/io.h>42#include <asm/irq.h>43 44#include <scsi/scsi.h>45#include <scsi/scsi_cmnd.h>46#include <scsi/scsi_host.h>47#include <scsi/scsi_ioctl.h>48 49#include <pcmcia/cistpl.h>50#include <pcmcia/cisreg.h>51#include <pcmcia/ds.h>52 53#include "nsp_cs.h"54 55MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");56MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module");57MODULE_LICENSE("GPL");58 59#include "nsp_io.h"60 61/*====================================================================*/62/* Parameters that can be set with 'insmod' */63 64static int       nsp_burst_mode = BURST_MEM32;65module_param(nsp_burst_mode, int, 0);66MODULE_PARM_DESC(nsp_burst_mode, "Burst transfer mode (0=io8, 1=io32, 2=mem32(default))");67 68/* Release IO ports after configuration? */69static bool       free_ports = 0;70module_param(free_ports, bool, 0);71MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 (=no))");72 73static struct scsi_pointer *nsp_priv(struct scsi_cmnd *cmd)74{75	return scsi_cmd_priv(cmd);76}77 78static struct scsi_host_template nsp_driver_template = {79	.proc_name	         = "nsp_cs",80	.show_info		 = nsp_show_info,81	.name			 = "WorkBit NinjaSCSI-3/32Bi(16bit)",82	.info			 = nsp_info,83	.queuecommand		 = nsp_queuecommand,84/*	.eh_abort_handler	 = nsp_eh_abort,*/85	.eh_bus_reset_handler	 = nsp_eh_bus_reset,86	.eh_host_reset_handler	 = nsp_eh_host_reset,87	.can_queue		 = 1,88	.this_id		 = NSP_INITIATOR_ID,89	.sg_tablesize		 = SG_ALL,90	.dma_boundary		 = PAGE_SIZE - 1,91	.cmd_size		 = sizeof(struct scsi_pointer),92};93 94static nsp_hw_data nsp_data_base; /* attach <-> detect glue */95 96 97 98/*99 * debug, error print100 */101#ifndef NSP_DEBUG102# define NSP_DEBUG_MASK		0x000000103# define nsp_msg(type, args...) nsp_cs_message("", 0, (type), args)104# define nsp_dbg(mask, args...) /* */105#else106# define NSP_DEBUG_MASK		0xffffff107# define nsp_msg(type, args...) \108	nsp_cs_message (__func__, __LINE__, (type), args)109# define nsp_dbg(mask, args...) \110	nsp_cs_dmessage(__func__, __LINE__, (mask), args)111#endif112 113#define NSP_DEBUG_QUEUECOMMAND		BIT(0)114#define NSP_DEBUG_REGISTER		BIT(1)115#define NSP_DEBUG_AUTOSCSI		BIT(2)116#define NSP_DEBUG_INTR			BIT(3)117#define NSP_DEBUG_SGLIST		BIT(4)118#define NSP_DEBUG_BUSFREE		BIT(5)119#define NSP_DEBUG_CDB_CONTENTS		BIT(6)120#define NSP_DEBUG_RESELECTION		BIT(7)121#define NSP_DEBUG_MSGINOCCUR		BIT(8)122#define NSP_DEBUG_EEPROM		BIT(9)123#define NSP_DEBUG_MSGOUTOCCUR		BIT(10)124#define NSP_DEBUG_BUSRESET		BIT(11)125#define NSP_DEBUG_RESTART		BIT(12)126#define NSP_DEBUG_SYNC			BIT(13)127#define NSP_DEBUG_WAIT			BIT(14)128#define NSP_DEBUG_TARGETFLAG		BIT(15)129#define NSP_DEBUG_PROC			BIT(16)130#define NSP_DEBUG_INIT			BIT(17)131#define NSP_DEBUG_DATA_IO      		BIT(18)132#define NSP_SPECIAL_PRINT_REGISTER	BIT(20)133 134#define NSP_DEBUG_BUF_LEN		150135 136static inline void nsp_inc_resid(struct scsi_cmnd *SCpnt, int residInc)137{138	scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) + residInc);139}140 141__printf(4, 5)142static void nsp_cs_message(const char *func, int line, char *type, char *fmt, ...)143{144	va_list args;145	char buf[NSP_DEBUG_BUF_LEN];146 147	va_start(args, fmt);148	vsnprintf(buf, sizeof(buf), fmt, args);149	va_end(args);150 151#ifndef NSP_DEBUG152	printk("%snsp_cs: %s\n", type, buf);153#else154	printk("%snsp_cs: %s (%d): %s\n", type, func, line, buf);155#endif156}157 158#ifdef NSP_DEBUG159static void nsp_cs_dmessage(const char *func, int line, int mask, char *fmt, ...)160{161	va_list args;162	char buf[NSP_DEBUG_BUF_LEN];163 164	va_start(args, fmt);165	vsnprintf(buf, sizeof(buf), fmt, args);166	va_end(args);167 168	if (mask & NSP_DEBUG_MASK) {169		printk("nsp_cs-debug: 0x%x %s (%d): %s\n", mask, func, line, buf);170	}171}172#endif173 174/***********************************************************/175 176/*====================================================177 * Clenaup parameters and call done() functions.178 * You must be set SCpnt->result before call this function.179 */180static void nsp_scsi_done(struct scsi_cmnd *SCpnt)181{182	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;183 184	data->CurrentSC = NULL;185 186	scsi_done(SCpnt);187}188 189static int nsp_queuecommand_lck(struct scsi_cmnd *const SCpnt)190{191	struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt);192#ifdef NSP_DEBUG193	/*unsigned int host_id = SCpnt->device->host->this_id;*/194	/*unsigned int base    = SCpnt->device->host->io_port;*/195	unsigned char target = scmd_id(SCpnt);196#endif197	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;198 199	nsp_dbg(NSP_DEBUG_QUEUECOMMAND,200		"SCpnt=0x%p target=%d lun=%llu sglist=0x%p bufflen=%d sg_count=%d",201		SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt),202		scsi_bufflen(SCpnt), scsi_sg_count(SCpnt));203	//nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC);204 205	if (data->CurrentSC != NULL) {206		nsp_msg(KERN_DEBUG, "CurrentSC!=NULL this can't be happen");207		SCpnt->result   = DID_BAD_TARGET << 16;208		nsp_scsi_done(SCpnt);209		return 0;210	}211 212#if 0213	/* XXX: pcmcia-cs generates SCSI command with "scsi_info" utility.214	        This makes kernel crash when suspending... */215	if (data->ScsiInfo->stop != 0) {216		nsp_msg(KERN_INFO, "suspending device. reject command.");217		SCpnt->result  = DID_BAD_TARGET << 16;218		nsp_scsi_done(SCpnt);219		return SCSI_MLQUEUE_HOST_BUSY;220	}221#endif222 223	show_command(SCpnt);224 225	data->CurrentSC		= SCpnt;226 227	scsi_pointer->Status	   = SAM_STAT_CHECK_CONDITION;228	scsi_pointer->Message	   = 0;229	scsi_pointer->have_data_in = IO_UNKNOWN;230	scsi_pointer->sent_command = 0;231	scsi_pointer->phase	   = PH_UNDETERMINED;232	scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));233 234	/* setup scratch area235	   SCp.ptr		: buffer pointer236	   SCp.this_residual	: buffer length237	   SCp.buffer		: next buffer238	   SCp.buffers_residual : left buffers in list239	   SCp.phase		: current state of the command */240	if (scsi_bufflen(SCpnt)) {241		scsi_pointer->buffer	       = scsi_sglist(SCpnt);242		scsi_pointer->ptr	       = BUFFER_ADDR(SCpnt);243		scsi_pointer->this_residual    = scsi_pointer->buffer->length;244		scsi_pointer->buffers_residual = scsi_sg_count(SCpnt) - 1;245	} else {246		scsi_pointer->ptr	       = NULL;247		scsi_pointer->this_residual    = 0;248		scsi_pointer->buffer	       = NULL;249		scsi_pointer->buffers_residual = 0;250	}251 252	if (!nsphw_start_selection(SCpnt)) {253		nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "selection fail");254		SCpnt->result   = DID_BUS_BUSY << 16;255		nsp_scsi_done(SCpnt);256		return 0;257	}258 259 260	//nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "out");261#ifdef NSP_DEBUG262	data->CmdId++;263#endif264	return 0;265}266 267static DEF_SCSI_QCMD(nsp_queuecommand)268 269/*270 * setup PIO FIFO transfer mode and enable/disable to data out271 */272static void nsp_setup_fifo(nsp_hw_data *data, bool enabled)273{274	unsigned int  base = data->BaseAddress;275	unsigned char transfer_mode_reg;276 277	//nsp_dbg(NSP_DEBUG_DATA_IO, "enabled=%d", enabled);278 279	if (enabled) {280		transfer_mode_reg = TRANSFER_GO | BRAIND;281	} else {282		transfer_mode_reg = 0;283	}284 285	transfer_mode_reg |= data->TransferMode;286 287	nsp_index_write(base, TRANSFERMODE, transfer_mode_reg);288}289 290static void nsphw_init_sync(nsp_hw_data *data)291{292	sync_data tmp_sync = { .SyncNegotiation = SYNC_NOT_YET,293			       .SyncPeriod      = 0,294			       .SyncOffset      = 0295	};296	int i;297 298	/* setup sync data */299	for ( i = 0; i < ARRAY_SIZE(data->Sync); i++ ) {300		data->Sync[i] = tmp_sync;301	}302}303 304/*305 * Initialize Ninja hardware306 */307static void nsphw_init(nsp_hw_data *data)308{309	unsigned int base     = data->BaseAddress;310 311	nsp_dbg(NSP_DEBUG_INIT, "in base=0x%x", base);312 313	data->ScsiClockDiv = CLOCK_40M | FAST_20;314	data->CurrentSC    = NULL;315	data->FifoCount    = 0;316	data->TransferMode = MODE_IO8;317 318	nsphw_init_sync(data);319 320	/* block all interrupts */321	nsp_write(base,	      IRQCONTROL,   IRQCONTROL_ALLMASK);322 323	/* setup SCSI interface */324	nsp_write(base,	      IFSELECT,	    IF_IFSEL);325 326	nsp_index_write(base, SCSIIRQMODE,  0);327 328	nsp_index_write(base, TRANSFERMODE, MODE_IO8);329	nsp_index_write(base, CLOCKDIV,	    data->ScsiClockDiv);330 331	nsp_index_write(base, PARITYCTRL,   0);332	nsp_index_write(base, POINTERCLR,   POINTER_CLEAR     |333					    ACK_COUNTER_CLEAR |334					    REQ_COUNTER_CLEAR |335					    HOST_COUNTER_CLEAR);336 337	/* setup fifo asic */338	nsp_write(base,	      IFSELECT,	    IF_REGSEL);339	nsp_index_write(base, TERMPWRCTRL,  0);340	if ((nsp_index_read(base, OTHERCONTROL) & TPWR_SENSE) == 0) {341		nsp_msg(KERN_INFO, "terminator power on");342		nsp_index_write(base, TERMPWRCTRL, POWER_ON);343	}344 345	nsp_index_write(base, TIMERCOUNT,   0);346	nsp_index_write(base, TIMERCOUNT,   0); /* requires 2 times!! */347 348	nsp_index_write(base, SYNCREG,	    0);349	nsp_index_write(base, ACKWIDTH,	    0);350 351	/* enable interrupts and ack them */352	nsp_index_write(base, SCSIIRQMODE,  SCSI_PHASE_CHANGE_EI |353					    RESELECT_EI		 |354					    SCSI_RESET_IRQ_EI	 );355	nsp_write(base,	      IRQCONTROL,   IRQCONTROL_ALLCLEAR);356 357	nsp_setup_fifo(data, false);358}359 360/*361 * Start selection phase362 */363static bool nsphw_start_selection(struct scsi_cmnd *const SCpnt)364{365	struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt);366	unsigned int  host_id	 = SCpnt->device->host->this_id;367	unsigned int  base	 = SCpnt->device->host->io_port;368	unsigned char target	 = scmd_id(SCpnt);369	nsp_hw_data  *data = (nsp_hw_data *)SCpnt->device->host->hostdata;370	int	      time_out;371	unsigned char phase, arbit;372 373	//nsp_dbg(NSP_DEBUG_RESELECTION, "in");374 375	phase = nsp_index_read(base, SCSIBUSMON);376	if(phase != BUSMON_BUS_FREE) {377		//nsp_dbg(NSP_DEBUG_RESELECTION, "bus busy");378		return false;379	}380 381	/* start arbitration */382	//nsp_dbg(NSP_DEBUG_RESELECTION, "start arbit");383	scsi_pointer->phase = PH_ARBSTART;384	nsp_index_write(base, SETARBIT, ARBIT_GO);385 386	time_out = 1000;387	do {388		/* XXX: what a stupid chip! */389		arbit = nsp_index_read(base, ARBITSTATUS);390		//nsp_dbg(NSP_DEBUG_RESELECTION, "arbit=%d, wait_count=%d", arbit, wait_count);391		udelay(1); /* hold 1.2us */392	} while((arbit & (ARBIT_WIN | ARBIT_FAIL)) == 0 &&393		(time_out-- != 0));394 395	if (!(arbit & ARBIT_WIN)) {396		//nsp_dbg(NSP_DEBUG_RESELECTION, "arbit fail");397		nsp_index_write(base, SETARBIT, ARBIT_FLAG_CLEAR);398		return false;399	}400 401	/* assert select line */402	//nsp_dbg(NSP_DEBUG_RESELECTION, "assert SEL line");403	scsi_pointer->phase = PH_SELSTART;404	udelay(3); /* wait 2.4us */405	nsp_index_write(base, SCSIDATALATCH, BIT(host_id) | BIT(target));406	nsp_index_write(base, SCSIBUSCTRL,   SCSI_SEL | SCSI_BSY                    | SCSI_ATN);407	udelay(2); /* wait >1.2us */408	nsp_index_write(base, SCSIBUSCTRL,   SCSI_SEL | SCSI_BSY | SCSI_DATAOUT_ENB | SCSI_ATN);409	nsp_index_write(base, SETARBIT,	     ARBIT_FLAG_CLEAR);410	/*udelay(1);*/ /* wait >90ns */411	nsp_index_write(base, SCSIBUSCTRL,   SCSI_SEL            | SCSI_DATAOUT_ENB | SCSI_ATN);412 413	/* check selection timeout */414	nsp_start_timer(SCpnt, 1000/51);415	data->SelectionTimeOut = 1;416 417	return true;418}419 420struct nsp_sync_table {421	unsigned int min_period;422	unsigned int max_period;423	unsigned int chip_period;424	unsigned int ack_width;425};426 427static struct nsp_sync_table nsp_sync_table_40M[] = {428	{0x0c, 0x0c, 0x1, 0},	/* 20MB	  50ns*/429	{0x19, 0x19, 0x3, 1},	/* 10MB	 100ns*/ 430	{0x1a, 0x25, 0x5, 2},	/* 7.5MB 150ns*/ 431	{0x26, 0x32, 0x7, 3},	/* 5MB	 200ns*/432	{   0,    0,   0, 0},433};434 435static struct nsp_sync_table nsp_sync_table_20M[] = {436	{0x19, 0x19, 0x1, 0},	/* 10MB	 100ns*/ 437	{0x1a, 0x25, 0x2, 0},	/* 7.5MB 150ns*/ 438	{0x26, 0x32, 0x3, 1},	/* 5MB	 200ns*/439	{   0,    0,   0, 0},440};441 442/*443 * setup synchronous data transfer mode444 */445static int nsp_analyze_sdtr(struct scsi_cmnd *SCpnt)446{447	unsigned char	       target = scmd_id(SCpnt);448//	unsigned char	       lun    = SCpnt->device->lun;449	nsp_hw_data           *data   = (nsp_hw_data *)SCpnt->device->host->hostdata;450	sync_data	      *sync   = &(data->Sync[target]);451	struct nsp_sync_table *sync_table;452	unsigned int	       period, offset;453 454	nsp_dbg(NSP_DEBUG_SYNC, "in");455 456	period = sync->SyncPeriod;457	offset = sync->SyncOffset;458 459	nsp_dbg(NSP_DEBUG_SYNC, "period=0x%x, offset=0x%x", period, offset);460 461	if ((data->ScsiClockDiv & (BIT(0)|BIT(1))) == CLOCK_20M) {462		sync_table = nsp_sync_table_20M;463	} else {464		sync_table = nsp_sync_table_40M;465	}466 467	for (; sync_table->max_period != 0; sync_table++) {468		if ( period >= sync_table->min_period &&469		     period <= sync_table->max_period	 ) {470			break;471		}472	}473 474	if (period != 0 && sync_table->max_period == 0) {475		/*476		 * No proper period/offset found477		 */478		nsp_dbg(NSP_DEBUG_SYNC, "no proper period/offset");479 480		sync->SyncPeriod      = 0;481		sync->SyncOffset      = 0;482		sync->SyncRegister    = 0;483		sync->AckWidth	      = 0;484 485		return false;486	}487 488	sync->SyncRegister    = (sync_table->chip_period << SYNCREG_PERIOD_SHIFT) |489		                (offset & SYNCREG_OFFSET_MASK);490	sync->AckWidth	      = sync_table->ack_width;491 492	nsp_dbg(NSP_DEBUG_SYNC, "sync_reg=0x%x, ack_width=0x%x", sync->SyncRegister, sync->AckWidth);493 494	return true;495}496 497 498/*499 * start ninja hardware timer500 */501static void nsp_start_timer(struct scsi_cmnd *SCpnt, int time)502{503	unsigned int base = SCpnt->device->host->io_port;504	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;505 506	//nsp_dbg(NSP_DEBUG_INTR, "in SCpnt=0x%p, time=%d", SCpnt, time);507	data->TimerCount = time;508	nsp_index_write(base, TIMERCOUNT, time);509}510 511/*512 * wait for bus phase change513 */514static int nsp_negate_signal(struct scsi_cmnd *SCpnt, unsigned char mask,515			     char *str)516{517	unsigned int  base = SCpnt->device->host->io_port;518	unsigned char reg;519	int	      time_out;520 521	//nsp_dbg(NSP_DEBUG_INTR, "in");522 523	time_out = 100;524 525	do {526		reg = nsp_index_read(base, SCSIBUSMON);527		if (reg == 0xff) {528			break;529		}530	} while ((--time_out != 0) && (reg & mask) != 0);531 532	if (time_out == 0) {533		nsp_msg(KERN_DEBUG, " %s signal off timeout", str);534	}535 536	return 0;537}538 539/*540 * expect Ninja Irq541 */542static int nsp_expect_signal(struct scsi_cmnd *SCpnt,543			     unsigned char current_phase,544			     unsigned char mask)545{546	unsigned int  base	 = SCpnt->device->host->io_port;547	int	      time_out;548	unsigned char phase, i_src;549 550	//nsp_dbg(NSP_DEBUG_INTR, "current_phase=0x%x, mask=0x%x", current_phase, mask);551 552	time_out = 100;553	do {554		phase = nsp_index_read(base, SCSIBUSMON);555		if (phase == 0xff) {556			//nsp_dbg(NSP_DEBUG_INTR, "ret -1");557			return -1;558		}559		i_src = nsp_read(base, IRQSTATUS);560		if (i_src & IRQSTATUS_SCSI) {561			//nsp_dbg(NSP_DEBUG_INTR, "ret 0 found scsi signal");562			return 0;563		}564		if ((phase & mask) != 0 && (phase & BUSMON_PHASE_MASK) == current_phase) {565			//nsp_dbg(NSP_DEBUG_INTR, "ret 1 phase=0x%x", phase);566			return 1;567		}568	} while(time_out-- != 0);569 570	//nsp_dbg(NSP_DEBUG_INTR, "timeout");571	return -1;572}573 574/*575 * transfer SCSI message576 */577static int nsp_xfer(struct scsi_cmnd *const SCpnt, int phase)578{579	struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt);580	unsigned int  base = SCpnt->device->host->io_port;581	nsp_hw_data  *data = (nsp_hw_data *)SCpnt->device->host->hostdata;582	char	     *buf  = data->MsgBuffer;583	int	      len  = min(MSGBUF_SIZE, data->MsgLen);584	int	      ptr;585	int	      ret;586 587	//nsp_dbg(NSP_DEBUG_DATA_IO, "in");588	for (ptr = 0; len > 0; len--, ptr++) {589 590		ret = nsp_expect_signal(SCpnt, phase, BUSMON_REQ);591		if (ret <= 0) {592			nsp_dbg(NSP_DEBUG_DATA_IO, "xfer quit");593			return 0;594		}595 596		/* if last byte, negate ATN */597		if (len == 1 && scsi_pointer->phase == PH_MSG_OUT) {598			nsp_index_write(base, SCSIBUSCTRL, AUTODIRECTION | ACKENB);599		}600 601		/* read & write message */602		if (phase & BUSMON_IO) {603			nsp_dbg(NSP_DEBUG_DATA_IO, "read msg");604			buf[ptr] = nsp_index_read(base, SCSIDATAWITHACK);605		} else {606			nsp_dbg(NSP_DEBUG_DATA_IO, "write msg");607			nsp_index_write(base, SCSIDATAWITHACK, buf[ptr]);608		}609		nsp_negate_signal(SCpnt, BUSMON_ACK, "xfer<ack>");610 611	}612	return len;613}614 615/*616 * get extra SCSI data from fifo617 */618static int nsp_dataphase_bypass(struct scsi_cmnd *const SCpnt)619{620	struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt);621	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;622	unsigned int count;623 624	//nsp_dbg(NSP_DEBUG_DATA_IO, "in");625 626	if (scsi_pointer->have_data_in != IO_IN) {627		return 0;628	}629 630	count = nsp_fifo_count(SCpnt);631	if (data->FifoCount == count) {632		//nsp_dbg(NSP_DEBUG_DATA_IO, "not use bypass quirk");633		return 0;634	}635 636	/*637	 * XXX: NSP_QUIRK638	 * data phase skip only occures in case of SCSI_LOW_READ639	 */640	nsp_dbg(NSP_DEBUG_DATA_IO, "use bypass quirk");641	scsi_pointer->phase = PH_DATA;642	nsp_pio_read(SCpnt);643	nsp_setup_fifo(data, false);644 645	return 0;646}647 648/*649 * accept reselection650 */651static void nsp_reselected(struct scsi_cmnd *SCpnt)652{653	unsigned int  base    = SCpnt->device->host->io_port;654	unsigned int  host_id = SCpnt->device->host->this_id;655	//nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;656	unsigned char bus_reg;657	unsigned char id_reg, tmp;658	int target;659 660	nsp_dbg(NSP_DEBUG_RESELECTION, "in");661 662	id_reg = nsp_index_read(base, RESELECTID);663	tmp    = id_reg & (~BIT(host_id));664	target = 0;665	while(tmp != 0) {666		if (tmp & BIT(0)) {667			break;668		}669		tmp >>= 1;670		target++;671	}672 673	if (scmd_id(SCpnt) != target) {674		nsp_msg(KERN_ERR, "XXX: reselect ID must be %d in this implementation.", target);675	}676 677	nsp_negate_signal(SCpnt, BUSMON_SEL, "reselect<SEL>");678 679	nsp_nexus(SCpnt);680	bus_reg = nsp_index_read(base, SCSIBUSCTRL) & ~(SCSI_BSY | SCSI_ATN);681	nsp_index_write(base, SCSIBUSCTRL, bus_reg);682	nsp_index_write(base, SCSIBUSCTRL, bus_reg | AUTODIRECTION | ACKENB);683}684 685/*686 * count how many data transferd687 */688static int nsp_fifo_count(struct scsi_cmnd *SCpnt)689{690	unsigned int base = SCpnt->device->host->io_port;691	unsigned int count;692	unsigned int l, m, h;693 694	nsp_index_write(base, POINTERCLR, POINTER_CLEAR | ACK_COUNTER);695 696	l     = nsp_index_read(base, TRANSFERCOUNT);697	m     = nsp_index_read(base, TRANSFERCOUNT);698	h     = nsp_index_read(base, TRANSFERCOUNT);699	nsp_index_read(base, TRANSFERCOUNT); /* required this! */700 701	count = (h << 16) | (m << 8) | (l << 0);702 703	//nsp_dbg(NSP_DEBUG_DATA_IO, "count=0x%x", count);704 705	return count;706}707 708/* fifo size */709#define RFIFO_CRIT 64710#define WFIFO_CRIT 64711 712/*713 * read data in DATA IN phase714 */715static void nsp_pio_read(struct scsi_cmnd *const SCpnt)716{717	struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt);718	unsigned int  base      = SCpnt->device->host->io_port;719	unsigned long mmio_base = SCpnt->device->host->base;720	nsp_hw_data  *data      = (nsp_hw_data *)SCpnt->device->host->hostdata;721	long	      time_out;722	int	      ocount, res;723	unsigned char stat, fifo_stat;724 725	ocount = data->FifoCount;726 727	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",728		SCpnt, scsi_get_resid(SCpnt), ocount, scsi_pointer->ptr,729		scsi_pointer->this_residual, scsi_pointer->buffer,730		scsi_pointer->buffers_residual);731 732	time_out = 1000;733 734	while ((time_out-- != 0) &&735	       (scsi_pointer->this_residual > 0 ||736		scsi_pointer->buffers_residual > 0)) {737 738		stat = nsp_index_read(base, SCSIBUSMON);739		stat &= BUSMON_PHASE_MASK;740 741 742		res = nsp_fifo_count(SCpnt) - ocount;743		//nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x ocount=0x%x res=0x%x", scsi_pointer->ptr, scsi_pointer->this_residual, ocount, res);744		if (res == 0) { /* if some data available ? */745			if (stat == BUSPHASE_DATA_IN) { /* phase changed? */746				//nsp_dbg(NSP_DEBUG_DATA_IO, " wait for data this=%d", scsi_pointer->this_residual);747				continue;748			} else {749				nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x", stat);750				break;751			}752		}753 754		fifo_stat = nsp_read(base, FIFOSTATUS);755		if ((fifo_stat & FIFOSTATUS_FULL_EMPTY) == 0 &&756		    stat                                == BUSPHASE_DATA_IN) {757			continue;758		}759 760		res = min(res, scsi_pointer->this_residual);761 762		switch (data->TransferMode) {763		case MODE_IO32:764			res &= ~(BIT(1)|BIT(0)); /* align 4 */765			nsp_fifo32_read(base, scsi_pointer->ptr, res >> 2);766			break;767		case MODE_IO8:768			nsp_fifo8_read(base, scsi_pointer->ptr, res);769			break;770 771		case MODE_MEM32:772			res &= ~(BIT(1)|BIT(0)); /* align 4 */773			nsp_mmio_fifo32_read(mmio_base, scsi_pointer->ptr,774					     res >> 2);775			break;776 777		default:778			nsp_dbg(NSP_DEBUG_DATA_IO, "unknown read mode");779			return;780		}781 782		nsp_inc_resid(SCpnt, -res);783		scsi_pointer->ptr += res;784		scsi_pointer->this_residual -= res;785		ocount			 += res;786		//nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this_residual=0x%x ocount=0x%x", scsi_pointer->ptr, scsi_pointer->this_residual, ocount);787 788		/* go to next scatter list if available */789		if (scsi_pointer->this_residual	== 0 &&790		    scsi_pointer->buffers_residual != 0 ) {791			//nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next timeout=%d", time_out);792			scsi_pointer->buffers_residual--;793			scsi_pointer->buffer = sg_next(scsi_pointer->buffer);794			scsi_pointer->ptr = BUFFER_ADDR(SCpnt);795			scsi_pointer->this_residual =796				scsi_pointer->buffer->length;797			time_out = 1000;798 799			//nsp_dbg(NSP_DEBUG_DATA_IO, "page: 0x%p, off: 0x%x", scsi_pointer->buffer->page, scsi_pointer->buffer->offset);800		}801	}802 803	data->FifoCount = ocount;804 805	if (time_out < 0) {806		nsp_msg(KERN_DEBUG, "pio read timeout resid=%d this_residual=%d buffers_residual=%d",807			scsi_get_resid(SCpnt), scsi_pointer->this_residual,808			scsi_pointer->buffers_residual);809	}810	nsp_dbg(NSP_DEBUG_DATA_IO, "read ocount=0x%x", ocount);811	nsp_dbg(NSP_DEBUG_DATA_IO, "r cmd=%d resid=0x%x\n", data->CmdId,812	                                                scsi_get_resid(SCpnt));813}814 815/*816 * write data in DATA OUT phase817 */818static void nsp_pio_write(struct scsi_cmnd *SCpnt)819{820	struct scsi_pointer *scsi_pointer = nsp_priv(SCpnt);821	unsigned int  base      = SCpnt->device->host->io_port;822	unsigned long mmio_base = SCpnt->device->host->base;823	nsp_hw_data  *data      = (nsp_hw_data *)SCpnt->device->host->hostdata;824	int	      time_out;825	int           ocount, res;826	unsigned char stat;827 828	ocount	 = data->FifoCount;829 830	nsp_dbg(NSP_DEBUG_DATA_IO, "in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x",831		data->FifoCount, scsi_pointer->ptr, scsi_pointer->this_residual,832		scsi_pointer->buffer, scsi_pointer->buffers_residual,833		scsi_get_resid(SCpnt));834 835	time_out = 1000;836 837	while ((time_out-- != 0) &&838	       (scsi_pointer->this_residual > 0 ||839		scsi_pointer->buffers_residual > 0)) {840		stat = nsp_index_read(base, SCSIBUSMON);841		stat &= BUSMON_PHASE_MASK;842 843		if (stat != BUSPHASE_DATA_OUT) {844			res = ocount - nsp_fifo_count(SCpnt);845 846			nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x, res=%d\n", stat, res);847			/* Put back pointer */848			nsp_inc_resid(SCpnt, res);849			scsi_pointer->ptr -= res;850			scsi_pointer->this_residual += res;851			ocount -= res;852 853			break;854		}855 856		res = ocount - nsp_fifo_count(SCpnt);857		if (res > 0) { /* write all data? */858			nsp_dbg(NSP_DEBUG_DATA_IO, "wait for all data out. ocount=0x%x res=%d", ocount, res);859			continue;860		}861 862		res = min(scsi_pointer->this_residual, WFIFO_CRIT);863 864		//nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x res=0x%x", scsi_pointer->ptr, scsi_pointer->this_residual, res);865		switch (data->TransferMode) {866		case MODE_IO32:867			res &= ~(BIT(1)|BIT(0)); /* align 4 */868			nsp_fifo32_write(base, scsi_pointer->ptr, res >> 2);869			break;870		case MODE_IO8:871			nsp_fifo8_write(base, scsi_pointer->ptr, res);872			break;873 874		case MODE_MEM32:875			res &= ~(BIT(1)|BIT(0)); /* align 4 */876			nsp_mmio_fifo32_write(mmio_base, scsi_pointer->ptr,877					      res >> 2);878			break;879 880		default:881			nsp_dbg(NSP_DEBUG_DATA_IO, "unknown write mode");882			break;883		}884 885		nsp_inc_resid(SCpnt, -res);886		scsi_pointer->ptr += res;887		scsi_pointer->this_residual -= res;888		ocount += res;889 890		/* go to next scatter list if available */891		if (scsi_pointer->this_residual	== 0 &&892		    scsi_pointer->buffers_residual != 0 ) {893			//nsp_dbg(NSP_DEBUG_DATA_IO, "scatterlist next");894			scsi_pointer->buffers_residual--;895			scsi_pointer->buffer = sg_next(scsi_pointer->buffer);896			scsi_pointer->ptr = BUFFER_ADDR(SCpnt);897			scsi_pointer->this_residual =898				scsi_pointer->buffer->length;899			time_out = 1000;900		}901	}902 903	data->FifoCount = ocount;904 905	if (time_out < 0) {906		nsp_msg(KERN_DEBUG, "pio write timeout resid=0x%x",907		                                        scsi_get_resid(SCpnt));908	}909	nsp_dbg(NSP_DEBUG_DATA_IO, "write ocount=0x%x", ocount);910	nsp_dbg(NSP_DEBUG_DATA_IO, "w cmd=%d resid=0x%x\n", data->CmdId,911	                                                scsi_get_resid(SCpnt));912}913#undef RFIFO_CRIT914#undef WFIFO_CRIT915 916/*917 * setup synchronous/asynchronous data transfer mode918 */919static int nsp_nexus(struct scsi_cmnd *SCpnt)920{921	unsigned int   base   = SCpnt->device->host->io_port;922	unsigned char  target = scmd_id(SCpnt);923//	unsigned char  lun    = SCpnt->device->lun;924	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;925	sync_data     *sync   = &(data->Sync[target]);926 927	//nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p", SCpnt);928 929	/* setup synch transfer registers */930	nsp_index_write(base, SYNCREG,	sync->SyncRegister);931	nsp_index_write(base, ACKWIDTH, sync->AckWidth);932 933	if (scsi_get_resid(SCpnt) % 4 != 0 ||934	    scsi_get_resid(SCpnt) <= PAGE_SIZE ) {935		data->TransferMode = MODE_IO8;936	} else if (nsp_burst_mode == BURST_MEM32) {937		data->TransferMode = MODE_MEM32;938	} else if (nsp_burst_mode == BURST_IO32) {939		data->TransferMode = MODE_IO32;940	} else {941		data->TransferMode = MODE_IO8;942	}943 944	/* setup pdma fifo */945	nsp_setup_fifo(data, true);946 947	/* clear ack counter */948 	data->FifoCount = 0;949	nsp_index_write(base, POINTERCLR, POINTER_CLEAR	    |950					  ACK_COUNTER_CLEAR |951					  REQ_COUNTER_CLEAR |952					  HOST_COUNTER_CLEAR);953 954	return 0;955}956 957#include "nsp_message.c"958/*959 * interrupt handler960 */961static irqreturn_t nspintr(int irq, void *dev_id)962{963	unsigned int   base;964	unsigned char  irq_status, irq_phase, phase;965	struct scsi_cmnd *tmpSC;966	struct scsi_pointer *scsi_pointer;967	unsigned char  target, lun;968	unsigned int  *sync_neg;969	int            i, tmp;970	nsp_hw_data   *data;971 972 973	//nsp_dbg(NSP_DEBUG_INTR, "dev_id=0x%p", dev_id);974	//nsp_dbg(NSP_DEBUG_INTR, "host=0x%p", ((scsi_info_t *)dev_id)->host);975 976	if (                dev_id        != NULL &&977	    ((scsi_info_t *)dev_id)->host != NULL  ) {978		scsi_info_t *info = (scsi_info_t *)dev_id;979 980		data = (nsp_hw_data *)info->host->hostdata;981	} else {982		nsp_dbg(NSP_DEBUG_INTR, "host data wrong");983		return IRQ_NONE;984	}985 986	//nsp_dbg(NSP_DEBUG_INTR, "&nsp_data_base=0x%p, dev_id=0x%p", &nsp_data_base, dev_id);987 988	base = data->BaseAddress;989	//nsp_dbg(NSP_DEBUG_INTR, "base=0x%x", base);990 991	/*992	 * interrupt check993	 */994	nsp_write(base, IRQCONTROL, IRQCONTROL_IRQDISABLE);995	irq_status = nsp_read(base, IRQSTATUS);996	//nsp_dbg(NSP_DEBUG_INTR, "irq_status=0x%x", irq_status);997	if ((irq_status == 0xff) || ((irq_status & IRQSTATUS_MASK) == 0)) {998		nsp_write(base, IRQCONTROL, 0);999		//nsp_dbg(NSP_DEBUG_INTR, "no irq/shared irq");1000		return IRQ_NONE;1001	}1002 1003	/* XXX: IMPORTANT1004	 * Do not read an irq_phase register if no scsi phase interrupt.1005	 * Unless, you should lose a scsi phase interrupt.1006	 */1007	phase = nsp_index_read(base, SCSIBUSMON);1008	if((irq_status & IRQSTATUS_SCSI) != 0) {1009		irq_phase = nsp_index_read(base, IRQPHASESENCE);1010	} else {1011		irq_phase = 0;1012	}1013 1014	//nsp_dbg(NSP_DEBUG_INTR, "irq_phase=0x%x", irq_phase);1015 1016	/*1017	 * timer interrupt handler (scsi vs timer interrupts)1018	 */1019	//nsp_dbg(NSP_DEBUG_INTR, "timercount=%d", data->TimerCount);1020	if (data->TimerCount != 0) {1021		//nsp_dbg(NSP_DEBUG_INTR, "stop timer");1022		nsp_index_write(base, TIMERCOUNT, 0);1023		nsp_index_write(base, TIMERCOUNT, 0);1024		data->TimerCount = 0;1025	}1026 1027	if ((irq_status & IRQSTATUS_MASK) == IRQSTATUS_TIMER &&1028	    data->SelectionTimeOut == 0) {1029		//nsp_dbg(NSP_DEBUG_INTR, "timer start");1030		nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR);1031		return IRQ_HANDLED;1032	}1033 1034	nsp_write(base, IRQCONTROL, IRQCONTROL_TIMER_CLEAR | IRQCONTROL_FIFO_CLEAR);1035 1036	if ((irq_status & IRQSTATUS_SCSI) &&1037	    (irq_phase  & SCSI_RESET_IRQ)) {1038		nsp_msg(KERN_ERR, "bus reset (power off?)");1039 1040		nsphw_init(data);1041		nsp_bus_reset(data);1042 1043		if(data->CurrentSC != NULL) {1044			tmpSC = data->CurrentSC;1045			scsi_pointer = nsp_priv(tmpSC);1046			tmpSC->result = (DID_RESET              << 16) |1047				((scsi_pointer->Message & 0xff) <<  8) |1048				((scsi_pointer->Status  & 0xff) <<  0);1049			nsp_scsi_done(tmpSC);1050		}1051		return IRQ_HANDLED;1052	}1053 1054	if (data->CurrentSC == NULL) {1055		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);1056		nsphw_init(data);1057		nsp_bus_reset(data);1058		return IRQ_HANDLED;1059	}1060 1061	tmpSC    = data->CurrentSC;1062	scsi_pointer = nsp_priv(tmpSC);1063	target   = tmpSC->device->id;1064	lun      = tmpSC->device->lun;1065	sync_neg = &(data->Sync[target].SyncNegotiation);1066 1067	/*1068	 * parse hardware SCSI irq reasons register1069	 */1070	if (irq_status & IRQSTATUS_SCSI) {1071		if (irq_phase & RESELECT_IRQ) {1072			nsp_dbg(NSP_DEBUG_INTR, "reselect");1073			nsp_write(base, IRQCONTROL, IRQCONTROL_RESELECT_CLEAR);1074			nsp_reselected(tmpSC);1075			return IRQ_HANDLED;1076		}1077 1078		if ((irq_phase & (PHASE_CHANGE_IRQ | LATCHED_BUS_FREE)) == 0) {1079			return IRQ_HANDLED;1080		}1081	}1082 1083	//show_phase(tmpSC);1084 1085	switch (scsi_pointer->phase) {1086	case PH_SELSTART:1087		// *sync_neg = SYNC_NOT_YET;1088		if ((phase & BUSMON_BSY) == 0) {1089			//nsp_dbg(NSP_DEBUG_INTR, "selection count=%d", data->SelectionTimeOut);1090			if (data->SelectionTimeOut >= NSP_SELTIMEOUT) {1091				nsp_dbg(NSP_DEBUG_INTR, "selection time out");1092				data->SelectionTimeOut = 0;1093				nsp_index_write(base, SCSIBUSCTRL, 0);1094 1095				tmpSC->result   = DID_TIME_OUT << 16;1096				nsp_scsi_done(tmpSC);1097 1098				return IRQ_HANDLED;1099			}1100			data->SelectionTimeOut += 1;1101			nsp_start_timer(tmpSC, 1000/51);1102			return IRQ_HANDLED;1103		}1104 1105		/* attention assert */1106		//nsp_dbg(NSP_DEBUG_INTR, "attention assert");1107		data->SelectionTimeOut = 0;1108		scsi_pointer->phase = PH_SELECTED;1109		nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN);1110		udelay(1);1111		nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN | AUTODIRECTION | ACKENB);1112		return IRQ_HANDLED;1113 1114	case PH_RESELECT:1115		//nsp_dbg(NSP_DEBUG_INTR, "phase reselect");1116		// *sync_neg = SYNC_NOT_YET;1117		if ((phase & BUSMON_PHASE_MASK) != BUSPHASE_MESSAGE_IN) {1118 1119			tmpSC->result	= DID_ABORT << 16;1120			nsp_scsi_done(tmpSC);1121			return IRQ_HANDLED;1122		}1123		fallthrough;1124	default:1125		if ((irq_status & (IRQSTATUS_SCSI | IRQSTATUS_FIFO)) == 0) {1126			return IRQ_HANDLED;1127		}1128		break;1129	}1130 1131	/*1132	 * SCSI sequencer1133	 */1134	//nsp_dbg(NSP_DEBUG_INTR, "start scsi seq");1135 1136	/* normal disconnect */1137	if ((scsi_pointer->phase == PH_MSG_IN ||1138	     scsi_pointer->phase == PH_MSG_OUT) &&1139	    (irq_phase & LATCHED_BUS_FREE) != 0) {1140		nsp_dbg(NSP_DEBUG_INTR, "normal disconnect irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase);1141 1142		//*sync_neg       = SYNC_NOT_YET;1143 1144		/* all command complete and return status */1145		if (scsi_pointer->Message == COMMAND_COMPLETE) {1146			tmpSC->result = (DID_OK		        << 16) |1147				((scsi_pointer->Message & 0xff) <<  8) |1148				((scsi_pointer->Status  & 0xff) <<  0);1149			nsp_dbg(NSP_DEBUG_INTR, "command complete result=0x%x", tmpSC->result);1150			nsp_scsi_done(tmpSC);1151 1152			return IRQ_HANDLED;1153		}1154 1155		return IRQ_HANDLED;1156	}1157 1158 1159	/* check unexpected bus free state */1160	if (phase == 0) {1161		nsp_msg(KERN_DEBUG, "unexpected bus free. irq_status=0x%x, phase=0x%x, irq_phase=0x%x", irq_status, phase, irq_phase);1162 1163		*sync_neg       = SYNC_NG;1164		tmpSC->result   = DID_ERROR << 16;1165		nsp_scsi_done(tmpSC);1166		return IRQ_HANDLED;1167	}1168 1169	switch (phase & BUSMON_PHASE_MASK) {1170	case BUSPHASE_COMMAND:1171		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_COMMAND");1172		if ((phase & BUSMON_REQ) == 0) {1173			nsp_dbg(NSP_DEBUG_INTR, "REQ == 0");1174			return IRQ_HANDLED;1175		}1176 1177		scsi_pointer->phase = PH_COMMAND;1178 1179		nsp_nexus(tmpSC);1180 1181		/* write scsi command */1182		nsp_dbg(NSP_DEBUG_INTR, "cmd_len=%d", tmpSC->cmd_len);1183		nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER);1184		for (i = 0; i < tmpSC->cmd_len; i++) {1185			nsp_index_write(base, COMMANDDATA, tmpSC->cmnd[i]);1186		}1187		nsp_index_write(base, COMMANDCTRL, CLEAR_COMMAND_POINTER | AUTO_COMMAND_GO);1188		break;1189 1190	case BUSPHASE_DATA_OUT:1191		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_OUT");1192 1193		scsi_pointer->phase        = PH_DATA;1194		scsi_pointer->have_data_in = IO_OUT;1195 1196		nsp_pio_write(tmpSC);1197 1198		break;1199 1200	case BUSPHASE_DATA_IN:1201		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_DATA_IN");1202 1203		scsi_pointer->phase        = PH_DATA;1204		scsi_pointer->have_data_in = IO_IN;1205 1206		nsp_pio_read(tmpSC);1207 1208		break;1209 1210	case BUSPHASE_STATUS:1211		nsp_dataphase_bypass(tmpSC);1212		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_STATUS");1213 1214		scsi_pointer->phase = PH_STATUS;1215 1216		scsi_pointer->Status = nsp_index_read(base, SCSIDATAWITHACK);1217		nsp_dbg(NSP_DEBUG_INTR, "message=0x%x status=0x%x",1218			scsi_pointer->Message, scsi_pointer->Status);1219 1220		break;1221 1222	case BUSPHASE_MESSAGE_OUT:1223		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_OUT");1224		if ((phase & BUSMON_REQ) == 0) {1225			goto timer_out;1226		}1227 1228		scsi_pointer->phase = PH_MSG_OUT;1229 1230		//*sync_neg = SYNC_NOT_YET;1231 1232		data->MsgLen = i = 0;1233		data->MsgBuffer[i] = IDENTIFY(true, lun); i++;1234 1235		if (*sync_neg == SYNC_NOT_YET) {1236			data->Sync[target].SyncPeriod = 0;1237			data->Sync[target].SyncOffset = 0;1238 1239			/**/1240			data->MsgBuffer[i] = EXTENDED_MESSAGE; i++;1241			data->MsgBuffer[i] = 3;            i++;1242			data->MsgBuffer[i] = EXTENDED_SDTR; i++;1243			data->MsgBuffer[i] = 0x0c;         i++;1244			data->MsgBuffer[i] = 15;           i++;1245			/**/1246		}1247		data->MsgLen = i;1248 1249		nsp_analyze_sdtr(tmpSC);1250		show_message(data);1251		nsp_message_out(tmpSC);1252		break;1253 1254	case BUSPHASE_MESSAGE_IN:1255		nsp_dataphase_bypass(tmpSC);1256		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE_MESSAGE_IN");1257		if ((phase & BUSMON_REQ) == 0) {1258			goto timer_out;1259		}1260 1261		scsi_pointer->phase = PH_MSG_IN;1262		nsp_message_in(tmpSC);1263 1264		/**/1265		if (*sync_neg == SYNC_NOT_YET) {1266			//nsp_dbg(NSP_DEBUG_INTR, "sync target=%d,lun=%d",target,lun);1267 1268			if (data->MsgLen       >= 5            &&1269			    data->MsgBuffer[0] == EXTENDED_MESSAGE &&1270			    data->MsgBuffer[1] == 3            &&1271			    data->MsgBuffer[2] == EXTENDED_SDTR ) {1272				data->Sync[target].SyncPeriod = data->MsgBuffer[3];1273				data->Sync[target].SyncOffset = data->MsgBuffer[4];1274				//nsp_dbg(NSP_DEBUG_INTR, "sync ok, %d %d", data->MsgBuffer[3], data->MsgBuffer[4]);1275				*sync_neg = SYNC_OK;1276			} else {1277				data->Sync[target].SyncPeriod = 0;1278				data->Sync[target].SyncOffset = 0;1279				*sync_neg = SYNC_NG;1280			}1281			nsp_analyze_sdtr(tmpSC);1282		}1283		/**/1284 1285		/* search last messeage byte */1286		tmp = -1;1287		for (i = 0; i < data->MsgLen; i++) {1288			tmp = data->MsgBuffer[i];1289			if (data->MsgBuffer[i] == EXTENDED_MESSAGE) {1290				i += (1 + data->MsgBuffer[i+1]);1291			}1292		}1293		scsi_pointer->Message = tmp;1294 1295		nsp_dbg(NSP_DEBUG_INTR, "message=0x%x len=%d",1296			scsi_pointer->Message, data->MsgLen);1297		show_message(data);1298 1299		break;1300 1301	case BUSPHASE_SELECT:1302	default:1303		nsp_dbg(NSP_DEBUG_INTR, "BUSPHASE other");1304 1305		break;1306	}1307 1308	//nsp_dbg(NSP_DEBUG_INTR, "out");1309	return IRQ_HANDLED; 	1310 1311timer_out:1312	nsp_start_timer(tmpSC, 1000/102);1313	return IRQ_HANDLED;1314}1315 1316#ifdef NSP_DEBUG1317#include "nsp_debug.c"1318#endif	/* NSP_DEBUG */1319 1320/*----------------------------------------------------------------*/1321/* look for ninja3 card and init if found			  */1322/*----------------------------------------------------------------*/1323static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht)1324{1325	struct Scsi_Host *host;	/* registered host structure */1326	nsp_hw_data *data_b = &nsp_data_base, *data;1327 1328	nsp_dbg(NSP_DEBUG_INIT, "this_id=%d", sht->this_id);1329	host = scsi_host_alloc(&nsp_driver_template, sizeof(nsp_hw_data));1330	if (host == NULL) {1331		nsp_dbg(NSP_DEBUG_INIT, "host failed");1332		return NULL;1333	}1334 1335	memcpy(host->hostdata, data_b, sizeof(nsp_hw_data));1336	data = (nsp_hw_data *)host->hostdata;1337	data->ScsiInfo->host = host;1338#ifdef NSP_DEBUG1339	data->CmdId = 0;1340#endif1341 1342	nsp_dbg(NSP_DEBUG_INIT, "irq=%d,%d", data_b->IrqNumber, ((nsp_hw_data *)host->hostdata)->IrqNumber);1343 1344	host->unique_id	  = data->BaseAddress;1345	host->io_port	  = data->BaseAddress;1346	host->n_io_port	  = data->NumAddress;1347	host->irq	  = data->IrqNumber;1348	host->base        = data->MmioAddress;1349 1350	spin_lock_init(&(data->Lock));1351 1352	snprintf(data->nspinfo,1353		 sizeof(data->nspinfo),1354		 "NinjaSCSI-3/32Bi Driver $Revision: 1.23 $ IO:0x%04lx-0x%04lx MMIO(virt addr):0x%04lx IRQ:%02d",1355		 host->io_port, host->io_port + host->n_io_port - 1,1356		 host->base,1357		 host->irq);1358	sht->name	  = data->nspinfo;1359 1360	nsp_dbg(NSP_DEBUG_INIT, "end");1361 1362 1363	return host; /* detect done. */1364}1365 1366/*----------------------------------------------------------------*/1367/* return info string						  */1368/*----------------------------------------------------------------*/1369static const char *nsp_info(struct Scsi_Host *shpnt)1370{1371	nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata;1372 1373	return data->nspinfo;1374}1375 1376static int nsp_show_info(struct seq_file *m, struct Scsi_Host *host)1377{1378	int id;1379	int speed;1380	unsigned long flags;1381	nsp_hw_data *data;1382	int hostno;1383 1384	hostno = host->host_no;1385	data = (nsp_hw_data *)host->hostdata;1386 1387	seq_puts(m, "NinjaSCSI status\n\n"1388		"Driver version:        $Revision: 1.23 $\n");1389	seq_printf(m, "SCSI host No.:         %d\n",          hostno);1390	seq_printf(m, "IRQ:                   %d\n",          host->irq);1391	seq_printf(m, "IO:                    0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1);1392	seq_printf(m, "MMIO(virtual address): 0x%lx-0x%lx\n", host->base, host->base + data->MmioLength - 1);1393	seq_printf(m, "sg_tablesize:          %d\n",          host->sg_tablesize);1394 1395	seq_puts(m, "burst transfer mode:   ");1396	switch (nsp_burst_mode) {1397	case BURST_IO8:1398		seq_puts(m, "io8");1399		break;1400	case BURST_IO32:1401		seq_puts(m, "io32");1402		break;1403	case BURST_MEM32:1404		seq_puts(m, "mem32");1405		break;1406	default:1407		seq_puts(m, "???");1408		break;1409	}1410	seq_putc(m, '\n');1411 1412 1413	spin_lock_irqsave(&(data->Lock), flags);1414	seq_printf(m, "CurrentSC:             0x%p\n\n",      data->CurrentSC);1415	spin_unlock_irqrestore(&(data->Lock), flags);1416 1417	seq_puts(m, "SDTR status\n");1418	for(id = 0; id < ARRAY_SIZE(data->Sync); id++) {1419 1420		seq_printf(m, "id %d: ", id);1421 1422		if (id == host->this_id) {1423			seq_puts(m, "----- NinjaSCSI-3 host adapter\n");1424			continue;1425		}1426 1427		switch(data->Sync[id].SyncNegotiation) {1428		case SYNC_OK:1429			seq_puts(m, " sync");1430			break;1431		case SYNC_NG:1432			seq_puts(m, "async");1433			break;1434		case SYNC_NOT_YET:1435			seq_puts(m, " none");1436			break;1437		default:1438			seq_puts(m, "?????");1439			break;1440		}1441 1442		if (data->Sync[id].SyncPeriod != 0) {1443			speed = 1000000 / (data->Sync[id].SyncPeriod * 4);1444 1445			seq_printf(m, " transfer %d.%dMB/s, offset %d",1446				speed / 1000,1447				speed % 1000,1448				data->Sync[id].SyncOffset1449				);1450		}1451		seq_putc(m, '\n');1452	}1453	return 0;1454}1455 1456/*---------------------------------------------------------------*/1457/* error handler                                                 */1458/*---------------------------------------------------------------*/1459 1460/*1461static int nsp_eh_abort(struct scsi_cmnd *SCpnt)1462{1463	nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt);1464 1465	return nsp_eh_bus_reset(SCpnt);1466}*/1467 1468static int nsp_bus_reset(nsp_hw_data *data)1469{1470	unsigned int base = data->BaseAddress;1471	int	     i;1472 1473	nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK);1474 1475	nsp_index_write(base, SCSIBUSCTRL, SCSI_RST);1476	mdelay(100); /* 100ms */1477	nsp_index_write(base, SCSIBUSCTRL, 0);1478	for(i = 0; i < 5; i++) {1479		nsp_index_read(base, IRQPHASESENCE); /* dummy read */1480	}1481 1482	nsphw_init_sync(data);1483 1484	nsp_write(base, IRQCONTROL, IRQCONTROL_ALLCLEAR);1485 1486	return SUCCESS;1487}1488 1489static int nsp_eh_bus_reset(struct scsi_cmnd *SCpnt)1490{1491	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;1492 1493	nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt);1494 1495	return nsp_bus_reset(data);1496}1497 1498static int nsp_eh_host_reset(struct scsi_cmnd *SCpnt)1499{1500	nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;1501 1502	nsp_dbg(NSP_DEBUG_BUSRESET, "in");1503 1504	nsphw_init(data);1505 1506	return SUCCESS;1507}1508 1509 1510/**********************************************************************1511  PCMCIA functions1512**********************************************************************/1513 1514static int nsp_cs_probe(struct pcmcia_device *link)1515{1516	scsi_info_t  *info;1517	nsp_hw_data  *data = &nsp_data_base;1518	int ret;1519 1520	nsp_dbg(NSP_DEBUG_INIT, "in");1521 1522	/* Create new SCSI device */1523	info = kzalloc(sizeof(*info), GFP_KERNEL);1524	if (info == NULL) { return -ENOMEM; }1525	info->p_dev = link;1526	link->priv = info;1527	data->ScsiInfo = info;1528 1529	nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);1530 1531	ret = nsp_cs_config(link);1532 1533	nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);1534	return ret;1535} /* nsp_cs_attach */1536 1537 1538static void nsp_cs_detach(struct pcmcia_device *link)1539{1540	nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);1541 1542	((scsi_info_t *)link->priv)->stop = 1;1543	nsp_cs_release(link);1544 1545	kfree(link->priv);1546	link->priv = NULL;1547} /* nsp_cs_detach */1548 1549 1550static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)1551{1552	nsp_hw_data		*data = priv_data;1553 1554	if (p_dev->config_index == 0)1555		return -ENODEV;1556 1557	/* This reserves IO space but doesn't actually enable it */1558	if (pcmcia_request_io(p_dev) != 0)1559		goto next_entry;1560 1561	if (resource_size(p_dev->resource[2])) {1562		p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |1563					WIN_MEMORY_TYPE_CM |1564					WIN_ENABLE);1565		if (p_dev->resource[2]->end < 0x1000)1566			p_dev->resource[2]->end = 0x1000;1567		if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0)1568			goto next_entry;1569		if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],1570						p_dev->card_addr) != 0)1571			goto next_entry;1572 1573		data->MmioAddress = (unsigned long)1574			ioremap(p_dev->resource[2]->start,1575					resource_size(p_dev->resource[2]));1576		if (!data->MmioAddress)1577			goto next_entry;1578 1579		data->MmioLength  = resource_size(p_dev->resource[2]);1580	}1581	/* If we got this far, we're cool! */1582	return 0;1583 1584next_entry:1585	nsp_dbg(NSP_DEBUG_INIT, "next");1586	pcmcia_disable_device(p_dev);1587	return -ENODEV;1588}1589 1590static int nsp_cs_config(struct pcmcia_device *link)1591{1592	int		  ret;1593	scsi_info_t	 *info	 = link->priv;1594	struct Scsi_Host *host;1595	nsp_hw_data      *data = &nsp_data_base;1596 1597	nsp_dbg(NSP_DEBUG_INIT, "in");1598 1599	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |1600		CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IOMEM |1601		CONF_AUTO_SET_IO;1602 1603	ret = pcmcia_loop_config(link, nsp_cs_config_check, data);1604	if (ret)1605		goto cs_failed;1606 1607	if (pcmcia_request_irq(link, nspintr))1608		goto cs_failed;1609 1610	ret = pcmcia_enable_device(link);1611	if (ret)1612		goto cs_failed;1613 1614	if (free_ports) {1615		if (link->resource[0]) {1616			release_region(link->resource[0]->start,1617					resource_size(link->resource[0]));1618		}1619		if (link->resource[1]) {1620			release_region(link->resource[1]->start,1621					resource_size(link->resource[1]));1622		}1623	}1624 1625	/* Set port and IRQ */1626	data->BaseAddress = link->resource[0]->start;1627	data->NumAddress  = resource_size(link->resource[0]);1628	data->IrqNumber   = link->irq;1629 1630	nsp_dbg(NSP_DEBUG_INIT, "I/O[0x%x+0x%x] IRQ %d",1631		data->BaseAddress, data->NumAddress, data->IrqNumber);1632 1633	nsphw_init(data);1634 1635	host = nsp_detect(&nsp_driver_template);1636 1637	if (host == NULL) {1638		nsp_dbg(NSP_DEBUG_INIT, "detect failed");1639		goto cs_failed;1640	}1641 1642 1643	ret = scsi_add_host (host, NULL);1644	if (ret)1645		goto cs_failed;1646 1647	scsi_scan_host(host);1648 1649	info->host = host;1650 1651	return 0;1652 1653 cs_failed:1654	nsp_dbg(NSP_DEBUG_INIT, "config fail");1655	nsp_cs_release(link);1656 1657	return -ENODEV;1658} /* nsp_cs_config */1659 1660 1661static void nsp_cs_release(struct pcmcia_device *link)1662{1663	scsi_info_t *info = link->priv;1664	nsp_hw_data *data = NULL;1665 1666	if (info->host == NULL) {1667		nsp_msg(KERN_DEBUG, "unexpected card release call.");1668	} else {1669		data = (nsp_hw_data *)info->host->hostdata;1670	}1671 1672	nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);1673 1674	/* Unlink the device chain */1675	if (info->host != NULL) {1676		scsi_remove_host(info->host);1677	}1678 1679	if (resource_size(link->resource[2])) {1680		if (data != NULL) {1681			iounmap((void *)(data->MmioAddress));1682		}1683	}1684	pcmcia_disable_device(link);1685 1686	if (info->host != NULL) {1687		scsi_host_put(info->host);1688	}1689} /* nsp_cs_release */1690 1691static int nsp_cs_suspend(struct pcmcia_device *link)1692{1693	scsi_info_t *info = link->priv;1694	nsp_hw_data *data;1695 1696	nsp_dbg(NSP_DEBUG_INIT, "event: suspend");1697 1698	if (info->host != NULL) {1699		nsp_msg(KERN_INFO, "clear SDTR status");1700 1701		data = (nsp_hw_data *)info->host->hostdata;1702 1703		nsphw_init_sync(data);1704	}1705 1706	info->stop = 1;1707 1708	return 0;1709}1710 1711static int nsp_cs_resume(struct pcmcia_device *link)1712{1713	scsi_info_t *info = link->priv;1714	nsp_hw_data *data;1715 1716	nsp_dbg(NSP_DEBUG_INIT, "event: resume");1717 1718	info->stop = 0;1719 1720	if (info->host != NULL) {1721		nsp_msg(KERN_INFO, "reset host and bus");1722 1723		data = (nsp_hw_data *)info->host->hostdata;1724 1725		nsphw_init   (data);1726		nsp_bus_reset(data);1727	}1728 1729	return 0;1730}1731 1732/*======================================================================*1733 *	module entry point1734 *====================================================================*/1735static const struct pcmcia_device_id nsp_cs_ids[] = {1736	PCMCIA_DEVICE_PROD_ID123("IO DATA", "CBSC16       ", "1", 0x547e66dc, 0x0d63a3fd, 0x51de003a),1737	PCMCIA_DEVICE_PROD_ID123("KME    ", "SCSI-CARD-001", "1", 0x534c02bc, 0x52008408, 0x51de003a),1738	PCMCIA_DEVICE_PROD_ID123("KME    ", "SCSI-CARD-002", "1", 0x534c02bc, 0xcb09d5b2, 0x51de003a),1739	PCMCIA_DEVICE_PROD_ID123("KME    ", "SCSI-CARD-003", "1", 0x534c02bc, 0xbc0ee524, 0x51de003a),1740	PCMCIA_DEVICE_PROD_ID123("KME    ", "SCSI-CARD-004", "1", 0x534c02bc, 0x226a7087, 0x51de003a),1741	PCMCIA_DEVICE_PROD_ID123("WBT", "NinjaSCSI-3", "R1.0", 0xc7ba805f, 0xfdc7c97d, 0x6973710e),1742	PCMCIA_DEVICE_PROD_ID123("WORKBIT", "UltraNinja-16", "1", 0x28191418, 0xb70f4b09, 0x51de003a),1743	PCMCIA_DEVICE_NULL1744};1745MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids);1746 1747static struct pcmcia_driver nsp_driver = {1748	.owner		= THIS_MODULE,1749	.name		= "nsp_cs",1750	.probe		= nsp_cs_probe,1751	.remove		= nsp_cs_detach,1752	.id_table	= nsp_cs_ids,1753	.suspend	= nsp_cs_suspend,1754	.resume		= nsp_cs_resume,1755};1756module_pcmcia_driver(nsp_driver);1757 1758/* end */1759