cregit-Linux how code gets into the kernel

Release 4.11 drivers/scsi/nsp32.c

Directory: drivers/scsi
/*
 * NinjaSCSI-32Bi Cardbus, NinjaSCSI-32UDE PCI/CardBus SCSI driver
 * Copyright (C) 2001, 2002, 2003
 *      YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
 *      GOTO Masanori <gotom@debian.or.jp>, <gotom@debian.org>
 *
 * 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.
 *
 *
 * Revision History:
 *   1.0: Initial Release.
 *   1.1: Add /proc SDTR status.
 *        Remove obsolete error handler nsp32_reset.
 *        Some clean up.
 *   1.2: PowerPC (big endian) support.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/dma-mapping.h>

#include <asm/dma.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_ioctl.h>

#include "nsp32.h"


/***********************************************************************
 * Module parameters
 */

static int       trans_mode = 0;	
/* default: BIOS */
module_param     (trans_mode, int, 0);
MODULE_PARM_DESC(trans_mode, "transfer mode (0: BIOS(default) 1: Async 2: Ultra20M");

#define ASYNC_MODE    1

#define ULTRA20M_MODE 2


static bool      auto_param = 0;	
/* default: ON */
module_param     (auto_param, bool, 0);
MODULE_PARM_DESC(auto_param, "AutoParameter mode (0: ON(default) 1: OFF)");


static bool      disc_priv  = 1;	
/* default: OFF */
module_param     (disc_priv, bool, 0);
MODULE_PARM_DESC(disc_priv,  "disconnection privilege mode (0: ON 1: OFF(default))");

MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>, GOTO Masanori <gotom@debian.or.jp>");
MODULE_DESCRIPTION("Workbit NinjaSCSI-32Bi/UDE CardBus/PCI SCSI host bus adapter module");
MODULE_LICENSE("GPL");


static const char *nsp32_release_version = "1.2";


/****************************************************************************
 * Supported hardware
 */

static struct pci_device_id nsp32_pci_table[] = {
	{
		.vendor      = PCI_VENDOR_ID_IODATA,
		.device      = PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II,
		.subvendor   = PCI_ANY_ID,
		.subdevice   = PCI_ANY_ID,
		.driver_data = MODEL_IODATA,
        },
	{
		.vendor      = PCI_VENDOR_ID_WORKBIT,
		.device      = PCI_DEVICE_ID_NINJASCSI_32BI_KME,
		.subvendor   = PCI_ANY_ID,
		.subdevice   = PCI_ANY_ID,
		.driver_data = MODEL_KME,
        },
	{
		.vendor      = PCI_VENDOR_ID_WORKBIT,
		.device      = PCI_DEVICE_ID_NINJASCSI_32BI_WBT,
		.subvendor   = PCI_ANY_ID,
		.subdevice   = PCI_ANY_ID,
		.driver_data = MODEL_WORKBIT,
        },
	{
		.vendor      = PCI_VENDOR_ID_WORKBIT,
		.device      = PCI_DEVICE_ID_WORKBIT_STANDARD,
		.subvendor   = PCI_ANY_ID,
		.subdevice   = PCI_ANY_ID,
		.driver_data = MODEL_PCI_WORKBIT,
        },
	{
		.vendor      = PCI_VENDOR_ID_WORKBIT,
		.device      = PCI_DEVICE_ID_NINJASCSI_32BI_LOGITEC,
		.subvendor   = PCI_ANY_ID,
		.subdevice   = PCI_ANY_ID,
		.driver_data = MODEL_LOGITEC,
        },
	{
		.vendor      = PCI_VENDOR_ID_WORKBIT,
		.device      = PCI_DEVICE_ID_NINJASCSI_32BIB_LOGITEC,
		.subvendor   = PCI_ANY_ID,
		.subdevice   = PCI_ANY_ID,
		.driver_data = MODEL_PCI_LOGITEC,
        },
	{
		.vendor      = PCI_VENDOR_ID_WORKBIT,
		.device      = PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO,
		.subvendor   = PCI_ANY_ID,
		.subdevice   = PCI_ANY_ID,
		.driver_data = MODEL_PCI_MELCO,
        },
	{
		.vendor      = PCI_VENDOR_ID_WORKBIT,
		.device      = PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO_II,
		.subvendor   = PCI_ANY_ID,
		.subdevice   = PCI_ANY_ID,
		.driver_data = MODEL_PCI_MELCO,
        },
	{0,0,},
};
MODULE_DEVICE_TABLE(pci, nsp32_pci_table);


