Release 4.11 drivers/scsi/aha152x.c
/* aha152x.c -- Adaptec AHA-152x driver
* Author: Jürgen E. Fischer, fischer@norbit.de
* Copyright 1993-2004 Jürgen E. Fischer
*
* 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.
*
*
* $Id: aha152x.c,v 2.7 2004/01/24 11:42:59 fischer Exp $
*
* $Log: aha152x.c,v $
* Revision 2.7 2004/01/24 11:42:59 fischer
* - gather code that is not used by PCMCIA at the end
* - move request_region for !PCMCIA case to detection
* - migration to new scsi host api (remove legacy code)
* - free host scribble before scsi_done
* - fix error handling
* - one isapnp device added to id_table
*
* Revision 2.6 2003/10/30 20:52:47 fischer
* - interfaces changes for kernel 2.6
* - aha152x_probe_one introduced for pcmcia stub
* - fixed pnpdev handling
* - instead of allocation a new one, reuse command for request sense after check condition and reset
* - fixes race in is_complete
*
* Revision 2.5 2002/04/14 11:24:53 fischer
* - isapnp support
* - abort fixed
* - 2.5 support
*
* Revision 2.4 2000/12/16 12:53:56 fischer
* - allow REQUEST SENSE to be queued
* - handle shared PCI interrupts
*
* Revision 2.3 2000/11/04 16:40:26 fischer
* - handle data overruns
* - extend timeout for data phases
*
* Revision 2.2 2000/08/08 19:54:53 fischer
* - minor changes
*
* Revision 2.1 2000/05/17 16:23:17 fischer
* - signature update
* - fix for data out w/o scatter gather
*
* Revision 2.0 1999/12/25 15:07:32 fischer
* - interrupt routine completly reworked
* - basic support for new eh code
*
* Revision 1.21 1999/11/10 23:46:36 fischer
* - default to synchronous operation
* - synchronous negotiation fixed
* - added timeout to loops
* - debugging output can be controlled through procfs
*
* Revision 1.20 1999/11/07 18:37:31 fischer
* - synchronous operation works
* - resid support for sg driver
*
* Revision 1.19 1999/11/02 22:39:59 fischer
* - moved leading comments to README.aha152x
* - new additional module parameters
* - updates for 2.3
* - support for the Tripace TC1550 controller
* - interrupt handling changed
*
* Revision 1.18 1996/09/07 20:10:40 fischer
* - fixed can_queue handling (multiple outstanding commands working again)
*
* Revision 1.17 1996/08/17 16:05:14 fischer
* - biosparam improved
* - interrupt verification
* - updated documentation
* - cleanups
*
* Revision 1.16 1996/06/09 00:04:56 root
* - added configuration symbols for insmod (aha152x/aha152x1)
*
* Revision 1.15 1996/04/30 14:52:06 fischer
* - proc info fixed
* - support for extended translation for >1GB disks
*
* Revision 1.14 1996/01/17 15:11:20 fischer
* - fixed lockup in MESSAGE IN phase after reconnection
*
* Revision 1.13 1996/01/09 02:15:53 fischer
* - some cleanups
* - moved request_irq behind controller initialization
* (to avoid spurious interrupts)
*
* Revision 1.12 1995/12/16 12:26:07 fischer
* - barrier()s added
* - configurable RESET delay added
*
* Revision 1.11 1995/12/06 21:18:35 fischer
* - some minor updates
*
* Revision 1.10 1995/07/22 19:18:45 fischer
* - support for 2 controllers
* - started synchronous data transfers (not working yet)
*
* Revision 1.9 1995/03/18 09:20:24 root
* - patches for PCMCIA and modules
*
* Revision 1.8 1995/01/21 22:07:19 root
* - snarf_region => request_region
* - aha152x_intr interface change
*
* Revision 1.7 1995/01/02 23:19:36 root
* - updated COMMAND_SIZE to cmd_len
* - changed sti() to restore_flags()
* - fixed some #ifdef which generated warnings
*
* Revision 1.6 1994/11/24 20:35:27 root
* - problem with odd number of bytes in fifo fixed
*
* Revision 1.5 1994/10/30 14:39:56 root
* - abort code fixed
* - debugging improved
*
* Revision 1.4 1994/09/12 11:33:01 root
* - irqaction to request_irq
* - abortion updated
*
* Revision 1.3 1994/08/04 13:53:05 root
* - updates for mid-level-driver changes
* - accept unexpected BUSFREE phase as error condition
* - parity check now configurable
*
* Revision 1.2 1994/07/03 12:56:36 root
* - cleaned up debugging code
* - more tweaking on reset delays
* - updated abort/reset code (pretty untested...)
*
* Revision 1.1 1994/05/28 21:18:49 root
* - update for mid-level interface change (abort-reset)
* - delays after resets adjusted for some slow devices
*
* Revision 1.0 1994/03/25 12:52:00 root
* - Fixed "more data than expected" problem
* - added new BIOS signatures
*
* Revision 0.102 1994/01/31 20:44:12 root
* - minor changes in insw/outsw handling
*
* Revision 0.101 1993/12/13 01:16:27 root
* - fixed STATUS phase (non-GOOD stati were dropped sometimes;
* fixes problems with CD-ROM sector size detection & media change)
*
* Revision 0.100 1993/12/10 16:58:47 root
* - fix for unsuccessful selections in case of non-continuous id assignments
* on the scsi bus.
*
* Revision 0.99 1993/10/24 16:19:59 root
* - fixed DATA IN (rare read errors gone)
*
* Revision 0.98 1993/10/17 12:54:44 root
* - fixed some recent fixes (shame on me)
* - moved initialization of scratch area to aha152x_queue
*
* Revision 0.97 1993/10/09 18:53:53 root
* - DATA IN fixed. Rarely left data in the fifo.
*
* Revision 0.96 1993/10/03 00:53:59 root
* - minor changes on DATA IN
*
* Revision 0.95 1993/09/24 10:36:01 root
* - change handling of MSGI after reselection
* - fixed sti/cli
* - minor changes
*
* Revision 0.94 1993/09/18 14:08:22 root
* - fixed bug in multiple outstanding command code
* - changed detection
* - support for kernel command line configuration
* - reset corrected
* - changed message handling
*
* Revision 0.93 1993/09/15 20:41:19 root
* - fixed bugs with multiple outstanding commands
*
* Revision 0.92 1993/09/13 02:46:33 root
* - multiple outstanding commands work (no problems with IBM drive)
*
* Revision 0.91 1993/09/12 20:51:46 root
* added multiple outstanding commands
* (some problem with this $%&? IBM device remain)
*
* Revision 0.9 1993/09/12 11:11:22 root
* - corrected auto-configuration
* - changed the auto-configuration (added some '#define's)
* - added support for dis-/reconnection
*
* Revision 0.8 1993/09/06 23:09:39 root
* - added support for the drive activity light
* - minor changes
*
* Revision 0.7 1993/09/05 14:30:15 root
* - improved phase detection
* - now using the new snarf_region code of 0.99pl13
*
* Revision 0.6 1993/09/02 11:01:38 root
* first public release; added some signatures and biosparam()
*
* Revision 0.5 1993/08/30 10:23:30 root
* fixed timing problems with my IBM drive
*
* Revision 0.4 1993/08/29 14:06:52 root
* fixed some problems with timeouts due incomplete commands
*
* Revision 0.3 1993/08/28 15:55:03 root
* writing data works too. mounted and worked on a dos partition
*
* Revision 0.2 1993/08/27 22:42:07 root
* reading data works. Mounted a msdos partition.
*
* Revision 0.1 1993/08/25 13:38:30 root
* first "damn thing doesn't work" version
*
* Revision 0.0 1993/08/14 19:54:25 root
* empty function bodies; detect() works.
*
*
**************************************************************************
see Documentation/scsi/aha152x.txt for configuration details
**************************************************************************/
#include <linux/module.h>
#include <asm/irq.h>
#include <linux/io.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/isapnp.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <scsi/scsicam.h>
#include "scsi.h"
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport_spi.h>
#include <scsi/scsi_eh.h>
#include "aha152x.h"
static LIST_HEAD(aha152x_host_list);
/* DEFINES */
/* For PCMCIA cards, always use AUTOCONF */
#if defined(PCMCIA) || defined(MODULE)
#if !defined(AUTOCONF)
#define AUTOCONF
#endif
#endif
#if !defined(AUTOCONF) && !defined(SETUP0)
#error define AUTOCONF or SETUP0
#endif
#define DO_LOCK(flags) spin_lock_irqsave(&QLOCK,flags)
#define DO_UNLOCK(flags) spin_unlock_irqrestore(&QLOCK,flags)
#define LEAD "(scsi%d:%d:%d) "
#define INFO_LEAD KERN_INFO LEAD
#define CMDINFO(cmd) \
(cmd) ? ((cmd)->device->host->host_no) : -1, \
(cmd) ? ((cmd)->device->id & 0x0f) : -1, \
(cmd) ? ((u8)(cmd)->device->lun & 0x07) : -1
static inline void
CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
{
scsi_set_resid(cmd, scsi_get_resid(cmd) + inc);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Boaz Harrosh | 27 | 100.00% | 1 | 100.00% |
Total | 27 | 100.00% | 1 | 100.00% |
#define DELAY_DEFAULT 1000
#if defined(PCMCIA)
#define IRQ_MIN 0
#define IRQ_MAX 16
#else
#define IRQ_MIN 9
#if defined(__PPC)
#define IRQ_MAX (nr_irqs-1)
#else
#define IRQ_MAX 12
#endif
#endif
enum {
not_issued = 0x0001, /* command not yet issued */
selecting = 0x0002, /* target is being selected */
identified = 0x0004, /* IDENTIFY was sent */
disconnected = 0x0008, /* target disconnected */
completed = 0x0010, /* target sent COMMAND COMPLETE */
aborted = 0x0020, /* ABORT was sent */
resetted = 0x0040, /* BUS DEVICE RESET was sent */
spiordy = 0x0080, /* waiting for SPIORDY to raise */
syncneg = 0x0100, /* synchronous negotiation in progress */
aborting = 0x0200, /* ABORT is pending */
resetting = 0x0400, /* BUS DEVICE RESET is pending */
check_condition = 0x0800, /* requesting sense after CHECK CONDITION */
};
MODULE_AUTHOR("Jürgen Fischer");
MODULE_DESCRIPTION(AHA152X_REVID);
MODULE_LICENSE("GPL");
#if !defined(PCMCIA)
#if defined(MODULE)
static int io[] = {0, 0};
module_param_array(io, int, NULL, 0);
MODULE_PARM_DESC(io,"base io address of controller");
static int irq[] = {0, 0};
module_param_array(irq, int, NULL, 0);
MODULE_PARM_DESC(irq,"interrupt for controller");
static int scsiid[] = {7, 7};
module_param_array(scsiid, int, NULL, 0);
MODULE_PARM_DESC(scsiid,"scsi id of controller");
static int reconnect[] = {1, 1};
module_param_array(reconnect, int, NULL, 0);
MODULE_PARM_DESC(reconnect,"allow targets to disconnect");
static int parity[] = {1, 1};
module_param_array(parity, int, NULL, 0);
MODULE_PARM_DESC(parity,"use scsi parity");
static int sync[] = {1, 1};
module_param_array(sync, int, NULL, 0);
MODULE_PARM_DESC(sync,"use synchronous transfers");
static int delay[] = {DELAY_DEFAULT, DELAY_DEFAULT};
module_param_array(delay, int, NULL, 0);
MODULE_PARM_DESC(delay,"scsi reset delay");
static int exttrans[] = {0, 0};
module_param_array(exttrans, int, NULL, 0);
MODULE_PARM_DESC(exttrans,"use extended translation");
static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
module_param_array(aha152x, int, NULL, 0);
MODULE_PARM_DESC(aha152x, "parameters for first controller");
static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
module_param_array(aha152x1, int, NULL, 0);
MODULE_PARM_DESC(aha152x1, "parameters for second controller");
#endif /* MODULE */
#ifdef __ISAPNP__
static struct isapnp_device_id id_table[] = {
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1502), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1505), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1510), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1515), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1520), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2015), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1522), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x2215), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1530), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3015), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1532), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x3215), 0 },
{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x6360), 0 },
{ ISAPNP_DEVICE_SINGLE_END, }
};
MODULE_DEVICE_TABLE(isapnp, id_table);
#endif /* ISAPNP */
#endif /* !PCMCIA */
static struct scsi_host_template aha152x_driver_template;
/*
* internal states of the host
*
*/
enum aha152x_state {
idle=0,
unknown,
seldo,
seldi,
selto,
busfree,
msgo,
cmd,
msgi,
status,
datai,
datao,
parerr,
rsti,
maxstate
};
/*
* current state information of the host
*
*/
struct aha152x_hostdata {
Scsi_Cmnd *issue_SC;
/* pending commands to issue */
Scsi_Cmnd *current_SC;
/* current command on the bus */
Scsi_Cmnd *disconnected_SC;
/* commands that disconnected */
Scsi_Cmnd *done_SC;
/* command that was completed */
spinlock_t lock;
/* host lock */
#if defined(AHA152X_STAT)
int total_commands;
int disconnections;
int busfree_without_any_action;
int busfree_without_old_command;
int busfree_without_new_command;
int busfree_without_done_command;
int busfree_with_check_condition;
int count[maxstate];
int count_trans[maxstate];
unsigned long time[maxstate];
#endif
int commands; /* current number of commands */
int reconnect; /* disconnection allowed */
int parity; /* parity checking enabled */
int synchronous; /* synchronous transferes enabled */
int delay; /* reset out delay */
int ext_trans; /* extended translation enabled */
int swint; /* software-interrupt was fired during detect() */
int service; /* bh needs to be run */
int in_intr; /* bh is running */
/* current state,
previous state,
last state different from current state */
enum aha152x_state state, prevstate, laststate;
int target;
/* reconnecting target */
unsigned char syncrate[8];
/* current synchronous transfer agreements */
unsigned char syncneg[8];
/* 0: no negotiation;
* 1: negotiation in progress;
* 2: negotiation completed
*/
int cmd_i;
/* number of sent bytes of current command */
int msgi_len;
/* number of received message bytes */
unsigned char msgi[256];
/* received message bytes */
int msgo_i, msgo_len;
/* number of sent bytes and length of current messages */
unsigned char msgo[256];
/* pending messages */
int data_len;
/* number of sent/received bytes in dataphase */
unsigned long io_port0;
unsigned long io_port1;
#ifdef __ISAPNP__
struct pnp_dev *pnpdev;
#endif
struct list_head host_list;
};
/*
* host specific command extension
*
*/
struct aha152x_scdata {
Scsi_Cmnd *next; /* next sc in queue */
struct completion *done;/* semaphore to block on */
struct scsi_eh_save ses;
};
/* access macros for hostdata */
#define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata)
#define HOSTNO ((shpnt)->host_no)
#define CURRENT_SC (HOSTDATA(shpnt)->current_SC)
#define DONE_SC (HOSTDATA(shpnt)->done_SC)
#define ISSUE_SC (HOSTDATA(shpnt)->issue_SC)
#define DISCONNECTED_SC (HOSTDATA(shpnt)->disconnected_SC)
#define QLOCK (HOSTDATA(shpnt)->lock)
#define QLOCKER (HOSTDATA(shpnt)->locker)
#define QLOCKERL (HOSTDATA(shpnt)->lockerl)
#define STATE (HOSTDATA(shpnt)->state)
#define PREVSTATE (HOSTDATA(shpnt)->prevstate)
#define LASTSTATE (HOSTDATA(shpnt)->laststate)
#define RECONN_TARGET (HOSTDATA(shpnt)->target)
#define CMD_I (HOSTDATA(shpnt)->cmd_i)
#define MSGO(i) (HOSTDATA(shpnt)->msgo[i])
#define MSGO_I (HOSTDATA(shpnt)->msgo_i)
#define MSGOLEN (HOSTDATA(shpnt)->msgo_len)
#define ADDMSGO(x) (MSGOLEN<256 ? (void)(MSGO(MSGOLEN++)=x) : aha152x_error(shpnt,"MSGO overflow"))
#define MSGI(i) (HOSTDATA(shpnt)->msgi[i])
#define MSGILEN (HOSTDATA(shpnt)->msgi_len)
#define ADDMSGI(x) (MSGILEN<256 ? (void)(MSGI(MSGILEN++)=x) : aha152x_error(shpnt,"MSGI overflow"))
#define DATA_LEN (HOSTDATA(shpnt)->data_len)
#define SYNCRATE (HOSTDATA(shpnt)->syncrate[CURRENT_SC->device->id])
#define SYNCNEG (HOSTDATA(shpnt)->syncneg[CURRENT_SC->device->id])
#define DELAY (HOSTDATA(shpnt)->delay)
#define EXT_TRANS (HOSTDATA(shpnt)->ext_trans)
#define TC1550 (HOSTDATA(shpnt)->tc1550)
#define RECONNECT (HOSTDATA(shpnt)->reconnect)
#define PARITY (HOSTDATA(shpnt)->parity)
#define SYNCHRONOUS (HOSTDATA(shpnt)->synchronous)
#define HOSTIOPORT0 (HOSTDATA(shpnt)->io_port0)
#define HOSTIOPORT1 (HOSTDATA(shpnt)->io_port1)
#define SCDATA(SCpnt) ((struct aha152x_scdata *) (SCpnt)->host_scribble)
#define SCNEXT(SCpnt) SCDATA(SCpnt)->next
#define SCSEM(SCpnt) SCDATA(SCpnt)->done
#define SG_ADDRESS(buffer) ((char *) sg_virt((buffer)))
/* state handling */
static void seldi_run(struct Scsi_Host *shpnt);
static void seldo_run(struct Scsi_Host *shpnt);
static void selto_run(struct Scsi_Host *shpnt);
static void busfree_run(struct Scsi_Host *shpnt);
static void msgo_init(struct Scsi_Host *shpnt);
static void msgo_run(struct Scsi_Host *shpnt);
static void msgo_end(struct Scsi_Host *shpnt);
static void cmd_init(struct Scsi_Host *shpnt);
static void cmd_run(struct Scsi_Host *shpnt);
static void cmd_end(struct Scsi_Host *shpnt);
static void datai_init(struct Scsi_Host *shpnt);
static void datai_run(struct Scsi_Host *shpnt);
static void datai_end(struct Scsi_Host *shpnt);
static void datao_init(struct Scsi_Host *shpnt);
static void datao_run(struct Scsi_Host *shpnt);
static void datao_end(struct Scsi_Host *shpnt);
static void status_run(struct Scsi_Host *shpnt);
static void msgi_run(struct Scsi_Host *shpnt);
static void msgi_end(struct Scsi_Host *shpnt);
static void parerr_run(struct Scsi_Host *shpnt);
static void rsti_run(struct Scsi_Host *shpnt);
static void is_complete(struct Scsi_Host *shpnt);
/*
* driver states
*
*/
static struct {
char *name;
void (*init)(struct Scsi_Host *);
void (*run)(struct Scsi_Host *);
void (*end)(struct Scsi_Host *);
int spio;
}
states[] = {
{ "idle", NULL, NULL, NULL, 0},
{ "unknown", NULL, NULL, NULL, 0},
{ "seldo", NULL, seldo_run, NULL, 0},
{ "seldi", NULL, seldi_run, NULL, 0},
{ "selto", NULL, selto_run, NULL, 0},
{ "busfree", NULL, busfree_run, NULL, 0},
{ "msgo", msgo_init, msgo_run, msgo_end, 1},
{ "cmd", cmd_init, cmd_run, cmd_end, 1},
{ "msgi", NULL, msgi_run, msgi_end, 1},
{ "status", NULL, status_run, NULL, 1},
{ "datai", datai_init, datai_run, datai_end, 0},
{ "datao", datao_init, datao_run, datao_end, 0},
{ "parerr", NULL, parerr_run, NULL, 0},
{ "rsti", NULL, rsti_run, NULL, 0},
};
/* setup & interrupt */
static irqreturn_t intr(int irq, void *dev_id);
static void reset_ports(struct Scsi_Host *shpnt);
static void aha152x_error(struct Scsi_Host *shpnt, char *msg);
static void done(struct Scsi_Host *shpnt, int error);
/* diagnostics */
static void show_command(Scsi_Cmnd * ptr);
static void show_queues(struct Scsi_Host *shpnt);
static void disp_enintr(struct Scsi_Host *shpnt);
/*
* queue services:
*
*/
static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
{
Scsi_Cmnd *end;
SCNEXT(new_SC) = NULL;
if (!*SC)
*SC = new_SC;
else {
for (end = *SC; SCNEXT(end); end = SCNEXT(end))
;
SCNEXT(end) = new_SC;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jürgen E. Fischer | 62 | 91.18% | 1 | 33.33% |
Linus Torvalds (pre-git) | 6 | 8.82% | 2 | 66.67% |
Total | 68 | 100.00% | 3 | 100.00% |
static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd ** SC)
{
Scsi_Cmnd *ptr;
ptr = *SC;
if (ptr) {
*SC = SCNEXT(*SC);
SCNEXT(ptr)=NULL;
}
return ptr;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 26 | 55.32% | 4 | 80.00% |
Jürgen E. Fischer | 21 | 44.68% | 1 | 20.00% |
Total | 47 | 100.00% | 5 | 100.00% |
static inline Scsi_Cmnd *remove_lun_SC(Scsi_Cmnd ** SC, int target, int lun)
{
Scsi_Cmnd *ptr, *prev;
for (ptr = *SC, prev = NULL;
ptr && ((ptr->device->id != target) || (ptr->device->lun != lun));
prev = ptr, ptr = SCNEXT(ptr))
;
if (ptr) {
if (prev)
SCNEXT(prev) = SCNEXT(ptr);
else
*SC = SCNEXT(ptr);
SCNEXT(ptr)=NULL;
}
return ptr;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 107 | 95.54% | 3 | 75.00% |
Randy Dunlap | 5 | 4.46% | 1 | 25.00% |
Total | 112 | 100.00% | 4 | 100.00% |
static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp)
{
Scsi_Cmnd *ptr, *prev;
for (ptr = *SC, prev = NULL;
ptr && SCp!=ptr;
prev = ptr, ptr = SCNEXT(ptr))
;
if (ptr) {
if (prev)
SCNEXT(prev) = SCNEXT(ptr);
else
*SC = SCNEXT(ptr);
SCNEXT(ptr)=NULL;
}
return ptr;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 92 | 100.00% | 3 | 100.00% |
Total | 92 | 100.00% | 3 | 100.00% |
static irqreturn_t swintr(int irqno, void *dev_id)
{
struct Scsi_Host *shpnt = dev_id;
HOSTDATA(shpnt)->swint++;
SETPORT(DMACNTRL0, INTEN);
return IRQ_HANDLED;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jürgen E. Fischer | 36 | 94.74% | 1 | 33.33% |
Linus Torvalds (pre-git) | 1 | 2.63% | 1 | 33.33% |
James Bottomley | 1 | 2.63% | 1 | 33.33% |
Total | 38 | 100.00% | 3 | 100.00% |
struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
{
struct Scsi_Host *shpnt;
shpnt = scsi_host_alloc(&aha152x_driver_template, sizeof(struct aha152x_hostdata));
if (!shpnt) {
printk(KERN_ERR "aha152x: scsi_host_alloc failed\n");
return NULL;
}
memset(HOSTDATA(shpnt), 0, sizeof *HOSTDATA(shpnt));
INIT_LIST_HEAD(&HOSTDATA(shpnt)->host_list);
/* need to have host registered before triggering any interrupt */
list_add_tail(&HOSTDATA(shpnt)->host_list, &aha152x_host_list);
shpnt->io_port = setup->io_port;
shpnt->n_io_port = IO_RANGE;
shpnt->irq = setup->irq;
if (!setup->tc1550) {
HOSTIOPORT0 = setup->io_port;
HOSTIOPORT1 = setup->io_port;
} else {
HOSTIOPORT0 = setup->io_port+0x10;
HOSTIOPORT1 = setup->io_port-0x10;
}
spin_lock_init(&QLOCK);
RECONNECT = setup->reconnect;
SYNCHRONOUS = setup->synchronous;
PARITY = setup->parity;
DELAY = setup->delay;
EXT_TRANS = setup->ext_trans;
SETPORT(SCSIID, setup->scsiid << 4);
shpnt->this_id = setup->scsiid;
if (setup->reconnect)
shpnt->can_queue = AHA152X_MAXQUEUE;
/* RESET OUT */
printk("aha152x: resetting bus...\n");
SETPORT(SCSISEQ, SCSIRSTO);
mdelay(256);
SETPORT(SCSISEQ, 0);
mdelay(DELAY);
reset_ports(shpnt);
printk(KERN_INFO
"aha152x%d%s: "
"vital data: rev=%x, "
"io=0x%03lx (0x%03lx/0x%03lx), "
"irq=%d, "
"scsiid=%d, "
"reconnect=%s, "
"parity=%s, "
"synchronous=%s, "
"delay=%d, "
"extended translation=%s\n",
shpnt->host_no, setup->tc1550 ? " (tc1550 mode)" : "",
GETPORT(REV) & 0x7,
shpnt->io_port, HOSTIOPORT0, HOSTIOPORT1,
shpnt->irq,
shpnt->this_id,
RECONNECT ? "enabled" : "disabled",
PARITY ? "enabled" : "disabled",
SYNCHRONOUS ? "enabled" : "disabled",
DELAY,
EXT_TRANS ? "enabled" : "disabled");
/* not expecting any interrupts */
SETPORT(SIMODE0, 0);
SETPORT(SIMODE1, 0);
if (request_irq(shpnt->irq, swintr, IRQF_SHARED, "aha152x", shpnt)) {
printk(KERN_ERR "aha152x%d: irq %d busy.\n", shpnt->host_no, shpnt->irq);
goto out_host_put;
}
HOSTDATA(shpnt)->swint = 0;
printk(KERN_INFO "aha152x%d: trying software interrupt, ", shpnt->host_no);
mb();
SETPORT(DMACNTRL0, SWINT|INTEN);
mdelay(1000);
free_irq(shpnt->irq, shpnt);
if (!HOSTDATA(shpnt)->swint) {
if (TESTHI(DMASTAT, INTSTAT)) {
printk("lost.\n");
} else {
printk("failed.\n");
}
SETPORT(DMACNTRL0, INTEN);
printk(KERN_ERR "aha152x%d: irq %d possibly wrong. "
"Please verify.\n", shpnt->host_no, shpnt->irq);
goto out_host_put;
}
printk("ok.\n");
/* clear interrupts */
SETPORT(SSTAT0, 0x7f);
SETPORT(SSTAT1, 0xef);
if (request_irq(shpnt->irq, intr, IRQF_SHARED, "aha152x", shpnt)) {
printk(KERN_ERR "aha152x%d: failed to reassign irq %d.\n", shpnt->host_no, shpnt->irq);
goto out_host_put;
}
if( scsi_add_host(shpnt, NULL) ) {
free_irq(shpnt->irq, shpnt);
printk(KERN_ERR "aha152x%d: failed to add host.\n", shpnt->host_no);
goto out_host_put;
}
scsi_scan_host(shpnt);
return shpnt;
out_host_put:
list_del(&HOSTDATA(shpnt)->host_list);
scsi_host_put(shpnt);
return NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jürgen E. Fischer | 450 | 74.38% | 3 | 30.00% |
Linus Torvalds (pre-git) | 112 | 18.51% | 3 | 30.00% |
James Bottomley | 36 | 5.95% | 1 | 10.00% |
Hannes Reinecke | 3 | 0.50% | 1 | 10.00% |
Thomas Gleixner | 2 | 0.33% | 1 | 10.00% |
Al Viro | 2 | 0.33% | 1 | 10.00% |
Total | 605 | 100.00% | 10 | 100.00% |
void aha152x_release(struct Scsi_Host *shpnt)
{
if (!shpnt)
return;
scsi_remove_host(shpnt);
if (shpnt->irq)
free_irq(shpnt->irq, shpnt);
#if !defined(PCMCIA)
if (shpnt->io_port)
release_region(shpnt->io_port, IO_RANGE);
#endif
#ifdef __ISAPNP__
if (HOSTDATA(shpnt)->pnpdev)
pnp_device_detach(HOSTDATA(shpnt)->pnpdev);
#endif
list_del(&HOSTDATA(shpnt)->host_list);
scsi_host_put(shpnt);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jürgen E. Fischer | 68 | 68.00% | 1 | 25.00% |
Linus Torvalds (pre-git) | 16 | 16.00% | 1 | 25.00% |
James Bottomley | 11 | 11.00% | 1 | 25.00% |
Matthew Wilcox | 5 | 5.00% | 1 | 25.00% |
Total | 100 | 100.00% | 4 | 100.00% |
/*
* setup controller to generate interrupts depending
* on current state (lock has to be acquired)
*
*/
static int setup_expected_interrupts(struct Scsi_Host *shpnt)
{
if(CURRENT_SC) {
CURRENT_SC->SCp.phase |= 1 << 16;
if(CURRENT_SC->SCp.phase & selecting) {
SETPORT(SSTAT1, SELTO);
SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
SETPORT(SIMODE1, ENSELTIMO);
} else {
SETPORT(SIMODE0, (CURRENT_SC->SCp.phase & spiordy) ? ENSPIORDY : 0);
SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
}
} else if(STATE==seldi) {
SETPORT(SIMODE0, 0);
SETPORT(