brintos

brintos / linux-shallow public Read only

0
0
Text · 79.7 KiB · 625fd54 Raw
2965 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/**************************************************************************3 * Initio 9100 device driver for Linux.4 *5 * Copyright (c) 1994-1998 Initio Corporation6 * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>7 * Copyright (c) 2004 Christoph Hellwig <hch@lst.de>8 * Copyright (c) 2007 Red Hat9 *10 *************************************************************************11 *12 * DESCRIPTION:13 *14 * This is the Linux low-level SCSI driver for Initio INI-9X00U/UW SCSI host15 * adapters16 *17 * 08/06/97 hc	- v1.01h18 *		- Support inic-940 and inic-93519 * 09/26/97 hc	- v1.01i20 *		- Make correction from J.W. Schultz suggestion21 * 10/13/97 hc	- Support reset function22 * 10/21/97 hc	- v1.01j23 *		- Support 32 LUN (SCSI 3)24 * 01/14/98 hc	- v1.01k25 *		- Fix memory allocation problem26 * 03/04/98 hc	- v1.01l27 *		- Fix tape rewind which will hang the system problem28 *		- Set can_queue to initio_num_scb29 * 06/25/98 hc	- v1.01m30 *		- Get it work for kernel version >= 2.1.7531 *		- Dynamic assign SCSI bus reset holding time in initio_init()32 * 07/02/98 hc	- v1.01n33 *		- Support 0002134A34 * 08/07/98 hc  - v1.01o35 *		- Change the initio_abort_srb routine to use scsi_done. <01>36 * 09/07/98 hl  - v1.0237 *              - Change the INI9100U define and proc_dir_entry to38 *                reflect the newer Kernel 2.1.118, but the v1.o1o39 *                should work with Kernel 2.1.118.40 * 09/20/98 wh  - v1.02a41 *              - Support Abort command.42 *              - Handle reset routine.43 * 09/21/98 hl  - v1.0344 *              - remove comments.45 * 12/09/98 bv	- v1.03a46 *		- Removed unused code47 * 12/13/98 bv	- v1.03b48 *		- Remove cli() locking for kernels >= 2.1.95. This uses49 *		  spinlocks to serialize access to the pSRB_head and50 *		  pSRB_tail members of the HCS structure.51 * 09/01/99 bv	- v1.03d52 *		- Fixed a deadlock problem in SMP.53 * 21/01/99 bv	- v1.03e54 *		- Add support for the Domex 3192U PCI SCSI55 *		  This is a slightly modified patch by56 *		  Brian Macy <bmacy@sunshinecomputing.com>57 * 22/02/99 bv	- v1.03f58 *		- Didn't detect the INIC-950 in 2.0.x correctly.59 *		  Now fixed.60 * 05/07/99 bv	- v1.03g61 *		- Changed the assumption that HZ = 10062 * 10/17/03 mc	- v1.0463 *		- added new DMA API support64 * 06/01/04 jmd	- v1.04a65 *		- Re-add reset_bus support66 **************************************************************************/67 68#include <linux/module.h>69#include <linux/errno.h>70#include <linux/delay.h>71#include <linux/pci.h>72#include <linux/init.h>73#include <linux/blkdev.h>74#include <linux/spinlock.h>75#include <linux/stat.h>76#include <linux/kernel.h>77#include <linux/proc_fs.h>78#include <linux/string.h>79#include <linux/interrupt.h>80#include <linux/ioport.h>81#include <linux/slab.h>82#include <linux/jiffies.h>83#include <linux/dma-mapping.h>84#include <asm/io.h>85 86#include <scsi/scsi.h>87#include <scsi/scsi_cmnd.h>88#include <scsi/scsi_device.h>89#include <scsi/scsi_host.h>90#include <scsi/scsi_tcq.h>91 92#include "initio.h"93 94#define SENSE_SIZE		1495 96#define i91u_MAXQUEUE		297#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a"98 99#ifdef DEBUG_i91u100static unsigned int i91u_debug = DEBUG_DEFAULT;101#endif102 103static int initio_tag_enable = 1;104 105#ifdef DEBUG_i91u106static int setup_debug = 0;107#endif108 109static void i91uSCBPost(u8 * pHcb, u8 * pScb);110 111#define DEBUG_INTERRUPT 0112#define DEBUG_QUEUE     0113#define DEBUG_STATE     0114#define INT_DISC	0115 116/*--- forward references ---*/117static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun);118static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host);119 120static int tulip_main(struct initio_host * host);121 122static int initio_next_state(struct initio_host * host);123static int initio_state_1(struct initio_host * host);124static int initio_state_2(struct initio_host * host);125static int initio_state_3(struct initio_host * host);126static int initio_state_4(struct initio_host * host);127static int initio_state_5(struct initio_host * host);128static int initio_state_6(struct initio_host * host);129static int initio_state_7(struct initio_host * host);130static int initio_xfer_data_in(struct initio_host * host);131static int initio_xfer_data_out(struct initio_host * host);132static int initio_xpad_in(struct initio_host * host);133static int initio_xpad_out(struct initio_host * host);134static int initio_status_msg(struct initio_host * host);135 136static int initio_msgin(struct initio_host * host);137static int initio_msgin_sync(struct initio_host * host);138static int initio_msgin_accept(struct initio_host * host);139static int initio_msgout_reject(struct initio_host * host);140static int initio_msgin_extend(struct initio_host * host);141 142static int initio_msgout_ide(struct initio_host * host);143static int initio_msgout_abort_targ(struct initio_host * host);144static int initio_msgout_abort_tag(struct initio_host * host);145 146static int initio_bus_device_reset(struct initio_host * host);147static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb);148static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb);149static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb);150static int int_initio_busfree(struct initio_host * host);151static int int_initio_scsi_rst(struct initio_host * host);152static int int_initio_bad_seq(struct initio_host * host);153static int int_initio_resel(struct initio_host * host);154static int initio_sync_done(struct initio_host * host);155static int wdtr_done(struct initio_host * host);156static int wait_tulip(struct initio_host * host);157static int initio_wait_done_disc(struct initio_host * host);158static int initio_wait_disc(struct initio_host * host);159static void tulip_scsi(struct initio_host * host);160static int initio_post_scsi_rst(struct initio_host * host);161 162static void initio_se2_ew_en(unsigned long base);163static void initio_se2_ew_ds(unsigned long base);164static int initio_se2_rd_all(unsigned long base);165static void initio_se2_update_all(unsigned long base);	/* setup default pattern */166static void initio_read_eeprom(unsigned long base);167 168/* ---- INTERNAL VARIABLES ---- */169 170static NVRAM i91unvram;171static NVRAM *i91unvramp;172 173static u8 i91udftNvRam[64] =174{175	/*----------- header -----------*/176	0x25, 0xc9,		/* Signature    */177	0x40,			/* Size         */178	0x01,			/* Revision     */179	/* -- Host Adapter Structure -- */180	0x95,			/* ModelByte0   */181	0x00,			/* ModelByte1   */182	0x00,			/* ModelInfo    */183	0x01,			/* NumOfCh      */184	NBC1_DEFAULT,		/* BIOSConfig1  */185	0,			/* BIOSConfig2  */186	0,			/* HAConfig1    */187	0,			/* HAConfig2    */188	/* SCSI channel 0 and target Structure  */189	7,			/* SCSIid       */190	NCC1_DEFAULT,		/* SCSIconfig1  */191	0,			/* SCSIconfig2  */192	0x10,			/* NumSCSItarget */193 194	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,195	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,196	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,197	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,198 199	/* SCSI channel 1 and target Structure  */200	7,			/* SCSIid       */201	NCC1_DEFAULT,		/* SCSIconfig1  */202	0,			/* SCSIconfig2  */203	0x10,			/* NumSCSItarget */204 205	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,206	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,207	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,208	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,209	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,210	0, 0};			/*      - CheckSum -            */211 212 213static u8 initio_rate_tbl[8] =	/* fast 20      */214{215				/* nanosecond divide by 4 */216	12,			/* 50ns,  20M   */217	18,			/* 75ns,  13.3M */218	25,			/* 100ns, 10M   */219	31,			/* 125ns, 8M    */220	37,			/* 150ns, 6.6M  */221	43,			/* 175ns, 5.7M  */222	50,			/* 200ns, 5M    */223	62			/* 250ns, 4M    */224};225 226static void initio_do_pause(unsigned amount)227{228	/* Pause for amount jiffies */229	unsigned long the_time = jiffies + amount;230 231	while (time_before_eq(jiffies, the_time))232		cpu_relax();233}234 235/*-- forward reference --*/236 237/******************************************************************238 Input: instruction for  Serial E2PROM239 240 EX: se2_rd(0 call se2_instr() to send address and read command241 242	 StartBit  OP_Code   Address                Data243	 --------- --------  ------------------     -------244	 1         1 , 0     A5,A4,A3,A2,A1,A0      D15-D0245 246		 +-----------------------------------------------------247		 |248 CS -----+249			+--+  +--+  +--+  +--+  +--+250			^  |  ^  |  ^  |  ^  |  ^  |251			|  |  |  |  |  |  |  |  |  |252 CLK -------+  +--+  +--+  +--+  +--+  +--253 (leading edge trigger)254 255		 +--1-----1--+256		 | SB    OP  |  OP    A5    A4257 DI  ----+           +--0------------------258 (address and cmd sent to nvram)259 260	 -------------------------------------------+261												|262 DO                                             +---263 (data sent from nvram)264 265 266******************************************************************/267 268/**269 *	initio_se2_instr	-	bitbang an instruction270 *	@base: Base of InitIO controller271 *	@instr: Instruction for serial E2PROM272 *273 *	Bitbang an instruction out to the serial E2Prom274 */275 276static void initio_se2_instr(unsigned long base, u8 instr)277{278	int i;279	u8 b;280 281	outb(SE2CS | SE2DO, base + TUL_NVRAM);		/* cs+start bit */282	udelay(30);283	outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM);	/* +CLK */284	udelay(30);285 286	for (i = 0; i < 8; i++) {287		if (instr & 0x80)288			b = SE2CS | SE2DO;		/* -CLK+dataBit */289		else290			b = SE2CS;			/* -CLK */291		outb(b, base + TUL_NVRAM);292		udelay(30);293		outb(b | SE2CLK, base + TUL_NVRAM);	/* +CLK */294		udelay(30);295		instr <<= 1;296	}297	outb(SE2CS, base + TUL_NVRAM);			/* -CLK */298	udelay(30);299}300 301 302/**303 *	initio_se2_ew_en	-	Enable erase/write304 *	@base: Base address of InitIO controller305 *306 *	Enable erase/write state of serial EEPROM307 */308void initio_se2_ew_en(unsigned long base)309{310	initio_se2_instr(base, 0x30);	/* EWEN */311	outb(0, base + TUL_NVRAM);	/* -CS  */312	udelay(30);313}314 315 316/**317 *	initio_se2_ew_ds	-	Disable erase/write318 *	@base: Base address of InitIO controller319 *320 *	Disable erase/write state of serial EEPROM321 */322void initio_se2_ew_ds(unsigned long base)323{324	initio_se2_instr(base, 0);	/* EWDS */325	outb(0, base + TUL_NVRAM);	/* -CS  */326	udelay(30);327}328 329 330/**331 *	initio_se2_rd		-	read E2PROM word332 *	@base: Base of InitIO controller333 *	@addr: Address of word in E2PROM334 *335 *	Read a word from the NV E2PROM device336 */337static u16 initio_se2_rd(unsigned long base, u8 addr)338{339	u8 instr, rb;340	u16 val = 0;341	int i;342 343	instr = (u8) (addr | 0x80);344	initio_se2_instr(base, instr);	/* READ INSTR */345 346	for (i = 15; i >= 0; i--) {347		outb(SE2CS | SE2CLK, base + TUL_NVRAM);	/* +CLK */348		udelay(30);349		outb(SE2CS, base + TUL_NVRAM);		/* -CLK */350 351		/* sample data after the following edge of clock  */352		rb = inb(base + TUL_NVRAM);353		rb &= SE2DI;354		val += (rb << i);355		udelay(30);	/* 6/20/95 */356	}357 358	outb(0, base + TUL_NVRAM);		/* no chip select */359	udelay(30);360	return val;361}362 363/**364 *	initio_se2_wr		-	read E2PROM word365 *	@base: Base of InitIO controller366 *	@addr: Address of word in E2PROM367 *	@val: Value to write368 *369 *	Write a word to the NV E2PROM device. Used when recovering from370 *	a problem with the NV.371 */372static void initio_se2_wr(unsigned long base, u8 addr, u16 val)373{374	u8 instr;375	int i;376 377	instr = (u8) (addr | 0x40);378	initio_se2_instr(base, instr);	/* WRITE INSTR */379	for (i = 15; i >= 0; i--) {380		if (val & 0x8000)381			outb(SE2CS | SE2DO, base + TUL_NVRAM);	/* -CLK+dataBit 1 */382		else383			outb(SE2CS, base + TUL_NVRAM);		/* -CLK+dataBit 0 */384		udelay(30);385		outb(SE2CS | SE2CLK, base + TUL_NVRAM);		/* +CLK */386		udelay(30);387		val <<= 1;388	}389	outb(SE2CS, base + TUL_NVRAM);				/* -CLK */390	udelay(30);391	outb(0, base + TUL_NVRAM);				/* -CS  */392	udelay(30);393 394	outb(SE2CS, base + TUL_NVRAM);				/* +CS  */395	udelay(30);396 397	for (;;) {398		outb(SE2CS | SE2CLK, base + TUL_NVRAM);		/* +CLK */399		udelay(30);400		outb(SE2CS, base + TUL_NVRAM);			/* -CLK */401		udelay(30);402		if (inb(base + TUL_NVRAM) & SE2DI)403			break;	/* write complete */404	}405	outb(0, base + TUL_NVRAM);				/* -CS */406}407 408/**409 *	initio_se2_rd_all	-	read hostadapter NV configuration410 *	@base: Base address of InitIO controller411 *412 *	Reads the E2PROM data into main memory. Ensures that the checksum413 *	and header marker are valid. Returns 1 on success -1 on error.414 */415 416static int initio_se2_rd_all(unsigned long base)417{418	int i;419	u16 chksum = 0;420	u16 *np;421 422	i91unvramp = &i91unvram;423	np = (u16 *) i91unvramp;424	for (i = 0; i < 32; i++)425		*np++ = initio_se2_rd(base, i);426 427	/* Is signature "ini" ok ? */428	if (i91unvramp->NVM_Signature != INI_SIGNATURE)429		return -1;430	/* Is ckecksum ok ? */431	np = (u16 *) i91unvramp;432	for (i = 0; i < 31; i++)433		chksum += *np++;434	if (i91unvramp->NVM_CheckSum != chksum)435		return -1;436	return 1;437}438 439/**440 *	initio_se2_update_all		-	Update E2PROM441 *	@base: Base of InitIO controller442 *443 *	Update the E2PROM by wrting any changes into the E2PROM444 *	chip, rewriting the checksum.445 */446static void initio_se2_update_all(unsigned long base)447{				/* setup default pattern */448	int i;449	u16 chksum = 0;450	u16 *np, *np1;451 452	i91unvramp = &i91unvram;453	/* Calculate checksum first */454	np = (u16 *) i91udftNvRam;455	for (i = 0; i < 31; i++)456		chksum += *np++;457	*np = chksum;458	initio_se2_ew_en(base);	/* Enable write  */459 460	np = (u16 *) i91udftNvRam;461	np1 = (u16 *) i91unvramp;462	for (i = 0; i < 32; i++, np++, np1++) {463		if (*np != *np1)464			initio_se2_wr(base, i, *np);465	}466	initio_se2_ew_ds(base);	/* Disable write   */467}468 469/**470 *	initio_read_eeprom		-	Retrieve configuration471 *	@base: Base of InitIO Host Adapter472 *473 *	Retrieve the host adapter configuration data from E2Prom. If the474 *	data is invalid then the defaults are used and are also restored475 *	into the E2PROM. This forms the access point for the SCSI driver476 *	into the E2PROM layer, the other functions for the E2PROM are all477 *	internal use.478 *479 *	Must be called single threaded, uses a shared global area.480 */481 482static void initio_read_eeprom(unsigned long base)483{484	u8 gctrl;485 486	i91unvramp = &i91unvram;487	/* Enable EEProm programming */488	gctrl = inb(base + TUL_GCTRL);489	outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);490	if (initio_se2_rd_all(base) != 1) {491		initio_se2_update_all(base);	/* setup default pattern */492		initio_se2_rd_all(base);	/* load again  */493	}494	/* Disable EEProm programming */495	gctrl = inb(base + TUL_GCTRL);496	outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL);497}498 499/**500 *	initio_stop_bm		-	stop bus master501 *	@host: InitIO we are stopping502 *503 *	Stop any pending DMA operation, aborting the DMA if necessary504 */505 506static void initio_stop_bm(struct initio_host * host)507{508 509	if (inb(host->addr + TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */510		outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);511		/* wait Abort DMA xfer done */512		while ((inb(host->addr + TUL_Int) & XABT) == 0)513			cpu_relax();514	}515	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);516}517 518/**519 *	initio_reset_scsi		-	Reset SCSI host controller520 *	@host: InitIO host to reset521 *	@seconds: Recovery time522 *523 *	Perform a full reset of the SCSI subsystem.524 */525 526static int initio_reset_scsi(struct initio_host * host, int seconds)527{528	outb(TSC_RST_BUS, host->addr + TUL_SCtrl0);529 530	while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT))531		cpu_relax();532 533	/* reset tulip chip */534	outb(0, host->addr + TUL_SSignal);535 536	/* Stall for a while, wait for target's firmware ready,make it 2 sec ! */537	/* SONY 5200 tape drive won't work if only stall for 1 sec */538	/* FIXME: this is a very long busy wait right now */539	initio_do_pause(seconds * HZ);540 541	inb(host->addr + TUL_SInt);542	return SCSI_RESET_SUCCESS;543}544 545/**546 *	initio_init		-	set up an InitIO host adapter547 *	@host: InitIO host adapter548 *	@bios_addr: BIOS address549 *550 *	Set up the host adapter and devices according to the configuration551 *	retrieved from the E2PROM.552 *553 *	Locking: Calls E2PROM layer code which is not re-enterable so must554 *	run single threaded for now.555 */556 557static void initio_init(struct initio_host * host, u8 *bios_addr)558{559	int i;560	u8 *flags;561	u8 *heads;562 563	/* Get E2Prom configuration */564	initio_read_eeprom(host->addr);565	if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)566		host->max_tar = 8;567	else568		host->max_tar = 16;569 570	host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;571 572	host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;573	host->idmask = ~(1 << host->scsi_id);574 575#ifdef CHK_PARITY576	/* Enable parity error response */577	outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD);578#endif579 580	/* Mask all the interrupt       */581	outb(0x1F, host->addr + TUL_Mask);582 583	initio_stop_bm(host);584	/* --- Initialize the tulip --- */585	outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0);586 587	/* program HBA's SCSI ID        */588	outb(host->scsi_id << 4, host->addr + TUL_SScsiId);589 590	/* Enable Initiator Mode ,phase latch,alternate sync period mode,591	   disable SCSI reset */592	if (host->config & HCC_EN_PAR)593		host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);594	else595		host->sconf1 = (TSC_INITDEFAULT);596	outb(host->sconf1, host->addr + TUL_SConfig);597 598	/* Enable HW reselect */599	outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);600 601	outb(0, host->addr + TUL_SPeriod);602 603	/* selection time out = 250 ms */604	outb(153, host->addr + TUL_STimeOut);605 606	/* Enable SCSI terminator */607	outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)),608		host->addr + TUL_XCtrl);609	outb(((host->config & HCC_AUTO_TERM) >> 4) |610		(inb(host->addr + TUL_GCTRL1) & 0xFE),611		host->addr + TUL_GCTRL1);612 613	for (i = 0,614	     flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),615	     heads = bios_addr + 0x180;616	     i < host->max_tar;617	     i++, flags++) {618		host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);619		if (host->targets[i].flags & TCF_EN_255)620			host->targets[i].drv_flags = TCF_DRV_255_63;621		else622			host->targets[i].drv_flags = 0;623		host->targets[i].js_period = 0;624		host->targets[i].sconfig0 = host->sconf1;625		host->targets[i].heads = *heads++;626		if (host->targets[i].heads == 255)627			host->targets[i].drv_flags = TCF_DRV_255_63;628		else629			host->targets[i].drv_flags = 0;630		host->targets[i].sectors = *heads++;631		host->targets[i].flags &= ~TCF_BUSY;632		host->act_tags[i] = 0;633		host->max_tags[i] = 0xFF;634	}			/* for                          */635	printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",636	       host->addr, host->pci_dev->irq,637	       host->bios_addr, host->scsi_id);638	/* Reset SCSI Bus */639	if (host->config & HCC_SCSI_RESET) {640		printk(KERN_INFO "i91u: Reset SCSI Bus ... \n");641		initio_reset_scsi(host, 10);642	}643	outb(0x17, host->addr + TUL_SCFG1);644	outb(0xE9, host->addr + TUL_SIntEnable);645}646 647/**648 *	initio_alloc_scb		-	Allocate an SCB649 *	@host: InitIO host we are allocating for650 *651 *	Walk the SCB list for the controller and allocate a free SCB if652 *	one exists.653 */654static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host)655{656	struct scsi_ctrl_blk *scb;657	unsigned long flags;658 659	spin_lock_irqsave(&host->avail_lock, flags);660	if ((scb = host->first_avail) != NULL) {661#if DEBUG_QUEUE662		printk("find scb at %p\n", scb);663#endif664		if ((host->first_avail = scb->next) == NULL)665			host->last_avail = NULL;666		scb->next = NULL;667		scb->status = SCB_RENT;668	}669	spin_unlock_irqrestore(&host->avail_lock, flags);670	return scb;671}672 673/**674 *	initio_release_scb		-	Release an SCB675 *	@host: InitIO host that owns the SCB676 *	@cmnd: SCB command block being returned677 *678 *	Return an allocated SCB to the host free list679 */680 681static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd)682{683	unsigned long flags;684 685#if DEBUG_QUEUE686	printk("Release SCB %p; ", cmnd);687#endif688	spin_lock_irqsave(&(host->avail_lock), flags);689	cmnd->srb = NULL;690	cmnd->status = 0;691	cmnd->next = NULL;692	if (host->last_avail != NULL) {693		host->last_avail->next = cmnd;694		host->last_avail = cmnd;695	} else {696		host->first_avail = cmnd;697		host->last_avail = cmnd;698	}699	spin_unlock_irqrestore(&(host->avail_lock), flags);700}701 702/***************************************************************************/703static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)704{705 706#if DEBUG_QUEUE707	printk("Append pend SCB %p; ", scbp);708#endif709	scbp->status = SCB_PEND;710	scbp->next = NULL;711	if (host->last_pending != NULL) {712		host->last_pending->next = scbp;713		host->last_pending = scbp;714	} else {715		host->first_pending = scbp;716		host->last_pending = scbp;717	}718}719 720/***************************************************************************/721static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)722{723 724#if DEBUG_QUEUE725	printk("Push pend SCB %p; ", scbp);726#endif727	scbp->status = SCB_PEND;728	if ((scbp->next = host->first_pending) != NULL) {729		host->first_pending = scbp;730	} else {731		host->first_pending = scbp;732		host->last_pending = scbp;733	}734}735 736static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host)737{738	struct scsi_ctrl_blk *first;739 740 741	first = host->first_pending;742	while (first != NULL) {743		if (first->opcode != ExecSCSI)744			return first;745		if (first->tagmsg == 0) {746			if ((host->act_tags[first->target] == 0) &&747			    !(host->targets[first->target].flags & TCF_BUSY))748				return first;749		} else {750			if ((host->act_tags[first->target] >=751			  host->max_tags[first->target]) |752			    (host->targets[first->target].flags & TCF_BUSY)) {753				first = first->next;754				continue;755			}756			return first;757		}758		first = first->next;759	}760	return first;761}762 763static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)764{765	struct scsi_ctrl_blk *tmp, *prev;766 767#if DEBUG_QUEUE768	printk("unlink pend SCB %p; ", scb);769#endif770 771	prev = tmp = host->first_pending;772	while (tmp != NULL) {773		if (scb == tmp) {	/* Unlink this SCB              */774			if (tmp == host->first_pending) {775				if ((host->first_pending = tmp->next) == NULL)776					host->last_pending = NULL;777			} else {778				prev->next = tmp->next;779				if (tmp == host->last_pending)780					host->last_pending = prev;781			}782			tmp->next = NULL;783			break;784		}785		prev = tmp;786		tmp = tmp->next;787	}788}789 790static void initio_append_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)791{792 793#if DEBUG_QUEUE794	printk("append busy SCB %p; ", scbp);795#endif796	if (scbp->tagmsg)797		host->act_tags[scbp->target]++;798	else799		host->targets[scbp->target].flags |= TCF_BUSY;800	scbp->status = SCB_BUSY;801	scbp->next = NULL;802	if (host->last_busy != NULL) {803		host->last_busy->next = scbp;804		host->last_busy = scbp;805	} else {806		host->first_busy = scbp;807		host->last_busy = scbp;808	}809}810 811/***************************************************************************/812static struct scsi_ctrl_blk *initio_pop_busy_scb(struct initio_host * host)813{814	struct scsi_ctrl_blk *tmp;815 816 817	if ((tmp = host->first_busy) != NULL) {818		if ((host->first_busy = tmp->next) == NULL)819			host->last_busy = NULL;820		tmp->next = NULL;821		if (tmp->tagmsg)822			host->act_tags[tmp->target]--;823		else824			host->targets[tmp->target].flags &= ~TCF_BUSY;825	}826#if DEBUG_QUEUE827	printk("Pop busy SCB %p; ", tmp);828#endif829	return tmp;830}831 832/***************************************************************************/833static void initio_unlink_busy_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)834{835	struct scsi_ctrl_blk *tmp, *prev;836 837#if DEBUG_QUEUE838	printk("unlink busy SCB %p; ", scb);839#endif840 841	prev = tmp = host->first_busy;842	while (tmp != NULL) {843		if (scb == tmp) {	/* Unlink this SCB              */844			if (tmp == host->first_busy) {845				if ((host->first_busy = tmp->next) == NULL)846					host->last_busy = NULL;847			} else {848				prev->next = tmp->next;849				if (tmp == host->last_busy)850					host->last_busy = prev;851			}852			tmp->next = NULL;853			if (tmp->tagmsg)854				host->act_tags[tmp->target]--;855			else856				host->targets[tmp->target].flags &= ~TCF_BUSY;857			break;858		}859		prev = tmp;860		tmp = tmp->next;861	}862	return;863}864 865struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun)866{867	struct scsi_ctrl_blk *tmp;868	u16 scbp_tarlun;869 870 871	tmp = host->first_busy;872	while (tmp != NULL) {873		scbp_tarlun = (tmp->lun << 8) | (tmp->target);874		if (scbp_tarlun == tarlun) {	/* Unlink this SCB              */875			break;876		}877		tmp = tmp->next;878	}879#if DEBUG_QUEUE880	printk("find busy SCB %p; ", tmp);881#endif882	return tmp;883}884 885static void initio_append_done_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp)886{887#if DEBUG_QUEUE888	printk("append done SCB %p; ", scbp);889#endif890 891	scbp->status = SCB_DONE;892	scbp->next = NULL;893	if (host->last_done != NULL) {894		host->last_done->next = scbp;895		host->last_done = scbp;896	} else {897		host->first_done = scbp;898		host->last_done = scbp;899	}900}901 902struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host)903{904	struct scsi_ctrl_blk *tmp;905 906	if ((tmp = host->first_done) != NULL) {907		if ((host->first_done = tmp->next) == NULL)908			host->last_done = NULL;909		tmp->next = NULL;910	}911#if DEBUG_QUEUE912	printk("find done SCB %p; ",tmp);913#endif914	return tmp;915}916 917static int initio_abort_srb(struct initio_host * host, struct scsi_cmnd *srbp)918{919	unsigned long flags;920	struct scsi_ctrl_blk *tmp, *prev;921 922	spin_lock_irqsave(&host->semaph_lock, flags);923 924	if ((host->semaph == 0) && (host->active == NULL)) {925		/* disable Jasmin SCSI Int        */926		outb(0x1F, host->addr + TUL_Mask);927		spin_unlock_irqrestore(&host->semaph_lock, flags);928		/* FIXME: synchronize_irq needed ? */929		tulip_main(host);930		spin_lock_irqsave(&host->semaph_lock, flags);931		host->semaph = 1;932		outb(0x0F, host->addr + TUL_Mask);933		spin_unlock_irqrestore(&host->semaph_lock, flags);934		return SCSI_ABORT_SNOOZE;935	}936	prev = tmp = host->first_pending;	/* Check Pend queue */937	while (tmp != NULL) {938		/* 07/27/98 */939		if (tmp->srb == srbp) {940			if (tmp == host->active) {941				spin_unlock_irqrestore(&host->semaph_lock, flags);942				return SCSI_ABORT_BUSY;943			} else if (tmp == host->first_pending) {944				if ((host->first_pending = tmp->next) == NULL)945					host->last_pending = NULL;946			} else {947				prev->next = tmp->next;948				if (tmp == host->last_pending)949					host->last_pending = prev;950			}951			tmp->hastat = HOST_ABORTED;952			tmp->flags |= SCF_DONE;953			if (tmp->flags & SCF_POST)954				(*tmp->post) ((u8 *) host, (u8 *) tmp);955			spin_unlock_irqrestore(&host->semaph_lock, flags);956			return SCSI_ABORT_SUCCESS;957		}958		prev = tmp;959		tmp = tmp->next;960	}961 962	prev = tmp = host->first_busy;	/* Check Busy queue */963	while (tmp != NULL) {964		if (tmp->srb == srbp) {965			if (tmp == host->active) {966				spin_unlock_irqrestore(&host->semaph_lock, flags);967				return SCSI_ABORT_BUSY;968			} else if (tmp->tagmsg == 0) {969				spin_unlock_irqrestore(&host->semaph_lock, flags);970				return SCSI_ABORT_BUSY;971			} else {972				host->act_tags[tmp->target]--;973				if (tmp == host->first_busy) {974					if ((host->first_busy = tmp->next) == NULL)975						host->last_busy = NULL;976				} else {977					prev->next = tmp->next;978					if (tmp == host->last_busy)979						host->last_busy = prev;980				}981				tmp->next = NULL;982 983 984				tmp->hastat = HOST_ABORTED;985				tmp->flags |= SCF_DONE;986				if (tmp->flags & SCF_POST)987					(*tmp->post) ((u8 *) host, (u8 *) tmp);988				spin_unlock_irqrestore(&host->semaph_lock, flags);989				return SCSI_ABORT_SUCCESS;990			}991		}992		prev = tmp;993		tmp = tmp->next;994	}995	spin_unlock_irqrestore(&host->semaph_lock, flags);996	return SCSI_ABORT_NOT_RUNNING;997}998 999/***************************************************************************/1000static int initio_bad_seq(struct initio_host * host)1001{1002	struct scsi_ctrl_blk *scb;1003 1004	printk("initio_bad_seg c=%d\n", host->index);1005 1006	if ((scb = host->active) != NULL) {1007		initio_unlink_busy_scb(host, scb);1008		scb->hastat = HOST_BAD_PHAS;1009		scb->tastat = 0;1010		initio_append_done_scb(host, scb);1011	}1012	initio_stop_bm(host);1013	initio_reset_scsi(host, 8);	/* 7/29/98 */1014	return initio_post_scsi_rst(host);1015}1016 1017 1018/************************************************************************/1019static void initio_exec_scb(struct initio_host * host, struct scsi_ctrl_blk * scb)1020{1021	unsigned long flags;1022 1023	scb->mode = 0;1024 1025	scb->sgidx = 0;1026	scb->sgmax = scb->sglen;1027 1028	spin_lock_irqsave(&host->semaph_lock, flags);1029 1030	initio_append_pend_scb(host, scb);	/* Append this SCB to Pending queue */1031 1032/* VVVVV 07/21/98 */1033	if (host->semaph == 1) {1034		/* Disable Jasmin SCSI Int */1035		outb(0x1F, host->addr + TUL_Mask);1036		host->semaph = 0;1037		spin_unlock_irqrestore(&host->semaph_lock, flags);1038 1039		tulip_main(host);1040 1041		spin_lock_irqsave(&host->semaph_lock, flags);1042		host->semaph = 1;1043		outb(0x0F, host->addr + TUL_Mask);1044	}1045	spin_unlock_irqrestore(&host->semaph_lock, flags);1046	return;1047}1048 1049/***************************************************************************/1050static int initio_isr(struct initio_host * host)1051{1052	if (inb(host->addr + TUL_Int) & TSS_INT_PENDING) {1053		if (host->semaph == 1) {1054			outb(0x1F, host->addr + TUL_Mask);1055			/* Disable Tulip SCSI Int */1056			host->semaph = 0;1057 1058			tulip_main(host);1059 1060			host->semaph = 1;1061			outb(0x0F, host->addr + TUL_Mask);1062			return 1;1063		}1064	}1065	return 0;1066}1067 1068static int tulip_main(struct initio_host * host)1069{1070	struct scsi_ctrl_blk *scb;1071 1072	for (;;) {1073		tulip_scsi(host);	/* Call tulip_scsi              */1074 1075		/* Walk the list of completed SCBs */1076		while ((scb = initio_find_done_scb(host)) != NULL) {	/* find done entry */1077			if (scb->tastat == INI_QUEUE_FULL) {1078				host->max_tags[scb->target] =1079				    host->act_tags[scb->target] - 1;1080				scb->tastat = 0;1081				initio_append_pend_scb(host, scb);1082				continue;1083			}1084			if (!(scb->mode & SCM_RSENS)) {		/* not in auto req. sense mode */1085				if (scb->tastat == 2) {1086 1087					/* clr sync. nego flag */1088 1089					if (scb->flags & SCF_SENSE) {1090						u8 len;1091						len = scb->senselen;1092						if (len == 0)1093							len = 1;1094						scb->buflen = scb->senselen;1095						scb->bufptr = scb->senseptr;1096						scb->flags &= ~(SCF_SG | SCF_DIR);	/* for xfer_data_in */1097						/* so, we won't report wrong direction in xfer_data_in,1098						   and won't report HOST_DO_DU in state_6 */1099						scb->mode = SCM_RSENS;1100						scb->ident &= 0xBF;	/* Disable Disconnect */1101						scb->tagmsg = 0;1102						scb->tastat = 0;1103						scb->cdblen = 6;1104						scb->cdb[0] = SCSICMD_RequestSense;1105						scb->cdb[1] = 0;1106						scb->cdb[2] = 0;1107						scb->cdb[3] = 0;1108						scb->cdb[4] = len;1109						scb->cdb[5] = 0;1110						initio_push_pend_scb(host, scb);1111						break;1112					}1113				}1114			} else {	/* in request sense mode */1115 1116				if (scb->tastat == 2) {		/* check contition status again after sending1117									   requset sense cmd 0x3 */1118					scb->hastat = HOST_BAD_PHAS;1119				}1120				scb->tastat = 2;1121			}1122			scb->flags |= SCF_DONE;1123			if (scb->flags & SCF_POST) {1124				/* FIXME: only one post method and lose casts */1125				(*scb->post) ((u8 *) host, (u8 *) scb);1126			}1127		}		/* while */1128		/* find_active: */1129		if (inb(host->addr + TUL_SStatus0) & TSS_INT_PENDING)1130			continue;1131		if (host->active)	/* return to OS and wait for xfer_done_ISR/Selected_ISR */1132			return 1;	/* return to OS, enable interrupt */1133		/* Check pending SCB            */1134		if (initio_find_first_pend_scb(host) == NULL)1135			return 1;	/* return to OS, enable interrupt */1136	}			/* End of for loop */1137	/* statement won't reach here */1138}1139 1140static void tulip_scsi(struct initio_host * host)1141{1142	struct scsi_ctrl_blk *scb;1143	struct target_control *active_tc;1144 1145	/* make sure to service interrupt asap */1146	if ((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING) {1147		host->phase = host->jsstatus0 & TSS_PH_MASK;1148		host->jsstatus1 = inb(host->addr + TUL_SStatus1);1149		host->jsint = inb(host->addr + TUL_SInt);1150		if (host->jsint & TSS_SCSIRST_INT) {	/* SCSI bus reset detected      */1151			int_initio_scsi_rst(host);1152			return;1153		}1154		if (host->jsint & TSS_RESEL_INT) {	/* if selected/reselected interrupt */1155			if (int_initio_resel(host) == 0)1156				initio_next_state(host);1157			return;1158		}1159		if (host->jsint & TSS_SEL_TIMEOUT) {1160			int_initio_busfree(host);1161			return;1162		}1163		if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection            */1164			int_initio_busfree(host);	/* unexpected bus free or sel timeout */1165			return;1166		}1167		if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV)) {	/* func complete or Bus service */1168			if (host->active)1169				initio_next_state(host);1170			return;1171		}1172	}1173	if (host->active != NULL)1174		return;1175 1176	if ((scb = initio_find_first_pend_scb(host)) == NULL)1177		return;1178 1179	/* program HBA's SCSI ID & target SCSI ID */1180	outb((host->scsi_id << 4) | (scb->target & 0x0F),1181		host->addr + TUL_SScsiId);1182	if (scb->opcode == ExecSCSI) {1183		active_tc = &host->targets[scb->target];1184 1185		if (scb->tagmsg)1186			active_tc->drv_flags |= TCF_DRV_EN_TAG;1187		else1188			active_tc->drv_flags &= ~TCF_DRV_EN_TAG;1189 1190		outb(active_tc->js_period, host->addr + TUL_SPeriod);1191		if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {	/* do wdtr negotiation          */1192			initio_select_atn_stop(host, scb);1193		} else {1194			if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync negotiation          */1195				initio_select_atn_stop(host, scb);1196			} else {1197				if (scb->tagmsg)1198					initio_select_atn3(host, scb);1199				else1200					initio_select_atn(host, scb);1201			}1202		}1203		if (scb->flags & SCF_POLL) {1204			while (wait_tulip(host) != -1) {1205				if (initio_next_state(host) == -1)1206					break;1207			}1208		}1209	} else if (scb->opcode == BusDevRst) {1210		initio_select_atn_stop(host, scb);1211		scb->next_state = 8;1212		if (scb->flags & SCF_POLL) {1213			while (wait_tulip(host) != -1) {1214				if (initio_next_state(host) == -1)1215					break;1216			}1217		}1218	} else if (scb->opcode == AbortCmd) {1219		if (initio_abort_srb(host, scb->srb) != 0) {1220			initio_unlink_pend_scb(host, scb);1221			initio_release_scb(host, scb);1222		} else {1223			scb->opcode = BusDevRst;1224			initio_select_atn_stop(host, scb);1225			scb->next_state = 8;1226		}1227	} else {1228		initio_unlink_pend_scb(host, scb);1229		scb->hastat = 0x16;	/* bad command */1230		initio_append_done_scb(host, scb);1231	}1232	return;1233}1234 1235/**1236 *	initio_next_state		-	Next SCSI state1237 *	@host: InitIO host we are processing1238 *1239 *	Progress the active command block along the state machine1240 *	until we hit a state which we must wait for activity to occur.1241 *1242 *	Returns zero or a negative code.1243 */1244 1245static int initio_next_state(struct initio_host * host)1246{1247	int next;1248 1249	next = host->active->next_state;1250	for (;;) {1251		switch (next) {1252		case 1:1253			next = initio_state_1(host);1254			break;1255		case 2:1256			next = initio_state_2(host);1257			break;1258		case 3:1259			next = initio_state_3(host);1260			break;1261		case 4:1262			next = initio_state_4(host);1263			break;1264		case 5:1265			next = initio_state_5(host);1266			break;1267		case 6:1268			next = initio_state_6(host);1269			break;1270		case 7:1271			next = initio_state_7(host);1272			break;1273		case 8:1274			return initio_bus_device_reset(host);1275		default:1276			return initio_bad_seq(host);1277		}1278		if (next <= 0)1279			return next;1280	}1281}1282 1283 1284/**1285 *	initio_state_1		-	SCSI state machine1286 *	@host: InitIO host we are controlling1287 *1288 *	Perform SCSI state processing for Select/Attention/Stop1289 */1290 1291static int initio_state_1(struct initio_host * host)1292{1293	struct scsi_ctrl_blk *scb = host->active;1294	struct target_control *active_tc = host->active_tc;1295#if DEBUG_STATE1296	printk("-s1-");1297#endif1298 1299	/* Move the SCB from pending to busy */1300	initio_unlink_pend_scb(host, scb);1301	initio_append_busy_scb(host, scb);1302 1303	outb(active_tc->sconfig0, host->addr + TUL_SConfig );1304	/* ATN on */1305	if (host->phase == MSG_OUT) {1306		outb(TSC_EN_BUS_IN | TSC_HW_RESELECT, host->addr + TUL_SCtrl1);1307		outb(scb->ident, host->addr + TUL_SFifo);1308 1309		if (scb->tagmsg) {1310			outb(scb->tagmsg, host->addr + TUL_SFifo);1311			outb(scb->tagid, host->addr + TUL_SFifo);1312		}1313		if ((active_tc->flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {1314			active_tc->flags |= TCF_WDTR_DONE;1315			outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);1316			outb(2, host->addr + TUL_SFifo);	/* Extended msg length */1317			outb(EXTENDED_SDTR, host->addr + TUL_SFifo);	/* Sync request */1318			outb(1, host->addr + TUL_SFifo);	/* Start from 16 bits */1319		} else if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {1320			active_tc->flags |= TCF_SYNC_DONE;1321			outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);1322			outb(3, host->addr + TUL_SFifo);	/* extended msg length */1323			outb(EXTENDED_SDTR, host->addr + TUL_SFifo);	/* sync request */1324			outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);1325			outb(MAX_OFFSET, host->addr + TUL_SFifo);	/* REQ/ACK offset */1326		}1327		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1328		if (wait_tulip(host) == -1)1329			return -1;1330	}1331	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1332	outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);1333	/* Into before CDB xfer */1334	return 3;1335}1336 1337 1338/**1339 *	initio_state_2		-	SCSI state machine1340 *	@host: InitIO host we are controlling1341 *1342 * state after selection with attention1343 * state after selection with attention31344 */1345 1346static int initio_state_2(struct initio_host * host)1347{1348	struct scsi_ctrl_blk *scb = host->active;1349	struct target_control *active_tc = host->active_tc;1350#if DEBUG_STATE1351	printk("-s2-");1352#endif1353 1354	initio_unlink_pend_scb(host, scb);1355	initio_append_busy_scb(host, scb);1356 1357	outb(active_tc->sconfig0, host->addr + TUL_SConfig);1358 1359	if (host->jsstatus1 & TSS_CMD_PH_CMP)1360		return 4;1361 1362	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1363	outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)), host->addr + TUL_SSignal);1364	/* Into before CDB xfer */1365	return 3;1366}1367 1368/**1369 *	initio_state_3		-	SCSI state machine1370 *	@host: InitIO host we are controlling1371 *1372 * state before CDB xfer is done1373 */1374 1375static int initio_state_3(struct initio_host * host)1376{1377	struct scsi_ctrl_blk *scb = host->active;1378	struct target_control *active_tc = host->active_tc;1379	int i;1380 1381#if DEBUG_STATE1382	printk("-s3-");1383#endif1384	for (;;) {1385		switch (host->phase) {1386		case CMD_OUT:	/* Command out phase            */1387			for (i = 0; i < (int) scb->cdblen; i++)1388				outb(scb->cdb[i], host->addr + TUL_SFifo);1389			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1390			if (wait_tulip(host) == -1)1391				return -1;1392			if (host->phase == CMD_OUT)1393				return initio_bad_seq(host);1394			return 4;1395 1396		case MSG_IN:	/* Message in phase             */1397			scb->next_state = 3;1398			if (initio_msgin(host) == -1)1399				return -1;1400			break;1401 1402		case STATUS_IN:	/* Status phase                 */1403			if (initio_status_msg(host) == -1)1404				return -1;1405			break;1406 1407		case MSG_OUT:	/* Message out phase            */1408			if (active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {1409				outb(NOP, host->addr + TUL_SFifo);		/* msg nop */1410				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1411				if (wait_tulip(host) == -1)1412					return -1;1413			} else {1414				active_tc->flags |= TCF_SYNC_DONE;1415 1416				outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);1417				outb(3, host->addr + TUL_SFifo);	/* ext. msg len */1418				outb(EXTENDED_SDTR, host->addr + TUL_SFifo);	/* sync request */1419				outb(initio_rate_tbl[active_tc->flags & TCF_SCSI_RATE], host->addr + TUL_SFifo);1420				outb(MAX_OFFSET, host->addr + TUL_SFifo);	/* REQ/ACK offset */1421				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1422				if (wait_tulip(host) == -1)1423					return -1;1424				outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1425				outb(inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7), host->addr + TUL_SSignal);1426 1427			}1428			break;1429		default:1430			return initio_bad_seq(host);1431		}1432	}1433}1434 1435/**1436 *	initio_state_4		-	SCSI state machine1437 *	@host: InitIO host we are controlling1438 *1439 *	SCSI state machine. State 41440 */1441 1442static int initio_state_4(struct initio_host * host)1443{1444	struct scsi_ctrl_blk *scb = host->active;1445 1446#if DEBUG_STATE1447	printk("-s4-");1448#endif1449	if ((scb->flags & SCF_DIR) == SCF_NO_XF) {1450		return 6;	/* Go to state 6 (After data) */1451	}1452	for (;;) {1453		if (scb->buflen == 0)1454			return 6;1455 1456		switch (host->phase) {1457 1458		case STATUS_IN:	/* Status phase                 */1459			if ((scb->flags & SCF_DIR) != 0)	/* if direction bit set then report data underrun */1460				scb->hastat = HOST_DO_DU;1461			if ((initio_status_msg(host)) == -1)1462				return -1;1463			break;1464 1465		case MSG_IN:	/* Message in phase             */1466			scb->next_state = 0x4;1467			if (initio_msgin(host) == -1)1468				return -1;1469			break;1470 1471		case MSG_OUT:	/* Message out phase            */1472			if (host->jsstatus0 & TSS_PAR_ERROR) {1473				scb->buflen = 0;1474				scb->hastat = HOST_DO_DU;1475				if (initio_msgout_ide(host) == -1)1476					return -1;1477				return 6;1478			} else {1479				outb(NOP, host->addr + TUL_SFifo);		/* msg nop */1480				outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1481				if (wait_tulip(host) == -1)1482					return -1;1483			}1484			break;1485 1486		case DATA_IN:	/* Data in phase                */1487			return initio_xfer_data_in(host);1488 1489		case DATA_OUT:	/* Data out phase               */1490			return initio_xfer_data_out(host);1491 1492		default:1493			return initio_bad_seq(host);1494		}1495	}1496}1497 1498 1499/**1500 *	initio_state_5		-	SCSI state machine1501 *	@host: InitIO host we are controlling1502 *1503 *	State after dma xfer done or phase change before xfer done1504 */1505 1506static int initio_state_5(struct initio_host * host)1507{1508	struct scsi_ctrl_blk *scb = host->active;1509	long cnt, xcnt;		/* cannot use unsigned !! code: if (xcnt < 0) */1510 1511#if DEBUG_STATE1512	printk("-s5-");1513#endif1514	/*------ get remaining count -------*/1515	cnt = inl(host->addr + TUL_SCnt0) & 0x0FFFFFF;1516 1517	if (inb(host->addr + TUL_XCmd) & 0x20) {1518		/* ----------------------- DATA_IN ----------------------------- */1519		/* check scsi parity error */1520		if (host->jsstatus0 & TSS_PAR_ERROR)1521			scb->hastat = HOST_DO_DU;1522		if (inb(host->addr + TUL_XStatus) & XPEND) {	/* DMA xfer pending, Send STOP  */1523			/* tell Hardware  scsi xfer has been terminated */1524			outb(inb(host->addr + TUL_XCtrl) | 0x80, host->addr + TUL_XCtrl);1525			/* wait until DMA xfer not pending */1526			while (inb(host->addr + TUL_XStatus) & XPEND)1527				cpu_relax();1528		}1529	} else {1530		/*-------- DATA OUT -----------*/1531		if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0) {1532			if (host->active_tc->js_period & TSC_WIDE_SCSI)1533				cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F) << 1;1534			else1535				cnt += (inb(host->addr + TUL_SFifoCnt) & 0x1F);1536		}1537		if (inb(host->addr + TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */1538			outb(TAX_X_ABT, host->addr + TUL_XCmd);1539			/* wait Abort DMA xfer done */1540			while ((inb(host->addr + TUL_Int) & XABT) == 0)1541				cpu_relax();1542		}1543		if ((cnt == 1) && (host->phase == DATA_OUT)) {1544			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1545			if (wait_tulip(host) == -1)1546				return -1;1547			cnt = 0;1548		} else {1549			if ((inb(host->addr + TUL_SStatus1) & TSS_XFER_CMP) == 0)1550				outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1551		}1552	}1553	if (cnt == 0) {1554		scb->buflen = 0;1555		return 6;	/* After Data */1556	}1557	/* Update active data pointer */1558	xcnt = (long) scb->buflen - cnt;	/* xcnt== bytes already xferred */1559	scb->buflen = (u32) cnt;		/* cnt == bytes left to be xferred */1560	if (scb->flags & SCF_SG) {1561		struct sg_entry *sgp;1562		unsigned long i;1563 1564		sgp = &scb->sglist[scb->sgidx];1565		for (i = scb->sgidx; i < scb->sgmax; sgp++, i++) {1566			xcnt -= (long) sgp->len;1567			if (xcnt < 0) {		/* this sgp xfer half done */1568				xcnt += (long) sgp->len;	/* xcnt == bytes xferred in this sgp */1569				sgp->data += (u32) xcnt;	/* new ptr to be xfer */1570				sgp->len -= (u32) xcnt;	/* new len to be xfer */1571				scb->bufptr += ((u32) (i - scb->sgidx) << 3);1572				/* new SG table ptr */1573				scb->sglen = (u8) (scb->sgmax - i);1574				/* new SG table len */1575				scb->sgidx = (u16) i;1576				/* for next disc and come in this loop */1577				return 4;	/* Go to state 4                */1578			}1579			/* else (xcnt >= 0 , i.e. this sgp already xferred */1580		}		/* for */1581		return 6;	/* Go to state 6                */1582	} else {1583		scb->bufptr += (u32) xcnt;1584	}1585	return 4;		/* Go to state 4                */1586}1587 1588/**1589 *	initio_state_6		-	SCSI state machine1590 *	@host: InitIO host we are controlling1591 *1592 *	State after Data phase1593 */1594 1595static int initio_state_6(struct initio_host * host)1596{1597	struct scsi_ctrl_blk *scb = host->active;1598 1599#if DEBUG_STATE1600	printk("-s6-");1601#endif1602	for (;;) {1603		switch (host->phase) {1604		case STATUS_IN:	/* Status phase                 */1605			if ((initio_status_msg(host)) == -1)1606				return -1;1607			break;1608 1609		case MSG_IN:	/* Message in phase             */1610			scb->next_state = 6;1611			if ((initio_msgin(host)) == -1)1612				return -1;1613			break;1614 1615		case MSG_OUT:	/* Message out phase            */1616			outb(NOP, host->addr + TUL_SFifo);		/* msg nop */1617			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1618			if (wait_tulip(host) == -1)1619				return -1;1620			break;1621 1622		case DATA_IN:	/* Data in phase                */1623			return initio_xpad_in(host);1624 1625		case DATA_OUT:	/* Data out phase               */1626			return initio_xpad_out(host);1627 1628		default:1629			return initio_bad_seq(host);1630		}1631	}1632}1633 1634/**1635 *	initio_state_7		-	SCSI state machine1636 *	@host: InitIO host we are controlling1637 *1638 */1639 1640static int initio_state_7(struct initio_host * host)1641{1642	int cnt, i;1643 1644#if DEBUG_STATE1645	printk("-s7-");1646#endif1647	/* flush SCSI FIFO */1648	cnt = inb(host->addr + TUL_SFifoCnt) & 0x1F;1649	if (cnt) {1650		for (i = 0; i < cnt; i++)1651			inb(host->addr + TUL_SFifo);1652	}1653	switch (host->phase) {1654	case DATA_IN:		/* Data in phase                */1655	case DATA_OUT:		/* Data out phase               */1656		return initio_bad_seq(host);1657	default:1658		return 6;	/* Go to state 6                */1659	}1660}1661 1662/**1663 *	initio_xfer_data_in	-	Commence data input1664 *	@host: InitIO host in use1665 *1666 *	Commence a block of data transfer. The transfer itself will1667 *	be managed by the controller and we will get a completion (or1668 *	failure) interrupt.1669 */1670static int initio_xfer_data_in(struct initio_host * host)1671{1672	struct scsi_ctrl_blk *scb = host->active;1673 1674	if ((scb->flags & SCF_DIR) == SCF_DOUT)1675		return 6;	/* wrong direction */1676 1677	outl(scb->buflen, host->addr + TUL_SCnt0);1678	outb(TSC_XF_DMA_IN, host->addr + TUL_SCmd);	/* 7/25/95 */1679 1680	if (scb->flags & SCF_SG) {	/* S/G xfer */1681		outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);1682		outl(scb->bufptr, host->addr + TUL_XAddH);1683		outb(TAX_SG_IN, host->addr + TUL_XCmd);1684	} else {1685		outl(scb->buflen, host->addr + TUL_XCntH);1686		outl(scb->bufptr, host->addr + TUL_XAddH);1687		outb(TAX_X_IN, host->addr + TUL_XCmd);1688	}1689	scb->next_state = 0x5;1690	return 0;		/* return to OS, wait xfer done , let jas_isr come in */1691}1692 1693/**1694 *	initio_xfer_data_out	-	Commence data output1695 *	@host: InitIO host in use1696 *1697 *	Commence a block of data transfer. The transfer itself will1698 *	be managed by the controller and we will get a completion (or1699 *	failure) interrupt.1700 */1701 1702static int initio_xfer_data_out(struct initio_host * host)1703{1704	struct scsi_ctrl_blk *scb = host->active;1705 1706	if ((scb->flags & SCF_DIR) == SCF_DIN)1707		return 6;	/* wrong direction */1708 1709	outl(scb->buflen, host->addr + TUL_SCnt0);1710	outb(TSC_XF_DMA_OUT, host->addr + TUL_SCmd);1711 1712	if (scb->flags & SCF_SG) {	/* S/G xfer */1713		outl(((u32) scb->sglen) << 3, host->addr + TUL_XCntH);1714		outl(scb->bufptr, host->addr + TUL_XAddH);1715		outb(TAX_SG_OUT, host->addr + TUL_XCmd);1716	} else {1717		outl(scb->buflen, host->addr + TUL_XCntH);1718		outl(scb->bufptr, host->addr + TUL_XAddH);1719		outb(TAX_X_OUT, host->addr + TUL_XCmd);1720	}1721 1722	scb->next_state = 0x5;1723	return 0;		/* return to OS, wait xfer done , let jas_isr come in */1724}1725 1726int initio_xpad_in(struct initio_host * host)1727{1728	struct scsi_ctrl_blk *scb = host->active;1729	struct target_control *active_tc = host->active_tc;1730 1731	if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)1732		scb->hastat = HOST_DO_DU;	/* over run             */1733	for (;;) {1734		if (active_tc->js_period & TSC_WIDE_SCSI)1735			outl(2, host->addr + TUL_SCnt0);1736		else1737			outl(1, host->addr + TUL_SCnt0);1738 1739		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);1740		if (wait_tulip(host) == -1)1741			return -1;1742		if (host->phase != DATA_IN) {1743			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1744			return 6;1745		}1746		inb(host->addr + TUL_SFifo);1747	}1748}1749 1750int initio_xpad_out(struct initio_host * host)1751{1752	struct scsi_ctrl_blk *scb = host->active;1753	struct target_control *active_tc = host->active_tc;1754 1755	if ((scb->flags & SCF_DIR) != SCF_NO_DCHK)1756		scb->hastat = HOST_DO_DU;	/* over run             */1757	for (;;) {1758		if (active_tc->js_period & TSC_WIDE_SCSI)1759			outl(2, host->addr + TUL_SCnt0);1760		else1761			outl(1, host->addr + TUL_SCnt0);1762 1763		outb(0, host->addr + TUL_SFifo);1764		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1765		if ((wait_tulip(host)) == -1)1766			return -1;1767		if (host->phase != DATA_OUT) {	/* Disable wide CPU to allow read 16 bits */1768			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);1769			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1770			return 6;1771		}1772	}1773}1774 1775int initio_status_msg(struct initio_host * host)1776{				/* status & MSG_IN */1777	struct scsi_ctrl_blk *scb = host->active;1778	u8 msg;1779 1780	outb(TSC_CMD_COMP, host->addr + TUL_SCmd);1781	if (wait_tulip(host) == -1)1782		return -1;1783 1784	/* get status */1785	scb->tastat = inb(host->addr + TUL_SFifo);1786 1787	if (host->phase == MSG_OUT) {1788		if (host->jsstatus0 & TSS_PAR_ERROR)1789			outb(MSG_PARITY_ERROR, host->addr + TUL_SFifo);1790		else1791			outb(NOP, host->addr + TUL_SFifo);1792		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1793		return wait_tulip(host);1794	}1795	if (host->phase == MSG_IN) {1796		msg = inb(host->addr + TUL_SFifo);1797		if (host->jsstatus0 & TSS_PAR_ERROR) {	/* Parity error                 */1798			if ((initio_msgin_accept(host)) == -1)1799				return -1;1800			if (host->phase != MSG_OUT)1801				return initio_bad_seq(host);1802			outb(MSG_PARITY_ERROR, host->addr + TUL_SFifo);1803			outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);1804			return wait_tulip(host);1805		}1806		if (msg == 0) {	/* Command complete             */1807 1808			if ((scb->tastat & 0x18) == 0x10)	/* No link support              */1809				return initio_bad_seq(host);1810			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1811			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);1812			return initio_wait_done_disc(host);1813 1814		}1815		if (msg == LINKED_CMD_COMPLETE ||1816		    msg == LINKED_FLG_CMD_COMPLETE) {1817			if ((scb->tastat & 0x18) == 0x10)1818				return initio_msgin_accept(host);1819		}1820	}1821	return initio_bad_seq(host);1822}1823 1824 1825/* scsi bus free */1826int int_initio_busfree(struct initio_host * host)1827{1828	struct scsi_ctrl_blk *scb = host->active;1829 1830	if (scb != NULL) {1831		if (scb->status & SCB_SELECT) {		/* selection timeout */1832			initio_unlink_pend_scb(host, scb);1833			scb->hastat = HOST_SEL_TOUT;1834			initio_append_done_scb(host, scb);1835		} else {	/* Unexpected bus free          */1836			initio_unlink_busy_scb(host, scb);1837			scb->hastat = HOST_BUS_FREE;1838			initio_append_done_scb(host, scb);1839		}1840		host->active = NULL;1841		host->active_tc = NULL;1842	}1843	outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);		/* Flush SCSI FIFO  */1844	outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);1845	outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect       */1846	return -1;1847}1848 1849 1850/**1851 *	int_initio_scsi_rst	-	SCSI reset occurred1852 *	@host: Host seeing the reset1853 *1854 *	A SCSI bus reset has occurred. Clean up any pending transfer1855 *	the hardware is doing by DMA and then abort all active and1856 *	disconnected commands. The mid layer should sort the rest out1857 *	for us1858 */1859 1860static int int_initio_scsi_rst(struct initio_host * host)1861{1862	struct scsi_ctrl_blk *scb;1863	int i;1864 1865	/* if DMA xfer is pending, abort DMA xfer */1866	if (inb(host->addr + TUL_XStatus) & 0x01) {1867		outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd);1868		/* wait Abort DMA xfer done */1869		while ((inb(host->addr + TUL_Int) & 0x04) == 0)1870			cpu_relax();1871		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);1872	}1873	/* Abort all active & disconnected scb */1874	while ((scb = initio_pop_busy_scb(host)) != NULL) {1875		scb->hastat = HOST_BAD_PHAS;1876		initio_append_done_scb(host, scb);1877	}1878	host->active = NULL;1879	host->active_tc = NULL;1880 1881	/* clr sync nego. done flag */1882	for (i = 0; i < host->max_tar; i++)1883		host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);1884	return -1;1885}1886 1887/**1888 *	int_initio_resel	-	Reselection occurred1889 *	@host: InitIO host adapter1890 *1891 *	A SCSI reselection event has been signalled and the interrupt1892 *	is now being processed. Work out which command block needs attention1893 *	and continue processing that command.1894 */1895 1896int int_initio_resel(struct initio_host * host)1897{1898	struct scsi_ctrl_blk *scb;1899	struct target_control *active_tc;1900	u8 tag, msg = 0;1901	u8 tar, lun;1902 1903	if ((scb = host->active) != NULL) {1904		/* FIXME: Why check and not just clear ? */1905		if (scb->status & SCB_SELECT)		/* if waiting for selection complete */1906			scb->status &= ~SCB_SELECT;1907		host->active = NULL;1908	}1909	/* --------- get target id---------------------- */1910	tar = inb(host->addr + TUL_SBusId);1911	/* ------ get LUN from Identify message----------- */1912	lun = inb(host->addr + TUL_SIdent) & 0x0F;1913	/* 07/22/98 from 0x1F -> 0x0F */1914	active_tc = &host->targets[tar];1915	host->active_tc = active_tc;1916	outb(active_tc->sconfig0, host->addr + TUL_SConfig);1917	outb(active_tc->js_period, host->addr + TUL_SPeriod);1918 1919	/* ------------- tag queueing ? ------------------- */1920	if (active_tc->drv_flags & TCF_DRV_EN_TAG) {1921		if ((initio_msgin_accept(host)) == -1)1922			return -1;1923		if (host->phase != MSG_IN)1924			goto no_tag;1925		outl(1, host->addr + TUL_SCnt0);1926		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);1927		if (wait_tulip(host) == -1)1928			return -1;1929		msg = inb(host->addr + TUL_SFifo);	/* Read Tag Message    */1930 1931		if (msg < SIMPLE_QUEUE_TAG || msg > ORDERED_QUEUE_TAG)1932			/* Is simple Tag      */1933			goto no_tag;1934 1935		if (initio_msgin_accept(host) == -1)1936			return -1;1937 1938		if (host->phase != MSG_IN)1939			goto no_tag;1940 1941		outl(1, host->addr + TUL_SCnt0);1942		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);1943		if (wait_tulip(host) == -1)1944			return -1;1945		tag = inb(host->addr + TUL_SFifo);	/* Read Tag ID       */1946		scb = host->scb + tag;1947		if (scb->target != tar || scb->lun != lun) {1948			return initio_msgout_abort_tag(host);1949		}1950		if (scb->status != SCB_BUSY) {	/* 03/24/95             */1951			return initio_msgout_abort_tag(host);1952		}1953		host->active = scb;1954		if ((initio_msgin_accept(host)) == -1)1955			return -1;1956	} else {		/* No tag               */1957	      no_tag:1958		if ((scb = initio_find_busy_scb(host, tar | (lun << 8))) == NULL) {1959			return initio_msgout_abort_targ(host);1960		}1961		host->active = scb;1962		if (!(active_tc->drv_flags & TCF_DRV_EN_TAG)) {1963			if ((initio_msgin_accept(host)) == -1)1964				return -1;1965		}1966	}1967	return 0;1968}1969 1970/**1971 *	int_initio_bad_seq		-	out of phase1972 *	@host: InitIO host flagging event1973 *1974 *	We have ended up out of phase somehow. Reset the host controller1975 *	and throw all our toys out of the pram. Let the midlayer clean up1976 */1977 1978static int int_initio_bad_seq(struct initio_host * host)1979{				/* target wrong phase           */1980	struct scsi_ctrl_blk *scb;1981	int i;1982 1983	initio_reset_scsi(host, 10);1984 1985	while ((scb = initio_pop_busy_scb(host)) != NULL) {1986		scb->hastat = HOST_BAD_PHAS;1987		initio_append_done_scb(host, scb);1988	}1989	for (i = 0; i < host->max_tar; i++)1990		host->targets[i].flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);1991	return -1;1992}1993 1994 1995/**1996 *	initio_msgout_abort_targ		-	abort a tag1997 *	@host: InitIO host1998 *1999 *	Abort when the target/lun does not match or when our SCB is not2000 *	busy. Used by untagged commands.2001 */2002 2003static int initio_msgout_abort_targ(struct initio_host * host)2004{2005 2006	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2007	if (initio_msgin_accept(host) == -1)2008		return -1;2009	if (host->phase != MSG_OUT)2010		return initio_bad_seq(host);2011 2012	outb(ABORT_TASK_SET, host->addr + TUL_SFifo);2013	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2014 2015	return initio_wait_disc(host);2016}2017 2018/**2019 *	initio_msgout_abort_tag		-	abort a tag2020 *	@host: InitIO host2021 *2022 *	Abort when the target/lun does not match or when our SCB is not2023 *	busy. Used for tagged commands.2024 */2025 2026static int initio_msgout_abort_tag(struct initio_host * host)2027{2028 2029	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2030	if (initio_msgin_accept(host) == -1)2031		return -1;2032	if (host->phase != MSG_OUT)2033		return initio_bad_seq(host);2034 2035	outb(ABORT_TASK, host->addr + TUL_SFifo);2036	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2037 2038	return initio_wait_disc(host);2039 2040}2041 2042/**2043 *	initio_msgin		-	Message in2044 *	@host: InitIO Host2045 *2046 *	Process incoming message2047 */2048static int initio_msgin(struct initio_host * host)2049{2050	struct target_control *active_tc;2051 2052	for (;;) {2053		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);2054 2055		outl(1, host->addr + TUL_SCnt0);2056		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);2057		if (wait_tulip(host) == -1)2058			return -1;2059 2060		switch (inb(host->addr + TUL_SFifo)) {2061		case DISCONNECT:	/* Disconnect msg */2062			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);2063			return initio_wait_disc(host);2064		case SAVE_POINTERS:2065		case RESTORE_POINTERS:2066		case NOP:2067			initio_msgin_accept(host);2068			break;2069		case MESSAGE_REJECT:	/* Clear ATN first              */2070			outb((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)),2071				host->addr + TUL_SSignal);2072			active_tc = host->active_tc;2073			if ((active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)	/* do sync nego */2074				outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN),2075					host->addr + TUL_SSignal);2076			initio_msgin_accept(host);2077			break;2078		case EXTENDED_MESSAGE:	/* extended msg */2079			initio_msgin_extend(host);2080			break;2081		case IGNORE_WIDE_RESIDUE:2082			initio_msgin_accept(host);2083			break;2084		case COMMAND_COMPLETE:2085			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);2086			outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);2087			return initio_wait_done_disc(host);2088		default:2089			initio_msgout_reject(host);2090			break;2091		}2092		if (host->phase != MSG_IN)2093			return host->phase;2094	}2095	/* statement won't reach here */2096}2097 2098static int initio_msgout_reject(struct initio_host * host)2099{2100	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2101 2102	if (initio_msgin_accept(host) == -1)2103		return -1;2104 2105	if (host->phase == MSG_OUT) {2106		outb(MESSAGE_REJECT, host->addr + TUL_SFifo);		/* Msg reject           */2107		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2108		return wait_tulip(host);2109	}2110	return host->phase;2111}2112 2113static int initio_msgout_ide(struct initio_host * host)2114{2115	outb(INITIATOR_ERROR, host->addr + TUL_SFifo);		/* Initiator Detected Error */2116	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2117	return wait_tulip(host);2118}2119 2120static int initio_msgin_extend(struct initio_host * host)2121{2122	u8 len, idx;2123 2124	if (initio_msgin_accept(host) != MSG_IN)2125		return host->phase;2126 2127	/* Get extended msg length      */2128	outl(1, host->addr + TUL_SCnt0);2129	outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);2130	if (wait_tulip(host) == -1)2131		return -1;2132 2133	len = inb(host->addr + TUL_SFifo);2134	host->msg[0] = len;2135	for (idx = 1; len != 0; len--) {2136 2137		if ((initio_msgin_accept(host)) != MSG_IN)2138			return host->phase;2139		outl(1, host->addr + TUL_SCnt0);2140		outb(TSC_XF_FIFO_IN, host->addr + TUL_SCmd);2141		if (wait_tulip(host) == -1)2142			return -1;2143		host->msg[idx++] = inb(host->addr + TUL_SFifo);2144	}2145	if (host->msg[1] == 1) {		/* if it's synchronous data transfer request */2146		u8 r;2147		if (host->msg[0] != 3)	/* if length is not right */2148			return initio_msgout_reject(host);2149		if (host->active_tc->flags & TCF_NO_SYNC_NEGO) {	/* Set OFFSET=0 to do async, nego back */2150			host->msg[3] = 0;2151		} else {2152			if (initio_msgin_sync(host) == 0 &&2153			    (host->active_tc->flags & TCF_SYNC_DONE)) {2154				initio_sync_done(host);2155				return initio_msgin_accept(host);2156			}2157		}2158 2159		r = inb(host->addr + TUL_SSignal);2160		outb((r & (TSC_SET_ACK | 7)) | TSC_SET_ATN,2161			host->addr + TUL_SSignal);2162		if (initio_msgin_accept(host) != MSG_OUT)2163			return host->phase;2164		/* sync msg out */2165		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);2166 2167		initio_sync_done(host);2168 2169		outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);2170		outb(3, host->addr + TUL_SFifo);2171		outb(EXTENDED_SDTR, host->addr + TUL_SFifo);2172		outb(host->msg[2], host->addr + TUL_SFifo);2173		outb(host->msg[3], host->addr + TUL_SFifo);2174		outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2175		return wait_tulip(host);2176	}2177	if (host->msg[0] != 2 || host->msg[1] != 3)2178		return initio_msgout_reject(host);2179	/* if it's WIDE DATA XFER REQ   */2180	if (host->active_tc->flags & TCF_NO_WDTR) {2181		host->msg[2] = 0;2182	} else {2183		if (host->msg[2] > 2)	/* > 32 bits            */2184			return initio_msgout_reject(host);2185		if (host->msg[2] == 2) {		/* == 32                */2186			host->msg[2] = 1;2187		} else {2188			if ((host->active_tc->flags & TCF_NO_WDTR) == 0) {2189				wdtr_done(host);2190				if ((host->active_tc->flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)2191					outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2192				return initio_msgin_accept(host);2193			}2194		}2195	}2196	outb(((inb(host->addr + TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN), host->addr + TUL_SSignal);2197 2198	if (initio_msgin_accept(host) != MSG_OUT)2199		return host->phase;2200	/* WDTR msg out                 */2201	outb(EXTENDED_MESSAGE, host->addr + TUL_SFifo);2202	outb(2, host->addr + TUL_SFifo);2203	outb(EXTENDED_WDTR, host->addr + TUL_SFifo);2204	outb(host->msg[2], host->addr + TUL_SFifo);2205	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2206	return wait_tulip(host);2207}2208 2209static int initio_msgin_sync(struct initio_host * host)2210{2211	char default_period;2212 2213	default_period = initio_rate_tbl[host->active_tc->flags & TCF_SCSI_RATE];2214	if (host->msg[3] > MAX_OFFSET) {2215		host->msg[3] = MAX_OFFSET;2216		if (host->msg[2] < default_period) {2217			host->msg[2] = default_period;2218			return 1;2219		}2220		if (host->msg[2] >= 59)	/* Change to async              */2221			host->msg[3] = 0;2222		return 1;2223	}2224	/* offset requests asynchronous transfers ? */2225	if (host->msg[3] == 0) {2226		return 0;2227	}2228	if (host->msg[2] < default_period) {2229		host->msg[2] = default_period;2230		return 1;2231	}2232	if (host->msg[2] >= 59) {2233		host->msg[3] = 0;2234		return 1;2235	}2236	return 0;2237}2238 2239static int wdtr_done(struct initio_host * host)2240{2241	host->active_tc->flags &= ~TCF_SYNC_DONE;2242	host->active_tc->flags |= TCF_WDTR_DONE;2243 2244	host->active_tc->js_period = 0;2245	if (host->msg[2])	/* if 16 bit */2246		host->active_tc->js_period |= TSC_WIDE_SCSI;2247	host->active_tc->sconfig0 &= ~TSC_ALT_PERIOD;2248	outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);2249	outb(host->active_tc->js_period, host->addr + TUL_SPeriod);2250 2251	return 1;2252}2253 2254static int initio_sync_done(struct initio_host * host)2255{2256	int i;2257 2258	host->active_tc->flags |= TCF_SYNC_DONE;2259 2260	if (host->msg[3]) {2261		host->active_tc->js_period |= host->msg[3];2262		for (i = 0; i < 8; i++) {2263			if (initio_rate_tbl[i] >= host->msg[2])	/* pick the big one */2264				break;2265		}2266		host->active_tc->js_period |= (i << 4);2267		host->active_tc->sconfig0 |= TSC_ALT_PERIOD;2268	}2269	outb(host->active_tc->sconfig0, host->addr + TUL_SConfig);2270	outb(host->active_tc->js_period, host->addr + TUL_SPeriod);2271 2272	return -1;2273}2274 2275 2276static int initio_post_scsi_rst(struct initio_host * host)2277{2278	struct scsi_ctrl_blk *scb;2279	struct target_control *active_tc;2280	int i;2281 2282	host->active = NULL;2283	host->active_tc = NULL;2284	host->flags = 0;2285 2286	while ((scb = initio_pop_busy_scb(host)) != NULL) {2287		scb->hastat = HOST_BAD_PHAS;2288		initio_append_done_scb(host, scb);2289	}2290	/* clear sync done flag         */2291	active_tc = &host->targets[0];2292	for (i = 0; i < host->max_tar; active_tc++, i++) {2293		active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);2294		/* Initialize the sync. xfer register values to an asyn xfer */2295		active_tc->js_period = 0;2296		active_tc->sconfig0 = host->sconf1;2297		host->act_tags[0] = 0;	/* 07/22/98 */2298		host->targets[i].flags &= ~TCF_BUSY;	/* 07/22/98 */2299	}			/* for */2300 2301	return -1;2302}2303 2304static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb)2305{2306	scb->status |= SCB_SELECT;2307	scb->next_state = 0x1;2308	host->active = scb;2309	host->active_tc = &host->targets[scb->target];2310	outb(TSC_SELATNSTOP, host->addr + TUL_SCmd);2311}2312 2313 2314static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb)2315{2316	int i;2317 2318	scb->status |= SCB_SELECT;2319	scb->next_state = 0x2;2320 2321	outb(scb->ident, host->addr + TUL_SFifo);2322	for (i = 0; i < (int) scb->cdblen; i++)2323		outb(scb->cdb[i], host->addr + TUL_SFifo);2324	host->active_tc = &host->targets[scb->target];2325	host->active = scb;2326	outb(TSC_SEL_ATN, host->addr + TUL_SCmd);2327}2328 2329static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb)2330{2331	int i;2332 2333	scb->status |= SCB_SELECT;2334	scb->next_state = 0x2;2335 2336	outb(scb->ident, host->addr + TUL_SFifo);2337	outb(scb->tagmsg, host->addr + TUL_SFifo);2338	outb(scb->tagid, host->addr + TUL_SFifo);2339	for (i = 0; i < scb->cdblen; i++)2340		outb(scb->cdb[i], host->addr + TUL_SFifo);2341	host->active_tc = &host->targets[scb->target];2342	host->active = scb;2343	outb(TSC_SEL_ATN3, host->addr + TUL_SCmd);2344}2345 2346/**2347 *	initio_bus_device_reset	-	 SCSI Bus Device Reset2348 *	@host: InitIO host to reset2349 *2350 *	Perform a device reset and abort all pending SCBs for the2351 *	victim device2352 */2353int initio_bus_device_reset(struct initio_host * host)2354{2355	struct scsi_ctrl_blk *scb = host->active;2356	struct target_control *active_tc = host->active_tc;2357	struct scsi_ctrl_blk *tmp, *prev;2358	u8 tar;2359 2360	if (host->phase != MSG_OUT)2361		return int_initio_bad_seq(host);	/* Unexpected phase */2362 2363	initio_unlink_pend_scb(host, scb);2364	initio_release_scb(host, scb);2365 2366 2367	tar = scb->target;	/* target                       */2368	active_tc->flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);2369	/* clr sync. nego & WDTR flags  07/22/98 */2370 2371	/* abort all SCB with same target */2372	prev = tmp = host->first_busy;	/* Check Busy queue */2373	while (tmp != NULL) {2374		if (tmp->target == tar) {2375			/* unlink it */2376			if (tmp == host->first_busy) {2377				if ((host->first_busy = tmp->next) == NULL)2378					host->last_busy = NULL;2379			} else {2380				prev->next = tmp->next;2381				if (tmp == host->last_busy)2382					host->last_busy = prev;2383			}2384			tmp->hastat = HOST_ABORTED;2385			initio_append_done_scb(host, tmp);2386		}2387		/* Previous haven't change      */2388		else {2389			prev = tmp;2390		}2391		tmp = tmp->next;2392	}2393	outb(TARGET_RESET, host->addr + TUL_SFifo);2394	outb(TSC_XF_FIFO_OUT, host->addr + TUL_SCmd);2395	return initio_wait_disc(host);2396 2397}2398 2399static int initio_msgin_accept(struct initio_host * host)2400{2401	outb(TSC_MSG_ACCEPT, host->addr + TUL_SCmd);2402	return wait_tulip(host);2403}2404 2405static int wait_tulip(struct initio_host * host)2406{2407 2408	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))2409		 & TSS_INT_PENDING))2410			cpu_relax();2411 2412	host->jsint = inb(host->addr + TUL_SInt);2413	host->phase = host->jsstatus0 & TSS_PH_MASK;2414	host->jsstatus1 = inb(host->addr + TUL_SStatus1);2415 2416	if (host->jsint & TSS_RESEL_INT)	/* if SCSI bus reset detected */2417		return int_initio_resel(host);2418	if (host->jsint & TSS_SEL_TIMEOUT)	/* if selected/reselected timeout interrupt */2419		return int_initio_busfree(host);2420	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected   */2421		return int_initio_scsi_rst(host);2422 2423	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection            */2424		if (host->flags & HCF_EXPECT_DONE_DISC) {2425			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */2426			initio_unlink_busy_scb(host, host->active);2427			host->active->hastat = 0;2428			initio_append_done_scb(host, host->active);2429			host->active = NULL;2430			host->active_tc = NULL;2431			host->flags &= ~HCF_EXPECT_DONE_DISC;2432			outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);2433			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */2434			return -1;2435		}2436		if (host->flags & HCF_EXPECT_DISC) {2437			outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */2438			host->active = NULL;2439			host->active_tc = NULL;2440			host->flags &= ~HCF_EXPECT_DISC;2441			outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);2442			outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */2443			return -1;2444		}2445		return int_initio_busfree(host);2446	}2447	/* The old code really does the below. Can probably be removed */2448	if (host->jsint & (TSS_FUNC_COMP | TSS_BUS_SERV))2449		return host->phase;2450	return host->phase;2451}2452 2453static int initio_wait_disc(struct initio_host * host)2454{2455	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0)) & TSS_INT_PENDING))2456		cpu_relax();2457 2458	host->jsint = inb(host->addr + TUL_SInt);2459 2460	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected */2461		return int_initio_scsi_rst(host);2462	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection */2463		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); /* Flush SCSI FIFO */2464		outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);2465		outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);	/* Enable HW reselect */2466		host->active = NULL;2467		return -1;2468	}2469	return initio_bad_seq(host);2470}2471 2472static int initio_wait_done_disc(struct initio_host * host)2473{2474	while (!((host->jsstatus0 = inb(host->addr + TUL_SStatus0))2475		 & TSS_INT_PENDING))2476		 cpu_relax();2477 2478	host->jsint = inb(host->addr + TUL_SInt);2479 2480	if (host->jsint & TSS_SCSIRST_INT)	/* if SCSI bus reset detected */2481		return int_initio_scsi_rst(host);2482	if (host->jsint & TSS_DISC_INT) {	/* BUS disconnection */2483		outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0);		/* Flush SCSI FIFO */2484		outb(TSC_INITDEFAULT, host->addr + TUL_SConfig);2485		outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1);		/* Enable HW reselect */2486		initio_unlink_busy_scb(host, host->active);2487 2488		initio_append_done_scb(host, host->active);2489		host->active = NULL;2490		return -1;2491	}2492	return initio_bad_seq(host);2493}2494 2495/**2496 *	i91u_intr		-	IRQ handler2497 *	@irqno: IRQ number2498 *	@dev_id: IRQ identifier2499 *2500 *	Take the relevant locks and then invoke the actual isr processing2501 *	code under the lock.2502 */2503 2504static irqreturn_t i91u_intr(int irqno, void *dev_id)2505{2506	struct Scsi_Host *dev = dev_id;2507	unsigned long flags;2508	int r;2509	2510	spin_lock_irqsave(dev->host_lock, flags);2511	r = initio_isr((struct initio_host *)dev->hostdata);2512	spin_unlock_irqrestore(dev->host_lock, flags);2513	if (r)2514		return IRQ_HANDLED;2515	else2516		return IRQ_NONE;2517}2518 2519 2520/**2521 *	initio_build_scb		-	Build the mappings and SCB2522 *	@host: InitIO host taking the command2523 *	@cblk: Firmware command block2524 *	@cmnd: SCSI midlayer command block2525 *2526 *	Translate the abstract SCSI command into a firmware command block2527 *	suitable for feeding to the InitIO host controller. This also requires2528 *	we build the scatter gather lists and ensure they are mapped properly.2529 */2530 2531static void initio_build_scb(struct initio_host * host, struct scsi_ctrl_blk * cblk, struct scsi_cmnd * cmnd)2532{				/* Create corresponding SCB     */2533	struct scatterlist *sglist;2534	struct sg_entry *sg;		/* Pointer to SG list           */2535	int i, nseg;2536	long total_len;2537	dma_addr_t dma_addr;2538 2539	/* Fill in the command headers */2540	cblk->post = i91uSCBPost;	/* i91u's callback routine      */2541	cblk->srb = cmnd;2542	cblk->opcode = ExecSCSI;2543	cblk->flags = SCF_POST;	/* After SCSI done, call post routine */2544	cblk->target = cmnd->device->id;2545	cblk->lun = cmnd->device->lun;2546	cblk->ident = cmnd->device->lun | DISC_ALLOW;2547 2548	cblk->flags |= SCF_SENSE;	/* Turn on auto request sense   */2549 2550	/* Map the sense buffer into bus memory */2551	dma_addr = dma_map_single(&host->pci_dev->dev, cmnd->sense_buffer,2552				  SENSE_SIZE, DMA_FROM_DEVICE);2553	cblk->senseptr = (u32)dma_addr;2554	cblk->senselen = SENSE_SIZE;2555	initio_priv(cmnd)->sense_dma_addr = dma_addr;2556	cblk->cdblen = cmnd->cmd_len;2557 2558	/* Clear the returned status */2559	cblk->hastat = 0;2560	cblk->tastat = 0;2561	/* Command the command */2562	memcpy(cblk->cdb, cmnd->cmnd, cmnd->cmd_len);2563 2564	/* Set up tags */2565	if (cmnd->device->tagged_supported) {	/* Tag Support                  */2566		cblk->tagmsg = SIMPLE_QUEUE_TAG;	/* Do simple tag only   */2567	} else {2568		cblk->tagmsg = 0;	/* No tag support               */2569	}2570 2571	/* todo handle map_sg error */2572	nseg = scsi_dma_map(cmnd);2573	BUG_ON(nseg < 0);2574	if (nseg) {2575		dma_addr = dma_map_single(&host->pci_dev->dev, &cblk->sglist[0],2576					  sizeof(struct sg_entry) * TOTAL_SG_ENTRY,2577					  DMA_BIDIRECTIONAL);2578		cblk->bufptr = (u32)dma_addr;2579		initio_priv(cmnd)->sglist_dma_addr = dma_addr;2580 2581		cblk->sglen = nseg;2582 2583		cblk->flags |= SCF_SG;	/* Turn on SG list flag       */2584		total_len = 0;2585		sg = &cblk->sglist[0];2586		scsi_for_each_sg(cmnd, sglist, cblk->sglen, i) {2587			sg->data = cpu_to_le32((u32)sg_dma_address(sglist));2588			sg->len = cpu_to_le32((u32)sg_dma_len(sglist));2589			total_len += sg_dma_len(sglist);2590			++sg;2591		}2592 2593		cblk->buflen = (scsi_bufflen(cmnd) > total_len) ?2594			total_len : scsi_bufflen(cmnd);2595	} else {	/* No data transfer required */2596		cblk->buflen = 0;2597		cblk->sglen = 0;2598	}2599}2600 2601/**2602 *	i91u_queuecommand_lck	-	Queue a new command if possible2603 *	@cmd: SCSI command block from the mid layer2604 *2605 *	Attempts to queue a new command with the host adapter. Will return2606 *	zero if successful or indicate a host busy condition if not (which2607 *	will cause the mid layer to call us again later with the command)2608 */2609static int i91u_queuecommand_lck(struct scsi_cmnd *cmd)2610{2611	struct initio_host *host = (struct initio_host *) cmd->device->host->hostdata;2612	struct scsi_ctrl_blk *cmnd;2613 2614	cmnd = initio_alloc_scb(host);2615	if (!cmnd)2616		return SCSI_MLQUEUE_HOST_BUSY;2617 2618	initio_build_scb(host, cmnd, cmd);2619	initio_exec_scb(host, cmnd);2620	return 0;2621}2622 2623static DEF_SCSI_QCMD(i91u_queuecommand)2624 2625/**2626 *	i91u_bus_reset		-	reset the SCSI bus2627 *	@cmnd: Command block we want to trigger the reset for2628 *2629 *	Initiate a SCSI bus reset sequence2630 */2631 2632static int i91u_bus_reset(struct scsi_cmnd * cmnd)2633{2634	struct initio_host *host;2635 2636	host = (struct initio_host *) cmnd->device->host->hostdata;2637 2638	spin_lock_irq(cmnd->device->host->host_lock);2639	initio_reset_scsi(host, 0);2640	spin_unlock_irq(cmnd->device->host->host_lock);2641 2642	return SUCCESS;2643}2644 2645/**2646 *	i91u_biosparam			-	return the "logical geometry2647 *	@sdev: SCSI device2648 *	@dev: Matching block device2649 *	@capacity: Sector size of drive2650 *	@info_array: Return space for BIOS geometry2651 *2652 *	Map the device geometry in a manner compatible with the host2653 *	controller BIOS behaviour.2654 *2655 *	FIXME: limited to 2^32 sector devices.2656 */2657 2658static int i91u_biosparam(struct scsi_device *sdev, struct block_device *dev,2659		sector_t capacity, int *info_array)2660{2661	struct initio_host *host;		/* Point to Host adapter control block */2662	struct target_control *tc;2663 2664	host = (struct initio_host *) sdev->host->hostdata;2665	tc = &host->targets[sdev->id];2666 2667	if (tc->heads) {2668		info_array[0] = tc->heads;2669		info_array[1] = tc->sectors;2670		info_array[2] = (unsigned long)capacity / tc->heads / tc->sectors;2671	} else {2672		if (tc->drv_flags & TCF_DRV_255_63) {2673			info_array[0] = 255;2674			info_array[1] = 63;2675			info_array[2] = (unsigned long)capacity / 255 / 63;2676		} else {2677			info_array[0] = 64;2678			info_array[1] = 32;2679			info_array[2] = (unsigned long)capacity >> 11;2680		}2681	}2682 2683#if defined(DEBUG_BIOSPARAM)2684	if (i91u_debug & debug_biosparam) {2685		printk("bios geometry: head=%d, sec=%d, cyl=%d\n",2686		       info_array[0], info_array[1], info_array[2]);2687		printk("WARNING: check, if the bios geometry is correct.\n");2688	}2689#endif2690 2691	return 0;2692}2693 2694/**2695 *	i91u_unmap_scb		-	Unmap a command2696 *	@pci_dev: PCI device the command is for2697 *	@cmnd: The command itself2698 *2699 *	Unmap any PCI mapping/IOMMU resources allocated when the command2700 *	was mapped originally as part of initio_build_scb2701 */2702 2703static void i91u_unmap_scb(struct pci_dev *pci_dev, struct scsi_cmnd *cmnd)2704{2705	/* auto sense buffer */2706	if (initio_priv(cmnd)->sense_dma_addr) {2707		dma_unmap_single(&pci_dev->dev,2708				 initio_priv(cmnd)->sense_dma_addr,2709				 SENSE_SIZE, DMA_FROM_DEVICE);2710		initio_priv(cmnd)->sense_dma_addr = 0;2711	}2712 2713	/* request buffer */2714	if (scsi_sg_count(cmnd)) {2715		dma_unmap_single(&pci_dev->dev,2716				 initio_priv(cmnd)->sglist_dma_addr,2717				 sizeof(struct sg_entry) * TOTAL_SG_ENTRY,2718				 DMA_BIDIRECTIONAL);2719 2720		scsi_dma_unmap(cmnd);2721	}2722}2723 2724/*2725 *	i91uSCBPost		-	SCSI callback2726 *2727 *	This is callback routine be called when tulip finish one2728 *	SCSI command.2729 */2730 2731static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem)2732{2733	struct scsi_cmnd *cmnd;	/* Pointer to SCSI request block */2734	struct initio_host *host;2735	struct scsi_ctrl_blk *cblk;2736 2737	host = (struct initio_host *) host_mem;2738	cblk = (struct scsi_ctrl_blk *) cblk_mem;2739	if ((cmnd = cblk->srb) == NULL) {2740		printk(KERN_ERR "i91uSCBPost: SRB pointer is empty\n");2741		WARN_ON(1);2742		initio_release_scb(host, cblk);	/* Release SCB for current channel */2743		return;2744	}2745 2746	/*2747	 *	Remap the firmware error status into a mid layer one2748	 */2749	switch (cblk->hastat) {2750	case 0x0:2751	case 0xa:		/* Linked command complete without error and linked normally */2752	case 0xb:		/* Linked command complete without error interrupt generated */2753		cblk->hastat = 0;2754		break;2755 2756	case 0x11:		/* Selection time out-The initiator selection or target2757				   reselection was not complete within the SCSI Time out period */2758		cblk->hastat = DID_TIME_OUT;2759		break;2760 2761	case 0x14:		/* Target bus phase sequence failure-An invalid bus phase or bus2762				   phase sequence was requested by the target. The host adapter2763				   will generate a SCSI Reset Condition, notifying the host with2764				   a SCRD interrupt */2765		cblk->hastat = DID_RESET;2766		break;2767 2768	case 0x1a:		/* SCB Aborted. 07/21/98 */2769		cblk->hastat = DID_ABORT;2770		break;2771 2772	case 0x12:		/* Data overrun/underrun-The target attempted to transfer more data2773				   than was allocated by the Data Length field or the sum of the2774				   Scatter / Gather Data Length fields. */2775	case 0x13:		/* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */2776	case 0x16:		/* Invalid SCB Operation Code. */2777 2778	default:2779		printk("ini9100u: %x %x\n", cblk->hastat, cblk->tastat);2780		cblk->hastat = DID_ERROR;	/* Couldn't find any better */2781		break;2782	}2783 2784	cmnd->result = cblk->tastat | (cblk->hastat << 16);2785	i91u_unmap_scb(host->pci_dev, cmnd);2786	scsi_done(cmnd);	/* Notify system DONE           */2787	initio_release_scb(host, cblk);	/* Release SCB for current channel */2788}2789 2790static const struct scsi_host_template initio_template = {2791	.proc_name		= "INI9100U",2792	.name			= "Initio INI-9X00U/UW SCSI device driver",2793	.queuecommand		= i91u_queuecommand,2794	.eh_bus_reset_handler	= i91u_bus_reset,2795	.bios_param		= i91u_biosparam,2796	.can_queue		= MAX_TARGETS * i91u_MAXQUEUE,2797	.this_id		= 1,2798	.sg_tablesize		= SG_ALL,2799	.cmd_size		= sizeof(struct initio_cmd_priv),2800};2801 2802static int initio_probe_one(struct pci_dev *pdev,2803	const struct pci_device_id *id)2804{2805	struct Scsi_Host *shost;2806	struct initio_host *host;2807	u32 reg;2808	u16 bios_seg;2809	struct scsi_ctrl_blk *scb, *tmp, *prev = NULL /* silence gcc */;2810	int num_scb, i, error;2811 2812	error = pci_enable_device(pdev);2813	if (error)2814		return error;2815 2816	pci_read_config_dword(pdev, 0x44, (u32 *) & reg);2817	bios_seg = (u16) (reg & 0xFF);2818	if (((reg & 0xFF00) >> 8) == 0xFF)2819		reg = 0;2820	bios_seg = (bios_seg << 8) + ((u16) ((reg & 0xFF00) >> 8));2821 2822	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {2823		printk(KERN_WARNING  "i91u: Could not set 32 bit DMA mask\n");2824		error = -ENODEV;2825		goto out_disable_device;2826	}2827	shost = scsi_host_alloc(&initio_template, sizeof(struct initio_host));2828	if (!shost) {2829		printk(KERN_WARNING "initio: Could not allocate host structure.\n");2830		error = -ENOMEM;2831		goto out_disable_device;2832	}2833	host = (struct initio_host *)shost->hostdata;2834	memset(host, 0, sizeof(struct initio_host));2835	host->addr = pci_resource_start(pdev, 0);2836	host->bios_addr = bios_seg;2837 2838	if (!request_region(host->addr, 256, "i91u")) {2839		printk(KERN_WARNING "initio: I/O port range 0x%x is busy.\n", host->addr);2840		error = -ENODEV;2841		goto out_host_put;2842	}2843 2844	if (initio_tag_enable)	/* 1.01i */2845		num_scb = MAX_TARGETS * i91u_MAXQUEUE;2846	else2847		num_scb = MAX_TARGETS + 3;	/* 1-tape, 1-CD_ROM, 1- extra */2848 2849	for (; num_scb >= MAX_TARGETS + 3; num_scb--) {2850		i = num_scb * sizeof(struct scsi_ctrl_blk);2851		scb = kzalloc(i, GFP_KERNEL);2852		if (scb)2853			break;2854	}2855 2856	if (!scb) {2857		printk(KERN_WARNING "initio: Cannot allocate SCB array.\n");2858		error = -ENOMEM;2859		goto out_release_region;2860	}2861 2862	host->pci_dev = pdev;2863 2864	host->semaph = 1;2865	spin_lock_init(&host->semaph_lock);2866	host->num_scbs = num_scb;2867	host->scb = scb;2868	host->next_pending = scb;2869	host->next_avail = scb;2870	for (i = 0, tmp = scb; i < num_scb; i++, tmp++) {2871		tmp->tagid = i;2872		if (i != 0)2873			prev->next = tmp;2874		prev = tmp;2875	}2876	prev->next = NULL;2877	host->scb_end = tmp;2878	host->first_avail = scb;2879	host->last_avail = prev;2880	spin_lock_init(&host->avail_lock);2881 2882	initio_init(host, phys_to_virt(((u32)bios_seg << 4)));2883 2884	host->jsstatus0 = 0;2885 2886	shost->io_port = host->addr;2887	shost->n_io_port = 0xff;2888	shost->can_queue = num_scb;		/* 03/05/98                      */2889	shost->unique_id = host->addr;2890	shost->max_id = host->max_tar;2891	shost->max_lun = 32;	/* 10/21/97                     */2892	shost->irq = pdev->irq;2893	shost->this_id = host->scsi_id;	/* Assign HCS index           */2894	shost->base = host->addr;2895	shost->sg_tablesize = TOTAL_SG_ENTRY;2896 2897	error = request_irq(pdev->irq, i91u_intr, IRQF_SHARED, "i91u", shost);2898	if (error < 0) {2899		printk(KERN_WARNING "initio: Unable to request IRQ %d\n", pdev->irq);2900		goto out_free_scbs;2901	}2902 2903	pci_set_drvdata(pdev, shost);2904 2905	error = scsi_add_host(shost, &pdev->dev);2906	if (error)2907		goto out_free_irq;2908	scsi_scan_host(shost);2909	return 0;2910out_free_irq:2911	free_irq(pdev->irq, shost);2912out_free_scbs:2913	kfree(host->scb);2914out_release_region:2915	release_region(host->addr, 256);2916out_host_put:2917	scsi_host_put(shost);2918out_disable_device:2919	pci_disable_device(pdev);2920	return error;2921}2922 2923/**2924 *	initio_remove_one	-	control shutdown2925 *	@pdev:	PCI device being released2926 *2927 *	Release the resources assigned to this adapter after it has2928 *	finished being used.2929 */2930 2931static void initio_remove_one(struct pci_dev *pdev)2932{2933	struct Scsi_Host *host = pci_get_drvdata(pdev);2934	struct initio_host *s = (struct initio_host *)host->hostdata;2935	scsi_remove_host(host);2936	free_irq(pdev->irq, host);2937	release_region(s->addr, 256);2938	scsi_host_put(host);2939	pci_disable_device(pdev);2940}2941 2942MODULE_LICENSE("GPL");2943 2944static struct pci_device_id initio_pci_tbl[] = {2945	{PCI_VENDOR_ID_INIT, 0x9500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2946	{PCI_VENDOR_ID_INIT, 0x9400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2947	{PCI_VENDOR_ID_INIT, 0x9401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2948	{PCI_VENDOR_ID_INIT, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2949	{PCI_VENDOR_ID_DOMEX, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},2950	{0,}2951};2952MODULE_DEVICE_TABLE(pci, initio_pci_tbl);2953 2954static struct pci_driver initio_pci_driver = {2955	.name		= "initio",2956	.id_table	= initio_pci_tbl,2957	.probe		= initio_probe_one,2958	.remove		= initio_remove_one,2959};2960module_pci_driver(initio_pci_driver);2961 2962MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");2963MODULE_AUTHOR("Initio Corporation");2964MODULE_LICENSE("GPL");2965