Release 4.11 drivers/scsi/dc395x.c
/*
* 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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 50 | 94.34% | 1 | 33.33% |
Alan Cox | 2 | 3.77% | 1 | 33.33% |
Jamie Lenehan | 1 | 1.89% | 1 | 33.33% |
Total | 53 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 116 | 96.67% | 1 | 33.33% |
Jamie Lenehan | 4 | 3.33% | 2 | 66.67% |
Total | 120 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 19 | 86.36% | 2 | 50.00% |
Alan Cox | 2 | 9.09% | 1 | 25.00% |
Jamie Lenehan | 1 | 4.55% | 1 | 25.00% |
Total | 22 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 33 | 100.00% | 2 | 100.00% |
Total | 33 | 100.00% | 2 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 181 | 94.76% | 3 | 60.00% |
Alan Cox | 9 | 4.71% | 1 | 20.00% |
Jamie Lenehan | 1 | 0.52% | 1 | 20.00% |
Total | 191 | 100.00% | 5 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Jamie Lenehan | 35 | 100.00% | 2 | 100.00% |
Total | 35 | 100.00% | 2 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Jamie Lenehan | 102 | 100.00% | 2 | 100.00% |
Total | 102 | 100.00% | 2 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 34 | 73.91% | 1 | 33.33% |
Alan Cox | 11 | 23.91% | 1 | 33.33% |
Jamie Lenehan | 1 | 2.17% | 1 | 33.33% |
Total | 46 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 25 | 54.35% | 1 | 20.00% |
Jamie Lenehan | 14 | 30.43% | 1 | 20.00% |
Alan Cox | 4 | 8.70% | 1 | 20.00% |
Christoph Hellwig | 2 | 4.35% | 1 | 20.00% |
Jesper Juhl | 1 | 2.17% | 1 | 20.00% |
Total | 46 | 100.00% | 5 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Jamie Lenehan | 41 | 56.16% | 3 | 60.00% |
Alan Cox | 20 | 27.40% | 1 | 20.00% |
Oliver Neukum | 12 | 16.44% | 1 | 20.00% |
Total | 73 | 100.00% | 5 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 17 | 44.74% | 2 | 33.33% |
Jamie Lenehan | 11 | 28.95% | 3 | 50.00% |
Alan Cox | 10 | 26.32% | 1 | 16.67% |
Total | 38 | 100.00% | 6 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 23 | 46.00% | 2 | 28.57% |
Jamie Lenehan | 20 | 40.00% | 3 | 42.86% |
Alan Cox | 6 | 12.00% | 1 | 14.29% |
Christoph Hellwig | 1 | 2.00% | 1 | 14.29% |
Total | 50 | 100.00% | 7 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 23 | 46.00% | 2 | 28.57% |
Jamie Lenehan | 20 | 40.00% | 3 | 42.86% |
Alan Cox | 6 | 12.00% | 1 | 14.29% |
Christoph Hellwig | 1 | 2.00% | 1 | 14.29% |
Total | 50 | 100.00% | 7 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 23 | 46.00% | 2 | 28.57% |
Jamie Lenehan | 21 | 42.00% | 3 | 42.86% |
Alan Cox | 5 | 10.00% | 1 | 14.29% |
Christoph Hellwig | 1 | 2.00% | 1 | 14.29% |
Total | 50 | 100.00% | 7 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 35 | 47.30% | 2 | 28.57% |
Jamie Lenehan | 35 | 47.30% | 3 | 42.86% |
Alan Cox | 3 | 4.05% | 1 | 14.29% |
Christoph Hellwig | 1 | 1.35% | 1 | 14.29% |
Total | 74 | 100.00% | 7 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 36 | 48.65% | 2 | 28.57% |
Jamie Lenehan | 32 | 43.24% | 3 | 42.86% |
Alan Cox | 5 | 6.76% | 1 | 14.29% |
Christoph Hellwig | 1 | 1.35% | 1 | 14.29% |
Total | 74 | 100.00% | 7 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 24 | 48.00% | 2 | 28.57% |
Jamie Lenehan | 19 | 38.00% | 3 | 42.86% |
Alan Cox | 6 | 12.00% | 1 | 14.29% |
Christoph Hellwig | 1 | 2.00% | 1 | 14.29% |
Total | 50 | 100.00% | 7 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Jamie Lenehan | 23 | 46.00% | 3 | 42.86% |
Oliver Neukum | 22 | 44.00% | 2 | 28.57% |
Alan Cox | 4 | 8.00% | 1 | 14.29% |
Christoph Hellwig | 1 | 2.00% | 1 | 14.29% |
Total | 50 | 100.00% | 7 | 100.00% |
/* Sets the timer to wake us up */
static void waiting_set_timer(struct AdapterCtlBlk *acb, unsigned long to)