cregit-Linux how code gets into the kernel

Release 4.11 drivers/scsi/initio.c

Directory: drivers/scsi
/**************************************************************************
 * Initio 9100 device driver for Linux.
 *
 * Copyright (c) 1994-1998 Initio Corporation
 * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
 * Copyright (c) 2004 Christoph Hellwig <hch@lst.de>
 * Copyright (c) 2007 Red Hat
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 *************************************************************************
 *
 * DESCRIPTION:
 *
 * This is the Linux low-level SCSI driver for Initio INI-9X00U/UW SCSI host
 * adapters
 *
 * 08/06/97 hc  - v1.01h
 *              - Support inic-940 and inic-935
 * 09/26/97 hc  - v1.01i
 *              - Make correction from J.W. Schultz suggestion
 * 10/13/97 hc  - Support reset function
 * 10/21/97 hc  - v1.01j
 *              - Support 32 LUN (SCSI 3)
 * 01/14/98 hc  - v1.01k
 *              - Fix memory allocation problem
 * 03/04/98 hc  - v1.01l
 *              - Fix tape rewind which will hang the system problem
 *              - Set can_queue to initio_num_scb
 * 06/25/98 hc  - v1.01m
 *              - Get it work for kernel version >= 2.1.75
 *              - Dynamic assign SCSI bus reset holding time in initio_init()
 * 07/02/98 hc  - v1.01n
 *              - Support 0002134A
 * 08/07/98 hc  - v1.01o
 *              - Change the initio_abort_srb routine to use scsi_done. <01>
 * 09/07/98 hl  - v1.02
 *              - Change the INI9100U define and proc_dir_entry to
 *                reflect the newer Kernel 2.1.118, but the v1.o1o
 *                should work with Kernel 2.1.118.
 * 09/20/98 wh  - v1.02a
 *              - Support Abort command.
 *              - Handle reset routine.
 * 09/21/98 hl  - v1.03
 *              - remove comments.
 * 12/09/98 bv  - v1.03a
 *              - Removed unused code
 * 12/13/98 bv  - v1.03b
 *              - Remove cli() locking for kernels >= 2.1.95. This uses
 *                spinlocks to serialize access to the pSRB_head and
 *                pSRB_tail members of the HCS structure.
 * 09/01/99 bv  - v1.03d
 *              - Fixed a deadlock problem in SMP.
 * 21/01/99 bv  - v1.03e
 *              - Add support for the Domex 3192U PCI SCSI
 *                This is a slightly modified patch by
 *                Brian Macy <bmacy@sunshinecomputing.com>
 * 22/02/99 bv  - v1.03f
 *              - Didn't detect the INIC-950 in 2.0.x correctly.
 *                Now fixed.
 * 05/07/99 bv  - v1.03g
 *              - Changed the assumption that HZ = 100
 * 10/17/03 mc  - v1.04
 *              - added new DMA API support
 * 06/01/04 jmd - v1.04a
 *              - Re-add reset_bus support
 **************************************************************************/

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/spinlock.h>
#include <linux/stat.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>

#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>

#include "initio.h"


#define SENSE_SIZE		14


#define i91u_MAXQUEUE		2

#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a"

#ifdef DEBUG_i91u

static unsigned int i91u_debug = DEBUG_DEFAULT;
#endif


static int initio_tag_enable = 1;

#ifdef DEBUG_i91u

static int setup_debug = 0;
#endif

static void i91uSCBPost(u8 * pHcb, u8 * pScb);


#define DEBUG_INTERRUPT 0

#define DEBUG_QUEUE     0

#define DEBUG_STATE     0

#define INT_DISC	0

/*--- forward references ---*/
static struct scsi_ctrl_blk *initio_find_busy_scb(struct initio_host * host, u16 tarlun);
static struct scsi_ctrl_blk *initio_find_done_scb(struct initio_host * host);

static int tulip_main(struct initio_host * host);

