cregit-Linux how code gets into the kernel

Release 4.11 drivers/scsi/dc395x.c

Directory: drivers/scsi
/*
 * dc395x.c
 *
 * Device Driver for Tekram DC395(U/UW/F), DC315(U)
 * PCI SCSI Bus Master Host Adapter
 * (SCSI chip set used Tekram ASIC TRM-S1040)
 *
 * Authors:
 *  C.L. Huang <ching@tekram.com.tw>
 *  Erich Chen <erich@tekram.com.tw>
 *  (C) Copyright 1995-1999 Tekram Technology Co., Ltd.
 *
 *  Kurt Garloff <garloff@suse.de>
 *  (C) 1999-2000 Kurt Garloff
 *
 *  Oliver Neukum <oliver@neukum.name>
 *  Ali Akcaagac <aliakc@web.de>
 *  Jamie Lenehan <lenehan@twibble.org>
 *  (C) 2003
 *
 * License: GNU GPL
 *
 *************************************************************************
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ************************************************************************
 */
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/list.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <asm/io.h>

#include <scsi/scsi.h>
#include <scsi/scsicam.h>	/* needed for scsicam_bios_param */
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>

#include "dc395x.h"


#define DC395X_NAME	"dc395x"

#define DC395X_BANNER	"Tekram DC395(U/UW/F), DC315(U) - ASIC TRM-S1040"

#define DC395X_VERSION	"v2.05, 2004/03/08"

/*---------------------------------------------------------------------------
                                  Features
 ---------------------------------------------------------------------------*/
/*
 * Set to disable parts of the driver
 */
/*#define DC395x_NO_DISCONNECT*/
/*#define DC395x_NO_TAGQ*/
/*#define DC395x_NO_SYNC*/
/*#define DC395x_NO_WIDE*/

/*---------------------------------------------------------------------------
                                  Debugging
 ---------------------------------------------------------------------------*/
/*
 * Types of debugging that can be enabled and disabled
 */

#define DBG_KG		0x0001

#define DBG_0		0x0002

#define DBG_1		0x0004

#define DBG_SG		0x0020

#define DBG_FIFO	0x0040

#define DBG_PIO		0x0080


/*
 * Set set of things to output debugging for.
 * Undefine to remove all debugging
 */
/*#define DEBUG_MASK (DBG_0|DBG_1|DBG_SG|DBG_FIFO|DBG_PIO)*/
/*#define  DEBUG_MASK   DBG_0*/


/*
 * Output a kernel mesage at the specified level and append the
 * driver name and a ": " to the start of the message
 */

