diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic7xxx_osm.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 223 |
1 files changed, 26 insertions, 197 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index b89094db14c1..116d0f51ca2c 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -136,10 +136,6 @@ static struct scsi_transport_template *ahc_linux_transport_template = NULL; | |||
136 | #include <linux/blkdev.h> /* For block_size() */ | 136 | #include <linux/blkdev.h> /* For block_size() */ |
137 | #include <linux/delay.h> /* For ssleep/msleep */ | 137 | #include <linux/delay.h> /* For ssleep/msleep */ |
138 | 138 | ||
139 | /* | ||
140 | * Lock protecting manipulation of the ahc softc list. | ||
141 | */ | ||
142 | spinlock_t ahc_list_spinlock; | ||
143 | 139 | ||
144 | /* | 140 | /* |
145 | * Set this to the delay in seconds after SCSI bus reset. | 141 | * Set this to the delay in seconds after SCSI bus reset. |
@@ -292,25 +288,6 @@ ahc_print_path(struct ahc_softc *ahc, struct scb *scb) | |||
292 | static uint32_t aic7xxx_no_reset; | 288 | static uint32_t aic7xxx_no_reset; |
293 | 289 | ||
294 | /* | 290 | /* |
295 | * Certain PCI motherboards will scan PCI devices from highest to lowest, | ||
296 | * others scan from lowest to highest, and they tend to do all kinds of | ||
297 | * strange things when they come into contact with PCI bridge chips. The | ||
298 | * net result of all this is that the PCI card that is actually used to boot | ||
299 | * the machine is very hard to detect. Most motherboards go from lowest | ||
300 | * PCI slot number to highest, and the first SCSI controller found is the | ||
301 | * one you boot from. The only exceptions to this are when a controller | ||
302 | * has its BIOS disabled. So, we by default sort all of our SCSI controllers | ||
303 | * from lowest PCI slot number to highest PCI slot number. We also force | ||
304 | * all controllers with their BIOS disabled to the end of the list. This | ||
305 | * works on *almost* all computers. Where it doesn't work, we have this | ||
306 | * option. Setting this option to non-0 will reverse the order of the sort | ||
307 | * to highest first, then lowest, but will still leave cards with their BIOS | ||
308 | * disabled at the very end. That should fix everyone up unless there are | ||
309 | * really strange cirumstances. | ||
310 | */ | ||
311 | static uint32_t aic7xxx_reverse_scan; | ||
312 | |||
313 | /* | ||
314 | * Should we force EXTENDED translation on a controller. | 291 | * Should we force EXTENDED translation on a controller. |
315 | * 0 == Use whatever is in the SEEPROM or default to off | 292 | * 0 == Use whatever is in the SEEPROM or default to off |
316 | * 1 == Use whatever is in the SEEPROM or default to on | 293 | * 1 == Use whatever is in the SEEPROM or default to on |
@@ -338,13 +315,6 @@ static uint32_t aic7xxx_pci_parity = ~0; | |||
338 | uint32_t aic7xxx_allow_memio = ~0; | 315 | uint32_t aic7xxx_allow_memio = ~0; |
339 | 316 | ||
340 | /* | 317 | /* |
341 | * aic7xxx_detect() has been run, so register all device arrivals | ||
342 | * immediately with the system rather than deferring to the sorted | ||
343 | * attachment performed by aic7xxx_detect(). | ||
344 | */ | ||
345 | int aic7xxx_detect_complete; | ||
346 | |||
347 | /* | ||
348 | * So that we can set how long each device is given as a selection timeout. | 318 | * So that we can set how long each device is given as a selection timeout. |
349 | * The table of values goes like this: | 319 | * The table of values goes like this: |
350 | * 0 - 256ms | 320 | * 0 - 256ms |
@@ -423,7 +393,9 @@ static int ahc_linux_run_command(struct ahc_softc*, | |||
423 | static void ahc_linux_setup_tag_info_global(char *p); | 393 | static void ahc_linux_setup_tag_info_global(char *p); |
424 | static aic_option_callback_t ahc_linux_setup_tag_info; | 394 | static aic_option_callback_t ahc_linux_setup_tag_info; |
425 | static int aic7xxx_setup(char *s); | 395 | static int aic7xxx_setup(char *s); |
426 | static int ahc_linux_next_unit(void); | 396 | |
397 | static int ahc_linux_unit; | ||
398 | |||
427 | 399 | ||
428 | /********************************* Inlines ************************************/ | 400 | /********************************* Inlines ************************************/ |
429 | static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); | 401 | static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); |
@@ -476,48 +448,6 @@ ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, | |||
476 | } | 448 | } |
477 | 449 | ||
478 | /* | 450 | /* |
479 | * Try to detect an Adaptec 7XXX controller. | ||
480 | */ | ||
481 | static int | ||
482 | ahc_linux_detect(struct scsi_host_template *template) | ||
483 | { | ||
484 | struct ahc_softc *ahc; | ||
485 | int found = 0; | ||
486 | |||
487 | /* | ||
488 | * If we've been passed any parameters, process them now. | ||
489 | */ | ||
490 | if (aic7xxx) | ||
491 | aic7xxx_setup(aic7xxx); | ||
492 | |||
493 | template->proc_name = "aic7xxx"; | ||
494 | |||
495 | /* | ||
496 | * Initialize our softc list lock prior to | ||
497 | * probing for any adapters. | ||
498 | */ | ||
499 | ahc_list_lockinit(); | ||
500 | |||
501 | found = ahc_linux_pci_init(); | ||
502 | if (!ahc_linux_eisa_init()) | ||
503 | found++; | ||
504 | |||
505 | /* | ||
506 | * Register with the SCSI layer all | ||
507 | * controllers we've found. | ||
508 | */ | ||
509 | TAILQ_FOREACH(ahc, &ahc_tailq, links) { | ||
510 | |||
511 | if (ahc_linux_register_host(ahc, template) == 0) | ||
512 | found++; | ||
513 | } | ||
514 | |||
515 | aic7xxx_detect_complete++; | ||
516 | |||
517 | return (found); | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * Return a string describing the driver. | 451 | * Return a string describing the driver. |
522 | */ | 452 | */ |
523 | static const char * | 453 | static const char * |
@@ -848,6 +778,7 @@ ahc_linux_bus_reset(struct scsi_cmnd *cmd) | |||
848 | struct scsi_host_template aic7xxx_driver_template = { | 778 | struct scsi_host_template aic7xxx_driver_template = { |
849 | .module = THIS_MODULE, | 779 | .module = THIS_MODULE, |
850 | .name = "aic7xxx", | 780 | .name = "aic7xxx", |
781 | .proc_name = "aic7xxx", | ||
851 | .proc_info = ahc_linux_proc_info, | 782 | .proc_info = ahc_linux_proc_info, |
852 | .info = ahc_linux_info, | 783 | .info = ahc_linux_info, |
853 | .queuecommand = ahc_linux_queue, | 784 | .queuecommand = ahc_linux_queue, |
@@ -959,99 +890,6 @@ ahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map) | |||
959 | return (0); | 890 | return (0); |
960 | } | 891 | } |
961 | 892 | ||
962 | /********************* Platform Dependent Functions ***************************/ | ||
963 | /* | ||
964 | * Compare "left hand" softc with "right hand" softc, returning: | ||
965 | * < 0 - lahc has a lower priority than rahc | ||
966 | * 0 - Softcs are equal | ||
967 | * > 0 - lahc has a higher priority than rahc | ||
968 | */ | ||
969 | int | ||
970 | ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc) | ||
971 | { | ||
972 | int value; | ||
973 | int rvalue; | ||
974 | int lvalue; | ||
975 | |||
976 | /* | ||
977 | * Under Linux, cards are ordered as follows: | ||
978 | * 1) VLB/EISA BIOS enabled devices sorted by BIOS address. | ||
979 | * 2) PCI devices with BIOS enabled sorted by bus/slot/func. | ||
980 | * 3) All remaining VLB/EISA devices sorted by ioport. | ||
981 | * 4) All remaining PCI devices sorted by bus/slot/func. | ||
982 | */ | ||
983 | value = (lahc->flags & AHC_BIOS_ENABLED) | ||
984 | - (rahc->flags & AHC_BIOS_ENABLED); | ||
985 | if (value != 0) | ||
986 | /* Controllers with BIOS enabled have a *higher* priority */ | ||
987 | return (value); | ||
988 | |||
989 | /* | ||
990 | * Same BIOS setting, now sort based on bus type. | ||
991 | * EISA and VL controllers sort together. EISA/VL | ||
992 | * have higher priority than PCI. | ||
993 | */ | ||
994 | rvalue = (rahc->chip & AHC_BUS_MASK); | ||
995 | if (rvalue == AHC_VL) | ||
996 | rvalue = AHC_EISA; | ||
997 | lvalue = (lahc->chip & AHC_BUS_MASK); | ||
998 | if (lvalue == AHC_VL) | ||
999 | lvalue = AHC_EISA; | ||
1000 | value = rvalue - lvalue; | ||
1001 | if (value != 0) | ||
1002 | return (value); | ||
1003 | |||
1004 | /* Still equal. Sort by BIOS address, ioport, or bus/slot/func. */ | ||
1005 | switch (rvalue) { | ||
1006 | #ifdef CONFIG_PCI | ||
1007 | case AHC_PCI: | ||
1008 | { | ||
1009 | char primary_channel; | ||
1010 | |||
1011 | if (aic7xxx_reverse_scan != 0) | ||
1012 | value = ahc_get_pci_bus(lahc->dev_softc) | ||
1013 | - ahc_get_pci_bus(rahc->dev_softc); | ||
1014 | else | ||
1015 | value = ahc_get_pci_bus(rahc->dev_softc) | ||
1016 | - ahc_get_pci_bus(lahc->dev_softc); | ||
1017 | if (value != 0) | ||
1018 | break; | ||
1019 | if (aic7xxx_reverse_scan != 0) | ||
1020 | value = ahc_get_pci_slot(lahc->dev_softc) | ||
1021 | - ahc_get_pci_slot(rahc->dev_softc); | ||
1022 | else | ||
1023 | value = ahc_get_pci_slot(rahc->dev_softc) | ||
1024 | - ahc_get_pci_slot(lahc->dev_softc); | ||
1025 | if (value != 0) | ||
1026 | break; | ||
1027 | /* | ||
1028 | * On multi-function devices, the user can choose | ||
1029 | * to have function 1 probed before function 0. | ||
1030 | * Give whichever channel is the primary channel | ||
1031 | * the highest priority. | ||
1032 | */ | ||
1033 | primary_channel = (lahc->flags & AHC_PRIMARY_CHANNEL) + 'A'; | ||
1034 | value = -1; | ||
1035 | if (lahc->channel == primary_channel) | ||
1036 | value = 1; | ||
1037 | break; | ||
1038 | } | ||
1039 | #endif | ||
1040 | case AHC_EISA: | ||
1041 | if ((rahc->flags & AHC_BIOS_ENABLED) != 0) { | ||
1042 | value = rahc->platform_data->bios_address | ||
1043 | - lahc->platform_data->bios_address; | ||
1044 | } else { | ||
1045 | value = rahc->bsh.ioport | ||
1046 | - lahc->bsh.ioport; | ||
1047 | } | ||
1048 | break; | ||
1049 | default: | ||
1050 | panic("ahc_softc_sort: invalid bus type"); | ||
1051 | } | ||
1052 | return (value); | ||
1053 | } | ||
1054 | |||
1055 | static void | 893 | static void |
1056 | ahc_linux_setup_tag_info_global(char *p) | 894 | ahc_linux_setup_tag_info_global(char *p) |
1057 | { | 895 | { |
@@ -1103,7 +941,6 @@ aic7xxx_setup(char *s) | |||
1103 | #ifdef AHC_DEBUG | 941 | #ifdef AHC_DEBUG |
1104 | { "debug", &ahc_debug }, | 942 | { "debug", &ahc_debug }, |
1105 | #endif | 943 | #endif |
1106 | { "reverse_scan", &aic7xxx_reverse_scan }, | ||
1107 | { "periodic_otag", &aic7xxx_periodic_otag }, | 944 | { "periodic_otag", &aic7xxx_periodic_otag }, |
1108 | { "pci_parity", &aic7xxx_pci_parity }, | 945 | { "pci_parity", &aic7xxx_pci_parity }, |
1109 | { "seltime", &aic7xxx_seltime }, | 946 | { "seltime", &aic7xxx_seltime }, |
@@ -1178,7 +1015,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa | |||
1178 | host->max_lun = AHC_NUM_LUNS; | 1015 | host->max_lun = AHC_NUM_LUNS; |
1179 | host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0; | 1016 | host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0; |
1180 | host->sg_tablesize = AHC_NSEG; | 1017 | host->sg_tablesize = AHC_NSEG; |
1181 | ahc_set_unit(ahc, ahc_linux_next_unit()); | 1018 | ahc_set_unit(ahc, ahc_linux_unit++); |
1182 | sprintf(buf, "scsi%d", host->host_no); | 1019 | sprintf(buf, "scsi%d", host->host_no); |
1183 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); | 1020 | new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); |
1184 | if (new_name != NULL) { | 1021 | if (new_name != NULL) { |
@@ -1207,29 +1044,6 @@ ahc_linux_get_memsize(void) | |||
1207 | } | 1044 | } |
1208 | 1045 | ||
1209 | /* | 1046 | /* |
1210 | * Find the smallest available unit number to use | ||
1211 | * for a new device. We don't just use a static | ||
1212 | * count to handle the "repeated hot-(un)plug" | ||
1213 | * scenario. | ||
1214 | */ | ||
1215 | static int | ||
1216 | ahc_linux_next_unit(void) | ||
1217 | { | ||
1218 | struct ahc_softc *ahc; | ||
1219 | int unit; | ||
1220 | |||
1221 | unit = 0; | ||
1222 | retry: | ||
1223 | TAILQ_FOREACH(ahc, &ahc_tailq, links) { | ||
1224 | if (ahc->unit == unit) { | ||
1225 | unit++; | ||
1226 | goto retry; | ||
1227 | } | ||
1228 | } | ||
1229 | return (unit); | ||
1230 | } | ||
1231 | |||
1232 | /* | ||
1233 | * Place the SCSI bus into a known state by either resetting it, | 1047 | * Place the SCSI bus into a known state by either resetting it, |
1234 | * or forcing transfer negotiations on the next command to any | 1048 | * or forcing transfer negotiations on the next command to any |
1235 | * target. | 1049 | * target. |
@@ -2633,6 +2447,11 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) | |||
2633 | ahc_unlock(ahc, &flags); | 2447 | ahc_unlock(ahc, &flags); |
2634 | } | 2448 | } |
2635 | 2449 | ||
2450 | #if 0 | ||
2451 | /* FIXME: This code claims to support IU and QAS. However, the actual | ||
2452 | * sequencer code and aic7xxx_core have no support for these parameters and | ||
2453 | * will get into a bad state if they're negotiated. Do not enable this | ||
2454 | * unless you know what you're doing */ | ||
2636 | static void ahc_linux_set_qas(struct scsi_target *starget, int qas) | 2455 | static void ahc_linux_set_qas(struct scsi_target *starget, int qas) |
2637 | { | 2456 | { |
2638 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 2457 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
@@ -2688,6 +2507,7 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu) | |||
2688 | ppr_options, AHC_TRANS_GOAL, FALSE); | 2507 | ppr_options, AHC_TRANS_GOAL, FALSE); |
2689 | ahc_unlock(ahc, &flags); | 2508 | ahc_unlock(ahc, &flags); |
2690 | } | 2509 | } |
2510 | #endif | ||
2691 | 2511 | ||
2692 | static struct spi_function_template ahc_linux_transport_functions = { | 2512 | static struct spi_function_template ahc_linux_transport_functions = { |
2693 | .set_offset = ahc_linux_set_offset, | 2513 | .set_offset = ahc_linux_set_offset, |
@@ -2698,10 +2518,12 @@ static struct spi_function_template ahc_linux_transport_functions = { | |||
2698 | .show_width = 1, | 2518 | .show_width = 1, |
2699 | .set_dt = ahc_linux_set_dt, | 2519 | .set_dt = ahc_linux_set_dt, |
2700 | .show_dt = 1, | 2520 | .show_dt = 1, |
2521 | #if 0 | ||
2701 | .set_iu = ahc_linux_set_iu, | 2522 | .set_iu = ahc_linux_set_iu, |
2702 | .show_iu = 1, | 2523 | .show_iu = 1, |
2703 | .set_qas = ahc_linux_set_qas, | 2524 | .set_qas = ahc_linux_set_qas, |
2704 | .show_qas = 1, | 2525 | .show_qas = 1, |
2526 | #endif | ||
2705 | }; | 2527 | }; |
2706 | 2528 | ||
2707 | 2529 | ||
@@ -2709,18 +2531,25 @@ static struct spi_function_template ahc_linux_transport_functions = { | |||
2709 | static int __init | 2531 | static int __init |
2710 | ahc_linux_init(void) | 2532 | ahc_linux_init(void) |
2711 | { | 2533 | { |
2712 | ahc_linux_transport_template = spi_attach_transport(&ahc_linux_transport_functions); | 2534 | /* |
2535 | * If we've been passed any parameters, process them now. | ||
2536 | */ | ||
2537 | if (aic7xxx) | ||
2538 | aic7xxx_setup(aic7xxx); | ||
2539 | |||
2540 | ahc_linux_transport_template = | ||
2541 | spi_attach_transport(&ahc_linux_transport_functions); | ||
2713 | if (!ahc_linux_transport_template) | 2542 | if (!ahc_linux_transport_template) |
2714 | return -ENODEV; | 2543 | return -ENODEV; |
2544 | |||
2715 | scsi_transport_reserve_target(ahc_linux_transport_template, | 2545 | scsi_transport_reserve_target(ahc_linux_transport_template, |
2716 | sizeof(struct ahc_linux_target)); | 2546 | sizeof(struct ahc_linux_target)); |
2717 | scsi_transport_reserve_device(ahc_linux_transport_template, | 2547 | scsi_transport_reserve_device(ahc_linux_transport_template, |
2718 | sizeof(struct ahc_linux_device)); | 2548 | sizeof(struct ahc_linux_device)); |
2719 | if (ahc_linux_detect(&aic7xxx_driver_template)) | 2549 | |
2720 | return 0; | 2550 | ahc_linux_pci_init(); |
2721 | spi_release_transport(ahc_linux_transport_template); | 2551 | ahc_linux_eisa_init(); |
2722 | ahc_linux_exit(); | 2552 | return 0; |
2723 | return -ENODEV; | ||
2724 | } | 2553 | } |
2725 | 2554 | ||
2726 | static void | 2555 | static void |