diff options
author | James Bottomley <jejb@titanic.(none)> | 2005-08-28 12:18:35 -0400 |
---|---|---|
committer | James Bottomley <jejb@titanic.(none)> | 2005-08-28 12:18:35 -0400 |
commit | 7a93aef7fbac6f4db40b6fec5c0c6b654ae7a93c (patch) | |
tree | 4cd7aae38012dfc1ff6c62be20ef8840e56d8383 /drivers/scsi/aic7xxx | |
parent | 392160335c798bbe94ab3aae6ea0c85d32b81bbc (diff) | |
parent | 8224bfa84d510630b40ea460b2bb380c91acb8ae (diff) |
Merge HEAD from ../scsi-misc-2.6-tmp
Diffstat (limited to 'drivers/scsi/aic7xxx')
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 @@ | |||
5 | config SCSI_AIC79XX | 5 | config 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) | |||
126 | int | 126 | int |
127 | aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io) | 127 | aic7770_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 | ||
1250 | TAILQ_HEAD(ahd_softc_tailq, ahd_softc); | ||
1251 | extern 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, | |||
1374 | void ahd_pause_and_flushwork(struct ahd_softc *ahd); | 1371 | void ahd_pause_and_flushwork(struct ahd_softc *ahd); |
1375 | int ahd_suspend(struct ahd_softc *ahd); | 1372 | int ahd_suspend(struct ahd_softc *ahd); |
1376 | int ahd_resume(struct ahd_softc *ahd); | 1373 | int ahd_resume(struct ahd_softc *ahd); |
1377 | void ahd_softc_insert(struct ahd_softc *); | ||
1378 | struct ahd_softc *ahd_find_softc(struct ahd_softc *ahd); | ||
1379 | void ahd_set_unit(struct ahd_softc *, int); | 1374 | void ahd_set_unit(struct ahd_softc *, int); |
1380 | void ahd_set_name(struct ahd_softc *, char *); | 1375 | void ahd_set_name(struct ahd_softc *, char *); |
1381 | struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); | 1376 | struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); |
@@ -1524,7 +1519,6 @@ void ahd_print_scb(struct scb *scb); | |||
1524 | void ahd_print_devinfo(struct ahd_softc *ahd, | 1519 | void ahd_print_devinfo(struct ahd_softc *ahd, |
1525 | struct ahd_devinfo *devinfo); | 1520 | struct ahd_devinfo *devinfo); |
1526 | void ahd_dump_sglist(struct scb *scb); | 1521 | void ahd_dump_sglist(struct scb *scb); |
1527 | void ahd_dump_all_cards_state(void); | ||
1528 | void ahd_dump_card_state(struct ahd_softc *ahd); | 1522 | void ahd_dump_card_state(struct ahd_softc *ahd); |
1529 | int ahd_print_register(ahd_reg_parse_entry_t *table, | 1523 | int 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 *************************************/ | ||
56 | struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq); | ||
57 | 55 | ||
58 | /***************************** Lookup Tables **********************************/ | 56 | /***************************** Lookup Tables **********************************/ |
59 | char *ahd_chip_names[] = | 57 | char *ahd_chip_names[] = |
@@ -5180,74 +5178,6 @@ ahd_softc_init(struct ahd_softc *ahd) | |||
5180 | } | 5178 | } |
5181 | 5179 | ||
5182 | void | 5180 | void |
5183 | ahd_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 | */ | ||
5238 | struct ahd_softc * | ||
5239 | ahd_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 | |||
5250 | void | ||
5251 | ahd_set_unit(struct ahd_softc *ahd, int unit) | 5181 | ahd_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) | |||
7902 | static void | 7832 | static void |
7903 | ahd_reset_poll(void *arg) | 7833 | ahd_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 ***************************/ |
7943 | static void | 7863 | static void |
7944 | ahd_stat_timer(void *arg) | 7864 | ahd_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 | ||
8748 | void | ||
8749 | ahd_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 | |||
8758 | int | 8659 | int |
8759 | ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, | 8660 | ahd_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 | ||
49 | static 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 | */ | ||
67 | spinlock_t ahd_list_spinlock; | ||
68 | |||
69 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
70 | /* For dynamic sglist size calculation. */ | ||
71 | u_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 | |||
202 | static 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 | |||
235 | static 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; | |||
375 | uint32_t aic79xx_allow_memio = ~0; | 298 | uint32_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 | */ | ||
382 | int 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>"); | |||
412 | MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); | 328 | MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver"); |
413 | MODULE_LICENSE("Dual BSD/GPL"); | 329 | MODULE_LICENSE("Dual BSD/GPL"); |
414 | MODULE_VERSION(AIC79XX_DRIVER_VERSION); | 330 | MODULE_VERSION(AIC79XX_DRIVER_VERSION); |
415 | module_param(aic79xx, charp, 0); | 331 | module_param(aic79xx, charp, 0444); |
416 | MODULE_PARM_DESC(aic79xx, | 332 | MODULE_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 | ||
450 | static void ahd_linux_handle_scsi_status(struct ahd_softc *, | 360 | static void ahd_linux_handle_scsi_status(struct ahd_softc *, |
451 | struct ahd_linux_device *, | 361 | struct scsi_device *, |
452 | struct scb *); | 362 | struct scb *); |
453 | static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, | 363 | static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, |
454 | Scsi_Cmnd *cmd); | 364 | struct scsi_cmnd *cmd); |
455 | static void ahd_linux_filter_inquiry(struct ahd_softc *ahd, | ||
456 | struct ahd_devinfo *devinfo); | ||
457 | static void ahd_linux_dev_timed_unfreeze(u_long arg); | ||
458 | static void ahd_linux_sem_timeout(u_long arg); | 365 | static void ahd_linux_sem_timeout(u_long arg); |
366 | static int ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); | ||
459 | static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); | 367 | static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); |
460 | static void ahd_linux_size_nseg(void); | ||
461 | static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd); | ||
462 | static void ahd_linux_start_dv(struct ahd_softc *ahd); | ||
463 | static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd); | ||
464 | static int ahd_linux_dv_thread(void *data); | ||
465 | static void ahd_linux_kill_dv_thread(struct ahd_softc *ahd); | ||
466 | static void ahd_linux_dv_target(struct ahd_softc *ahd, u_int target); | ||
467 | static 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); | ||
471 | static void ahd_linux_dv_fill_cmd(struct ahd_softc *ahd, | ||
472 | struct scsi_cmnd *cmd, | ||
473 | struct ahd_devinfo *devinfo); | ||
474 | static 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); | ||
479 | static void ahd_linux_dv_tur(struct ahd_softc *ahd, | ||
480 | struct scsi_cmnd *cmd, | ||
481 | struct ahd_devinfo *devinfo); | ||
482 | static 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); | ||
486 | static 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); | ||
490 | static 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); | ||
494 | static 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); | ||
498 | static int ahd_linux_fallback(struct ahd_softc *ahd, | ||
499 | struct ahd_devinfo *devinfo); | ||
500 | static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd, | ||
501 | struct ahd_devinfo *devinfo); | ||
502 | static void ahd_linux_dv_complete(Scsi_Cmnd *cmd); | ||
503 | static void ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ); | ||
504 | static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, | 368 | static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd, |
505 | struct ahd_devinfo *devinfo); | 369 | struct ahd_devinfo *devinfo); |
506 | static u_int ahd_linux_user_dv_setting(struct ahd_softc *ahd); | 370 | static void ahd_linux_device_queue_depth(struct scsi_device *); |
507 | static void ahd_linux_setup_user_rd_strm_settings(struct ahd_softc *ahd); | 371 | static int ahd_linux_run_command(struct ahd_softc*, |
508 | static 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 *); |
510 | static struct ahd_linux_target* ahd_linux_alloc_target(struct ahd_softc*, | ||
511 | u_int, u_int); | ||
512 | static void ahd_linux_free_target(struct ahd_softc*, | ||
513 | struct ahd_linux_target*); | ||
514 | static struct ahd_linux_device* ahd_linux_alloc_device(struct ahd_softc*, | ||
515 | struct ahd_linux_target*, | ||
516 | u_int); | ||
517 | static void ahd_linux_free_device(struct ahd_softc*, | ||
518 | struct ahd_linux_device*); | ||
519 | static void ahd_linux_run_device_queue(struct ahd_softc*, | ||
520 | struct ahd_linux_device*); | ||
521 | static void ahd_linux_setup_tag_info_global(char *p); | 374 | static void ahd_linux_setup_tag_info_global(char *p); |
522 | static aic_option_callback_t ahd_linux_setup_tag_info; | 375 | static aic_option_callback_t ahd_linux_setup_tag_info; |
523 | static aic_option_callback_t ahd_linux_setup_rd_strm_info; | ||
524 | static aic_option_callback_t ahd_linux_setup_dv; | ||
525 | static aic_option_callback_t ahd_linux_setup_iocell_info; | 376 | static aic_option_callback_t ahd_linux_setup_iocell_info; |
526 | static int ahd_linux_next_unit(void); | 377 | static int aic79xx_setup(char *c); |
527 | static void ahd_runq_tasklet(unsigned long data); | ||
528 | static int aic79xx_setup(char *c); | ||
529 | |||
530 | /****************************** Inlines ***************************************/ | ||
531 | static __inline void ahd_schedule_completeq(struct ahd_softc *ahd); | ||
532 | static __inline void ahd_schedule_runq(struct ahd_softc *ahd); | ||
533 | static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd); | ||
534 | static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd); | ||
535 | static __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); | ||
538 | static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd); | ||
539 | static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd, | ||
540 | struct ahd_linux_device *dev); | ||
541 | static __inline struct ahd_linux_device * | ||
542 | ahd_linux_next_device_to_run(struct ahd_softc *ahd); | ||
543 | static __inline void ahd_linux_run_device_queues(struct ahd_softc *ahd); | ||
544 | static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); | ||
545 | |||
546 | static __inline void | ||
547 | ahd_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 | */ | ||
559 | static __inline void | ||
560 | ahd_schedule_runq(struct ahd_softc *ahd) | ||
561 | { | ||
562 | tasklet_schedule(&ahd->platform_data->runq_tasklet); | ||
563 | } | ||
564 | |||
565 | static __inline | ||
566 | void 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 | ||
572 | static __inline void | 379 | static int ahd_linux_unit; |
573 | ahd_teardown_runq_tasklet(struct ahd_softc *ahd) | ||
574 | { | ||
575 | tasklet_kill(&ahd->platform_data->runq_tasklet); | ||
576 | } | ||
577 | 380 | ||
578 | static __inline struct ahd_linux_device* | ||
579 | ahd_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) | 383 | static __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 | ||
605 | static struct ahd_cmd * | ||
606 | ahd_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 | |||
643 | static __inline void | ||
644 | ahd_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 | |||
660 | static __inline struct ahd_linux_device * | ||
661 | ahd_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 | |||
671 | static __inline void | ||
672 | ahd_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 | ||
683 | static __inline void | 385 | static __inline void |
684 | ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) | 386 | ahd_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 *************************/ | ||
709 | static int ahd_linux_detect(Scsi_Host_Template *); | ||
710 | static const char *ahd_linux_info(struct Scsi_Host *); | ||
711 | static int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); | ||
712 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
713 | static int ahd_linux_slave_alloc(Scsi_Device *); | ||
714 | static int ahd_linux_slave_configure(Scsi_Device *); | ||
715 | static void ahd_linux_slave_destroy(Scsi_Device *); | ||
716 | #if defined(__i386__) | ||
717 | static int ahd_linux_biosparam(struct scsi_device*, | ||
718 | struct block_device*, sector_t, int[]); | ||
719 | #endif | ||
720 | #else | ||
721 | static int ahd_linux_release(struct Scsi_Host *); | ||
722 | static void ahd_linux_select_queue_depth(struct Scsi_Host *host, | ||
723 | Scsi_Device *scsi_devs); | ||
724 | #if defined(__i386__) | ||
725 | static int ahd_linux_biosparam(Disk *, kdev_t, int[]); | ||
726 | #endif | ||
727 | #endif | ||
728 | static int ahd_linux_bus_reset(Scsi_Cmnd *); | ||
729 | static int ahd_linux_dev_reset(Scsi_Cmnd *); | ||
730 | static 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 | */ | ||
749 | static void | ||
750 | ahd_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 | */ | ||
796 | static int | ||
797 | ahd_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 | */ | ||
870 | static int | ||
871 | ahd_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 | */ |
930 | static int | 441 | static int |
931 | ahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)) | 442 | ahd_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); | 471 | static inline struct scsi_target ** |
981 | } | 472 | ahd_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) | ||
987 | static int | 485 | static int |
988 | ahd_linux_slave_alloc(Scsi_Device *device) | 486 | ahd_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 | |||
526 | static void | ||
527 | ahd_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 | ||
998 | static int | 534 | static int |
999 | ahd_linux_slave_configure(Scsi_Device *device) | 535 | ahd_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 | ||
1027 | static void | 569 | static int |
1028 | ahd_linux_slave_destroy(Scsi_Device *device) | 570 | ahd_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 | */ | ||
1064 | static void | 587 | static void |
1065 | ahd_linux_select_queue_depth(struct Scsi_Host * host, | 588 | ahd_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 | */ |
1132 | static int | 608 | static int |
1133 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | ||
1134 | ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, | 609 | ahd_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 | ||
1139 | ahd_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 | */ |
1196 | static int | 653 | static int |
1197 | ahd_linux_abort(Scsi_Cmnd *cmd) | 654 | ahd_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 | |||
1439 | no_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; | ||
1447 | done: | ||
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 | |||
1478 | static void | ||
1479 | ahd_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 | */ |
1487 | static int | 667 | static int |
1488 | ahd_linux_dev_reset(Scsi_Cmnd *cmd) | 668 | ahd_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 | */ |
1581 | static int | 681 | static int |
1582 | ahd_linux_bus_reset(Scsi_Cmnd *cmd) | 682 | ahd_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 | ||
1607 | Scsi_Host_Template aic79xx_driver_template = { | 706 | struct 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 | */ | ||
1636 | static void | ||
1637 | ahd_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 *************************************/ |
1658 | int | 731 | int |
1659 | ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, | 732 | ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, |
@@ -1693,36 +766,10 @@ int | |||
1693 | ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr, | 766 | ahd_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 | ||
1737 | int | 784 | int |
@@ -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, | |||
1754 | void | 801 | void |
1755 | ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map) | 802 | ahd_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 | ||
1764 | int | 806 | int |
@@ -1823,41 +865,6 @@ ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd) | |||
1823 | } | 865 | } |
1824 | 866 | ||
1825 | static void | 867 | static void |
1826 | ahd_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 | |||
1838 | static void | ||
1839 | ahd_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 | |||
1849 | static void | ||
1850 | ahd_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 | |||
1860 | static void | ||
1861 | ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) | 868 | ahd_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 | ||
897 | static void | ||
898 | ahd_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); | |||
1982 | uint32_t aic79xx_verbose; | 994 | uint32_t aic79xx_verbose; |
1983 | 995 | ||
1984 | int | 996 | int |
1985 | ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) | 997 | ahd_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 | */ | ||
2089 | static int | ||
2090 | ahd_linux_next_unit(void) | ||
2091 | { | ||
2092 | struct ahd_softc *ahd; | ||
2093 | int unit; | ||
2094 | |||
2095 | unit = 0; | ||
2096 | retry: | ||
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) | |||
2183 | void | 1116 | void |
2184 | ahd_platform_free(struct ahd_softc *ahd) | 1117 | ahd_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 | |||
2280 | ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, | 1191 | ahd_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 | |||
2371 | int | ||
2372 | ahd_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 | |||
2429 | static void | ||
2430 | ahd_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 | |||
2441 | static void | ||
2442 | ahd_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 | |||
2463 | static int | ||
2464 | ahd_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(¤t->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 | |||
2556 | static void | ||
2557 | ahd_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 | |||
2605 | static __inline void | ||
2606 | ahd_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 | |||
2625 | static void | ||
2626 | ahd_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 | |||
2772 | out: | ||
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 | |||
2815 | static __inline int | ||
2816 | ahd_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 | |||
2828 | static void | ||
2829 | ahd_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 | |||
3305 | static void | ||
3306 | ahd_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 | */ | ||
3318 | static void | ||
3319 | ahd_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 | |||
3353 | static void | ||
3354 | ahd_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 | |||
3373 | static void | ||
3374 | ahd_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 | |||
3398 | static void | ||
3399 | ahd_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 | |||
3420 | static void | ||
3421 | ahd_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 | |||
3442 | static void | ||
3443 | ahd_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 | |||
3464 | static int | ||
3465 | ahd_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 | |||
3638 | static void | ||
3639 | ahd_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 | |||
3694 | static void | ||
3695 | ahd_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 | ||
3715 | static void | 1288 | int |
3716 | ahd_linux_generate_dv_pattern(struct ahd_linux_target *targ) | 1289 | ahd_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 | ||
3772 | static u_int | 1295 | static 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 | ||
3803 | static u_int | ||
3804 | ahd_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 | |||
3836 | static void | ||
3837 | ahd_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 | */ |
3881 | static void | 1329 | static void |
3882 | ahd_linux_device_queue_depth(struct ahd_softc *ahd, | 1330 | ahd_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 | ||
3906 | static void | 1352 | static int |
3907 | ahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev) | 1353 | ahd_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 | |||
4092 | ahd_platform_flushwork(struct ahd_softc *ahd) | 1499 | ahd_platform_flushwork(struct ahd_softc *ahd) |
4093 | { | 1500 | { |
4094 | 1501 | ||
4095 | while (ahd_linux_run_complete_queue(ahd) != NULL) | ||
4096 | ; | ||
4097 | } | ||
4098 | |||
4099 | static struct ahd_linux_target* | ||
4100 | ahd_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 | |||
4116 | static void | ||
4117 | ahd_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 | |||
4153 | static struct ahd_linux_device* | ||
4154 | ahd_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 | |||
4187 | static void | ||
4188 | ahd_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 | ||
4202 | void | 1504 | void |
@@ -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, | |||
4305 | void | 1600 | void |
4306 | ahd_done(struct ahd_softc *ahd, struct scb *scb) | 1601 | ahd_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 | ||
4440 | static void | 1708 | static void |
4441 | ahd_linux_handle_scsi_status(struct ahd_softc *ahd, | 1709 | ahd_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 | ||
4606 | static void | 1853 | static void |
4607 | ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, Scsi_Cmnd *cmd) | 1854 | ahd_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 | } | ||
4673 | no_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 | ||
4761 | static void | 1925 | static void |
4762 | ahd_linux_filter_inquiry(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) | 1926 | ahd_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 | ||
4860 | void | 1941 | void |
@@ -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 | ||
4902 | static void | 1977 | static int |
4903 | ahd_linux_sem_timeout(u_long arg) | 1978 | ahd_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 | |||
2217 | no_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; | ||
2225 | done: | ||
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 | ||
4919 | static void | 2253 | static void ahd_linux_set_width(struct scsi_target *starget, int width) |
4920 | ahd_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 | ||
4941 | void | 2267 | static void ahd_linux_set_period(struct scsi_target *starget, int period) |
4942 | ahd_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 | ||
4972 | static int __init | 2317 | static void ahd_linux_set_offset(struct scsi_target *starget, int offset) |
4973 | ahd_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 | |||
2352 | static 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 | |||
2394 | static 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 | |||
2433 | static 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 | ||
4989 | static void __exit | 2473 | static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm) |
4990 | ahd_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 | |||
2509 | static 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 | |||
2545 | static 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 | |||
2589 | static 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 | |||
2625 | static 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 | |||
2657 | static 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 | |||
2682 | static int __init | ||
2683 | ahd_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 | |||
2709 | static void __exit | ||
2710 | ahd_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 | ||
5016 | module_init(ahd_linux_init); | 2716 | module_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 *******************************/ |
96 | struct ahd_softc; | 102 | struct ahd_softc; |
97 | typedef struct pci_dev *ahd_dev_softc_t; | 103 | typedef struct pci_dev *ahd_dev_softc_t; |
98 | typedef Scsi_Cmnd *ahd_io_ctx_t; | 104 | typedef 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 *********************************/ |
116 | extern uint32_t aic79xx_allow_memio; | 122 | extern uint32_t aic79xx_allow_memio; |
117 | extern int aic79xx_detect_complete; | 123 | extern struct scsi_host_template aic79xx_driver_template; |
118 | extern 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 | }; |
146 | typedef struct ahd_linux_dma_tag* bus_dma_tag_t; | 151 | typedef struct ahd_linux_dma_tag* bus_dma_tag_t; |
147 | 152 | ||
148 | struct ahd_linux_dmamap | 153 | typedef dma_addr_t bus_dmamap_t; |
149 | { | ||
150 | dma_addr_t bus_addr; | ||
151 | }; | ||
152 | typedef struct ahd_linux_dmamap* bus_dmamap_t; | ||
153 | 154 | ||
154 | typedef int bus_dma_filter_t(void*, dma_addr_t); | 155 | typedef int bus_dma_filter_t(void*, dma_addr_t); |
155 | typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); | 156 | typedef 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 |
228 | typedef void ahd_linux_callback_t (u_long); | 229 | typedef void ahd_linux_callback_t (u_long); |
229 | static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec, | 230 | static __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); |
231 | static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); | 232 | static __inline void ahd_scb_timer_reset(struct scb *scb, u_int usec); |
232 | 233 | ||
233 | static __inline void | 234 | static __inline void |
234 | ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg) | 235 | ahd_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 | */ | ||
270 | struct 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 | |||
281 | struct 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 | */ |
300 | TAILQ_HEAD(ahd_busyq, ahd_cmd); | 266 | |
301 | typedef enum { | 267 | typedef 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 | ||
312 | struct ahd_linux_target; | 274 | struct ahd_linux_target; |
313 | struct ahd_linux_device { | 275 | struct 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 | ||
397 | typedef 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 */ | ||
405 | typedef 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 | |||
419 | struct ahd_linux_target { | 354 | struct 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 | */ | ||
462 | extern 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 | */ |
472 | typedef enum { | ||
473 | AHD_SCB_UP_EH_SEM = 0x1 | ||
474 | } ahd_linux_scb_flags; | ||
475 | |||
476 | struct scb_platform_data { | 372 | struct 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 | */ |
490 | typedef 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 | |||
498 | TAILQ_HEAD(ahd_completeq, ahd_cmd); | ||
499 | |||
500 | struct ahd_platform_data { | 385 | struct 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 **********************************/ |
643 | int ahd_linux_register_host(struct ahd_softc *, | 517 | int ahd_linux_register_host(struct ahd_softc *, |
644 | Scsi_Host_Template *); | 518 | struct scsi_host_template *); |
645 | 519 | ||
646 | uint64_t ahd_linux_get_memsize(void); | 520 | uint64_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 */ | ||
661 | static __inline void ahd_lockinit(struct ahd_softc *); | ||
662 | static __inline void ahd_lock(struct ahd_softc *, unsigned long *flags); | ||
663 | static __inline void ahd_unlock(struct ahd_softc *, unsigned long *flags); | ||
664 | |||
665 | /* Lock acquisition and release of the above lock in midlayer entry points. */ | ||
666 | static __inline void ahd_midlayer_entrypoint_lock(struct ahd_softc *, | ||
667 | unsigned long *flags); | ||
668 | static __inline void ahd_midlayer_entrypoint_unlock(struct ahd_softc *, | ||
669 | unsigned long *flags); | ||
670 | |||
671 | /* Lock held during command compeletion to the upper layer */ | ||
672 | static __inline void ahd_done_lockinit(struct ahd_softc *); | ||
673 | static __inline void ahd_done_lock(struct ahd_softc *, unsigned long *flags); | ||
674 | static __inline void ahd_done_unlock(struct ahd_softc *, unsigned long *flags); | ||
675 | |||
676 | /* Lock held during ahd_list manipulation and ahd softc frees */ | ||
677 | extern spinlock_t ahd_list_spinlock; | ||
678 | static __inline void ahd_list_lockinit(void); | ||
679 | static __inline void ahd_list_lock(unsigned long *flags); | ||
680 | static __inline void ahd_list_unlock(unsigned long *flags); | ||
681 | |||
682 | static __inline void | 534 | static __inline void |
683 | ahd_lockinit(struct ahd_softc *ahd) | 535 | ahd_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 | ||
700 | static __inline void | ||
701 | ahd_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 | |||
716 | static __inline void | ||
717 | ahd_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 | |||
725 | static __inline void | ||
726 | ahd_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 | |||
735 | static __inline void | ||
736 | ahd_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 | |||
743 | static __inline void | ||
744 | ahd_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 | |||
751 | static __inline void | ||
752 | ahd_list_lockinit(void) | ||
753 | { | ||
754 | spin_lock_init(&ahd_list_spinlock); | ||
755 | } | ||
756 | |||
757 | static __inline void | ||
758 | ahd_list_lock(unsigned long *flags) | ||
759 | { | ||
760 | spin_lock_irqsave(&ahd_list_spinlock, *flags); | ||
761 | } | ||
762 | |||
763 | static __inline void | ||
764 | ahd_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) | ||
929 | int ahd_linux_proc_info(char *, char **, off_t, int, int, int); | ||
930 | #else | ||
931 | int ahd_linux_proc_info(struct Scsi_Host *, char *, char **, | 711 | int 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 **************************/ |
942 | static __inline void ahd_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t); | 715 | static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t); |
943 | static __inline void ahd_set_transaction_status(struct scb *, uint32_t); | 716 | static __inline void ahd_set_transaction_status(struct scb *, uint32_t); |
944 | static __inline void ahd_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t); | 717 | static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t); |
945 | static __inline void ahd_set_scsi_status(struct scb *, uint32_t); | 718 | static __inline void ahd_set_scsi_status(struct scb *, uint32_t); |
946 | static __inline uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd); | 719 | static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd); |
947 | static __inline uint32_t ahd_get_transaction_status(struct scb *); | 720 | static __inline uint32_t ahd_get_transaction_status(struct scb *); |
948 | static __inline uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd); | 721 | static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd); |
949 | static __inline uint32_t ahd_get_scsi_status(struct scb *); | 722 | static __inline uint32_t ahd_get_scsi_status(struct scb *); |
950 | static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); | 723 | static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); |
951 | static __inline u_long ahd_get_transfer_length(struct scb *); | 724 | static __inline u_long ahd_get_transfer_length(struct scb *); |
@@ -964,7 +737,7 @@ static __inline void ahd_platform_scb_free(struct ahd_softc *ahd, | |||
964 | static __inline void ahd_freeze_scb(struct scb *scb); | 737 | static __inline void ahd_freeze_scb(struct scb *scb); |
965 | 738 | ||
966 | static __inline | 739 | static __inline |
967 | void ahd_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status) | 740 | void 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 | ||
979 | static __inline | 752 | static __inline |
980 | void ahd_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status) | 753 | void 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 | ||
992 | static __inline | 765 | static __inline |
993 | uint32_t ahd_cmd_get_transaction_status(Scsi_Cmnd *cmd) | 766 | uint32_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 | ||
1004 | static __inline | 777 | static __inline |
1005 | uint32_t ahd_cmd_get_scsi_status(Scsi_Cmnd *cmd) | 778 | uint32_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*); | |||
1117 | void ahd_send_async(struct ahd_softc *, char channel, | 890 | void 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 *); |
1119 | void ahd_print_path(struct ahd_softc *, struct scb *); | 892 | void ahd_print_path(struct ahd_softc *, struct scb *); |
1120 | void 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 = { | |||
92 | static void | 92 | static void |
93 | ahd_linux_pci_dev_remove(struct pci_dev *pdev) | 93 | ahd_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)); | 104 | static void |
105 | if (ahd != NULL) { | 105 | ahd_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 | ||
118 | static int | 122 | static 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 | |||
283 | ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) | 283 | ahd_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); |
51 | static void ahd_dump_device_state(struct info_str *info, | 51 | static void ahd_dump_device_state(struct info_str *info, |
52 | struct ahd_linux_device *dev); | 52 | struct scsi_device *sdev); |
53 | static int ahd_proc_write_seeprom(struct ahd_softc *ahd, | 53 | static 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 | ||
201 | static void | 202 | static void |
202 | ahd_dump_device_state(struct info_str *info, struct ahd_linux_device *dev) | 203 | ahd_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 | */ |
280 | int | 284 | int |
281 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) | ||
282 | ahd_linux_proc_info(char *buffer, char **start, off_t offset, | ||
283 | int length, int hostno, int inout) | ||
284 | #else | ||
285 | ahd_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, | 285 | ahd_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; |
359 | done: | 343 | done: |
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 | */ |
42 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $" | 42 | VERSION = "$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 | ||
43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#56 $" | 43 | VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $" |
44 | PATCH_ARG_LIST = "struct ahc_softc *ahc" | 44 | PATCH_ARG_LIST = "struct ahc_softc *ahc" |
45 | PREFIX = "ahc_" | 45 | PREFIX = "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 | */ |
84 | static struct seeprom_cmd { | 81 | struct 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 */ | ||
89 | static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; | 87 | static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; |
90 | static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; | 88 | static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; |
89 | |||
90 | /* Long opcodes for the C56/C66 */ | ||
91 | static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; | ||
92 | static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; | ||
93 | |||
94 | /* Common opcodes */ | ||
91 | static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; | 95 | static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; |
96 | static 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 | |||
222 | ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, | 227 | ahc_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 | ||
2332 | static void ahc_linux_exit(void); | ||
2333 | |||
2334 | static void ahc_linux_set_width(struct scsi_target *starget, int width) | 2334 | static 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 | ||
152 | static void | ||
153 | ahc_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 | |||
152 | static int | 173 | static int |
153 | ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 174 | ahc_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 | */ |
8 | typedef int (ahc_reg_print_t)(u_int, u_int *, u_int); | 8 | typedef int (ahc_reg_print_t)(u_int, u_int *, u_int); |
9 | typedef struct ahc_reg_parse_entry { | 9 | typedef 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 | */ |
8 | static uint8_t seqprog[] = { | 8 | static 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; | |||
941 | static int | 942 | static int |
942 | ahc_patch17_func(struct ahc_softc *ahc) | 943 | ahc_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 | ||
947 | static ahc_patch_func_t ahc_patch16_func; | 948 | static 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 | ||
1293 | static struct cs { | 1294 | static 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 | ||
1306 | static const int num_critical_sections = sizeof(critical_sections) | 1307 | static 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 | |||
55 | static int ascentrycomp(const void *key, const void *member); | ||
56 | static int senseentrycomp(const void *key, const void *member); | ||
57 | static 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 **); | ||
61 | static void * scsibsearch(const void *key, const void *base, size_t nmemb, | ||
62 | size_t size, | ||
63 | int (*compar)(const void *, const void *)); | ||
64 | typedef int (cam_quirkmatch_t)(caddr_t, caddr_t); | ||
65 | static int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, | ||
66 | int str_len); | ||
67 | static 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 | ||
76 | static const char empty_string[] = ""; | ||
77 | |||
78 | #define SST(asc, ascq, action, desc) \ | ||
79 | asc, ascq, action, empty_string | ||
80 | #endif | ||
81 | |||
82 | static 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 | |||
105 | static const int sense_key_table_size = | ||
106 | sizeof(sense_key_table)/sizeof(sense_key_table[0]); | ||
107 | |||
108 | static 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 | |||
113 | static 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 | |||
118 | static 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 | |||
145 | static const int sense_quirk_table_size = | ||
146 | sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]); | ||
147 | |||
148 | static 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 | |||
848 | static const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]); | ||
849 | |||
850 | struct asc_key | ||
851 | { | ||
852 | int asc; | ||
853 | int ascq; | ||
854 | }; | ||
855 | |||
856 | static int | ||
857 | ascentrycomp(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 | |||
885 | static int | ||
886 | senseentrycomp(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 | |||
902 | static void | ||
903 | fetchtableentries(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 | |||
984 | static void * | ||
985 | scsibsearch(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 | */ | ||
1018 | static int | ||
1019 | cam_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 | |||
1041 | static caddr_t | ||
1042 | cam_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 | |||
1052 | void | ||
1053 | aic_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 | */ | ||
1082 | aic_sense_action | ||
1083 | aic_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 | */ | ||
1167 | int | ||
1168 | aic_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 | */ | ||
1235 | u_int | ||
1236 | aic_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 | |||
1249 | uint32_t | ||
1250 | aic_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 | |||
1334 | char * | 78 | char * |
1335 | aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, | 79 | aic_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 | ||
64 | typedef 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 | */ | ||
93 | typedef 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 | |||
110 | typedef 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 | |||
139 | struct scsi_generic | ||
140 | { | ||
141 | uint8_t opcode; | ||
142 | uint8_t bytes[11]; | ||
143 | }; | ||
144 | |||
145 | struct 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 | |||
154 | struct scsi_test_unit_ready | ||
155 | { | ||
156 | uint8_t opcode; | ||
157 | uint8_t byte2; | ||
158 | uint8_t unused[3]; | ||
159 | uint8_t control; | ||
160 | }; | ||
161 | |||
162 | struct 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 | |||
175 | struct scsi_sense | 60 | struct 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 | ||
184 | struct 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 | |||
195 | struct 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 | |||
217 | struct 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 | |||
227 | struct 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 | |||
238 | struct 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 | */ | ||
250 | struct 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 | |||
258 | struct 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 | |||
267 | struct 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 | |||
275 | struct 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 | |||
302 | struct 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 | |||
319 | struct scsi_log_header | ||
320 | { | ||
321 | uint8_t page; | ||
322 | uint8_t reserved; | ||
323 | uint8_t datalen[2]; | ||
324 | }; | ||
325 | |||
326 | struct 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 | |||
343 | struct 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 | |||
363 | struct 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 | |||
372 | struct 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 | |||
381 | struct 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 | |||
392 | struct 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 | |||
403 | struct 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 | |||
414 | struct 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 | |||
429 | struct 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 | |||
439 | struct 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 | |||
449 | struct 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 | |||
462 | struct 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 | |||
475 | struct 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 | |||
561 | struct 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 | |||
666 | struct 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 | |||
677 | struct 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 | |||
686 | struct scsi_read_capacity_data | ||
687 | { | ||
688 | uint8_t addr[4]; | ||
689 | uint8_t length[4]; | ||
690 | }; | ||
691 | |||
692 | struct 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 | |||
701 | struct 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 | |||
715 | struct scsi_sense_data | 75 | struct 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 | ||
760 | struct 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 | |||
768 | struct 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 | |||
777 | struct scsi_mode_page_header | ||
778 | { | ||
779 | uint8_t page_code; | ||
780 | uint8_t page_length; | ||
781 | }; | ||
782 | |||
783 | struct 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 | ||
810 | struct 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 | |||
820 | struct 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 | |||
828 | struct 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 | |||
836 | struct sense_key_table_entry { | ||
837 | uint8_t sense_key; | ||
838 | uint32_t action; | ||
839 | const char *desc; | ||
840 | }; | ||
841 | |||
842 | struct asc_table_entry { | ||
843 | uint8_t asc; | ||
844 | uint8_t ascq; | ||
845 | uint32_t action; | ||
846 | const char *desc; | ||
847 | }; | ||
848 | |||
849 | struct op_table_entry { | ||
850 | uint8_t opcode; | ||
851 | uint16_t opmask; | ||
852 | const char *desc; | ||
853 | }; | ||
854 | |||
855 | struct scsi_op_quirk_entry { | ||
856 | struct scsi_inquiry_pattern inq_pat; | ||
857 | int num_ops; | ||
858 | struct op_table_entry *op_table; | ||
859 | }; | ||
860 | |||
861 | typedef enum { | ||
862 | SSS_FLAG_NONE = 0x00, | ||
863 | SSS_FLAG_PRINT_COMMAND = 0x01 | ||
864 | } scsi_sense_string_flags; | ||
865 | |||
866 | extern 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) | ||
870 | static __inline int aic_sector_div(u_long capacity, int heads, int sectors); | ||
871 | |||
872 | static __inline int | ||
873 | aic_sector_div(u_long capacity, int heads, int sectors) | ||
874 | { | ||
875 | return (capacity / (heads * sectors)); | ||
876 | } | ||
877 | #else | ||
878 | static __inline int aic_sector_div(sector_t capacity, int heads, int sectors); | ||
879 | |||
880 | static __inline int | 136 | static __inline int |
881 | aic_sector_div(sector_t capacity, int heads, int sectors) | 137 | aic_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 | |||
917 | void 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*/); | ||
921 | aic_sense_action aic_sense_error_action(struct scsi_sense_data*, | ||
922 | struct scsi_inquiry_data*, | ||
923 | uint32_t /*sense_flags*/); | ||
924 | uint32_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 | |||
934 | const char * aic_op_desc(uint16_t /*opcode*/, struct scsi_inquiry_data*); | ||
935 | char * aic_cdb_string(uint8_t* /*cdb_ptr*/, char* /*cdb_string*/, | ||
936 | size_t /*len*/); | ||
937 | void aic_print_inquiry(struct scsi_inquiry_data*); | ||
938 | 158 | ||
939 | u_int aic_calc_syncsrate(u_int /*period_factor*/); | 159 | u_int aic_calc_syncsrate(u_int /*period_factor*/); |
940 | u_int aic_calc_syncparam(u_int /*period*/); | ||
941 | u_int aic_calc_speed(u_int width, u_int period, u_int offset, | ||
942 | u_int min_rate); | ||
943 | |||
944 | int aic_inquiry_match(caddr_t /*inqbuffer*/, | ||
945 | caddr_t /*table_entry*/); | ||
946 | int aic_static_inquiry_match(caddr_t /*inqbuffer*/, | ||
947 | caddr_t /*table_entry*/); | ||
948 | 160 | ||
949 | typedef void aic_option_callback_t(u_long, int, int, int32_t); | 161 | typedef void aic_option_callback_t(u_long, int, int, int32_t); |
950 | char * aic_parse_brace_option(char *opt_name, char *opt_arg, | 162 | char * 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 | ||
954 | static __inline void scsi_extract_sense(struct scsi_sense_data *sense, | ||
955 | int *error_code, int *sense_key, | ||
956 | int *asc, int *ascq); | ||
957 | static __inline void scsi_ulto2b(uint32_t val, uint8_t *bytes); | ||
958 | static __inline void scsi_ulto3b(uint32_t val, uint8_t *bytes); | ||
959 | static __inline void scsi_ulto4b(uint32_t val, uint8_t *bytes); | ||
960 | static __inline uint32_t scsi_2btoul(uint8_t *bytes); | ||
961 | static __inline uint32_t scsi_3btoul(uint8_t *bytes); | ||
962 | static __inline int32_t scsi_3btol(uint8_t *bytes); | ||
963 | static __inline uint32_t scsi_4btoul(uint8_t *bytes); | ||
964 | |||
965 | static __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 | |||
975 | static __inline void | ||
976 | scsi_ulto2b(uint32_t val, uint8_t *bytes) | ||
977 | { | ||
978 | |||
979 | bytes[0] = (val >> 8) & 0xff; | ||
980 | bytes[1] = val & 0xff; | ||
981 | } | ||
982 | |||
983 | static __inline void | ||
984 | scsi_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 | |||
992 | static __inline void | ||
993 | scsi_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 | |||
1002 | static __inline uint32_t | ||
1003 | scsi_2btoul(uint8_t *bytes) | ||
1004 | { | ||
1005 | uint32_t rv; | ||
1006 | |||
1007 | rv = (bytes[0] << 8) | | ||
1008 | bytes[1]; | ||
1009 | return (rv); | ||
1010 | } | ||
1011 | |||
1012 | static __inline uint32_t | ||
1013 | scsi_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 | |||
1023 | static __inline int32_t | ||
1024 | scsi_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 | |||
1034 | static __inline uint32_t | 166 | static __inline uint32_t |
1035 | scsi_4btoul(uint8_t *bytes) | 167 | scsi_4btoul(uint8_t *bytes) |
1036 | { | 168 | { |