#define dprintkl(level, format, arg...)  \
    printk(level DC395X_NAME ": " format , ## arg)


#ifdef DEBUG_MASK
/*
 * print a debug message - this is formated with KERN_DEBUG, then the
 * driver name followed by a ": " and then the message is output. 
 * This also checks that the specified debug level is enabled before
 * outputing the message
 */

#define dprintkdbg(type, format, arg...) \
	do { \
                if ((type) & (DEBUG_MASK)) \
                        dprintkl(KERN_DEBUG , format , ## arg); \
        } while (0)

/*
 * Check if the specified type of debugging is enabled
 */

#define debug_enabled(type)	((DEBUG_MASK) & (type))

#else
/*
 * No debugging. Do nothing
 */

#define dprintkdbg(type, format, arg...) \
	do {} while (0)

#define debug_enabled(type)	(0)

#endif


#ifndef PCI_VENDOR_ID_TEKRAM

#define PCI_VENDOR_ID_TEKRAM                    0x1DE1	
/* Vendor ID    */
#endif
#ifndef PCI_DEVICE_ID_TEKRAM_TRMS1040

#define PCI_DEVICE_ID_TEKRAM_TRMS1040           0x0391	
/* Device ID    */
#endif



#define DC395x_LOCK_IO(dev,flags)		spin_lock_irqsave(((struct Scsi_Host *)dev)->host_lock, flags)

#define DC395x_UNLOCK_IO(dev,flags)		spin_unlock_irqrestore(((struct Scsi_Host *)dev)->host_lock, flags)


#define DC395x_read8(acb,address)		(u8)(inb(acb->io_port_base + (address)))

#define DC395x_read16(acb,address)		(u16)(inw(acb->io_port_base + (address)))

#define DC395x_read32(acb,address)		(u32)(inl(acb->io_port_base + (address)))

#define DC395x_write8(acb,address,value)	outb((value), acb->io_port_base + (address))

#define DC395x_write16(acb,address,value)	outw((value), acb->io_port_base + (address))

#define DC395x_write32(acb,address,value)	outl((value), acb->io_port_base + (address))

/* cmd->result */

#define RES_TARGET		0x000000FF	
/* Target State */

#define RES_TARGET_LNX  STATUS_MASK	
/* Only official ... */

#define RES_ENDMSG		0x0000FF00	
/* End Message */

#define RES_DID			0x00FF0000	
/* DID_ codes */

#define RES_DRV			0xFF000000	
/* DRIVER_ codes */


#define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))

#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt)<<1)


#define SET_RES_TARGET(who,tgt) { who &= ~RES_TARGET; who |= (int)(tgt); }

#define SET_RES_TARGET_LNX(who,tgt) { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; }

#define SET_RES_MSG(who,msg) { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; }

#define SET_RES_DID(who,did) { who &= ~RES_DID; who |= (int)(did) << 16; }

#define SET_RES_DRV(who,drv) { who &= ~RES_DRV; who |= (int)(drv) << 24; }


#define TAG_NONE 255

/*
 * srb->segement_x is the hw sg list. It is always allocated as a
 * DC395x_MAX_SG_LISTENTRY entries in a linear block which does not
 * cross a page boundy.
 */

#define SEGMENTX_LEN	(sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)



struct SGentry {
	
u32 address;		/* bus! address */
	
u32 length;
};

/* The SEEPROM structure for TRM_S1040 */

struct NVRamTarget {
	
u8 cfg0;		/* Target configuration byte 0  */
	
u8 period;		/* Target period                */
	
u8 cfg2;		/* Target configuration byte 2  */
	
u8 cfg3;		/* Target configuration byte 3  */
};


struct NvRamType {
	
u8 sub_vendor_id[2];	/* 0,1  Sub Vendor ID   */
	
u8 sub_sys_id[2];	/* 2,3  Sub System ID   */
	
u8 sub_class;		/* 4    Sub Class       */
	
u8 vendor_id[2];	/* 5,6  Vendor ID       */
	
u8 device_id[2];	/* 7,8  Device ID       */
	
u8 reserved;		/* 9    Reserved        */
	
struct NVRamTarget target[DC395x_MAX_SCSI_ID];
						/** 10,11,12,13
                                                 ** 14,15,16,17
                                                 ** ....
                                                 ** ....
                                                 ** 70,71,72,73
                                                 */
	
u8 scsi_id;		/* 74 Host Adapter SCSI ID      */
	
u8 channel_cfg;		/* 75 Channel configuration     */
	
u8 delay_time;		/* 76 Power on delay time       */
	
u8 max_tag;		/* 77 Maximum tags              */
	
u8 reserved0;		/* 78  */
	
u8 boot_target;		/* 79  */
	
u8 boot_lun;		/* 80  */
	
u8 reserved1;		/* 81  */
	
u16 reserved2[22];	/* 82,..125 */
	
u16 cksum;		/* 126,127 */
};


struct ScsiReqBlk {
	
struct list_head list;		/* next/prev ptrs for srb lists */
	
struct DeviceCtlBlk *dcb;
	
struct scsi_cmnd *cmd;

	
struct SGentry *segment_x;	/* Linear array of hw sg entries (up to 64 entries) */
	
dma_addr_t sg_bus_addr;	        /* Bus address of sg list (ie, of segment_x) */

	
u8 sg_count;			/* No of HW sg entries for this request */
	
u8 sg_index;			/* Index of HW sg entry for this request */
	
size_t total_xfer_length;	/* Total number of bytes remaining to be transferred */
	
size_t request_length;		/* Total number of bytes in this request */
	/*
         * The sense buffer handling function, request_sense, uses
         * the first hw sg entry (segment_x[0]) and the transfer
         * length (total_xfer_length). While doing this it stores the
         * original values into the last sg hw list
         * (srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1] and the
         * total_xfer_length in xferred. These values are restored in
         * pci_unmap_srb_sense. This is the only place xferred is used.
         */
	
size_t xferred;		        /* Saved copy of total_xfer_length */

	
u16 state;

	
u8 msgin_buf[6];
	
u8 msgout_buf[6];

	
u8 adapter_status;
	
u8 target_status;
	
u8 msg_count;
	
u8 end_message;

	
u8 tag_number;
	
u8 status;
	
u8 retry_count;
	
u8 flag;

	
u8 scsi_phase;
};


struct DeviceCtlBlk {
	
struct list_head list;		/* next/prev ptrs for the dcb list */
	
struct AdapterCtlBlk *acb;
	
struct list_head srb_going_list;	/* head of going srb list */
	
struct list_head srb_waiting_list;	/* head of waiting srb list */

	
struct ScsiReqBlk *active_srb;
	
u32 tag_mask;

	
u16 max_command;

	
u8 target_id;		/* SCSI Target ID  (SCSI Only) */
	
u8 target_lun;		/* SCSI Log.  Unit (SCSI Only) */
	
u8 identify_msg;
	
u8 dev_mode;

	
u8 inquiry7;		/* To store Inquiry flags */
	
u8 sync_mode;		/* 0:async mode */
	
u8 min_nego_period;	/* for nego. */
	
u8 sync_period;		/* for reg.  */

	
u8 sync_offset;		/* for reg. and nego.(low nibble) */
	
u8 flag;
	
u8 dev_type;
	
u8 init_tcq_flag;
};


struct AdapterCtlBlk {
	
struct Scsi_Host *scsi_host;

	
unsigned long io_port_base;
	
unsigned long io_port_len;

	
struct list_head dcb_list;		/* head of going dcb list */
	
struct DeviceCtlBlk *dcb_run_robin;
	
struct DeviceCtlBlk *active_dcb;

	
struct list_head srb_free_list;		/* head of free srb list */
	
struct ScsiReqBlk *tmp_srb;
	
struct timer_list waiting_timer;
	
struct timer_list selto_timer;

	
unsigned long last_reset;

	
u16 srb_count;

	
u8 sel_timeout;

	
unsigned int irq_level;
	
u8 tag_max_num;
	
u8 acb_flag;
	
u8 gmode2;

	
u8 config;
	
u8 lun_chk;
	
u8 scan_devices;
	
u8 hostid_bit;

	
u8 dcb_map[DC395x_MAX_SCSI_ID];
	
struct DeviceCtlBlk *children[DC395x_MAX_SCSI_ID][32];

	
struct pci_dev *dev;

	
u8 msg_len;

	
struct ScsiReqBlk srb_array[DC395x_MAX_SRB_CNT];
	
struct ScsiReqBlk srb;

	
struct NvRamType eeprom;	/* eeprom settings for this adapter */
};


/*---------------------------------------------------------------------------
                            Forward declarations
 ---------------------------------------------------------------------------*/
static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void nop0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
		u16 *pscsi_status);
static void nop1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, 
		u16 *pscsi_status);