static int initio_next_state(struct initio_host * host);
static int initio_state_1(struct initio_host * host);
static int initio_state_2(struct initio_host * host);
static int initio_state_3(struct initio_host * host);
static int initio_state_4(struct initio_host * host);
static int initio_state_5(struct initio_host * host);
static int initio_state_6(struct initio_host * host);
static int initio_state_7(struct initio_host * host);
static int initio_xfer_data_in(struct initio_host * host);
static int initio_xfer_data_out(struct initio_host * host);
static int initio_xpad_in(struct initio_host * host);
static int initio_xpad_out(struct initio_host * host);
static int initio_status_msg(struct initio_host * host);

static int initio_msgin(struct initio_host * host);
static int initio_msgin_sync(struct initio_host * host);
static int initio_msgin_accept(struct initio_host * host);
static int initio_msgout_reject(struct initio_host * host);
static int initio_msgin_extend(struct initio_host * host);

static int initio_msgout_ide(struct initio_host * host);
static int initio_msgout_abort_targ(struct initio_host * host);
static int initio_msgout_abort_tag(struct initio_host * host);

static int initio_bus_device_reset(struct initio_host * host);
static void initio_select_atn(struct initio_host * host, struct scsi_ctrl_blk * scb);
static void initio_select_atn3(struct initio_host * host, struct scsi_ctrl_blk * scb);
static void initio_select_atn_stop(struct initio_host * host, struct scsi_ctrl_blk * scb);
static int int_initio_busfree(struct initio_host * host);
static int int_initio_scsi_rst(struct initio_host * host);
static int int_initio_bad_seq(struct initio_host * host);
static int int_initio_resel(struct initio_host * host);
static int initio_sync_done(struct initio_host * host);
static int wdtr_done(struct initio_host * host);
static int wait_tulip(struct initio_host * host);
static int initio_wait_done_disc(struct initio_host * host);
static int initio_wait_disc(struct initio_host * host);
static void tulip_scsi(struct initio_host * host);
static int initio_post_scsi_rst(struct initio_host * host);

static void initio_se2_ew_en(unsigned long base);
static void initio_se2_ew_ds(unsigned long base);
static int initio_se2_rd_all(unsigned long base);
static void initio_se2_update_all(unsigned long base);	/* setup default pattern */
static void initio_read_eeprom(unsigned long base);

/* ---- INTERNAL VARIABLES ---- */


static NVRAM i91unvram;

static NVRAM *i91unvramp;


static u8 i91udftNvRam[64] =
{
	/*----------- header -----------*/
	0x25, 0xc9,		/* Signature    */
	0x40,			/* Size         */
	0x01,			/* Revision     */
	/* -- Host Adapter Structure -- */
	0x95,			/* ModelByte0   */
	0x00,			/* ModelByte1   */
	0x00,			/* ModelInfo    */
	0x01,			/* NumOfCh      */
	NBC1_DEFAULT,		/* BIOSConfig1  */
	0,			/* BIOSConfig2  */
	0,			/* HAConfig1    */
	0,			/* HAConfig2    */
	/* SCSI channel 0 and target Structure  */
	7,			/* SCSIid       */
	NCC1_DEFAULT,		/* SCSIconfig1  */
	0,			/* SCSIconfig2  */
	0x10,			/* NumSCSItarget */

	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,

	/* SCSI channel 1 and target Structure  */
	7,			/* SCSIid       */
	NCC1_DEFAULT,		/* SCSIconfig1  */
	0,			/* SCSIconfig2  */
	0x10,			/* NumSCSItarget */

	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0};			/*      - CheckSum -            */



static u8 initio_rate_tbl[8] =	/* fast 20      */
{
				/* nanosecond divide by 4 */
	12,			/* 50ns,  20M   */
	18,			/* 75ns,  13.3M */
	25,			/* 100ns, 10M   */
	31,			/* 125ns, 8M    */
	37,			/* 150ns, 6.6M  */
	43,			/* 175ns, 5.7M  */
	50,			/* 200ns, 5M    */
	62			/* 250ns, 4M    */
};


