aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/aic7xxx
diff options
context:
space:
mode:
authorJames Bottomley <jejb@titanic.(none)>2005-08-28 11:18:35 -0500
committerJames Bottomley <jejb@titanic.(none)>2005-08-28 11:18:35 -0500
commit7a93aef7fbac6f4db40b6fec5c0c6b654ae7a93c (patch)
tree4cd7aae38012dfc1ff6c62be20ef8840e56d8383 /drivers/scsi/aic7xxx
parent392160335c798bbe94ab3aae6ea0c85d32b81bbc (diff)
parent8224bfa84d510630b40ea460b2bb380c91acb8ae (diff)
Merge HEAD from ../scsi-misc-2.6-tmp
Diffstat (limited to 'drivers/scsi/aic7xxx')
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx1
-rw-r--r--drivers/scsi/aic7xxx/aic7770.c1
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h6
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c104
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c4476
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h288
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm_pci.c82
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c14
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_proc.c43
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.reg4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.seq5
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_93cx6.c36
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c60
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c8
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c29
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped6
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped4
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped933
-rw-r--r--drivers/scsi/aic7xxx/aiclib.c1256
-rw-r--r--drivers/scsi/aic7xxx/aiclib.h868
22 files changed, 1746 insertions, 6484 deletions
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index c2523a30a7f..69ed77fcb71 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -5,6 +5,7 @@
config SCSI_AIC79XX
tristate "Adaptec AIC79xx U320 support"
depends on PCI && SCSI
+ select SCSI_SPI_ATTRS
help
This driver supports all of Adaptec's Ultra 320 PCI-X
based SCSI controllers.
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
index 00f3bd1e181..527efd36f5c 100644
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -126,7 +126,6 @@ aic7770_find_device(uint32_t id)
int
aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
{
- u_long l;
int error;
int have_seeprom;
u_int hostconf;
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index fd4b2f3eb0c..653fb0b42ae 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1247,9 +1247,6 @@ struct ahd_softc {
uint16_t user_tagenable;/* Tagged Queuing allowed */
};
-TAILQ_HEAD(ahd_softc_tailq, ahd_softc);
-extern struct ahd_softc_tailq ahd_tailq;
-
/*************************** IO Cell Configuration ****************************/
#define AHD_PRECOMP_SLEW_INDEX \
(AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0)
@@ -1374,8 +1371,6 @@ void ahd_enable_coalescing(struct ahd_softc *ahd,
void ahd_pause_and_flushwork(struct ahd_softc *ahd);
int ahd_suspend(struct ahd_softc *ahd);
int ahd_resume(struct ahd_softc *ahd);
-void ahd_softc_insert(struct ahd_softc *);
-struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd);
void ahd_set_unit(struct ahd_softc *, int);
void ahd_set_name(struct ahd_softc *, char *);
struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
@@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb);
void ahd_print_devinfo(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
void ahd_dump_sglist(struct scb *scb);
-void ahd_dump_all_cards_state(void);
void ahd_dump_card_state(struct ahd_softc *ahd);
int ahd_print_register(ahd_reg_parse_entry_t *table,
u_int num_entries,
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 137fb1a37dd..4e8f00df978 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -52,8 +52,6 @@
#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
#endif
-/******************************** Globals *************************************/
-struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
/***************************** Lookup Tables **********************************/
char *ahd_chip_names[] =
@@ -5180,74 +5178,6 @@ ahd_softc_init(struct ahd_softc *ahd)
}
void
-ahd_softc_insert(struct ahd_softc *ahd)
-{
- struct ahd_softc *list_ahd;
-
-#if AHD_PCI_CONFIG > 0
- /*
- * Second Function PCI devices need to inherit some
- * settings from function 0.
- */
- if ((ahd->features & AHD_MULTI_FUNC) != 0) {
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- ahd_dev_softc_t list_pci;
- ahd_dev_softc_t pci;
-
- list_pci = list_ahd->dev_softc;
- pci = ahd->dev_softc;
- if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
- && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
- struct ahd_softc *master;
- struct ahd_softc *slave;
-
- if (ahd_get_pci_function(list_pci) == 0) {
- master = list_ahd;
- slave = ahd;
- } else {
- master = ahd;
- slave = list_ahd;
- }
- slave->flags &= ~AHD_BIOS_ENABLED;
- slave->flags |=
- master->flags & AHD_BIOS_ENABLED;
- break;
- }
- }
- }
-#endif
-
- /*
- * Insertion sort into our list of softcs.
- */
- list_ahd = TAILQ_FIRST(&ahd_tailq);
- while (list_ahd != NULL
- && ahd_softc_comp(ahd, list_ahd) <= 0)
- list_ahd = TAILQ_NEXT(list_ahd, links);
- if (list_ahd != NULL)
- TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
- else
- TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
- ahd->init_level++;
-}
-
-/*
- * Verify that the passed in softc pointer is for a
- * controller that is still configured.
- */
-struct ahd_softc *
-ahd_find_softc(struct ahd_softc *ahd)
-{
- struct ahd_softc *list_ahd;
-
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- if (list_ahd == ahd)
- return (ahd);
- }
- return (NULL);
-}
-
-void
ahd_set_unit(struct ahd_softc *ahd, int unit)
{
ahd->unit = unit;
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
static void
ahd_reset_poll(void *arg)
{
- struct ahd_softc *ahd;
+ struct ahd_softc *ahd = arg;
u_int scsiseq1;
- u_long l;
u_long s;
- ahd_list_lock(&l);
- ahd = ahd_find_softc((struct ahd_softc *)arg);
- if (ahd == NULL) {
- printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
- ahd_list_unlock(&l);
- return;
- }
ahd_lock(ahd, &s);
ahd_pause(ahd);
ahd_update_modes(ahd);
@@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg)
ahd_reset_poll, ahd);
ahd_unpause(ahd);
ahd_unlock(ahd, &s);
- ahd_list_unlock(&l);
return;
}
@@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg)
ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
ahd_unlock(ahd, &s);
ahd_release_simq(ahd);
- ahd_list_unlock(&l);
}
/**************************** Statistics Processing ***************************/
static void
ahd_stat_timer(void *arg)
{
- struct ahd_softc *ahd;
- u_long l;
+ struct ahd_softc *ahd = arg;
u_long s;
int enint_coal;
- ahd_list_lock(&l);
- ahd = ahd_find_softc((struct ahd_softc *)arg);
- if (ahd == NULL) {
- printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
- ahd_list_unlock(&l);
- return;
- }
ahd_lock(ahd, &s);
enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
@@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg)
ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
ahd_stat_timer, ahd);
ahd_unlock(ahd, &s);
- ahd_list_unlock(&l);
}
/****************************** Status Processing *****************************/
@@ -8745,16 +8656,6 @@ sized:
return (last_probe);
}
-void
-ahd_dump_all_cards_state(void)
-{
- struct ahd_softc *list_ahd;
-
- TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
- ahd_dump_card_state(list_ahd);
- }
-}
-
int
ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
const char *name, u_int address, u_int value,
@@ -9039,7 +8940,6 @@ ahd_dump_card_state(struct ahd_softc *ahd)
ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
}
printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
- ahd_platform_dump_card_state(ahd);
ahd_restore_modes(ahd, saved_modes);
if (paused == 0)
ahd_unpause(ahd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 329cb233133..3feb739cd55 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -46,6 +46,8 @@
#include "aic79xx_inline.h"
#include <scsi/scsicam.h>
+static struct scsi_transport_template *ahd_linux_transport_template = NULL;
+
/*
* Include aiclib.c as part of our
* "module dependencies are hard" work around.
@@ -53,25 +55,11 @@
#include "aiclib.c"
#include <linux/init.h> /* __setup */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "sd.h" /* For geometry detection */
-#endif
-
#include <linux/mm.h> /* For fetching system memory size */
+#include <linux/blkdev.h> /* For block_size() */
#include <linux/delay.h> /* For ssleep/msleep */
/*
- * Lock protecting manipulation of the ahd softc list.
- */
-spinlock_t ahd_list_spinlock;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* For dynamic sglist size calculation. */
-u_int ahd_linux_nseg;
-#endif
-
-/*
* Bucket size for counting good commands in between bad ones.
*/
#define AHD_LINUX_ERR_THRESH 1000
@@ -188,71 +176,6 @@ static adapter_tag_info_t aic79xx_tag_info[] =
};
/*
- * By default, read streaming is disabled. In theory,
- * read streaming should enhance performance, but early
- * U320 drive firmware actually performs slower with
- * read streaming enabled.
- */
-#ifdef CONFIG_AIC79XX_ENABLE_RD_STRM
-#define AIC79XX_CONFIGED_RD_STRM 0xFFFF
-#else
-#define AIC79XX_CONFIGED_RD_STRM 0
-#endif
-
-static uint16_t aic79xx_rd_strm_info[] =
-{
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM,
- AIC79XX_CONFIGED_RD_STRM
-};
-
-/*
- * DV option:
- *
- * positive value = DV Enabled
- * zero = DV Disabled
- * negative value = DV Default for adapter type/seeprom
- */
-#ifdef CONFIG_AIC79XX_DV_SETTING
-#define AIC79XX_CONFIGED_DV CONFIG_AIC79XX_DV_SETTING
-#else
-#define AIC79XX_CONFIGED_DV -1
-#endif
-
-static int8_t aic79xx_dv_settings[] =
-{
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV,
- AIC79XX_CONFIGED_DV
-};
-
-/*
* The I/O cell on the chip is very configurable in respect to its analog
* characteristics. Set the defaults here; they can be overriden with
* the proper insmod parameters.
@@ -375,13 +298,6 @@ static uint32_t aic79xx_pci_parity = ~0;
uint32_t aic79xx_allow_memio = ~0;
/*
- * aic79xx_detect() has been run, so register all device arrivals
- * immediately with the system rather than deferring to the sorted
- * attachment performed by aic79xx_detect().
- */
-int aic79xx_detect_complete;
-
-/*
* So that we can set how long each device is given as a selection timeout.
* The table of values goes like this:
* 0 - 256ms
@@ -412,7 +328,7 @@ MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(AIC79XX_DRIVER_VERSION);
-module_param(aic79xx, charp, 0);
+module_param(aic79xx, charp, 0444);
MODULE_PARM_DESC(aic79xx,
"period delimited, options string.\n"
" verbose Enable verbose/diagnostic logging\n"
@@ -427,8 +343,6 @@ MODULE_PARM_DESC(aic79xx,
" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
" tag_info:<tag_str> Set per-target tag depth\n"
" global_tag_depth:<int> Global tag depth for all targets on all buses\n"
-" rd_strm:<rd_strm_masks> Set per-target read streaming setting.\n"
-" dv:<dv_settings> Set per-controller Domain Validation Setting.\n"
" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
" precomp:<pcomp_list> Set the signal precompensation (0-7).\n"
" amplitude:<int> Set the signal amplitude (0-7).\n"
@@ -441,249 +355,37 @@ MODULE_PARM_DESC(aic79xx,
" Shorten the selection timeout to 128ms\n"
"\n"
" options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n"
-"\n"
-" Sample /etc/modprobe.conf line:\n"
-" Change Read Streaming for Controller's 2 and 3\n"
-"\n"
-" options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
+"\n");
static void ahd_linux_handle_scsi_status(struct ahd_softc *,
- struct ahd_linux_device *,
+ struct scsi_device *,
struct scb *);
static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
- Scsi_Cmnd *cmd);
-static void ahd_linux_filter_inquiry(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dev_timed_unfreeze(u_long arg);
+ struct scsi_cmnd *cmd);
static void ahd_linux_sem_timeout(u_long arg);
+static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
-static void ahd_linux_size_nseg(void);
-static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd);
-static void ahd_linux_start_dv(struct ahd_softc *ahd);
-static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd);
-static int ahd_linux_dv_thread(void *data);
-static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd);
-static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target);
-static void ahd_linux_dv_transition(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_inq(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ,
- u_int request_length);
-static void ahd_linux_dv_tur(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_rebd(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_web(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_reb(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static void ahd_linux_dv_su(struct ahd_softc *ahd,
- struct scsi_cmnd *cmd,
- struct ahd_devinfo *devinfo,
- struct ahd_linux_target *targ);
-static int ahd_linux_fallback(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd,
- struct ahd_devinfo *devinfo);
-static void ahd_linux_dv_complete(Scsi_Cmnd *cmd);
-static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ);
static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
-static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd);
-static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd);
-static void ahd_linux_device_queue_depth(struct ahd_softc *ahd,
- struct ahd_linux_device *dev);
-static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*,
- u_int, u_int);
-static void ahd_linux_free_target(struct ahd_softc*,
- struct ahd_linux_target*);
-static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*,
- struct ahd_linux_target*,
- u_int);
-static void ahd_linux_free_device(struct ahd_softc*,
- struct ahd_linux_device*);
-static void ahd_linux_run_device_queue(struct ahd_softc*,
- struct ahd_linux_device*);
+static void ahd_linux_device_queue_depth(struct scsi_device *);
+static int ahd_linux_run_command(struct ahd_softc*,
+ struct ahd_linux_device *,
+ struct scsi_cmnd *);
static void ahd_linux_setup_tag_info_global(char *p);
static aic_option_callback_t ahd_linux_setup_tag_info;
-static aic_option_callback_t ahd_linux_setup_rd_strm_info;
-static aic_option_callback_t ahd_linux_setup_dv;
static aic_option_callback_t ahd_linux_setup_iocell_info;
-static int ahd_linux_next_unit(void);
-static void ahd_runq_tasklet(unsigned long data);
-static int aic79xx_setup(char *c);
-
-/****************************** Inlines ***************************************/
-static __inline void ahd_schedule_completeq(struct ahd_softc *ahd);
-static __inline void ahd_schedule_runq(struct ahd_softc *ahd);
-static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd);
-static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd);
-static __inline struct ahd_linux_device*
- ahd_linux_get_device(struct ahd_softc *ahd, u_int channel,
- u_int target, u_int lun, int alloc);
-static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd);
-static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd,
- struct ahd_linux_device *dev);
-static __inline struct ahd_linux_device *
- ahd_linux_next_device_to_run(struct ahd_softc *ahd);
-static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd);
-static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
-
-static __inline void
-ahd_schedule_completeq(struct ahd_softc *ahd)
-{
- if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) {
- ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER;
- ahd->platform_data->completeq_timer.expires = jiffies;
- add_timer(&ahd->platform_data->completeq_timer);
- }
-}
-
-/*
- * Must be called with our lock held.
- */
-static __inline void
-ahd_schedule_runq(struct ahd_softc *ahd)
-{
- tasklet_schedule(&ahd->platform_data->runq_tasklet);
-}
-
-static __inline
-void ahd_setup_runq_tasklet(struct ahd_softc *ahd)
-{
- tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet,
- (unsigned long)ahd);
-}
+static int aic79xx_setup(char *c);
-static __inline void
-ahd_teardown_runq_tasklet(struct ahd_softc *ahd)
-{
- tasklet_kill(&ahd->platform_data->runq_tasklet);
-}
+static int ahd_linux_unit;
-static __inline struct ahd_linux_device*
-ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target,
- u_int lun, int alloc)
-{
- struct ahd_linux_target *targ;
- struct ahd_linux_device *dev;
- u_int target_offset;
- target_offset = target;
- if (channel != 0)
- target_offset += 8;
- targ = ahd->platform_data->targets[target_offset];
- if (targ == NULL) {
- if (alloc != 0) {
- targ = ahd_linux_alloc_target(ahd, channel, target);
- if (targ == NULL)
- return (NULL);
- } else
- return (NULL);
- }
- dev = targ->devices[lun];
- if (dev == NULL && alloc != 0)
- dev = ahd_linux_alloc_device(ahd, targ, lun);
- return (dev);
-}
-
-#define AHD_LINUX_MAX_RETURNED_ERRORS 4
-static struct ahd_cmd *
-ahd_linux_run_complete_queue(struct ahd_softc *ahd)
-{
- struct ahd_cmd *acmd;
- u_long done_flags;
- int with_errors;
-
- with_errors = 0;
- ahd_done_lock(ahd, &done_flags);
- while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) {
- Scsi_Cmnd *cmd;
-
- if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) {
- /*
- * Linux uses stack recursion to requeue
- * commands that need to be retried. Avoid
- * blowing out the stack by "spoon feeding"
- * commands that completed with error back
- * the operating system in case they are going
- * to be retried. "ick"
- */
- ahd_schedule_completeq(ahd);
- break;
- }
- TAILQ_REMOVE(&ahd->platform_data->completeq,
- acmd, acmd_links.tqe);
- cmd = &acmd_scsi_cmd(acmd);
- cmd->host_scribble = NULL;
- if (ahd_cmd_get_transaction_status(cmd) != DID_OK
- || (cmd->result & 0xFF) != SCSI_STATUS_OK)
- with_errors++;
-
- cmd->scsi_done(cmd);
- }
- ahd_done_unlock(ahd, &done_flags);
- return (acmd);
-}
-
-static __inline void
-ahd_linux_check_device_queue(struct ahd_softc *ahd,
- struct ahd_linux_device *dev)
-{
- if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0
- && dev->active == 0) {
- dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY;
- dev->qfrozen--;
- }
-
- if (TAILQ_FIRST(&dev->busyq) == NULL
- || dev->openings == 0 || dev->qfrozen != 0)
- return;
-
- ahd_linux_run_device_queue(ahd, dev);
-}
-
-static __inline struct ahd_linux_device *
-ahd_linux_next_device_to_run(struct ahd_softc *ahd)
-{
-
- if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0
- || (ahd->platform_data->qfrozen != 0
- && AHD_DV_SIMQ_FROZEN(ahd) == 0))
- return (NULL);
- return (TAILQ_FIRST(&ahd->platform_data->device_runq));
-}
-
-static __inline void
-ahd_linux_run_device_queues(struct ahd_softc *ahd)
-{
- struct ahd_linux_device *dev;
-
- while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
- TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
- dev->flags &= ~AHD_DEV_ON_RUN_LIST;
- ahd_linux_check_device_queue(ahd, dev);
- }
-}
+/****************************** Inlines ***************************************/
+static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
static __inline void
ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
int direction;
cmd = scb->io_ctx;
@@ -705,197 +407,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
#define BUILD_SCSIID(ahd, cmd) \
((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)
-/************************ Host template entry points *************************/
-static int ahd_linux_detect(Scsi_Host_Template *);
-static const char *ahd_linux_info(struct Scsi_Host *);
-static int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int ahd_linux_slave_alloc(Scsi_Device *);
-static int ahd_linux_slave_configure(Scsi_Device *);
-static void ahd_linux_slave_destroy(Scsi_Device *);
-#if defined(__i386__)
-static int ahd_linux_biosparam(struct scsi_device*,
- struct block_device*, sector_t, int[]);
-#endif
-#else
-static int ahd_linux_release(struct Scsi_Host *);
-static void ahd_linux_select_queue_depth(struct Scsi_Host *host,
- Scsi_Device *scsi_devs);
-#if defined(__i386__)
-static int ahd_linux_biosparam(Disk *, kdev_t, int[]);
-#endif
-#endif
-static int ahd_linux_bus_reset(Scsi_Cmnd *);
-static int ahd_linux_dev_reset(Scsi_Cmnd *);
-static int ahd_linux_abort(Scsi_Cmnd *);
-
-/*
- * Calculate a safe value for AHD_NSEG (as expressed through ahd_linux_nseg).
- *
- * In pre-2.5.X...
- * The midlayer allocates an S/G array dynamically when a command is issued
- * using SCSI malloc. This array, which is in an OS dependent format that
- * must later be copied to our private S/G list, is sized to house just the
- * number of segments needed for the current transfer. Since the code that
- * sizes the SCSI malloc pool does not take into consideration fragmentation
- * of the pool, executing transactions numbering just a fraction of our
- * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will
- * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the
- * mid-layer does not properly handle this scsi malloc failures for the S/G
- * array and the result can be a lockup of the I/O subsystem. We try to size
- * our S/G list so that it satisfies our drivers allocation requirements in
- * addition to avoiding fragmentation of the SCSI malloc pool.
- */
-static void
-ahd_linux_size_nseg(void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- u_int cur_size;
- u_int best_size;
-
- /*
- * The SCSI allocator rounds to the nearest 512 bytes
- * an cannot allocate across a page boundary. Our algorithm
- * is to start at 1K of scsi malloc space per-command and
- * loop through all factors of the PAGE_SIZE and pick the best.
- */
- best_size = 0;
- for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
- u_int nseg;
-
- nseg = cur_size / sizeof(struct scatterlist);
- if (nseg < AHD_LINUX_MIN_NSEG)
- continue;
-
- if (best_size == 0) {
- best_size = cur_size;
- ahd_linux_nseg = nseg;
- } else {
- u_int best_rem;
- u_int cur_rem;
-
- /*
- * Compare the traits of the current "best_size"
- * with the current size to determine if the
- * current size is a better size.
- */
- best_rem = best_size % sizeof(struct scatterlist);
- cur_rem = cur_size % sizeof(struct scatterlist);
- if (cur_rem < best_rem) {
- best_size = cur_size;
- ahd_linux_nseg = nseg;
- }
- }
- }
-#endif
-}
-
-/*
- * Try to detect an Adaptec 79XX controller.
- */
-static int
-ahd_linux_detect(Scsi_Host_Template *template)
-{
- struct ahd_softc *ahd;
- int found;
- int error = 0;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /*
- * It is a bug that the upper layer takes
- * this lock just prior to calling us.
- */
- spin_unlock_irq(&io_request_lock);
-#endif
-
- /*
- * Sanity checking of Linux SCSI data structures so
- * that some of our hacks^H^H^H^H^Hassumptions aren't
- * violated.
- */
- if (offsetof(struct ahd_cmd_internal, end)
- > offsetof(struct scsi_cmnd, host_scribble)) {
- printf("ahd_linux_detect: SCSI data structures changed.\n");
- printf("ahd_linux_detect: Unable to attach\n");
- return (0);
- }
- /*
- * Determine an appropriate size for our Scatter Gatther lists.
- */
- ahd_linux_size_nseg();
-#ifdef MODULE
- /*
- * If we've been passed any parameters, process them now.
- */
- if (aic79xx)
- aic79xx_setup(aic79xx);
-#endif
-
- template->proc_name = "aic79xx";
-
- /*
- * Initialize our softc list lock prior to
- * probing for any adapters.
- */
- ahd_list_lockinit();
-
-#ifdef CONFIG_PCI
- error = ahd_linux_pci_init();
- if (error)
- return error;
-#endif
-
- /*
- * Register with the SCSI layer all
- * controllers we've found.
- */
- found = 0;
- TAILQ_FOREACH(ahd, &ahd_tailq, links) {
-
- if (ahd_linux_register_host(ahd, template) == 0)
- found++;
- }
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- spin_lock_irq(&io_request_lock);
-#endif
- aic79xx_detect_complete++;
- return 0;
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * Free the passed in Scsi_Host memory structures prior to unloading the
- * module.
- */
-static int
-ahd_linux_release(struct Scsi_Host * host)
-{
- struct ahd_softc *ahd;
- u_long l;
-
- ahd_list_lock(&l);
- if (host != NULL) {
-
- /*
- * We should be able to just perform
- * the free directly, but check our
- * list for extra sanity.
- */
- ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata);
- if (ahd != NULL) {
- u_long s;
-
- ahd_lock(ahd, &s);
- ahd_intr_enable(ahd, FALSE);
- ahd_unlock(ahd, &s);
- ahd_free(ahd);
- }
- }
- ahd_list_unlock(&l);
- return (0);
-}
-#endif
-
/*
* Return a string describing the driver.
*/
@@ -928,220 +439,177 @@ ahd_linux_info(struct Scsi_Host *host)
* Queue an SCB to the controller.
*/
static int
-ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
+ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
{
struct ahd_softc *ahd;
- struct ahd_linux_device *dev;
- u_long flags;
+ struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
/*
- * Save the callback on completion function.
- */
- cmd->scsi_done = scsi_done;
-
- ahd_midlayer_entrypoint_lock(ahd, &flags);
-
- /*
* Close the race of a command that was in the process of
* being queued to us just as our simq was frozen. Let
* DV commands through so long as we are only frozen to
* perform DV.
*/
- if (ahd->platform_data->qfrozen != 0
- && AHD_DV_CMD(cmd) == 0) {
-
- ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
- ahd_linux_queue_cmd_complete(ahd, cmd);
- ahd_schedule_completeq(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
- return (0);
- }
- dev = ahd_linux_get_device(ahd, cmd->device->channel,
- cmd->device->id, cmd->device->lun,
- /*alloc*/TRUE);
- if (dev == NULL) {
- ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
- ahd_linux_queue_cmd_complete(ahd, cmd);
- ahd_schedule_completeq(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &flags);
- printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
- ahd_name(ahd));
- return (0);
+ if (ahd->platform_data->qfrozen != 0) {
+ printf("%s: queue frozen\n", ahd_name(ahd));
+
+ return SCSI_MLQUEUE_HOST_BUSY;
}
- if (cmd->cmd_len > MAX_CDB_LEN)
- return (-EINVAL);
+
+ /*
+ * Save the callback on completion function.
+ */
+ cmd->scsi_done = scsi_done;
+
cmd->result = CAM_REQ_INP