static void set_basic_config(struct AdapterCtlBlk *acb);
static void cleanup_after_transfer(struct AdapterCtlBlk *acb,
		struct ScsiReqBlk *srb);
static void reset_scsi_bus(struct AdapterCtlBlk *acb);
static void data_io_transfer(struct AdapterCtlBlk *acb,
		struct ScsiReqBlk *srb, u16 io_dir);
static void disconnect(struct AdapterCtlBlk *acb);
static void reselect(struct AdapterCtlBlk *acb);
static u8 start_scsi(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
		struct ScsiReqBlk *srb);
static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
		struct ScsiReqBlk *srb);
static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
		struct ScsiReqBlk *srb);
static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_code,
		struct scsi_cmnd *cmd, u8 force);
static void scsi_reset_detect(struct AdapterCtlBlk *acb);
static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb);
static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb,
		struct ScsiReqBlk *srb);
static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
		struct ScsiReqBlk *srb);
static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
		struct ScsiReqBlk *srb);
static void set_xfer_rate(struct AdapterCtlBlk *acb,
		struct DeviceCtlBlk *dcb);
static void waiting_timeout(unsigned long ptr);


/*---------------------------------------------------------------------------
                                 Static Data
 ---------------------------------------------------------------------------*/

static u16 current_sync_offset = 0;