static nsp32_hw_data nsp32_data_base;  
/* probe <-> detect glue */


/*
 * Period/AckWidth speed conversion table
 *
 * Note: This period/ackwidth speed table must be in descending order.
 */

static nsp32_sync_table nsp32_sync_table_40M[] = {
     /* {PNo, AW,   SP,   EP, SREQ smpl}  Speed(MB/s) Period AckWidth */
	{0x1,  0, 0x0c, 0x0c, SMPL_40M},  /*  20.0 :  50ns,  25ns */
	{0x2,  0, 0x0d, 0x18, SMPL_40M},  /*  13.3 :  75ns,  25ns */
	{0x3,  1, 0x19, 0x19, SMPL_40M},  /*  10.0 : 100ns,  50ns */
	{0x4,  1, 0x1a, 0x1f, SMPL_20M},  /*   8.0 : 125ns,  50ns */
	{0x5,  2, 0x20, 0x25, SMPL_20M},  /*   6.7 : 150ns,  75ns */
	{0x6,  2, 0x26, 0x31, SMPL_20M},  /*   5.7 : 175ns,  75ns */
	{0x7,  3, 0x32, 0x32, SMPL_20M},  /*   5.0 : 200ns, 100ns */
	{0x8,  3, 0x33, 0x38, SMPL_10M},  /*   4.4 : 225ns, 100ns */
	{0x9,  3, 0x39, 0x3e, SMPL_10M},  /*   4.0 : 250ns, 100ns */
};


static nsp32_sync_table nsp32_sync_table_20M[] = {
	{0x1,  0, 0x19, 0x19, SMPL_40M},  /* 10.0 : 100ns,  50ns */
	{0x2,  0, 0x1a, 0x25, SMPL_20M},  /*  6.7 : 150ns,  50ns */
	{0x3,  1, 0x26, 0x32, SMPL_20M},  /*  5.0 : 200ns, 100ns */
	{0x4,  1, 0x33, 0x3e, SMPL_10M},  /*  4.0 : 250ns, 100ns */
	{0x5,  2, 0x3f, 0x4b, SMPL_10M},  /*  3.3 : 300ns, 150ns */
	{0x6,  2, 0x4c, 0x57, SMPL_10M},  /*  2.8 : 350ns, 150ns */
	{0x7,  3, 0x58, 0x64, SMPL_10M},  /*  2.5 : 400ns, 200ns */
	{0x8,  3, 0x65, 0x70, SMPL_10M},  /*  2.2 : 450ns, 200ns */
	{0x9,  3, 0x71, 0x7d, SMPL_10M},  /*  2.0 : 500ns, 200ns */
};


static nsp32_sync_table nsp32_sync_table_pci[] = {
	{0x1,  0, 0x0c, 0x0f, SMPL_40M},  /* 16.6 :  60ns,  30ns */
	{0x2,  0, 0x10, 0x16, SMPL_40M},  /* 11.1 :  90ns,  30ns */
	{0x3,  1, 0x17, 0x1e, SMPL_20M},  /*  8.3 : 120ns,  60ns */
	{0x4,  1, 0x1f, 0x25, SMPL_20M},  /*  6.7 : 150ns,  60ns */
	{0x5,  2, 0x26, 0x2d, SMPL_20M},  /*  5.6 : 180ns,  90ns */
	{0x6,  2, 0x2e, 0x34, SMPL_10M},  /*  4.8 : 210ns,  90ns */
	{0x7,  3, 0x35, 0x3c, SMPL_10M},  /*  4.2 : 240ns, 120ns */
	{0x8,  3, 0x3d, 0x43, SMPL_10M},  /*  3.7 : 270ns, 120ns */
	{0x9,  3, 0x44, 0x4b, SMPL_10M},  /*  3.3 : 300ns, 120ns */
};

/*
 * function declaration
 */
/* module entry point */
static int         nsp32_probe (struct pci_dev *, const struct pci_device_id *);
static void        nsp32_remove(struct pci_dev *);
static int  __init init_nsp32  (void);
static void __exit exit_nsp32  (void);

