aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic7xxx
diff options
context:
space:
mode:
authorJames Bottomley <jejb@titanic.(none)>2005-08-28 12:18:35 -0400
committerJames Bottomley <jejb@titanic.(none)>2005-08-28 12:18:35 -0400
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 c2523a30a7f5..69ed77fcb71f 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -5,6 +5,7 @@
5config SCSI_AIC79XX 5config SCSI_AIC79XX
6 tristate "Adaptec AIC79xx U320 support" 6 tristate "Adaptec AIC79xx U320 support"
7 depends on PCI && SCSI 7 depends on PCI && SCSI
8 select SCSI_SPI_ATTRS
8 help 9 help
9 This driver supports all of Adaptec's Ultra 320 PCI-X 10 This driver supports all of Adaptec's Ultra 320 PCI-X
10 based SCSI controllers. 11 based SCSI controllers.
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
index 00f3bd1e181e..527efd36f5c1 100644
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -126,7 +126,6 @@ aic7770_find_device(uint32_t id)
126int 126int
127aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) 127aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
128{ 128{
129 u_long l;
130 int error; 129 int error;
131 int have_seeprom; 130 int have_seeprom;
132 u_int hostconf; 131 u_int hostconf;
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index fd4b2f3eb0c2..653fb0b42aea 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -1247,9 +1247,6 @@ struct ahd_softc {
1247 uint16_t user_tagenable;/* Tagged Queuing allowed */ 1247 uint16_t user_tagenable;/* Tagged Queuing allowed */
1248}; 1248};
1249 1249
1250TAILQ_HEAD(ahd_softc_tailq, ahd_softc);
1251extern struct ahd_softc_tailq ahd_tailq;
1252
1253/*************************** IO Cell Configuration ****************************/ 1250/*************************** IO Cell Configuration ****************************/
1254#define AHD_PRECOMP_SLEW_INDEX \ 1251#define AHD_PRECOMP_SLEW_INDEX \
1255 (AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0) 1252 (AHD_ANNEXCOL_PRECOMP_SLEW - AHD_ANNEXCOL_PER_DEV0)
@@ -1374,8 +1371,6 @@ void ahd_enable_coalescing(struct ahd_softc *ahd,
1374void ahd_pause_and_flushwork(struct ahd_softc *ahd); 1371void ahd_pause_and_flushwork(struct ahd_softc *ahd);
1375int ahd_suspend(struct ahd_softc *ahd); 1372int ahd_suspend(struct ahd_softc *ahd);
1376int ahd_resume(struct ahd_softc *ahd); 1373int ahd_resume(struct ahd_softc *ahd);
1377void ahd_softc_insert(struct ahd_softc *);
1378struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd);
1379void ahd_set_unit(struct ahd_softc *, int); 1374void ahd_set_unit(struct ahd_softc *, int);
1380void ahd_set_name(struct ahd_softc *, char *); 1375void ahd_set_name(struct ahd_softc *, char *);
1381struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); 1376struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
@@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb);
1524void ahd_print_devinfo(struct ahd_softc *ahd, 1519void ahd_print_devinfo(struct ahd_softc *ahd,
1525 struct ahd_devinfo *devinfo); 1520 struct ahd_devinfo *devinfo);
1526void ahd_dump_sglist(struct scb *scb); 1521void ahd_dump_sglist(struct scb *scb);
1527void ahd_dump_all_cards_state(void);
1528void ahd_dump_card_state(struct ahd_softc *ahd); 1522void ahd_dump_card_state(struct ahd_softc *ahd);
1529int ahd_print_register(ahd_reg_parse_entry_t *table, 1523int ahd_print_register(ahd_reg_parse_entry_t *table,
1530 u_int num_entries, 1524 u_int num_entries,
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 137fb1a37dd1..4e8f00df978d 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -52,8 +52,6 @@
52#include <dev/aic7xxx/aicasm/aicasm_insformat.h> 52#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
53#endif 53#endif
54 54
55/******************************** Globals *************************************/
56struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
57 55
58/***************************** Lookup Tables **********************************/ 56/***************************** Lookup Tables **********************************/
59char *ahd_chip_names[] = 57char *ahd_chip_names[] =
@@ -5180,74 +5178,6 @@ ahd_softc_init(struct ahd_softc *ahd)
5180} 5178}
5181 5179
5182void 5180void
5183ahd_softc_insert(struct ahd_softc *ahd)
5184{
5185 struct ahd_softc *list_ahd;
5186
5187#if AHD_PCI_CONFIG > 0
5188 /*
5189 * Second Function PCI devices need to inherit some
5190 * settings from function 0.
5191 */
5192 if ((ahd->features & AHD_MULTI_FUNC) != 0) {
5193 TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
5194 ahd_dev_softc_t list_pci;
5195 ahd_dev_softc_t pci;
5196
5197 list_pci = list_ahd->dev_softc;
5198 pci = ahd->dev_softc;
5199 if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci)
5200 && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) {
5201 struct ahd_softc *master;
5202 struct ahd_softc *slave;
5203
5204 if (ahd_get_pci_function(list_pci) == 0) {
5205 master = list_ahd;
5206 slave = ahd;
5207 } else {
5208 master = ahd;
5209 slave = list_ahd;
5210 }
5211 slave->flags &= ~AHD_BIOS_ENABLED;
5212 slave->flags |=
5213 master->flags & AHD_BIOS_ENABLED;
5214 break;
5215 }
5216 }
5217 }
5218#endif
5219
5220 /*
5221 * Insertion sort into our list of softcs.
5222 */
5223 list_ahd = TAILQ_FIRST(&ahd_tailq);
5224 while (list_ahd != NULL
5225 && ahd_softc_comp(ahd, list_ahd) <= 0)
5226 list_ahd = TAILQ_NEXT(list_ahd, links);
5227 if (list_ahd != NULL)
5228 TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
5229 else
5230 TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
5231 ahd->init_level++;
5232}
5233
5234/*
5235 * Verify that the passed in softc pointer is for a
5236 * controller that is still configured.
5237 */
5238struct ahd_softc *
5239ahd_find_softc(struct ahd_softc *ahd)
5240{
5241 struct ahd_softc *list_ahd;
5242
5243 TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
5244 if (list_ahd == ahd)
5245 return (ahd);
5246 }
5247 return (NULL);
5248}
5249
5250void
5251ahd_set_unit(struct ahd_softc *ahd, int unit) 5181ahd_set_unit(struct ahd_softc *ahd, int unit)
5252{ 5182{
5253 ahd->unit = unit; 5183 ahd->unit = unit;
@@ -7902,18 +7832,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
7902static void 7832static void
7903ahd_reset_poll(void *arg) 7833ahd_reset_poll(void *arg)
7904{ 7834{
7905 struct ahd_softc *ahd; 7835 struct ahd_softc *ahd = arg;
7906 u_int scsiseq1; 7836 u_int scsiseq1;
7907 u_long l;
7908 u_long s; 7837 u_long s;
7909 7838
7910 ahd_list_lock(&l);
7911 ahd = ahd_find_softc((struct ahd_softc *)arg);
7912 if (ahd == NULL) {
7913 printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
7914 ahd_list_unlock(&l);
7915 return;
7916 }
7917 ahd_lock(ahd, &s); 7839 ahd_lock(ahd, &s);
7918 ahd_pause(ahd); 7840 ahd_pause(ahd);
7919 ahd_update_modes(ahd); 7841 ahd_update_modes(ahd);
@@ -7924,7 +7846,6 @@ ahd_reset_poll(void *arg)
7924 ahd_reset_poll, ahd); 7846 ahd_reset_poll, ahd);
7925 ahd_unpause(ahd); 7847 ahd_unpause(ahd);
7926 ahd_unlock(ahd, &s); 7848 ahd_unlock(ahd, &s);
7927 ahd_list_unlock(&l);
7928 return; 7849 return;
7929 } 7850 }
7930 7851
@@ -7936,25 +7857,16 @@ ahd_reset_poll(void *arg)
7936 ahd->flags &= ~AHD_RESET_POLL_ACTIVE; 7857 ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
7937 ahd_unlock(ahd, &s); 7858 ahd_unlock(ahd, &s);
7938 ahd_release_simq(ahd); 7859 ahd_release_simq(ahd);
7939 ahd_list_unlock(&l);
7940} 7860}
7941 7861
7942/**************************** Statistics Processing ***************************/ 7862/**************************** Statistics Processing ***************************/
7943static void 7863static void
7944ahd_stat_timer(void *arg) 7864ahd_stat_timer(void *arg)
7945{ 7865{
7946 struct ahd_softc *ahd; 7866 struct ahd_softc *ahd = arg;
7947 u_long l;
7948 u_long s; 7867 u_long s;
7949 int enint_coal; 7868 int enint_coal;
7950 7869
7951 ahd_list_lock(&l);
7952 ahd = ahd_find_softc((struct ahd_softc *)arg);
7953 if (ahd == NULL) {
7954 printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
7955 ahd_list_unlock(&l);
7956 return;
7957 }
7958 ahd_lock(ahd, &s); 7870 ahd_lock(ahd, &s);
7959 7871
7960 enint_coal = ahd->hs_mailbox & ENINT_COALESCE; 7872 enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
@@ -7981,7 +7893,6 @@ ahd_stat_timer(void *arg)
7981 ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, 7893 ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US,
7982 ahd_stat_timer, ahd); 7894 ahd_stat_timer, ahd);
7983 ahd_unlock(ahd, &s); 7895 ahd_unlock(ahd, &s);
7984 ahd_list_unlock(&l);
7985} 7896}
7986 7897
7987/****************************** Status Processing *****************************/ 7898/****************************** Status Processing *****************************/
@@ -8745,16 +8656,6 @@ sized:
8745 return (last_probe); 8656 return (last_probe);
8746} 8657}
8747 8658
8748void
8749ahd_dump_all_cards_state(void)
8750{
8751 struct ahd_softc *list_ahd;
8752
8753 TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
8754 ahd_dump_card_state(list_ahd);
8755 }
8756}
8757
8758int 8659int
8759ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, 8660ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
8760 const char *name, u_int address, u_int value, 8661 const char *name, u_int address, u_int value,
@@ -9039,7 +8940,6 @@ ahd_dump_card_state(struct ahd_softc *ahd)
9039 ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF); 8940 ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
9040 } 8941 }
9041 printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); 8942 printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
9042 ahd_platform_dump_card_state(ahd);
9043 ahd_restore_modes(ahd, saved_modes); 8943 ahd_restore_modes(ahd, saved_modes);
9044 if (paused == 0) 8944 if (paused == 0)
9045 ahd_unpause(ahd); 8945 ahd_unpause(ahd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 329cb2331339..3feb739cd554 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -46,6 +46,8 @@
46#include "aic79xx_inline.h" 46#include "aic79xx_inline.h"
47#include <scsi/scsicam.h> 47#include <scsi/scsicam.h>
48 48
49static struct scsi_transport_template *ahd_linux_transport_template = NULL;
50
49/* 51/*
50 * Include aiclib.c as part of our 52 * Include aiclib.c as part of our
51 * "module dependencies are hard" work around. 53 * "module dependencies are hard" work around.
@@ -53,25 +55,11 @@
53#include "aiclib.c" 55#include "aiclib.c"
54 56
55#include <linux/init.h> /* __setup */ 57#include <linux/init.h> /* __setup */
56
57#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
58#include "sd.h" /* For geometry detection */
59#endif
60
61#include <linux/mm.h> /* For fetching system memory size */ 58#include <linux/mm.h> /* For fetching system memory size */
59#include <linux/blkdev.h> /* For block_size() */
62#include <linux/delay.h> /* For ssleep/msleep */ 60#include <linux/delay.h> /* For ssleep/msleep */
63 61
64/* 62/*
65 * Lock protecting manipulation of the ahd softc list.
66 */
67spinlock_t ahd_list_spinlock;
68
69#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
70/* For dynamic sglist size calculation. */
71u_int ahd_linux_nseg;
72#endif
73
74/*
75 * Bucket size for counting good commands in between bad ones. 63 * Bucket size for counting good commands in between bad ones.
76 */ 64 */
77#define AHD_LINUX_ERR_THRESH 1000 65#define AHD_LINUX_ERR_THRESH 1000
@@ -188,71 +176,6 @@ static adapter_tag_info_t aic79xx_tag_info[] =
188}; 176};
189 177
190/* 178/*
191 * By default, read streaming is disabled. In theory,
192 * read streaming should enhance performance, but early
193 * U320 drive firmware actually performs slower with
194 * read streaming enabled.
195 */
196#ifdef CONFIG_AIC79XX_ENABLE_RD_STRM
197#define AIC79XX_CONFIGED_RD_STRM 0xFFFF
198#else
199#define AIC79XX_CONFIGED_RD_STRM 0
200#endif
201
202static uint16_t aic79xx_rd_strm_info[] =
203{
204 AIC79XX_CONFIGED_RD_STRM,
205 AIC79XX_CONFIGED_RD_STRM,
206 AIC79XX_CONFIGED_RD_STRM,
207 AIC79XX_CONFIGED_RD_STRM,
208 AIC79XX_CONFIGED_RD_STRM,
209 AIC79XX_CONFIGED_RD_STRM,
210 AIC79XX_CONFIGED_RD_STRM,
211 AIC79XX_CONFIGED_RD_STRM,
212 AIC79XX_CONFIGED_RD_STRM,
213 AIC79XX_CONFIGED_RD_STRM,
214 AIC79XX_CONFIGED_RD_STRM,
215 AIC79XX_CONFIGED_RD_STRM,
216 AIC79XX_CONFIGED_RD_STRM,
217 AIC79XX_CONFIGED_RD_STRM,
218 AIC79XX_CONFIGED_RD_STRM,
219 AIC79XX_CONFIGED_RD_STRM
220};
221
222/*
223 * DV option:
224 *
225 * positive value = DV Enabled
226 * zero = DV Disabled
227 * negative value = DV Default for adapter type/seeprom
228 */
229#ifdef CONFIG_AIC79XX_DV_SETTING
230#define AIC79XX_CONFIGED_DV CONFIG_AIC79XX_DV_SETTING
231#else
232#define AIC79XX_CONFIGED_DV -1
233#endif
234
235static int8_t aic79xx_dv_settings[] =
236{
237 AIC79XX_CONFIGED_DV,
238 AIC79XX_CONFIGED_DV,
239 AIC79XX_CONFIGED_DV,
240 AIC79XX_CONFIGED_DV,
241 AIC79XX_CONFIGED_DV,
242 AIC79XX_CONFIGED_DV,
243 AIC79XX_CONFIGED_DV,
244 AIC79XX_CONFIGED_DV,
245 AIC79XX_CONFIGED_DV,
246 AIC79XX_CONFIGED_DV,
247 AIC79XX_CONFIGED_DV,
248 AIC79XX_CONFIGED_DV,
249 AIC79XX_CONFIGED_DV,
250 AIC79XX_CONFIGED_DV,
251 AIC79XX_CONFIGED_DV,
252 AIC79XX_CONFIGED_DV
253};
254
255/*
256 * The I/O cell on the chip is very configurable in respect to its analog 179 * The I/O cell on the chip is very configurable in respect to its analog
257 * characteristics. Set the defaults here; they can be overriden with 180 * characteristics. Set the defaults here; they can be overriden with
258 * the proper insmod parameters. 181 * the proper insmod parameters.
@@ -375,13 +298,6 @@ static uint32_t aic79xx_pci_parity = ~0;
375uint32_t aic79xx_allow_memio = ~0; 298uint32_t aic79xx_allow_memio = ~0;
376 299
377/* 300/*
378 * aic79xx_detect() has been run, so register all device arrivals
379 * immediately with the system rather than deferring to the sorted
380 * attachment performed by aic79xx_detect().
381 */
382int aic79xx_detect_complete;
383
384/*
385 * So that we can set how long each device is given as a selection timeout. 301 * So that we can set how long each device is given as a selection timeout.
386 * The table of values goes like this: 302 * The table of values goes like this:
387 * 0 - 256ms 303 * 0 - 256ms
@@ -412,7 +328,7 @@ MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
412MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); 328MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
413MODULE_LICENSE("Dual BSD/GPL"); 329MODULE_LICENSE("Dual BSD/GPL");
414MODULE_VERSION(AIC79XX_DRIVER_VERSION); 330MODULE_VERSION(AIC79XX_DRIVER_VERSION);
415module_param(aic79xx, charp, 0); 331module_param(aic79xx, charp, 0444);
416MODULE_PARM_DESC(aic79xx, 332MODULE_PARM_DESC(aic79xx,
417"period delimited, options string.\n" 333"period delimited, options string.\n"
418" verbose Enable verbose/diagnostic logging\n" 334" verbose Enable verbose/diagnostic logging\n"
@@ -427,8 +343,6 @@ MODULE_PARM_DESC(aic79xx,
427" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n" 343" reverse_scan Sort PCI devices highest Bus/Slot to lowest\n"
428" tag_info:<tag_str> Set per-target tag depth\n" 344" tag_info:<tag_str> Set per-target tag depth\n"
429" global_tag_depth:<int> Global tag depth for all targets on all buses\n" 345" global_tag_depth:<int> Global tag depth for all targets on all buses\n"
430" rd_strm:<rd_strm_masks> Set per-target read streaming setting.\n"
431" dv:<dv_settings> Set per-controller Domain Validation Setting.\n"
432" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n" 346" slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
433" precomp:<pcomp_list> Set the signal precompensation (0-7).\n" 347" precomp:<pcomp_list> Set the signal precompensation (0-7).\n"
434" amplitude:<int> Set the signal amplitude (0-7).\n" 348" amplitude:<int> Set the signal amplitude (0-7).\n"
@@ -441,249 +355,37 @@ MODULE_PARM_DESC(aic79xx,
441" Shorten the selection timeout to 128ms\n" 355" Shorten the selection timeout to 128ms\n"
442"\n" 356"\n"
443" options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" 357" options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n"
444"\n" 358"\n");
445" Sample /etc/modprobe.conf line:\n"
446" Change Read Streaming for Controller's 2 and 3\n"
447"\n"
448" options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
449 359
450static void ahd_linux_handle_scsi_status(struct ahd_softc *, 360static void ahd_linux_handle_scsi_status(struct ahd_softc *,
451 struct ahd_linux_device *, 361 struct scsi_device *,
452 struct scb *); 362 struct scb *);
453static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, 363static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
454 Scsi_Cmnd *cmd); 364 struct scsi_cmnd *cmd);
455static void ahd_linux_filter_inquiry(struct ahd_softc *ahd,
456 struct ahd_devinfo *devinfo);
457static void ahd_linux_dev_timed_unfreeze(u_long arg);
458static void ahd_linux_sem_timeout(u_long arg); 365static void ahd_linux_sem_timeout(u_long arg);
366static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
459static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); 367static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
460static void ahd_linux_size_nseg(void);
461static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd);
462static void ahd_linux_start_dv(struct ahd_softc *ahd);
463static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd);
464static int ahd_linux_dv_thread(void *data);
465static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd);
466static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target);
467static void ahd_linux_dv_transition(struct ahd_softc *ahd,
468 struct scsi_cmnd *cmd,
469 struct ahd_devinfo *devinfo,
470 struct ahd_linux_target *targ);
471static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd,
472 struct scsi_cmnd *cmd,
473 struct ahd_devinfo *devinfo);
474static void ahd_linux_dv_inq(struct ahd_softc *ahd,
475 struct scsi_cmnd *cmd,
476 struct ahd_devinfo *devinfo,
477 struct ahd_linux_target *targ,
478 u_int request_length);
479static void ahd_linux_dv_tur(struct ahd_softc *ahd,
480 struct scsi_cmnd *cmd,
481 struct ahd_devinfo *devinfo);
482static void ahd_linux_dv_rebd(struct ahd_softc *ahd,
483 struct scsi_cmnd *cmd,
484 struct ahd_devinfo *devinfo,
485 struct ahd_linux_target *targ);
486static void ahd_linux_dv_web(struct ahd_softc *ahd,
487 struct scsi_cmnd *cmd,
488 struct ahd_devinfo *devinfo,
489 struct ahd_linux_target *targ);
490static void ahd_linux_dv_reb(struct ahd_softc *ahd,
491 struct scsi_cmnd *cmd,
492 struct ahd_devinfo *devinfo,
493 struct ahd_linux_target *targ);
494static void ahd_linux_dv_su(struct ahd_softc *ahd,
495 struct scsi_cmnd *cmd,
496 struct ahd_devinfo *devinfo,
497 struct ahd_linux_target *targ);
498static int ahd_linux_fallback(struct ahd_softc *ahd,
499 struct ahd_devinfo *devinfo);
500static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd,
501 struct ahd_devinfo *devinfo);
502static void ahd_linux_dv_complete(Scsi_Cmnd *cmd);
503static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ);
504static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, 368static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
505 struct ahd_devinfo *devinfo); 369 struct ahd_devinfo *devinfo);
506static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd); 370static void ahd_linux_device_queue_depth(struct scsi_device *);
507static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd); 371static int ahd_linux_run_command(struct ahd_softc*,
508static void ahd_linux_device_queue_depth(struct ahd_softc *ahd, 372 struct ahd_linux_device *,
509 struct ahd_linux_device *dev); 373 struct scsi_cmnd *);
510static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*,
511 u_int, u_int);
512static void ahd_linux_free_target(struct ahd_softc*,
513 struct ahd_linux_target*);
514static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*,
515 struct ahd_linux_target*,
516 u_int);
517static void ahd_linux_free_device(struct ahd_softc*,
518 struct ahd_linux_device*);
519static void ahd_linux_run_device_queue(struct ahd_softc*,
520 struct ahd_linux_device*);
521static void ahd_linux_setup_tag_info_global(char *p); 374static void ahd_linux_setup_tag_info_global(char *p);
522static aic_option_callback_t ahd_linux_setup_tag_info; 375static aic_option_callback_t ahd_linux_setup_tag_info;
523static aic_option_callback_t ahd_linux_setup_rd_strm_info;
524static aic_option_callback_t ahd_linux_setup_dv;
525static aic_option_callback_t ahd_linux_setup_iocell_info; 376static aic_option_callback_t ahd_linux_setup_iocell_info;
526static int ahd_linux_next_unit(void); 377static int aic79xx_setup(char *c);
527static void ahd_runq_tasklet(unsigned long data);
528static int aic79xx_setup(char *c);
529
530/****************************** Inlines ***************************************/
531static __inline void ahd_schedule_completeq(struct ahd_softc *ahd);
532static __inline void ahd_schedule_runq(struct ahd_softc *ahd);
533static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd);
534static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd);
535static __inline struct ahd_linux_device*
536 ahd_linux_get_device(struct ahd_softc *ahd, u_int channel,
537 u_int target, u_int lun, int alloc);
538static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd);
539static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd,
540 struct ahd_linux_device *dev);
541static __inline struct ahd_linux_device *
542 ahd_linux_next_device_to_run(struct ahd_softc *ahd);
543static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd);
544static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
545
546static __inline void
547ahd_schedule_completeq(struct ahd_softc *ahd)
548{
549 if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) {
550 ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER;
551 ahd->platform_data->completeq_timer.expires = jiffies;
552 add_timer(&ahd->platform_data->completeq_timer);
553 }
554}
555
556/*
557 * Must be called with our lock held.
558 */
559static __inline void
560ahd_schedule_runq(struct ahd_softc *ahd)
561{
562 tasklet_schedule(&ahd->platform_data->runq_tasklet);
563}
564
565static __inline
566void ahd_setup_runq_tasklet(struct ahd_softc *ahd)
567{
568 tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet,
569 (unsigned long)ahd);
570}
571 378
572static __inline void 379static int ahd_linux_unit;
573ahd_teardown_runq_tasklet(struct ahd_softc *ahd)
574{
575 tasklet_kill(&ahd->platform_data->runq_tasklet);
576}
577 380
578static __inline struct ahd_linux_device*
579ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target,
580 u_int lun, int alloc)
581{
582 struct ahd_linux_target *targ;
583 struct ahd_linux_device *dev;
584 u_int target_offset;
585 381
586 target_offset = target; 382/****************************** Inlines ***************************************/
587 if (channel != 0) 383static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
588 target_offset += 8;
589 targ = ahd->platform_data->targets[target_offset];
590 if (targ == NULL) {
591 if (alloc != 0) {
592 targ = ahd_linux_alloc_target(ahd, channel, target);
593 if (targ == NULL)
594 return (NULL);
595 } else
596 return (NULL);
597 }
598 dev = targ->devices[lun];
599 if (dev == NULL && alloc != 0)
600 dev = ahd_linux_alloc_device(ahd, targ, lun);
601 return (dev);
602}
603
604#define AHD_LINUX_MAX_RETURNED_ERRORS 4
605static struct ahd_cmd *
606ahd_linux_run_complete_queue(struct ahd_softc *ahd)
607{
608 struct ahd_cmd *acmd;
609 u_long done_flags;
610 int with_errors;
611
612 with_errors = 0;
613 ahd_done_lock(ahd, &done_flags);
614 while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) {
615 Scsi_Cmnd *cmd;
616
617 if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) {
618 /*
619 * Linux uses stack recursion to requeue
620 * commands that need to be retried. Avoid
621 * blowing out the stack by "spoon feeding"
622 * commands that completed with error back
623 * the operating system in case they are going
624 * to be retried. "ick"
625 */
626 ahd_schedule_completeq(ahd);
627 break;
628 }
629 TAILQ_REMOVE(&ahd->platform_data->completeq,
630 acmd, acmd_links.tqe);
631 cmd = &acmd_scsi_cmd(acmd);
632 cmd->host_scribble = NULL;
633 if (ahd_cmd_get_transaction_status(cmd) != DID_OK
634 || (cmd->result & 0xFF) != SCSI_STATUS_OK)
635 with_errors++;
636
637 cmd->scsi_done(cmd);
638 }
639 ahd_done_unlock(ahd, &done_flags);
640 return (acmd);
641}
642
643static __inline void
644ahd_linux_check_device_queue(struct ahd_softc *ahd,
645 struct ahd_linux_device *dev)
646{
647 if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) != 0
648 && dev->active == 0) {
649 dev->flags &= ~AHD_DEV_FREEZE_TIL_EMPTY;
650 dev->qfrozen--;
651 }
652
653 if (TAILQ_FIRST(&dev->busyq) == NULL
654 || dev->openings == 0 || dev->qfrozen != 0)
655 return;
656
657 ahd_linux_run_device_queue(ahd, dev);
658}
659
660static __inline struct ahd_linux_device *
661ahd_linux_next_device_to_run(struct ahd_softc *ahd)
662{
663
664 if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0
665 || (ahd->platform_data->qfrozen != 0
666 && AHD_DV_SIMQ_FROZEN(ahd) == 0))
667 return (NULL);
668 return (TAILQ_FIRST(&ahd->platform_data->device_runq));
669}
670
671static __inline void
672ahd_linux_run_device_queues(struct ahd_softc *ahd)
673{
674 struct ahd_linux_device *dev;
675
676 while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
677 TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
678 dev->flags &= ~AHD_DEV_ON_RUN_LIST;
679 ahd_linux_check_device_queue(ahd, dev);
680 }
681}
682 384
683static __inline void 385static __inline void
684ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) 386ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
685{ 387{
686 Scsi_Cmnd *cmd; 388 struct scsi_cmnd *cmd;
687 int direction; 389 int direction;
688 390
689 cmd = scb->io_ctx; 391 cmd = scb->io_ctx;
@@ -705,197 +407,6 @@ ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
705#define BUILD_SCSIID(ahd, cmd) \ 407#define BUILD_SCSIID(ahd, cmd) \
706 ((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id) 408 ((((cmd)->device->id << TID_SHIFT) & TID) | (ahd)->our_id)
707 409
708/************************ Host template entry points *************************/
709static int ahd_linux_detect(Scsi_Host_Template *);
710static const char *ahd_linux_info(struct Scsi_Host *);
711static int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
712#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
713static int ahd_linux_slave_alloc(Scsi_Device *);
714static int ahd_linux_slave_configure(Scsi_Device *);
715static void ahd_linux_slave_destroy(Scsi_Device *);
716#if defined(__i386__)
717static int ahd_linux_biosparam(struct scsi_device*,
718 struct block_device*, sector_t, int[]);
719#endif
720#else
721static int ahd_linux_release(struct Scsi_Host *);
722static void ahd_linux_select_queue_depth(struct Scsi_Host *host,
723 Scsi_Device *scsi_devs);
724#if defined(__i386__)
725static int ahd_linux_biosparam(Disk *, kdev_t, int[]);
726#endif
727#endif
728static int ahd_linux_bus_reset(Scsi_Cmnd *);
729static int ahd_linux_dev_reset(Scsi_Cmnd *);
730static int ahd_linux_abort(Scsi_Cmnd *);
731
732/*
733 * Calculate a safe value for AHD_NSEG (as expressed through ahd_linux_nseg).
734 *
735 * In pre-2.5.X...
736 * The midlayer allocates an S/G array dynamically when a command is issued
737 * using SCSI malloc. This array, which is in an OS dependent format that
738 * must later be copied to our private S/G list, is sized to house just the
739 * number of segments needed for the current transfer. Since the code that
740 * sizes the SCSI malloc pool does not take into consideration fragmentation
741 * of the pool, executing transactions numbering just a fraction of our
742 * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will
743 * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the
744 * mid-layer does not properly handle this scsi malloc failures for the S/G
745 * array and the result can be a lockup of the I/O subsystem. We try to size
746 * our S/G list so that it satisfies our drivers allocation requirements in
747 * addition to avoiding fragmentation of the SCSI malloc pool.
748 */
749static void
750ahd_linux_size_nseg(void)
751{
752#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
753 u_int cur_size;
754 u_int best_size;
755
756 /*
757 * The SCSI allocator rounds to the nearest 512 bytes
758 * an cannot allocate across a page boundary. Our algorithm
759 * is to start at 1K of scsi malloc space per-command and
760 * loop through all factors of the PAGE_SIZE and pick the best.
761 */
762 best_size = 0;
763 for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
764 u_int nseg;
765
766 nseg = cur_size / sizeof(struct scatterlist);
767 if (nseg < AHD_LINUX_MIN_NSEG)
768 continue;
769
770 if (best_size == 0) {
771 best_size = cur_size;
772 ahd_linux_nseg = nseg;
773 } else {
774 u_int best_rem;
775 u_int cur_rem;
776
777 /*
778 * Compare the traits of the current "best_size"
779 * with the current size to determine if the
780 * current size is a better size.
781 */
782 best_rem = best_size % sizeof(struct scatterlist);
783 cur_rem = cur_size % sizeof(struct scatterlist);
784 if (cur_rem < best_rem) {
785 best_size = cur_size;
786 ahd_linux_nseg = nseg;
787 }
788 }
789 }
790#endif
791}
792
793/*
794 * Try to detect an Adaptec 79XX controller.
795 */
796static int
797ahd_linux_detect(Scsi_Host_Template *template)
798{
799 struct ahd_softc *ahd;
800 int found;
801 int error = 0;
802
803#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
804 /*
805 * It is a bug that the upper layer takes
806 * this lock just prior to calling us.
807 */
808 spin_unlock_irq(&io_request_lock);
809#endif
810
811 /*
812 * Sanity checking of Linux SCSI data structures so
813 * that some of our hacks^H^H^H^H^Hassumptions aren't
814 * violated.
815 */
816 if (offsetof(struct ahd_cmd_internal, end)
817 > offsetof(struct scsi_cmnd, host_scribble)) {
818 printf("ahd_linux_detect: SCSI data structures changed.\n");
819 printf("ahd_linux_detect: Unable to attach\n");
820 return (0);
821 }
822 /*
823 * Determine an appropriate size for our Scatter Gatther lists.
824 */
825 ahd_linux_size_nseg();
826#ifdef MODULE
827 /*
828 * If we've been passed any parameters, process them now.
829 */
830 if (aic79xx)
831 aic79xx_setup(aic79xx);
832#endif
833
834 template->proc_name = "aic79xx";
835
836 /*
837 * Initialize our softc list lock prior to
838 * probing for any adapters.
839 */
840 ahd_list_lockinit();
841
842#ifdef CONFIG_PCI
843 error = ahd_linux_pci_init();
844 if (error)
845 return error;
846#endif
847
848 /*
849 * Register with the SCSI layer all
850 * controllers we've found.
851 */
852 found = 0;
853 TAILQ_FOREACH(ahd, &ahd_tailq, links) {
854
855 if (ahd_linux_register_host(ahd, template) == 0)
856 found++;
857 }
858#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
859 spin_lock_irq(&io_request_lock);
860#endif
861 aic79xx_detect_complete++;
862 return 0;
863}
864
865#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
866/*
867 * Free the passed in Scsi_Host memory structures prior to unloading the
868 * module.
869 */
870static int
871ahd_linux_release(struct Scsi_Host * host)
872{
873 struct ahd_softc *ahd;
874 u_long l;
875
876 ahd_list_lock(&l);
877 if (host != NULL) {
878
879 /*
880 * We should be able to just perform
881 * the free directly, but check our
882 * list for extra sanity.
883 */
884 ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata);
885 if (ahd != NULL) {
886 u_long s;
887
888 ahd_lock(ahd, &s);
889 ahd_intr_enable(ahd, FALSE);
890 ahd_unlock(ahd, &s);
891 ahd_free(ahd);
892 }
893 }
894 ahd_list_unlock(&l);
895 return (0);
896}
897#endif
898
899/* 410/*
900 * Return a string describing the driver. 411 * Return a string describing the driver.
901 */ 412 */
@@ -928,220 +439,177 @@ ahd_linux_info(struct Scsi_Host *host)
928 * Queue an SCB to the controller. 439 * Queue an SCB to the controller.
929 */ 440 */
930static int 441static int
931ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) 442ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
932{ 443{
933 struct ahd_softc *ahd; 444 struct ahd_softc *ahd;
934 struct ahd_linux_device *dev; 445 struct ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
935 u_long flags;
936 446
937 ahd = *(struct ahd_softc **)cmd->device->host->hostdata; 447 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
938 448
939 /* 449 /*
940 * Save the callback on completion function.
941 */
942 cmd->scsi_done = scsi_done;
943
944 ahd_midlayer_entrypoint_lock(ahd, &flags);
945
946 /*
947 * Close the race of a command that was in the process of 450 * Close the race of a command that was in the process of
948 * being queued to us just as our simq was frozen. Let 451 * being queued to us just as our simq was frozen. Let
949 * DV commands through so long as we are only frozen to 452 * DV commands through so long as we are only frozen to
950 * perform DV. 453 * perform DV.
951 */ 454 */
952 if (ahd->platform_data->qfrozen != 0 455 if (ahd->platform_data->qfrozen != 0) {
953 && AHD_DV_CMD(cmd) == 0) { 456 printf("%s: queue frozen\n", ahd_name(ahd));
954 457
955 ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); 458 return SCSI_MLQUEUE_HOST_BUSY;
956 ahd_linux_queue_cmd_complete(ahd, cmd);
957 ahd_schedule_completeq(ahd);
958 ahd_midlayer_entrypoint_unlock(ahd, &flags);
959 return (0);
960 }
961 dev = ahd_linux_get_device(ahd, cmd->device->channel,
962 cmd->device->id, cmd->device->lun,
963 /*alloc*/TRUE);
964 if (dev == NULL) {
965 ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
966 ahd_linux_queue_cmd_complete(ahd, cmd);
967 ahd_schedule_completeq(ahd);
968 ahd_midlayer_entrypoint_unlock(ahd, &flags);
969 printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",
970 ahd_name(ahd));
971 return (0);
972 } 459 }
973 if (cmd->cmd_len > MAX_CDB_LEN) 460
974 return (-EINVAL); 461 /*
462 * Save the callback on completion function.
463 */
464 cmd->scsi_done = scsi_done;
465
975 cmd->result = CAM_REQ_INPROG << 16; 466 cmd->result = CAM_REQ_INPROG << 16;
976 TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe); 467
977 if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { 468 return ahd_linux_run_command(ahd, dev, cmd);
978 TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); 469}
979 dev->flags |= AHD_DEV_ON_RUN_LIST; 470
980 ahd_linux_run_device_queues(ahd); 471static inline struct scsi_target **
981 } 472ahd_linux_target_in_softc(struct scsi_target *starget)
982 ahd_midlayer_entrypoint_unlock(ahd, &flags); 473{
983 return (0); 474 struct ahd_softc *ahd =
475 *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
476 unsigned int target_offset;
477
478 target_offset = starget->id;
479 if (starget->channel != 0)
480 target_offset += 8;
481
482 return &ahd->platform_data->starget[target_offset];
984} 483}
985 484
986#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
987static int 485static int
988ahd_linux_slave_alloc(Scsi_Device *device) 486ahd_linux_target_alloc(struct scsi_target *starget)
989{ 487{
990 struct ahd_softc *ahd; 488 struct ahd_softc *ahd =
489 *((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
490 unsigned long flags;
491 struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
492 struct ahd_linux_target *targ = scsi_transport_target_data(starget);
493 struct ahd_devinfo devinfo;
494 struct ahd_initiator_tinfo *tinfo;
495 struct ahd_tmode_tstate *tstate;
496 char channel = starget->channel + 'A';
991 497
992 ahd = *((struct ahd_softc **)device->host->hostdata); 498 ahd_lock(ahd, &flags);
993 if (bootverbose) 499
994 printf("%s: Slave Alloc %d\n", ahd_name(ahd), device->id); 500 BUG_ON(*ahd_targp != NULL);
995 return (0); 501
502 *ahd_targp = starget;
503 memset(targ, 0, sizeof(*targ));
504
505 tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
506 starget->id, &tstate);
507 ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id,
508 CAM_LUN_WILDCARD, channel,
509 ROLE_INITIATOR);
510 spi_min_period(starget) = AHD_SYNCRATE_MAX; /* We can do U320 */
511 if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
512 spi_max_offset(starget) = MAX_OFFSET_PACED_BUG;
513 else
514 spi_max_offset(starget) = MAX_OFFSET_PACED;
515 spi_max_width(starget) = ahd->features & AHD_WIDE;
516
517 ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
518 AHD_TRANS_GOAL, /*paused*/FALSE);
519 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
520 AHD_TRANS_GOAL, /*paused*/FALSE);
521 ahd_unlock(ahd, &flags);
522
523 return 0;
524}
525
526static void
527ahd_linux_target_destroy(struct scsi_target *starget)
528{
529 struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
530
531 *ahd_targp = NULL;
996} 532}
997 533
998static int 534static int
999ahd_linux_slave_configure(Scsi_Device *device) 535ahd_linux_slave_alloc(struct scsi_device *sdev)
1000{ 536{
1001 struct ahd_softc *ahd; 537 struct ahd_softc *ahd =
1002 struct ahd_linux_device *dev; 538 *((struct ahd_softc **)sdev->host->hostdata);
1003 u_long flags; 539 struct scsi_target *starget = sdev->sdev_target;
540 struct ahd_linux_target *targ = scsi_transport_target_data(starget);
541 struct ahd_linux_device *dev;
1004 542
1005 ahd = *((struct ahd_softc **)device->host->hostdata);
1006 if (bootverbose) 543 if (bootverbose)
1007 printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id); 544 printf("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id);
1008 ahd_midlayer_entrypoint_lock(ahd, &flags); 545
546 BUG_ON(targ->sdev[sdev->lun] != NULL);
547
548 dev = scsi_transport_device_data(sdev);
549 memset(dev, 0, sizeof(*dev));
550
1009 /* 551 /*
1010 * Since Linux has attached to the device, configure 552 * We start out life using untagged
1011 * it so we don't free and allocate the device 553 * transactions of which we allow one.
1012 * structure on every command.
1013 */ 554 */
1014 dev = ahd_linux_get_device(ahd, device->channel, 555 dev->openings = 1;
1015 device->id, device->lun, 556
1016 /*alloc*/TRUE); 557 /*
1017 if (dev != NULL) { 558 * Set maxtags to 0. This will be changed if we
1018 dev->flags &= ~AHD_DEV_UNCONFIGURED; 559 * later determine that we are dealing with
1019 dev->flags |= AHD_DEV_SLAVE_CONFIGURED; 560 * a tagged queuing capable device.
1020 dev->scsi_device = device; 561 */
1021 ahd_linux_device_queue_depth(ahd, dev); 562 dev->maxtags = 0;
1022 } 563
1023 ahd_midlayer_entrypoint_unlock(ahd, &flags); 564 targ->sdev[sdev->lun] = sdev;
565
1024 return (0); 566 return (0);
1025} 567}
1026 568
1027static void 569static int
1028ahd_linux_slave_destroy(Scsi_Device *device) 570ahd_linux_slave_configure(struct scsi_device *sdev)
1029{ 571{
1030 struct ahd_softc *ahd; 572 struct ahd_softc *ahd;
1031 struct ahd_linux_device *dev;
1032 u_long flags;
1033 573
1034 ahd = *((struct ahd_softc **)device->host->hostdata); 574 ahd = *((struct ahd_softc **)sdev->host->hostdata);
1035 if (bootverbose) 575 if (bootverbose)
1036 printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id); 576 printf("%s: Slave Configure %d\n", ahd_name(ahd), sdev->id);
1037 ahd_midlayer_entrypoint_lock(ahd, &flags);
1038 dev = ahd_linux_get_device(ahd, device->channel,
1039 device->id, device->lun,
1040 /*alloc*/FALSE);
1041 577
1042 /* 578 ahd_linux_device_queue_depth(sdev);
1043 * Filter out "silly" deletions of real devices by only 579
1044 * deleting devices that have had slave_configure() 580 /* Initial Domain Validation */
1045 * called on them. All other devices that have not 581 if (!spi_initial_dv(sdev->sdev_target))
1046 * been configured will automatically be deleted by 582 spi_dv_device(sdev);
1047 * the refcounting process. 583
1048 */ 584 return 0;
1049 if (dev != NULL
1050 && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) {
1051 dev->flags |= AHD_DEV_UNCONFIGURED;
1052 if (TAILQ_EMPTY(&dev->busyq)
1053 && dev->active == 0
1054 && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
1055 ahd_linux_free_device(ahd, dev);
1056 }
1057 ahd_midlayer_entrypoint_unlock(ahd, &flags);
1058} 585}
1059#else 586
1060/*
1061 * Sets the queue depth for each SCSI device hanging
1062 * off the input host adapter.
1063 */
1064static void 587static void
1065ahd_linux_select_queue_depth(struct Scsi_Host * host, 588ahd_linux_slave_destroy(struct scsi_device *sdev)
1066 Scsi_Device * scsi_devs)
1067{ 589{
1068 Scsi_Device *device;
1069 Scsi_Device *ldev;
1070 struct ahd_softc *ahd; 590 struct ahd_softc *ahd;
1071 u_long flags; 591 struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
592 struct ahd_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);
1072 593
1073 ahd = *((struct ahd_softc **)host->hostdata); 594 ahd = *((struct ahd_softc **)sdev->host->hostdata);
1074 ahd_lock(ahd, &flags); 595 if (bootverbose)
1075 for (device = scsi_devs; device != NULL; device = device->next) { 596 printf("%s: Slave Destroy %d\n", ahd_name(ahd), sdev->id);
1076 597
1077 /* 598 BUG_ON(dev->active);
1078 * Watch out for duplicate devices. This works around
1079 * some quirks in how the SCSI scanning code does its
1080 * device management.
1081 */
1082 for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {
1083 if (ldev->host == device->host
1084 && ldev->channel == device->channel
1085 && ldev->id == device->id
1086 && ldev->lun == device->lun)
1087 break;
1088 }
1089 /* Skip duplicate. */
1090 if (ldev != device)
1091 continue;
1092 599
1093 if (device->host == host) { 600 targ->sdev[sdev->lun] = NULL;
1094 struct ahd_linux_device *dev;
1095 601
1096 /*
1097 * Since Linux has attached to the device, configure
1098 * it so we don't free and allocate the device
1099 * structure on every command.
1100 */
1101 dev = ahd_linux_get_device(ahd, device->channel,
1102 device->id, device->lun,
1103 /*alloc*/TRUE);
1104 if (dev != NULL) {
1105 dev->flags &= ~AHD_DEV_UNCONFIGURED;
1106 dev->scsi_device = device;
1107 ahd_linux_device_queue_depth(ahd, dev);
1108 device->queue_depth = dev->openings
1109 + dev->active;
1110 if ((dev->flags & (AHD_DEV_Q_BASIC
1111 | AHD_DEV_Q_TAGGED)) == 0) {
1112 /*
1113 * We allow the OS to queue 2 untagged
1114 * transactions to us at any time even
1115 * though we can only execute them
1116 * serially on the controller/device.
1117 * This should remove some latency.
1118 */
1119 device->queue_depth = 2;
1120 }
1121 }
1122 }
1123 }
1124 ahd_unlock(ahd, &flags);
1125} 602}
1126#endif
1127 603
1128#if defined(__i386__) 604#if defined(__i386__)
1129/* 605/*
1130 * Return the disk geometry for the given SCSI device. 606 * Return the disk geometry for the given SCSI device.
1131 */ 607 */
1132static int 608static int
1133#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1134ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, 609ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
1135 sector_t capacity, int geom[]) 610 sector_t capacity, int geom[])
1136{ 611{
1137 uint8_t *bh; 612 uint8_t *bh;
1138#else
1139ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
1140{
1141 struct scsi_device *sdev = disk->device;
1142 u_long capacity = disk->capacity;
1143 struct buffer_head *bh;
1144#endif
1145 int heads; 613 int heads;
1146 int sectors; 614 int sectors;
1147 int cylinders; 615 int cylinders;
@@ -1151,22 +619,11 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
1151 619
1152 ahd = *((struct ahd_softc **)sdev->host->hostdata); 620 ahd = *((struct ahd_softc **)sdev->host->hostdata);
1153 621
1154#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1155 bh = scsi_bios_ptable(bdev); 622 bh = scsi_bios_ptable(bdev);
1156#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
1157 bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));
1158#else
1159 bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024);
1160#endif
1161
1162 if (bh) { 623 if (bh) {
1163 ret = scsi_partsize(bh, capacity, 624 ret = scsi_partsize(bh, capacity,
1164 &geom[2], &geom[0], &geom[1]); 625 &geom[2], &geom[0], &geom[1]);
1165#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1166 kfree(bh); 626 kfree(bh);
1167#else
1168 brelse(bh);
1169#endif
1170 if (ret != -1) 627 if (ret != -1)
1171 return (ret); 628 return (ret);
1172 } 629 }
@@ -1194,392 +651,35 @@ ahd_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
1194 * Abort the current SCSI command(s). 651 * Abort the current SCSI command(s).
1195 */ 652 */
1196static int 653static int
1197ahd_linux_abort(Scsi_Cmnd *cmd) 654ahd_linux_abort(struct scsi_cmnd *cmd)
1198{ 655{
1199 struct ahd_softc *ahd; 656 int error;
1200 struct ahd_cmd *acmd;
1201 struct ahd_cmd *list_acmd;
1202 struct ahd_linux_device *dev;
1203 struct scb *pending_scb;
1204 u_long s;
1205 u_int saved_scbptr;
1206 u_int active_scbptr;
1207 u_int last_phase;
1208 u_int cdb_byte;
1209 int retval;
1210 int was_paused;
1211 int paused;
1212 int wait;
1213 int disconnected;
1214 ahd_mode_state saved_modes;
1215
1216 pending_scb = NULL;
1217 paused = FALSE;
1218 wait = FALSE;
1219 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
1220 acmd = (struct ahd_cmd *)cmd;
1221
1222 printf("%s:%d:%d:%d: Attempting to abort cmd %p:",
1223 ahd_name(ahd), cmd->device->channel, cmd->device->id,
1224 cmd->device->lun, cmd);
1225 for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
1226 printf(" 0x%x", cmd->cmnd[cdb_byte]);
1227 printf("\n");
1228
1229 /*
1230 * In all versions of Linux, we have to work around
1231 * a major flaw in how the mid-layer is locked down
1232 * if we are to sleep successfully in our error handler
1233 * while allowing our interrupt handler to run. Since
1234 * the midlayer acquires either the io_request_lock or
1235 * our lock prior to calling us, we must use the
1236 * spin_unlock_irq() method for unlocking our lock.
1237 * This will force interrupts to be enabled on the
1238 * current CPU. Since the EH thread should not have
1239 * been running with CPU interrupts disabled other than
1240 * by acquiring either the io_request_lock or our own
1241 * lock, this *should* be safe.
1242 */
1243 ahd_midlayer_entrypoint_lock(ahd, &s);
1244
1245 /*
1246 * First determine if we currently own this command.
1247 * Start by searching the device queue. If not found
1248 * there, check the pending_scb list. If not found
1249 * at all, and the system wanted us to just abort the
1250 * command, return success.
1251 */
1252 dev = ahd_linux_get_device(ahd, cmd->device->channel,
1253 cmd->device->id, cmd->device->lun,
1254 /*alloc*/FALSE);
1255
1256 if (dev == NULL) {
1257 /*
1258 * No target device for this command exists,
1259 * so we must not still own the command.
1260 */
1261 printf("%s:%d:%d:%d: Is not an active device\n",
1262 ahd_name(ahd), cmd->device->channel, cmd->device->id,
1263 cmd->device->lun);
1264 retval = SUCCESS;
1265 goto no_cmd;
1266 }
1267
1268 TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) {
1269 if (list_acmd == acmd)
1270 break;
1271 }
1272
1273 if (list_acmd != NULL) {
1274 printf("%s:%d:%d:%d: Command found on device queue\n",
1275 ahd_name(ahd), cmd->device->channel, cmd->device->id,
1276 cmd->device->lun);
1277 TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
1278 cmd->result = DID_ABORT << 16;
1279 ahd_linux_queue_cmd_complete(ahd, cmd);
1280 retval = SUCCESS;
1281 goto done;
1282 }
1283
1284 /*
1285 * See if we can find a matching cmd in the pending list.
1286 */
1287 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
1288 if (pending_scb->io_ctx == cmd)
1289 break;
1290 }
1291
1292 if (pending_scb == NULL) {
1293 printf("%s:%d:%d:%d: Command not found\n",
1294 ahd_name(ahd), cmd->device->channel, cmd->device->id,
1295 cmd->device->lun);
1296 goto no_cmd;
1297 }
1298
1299 if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
1300 /*
1301 * We can't queue two recovery actions using the same SCB
1302 */
1303 retval = FAILED;
1304 goto done;
1305 }
1306
1307 /*
1308 * Ensure that the card doesn't do anything
1309 * behind our back. Also make sure that we
1310 * didn't "just" miss an interrupt that would
1311 * affect this cmd.
1312 */
1313 was_paused = ahd_is_paused(ahd);
1314 ahd_pause_and_flushwork(ahd);
1315 paused = TRUE;
1316
1317 if ((pending_scb->flags & SCB_ACTIVE) == 0) {
1318 printf("%s:%d:%d:%d: Command already completed\n",
1319 ahd_name(ahd), cmd->device->channel, cmd->device->id,
1320 cmd->device->lun);
1321 goto no_cmd;
1322 }
1323
1324 printf("%s: At time of recovery, card was %spaused\n",
1325 ahd_name(ahd), was_paused ? "" : "not ");
1326 ahd_dump_card_state(ahd);
1327
1328 disconnected = TRUE;
1329 if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A',
1330 cmd->device->lun, SCB_GET_TAG(pending_scb),
1331 ROLE_INITIATOR, CAM_REQ_ABORTED,
1332 SEARCH_COMPLETE) > 0) {
1333 printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
1334 ahd_name(ahd), cmd->device->channel, cmd->device->id,
1335 cmd->device->lun);
1336 retval = SUCCESS;
1337 goto done;
1338 }
1339
1340 saved_modes = ahd_save_modes(ahd);
1341 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
1342 last_phase = ahd_inb(ahd, LASTPHASE);
1343 saved_scbptr = ahd_get_scbptr(ahd);
1344 active_scbptr = saved_scbptr;
1345 if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
1346 struct scb *bus_scb;
1347
1348 bus_scb = ahd_lookup_scb(ahd, active_scbptr);
1349 if (bus_scb == pending_scb)
1350 disconnected = FALSE;
1351 }
1352
1353 /*
1354 * At this point, pending_scb is the scb associated with the
1355 * passed in command. That command is currently active on the
1356 * bus or is in the disconnected state.
1357 */
1358 if (last_phase != P_BUSFREE
1359 && SCB_GET_TAG(pending_scb) == active_scbptr) {
1360
1361 /*
1362 * We're active on the bus, so assert ATN
1363 * and hope that the target responds.
1364 */
1365 pending_scb = ahd_lookup_scb(ahd, active_scbptr);
1366 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
1367 ahd_outb(ahd, MSG_OUT, HOST_MSG);
1368 ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
1369 printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
1370 ahd_name(ahd), cmd->device->channel,
1371 cmd->device->id, cmd->device->lun);
1372 wait = TRUE;
1373 } else if (disconnected) {
1374
1375 /*
1376 * Actually re-queue this SCB in an attempt
1377 * to select the device before it reconnects.
1378 */
1379 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
1380 ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
1381 pending_scb->hscb->cdb_len = 0;
1382 pending_scb->hscb->task_attribute = 0;
1383 pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
1384
1385 if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
1386 /*
1387 * Mark the SCB has having an outstanding
1388 * task management function. Should the command
1389 * complete normally before the task management
1390 * function can be sent, the host will be notified
1391 * to abort our requeued SCB.
1392 */
1393 ahd_outb(ahd, SCB_TASK_MANAGEMENT,
1394 pending_scb->hscb->task_management);
1395 } else {
1396 /*
1397 * If non-packetized, set the MK_MESSAGE control
1398 * bit indicating that we desire to send a message.
1399 * We also set the disconnected flag since there is
1400 * no guarantee that our SCB control byte matches
1401 * the version on the card. We don't want the
1402 * sequencer to abort the command thinking an
1403 * unsolicited reselection occurred.
1404 */
1405 pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
1406
1407 /*
1408 * The sequencer will never re-reference the
1409 * in-core SCB. To make sure we are notified
1410 * during reslection, set the MK_MESSAGE flag in
1411 * the card's copy of the SCB.
1412 */
1413 ahd_outb(ahd, SCB_CONTROL,
1414 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
1415 }
1416
1417 /*
1418 * Clear out any entries in the QINFIFO first
1419 * so we are the next SCB for this target
1420 * to run.
1421 */
1422 ahd_search_qinfifo(ahd, cmd->device->id,
1423 cmd->device->channel + 'A', cmd->device->lun,
1424 SCB_LIST_NULL, ROLE_INITIATOR,
1425 CAM_REQUEUE_REQ, SEARCH_COMPLETE);
1426 ahd_qinfifo_requeue_tail(ahd, pending_scb);
1427 ahd_set_scbptr(ahd, saved_scbptr);
1428 ahd_print_path(ahd, pending_scb);
1429 printf("Device is disconnected, re-queuing SCB\n");
1430 wait = TRUE;
1431 } else {
1432 printf("%s:%d:%d:%d: Unable to deliver message\n",
1433 ahd_name(ahd), cmd->device->channel,
1434 cmd->device->id, cmd->device->lun);
1435 retval = FAILED;
1436 goto done;
1437 }
1438
1439no_cmd:
1440 /*
1441 * Our assumption is that if we don't have the command, no
1442 * recovery action was required, so we return success. Again,
1443 * the semantics of the mid-layer recovery engine are not
1444 * well defined, so this may change in time.
1445 */
1446 retval = SUCCESS;
1447done:
1448 if (paused)
1449 ahd_unpause(ahd);
1450 if (wait) {
1451 struct timer_list timer;
1452 int ret;
1453 657
1454 pending_scb->platform_data->flags |= AHD_SCB_UP_EH_SEM; 658 error = ahd_linux_queue_recovery_cmd(cmd, SCB_ABORT);
1455 spin_unlock_irq(&ahd->platform_data->spin_lock); 659 if (error != 0)
1456 init_timer(&timer); 660 printf("aic79xx_abort returns 0x%x\n", error);
1457 timer.data = (u_long)pending_scb; 661 return error;
1458 timer.expires = jiffies + (5 * HZ);
1459 timer.function = ahd_linux_sem_timeout;
1460 add_timer(&timer);
1461 printf("Recovery code sleeping\n");
1462 down(&ahd->platform_data->eh_sem);
1463 printf("Recovery code awake\n");
1464 ret = del_timer_sync(&timer);
1465 if (ret == 0) {
1466 printf("Timer Expired\n");
1467 retval = FAILED;
1468 }
1469 spin_lock_irq(&ahd->platform_data->spin_lock);
1470 }
1471 ahd_schedule_runq(ahd);
1472 ahd_linux_run_complete_queue(ahd);
1473 ahd_midlayer_entrypoint_unlock(ahd, &s);
1474 return (retval);
1475}
1476
1477
1478static void
1479ahd_linux_dev_reset_complete(Scsi_Cmnd *cmd)
1480{
1481 free(cmd, M_DEVBUF);
1482} 662}
1483 663
1484/* 664/*
1485 * Attempt to send a target reset message to the device that timed out. 665 * Attempt to send a target reset message to the device that timed out.
1486 */ 666 */
1487static int 667static int
1488ahd_linux_dev_reset(Scsi_Cmnd *cmd) 668ahd_linux_dev_reset(struct scsi_cmnd *cmd)
1489{ 669{
1490 struct ahd_softc *ahd; 670 int error;
1491 struct scsi_cmnd *recovery_cmd;
1492 struct ahd_linux_device *dev;
1493 struct ahd_initiator_tinfo *tinfo;
1494 struct ahd_tmode_tstate *tstate;
1495 struct scb *scb;
1496 struct hardware_scb *hscb;
1497 u_long s;
1498 struct timer_list timer;
1499 int retval;
1500 671
1501 ahd = *(struct ahd_softc **)cmd->device->host->hostdata; 672 error = ahd_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
1502 recovery_cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK); 673 if (error != 0)
1503 if (!recovery_cmd) 674 printf("aic79xx_dev_reset returns 0x%x\n", error);
1504 return (FAILED); 675 return error;
1505 memset(recovery_cmd, 0, sizeof(struct scsi_cmnd));
1506 recovery_cmd->device = cmd->device;
1507 recovery_cmd->scsi_done = ahd_linux_dev_reset_complete;
1508#ifdef AHD_DEBUG
1509 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
1510 printf("%s:%d:%d:%d: Device reset called for cmd %p\n",
1511 ahd_name(ahd), cmd->device->channel, cmd->device->id,
1512 cmd->device->lun, cmd);
1513#endif
1514 ahd_lock(ahd, &s);
1515
1516 dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id,
1517 cmd->device->lun, /*alloc*/FALSE);
1518 if (dev == NULL) {
1519 ahd_unlock(ahd, &s);
1520 kfree(recovery_cmd);
1521 return (FAILED);
1522 }
1523 if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) {
1524 ahd_unlock(ahd, &s);
1525 kfree(recovery_cmd);
1526 return (FAILED);
1527 }
1528 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
1529 cmd->device->id, &tstate);
1530 recovery_cmd->result = CAM_REQ_INPROG << 16;
1531 recovery_cmd->host_scribble = (char *)scb;
1532 scb->io_ctx = recovery_cmd;
1533 scb->platform_data->dev = dev;
1534 scb->sg_count = 0;
1535 ahd_set_residual(scb, 0);
1536 ahd_set_sense_residual(scb, 0);
1537 hscb = scb->hscb;
1538 hscb->control = 0;
1539 hscb->scsiid = BUILD_SCSIID(ahd, cmd);
1540 hscb->lun = cmd->device->lun;
1541 hscb->cdb_len = 0;
1542 hscb->task_management = SIU_TASKMGMT_LUN_RESET;
1543 scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE;
1544 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
1545 scb->flags |= SCB_PACKETIZED;
1546 } else {
1547 hscb->control |= MK_MESSAGE;
1548 }
1549 dev->openings--;
1550 dev->active++;
1551 dev->commands_issued++;
1552 LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
1553 ahd_queue_scb(ahd, scb);
1554
1555 scb->platform_data->flags |= AHD_SCB_UP_EH_SEM;
1556 ahd_unlock(ahd, &s);
1557 init_timer(&timer);
1558 timer.data = (u_long)scb;
1559 timer.expires = jiffies + (5 * HZ);
1560 timer.function = ahd_linux_sem_timeout;
1561 add_timer(&timer);
1562 printf("Recovery code sleeping\n");
1563 down(&ahd->platform_data->eh_sem);
1564 printf("Recovery code awake\n");
1565 retval = SUCCESS;
1566 if (del_timer_sync(&timer) == 0) {
1567 printf("Timer Expired\n");
1568 retval = FAILED;
1569 }
1570 ahd_lock(ahd, &s);
1571 ahd_schedule_runq(ahd);
1572 ahd_linux_run_complete_queue(ahd);
1573 ahd_unlock(ahd, &s);
1574 printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
1575 return (retval);
1576} 676}
1577 677
1578/* 678/*
1579 * Reset the SCSI bus. 679 * Reset the SCSI bus.
1580 */ 680 */
1581static int 681static int
1582ahd_linux_bus_reset(Scsi_Cmnd *cmd) 682ahd_linux_bus_reset(struct scsi_cmnd *cmd)
1583{ 683{
1584 struct ahd_softc *ahd; 684 struct ahd_softc *ahd;
1585 u_long s; 685 u_long s;
@@ -1594,7 +694,6 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
1594 ahd_lock(ahd, &s); 694 ahd_lock(ahd, &s);
1595 found = ahd_reset_channel(ahd, cmd->device->channel + 'A', 695 found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
1596 /*initiate reset*/TRUE); 696 /*initiate reset*/TRUE);
1597 ahd_linux_run_complete_queue(ahd);
1598 ahd_unlock(ahd, &s); 697 ahd_unlock(ahd, &s);
1599 698
1600 if (bootverbose) 699 if (bootverbose)
@@ -1604,9 +703,10 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
1604 return (SUCCESS); 703 return (SUCCESS);
1605} 704}
1606 705
1607Scsi_Host_Template aic79xx_driver_template = { 706struct scsi_host_template aic79xx_driver_template = {
1608 .module = THIS_MODULE, 707 .module = THIS_MODULE,
1609 .name = "aic79xx", 708 .name = "aic79xx",
709 .proc_name = "aic79xx",
1610 .proc_info = ahd_linux_proc_info, 710 .proc_info = ahd_linux_proc_info,
1611 .info = ahd_linux_info, 711 .info = ahd_linux_info,
1612 .queuecommand = ahd_linux_queue, 712 .queuecommand = ahd_linux_queue,
@@ -1623,37 +723,10 @@ Scsi_Host_Template aic79xx_driver_template = {
1623 .slave_alloc = ahd_linux_slave_alloc, 723 .slave_alloc = ahd_linux_slave_alloc,
1624 .slave_configure = ahd_linux_slave_configure, 724 .slave_configure = ahd_linux_slave_configure,
1625 .slave_destroy = ahd_linux_slave_destroy, 725 .slave_destroy = ahd_linux_slave_destroy,
726 .target_alloc = ahd_linux_target_alloc,
727 .target_destroy = ahd_linux_target_destroy,
1626}; 728};
1627 729
1628/**************************** Tasklet Handler *********************************/
1629
1630/*
1631 * In 2.4.X and above, this routine is called from a tasklet,
1632 * so we must re-acquire our lock prior to executing this code.
1633 * In all prior kernels, ahd_schedule_runq() calls this routine
1634 * directly and ahd_schedule_runq() is called with our lock held.
1635 */
1636static void
1637ahd_runq_tasklet(unsigned long data)
1638{
1639 struct ahd_softc* ahd;
1640 struct ahd_linux_device *dev;
1641 u_long flags;
1642
1643 ahd = (struct ahd_softc *)data;
1644 ahd_lock(ahd, &flags);
1645 while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
1646
1647 TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
1648 dev->flags &= ~AHD_DEV_ON_RUN_LIST;
1649 ahd_linux_check_device_queue(ahd, dev);
1650 /* Yeild to our interrupt handler */
1651 ahd_unlock(ahd, &flags);
1652 ahd_lock(ahd, &flags);
1653 }
1654 ahd_unlock(ahd, &flags);
1655}
1656
1657/******************************** Bus DMA *************************************/ 730/******************************** Bus DMA *************************************/
1658int 731int
1659ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, 732ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
@@ -1693,36 +766,10 @@ int
1693ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, 766ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
1694 int flags, bus_dmamap_t *mapp) 767 int flags, bus_dmamap_t *mapp)
1695{ 768{
1696 bus_dmamap_t map;
1697
1698 map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
1699 if (map == NULL)
1700 return (ENOMEM);
1701 /*
1702 * Although we can dma data above 4GB, our
1703 * "consistent" memory is below 4GB for
1704 * space efficiency reasons (only need a 4byte
1705 * address). For this reason, we have to reset
1706 * our dma mask when doing allocations.
1707 */
1708 if (ahd->dev_softc != NULL)
1709 if (pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) {
1710 printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
1711 kfree(map);
1712 return (ENODEV);
1713 }
1714 *vaddr = pci_alloc_consistent(ahd->dev_softc, 769 *vaddr = pci_alloc_consistent(ahd->dev_softc,
1715 dmat->maxsize, &map->bus_addr); 770 dmat->maxsize, mapp);
1716 if (ahd->dev_softc != NULL)
1717 if (pci_set_dma_mask(ahd->dev_softc,
1718 ahd->platform_data->hw_dma_mask)) {
1719 printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
1720 kfree(map);
1721 return (ENODEV);
1722 }
1723 if (*vaddr == NULL) 771 if (*vaddr == NULL)
1724 return (ENOMEM); 772 return (ENOMEM);
1725 *mapp = map;
1726 return(0); 773 return(0);
1727} 774}
1728 775
@@ -1731,7 +778,7 @@ ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
1731 void* vaddr, bus_dmamap_t map) 778 void* vaddr, bus_dmamap_t map)
1732{ 779{
1733 pci_free_consistent(ahd->dev_softc, dmat->maxsize, 780 pci_free_consistent(ahd->dev_softc, dmat->maxsize,
1734 vaddr, map->bus_addr); 781 vaddr, map);
1735} 782}
1736 783
1737int 784int
@@ -1745,7 +792,7 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
1745 */ 792 */
1746 bus_dma_segment_t stack_sg; 793 bus_dma_segment_t stack_sg;
1747 794
1748 stack_sg.ds_addr = map->bus_addr; 795 stack_sg.ds_addr = map;
1749 stack_sg.ds_len = dmat->maxsize; 796 stack_sg.ds_len = dmat->maxsize;
1750 cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0); 797 cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
1751 return (0); 798 return (0);
@@ -1754,11 +801,6 @@ ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
1754void 801void
1755ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) 802ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
1756{ 803{
1757 /*
1758 * The map may is NULL in our < 2.3.X implementation.
1759 */
1760 if (map != NULL)
1761 free(map, M_DEVBUF);
1762} 804}
1763 805
1764int 806int
@@ -1823,41 +865,6 @@ ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
1823} 865}
1824 866
1825static void 867static void
1826ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
1827{
1828
1829 if ((instance >= 0) && (targ >= 0)
1830 && (instance < NUM_ELEMENTS(aic79xx_tag_info))
1831 && (targ < AHD_NUM_TARGETS)) {
1832 aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
1833 if (bootverbose)
1834 printf("tag_info[%d:%d] = %d\n", instance, targ, value);
1835 }
1836}
1837
1838static void
1839ahd_linux_setup_rd_strm_info(u_long arg, int instance, int targ, int32_t value)
1840{
1841 if ((instance >= 0)
1842 && (instance < NUM_ELEMENTS(aic79xx_rd_strm_info))) {
1843 aic79xx_rd_strm_info[instance] = value & 0xFFFF;
1844 if (bootverbose)
1845 printf("rd_strm[%d] = 0x%x\n", instance, value);
1846 }
1847}
1848
1849static void
1850ahd_linux_setup_dv(u_long arg, int instance, int targ, int32_t value)
1851{
1852 if ((instance >= 0)
1853 && (instance < NUM_ELEMENTS(aic79xx_dv_settings))) {
1854 aic79xx_dv_settings[instance] = value;
1855 if (bootverbose)
1856 printf("dv[%d] = %d\n", instance, value);
1857 }
1858}
1859
1860static void
1861ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) 868ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
1862{ 869{
1863 870
@@ -1887,6 +894,19 @@ ahd_linux_setup_tag_info_global(char *p)
1887 } 894 }
1888} 895}
1889 896
897static void
898ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
899{
900
901 if ((instance >= 0) && (targ >= 0)
902 && (instance < NUM_ELEMENTS(aic79xx_tag_info))
903 && (targ < AHD_NUM_TARGETS)) {
904 aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
905 if (bootverbose)
906 printf("tag_info[%d:%d] = %d\n", instance, targ, value);
907 }
908}
909
1890/* 910/*
1891 * Handle Linux boot parameters. This routine allows for assigning a value 911 * Handle Linux boot parameters. This routine allows for assigning a value
1892 * to a parameter with a ':' between the parameter and the value. 912 * to a parameter with a ':' between the parameter and the value.
@@ -1916,8 +936,6 @@ aic79xx_setup(char *s)
1916 { "seltime", &aic79xx_seltime }, 936 { "seltime", &aic79xx_seltime },
1917 { "tag_info", NULL }, 937 { "tag_info", NULL },
1918 { "global_tag_depth", NULL}, 938 { "global_tag_depth", NULL},
1919 { "rd_strm", NULL },
1920 { "dv", NULL },
1921 { "slewrate", NULL }, 939 { "slewrate", NULL },
1922 { "precomp", NULL }, 940 { "precomp", NULL },
1923 { "amplitude", NULL }, 941 { "amplitude", NULL },
@@ -1948,12 +966,6 @@ aic79xx_setup(char *s)
1948 } else if (strncmp(p, "tag_info", n) == 0) { 966 } else if (strncmp(p, "tag_info", n) == 0) {
1949 s = aic_parse_brace_option("tag_info", p + n, end, 967 s = aic_parse_brace_option("tag_info", p + n, end,
1950 2, ahd_linux_setup_tag_info, 0); 968 2, ahd_linux_setup_tag_info, 0);
1951 } else if (strncmp(p, "rd_strm", n) == 0) {
1952 s = aic_parse_brace_option("rd_strm", p + n, end,
1953 1, ahd_linux_setup_rd_strm_info, 0);
1954 } else if (strncmp(p, "dv", n) == 0) {
1955 s = aic_parse_brace_option("dv", p + n, end, 1,
1956 ahd_linux_setup_dv, 0);
1957 } else if (strncmp(p, "slewrate", n) == 0) { 969 } else if (strncmp(p, "slewrate", n) == 0) {
1958 s = aic_parse_brace_option("slewrate", 970 s = aic_parse_brace_option("slewrate",
1959 p + n, end, 1, ahd_linux_setup_iocell_info, 971 p + n, end, 1, ahd_linux_setup_iocell_info,
@@ -1982,13 +994,12 @@ __setup("aic79xx=", aic79xx_setup);
1982uint32_t aic79xx_verbose; 994uint32_t aic79xx_verbose;
1983 995
1984int 996int
1985ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) 997ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template)
1986{ 998{
1987 char buf[80]; 999 char buf[80];
1988 struct Scsi_Host *host; 1000 struct Scsi_Host *host;
1989 char *new_name; 1001 char *new_name;
1990 u_long s; 1002 u_long s;
1991 u_long target;
1992 1003
1993 template->name = ahd->description; 1004 template->name = ahd->description;
1994 host = scsi_host_alloc(template, sizeof(struct ahd_softc *)); 1005 host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
@@ -1997,11 +1008,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
1997 1008
1998 *((struct ahd_softc **)host->hostdata) = ahd; 1009 *((struct ahd_softc **)host->hostdata) = ahd;
1999 ahd_lock(ahd, &s); 1010 ahd_lock(ahd, &s);
2000#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
2001 scsi_assign_lock(host, &ahd->platform_data->spin_lock); 1011 scsi_assign_lock(host, &ahd->platform_data->spin_lock);
2002#elif AHD_SCSI_HAS_HOST_LOCK != 0
2003 host->lock = &ahd->platform_data->spin_lock;
2004#endif
2005 ahd->platform_data->host = host; 1012 ahd->platform_data->host = host;
2006 host->can_queue = AHD_MAX_QUEUE; 1013 host->can_queue = AHD_MAX_QUEUE;
2007 host->cmd_per_lun = 2; 1014 host->cmd_per_lun = 2;
@@ -2012,7 +1019,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
2012 host->max_lun = AHD_NUM_LUNS; 1019 host->max_lun = AHD_NUM_LUNS;
2013 host->max_channel = 0; 1020 host->max_channel = 0;
2014 host->sg_tablesize = AHD_NSEG; 1021 host->sg_tablesize = AHD_NSEG;
2015 ahd_set_unit(ahd, ahd_linux_next_unit()); 1022 ahd_set_unit(ahd, ahd_linux_unit++);
2016 sprintf(buf, "scsi%d", host->host_no); 1023 sprintf(buf, "scsi%d", host->host_no);
2017 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); 1024 new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
2018 if (new_name != NULL) { 1025 if (new_name != NULL) {
@@ -2020,54 +1027,14 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
2020 ahd_set_name(ahd, new_name); 1027 ahd_set_name(ahd, new_name);
2021 } 1028 }
2022 host->unique_id = ahd->unit; 1029 host->unique_id = ahd->unit;
2023#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
2024 scsi_set_pci_device(host, ahd->dev_softc);
2025#endif
2026 ahd_linux_setup_user_rd_strm_settings(ahd);
2027 ahd_linux_initialize_scsi_bus(ahd); 1030 ahd_linux_initialize_scsi_bus(ahd);
2028 ahd_unlock(ahd, &s);
2029 ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0);
2030 ahd_lock(ahd, &s);
2031 if (ahd->platform_data->dv_pid < 0) {
2032 printf("%s: Failed to create DV thread, error= %d\n",
2033 ahd_name(ahd), ahd->platform_data->dv_pid);
2034 return (-ahd->platform_data->dv_pid);
2035 }
2036 /*
2037 * Initially allocate *all* of our linux target objects
2038 * so that the DV thread will scan them all in parallel
2039 * just after driver initialization. Any device that
2040 * does not exist will have its target object destroyed
2041 * by the selection timeout handler. In the case of a
2042 * device that appears after the initial DV scan, async
2043 * negotiation will occur for the first command, and DV
2044 * will comence should that first command be successful.
2045 */
2046 for (target = 0; target < host->max_id; target++) {
2047
2048 /*
2049 * Skip our own ID. Some Compaq/HP storage devices
2050 * have enclosure management devices that respond to
2051 * single bit selection (i.e. selecting ourselves).
2052 * It is expected that either an external application
2053 * or a modified kernel will be used to probe this
2054 * ID if it is appropriate. To accommodate these
2055 * installations, ahc_linux_alloc_target() will allocate
2056 * for our ID if asked to do so.
2057 */
2058 if (target == ahd->our_id)
2059 continue;
2060
2061 ahd_linux_alloc_target(ahd, 0, target);
2062 }
2063 ahd_intr_enable(ahd, TRUE); 1031 ahd_intr_enable(ahd, TRUE);
2064 ahd_linux_start_dv(ahd);
2065 ahd_unlock(ahd, &s); 1032 ahd_unlock(ahd, &s);
2066 1033
2067#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 1034 host->transportt = ahd_linux_transport_template;
1035
2068 scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */ 1036 scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
2069 scsi_scan_host(host); 1037 scsi_scan_host(host);
2070#endif
2071 return (0); 1038 return (0);
2072} 1039}
2073 1040
@@ -2081,29 +1048,6 @@ ahd_linux_get_memsize(void)
2081} 1048}
2082 1049
2083/* 1050/*
2084 * Find the smallest available unit number to use
2085 * for a new device. We don't just use a static
2086 * count to handle the "repeated hot-(un)plug"
2087 * scenario.
2088 */
2089static int
2090ahd_linux_next_unit(void)
2091{
2092 struct ahd_softc *ahd;
2093 int unit;
2094
2095 unit = 0;
2096retry:
2097 TAILQ_FOREACH(ahd, &ahd_tailq, links) {
2098 if (ahd->unit == unit) {
2099 unit++;
2100 goto retry;
2101 }
2102 }
2103 return (unit);
2104}
2105
2106/*
2107 * Place the SCSI bus into a known state by either resetting it, 1051 * Place the SCSI bus into a known state by either resetting it,
2108 * or forcing transfer negotiations on the next command to any 1052 * or forcing transfer negotiations on the next command to any
2109 * target. 1053 * target.
@@ -2162,20 +1106,9 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
2162 if (ahd->platform_data == NULL) 1106 if (ahd->platform_data == NULL)
2163 return (ENOMEM); 1107 return (ENOMEM);
2164 memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); 1108 memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));
2165 TAILQ_INIT(&ahd->platform_data->completeq);
2166 TAILQ_INIT(&ahd->platform_data->device_runq);
2167 ahd->platform_data->irq = AHD_LINUX_NOIRQ; 1109 ahd->platform_data->irq = AHD_LINUX_NOIRQ;
2168 ahd->platform_data->hw_dma_mask = 0xFFFFFFFF;
2169 ahd_lockinit(ahd); 1110 ahd_lockinit(ahd);
2170 ahd_done_lockinit(ahd);
2171 init_timer(&ahd->platform_data->completeq_timer);
2172 ahd->platform_data->completeq_timer.data = (u_long)ahd;
2173 ahd->platform_data->completeq_timer.function =
2174 (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue;
2175 init_MUTEX_LOCKED(&ahd->platform_data->eh_sem); 1111 init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
2176 init_MUTEX_LOCKED(&ahd->platform_data->dv_sem);
2177 init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem);
2178 ahd_setup_runq_tasklet(ahd);
2179 ahd->seltime = (aic79xx_seltime & 0x3) << 4; 1112 ahd->seltime = (aic79xx_seltime & 0x3) << 4;
2180 return (0); 1113 return (0);
2181} 1114}
@@ -2183,39 +1116,27 @@ ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
2183void 1116void
2184ahd_platform_free(struct ahd_softc *ahd) 1117ahd_platform_free(struct ahd_softc *ahd)
2185{ 1118{
2186 struct ahd_linux_target *targ; 1119 struct scsi_target *starget;
2187 struct ahd_linux_device *dev;
2188 int i, j; 1120 int i, j;
2189 1121
2190 if (ahd->platform_data != NULL) { 1122 if (ahd->platform_data != NULL) {
2191 del_timer_sync(&ahd->platform_data->completeq_timer);
2192 ahd_linux_kill_dv_thread(ahd);
2193 ahd_teardown_runq_tasklet(ahd);
2194 if (ahd->platform_data->host != NULL) { 1123 if (ahd->platform_data->host != NULL) {
2195#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
2196 scsi_remove_host(ahd->platform_data->host); 1124 scsi_remove_host(ahd->platform_data->host);
2197#endif
2198 scsi_host_put(ahd->platform_data->host); 1125 scsi_host_put(ahd->platform_data->host);
2199 } 1126 }
2200 1127
2201 /* destroy all of the device and target objects */ 1128 /* destroy all of the device and target objects */
2202 for (i = 0; i < AHD_NUM_TARGETS; i++) { 1129 for (i = 0; i < AHD_NUM_TARGETS; i++) {
2203 targ = ahd->platform_data->targets[i]; 1130 starget = ahd->platform_data->starget[i];
2204 if (targ != NULL) { 1131 if (starget != NULL) {
2205 /* Keep target around through the loop. */
2206 targ->refcount++;
2207 for (j = 0; j < AHD_NUM_LUNS; j++) { 1132 for (j = 0; j < AHD_NUM_LUNS; j++) {
2208 1133 struct ahd_linux_target *targ =
2209 if (targ->devices[j] == NULL) 1134 scsi_transport_target_data(starget);
1135 if (targ->sdev[j] == NULL)
2210 continue; 1136 continue;
2211 dev = targ->devices[j]; 1137 targ->sdev[j] = NULL;
2212 ahd_linux_free_device(ahd, dev);
2213 } 1138 }
2214 /* 1139 ahd->platform_data->starget[i] = NULL;
2215 * Forcibly free the target now that
2216 * all devices are gone.
2217 */
2218 ahd_linux_free_target(ahd, targ);
2219 } 1140 }
2220 } 1141 }
2221 1142
@@ -2233,16 +1154,6 @@ ahd_platform_free(struct ahd_softc *ahd)
2233 release_mem_region(ahd->platform_data->mem_busaddr, 1154 release_mem_region(ahd->platform_data->mem_busaddr,
2234 0x1000); 1155 0x1000);
2235 } 1156 }
2236#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
2237 /*
2238 * In 2.4 we detach from the scsi midlayer before the PCI
2239 * layer invokes our remove callback. No per-instance
2240 * detach is provided, so we must reach inside the PCI
2241 * subsystem's internals and detach our driver manually.
2242 */
2243 if (ahd->dev_softc != NULL)
2244 ahd->dev_softc->driver = NULL;
2245#endif
2246 free(ahd->platform_data, M_DEVBUF); 1157 free(ahd->platform_data, M_DEVBUF);
2247 } 1158 }
2248} 1159}
@@ -2280,13 +1191,22 @@ void
2280ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, 1191ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
2281 ahd_queue_alg alg) 1192 ahd_queue_alg alg)
2282{ 1193{
1194 struct scsi_target *starget;
1195 struct ahd_linux_target *targ;
2283 struct ahd_linux_device *dev; 1196 struct ahd_linux_device *dev;
1197 struct scsi_device *sdev;
2284 int was_queuing; 1198 int was_queuing;
2285 int now_queuing; 1199 int now_queuing;
2286 1200
2287 dev = ahd_linux_get_device(ahd, devinfo->channel - 'A', 1201 starget = ahd->platform_data->starget[devinfo->target];
2288 devinfo->target, 1202 targ = scsi_transport_target_data(starget);
2289 devinfo->lun, /*alloc*/FALSE); 1203 BUG_ON(targ == NULL);
1204 sdev = targ->sdev[devinfo->lun];
1205 if (sdev == NULL)
1206 return;
1207
1208 dev = scsi_transport_device_data(sdev);
1209
2290 if (dev == NULL) 1210 if (dev == NULL)
2291 return; 1211 return;
2292 was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED); 1212 was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
@@ -2339,1434 +1259,37 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
2339 dev->maxtags = 0; 1259 dev->maxtags = 0;
2340 dev->openings = 1 - dev->active; 1260 dev->openings = 1 - dev->active;
2341 } 1261 }
2342#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
2343 if (dev->scsi_device != NULL) {
2344 switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
2345 case AHD_DEV_Q_BASIC:
2346 scsi_adjust_queue_depth(dev->scsi_device,
2347 MSG_SIMPLE_TASK,
2348 dev->openings + dev->active);
2349 break;
2350 case AHD_DEV_Q_TAGGED:
2351 scsi_adjust_queue_depth(dev->scsi_device,
2352 MSG_ORDERED_TASK,
2353 dev->openings + dev->active);
2354 break;
2355 default:
2356 /*
2357 * We allow the OS to queue 2 untagged transactions to
2358 * us at any time even though we can only execute them
2359 * serially on the controller/device. This should
2360 * remove some latency.
2361 */
2362 scsi_adjust_queue_depth(dev->scsi_device,
2363 /*NON-TAGGED*/0,
2364 /*queue depth*/2);
2365 break;
2366 }
2367 }
2368#endif
2369}
2370
2371int
2372ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
2373 int lun, u_int tag, role_t role, uint32_t status)
2374{
2375 int targ;
2376 int maxtarg;
2377 int maxlun;
2378 int clun;
2379 int count;
2380
2381 if (tag != SCB_LIST_NULL)
2382 return (0);
2383
2384 targ = 0;
2385 if (target != CAM_TARGET_WILDCARD) {
2386 targ = target;
2387 maxtarg = targ + 1;
2388 } else {
2389 maxtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
2390 }
2391 clun = 0;
2392 if (lun != CAM_LUN_WILDCARD) {
2393 clun = lun;
2394 maxlun = clun + 1;
2395 } else {
2396 maxlun = AHD_NUM_LUNS;
2397 }
2398
2399 count = 0;
2400 for (; targ < maxtarg; targ++) {
2401
2402 for (; clun < maxlun; clun++) {
2403 struct ahd_linux_device *dev;
2404 struct ahd_busyq *busyq;
2405 struct ahd_cmd *acmd;
2406
2407 dev = ahd_linux_get_device(ahd, /*chan*/0, targ,
2408 clun, /*alloc*/FALSE);
2409 if (dev == NULL)
2410 continue;
2411
2412 busyq = &dev->busyq;
2413 while ((acmd = TAILQ_FIRST(busyq)) != NULL) {
2414 Scsi_Cmnd *cmd;
2415
2416 cmd = &acmd_scsi_cmd(acmd);
2417 TAILQ_REMOVE(busyq, acmd,
2418 acmd_links.tqe);
2419 count++;
2420 cmd->result = status << 16;
2421 ahd_linux_queue_cmd_complete(ahd, cmd);
2422 }
2423 }
2424 }
2425
2426 return (count);
2427}
2428
2429static void
2430ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd)
2431{
2432 u_long flags;
2433
2434 ahd_lock(ahd, &flags);
2435 del_timer(&ahd->platform_data->completeq_timer);
2436 ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER;
2437 ahd_linux_run_complete_queue(ahd);
2438 ahd_unlock(ahd, &flags);
2439}
2440
2441static void
2442ahd_linux_start_dv(struct ahd_softc *ahd)
2443{
2444
2445 /*
2446 * Freeze the simq and signal ahd_linux_queue to not let any
2447 * more commands through
2448 */
2449 if ((ahd->platform_data->flags & AHD_DV_ACTIVE) == 0) {
2450#ifdef AHD_DEBUG
2451 if (ahd_debug & AHD_SHOW_DV)
2452 printf("%s: Starting DV\n", ahd_name(ahd));
2453#endif
2454
2455 ahd->platform_data->flags |= AHD_DV_ACTIVE;
2456 ahd_freeze_simq(ahd);
2457
2458 /* Wake up the DV kthread */
2459 up(&ahd->platform_data->dv_sem);
2460 }
2461}
2462
2463static int
2464ahd_linux_dv_thread(void *data)
2465{
2466 struct ahd_softc *ahd;
2467 int target;
2468 u_long s;
2469
2470 ahd = (struct ahd_softc *)data;
2471
2472#ifdef AHD_DEBUG
2473 if (ahd_debug & AHD_SHOW_DV)
2474 printf("In DV Thread\n");
2475#endif
2476
2477 /*
2478 * Complete thread creation.
2479 */
2480 lock_kernel();
2481#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
2482 /*
2483 * Don't care about any signals.
2484 */
2485 siginitsetinv(&current->blocked, 0);
2486
2487 daemonize();
2488 sprintf(current->comm, "ahd_dv_%d", ahd->unit);
2489#else
2490 daemonize("ahd_dv_%d", ahd->unit);
2491 current->flags |= PF_NOFREEZE;
2492#endif
2493 unlock_kernel();
2494
2495 while (1) {
2496 /*
2497 * Use down_interruptible() rather than down() to
2498 * avoid inclusion in the load average.
2499 */
2500 down_interruptible(&ahd->platform_data->dv_sem);
2501
2502 /* Check to see if we've been signaled to exit */
2503 ahd_lock(ahd, &s);
2504 if ((ahd->platform_data->flags & AHD_DV_SHUTDOWN) != 0) {
2505 ahd_unlock(ahd, &s);
2506 break;
2507 }
2508 ahd_unlock(ahd, &s);
2509
2510#ifdef AHD_DEBUG
2511 if (ahd_debug & AHD_SHOW_DV)
2512 printf("%s: Beginning Domain Validation\n",
2513 ahd_name(ahd));
2514#endif
2515
2516 /*
2517 * Wait for any pending commands to drain before proceeding.
2518 */
2519 ahd_lock(ahd, &s);
2520 while (LIST_FIRST(&ahd->pending_scbs) != NULL) {
2521 ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_EMPTY;
2522 ahd_unlock(ahd, &s);
2523 down_interruptible(&ahd->platform_data->dv_sem);
2524 ahd_lock(ahd, &s);
2525 }
2526
2527 /*
2528 * Wait for the SIMQ to be released so that DV is the
2529 * only reason the queue is frozen.
2530 */
2531 while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
2532 ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
2533 ahd_unlock(ahd, &s);
2534 down_interruptible(&ahd->platform_data->dv_sem);
2535 ahd_lock(ahd, &s);
2536 }
2537 ahd_unlock(ahd, &s);
2538
2539 for (target = 0; target < AHD_NUM_TARGETS; target++)
2540 ahd_linux_dv_target(ahd, target);
2541
2542 ahd_lock(ahd, &s);
2543 ahd->platform_data->flags &= ~AHD_DV_ACTIVE;
2544 ahd_unlock(ahd, &s);
2545
2546 /*
2547 * Release the SIMQ so that normal commands are
2548 * allowed to continue on the bus.
2549 */
2550 ahd_release_simq(ahd);
2551 }
2552 up(&ahd->platform_data->eh_sem);
2553 return (0);
2554}
2555
2556static void
2557ahd_linux_kill_dv_thread(struct ahd_softc *ahd)
2558{
2559 u_long s;
2560
2561 ahd_lock(ahd, &s);
2562 if (ahd->platform_data->dv_pid != 0) {
2563 ahd->platform_data->flags |= AHD_DV_SHUTDOWN;
2564 ahd_unlock(ahd, &s);
2565 up(&ahd->platform_data->dv_sem);
2566
2567 /*
2568 * Use the eh_sem as an indicator that the
2569 * dv thread is exiting. Note that the dv
2570 * thread must still return after performing
2571 * the up on our semaphore before it has
2572 * completely exited this module. Unfortunately,
2573 * there seems to be no easy way to wait for the
2574 * exit of a thread for which you are not the
2575 * parent (dv threads are parented by init).
2576 * Cross your fingers...
2577 */
2578 down(&ahd->platform_data->eh_sem);
2579
2580 /*
2581 * Mark the dv thread as already dead. This
2582 * avoids attempting to kill it a second time.
2583 * This is necessary because we must kill the
2584 * DV thread before calling ahd_free() in the
2585 * module shutdown case to avoid bogus locking
2586 * in the SCSI mid-layer, but we ahd_free() is
2587 * called without killing the DV thread in the
2588 * instance detach case, so ahd_platform_free()
2589 * calls us again to verify that the DV thread
2590 * is dead.
2591 */
2592 ahd->platform_data->dv_pid = 0;
2593 } else {
2594 ahd_unlock(ahd, &s);
2595 }
2596}
2597
2598#define AHD_LINUX_DV_INQ_SHORT_LEN 36
2599#define AHD_LINUX_DV_INQ_LEN 256
2600#define AHD_LINUX_DV_TIMEOUT (HZ / 4)
2601
2602#define AHD_SET_DV_STATE(ahd, targ, newstate) \
2603 ahd_set_dv_state(ahd, targ, newstate, __LINE__)
2604
2605static __inline void
2606ahd_set_dv_state(struct ahd_softc *ahd, struct ahd_linux_target *targ,
2607 ahd_dv_state newstate, u_int line)
2608{
2609 ahd_dv_state oldstate;
2610
2611 oldstate = targ->dv_state;
2612#ifdef AHD_DEBUG
2613 if (ahd_debug & AHD_SHOW_DV)
2614 printf("%s:%d: Going from state %d to state %d\n",
2615 ahd_name(ahd), line, oldstate, newstate);
2616#endif
2617
2618 if (oldstate == newstate)
2619 targ->dv_state_retry++;
2620 else
2621 targ->dv_state_retry = 0;
2622 targ->dv_state = newstate;
2623}
2624
2625static void
2626ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
2627{
2628 struct ahd_devinfo devinfo;
2629 struct ahd_linux_target *targ;
2630 struct scsi_cmnd *cmd;
2631 struct scsi_device *scsi_dev;
2632 struct scsi_sense_data *sense;
2633 uint8_t *buffer;
2634 u_long s;
2635 u_int timeout;
2636 int echo_size;
2637
2638 sense = NULL;
2639 buffer = NULL;
2640 echo_size = 0;
2641 ahd_lock(ahd, &s);
2642 targ = ahd->platform_data->targets[target_offset];
2643 if (targ == NULL || (targ->flags & AHD_DV_REQUIRED) == 0) {
2644 ahd_unlock(ahd, &s);
2645 return;
2646 }
2647 ahd_compile_devinfo(&devinfo, ahd->our_id, targ->target, /*lun*/0,
2648 targ->channel + 'A', ROLE_INITIATOR);
2649#ifdef AHD_DEBUG
2650 if (ahd_debug & AHD_SHOW_DV) {
2651 ahd_print_devinfo(ahd, &devinfo);
2652 printf("Performing DV\n");
2653 }
2654#endif
2655
2656 ahd_unlock(ahd, &s);
2657
2658 cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
2659 scsi_dev = malloc(sizeof(struct scsi_device), M_DEVBUF, M_WAITOK);
2660 scsi_dev->host = ahd->platform_data->host;
2661 scsi_dev->id = devinfo.target;
2662 scsi_dev->lun = devinfo.lun;
2663 scsi_dev->channel = devinfo.channel - 'A';
2664 ahd->platform_data->dv_scsi_dev = scsi_dev;
2665
2666 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_SHORT_ASYNC);
2667
2668 while (targ->dv_state != AHD_DV_STATE_EXIT) {
2669 timeout = AHD_LINUX_DV_TIMEOUT;
2670 switch (targ->dv_state) {
2671 case AHD_DV_STATE_INQ_SHORT_ASYNC:
2672 case AHD_DV_STATE_INQ_ASYNC:
2673 case AHD_DV_STATE_INQ_ASYNC_VERIFY:
2674 /*
2675 * Set things to async narrow to reduce the
2676 * chance that the INQ will fail.
2677 */
2678 ahd_lock(ahd, &s);
2679 ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
2680 AHD_TRANS_GOAL, /*paused*/FALSE);
2681 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
2682 AHD_TRANS_GOAL, /*paused*/FALSE);
2683 ahd_unlock(ahd, &s);
2684 timeout = 10 * HZ;
2685 targ->flags &= ~AHD_INQ_VALID;
2686 /* FALLTHROUGH */
2687 case AHD_DV_STATE_INQ_VERIFY:
2688 {
2689 u_int inq_len;
2690
2691 if (targ->dv_state == AHD_DV_STATE_INQ_SHORT_ASYNC)
2692 inq_len = AHD_LINUX_DV_INQ_SHORT_LEN;
2693 else
2694 inq_len = targ->inq_data->additional_length + 5;
2695 ahd_linux_dv_inq(ahd, cmd, &devinfo, targ, inq_len);
2696 break;
2697 }
2698 case AHD_DV_STATE_TUR:
2699 case AHD_DV_STATE_BUSY:
2700 timeout = 5 * HZ;
2701 ahd_linux_dv_tur(ahd, cmd, &devinfo);
2702 break;
2703 case AHD_DV_STATE_REBD:
2704 ahd_linux_dv_rebd(ahd, cmd, &devinfo, targ);
2705 break;
2706 case AHD_DV_STATE_WEB:
2707 ahd_linux_dv_web(ahd, cmd, &devinfo, targ);
2708 break;
2709
2710 case AHD_DV_STATE_REB:
2711 ahd_linux_dv_reb(ahd, cmd, &devinfo, targ);
2712 break;
2713
2714 case AHD_DV_STATE_SU:
2715 ahd_linux_dv_su(ahd, cmd, &devinfo, targ);
2716 timeout = 50 * HZ;
2717 break;
2718
2719 default:
2720 ahd_print_devinfo(ahd, &devinfo);
2721 printf("Unknown DV state %d\n", targ->dv_state);
2722 goto out;
2723 }
2724
2725 /* Queue the command and wait for it to complete */
2726 /* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
2727 init_timer(&cmd->eh_timeout);
2728#ifdef AHD_DEBUG
2729 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
2730 /*
2731 * All of the printfs during negotiation
2732 * really slow down the negotiation.
2733 * Add a bit of time just to be safe.
2734 */
2735 timeout += HZ;
2736#endif
2737 scsi_add_timer(cmd, timeout, ahd_linux_dv_timeout);
2738 /*
2739 * In 2.5.X, it is assumed that all calls from the
2740 * "midlayer" (which we are emulating) will have the
2741 * ahd host lock held. For other kernels, the
2742 * io_request_lock must be held.
2743 */
2744#if AHD_SCSI_HAS_HOST_LOCK != 0
2745 ahd_lock(ahd, &s);
2746#else
2747 spin_lock_irqsave(&io_request_lock, s);
2748#endif
2749 ahd_linux_queue(cmd, ahd_linux_dv_complete);
2750#if AHD_SCSI_HAS_HOST_LOCK != 0
2751 ahd_unlock(ahd, &s);
2752#else
2753 spin_unlock_irqrestore(&io_request_lock, s);
2754#endif
2755 down_interruptible(&ahd->platform_data->dv_cmd_sem);
2756 /*
2757 * Wait for the SIMQ to be released so that DV is the
2758 * only reason the queue is frozen.
2759 */
2760 ahd_lock(ahd, &s);
2761 while (AHD_DV_SIMQ_FROZEN(ahd) == 0) {
2762 ahd->platform_data->flags |= AHD_DV_WAIT_SIMQ_RELEASE;
2763 ahd_unlock(ahd, &s);
2764 down_interruptible(&ahd->platform_data->dv_sem);
2765 ahd_lock(ahd, &s);
2766 }
2767 ahd_unlock(ahd, &s);
2768
2769 ahd_linux_dv_transition(ahd, cmd, &devinfo, targ);
2770 }
2771
2772out:
2773 if ((targ->flags & AHD_INQ_VALID) != 0
2774 && ahd_linux_get_device(ahd, devinfo.channel - 'A',
2775 devinfo.target, devinfo.lun,
2776 /*alloc*/FALSE) == NULL) {
2777 /*
2778 * The DV state machine failed to configure this device.
2779 * This is normal if DV is disabled. Since we have inquiry
2780 * data, filter it and use the "optimistic" negotiation
2781 * parameters found in the inquiry string.
2782 */
2783 ahd_linux_filter_inquiry(ahd, &devinfo);
2784 if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) {
2785 ahd_print_devinfo(ahd, &devinfo);
2786 printf("DV failed to configure device. "
2787 "Please file a bug report against "
2788 "this driver.\n");
2789 }
2790 }
2791
2792 if (cmd != NULL)
2793 free(cmd, M_DEVBUF);
2794
2795 if (ahd->platform_data->dv_scsi_dev != NULL) {
2796 free(ahd->platform_data->dv_scsi_dev, M_DEVBUF);
2797 ahd->platform_data->dv_scsi_dev = NULL;
2798 }
2799
2800 ahd_lock(ahd, &s);
2801 if (targ->dv_buffer != NULL) {
2802 free(targ->dv_buffer, M_DEVBUF);
2803 targ->dv_buffer = NULL;
2804 }
2805 if (targ->dv_buffer1 != NULL) {
2806 free(targ->dv_buffer1, M_DEVBUF);
2807 targ->dv_buffer1 = NULL;
2808 }
2809 targ->flags &= ~AHD_DV_REQUIRED;
2810 if (targ->refcount == 0)
2811 ahd_linux_free_target(ahd, targ);
2812 ahd_unlock(ahd, &s);
2813}
2814
2815static __inline int
2816ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
2817{
2818 u_long s;
2819 int retval;
2820
2821 ahd_lock(ahd, &s);
2822 retval = ahd_linux_fallback(ahd, devinfo);
2823 ahd_unlock(ahd, &s);
2824
2825 return (retval);
2826}
2827
2828static void
2829ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
2830 struct ahd_devinfo *devinfo,
2831 struct ahd_linux_target *targ)
2832{
2833 u_int32_t status;
2834
2835 status = aic_error_action(cmd, targ->inq_data,
2836 ahd_cmd_get_transaction_status(cmd),
2837 ahd_cmd_get_scsi_status(cmd));
2838
2839
2840#ifdef AHD_DEBUG
2841 if (ahd_debug & AHD_SHOW_DV) {
2842 ahd_print_devinfo(ahd, devinfo);
2843 printf("Entering ahd_linux_dv_transition, state= %d, "
2844 "status= 0x%x, cmd->result= 0x%x\n", targ->dv_state,
2845 status, cmd->result);
2846 }
2847#endif
2848
2849 switch (targ->dv_state) {
2850 case AHD_DV_STATE_INQ_SHORT_ASYNC:
2851 case AHD_DV_STATE_INQ_ASYNC:
2852 switch (status & SS_MASK) {
2853 case SS_NOP:
2854 {
2855 AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
2856 break;
2857 }
2858 case SS_INQ_REFRESH:
2859 AHD_SET_DV_STATE(ahd, targ,
2860 AHD_DV_STATE_INQ_SHORT_ASYNC);
2861 break;
2862 case SS_TUR:
2863 case SS_RETRY:
2864 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
2865 if (ahd_cmd_get_transaction_status(cmd)
2866 == CAM_REQUEUE_REQ)
2867 targ->dv_state_retry--;
2868 if ((status & SS_ERRMASK) == EBUSY)
2869 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
2870 if (targ->dv_state_retry < 10)
2871 break;
2872 /* FALLTHROUGH */
2873 default:
2874 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
2875#ifdef AHD_DEBUG
2876 if (ahd_debug & AHD_SHOW_DV) {
2877 ahd_print_devinfo(ahd, devinfo);
2878 printf("Failed DV inquiry, skipping\n");
2879 }
2880#endif
2881 break;
2882 }
2883 break;
2884 case AHD_DV_STATE_INQ_ASYNC_VERIFY:
2885 switch (status & SS_MASK) {
2886 case SS_NOP:
2887 {
2888 u_int xportflags;
2889 u_int spi3data;
2890
2891 if (memcmp(targ->inq_data, targ->dv_buffer,
2892 AHD_LINUX_DV_INQ_LEN) != 0) {
2893 /*
2894 * Inquiry data must have changed.
2895 * Try from the top again.
2896 */
2897 AHD_SET_DV_STATE(ahd, targ,
2898 AHD_DV_STATE_INQ_SHORT_ASYNC);
2899 break;
2900 }
2901
2902 AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
2903 targ->flags |= AHD_INQ_VALID;
2904 if (ahd_linux_user_dv_setting(ahd) == 0)
2905 break;
2906
2907 xportflags = targ->inq_data->flags;
2908 if ((xportflags & (SID_Sync|SID_WBus16)) == 0)
2909 break;
2910
2911 spi3data = targ->inq_data->spi3data;
2912 switch (spi3data & SID_SPI_CLOCK_DT_ST) {
2913 default:
2914 case SID_SPI_CLOCK_ST:
2915 /* Assume only basic DV is supported. */
2916 targ->flags |= AHD_BASIC_DV;
2917 break;
2918 case SID_SPI_CLOCK_DT:
2919 case SID_SPI_CLOCK_DT_ST:
2920 targ->flags |= AHD_ENHANCED_DV;
2921 break;
2922 }
2923 break;
2924 }
2925 case SS_INQ_REFRESH:
2926 AHD_SET_DV_STATE(ahd, targ,
2927 AHD_DV_STATE_INQ_SHORT_ASYNC);
2928 break;
2929 case SS_TUR:
2930 case SS_RETRY:
2931 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
2932 if (ahd_cmd_get_transaction_status(cmd)
2933 == CAM_REQUEUE_REQ)
2934 targ->dv_state_retry--;
2935
2936 if ((status & SS_ERRMASK) == EBUSY)
2937 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
2938 if (targ->dv_state_retry < 10)
2939 break;
2940 /* FALLTHROUGH */
2941 default:
2942 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
2943#ifdef AHD_DEBUG
2944 if (ahd_debug & AHD_SHOW_DV) {
2945 ahd_print_devinfo(ahd, devinfo);
2946 printf("Failed DV inquiry, skipping\n");
2947 }
2948#endif
2949 break;
2950 }
2951 break;
2952 case AHD_DV_STATE_INQ_VERIFY:
2953 switch (status & SS_MASK) {
2954 case SS_NOP:
2955 {
2956
2957 if (memcmp(targ->inq_data, targ->dv_buffer,
2958 AHD_LINUX_DV_INQ_LEN) == 0) {
2959 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
2960 break;
2961 }
2962
2963#ifdef AHD_DEBUG
2964 if (ahd_debug & AHD_SHOW_DV) {
2965 int i;
2966
2967 ahd_print_devinfo(ahd, devinfo);
2968 printf("Inquiry buffer mismatch:");
2969 for (i = 0; i < AHD_LINUX_DV_INQ_LEN; i++) {
2970 if ((i & 0xF) == 0)
2971 printf("\n ");
2972 printf("0x%x:0x0%x ",
2973 ((uint8_t *)targ->inq_data)[i],
2974 targ->dv_buffer[i]);
2975 }
2976 printf("\n");
2977 }
2978#endif
2979
2980 if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
2981 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
2982 break;
2983 }
2984 /*
2985 * Do not count "falling back"
2986 * against our retries.
2987 */
2988 targ->dv_state_retry = 0;
2989 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
2990 break;
2991 }
2992 case SS_INQ_REFRESH:
2993 AHD_SET_DV_STATE(ahd, targ,
2994 AHD_DV_STATE_INQ_SHORT_ASYNC);
2995 break;
2996 case SS_TUR:
2997 case SS_RETRY:
2998 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
2999 if (ahd_cmd_get_transaction_status(cmd)
3000 == CAM_REQUEUE_REQ) {
3001 targ->dv_state_retry--;
3002 } else if ((status & SSQ_FALLBACK) != 0) {
3003 if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
3004 AHD_SET_DV_STATE(ahd, targ,
3005 AHD_DV_STATE_EXIT);
3006 break;
3007 }
3008 /*
3009 * Do not count "falling back"
3010 * against our retries.
3011 */
3012 targ->dv_state_retry = 0;
3013 } else if ((status & SS_ERRMASK) == EBUSY)
3014 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
3015 if (targ->dv_state_retry < 10)
3016 break;
3017 /* FALLTHROUGH */
3018 default:
3019 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3020#ifdef AHD_DEBUG
3021 if (ahd_debug & AHD_SHOW_DV) {
3022 ahd_print_devinfo(ahd, devinfo);
3023 printf("Failed DV inquiry, skipping\n");
3024 }
3025#endif
3026 break;
3027 }
3028 break;
3029
3030 case AHD_DV_STATE_TUR:
3031 switch (status & SS_MASK) {
3032 case SS_NOP:
3033 if ((targ->flags & AHD_BASIC_DV) != 0) {
3034 ahd_linux_filter_inquiry(ahd, devinfo);
3035 AHD_SET_DV_STATE(ahd, targ,
3036 AHD_DV_STATE_INQ_VERIFY);
3037 } else if ((targ->flags & AHD_ENHANCED_DV) != 0) {
3038 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD);
3039 } else {
3040 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3041 }
3042 break;
3043 case SS_RETRY:
3044 case SS_TUR:
3045 if ((status & SS_ERRMASK) == EBUSY) {
3046 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_BUSY);
3047 break;
3048 }
3049 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
3050 if (ahd_cmd_get_transaction_status(cmd)
3051 == CAM_REQUEUE_REQ) {
3052 targ->dv_state_retry--;
3053 } else if ((status & SSQ_FALLBACK) != 0) {
3054 if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
3055 AHD_SET_DV_STATE(ahd, targ,
3056 AHD_DV_STATE_EXIT);
3057 break;
3058 }
3059 /*
3060 * Do not count "falling back"
3061 * against our retries.
3062 */
3063 targ->dv_state_retry = 0;
3064 }
3065 if (targ->dv_state_retry >= 10) {
3066#ifdef AHD_DEBUG
3067 if (ahd_debug & AHD_SHOW_DV) {
3068 ahd_print_devinfo(ahd, devinfo);
3069 printf("DV TUR reties exhausted\n");
3070 }
3071#endif
3072 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3073 break;
3074 }
3075 if (status & SSQ_DELAY)
3076 ssleep(1);
3077 1262
3078 break; 1263 switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
3079 case SS_START: 1264 case AHD_DEV_Q_BASIC:
3080 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_SU); 1265 scsi_adjust_queue_depth(sdev,
3081 break; 1266 MSG_SIMPLE_TASK,
3082 case SS_INQ_REFRESH: 1267 dev->openings + dev->active);
3083 AHD_SET_DV_STATE(ahd, targ,
3084 AHD_DV_STATE_INQ_SHORT_ASYNC);
3085 break;
3086 default:
3087 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3088 break;
3089 }
3090 break; 1268 break;
3091 1269 case AHD_DEV_Q_TAGGED:
3092 case AHD_DV_STATE_REBD: 1270 scsi_adjust_queue_depth(sdev,
3093 switch (status & SS_MASK) { 1271 MSG_ORDERED_TASK,
3094 case SS_NOP: 1272 dev->openings + dev->active);
3095 {
3096 uint32_t echo_size;
3097
3098 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
3099 echo_size = scsi_3btoul(&targ->dv_buffer[1]);
3100 echo_size &= 0x1FFF;
3101#ifdef AHD_DEBUG
3102 if (ahd_debug & AHD_SHOW_DV) {
3103 ahd_print_devinfo(ahd, devinfo);
3104 printf("Echo buffer size= %d\n", echo_size);
3105 }
3106#endif
3107 if (echo_size == 0) {
3108 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3109 break;
3110 }
3111
3112 /* Generate the buffer pattern */
3113 targ->dv_echo_size = echo_size;
3114 ahd_linux_generate_dv_pattern(targ);
3115 /*
3116 * Setup initial negotiation values.
3117 */
3118 ahd_linux_filter_inquiry(ahd, devinfo);
3119 break;
3120 }
3121 case SS_INQ_REFRESH:
3122 AHD_SET_DV_STATE(ahd, targ,
3123 AHD_DV_STATE_INQ_SHORT_ASYNC);
3124 break;
3125 case SS_RETRY:
3126 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
3127 if (ahd_cmd_get_transaction_status(cmd)
3128 == CAM_REQUEUE_REQ)
3129 targ->dv_state_retry--;
3130 if (targ->dv_state_retry <= 10)
3131 break;
3132#ifdef AHD_DEBUG
3133 if (ahd_debug & AHD_SHOW_DV) {
3134 ahd_print_devinfo(ahd, devinfo);
3135 printf("DV REBD reties exhausted\n");
3136 }
3137#endif
3138 /* FALLTHROUGH */
3139 case SS_FATAL:
3140 default:
3141 /*
3142 * Setup initial negotiation values
3143 * and try level 1 DV.
3144 */
3145 ahd_linux_filter_inquiry(ahd, devinfo);
3146 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_INQ_VERIFY);
3147 targ->dv_echo_size = 0;
3148 break;
3149 }
3150 break;
3151
3152 case AHD_DV_STATE_WEB:
3153 switch (status & SS_MASK) {
3154 case SS_NOP:
3155 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REB);
3156 break;
3157 case SS_INQ_REFRESH:
3158 AHD_SET_DV_STATE(ahd, targ,
3159 AHD_DV_STATE_INQ_SHORT_ASYNC);
3160 break;
3161 case SS_RETRY:
3162 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
3163 if (ahd_cmd_get_transaction_status(cmd)
3164 == CAM_REQUEUE_REQ) {
3165 targ->dv_state_retry--;
3166 } else if ((status & SSQ_FALLBACK) != 0) {
3167 if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
3168 AHD_SET_DV_STATE(ahd, targ,
3169 AHD_DV_STATE_EXIT);
3170 break;
3171 }
3172 /*
3173 * Do not count "falling back"
3174 * against our retries.
3175 */
3176 targ->dv_state_retry = 0;
3177 }
3178 if (targ->dv_state_retry <= 10)
3179 break;
3180 /* FALLTHROUGH */
3181#ifdef AHD_DEBUG
3182 if (ahd_debug & AHD_SHOW_DV) {
3183 ahd_print_devinfo(ahd, devinfo);
3184 printf("DV WEB reties exhausted\n");
3185 }
3186#endif
3187 default:
3188 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3189 break;
3190 }
3191 break;
3192
3193 case AHD_DV_STATE_REB:
3194 switch (status & SS_MASK) {
3195 case SS_NOP:
3196 if (memcmp(targ->dv_buffer, targ->dv_buffer1,
3197 targ->dv_echo_size) != 0) {
3198 if (ahd_linux_dv_fallback(ahd, devinfo) != 0)
3199 AHD_SET_DV_STATE(ahd, targ,
3200 AHD_DV_STATE_EXIT);
3201 else
3202 AHD_SET_DV_STATE(ahd, targ,
3203 AHD_DV_STATE_WEB);
3204 break;
3205 }
3206
3207 if (targ->dv_buffer != NULL) {
3208 free(targ->dv_buffer, M_DEVBUF);
3209 targ->dv_buffer = NULL;
3210 }
3211 if (targ->dv_buffer1 != NULL) {
3212 free(targ->dv_buffer1, M_DEVBUF);
3213 targ->dv_buffer1 = NULL;
3214 }
3215 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3216 break;
3217 case SS_INQ_REFRESH:
3218 AHD_SET_DV_STATE(ahd, targ,
3219 AHD_DV_STATE_INQ_SHORT_ASYNC);
3220 break;
3221 case SS_RETRY:
3222 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
3223 if (ahd_cmd_get_transaction_status(cmd)
3224 == CAM_REQUEUE_REQ) {
3225 targ->dv_state_retry--;
3226 } else if ((status & SSQ_FALLBACK) != 0) {
3227 if (ahd_linux_dv_fallback(ahd, devinfo) != 0) {
3228 AHD_SET_DV_STATE(ahd, targ,
3229 AHD_DV_STATE_EXIT);
3230 break;
3231 }
3232 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_WEB);
3233 }
3234 if (targ->dv_state_retry <= 10) {
3235 if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
3236 msleep(ahd->our_id*1000/10);
3237 break;
3238 }
3239#ifdef AHD_DEBUG
3240 if (ahd_debug & AHD_SHOW_DV) {
3241 ahd_print_devinfo(ahd, devinfo);
3242 printf("DV REB reties exhausted\n");
3243 }
3244#endif
3245 /* FALLTHROUGH */
3246 default:
3247 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3248 break;
3249 }
3250 break;
3251
3252 case AHD_DV_STATE_SU:
3253 switch (status & SS_MASK) {
3254 case SS_NOP:
3255 case SS_INQ_REFRESH:
3256 AHD_SET_DV_STATE(ahd, targ,
3257 AHD_DV_STATE_INQ_SHORT_ASYNC);
3258 break;
3259 default:
3260 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3261 break;
3262 }
3263 break;
3264
3265 case AHD_DV_STATE_BUSY:
3266 switch (status & SS_MASK) {
3267 case SS_NOP:
3268 case SS_INQ_REFRESH:
3269 AHD_SET_DV_STATE(ahd, targ,
3270 AHD_DV_STATE_INQ_SHORT_ASYNC);
3271 break;
3272 case SS_TUR:
3273 case SS_RETRY:
3274 AHD_SET_DV_STATE(ahd, targ, targ->dv_state);
3275 if (ahd_cmd_get_transaction_status(cmd)
3276 == CAM_REQUEUE_REQ) {
3277 targ->dv_state_retry--;
3278 } else if (targ->dv_state_retry < 60) {
3279 if ((status & SSQ_DELAY) != 0)
3280 ssleep(1);
3281 } else {
3282#ifdef AHD_DEBUG
3283 if (ahd_debug & AHD_SHOW_DV) {
3284 ahd_print_devinfo(ahd, devinfo);
3285 printf("DV BUSY reties exhausted\n");
3286 }
3287#endif
3288 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3289 }
3290 break;
3291 default:
3292 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3293 break;
3294 }
3295 break; 1273 break;
3296
3297 default: 1274 default:
3298 printf("%s: Invalid DV completion state %d\n", ahd_name(ahd),
3299 targ->dv_state);
3300 AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
3301 break;
3302 }
3303}
3304
3305static void
3306ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
3307 struct ahd_devinfo *devinfo)
3308{
3309 memset(cmd, 0, sizeof(struct scsi_cmnd));
3310 cmd->device = ahd->platform_data->dv_scsi_dev;
3311 cmd->scsi_done = ahd_linux_dv_complete;
3312}
3313
3314/*
3315 * Synthesize an inquiry command. On the return trip, it'll be
3316 * sniffed and the device transfer settings set for us.
3317 */
3318static void
3319ahd_linux_dv_inq(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
3320 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ,
3321 u_int request_length)
3322{
3323
3324#ifdef AHD_DEBUG
3325 if (ahd_debug & AHD_SHOW_DV) {
3326 ahd_print_devinfo(ahd, devinfo);
3327 printf("Sending INQ\n");
3328 }
3329#endif
3330 if (targ->inq_data == NULL)
3331 targ->inq_data = malloc(AHD_LINUX_DV_INQ_LEN,
3332 M_DEVBUF, M_WAITOK);
3333 if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC) {
3334 if (targ->dv_buffer != NULL)
3335 free(targ->dv_buffer, M_DEVBUF);
3336 targ->dv_buffer = malloc(AHD_LINUX_DV_INQ_LEN,
3337 M_DEVBUF, M_WAITOK);
3338 }
3339
3340 ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
3341 cmd->sc_data_direction = DMA_FROM_DEVICE;
3342 cmd->cmd_len = 6;
3343 cmd->cmnd[0] = INQUIRY;
3344 cmd->cmnd[4] = request_length;
3345 cmd->request_bufflen = request_length;
3346 if (targ->dv_state > AHD_DV_STATE_INQ_ASYNC)
3347 cmd->request_buffer = targ->dv_buffer;
3348 else
3349 cmd->request_buffer = targ->inq_data;
3350 memset(cmd->request_buffer, 0, AHD_LINUX_DV_INQ_LEN);
3351}
3352
3353static void
3354ahd_linux_dv_tur(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
3355 struct ahd_devinfo *devinfo)
3356{
3357
3358#ifdef AHD_DEBUG
3359 if (ahd_debug & AHD_SHOW_DV) {
3360 ahd_print_devinfo(ahd, devinfo);
3361 printf("Sending TUR\n");
3362 }
3363#endif
3364 /* Do a TUR to clear out any non-fatal transitional state */
3365 ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
3366 cmd->sc_data_direction = DMA_NONE;
3367 cmd->cmd_len = 6;
3368 cmd->cmnd[0] = TEST_UNIT_READY;
3369}
3370
3371#define AHD_REBD_LEN 4
3372
3373static void
3374ahd_linux_dv_rebd(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
3375 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
3376{
3377
3378#ifdef AHD_DEBUG
3379 if (ahd_debug & AHD_SHOW_DV) {
3380 ahd_print_devinfo(ahd, devinfo);
3381 printf("Sending REBD\n");
3382 }
3383#endif
3384 if (targ->dv_buffer != NULL)
3385 free(targ->dv_buffer, M_DEVBUF);
3386 targ->dv_buffer = malloc(AHD_REBD_LEN, M_DEVBUF, M_WAITOK);
3387 ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
3388 cmd->sc_data_direction = DMA_FROM_DEVICE;
3389 cmd->cmd_len = 10;
3390 cmd->cmnd[0] = READ_BUFFER;
3391 cmd->cmnd[1] = 0x0b;
3392 scsi_ulto3b(AHD_REBD_LEN, &cmd->cmnd[6]);
3393 cmd->request_bufflen = AHD_REBD_LEN;
3394 cmd->underflow = cmd->request_bufflen;
3395 cmd->request_buffer = targ->dv_buffer;
3396}
3397
3398static void
3399ahd_linux_dv_web(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
3400 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
3401{
3402
3403#ifdef AHD_DEBUG
3404 if (ahd_debug & AHD_SHOW_DV) {
3405 ahd_print_devinfo(ahd, devinfo);
3406 printf("Sending WEB\n");
3407 }
3408#endif
3409 ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
3410 cmd->sc_data_direction = DMA_TO_DEVICE;
3411 cmd->cmd_len = 10;
3412 cmd->cmnd[0] = WRITE_BUFFER;
3413 cmd->cmnd[1] = 0x0a;
3414 scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
3415 cmd->request_bufflen = targ->dv_echo_size;
3416 cmd->underflow = cmd->request_bufflen;
3417 cmd->request_buffer = targ->dv_buffer;
3418}
3419
3420static void
3421ahd_linux_dv_reb(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
3422 struct ahd_devinfo *devinfo, struct ahd_linux_target *targ)
3423{
3424
3425#ifdef AHD_DEBUG
3426 if (ahd_debug & AHD_SHOW_DV) {
3427 ahd_print_devinfo(ahd, devinfo);
3428 printf("Sending REB\n");
3429 }
3430#endif
3431 ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
3432 cmd->sc_data_direction = DMA_FROM_DEVICE;
3433 cmd->cmd_len = 10;
3434 cmd->cmnd[0] = READ_BUFFER;
3435 cmd->cmnd[1] = 0x0a;
3436 scsi_ulto3b(targ->dv_echo_size, &cmd->cmnd[6]);
3437 cmd->request_bufflen = targ->dv_echo_size;
3438 cmd->underflow = cmd->request_bufflen;
3439 cmd->request_buffer = targ->dv_buffer1;
3440}
3441
3442static void
3443ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
3444 struct ahd_devinfo *devinfo,
3445 struct ahd_linux_target *targ)
3446{
3447 u_int le;
3448
3449 le = SID_IS_REMOVABLE(targ->inq_data) ? SSS_LOEJ : 0;
3450
3451#ifdef AHD_DEBUG
3452 if (ahd_debug & AHD_SHOW_DV) {
3453 ahd_print_devinfo(ahd, devinfo);
3454 printf("Sending SU\n");
3455 }
3456#endif
3457 ahd_linux_dv_fill_cmd(ahd, cmd, devinfo);
3458 cmd->sc_data_direction = DMA_NONE;
3459 cmd->cmd_len = 6;
3460 cmd->cmnd[0] = START_STOP_UNIT;
3461 cmd->cmnd[4] = le | SSS_START;
3462}
3463
3464static int
3465ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
3466{
3467 struct ahd_linux_target *targ;
3468 struct ahd_initiator_tinfo *tinfo;
3469 struct ahd_transinfo *goal;
3470 struct ahd_tmode_tstate *tstate;
3471 u_int width;
3472 u_int period;
3473 u_int offset;
3474 u_int ppr_options;
3475 u_int cur_speed;
3476 u_int wide_speed;
3477 u_int narrow_speed;
3478 u_int fallback_speed;
3479
3480#ifdef AHD_DEBUG
3481 if (ahd_debug & AHD_SHOW_DV) {
3482 ahd_print_devinfo(ahd, devinfo);
3483 printf("Trying to fallback\n");
3484 }
3485#endif
3486 targ = ahd->platform_data->targets[devinfo->target_offset];
3487 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
3488 devinfo->our_scsiid,
3489 devinfo->target, &tstate);
3490 goal = &tinfo->goal;
3491 width = goal->width;
3492 period = goal->period;
3493 offset = goal->offset;
3494 ppr_options = goal->ppr_options;
3495 if (offset == 0)
3496 period = AHD_ASYNC_XFER_PERIOD;
3497 if (targ->dv_next_narrow_period == 0)
3498 targ->dv_next_narrow_period = MAX(period, AHD_SYNCRATE_ULTRA2);
3499 if (targ->dv_next_wide_period == 0)
3500 targ->dv_next_wide_period = period;
3501 if (targ->dv_max_width == 0)
3502 targ->dv_max_width = width;
3503 if (targ->dv_max_ppr_options == 0)
3504 targ->dv_max_ppr_options = ppr_options;
3505 if (targ->dv_last_ppr_options == 0)
3506 targ->dv_last_ppr_options = ppr_options;
3507
3508 cur_speed = aic_calc_speed(width, period, offset, AHD_SYNCRATE_MIN);
3509 wide_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_16_BIT,
3510 targ->dv_next_wide_period,
3511 MAX_OFFSET, AHD_SYNCRATE_MIN);
3512 narrow_speed = aic_calc_speed(MSG_EXT_WDTR_BUS_8_BIT,
3513 targ->dv_next_narrow_period,
3514 MAX_OFFSET, AHD_SYNCRATE_MIN);
3515 fallback_speed = aic_calc_speed(width, period+1, offset,
3516 AHD_SYNCRATE_MIN);
3517#ifdef AHD_DEBUG
3518 if (ahd_debug & AHD_SHOW_DV) {
3519 printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, "
3520 "fallback_speed= %d\n", cur_speed, wide_speed,
3521 narrow_speed, fallback_speed);
3522 }
3523#endif
3524
3525 if (cur_speed > 160000) {
3526 /* 1275 /*
3527 * Paced/DT/IU_REQ only transfer speeds. All we 1276 * We allow the OS to queue 2 untagged transactions to
3528 * can do is fallback in terms of syncrate. 1277 * us at any time even though we can only execute them
1278 * serially on the controller/device. This should
1279 * remove some latency.
3529 */ 1280 */
3530 period++; 1281 scsi_adjust_queue_depth(sdev,
3531 } else if (cur_speed > 80000) { 1282 /*NON-TAGGED*/0,
3532 if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { 1283 /*queue depth*/2);
3533 /* 1284 break;
3534 * Try without IU_REQ as it may be confusing
3535 * an expander.
3536 */
3537 ppr_options &= ~MSG_EXT_PPR_IU_REQ;
3538 } else {
3539 /*
3540 * Paced/DT only transfer speeds. All we
3541 * can do is fallback in terms of syncrate.
3542 */
3543 period++;
3544 ppr_options = targ->dv_max_ppr_options;
3545 }
3546 } else if (cur_speed > 3300) {
3547
3548 /*
3549 * In this range we the following
3550 * options ordered from highest to
3551 * lowest desireability:
3552 *
3553 * o Wide/DT
3554 * o Wide/non-DT
3555 * o Narrow at a potentally higher sync rate.
3556 *
3557 * All modes are tested with and without IU_REQ
3558 * set since using IUs may confuse an expander.
3559 */
3560 if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
3561
3562 ppr_options &= ~MSG_EXT_PPR_IU_REQ;
3563 } else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
3564 /*
3565 * Try going non-DT.
3566 */
3567 ppr_options = targ->dv_max_ppr_options;
3568 ppr_options &= ~MSG_EXT_PPR_DT_REQ;
3569 } else if (targ->dv_last_ppr_options != 0) {
3570 /*
3571 * Try without QAS or any other PPR options.
3572 * We may need a non-PPR message to work with
3573 * an expander. We look at the "last PPR options"
3574 * so we will perform this fallback even if the
3575 * target responded to our PPR negotiation with
3576 * no option bits set.
3577 */
3578 ppr_options = 0;
3579 } else if (width == MSG_EXT_WDTR_BUS_16_BIT) {
3580 /*
3581 * If the next narrow speed is greater than
3582 * the next wide speed, fallback to narrow.
3583 * Otherwise fallback to the next DT/Wide setting.
3584 * The narrow async speed will always be smaller
3585 * than the wide async speed, so handle this case
3586 * specifically.
3587 */
3588 ppr_options = targ->dv_max_ppr_options;
3589 if (narrow_speed > fallback_speed
3590 || period >= AHD_ASYNC_XFER_PERIOD) {
3591 targ->dv_next_wide_period = period+1;
3592 width = MSG_EXT_WDTR_BUS_8_BIT;
3593 period = targ->dv_next_narrow_period;
3594 } else {
3595 period++;
3596 }
3597 } else if ((ahd->features & AHD_WIDE) != 0
3598 && targ->dv_max_width != 0
3599 && wide_speed >= fallback_speed
3600 && (targ->dv_next_wide_period <= AHD_ASYNC_XFER_PERIOD
3601 || period >= AHD_ASYNC_XFER_PERIOD)) {
3602
3603 /*
3604 * We are narrow. Try falling back
3605 * to the next wide speed with
3606 * all supported ppr options set.
3607 */
3608 targ->dv_next_narrow_period = period+1;
3609 width = MSG_EXT_WDTR_BUS_16_BIT;
3610 period = targ->dv_next_wide_period;
3611 ppr_options = targ->dv_max_ppr_options;
3612 } else {
3613 /* Only narrow fallback is allowed. */
3614 period++;
3615 ppr_options = targ->dv_max_ppr_options;
3616 }
3617 } else {
3618 return (-1);
3619 }
3620 offset = MAX_OFFSET;
3621 ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_PACED);
3622 ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, FALSE);
3623 if (period == 0) {
3624 period = 0;
3625 offset = 0;
3626 ppr_options = 0;
3627 if (width == MSG_EXT_WDTR_BUS_8_BIT)
3628 targ->dv_next_narrow_period = AHD_ASYNC_XFER_PERIOD;
3629 else
3630 targ->dv_next_wide_period = AHD_ASYNC_XFER_PERIOD;
3631 }
3632 ahd_set_syncrate(ahd, devinfo, period, offset,
3633 ppr_options, AHD_TRANS_GOAL, FALSE);
3634 targ->dv_last_ppr_options = ppr_options;
3635 return (0);
3636}
3637
3638static void
3639ahd_linux_dv_timeout(struct scsi_cmnd *cmd)
3640{
3641 struct ahd_softc *ahd;
3642 struct scb *scb;
3643 u_long flags;
3644
3645 ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
3646 ahd_lock(ahd, &flags);
3647
3648#ifdef AHD_DEBUG
3649 if (ahd_debug & AHD_SHOW_DV) {
3650 printf("%s: Timeout while doing DV command %x.\n",
3651 ahd_name(ahd), cmd->cmnd[0]);
3652 ahd_dump_card_state(ahd);
3653 }
3654#endif
3655
3656 /*
3657 * Guard against "done race". No action is
3658 * required if we just completed.
3659 */
3660 if ((scb = (struct scb *)cmd->host_scribble) == NULL) {
3661 ahd_unlock(ahd, &flags);
3662 return;
3663 } 1285 }
3664
3665 /*
3666 * Command has not completed. Mark this
3667 * SCB as having failing status prior to
3668 * resetting the bus, so we get the correct
3669 * error code.
3670 */
3671 if ((scb->flags & SCB_SENSE) != 0)
3672 ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
3673 else
3674 ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
3675 ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate*/TRUE);
3676
3677 /*
3678 * Add a minimal bus settle delay for devices that are slow to
3679 * respond after bus resets.
3680 */
3681 ahd_freeze_simq(ahd);
3682 init_timer(&ahd->platform_data->reset_timer);
3683 ahd->platform_data->reset_timer.data = (u_long)ahd;
3684 ahd->platform_data->reset_timer.expires = jiffies + HZ / 2;
3685 ahd->platform_data->reset_timer.function =
3686 (ahd_linux_callback_t *)ahd_release_simq;
3687 add_timer(&ahd->platform_data->reset_timer);
3688 if (ahd_linux_next_device_to_run(ahd) != NULL)
3689 ahd_schedule_runq(ahd);
3690 ahd_linux_run_complete_queue(ahd);
3691 ahd_unlock(ahd, &flags);
3692}
3693
3694static void
3695ahd_linux_dv_complete(struct scsi_cmnd *cmd)
3696{
3697 struct ahd_softc *ahd;
3698
3699 ahd = *((struct ahd_softc **)cmd->device->host->hostdata);
3700
3701 /* Delete the DV timer before it goes off! */
3702 scsi_delete_timer(cmd);
3703
3704#ifdef AHD_DEBUG
3705 if (ahd_debug & AHD_SHOW_DV)
3706 printf("%s:%c:%d: Command completed, status= 0x%x\n",
3707 ahd_name(ahd), cmd->device->channel, cmd->device->id,
3708 cmd->result);
3709#endif
3710
3711 /* Wake up the state machine */
3712 up(&ahd->platform_data->dv_cmd_sem);
3713} 1286}
3714 1287
3715static void 1288int
3716ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ) 1289ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
1290 int lun, u_int tag, role_t role, uint32_t status)
3717{ 1291{
3718 uint16_t b; 1292 return 0;
3719 u_int i;
3720 u_int j;
3721
3722 if (targ->dv_buffer != NULL)
3723 free(targ->dv_buffer, M_DEVBUF);
3724 targ->dv_buffer = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
3725 if (targ->dv_buffer1 != NULL)
3726 free(targ->dv_buffer1, M_DEVBUF);
3727 targ->dv_buffer1 = malloc(targ->dv_echo_size, M_DEVBUF, M_WAITOK);
3728
3729 i = 0;
3730
3731 b = 0x0001;
3732 for (j = 0 ; i < targ->dv_echo_size; j++) {
3733 if (j < 32) {
3734 /*
3735 * 32bytes of sequential numbers.
3736 */
3737 targ->dv_buffer[i++] = j & 0xff;
3738 } else if (j < 48) {
3739 /*
3740 * 32bytes of repeating 0x0000, 0xffff.
3741 */
3742 targ->dv_buffer[i++] = (j & 0x02) ? 0xff : 0x00;
3743 } else if (j < 64) {
3744 /*
3745 * 32bytes of repeating 0x5555, 0xaaaa.
3746 */
3747 targ->dv_buffer[i++] = (j & 0x02) ? 0xaa : 0x55;
3748 } else {
3749 /*
3750 * Remaining buffer is filled with a repeating
3751 * patter of:
3752 *
3753 * 0xffff
3754 * ~0x0001 << shifted once in each loop.
3755 */
3756 if (j & 0x02) {
3757 if (j & 0x01) {
3758 targ->dv_buffer[i++] = ~(b >> 8) & 0xff;
3759 b <<= 1;
3760 if (b == 0x0000)
3761 b = 0x0001;
3762 } else {
3763 targ->dv_buffer[i++] = (~b & 0xff);
3764 }
3765 } else {
3766 targ->dv_buffer[i++] = 0xff;
3767 }
3768 }
3769 }
3770} 1293}
3771 1294
3772static u_int 1295static u_int
@@ -3800,100 +1323,23 @@ ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
3800 return (tags); 1323 return (tags);
3801} 1324}
3802 1325
3803static u_int
3804ahd_linux_user_dv_setting(struct ahd_softc *ahd)
3805{
3806 static int warned_user;
3807 int dv;
3808
3809 if (ahd->unit >= NUM_ELEMENTS(aic79xx_dv_settings)) {
3810
3811 if (warned_user == 0) {
3812 printf(KERN_WARNING
3813"aic79xx: WARNING: Insufficient dv settings instances\n"
3814"aic79xx: for installed controllers. Using defaults\n"
3815"aic79xx: Please update the aic79xx_dv_settings array in"
3816"aic79xx: the aic79xx_osm.c source file.\n");
3817 warned_user++;
3818 }
3819 dv = -1;
3820 } else {
3821
3822 dv = aic79xx_dv_settings[ahd->unit];
3823 }
3824
3825 if (dv < 0) {
3826 /*
3827 * Apply the default.
3828 */
3829 dv = 1;
3830 if (ahd->seep_config != 0)
3831 dv = (ahd->seep_config->bios_control & CFENABLEDV);
3832 }
3833 return (dv);
3834}
3835
3836static void
3837ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd)
3838{
3839 static int warned_user;
3840 u_int rd_strm_mask;
3841 u_int target_id;
3842
3843 /*
3844 * If we have specific read streaming info for this controller,
3845 * apply it. Otherwise use the defaults.
3846 */
3847 if (ahd->unit >= NUM_ELEMENTS(aic79xx_rd_strm_info)) {
3848
3849 if (warned_user == 0) {
3850
3851 printf(KERN_WARNING
3852"aic79xx: WARNING: Insufficient rd_strm instances\n"
3853"aic79xx: for installed controllers. Using defaults\n"
3854"aic79xx: Please update the aic79xx_rd_strm_info array\n"
3855"aic79xx: in the aic79xx_osm.c source file.\n");
3856 warned_user++;
3857 }
3858 rd_strm_mask = AIC79XX_CONFIGED_RD_STRM;
3859 } else {
3860
3861 rd_strm_mask = aic79xx_rd_strm_info[ahd->unit];
3862 }
3863 for (target_id = 0; target_id < 16; target_id++) {
3864 struct ahd_devinfo devinfo;
3865 struct ahd_initiator_tinfo *tinfo;
3866 struct ahd_tmode_tstate *tstate;
3867
3868 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
3869 target_id, &tstate);
3870 ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
3871 CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
3872 tinfo->user.ppr_options &= ~MSG_EXT_PPR_RD_STRM;
3873 if ((rd_strm_mask & devinfo.target_mask) != 0)
3874 tinfo->user.ppr_options |= MSG_EXT_PPR_RD_STRM;
3875 }
3876}
3877
3878/* 1326/*
3879 * Determines the queue depth for a given device. 1327 * Determines the queue depth for a given device.
3880 */ 1328 */
3881static void 1329static void
3882ahd_linux_device_queue_depth(struct ahd_softc *ahd, 1330ahd_linux_device_queue_depth(struct scsi_device *sdev)
3883 struct ahd_linux_device *dev)
3884{ 1331{
3885 struct ahd_devinfo devinfo; 1332 struct ahd_devinfo devinfo;
3886 u_int tags; 1333 u_int tags;
1334 struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata);
3887 1335
3888 ahd_compile_devinfo(&devinfo, 1336 ahd_compile_devinfo(&devinfo,
3889 ahd->our_id, 1337 ahd->our_id,
3890 dev->target->target, dev->lun, 1338 sdev->sdev_target->id, sdev->lun,
3891 dev->target->channel == 0 ? 'A' : 'B', 1339 sdev->sdev_target->channel == 0 ? 'A' : 'B',
3892 ROLE_INITIATOR); 1340 ROLE_INITIATOR);
3893 tags = ahd_linux_user_tagdepth(ahd, &devinfo); 1341 tags = ahd_linux_user_tagdepth(ahd, &devinfo);
3894 if (tags != 0 1342 if (tags != 0 && sdev->tagged_supported != 0) {
3895 && dev->scsi_device != NULL
3896 && dev->scsi_device->tagged_supported != 0) {
3897 1343
3898 ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED); 1344 ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED);
3899 ahd_print_devinfo(ahd, &devinfo); 1345 ahd_print_devinfo(ahd, &devinfo);
@@ -3903,11 +1349,10 @@ ahd_linux_device_queue_depth(struct ahd_softc *ahd,
3903 } 1349 }
3904} 1350}
3905 1351
3906static void 1352static int
3907ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) 1353ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
1354 struct scsi_cmnd *cmd)
3908{ 1355{
3909 struct ahd_cmd *acmd;
3910 struct scsi_cmnd *cmd;
3911 struct scb *scb; 1356 struct scb *scb;
3912 struct hardware_scb *hscb; 1357 struct hardware_scb *hscb;
3913 struct ahd_initiator_tinfo *tinfo; 1358 struct ahd_initiator_tinfo *tinfo;
@@ -3915,157 +1360,122 @@ ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev)
3915 u_int col_idx; 1360 u_int col_idx;
3916 uint16_t mask; 1361 uint16_t mask;
3917 1362
3918 if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0) 1363 /*
3919 panic("running device on run list"); 1364 * Get an scb to use.
3920 1365 */
3921 while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL 1366 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
3922 && dev->openings > 0 && dev->qfrozen == 0) { 1367 cmd->device->id, &tstate);
3923 1368 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
3924 /* 1369 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
3925 * Schedule us to run later. The only reason we are not 1370 col_idx = AHD_NEVER_COL_IDX;
3926 * running is because the whole controller Q is frozen. 1371 } else {
3927 */ 1372 col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
3928 if (ahd->platform_data->qfrozen != 0 1373 cmd->device->lun);
3929 && AHD_DV_SIMQ_FROZEN(ahd) == 0) { 1374 }
3930 1375 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
3931 TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, 1376 ahd->flags |= AHD_RESOURCE_SHORTAGE;
3932 dev, links); 1377 return SCSI_MLQUEUE_HOST_BUSY;
3933 dev->flags |= AHD_DEV_ON_RUN_LIST; 1378 }
3934 return;
3935 }
3936
3937 cmd = &acmd_scsi_cmd(acmd);
3938 1379
3939 /* 1380 scb->io_ctx = cmd;
3940 * Get an scb to use. 1381 scb->platform_data->dev = dev;
3941 */ 1382 hscb = scb->hscb;
3942 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, 1383 cmd->host_scribble = (char *)scb;
3943 cmd->device->id, &tstate);
3944 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
3945 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
3946 col_idx = AHD_NEVER_COL_IDX;
3947 } else {
3948 col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
3949 cmd->device->lun);
3950 }
3951 if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
3952 TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,
3953 dev, links);
3954 dev->flags |= AHD_DEV_ON_RUN_LIST;
3955 ahd->flags |= AHD_RESOURCE_SHORTAGE;
3956 return;
3957 }
3958 TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);
3959 scb->io_ctx = cmd;
3960 scb->platform_data->dev = dev;
3961 hscb = scb->hscb;
3962 cmd->host_scribble = (char *)scb;
3963 1384
3964 /* 1385 /*
3965 * Fill out basics of the HSCB. 1386 * Fill out basics of the HSCB.
3966 */ 1387 */
3967 hscb->control = 0; 1388 hscb->control = 0;
3968 hscb->scsiid = BUILD_SCSIID(ahd, cmd); 1389 hscb->scsiid = BUILD_SCSIID(ahd, cmd);
3969 hscb->lun = cmd->device->lun; 1390 hscb->lun = cmd->device->lun;
3970 scb->hscb->task_management = 0; 1391 scb->hscb->task_management = 0;
3971 mask = SCB_GET_TARGET_MASK(ahd, scb); 1392 mask = SCB_GET_TARGET_MASK(ahd, scb);
3972 1393
3973 if ((ahd->user_discenable & mask) != 0) 1394 if ((ahd->user_discenable & mask) != 0)
3974 hscb->control |= DISCENB; 1395 hscb->control |= DISCENB;
3975 1396
3976 if (AHD_DV_CMD(cmd) != 0) 1397 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
3977 scb->flags |= SCB_SILENT; 1398 scb->flags |= SCB_PACKETIZED;
3978 1399
3979 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) 1400 if ((tstate->auto_negotiate & mask) != 0) {
3980 scb->flags |= SCB_PACKETIZED; 1401 scb->flags |= SCB_AUTO_NEGOTIATE;
1402 scb->hscb->control |= MK_MESSAGE;
1403 }
3981 1404
3982 if ((tstate->auto_negotiate & mask) != 0) { 1405 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
3983 scb->flags |= SCB_AUTO_NEGOTIATE; 1406 int msg_bytes;
3984 scb->hscb->control |= MK_MESSAGE; 1407 uint8_t tag_msgs[2];
3985 }
3986 1408
3987 if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { 1409 msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
3988#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 1410 if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
3989 int msg_bytes; 1411 hscb->control |= tag_msgs[0];
3990 uint8_t tag_msgs[2]; 1412 if (tag_msgs[0] == MSG_ORDERED_TASK)
3991
3992 msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
3993 if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
3994 hscb->control |= tag_msgs[0];
3995 if (tag_msgs[0] == MSG_ORDERED_TASK)
3996 dev->commands_since_idle_or_otag = 0;
3997 } else
3998#endif
3999 if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
4000 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
4001 hscb->control |= MSG_ORDERED_TASK;
4002 dev->commands_since_idle_or_otag = 0; 1413 dev->commands_since_idle_or_otag = 0;
4003 } else { 1414 } else
4004 hscb->control |= MSG_SIMPLE_TASK; 1415 if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
4005 } 1416 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
1417 hscb->control |= MSG_ORDERED_TASK;
1418 dev->commands_since_idle_or_otag = 0;
1419 } else {
1420 hscb->control |= MSG_SIMPLE_TASK;
4006 } 1421 }
1422 }
4007 1423
4008 hscb->cdb_len = cmd->cmd_len; 1424 hscb->cdb_len = cmd->cmd_len;
4009 memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len); 1425 memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
4010 1426
4011 scb->sg_count = 0; 1427 scb->platform_data->xfer_len = 0;
4012 ahd_set_residual(scb, 0); 1428 ahd_set_residual(scb, 0);
4013 ahd_set_sense_residual(scb, 0); 1429 ahd_set_sense_residual(scb, 0);
4014 if (cmd->use_sg != 0) { 1430 scb->sg_count = 0;
4015 void *sg; 1431 if (cmd->use_sg != 0) {
4016 struct scatterlist *cur_seg; 1432 void *sg;
4017 u_int nseg; 1433 struct scatterlist *cur_seg;
4018 int dir; 1434 u_int nseg;
4019 1435 int dir;
4020 cur_seg = (struct scatterlist *)cmd->request_buffer; 1436
4021 dir = cmd->sc_data_direction; 1437 cur_seg = (struct scatterlist *)cmd->request_buffer;
4022 nseg = pci_map_sg(ahd->dev_softc, cur_seg, 1438 dir = cmd->sc_data_direction;
4023 cmd->use_sg, dir); 1439 nseg = pci_map_sg(ahd->dev_softc, cur_seg,
4024 scb->platform_data->xfer_len = 0; 1440 cmd->use_sg, dir);
4025 for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) { 1441 scb->platform_data->xfer_len = 0;
4026 dma_addr_t addr; 1442 for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
4027 bus_size_t len;
4028
4029 addr = sg_dma_address(cur_seg);
4030 len = sg_dma_len(cur_seg);
4031 scb->platform_data->xfer_len += len;
4032 sg = ahd_sg_setup(ahd, scb, sg, addr, len,
4033 /*last*/nseg == 1);
4034 }
4035 } else if (cmd->request_bufflen != 0) {
4036 void *sg;
4037 dma_addr_t addr; 1443 dma_addr_t addr;
4038 int dir; 1444 bus_size_t len;
4039
4040 sg = scb->sg_list;
4041 dir = cmd->sc_data_direction;
4042 addr = pci_map_single(ahd->dev_softc,
4043 cmd->request_buffer,
4044 cmd->request_bufflen, dir);
4045 scb->platform_data->xfer_len = cmd->request_bufflen;
4046 scb->platform_data->buf_busaddr = addr;
4047 sg = ahd_sg_setup(ahd, scb, sg, addr,
4048 cmd->request_bufflen, /*last*/TRUE);
4049 }
4050 1445
4051 LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links); 1446 addr = sg_dma_address(cur_seg);
4052 dev->openings--; 1447 len = sg_dma_len(cur_seg);
4053 dev->active++; 1448 scb->platform_data->xfer_len += len;
4054 dev->commands_issued++; 1449 sg = ahd_sg_setup(ahd, scb, sg, addr, len,
4055 1450 /*last*/nseg == 1);
4056 /* Update the error counting bucket and dump if needed */
4057 if (dev->target->cmds_since_error) {
4058 dev->target->cmds_since_error++;
4059 if (dev->target->cmds_since_error >
4060 AHD_LINUX_ERR_THRESH)
4061 dev->target->cmds_since_error = 0;
4062 } 1451 }
1452 } else if (cmd->request_bufflen != 0) {
1453 void *sg;
1454 dma_addr_t addr;
1455 int dir;
4063 1456
4064 if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0) 1457 sg = scb->sg_list;
4065 dev->commands_since_idle_or_otag++; 1458 dir = cmd->sc_data_direction;
4066 scb->flags |= SCB_ACTIVE; 1459 addr = pci_map_single(ahd->dev_softc,
4067 ahd_queue_scb(ahd, scb); 1460 cmd->request_buffer,
1461 cmd->request_bufflen, dir);
1462 scb->platform_data->xfer_len = cmd->request_bufflen;
1463 scb->platform_data->buf_busaddr = addr;
1464 sg = ahd_sg_setup(ahd, scb, sg, addr,
1465 cmd->request_bufflen, /*last*/TRUE);
4068 } 1466 }
1467
1468 LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
1469 dev->openings--;
1470 dev->active++;
1471 dev->commands_issued++;
1472
1473 if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
1474 dev->commands_since_idle_or_otag++;
1475 scb->flags |= SCB_ACTIVE;
1476 ahd_queue_scb(ahd, scb);
1477
1478 return 0;
4069} 1479}
4070 1480
4071/* 1481/*
@@ -4081,9 +1491,6 @@ ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
4081 ahd = (struct ahd_softc *) dev_id; 1491 ahd = (struct ahd_softc *) dev_id;
4082 ahd_lock(ahd, &flags); 1492 ahd_lock(ahd, &flags);
4083 ours = ahd_intr(ahd); 1493 ours = ahd_intr(ahd);
4084 if (ahd_linux_next_device_to_run(ahd) != NULL)
4085 ahd_schedule_runq(ahd);
4086 ahd_linux_run_complete_queue(ahd);
4087 ahd_unlock(ahd, &flags); 1494 ahd_unlock(ahd, &flags);
4088 return IRQ_RETVAL(ours); 1495 return IRQ_RETVAL(ours);
4089} 1496}
@@ -4092,111 +1499,6 @@ void
4092ahd_platform_flushwork(struct ahd_softc *ahd) 1499ahd_platform_flushwork(struct ahd_softc *ahd)
4093{ 1500{
4094 1501
4095 while (ahd_linux_run_complete_queue(ahd) != NULL)
4096 ;
4097}
4098
4099static struct ahd_linux_target*
4100ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target)
4101{
4102 struct ahd_linux_target *targ;
4103
4104 targ = malloc(sizeof(*targ), M_DEVBUF, M_NOWAIT);
4105 if (targ == NULL)
4106 return (NULL);
4107 memset(targ, 0, sizeof(*targ));
4108 targ->channel = channel;
4109 targ->target = target;
4110 targ->ahd = ahd;
4111 targ->flags = AHD_DV_REQUIRED;
4112 ahd->platform_data->targets[target] = targ;
4113 return (targ);
4114}
4115
4116static void
4117ahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ)
4118{
4119 struct ahd_devinfo devinfo;
4120 struct ahd_initiator_tinfo *tinfo;
4121 struct ahd_tmode_tstate *tstate;
4122 u_int our_id;
4123 u_int target_offset;
4124 char channel;
4125
4126 /*
4127 * Force a negotiation to async/narrow on any
4128 * future command to this device unless a bus
4129 * reset occurs between now and that command.
4130 */
4131 channel = 'A' + targ->channel;
4132 our_id = ahd->our_id;
4133 target_offset = targ->target;
4134 tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
4135 targ->target, &tstate);
4136 ahd_compile_devinfo(&devinfo, our_id, targ->target, CAM_LUN_WILDCARD,
4137 channel, ROLE_INITIATOR);
4138 ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
4139 AHD_TRANS_GOAL, /*paused*/FALSE);
4140 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
4141 AHD_TRANS_GOAL, /*paused*/FALSE);
4142 ahd_update_neg_request(ahd, &devinfo, tstate, tinfo, AHD_NEG_ALWAYS);
4143 ahd->platform_data->targets[target_offset] = NULL;
4144 if (targ->inq_data != NULL)
4145 free(targ->inq_data, M_DEVBUF);
4146 if (targ->dv_buffer != NULL)
4147 free(targ->dv_buffer, M_DEVBUF);
4148 if (targ->dv_buffer1 != NULL)
4149 free(targ->dv_buffer1, M_DEVBUF);
4150 free(targ, M_DEVBUF);
4151}
4152
4153static struct ahd_linux_device*
4154ahd_linux_alloc_device(struct ahd_softc *ahd,
4155 struct ahd_linux_target *targ, u_int lun)
4156{
4157 struct ahd_linux_device *dev;
4158
4159 dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);
4160 if (dev == NULL)
4161 return (NULL);
4162 memset(dev, 0, sizeof(*dev));
4163 init_timer(&dev->timer);
4164 TAILQ_INIT(&dev->busyq);
4165 dev->flags = AHD_DEV_UNCONFIGURED;
4166 dev->lun = lun;
4167 dev->target = targ;
4168
4169 /*
4170 * We start out life using untagged
4171 * transactions of which we allow one.
4172 */
4173 dev->openings = 1;
4174
4175 /*
4176 * Set maxtags to 0. This will be changed if we
4177 * later determine that we are dealing with
4178 * a tagged queuing capable device.
4179 */
4180 dev->maxtags = 0;
4181
4182 targ->refcount++;
4183 targ->devices[lun] = dev;
4184 return (dev);
4185}
4186
4187static void
4188ahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev)
4189{
4190 struct ahd_linux_target *targ;
4191
4192 del_timer(&dev->timer);
4193 targ = dev->target;
4194 targ->devices[dev->lun] = NULL;
4195 free(dev, M_DEVBUF);
4196 targ->refcount--;
4197 if (targ->refcount == 0
4198 && (targ->flags & AHD_DV_REQUIRED) == 0)
4199 ahd_linux_free_target(ahd, targ);
4200} 1502}
4201 1503
4202void 1504void
@@ -4207,10 +1509,14 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
4207 case AC_TRANSFER_NEG: 1509 case AC_TRANSFER_NEG:
4208 { 1510 {
4209 char buf[80]; 1511 char buf[80];
1512 struct scsi_target *starget;
4210 struct ahd_linux_target *targ; 1513 struct ahd_linux_target *targ;
4211 struct info_str info; 1514 struct info_str info;
4212 struct ahd_initiator_tinfo *tinfo; 1515 struct ahd_initiator_tinfo *tinfo;
4213 struct ahd_tmode_tstate *tstate; 1516 struct ahd_tmode_tstate *tstate;
1517 unsigned int target_ppr_options;
1518
1519 BUG_ON(target == CAM_TARGET_WILDCARD);
4214 1520
4215 info.buffer = buf; 1521 info.buffer = buf;
4216 info.length = sizeof(buf); 1522 info.length = sizeof(buf);
@@ -4234,58 +1540,47 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
4234 * Don't bother reporting results that 1540 * Don't bother reporting results that
4235 * are identical to those last reported. 1541 * are identical to those last reported.
4236 */ 1542 */
4237 targ = ahd->platform_data->targets[target]; 1543 starget = ahd->platform_data->starget[target];
4238 if (targ == NULL) 1544 if (starget == NULL)
4239 break; 1545 break;
4240 if (tinfo->curr.period == targ->last_tinfo.period 1546 targ = scsi_transport_target_data(starget);
4241 && tinfo->curr.width == targ->last_tinfo.width 1547
4242 && tinfo->curr.offset == targ->last_tinfo.offset 1548 target_ppr_options =
4243 && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options) 1549 (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
1550 + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
1551 + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0)
1552 + (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0)
1553 + (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0)
1554 + (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0)
1555 + (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0)
1556 + (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0);
1557
1558 if (tinfo->curr.period == spi_period(starget)
1559 && tinfo->curr.width == spi_width(starget)
1560 && tinfo->curr.offset == spi_offset(starget)
1561 && tinfo->curr.ppr_options == target_ppr_options)
4244 if (bootverbose == 0) 1562 if (bootverbose == 0)
4245 break; 1563 break;
4246 1564
4247 targ->last_tinfo.period = tinfo->curr.period; 1565 spi_period(starget) = tinfo->curr.period;
4248 targ->last_tinfo.width = tinfo->curr.width; 1566 spi_width(starget) = tinfo->curr.width;
4249 targ->last_tinfo.offset = tinfo->curr.offset; 1567 spi_offset(starget) = tinfo->curr.offset;
4250 targ->last_tinfo.ppr_options = tinfo->curr.ppr_options; 1568 spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
4251 1569 spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
4252 printf("(%s:%c:", ahd_name(ahd), channel); 1570 spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
4253 if (target == CAM_TARGET_WILDCARD) 1571 spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0;
4254 printf("*): "); 1572 spi_pcomp_en(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0;
4255 else 1573 spi_rti(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RTI ? 1 : 0;
4256 printf("%d): ", target); 1574 spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0;
4257 ahd_format_transinfo(&info, &tinfo->curr); 1575 spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0;
4258 if (info.pos < info.length) 1576 spi_display_xfer_agreement(starget);
4259 *info.buffer = '\0';
4260 else
4261 buf[info.length - 1] = '\0';
4262 printf("%s", buf);
4263 break; 1577 break;
4264 } 1578 }
4265 case AC_SENT_BDR: 1579 case AC_SENT_BDR:
4266 { 1580 {
4267#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
4268 WARN_ON(lun != CAM_LUN_WILDCARD); 1581 WARN_ON(lun != CAM_LUN_WILDCARD);
4269 scsi_report_device_reset(ahd->platform_data->host, 1582 scsi_report_device_reset(ahd->platform_data->host,
4270 channel - 'A', target); 1583 channel - 'A', target);
4271#else
4272 Scsi_Device *scsi_dev;
4273
4274 /*
4275 * Find the SCSI device associated with this
4276 * request and indicate that a UA is expected.
4277 */
4278 for (scsi_dev = ahd->platform_data->host->host_queue;
4279 scsi_dev != NULL; scsi_dev = scsi_dev->next) {
4280 if (channel - 'A' == scsi_dev->channel
4281 && target == scsi_dev->id
4282 && (lun == CAM_LUN_WILDCARD
4283 || lun == scsi_dev->lun)) {
4284 scsi_dev->was_reset = 1;
4285 scsi_dev->expecting_cc_ua = 1;
4286 }
4287 }
4288#endif
4289 break; 1584 break;
4290 } 1585 }
4291 case AC_BUS_RESET: 1586 case AC_BUS_RESET:
@@ -4305,7 +1600,7 @@ ahd_send_async(struct ahd_softc *ahd, char channel,
4305void 1600void
4306ahd_done(struct ahd_softc *ahd, struct scb *scb) 1601ahd_done(struct ahd_softc *ahd, struct scb *scb)
4307{ 1602{
4308 Scsi_Cmnd *cmd; 1603 struct scsi_cmnd *cmd;
4309 struct ahd_linux_device *dev; 1604 struct ahd_linux_device *dev;
4310 1605
4311 if ((scb->flags & SCB_ACTIVE) == 0) { 1606 if ((scb->flags & SCB_ACTIVE) == 0) {
@@ -4373,19 +1668,8 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
4373 ahd_set_transaction_status(scb, CAM_REQ_CMP); 1668 ahd_set_transaction_status(scb, CAM_REQ_CMP);
4374 } 1669 }
4375 } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) { 1670 } else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
4376 ahd_linux_handle_scsi_status(ahd, dev, scb); 1671 ahd_linux_handle_scsi_status(ahd, cmd->device, scb);
4377 } else if (ahd_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
4378 dev->flags |= AHD_DEV_UNCONFIGURED;
4379 if (AHD_DV_CMD(cmd) == FALSE)
4380 dev->target->flags &= ~AHD_DV_REQUIRED;
4381 } 1672 }
4382 /*
4383 * Start DV for devices that require it assuming the first command
4384 * sent does not result in a selection timeout.
4385 */
4386 if (ahd_get_transaction_status(scb) != CAM_SEL_TIMEOUT
4387 && (dev->target->flags & AHD_DV_REQUIRED) != 0)
4388 ahd_linux_start_dv(ahd);
4389 1673
4390 if (dev->openings == 1 1674 if (dev->openings == 1
4391 && ahd_get_transaction_status(scb) == CAM_REQ_CMP 1675 && ahd_get_transaction_status(scb) == CAM_REQ_CMP
@@ -4406,47 +1690,32 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
4406 if (dev->active == 0) 1690 if (dev->active == 0)
4407 dev->commands_since_idle_or_otag = 0; 1691 dev->commands_since_idle_or_otag = 0;
4408 1692
4409 if (TAILQ_EMPTY(&dev->busyq)) {
4410 if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
4411 && dev->active == 0
4412 && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)
4413 ahd_linux_free_device(ahd, dev);
4414 } else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {
4415 TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);
4416 dev->flags |= AHD_DEV_ON_RUN_LIST;
4417 }
4418
4419 if ((scb->flags & SCB_RECOVERY_SCB) != 0) { 1693 if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
4420 printf("Recovery SCB completes\n"); 1694 printf("Recovery SCB completes\n");
4421 if (ahd_get_transaction_status(scb) == CAM_BDR_SENT 1695 if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
4422 || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED) 1696 || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
4423 ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT); 1697 ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
4424 if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { 1698 if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
4425 scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; 1699 ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
4426 up(&ahd->platform_data->eh_sem); 1700 up(&ahd->platform_data->eh_sem);
4427 } 1701 }
4428 } 1702 }
4429 1703
4430 ahd_free_scb(ahd, scb); 1704 ahd_free_scb(ahd, scb);
4431 ahd_linux_queue_cmd_complete(ahd, cmd); 1705 ahd_linux_queue_cmd_complete(ahd, cmd);
4432
4433 if ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_EMPTY) != 0
4434 && LIST_FIRST(&ahd->pending_scbs) == NULL) {
4435 ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_EMPTY;
4436 up(&ahd->platform_data->dv_sem);
4437 }
4438} 1706}
4439 1707
4440static void 1708static void
4441ahd_linux_handle_scsi_status(struct ahd_softc *ahd, 1709ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
4442 struct ahd_linux_device *dev, struct scb *scb) 1710 struct scsi_device *sdev, struct scb *scb)
4443{ 1711{
4444 struct ahd_devinfo devinfo; 1712 struct ahd_devinfo devinfo;
1713 struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
4445 1714
4446 ahd_compile_devinfo(&devinfo, 1715 ahd_compile_devinfo(&devinfo,
4447 ahd->our_id, 1716 ahd->our_id,
4448 dev->target->target, dev->lun, 1717 sdev->sdev_target->id, sdev->lun,
4449 dev->target->channel == 0 ? 'A' : 'B', 1718 sdev->sdev_target->channel == 0 ? 'A' : 'B',
4450 ROLE_INITIATOR); 1719 ROLE_INITIATOR);
4451 1720
4452 /* 1721 /*
@@ -4465,7 +1734,7 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
4465 case SCSI_STATUS_CHECK_COND: 1734 case SCSI_STATUS_CHECK_COND:
4466 case SCSI_STATUS_CMD_TERMINATED: 1735 case SCSI_STATUS_CMD_TERMINATED:
4467 { 1736 {
4468 Scsi_Cmnd *cmd; 1737 struct scsi_cmnd *cmd;
4469 1738
4470 /* 1739 /*
4471 * Copy sense information to the OS's cmd 1740 * Copy sense information to the OS's cmd
@@ -4518,7 +1787,6 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
4518 break; 1787 break;
4519 } 1788 }
4520 case SCSI_STATUS_QUEUE_FULL: 1789 case SCSI_STATUS_QUEUE_FULL:
4521 {
4522 /* 1790 /*
4523 * By the time the core driver has returned this 1791 * By the time the core driver has returned this
4524 * command, all other commands that were queued 1792 * command, all other commands that were queued
@@ -4579,98 +1847,23 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
4579 (dev->flags & AHD_DEV_Q_BASIC) 1847 (dev->flags & AHD_DEV_Q_BASIC)
4580 ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED); 1848 ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
4581 ahd_set_scsi_status(scb, SCSI_STATUS_BUSY); 1849 ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
4582 /* FALLTHROUGH */
4583 }
4584 case SCSI_STATUS_BUSY:
4585 /*
4586 * Set a short timer to defer sending commands for
4587 * a bit since Linux will not delay in this case.
4588 */
4589 if ((dev->flags & AHD_DEV_TIMER_ACTIVE) != 0) {
4590 printf("%s:%c:%d: Device Timer still active during "
4591 "busy processing\n", ahd_name(ahd),
4592 dev->target->channel, dev->target->target);
4593 break;
4594 }
4595 dev->flags |= AHD_DEV_TIMER_ACTIVE;
4596 dev->qfrozen++;
4597 init_timer(&dev->timer);
4598 dev->timer.data = (u_long)dev;
4599 dev->timer.expires = jiffies + (HZ/2);
4600 dev->timer.function = ahd_linux_dev_timed_unfreeze;
4601 add_timer(&dev->timer);
4602 break;
4603 } 1850 }
4604} 1851}
4605 1852
4606static void 1853static void
4607ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd) 1854ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
4608{ 1855{
4609 /* 1856 /*
4610 * Typically, the complete queue has very few entries
4611 * queued to it before the queue is emptied by
4612 * ahd_linux_run_complete_queue, so sorting the entries
4613 * by generation number should be inexpensive.
4614 * We perform the sort so that commands that complete
4615 * with an error are retuned in the order origionally
4616 * queued to the controller so that any subsequent retries
4617 * are performed in order. The underlying ahd routines do
4618 * not guarantee the order that aborted commands will be
4619 * returned to us.
4620 */
4621 struct ahd_completeq *completeq;
4622 struct ahd_cmd *list_cmd;
4623 struct ahd_cmd *acmd;
4624
4625 /*
4626 * Map CAM error codes into Linux Error codes. We 1857 * Map CAM error codes into Linux Error codes. We
4627 * avoid the conversion so that the DV code has the 1858 * avoid the conversion so that the DV code has the
4628 * full error information available when making 1859 * full error information available when making
4629 * state change decisions. 1860 * state change decisions.
4630 */ 1861 */
4631 if (AHD_DV_CMD(cmd) == FALSE) { 1862 {
4632 uint32_t status; 1863 uint32_t status;
4633 u_int new_status; 1864 u_int new_status;
4634 1865
4635 status = ahd_cmd_get_transaction_status(cmd); 1866 status = ahd_cmd_get_transaction_status(cmd);
4636 if (status != CAM_REQ_CMP) {
4637 struct ahd_linux_device *dev;
4638 struct ahd_devinfo devinfo;
4639 cam_status cam_status;
4640 uint32_t action;
4641 u_int scsi_status;
4642
4643 dev = ahd_linux_get_device(ahd, cmd->device->channel,
4644 cmd->device->id,
4645 cmd->device->lun,
4646 /*alloc*/FALSE);
4647
4648 if (dev == NULL)
4649 goto no_fallback;
4650
4651 ahd_compile_devinfo(&devinfo,
4652 ahd->our_id,
4653 dev->target->target, dev->lun,
4654 dev->target->channel == 0 ? 'A':'B',
4655 ROLE_INITIATOR);
4656
4657 scsi_status = ahd_cmd_get_scsi_status(cmd);
4658 cam_status = ahd_cmd_get_transaction_status(cmd);
4659 action = aic_error_action(cmd, dev->target->inq_data,
4660 cam_status, scsi_status);
4661 if ((action & SSQ_FALLBACK) != 0) {
4662
4663 /* Update stats */
4664 dev->target->errors_detected++;
4665 if (dev->target->cmds_since_error == 0)
4666 dev->target->cmds_since_error++;
4667 else {
4668 dev->target->cmds_since_error = 0;
4669 ahd_linux_fallback(ahd, &devinfo);
4670 }
4671 }
4672 }
4673no_fallback:
4674 switch (status) { 1867 switch (status) {
4675 case CAM_REQ_INPROG: 1868 case CAM_REQ_INPROG:
4676 case CAM_REQ_CMP: 1869 case CAM_REQ_CMP:
@@ -4715,26 +1908,7 @@ no_fallback:
4715 new_status = DID_ERROR; 1908 new_status = DID_ERROR;
4716 break; 1909 break;
4717 case CAM_REQUEUE_REQ: 1910 case CAM_REQUEUE_REQ:
4718 /* 1911 new_status = DID_REQUEUE;
4719 * If we want the request requeued, make sure there
4720 * are sufficent retries. In the old scsi error code,
4721 * we used to be able to specify a result code that
4722 * bypassed the retry count. Now we must use this
4723 * hack. We also "fake" a check condition with
4724 * a sense code of ABORTED COMMAND. This seems to
4725 * evoke a retry even if this command is being sent
4726 * via the eh thread. Ick! Ick! Ick!
4727 */
4728 if (cmd->retries > 0)
4729 cmd->retries--;
4730 new_status = DID_OK;
4731 ahd_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
4732 cmd->result |= (DRIVER_SENSE << 24);
4733 memset(cmd->sense_buffer, 0,
4734 sizeof(cmd->sense_buffer));
4735 cmd->sense_buffer[0] = SSD_ERRCODE_VALID
4736 | SSD_CURRENT_ERROR;
4737 cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND;
4738 break; 1912 break;
4739 default: 1913 default:
4740 /* We should never get here */ 1914 /* We should never get here */
@@ -4745,116 +1919,23 @@ no_fallback:
4745 ahd_cmd_set_transaction_status(cmd, new_status); 1919 ahd_cmd_set_transaction_status(cmd, new_status);
4746 } 1920 }
4747 1921
4748 completeq = &ahd->platform_data->completeq; 1922 cmd->scsi_done(cmd);
4749 list_cmd = TAILQ_FIRST(completeq);
4750 acmd = (struct ahd_cmd *)cmd;
4751 while (list_cmd != NULL
4752 && acmd_scsi_cmd(list_cmd).serial_number
4753 < acmd_scsi_cmd(acmd).serial_number)
4754 list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
4755 if (list_cmd != NULL)
4756 TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
4757 else
4758 TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
4759} 1923}
4760 1924
4761static void 1925static void
4762ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) 1926ahd_linux_sem_timeout(u_long arg)
4763{ 1927{
4764 struct scsi_inquiry_data *sid; 1928 struct ahd_softc *ahd;
4765 struct ahd_initiator_tinfo *tinfo; 1929 u_long s;
4766 struct ahd_transinfo *user;
4767 struct ahd_transinfo *goal;
4768 struct ahd_transinfo *curr;
4769 struct ahd_tmode_tstate *tstate;
4770 struct ahd_linux_device *dev;
4771 u_int width;
4772 u_int period;
4773 u_int offset;
4774 u_int ppr_options;
4775 u_int trans_version;
4776 u_int prot_version;
4777
4778 /*
4779 * Determine if this lun actually exists. If so,
4780 * hold on to its corresponding device structure.
4781 * If not, make sure we release the device and
4782 * don't bother processing the rest of this inquiry
4783 * command.
4784 */
4785 dev = ahd_linux_get_device(ahd, devinfo->channel - 'A',
4786 devinfo->target, devinfo->lun,
4787 /*alloc*/TRUE);
4788
4789 sid = (struct scsi_inquiry_data *)dev->target->inq_data;
4790 if (SID_QUAL(sid) == SID_QUAL_LU_CONNECTED) {
4791
4792 dev->flags &= ~AHD_DEV_UNCONFIGURED;
4793 } else {
4794 dev->flags |= AHD_DEV_UNCONFIGURED;
4795 return;
4796 }
4797 1930
4798 /* 1931 ahd = (struct ahd_softc *)arg;
4799 * Update our notion of this device's transfer
4800 * negotiation capabilities.
4801 */
4802 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
4803 devinfo->our_scsiid,
4804 devinfo->target, &tstate);
4805 user = &tinfo->user;
4806 goal = &tinfo->goal;
4807 curr = &tinfo->curr;
4808 width = user->width;
4809 period = user->period;
4810 offset = user->offset;
4811 ppr_options = user->ppr_options;
4812 trans_version = user->transport_version;
4813 prot_version = MIN(user->protocol_version, SID_ANSI_REV(sid));
4814 1932
4815 /* 1933 ahd_lock(ahd, &s);
4816 * Only attempt SPI3/4 once we've verified that 1934 if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {
4817 * the device claims to support SPI3/4 features. 1935 ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;
4818 */ 1936 up(&ahd->platform_data->eh_sem);
4819 if (prot_version < SCSI_REV_2)
4820 trans_version = SID_ANSI_REV(sid);
4821 else
4822 trans_version = SCSI_REV_2;
4823
4824 if ((sid->flags & SID_WBus16) == 0)
4825 width = MSG_EXT_WDTR_BUS_8_BIT;
4826 if ((sid->flags & SID_Sync) == 0) {
4827 period = 0;
4828 offset = 0;
4829 ppr_options = 0;
4830 }
4831 if ((sid->spi3data & SID_SPI_QAS) == 0)
4832 ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
4833 if ((sid->spi3data & SID_SPI_CLOCK_DT) == 0)
4834 ppr_options &= MSG_EXT_PPR_QAS_REQ;
4835 if ((sid->spi3data & SID_SPI_IUS) == 0)
4836 ppr_options &= (MSG_EXT_PPR_DT_REQ
4837 | MSG_EXT_PPR_QAS_REQ);
4838
4839 if (prot_version > SCSI_REV_2
4840 && ppr_options != 0)
4841 trans_version = user->transport_version;
4842
4843 ahd_validate_width(ahd, /*tinfo limit*/NULL, &width, ROLE_UNKNOWN);
4844 ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
4845 ahd_validate_offset(ahd, /*tinfo limit*/NULL, period,
4846 &offset, width, ROLE_UNKNOWN);
4847 if (offset == 0 || period == 0) {
4848 period = 0;
4849 offset = 0;
4850 ppr_options = 0;
4851 } 1937 }
4852 /* Apply our filtered user settings. */ 1938 ahd_unlock(ahd, &s);
4853 curr->transport_version = trans_version;
4854 curr->protocol_version = prot_version;
4855 ahd_set_width(ahd, devinfo, width, AHD_TRANS_GOAL, /*paused*/FALSE);
4856 ahd_set_syncrate(ahd, devinfo, period, offset, ppr_options,
4857 AHD_TRANS_GOAL, /*paused*/FALSE);
4858} 1939}
4859 1940
4860void 1941void
@@ -4882,12 +1963,6 @@ ahd_release_simq(struct ahd_softc *ahd)
4882 if (ahd->platform_data->qfrozen == 0) { 1963 if (ahd->platform_data->qfrozen == 0) {
4883 unblock_reqs = 1; 1964 unblock_reqs = 1;
4884 } 1965 }
4885 if (AHD_DV_SIMQ_FROZEN(ahd)
4886 && ((ahd->platform_data->flags & AHD_DV_WAIT_SIMQ_RELEASE) != 0)) {
4887 ahd->platform_data->flags &= ~AHD_DV_WAIT_SIMQ_RELEASE;
4888 up(&ahd->platform_data->dv_sem);
4889 }
4890 ahd_schedule_runq(ahd);
4891 ahd_unlock(ahd, &s); 1966 ahd_unlock(ahd, &s);
4892 /* 1967 /*
4893 * There is still a race here. The mid-layer 1968 * There is still a race here. The mid-layer
@@ -4899,118 +1974,743 @@ ahd_release_simq(struct ahd_softc *ahd)
4899 scsi_unblock_requests(ahd->platform_data->host); 1974 scsi_unblock_requests(ahd->platform_data->host);
4900} 1975}
4901 1976
4902static void 1977static int
4903ahd_linux_sem_timeout(u_long arg) 1978ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
4904{ 1979{
4905 struct scb *scb; 1980 struct ahd_softc *ahd;
4906 struct ahd_softc *ahd; 1981 struct ahd_linux_device *dev;
4907 u_long s; 1982 struct scb *pending_scb;
1983 u_int saved_scbptr;
1984 u_int active_scbptr;
1985 u_int last_phase;
1986 u_int saved_scsiid;
1987 u_int cdb_byte;
1988 int retval;
1989 int was_paused;
1990 int paused;
1991 int wait;
1992 int disconnected;
1993 ahd_mode_state saved_modes;
4908 1994
4909 scb = (struct scb *)arg; 1995 pending_scb = NULL;
4910 ahd = scb->ahd_softc; 1996 paused = FALSE;
4911 ahd_lock(ahd, &s); 1997 wait = FALSE;
4912 if ((scb->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) { 1998 ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
4913 scb->platform_data->flags &= ~AHD_SCB_UP_EH_SEM; 1999
4914 up(&ahd->platform_data->eh_sem); 2000 printf("%s:%d:%d:%d: Attempting to queue a%s message:",
2001 ahd_name(ahd), cmd->device->channel,
2002 cmd->device->id, cmd->device->lun,
2003 flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
2004
2005 printf("CDB:");
2006 for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
2007 printf(" 0x%x", cmd->cmnd[cdb_byte]);
2008 printf("\n");
2009
2010 spin_lock_irq(&ahd->platform_data->spin_lock);
2011
2012 /*
2013 * First determine if we currently own this command.
2014 * Start by searching the device queue. If not found
2015 * there, check the pending_scb list. If not found
2016 * at all, and the system wanted us to just abort the
2017 * command, return success.
2018 */
2019 dev = scsi_transport_device_data(cmd->device);
2020
2021 if (dev == NULL) {
2022 /*
2023 * No target device for this command exists,
2024 * so we must not still own the command.
2025 */
2026 printf("%s:%d:%d:%d: Is not an active device\n",
2027 ahd_name(ahd), cmd->device->channel, cmd->device->id,
2028 cmd->device->lun);
2029 retval = SUCCESS;
2030 goto no_cmd;
4915 } 2031 }
4916 ahd_unlock(ahd, &s); 2032
2033 /*
2034 * See if we can find a matching cmd in the pending list.
2035 */
2036 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
2037 if (pending_scb->io_ctx == cmd)
2038 break;
2039 }
2040
2041 if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {
2042
2043 /* Any SCB for this device will do for a target reset */
2044 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
2045 if (ahd_match_scb(ahd, pending_scb, cmd->device->id,
2046 cmd->device->channel + 'A',
2047 CAM_LUN_WILDCARD,
2048 SCB_LIST_NULL, ROLE_INITIATOR) == 0)
2049 break;
2050 }
2051 }
2052
2053 if (pending_scb == NULL) {
2054 printf("%s:%d:%d:%d: Command not found\n",
2055 ahd_name(ahd), cmd->device->channel, cmd->device->id,
2056 cmd->device->lun);
2057 goto no_cmd;
2058 }
2059
2060 if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
2061 /*
2062 * We can't queue two recovery actions using the same SCB
2063 */
2064 retval = FAILED;
2065 goto done;
2066 }
2067
2068 /*
2069 * Ensure that the card doesn't do anything
2070 * behind our back. Also make sure that we
2071 * didn't "just" miss an interrupt that would
2072 * affect this cmd.
2073 */
2074 was_paused = ahd_is_paused(ahd);
2075 ahd_pause_and_flushwork(ahd);
2076 paused = TRUE;
2077
2078 if ((pending_scb->flags & SCB_ACTIVE) == 0) {
2079 printf("%s:%d:%d:%d: Command already completed\n",
2080 ahd_name(ahd), cmd->device->channel, cmd->device->id,
2081 cmd->device->lun);
2082 goto no_cmd;
2083 }
2084
2085 printf("%s: At time of recovery, card was %spaused\n",
2086 ahd_name(ahd), was_paused ? "" : "not ");
2087 ahd_dump_card_state(ahd);
2088
2089 disconnected = TRUE;
2090 if (flag == SCB_ABORT) {
2091 if (ahd_search_qinfifo(ahd, cmd->device->id,
2092 cmd->device->channel + 'A',
2093 cmd->device->lun,
2094 pending_scb->hscb->tag,
2095 ROLE_INITIATOR, CAM_REQ_ABORTED,
2096 SEARCH_COMPLETE) > 0) {
2097 printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
2098 ahd_name(ahd), cmd->device->channel,
2099 cmd->device->id, cmd->device->lun);
2100 retval = SUCCESS;
2101 goto done;
2102 }
2103 } else if (ahd_search_qinfifo(ahd, cmd->device->id,
2104 cmd->device->channel + 'A',
2105 cmd->device->lun, pending_scb->hscb->tag,
2106 ROLE_INITIATOR, /*status*/0,
2107 SEARCH_COUNT) > 0) {
2108 disconnected = FALSE;
2109 }
2110
2111 saved_modes = ahd_save_modes(ahd);
2112 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
2113 last_phase = ahd_inb(ahd, LASTPHASE);
2114 saved_scbptr = ahd_get_scbptr(ahd);
2115 active_scbptr = saved_scbptr;
2116 if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
2117 struct scb *bus_scb;
2118
2119 bus_scb = ahd_lookup_scb(ahd, active_scbptr);
2120 if (bus_scb == pending_scb)
2121 disconnected = FALSE;
2122 else if (flag != SCB_ABORT
2123 && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid
2124 && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb))
2125 disconnected = FALSE;
2126 }
2127
2128 /*
2129 * At this point, pending_scb is the scb associated with the
2130 * passed in command. That command is currently active on the
2131 * bus or is in the disconnected state.
2132 */
2133 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
2134 if (last_phase != P_BUSFREE
2135 && (SCB_GET_TAG(pending_scb) == active_scbptr
2136 || (flag == SCB_DEVICE_RESET
2137 && SCSIID_TARGET(ahd, saved_scsiid) == cmd->device->id))) {
2138
2139 /*
2140 * We're active on the bus, so assert ATN
2141 * and hope that the target responds.
2142 */
2143 pending_scb = ahd_lookup_scb(ahd, active_scbptr);
2144 pending_scb->flags |= SCB_RECOVERY_SCB|flag;
2145 ahd_outb(ahd, MSG_OUT, HOST_MSG);
2146 ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
2147 printf("%s:%d:%d:%d: Device is active, asserting ATN\n",
2148 ahd_name(ahd), cmd->device->channel,
2149 cmd->device->id, cmd->device->lun);
2150 wait = TRUE;
2151 } else if (disconnected) {
2152
2153 /*
2154 * Actually re-queue this SCB in an attempt
2155 * to select the device before it reconnects.
2156 */
2157 pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
2158 ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
2159 pending_scb->hscb->cdb_len = 0;
2160 pending_scb->hscb->task_attribute = 0;
2161 pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
2162
2163 if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
2164 /*
2165 * Mark the SCB has having an outstanding
2166 * task management function. Should the command
2167 * complete normally before the task management
2168 * function can be sent, the host will be notified
2169 * to abort our requeued SCB.
2170 */
2171 ahd_outb(ahd, SCB_TASK_MANAGEMENT,
2172 pending_scb->hscb->task_management);
2173 } else {
2174 /*
2175 * If non-packetized, set the MK_MESSAGE control
2176 * bit indicating that we desire to send a message.
2177 * We also set the disconnected flag since there is
2178 * no guarantee that our SCB control byte matches
2179 * the version on the card. We don't want the
2180 * sequencer to abort the command thinking an
2181 * unsolicited reselection occurred.
2182 */
2183 pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
2184
2185 /*
2186 * The sequencer will never re-reference the
2187 * in-core SCB. To make sure we are notified
2188 * during reslection, set the MK_MESSAGE flag in
2189 * the card's copy of the SCB.
2190 */
2191 ahd_outb(ahd, SCB_CONTROL,
2192 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
2193 }
2194
2195 /*
2196 * Clear out any entries in the QINFIFO first
2197 * so we are the next SCB for this target
2198 * to run.
2199 */
2200 ahd_search_qinfifo(ahd, cmd->device->id,
2201 cmd->device->channel + 'A', cmd->device->lun,
2202 SCB_LIST_NULL, ROLE_INITIATOR,
2203 CAM_REQUEUE_REQ, SEARCH_COMPLETE);
2204 ahd_qinfifo_requeue_tail(ahd, pending_scb);
2205 ahd_set_scbptr(ahd, saved_scbptr);
2206 ahd_print_path(ahd, pending_scb);
2207 printf("Device is disconnected, re-queuing SCB\n");
2208 wait = TRUE;
2209 } else {
2210 printf("%s:%d:%d:%d: Unable to deliver message\n",
2211 ahd_name(ahd), cmd->device->channel,
2212 cmd->device->id, cmd->device->lun);
2213 retval = FAILED;
2214 goto done;
2215 }
2216
2217no_cmd:
2218 /*
2219 * Our assumption is that if we don't have the command, no
2220 * recovery action was required, so we return success. Again,
2221 * the semantics of the mid-layer recovery engine are not
2222 * well defined, so this may change in time.
2223 */
2224 retval = SUCCESS;
2225done:
2226 if (paused)
2227 ahd_unpause(ahd);
2228 if (wait) {
2229 struct timer_list timer;
2230 int ret;
2231
2232 ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM;
2233 spin_unlock_irq(&ahd->platform_data->spin_lock);
2234 init_timer(&timer);
2235 timer.data = (u_long)ahd;
2236 timer.expires = jiffies + (5 * HZ);
2237 timer.function = ahd_linux_sem_timeout;
2238 add_timer(&timer);
2239 printf("Recovery code sleeping\n");
2240 down(&ahd->platform_data->eh_sem);
2241 printf("Recovery code awake\n");
2242 ret = del_timer_sync(&timer);
2243 if (ret == 0) {
2244 printf("Timer Expired\n");
2245 retval = FAILED;
2246 }
2247 spin_lock_irq(&ahd->platform_data->spin_lock);
2248 }
2249 spin_unlock_irq(&ahd->platform_data->spin_lock);
2250 return (retval);
4917} 2251}
4918 2252
4919static void 2253static void ahd_linux_set_width(struct scsi_target *starget, int width)
4920ahd_linux_dev_timed_unfreeze(u_long arg)
4921{ 2254{
4922 struct ahd_linux_device *dev; 2255 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
4923 struct ahd_softc *ahd; 2256 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
4924 u_long s; 2257 struct ahd_devinfo devinfo;
2258 unsigned long flags;
4925 2259
4926 dev = (struct ahd_linux_device *)arg; 2260 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
4927 ahd = dev->target->ahd; 2261 starget->channel + 'A', ROLE_INITIATOR);
4928 ahd_lock(ahd, &s); 2262 ahd_lock(ahd, &flags);
4929 dev->flags &= ~AHD_DEV_TIMER_ACTIVE; 2263 ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
4930 if (dev->qfrozen > 0) 2264 ahd_unlock(ahd, &flags);
4931 dev->qfrozen--;
4932 if (dev->qfrozen == 0
4933 && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0)
4934 ahd_linux_run_device_queue(ahd, dev);
4935 if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0
4936 && dev->active == 0)
4937 ahd_linux_free_device(ahd, dev);
4938 ahd_unlock(ahd, &s);
4939} 2265}
4940 2266
4941void 2267static void ahd_linux_set_period(struct scsi_target *starget, int period)
4942ahd_platform_dump_card_state(struct ahd_softc *ahd)
4943{ 2268{
4944 struct ahd_linux_device *dev; 2269 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
4945 int target; 2270 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
4946 int maxtarget; 2271 struct ahd_tmode_tstate *tstate;
4947 int lun; 2272 struct ahd_initiator_tinfo *tinfo
4948 int i; 2273 = ahd_fetch_transinfo(ahd,
4949 2274 starget->channel + 'A',
4950 maxtarget = (ahd->features & AHD_WIDE) ? 15 : 7; 2275 shost->this_id, starget->id, &tstate);
4951 for (target = 0; target <=maxtarget; target++) { 2276 struct ahd_devinfo devinfo;
4952 2277 unsigned int ppr_options = tinfo->goal.ppr_options;
4953 for (lun = 0; lun < AHD_NUM_LUNS; lun++) { 2278 unsigned int dt;
4954 struct ahd_cmd *acmd; 2279 unsigned long flags;
4955 2280 unsigned long offset = tinfo->goal.offset;
4956 dev = ahd_linux_get_device(ahd, 0, target, 2281
4957 lun, /*alloc*/FALSE); 2282#ifdef AHD_DEBUG
4958 if (dev == NULL) 2283 if ((ahd_debug & AHD_SHOW_DV) != 0)
4959 continue; 2284 printf("%s: set period to %d\n", ahd_name(ahd), period);
4960 2285#endif
4961 printf("DevQ(%d:%d:%d): ", 0, target, lun); 2286 if (offset == 0)
4962 i = 0; 2287 offset = MAX_OFFSET;
4963 TAILQ_FOREACH(acmd, &dev->busyq, acmd_links.tqe) { 2288
4964 if (i++ > AHD_SCB_MAX) 2289 if (period < 8)
4965 break; 2290 period = 8;
4966 } 2291 if (period < 10) {
4967 printf("%d waiting\n", i); 2292 ppr_options |= MSG_EXT_PPR_DT_REQ;
4968 } 2293 if (period == 8)
2294 ppr_options |= MSG_EXT_PPR_IU_REQ;
2295 }
2296
2297 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2298
2299 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2300 starget->channel + 'A', ROLE_INITIATOR);
2301
2302 /* all PPR requests apart from QAS require wide transfers */
2303 if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
2304 if (spi_width(starget) == 0)
2305 ppr_options &= MSG_EXT_PPR_QAS_REQ;
4969 } 2306 }
2307
2308 ahd_find_syncrate(ahd, &period, &ppr_options,
2309 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2310
2311 ahd_lock(ahd, &flags);
2312 ahd_set_syncrate(ahd, &devinfo, period, offset,
2313 ppr_options, AHD_TRANS_GOAL, FALSE);
2314 ahd_unlock(ahd, &flags);
4970} 2315}
4971 2316
4972static int __init 2317static void ahd_linux_set_offset(struct scsi_target *starget, int offset)
4973ahd_linux_init(void)
4974{ 2318{
4975#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 2319 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
4976 return ahd_linux_detect(&aic79xx_driver_template); 2320 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
4977#else 2321 struct ahd_tmode_tstate *tstate;
4978 scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template); 2322 struct ahd_initiator_tinfo *tinfo
4979 if (aic79xx_driver_template.present == 0) { 2323 = ahd_fetch_transinfo(ahd,
4980 scsi_unregister_module(MODULE_SCSI_HA, 2324 starget->channel + 'A',
4981 &aic79xx_driver_template); 2325 shost->this_id, starget->id, &tstate);
4982 return (-ENODEV); 2326 struct ahd_devinfo devinfo;
2327 unsigned int ppr_options = 0;
2328 unsigned int period = 0;
2329 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2330 unsigned long flags;
2331
2332#ifdef AHD_DEBUG
2333 if ((ahd_debug & AHD_SHOW_DV) != 0)
2334 printf("%s: set offset to %d\n", ahd_name(ahd), offset);
2335#endif
2336
2337 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2338 starget->channel + 'A', ROLE_INITIATOR);
2339 if (offset != 0) {
2340 period = tinfo->goal.period;
2341 ppr_options = tinfo->goal.ppr_options;
2342 ahd_find_syncrate(ahd, &period, &ppr_options,
2343 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
4983 } 2344 }
4984 2345
4985 return (0); 2346 ahd_lock(ahd, &flags);
2347 ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
2348 AHD_TRANS_GOAL, FALSE);
2349 ahd_unlock(ahd, &flags);
2350}
2351
2352static void ahd_linux_set_dt(struct scsi_target *starget, int dt)
2353{
2354 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2355 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2356 struct ahd_tmode_tstate *tstate;
2357 struct ahd_initiator_tinfo *tinfo
2358 = ahd_fetch_transinfo(ahd,
2359 starget->channel + 'A',
2360 shost->this_id, starget->id, &tstate);
2361 struct ahd_devinfo devinfo;
2362 unsigned int ppr_options = tinfo->goal.ppr_options
2363 & ~MSG_EXT_PPR_DT_REQ;
2364 unsigned int period = tinfo->goal.period;
2365 unsigned int width = tinfo->goal.width;
2366 unsigned long flags;
2367
2368#ifdef AHD_DEBUG
2369 if ((ahd_debug & AHD_SHOW_DV) != 0)
2370 printf("%s: %s DT\n", ahd_name(ahd),
2371 dt ? "enabling" : "disabling");
2372#endif
2373 if (dt) {
2374 ppr_options |= MSG_EXT_PPR_DT_REQ;
2375 if (!width)
2376 ahd_linux_set_width(starget, 1);
2377 } else {
2378 if (period <= 9)
2379 period = 10; /* If resetting DT, period must be >= 25ns */
2380 /* IU is invalid without DT set */
2381 ppr_options &= ~MSG_EXT_PPR_IU_REQ;
2382 }
2383 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2384 starget->channel + 'A', ROLE_INITIATOR);
2385 ahd_find_syncrate(ahd, &period, &ppr_options,
2386 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2387
2388 ahd_lock(ahd, &flags);
2389 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2390 ppr_options, AHD_TRANS_GOAL, FALSE);
2391 ahd_unlock(ahd, &flags);
2392}
2393
2394static void ahd_linux_set_qas(struct scsi_target *starget, int qas)
2395{
2396 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2397 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2398 struct ahd_tmode_tstate *tstate;
2399 struct ahd_initiator_tinfo *tinfo
2400 = ahd_fetch_transinfo(ahd,
2401 starget->channel + 'A',
2402 shost->this_id, starget->id, &tstate);
2403 struct ahd_devinfo devinfo;
2404 unsigned int ppr_options = tinfo->goal.ppr_options
2405 & ~MSG_EXT_PPR_QAS_REQ;
2406 unsigned int period = tinfo->goal.period;
2407 unsigned int dt;
2408 unsigned long flags;
2409
2410#ifdef AHD_DEBUG
2411 if ((ahd_debug & AHD_SHOW_DV) != 0)
2412 printf("%s: %s QAS\n", ahd_name(ahd),
2413 qas ? "enabling" : "disabling");
2414#endif
2415
2416 if (qas) {
2417 ppr_options |= MSG_EXT_PPR_QAS_REQ;
2418 }
2419
2420 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2421
2422 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2423 starget->channel + 'A', ROLE_INITIATOR);
2424 ahd_find_syncrate(ahd, &period, &ppr_options,
2425 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2426
2427 ahd_lock(ahd, &flags);
2428 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2429 ppr_options, AHD_TRANS_GOAL, FALSE);
2430 ahd_unlock(ahd, &flags);
2431}
2432
2433static void ahd_linux_set_iu(struct scsi_target *starget, int iu)
2434{
2435 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2436 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2437 struct ahd_tmode_tstate *tstate;
2438 struct ahd_initiator_tinfo *tinfo
2439 = ahd_fetch_transinfo(ahd,
2440 starget->channel + 'A',
2441 shost->this_id, starget->id, &tstate);
2442 struct ahd_devinfo devinfo;
2443 unsigned int ppr_options = tinfo->goal.ppr_options
2444 & ~MSG_EXT_PPR_IU_REQ;
2445 unsigned int period = tinfo->goal.period;
2446 unsigned int dt;
2447 unsigned long flags;
2448
2449#ifdef AHD_DEBUG
2450 if ((ahd_debug & AHD_SHOW_DV) != 0)
2451 printf("%s: %s IU\n", ahd_name(ahd),
2452 iu ? "enabling" : "disabling");
4986#endif 2453#endif
2454
2455 if (iu) {
2456 ppr_options |= MSG_EXT_PPR_IU_REQ;
2457 ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */
2458 }
2459
2460 dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2461
2462 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2463 starget->channel + 'A', ROLE_INITIATOR);
2464 ahd_find_syncrate(ahd, &period, &ppr_options,
2465 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2466
2467 ahd_lock(ahd, &flags);
2468 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2469 ppr_options, AHD_TRANS_GOAL, FALSE);
2470 ahd_unlock(ahd, &flags);
4987} 2471}
4988 2472
4989static void __exit 2473static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm)
4990ahd_linux_exit(void)
4991{ 2474{
4992 struct ahd_softc *ahd; 2475 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2476 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2477 struct ahd_tmode_tstate *tstate;
2478 struct ahd_initiator_tinfo *tinfo
2479 = ahd_fetch_transinfo(ahd,
2480 starget->channel + 'A',
2481 shost->this_id, starget->id, &tstate);
2482 struct ahd_devinfo devinfo;
2483 unsigned int ppr_options = tinfo->goal.ppr_options
2484 & ~MSG_EXT_PPR_RD_STRM;
2485 unsigned int period = tinfo->goal.period;
2486 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2487 unsigned long flags;
4993 2488
4994 /* 2489#ifdef AHD_DEBUG
4995 * Shutdown DV threads before going into the SCSI mid-layer. 2490 if ((ahd_debug & AHD_SHOW_DV) != 0)
4996 * This avoids situations where the mid-layer locks the entire 2491 printf("%s: %s Read Streaming\n", ahd_name(ahd),
4997 * kernel so that waiting for our DV threads to exit leads 2492 rdstrm ? "enabling" : "disabling");
4998 * to deadlock. 2493#endif
4999 */ 2494
5000 TAILQ_FOREACH(ahd, &ahd_tailq, links) { 2495 if (rdstrm)
2496 ppr_options |= MSG_EXT_PPR_RD_STRM;
2497
2498 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2499 starget->channel + 'A', ROLE_INITIATOR);
2500 ahd_find_syncrate(ahd, &period, &ppr_options,
2501 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2502
2503 ahd_lock(ahd, &flags);
2504 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2505 ppr_options, AHD_TRANS_GOAL, FALSE);
2506 ahd_unlock(ahd, &flags);
2507}
2508
2509static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow)
2510{
2511 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2512 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2513 struct ahd_tmode_tstate *tstate;
2514 struct ahd_initiator_tinfo *tinfo
2515 = ahd_fetch_transinfo(ahd,
2516 starget->channel + 'A',
2517 shost->this_id, starget->id, &tstate);
2518 struct ahd_devinfo devinfo;
2519 unsigned int ppr_options = tinfo->goal.ppr_options
2520 & ~MSG_EXT_PPR_WR_FLOW;
2521 unsigned int period = tinfo->goal.period;
2522 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2523 unsigned long flags;
2524
2525#ifdef AHD_DEBUG
2526 if ((ahd_debug & AHD_SHOW_DV) != 0)
2527 printf("%s: %s Write Flow Control\n", ahd_name(ahd),
2528 wrflow ? "enabling" : "disabling");
2529#endif
2530
2531 if (wrflow)
2532 ppr_options |= MSG_EXT_PPR_WR_FLOW;
2533
2534 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2535 starget->channel + 'A', ROLE_INITIATOR);
2536 ahd_find_syncrate(ahd, &period, &ppr_options,
2537 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2538
2539 ahd_lock(ahd, &flags);
2540 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2541 ppr_options, AHD_TRANS_GOAL, FALSE);
2542 ahd_unlock(ahd, &flags);
2543}
2544
2545static void ahd_linux_set_rti(struct scsi_target *starget, int rti)
2546{
2547 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2548 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2549 struct ahd_tmode_tstate *tstate;
2550 struct ahd_initiator_tinfo *tinfo
2551 = ahd_fetch_transinfo(ahd,
2552 starget->channel + 'A',
2553 shost->this_id, starget->id, &tstate);
2554 struct ahd_devinfo devinfo;
2555 unsigned int ppr_options = tinfo->goal.ppr_options
2556 & ~MSG_EXT_PPR_RTI;
2557 unsigned int period = tinfo->goal.period;
2558 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2559 unsigned long flags;
5001 2560
5002 ahd_linux_kill_dv_thread(ahd); 2561 if ((ahd->features & AHD_RTI) == 0) {
2562#ifdef AHD_DEBUG
2563 if ((ahd_debug & AHD_SHOW_DV) != 0)
2564 printf("%s: RTI not available\n", ahd_name(ahd));
2565#endif
2566 return;
5003 } 2567 }
5004 2568
5005#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 2569#ifdef AHD_DEBUG
2570 if ((ahd_debug & AHD_SHOW_DV) != 0)
2571 printf("%s: %s RTI\n", ahd_name(ahd),
2572 rti ? "enabling" : "disabling");
2573#endif
2574
2575 if (rti)
2576 ppr_options |= MSG_EXT_PPR_RTI;
2577
2578 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2579 starget->channel + 'A', ROLE_INITIATOR);
2580 ahd_find_syncrate(ahd, &period, &ppr_options,
2581 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2582
2583 ahd_lock(ahd, &flags);
2584 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2585 ppr_options, AHD_TRANS_GOAL, FALSE);
2586 ahd_unlock(ahd, &flags);
2587}
2588
2589static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
2590{
2591 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2592 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2593 struct ahd_tmode_tstate *tstate;
2594 struct ahd_initiator_tinfo *tinfo
2595 = ahd_fetch_transinfo(ahd,
2596 starget->channel + 'A',
2597 shost->this_id, starget->id, &tstate);
2598 struct ahd_devinfo devinfo;
2599 unsigned int ppr_options = tinfo->goal.ppr_options
2600 & ~MSG_EXT_PPR_PCOMP_EN;
2601 unsigned int period = tinfo->goal.period;
2602 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2603 unsigned long flags;
2604
2605#ifdef AHD_DEBUG
2606 if ((ahd_debug & AHD_SHOW_DV) != 0)
2607 printf("%s: %s Precompensation\n", ahd_name(ahd),
2608 pcomp ? "Enable" : "Disable");
2609#endif
2610
2611 if (pcomp)
2612 ppr_options |= MSG_EXT_PPR_PCOMP_EN;
2613
2614 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2615 starget->channel + 'A', ROLE_INITIATOR);
2616 ahd_find_syncrate(ahd, &period, &ppr_options,
2617 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2618
2619 ahd_lock(ahd, &flags);
2620 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2621 ppr_options, AHD_TRANS_GOAL, FALSE);
2622 ahd_unlock(ahd, &flags);
2623}
2624
2625static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold)
2626{
2627 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
2628 struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
2629 struct ahd_tmode_tstate *tstate;
2630 struct ahd_initiator_tinfo *tinfo
2631 = ahd_fetch_transinfo(ahd,
2632 starget->channel + 'A',
2633 shost->this_id, starget->id, &tstate);
2634 struct ahd_devinfo devinfo;
2635 unsigned int ppr_options = tinfo->goal.ppr_options
2636 & ~MSG_EXT_PPR_HOLD_MCS;
2637 unsigned int period = tinfo->goal.period;
2638 unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
2639 unsigned long flags;
2640
2641 if (hold)
2642 ppr_options |= MSG_EXT_PPR_HOLD_MCS;
2643
2644 ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
2645 starget->channel + 'A', ROLE_INITIATOR);
2646 ahd_find_syncrate(ahd, &period, &ppr_options,
2647 dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
2648
2649 ahd_lock(ahd, &flags);
2650 ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
2651 ppr_options, AHD_TRANS_GOAL, FALSE);
2652 ahd_unlock(ahd, &flags);
2653}
2654
2655
2656
2657static struct spi_function_template ahd_linux_transport_functions = {
2658 .set_offset = ahd_linux_set_offset,
2659 .show_offset = 1,
2660 .set_period = ahd_linux_set_period,
2661 .show_period = 1,
2662 .set_width = ahd_linux_set_width,
2663 .show_width = 1,
2664 .set_dt = ahd_linux_set_dt,
2665 .show_dt = 1,
2666 .set_iu = ahd_linux_set_iu,
2667 .show_iu = 1,
2668 .set_qas = ahd_linux_set_qas,
2669 .show_qas = 1,
2670 .set_rd_strm = ahd_linux_set_rd_strm,
2671 .show_rd_strm = 1,
2672 .set_wr_flow = ahd_linux_set_wr_flow,
2673 .show_wr_flow = 1,
2674 .set_rti = ahd_linux_set_rti,
2675 .show_rti = 1,
2676 .set_pcomp_en = ahd_linux_set_pcomp_en,
2677 .show_pcomp_en = 1,
2678 .set_hold_mcs = ahd_linux_set_hold_mcs,
2679 .show_hold_mcs = 1,
2680};
2681
2682static int __init
2683ahd_linux_init(void)
2684{
2685 int error = 0;
2686
5006 /* 2687 /*
5007 * In 2.4 we have to unregister from the PCI core _after_ 2688 * If we've been passed any parameters, process them now.
5008 * unregistering from the scsi midlayer to avoid dangling
5009 * references.
5010 */ 2689 */
5011 scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template); 2690 if (aic79xx)
5012#endif 2691 aic79xx_setup(aic79xx);
2692
2693 ahd_linux_transport_template =
2694 spi_attach_transport(&ahd_linux_transport_functions);
2695 if (!ahd_linux_transport_template)
2696 return -ENODEV;
2697
2698 scsi_transport_reserve_target(ahd_linux_transport_template,
2699 sizeof(struct ahd_linux_target));
2700 scsi_transport_reserve_device(ahd_linux_transport_template,
2701 sizeof(struct ahd_linux_device));
2702
2703 error = ahd_linux_pci_init();
2704 if (error)
2705 spi_release_transport(ahd_linux_transport_template);
2706 return error;
2707}
2708
2709static void __exit
2710ahd_linux_exit(void)
2711{
5013 ahd_linux_pci_exit(); 2712 ahd_linux_pci_exit();
2713 spi_release_transport(ahd_linux_transport_template);
5014} 2714}
5015 2715
5016module_init(ahd_linux_init); 2716module_init(ahd_linux_init);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 7823e52e99ab..052c6619accc 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -42,6 +42,7 @@
42#ifndef _AIC79XX_LINUX_H_ 42#ifndef _AIC79XX_LINUX_H_
43#define _AIC79XX_LINUX_H_ 43#define _AIC79XX_LINUX_H_
44 44
45#include <linux/config.h>
45#include <linux/types.h> 46#include <linux/types.h>
46#include <linux/blkdev.h> 47#include <linux/blkdev.h>
47#include <linux/delay.h> 48#include <linux/delay.h>
@@ -49,18 +50,23 @@
49#include <linux/pci.h> 50#include <linux/pci.h>
50#include <linux/smp_lock.h> 51#include <linux/smp_lock.h>
51#include <linux/version.h> 52#include <linux/version.h>
53#include <linux/interrupt.h>
52#include <linux/module.h> 54#include <linux/module.h>
55#include <linux/slab.h>
53#include <asm/byteorder.h> 56#include <asm/byteorder.h>
54#include <asm/io.h> 57#include <asm/io.h>
55 58
56#include <linux/interrupt.h> /* For tasklet support. */ 59#include <scsi/scsi.h>
57#include <linux/config.h> 60#include <scsi/scsi_cmnd.h>
58#include <linux/slab.h> 61#include <scsi/scsi_eh.h>
62#include <scsi/scsi_device.h>
63#include <scsi/scsi_host.h>
64#include <scsi/scsi_tcq.h>
65#include <scsi/scsi_transport.h>
66#include <scsi/scsi_transport_spi.h>
59 67
60/* Core SCSI definitions */ 68/* Core SCSI definitions */
61#define AIC_LIB_PREFIX ahd 69#define AIC_LIB_PREFIX ahd
62#include "scsi.h"
63#include <scsi/scsi_host.h>
64 70
65/* Name space conflict with BSD queue macros */ 71/* Name space conflict with BSD queue macros */
66#ifdef LIST_HEAD 72#ifdef LIST_HEAD
@@ -95,7 +101,7 @@
95/************************* Forward Declarations *******************************/ 101/************************* Forward Declarations *******************************/
96struct ahd_softc; 102struct ahd_softc;
97typedef struct pci_dev *ahd_dev_softc_t; 103typedef struct pci_dev *ahd_dev_softc_t;
98typedef Scsi_Cmnd *ahd_io_ctx_t; 104typedef struct scsi_cmnd *ahd_io_ctx_t;
99 105
100/******************************* Byte Order ***********************************/ 106/******************************* Byte Order ***********************************/
101#define ahd_htobe16(x) cpu_to_be16(x) 107#define ahd_htobe16(x) cpu_to_be16(x)
@@ -114,8 +120,7 @@ typedef Scsi_Cmnd *ahd_io_ctx_t;
114 120
115/************************* Configuration Data *********************************/ 121/************************* Configuration Data *********************************/
116extern uint32_t aic79xx_allow_memio; 122extern uint32_t aic79xx_allow_memio;
117extern int aic79xx_detect_complete; 123extern struct scsi_host_template aic79xx_driver_template;
118extern Scsi_Host_Template aic79xx_driver_template;
119 124
120/***************************** Bus Space/DMA **********************************/ 125/***************************** Bus Space/DMA **********************************/
121 126
@@ -145,11 +150,7 @@ struct ahd_linux_dma_tag
145}; 150};
146typedef struct ahd_linux_dma_tag* bus_dma_tag_t; 151typedef struct ahd_linux_dma_tag* bus_dma_tag_t;
147 152
148struct ahd_linux_dmamap 153typedef dma_addr_t bus_dmamap_t;
149{
150 dma_addr_t bus_addr;
151};
152typedef struct ahd_linux_dmamap* bus_dmamap_t;
153 154
154typedef int bus_dma_filter_t(void*, dma_addr_t); 155typedef int bus_dma_filter_t(void*, dma_addr_t);
155typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 156typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
@@ -226,12 +227,12 @@ typedef struct timer_list ahd_timer_t;
226#define ahd_timer_init init_timer 227#define ahd_timer_init init_timer
227#define ahd_timer_stop del_timer_sync 228#define ahd_timer_stop del_timer_sync
228typedef void ahd_linux_callback_t (u_long); 229typedef void ahd_linux_callback_t (u_long);
229static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec, 230static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec,
230 ahd_callback_t *func, void *arg); 231 ahd_callback_t *func, void *arg);
231static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); 232static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec);
232 233
233static __inline void 234static __inline void
234ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg) 235ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
235{ 236{
236 struct ahd_softc *ahd; 237 struct ahd_softc *ahd;
237 238
@@ -252,43 +253,8 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
252/***************************** SMP support ************************************/ 253/***************************** SMP support ************************************/
253#include <linux/spinlock.h> 254#include <linux/spinlock.h>
254 255
255#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK))
256#define AHD_SCSI_HAS_HOST_LOCK 1
257#else
258#define AHD_SCSI_HAS_HOST_LOCK 0
259#endif
260
261#define AIC79XX_DRIVER_VERSION "1.3.11" 256#define AIC79XX_DRIVER_VERSION "1.3.11"
262 257
263/**************************** Front End Queues ********************************/
264/*
265 * Data structure used to cast the Linux struct scsi_cmnd to something
266 * that allows us to use the queue macros. The linux structure has
267 * plenty of space to hold the links fields as required by the queue
268 * macros, but the queue macors require them to have the correct type.
269 */
270struct ahd_cmd_internal {
271 /* Area owned by the Linux scsi layer. */
272 uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)];
273 union {
274 STAILQ_ENTRY(ahd_cmd) ste;
275 LIST_ENTRY(ahd_cmd) le;
276 TAILQ_ENTRY(ahd_cmd) tqe;
277 } links;
278 uint32_t end;
279};
280
281struct ahd_cmd {
282 union {
283 struct ahd_cmd_internal icmd;
284 struct scsi_cmnd scsi_cmd;
285 } un;
286};
287
288#define acmd_icmd(cmd) ((cmd)->un.icmd)
289#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
290#define acmd_links un.icmd.links
291
292/*************************** Device Data Structures ***************************/ 258/*************************** Device Data Structures ***************************/
293/* 259/*
294 * A per probed device structure used to deal with some error recovery 260 * A per probed device structure used to deal with some error recovery
@@ -297,22 +263,17 @@ struct ahd_cmd {
297 * after a successfully completed inquiry command to the target when 263 * after a successfully completed inquiry command to the target when
298 * that inquiry data indicates a lun is present. 264 * that inquiry data indicates a lun is present.
299 */ 265 */
300TAILQ_HEAD(ahd_busyq, ahd_cmd); 266
301typedef enum { 267typedef enum {
302 AHD_DEV_UNCONFIGURED = 0x01,
303 AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */ 268 AHD_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
304 AHD_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */
305 AHD_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */
306 AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */ 269 AHD_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */
307 AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */ 270 AHD_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */
308 AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ 271 AHD_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
309 AHD_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */
310} ahd_linux_dev_flags; 272} ahd_linux_dev_flags;
311 273
312struct ahd_linux_target; 274struct ahd_linux_target;
313struct ahd_linux_device { 275struct ahd_linux_device {
314 TAILQ_ENTRY(ahd_linux_device) links; 276 TAILQ_ENTRY(ahd_linux_device) links;
315 struct ahd_busyq busyq;
316 277
317 /* 278 /*
318 * The number of transactions currently 279 * The number of transactions currently
@@ -388,62 +349,12 @@ struct ahd_linux_device {
388 */ 349 */
389 u_int commands_since_idle_or_otag; 350 u_int commands_since_idle_or_otag;
390#define AHD_OTAG_THRESH 500 351#define AHD_OTAG_THRESH 500
391
392 int lun;
393 Scsi_Device *scsi_device;
394 struct ahd_linux_target *target;
395}; 352};
396 353
397typedef enum {
398 AHD_DV_REQUIRED = 0x01,
399 AHD_INQ_VALID = 0x02,
400 AHD_BASIC_DV = 0x04,
401 AHD_ENHANCED_DV = 0x08
402} ahd_linux_targ_flags;
403
404/* DV States */
405typedef enum {
406 AHD_DV_STATE_EXIT = 0,
407 AHD_DV_STATE_INQ_SHORT_ASYNC,
408 AHD_DV_STATE_INQ_ASYNC,
409 AHD_DV_STATE_INQ_ASYNC_VERIFY,
410 AHD_DV_STATE_TUR,
411 AHD_DV_STATE_REBD,
412 AHD_DV_STATE_INQ_VERIFY,
413 AHD_DV_STATE_WEB,
414 AHD_DV_STATE_REB,
415 AHD_DV_STATE_SU,
416 AHD_DV_STATE_BUSY
417} ahd_dv_state;
418
419struct ahd_linux_target { 354struct ahd_linux_target {
420 struct ahd_linux_device *devices[AHD_NUM_LUNS]; 355 struct scsi_device *sdev[AHD_NUM_LUNS];
421 int channel;
422 int target;
423 int refcount;
424 struct ahd_transinfo last_tinfo; 356 struct ahd_transinfo last_tinfo;
425 struct ahd_softc *ahd; 357 struct ahd_softc *ahd;
426 ahd_linux_targ_flags flags;
427 struct scsi_inquiry_data *inq_data;
428 /*
429 * The next "fallback" period to use for narrow/wide transfers.
430 */
431 uint8_t dv_next_narrow_period;
432 uint8_t dv_next_wide_period;
433 uint8_t dv_max_width;
434 uint8_t dv_max_ppr_options;
435 uint8_t dv_last_ppr_options;
436 u_int dv_echo_size;
437 ahd_dv_state dv_state;
438 u_int dv_state_retry;
439 uint8_t *dv_buffer;
440 uint8_t *dv_buffer1;
441
442 /*
443 * Cumulative counter of errors.
444 */
445 u_long errors_detected;
446 u_long cmds_since_error;
447}; 358};
448 359
449/********************* Definitions Required by the Core ***********************/ 360/********************* Definitions Required by the Core ***********************/
@@ -453,32 +364,16 @@ struct ahd_linux_target {
453 * manner and are allocated below 4GB, the number of S/G segments is 364 * manner and are allocated below 4GB, the number of S/G segments is
454 * unrestricted. 365 * unrestricted.
455 */ 366 */
456#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
457/*
458 * We dynamically adjust the number of segments in pre-2.5 kernels to
459 * avoid fragmentation issues in the SCSI mid-layer's private memory
460 * allocator. See aic79xx_osm.c ahd_linux_size_nseg() for details.
461 */
462extern u_int ahd_linux_nseg;
463#define AHD_NSEG ahd_linux_nseg
464#define AHD_LINUX_MIN_NSEG 64
465#else
466#define AHD_NSEG 128 367#define AHD_NSEG 128
467#endif
468 368
469/* 369/*
470 * Per-SCB OSM storage. 370 * Per-SCB OSM storage.
471 */ 371 */
472typedef enum {
473 AHD_SCB_UP_EH_SEM = 0x1
474} ahd_linux_scb_flags;
475
476struct scb_platform_data { 372struct scb_platform_data {
477 struct ahd_linux_device *dev; 373 struct ahd_linux_device *dev;
478 dma_addr_t buf_busaddr; 374 dma_addr_t buf_busaddr;
479 uint32_t xfer_len; 375 uint32_t xfer_len;
480 uint32_t sense_resid; /* Auto-Sense residual */ 376 uint32_t sense_resid; /* Auto-Sense residual */
481 ahd_linux_scb_flags flags;
482}; 377};
483 378
484/* 379/*
@@ -487,44 +382,23 @@ struct scb_platform_data {
487 * alignment restrictions of the various platforms supported by 382 * alignment restrictions of the various platforms supported by
488 * this driver. 383 * this driver.
489 */ 384 */
490typedef enum {
491 AHD_DV_WAIT_SIMQ_EMPTY = 0x01,
492 AHD_DV_WAIT_SIMQ_RELEASE = 0x02,
493 AHD_DV_ACTIVE = 0x04,
494 AHD_DV_SHUTDOWN = 0x08,
495 AHD_RUN_CMPLT_Q_TIMER = 0x10
496} ahd_linux_softc_flags;
497
498TAILQ_HEAD(ahd_completeq, ahd_cmd);
499
500struct ahd_platform_data { 385struct ahd_platform_data {
501 /* 386 /*
502 * Fields accessed from interrupt context. 387 * Fields accessed from interrupt context.
503 */ 388 */
504 struct ahd_linux_target *targets[AHD_NUM_TARGETS]; 389 struct scsi_target *starget[AHD_NUM_TARGETS];
505 TAILQ_HEAD(, ahd_linux_device) device_runq;
506 struct ahd_completeq completeq;
507 390
508 spinlock_t spin_lock; 391 spinlock_t spin_lock;
509 struct tasklet_struct runq_tasklet;
510 u_int qfrozen; 392 u_int qfrozen;
511 pid_t dv_pid;
512 struct timer_list completeq_timer;
513 struct timer_list reset_timer; 393 struct timer_list reset_timer;
514 struct timer_list stats_timer;
515 struct semaphore eh_sem; 394 struct semaphore eh_sem;
516 struct semaphore dv_sem;
517 struct semaphore dv_cmd_sem; /* XXX This needs to be in
518 * the target struct
519 */
520 struct scsi_device *dv_scsi_dev;
521 struct Scsi_Host *host; /* pointer to scsi host */ 395 struct Scsi_Host *host; /* pointer to scsi host */
522#define AHD_LINUX_NOIRQ ((uint32_t)~0) 396#define AHD_LINUX_NOIRQ ((uint32_t)~0)
523 uint32_t irq; /* IRQ for this adapter */ 397 uint32_t irq; /* IRQ for this adapter */
524 uint32_t bios_address; 398 uint32_t bios_address;
525 uint32_t mem_busaddr; /* Mem Base Addr */ 399 uint32_t mem_busaddr; /* Mem Base Addr */
526 uint64_t hw_dma_mask; 400#define AHD_SCB_UP_EH_SEM 0x1
527 ahd_linux_softc_flags flags; 401 uint32_t flags;
528}; 402};
529 403
530/************************** OS Utility Wrappers *******************************/ 404/************************** OS Utility Wrappers *******************************/
@@ -641,7 +515,7 @@ ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
641 515
642/**************************** Initialization **********************************/ 516/**************************** Initialization **********************************/
643int ahd_linux_register_host(struct ahd_softc *, 517int ahd_linux_register_host(struct ahd_softc *,
644 Scsi_Host_Template *); 518 struct scsi_host_template *);
645 519
646uint64_t ahd_linux_get_memsize(void); 520uint64_t ahd_linux_get_memsize(void);
647 521
@@ -657,28 +531,6 @@ void ahd_format_transinfo(struct info_str *info,
657 struct ahd_transinfo *tinfo); 531 struct ahd_transinfo *tinfo);
658 532
659/******************************** Locking *************************************/ 533/******************************** Locking *************************************/
660/* Lock protecting internal data structures */
661static __inline void ahd_lockinit(struct ahd_softc *);
662static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags);
663static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags);
664
665/* Lock acquisition and release of the above lock in midlayer entry points. */
666static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *,
667 unsigned long *flags);
668static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *,
669 unsigned long *flags);
670
671/* Lock held during command compeletion to the upper layer */
672static __inline void ahd_done_lockinit(struct ahd_softc *);
673static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags);
674static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags);
675
676/* Lock held during ahd_list manipulation and ahd softc frees */
677extern spinlock_t ahd_list_spinlock;
678static __inline void ahd_list_lockinit(void);
679static __inline void ahd_list_lock(unsigned long *flags);
680static __inline void ahd_list_unlock(unsigned long *flags);
681
682static __inline void 534static __inline void
683ahd_lockinit(struct ahd_softc *ahd) 535ahd_lockinit(struct ahd_softc *ahd)
684{ 536{
@@ -697,75 +549,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
697 spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags); 549 spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
698} 550}
699 551
700static __inline void
701ahd_midlayer_entrypoint_lock(struct ahd_softc *ahd, unsigned long *flags)
702{
703 /*
704 * In 2.5.X and some 2.4.X versions, the midlayer takes our
705 * lock just before calling us, so we avoid locking again.
706 * For other kernel versions, the io_request_lock is taken
707 * just before our entry point is called. In this case, we
708 * trade the io_request_lock for our per-softc lock.
709 */
710#if AHD_SCSI_HAS_HOST_LOCK == 0
711 spin_unlock(&io_request_lock);
712 spin_lock(&ahd->platform_data->spin_lock);
713#endif
714}
715
716static __inline void
717ahd_midlayer_entrypoint_unlock(struct ahd_softc *ahd, unsigned long *flags)
718{
719#if AHD_SCSI_HAS_HOST_LOCK == 0
720 spin_unlock(&ahd->platform_data->spin_lock);
721 spin_lock(&io_request_lock);
722#endif
723}
724
725static __inline void
726ahd_done_lockinit(struct ahd_softc *ahd)
727{
728 /*
729 * In 2.5.X, our own lock is held during completions.
730 * In previous versions, the io_request_lock is used.
731 * In either case, we can't initialize this lock again.
732 */
733}
734
735static __inline void
736ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
737{
738#if AHD_SCSI_HAS_HOST_LOCK == 0
739 spin_lock(&io_request_lock);
740#endif
741}
742
743static __inline void
744ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
745{
746#if AHD_SCSI_HAS_HOST_LOCK == 0
747 spin_unlock(&io_request_lock);
748#endif
749}
750
751static __inline void
752ahd_list_lockinit(void)
753{
754 spin_lock_init(&ahd_list_spinlock);
755}
756
757static __inline void
758ahd_list_lock(unsigned long *flags)
759{
760 spin_lock_irqsave(&ahd_list_spinlock, *flags);
761}
762
763static __inline void
764ahd_list_unlock(unsigned long *flags)
765{
766 spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
767}
768
769/******************************* PCI Definitions ******************************/ 552/******************************* PCI Definitions ******************************/
770/* 553/*
771 * PCIM_xxx: mask to locate subfield in register 554 * PCIM_xxx: mask to locate subfield in register
@@ -925,27 +708,17 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
925} 708}
926 709
927/**************************** Proc FS Support *********************************/ 710/**************************** Proc FS Support *********************************/
928#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
929int ahd_linux_proc_info(char *, char **, off_t, int, int, int);
930#else
931int ahd_linux_proc_info(struct Scsi_Host *, char *, char **, 711int ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
932 off_t, int, int); 712 off_t, int, int);
933#endif
934
935/*************************** Domain Validation ********************************/
936#define AHD_DV_CMD(cmd) ((cmd)->scsi_done == ahd_linux_dv_complete)
937#define AHD_DV_SIMQ_FROZEN(ahd) \
938 ((((ahd)->platform_data->flags & AHD_DV_ACTIVE) != 0) \
939 && (ahd)->platform_data->qfrozen == 1)
940 713
941/*********************** Transaction Access Wrappers **************************/ 714/*********************** Transaction Access Wrappers **************************/
942static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); 715static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
943static __inline void ahd_set_transaction_status(struct scb *, uint32_t); 716static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
944static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); 717static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
945static __inline void ahd_set_scsi_status(struct scb *, uint32_t); 718static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
946static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd); 719static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
947static __inline uint32_t ahd_get_transaction_status(struct scb *); 720static __inline uint32_t ahd_get_transaction_status(struct scb *);
948static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd); 721static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
949static __inline uint32_t ahd_get_scsi_status(struct scb *); 722static __inline uint32_t ahd_get_scsi_status(struct scb *);
950static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); 723static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
951static __inline u_long ahd_get_transfer_length(struct scb *); 724static __inline u_long ahd_get_transfer_length(struct scb *);
@@ -964,7 +737,7 @@ static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
964static __inline void ahd_freeze_scb(struct scb *scb); 737static __inline void ahd_freeze_scb(struct scb *scb);
965 738
966static __inline 739static __inline
967void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) 740void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
968{ 741{
969 cmd->result &= ~(CAM_STATUS_MASK << 16); 742 cmd->result &= ~(CAM_STATUS_MASK << 16);
970 cmd->result |= status << 16; 743 cmd->result |= status << 16;
@@ -977,7 +750,7 @@ void ahd_set_transaction_status(struct scb *scb, uint32_t status)
977} 750}
978 751
979static __inline 752static __inline
980void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) 753void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
981{ 754{
982 cmd->result &= ~0xFFFF; 755 cmd->result &= ~0xFFFF;
983 cmd->result |= status; 756 cmd->result |= status;
@@ -990,7 +763,7 @@ void ahd_set_scsi_status(struct scb *scb, uint32_t status)
990} 763}
991 764
992static __inline 765static __inline
993uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd) 766uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
994{ 767{
995 return ((cmd->result >> 16) & CAM_STATUS_MASK); 768 return ((cmd->result >> 16) & CAM_STATUS_MASK);
996} 769}
@@ -1002,7 +775,7 @@ uint32_t ahd_get_transaction_status(struct scb *scb)
1002} 775}
1003 776
1004static __inline 777static __inline
1005uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd) 778uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
1006{ 779{
1007 return (cmd->result & 0xFFFF); 780 return (cmd->result & 0xFFFF);
1008} 781}
@@ -1117,7 +890,6 @@ void ahd_done(struct ahd_softc*, struct scb*);
1117void ahd_send_async(struct ahd_softc *, char channel, 890void ahd_send_async(struct ahd_softc *, char channel,
1118 u_int target, u_int lun, ac_code, void *); 891 u_int target, u_int lun, ac_code, void *);
1119void ahd_print_path(struct ahd_softc *, struct scb *); 892void ahd_print_path(struct ahd_softc *, struct scb *);
1120void ahd_platform_dump_card_state(struct ahd_softc *ahd);
1121 893
1122#ifdef CONFIG_PCI 894#ifdef CONFIG_PCI
1123#define AHD_PCI_CONFIG 1 895#define AHD_PCI_CONFIG 1
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 91daf0c7fb10..390b53852d4b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -92,27 +92,31 @@ struct pci_driver aic79xx_pci_driver = {
92static void 92static void
93ahd_linux_pci_dev_remove(struct pci_dev *pdev) 93ahd_linux_pci_dev_remove(struct pci_dev *pdev)
94{ 94{
95 struct ahd_softc *ahd; 95 struct ahd_softc *ahd = pci_get_drvdata(pdev);
96 u_long l; 96 u_long s;
97 97
98 /* 98 ahd_lock(ahd, &s);
99 * We should be able to just perform 99 ahd_intr_enable(ahd, FALSE);
100 * the free directly, but check our 100 ahd_unlock(ahd, &s);
101 * list for extra sanity. 101 ahd_free(ahd);
102 */ 102}
103 ahd_list_lock(&l); 103
104 ahd = ahd_find_softc((struct ahd_softc *)pci_get_drvdata(pdev)); 104static void
105 if (ahd != NULL) { 105ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
106 u_long s; 106{
107 107 struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
108 TAILQ_REMOVE(&ahd_tailq, ahd, links); 108 unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
109 ahd_list_unlock(&l); 109
110 ahd_lock(ahd, &s); 110 master_pdev = pci_get_slot(pdev->bus, master_devfn);
111 ahd_intr_enable(ahd, FALSE); 111 if (master_pdev) {
112 ahd_unlock(ahd, &s); 112 struct ahd_softc *master = pci_get_drvdata(master_pdev);
113 ahd_free(ahd); 113 if (master) {
114 } else 114 ahd->flags &= ~AHD_BIOS_ENABLED;
115 ahd_list_unlock(&l); 115 ahd->flags |= master->flags & AHD_BIOS_ENABLED;
116 } else
117 printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
118 pci_dev_put(master_pdev);
119 }
116} 120}
117 121
118static int 122static int
@@ -125,22 +129,6 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
125 char *name; 129 char *name;
126 int error; 130 int error;
127 131
128 /*
129 * Some BIOSen report the same device multiple times.
130 */
131 TAILQ_FOREACH(ahd, &ahd_tailq, links) {
132 struct pci_dev *probed_pdev;
133
134 probed_pdev = ahd->dev_softc;
135 if (probed_pdev->bus->number == pdev->bus->number
136 && probed_pdev->devfn == pdev->devfn)
137 break;
138 }
139 if (ahd != NULL) {
140 /* Skip duplicate. */
141 return (-ENODEV);
142 }
143
144 pci = pdev; 132 pci = pdev;
145 entry = ahd_find_pci_device(pci); 133 entry = ahd_find_pci_device(pci);
146 if (entry == NULL) 134 if (entry == NULL)
@@ -177,15 +165,12 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
177 if (memsize >= 0x8000000000ULL 165 if (memsize >= 0x8000000000ULL
178 && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { 166 && pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
179 ahd->flags |= AHD_64BIT_ADDRESSING; 167 ahd->flags |= AHD_64BIT_ADDRESSING;
180 ahd->platform_data->hw_dma_mask = DMA_64BIT_MASK;
181 } else if (memsize > 0x80000000 168 } else if (memsize > 0x80000000
182 && pci_set_dma_mask(pdev, mask_39bit) == 0) { 169 && pci_set_dma_mask(pdev, mask_39bit) == 0) {
183 ahd->flags |= AHD_39BIT_ADDRESSING; 170 ahd->flags |= AHD_39BIT_ADDRESSING;
184 ahd->platform_data->hw_dma_mask = mask_39bit;
185 } 171 }
186 } else { 172 } else {
187 pci_set_dma_mask(pdev, DMA_32BIT_MASK); 173 pci_set_dma_mask(pdev, DMA_32BIT_MASK);
188 ahd->platform_data->hw_dma_mask = DMA_32BIT_MASK;
189 } 174 }
190 ahd->dev_softc = pci; 175 ahd->dev_softc = pci;
191 error = ahd_pci_config(ahd, entry); 176 error = ahd_pci_config(ahd, entry);
@@ -193,16 +178,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
193 ahd_free(ahd); 178 ahd_free(ahd);
194 return (-error); 179 return (-error);
195 } 180 }
181
182 /*
183 * Second Function PCI devices need to inherit some
184 * * settings from function 0.
185 */
186 if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
187 ahd_linux_pci_inherit_flags(ahd);
188
196 pci_set_drvdata(pdev, ahd); 189 pci_set_drvdata(pdev, ahd);
197 if (aic79xx_detect_complete) { 190
198#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 191 ahd_linux_register_host(ahd, &aic79xx_driver_template);
199 ahd_linux_register_host(ahd, &aic79xx_driver_template);
200#else
201 printf("aic79xx: ignoring PCI device found after "
202 "initialization\n");
203 return (-ENODEV);
204#endif
205 }
206 return (0); 192 return (0);
207} 193}
208 194
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 703f6e44889d..2131db60018a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -283,7 +283,6 @@ int
283ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) 283ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
284{ 284{
285 struct scb_data *shared_scb_data; 285 struct scb_data *shared_scb_data;
286 u_long l;
287 u_int command; 286 u_int command;
288 uint32_t devconfig; 287 uint32_t devconfig;
289 uint16_t subvendor; 288 uint16_t subvendor;
@@ -373,16 +372,9 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
373 * Allow interrupts now that we are completely setup. 372 * Allow interrupts now that we are completely setup.
374 */ 373 */
375 error = ahd_pci_map_int(ahd); 374 error = ahd_pci_map_int(ahd);
376 if (error != 0) 375 if (!error)
377 return (error); 376 ahd->init_level++;
378 377 return error;
379 ahd_list_lock(&l);
380 /*
381 * Link this softc in with all other ahd instances.
382 */
383 ahd_softc_insert(ahd);
384 ahd_list_unlock(&l);
385 return (0);
386} 378}
387 379
388/* 380/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index e01cd6175e34..32be1f55998c 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -49,7 +49,7 @@ static void ahd_dump_target_state(struct ahd_softc *ahd,
49 u_int our_id, char channel, 49 u_int our_id, char channel,
50 u_int target_id, u_int target_offset); 50 u_int target_id, u_int target_offset);
51static void ahd_dump_device_state(struct info_str *info, 51static void ahd_dump_device_state(struct info_str *info,
52 struct ahd_linux_device *dev); 52 struct scsi_device *sdev);
53static int ahd_proc_write_seeprom(struct ahd_softc *ahd, 53static int ahd_proc_write_seeprom(struct ahd_softc *ahd,
54 char *buffer, int length); 54 char *buffer, int length);
55 55
@@ -167,6 +167,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
167 u_int target_offset) 167 u_int target_offset)
168{ 168{
169 struct ahd_linux_target *targ; 169 struct ahd_linux_target *targ;
170 struct scsi_target *starget;
170 struct ahd_initiator_tinfo *tinfo; 171 struct ahd_initiator_tinfo *tinfo;
171 struct ahd_tmode_tstate *tstate; 172 struct ahd_tmode_tstate *tstate;
172 int lun; 173 int lun;
@@ -176,20 +177,20 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
176 copy_info(info, "Target %d Negotiation Settings\n", target_id); 177 copy_info(info, "Target %d Negotiation Settings\n", target_id);
177 copy_info(info, "\tUser: "); 178 copy_info(info, "\tUser: ");
178 ahd_format_transinfo(info, &tinfo->user); 179 ahd_format_transinfo(info, &tinfo->user);
179 targ = ahd->platform_data->targets[target_offset]; 180 starget = ahd->platform_data->starget[target_offset];
180 if (targ == NULL) 181 if (starget == NULL)
181 return; 182 return;
183 targ = scsi_transport_target_data(starget);
182 184
183 copy_info(info, "\tGoal: "); 185 copy_info(info, "\tGoal: ");
184 ahd_format_transinfo(info, &tinfo->goal); 186 ahd_format_transinfo(info, &tinfo->goal);
185 copy_info(info, "\tCurr: "); 187 copy_info(info, "\tCurr: ");
186 ahd_format_transinfo(info, &tinfo->curr); 188 ahd_format_transinfo(info, &tinfo->curr);
187 copy_info(info, "\tTransmission Errors %ld\n", targ->errors_detected);
188 189
189 for (lun = 0; lun < AHD_NUM_LUNS; lun++) { 190 for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
190 struct ahd_linux_device *dev; 191 struct scsi_device *dev;
191 192
192 dev = targ->devices[lun]; 193 dev = targ->sdev[lun];
193 194
194 if (dev == NULL) 195 if (dev == NULL)
195 continue; 196 continue;
@@ -199,10 +200,13 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
199} 200}
200 201
201static void 202static void
202ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev) 203ahd_dump_device_state(struct info_str *info, struct scsi_device *sdev)
203{ 204{
205 struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
206
204 copy_info(info, "\tChannel %c Target %d Lun %d Settings\n", 207 copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
205 dev->target->channel + 'A', dev->target->target, dev->lun); 208 sdev->sdev_target->channel + 'A',
209 sdev->sdev_target->id, sdev->lun);
206 210
207 copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued); 211 copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
208 copy_info(info, "\t\tCommands Active %d\n", dev->active); 212 copy_info(info, "\t\tCommands Active %d\n", dev->active);
@@ -278,36 +282,16 @@ done:
278 * Return information to handle /proc support for the driver. 282 * Return information to handle /proc support for the driver.
279 */ 283 */
280int 284int
281#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
282ahd_linux_proc_info(char *buffer, char **start, off_t offset,
283 int length, int hostno, int inout)
284#else
285ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, 285ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
286 off_t offset, int length, int inout) 286 off_t offset, int length, int inout)
287#endif
288{ 287{
289 struct ahd_softc *ahd; 288 struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
290 struct info_str info; 289 struct info_str info;
291 char ahd_info[256]; 290 char ahd_info[256];
292 u_long l;
293 u_int max_targ; 291 u_int max_targ;
294 u_int i; 292 u_int i;
295 int retval; 293 int retval;
296 294
297 retval = -EINVAL;
298 ahd_list_lock(&l);
299#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
300 TAILQ_FOREACH(ahd, &ahd_tailq, links) {
301 if (ahd->platform_data->host->host_no == hostno)
302 break;
303 }
304#else
305 ahd = ahd_find_softc(*(struct ahd_softc **)shost->hostdata);
306#endif
307
308 if (ahd == NULL)
309 goto done;
310
311 /* Has data been written to the file? */ 295 /* Has data been written to the file? */
312 if (inout == TRUE) { 296 if (inout == TRUE) {
313 retval = ahd_proc_write_seeprom(ahd, buffer, length); 297 retval = ahd_proc_write_seeprom(ahd, buffer, length);
@@ -357,6 +341,5 @@ ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
357 } 341 }
358 retval = info.pos > info.offset ? info.pos - info.offset : 0; 342 retval = info.pos > info.offset ? info.pos - info.offset : 0;
359done: 343done:
360 ahd_list_unlock(&l);
361 return (retval); 344 return (retval);
362} 345}
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 088cbc23743d..91d294c6334e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -37,7 +37,7 @@
37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGES. 38 * POSSIBILITY OF SUCH DAMAGES.
39 * 39 *
40 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#79 $ 40 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#85 $
41 * 41 *
42 * $FreeBSD$ 42 * $FreeBSD$
43 */ 43 */
@@ -243,7 +243,7 @@ typedef enum {
243 */ 243 */
244 AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA, 244 AHC_AIC7850_FE = AHC_SPIOCAP|AHC_AUTOPAUSE|AHC_TARGETMODE|AHC_ULTRA,
245 AHC_AIC7860_FE = AHC_AIC7850_FE, 245 AHC_AIC7860_FE = AHC_AIC7850_FE,
246 AHC_AIC7870_FE = AHC_TARGETMODE, 246 AHC_AIC7870_FE = AHC_TARGETMODE|AHC_AUTOPAUSE,
247 AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA, 247 AHC_AIC7880_FE = AHC_AIC7870_FE|AHC_ULTRA,
248 /* 248 /*
249 * Although we have space for both the initiator and 249 * Although we have space for both the initiator and
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
index 810ec700d9fc..e196d83b93c7 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.reg
+++ b/drivers/scsi/aic7xxx/aic7xxx.reg
@@ -39,7 +39,7 @@
39 * 39 *
40 * $FreeBSD$ 40 * $FreeBSD$
41 */ 41 */
42VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $" 42VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $"
43 43
44/* 44/*
45 * This file is processed by the aic7xxx_asm utility for use in assembling 45 * This file is processed by the aic7xxx_asm utility for use in assembling
@@ -1306,7 +1306,6 @@ scratch_ram {
1306 */ 1306 */
1307 MWI_RESIDUAL { 1307 MWI_RESIDUAL {
1308 size 1 1308 size 1
1309 alias TARG_IMMEDIATE_SCB
1310 } 1309 }
1311 /* 1310 /*
1312 * SCBID of the next SCB to be started by the controller. 1311 * SCBID of the next SCB to be started by the controller.
@@ -1461,6 +1460,7 @@ scratch_ram {
1461 */ 1460 */
1462 LAST_MSG { 1461 LAST_MSG {
1463 size 1 1462 size 1
1463 alias TARG_IMMEDIATE_SCB
1464 } 1464 }
1465 1465
1466 /* 1466 /*
diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq
index d84b741fbab5..15196390e28d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.seq
+++ b/drivers/scsi/aic7xxx/aic7xxx.seq
@@ -40,7 +40,7 @@
40 * $FreeBSD$ 40 * $FreeBSD$
41 */ 41 */
42 42
43VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $" 43VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $"
44PATCH_ARG_LIST = "struct ahc_softc *ahc" 44PATCH_ARG_LIST = "struct ahc_softc *ahc"
45PREFIX = "ahc_" 45PREFIX = "ahc_"
46 46
@@ -679,6 +679,7 @@ await_busfree:
679 clr SCSIBUSL; /* Prevent bit leakage durint SELTO */ 679 clr SCSIBUSL; /* Prevent bit leakage durint SELTO */
680 } 680 }
681 and SXFRCTL0, ~SPIOEN; 681 and SXFRCTL0, ~SPIOEN;
682 mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
682 test SSTAT1,REQINIT|BUSFREE jz .; 683 test SSTAT1,REQINIT|BUSFREE jz .;
683 test SSTAT1, BUSFREE jnz poll_for_work; 684 test SSTAT1, BUSFREE jnz poll_for_work;
684 mvi MISSED_BUSFREE call set_seqint; 685 mvi MISSED_BUSFREE call set_seqint;
@@ -1097,7 +1098,7 @@ ultra2_dmahalt:
1097 test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg; 1098 test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz dma_mid_sg;
1098 if ((ahc->flags & AHC_TARGETROLE) != 0) { 1099 if ((ahc->flags & AHC_TARGETROLE) != 0) {
1099 test SSTAT0, TARGET jz dma_last_sg; 1100 test SSTAT0, TARGET jz dma_last_sg;
1100 if ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0) { 1101 if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0) {
1101 test DMAPARAMS, DIRECTION jz dma_mid_sg; 1102 test DMAPARAMS, DIRECTION jz dma_mid_sg;
1102 } 1103 }
1103 } 1104 }
diff --git a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
index 468d612a44f6..3cb07e114e89 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
@@ -28,9 +28,7 @@
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 * 30 *
31 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#17 $ 31 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#19 $
32 *
33 * $FreeBSD$
34 */ 32 */
35 33
36/* 34/*
@@ -64,7 +62,6 @@
64 * is preceded by an initial zero (leading 0, followed by 16-bits, MSB 62 * is preceded by an initial zero (leading 0, followed by 16-bits, MSB
65 * first). The clock cycling from low to high initiates the next data 63 * first). The clock cycling from low to high initiates the next data
66 * bit to be sent from the chip. 64 * bit to be sent from the chip.
67 *
68 */ 65 */
69 66
70#ifdef __linux__ 67#ifdef __linux__
@@ -81,14 +78,22 @@
81 * Right now, we only have to read the SEEPROM. But we make it easier to 78 * Right now, we only have to read the SEEPROM. But we make it easier to
82 * add other 93Cx6 functions. 79 * add other 93Cx6 functions.
83 */ 80 */
84static struct seeprom_cmd { 81struct seeprom_cmd {
85 uint8_t len; 82 uint8_t len;
86 uint8_t bits[9]; 83 uint8_t bits[11];
87} seeprom_read = {3, {1, 1, 0}}; 84};
88 85
86/* Short opcodes for the c46 */
89static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; 87static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
90static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; 88static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
89
90/* Long opcodes for the C56/C66 */
91static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
92static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
93
94/* Common opcodes */
91static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; 95static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
96static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
92 97
93/* 98/*
94 * Wait for the SEERDY to go high; about 800 ns. 99 * Wait for the SEERDY to go high; about 800 ns.
@@ -222,12 +227,25 @@ int
222ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, 227ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
223 u_int start_addr, u_int count) 228 u_int start_addr, u_int count)
224{ 229{
230 struct seeprom_cmd *ewen, *ewds;
225 uint16_t v; 231 uint16_t v;
226 uint8_t temp; 232 uint8_t temp;
227 int i, k; 233 int i, k;
228 234
229 /* Place the chip into write-enable mode */ 235 /* Place the chip into write-enable mode */
230 send_seeprom_cmd(sd, &seeprom_ewen); 236 if (sd->sd_chip == C46) {
237 ewen = &seeprom_ewen;
238 ewds = &seeprom_ewds;
239 } else if (sd->sd_chip == C56_66) {
240 ewen = &seeprom_long_ewen;
241 ewds = &seeprom_long_ewds;
242 } else {
243 printf("ahc_write_seeprom: unsupported seeprom type %d\n",
244 sd->sd_chip);
245 return (0);
246 }
247
248 send_seeprom_cmd(sd, ewen);
231 reset_seeprom(sd); 249 reset_seeprom(sd);
232 250
233 /* Write all requested data out to the seeprom. */ 251 /* Write all requested data out to the seeprom. */
@@ -277,7 +295,7 @@ ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
277 } 295 }
278 296
279 /* Put the chip back into write-protect mode */ 297 /* Put the chip back into write-protect mode */
280 send_seeprom_cmd(sd, &seeprom_ewds); 298 send_seeprom_cmd(sd, ewds);
281 reset_seeprom(sd); 299 reset_seeprom(sd);
282 300
283 return (1); 301 return (1);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 7bc01e41bcce..58ac46103eb6 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -37,9 +37,7 @@
37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGES. 38 * POSSIBILITY OF SUCH DAMAGES.
39 * 39 *
40 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#134 $ 40 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#155 $
41 *
42 * $FreeBSD$
43 */ 41 */
44 42
45#ifdef __linux__ 43#ifdef __linux__
@@ -287,10 +285,19 @@ ahc_restart(struct ahc_softc *ahc)
287 ahc_outb(ahc, SEQ_FLAGS2, 285 ahc_outb(ahc, SEQ_FLAGS2,
288 ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA); 286 ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA);
289 } 287 }
288
289 /*
290 * Clear any pending sequencer interrupt. It is no
291 * longer relevant since we're resetting the Program
292 * Counter.
293 */
294 ahc_outb(ahc, CLRINT, CLRSEQINT);
295
290 ahc_outb(ahc, MWI_RESIDUAL, 0); 296 ahc_outb(ahc, MWI_RESIDUAL, 0);
291 ahc_outb(ahc, SEQCTL, ahc->seqctl); 297 ahc_outb(ahc, SEQCTL, ahc->seqctl);
292 ahc_outb(ahc, SEQADDR0, 0); 298 ahc_outb(ahc, SEQADDR0, 0);
293 ahc_outb(ahc, SEQADDR1, 0); 299 ahc_outb(ahc, SEQADDR1, 0);
300
294 ahc_unpause(ahc); 301 ahc_unpause(ahc);
295} 302}
296 303
@@ -1174,19 +1181,20 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
1174 scb_index); 1181 scb_index);
1175 } 1182 }
1176#endif 1183#endif
1177 /*
1178 * Force a renegotiation with this target just in
1179 * case the cable was pulled and will later be
1180 * re-attached. The target may forget its negotiation
1181 * settings with us should it attempt to reselect
1182 * during the interruption. The target will not issue
1183 * a unit attention in this case, so we must always
1184 * renegotiate.
1185 */
1186 ahc_scb_devinfo(ahc, &devinfo, scb); 1184 ahc_scb_devinfo(ahc, &devinfo, scb);
1187 ahc_force_renegotiation(ahc, &devinfo);
1188 ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT); 1185 ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
1189 ahc_freeze_devq(ahc, scb); 1186 ahc_freeze_devq(ahc, scb);
1187
1188 /*
1189 * Cancel any pending transactions on the device
1190 * now that it seems to be missing. This will
1191 * also revert us to async/narrow transfers until
1192 * we can renegotiate with the device.
1193 */
1194 ahc_handle_devreset(ahc, &devinfo,
1195 CAM_SEL_TIMEOUT,
1196 "Selection Timeout",
1197 /*verbose_level*/1);
1190 } 1198 }
1191 ahc_outb(ahc, CLRINT, CLRSCSIINT); 1199 ahc_outb(ahc, CLRINT, CLRSCSIINT);
1192 ahc_restart(ahc); 1200 ahc_restart(ahc);
@@ -3763,8 +3771,9 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
3763 /*period*/0, /*offset*/0, /*ppr_options*/0, 3771 /*period*/0, /*offset*/0, /*ppr_options*/0,
3764 AHC_TRANS_CUR, /*paused*/TRUE); 3772 AHC_TRANS_CUR, /*paused*/TRUE);
3765 3773
3766 ahc_send_async(ahc, devinfo->channel, devinfo->target, 3774 if (status != CAM_SEL_TIMEOUT)
3767 CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); 3775 ahc_send_async(ahc, devinfo->channel, devinfo->target,
3776 CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
3768 3777
3769 if (message != NULL 3778 if (message != NULL
3770 && (verbose_level <= bootverbose)) 3779 && (verbose_level <= bootverbose))
@@ -4003,14 +4012,6 @@ ahc_reset(struct ahc_softc *ahc, int reinit)
4003 * to disturb the integrity of the bus. 4012 * to disturb the integrity of the bus.
4004 */ 4013 */
4005 ahc_pause(ahc); 4014 ahc_pause(ahc);
4006 if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) {
4007 /*
4008 * The chip has not been initialized since
4009 * PCI/EISA/VLB bus reset. Don't trust
4010 * "left over BIOS data".
4011 */
4012 ahc->flags |= AHC_NO_BIOS_INIT;
4013 }
4014 sxfrctl1_b = 0; 4015 sxfrctl1_b = 0;
4015 if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) { 4016 if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
4016 u_int sblkctl; 4017 u_int sblkctl;
@@ -5036,14 +5037,23 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
5036 ahc->flags |= AHC_ALL_INTERRUPTS; 5037 ahc->flags |= AHC_ALL_INTERRUPTS;
5037 paused = FALSE; 5038 paused = FALSE;
5038 do { 5039 do {
5039 if (paused) 5040 if (paused) {
5040 ahc_unpause(ahc); 5041 ahc_unpause(ahc);
5042 /*
5043 * Give the sequencer some time to service
5044 * any active selections.
5045 */
5046 ahc_delay(500);
5047 }
5041 ahc_intr(ahc); 5048 ahc_intr(ahc);
5042 ahc_pause(ahc); 5049 ahc_pause(ahc);
5043 paused = TRUE; 5050 paused = TRUE;
5044 ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO); 5051 ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO);
5045 ahc_clear_critical_section(ahc);
5046 intstat = ahc_inb(ahc, INTSTAT); 5052 intstat = ahc_inb(ahc, INTSTAT);
5053 if ((intstat & INT_PEND) == 0) {
5054 ahc_clear_critical_section(ahc);
5055 intstat = ahc_inb(ahc, INTSTAT);
5056 }
5047 } while (--maxloops 5057 } while (--maxloops
5048 && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0) 5058 && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
5049 && ((intstat & INT_PEND) != 0 5059 && ((intstat & INT_PEND) != 0
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 687f19e9cf03..54173887e160 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -635,6 +635,8 @@ ahc_linux_slave_alloc(struct scsi_device *sdev)
635 635
636 targ->sdev[sdev->lun] = sdev; 636 targ->sdev[sdev->lun] = sdev;
637 637
638 spi_period(starget) = 0;
639
638 return 0; 640 return 0;
639} 641}
640 642
@@ -1612,9 +1614,9 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
1612 if (channel == 'B') 1614 if (channel == 'B')
1613 target_offset += 8; 1615 target_offset += 8;
1614 starget = ahc->platform_data->starget[target_offset]; 1616 starget = ahc->platform_data->starget[target_offset];
1615 targ = scsi_transport_target_data(starget); 1617 if (starget == NULL)
1616 if (targ == NULL)
1617 break; 1618 break;
1619 targ = scsi_transport_target_data(starget);
1618 1620
1619 target_ppr_options = 1621 target_ppr_options =
1620 (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0) 1622 (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
@@ -2329,8 +2331,6 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
2329{ 2331{
2330} 2332}
2331 2333
2332static void ahc_linux_exit(void);
2333
2334static void ahc_linux_set_width(struct scsi_target *starget, int width) 2334static void ahc_linux_set_width(struct scsi_target *starget, int width)
2335{ 2335{
2336 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 2336 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 0e47ac217549..c52996269240 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -265,7 +265,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
265/***************************** SMP support ************************************/ 265/***************************** SMP support ************************************/
266#include <linux/spinlock.h> 266#include <linux/spinlock.h>
267 267
268#define AIC7XXX_DRIVER_VERSION "6.2.36" 268#define AIC7XXX_DRIVER_VERSION "7.0"
269 269
270/*************************** Device Data Structures ***************************/ 270/*************************** Device Data Structures ***************************/
271/* 271/*
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 9d318ce2c993..0d44a6907dd2 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -149,6 +149,27 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
149 ahc_free(ahc); 149 ahc_free(ahc);
150} 150}
151 151
152static void
153ahc_linux_pci_inherit_flags(struct ahc_softc *ahc)
154{
155 struct pci_dev *pdev = ahc->dev_softc, *master_pdev;
156 unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
157
158 master_pdev = pci_get_slot(pdev->bus, master_devfn);
159 if (master_pdev) {
160 struct ahc_softc *master = pci_get_drvdata(master_pdev);
161 if (master) {
162 ahc->flags &= ~AHC_BIOS_ENABLED;
163 ahc->flags |= master->flags & AHC_BIOS_ENABLED;
164
165 ahc->flags &= ~AHC_PRIMARY_CHANNEL;
166 ahc->flags |= master->flags & AHC_PRIMARY_CHANNEL;
167 } else
168 printk(KERN_ERR "aic7xxx: no multichannel peer found!\n");
169 pci_dev_put(master_pdev);
170 }
171}
172
152static int 173static int
153ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 174ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
154{ 175{
@@ -203,6 +224,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
203 ahc_free(ahc); 224 ahc_free(ahc);
204 return (-error); 225 return (-error);
205 } 226 }
227
228 /*
229 * Second Function PCI devices need to inherit some
230 * settings from function 0.
231 */
232 if ((ahc->features & AHC_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
233 ahc_linux_pci_inherit_flags(ahc);
234
206 pci_set_drvdata(pdev, ahc); 235 pci_set_drvdata(pdev, ahc);
207 ahc_linux_register_host(ahc, &aic7xxx_driver_template); 236 ahc_linux_register_host(ahc, &aic7xxx_driver_template);
208 return (0); 237 return (0);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
index 7c1390ed1179..2ce1febca207 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg.h_shipped
@@ -2,8 +2,8 @@
2 * DO NOT EDIT - This file is automatically generated 2 * DO NOT EDIT - This file is automatically generated
3 * from the following source files: 3 * from the following source files:
4 * 4 *
5 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ 5 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
6 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ 6 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
7 */ 7 */
8typedef int (ahc_reg_print_t)(u_int, u_int *, u_int); 8typedef int (ahc_reg_print_t)(u_int, u_int *, u_int);
9typedef struct ahc_reg_parse_entry { 9typedef struct ahc_reg_parse_entry {
@@ -1298,7 +1298,6 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
1298#define CMDSIZE_TABLE_TAIL 0x34 1298#define CMDSIZE_TABLE_TAIL 0x34
1299 1299
1300#define MWI_RESIDUAL 0x38 1300#define MWI_RESIDUAL 0x38
1301#define TARG_IMMEDIATE_SCB 0x38
1302 1301
1303#define NEXT_QUEUED_SCB 0x39 1302#define NEXT_QUEUED_SCB 0x39
1304 1303
@@ -1380,6 +1379,7 @@ ahc_reg_print_t ahc_sg_cache_pre_print;
1380#define RETURN_2 0x52 1379#define RETURN_2 0x52
1381 1380
1382#define LAST_MSG 0x53 1381#define LAST_MSG 0x53
1382#define TARG_IMMEDIATE_SCB 0x53
1383 1383
1384#define SCSISEQ_TEMPLATE 0x54 1384#define SCSISEQ_TEMPLATE 0x54
1385#define ENSELO 0x40 1385#define ENSELO 0x40
diff --git a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
index 9c713775d44a..88bfd767c51c 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_reg_print.c_shipped
@@ -2,8 +2,8 @@
2 * DO NOT EDIT - This file is automatically generated 2 * DO NOT EDIT - This file is automatically generated
3 * from the following source files: 3 * from the following source files:
4 * 4 *
5 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ 5 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
6 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ 6 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
7 */ 7 */
8 8
9#include "aic7xxx_osm.h" 9#include "aic7xxx_osm.h"
diff --git a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
index cf411368a871..4cee08521e75 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic7xxx_seq.h_shipped
@@ -2,13 +2,13 @@
2 * DO NOT EDIT - This file is automatically generated 2 * DO NOT EDIT - This file is automatically generated
3 * from the following source files: 3 * from the following source files:
4 * 4 *
5 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $ 5 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
6 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $ 6 * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
7 */ 7 */
8static uint8_t seqprog[] = { 8static uint8_t seqprog[] = {
9 0xb2, 0x00, 0x00, 0x08, 9 0xb2, 0x00, 0x00, 0x08,
10 0xf7, 0x11, 0x22, 0x08, 10 0xf7, 0x11, 0x22, 0x08,
11 0x00, 0x65, 0xec, 0x59, 11 0x00, 0x65, 0xee, 0x59,
12 0xf7, 0x01, 0x02, 0x08, 12 0xf7, 0x01, 0x02, 0x08,
13 0xff, 0x6a, 0x24, 0x08, 13 0xff, 0x6a, 0x24, 0x08,
14 0x40, 0x00, 0x40, 0x68, 14 0x40, 0x00, 0x40, 0x68,
@@ -21,15 +21,15 @@ static uint8_t seqprog[] = {
21 0x01, 0x4d, 0xc8, 0x30, 21 0x01, 0x4d, 0xc8, 0x30,
22 0x00, 0x4c, 0x12, 0x70, 22 0x00, 0x4c, 0x12, 0x70,
23 0x01, 0x39, 0xa2, 0x30, 23 0x01, 0x39, 0xa2, 0x30,
24 0x00, 0x6a, 0xc0, 0x5e, 24 0x00, 0x6a, 0xc2, 0x5e,
25 0x01, 0x51, 0x20, 0x31, 25 0x01, 0x51, 0x20, 0x31,
26 0x01, 0x57, 0xae, 0x00, 26 0x01, 0x57, 0xae, 0x00,
27 0x0d, 0x6a, 0x76, 0x00, 27 0x0d, 0x6a, 0x76, 0x00,
28 0x00, 0x51, 0x12, 0x5e, 28 0x00, 0x51, 0x14, 0x5e,
29 0x01, 0x51, 0xc8, 0x30, 29 0x01, 0x51, 0xc8, 0x30,
30 0x00, 0x39, 0xc8, 0x60, 30 0x00, 0x39, 0xc8, 0x60,
31 0x00, 0xbb, 0x30, 0x70, 31 0x00, 0xbb, 0x30, 0x70,
32 0xc1, 0x6a, 0xd8, 0x5e, 32 0xc1, 0x6a, 0xda, 0x5e,
33 0x01, 0xbf, 0x72, 0x30, 33 0x01, 0xbf, 0x72, 0x30,
34 0x01, 0x40, 0x7e, 0x31, 34 0x01, 0x40, 0x7e, 0x31,
35 0x01, 0x90, 0x80, 0x30, 35 0x01, 0x90, 0x80, 0x30,
@@ -49,10 +49,10 @@ static uint8_t seqprog[] = {
49 0x08, 0x6a, 0x78, 0x00, 49 0x08, 0x6a, 0x78, 0x00,
50 0x01, 0x50, 0xc8, 0x30, 50 0x01, 0x50, 0xc8, 0x30,
51 0xe0, 0x6a, 0xcc, 0x00, 51 0xe0, 0x6a, 0xcc, 0x00,
52 0x48, 0x6a, 0xfc, 0x5d, 52 0x48, 0x6a, 0xfe, 0x5d,
53 0x01, 0x6a, 0xdc, 0x01, 53 0x01, 0x6a, 0xdc, 0x01,
54 0x88, 0x6a, 0xcc, 0x00, 54 0x88, 0x6a, 0xcc, 0x00,
55 0x48, 0x6a, 0xfc, 0x5d, 55 0x48, 0x6a, 0xfe, 0x5d,
56 0x01, 0x6a, 0x26, 0x01, 56 0x01, 0x6a, 0x26, 0x01,
57 0xf0, 0x19, 0x7a, 0x08, 57 0xf0, 0x19, 0x7a, 0x08,
58 0x0f, 0x18, 0xc8, 0x08, 58 0x0f, 0x18, 0xc8, 0x08,
@@ -93,7 +93,7 @@ static uint8_t seqprog[] = {
93 0x00, 0x65, 0x20, 0x41, 93 0x00, 0x65, 0x20, 0x41,
94 0x02, 0x57, 0xae, 0x00, 94 0x02, 0x57, 0xae, 0x00,
95 0x00, 0x65, 0x9e, 0x40, 95 0x00, 0x65, 0x9e, 0x40,
96 0x61, 0x6a, 0xd8, 0x5e, 96 0x61, 0x6a, 0xda, 0x5e,
97 0x08, 0x51, 0x20, 0x71, 97 0x08, 0x51, 0x20, 0x71,
98 0x02, 0x0b, 0xb2, 0x78, 98 0x02, 0x0b, 0xb2, 0x78,
99 0x00, 0x65, 0xae, 0x40, 99 0x00, 0x65, 0xae, 0x40,
@@ -106,7 +106,7 @@ static uint8_t seqprog[] = {
106 0x80, 0x3d, 0x7a, 0x00, 106 0x80, 0x3d, 0x7a, 0x00,
107 0x20, 0x6a, 0x16, 0x00, 107 0x20, 0x6a, 0x16, 0x00,
108 0x00, 0x65, 0xcc, 0x41, 108 0x00, 0x65, 0xcc, 0x41,
109 0x00, 0x65, 0xb2, 0x5e, 109 0x00, 0x65, 0xb4, 0x5e,
110 0x00, 0x65, 0x12, 0x40, 110 0x00, 0x65, 0x12, 0x40,
111 0x20, 0x11, 0xd2, 0x68, 111 0x20, 0x11, 0xd2, 0x68,
112 0x20, 0x6a, 0x18, 0x00, 112 0x20, 0x6a, 0x18, 0x00,
@@ -140,27 +140,27 @@ static uint8_t seqprog[] = {
140 0x80, 0x0b, 0xc4, 0x79, 140 0x80, 0x0b, 0xc4, 0x79,
141 0x12, 0x01, 0x02, 0x00, 141 0x12, 0x01, 0x02, 0x00,
142 0x01, 0xab, 0xac, 0x30, 142 0x01, 0xab, 0xac, 0x30,
143 0xe4, 0x6a, 0x6e, 0x5d, 143 0xe4, 0x6a, 0x70, 0x5d,
144 0x40, 0x6a, 0x16, 0x00, 144 0x40, 0x6a, 0x16, 0x00,
145 0x80, 0x3e, 0x84, 0x5d, 145 0x80, 0x3e, 0x86, 0x5d,
146 0x20, 0xb8, 0x18, 0x79, 146 0x20, 0xb8, 0x18, 0x79,
147 0x20, 0x6a, 0x84, 0x5d, 147 0x20, 0x6a, 0x86, 0x5d,
148 0x00, 0xab, 0x84, 0x5d, 148 0x00, 0xab, 0x86, 0x5d,
149 0x01, 0xa9, 0x78, 0x30, 149 0x01, 0xa9, 0x78, 0x30,
150 0x10, 0xb8, 0x20, 0x79, 150 0x10, 0xb8, 0x20, 0x79,
151 0xe4, 0x6a, 0x6e, 0x5d, 151 0xe4, 0x6a, 0x70, 0x5d,
152 0x00, 0x65, 0xae, 0x40, 152 0x00, 0x65, 0xae, 0x40,
153 0x10, 0x03, 0x3c, 0x69, 153 0x10, 0x03, 0x3c, 0x69,
154 0x08, 0x3c, 0x5a, 0x69, 154 0x08, 0x3c, 0x5a, 0x69,
155 0x04, 0x3c, 0x92, 0x69, 155 0x04, 0x3c, 0x92, 0x69,
156 0x02, 0x3c, 0x98, 0x69, 156 0x02, 0x3c, 0x98, 0x69,
157 0x01, 0x3c, 0x44, 0x79, 157 0x01, 0x3c, 0x44, 0x79,
158 0xff, 0x6a, 0x70, 0x00, 158 0xff, 0x6a, 0xa6, 0x00,
159 0x00, 0x65, 0xa4, 0x59, 159 0x00, 0x65, 0xa4, 0x59,
160 0x00, 0x6a, 0xc0, 0x5e, 160 0x00, 0x6a, 0xc2, 0x5e,
161 0xff, 0x38, 0x30, 0x71, 161 0xff, 0x53, 0x30, 0x71,
162 0x0d, 0x6a, 0x76, 0x00, 162 0x0d, 0x6a, 0x76, 0x00,
163 0x00, 0x38, 0x12, 0x5e, 163 0x00, 0x53, 0x14, 0x5e,
164 0x00, 0x65, 0xea, 0x58, 164 0x00, 0x65, 0xea, 0x58,
165 0x12, 0x01, 0x02, 0x00, 165 0x12, 0x01, 0x02, 0x00,
166 0x00, 0x65, 0x18, 0x41, 166 0x00, 0x65, 0x18, 0x41,
@@ -168,10 +168,10 @@ static uint8_t seqprog[] = {
168 0x00, 0x65, 0xf2, 0x58, 168 0x00, 0x65, 0xf2, 0x58,
169 0xfd, 0x57, 0xae, 0x08, 169 0xfd, 0x57, 0xae, 0x08,
170 0x00, 0x65, 0xae, 0x40, 170 0x00, 0x65, 0xae, 0x40,
171 0xe4, 0x6a, 0x6e, 0x5d, 171 0xe4, 0x6a, 0x70, 0x5d,
172 0x20, 0x3c, 0x4a, 0x79, 172 0x20, 0x3c, 0x4a, 0x79,
173 0x02, 0x6a, 0x84, 0x5d, 173 0x02, 0x6a, 0x86, 0x5d,
174 0x04, 0x6a, 0x84, 0x5d, 174 0x04, 0x6a, 0x86, 0x5d,
175 0x01, 0x03, 0x4c, 0x69, 175 0x01, 0x03, 0x4c, 0x69,
176 0xf7, 0x11, 0x22, 0x08, 176 0xf7, 0x11, 0x22, 0x08,
177 0xff, 0x6a, 0x24, 0x08, 177 0xff, 0x6a, 0x24, 0x08,
@@ -182,13 +182,13 @@ static uint8_t seqprog[] = {
182 0x80, 0x86, 0xc8, 0x08, 182 0x80, 0x86, 0xc8, 0x08,
183 0x01, 0x4f, 0xc8, 0x30, 183 0x01, 0x4f, 0xc8, 0x30,
184 0x00, 0x50, 0x6c, 0x61, 184 0x00, 0x50, 0x6c, 0x61,
185 0xc4, 0x6a, 0x6e, 0x5d, 185 0xc4, 0x6a, 0x70, 0x5d,
186 0x40, 0x3c, 0x68, 0x79, 186 0x40, 0x3c, 0x68, 0x79,
187 0x28, 0x6a, 0x84, 0x5d, 187 0x28, 0x6a, 0x86, 0x5d,
188 0x00, 0x65, 0x4c, 0x41, 188 0x00, 0x65, 0x4c, 0x41,
189 0x08, 0x6a, 0x84, 0x5d, 189 0x08, 0x6a, 0x86, 0x5d,
190 0x00, 0x65, 0x4c, 0x41, 190 0x00, 0x65, 0x4c, 0x41,
191 0x84, 0x6a, 0x6e, 0x5d, 191 0x84, 0x6a, 0x70, 0x5d,
192 0x00, 0x65, 0xf2, 0x58, 192 0x00, 0x65, 0xf2, 0x58,
193 0x01, 0x66, 0xc8, 0x30, 193 0x01, 0x66, 0xc8, 0x30,
194 0x01, 0x64, 0xd8, 0x31, 194 0x01, 0x64, 0xd8, 0x31,
@@ -208,16 +208,16 @@ static uint8_t seqprog[] = {
208 0xf7, 0x3c, 0x78, 0x08, 208 0xf7, 0x3c, 0x78, 0x08,
209 0x00, 0x65, 0x20, 0x41, 209 0x00, 0x65, 0x20, 0x41,
210 0x40, 0xaa, 0x7e, 0x10, 210 0x40, 0xaa, 0x7e, 0x10,
211 0x04, 0xaa, 0x6e, 0x5d, 211 0x04, 0xaa, 0x70, 0x5d,
212 0x00, 0x65, 0x56, 0x42, 212 0x00, 0x65, 0x58, 0x42,
213 0xc4, 0x6a, 0x6e, 0x5d, 213 0xc4, 0x6a, 0x70, 0x5d,
214 0xc0, 0x6a, 0x7e, 0x00, 214 0xc0, 0x6a, 0x7e, 0x00,
215 0x00, 0xa8, 0x84, 0x5d, 215 0x00, 0xa8, 0x86, 0x5d,
216 0xe4, 0x6a, 0x06, 0x00, 216 0xe4, 0x6a, 0x06, 0x00,
217 0x00, 0x6a, 0x84, 0x5d, 217 0x00, 0x6a, 0x86, 0x5d,
218 0x00, 0x65, 0x4c, 0x41, 218 0x00, 0x65, 0x4c, 0x41,
219 0x10, 0x3c, 0xa8, 0x69, 219 0x10, 0x3c, 0xa8, 0x69,
220 0x00, 0xbb, 0x8a, 0x44, 220 0x00, 0xbb, 0x8c, 0x44,
221 0x18, 0x6a, 0xda, 0x01, 221 0x18, 0x6a, 0xda, 0x01,
222 0x01, 0x69, 0xd8, 0x31, 222 0x01, 0x69, 0xd8, 0x31,
223 0x1c, 0x6a, 0xd0, 0x01, 223 0x1c, 0x6a, 0xd0, 0x01,
@@ -227,31 +227,32 @@ static uint8_t seqprog[] = {
227 0x01, 0x93, 0x26, 0x01, 227 0x01, 0x93, 0x26, 0x01,
228 0x03, 0x6a, 0x2a, 0x01, 228 0x03, 0x6a, 0x2a, 0x01,
229 0x01, 0x69, 0x32, 0x31, 229 0x01, 0x69, 0x32, 0x31,
230 0x1c, 0x6a, 0xe0, 0x5d, 230 0x1c, 0x6a, 0xe2, 0x5d,
231 0x0a, 0x93, 0x26, 0x01, 231 0x0a, 0x93, 0x26, 0x01,
232 0x00, 0x65, 0xa8, 0x5e, 232 0x00, 0x65, 0xaa, 0x5e,
233 0x01, 0x50, 0xa0, 0x18, 233 0x01, 0x50, 0xa0, 0x18,
234 0x02, 0x6a, 0x22, 0x05, 234 0x02, 0x6a, 0x22, 0x05,
235 0x1a, 0x01, 0x02, 0x00, 235 0x1a, 0x01, 0x02, 0x00,
236 0x80, 0x6a, 0x74, 0x00, 236 0x80, 0x6a, 0x74, 0x00,
237 0x40, 0x6a, 0x78, 0x00, 237 0x40, 0x6a, 0x78, 0x00,
238 0x40, 0x6a, 0x16, 0x00, 238 0x40, 0x6a, 0x16, 0x00,
239 0x00, 0x65, 0xd8, 0x5d, 239 0x00, 0x65, 0xda, 0x5d,
240 0x01, 0x3f, 0xc8, 0x30, 240 0x01, 0x3f, 0xc8, 0x30,
241 0xbf, 0x64, 0x56, 0x7a, 241 0xbf, 0x64, 0x58, 0x7a,
242 0x80, 0x64, 0x9e, 0x73, 242 0x80, 0x64, 0xa0, 0x73,
243 0xa0, 0x64, 0x00, 0x74, 243 0xa0, 0x64, 0x02, 0x74,
244 0xc0, 0x64, 0xf4, 0x73, 244 0xc0, 0x64, 0xf6, 0x73,
245 0xe0, 0x64, 0x30, 0x74, 245 0xe0, 0x64, 0x32, 0x74,
246 0x01, 0x6a, 0xd8, 0x5e, 246 0x01, 0x6a, 0xda, 0x5e,
247 0x00, 0x65, 0xcc, 0x41, 247 0x00, 0x65, 0xcc, 0x41,
248 0xf7, 0x11, 0x22, 0x08, 248 0xf7, 0x11, 0x22, 0x08,
249 0x01, 0x06, 0xd4, 0x30, 249 0x01, 0x06, 0xd4, 0x30,
250 0xff, 0x6a, 0x24, 0x08, 250 0xff, 0x6a, 0x24, 0x08,
251 0xf7, 0x01, 0x02, 0x08, 251 0xf7, 0x01, 0x02, 0x08,
252 0x09, 0x0c, 0xe6, 0x79, 252 0xc0, 0x6a, 0x78, 0x00,
253 0x09, 0x0c, 0xe8, 0x79,
253 0x08, 0x0c, 0x04, 0x68, 254 0x08, 0x0c, 0x04, 0x68,
254 0xb1, 0x6a, 0xd8, 0x5e, 255 0xb1, 0x6a, 0xda, 0x5e,
255 0xff, 0x6a, 0x26, 0x09, 256 0xff, 0x6a, 0x26, 0x09,
256 0x12, 0x01, 0x02, 0x00, 257 0x12, 0x01, 0x02, 0x00,
257 0x02, 0x6a, 0x08, 0x30, 258 0x02, 0x6a, 0x08, 0x30,
@@ -264,29 +265,29 @@ static uint8_t seqprog[] = {
264 0x00, 0xa5, 0x4a, 0x21, 265 0x00, 0xa5, 0x4a, 0x21,
265 0x00, 0xa6, 0x4c, 0x21, 266 0x00, 0xa6, 0x4c, 0x21,
266 0x00, 0xa7, 0x4e, 0x25, 267 0x00, 0xa7, 0x4e, 0x25,
267 0x08, 0xeb, 0xdc, 0x7e, 268 0x08, 0xeb, 0xde, 0x7e,
268 0x80, 0xeb, 0x06, 0x7a, 269 0x80, 0xeb, 0x08, 0x7a,
269 0xff, 0x6a, 0xd6, 0x09, 270 0xff, 0x6a, 0xd6, 0x09,
270 0x08, 0xeb, 0x0a, 0x6a, 271 0x08, 0xeb, 0x0c, 0x6a,
271 0xff, 0x6a, 0xd4, 0x0c, 272 0xff, 0x6a, 0xd4, 0x0c,
272 0x80, 0xa3, 0xdc, 0x6e, 273 0x80, 0xa3, 0xde, 0x6e,
273 0x88, 0xeb, 0x20, 0x72, 274 0x88, 0xeb, 0x22, 0x72,
274 0x08, 0xeb, 0xdc, 0x6e, 275 0x08, 0xeb, 0xde, 0x6e,
275 0x04, 0xea, 0x24, 0xe2, 276 0x04, 0xea, 0x26, 0xe2,
276 0x08, 0xee, 0xdc, 0x6e, 277 0x08, 0xee, 0xde, 0x6e,
277 0x04, 0x6a, 0xd0, 0x81, 278 0x04, 0x6a, 0xd0, 0x81,
278 0x05, 0xa4, 0xc0, 0x89, 279 0x05, 0xa4, 0xc0, 0x89,
279 0x03, 0xa5, 0xc2, 0x31, 280 0x03, 0xa5, 0xc2, 0x31,
280 0x09, 0x6a, 0xd6, 0x05, 281 0x09, 0x6a, 0xd6, 0x05,
281 0x00, 0x65, 0x08, 0x5a, 282 0x00, 0x65, 0x0a, 0x5a,
282 0x06, 0xa4, 0xd4, 0x89, 283 0x06, 0xa4, 0xd4, 0x89,
283 0x80, 0x94, 0xdc, 0x7e, 284 0x80, 0x94, 0xde, 0x7e,
284 0x07, 0xe9, 0x10, 0x31, 285 0x07, 0xe9, 0x10, 0x31,
285 0x01, 0xe9, 0x46, 0x31, 286 0x01, 0xe9, 0x46, 0x31,
286 0x00, 0xa3, 0xba, 0x5e, 287 0x00, 0xa3, 0xbc, 0x5e,
287 0x00, 0x65, 0xfa, 0x59, 288 0x00, 0x65, 0xfc, 0x59,
288 0x01, 0xa4, 0xca, 0x30, 289 0x01, 0xa4, 0xca, 0x30,
289 0x80, 0xa3, 0x34, 0x7a, 290 0x80, 0xa3, 0x36, 0x7a,
290 0x02, 0x65, 0xca, 0x00, 291 0x02, 0x65, 0xca, 0x00,
291 0x01, 0x65, 0xf8, 0x31, 292 0x01, 0x65, 0xf8, 0x31,
292 0x80, 0x93, 0x26, 0x01, 293 0x80, 0x93, 0x26, 0x01,
@@ -294,162 +295,162 @@ static uint8_t seqprog[] = {
294 0x01, 0x8c, 0xc8, 0x30, 295 0x01, 0x8c, 0xc8, 0x30,
295 0x00, 0x88, 0xc8, 0x18, 296 0x00, 0x88, 0xc8, 0x18,
296 0x02, 0x64, 0xc8, 0x88, 297 0x02, 0x64, 0xc8, 0x88,
297 0xff, 0x64, 0xdc, 0x7e, 298 0xff, 0x64, 0xde, 0x7e,
298 0xff, 0x8d, 0x4a, 0x6a, 299 0xff, 0x8d, 0x4c, 0x6a,
299 0xff, 0x8e, 0x4a, 0x6a, 300 0xff, 0x8e, 0x4c, 0x6a,
300 0x03, 0x8c, 0xd4, 0x98, 301 0x03, 0x8c, 0xd4, 0x98,
301 0x00, 0x65, 0xdc, 0x56, 302 0x00, 0x65, 0xde, 0x56,
302 0x01, 0x64, 0x70, 0x30, 303 0x01, 0x64, 0x70, 0x30,
303 0xff, 0x64, 0xc8, 0x10, 304 0xff, 0x64, 0xc8, 0x10,
304 0x01, 0x64, 0xc8, 0x18, 305 0x01, 0x64, 0xc8, 0x18,
305 0x00, 0x8c, 0x18, 0x19, 306 0x00, 0x8c, 0x18, 0x19,
306 0xff, 0x8d, 0x1a, 0x21, 307 0xff, 0x8d, 0x1a, 0x21,
307 0xff, 0x8e, 0x1c, 0x25, 308 0xff, 0x8e, 0x1c, 0x25,
308 0xc0, 0x3c, 0x5a, 0x7a, 309 0xc0, 0x3c, 0x5c, 0x7a,
309 0x21, 0x6a, 0xd8, 0x5e, 310 0x21, 0x6a, 0xda, 0x5e,
310 0xa8, 0x6a, 0x76, 0x00, 311 0xa8, 0x6a, 0x76, 0x00,
311 0x79, 0x6a, 0x76, 0x00, 312 0x79, 0x6a, 0x76, 0x00,
312 0x40, 0x3f, 0x62, 0x6a, 313 0x40, 0x3f, 0x64, 0x6a,
313 0x04, 0x3b, 0x76, 0x00, 314 0x04, 0x3b, 0x76, 0x00,
314 0x04, 0x6a, 0xd4, 0x81, 315 0x04, 0x6a, 0xd4, 0x81,
315 0x20, 0x3c, 0x6a, 0x7a, 316 0x20, 0x3c, 0x6c, 0x7a,
316 0x51, 0x6a, 0xd8, 0x5e, 317 0x51, 0x6a, 0xda, 0x5e,
317 0x00, 0x65, 0x82, 0x42, 318 0x00, 0x65, 0x84, 0x42,
318 0x20, 0x3c, 0x78, 0x00, 319 0x20, 0x3c, 0x78, 0x00,
319 0x00, 0xb3, 0xba, 0x5e, 320 0x00, 0xb3, 0xbc, 0x5e,
320 0x07, 0xac, 0x10, 0x31, 321 0x07, 0xac, 0x10, 0x31,
321 0x05, 0xb3, 0x46, 0x31, 322 0x05, 0xb3, 0x46, 0x31,
322 0x88, 0x6a, 0xcc, 0x00, 323 0x88, 0x6a, 0xcc, 0x00,
323 0xac, 0x6a, 0xee, 0x5d, 324 0xac, 0x6a, 0xf0, 0x5d,
324 0xa3, 0x6a, 0xcc, 0x00, 325 0xa3, 0x6a, 0xcc, 0x00,
325 0xb3, 0x6a, 0xf2, 0x5d, 326 0xb3, 0x6a, 0xf4, 0x5d,
326 0x00, 0x65, 0x3a, 0x5a, 327 0x00, 0x65, 0x3c, 0x5a,
327 0xfd, 0xa4, 0x48, 0x09, 328 0xfd, 0xa4, 0x48, 0x09,
328 0x03, 0x8c, 0x10, 0x30, 329 0x03, 0x8c, 0x10, 0x30,
329 0x00, 0x65, 0xe6, 0x5d, 330 0x00, 0x65, 0xe8, 0x5d,
330 0x01, 0xa4, 0x94, 0x7a, 331 0x01, 0xa4, 0x96, 0x7a,
331 0x04, 0x3b, 0x76, 0x08, 332 0x04, 0x3b, 0x76, 0x08,
332 0x01, 0x3b, 0x26, 0x31, 333 0x01, 0x3b, 0x26, 0x31,
333 0x80, 0x02, 0x04, 0x00, 334 0x80, 0x02, 0x04, 0x00,
334 0x10, 0x0c, 0x8a, 0x7a, 335 0x10, 0x0c, 0x8c, 0x7a,
335 0x03, 0x9e, 0x8c, 0x6a, 336 0x03, 0x9e, 0x8e, 0x6a,
336 0x7f, 0x02, 0x04, 0x08, 337 0x7f, 0x02, 0x04, 0x08,
337 0x91, 0x6a, 0xd8, 0x5e, 338 0x91, 0x6a, 0xda, 0x5e,
338 0x00, 0x65, 0xcc, 0x41, 339 0x00, 0x65, 0xcc, 0x41,
339 0x01, 0xa4, 0xca, 0x30, 340 0x01, 0xa4, 0xca, 0x30,
340 0x80, 0xa3, 0x9a, 0x7a, 341 0x80, 0xa3, 0x9c, 0x7a,
341 0x02, 0x65, 0xca, 0x00, 342 0x02, 0x65, 0xca, 0x00,
342 0x01, 0x65, 0xf8, 0x31, 343 0x01, 0x65, 0xf8, 0x31,
343 0x01, 0x3b, 0x26, 0x31, 344 0x01, 0x3b, 0x26, 0x31,
344 0x00, 0x65, 0x0e, 0x5a, 345 0x00, 0x65, 0x10, 0x5a,
345 0x01, 0xfc, 0xa8, 0x6a, 346 0x01, 0xfc, 0xaa, 0x6a,
346 0x80, 0x0b, 0x9e, 0x6a, 347 0x80, 0x0b, 0xa0, 0x6a,
347 0x10, 0x0c, 0x9e, 0x7a, 348 0x10, 0x0c, 0xa0, 0x7a,
348 0x20, 0x93, 0x9e, 0x6a, 349 0x20, 0x93, 0xa0, 0x6a,
349 0x02, 0x93, 0x26, 0x01, 350 0x02, 0x93, 0x26, 0x01,
350 0x02, 0xfc, 0xb2, 0x7a, 351 0x02, 0xfc, 0xb4, 0x7a,
351 0x40, 0x0d, 0xc6, 0x6a, 352 0x40, 0x0d, 0xc8, 0x6a,
352 0x01, 0xa4, 0x48, 0x01, 353 0x01, 0xa4, 0x48, 0x01,
353 0x00, 0x65, 0xc6, 0x42, 354 0x00, 0x65, 0xc8, 0x42,
354 0x40, 0x0d, 0xb8, 0x6a, 355 0x40, 0x0d, 0xba, 0x6a,
355 0x00, 0x65, 0x0e, 0x5a, 356 0x00, 0x65, 0x10, 0x5a,
356 0x00, 0x65, 0xaa, 0x42, 357 0x00, 0x65, 0xac, 0x42,
357 0x80, 0xfc, 0xc2, 0x7a, 358 0x80, 0xfc, 0xc4, 0x7a,
358 0x80, 0xa4, 0xc2, 0x6a, 359 0x80, 0xa4, 0xc4, 0x6a,
359 0xff, 0xa5, 0x4a, 0x19, 360 0xff, 0xa5, 0x4a, 0x19,
360 0xff, 0xa6, 0x4c, 0x21, 361 0xff, 0xa6, 0x4c, 0x21,
361 0xff, 0xa7, 0x4e, 0x21, 362 0xff, 0xa7, 0x4e, 0x21,
362 0xf8, 0xfc, 0x48, 0x09, 363 0xf8, 0xfc, 0x48, 0x09,
363 0x7f, 0xa3, 0x46, 0x09, 364 0x7f, 0xa3, 0x46, 0x09,
364 0x04, 0x3b, 0xe2, 0x6a, 365 0x04, 0x3b, 0xe4, 0x6a,
365 0x02, 0x93, 0x26, 0x01, 366 0x02, 0x93, 0x26, 0x01,
366 0x01, 0x94, 0xc8, 0x7a, 367 0x01, 0x94, 0xca, 0x7a,
367 0x01, 0x94, 0xc8, 0x7a, 368 0x01, 0x94, 0xca, 0x7a,
368 0x01, 0x94, 0xc8, 0x7a, 369 0x01, 0x94, 0xca, 0x7a,
369 0x01, 0x94, 0xc8, 0x7a, 370 0x01, 0x94, 0xca, 0x7a,
370 0x01, 0x94, 0xc8, 0x7a, 371 0x01, 0x94, 0xca, 0x7a,
371 0x01, 0xa4, 0xe0, 0x7a, 372 0x01, 0xa4, 0xe2, 0x7a,
372 0x01, 0xfc, 0xd6, 0x7a, 373 0x01, 0xfc, 0xd8, 0x7a,
373 0x01, 0x94, 0xe2, 0x6a, 374 0x01, 0x94, 0xe4, 0x6a,
374 0x01, 0x94, 0xe2, 0x6a, 375 0x01, 0x94, 0xe4, 0x6a,
375 0x01, 0x94, 0xe2, 0x6a, 376 0x01, 0x94, 0xe4, 0x6a,
376 0x00, 0x65, 0x82, 0x42, 377 0x00, 0x65, 0x84, 0x42,
377 0x01, 0x94, 0xe0, 0x7a, 378 0x01, 0x94, 0xe2, 0x7a,
378 0x10, 0x94, 0xe2, 0x6a, 379 0x10, 0x94, 0xe4, 0x6a,
379 0xd7, 0x93, 0x26, 0x09, 380 0xd7, 0x93, 0x26, 0x09,
380 0x28, 0x93, 0xe6, 0x6a, 381 0x28, 0x93, 0xe8, 0x6a,
381 0x01, 0x85, 0x0a, 0x01, 382 0x01, 0x85, 0x0a, 0x01,
382 0x02, 0xfc, 0xee, 0x6a, 383 0x02, 0xfc, 0xf0, 0x6a,
383 0x01, 0x14, 0x46, 0x31, 384 0x01, 0x14, 0x46, 0x31,
384 0xff, 0x6a, 0x10, 0x09, 385 0xff, 0x6a, 0x10, 0x09,
385 0xfe, 0x85, 0x0a, 0x09, 386 0xfe, 0x85, 0x0a, 0x09,
386 0xff, 0x38, 0xfc, 0x6a, 387 0xff, 0x38, 0xfe, 0x6a,
387 0x80, 0xa3, 0xfc, 0x7a, 388 0x80, 0xa3, 0xfe, 0x7a,
388 0x80, 0x0b, 0xfa, 0x7a, 389 0x80, 0x0b, 0xfc, 0x7a,
389 0x04, 0x3b, 0xfc, 0x7a, 390 0x04, 0x3b, 0xfe, 0x7a,
390 0xbf, 0x3b, 0x76, 0x08, 391 0xbf, 0x3b, 0x76, 0x08,
391 0x01, 0x3b, 0x26, 0x31, 392 0x01, 0x3b, 0x26, 0x31,
392 0x00, 0x65, 0x0e, 0x5a, 393 0x00, 0x65, 0x10, 0x5a,
393 0x01, 0x0b, 0x0a, 0x6b, 394 0x01, 0x0b, 0x0c, 0x6b,
394 0x10, 0x0c, 0xfe, 0x7a, 395 0x10, 0x0c, 0x00, 0x7b,
395 0x04, 0x93, 0x08, 0x6b, 396 0x04, 0x93, 0x0a, 0x6b,
396 0x01, 0x94, 0x06, 0x7b, 397 0x01, 0x94, 0x08, 0x7b,
397 0x10, 0x94, 0x08, 0x6b, 398 0x10, 0x94, 0x0a, 0x6b,
398 0xc7, 0x93, 0x26, 0x09, 399 0xc7, 0x93, 0x26, 0x09,
399 0x01, 0x99, 0xd4, 0x30, 400 0x01, 0x99, 0xd4, 0x30,
400 0x38, 0x93, 0x0c, 0x6b, 401 0x38, 0x93, 0x0e, 0x6b,
401 0xff, 0x08, 0x5a, 0x6b, 402 0xff, 0x08, 0x5c, 0x6b,
402 0xff, 0x09, 0x5a, 0x6b, 403 0xff, 0x09, 0x5c, 0x6b,
403 0xff, 0x0a, 0x5a, 0x6b, 404 0xff, 0x0a, 0x5c, 0x6b,
404 0xff, 0x38, 0x28, 0x7b, 405 0xff, 0x38, 0x2a, 0x7b,
405 0x04, 0x14, 0x10, 0x31, 406 0x04, 0x14, 0x10, 0x31,
406 0x01, 0x38, 0x18, 0x31, 407 0x01, 0x38, 0x18, 0x31,
407 0x02, 0x6a, 0x1a, 0x31, 408 0x02, 0x6a, 0x1a, 0x31,
408 0x88, 0x6a, 0xcc, 0x00, 409 0x88, 0x6a, 0xcc, 0x00,
409 0x14, 0x6a, 0xf4, 0x5d, 410 0x14, 0x6a, 0xf6, 0x5d,
410 0x00, 0x38, 0xe0, 0x5d, 411 0x00, 0x38, 0xe2, 0x5d,
411 0xff, 0x6a, 0x70, 0x08, 412 0xff, 0x6a, 0x70, 0x08,
412 0x00, 0x65, 0x54, 0x43, 413 0x00, 0x65, 0x56, 0x43,
413 0x80, 0xa3, 0x2e, 0x7b, 414 0x80, 0xa3, 0x30, 0x7b,
414 0x01, 0xa4, 0x48, 0x01, 415 0x01, 0xa4, 0x48, 0x01,
415 0x00, 0x65, 0x5a, 0x43, 416 0x00, 0x65, 0x5c, 0x43,
416 0x08, 0xeb, 0x34, 0x7b, 417 0x08, 0xeb, 0x36, 0x7b,
417 0x00, 0x65, 0x0e, 0x5a, 418 0x00, 0x65, 0x10, 0x5a,
418 0x08, 0xeb, 0x30, 0x6b, 419 0x08, 0xeb, 0x32, 0x6b,
419 0x07, 0xe9, 0x10, 0x31, 420 0x07, 0xe9, 0x10, 0x31,
420 0x01, 0xe9, 0xca, 0x30, 421 0x01, 0xe9, 0xca, 0x30,
421 0x01, 0x65, 0x46, 0x31, 422 0x01, 0x65, 0x46, 0x31,
422 0x00, 0x6a, 0xba, 0x5e, 423 0x00, 0x6a, 0xbc, 0x5e,
423 0x88, 0x6a, 0xcc, 0x00, 424 0x88, 0x6a, 0xcc, 0x00,
424 0xa4, 0x6a, 0xf4, 0x5d, 425 0xa4, 0x6a, 0xf6, 0x5d,
425 0x08, 0x6a, 0xe0, 0x5d, 426 0x08, 0x6a, 0xe2, 0x5d,
426 0x0d, 0x93, 0x26, 0x01, 427 0x0d, 0x93, 0x26, 0x01,
427 0x00, 0x65, 0xa8, 0x5e, 428 0x00, 0x65, 0xaa, 0x5e,
428 0x88, 0x6a, 0xcc, 0x00, 429 0x88, 0x6a, 0xcc, 0x00,
429 0x00, 0x65, 0x8a, 0x5e, 430 0x00, 0x65, 0x8c, 0x5e,
430 0x01, 0x99, 0x46, 0x31, 431 0x01, 0x99, 0x46, 0x31,
431 0x00, 0xa3, 0xba, 0x5e, 432 0x00, 0xa3, 0xbc, 0x5e,
432 0x01, 0x88, 0x10, 0x31, 433 0x01, 0x88, 0x10, 0x31,
433 0x00, 0x65, 0x3a, 0x5a, 434 0x00, 0x65, 0x3c, 0x5a,
434 0x00, 0x65, 0xfa, 0x59, 435 0x00, 0x65, 0xfc, 0x59,
435 0x03, 0x8c, 0x10, 0x30, 436 0x03, 0x8c, 0x10, 0x30,
436 0x00, 0x65, 0xe6, 0x5d, 437 0x00, 0x65, 0xe8, 0x5d,
437 0x80, 0x0b, 0x82, 0x6a, 438 0x80, 0x0b, 0x84, 0x6a,
438 0x80, 0x0b, 0x62, 0x6b, 439 0x80, 0x0b, 0x64, 0x6b,
439 0x01, 0x0c, 0x5c, 0x7b, 440 0x01, 0x0c, 0x5e, 0x7b,
440 0x10, 0x0c, 0x82, 0x7a, 441 0x10, 0x0c, 0x84, 0x7a,
441 0x03, 0x9e, 0x82, 0x6a, 442 0x03, 0x9e, 0x84, 0x6a,
442 0x00, 0x65, 0x04, 0x5a, 443 0x00, 0x65, 0x06, 0x5a,
443 0x00, 0x6a, 0xba, 0x5e, 444 0x00, 0x6a, 0xbc, 0x5e,
444 0x01, 0xa4, 0x82, 0x6b, 445 0x01, 0xa4, 0x84, 0x6b,
445 0xff, 0x38, 0x78, 0x7b, 446 0xff, 0x38, 0x7a, 0x7b,
446 0x01, 0x38, 0xc8, 0x30, 447 0x01, 0x38, 0xc8, 0x30,
447 0x00, 0x08, 0x40, 0x19, 448 0x00, 0x08, 0x40, 0x19,
448 0xff, 0x6a, 0xc8, 0x08, 449 0xff, 0x6a, 0xc8, 0x08,
449 0x00, 0x09, 0x42, 0x21, 450 0x00, 0x09, 0x42, 0x21,
450 0x00, 0x0a, 0x44, 0x21, 451 0x00, 0x0a, 0x44, 0x21,
451 0xff, 0x6a, 0x70, 0x08, 452 0xff, 0x6a, 0x70, 0x08,
452 0x00, 0x65, 0x7a, 0x43, 453 0x00, 0x65, 0x7c, 0x43,
453 0x03, 0x08, 0x40, 0x31, 454 0x03, 0x08, 0x40, 0x31,
454 0x03, 0x08, 0x40, 0x31, 455 0x03, 0x08, 0x40, 0x31,
455 0x01, 0x08, 0x40, 0x31, 456 0x01, 0x08, 0x40, 0x31,
@@ -461,16 +462,16 @@ static uint8_t seqprog[] = {
461 0x04, 0x3c, 0xcc, 0x79, 462 0x04, 0x3c, 0xcc, 0x79,
462 0xfb, 0x3c, 0x78, 0x08, 463 0xfb, 0x3c, 0x78, 0x08,
463 0x04, 0x93, 0x20, 0x79, 464 0x04, 0x93, 0x20, 0x79,
464 0x01, 0x0c, 0x8e, 0x6b, 465 0x01, 0x0c, 0x90, 0x6b,
465 0x80, 0xba, 0x20, 0x79, 466 0x80, 0xba, 0x20, 0x79,
466 0x80, 0x04, 0x20, 0x79, 467 0x80, 0x04, 0x20, 0x79,
467 0xe4, 0x6a, 0x6e, 0x5d, 468 0xe4, 0x6a, 0x70, 0x5d,
468 0x23, 0x6a, 0x84, 0x5d, 469 0x23, 0x6a, 0x86, 0x5d,
469 0x01, 0x6a, 0x84, 0x5d, 470 0x01, 0x6a, 0x86, 0x5d,
470 0x00, 0x65, 0x20, 0x41, 471 0x00, 0x65, 0x20, 0x41,
471 0x00, 0x65, 0xcc, 0x41, 472 0x00, 0x65, 0xcc, 0x41,
472 0x80, 0x3c, 0xa2, 0x7b, 473 0x80, 0x3c, 0xa4, 0x7b,
473 0x21, 0x6a, 0xd8, 0x5e, 474 0x21, 0x6a, 0xda, 0x5e,
474 0x01, 0xbc, 0x18, 0x31, 475 0x01, 0xbc, 0x18, 0x31,
475 0x02, 0x6a, 0x1a, 0x31, 476 0x02, 0x6a, 0x1a, 0x31,
476 0x02, 0x6a, 0xf8, 0x01, 477 0x02, 0x6a, 0xf8, 0x01,
@@ -480,16 +481,16 @@ static uint8_t seqprog[] = {
480 0xff, 0x6a, 0x12, 0x08, 481 0xff, 0x6a, 0x12, 0x08,
481 0xff, 0x6a, 0x14, 0x08, 482 0xff, 0x6a, 0x14, 0x08,
482 0xf3, 0xbc, 0xd4, 0x18, 483 0xf3, 0xbc, 0xd4, 0x18,
483 0xa0, 0x6a, 0xc8, 0x53, 484 0xa0, 0x6a, 0xca, 0x53,
484 0x04, 0xa0, 0x10, 0x31, 485 0x04, 0xa0, 0x10, 0x31,
485 0xac, 0x6a, 0x26, 0x01, 486 0xac, 0x6a, 0x26, 0x01,
486 0x04, 0xa0, 0x10, 0x31, 487 0x04, 0xa0, 0x10, 0x31,
487 0x03, 0x08, 0x18, 0x31, 488 0x03, 0x08, 0x18, 0x31,
488 0x88, 0x6a, 0xcc, 0x00, 489 0x88, 0x6a, 0xcc, 0x00,
489 0xa0, 0x6a, 0xf4, 0x5d, 490 0xa0, 0x6a, 0xf6, 0x5d,
490 0x00, 0xbc, 0xe0, 0x5d, 491 0x00, 0xbc, 0xe2, 0x5d,
491 0x3d, 0x6a, 0x26, 0x01, 492 0x3d, 0x6a, 0x26, 0x01,
492 0x00, 0x65, 0xe0, 0x43, 493 0x00, 0x65, 0xe2, 0x43,
493 0xff, 0x6a, 0x10, 0x09, 494 0xff, 0x6a, 0x10, 0x09,
494 0xa4, 0x6a, 0x26, 0x01, 495 0xa4, 0x6a, 0x26, 0x01,
495 0x0c, 0xa0, 0x32, 0x31, 496 0x0c, 0xa0, 0x32, 0x31,
@@ -499,128 +500,128 @@ static uint8_t seqprog[] = {
499 0x36, 0x6a, 0x26, 0x01, 500 0x36, 0x6a, 0x26, 0x01,
500 0x02, 0x93, 0x26, 0x01, 501 0x02, 0x93, 0x26, 0x01,
501 0x35, 0x6a, 0x26, 0x01, 502 0x35, 0x6a, 0x26, 0x01,
502 0x00, 0x65, 0x9c, 0x5e, 503 0x00, 0x65, 0x9e, 0x5e,
503 0x00, 0x65, 0x9c, 0x5e, 504 0x00, 0x65, 0x9e, 0x5e,
504 0x02, 0x93, 0x26, 0x01, 505 0x02, 0x93, 0x26, 0x01,
505 0xbf, 0x3c, 0x78, 0x08, 506 0xbf, 0x3c, 0x78, 0x08,
506 0x04, 0x0b, 0xe6, 0x6b, 507 0x04, 0x0b, 0xe8, 0x6b,
507 0x10, 0x0c, 0xe2, 0x7b, 508 0x10, 0x0c, 0xe4, 0x7b,
508 0x01, 0x03, 0xe6, 0x6b, 509 0x01, 0x03, 0xe8, 0x6b,
509 0x20, 0x93, 0xe8, 0x6b, 510 0x20, 0x93, 0xea, 0x6b,
510 0x04, 0x0b, 0xee, 0x6b, 511 0x04, 0x0b, 0xf0, 0x6b,
511 0x40, 0x3c, 0x78, 0x00, 512 0x40, 0x3c, 0x78, 0x00,
512 0xc7, 0x93, 0x26, 0x09, 513 0xc7, 0x93, 0x26, 0x09,
513 0x38, 0x93, 0xf0, 0x6b, 514 0x38, 0x93, 0xf2, 0x6b,
514 0x00, 0x65, 0xcc, 0x41, 515 0x00, 0x65, 0xcc, 0x41,
515 0x80, 0x3c, 0x56, 0x6c, 516 0x80, 0x3c, 0x58, 0x6c,
516 0x01, 0x06, 0x50, 0x31, 517 0x01, 0x06, 0x50, 0x31,
517 0x80, 0xb8, 0x70, 0x01, 518 0x80, 0xb8, 0x70, 0x01,
518 0x00, 0x65, 0xcc, 0x41, 519 0x00, 0x65, 0xcc, 0x41,
519 0x10, 0x3f, 0x06, 0x00, 520 0x10, 0x3f, 0x06, 0x00,
520 0x10, 0x6a, 0x06, 0x00, 521 0x10, 0x6a, 0x06, 0x00,
521 0x01, 0x3a, 0xca, 0x30, 522 0x01, 0x3a, 0xca, 0x30,
522 0x80, 0x65, 0x1c, 0x64, 523 0x80, 0x65, 0x1e, 0x64,
523 0x10, 0xb8, 0x40, 0x6c, 524 0x10, 0xb8, 0x42, 0x6c,
524 0xc0, 0x3e, 0xca, 0x00, 525 0xc0, 0x3e, 0xca, 0x00,
525 0x40, 0xb8, 0x0c, 0x6c, 526 0x40, 0xb8, 0x0e, 0x6c,
526 0xbf, 0x65, 0xca, 0x08, 527 0xbf, 0x65, 0xca, 0x08,
527 0x20, 0xb8, 0x20, 0x7c, 528 0x20, 0xb8, 0x22, 0x7c,
528 0x01, 0x65, 0x0c, 0x30, 529 0x01, 0x65, 0x0c, 0x30,
529 0x00, 0x65, 0xd8, 0x5d, 530 0x00, 0x65, 0xda, 0x5d,
530 0xa0, 0x3f, 0x28, 0x64, 531 0xa0, 0x3f, 0x2a, 0x64,
531 0x23, 0xb8, 0x0c, 0x08, 532 0x23, 0xb8, 0x0c, 0x08,
532 0x00, 0x65, 0xd8, 0x5d, 533 0x00, 0x65, 0xda, 0x5d,
533 0xa0, 0x3f, 0x28, 0x64, 534 0xa0, 0x3f, 0x2a, 0x64,
534 0x00, 0xbb, 0x20, 0x44, 535 0x00, 0xbb, 0x22, 0x44,
535 0xff, 0x65, 0x20, 0x64, 536 0xff, 0x65, 0x22, 0x64,
536 0x00, 0x65, 0x40, 0x44, 537 0x00, 0x65, 0x42, 0x44,
537 0x40, 0x6a, 0x18, 0x00, 538 0x40, 0x6a, 0x18, 0x00,
538 0x01, 0x65, 0x0c, 0x30, 539 0x01, 0x65, 0x0c, 0x30,
539 0x00, 0x65, 0xd8, 0x5d, 540 0x00, 0x65, 0xda, 0x5d,
540 0xa0, 0x3f, 0xfc, 0x73, 541 0xa0, 0x3f, 0xfe, 0x73,
541 0x40, 0x6a, 0x18, 0x00, 542 0x40, 0x6a, 0x18, 0x00,
542 0x01, 0x3a, 0xa6, 0x30, 543 0x01, 0x3a, 0xa6, 0x30,
543 0x08, 0x6a, 0x74, 0x00, 544 0x08, 0x6a, 0x74, 0x00,
544 0x00, 0x65, 0xcc, 0x41, 545 0x00, 0x65, 0xcc, 0x41,
545 0x64, 0x6a, 0x68, 0x5d, 546 0x64, 0x6a, 0x6a, 0x5d,
546 0x80, 0x64, 0xd8, 0x6c, 547 0x80, 0x64, 0xda, 0x6c,
547 0x04, 0x64, 0x9a, 0x74, 548 0x04, 0x64, 0x9c, 0x74,
548 0x02, 0x64, 0xaa, 0x74, 549 0x02, 0x64, 0xac, 0x74,
549 0x00, 0x6a, 0x60, 0x74, 550 0x00, 0x6a, 0x62, 0x74,
550 0x03, 0x64, 0xc8, 0x74, 551 0x03, 0x64, 0xca, 0x74,
551 0x23, 0x64, 0x48, 0x74, 552 0x23, 0x64, 0x4a, 0x74,
552 0x08, 0x64, 0x5c, 0x74, 553 0x08, 0x64, 0x5e, 0x74,
553 0x61, 0x6a, 0xd8, 0x5e, 554 0x61, 0x6a, 0xda, 0x5e,
554 0x00, 0x65, 0xd8, 0x5d, 555 0x00, 0x65, 0xda, 0x5d,
555 0x08, 0x51, 0xce, 0x71, 556 0x08, 0x51, 0xce, 0x71,
556 0x00, 0x65, 0x40, 0x44, 557 0x00, 0x65, 0x42, 0x44,
557 0x80, 0x04, 0x5a, 0x7c, 558 0x80, 0x04, 0x5c, 0x7c,
558 0x51, 0x6a, 0x5e, 0x5d, 559 0x51, 0x6a, 0x60, 0x5d,
559 0x01, 0x51, 0x5a, 0x64, 560 0x01, 0x51, 0x5c, 0x64,
560 0x01, 0xa4, 0x52, 0x7c, 561 0x01, 0xa4, 0x54, 0x7c,
561 0x80, 0xba, 0x5c, 0x6c, 562 0x80, 0xba, 0x5e, 0x6c,
562 0x41, 0x6a, 0xd8, 0x5e, 563 0x41, 0x6a, 0xda, 0x5e,
563 0x00, 0x65, 0x5c, 0x44, 564 0x00, 0x65, 0x5e, 0x44,
564 0x21, 0x6a, 0xd8, 0x5e, 565 0x21, 0x6a, 0xda, 0x5e,
565 0x00, 0x65, 0x5c, 0x44, 566 0x00, 0x65, 0x5e, 0x44,
566 0x07, 0x6a, 0x54, 0x5d, 567 0x07, 0x6a, 0x56, 0x5d,
567 0x01, 0x06, 0xd4, 0x30, 568 0x01, 0x06, 0xd4, 0x30,
568 0x00, 0x65, 0xcc, 0x41, 569 0x00, 0x65, 0xcc, 0x41,
569 0x80, 0xb8, 0x56, 0x7c, 570 0x80, 0xb8, 0x58, 0x7c,
570 0xc0, 0x3c, 0x6a, 0x7c, 571 0xc0, 0x3c, 0x6c, 0x7c,
571 0x80, 0x3c, 0x56, 0x6c, 572 0x80, 0x3c, 0x58, 0x6c,
572 0xff, 0xa8, 0x6a, 0x6c, 573 0xff, 0xa8, 0x6c, 0x6c,
573 0x40, 0x3c, 0x56, 0x6c, 574 0x40, 0x3c, 0x58, 0x6c,
574 0x10, 0xb8, 0x6e, 0x7c, 575 0x10, 0xb8, 0x70, 0x7c,
575 0xa1, 0x6a, 0xd8, 0x5e, 576 0xa1, 0x6a, 0xda, 0x5e,
576 0x01, 0xb4, 0x74, 0x6c, 577 0x01, 0xb4, 0x76, 0x6c,
577 0x02, 0xb4, 0x76, 0x6c, 578 0x02, 0xb4, 0x78, 0x6c,
578 0x01, 0xa4, 0x76, 0x7c, 579 0x01, 0xa4, 0x78, 0x7c,
579 0xff, 0xa8, 0x86, 0x7c, 580 0xff, 0xa8, 0x88, 0x7c,
580 0x04, 0xb4, 0x68, 0x01, 581 0x04, 0xb4, 0x68, 0x01,
581 0x01, 0x6a, 0x76, 0x00, 582 0x01, 0x6a, 0x76, 0x00,
582 0x00, 0xbb, 0x12, 0x5e, 583 0x00, 0xbb, 0x14, 0x5e,
583 0xff, 0xa8, 0x86, 0x7c, 584 0xff, 0xa8, 0x88, 0x7c,
584 0x71, 0x6a, 0xd8, 0x5e, 585 0x71, 0x6a, 0xda, 0x5e,
585 0x40, 0x51, 0x86, 0x64, 586 0x40, 0x51, 0x88, 0x64,
586 0x00, 0x65, 0xb2, 0x5e, 587 0x00, 0x65, 0xb4, 0x5e,
587 0x00, 0x65, 0xde, 0x41, 588 0x00, 0x65, 0xde, 0x41,
588 0x00, 0xbb, 0x8a, 0x5c, 589 0x00, 0xbb, 0x8c, 0x5c,
589 0x00, 0x65, 0xde, 0x41, 590 0x00, 0x65, 0xde, 0x41,
590 0x00, 0x65, 0xb2, 0x5e, 591 0x00, 0x65, 0xb4, 0x5e,
591 0x01, 0x65, 0xa2, 0x30, 592 0x01, 0x65, 0xa2, 0x30,
592 0x01, 0xf8, 0xc8, 0x30, 593 0x01, 0xf8, 0xc8, 0x30,
593 0x01, 0x4e, 0xc8, 0x30, 594 0x01, 0x4e, 0xc8, 0x30,
594 0x00, 0x6a, 0xb6, 0xdd, 595 0x00, 0x6a, 0xb8, 0xdd,
595 0x00, 0x51, 0xc8, 0x5d, 596 0x00, 0x51, 0xca, 0x5d,
596 0x01, 0x4e, 0x9c, 0x18, 597 0x01, 0x4e, 0x9c, 0x18,
597 0x02, 0x6a, 0x22, 0x05, 598 0x02, 0x6a, 0x22, 0x05,
598 0xc0, 0x3c, 0x56, 0x6c, 599 0xc0, 0x3c, 0x58, 0x6c,
599 0x04, 0xb8, 0x70, 0x01, 600 0x04, 0xb8, 0x70, 0x01,
600 0x00, 0x65, 0xd4, 0x5e, 601 0x00, 0x65, 0xd6, 0x5e,
601 0x20, 0xb8, 0xde, 0x69, 602 0x20, 0xb8, 0xde, 0x69,
602 0x01, 0xbb, 0xa2, 0x30, 603 0x01, 0xbb, 0xa2, 0x30,
603 0x3f, 0xba, 0x7c, 0x08, 604 0x3f, 0xba, 0x7c, 0x08,
604 0x00, 0xb9, 0xce, 0x5c, 605 0x00, 0xb9, 0xd0, 0x5c,
605 0x00, 0x65, 0xde, 0x41, 606 0x00, 0x65, 0xde, 0x41,
606 0x01, 0x06, 0xd4, 0x30, 607 0x01, 0x06, 0xd4, 0x30,
607 0x20, 0x3c, 0xcc, 0x79, 608 0x20, 0x3c, 0xcc, 0x79,
608 0x20, 0x3c, 0x5c, 0x7c, 609 0x20, 0x3c, 0x5e, 0x7c,
609 0x01, 0xa4, 0xb8, 0x7c, 610 0x01, 0xa4, 0xba, 0x7c,
610 0x01, 0xb4, 0x68, 0x01, 611 0x01, 0xb4, 0x68, 0x01,
611 0x00, 0x65, 0xcc, 0x41, 612 0x00, 0x65, 0xcc, 0x41,
612 0x00, 0x65, 0x5c, 0x44, 613 0x00, 0x65, 0x5e, 0x44,
613 0x04, 0x14, 0x58, 0x31, 614 0x04, 0x14, 0x58, 0x31,
614 0x01, 0x06, 0xd4, 0x30, 615 0x01, 0x06, 0xd4, 0x30,
615 0x08, 0xa0, 0x60, 0x31, 616 0x08, 0xa0, 0x60, 0x31,
616 0xac, 0x6a, 0xcc, 0x00, 617 0xac, 0x6a, 0xcc, 0x00,
617 0x14, 0x6a, 0xf4, 0x5d, 618 0x14, 0x6a, 0xf6, 0x5d,
618 0x01, 0x06, 0xd4, 0x30, 619 0x01, 0x06, 0xd4, 0x30,
619 0xa0, 0x6a, 0xec, 0x5d, 620 0xa0, 0x6a, 0xee, 0x5d,
620 0x00, 0x65, 0xcc, 0x41, 621 0x00, 0x65, 0xcc, 0x41,
621 0xdf, 0x3c, 0x78, 0x08, 622 0xdf, 0x3c, 0x78, 0x08,
622 0x12, 0x01, 0x02, 0x00, 623 0x12, 0x01, 0x02, 0x00,
623 0x00, 0x65, 0x5c, 0x44, 624 0x00, 0x65, 0x5e, 0x44,
624 0x4c, 0x65, 0xcc, 0x28, 625 0x4c, 0x65, 0xcc, 0x28,
625 0x01, 0x3e, 0x20, 0x31, 626 0x01, 0x3e, 0x20, 0x31,
626 0xd0, 0x66, 0xcc, 0x18, 627 0xd0, 0x66, 0xcc, 0x18,
@@ -631,102 +632,102 @@ static uint8_t seqprog[] = {
631 0xd0, 0x65, 0xca, 0x18, 632 0xd0, 0x65, 0xca, 0x18,
632 0x01, 0x3e, 0x20, 0x31, 633 0x01, 0x3e, 0x20, 0x31,
633 0x30, 0x65, 0xd4, 0x18, 634 0x30, 0x65, 0xd4, 0x18,
634 0x00, 0x65, 0xe6, 0x4c, 635 0x00, 0x65, 0xe8, 0x4c,
635 0xe1, 0x6a, 0x22, 0x01, 636 0xe1, 0x6a, 0x22, 0x01,
636 0xff, 0x6a, 0xd4, 0x08, 637 0xff, 0x6a, 0xd4, 0x08,
637 0x20, 0x65, 0xd4, 0x18, 638 0x20, 0x65, 0xd4, 0x18,
638 0x00, 0x65, 0xee, 0x54, 639 0x00, 0x65, 0xf0, 0x54,
639 0xe1, 0x6a, 0x22, 0x01, 640 0xe1, 0x6a, 0x22, 0x01,
640 0xff, 0x6a, 0xd4, 0x08, 641 0xff, 0x6a, 0xd4, 0x08,
641 0x20, 0x65, 0xca, 0x18, 642 0x20, 0x65, 0xca, 0x18,
642 0xe0, 0x65, 0xd4, 0x18, 643 0xe0, 0x65, 0xd4, 0x18,
643 0x00, 0x65, 0xf8, 0x4c, 644 0x00, 0x65, 0xfa, 0x4c,
644 0xe1, 0x6a, 0x22, 0x01, 645 0xe1, 0x6a, 0x22, 0x01,
645 0xff, 0x6a, 0xd4, 0x08, 646 0xff, 0x6a, 0xd4, 0x08,
646 0xd0, 0x65, 0xd4, 0x18, 647 0xd0, 0x65, 0xd4, 0x18,
647 0x00, 0x65, 0x00, 0x55, 648 0x00, 0x65, 0x02, 0x55,
648 0xe1, 0x6a, 0x22, 0x01, 649 0xe1, 0x6a, 0x22, 0x01,
649 0xff, 0x6a, 0xd4, 0x08, 650 0xff, 0x6a, 0xd4, 0x08,
650 0x01, 0x6c, 0xa2, 0x30, 651 0x01, 0x6c, 0xa2, 0x30,
651 0xff, 0x51, 0x12, 0x75, 652 0xff, 0x51, 0x14, 0x75,
652 0x00, 0x51, 0x8e, 0x5d, 653 0x00, 0x51, 0x90, 0x5d,
653 0x01, 0x51, 0x20, 0x31, 654 0x01, 0x51, 0x20, 0x31,
654 0x00, 0x65, 0x34, 0x45, 655 0x00, 0x65, 0x36, 0x45,
655 0x3f, 0xba, 0xc8, 0x08, 656 0x3f, 0xba, 0xc8, 0x08,
656 0x00, 0x3e, 0x34, 0x75, 657 0x00, 0x3e, 0x36, 0x75,
657 0x00, 0x65, 0xb0, 0x5e, 658 0x00, 0x65, 0xb2, 0x5e,
658 0x80, 0x3c, 0x78, 0x00, 659 0x80, 0x3c, 0x78, 0x00,
659 0x01, 0x06, 0xd4, 0x30, 660 0x01, 0x06, 0xd4, 0x30,
660 0x00, 0x65, 0xd8, 0x5d, 661 0x00, 0x65, 0xda, 0x5d,
661 0x01, 0x3c, 0x78, 0x00, 662 0x01, 0x3c, 0x78, 0x00,
662 0xe0, 0x3f, 0x50, 0x65, 663 0xe0, 0x3f, 0x52, 0x65,
663 0x02, 0x3c, 0x78, 0x00, 664 0x02, 0x3c, 0x78, 0x00,
664 0x20, 0x12, 0x50, 0x65, 665 0x20, 0x12, 0x52, 0x65,
665 0x51, 0x6a, 0x5e, 0x5d, 666 0x51, 0x6a, 0x60, 0x5d,
666 0x00, 0x51, 0x8e, 0x5d, 667 0x00, 0x51, 0x90, 0x5d,
667 0x51, 0x6a, 0x5e, 0x5d, 668 0x51, 0x6a, 0x60, 0x5d,
668 0x01, 0x51, 0x20, 0x31, 669 0x01, 0x51, 0x20, 0x31,
669 0x04, 0x3c, 0x78, 0x00, 670 0x04, 0x3c, 0x78, 0x00,
670 0x01, 0xb9, 0xc8, 0x30, 671 0x01, 0xb9, 0xc8, 0x30,
671 0x00, 0x3d, 0x4e, 0x65, 672 0x00, 0x3d, 0x50, 0x65,
672 0x08, 0x3c, 0x78, 0x00, 673 0x08, 0x3c, 0x78, 0x00,
673 0x3f, 0xba, 0xc8, 0x08, 674 0x3f, 0xba, 0xc8, 0x08,
674 0x00, 0x3e, 0x4e, 0x65, 675 0x00, 0x3e, 0x50, 0x65,
675 0x10, 0x3c, 0x78, 0x00, 676 0x10, 0x3c, 0x78, 0x00,
676 0x04, 0xb8, 0x4e, 0x7d, 677 0x04, 0xb8, 0x50, 0x7d,
677 0xfb, 0xb8, 0x70, 0x09, 678 0xfb, 0xb8, 0x70, 0x09,
678 0x20, 0xb8, 0x44, 0x6d, 679 0x20, 0xb8, 0x46, 0x6d,
679 0x01, 0x90, 0xc8, 0x30, 680 0x01, 0x90, 0xc8, 0x30,
680 0xff, 0x6a, 0xa2, 0x00, 681 0xff, 0x6a, 0xa2, 0x00,
681 0x00, 0x3d, 0xce, 0x5c, 682 0x00, 0x3d, 0xd0, 0x5c,
682 0x01, 0x64, 0x20, 0x31, 683 0x01, 0x64, 0x20, 0x31,
683 0xff, 0x6a, 0x78, 0x08, 684 0xff, 0x6a, 0x78, 0x08,
684 0x00, 0x65, 0xea, 0x58, 685 0x00, 0x65, 0xea, 0x58,
685 0x10, 0xb8, 0x5c, 0x7c, 686 0x10, 0xb8, 0x5e, 0x7c,
686 0xff, 0x6a, 0x54, 0x5d, 687 0xff, 0x6a, 0x56, 0x5d,
687 0x00, 0x65, 0x5c, 0x44, 688 0x00, 0x65, 0x5e, 0x44,
688 0x00, 0x65, 0xb0, 0x5e, 689 0x00, 0x65, 0xb2, 0x5e,
689 0x31, 0x6a, 0xd8, 0x5e, 690 0x31, 0x6a, 0xda, 0x5e,
690 0x00, 0x65, 0x5c, 0x44, 691 0x00, 0x65, 0x5e, 0x44,
691 0x10, 0x3f, 0x06, 0x00, 692 0x10, 0x3f, 0x06, 0x00,
692 0x10, 0x6a, 0x06, 0x00, 693 0x10, 0x6a, 0x06, 0x00,
693 0x01, 0x65, 0x74, 0x34, 694 0x01, 0x65, 0x74, 0x34,
694 0x81, 0x6a, 0xd8, 0x5e, 695 0x81, 0x6a, 0xda, 0x5e,
695 0x00, 0x65, 0x60, 0x45, 696 0x00, 0x65, 0x62, 0x45,
696 0x01, 0x06, 0xd4, 0x30, 697 0x01, 0x06, 0xd4, 0x30,
697 0x01, 0x0c, 0x60, 0x7d, 698 0x01, 0x0c, 0x62, 0x7d,
698 0x04, 0x0c, 0x5a, 0x6d, 699 0x04, 0x0c, 0x5c, 0x6d,
699 0xe0, 0x03, 0x7e, 0x08, 700 0xe0, 0x03, 0x7e, 0x08,
700 0xe0, 0x3f, 0xcc, 0x61, 701 0xe0, 0x3f, 0xcc, 0x61,
701 0x01, 0x65, 0xcc, 0x30, 702 0x01, 0x65, 0xcc, 0x30,
702 0x01, 0x12, 0xda, 0x34, 703 0x01, 0x12, 0xda, 0x34,
703 0x01, 0x06, 0xd4, 0x34, 704 0x01, 0x06, 0xd4, 0x34,
704 0x01, 0x03, 0x6e, 0x6d, 705 0x01, 0x03, 0x70, 0x6d,
705 0x40, 0x03, 0xcc, 0x08, 706 0x40, 0x03, 0xcc, 0x08,
706 0x01, 0x65, 0x06, 0x30, 707 0x01, 0x65, 0x06, 0x30,
707 0x40, 0x65, 0xc8, 0x08, 708 0x40, 0x65, 0xc8, 0x08,
708 0x00, 0x66, 0x7c, 0x75, 709 0x00, 0x66, 0x7e, 0x75,
709 0x40, 0x65, 0x7c, 0x7d, 710 0x40, 0x65, 0x7e, 0x7d,
710 0x00, 0x65, 0x7c, 0x5d, 711 0x00, 0x65, 0x7e, 0x5d,
711 0xff, 0x6a, 0xd4, 0x08, 712 0xff, 0x6a, 0xd4, 0x08,
712 0xff, 0x6a, 0xd4, 0x08, 713 0xff, 0x6a, 0xd4, 0x08,
713 0xff, 0x6a, 0xd4, 0x08, 714 0xff, 0x6a, 0xd4, 0x08,
714 0xff, 0x6a, 0xd4, 0x0c, 715 0xff, 0x6a, 0xd4, 0x0c,
715 0x08, 0x01, 0x02, 0x00, 716 0x08, 0x01, 0x02, 0x00,
716 0x02, 0x0b, 0x86, 0x7d, 717 0x02, 0x0b, 0x88, 0x7d,
717 0x01, 0x65, 0x0c, 0x30, 718 0x01, 0x65, 0x0c, 0x30,
718 0x02, 0x0b, 0x8a, 0x7d, 719 0x02, 0x0b, 0x8c, 0x7d,
719 0xf7, 0x01, 0x02, 0x0c, 720 0xf7, 0x01, 0x02, 0x0c,
720 0x01, 0x65, 0xc8, 0x30, 721 0x01, 0x65, 0xc8, 0x30,
721 0xff, 0x41, 0xae, 0x75, 722 0xff, 0x41, 0xb0, 0x75,
722 0x01, 0x41, 0x20, 0x31, 723 0x01, 0x41, 0x20, 0x31,
723 0xff, 0x6a, 0xa4, 0x00, 724 0xff, 0x6a, 0xa4, 0x00,
724 0x00, 0x65, 0x9e, 0x45, 725 0x00, 0x65, 0xa0, 0x45,
725 0xff, 0xbf, 0xae, 0x75, 726 0xff, 0xbf, 0xb0, 0x75,
726 0x01, 0x90, 0xa4, 0x30, 727 0x01, 0x90, 0xa4, 0x30,
727 0x01, 0xbf, 0x20, 0x31, 728 0x01, 0xbf, 0x20, 0x31,
728 0x00, 0xbb, 0x98, 0x65, 729 0x00, 0xbb, 0x9a, 0x65,
729 0xff, 0x52, 0xac, 0x75, 730 0xff, 0x52, 0xae, 0x75,
730 0x01, 0xbf, 0xcc, 0x30, 731 0x01, 0xbf, 0xcc, 0x30,
731 0x01, 0x90, 0xca, 0x30, 732 0x01, 0x90, 0xca, 0x30,
732 0x01, 0x52, 0x20, 0x31, 733 0x01, 0x52, 0x20, 0x31,
@@ -734,28 +735,28 @@ static uint8_t seqprog[] = {
734 0x01, 0x65, 0x20, 0x35, 735 0x01, 0x65, 0x20, 0x35,
735 0x01, 0xbf, 0x82, 0x34, 736 0x01, 0xbf, 0x82, 0x34,
736 0x01, 0x64, 0xa2, 0x30, 737 0x01, 0x64, 0xa2, 0x30,
737 0x00, 0x6a, 0xc0, 0x5e, 738 0x00, 0x6a, 0xc2, 0x5e,
738 0x0d, 0x6a, 0x76, 0x00, 739 0x0d, 0x6a, 0x76, 0x00,
739 0x00, 0x51, 0x12, 0x46, 740 0x00, 0x51, 0x14, 0x46,
740 0x01, 0x65, 0xa4, 0x30, 741 0x01, 0x65, 0xa4, 0x30,
741 0xe0, 0x6a, 0xcc, 0x00, 742 0xe0, 0x6a, 0xcc, 0x00,
742 0x48, 0x6a, 0x06, 0x5e, 743 0x48, 0x6a, 0x08, 0x5e,
743 0x01, 0x6a, 0xd0, 0x01, 744 0x01, 0x6a, 0xd0, 0x01,
744 0x01, 0x6a, 0xdc, 0x05, 745 0x01, 0x6a, 0xdc, 0x05,
745 0x88, 0x6a, 0xcc, 0x00, 746 0x88, 0x6a, 0xcc, 0x00,
746 0x48, 0x6a, 0x06, 0x5e, 747 0x48, 0x6a, 0x08, 0x5e,
747 0x01, 0x6a, 0xe0, 0x5d, 748 0x01, 0x6a, 0xe2, 0x5d,
748 0x01, 0x6a, 0x26, 0x05, 749 0x01, 0x6a, 0x26, 0x05,
749 0x01, 0x65, 0xd8, 0x31, 750 0x01, 0x65, 0xd8, 0x31,
750 0x09, 0xee, 0xdc, 0x01, 751 0x09, 0xee, 0xdc, 0x01,
751 0x80, 0xee, 0xcc, 0x7d, 752 0x80, 0xee, 0xce, 0x7d,
752 0xff, 0x6a, 0xdc, 0x0d, 753 0xff, 0x6a, 0xdc, 0x0d,
753 0x01, 0x65, 0x32, 0x31, 754 0x01, 0x65, 0x32, 0x31,
754 0x0a, 0x93, 0x26, 0x01, 755 0x0a, 0x93, 0x26, 0x01,
755 0x00, 0x65, 0xa8, 0x46, 756 0x00, 0x65, 0xaa, 0x46,
756 0x81, 0x6a, 0xd8, 0x5e, 757 0x81, 0x6a, 0xda, 0x5e,
757 0x01, 0x0c, 0xd8, 0x7d, 758 0x01, 0x0c, 0xda, 0x7d,
758 0x04, 0x0c, 0xd6, 0x6d, 759 0x04, 0x0c, 0xd8, 0x6d,
759 0xe0, 0x03, 0x06, 0x08, 760 0xe0, 0x03, 0x06, 0x08,
760 0xe0, 0x03, 0x7e, 0x0c, 761 0xe0, 0x03, 0x7e, 0x0c,
761 0x01, 0x65, 0x18, 0x31, 762 0x01, 0x65, 0x18, 0x31,
@@ -774,7 +775,7 @@ static uint8_t seqprog[] = {
774 0x01, 0x6c, 0xda, 0x34, 775 0x01, 0x6c, 0xda, 0x34,
775 0x3d, 0x64, 0xa4, 0x28, 776 0x3d, 0x64, 0xa4, 0x28,
776 0x55, 0x64, 0xc8, 0x28, 777 0x55, 0x64, 0xc8, 0x28,
777 0x00, 0x65, 0x06, 0x46, 778 0x00, 0x65, 0x08, 0x46,
778 0x2e, 0x64, 0xa4, 0x28, 779 0x2e, 0x64, 0xa4, 0x28,
779 0x66, 0x64, 0xc8, 0x28, 780 0x66, 0x64, 0xc8, 0x28,
780 0x00, 0x6c, 0xda, 0x18, 781 0x00, 0x6c, 0xda, 0x18,
@@ -785,63 +786,63 @@ static uint8_t seqprog[] = {
785 0x00, 0x6c, 0xda, 0x24, 786 0x00, 0x6c, 0xda, 0x24,
786 0x01, 0x65, 0xc8, 0x30, 787 0x01, 0x65, 0xc8, 0x30,
787 0xe0, 0x6a, 0xcc, 0x00, 788 0xe0, 0x6a, 0xcc, 0x00,
788 0x44, 0x6a, 0x02, 0x5e, 789 0x44, 0x6a, 0x04, 0x5e,
789 0x01, 0x90, 0xe2, 0x31, 790 0x01, 0x90, 0xe2, 0x31,
790 0x04, 0x3b, 0x26, 0x7e, 791 0x04, 0x3b, 0x28, 0x7e,
791 0x30, 0x6a, 0xd0, 0x01, 792 0x30, 0x6a, 0xd0, 0x01,
792 0x20, 0x6a, 0xd0, 0x01, 793 0x20, 0x6a, 0xd0, 0x01,
793 0x1d, 0x6a, 0xdc, 0x01, 794 0x1d, 0x6a, 0xdc, 0x01,
794 0xdc, 0xee, 0x22, 0x66, 795 0xdc, 0xee, 0x24, 0x66,
795 0x00, 0x65, 0x3e, 0x46, 796 0x00, 0x65, 0x40, 0x46,
796 0x20, 0x6a, 0xd0, 0x01, 797 0x20, 0x6a, 0xd0, 0x01,
797 0x01, 0x6a, 0xdc, 0x01, 798 0x01, 0x6a, 0xdc, 0x01,
798 0x20, 0xa0, 0xd8, 0x31, 799 0x20, 0xa0, 0xd8, 0x31,
799 0x09, 0xee, 0xdc, 0x01, 800 0x09, 0xee, 0xdc, 0x01,
800 0x80, 0xee, 0x2e, 0x7e, 801 0x80, 0xee, 0x30, 0x7e,
801 0x11, 0x6a, 0xdc, 0x01, 802 0x11, 0x6a, 0xdc, 0x01,
802 0x50, 0xee, 0x32, 0x66, 803 0x50, 0xee, 0x34, 0x66,
803 0x20, 0x6a, 0xd0, 0x01, 804 0x20, 0x6a, 0xd0, 0x01,
804 0x09, 0x6a, 0xdc, 0x01, 805 0x09, 0x6a, 0xdc, 0x01,
805 0x88, 0xee, 0x38, 0x66, 806 0x88, 0xee, 0x3a, 0x66,
806 0x19, 0x6a, 0xdc, 0x01, 807 0x19, 0x6a, 0xdc, 0x01,
807 0xd8, 0xee, 0x3c, 0x66, 808 0xd8, 0xee, 0x3e, 0x66,
808 0xff, 0x6a, 0xdc, 0x09, 809 0xff, 0x6a, 0xdc, 0x09,
809 0x18, 0xee, 0x40, 0x6e, 810 0x18, 0xee, 0x42, 0x6e,
810 0xff, 0x6a, 0xd4, 0x0c, 811 0xff, 0x6a, 0xd4, 0x0c,
811 0x88, 0x6a, 0xcc, 0x00, 812 0x88, 0x6a, 0xcc, 0x00,
812 0x44, 0x6a, 0x02, 0x5e, 813 0x44, 0x6a, 0x04, 0x5e,
813 0x20, 0x6a, 0xe0, 0x5d, 814 0x20, 0x6a, 0xe2, 0x5d,
814 0x01, 0x3b, 0x26, 0x31, 815 0x01, 0x3b, 0x26, 0x31,
815 0x04, 0x3b, 0x5a, 0x6e, 816 0x04, 0x3b, 0x5c, 0x6e,
816 0xa0, 0x6a, 0xca, 0x00, 817 0xa0, 0x6a, 0xca, 0x00,
817 0x20, 0x65, 0xc8, 0x18, 818 0x20, 0x65, 0xc8, 0x18,
818 0x00, 0x65, 0x98, 0x5e, 819 0x00, 0x65, 0x9a, 0x5e,
819 0x00, 0x65, 0x52, 0x66, 820 0x00, 0x65, 0x54, 0x66,
820 0x0a, 0x93, 0x26, 0x01, 821 0x0a, 0x93, 0x26, 0x01,
821 0x00, 0x65, 0xa8, 0x46, 822 0x00, 0x65, 0xaa, 0x46,
822 0xa0, 0x6a, 0xcc, 0x00, 823 0xa0, 0x6a, 0xcc, 0x00,
823 0xff, 0x6a, 0xc8, 0x08, 824 0xff, 0x6a, 0xc8, 0x08,
824 0x20, 0x94, 0x5e, 0x6e, 825 0x20, 0x94, 0x60, 0x6e,
825 0x10, 0x94, 0x60, 0x6e, 826 0x10, 0x94, 0x62, 0x6e,
826 0x08, 0x94, 0x7a, 0x6e, 827 0x08, 0x94, 0x7c, 0x6e,
827 0x08, 0x94, 0x7a, 0x6e, 828 0x08, 0x94, 0x7c, 0x6e,
828 0x08, 0x94, 0x7a, 0x6e, 829 0x08, 0x94, 0x7c, 0x6e,
829 0xff, 0x8c, 0xc8, 0x10, 830 0xff, 0x8c, 0xc8, 0x10,
830 0xc1, 0x64, 0xc8, 0x18, 831 0xc1, 0x64, 0xc8, 0x18,
831 0xf8, 0x64, 0xc8, 0x08, 832 0xf8, 0x64, 0xc8, 0x08,
832 0x01, 0x99, 0xda, 0x30, 833 0x01, 0x99, 0xda, 0x30,
833 0x00, 0x66, 0x6e, 0x66, 834 0x00, 0x66, 0x70, 0x66,
834 0xc0, 0x66, 0xaa, 0x76, 835 0xc0, 0x66, 0xac, 0x76,
835 0x60, 0x66, 0xc8, 0x18, 836 0x60, 0x66, 0xc8, 0x18,
836 0x3d, 0x64, 0xc8, 0x28, 837 0x3d, 0x64, 0xc8, 0x28,
837 0x00, 0x65, 0x5e, 0x46, 838 0x00, 0x65, 0x60, 0x46,
838 0xf7, 0x93, 0x26, 0x09, 839 0xf7, 0x93, 0x26, 0x09,
839 0x08, 0x93, 0x7c, 0x6e, 840 0x08, 0x93, 0x7e, 0x6e,
840 0x00, 0x62, 0xc4, 0x18, 841 0x00, 0x62, 0xc4, 0x18,
841 0x00, 0x65, 0xa8, 0x5e, 842 0x00, 0x65, 0xaa, 0x5e,
842 0x00, 0x65, 0x88, 0x5e, 843 0x00, 0x65, 0x8a, 0x5e,
843 0x00, 0x65, 0x88, 0x5e, 844 0x00, 0x65, 0x8a, 0x5e,
844 0x00, 0x65, 0x88, 0x5e, 845 0x00, 0x65, 0x8a, 0x5e,
845 0x01, 0x99, 0xda, 0x30, 846 0x01, 0x99, 0xda, 0x30,
846 0x01, 0x99, 0xda, 0x30, 847 0x01, 0x99, 0xda, 0x30,
847 0x01, 0x99, 0xda, 0x30, 848 0x01, 0x99, 0xda, 0x30,
@@ -858,11 +859,11 @@ static uint8_t seqprog[] = {
858 0x01, 0x6c, 0x32, 0x31, 859 0x01, 0x6c, 0x32, 0x31,
859 0x01, 0x6c, 0x32, 0x31, 860 0x01, 0x6c, 0x32, 0x31,
860 0x01, 0x6c, 0x32, 0x35, 861 0x01, 0x6c, 0x32, 0x35,
861 0x08, 0x94, 0xa8, 0x7e, 862 0x08, 0x94, 0xaa, 0x7e,
862 0xf7, 0x93, 0x26, 0x09, 863 0xf7, 0x93, 0x26, 0x09,
863 0x08, 0x93, 0xac, 0x6e, 864 0x08, 0x93, 0xae, 0x6e,
864 0xff, 0x6a, 0xd4, 0x0c, 865 0xff, 0x6a, 0xd4, 0x0c,
865 0x04, 0xb8, 0xd4, 0x6e, 866 0x04, 0xb8, 0xd6, 0x6e,
866 0x01, 0x42, 0x7e, 0x31, 867 0x01, 0x42, 0x7e, 0x31,
867 0xff, 0x6a, 0x76, 0x01, 868 0xff, 0x6a, 0x76, 0x01,
868 0x01, 0x90, 0x84, 0x34, 869 0x01, 0x90, 0x84, 0x34,
@@ -870,14 +871,14 @@ static uint8_t seqprog[] = {
870 0x01, 0x85, 0x0a, 0x01, 871 0x01, 0x85, 0x0a, 0x01,
871 0x7f, 0x65, 0x10, 0x09, 872 0x7f, 0x65, 0x10, 0x09,
872 0xfe, 0x85, 0x0a, 0x0d, 873 0xfe, 0x85, 0x0a, 0x0d,
873 0xff, 0x42, 0xd0, 0x66, 874 0xff, 0x42, 0xd2, 0x66,
874 0xff, 0x41, 0xc8, 0x66, 875 0xff, 0x41, 0xca, 0x66,
875 0xd1, 0x6a, 0xd8, 0x5e, 876 0xd1, 0x6a, 0xda, 0x5e,
876 0xff, 0x6a, 0xca, 0x04, 877 0xff, 0x6a, 0xca, 0x04,
877 0x01, 0x41, 0x20, 0x31, 878 0x01, 0x41, 0x20, 0x31,
878 0x01, 0xbf, 0x82, 0x30, 879 0x01, 0xbf, 0x82, 0x30,
879 0x01, 0x6a, 0x76, 0x00, 880 0x01, 0x6a, 0x76, 0x00,
880 0x00, 0xbb, 0x12, 0x46, 881 0x00, 0xbb, 0x14, 0x46,
881 0x01, 0x42, 0x20, 0x31, 882 0x01, 0x42, 0x20, 0x31,
882 0x01, 0xbf, 0x84, 0x34, 883 0x01, 0xbf, 0x84, 0x34,
883 0x01, 0x41, 0x7e, 0x31, 884 0x01, 0x41, 0x7e, 0x31,
@@ -941,7 +942,7 @@ static ahc_patch_func_t ahc_patch17_func;
941static int 942static int
942ahc_patch17_func(struct ahc_softc *ahc) 943ahc_patch17_func(struct ahc_softc *ahc)
943{ 944{
944 return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0); 945 return ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0);
945} 946}
946 947
947static ahc_patch_func_t ahc_patch16_func; 948static ahc_patch_func_t ahc_patch16_func;
@@ -1142,152 +1143,152 @@ static struct patch {
1142 { ahc_patch0_func, 196, 1, 1 }, 1143 { ahc_patch0_func, 196, 1, 1 },
1143 { ahc_patch9_func, 212, 6, 2 }, 1144 { ahc_patch9_func, 212, 6, 2 },
1144 { ahc_patch0_func, 218, 6, 1 }, 1145 { ahc_patch0_func, 218, 6, 1 },
1145 { ahc_patch8_func, 226, 20, 2 }, 1146 { ahc_patch8_func, 226, 21, 2 },
1146 { ahc_patch1_func, 241, 1, 1 }, 1147 { ahc_patch1_func, 241, 1, 1 },
1147 { ahc_patch1_func, 248, 1, 2 }, 1148 { ahc_patch1_func, 249, 1, 2 },
1148 { ahc_patch0_func, 249, 2, 2 }, 1149 { ahc_patch0_func, 250, 2, 2 },
1149 { ahc_patch11_func, 250, 1, 1 }, 1150 { ahc_patch11_func, 251, 1, 1 },
1150 { ahc_patch9_func, 258, 27, 3 }, 1151 { ahc_patch9_func, 259, 27, 3 },
1151 { ahc_patch1_func, 274, 10, 2 }, 1152 { ahc_patch1_func, 275, 10, 2 },
1152 { ahc_patch13_func, 277, 1, 1 }, 1153 { ahc_patch13_func, 278, 1, 1 },
1153 { ahc_patch14_func, 285, 14, 1 }, 1154 { ahc_patch14_func, 286, 14, 1 },
1154 { ahc_patch1_func, 301, 1, 2 }, 1155 { ahc_patch1_func, 302, 1, 2 },
1155 { ahc_patch0_func, 302, 1, 1 }, 1156 { ahc_patch0_func, 303, 1, 1 },
1156 { ahc_patch9_func, 305, 1, 1 }, 1157 { ahc_patch9_func, 306, 1, 1 },
1157 { ahc_patch13_func, 310, 1, 1 }, 1158 { ahc_patch13_func, 311, 1, 1 },
1158 { ahc_patch9_func, 311, 2, 2 }, 1159 { ahc_patch9_func, 312, 2, 2 },
1159 { ahc_patch0_func, 313, 4, 1 }, 1160 { ahc_patch0_func, 314, 4, 1 },
1160 { ahc_patch14_func, 317, 1, 1 }, 1161 { ahc_patch14_func, 318, 1, 1 },
1161 { ahc_patch15_func, 319, 2, 3 }, 1162 { ahc_patch15_func, 320, 2, 3 },
1162 { ahc_patch9_func, 319, 1, 2 }, 1163 { ahc_patch9_func, 320, 1, 2 },
1163 { ahc_patch0_func, 320, 1, 1 }, 1164 { ahc_patch0_func, 321, 1, 1 },
1164 { ahc_patch6_func, 325, 1, 2 }, 1165 { ahc_patch6_func, 326, 1, 2 },
1165 { ahc_patch0_func, 326, 1, 1 }, 1166 { ahc_patch0_func, 327, 1, 1 },
1166 { ahc_patch1_func, 330, 47, 11 }, 1167 { ahc_patch1_func, 331, 47, 11 },
1167 { ahc_patch6_func, 337, 2, 4 }, 1168 { ahc_patch6_func, 338, 2, 4 },
1168 { ahc_patch7_func, 337, 1, 1 }, 1169 { ahc_patch7_func, 338, 1, 1 },
1169 { ahc_patch8_func, 338, 1, 1 }, 1170 { ahc_patch8_func, 339, 1, 1 },
1170 { ahc_patch0_func, 339, 1, 1 }, 1171 { ahc_patch0_func, 340, 1, 1 },
1171 { ahc_patch16_func, 340, 1, 1 }, 1172 { ahc_patch16_func, 341, 1, 1 },
1172 { ahc_patch6_func, 356, 6, 3 }, 1173 { ahc_patch6_func, 357, 6, 3 },
1173 { ahc_patch16_func, 356, 5, 1 }, 1174 { ahc_patch16_func, 357, 5, 1 },
1174 { ahc_patch0_func, 362, 7, 1 }, 1175 { ahc_patch0_func, 363, 7, 1 },
1175 { ahc_patch13_func, 372, 5, 1 }, 1176 { ahc_patch13_func, 373, 5, 1 },
1176 { ahc_patch0_func, 377, 52, 17 }, 1177 { ahc_patch0_func, 378, 52, 17 },
1177 { ahc_patch14_func, 377, 1, 1 }, 1178 { ahc_patch14_func, 378, 1, 1 },
1178 { ahc_patch7_func, 379, 2, 2 }, 1179 { ahc_patch7_func, 380, 2, 2 },
1179 { ahc_patch17_func, 380, 1, 1 }, 1180 { ahc_patch17_func, 381, 1, 1 },
1180 { ahc_patch9_func, 383, 1, 1 }, 1181 { ahc_patch9_func, 384, 1, 1 },
1181 { ahc_patch18_func, 390, 1, 1 }, 1182 { ahc_patch18_func, 391, 1, 1 },
1182 { ahc_patch14_func, 395, 9, 3 }, 1183 { ahc_patch14_func, 396, 9, 3 },
1183 { ahc_patch9_func, 396, 3, 2 }, 1184 { ahc_patch9_func, 397, 3, 2 },
1184 { ahc_patch0_func, 399, 3, 1 }, 1185 { ahc_patch0_func, 400, 3, 1 },
1185 { ahc_patch9_func, 407, 6, 2 }, 1186 { ahc_patch9_func, 408, 6, 2 },
1186 { ahc_patch0_func, 413, 9, 2 }, 1187 { ahc_patch0_func, 414, 9, 2 },
1187 { ahc_patch13_func, 413, 1, 1 }, 1188 { ahc_patch13_func, 414, 1, 1 },
1188 { ahc_patch13_func, 422, 2, 1 }, 1189 { ahc_patch13_func, 423, 2, 1 },
1189 { ahc_patch14_func, 424, 1, 1 }, 1190 { ahc_patch14_func, 425, 1, 1 },
1190 { ahc_patch9_func, 426, 1, 2 }, 1191 { ahc_patch9_func, 427, 1, 2 },
1191 { ahc_patch0_func, 427, 1, 1 }, 1192 { ahc_patch0_func, 428, 1, 1 },
1192 { ahc_patch7_func, 428, 1, 1 },
1193 { ahc_patch7_func, 429, 1, 1 }, 1193 { ahc_patch7_func, 429, 1, 1 },
1194 { ahc_patch8_func, 430, 3, 3 }, 1194 { ahc_patch7_func, 430, 1, 1 },
1195 { ahc_patch6_func, 431, 1, 2 }, 1195 { ahc_patch8_func, 431, 3, 3 },
1196 { ahc_patch0_func, 432, 1, 1 }, 1196 { ahc_patch6_func, 432, 1, 2 },
1197 { ahc_patch9_func, 433, 1, 1 }, 1197 { ahc_patch0_func, 433, 1, 1 },
1198 { ahc_patch15_func, 434, 1, 2 }, 1198 { ahc_patch9_func, 434, 1, 1 },
1199 { ahc_patch13_func, 434, 1, 1 }, 1199 { ahc_patch15_func, 435, 1, 2 },
1200 { ahc_patch14_func, 436, 9, 4 }, 1200 { ahc_patch13_func, 435, 1, 1 },
1201 { ahc_patch9_func, 436, 1, 1 }, 1201 { ahc_patch14_func, 437, 9, 4 },
1202 { ahc_patch9_func, 443, 2, 1 }, 1202 { ahc_patch9_func, 437, 1, 1 },
1203 { ahc_patch0_func, 445, 4, 3 }, 1203 { ahc_patch9_func, 444, 2, 1 },
1204 { ahc_patch9_func, 445, 1, 2 }, 1204 { ahc_patch0_func, 446, 4, 3 },
1205 { ahc_patch0_func, 446, 3, 1 }, 1205 { ahc_patch9_func, 446, 1, 2 },
1206 { ahc_patch1_func, 450, 2, 1 }, 1206 { ahc_patch0_func, 447, 3, 1 },
1207 { ahc_patch7_func, 452, 10, 2 }, 1207 { ahc_patch1_func, 451, 2, 1 },
1208 { ahc_patch0_func, 462, 1, 1 }, 1208 { ahc_patch7_func, 453, 10, 2 },
1209 { ahc_patch8_func, 463, 118, 22 }, 1209 { ahc_patch0_func, 463, 1, 1 },
1210 { ahc_patch1_func, 465, 3, 2 }, 1210 { ahc_patch8_func, 464, 118, 22 },
1211 { ahc_patch0_func, 468, 5, 3 }, 1211 { ahc_patch1_func, 466, 3, 2 },
1212 { ahc_patch9_func, 468, 2, 2 }, 1212 { ahc_patch0_func, 469, 5, 3 },
1213 { ahc_patch0_func, 470, 3, 1 }, 1213 { ahc_patch9_func, 469, 2, 2 },
1214 { ahc_patch1_func, 475, 2, 2 }, 1214 { ahc_patch0_func, 471, 3, 1 },
1215 { ahc_patch0_func, 477, 6, 3 }, 1215 { ahc_patch1_func, 476, 2, 2 },
1216 { ahc_patch9_func, 477, 2, 2 }, 1216 { ahc_patch0_func, 478, 6, 3 },
1217 { ahc_patch0_func, 479, 3, 1 }, 1217 { ahc_patch9_func, 478, 2, 2 },
1218 { ahc_patch1_func, 485, 2, 2 }, 1218 { ahc_patch0_func, 480, 3, 1 },
1219 { ahc_patch0_func, 487, 9, 7 }, 1219 { ahc_patch1_func, 486, 2, 2 },
1220 { ahc_patch9_func, 487, 5, 6 }, 1220 { ahc_patch0_func, 488, 9, 7 },
1221 { ahc_patch19_func, 487, 1, 2 }, 1221 { ahc_patch9_func, 488, 5, 6 },
1222 { ahc_patch0_func, 488, 1, 1 }, 1222 { ahc_patch19_func, 488, 1, 2 },
1223 { ahc_patch19_func, 490, 1, 2 }, 1223 { ahc_patch0_func, 489, 1, 1 },
1224 { ahc_patch0_func, 491, 1, 1 }, 1224 { ahc_patch19_func, 491, 1, 2 },
1225 { ahc_patch0_func, 492, 4, 1 }, 1225 { ahc_patch0_func, 492, 1, 1 },
1226 { ahc_patch6_func, 497, 3, 2 }, 1226 { ahc_patch0_func, 493, 4, 1 },
1227 { ahc_patch0_func, 500, 1, 1 }, 1227 { ahc_patch6_func, 498, 3, 2 },
1228 { ahc_patch6_func, 510, 1, 2 }, 1228 { ahc_patch0_func, 501, 1, 1 },
1229 { ahc_patch0_func, 511, 1, 1 }, 1229 { ahc_patch6_func, 511, 1, 2 },
1230 { ahc_patch20_func, 548, 7, 1 }, 1230 { ahc_patch0_func, 512, 1, 1 },
1231 { ahc_patch3_func, 583, 1, 2 }, 1231 { ahc_patch20_func, 549, 7, 1 },
1232 { ahc_patch0_func, 584, 1, 1 }, 1232 { ahc_patch3_func, 584, 1, 2 },
1233 { ahc_patch21_func, 587, 1, 1 }, 1233 { ahc_patch0_func, 585, 1, 1 },
1234 { ahc_patch8_func, 589, 106, 33 }, 1234 { ahc_patch21_func, 588, 1, 1 },
1235 { ahc_patch4_func, 591, 1, 1 }, 1235 { ahc_patch8_func, 590, 106, 33 },
1236 { ahc_patch1_func, 597, 2, 2 }, 1236 { ahc_patch4_func, 592, 1, 1 },
1237 { ahc_patch0_func, 599, 1, 1 }, 1237 { ahc_patch1_func, 598, 2, 2 },
1238 { ahc_patch1_func, 602, 1, 2 }, 1238 { ahc_patch0_func, 600, 1, 1 },
1239 { ahc_patch0_func, 603, 1, 1 }, 1239 { ahc_patch1_func, 603, 1, 2 },
1240 { ahc_patch9_func, 604, 3, 3 }, 1240 { ahc_patch0_func, 604, 1, 1 },
1241 { ahc_patch15_func, 605, 1, 1 }, 1241 { ahc_patch9_func, 605, 3, 3 },
1242 { ahc_patch0_func, 607, 4, 1 }, 1242 { ahc_patch15_func, 606, 1, 1 },
1243 { ahc_patch19_func, 616, 2, 2 }, 1243 { ahc_patch0_func, 608, 4, 1 },
1244 { ahc_patch0_func, 618, 1, 1 }, 1244 { ahc_patch19_func, 617, 2, 2 },
1245 { ahc_patch19_func, 622, 10, 3 }, 1245 { ahc_patch0_func, 619, 1, 1 },
1246 { ahc_patch5_func, 624, 8, 1 }, 1246 { ahc_patch19_func, 623, 10, 3 },
1247 { ahc_patch0_func, 632, 9, 2 }, 1247 { ahc_patch5_func, 625, 8, 1 },
1248 { ahc_patch5_func, 633, 8, 1 }, 1248 { ahc_patch0_func, 633, 9, 2 },
1249 { ahc_patch4_func, 643, 1, 2 }, 1249 { ahc_patch5_func, 634, 8, 1 },
1250 { ahc_patch0_func, 644, 1, 1 }, 1250 { ahc_patch4_func, 644, 1, 2 },
1251 { ahc_patch19_func, 645, 1, 2 }, 1251 { ahc_patch0_func, 645, 1, 1 },
1252 { ahc_patch0_func, 646, 3, 2 }, 1252 { ahc_patch19_func, 646, 1, 2 },
1253 { ahc_patch4_func, 648, 1, 1 }, 1253 { ahc_patch0_func, 647, 3, 2 },
1254 { ahc_patch5_func, 649, 1, 1 }, 1254 { ahc_patch4_func, 649, 1, 1 },
1255 { ahc_patch5_func, 652, 1, 1 }, 1255 { ahc_patch5_func, 650, 1, 1 },
1256 { ahc_patch5_func, 654, 1, 1 }, 1256 { ahc_patch5_func, 653, 1, 1 },
1257 { ahc_patch4_func, 656, 2, 2 }, 1257 { ahc_patch5_func, 655, 1, 1 },
1258 { ahc_patch0_func, 658, 2, 1 }, 1258 { ahc_patch4_func, 657, 2, 2 },
1259 { ahc_patch5_func, 660, 1, 1 }, 1259 { ahc_patch0_func, 659, 2, 1 },
1260 { ahc_patch5_func, 663, 1, 1 }, 1260 { ahc_patch5_func, 661, 1, 1 },
1261 { ahc_patch5_func, 666, 1, 1 }, 1261 { ahc_patch5_func, 664, 1, 1 },
1262 { ahc_patch19_func, 670, 1, 1 }, 1262 { ahc_patch5_func, 667, 1, 1 },
1263 { ahc_patch19_func, 673, 1, 1 }, 1263 { ahc_patch19_func, 671, 1, 1 },
1264 { ahc_patch4_func, 679, 1, 1 }, 1264 { ahc_patch19_func, 674, 1, 1 },
1265 { ahc_patch6_func, 682, 1, 2 }, 1265 { ahc_patch4_func, 680, 1, 1 },
1266 { ahc_patch0_func, 683, 1, 1 }, 1266 { ahc_patch6_func, 683, 1, 2 },
1267 { ahc_patch7_func, 695, 16, 1 }, 1267 { ahc_patch0_func, 684, 1, 1 },
1268 { ahc_patch4_func, 711, 20, 1 }, 1268 { ahc_patch7_func, 696, 16, 1 },
1269 { ahc_patch9_func, 732, 4, 2 }, 1269 { ahc_patch4_func, 712, 20, 1 },
1270 { ahc_patch0_func, 736, 4, 1 }, 1270 { ahc_patch9_func, 733, 4, 2 },
1271 { ahc_patch9_func, 740, 4, 2 }, 1271 { ahc_patch0_func, 737, 4, 1 },
1272 { ahc_patch0_func, 744, 3, 1 }, 1272 { ahc_patch9_func, 741, 4, 2 },
1273 { ahc_patch6_func, 750, 1, 1 }, 1273 { ahc_patch0_func, 745, 3, 1 },
1274 { ahc_patch22_func, 752, 14, 1 }, 1274 { ahc_patch6_func, 751, 1, 1 },
1275 { ahc_patch7_func, 766, 3, 1 }, 1275 { ahc_patch22_func, 753, 14, 1 },
1276 { ahc_patch9_func, 778, 24, 8 }, 1276 { ahc_patch7_func, 767, 3, 1 },
1277 { ahc_patch19_func, 782, 1, 2 }, 1277 { ahc_patch9_func, 779, 24, 8 },
1278 { ahc_patch0_func, 783, 1, 1 }, 1278 { ahc_patch19_func, 783, 1, 2 },
1279 { ahc_patch15_func, 788, 4, 2 }, 1279 { ahc_patch0_func, 784, 1, 1 },
1280 { ahc_patch0_func, 792, 7, 3 }, 1280 { ahc_patch15_func, 789, 4, 2 },
1281 { ahc_patch23_func, 792, 5, 2 }, 1281 { ahc_patch0_func, 793, 7, 3 },
1282 { ahc_patch0_func, 797, 2, 1 }, 1282 { ahc_patch23_func, 793, 5, 2 },
1283 { ahc_patch0_func, 802, 42, 3 }, 1283 { ahc_patch0_func, 798, 2, 1 },
1284 { ahc_patch18_func, 814, 18, 2 }, 1284 { ahc_patch0_func, 803, 42, 3 },
1285 { ahc_patch0_func, 832, 1, 1 }, 1285 { ahc_patch18_func, 815, 18, 2 },
1286 { ahc_patch4_func, 856, 1, 1 }, 1286 { ahc_patch0_func, 833, 1, 1 },
1287 { ahc_patch4_func, 857, 3, 2 }, 1287 { ahc_patch4_func, 857, 1, 1 },
1288 { ahc_patch0_func, 860, 1, 1 }, 1288 { ahc_patch4_func, 858, 3, 2 },
1289 { ahc_patch13_func, 861, 3, 1 }, 1289 { ahc_patch0_func, 861, 1, 1 },
1290 { ahc_patch4_func, 864, 12, 1 } 1290 { ahc_patch13_func, 862, 3, 1 },
1291 { ahc_patch4_func, 865, 12, 1 }
1291}; 1292};
1292 1293
1293static struct cs { 1294static struct cs {
@@ -1296,11 +1297,11 @@ static struct cs {
1296} critical_sections[] = { 1297} critical_sections[] = {
1297 { 11, 18 }, 1298 { 11, 18 },
1298 { 21, 30 }, 1299 { 21, 30 },
1299 { 711, 727 }, 1300 { 712, 728 },
1300 { 857, 860 }, 1301 { 858, 861 },
1301 { 864, 870 }, 1302 { 865, 871 },
1302 { 872, 874 }, 1303 { 873, 875 },
1303 { 874, 876 } 1304 { 875, 877 }
1304}; 1305};
1305 1306
1306static const int num_critical_sections = sizeof(critical_sections) 1307static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c
index 7c5a6db0e672..4d44a9211185 100644
--- a/drivers/scsi/aic7xxx/aiclib.c
+++ b/drivers/scsi/aic7xxx/aiclib.c
@@ -30,1162 +30,8 @@
30 * $Id$ 30 * $Id$
31 */ 31 */
32 32
33#include <linux/blkdev.h>
34#include <linux/delay.h>
35#include <linux/version.h>
36
37/* Core SCSI definitions */
38#include <scsi/scsi_host.h>
39#include "aiclib.h" 33#include "aiclib.h"
40#include "cam.h"
41
42#ifndef FALSE
43#define FALSE 0
44#endif /* FALSE */
45#ifndef TRUE
46#define TRUE 1
47#endif /* TRUE */
48#ifndef ERESTART
49#define ERESTART -1 /* restart syscall */
50#endif
51#ifndef EJUSTRETURN
52#define EJUSTRETURN -2 /* don't modify regs, just return */
53#endif
54
55static int ascentrycomp(const void *key, const void *member);
56static int senseentrycomp(const void *key, const void *member);
57static void fetchtableentries(int sense_key, int asc, int ascq,
58 struct scsi_inquiry_data *,
59 const struct sense_key_table_entry **,
60 const struct asc_table_entry **);
61static void * scsibsearch(const void *key, const void *base, size_t nmemb,
62 size_t size,
63 int (*compar)(const void *, const void *));
64typedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
65static int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern,
66 int str_len);
67static caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table,
68 int num_entries, int entry_size,
69 cam_quirkmatch_t *comp_func);
70
71#define SCSI_NO_SENSE_STRINGS 1
72#if !defined(SCSI_NO_SENSE_STRINGS)
73#define SST(asc, ascq, action, desc) \
74 asc, ascq, action, desc
75#else
76static const char empty_string[] = "";
77
78#define SST(asc, ascq, action, desc) \
79 asc, ascq, action, empty_string
80#endif
81
82static const struct sense_key_table_entry sense_key_table[] =
83{
84 { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" },
85 { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" },
86 {
87 SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
88 "NOT READY"
89 },
90 { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" },
91 { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" },
92 { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" },
93 { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" },
94 { SSD_KEY_DATA_PROTECT, SS_FATAL|EACCES, "DATA PROTECT" },
95 { SSD_KEY_BLANK_CHECK, SS_FATAL|ENOSPC, "BLANK CHECK" },
96 { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" },
97 { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" },
98 { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" },
99 { SSD_KEY_EQUAL, SS_NOP, "EQUAL" },
100 { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" },
101 { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" },
102 { SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" }
103};
104
105static const int sense_key_table_size =
106 sizeof(sense_key_table)/sizeof(sense_key_table[0]);
107
108static struct asc_table_entry quantum_fireball_entries[] = {
109 {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
110 "Logical unit not ready, initializing cmd. required")}
111};
112
113static struct asc_table_entry sony_mo_entries[] = {
114 {SST(0x04, 0x00, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
115 "Logical unit not ready, cause not reportable")}
116};
117
118static struct scsi_sense_quirk_entry sense_quirk_table[] = {
119 {
120 /*
121 * The Quantum Fireball ST and SE like to return 0x04 0x0b when
122 * they really should return 0x04 0x02. 0x04,0x0b isn't
123 * defined in any SCSI spec, and it isn't mentioned in the
124 * hardware manual for these drives.
125 */
126 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
127 /*num_sense_keys*/0,
128 sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry),
129 /*sense key entries*/NULL,
130 quantum_fireball_entries
131 },
132 {
133 /*
134 * This Sony MO drive likes to return 0x04, 0x00 when it
135 * isn't spun up.
136 */
137 {T_DIRECT, SIP_MEDIA_REMOVABLE, "SONY", "SMO-*", "*"},
138 /*num_sense_keys*/0,
139 sizeof(sony_mo_entries)/sizeof(struct asc_table_entry),
140 /*sense key entries*/NULL,
141 sony_mo_entries
142 }
143};
144
145static const int sense_quirk_table_size =
146 sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]);
147
148static struct asc_table_entry asc_table[] = {
149/*
150 * From File: ASC-NUM.TXT
151 * SCSI ASC/ASCQ Assignments
152 * Numeric Sorted Listing
153 * as of 5/12/97
154 *
155 * D - DIRECT ACCESS DEVICE (SBC) device column key
156 * .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
157 * . L - PRINTER DEVICE (SSC) blank = reserved
158 * . P - PROCESSOR DEVICE (SPC) not blank = allowed
159 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)
160 * . . R - CD DEVICE (MMC)
161 * . . S - SCANNER DEVICE (SGC)
162 * . . .O - OPTICAL MEMORY DEVICE (SBC)
163 * . . . M - MEDIA CHANGER DEVICE (SMC)
164 * . . . C - COMMUNICATION DEVICE (SSC)
165 * . . . .A - STORAGE ARRAY DEVICE (SCC)
166 * . . . . E - ENCLOSURE SERVICES DEVICE (SES)
167 * DTLPWRSOMCAE ASC ASCQ Action Description
168 * ------------ ---- ---- ------ -----------------------------------*/
169/* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP,
170 "No additional sense information") },
171/* T S */{SST(0x00, 0x01, SS_RDEF,
172 "Filemark detected") },
173/* T S */{SST(0x00, 0x02, SS_RDEF,
174 "End-of-partition/medium detected") },
175/* T */{SST(0x00, 0x03, SS_RDEF,
176 "Setmark detected") },
177/* T S */{SST(0x00, 0x04, SS_RDEF,
178 "Beginning-of-partition/medium detected") },
179/* T S */{SST(0x00, 0x05, SS_RDEF,
180 "End-of-data detected") },
181/* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF,
182 "I/O process terminated") },
183/* R */{SST(0x00, 0x11, SS_FATAL|EBUSY,
184 "Audio play operation in progress") },
185/* R */{SST(0x00, 0x12, SS_NOP,
186 "Audio play operation paused") },
187/* R */{SST(0x00, 0x13, SS_NOP,
188 "Audio play operation successfully completed") },
189/* R */{SST(0x00, 0x14, SS_RDEF,
190 "Audio play operation stopped due to error") },
191/* R */{SST(0x00, 0x15, SS_NOP,
192 "No current audio status to return") },
193/* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY,
194 "Operation in progress") },
195/* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF,
196 "Cleaning requested") },
197/* D W O */{SST(0x01, 0x00, SS_RDEF,
198 "No index/sector signal") },
199/* D WR OM */{SST(0x02, 0x00, SS_RDEF,
200 "No seek complete") },
201/* DTL W SO */{SST(0x03, 0x00, SS_RDEF,
202 "Peripheral device write fault") },
203/* T */{SST(0x03, 0x01, SS_RDEF,
204 "No write current") },
205/* T */{SST(0x03, 0x02, SS_RDEF,
206 "Excessive write errors") },
207/* DTLPWRSOMCAE */{SST(0x04, 0x00,
208 SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
209 "Logical unit not ready, cause not reportable") },
210/* DTLPWRSOMCAE */{SST(0x04, 0x01,
211 SS_TUR|SSQ_DELAY|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
212 "Logical unit is in process of becoming ready") },
213/* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
214 "Logical unit not ready, initializing cmd. required") },
215/* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO,
216 "Logical unit not ready, manual intervention required")},
217/* DTL O */{SST(0x04, 0x04, SS_FATAL|EBUSY,
218 "Logical unit not ready, format in progress") },
219/* DT W OMCA */{SST(0x04, 0x05, SS_FATAL|EBUSY,
220 "Logical unit not ready, rebuild in progress") },
221/* DT W OMCA */{SST(0x04, 0x06, SS_FATAL|EBUSY,
222 "Logical unit not ready, recalculation in progress") },
223/* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY,
224 "Logical unit not ready, operation in progress") },
225/* R */{SST(0x04, 0x08, SS_FATAL|EBUSY,
226 "Logical unit not ready, long write in progress") },
227/* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF,
228 "Logical unit does not respond to selection") },
229/* D WR OM */{SST(0x06, 0x00, SS_RDEF,
230 "No reference position found") },
231/* DTL WRSOM */{SST(0x07, 0x00, SS_RDEF,
232 "Multiple peripheral devices selected") },
233/* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF,
234 "Logical unit communication failure") },
235/* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF,
236 "Logical unit communication time-out") },
237/* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF,
238 "Logical unit communication parity error") },
239/* DT R OM */{SST(0x08, 0x03, SS_RDEF,
240 "Logical unit communication crc error (ultra-dma/32)")},
241/* DT WR O */{SST(0x09, 0x00, SS_RDEF,
242 "Track following error") },
243/* WR O */{SST(0x09, 0x01, SS_RDEF,
244 "Tracking servo failure") },
245/* WR O */{SST(0x09, 0x02, SS_RDEF,
246 "Focus servo failure") },
247/* WR O */{SST(0x09, 0x03, SS_RDEF,
248 "Spindle servo failure") },
249/* DT WR O */{SST(0x09, 0x04, SS_RDEF,
250 "Head select fault") },
251/* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC,
252 "Error log overflow") },
253/* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF,
254 "Warning") },
255/* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF,
256 "Specified temperature exceeded") },
257/* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF,
258 "Enclosure degraded") },
259/* T RS */{SST(0x0C, 0x00, SS_RDEF,
260 "Write error") },
261/* D W O */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
262 "Write error - recovered with auto reallocation") },
263/* D W O */{SST(0x0C, 0x02, SS_RDEF,
264 "Write error - auto reallocation failed") },
265/* D W O */{SST(0x0C, 0x03, SS_RDEF,
266 "Write error - recommend reassignment") },
267/* DT W O */{SST(0x0C, 0x04, SS_RDEF,
268 "Compression check miscompare error") },
269/* DT W O */{SST(0x0C, 0x05, SS_RDEF,
270 "Data expansion occurred during compression") },
271/* DT W O */{SST(0x0C, 0x06, SS_RDEF,
272 "Block not compressible") },
273/* R */{SST(0x0C, 0x07, SS_RDEF,
274 "Write error - recovery needed") },
275/* R */{SST(0x0C, 0x08, SS_RDEF,
276 "Write error - recovery failed") },
277/* R */{SST(0x0C, 0x09, SS_RDEF,
278 "Write error - loss of streaming") },
279/* R */{SST(0x0C, 0x0A, SS_RDEF,
280 "Write error - padding blocks added") },
281/* D W O */{SST(0x10, 0x00, SS_RDEF,
282 "ID CRC or ECC error") },
283/* DT WRSO */{SST(0x11, 0x00, SS_RDEF,
284 "Unrecovered read error") },
285/* DT W SO */{SST(0x11, 0x01, SS_RDEF,
286 "Read retries exhausted") },
287/* DT W SO */{SST(0x11, 0x02, SS_RDEF,
288 "Error too long to correct") },
289/* DT W SO */{SST(0x11, 0x03, SS_RDEF,
290 "Multiple read errors") },
291/* D W O */{SST(0x11, 0x04, SS_RDEF,
292 "Unrecovered read error - auto reallocate failed") },
293/* WR O */{SST(0x11, 0x05, SS_RDEF,
294 "L-EC uncorrectable error") },
295/* WR O */{SST(0x11, 0x06, SS_RDEF,
296 "CIRC unrecovered error") },
297/* W O */{SST(0x11, 0x07, SS_RDEF,
298 "Data re-synchronization error") },
299/* T */{SST(0x11, 0x08, SS_RDEF,
300 "Incomplete block read") },
301/* T */{SST(0x11, 0x09, SS_RDEF,
302 "No gap found") },
303/* DT O */{SST(0x11, 0x0A, SS_RDEF,
304 "Miscorrected error") },
305/* D W O */{SST(0x11, 0x0B, SS_RDEF,
306 "Unrecovered read error - recommend reassignment") },
307/* D W O */{SST(0x11, 0x0C, SS_RDEF,
308 "Unrecovered read error - recommend rewrite the data")},
309/* DT WR O */{SST(0x11, 0x0D, SS_RDEF,
310 "De-compression CRC error") },
311/* DT WR O */{SST(0x11, 0x0E, SS_RDEF,
312 "Cannot decompress using declared algorithm") },
313/* R */{SST(0x11, 0x0F, SS_RDEF,
314 "Error reading UPC/EAN number") },
315/* R */{SST(0x11, 0x10, SS_RDEF,
316 "Error reading ISRC number") },
317/* R */{SST(0x11, 0x11, SS_RDEF,
318 "Read error - loss of streaming") },
319/* D W O */{SST(0x12, 0x00, SS_RDEF,
320 "Address mark not found for id field") },
321/* D W O */{SST(0x13, 0x00, SS_RDEF,
322 "Address mark not found for data field") },
323/* DTL WRSO */{SST(0x14, 0x00, SS_RDEF,
324 "Recorded entity not found") },
325/* DT WR O */{SST(0x14, 0x01, SS_RDEF,
326 "Record not found") },
327/* T */{SST(0x14, 0x02, SS_RDEF,
328 "Filemark or setmark not found") },
329/* T */{SST(0x14, 0x03, SS_RDEF,
330 "End-of-data not found") },
331/* T */{SST(0x14, 0x04, SS_RDEF,
332 "Block sequence error") },
333/* DT W O */{SST(0x14, 0x05, SS_RDEF,
334 "Record not found - recommend reassignment") },
335/* DT W O */{SST(0x14, 0x06, SS_RDEF,
336 "Record not found - data auto-reallocated") },
337/* DTL WRSOM */{SST(0x15, 0x00, SS_RDEF,
338 "Random positioning error") },
339/* DTL WRSOM */{SST(0x15, 0x01, SS_RDEF,
340 "Mechanical positioning error") },
341/* DT WR O */{SST(0x15, 0x02, SS_RDEF,
342 "Positioning error detected by read of medium") },
343/* D W O */{SST(0x16, 0x00, SS_RDEF,
344 "Data synchronization mark error") },
345/* D W O */{SST(0x16, 0x01, SS_RDEF,
346 "Data sync error - data rewritten") },
347/* D W O */{SST(0x16, 0x02, SS_RDEF,
348 "Data sync error - recommend rewrite") },
349/* D W O */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE,
350 "Data sync error - data auto-reallocated") },
351/* D W O */{SST(0x16, 0x04, SS_RDEF,
352 "Data sync error - recommend reassignment") },
353/* DT WRSO */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE,
354 "Recovered data with no error correction applied") },
355/* DT WRSO */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE,
356 "Recovered data with retries") },
357/* DT WR O */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE,
358 "Recovered data with positive head offset") },
359/* DT WR O */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE,
360 "Recovered data with negative head offset") },
361/* WR O */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE,
362 "Recovered data with retries and/or CIRC applied") },
363/* D WR O */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE,
364 "Recovered data using previous sector id") },
365/* D W O */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE,
366 "Recovered data without ECC - data auto-reallocated") },
367/* D W O */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE,
368 "Recovered data without ECC - recommend reassignment")},
369/* D W O */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE,
370 "Recovered data without ECC - recommend rewrite") },
371/* D W O */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE,
372 "Recovered data without ECC - data rewritten") },
373/* D W O */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE,
374 "Recovered data with error correction applied") },
375/* D WR O */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE,
376 "Recovered data with error corr. & retries applied") },
377/* D WR O */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE,
378 "Recovered data - data auto-reallocated") },
379/* R */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE,
380 "Recovered data with CIRC") },
381/* R */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE,
382 "Recovered data with L-EC") },
383/* D WR O */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE,
384 "Recovered data - recommend reassignment") },
385/* D WR O */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE,
386 "Recovered data - recommend rewrite") },
387/* D W O */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE,
388 "Recovered data with ECC - data rewritten") },
389/* D O */{SST(0x19, 0x00, SS_RDEF,
390 "Defect list error") },
391/* D O */{SST(0x19, 0x01, SS_RDEF,
392 "Defect list not available") },
393/* D O */{SST(0x19, 0x02, SS_RDEF,
394 "Defect list error in primary list") },
395/* D O */{SST(0x19, 0x03, SS_RDEF,
396 "Defect list error in grown list") },
397/* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF,
398 "Parameter list length error") },
399/* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF,
400 "Synchronous data transfer error") },
401/* D O */{SST(0x1C, 0x00, SS_RDEF,
402 "Defect list not found") },
403/* D O */{SST(0x1C, 0x01, SS_RDEF,
404 "Primary defect list not found") },
405/* D O */{SST(0x1C, 0x02, SS_RDEF,
406 "Grown defect list not found") },
407/* D W O */{SST(0x1D, 0x00, SS_FATAL,
408 "Miscompare during verify operation" )},
409/* D W O */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE,
410 "Recovered id with ecc correction") },
411/* D O */{SST(0x1F, 0x00, SS_RDEF,
412 "Partial defect list transfer") },
413/* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL,
414 "Invalid command operation code") },
415/* DT WR OM */{SST(0x21, 0x00, SS_FATAL|EINVAL,
416 "Logical block address out of range" )},
417/* DT WR OM */{SST(0x21, 0x01, SS_FATAL|EINVAL,
418 "Invalid element address") },
419/* D */{SST(0x22, 0x00, SS_FATAL|EINVAL,
420 "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
421/* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL,
422 "Invalid field in CDB") },
423/* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO,
424 "Logical unit not supported") },
425/* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL,
426 "Invalid field in parameter list") },
427/* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL,
428 "Parameter not supported") },
429/* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL,
430 "Parameter value invalid") },
431/* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL,
432 "Threshold parameters not supported") },
433/* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL,
434 "Invalid release of active persistent reservation") },
435/* DT W O */{SST(0x27, 0x00, SS_FATAL|EACCES,
436 "Write protected") },
437/* DT W O */{SST(0x27, 0x01, SS_FATAL|EACCES,
438 "Hardware write protected") },
439/* DT W O */{SST(0x27, 0x02, SS_FATAL|EACCES,
440 "Logical unit software write protected") },
441/* T */{SST(0x27, 0x03, SS_FATAL|EACCES,
442 "Associated write protect") },
443/* T */{SST(0x27, 0x04, SS_FATAL|EACCES,
444 "Persistent write protect") },
445/* T */{SST(0x27, 0x05, SS_FATAL|EACCES,
446 "Permanent write protect") },
447/* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_RDEF,
448 "Not ready to ready change, medium may have changed") },
449/* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO,
450 "Import or export element accessed") },
451/*
452 * XXX JGibbs - All of these should use the same errno, but I don't think
453 * ENXIO is the correct choice. Should we borrow from the networking
454 * errnos? ECONNRESET anyone?
455 */
456/* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_RDEF,
457 "Power on, reset, or bus device reset occurred") },
458/* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF,
459 "Power on occurred") },
460/* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF,
461 "Scsi bus reset occurred") },
462/* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF,
463 "Bus device reset function occurred") },
464/* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF,
465 "Device internal reset") },
466/* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF,
467 "Transceiver mode changed to single-ended") },
468/* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF,
469 "Transceiver mode changed to LVD") },
470/* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF,
471 "Parameters changed") },
472/* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF,
473 "Mode parameters changed") },
474/* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF,
475 "Log parameters changed") },
476/* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF,
477 "Reservations preempted") },
478/* DTLPWRSO C */{SST(0x2B, 0x00, SS_RDEF,
479 "Copy cannot execute since host cannot disconnect") },
480/* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF,
481 "Command sequence error") },
482/* S */{SST(0x2C, 0x01, SS_RDEF,
483 "Too many windows specified") },
484/* S */{SST(0x2C, 0x02, SS_RDEF,
485 "Invalid combination of windows specified") },
486/* R */{SST(0x2C, 0x03, SS_RDEF,
487 "Current program area is not empty") },
488/* R */{SST(0x2C, 0x04, SS_RDEF,
489 "Current program area is empty") },
490/* T */{SST(0x2D, 0x00, SS_RDEF,
491 "Overwrite error on update in place") },
492/* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF,
493 "Commands cleared by another initiator") },
494/* DT WR OM */{SST(0x30, 0x00, SS_RDEF,
495 "Incompatible medium installed") },
496/* DT WR O */{SST(0x30, 0x01, SS_RDEF,
497 "Cannot read medium - unknown format") },
498/* DT WR O */{SST(0x30, 0x02, SS_RDEF,
499 "Cannot read medium - incompatible format") },
500/* DT */{SST(0x30, 0x03, SS_RDEF,
501 "Cleaning cartridge installed") },
502/* DT WR O */{SST(0x30, 0x04, SS_RDEF,
503 "Cannot write medium - unknown format") },
504/* DT WR O */{SST(0x30, 0x05, SS_RDEF,
505 "Cannot write medium - incompatible format") },
506/* DT W O */{SST(0x30, 0x06, SS_RDEF,
507 "Cannot format medium - incompatible medium") },
508/* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF,
509 "Cleaning failure") },
510/* R */{SST(0x30, 0x08, SS_RDEF,
511 "Cannot write - application code mismatch") },
512/* R */{SST(0x30, 0x09, SS_RDEF,
513 "Current session not fixated for append") },
514/* DT WR O */{SST(0x31, 0x00, SS_RDEF,
515 "Medium format corrupted") },
516/* D L R O */{SST(0x31, 0x01, SS_RDEF,
517 "Format command failed") },
518/* D W O */{SST(0x32, 0x00, SS_RDEF,
519 "No defect spare location available") },
520/* D W O */{SST(0x32, 0x01, SS_RDEF,
521 "Defect list update failure") },
522/* T */{SST(0x33, 0x00, SS_RDEF,
523 "Tape length error") },
524/* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF,
525 "Enclosure failure") },
526/* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF,
527 "Enclosure services failure") },
528/* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF,
529 "Unsupported enclosure function") },
530/* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF,
531 "Enclosure services unavailable") },
532/* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF,
533 "Enclosure services transfer failure") },
534/* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF,
535 "Enclosure services transfer refused") },
536/* L */{SST(0x36, 0x00, SS_RDEF,
537 "Ribbon, ink, or toner failure") },
538/* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF,
539 "Rounded parameter") },
540/* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF,
541 "Saving parameters not supported") },
542/* DTL WRSOM */{SST(0x3A, 0x00, SS_NOP,
543 "Medium not present") },
544/* DT WR OM */{SST(0x3A, 0x01, SS_NOP,
545 "Medium not present - tray closed") },
546/* DT WR OM */{SST(0x3A, 0x01, SS_NOP,
547 "Medium not present - tray open") },
548/* DT WR OM */{SST(0x3A, 0x03, SS_NOP,
549 "Medium not present - Loadable") },
550/* DT WR OM */{SST(0x3A, 0x04, SS_NOP,
551 "Medium not present - medium auxiliary "
552 "memory accessible") },
553/* DT WR OM */{SST(0x3A, 0xFF, SS_NOP, NULL) },/* Range 0x05->0xFF */
554/* TL */{SST(0x3B, 0x00, SS_RDEF,
555 "Sequential positioning error") },
556/* T */{SST(0x3B, 0x01, SS_RDEF,
557 "Tape position error at beginning-of-medium") },
558/* T */{SST(0x3B, 0x02, SS_RDEF,
559 "Tape position error at end-of-medium") },
560/* L */{SST(0x3B, 0x03, SS_RDEF,
561 "Tape or electronic vertical forms unit not ready") },
562/* L */{SST(0x3B, 0x04, SS_RDEF,
563 "Slew failure") },
564/* L */{SST(0x3B, 0x05, SS_RDEF,
565 "Paper jam") },
566/* L */{SST(0x3B, 0x06, SS_RDEF,
567 "Failed to sense top-of-form") },
568/* L */{SST(0x3B, 0x07, SS_RDEF,
569 "Failed to sense bottom-of-form") },
570/* T */{SST(0x3B, 0x08, SS_RDEF,
571 "Reposition error") },
572/* S */{SST(0x3B, 0x09, SS_RDEF,
573 "Read past end of medium") },
574/* S */{SST(0x3B, 0x0A, SS_RDEF,
575 "Read past beginning of medium") },
576/* S */{SST(0x3B, 0x0B, SS_RDEF,
577 "Position past end of medium") },
578/* T S */{SST(0x3B, 0x0C, SS_RDEF,
579 "Position past beginning of medium") },
580/* DT WR OM */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC,
581 "Medium destination element full") },
582/* DT WR OM */{SST(0x3B, 0x0E, SS_RDEF,
583 "Medium source element empty") },
584/* R */{SST(0x3B, 0x0F, SS_RDEF,
585 "End of medium reached") },
586/* DT WR OM */{SST(0x3B, 0x11, SS_RDEF,
587 "Medium magazine not accessible") },
588/* DT WR OM */{SST(0x3B, 0x12, SS_RDEF,
589 "Medium magazine removed") },
590/* DT WR OM */{SST(0x3B, 0x13, SS_RDEF,
591 "Medium magazine inserted") },
592/* DT WR OM */{SST(0x3B, 0x14, SS_RDEF,
593 "Medium magazine locked") },
594/* DT WR OM */{SST(0x3B, 0x15, SS_RDEF,
595 "Medium magazine unlocked") },
596/* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF,
597 "Invalid bits in identify message") },
598/* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF,
599 "Logical unit has not self-configured yet") },
600/* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF,
601 "Logical unit failure") },
602/* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF,
603 "Timeout on logical unit") },
604/* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF,
605 "Target operating conditions have changed") },
606/* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF,
607 "Microcode has been changed") },
608/* DTLPWRSOMC */{SST(0x3F, 0x02, SS_RDEF,
609 "Changed operating definition") },
610/* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_INQ_REFRESH|SSQ_DECREMENT_COUNT,
611 "Inquiry data has changed") },
612/* DT WR OMCAE */{SST(0x3F, 0x04, SS_RDEF,
613 "Component device attached") },
614/* DT WR OMCAE */{SST(0x3F, 0x05, SS_RDEF,
615 "Device identifier changed") },
616/* DT WR OMCAE */{SST(0x3F, 0x06, SS_RDEF,
617 "Redundancy group created or modified") },
618/* DT WR OMCAE */{SST(0x3F, 0x07, SS_RDEF,
619 "Redundancy group deleted") },
620/* DT WR OMCAE */{SST(0x3F, 0x08, SS_RDEF,
621 "Spare created or modified") },
622/* DT WR OMCAE */{SST(0x3F, 0x09, SS_RDEF,
623 "Spare deleted") },
624/* DT WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF,
625 "Volume set created or modified") },
626/* DT WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF,
627 "Volume set deleted") },
628/* DT WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF,
629 "Volume set deassigned") },
630/* DT WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF,
631 "Volume set reassigned") },
632/* DTLPWRSOMCAE */{SST(0x3F, 0x0E, SS_RDEF,
633 "Reported luns data has changed") },
634/* DTLPWRSOMCAE */{SST(0x3F, 0x0F, SS_RETRY|SSQ_DECREMENT_COUNT
635 | SSQ_DELAY_RANDOM|EBUSY,
636 "Echo buffer overwritten") },
637/* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF, "Medium Loadable") },
638/* DT WR OM B*/{SST(0x3F, 0x0F, SS_RDEF,
639 "Medium auxiliary memory accessible") },
640/* D */{SST(0x40, 0x00, SS_RDEF,
641 "Ram failure") }, /* deprecated - use 40 NN instead */
642/* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF,
643 "Diagnostic failure: ASCQ = Component ID") },
644/* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE,
645 NULL) },/* Range 0x80->0xFF */
646/* D */{SST(0x41, 0x00, SS_RDEF,
647 "Data path failure") }, /* deprecated - use 40 NN instead */
648/* D */{SST(0x42, 0x00, SS_RDEF,
649 "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
650/* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF,
651 "Message error") },
652/* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF,
653 "Internal target failure") },
654/* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF,
655 "Select or reselect failure") },
656/* DTLPWRSOMC */{SST(0x46, 0x00, SS_RDEF,
657 "Unsuccessful soft reset") },
658/* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF|SSQ_FALLBACK,
659 "SCSI parity error") },
660/* DTLPWRSOMCAE */{SST(0x47, 0x01, SS_RDEF|SSQ_FALLBACK,
661 "Data Phase CRC error detected") },
662/* DTLPWRSOMCAE */{SST(0x47, 0x02, SS_RDEF|SSQ_FALLBACK,
663 "SCSI parity error detected during ST data phase") },
664/* DTLPWRSOMCAE */{SST(0x47, 0x03, SS_RDEF|SSQ_FALLBACK,
665 "Information Unit iuCRC error") },
666/* DTLPWRSOMCAE */{SST(0x47, 0x04, SS_RDEF|SSQ_FALLBACK,
667 "Asynchronous information protection error detected") },
668/* DTLPWRSOMCAE */{SST(0x47, 0x05, SS_RDEF|SSQ_FALLBACK,
669 "Protocol server CRC error") },
670/* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF|SSQ_FALLBACK,
671 "Initiator detected error message received") },
672/* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF,
673 "Invalid message error") },
674/* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF,
675 "Command phase error") },
676/* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF,
677 "Data phase error") },
678/* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF,
679 "Logical unit failed self-configuration") },
680/* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF,
681 "Tagged overlapped commands: ASCQ = Queue tag ID") },
682/* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE,
683 NULL)}, /* Range 0x00->0xFF */
684/* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF,
685 "Overlapped commands attempted") },
686/* T */{SST(0x50, 0x00, SS_RDEF,
687 "Write append error") },
688/* T */{SST(0x50, 0x01, SS_RDEF,
689 "Write append position error") },
690/* T */{SST(0x50, 0x02, SS_RDEF,
691 "Position error related to timing") },
692/* T O */{SST(0x51, 0x00, SS_RDEF,
693 "Erase failure") },
694/* T */{SST(0x52, 0x00, SS_RDEF,
695 "Cartridge fault") },
696/* DTL WRSOM */{SST(0x53, 0x00, SS_RDEF,
697 "Media load or eject failed") },
698/* T */{SST(0x53, 0x01, SS_RDEF,
699 "Unload tape failure") },
700/* DT WR OM */{SST(0x53, 0x02, SS_RDEF,
701 "Medium removal prevented") },
702/* P */{SST(0x54, 0x00, SS_RDEF,
703 "Scsi to host system interface failure") },
704/* P */{SST(0x55, 0x00, SS_RDEF,
705 "System resource failure") },
706/* D O */{SST(0x55, 0x01, SS_FATAL|ENOSPC,
707 "System buffer full") },
708/* R */{SST(0x57, 0x00, SS_RDEF,
709 "Unable to recover table-of-contents") },
710/* O */{SST(0x58, 0x00, SS_RDEF,
711 "Generation does not exist") },
712/* O */{SST(0x59, 0x00, SS_RDEF,
713 "Updated block read") },
714/* DTLPWRSOM */{SST(0x5A, 0x00, SS_RDEF,
715 "Operator request or state change input") },
716/* DT WR OM */{SST(0x5A, 0x01, SS_RDEF,
717 "Operator medium removal request") },
718/* DT W O */{SST(0x5A, 0x02, SS_RDEF,
719 "Operator selected write protect") },
720/* DT W O */{SST(0x5A, 0x03, SS_RDEF,
721 "Operator selected write permit") },
722/* DTLPWRSOM */{SST(0x5B, 0x00, SS_RDEF,
723 "Log exception") },
724/* DTLPWRSOM */{SST(0x5B, 0x01, SS_RDEF,
725 "Threshold condition met") },
726/* DTLPWRSOM */{SST(0x5B, 0x02, SS_RDEF,
727 "Log counter at maximum") },
728/* DTLPWRSOM */{SST(0x5B, 0x03, SS_RDEF,
729 "Log list codes exhausted") },
730/* D O */{SST(0x5C, 0x00, SS_RDEF,
731 "RPL status change") },
732/* D O */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE,
733 "Spindles synchronized") },
734/* D O */{SST(0x5C, 0x02, SS_RDEF,
735 "Spindles not synchronized") },
736/* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF,
737 "Failure prediction threshold exceeded") },
738/* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF,
739 "Failure prediction threshold exceeded (false)") },
740/* DTLPWRSO CA */{SST(0x5E, 0x00, SS_RDEF,
741 "Low power condition on") },
742/* DTLPWRSO CA */{SST(0x5E, 0x01, SS_RDEF,
743 "Idle condition activated by timer") },
744/* DTLPWRSO CA */{SST(0x5E, 0x02, SS_RDEF,
745 "Standby condition activated by timer") },
746/* DTLPWRSO CA */{SST(0x5E, 0x03, SS_RDEF,
747 "Idle condition activated by command") },
748/* DTLPWRSO CA */{SST(0x5E, 0x04, SS_RDEF,
749 "Standby condition activated by command") },
750/* S */{SST(0x60, 0x00, SS_RDEF,
751 "Lamp failure") },
752/* S */{SST(0x61, 0x00, SS_RDEF,
753 "Video acquisition error") },
754/* S */{SST(0x61, 0x01, SS_RDEF,
755 "Unable to acquire video") },
756/* S */{SST(0x61, 0x02, SS_RDEF,
757 "Out of focus") },
758/* S */{SST(0x62, 0x00, SS_RDEF,
759 "Scan head positioning error") },
760/* R */{SST(0x63, 0x00, SS_RDEF,
761 "End of user area encountered on this track") },
762/* R */{SST(0x63, 0x01, SS_FATAL|ENOSPC,
763 "Packet does not fit in available space") },
764/* R */{SST(0x64, 0x00, SS_RDEF,
765 "Illegal mode for this track") },
766/* R */{SST(0x64, 0x01, SS_RDEF,
767 "Invalid packet size") },
768/* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF,
769 "Voltage fault") },
770/* S */{SST(0x66, 0x00, SS_RDEF,
771 "Automatic document feeder cover up") },
772/* S */{SST(0x66, 0x01, SS_RDEF,
773 "Automatic document feeder lift up") },
774/* S */{SST(0x66, 0x02, SS_RDEF,
775 "Document jam in automatic document feeder") },
776/* S */{SST(0x66, 0x03, SS_RDEF,
777 "Document miss feed automatic in document feeder") },
778/* A */{SST(0x67, 0x00, SS_RDEF,
779 "Configuration failure") },
780/* A */{SST(0x67, 0x01, SS_RDEF,
781 "Configuration of incapable logical units failed") },
782/* A */{SST(0x67, 0x02, SS_RDEF,
783 "Add logical unit failed") },
784/* A */{SST(0x67, 0x03, SS_RDEF,
785 "Modification of logical unit failed") },
786/* A */{SST(0x67, 0x04, SS_RDEF,
787 "Exchange of logical unit failed") },
788/* A */{SST(0x67, 0x05, SS_RDEF,
789 "Remove of logical unit failed") },
790/* A */{SST(0x67, 0x06, SS_RDEF,
791 "Attachment of logical unit failed") },
792/* A */{SST(0x67, 0x07, SS_RDEF,
793 "Creation of logical unit failed") },
794/* A */{SST(0x68, 0x00, SS_RDEF,
795 "Logical unit not configured") },
796/* A */{SST(0x69, 0x00, SS_RDEF,
797 "Data loss on logical unit") },
798/* A */{SST(0x69, 0x01, SS_RDEF,
799 "Multiple logical unit failures") },
800/* A */{SST(0x69, 0x02, SS_RDEF,
801 "Parity/data mismatch") },
802/* A */{SST(0x6A, 0x00, SS_RDEF,
803 "Informational, refer to log") },
804/* A */{SST(0x6B, 0x00, SS_RDEF,
805 "State change has occurred") },
806/* A */{SST(0x6B, 0x01, SS_RDEF,
807 "Redundancy level got better") },
808/* A */{SST(0x6B, 0x02, SS_RDEF,
809 "Redundancy level got worse") },
810/* A */{SST(0x6C, 0x00, SS_RDEF,
811 "Rebuild failure occurred") },
812/* A */{SST(0x6D, 0x00, SS_RDEF,
813 "Recalculate failure occurred") },
814/* A */{SST(0x6E, 0x00, SS_RDEF,
815 "Command to logical unit failed") },
816/* T */{SST(0x70, 0x00, SS_RDEF,
817 "Decompression exception short: ASCQ = Algorithm ID") },
818/* T */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE,
819 NULL) }, /* Range 0x00 -> 0xFF */
820/* T */{SST(0x71, 0x00, SS_RDEF,
821 "Decompression exception long: ASCQ = Algorithm ID") },
822/* T */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE,
823 NULL) }, /* Range 0x00 -> 0xFF */
824/* R */{SST(0x72, 0x00, SS_RDEF,
825 "Session fixation error") },
826/* R */{SST(0x72, 0x01, SS_RDEF,
827 "Session fixation error writing lead-in") },
828/* R */{SST(0x72, 0x02, SS_RDEF,
829 "Session fixation error writing lead-out") },
830/* R */{SST(0x72, 0x03, SS_RDEF,
831 "Session fixation error - incomplete track in session") },
832/* R */{SST(0x72, 0x04, SS_RDEF,
833 "Empty or partially written reserved track") },
834/* R */{SST(0x73, 0x00, SS_RDEF,
835 "CD control error") },
836/* R */{SST(0x73, 0x01, SS_RDEF,
837 "Power calibration area almost full") },
838/* R */{SST(0x73, 0x02, SS_FATAL|ENOSPC,
839 "Power calibration area is full") },
840/* R */{SST(0x73, 0x03, SS_RDEF,
841 "Power calibration area error") },
842/* R */{SST(0x73, 0x04, SS_RDEF,
843 "Program memory area update failure") },
844/* R */{SST(0x73, 0x05, SS_RDEF,
845 "program memory area is full") }
846};
847
848static const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]);
849
850struct asc_key
851{
852 int asc;
853 int ascq;
854};
855
856static int
857ascentrycomp(const void *key, const void *member)
858{
859 int asc;
860 int ascq;
861 const struct asc_table_entry *table_entry;
862
863 asc = ((const struct asc_key *)key)->asc;
864 ascq = ((const struct asc_key *)key)->ascq;
865 table_entry = (const struct asc_table_entry *)member;
866
867 if (asc >= table_entry->asc) {
868
869 if (asc > table_entry->asc)
870 return (1);
871
872 if (ascq <= table_entry->ascq) {
873 /* Check for ranges */
874 if (ascq == table_entry->ascq
875 || ((table_entry->action & SSQ_RANGE) != 0
876 && ascq >= (table_entry - 1)->ascq))
877 return (0);
878 return (-1);
879 }
880 return (1);
881 }
882 return (-1);
883}
884
885static int
886senseentrycomp(const void *key, const void *member)
887{
888 int sense_key;
889 const struct sense_key_table_entry *table_entry;
890
891 sense_key = *((const int *)key);
892 table_entry = (const struct sense_key_table_entry *)member;
893
894 if (sense_key >= table_entry->sense_key) {
895 if (sense_key == table_entry->sense_key)
896 return (0);
897 return (1);
898 }
899 return (-1);
900}
901
902static void
903fetchtableentries(int sense_key, int asc, int ascq,
904 struct scsi_inquiry_data *inq_data,
905 const struct sense_key_table_entry **sense_entry,
906 const struct asc_table_entry **asc_entry)
907{
908 void *match;
909 const struct asc_table_entry *asc_tables[2];
910 const struct sense_key_table_entry *sense_tables[2];
911 struct asc_key asc_ascq;
912 size_t asc_tables_size[2];
913 size_t sense_tables_size[2];
914 int num_asc_tables;
915 int num_sense_tables;
916 int i;
917
918 /* Default to failure */
919 *sense_entry = NULL;
920 *asc_entry = NULL;
921 match = NULL;
922 if (inq_data != NULL)
923 match = cam_quirkmatch((void *)inq_data,
924 (void *)sense_quirk_table,
925 sense_quirk_table_size,
926 sizeof(*sense_quirk_table),
927 aic_inquiry_match);
928
929 if (match != NULL) {
930 struct scsi_sense_quirk_entry *quirk;
931
932 quirk = (struct scsi_sense_quirk_entry *)match;
933 asc_tables[0] = quirk->asc_info;
934 asc_tables_size[0] = quirk->num_ascs;
935 asc_tables[1] = asc_table;
936 asc_tables_size[1] = asc_table_size;
937 num_asc_tables = 2;
938 sense_tables[0] = quirk->sense_key_info;
939 sense_tables_size[0] = quirk->num_sense_keys;
940 sense_tables[1] = sense_key_table;
941 sense_tables_size[1] = sense_key_table_size;
942 num_sense_tables = 2;
943 } else {
944 asc_tables[0] = asc_table;
945 asc_tables_size[0] = asc_table_size;
946 num_asc_tables = 1;
947 sense_tables[0] = sense_key_table;
948 sense_tables_size[0] = sense_key_table_size;
949 num_sense_tables = 1;
950 }
951
952 asc_ascq.asc = asc;
953 asc_ascq.ascq = ascq;
954 for (i = 0; i < num_asc_tables; i++) {
955 void *found_entry;
956
957 found_entry = scsibsearch(&asc_ascq, asc_tables[i],
958 asc_tables_size[i],
959 sizeof(**asc_tables),
960 ascentrycomp);
961
962 if (found_entry) {
963 *asc_entry = (struct asc_table_entry *)found_entry;
964 break;
965 }
966 }
967
968 for (i = 0; i < num_sense_tables; i++) {
969 void *found_entry;
970
971 found_entry = scsibsearch(&sense_key, sense_tables[i],
972 sense_tables_size[i],
973 sizeof(**sense_tables),
974 senseentrycomp);
975
976 if (found_entry) {
977 *sense_entry =
978 (struct sense_key_table_entry *)found_entry;
979 break;
980 }
981 }
982}
983
984static void *
985scsibsearch(const void *key, const void *base, size_t nmemb, size_t size,
986 int (*compar)(const void *, const void *))
987{
988 const void *entry;
989 u_int l;
990 u_int u;
991 u_int m;
992
993 l = -1;
994 u = nmemb;
995 while (l + 1 != u) {
996 m = (l + u) / 2;
997 entry = base + m * size;
998 if (compar(key, entry) > 0)
999 l = m;
1000 else
1001 u = m;
1002 }
1003
1004 entry = base + u * size;
1005 if (u == nmemb
1006 || compar(key, entry) != 0)
1007 return (NULL);
1008 34
1009 return ((void *)entry);
1010}
1011
1012/*
1013 * Compare string with pattern, returning 0 on match.
1014 * Short pattern matches trailing blanks in name,
1015 * wildcard '*' in pattern matches rest of name,
1016 * wildcard '?' matches a single non-space character.
1017 */
1018static int
1019cam_strmatch(const uint8_t *str, const uint8_t *pattern, int str_len)
1020{
1021
1022 while (*pattern != '\0'&& str_len > 0) {
1023
1024 if (*pattern == '*') {
1025 return (0);
1026 }
1027 if ((*pattern != *str)
1028 && (*pattern != '?' || *str == ' ')) {
1029 return (1);
1030 }
1031 pattern++;
1032 str++;
1033 str_len--;
1034 }
1035 while (str_len > 0 && *str++ == ' ')
1036 str_len--;
1037
1038 return (str_len);
1039}
1040
1041static caddr_t
1042cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
1043 int entry_size, cam_quirkmatch_t *comp_func)
1044{
1045 for (; num_entries > 0; num_entries--, quirk_table += entry_size) {
1046 if ((*comp_func)(target, quirk_table) == 0)
1047 return (quirk_table);
1048 }
1049 return (NULL);
1050}
1051
1052void
1053aic_sense_desc(int sense_key, int asc, int ascq,
1054 struct scsi_inquiry_data *inq_data,
1055 const char **sense_key_desc, const char **asc_desc)
1056{
1057 const struct asc_table_entry *asc_entry;
1058 const struct sense_key_table_entry *sense_entry;
1059
1060 fetchtableentries(sense_key, asc, ascq,
1061 inq_data,
1062 &sense_entry,
1063 &asc_entry);
1064
1065 *sense_key_desc = sense_entry->desc;
1066
1067 if (asc_entry != NULL)
1068 *asc_desc = asc_entry->desc;
1069 else if (asc >= 0x80 && asc <= 0xff)
1070 *asc_desc = "Vendor Specific ASC";
1071 else if (ascq >= 0x80 && ascq <= 0xff)
1072 *asc_desc = "Vendor Specific ASCQ";
1073 else
1074 *asc_desc = "Reserved ASC/ASCQ pair";
1075}
1076
1077/*
1078 * Given sense and device type information, return the appropriate action.
1079 * If we do not understand the specific error as identified by the ASC/ASCQ
1080 * pair, fall back on the more generic actions derived from the sense key.
1081 */
1082aic_sense_action
1083aic_sense_error_action(struct scsi_sense_data *sense_data,
1084 struct scsi_inquiry_data *inq_data, uint32_t sense_flags)
1085{
1086 const struct asc_table_entry *asc_entry;
1087 const struct sense_key_table_entry *sense_entry;
1088 int error_code, sense_key, asc, ascq;
1089 aic_sense_action action;
1090
1091 scsi_extract_sense(sense_data, &error_code, &sense_key, &asc, &ascq);
1092
1093 if (error_code == SSD_DEFERRED_ERROR) {
1094 /*
1095 * XXX dufault@FreeBSD.org
1096 * This error doesn't relate to the command associated
1097 * with this request sense. A deferred error is an error
1098 * for a command that has already returned GOOD status
1099 * (see SCSI2 8.2.14.2).
1100 *
1101 * By my reading of that section, it looks like the current
1102 * command has been cancelled, we should now clean things up
1103 * (hopefully recovering any lost data) and then retry the
1104 * current command. There are two easy choices, both wrong:
1105 *
1106 * 1. Drop through (like we had been doing), thus treating
1107 * this as if the error were for the current command and
1108 * return and stop the current command.
1109 *
1110 * 2. Issue a retry (like I made it do) thus hopefully
1111 * recovering the current transfer, and ignoring the
1112 * fact that we've dropped a command.
1113 *
1114 * These should probably be handled in a device specific
1115 * sense handler or punted back up to a user mode daemon
1116 */
1117 action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;
1118 } else {
1119 fetchtableentries(sense_key, asc, ascq,
1120 inq_data,
1121 &sense_entry,
1122 &asc_entry);
1123
1124 /*
1125 * Override the 'No additional Sense' entry (0,0)
1126 * with the error action of the sense key.
1127 */
1128 if (asc_entry != NULL
1129 && (asc != 0 || ascq != 0))
1130 action = asc_entry->action;
1131 else
1132 action = sense_entry->action;
1133
1134 if (sense_key == SSD_KEY_RECOVERED_ERROR) {
1135 /*
1136 * The action succeeded but the device wants
1137 * the user to know that some recovery action
1138 * was required.
1139 */
1140 action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);
1141 action |= SS_NOP|SSQ_PRINT_SENSE;
1142 } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {
1143 if ((sense_flags & SF_QUIET_IR) != 0)
1144 action &= ~SSQ_PRINT_SENSE;
1145 } else if (sense_key == SSD_KEY_UNIT_ATTENTION) {
1146 if ((sense_flags & SF_RETRY_UA) != 0
1147 && (action & SS_MASK) == SS_FAIL) {
1148 action &= ~(SS_MASK|SSQ_MASK);
1149 action |= SS_RETRY|SSQ_DECREMENT_COUNT|
1150 SSQ_PRINT_SENSE;
1151 }
1152 }
1153 }
1154
1155 if ((sense_flags & SF_PRINT_ALWAYS) != 0)
1156 action |= SSQ_PRINT_SENSE;
1157 else if ((sense_flags & SF_NO_PRINT) != 0)
1158 action &= ~SSQ_PRINT_SENSE;
1159
1160 return (action);
1161}
1162
1163/*
1164 * Try make as good a match as possible with
1165 * available sub drivers
1166 */
1167int
1168aic_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
1169{
1170 struct scsi_inquiry_pattern *entry;
1171 struct scsi_inquiry_data *inq;
1172
1173 entry = (struct scsi_inquiry_pattern *)table_entry;
1174 inq = (struct scsi_inquiry_data *)inqbuffer;
1175
1176 if (((SID_TYPE(inq) == entry->type)
1177 || (entry->type == T_ANY))
1178 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
1179 : entry->media_type & SIP_MEDIA_FIXED)
1180 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
1181 && (cam_strmatch(inq->product, entry->product,
1182 sizeof(inq->product)) == 0)
1183 && (cam_strmatch(inq->revision, entry->revision,
1184 sizeof(inq->revision)) == 0)) {
1185 return (0);
1186 }
1187 return (-1);
1188}
1189 35
1190/* 36/*
1191 * Table of syncrates that don't follow the "divisible by 4" 37 * Table of syncrates that don't follow the "divisible by 4"
@@ -1229,108 +75,6 @@ aic_calc_syncsrate(u_int period_factor)
1229 return (10000000 / (period_factor * 4 * 10)); 75 return (10000000 / (period_factor * 4 * 10));
1230} 76}
1231 77
1232/*
1233 * Return speed in KB/s.
1234 */
1235u_int
1236aic_calc_speed(u_int width, u_int period, u_int offset, u_int min_rate)
1237{
1238 u_int freq;
1239
1240 if (offset != 0 && period < min_rate)
1241 freq = aic_calc_syncsrate(period);
1242 else
1243 /* Roughly 3.3MB/s for async */
1244 freq = 3300;
1245 freq <<= width;
1246 return (freq);
1247}
1248
1249uint32_t
1250aic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data,
1251 cam_status status, u_int scsi_status)
1252{
1253 aic_sense_action err_action;
1254 int sense;
1255
1256 sense = (cmd->result >> 24) == DRIVER_SENSE;
1257
1258 switch (status) {
1259 case CAM_REQ_CMP:
1260 err_action = SS_NOP;
1261 break;
1262 case CAM_AUTOSENSE_FAIL:
1263 case CAM_SCSI_STATUS_ERROR:
1264
1265 switch (scsi_status) {
1266 case SCSI_STATUS_OK:
1267 case SCSI_STATUS_COND_MET:
1268 case SCSI_STATUS_INTERMED:
1269 case SCSI_STATUS_INTERMED_COND_MET:
1270 err_action = SS_NOP;
1271 break;
1272 case SCSI_STATUS_CMD_TERMINATED:
1273 case SCSI_STATUS_CHECK_COND:
1274 if (sense != 0) {
1275 struct scsi_sense_data *sense;
1276
1277 sense = (struct scsi_sense_data *)
1278 &cmd->sense_buffer;
1279 err_action =
1280 aic_sense_error_action(sense, inq_data, 0);
1281
1282 } else {
1283 err_action = SS_RETRY|SSQ_FALLBACK
1284 | SSQ_DECREMENT_COUNT|EIO;
1285 }
1286 break;
1287 case SCSI_STATUS_QUEUE_FULL:
1288 case SCSI_STATUS_BUSY:
1289 err_action = SS_RETRY|SSQ_DELAY|SSQ_MANY
1290 | SSQ_DECREMENT_COUNT|EBUSY;
1291 break;
1292 case SCSI_STATUS_RESERV_CONFLICT:
1293 default:
1294 err_action = SS_FAIL|EBUSY;
1295 break;
1296 }
1297 break;
1298 case CAM_CMD_TIMEOUT:
1299 case CAM_REQ_CMP_ERR:
1300 case CAM_UNEXP_BUSFREE:
1301 case CAM_UNCOR_PARITY:
1302 case CAM_DATA_RUN_ERR:
1303 err_action = SS_RETRY|SSQ_FALLBACK|EIO;
1304 break;
1305 case CAM_UA_ABORT:
1306 case CAM_UA_TERMIO:
1307 case CAM_MSG_REJECT_REC:
1308 case CAM_SEL_TIMEOUT:
1309 err_action = SS_FAIL|EIO;
1310 break;
1311 case CAM_REQ_INVALID:
1312 case CAM_PATH_INVALID:
1313 case CAM_DEV_NOT_THERE:
1314 case CAM_NO_HBA:
1315 case CAM_PROVIDE_FAIL:
1316 case CAM_REQ_TOO_BIG:
1317 case CAM_RESRC_UNAVAIL:
1318 case CAM_BUSY:
1319 default:
1320 /* panic?? These should never occur in our application. */
1321 err_action = SS_FAIL|EIO;
1322 break;
1323 case CAM_SCSI_BUS_RESET:
1324 case CAM_BDR_SENT:
1325 case CAM_REQUEUE_REQ:
1326 /* Unconditional requeue */
1327 err_action = SS_RETRY;
1328 break;
1329 }
1330
1331 return (err_action);
1332}
1333
1334char * 78char *
1335aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, 79aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
1336 aic_option_callback_t *callback, u_long callback_arg) 80 aic_option_callback_t *callback, u_long callback_arg)
diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h
index bfe6f954d3c4..e7d94cbaf2a8 100644
--- a/drivers/scsi/aic7xxx/aiclib.h
+++ b/drivers/scsi/aic7xxx/aiclib.h
@@ -57,121 +57,6 @@
57#ifndef _AICLIB_H 57#ifndef _AICLIB_H
58#define _AICLIB_H 58#define _AICLIB_H
59 59
60/*
61 * Linux Interrupt Support.
62 */
63#ifndef IRQ_RETVAL
64typedef void irqreturn_t;
65#define IRQ_RETVAL(x)
66#endif
67
68/*
69 * SCSI command format
70 */
71
72/*
73 * Define dome bits that are in ALL (or a lot of) scsi commands
74 */
75#define SCSI_CTL_LINK 0x01
76#define SCSI_CTL_FLAG 0x02
77#define SCSI_CTL_VENDOR 0xC0
78#define SCSI_CMD_LUN 0xA0 /* these two should not be needed */
79#define SCSI_CMD_LUN_SHIFT 5 /* LUN in the cmd is no longer SCSI */
80
81#define SCSI_MAX_CDBLEN 16 /*
82 * 16 byte commands are in the
83 * SCSI-3 spec
84 */
85/* 6byte CDBs special case 0 length to be 256 */
86#define SCSI_CDB6_LEN(len) ((len) == 0 ? 256 : len)
87
88/*
89 * This type defines actions to be taken when a particular sense code is
90 * received. Right now, these flags are only defined to take up 16 bits,
91 * but can be expanded in the future if necessary.
92 */
93typedef enum {
94 SS_NOP = 0x000000, /* Do nothing */
95 SS_RETRY = 0x010000, /* Retry the command */
96 SS_FAIL = 0x020000, /* Bail out */
97 SS_START = 0x030000, /* Send a Start Unit command to the device,
98 * then retry the original command.
99 */
100 SS_TUR = 0x040000, /* Send a Test Unit Ready command to the
101 * device, then retry the original command.
102 */
103 SS_REQSENSE = 0x050000, /* Send a RequestSense command to the
104 * device, then retry the original command.
105 */
106 SS_INQ_REFRESH = 0x060000,
107 SS_MASK = 0xff0000
108} aic_sense_action;
109
110typedef enum {
111 SSQ_NONE = 0x0000,
112 SSQ_DECREMENT_COUNT = 0x0100, /* Decrement the retry count */
113 SSQ_MANY = 0x0200, /* send lots of recovery commands */
114 SSQ_RANGE = 0x0400, /*
115 * This table entry represents the
116 * end of a range of ASCQs that
117 * have identical error actions
118 * and text.
119 */
120 SSQ_PRINT_SENSE = 0x0800,
121 SSQ_DELAY = 0x1000, /* Delay before retry. */
122 SSQ_DELAY_RANDOM = 0x2000, /* Randomized delay before retry. */
123 SSQ_FALLBACK = 0x4000, /* Do a speed fallback to recover */
124 SSQ_MASK = 0xff00
125} aic_sense_action_qualifier;
126
127/* Mask for error status values */
128#define SS_ERRMASK 0xff
129
130/* The default, retyable, error action */
131#define SS_RDEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO
132
133/* The retyable, error action, with table specified error code */
134#define SS_RET SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE
135
136/* Fatal error action, with table specified error code */
137#define SS_FATAL SS_FAIL|SSQ_PRINT_SENSE
138
139struct scsi_generic
140{
141 uint8_t opcode;
142 uint8_t bytes[11];
143};
144
145struct scsi_request_sense
146{
147 uint8_t opcode;
148 uint8_t byte2;
149 uint8_t unused[2];
150 uint8_t length;
151 uint8_t control;
152};
153
154struct scsi_test_unit_ready
155{
156 uint8_t opcode;
157 uint8_t byte2;
158 uint8_t unused[3];
159 uint8_t control;
160};
161
162struct scsi_send_diag
163{
164 uint8_t opcode;
165 uint8_t byte2;
166#define SSD_UOL 0x01
167#define SSD_DOL 0x02
168#define SSD_SELFTEST 0x04
169#define SSD_PF 0x10
170 uint8_t unused[1];
171 uint8_t paramlen[2];
172 uint8_t control;
173};
174
175struct scsi_sense 60struct scsi_sense
176{ 61{
177 uint8_t opcode; 62 uint8_t opcode;
@@ -181,537 +66,12 @@ struct scsi_sense
181 uint8_t control; 66 uint8_t control;
182}; 67};
183 68
184struct scsi_inquiry
185{
186 uint8_t opcode;
187 uint8_t byte2;
188#define SI_EVPD 0x01
189 uint8_t page_code;
190 uint8_t reserved;
191 uint8_t length;
192 uint8_t control;
193};
194
195struct scsi_mode_sense_6
196{
197 uint8_t opcode;
198 uint8_t byte2;
199#define SMS_DBD 0x08
200 uint8_t page;
201#define SMS_PAGE_CODE 0x3F
202#define SMS_VENDOR_SPECIFIC_PAGE 0x00
203#define SMS_DISCONNECT_RECONNECT_PAGE 0x02
204#define SMS_PERIPHERAL_DEVICE_PAGE 0x09
205#define SMS_CONTROL_MODE_PAGE 0x0A
206#define SMS_ALL_PAGES_PAGE 0x3F
207#define SMS_PAGE_CTRL_MASK 0xC0
208#define SMS_PAGE_CTRL_CURRENT 0x00
209#define SMS_PAGE_CTRL_CHANGEABLE 0x40
210#define SMS_PAGE_CTRL_DEFAULT 0x80
211#define SMS_PAGE_CTRL_SAVED 0xC0
212 uint8_t unused;
213 uint8_t length;
214 uint8_t control;
215};
216
217struct scsi_mode_sense_10
218{
219 uint8_t opcode;
220 uint8_t byte2; /* same bits as small version */
221 uint8_t page; /* same bits as small version */
222 uint8_t unused[4];
223 uint8_t length[2];
224 uint8_t control;
225};
226
227struct scsi_mode_select_6
228{
229 uint8_t opcode;
230 uint8_t byte2;
231#define SMS_SP 0x01
232#define SMS_PF 0x10
233 uint8_t unused[2];
234 uint8_t length;
235 uint8_t control;
236};
237
238struct scsi_mode_select_10
239{
240 uint8_t opcode;
241 uint8_t byte2; /* same bits as small version */
242 uint8_t unused[5];
243 uint8_t length[2];
244 uint8_t control;
245};
246
247/*
248 * When sending a mode select to a tape drive, the medium type must be 0.
249 */
250struct scsi_mode_hdr_6
251{
252 uint8_t datalen;
253 uint8_t medium_type;
254 uint8_t dev_specific;
255 uint8_t block_descr_len;
256};
257
258struct scsi_mode_hdr_10
259{
260 uint8_t datalen[2];
261 uint8_t medium_type;
262 uint8_t dev_specific;
263 uint8_t reserved[2];
264 uint8_t block_descr_len[2];
265};
266
267struct scsi_mode_block_descr
268{
269 uint8_t density_code;
270 uint8_t num_blocks[3];
271 uint8_t reserved;
272 uint8_t block_len[3];
273};
274
275struct scsi_log_sense
276{
277 uint8_t opcode;
278 uint8_t byte2;
279#define SLS_SP 0x01
280#define SLS_PPC 0x02
281 uint8_t page;
282#define SLS_PAGE_CODE 0x3F
283#define SLS_ALL_PAGES_PAGE 0x00
284#define SLS_OVERRUN_PAGE 0x01
285#define SLS_ERROR_WRITE_PAGE 0x02
286#define SLS_ERROR_READ_PAGE 0x03
287#define SLS_ERROR_READREVERSE_PAGE 0x04
288#define SLS_ERROR_VERIFY_PAGE 0x05
289#define SLS_ERROR_NONMEDIUM_PAGE 0x06
290#define SLS_ERROR_LASTN_PAGE 0x07
291#define SLS_PAGE_CTRL_MASK 0xC0
292#define SLS_PAGE_CTRL_THRESHOLD 0x00
293#define SLS_PAGE_CTRL_CUMULATIVE 0x40
294#define SLS_PAGE_CTRL_THRESH_DEFAULT 0x80
295#define SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0
296 uint8_t reserved[2];
297 uint8_t paramptr[2];
298 uint8_t length[2];
299 uint8_t control;
300};
301
302struct scsi_log_select
303{
304 uint8_t opcode;
305 uint8_t byte2;
306/* SLS_SP 0x01 */
307#define SLS_PCR 0x02
308 uint8_t page;
309/* SLS_PAGE_CTRL_MASK 0xC0 */
310/* SLS_PAGE_CTRL_THRESHOLD 0x00 */
311/* SLS_PAGE_CTRL_CUMULATIVE 0x40 */
312/* SLS_PAGE_CTRL_THRESH_DEFAULT 0x80 */
313/* SLS_PAGE_CTRL_CUMUL_DEFAULT 0xC0 */
314 uint8_t reserved[4];
315 uint8_t length[2];
316 uint8_t control;
317};
318
319struct scsi_log_header
320{
321 uint8_t page;
322 uint8_t reserved;
323 uint8_t datalen[2];
324};
325
326struct scsi_log_param_header {
327 uint8_t param_code[2];
328 uint8_t param_control;
329#define SLP_LP 0x01
330#define SLP_LBIN 0x02
331#define SLP_TMC_MASK 0x0C
332#define SLP_TMC_ALWAYS 0x00
333#define SLP_TMC_EQUAL 0x04
334#define SLP_TMC_NOTEQUAL 0x08
335#define SLP_TMC_GREATER 0x0C
336#define SLP_ETC 0x10
337#define SLP_TSD 0x20
338#define SLP_DS 0x40
339#define SLP_DU 0x80
340 uint8_t param_len;
341};
342
343struct scsi_control_page {
344 uint8_t page_code;
345 uint8_t page_length;
346 uint8_t rlec;
347#define SCB_RLEC 0x01 /*Report Log Exception Cond*/
348 uint8_t queue_flags;
349#define SCP_QUEUE_ALG_MASK 0xF0
350#define SCP_QUEUE_ALG_RESTRICTED 0x00
351#define SCP_QUEUE_ALG_UNRESTRICTED 0x10
352#define SCP_QUEUE_ERR 0x02 /*Queued I/O aborted for CACs*/
353#define SCP_QUEUE_DQUE 0x01 /*Queued I/O disabled*/
354 uint8_t eca_and_aen;
355#define SCP_EECA 0x80 /*Enable Extended CA*/
356#define SCP_RAENP 0x04 /*Ready AEN Permission*/
357#define SCP_UAAENP 0x02 /*UA AEN Permission*/
358#define SCP_EAENP 0x01 /*Error AEN Permission*/
359 uint8_t reserved;
360 uint8_t aen_holdoff_period[2];
361};
362
363struct scsi_reserve
364{
365 uint8_t opcode;
366 uint8_t byte2;
367 uint8_t unused[2];
368 uint8_t length;
369 uint8_t control;
370};
371
372struct scsi_release
373{
374 uint8_t opcode;
375 uint8_t byte2;
376 uint8_t unused[2];
377 uint8_t length;
378 uint8_t control;
379};
380
381struct scsi_prevent
382{
383 uint8_t opcode;
384 uint8_t byte2;
385 uint8_t unused[2];
386 uint8_t how;
387 uint8_t control;
388};
389#define PR_PREVENT 0x01
390#define PR_ALLOW 0x00
391
392struct scsi_sync_cache
393{
394 uint8_t opcode;
395 uint8_t byte2;
396 uint8_t begin_lba[4];
397 uint8_t reserved;
398 uint8_t lb_count[2];
399 uint8_t control;
400};
401
402
403struct scsi_changedef
404{
405 uint8_t opcode;
406 uint8_t byte2;
407 uint8_t unused1;
408 uint8_t how;
409 uint8_t unused[4];
410 uint8_t datalen;
411 uint8_t control;
412};
413
414struct scsi_read_buffer
415{
416 uint8_t opcode;
417 uint8_t byte2;
418#define RWB_MODE 0x07
419#define RWB_MODE_HDR_DATA 0x00
420#define RWB_MODE_DATA 0x02
421#define RWB_MODE_DOWNLOAD 0x04
422#define RWB_MODE_DOWNLOAD_SAVE 0x05
423 uint8_t buffer_id;
424 uint8_t offset[3];
425 uint8_t length[3];
426 uint8_t control;
427};
428
429struct scsi_write_buffer
430{
431 uint8_t opcode;
432 uint8_t byte2;
433 uint8_t buffer_id;
434 uint8_t offset[3];
435 uint8_t length[3];
436 uint8_t control;
437};
438
439struct scsi_rw_6
440{
441 uint8_t opcode;
442 uint8_t addr[3];
443/* only 5 bits are valid in the MSB address byte */
444#define SRW_TOPADDR 0x1F
445 uint8_t length;
446 uint8_t control;
447};
448
449struct scsi_rw_10
450{
451 uint8_t opcode;
452#define SRW10_RELADDR 0x01
453#define SRW10_FUA 0x08
454#define SRW10_DPO 0x10
455 uint8_t byte2;
456 uint8_t addr[4];
457 uint8_t reserved;
458 uint8_t length[2];
459 uint8_t control;
460};
461
462struct scsi_rw_12
463{
464 uint8_t opcode;
465#define SRW12_RELADDR 0x01
466#define SRW12_FUA 0x08
467#define SRW12_DPO 0x10
468 uint8_t byte2;
469 uint8_t addr[4];
470 uint8_t length[4];
471 uint8_t reserved;
472 uint8_t control;
473};
474
475struct scsi_start_stop_unit
476{
477 uint8_t opcode;
478 uint8_t byte2;
479#define SSS_IMMED 0x01
480 uint8_t reserved[2];
481 uint8_t how;
482#define SSS_START 0x01
483#define SSS_LOEJ 0x02
484 uint8_t control;
485};
486
487#define SC_SCSI_1 0x01
488#define SC_SCSI_2 0x03
489
490/*
491 * Opcodes
492 */
493
494#define TEST_UNIT_READY 0x00
495#define REQUEST_SENSE 0x03
496#define READ_6 0x08
497#define WRITE_6 0x0a
498#define INQUIRY 0x12
499#define MODE_SELECT_6 0x15
500#define MODE_SENSE_6 0x1a
501#define START_STOP_UNIT 0x1b
502#define START_STOP 0x1b
503#define RESERVE 0x16
504#define RELEASE 0x17
505#define RECEIVE_DIAGNOSTIC 0x1c
506#define SEND_DIAGNOSTIC 0x1d
507#define PREVENT_ALLOW 0x1e
508#define READ_CAPACITY 0x25
509#define READ_10 0x28
510#define WRITE_10 0x2a
511#define POSITION_TO_ELEMENT 0x2b
512#define SYNCHRONIZE_CACHE 0x35
513#define WRITE_BUFFER 0x3b
514#define READ_BUFFER 0x3c
515#define CHANGE_DEFINITION 0x40
516#define LOG_SELECT 0x4c
517#define LOG_SENSE 0x4d
518#ifdef XXXCAM
519#define MODE_SENSE_10 0x5A
520#endif
521#define MODE_SELECT_10 0x55
522#define MOVE_MEDIUM 0xa5
523#define READ_12 0xa8
524#define WRITE_12 0xaa
525#define READ_ELEMENT_STATUS 0xb8
526
527
528/*
529 * Device Types
530 */
531#define T_DIRECT 0x00
532#define T_SEQUENTIAL 0x01
533#define T_PRINTER 0x02
534#define T_PROCESSOR 0x03
535#define T_WORM 0x04
536#define T_CDROM 0x05
537#define T_SCANNER 0x06
538#define T_OPTICAL 0x07
539#define T_CHANGER 0x08
540#define T_COMM 0x09
541#define T_ASC0 0x0a
542#define T_ASC1 0x0b
543#define T_STORARRAY 0x0c
544#define T_ENCLOSURE 0x0d
545#define T_RBC 0x0e
546#define T_OCRW 0x0f
547#define T_NODEVICE 0x1F
548#define T_ANY 0xFF /* Used in Quirk table matches */
549
550#define T_REMOV 1
551#define T_FIXED 0
552
553/*
554 * This length is the initial inquiry length used by the probe code, as
555 * well as the legnth necessary for aic_print_inquiry() to function
556 * correctly. If either use requires a different length in the future,
557 * the two values should be de-coupled.
558 */
559#define SHORT_INQUIRY_LENGTH 36
560
561struct scsi_inquiry_data
562{
563 uint8_t device;
564#define SID_TYPE(inq_data) ((inq_data)->device & 0x1f)
565#define SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5)
566#define SID_QUAL_LU_CONNECTED 0x00 /*
567 * The specified peripheral device
568 * type is currently connected to
569 * logical unit. If the target cannot
570 * determine whether or not a physical
571 * device is currently connected, it
572 * shall also use this peripheral
573 * qualifier when returning the INQUIRY
574 * data. This peripheral qualifier
575 * does not mean that the device is
576 * ready for access by the initiator.
577 */
578#define SID_QUAL_LU_OFFLINE 0x01 /*
579 * The target is capable of supporting
580 * the specified peripheral device type
581 * on this logical unit; however, the
582 * physical device is not currently
583 * connected to this logical unit.
584 */
585#define SID_QUAL_RSVD 0x02
586#define SID_QUAL_BAD_LU 0x03 /*
587 * The target is not capable of
588 * supporting a physical device on
589 * this logical unit. For this
590 * peripheral qualifier the peripheral
591 * device type shall be set to 1Fh to
592 * provide compatibility with previous
593 * versions of SCSI. All other
594 * peripheral device type values are
595 * reserved for this peripheral
596 * qualifier.
597 */
598#define SID_QUAL_IS_VENDOR_UNIQUE(inq_data) ((SID_QUAL(inq_data) & 0x08) != 0)
599 uint8_t dev_qual2;
600#define SID_QUAL2 0x7F
601#define SID_IS_REMOVABLE(inq_data) (((inq_data)->dev_qual2 & 0x80) != 0)
602 uint8_t version;
603#define SID_ANSI_REV(inq_data) ((inq_data)->version & 0x07)
604#define SCSI_REV_0 0 69#define SCSI_REV_0 0
605#define SCSI_REV_CCS 1 70#define SCSI_REV_CCS 1
606#define SCSI_REV_2 2 71#define SCSI_REV_2 2
607#define SCSI_REV_SPC 3 72#define SCSI_REV_SPC 3
608#define SCSI_REV_SPC2 4 73#define SCSI_REV_SPC2 4
609 74
610#define SID_ECMA 0x38
611#define SID_ISO 0xC0
612 uint8_t response_format;
613#define SID_AENC 0x80
614#define SID_TrmIOP 0x40
615 uint8_t additional_length;
616 uint8_t reserved[2];
617 uint8_t flags;
618#define SID_SftRe 0x01
619#define SID_CmdQue 0x02
620#define SID_Linked 0x08
621#define SID_Sync 0x10
622#define SID_WBus16 0x20
623#define SID_WBus32 0x40
624#define SID_RelAdr 0x80
625#define SID_VENDOR_SIZE 8
626 char vendor[SID_VENDOR_SIZE];
627#define SID_PRODUCT_SIZE 16
628 char product[SID_PRODUCT_SIZE];
629#define SID_REVISION_SIZE 4
630 char revision[SID_REVISION_SIZE];
631 /*
632 * The following fields were taken from SCSI Primary Commands - 2
633 * (SPC-2) Revision 14, Dated 11 November 1999
634 */
635#define SID_VENDOR_SPECIFIC_0_SIZE 20
636 uint8_t vendor_specific0[SID_VENDOR_SPECIFIC_0_SIZE];
637 /*
638 * An extension of SCSI Parallel Specific Values
639 */
640#define SID_SPI_IUS 0x01
641#define SID_SPI_QAS 0x02
642#define SID_SPI_CLOCK_ST 0x00
643#define SID_SPI_CLOCK_DT 0x04
644#define SID_SPI_CLOCK_DT_ST 0x0C
645#define SID_SPI_MASK 0x0F
646 uint8_t spi3data;
647 uint8_t reserved2;
648 /*
649 * Version Descriptors, stored 2 byte values.
650 */
651 uint8_t version1[2];
652 uint8_t version2[2];
653 uint8_t version3[2];
654 uint8_t version4[2];
655 uint8_t version5[2];
656 uint8_t version6[2];
657 uint8_t version7[2];
658 uint8_t version8[2];
659
660 uint8_t reserved3[22];
661
662#define SID_VENDOR_SPECIFIC_1_SIZE 160
663 uint8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE];
664};
665
666struct scsi_vpd_unit_serial_number
667{
668 uint8_t device;
669 uint8_t page_code;
670#define SVPD_UNIT_SERIAL_NUMBER 0x80
671 uint8_t reserved;
672 uint8_t length; /* serial number length */
673#define SVPD_SERIAL_NUM_SIZE 251
674 uint8_t serial_num[SVPD_SERIAL_NUM_SIZE];
675};
676
677struct scsi_read_capacity
678{
679 uint8_t opcode;
680 uint8_t byte2;
681 uint8_t addr[4];
682 uint8_t unused[3];
683 uint8_t control;
684};
685
686struct scsi_read_capacity_data
687{
688 uint8_t addr[4];
689 uint8_t length[4];
690};
691
692struct scsi_report_luns
693{
694 uint8_t opcode;
695 uint8_t byte2;
696 uint8_t unused[3];
697 uint8_t addr[4];
698 uint8_t control;
699};
700
701struct scsi_report_luns_data {
702 uint8_t length[4]; /* length of LUN inventory, in bytes */
703 uint8_t reserved[4]; /* unused */
704 /*
705 * LUN inventory- we only support the type zero form for now.
706 */
707 struct {
708 uint8_t lundata[8];
709 } luns[1];
710};
711#define RPL_LUNDATA_ATYP_MASK 0xc0 /* MBZ for type 0 lun */
712#define RPL_LUNDATA_T0LUN 1 /* @ lundata[1] */
713
714
715struct scsi_sense_data 75struct scsi_sense_data
716{ 76{
717 uint8_t error_code; 77 uint8_t error_code;
@@ -757,41 +117,6 @@ struct scsi_sense_data
757#define SSD_FULL_SIZE sizeof(struct scsi_sense_data) 117#define SSD_FULL_SIZE sizeof(struct scsi_sense_data)
758}; 118};
759 119
760struct scsi_mode_header_6
761{
762 uint8_t data_length; /* Sense data length */
763 uint8_t medium_type;
764 uint8_t dev_spec;
765 uint8_t blk_desc_len;
766};
767
768struct scsi_mode_header_10
769{
770 uint8_t data_length[2];/* Sense data length */
771 uint8_t medium_type;
772 uint8_t dev_spec;
773 uint8_t unused[2];
774 uint8_t blk_desc_len[2];
775};
776
777struct scsi_mode_page_header
778{
779 uint8_t page_code;
780 uint8_t page_length;
781};
782
783struct scsi_mode_blk_desc
784{
785 uint8_t density;
786 uint8_t nblocks[3];
787 uint8_t reserved;
788 uint8_t blklen[3];
789};
790
791#define SCSI_DEFAULT_DENSITY 0x00 /* use 'default' density */
792#define SCSI_SAME_DENSITY 0x7f /* use 'same' density- >= SCSI-2 only */
793
794
795/* 120/*
796 * Status Byte 121 * Status Byte
797 */ 122 */
@@ -807,76 +132,7 @@ struct scsi_mode_blk_desc
807#define SCSI_STATUS_ACA_ACTIVE 0x30 132#define SCSI_STATUS_ACA_ACTIVE 0x30
808#define SCSI_STATUS_TASK_ABORTED 0x40 133#define SCSI_STATUS_TASK_ABORTED 0x40
809 134
810struct scsi_inquiry_pattern {
811 uint8_t type;
812 uint8_t media_type;
813#define SIP_MEDIA_REMOVABLE 0x01
814#define SIP_MEDIA_FIXED 0x02
815 const char *vendor;
816 const char *product;
817 const char *revision;
818};
819
820struct scsi_static_inquiry_pattern {
821 uint8_t type;
822 uint8_t media_type;
823 char vendor[SID_VENDOR_SIZE+1];
824 char product[SID_PRODUCT_SIZE+1];
825 char revision[SID_REVISION_SIZE+1];
826};
827
828struct scsi_sense_quirk_entry {
829 struct scsi_inquiry_pattern inq_pat;
830 int num_sense_keys;
831 int num_ascs;
832 struct sense_key_table_entry *sense_key_info;
833 struct asc_table_entry *asc_info;
834};
835
836struct sense_key_table_entry {
837 uint8_t sense_key;
838 uint32_t action;
839 const char *desc;
840};
841
842struct asc_table_entry {
843 uint8_t asc;
844 uint8_t ascq;
845 uint32_t action;
846 const char *desc;
847};
848
849struct op_table_entry {
850 uint8_t opcode;
851 uint16_t opmask;
852 const char *desc;
853};
854
855struct scsi_op_quirk_entry {
856 struct scsi_inquiry_pattern inq_pat;
857 int num_ops;
858 struct op_table_entry *op_table;
859};
860
861typedef enum {
862 SSS_FLAG_NONE = 0x00,
863 SSS_FLAG_PRINT_COMMAND = 0x01
864} scsi_sense_string_flags;
865
866extern const char *scsi_sense_key_text[];
867
868/************************* Large Disk Handling ********************************/ 135/************************* Large Disk Handling ********************************/
869#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
870static __inline int aic_sector_div(u_long capacity, int heads, int sectors);
871
872static __inline int
873aic_sector_div(u_long capacity, int heads, int sectors)
874{
875 return (capacity / (heads * sectors));
876}
877#else
878static __inline int aic_sector_div(sector_t capacity, int heads, int sectors);
879
880static __inline int 136static __inline int
881aic_sector_div(sector_t capacity, int heads, int sectors) 137aic_sector_div(sector_t capacity, int heads, int sectors)
882{ 138{
@@ -884,7 +140,6 @@ aic_sector_div(sector_t capacity, int heads, int sectors)
884 sector_div(capacity, (heads * sectors)); 140 sector_div(capacity, (heads * sectors));
885 return (int)capacity; 141 return (int)capacity;
886} 142}
887#endif
888 143
889/**************************** Module Library Hack *****************************/ 144/**************************** Module Library Hack *****************************/
890/* 145/*
@@ -899,138 +154,15 @@ aic_sector_div(sector_t capacity, int heads, int sectors)
899#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix) 154#define AIC_LIB_ENTRY_EXPAND(x, prefix) AIC_LIB_ENTRY_CONCAT(x, prefix)
900#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX) 155#define AIC_LIB_ENTRY(x) AIC_LIB_ENTRY_EXPAND(x, AIC_LIB_PREFIX)
901 156
902#define aic_sense_desc AIC_LIB_ENTRY(_sense_desc)
903#define aic_sense_error_action AIC_LIB_ENTRY(_sense_error_action)
904#define aic_error_action AIC_LIB_ENTRY(_error_action)
905#define aic_op_desc AIC_LIB_ENTRY(_op_desc)
906#define aic_cdb_string AIC_LIB_ENTRY(_cdb_string)
907#define aic_print_inquiry AIC_LIB_ENTRY(_print_inquiry)
908#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate) 157#define aic_calc_syncsrate AIC_LIB_ENTRY(_calc_syncrate)
909#define aic_calc_syncparam AIC_LIB_ENTRY(_calc_syncparam)
910#define aic_calc_speed AIC_LIB_ENTRY(_calc_speed)
911#define aic_inquiry_match AIC_LIB_ENTRY(_inquiry_match)
912#define aic_static_inquiry_match AIC_LIB_ENTRY(_static_inquiry_match)
913#define aic_parse_brace_option AIC_LIB_ENTRY(_parse_brace_option)
914
915/******************************************************************************/
916
917void aic_sense_desc(int /*sense_key*/, int /*asc*/,
918 int /*ascq*/, struct scsi_inquiry_data*,
919 const char** /*sense_key_desc*/,
920 const char** /*asc_desc*/);
921aic_sense_action aic_sense_error_action(struct scsi_sense_data*,
922 struct scsi_inquiry_data*,
923 uint32_t /*sense_flags*/);
924uint32_t aic_error_action(struct scsi_cmnd *,
925 struct scsi_inquiry_data *,
926 cam_status, u_int);
927
928#define SF_RETRY_UA 0x01
929#define SF_NO_PRINT 0x02
930#define SF_QUIET_IR 0x04 /* Be quiet about Illegal Request reponses */
931#define SF_PRINT_ALWAYS 0x08
932
933
934const char * aic_op_desc(uint16_t /*opcode*/, struct scsi_inquiry_data*);
935char * aic_cdb_string(uint8_t* /*cdb_ptr*/, char* /*cdb_string*/,
936 size_t /*len*/);
937void aic_print_inquiry(struct scsi_inquiry_data*);
938 158
939u_int aic_calc_syncsrate(u_int /*period_factor*/); 159u_int aic_calc_syncsrate(u_int /*period_factor*/);
940u_int aic_calc_syncparam(u_int /*period*/);
941u_int aic_calc_speed(u_int width, u_int period, u_int offset,
942 u_int min_rate);
943
944int aic_inquiry_match(caddr_t /*inqbuffer*/,
945 caddr_t /*table_entry*/);
946int aic_static_inquiry_match(caddr_t /*inqbuffer*/,
947 caddr_t /*table_entry*/);
948 160
949typedef void aic_option_callback_t(u_long, int, int, int32_t); 161typedef void aic_option_callback_t(u_long, int, int, int32_t);
950char * aic_parse_brace_option(char *opt_name, char *opt_arg, 162char * aic_parse_brace_option(char *opt_name, char *opt_arg,
951 char *end, int depth, 163 char *end, int depth,
952 aic_option_callback_t *, u_long); 164 aic_option_callback_t *, u_long);
953 165
954static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
955 int *error_code, int *sense_key,
956 int *asc, int *ascq);
957static __inline void scsi_ulto2b(uint32_t val, uint8_t *bytes);
958static __inline void scsi_ulto3b(uint32_t val, uint8_t *bytes);
959static __inline void scsi_ulto4b(uint32_t val, uint8_t *bytes);
960static __inline uint32_t scsi_2btoul(uint8_t *bytes);
961static __inline uint32_t scsi_3btoul(uint8_t *bytes);
962static __inline int32_t scsi_3btol(uint8_t *bytes);
963static __inline uint32_t scsi_4btoul(uint8_t *bytes);
964
965static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
966 int *error_code, int *sense_key,
967 int *asc, int *ascq)
968{
969 *error_code = sense->error_code & SSD_ERRCODE;
970 *sense_key = sense->flags & SSD_KEY;
971 *asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
972 *ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
973}
974
975static __inline void
976scsi_ulto2b(uint32_t val, uint8_t *bytes)
977{
978
979 bytes[0] = (val >> 8) & 0xff;
980 bytes[1] = val & 0xff;
981}
982
983static __inline void
984scsi_ulto3b(uint32_t val, uint8_t *bytes)
985{
986
987 bytes[0] = (val >> 16) & 0xff;
988 bytes[1] = (val >> 8) & 0xff;
989 bytes[2] = val & 0xff;
990}
991
992static __inline void
993scsi_ulto4b(uint32_t val, uint8_t *bytes)
994{
995
996 bytes[0] = (val >> 24) & 0xff;
997 bytes[1] = (val >> 16) & 0xff;
998 bytes[2] = (val >> 8) & 0xff;
999 bytes[3] = val & 0xff;
1000}
1001
1002static __inline uint32_t
1003scsi_2btoul(uint8_t *bytes)
1004{
1005 uint32_t rv;
1006
1007 rv = (bytes[0] << 8) |
1008 bytes[1];
1009 return (rv);
1010}
1011
1012static __inline uint32_t
1013scsi_3btoul(uint8_t *bytes)
1014{
1015 uint32_t rv;
1016
1017 rv = (bytes[0] << 16) |
1018 (bytes[1] << 8) |
1019 bytes[2];
1020 return (rv);
1021}
1022
1023static __inline int32_t
1024scsi_3btol(uint8_t *bytes)
1025{
1026 uint32_t rc = scsi_3btoul(bytes);
1027
1028 if (rc & 0x00800000)
1029 rc |= 0xff000000;
1030
1031 return (int32_t) rc;
1032}
1033
1034static __inline uint32_t 166static __inline uint32_t
1035scsi_4btoul(uint8_t *bytes) 167scsi_4btoul(uint8_t *bytes)
1036{ 168{