static void *dc395x_scsi_phase0[] = {
	data_out_phase0,/* phase:0 */
	data_in_phase0,	/* phase:1 */
	command_phase0,	/* phase:2 */
	status_phase0,	/* phase:3 */
	nop0,		/* phase:4 PH_BUS_FREE .. initial phase */
	nop0,		/* phase:5 PH_BUS_FREE .. initial phase */
	msgout_phase0,	/* phase:6 */
	msgin_phase0,	/* phase:7 */
};


static void *dc395x_scsi_phase1[] = {
	data_out_phase1,/* phase:0 */
	data_in_phase1,	/* phase:1 */
	command_phase1,	/* phase:2 */
	status_phase1,	/* phase:3 */
	nop1,		/* phase:4 PH_BUS_FREE .. initial phase */
	nop1,		/* phase:5 PH_BUS_FREE .. initial phase */
	msgout_phase1,	/* phase:6 */
	msgin_phase1,	/* phase:7 */
};

/*
 *Fast20:       000      50ns, 20.0 MHz
 *              001      75ns, 13.3 MHz
 *              010     100ns, 10.0 MHz
 *              011     125ns,  8.0 MHz
 *              100     150ns,  6.6 MHz
 *              101     175ns,  5.7 MHz
 *              110     200ns,  5.0 MHz
 *              111     250ns,  4.0 MHz
 *
 *Fast40(LVDS): 000      25ns, 40.0 MHz
 *              001      50ns, 20.0 MHz
 *              010      75ns, 13.3 MHz
 *              011     100ns, 10.0 MHz
 *              100     125ns,  8.0 MHz
 *              101     150ns,  6.6 MHz
 *              110     175ns,  5.7 MHz
 *              111     200ns,  5.0 MHz
 */
/*static u8     clock_period[] = {12,19,25,31,37,44,50,62};*/

/* real period:48ns,76ns,100ns,124ns,148ns,176ns,200ns,248ns */

static u8 clock_period[] = { 12, 18, 25, 31, 37, 43, 50, 62 };

static u16 clock_speed[] = { 200, 133, 100, 80, 67, 58, 50, 40 };


/*---------------------------------------------------------------------------
                                Configuration
  ---------------------------------------------------------------------------*/
/*
 * Module/boot parameters currently effect *all* instances of the
 * card in the system.
 */

/*
 * Command line parameters are stored in a structure below.
 * These are the index's into the structure for the various
 * command line options.
 */

#define CFG_ADAPTER_ID		0

#define CFG_MAX_SPEED		1

#define CFG_DEV_MODE		2

#define CFG_ADAPTER_MODE	3

#define CFG_TAGS		4

#define CFG_RESET_DELAY		5


#define CFG_NUM			6	
/* number of configuration items */


/*
 * Value used to indicate that a command line override
 * hasn't been used to modify the value.
 */

#define CFG_PARAM_UNSET -1


/*
 * Hold command line parameters.
 */

struct ParameterData {
	
int value;		/* value of this setting */
	
int min;		/* minimum value */
	
int max;		/* maximum value */
	
int def;		/* default value */
	
int safe;		/* safe value */
};