/* struct struct scsi_host_template */
static int         nsp32_show_info   (struct seq_file *, struct Scsi_Host *);

static int         nsp32_detect      (struct pci_dev *pdev);
static int         nsp32_queuecommand(struct Scsi_Host *, struct scsi_cmnd *);
static const char *nsp32_info        (struct Scsi_Host *);
static int         nsp32_release     (struct Scsi_Host *);

/* SCSI error handler */
static int         nsp32_eh_abort     (struct scsi_cmnd *);
static int         nsp32_eh_bus_reset (struct scsi_cmnd *);
static int         nsp32_eh_host_reset(struct scsi_cmnd *);

/* generate SCSI message */
static void nsp32_build_identify(struct scsi_cmnd *);
static void nsp32_build_nop     (struct scsi_cmnd *);
static void nsp32_build_reject  (struct scsi_cmnd *);
static void nsp32_build_sdtr    (struct scsi_cmnd *, unsigned char, unsigned char);

/* SCSI message handler */
static int  nsp32_busfree_occur(struct scsi_cmnd *, unsigned short);
static void nsp32_msgout_occur (struct scsi_cmnd *);
static void nsp32_msgin_occur  (struct scsi_cmnd *, unsigned long, unsigned short);

static int  nsp32_setup_sg_table    (struct scsi_cmnd *);
static int  nsp32_selection_autopara(struct scsi_cmnd *);
static int  nsp32_selection_autoscsi(struct scsi_cmnd *);
static void nsp32_scsi_done         (struct scsi_cmnd *);
static int  nsp32_arbitration       (struct scsi_cmnd *, unsigned int);
static int  nsp32_reselection       (struct scsi_cmnd *, unsigned char);
static void nsp32_adjust_busfree    (struct scsi_cmnd *, unsigned int);
static void nsp32_restart_autoscsi  (struct scsi_cmnd *, unsigned short);

/* SCSI SDTR */
static void nsp32_analyze_sdtr       (struct scsi_cmnd *);
static int  nsp32_search_period_entry(nsp32_hw_data *, nsp32_target *, unsigned char);
static void nsp32_set_async          (nsp32_hw_data *, nsp32_target *);
static void nsp32_set_max_sync       (nsp32_hw_data *, nsp32_target *, unsigned char *, unsigned char *);
static void nsp32_set_sync_entry     (nsp32_hw_data *, nsp32_target *, int, unsigned char);

/* SCSI bus status handler */
static void nsp32_wait_req    (nsp32_hw_data *, int);
static void nsp32_wait_sack   (nsp32_hw_data *, int);
static void nsp32_sack_assert (nsp32_hw_data *);
static void nsp32_sack_negate (nsp32_hw_data *);
static void nsp32_do_bus_reset(nsp32_hw_data *);

/* hardware interrupt handler */
static irqreturn_t do_nsp32_isr(int, void *);

/* initialize hardware */
static int  nsp32hw_init(nsp32_hw_data *);

/* EEPROM handler */
static        int  nsp32_getprom_param (nsp32_hw_data *);
static        int  nsp32_getprom_at24  (nsp32_hw_data *);
static        int  nsp32_getprom_c16   (nsp32_hw_data *);
static        void nsp32_prom_start    (nsp32_hw_data *);
static        void nsp32_prom_stop     (nsp32_hw_data *);
static        int  nsp32_prom_read     (nsp32_hw_data *, int);
static        int  nsp32_prom_read_bit (nsp32_hw_data *);
static        void nsp32_prom_write_bit(nsp32_hw_data *, int);
static        void nsp32_prom_set      (nsp32_hw_data *, int, int);
static        int  nsp32_prom_get      (nsp32_hw_data *, int);

/* debug/warning/info message */
static void nsp32_message (const char *, int, char *, char *, ...);
#ifdef NSP32_DEBUG
static void nsp32_dmessage(const char *, int, int,    char *, ...);
#endif

/*
 * max_sectors is currently limited up to 128.
 */

