Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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