static struct ParameterData cfg_data[] = {
	{ /* adapter id */
		CFG_PARAM_UNSET,
		0,
		15,
		7,
		7
	},
	{ /* max speed */
		CFG_PARAM_UNSET,
		  0,
		  7,
		  1,	/* 13.3Mhz */
		  4,	/*  6.7Hmz */
	},
	{ /* dev mode */
		CFG_PARAM_UNSET,
		0,
		0x3f,
		NTC_DO_PARITY_CHK | NTC_DO_DISCONNECT | NTC_DO_SYNC_NEGO |
			NTC_DO_WIDE_NEGO | NTC_DO_TAG_QUEUEING |
			NTC_DO_SEND_START,
		NTC_DO_PARITY_CHK | NTC_DO_SEND_START
	},
	{ /* adapter mode */
		CFG_PARAM_UNSET,
		0,
		0x2f,
		NAC_SCANLUN |
		NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET
			/*| NAC_ACTIVE_NEG*/,
		NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET | 0x08
	},
	{ /* tags */
		CFG_PARAM_UNSET,
		0,
		5,
		3,	/* 16 tags (??) */
		2,
        },
	{ /* reset delay */
		CFG_PARAM_UNSET,
		0,
		180,
		1,	/* 1 second */
		10,	/* 10 seconds */
	}
};


/*
 * Safe settings. If set to zero the BIOS/default values with
 * command line overrides will be used. If set to 1 then safe and
 * slow settings will be used.
 */

static bool use_safe_settings = 0;
module_param_named(safe, use_safe_settings, bool, 0);
MODULE_PARM_DESC(safe, "Use safe and slow settings only. Default: false");


module_param_named(adapter_id, cfg_data[CFG_ADAPTER_ID].value, int, 0);
MODULE_PARM_DESC(adapter_id, "Adapter SCSI ID. Default 7 (0-15)");

module_param_named(max_speed, cfg_data[CFG_MAX_SPEED].value, int, 0);
MODULE_PARM_DESC(max_speed, "Maximum bus speed. Default 1 (0-7) Speeds: 0=20, 1=13.3, 2=10, 3=8, 4=6.7, 5=5.8, 6=5, 7=4 Mhz");

module_param_named(dev_mode, cfg_data[CFG_DEV_MODE].value, int, 0);
MODULE_PARM_DESC(dev_mode, "Device mode.");

module_param_named(adapter_mode, cfg_data[CFG_ADAPTER_MODE].value, int, 0);
MODULE_PARM_DESC(adapter_mode, "Adapter mode.");

module_param_named(tags, cfg_data[CFG_TAGS].value, int, 0);
MODULE_PARM_DESC(tags, "Number of tags (1<<x). Default 3 (0-5)");

module_param_named(reset_delay, cfg_data[CFG_RESET_DELAY].value, int, 0);
MODULE_PARM_DESC(reset_delay, "Reset delay in seconds. Default 1 (0-180)");


/**
 * set_safe_settings - if the use_safe_settings option is set then
 * set all values to the safe and slow values.
 **/

static void set_safe_settings(void) { if (use_safe_settings) { int i; dprintkl(KERN_INFO, "Using safe settings.\n"); for (i = 0; i < CFG_NUM; i++) { cfg_data[i].value = cfg_data[i].safe; } } }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum5094.34%133.33%
Alan Cox23.77%133.33%
Jamie Lenehan11.89%133.33%
Total53100.00%3100.00%

/** * fix_settings - reset any boot parameters which are out of range * back to the default values. **/
static void fix_settings(void) { int i; dprintkdbg(DBG_1, "setup: AdapterId=%08x MaxSpeed=%08x DevMode=%08x " "AdapterMode=%08x Tags=%08x ResetDelay=%08x\n", cfg_data[CFG_ADAPTER_ID].value, cfg_data[CFG_MAX_SPEED].value, cfg_data[CFG_DEV_MODE].value, cfg_data[CFG_ADAPTER_MODE].value, cfg_data[CFG_TAGS].value, cfg_data[CFG_RESET_DELAY].value); for (i = 0; i < CFG_NUM; i++) { if (cfg_data[i].value < cfg_data[i].min || cfg_data[i].value > cfg_data[i].max) cfg_data[i].value = cfg_data[i].def; } }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum11696.67%133.33%
Jamie Lenehan43.33%266.67%
Total120100.00%3100.00%