static struct scsi_host_template nsp32_template = {
	.proc_name			= "nsp32",
	.name				= "Workbit NinjaSCSI-32Bi/UDE",
	.show_info			= nsp32_show_info,
	.info				= nsp32_info,
	.queuecommand			= nsp32_queuecommand,
	.can_queue			= 1,
	.sg_tablesize			= NSP32_SG_SIZE,
	.max_sectors			= 128,
	.this_id			= NSP32_HOST_SCSIID,
	.use_clustering			= DISABLE_CLUSTERING,
	.eh_abort_handler       	= nsp32_eh_abort,
	.eh_bus_reset_handler		= nsp32_eh_bus_reset,
	.eh_host_reset_handler		= nsp32_eh_host_reset,
/*      .highmem_io                     = 1, */
};

#include "nsp32_io.h"

/***********************************************************************
 * debug, error print
 */
#ifndef NSP32_DEBUG

# define NSP32_DEBUG_MASK	      0x000000

# define nsp32_msg(type, args...)     nsp32_message ("", 0, (type), args)

# define nsp32_dbg(mask, args...)     
/* */
#else

# define NSP32_DEBUG_MASK	      0xffffff

# define nsp32_msg(type, args...) \
	nsp32_message (__func__, __LINE__, (type), args)

# define nsp32_dbg(mask, args...) \
	nsp32_dmessage(__func__, __LINE__, (mask), args)
#endif


#define NSP32_DEBUG_QUEUECOMMAND	BIT(0)

#define NSP32_DEBUG_REGISTER		BIT(1)

#define NSP32_DEBUG_AUTOSCSI		BIT(2)

#define NSP32_DEBUG_INTR		BIT(3)

#define NSP32_DEBUG_SGLIST		BIT(4)

#define NSP32_DEBUG_BUSFREE		BIT(5)

#define NSP32_DEBUG_CDB_CONTENTS	BIT(6)

#define NSP32_DEBUG_RESELECTION		BIT(7)

#define NSP32_DEBUG_MSGINOCCUR		BIT(8)

#define NSP32_DEBUG_EEPROM		BIT(9)

#define NSP32_DEBUG_MSGOUTOCCUR		BIT(10)

#define NSP32_DEBUG_BUSRESET		BIT(11)

#define NSP32_DEBUG_RESTART		BIT(12)

#define NSP32_DEBUG_SYNC		BIT(13)

#define NSP32_DEBUG_WAIT		BIT(14)

#define NSP32_DEBUG_TARGETFLAG		BIT(15)

#define NSP32_DEBUG_PROC		BIT(16)

#define NSP32_DEBUG_INIT		BIT(17)

#define NSP32_SPECIAL_PRINT_REGISTER	BIT(20)


#define NSP32_DEBUG_BUF_LEN		100


static void nsp32_message(const char *func, int line, char *type, char *fmt, ...) { va_list args; char buf[NSP32_DEBUG_BUF_LEN]; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); #ifndef NSP32_DEBUG printk("%snsp32: %s\n", type, buf); #else printk("%snsp32: %s (%d): %s\n", type, func, line, buf); #endif }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds8090.91%150.00%
Goto Masanori89.09%150.00%
Total88100.00%2100.00%