static void initio_do_pause(unsigned amount) { /* Pause for amount jiffies */ unsigned long the_time = jiffies + amount; while (time_before_eq(jiffies, the_time)) cpu_relax(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2686.67%266.67%
Alan Cox413.33%133.33%
Total30100.00%3100.00%

/*-- forward reference --*/ /****************************************************************** Input: instruction for Serial E2PROM EX: se2_rd(0 call se2_instr() to send address and read command StartBit OP_Code Address Data --------- -------- ------------------ ------- 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0 +----------------------------------------------------- | CS -----+ +--+ +--+ +--+ +--+ +--+ ^ | ^ | ^ | ^ | ^ | | | | | | | | | | | CLK -------+ +--+ +--+ +--+ +--+ +-- (leading edge trigger) +--1-----1--+ | SB OP | OP A5 A4 DI ----+ +--0------------------ (address and cmd sent to nvram) -------------------------------------------+ | DO +--- (data sent from nvram) ******************************************************************/ /** * initio_se2_instr - bitbang an instruction * @base: Base of InitIO controller * @instr: Instruction for serial E2PROM * * Bitbang an instruction out to the serial E2Prom */
static void initio_se2_instr(unsigned long base, u8 instr) { int i; u8 b; outb(SE2CS | SE2DO, base + TUL_NVRAM); /* cs+start bit */ udelay(30); outb(SE2CS | SE2CLK | SE2DO, base + TUL_NVRAM); /* +CLK */ udelay(30); for (i = 0; i < 8; i++) { if (instr & 0x80) b = SE2CS | SE2DO; /* -CLK+dataBit */ else b = SE2CS; /* -CLK */ outb(b, base + TUL_NVRAM); udelay(30); outb(b | SE2CLK, base + TUL_NVRAM); /* +CLK */ udelay(30); instr <<= 1; } outb(SE2CS, base + TUL_NVRAM); /* -CLK */ udelay(30); }

Contributors

PersonTokensPropCommitsCommitProp
Alan Cox7352.52%133.33%
Linus Torvalds (pre-git)6446.04%133.33%
Al Viro21.44%133.33%
Total139100.00%3100.00%

/** * initio_se2_ew_en - Enable erase/write * @base: Base address of InitIO controller * * Enable erase/write state of serial EEPROM */
void initio_se2_ew_en(unsigned long base) { initio_se2_instr(base, 0x30); /* EWEN */ outb(0, base + TUL_NVRAM); /* -CS */ udelay(30); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1856.25%150.00%
Alan Cox1443.75%150.00%
Total32100.00%2100.00%

/** * initio_se2_ew_ds - Disable erase/write * @base: Base address of InitIO controller * * Disable erase/write state of serial EEPROM */
void initio_se2_ew_ds(unsigned long base) { initio_se2_instr(base, 0); /* EWDS */ outb(0, base + TUL_NVRAM); /* -CS */ udelay(30); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1856.25%150.00%
Alan Cox1443.75%150.00%
Total32100.00%2100.00%

/** * initio_se2_rd - read E2PROM word * @base: Base of InitIO controller * @addr: Address of word in E2PROM * * Read a word from the NV E2PROM device */
static u16 initio_se2_rd(unsigned long base, u8 addr) { u8 instr, rb; u16 val = 0; int i; instr = (u8) (addr | 0x80); initio_se2_instr(base, instr); /* READ INSTR */ for (i = 15; i >= 0; i--) { outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */ udelay(30); outb(SE2CS, base + TUL_NVRAM); /* -CLK */ /* sample data after the following edge of clock */ rb = inb(base + TUL_NVRAM); rb &= SE2DI; val += (rb << i); udelay(30); /* 6/20/95 */ } outb(0, base + TUL_NVRAM); /* no chip select */ udelay(30); return val; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)8261.65%133.33%
Alan Cox5037.59%133.33%
Adrian Bunk10.75%133.33%
Total133100.00%3100.00%

/** * initio_se2_wr - read E2PROM word * @base: Base of InitIO controller * @addr: Address of word in E2PROM * @val: Value to write * * Write a word to the NV E2PROM device. Used when recovering from * a problem with the NV. */
static void initio_se2_wr(unsigned long base, u8 addr, u16 val) { u8 rb; u8 instr; int i; instr = (u8) (addr | 0x40); initio_se2_instr(base, instr); /* WRITE INSTR */ for (i = 15; i >= 0; i--) { if (val & 0x8000) outb(SE2CS | SE2DO, base + TUL_NVRAM); /* -CLK+dataBit 1 */ else outb(SE2CS, base + TUL_NVRAM); /* -CLK+dataBit 0 */ udelay(30); outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */ udelay(30); val <<= 1; } outb(SE2CS, base + TUL_NVRAM); /* -CLK */ udelay(30); outb(0, base + TUL_NVRAM); /* -CS */ udelay(30); outb(SE2CS, base + TUL_NVRAM); /* +CS */ udelay(30); for (;;) { outb(SE2CS | SE2CLK, base + TUL_NVRAM); /* +CLK */ udelay(30); outb(SE2CS, base + TUL_NVRAM); /* -CLK */ udelay(30); if ((rb = inb(base + TUL_NVRAM)) & SE2DI) break; /* write complete */ } outb(0, base + TUL_NVRAM); /* -CS */ }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13660.44%133.33%
Alan Cox8839.11%133.33%
Adrian Bunk10.44%133.33%
Total225100.00%3100.00%

/** * initio_se2_rd_all - read hostadapter NV configuration * @base: Base address of InitIO controller * * Reads the E2PROM data into main memory. Ensures that the checksum * and header marker are valid. Returns 1 on success -1 on error. */
static int initio_se2_rd_all(unsigned long base) { int i; u16 chksum = 0; u16 *np; i91unvramp = &i91unvram; np = (u16 *) i91unvramp; for (i = 0; i < 32; i++) *np++ = initio_se2_rd(base, i); /* Is signature "ini" ok ? */ if (i91unvramp->NVM_Signature != INI_SIGNATURE) return -1; /* Is ckecksum ok ? */ np = (u16 *) i91unvramp; for (i = 0; i < 31; i++) chksum += *np++; if (i91unvramp->NVM_CheckSum != chksum) return -1; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)10288.70%150.00%
Alan Cox1311.30%150.00%
Total115100.00%2100.00%

/** * initio_se2_update_all - Update E2PROM * @base: Base of InitIO controller * * Update the E2PROM by wrting any changes into the E2PROM * chip, rewriting the checksum. */
static void initio_se2_update_all(unsigned long base) { /* setup default pattern */ int i; u16 chksum = 0; u16 *np, *np1; i91unvramp = &i91unvram; /* Calculate checksum first */ np = (u16 *) i91udftNvRam; for (i = 0; i < 31; i++) chksum += *np++; *np = chksum; initio_se2_ew_en(base); /* Enable write */ np = (u16 *) i91udftNvRam; np1 = (u16 *) i91unvramp; for (i = 0; i < 32; i++, np++, np1++) { if (*np != *np1) initio_se2_wr(base, i, *np); } initio_se2_ew_ds(base); /* Disable write */ }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)11587.79%150.00%
Alan Cox1612.21%150.00%
Total131100.00%2100.00%

/** * initio_read_eeprom - Retrieve configuration * @base: Base of InitIO Host Adapter * * Retrieve the host adapter configuration data from E2Prom. If the * data is invalid then the defaults are used and are also restored * into the E2PROM. This forms the access point for the SCSI driver * into the E2PROM layer, the other functions for the E2PROM are all * internal use. * * Must be called single threaded, uses a shared global area. */
static void initio_read_eeprom(unsigned long base) { u8 gctrl; i91unvramp = &i91unvram; /* Enable EEProm programming */ gctrl = inb(base + TUL_GCTRL); outb(gctrl | TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL); if (initio_se2_rd_all(base) != 1) { initio_se2_update_all(base); /* setup default pattern */ initio_se2_rd_all(base); /* load again */ } /* Disable EEProm programming */ gctrl = inb(base + TUL_GCTRL); outb(gctrl & ~TUL_GCTRL_EEPROM_BIT, base + TUL_GCTRL); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5464.29%150.00%
Alan Cox3035.71%150.00%
Total84100.00%2100.00%

/** * initio_stop_bm - stop bus master * @host: InitIO we are stopping * * Stop any pending DMA operation, aborting the DMA if necessary */
static void initio_stop_bm(struct initio_host * host) { if (inb(host->addr + TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ outb(TAX_X_ABT | TAX_X_CLR_FIFO, host->addr + TUL_XCmd); /* wait Abort DMA xfer done */ while ((inb(host->addr + TUL_Int) & XABT) == 0) cpu_relax(); } outb(TSC_FLUSH_FIFO, host->addr + TUL_SCtrl0); }

Contributors

PersonTokensPropCommitsCommitProp
Alan Cox5981.94%125.00%
Linus Torvalds (pre-git)1216.67%250.00%
Adrian Bunk11.39%125.00%
Total72100.00%4100.00%

/** * initio_reset_scsi - Reset SCSI host controller * @host: InitIO host to reset * @seconds: Recovery time * * Perform a full reset of the SCSI subsystem. */
static int initio_reset_scsi(struct initio_host * host, int seconds) { outb(TSC_RST_BUS, host->addr + TUL_SCtrl0); while (!((host->jsint = inb(host->addr + TUL_SInt)) & TSS_SCSIRST_INT)) cpu_relax(); /* reset tulip chip */ outb(0, host->addr + TUL_SSignal); /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */ /* SONY 5200 tape drive won't work if only stall for 1 sec */ /* FIXME: this is a very long busy wait right now */ initio_do_pause(seconds * HZ); inb(host->addr + TUL_SInt); return SCSI_RESET_SUCCESS; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4857.14%266.67%
Alan Cox3642.86%133.33%
Total84100.00%3100.00%

/** * initio_init - set up an InitIO host adapter * @host: InitIO host adapter * @num_scbs: Number of SCBS * @bios_addr: BIOS address * * Set up the host adapter and devices according to the configuration * retrieved from the E2PROM. * * Locking: Calls E2PROM layer code which is not re-enterable so must * run single threaded for now. */
static void initio_init(struct initio_host * host, u8 *bios_addr) { int i; u8 *flags; u8 *heads; /* Get E2Prom configuration */ initio_read_eeprom(host->addr); if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8) host->max_tar = 8; else host->max_tar = 16; host->config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1; host->scsi_id = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID; host->idmask = ~(1 << host->scsi_id); #ifdef CHK_PARITY /* Enable parity error response */ outb(inb(host->addr + TUL_PCMD) | 0x40, host->addr + TUL_PCMD); #endif /* Mask all the interrupt */ outb(0x1F, host->addr + TUL_Mask); initio_stop_bm(host); /* --- Initialize the tulip --- */ outb(TSC_RST_CHIP, host->addr + TUL_SCtrl0); /* program HBA's SCSI ID */ outb(host->scsi_id << 4, host->addr + TUL_SScsiId); /* Enable Initiator Mode ,phase latch,alternate sync period mode, disable SCSI reset */ if (host->config & HCC_EN_PAR) host->sconf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR); else host->sconf1 = (TSC_INITDEFAULT); outb(host->sconf1, host->addr + TUL_SConfig); /* Enable HW reselect */ outb(TSC_HW_RESELECT, host->addr + TUL_SCtrl1); outb(0, host->addr + TUL_SPeriod); /* selection time out = 250 ms */ outb(153, host->addr + TUL_STimeOut); /* Enable SCSI terminator */ outb((host->config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)), host->addr + TUL_XCtrl); outb(((host->config & HCC_AUTO_TERM) >> 4) | (inb(host->addr + TUL_GCTRL1) & 0xFE), host->addr + TUL_GCTRL1); for (i = 0, flags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config), heads = bios_addr + 0x180; i < host->max_tar; i++, flags++) { host->targets[i].flags = *flags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE); if (host->targets[i].flags & TCF_EN_255) host->targets[i].drv_flags = TCF_DRV_255_63; else host->targets[i].drv_flags = 0; host->targets[i].js_period = 0; host->targets[i].sconfig0 = host->sconf1; host->targets[i].heads = *heads++; if (host->targets[i].heads == 255) host->targets[i].drv_flags = TCF_DRV_255_63; else host->targets[i].drv_flags = 0; host->targets[i].sectors = *heads++; host->targets[i].flags &= ~TCF_BUSY; host->act_tags[i] = 0; host->max_tags[i] = 0xFF; } /* for */ printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n", host->addr, host->pci_dev->irq, host->bios_addr, host->scsi_id); /* Reset SCSI Bus */ if (host->config & HCC_SCSI_RESET) { printk(KERN_INFO "i91u: Reset SCSI Bus ... \n"); initio_reset_scsi(host, 10); } outb(0x17, host->addr + TUL_SCFG1); outb(0xE9, host->addr + TUL_SIntEnable); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)39167.07%120.00%
Alan Cox18932.42%240.00%
Olaf Hering20.34%120.00%
Adrian Bunk10.17%120.00%
Total583100.00%5100.00%

/** * initio_alloc_scb - Allocate an SCB * @host: InitIO host we are allocating for * * Walk the SCB list for the controller and allocate a free SCB if * one exists. */
static struct scsi_ctrl_blk *initio_alloc_scb(struct initio_host *host) { struct scsi_ctrl_blk *scb; unsigned long flags; spin_lock_irqsave(&host->avail_lock, flags); if ((scb = host->first_avail) != NULL) { #if DEBUG_QUEUE printk("find scb at %p\n", scb); #endif if ((host->first_avail = scb->next) == NULL) host->last_avail = NULL; scb->next = NULL; scb->status = SCB_RENT; } spin_unlock_irqrestore(&host->avail_lock, flags); return scb; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7168.93%133.33%
Alan Cox3130.10%133.33%
Adrian Bunk10.97%133.33%
Total103100.00%3100.00%

/** * initio_release_scb - Release an SCB * @host: InitIO host that owns the SCB * @cmnd: SCB command block being returned * * Return an allocated SCB to the host free list */
static void initio_release_scb(struct initio_host * host, struct scsi_ctrl_blk * cmnd) { unsigned long flags; #if DEBUG_QUEUE printk("Release SCB %p; ", cmnd); #endif spin_lock_irqsave(&(host->avail_lock), flags); cmnd->srb = NULL; cmnd->status = 0; cmnd->next = NULL; if (host->last_avail != NULL) { host->last_avail->next = cmnd; host->last_avail = cmnd; } else { host->first_avail = cmnd; host->last_avail = cmnd; } spin_unlock_irqrestore(&(host->avail_lock), flags); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7566.37%125.00%
Alan Cox3631.86%125.00%
Adrian Bunk10.88%125.00%
Al Viro10.88%125.00%
Total113100.00%4100.00%

/***************************************************************************/
static void initio_append_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp) { #if DEBUG_QUEUE printk("Append pend SCB %p; ", scbp); #endif scbp->status = SCB_PEND; scbp->next = NULL; if (host->last_pending != NULL) { host->last_pending->next = scbp; host->last_pending = scbp; } else { host->first_pending = scbp; host->last_pending = scbp; } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5873.42%133.33%
Alan Cox2025.32%133.33%
Adrian Bunk11.27%133.33%
Total79100.00%3100.00%

/***************************************************************************/
static void initio_push_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scbp) { #if DEBUG_QUEUE printk("Push pend SCB %p; ", scbp); #endif scbp->status = SCB_PEND; if ((scbp->next = host->first_pending) != NULL) { host->first_pending = scbp; } else { host->first_pending = scbp; host->last_pending = scbp; } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5374.65%133.33%
Alan Cox1723.94%133.33%
Adrian Bunk11.41%133.33%
Total71100.00%3100.00%


static struct scsi_ctrl_blk *initio_find_first_pend_scb(struct initio_host * host) { struct scsi_ctrl_blk *first; first = host->first_pending; while (first != NULL) { if (first->opcode != ExecSCSI) return first; if (first->tagmsg == 0) { if ((host->act_tags[first->target] == 0) && !(host->targets[first->target].flags & TCF_BUSY)) return first; } else { if ((host->act_tags[first->target] >= host->max_tags[first->target]) | (host->targets[first->target].flags & TCF_BUSY)) { first = first->next; continue; } return first; } first = first->next; } return first; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)9866.22%133.33%
Alan Cox4933.11%133.33%
Adrian Bunk10.68%133.33%
Total148100.00%3100.00%


static void initio_unlink_pend_scb(struct initio_host * host, struct scsi_ctrl_blk * scb) { struct scsi_ctrl_blk *tmp, *prev; #if DEBUG_QUEUE printk("unlink pend SCB %p; ", scb);