/* * Mapping from the eeprom delay index value (index into this array) * to the number of actual seconds that the delay should be for. */ static char eeprom_index_to_delay_map[] = { 1, 3, 5, 10, 16, 30, 60, 120 }; /** * eeprom_index_to_delay - Take the eeprom delay setting and convert it * into a number of seconds. * * @eeprom: The eeprom structure in which we find the delay index to map. **/
static void eeprom_index_to_delay(struct NvRamType *eeprom) { eeprom->delay_time = eeprom_index_to_delay_map[eeprom->delay_time]; }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum1986.36%250.00%
Alan Cox29.09%125.00%
Jamie Lenehan14.55%125.00%
Total22100.00%4100.00%

/** * delay_to_eeprom_index - Take a delay in seconds and return the * closest eeprom index which will delay for at least that amount of * seconds. * * @delay: The delay, in seconds, to find the eeprom index for. **/
static int delay_to_eeprom_index(int delay) { u8 idx = 0; while (idx < 7 && eeprom_index_to_delay_map[idx] < delay) idx++; return idx; }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum33100.00%2100.00%
Total33100.00%2100.00%

/** * eeprom_override - Override the eeprom settings, in the provided * eeprom structure, with values that have been set on the command * line. * * @eeprom: The eeprom data to override with command line options. **/
static void eeprom_override(struct NvRamType *eeprom) { u8 id; /* Adapter Settings */ if (cfg_data[CFG_ADAPTER_ID].value != CFG_PARAM_UNSET) eeprom->scsi_id = (u8)cfg_data[CFG_ADAPTER_ID].value; if (cfg_data[CFG_ADAPTER_MODE].value != CFG_PARAM_UNSET) eeprom->channel_cfg = (u8)cfg_data[CFG_ADAPTER_MODE].value; if (cfg_data[CFG_RESET_DELAY].value != CFG_PARAM_UNSET) eeprom->delay_time = delay_to_eeprom_index( cfg_data[CFG_RESET_DELAY].value); if (cfg_data[CFG_TAGS].value != CFG_PARAM_UNSET) eeprom->max_tag = (u8)cfg_data[CFG_TAGS].value; /* Device Settings */ for (id = 0; id < DC395x_MAX_SCSI_ID; id++) { if (cfg_data[CFG_DEV_MODE].value != CFG_PARAM_UNSET) eeprom->target[id].cfg0 = (u8)cfg_data[CFG_DEV_MODE].value; if (cfg_data[CFG_MAX_SPEED].value != CFG_PARAM_UNSET) eeprom->target[id].period = (u8)cfg_data[CFG_MAX_SPEED].value; } }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum18194.76%360.00%
Alan Cox94.71%120.00%
Jamie Lenehan10.52%120.00%
Total191100.00%5100.00%

/*--------------------------------------------------------------------------- ---------------------------------------------------------------------------*/
static unsigned int list_size(struct list_head *head) { unsigned int count = 0; struct list_head *pos; list_for_each(pos, head) count++; return count; }

Contributors

PersonTokensPropCommitsCommitProp
Jamie Lenehan35100.00%2100.00%
Total35100.00%2100.00%


static struct DeviceCtlBlk *dcb_get_next(struct list_head *head, struct DeviceCtlBlk *pos) { int use_next = 0; struct DeviceCtlBlk* next = NULL; struct DeviceCtlBlk* i; if (list_empty(head)) return NULL; /* find supplied dcb and then select the next one */ list_for_each_entry(i, head, list) if (use_next) { next = i; break; } else if (i == pos) { use_next = 1; } /* if no next one take the head one (ie, wraparound) */ if (!next) list_for_each_entry(i, head, list) { next = i; break; } return next; }

Contributors

PersonTokensPropCommitsCommitProp
Jamie Lenehan102100.00%2100.00%
Total102100.00%2100.00%