#ifdef NSP32_DEBUG
static void nsp32_dmessage(const char *func, int line, int mask, char *fmt, ...) { va_list args; char buf[NSP32_DEBUG_BUF_LEN]; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if (mask & NSP32_DEBUG_MASK) { printk("nsp32-debug: 0x%x %s (%d): %s\n", mask, func, line, buf); } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds6683.54%150.00%
Goto Masanori1316.46%150.00%
Total79100.00%2100.00%

#endif #ifdef NSP32_DEBUG # include "nsp32_debug.c" #else # define show_command(arg) /* */ # define show_busphase(arg) /* */ # define show_autophase(arg) /* */ #endif /* * IDENTIFY Message */
static void nsp32_build_identify(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; int pos = data->msgout_len; int mode = FALSE; /* XXX: Auto DiscPriv detection is progressing... */ if (disc_priv == 0) { /* mode = TRUE; */ } data->msgoutbuf[pos] = IDENTIFY(mode, SCpnt->device->lun); pos++; data->msgout_len = pos; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds7497.37%150.00%
Christoph Hellwig22.63%150.00%
Total76100.00%2100.00%

/* * SDTR Message Routine */
static void nsp32_build_sdtr(struct scsi_cmnd *SCpnt, unsigned char period, unsigned char offset) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; int pos = data->msgout_len; data->msgoutbuf[pos] = EXTENDED_MESSAGE; pos++; data->msgoutbuf[pos] = EXTENDED_SDTR_LEN; pos++; data->msgoutbuf[pos] = EXTENDED_SDTR; pos++; data->msgoutbuf[pos] = period; pos++; data->msgoutbuf[pos] = offset; pos++; data->msgout_len = pos; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds9386.11%133.33%
Goto Masanori1312.04%133.33%
Christoph Hellwig21.85%133.33%
Total108100.00%3100.00%

/* * No Operation Message */
static void nsp32_build_nop(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; int pos = data->msgout_len; if (pos != 0) { nsp32_msg(KERN_WARNING, "Some messages are already contained!"); return; } data->msgoutbuf[pos] = NOP; pos++; data->msgout_len = pos; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds5986.76%133.33%
Goto Masanori710.29%133.33%
Christoph Hellwig22.94%133.33%
Total68100.00%3100.00%

/* * Reject Message */
static void nsp32_build_reject(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; int pos = data->msgout_len; data->msgoutbuf[pos] = MESSAGE_REJECT; pos++; data->msgout_len = pos; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds4790.38%133.33%
Goto Masanori35.77%133.33%
Christoph Hellwig23.85%133.33%
Total52100.00%3100.00%

/* * timer */ #if 0 static void nsp32_start_timer(struct scsi_cmnd *SCpnt, int time) { unsigned int base = SCpnt->host->io_port; nsp32_dbg(NSP32_DEBUG_INTR, "timer=%d", time); if (time & (~TIMER_CNT_MASK)) { nsp32_dbg(NSP32_DEBUG_INTR, "timer set overflow"); } nsp32_write2(base, TIMER_SET, time & TIMER_CNT_MASK); } #endif /* * set SCSI command and other parameter to asic, and start selection phase */
static int nsp32_selection_autopara(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; unsigned int host_id = SCpnt->device->host->this_id; unsigned char target = scmd_id(SCpnt); nsp32_autoparam *param = data->autoparam; unsigned char phase; int i, ret; unsigned int msgout; u16_le s; nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "in"); /* * check bus free */ phase = nsp32_read1(base, SCSI_BUS_MONITOR); if (phase != BUSMON_BUS_FREE) { nsp32_msg(KERN_WARNING, "bus busy"); show_busphase(phase & BUSMON_PHASE_MASK); SCpnt->result = DID_BUS_BUSY << 16; return FALSE; } /* * message out * * Note: If the range of msgout_len is 1 - 3, fill scsi_msgout. * over 3 messages needs another routine. */ if (data->msgout_len == 0) { nsp32_msg(KERN_ERR, "SCSI MsgOut without any message!"); SCpnt->result = DID_ERROR << 16; return FALSE; } else if (data->msgout_len > 0 && data->msgout_len <= 3) { msgout = 0; for (i = 0; i < data->msgout_len; i++) { /* * the sending order of the message is: * MCNT 3: MSG#0 -> MSG#1 -> MSG#2 * MCNT 2: MSG#1 -> MSG#2 * MCNT 1: MSG#2 */ msgout >>= 8; msgout |= ((unsigned int)(data->msgoutbuf[i]) << 24); } msgout |= MV_VALID; /* MV valid */ msgout |= (unsigned int)data->msgout_len; /* len */ } else { /* data->msgout_len > 3 */ msgout = 0; } // nsp_dbg(NSP32_DEBUG_AUTOSCSI, "sel time out=0x%x\n", nsp32_read2(base, SEL_TIME_OUT)); // nsp32_write2(base, SEL_TIME_OUT, SEL_TIMEOUT_TIME); /* * setup asic parameter */ memset(param, 0, sizeof(nsp32_autoparam)); /* cdb */ for (i = 0; i < SCpnt->cmd_len; i++) { param->cdb[4 * i] = SCpnt->cmnd[i]; } /* outgoing messages */ param->msgout = cpu_to_le32(msgout); /* syncreg, ackwidth, target id, SREQ sampling rate */ param->syncreg = data->cur_target->syncreg; param->ackwidth = data->cur_target->ackwidth; param->target_id = BIT(host_id) | BIT(target); param->sample_reg = data->cur_target->sample_reg; // nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "sample rate=0x%x\n", data->cur_target->sample_reg); /* command control */ param->command_control = cpu_to_le16(CLEAR_CDB_FIFO_POINTER | AUTOSCSI_START | AUTO_MSGIN_00_OR_04 | AUTO_MSGIN_02 | AUTO_ATN ); /* transfer control */ s = 0; switch (data->trans_method) { case NSP32_TRANSFER_BUSMASTER: s |= BM_START; break; case NSP32_TRANSFER_MMIO: s |= CB_MMIO_MODE; break; case NSP32_TRANSFER_PIO: s |= CB_IO_MODE; break; default: nsp32_msg(KERN_ERR, "unknown trans_method"); break; } /* * OR-ed BLIEND_MODE, FIFO intr is decreased, instead of PCI bus waits. * For bus master transfer, it's taken off. */ s |= (TRANSFER_GO | ALL_COUNTER_CLR); param->transfer_control = cpu_to_le16(s); /* sg table addr */ param->sgt_pointer = cpu_to_le32(data->cur_lunt->sglun_paddr); /* * transfer parameter to ASIC */ nsp32_write4(base, SGT_ADR, data->auto_paddr); nsp32_write2(base, COMMAND_CONTROL, CLEAR_CDB_FIFO_POINTER | AUTO_PARAMETER ); /* * Check arbitration */ ret = nsp32_arbitration(SCpnt, base); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds38980.04%120.00%
Goto Masanori9118.72%120.00%
Jeff Garzik30.62%120.00%
Christoph Hellwig20.41%120.00%
Luben Tuikov10.21%120.00%
Total486100.00%5100.00%

/* * Selection with AUTO SCSI (without AUTO PARAMETER) */
static int nsp32_selection_autoscsi(struct scsi_cmnd *SCpnt) { nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata; unsigned int base = SCpnt->device->host->io_port; unsigned int host_id = SCpnt->device->host->this_id; unsigned char target = scmd_id(SCpnt); unsigned char phase; int status; unsigned short command = 0; unsigned int msgout = 0; unsigned short execph; int i; nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "in"); /* * IRQ disable */ nsp32_write2(base, IRQ_CONTROL, IRQ_CONTROL_ALL_IRQ_MASK); /* * check bus line */ phase = nsp32_read1(base, SCSI_BUS_MONITOR); if(((phase & BUSMON_BSY) == 1) || (phase & BUSMON_SEL) == 1) { nsp32_msg(KERN_WARNING, "bus busy"); SCpnt->result = DID_BUS_BUSY << 16; status = 1; goto out; } /* * clear execph */ execph = nsp32_read2(base, SCSI_EXECUTE_PHASE); /* * clear FIFO counter to set CDBs */ nsp32_write2(base, COMMAND_CONTROL, CLEAR_CDB_FIFO_POINTER); /* * set CDB0 - CDB15 */ for (i = 0; i < SCpnt->cmd_len; i++) { nsp32_write1(base, COMMAND_DATA, SCpnt->cmnd[i]); } nsp32_dbg(NSP32_DEBUG_CDB_CONTENTS, "CDB[0]=[0x%x]", SCpnt->cmnd[0]); /* * set SCSIOUT LATCH(initiator)/TARGET(target) (OR-ed) ID */ nsp32_write1(base, SCSI_OUT_LATCH_TARGET_ID, BIT(host_id) | BIT(target)); /* * set SCSI MSGOUT REG * * Note: If the range of msgout_len is 1 - 3, fill scsi_msgout. * over 3 messages needs another routine. */ if (data->msgout_len == 0) { nsp32_msg(KERN_ERR, "SCSI MsgOut without any message!"); SCpnt->result = DID_ERROR << 16; status = 1; goto out; } else if (data->msgout_len > 0 && data->msgout_len <= 3) { msgout = 0; for (i = 0; i < data->msgout_len; i++) { /* * the sending order of the message is: * MCNT 3: MSG#0 -> MSG#1 -> MSG#2 * MCNT 2: MSG#1 -> MSG#2 * MCNT 1: MSG#2 */ msgout >>= 8; msgout |= ((unsigned int)(data->msgoutbuf[i]) << 24);