static void free_tag(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { if (srb->tag_number < 255) { dcb->tag_mask &= ~(1 << srb->tag_number); /* free tag mask */ srb->tag_number = 255; } }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum3473.91%133.33%
Alan Cox1123.91%133.33%
Jamie Lenehan12.17%133.33%
Total46100.00%3100.00%

/* Find cmd in SRB list */
static inline struct ScsiReqBlk *find_cmd(struct scsi_cmnd *cmd, struct list_head *head) { struct ScsiReqBlk *i; list_for_each_entry(i, head, list) if (i->cmd == cmd) return i; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum2554.35%120.00%
Jamie Lenehan1430.43%120.00%
Alan Cox48.70%120.00%
Christoph Hellwig24.35%120.00%
Jesper Juhl12.17%120.00%
Total46100.00%5100.00%


static struct ScsiReqBlk *srb_get_free(struct AdapterCtlBlk *acb) { struct list_head *head = &acb->srb_free_list; struct ScsiReqBlk *srb = NULL; if (!list_empty(head)) { srb = list_entry(head->next, struct ScsiReqBlk, list); list_del(head->next); dprintkdbg(DBG_0, "srb_get_free: srb=%p\n", srb); } return srb; }

Contributors

PersonTokensPropCommitsCommitProp
Jamie Lenehan4156.16%360.00%
Alan Cox2027.40%120.00%
Oliver Neukum1216.44%120.00%
Total73100.00%5100.00%


static void srb_free_insert(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_free_insert: srb=%p\n", srb); list_add_tail(&srb->list, &acb->srb_free_list); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum1744.74%233.33%
Jamie Lenehan1128.95%350.00%
Alan Cox1026.32%116.67%
Total38100.00%6100.00%


static void srb_waiting_insert(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_waiting_insert: (0x%p) <%02i-%i> srb=%p\n", srb->cmd, dcb->target_id, dcb->target_lun, srb); list_add(&srb->list, &dcb->srb_waiting_list); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum2346.00%228.57%
Jamie Lenehan2040.00%342.86%
Alan Cox612.00%114.29%
Christoph Hellwig12.00%114.29%
Total50100.00%7100.00%


static void srb_waiting_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_waiting_append: (0x%p) <%02i-%i> srb=%p\n", srb->cmd, dcb->target_id, dcb->target_lun, srb); list_add_tail(&srb->list, &dcb->srb_waiting_list); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum2346.00%228.57%
Jamie Lenehan2040.00%342.86%
Alan Cox612.00%114.29%
Christoph Hellwig12.00%114.29%
Total50100.00%7100.00%


static void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_going_append: (0x%p) <%02i-%i> srb=%p\n", srb->cmd, dcb->target_id, dcb->target_lun, srb); list_add_tail(&srb->list, &dcb->srb_going_list); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum2346.00%228.57%
Jamie Lenehan2142.00%342.86%
Alan Cox510.00%114.29%
Christoph Hellwig12.00%114.29%
Total50100.00%7100.00%


static void srb_going_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; dprintkdbg(DBG_0, "srb_going_remove: (0x%p) <%02i-%i> srb=%p\n", srb->cmd, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list) if (i == srb) { list_del(&srb->list); break; } }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum3547.30%228.57%
Jamie Lenehan3547.30%342.86%
Alan Cox34.05%114.29%
Christoph Hellwig11.35%114.29%
Total74100.00%7100.00%


static void srb_waiting_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; dprintkdbg(DBG_0, "srb_waiting_remove: (0x%p) <%02i-%i> srb=%p\n", srb->cmd, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list) if (i == srb) { list_del(&srb->list); break; } }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum3648.65%228.57%
Jamie Lenehan3243.24%342.86%
Alan Cox56.76%114.29%
Christoph Hellwig11.35%114.29%
Total74100.00%7100.00%


static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_going_to_waiting_move: (0x%p) <%02i-%i> srb=%p\n", srb->cmd, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_waiting_list); }

Contributors

PersonTokensPropCommitsCommitProp
Oliver Neukum2448.00%228.57%
Jamie Lenehan1938.00%342.86%
Alan Cox612.00%114.29%
Christoph Hellwig12.00%114.29%
Total50100.00%7100.00%


static void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_waiting_to_going_move: (0x%p) <%02i-%i> srb=%p\n", srb->cmd, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_going_list); }

Contributors

PersonTokensPropCommitsCommitProp
Jamie Lenehan2346.00%342.86%
Oliver Neukum2244.00%228.57%
Alan Cox48.00%114.29%
Christoph Hellwig12.00%114.29%
Total50100.00%7100.00%

/* Sets the timer to wake us up */
static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to)